From 527b15e8f17d8b200b95bcc843d4d717d6848c67 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Wed, 24 Oct 2012 23:51:56 +0000 Subject: [PATCH] PR14171: Don't crash if we hit one of the paths where GetFullTypeForDeclarator rebuilds a function type, and that function type has parens around its name. llvm-svn: 166644 --- clang/lib/Sema/SemaType.cpp | 15 +++++++++++++++ clang/test/SemaCXX/constant-expression-cxx11.cpp | 9 +++++++++ clang/test/SemaCXX/function-type-qual.cpp | 3 +++ 3 files changed, 27 insertions(+) diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 22da2164dfca..4b23167951aa 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -2661,6 +2661,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // C++0x [dcl.constexpr]p8: A constexpr specifier for a non-static member // function that is not a constructor declares that function to be const. + // FIXME: This should be deferred until we know whether this is a static + // member function (for an out-of-class definition, we don't know + // this until we perform redeclaration lookup). if (D.getDeclSpec().isConstexprSpecified() && !FreeFunction && D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static && D.getName().getKind() != UnqualifiedId::IK_ConstructorName && @@ -2672,6 +2675,12 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, T = Context.getFunctionType(FnTy->getResultType(), FnTy->arg_type_begin(), FnTy->getNumArgs(), EPI); + // Rebuild any parens around the identifier in the function type. + for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) { + if (D.getTypeObject(i).Kind != DeclaratorChunk::Paren) + break; + T = S.BuildParenType(T); + } } // C++11 [dcl.fct]p6 (w/DR1417): @@ -2725,6 +2734,12 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, T = Context.getFunctionType(FnTy->getResultType(), FnTy->arg_type_begin(), FnTy->getNumArgs(), EPI); + // Rebuild any parens around the identifier in the function type. + for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) { + if (D.getTypeObject(i).Kind != DeclaratorChunk::Paren) + break; + T = S.BuildParenType(T); + } } } diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp index 583344c793c8..9ce5b857d99b 100644 --- a/clang/test/SemaCXX/constant-expression-cxx11.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp @@ -741,6 +741,15 @@ constexpr bool check(T a, T b) { return a == b.k; } static_assert(S(5) == 11, ""); static_assert(check(S(5), 11), ""); +namespace PR14171 { + +struct X { + constexpr (operator int)() { return 0; } +}; +static_assert(X() == 0, ""); + +} + } } diff --git a/clang/test/SemaCXX/function-type-qual.cpp b/clang/test/SemaCXX/function-type-qual.cpp index 73613aef8d01..ccb57472925d 100644 --- a/clang/test/SemaCXX/function-type-qual.cpp +++ b/clang/test/SemaCXX/function-type-qual.cpp @@ -26,3 +26,6 @@ class C { void (C::*mpf)() const; cfn C::*mpg; + +// Don't crash! +void (PR14171)() const; // expected-error {{non-member function cannot have 'const' qualifier}}