From 3312933e244d820c1c6fec83c4c0c0f67f42d25b Mon Sep 17 00:00:00 2001 From: Wei Pan Date: Mon, 16 Sep 2013 13:57:27 +0000 Subject: [PATCH] Handle PredefinedExpr with templates and lambdas Summary: - lambdas, blocks or captured statements in templates were not handled which causes codegen crashes. Differential Revision: http://llvm-reviews.chandlerc.com/D1628 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@190784 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Sema/Sema.h | 2 ++ lib/Sema/SemaExpr.cpp | 41 ++++++++++++++++------------ lib/Sema/SemaTemplateInstantiate.cpp | 20 +------------- test/CodeGenCXX/predefined-expr.cpp | 22 +++++++++++++++ test/SemaCXX/predefined-expr.cpp | 38 ++++++++++++++++++++++++++ 5 files changed, 86 insertions(+), 37 deletions(-) diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index d6ce4d932e..ad27b3fd3f 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -3236,6 +3236,8 @@ public: SourceLocation LitEndLoc, TemplateArgumentListInfo *ExplicitTemplateArgs = 0); + ExprResult BuildPredefinedExpr(SourceLocation Loc, + PredefinedExpr::IdentType IT); ExprResult ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind); ExprResult ActOnIntegerConstant(SourceLocation Loc, uint64_t Val); ExprResult ActOnNumericConstant(const Token &Tok, Scope *UDLScope = 0); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 4e2e24eab4..10d384b8d8 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -2745,22 +2745,10 @@ ExprResult Sema::BuildDeclarationNameExpr( } } -ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) { - PredefinedExpr::IdentType IT; - - switch (Kind) { - default: llvm_unreachable("Unknown simple primary expr!"); - case tok::kw___func__: IT = PredefinedExpr::Func; break; // [C99 6.4.2.2] - case tok::kw___FUNCTION__: IT = PredefinedExpr::Function; break; - case tok::kw_L__FUNCTION__: IT = PredefinedExpr::LFunction; break; - case tok::kw___PRETTY_FUNCTION__: IT = PredefinedExpr::PrettyFunction; break; - } - - // Pre-defined identifiers are of type char[x], where x is the length of the - // string. - - // Pick the current block, lambda or function. - Decl *currentDecl; +ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc, + PredefinedExpr::IdentType IT) { + // Pick the current block, lambda, captured statement or function. + Decl *currentDecl = 0; if (const BlockScopeInfo *BSI = getCurBlock()) currentDecl = BSI->TheDecl; else if (const LambdaScopeInfo *LSI = getCurLambda()) @@ -2776,9 +2764,11 @@ ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) { } QualType ResTy; - if (cast(currentDecl)->isDependentContext()) { + if (cast(currentDecl)->isDependentContext()) ResTy = Context.DependentTy; - } else { + else { + // Pre-defined identifiers are of type char[x], where x is the length of + // the string. unsigned Length = PredefinedExpr::ComputeName(IT, currentDecl).length(); llvm::APInt LengthI(32, Length + 1); @@ -2788,9 +2778,24 @@ ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) { ResTy = Context.CharTy.withConst(); ResTy = Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal, 0); } + return Owned(new (Context) PredefinedExpr(Loc, ResTy, IT)); } +ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) { + PredefinedExpr::IdentType IT; + + switch (Kind) { + default: llvm_unreachable("Unknown simple primary expr!"); + case tok::kw___func__: IT = PredefinedExpr::Func; break; // [C99 6.4.2.2] + case tok::kw___FUNCTION__: IT = PredefinedExpr::Function; break; + case tok::kw_L__FUNCTION__: IT = PredefinedExpr::LFunction; break; + case tok::kw___PRETTY_FUNCTION__: IT = PredefinedExpr::PrettyFunction; break; + } + + return BuildPredefinedExpr(Loc, IT); +} + ExprResult Sema::ActOnCharacterConstant(const Token &Tok, Scope *UDLScope) { SmallString<16> CharBuffer; bool Invalid = false; diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 9b7b4a8596..dd10cbe2b7 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -1149,25 +1149,7 @@ TemplateInstantiator::TransformPredefinedExpr(PredefinedExpr *E) { if (!E->isTypeDependent()) return SemaRef.Owned(E); - FunctionDecl *currentDecl = getSema().getCurFunctionDecl(); - assert(currentDecl && "Must have current function declaration when " - "instantiating."); - - PredefinedExpr::IdentType IT = E->getIdentType(); - - unsigned Length = PredefinedExpr::ComputeName(IT, currentDecl).length(); - - llvm::APInt LengthI(32, Length + 1); - QualType ResTy; - if (IT == PredefinedExpr::LFunction) - ResTy = getSema().Context.WideCharTy.withConst(); - else - ResTy = getSema().Context.CharTy.withConst(); - ResTy = getSema().Context.getConstantArrayType(ResTy, LengthI, - ArrayType::Normal, 0); - PredefinedExpr *PE = - new (getSema().Context) PredefinedExpr(E->getLocation(), ResTy, IT); - return getSema().Owned(PE); + return getSema().BuildPredefinedExpr(E->getLocation(), E->getIdentType()); } ExprResult diff --git a/test/CodeGenCXX/predefined-expr.cpp b/test/CodeGenCXX/predefined-expr.cpp index 24ead8f8f4..9062ee095c 100644 --- a/test/CodeGenCXX/predefined-expr.cpp +++ b/test/CodeGenCXX/predefined-expr.cpp @@ -9,6 +9,8 @@ // CHECK: private unnamed_addr constant [57 x i8] c"void NonTypeTemplateParam<42>::size() const [Count = 42]\00" // CHECK: private unnamed_addr constant [122 x i8] c"static void ClassWithTemplateTemplateParam::staticMember() [T = char, Param = NS::ClassTemplate]\00" // CHECK: private unnamed_addr constant [106 x i8] c"void OuterClass::MiddleClass::InnerClass::memberFunction(T, U) const [T = int *, U = float]\00" +// CHECK: private unnamed_addr constant [51 x i8] c"void functionTemplateWithCapturedStmt(T) [T = int]\00" +// CHECK: private unnamed_addr constant [76 x i8] c"auto functionTemplateWithLambda(int)::::operator()() const\00" // CHECK: private unnamed_addr constant [65 x i8] c"void functionTemplateWithUnnamedTemplateParameter(T) [T = float]\00" // CHECK: private unnamed_addr constant [60 x i8] c"void functionTemplateExplicitSpecialization(T) [T = double]\00" @@ -375,6 +377,23 @@ void functionTemplateWithUnnamedTemplateParameter(T t) printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); } +template +void functionTemplateWithLambda(T t) +{ + []() { + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + } (); +} + +template +void functionTemplateWithCapturedStmt(T t) +{ + #pragma clang __debug captured + { + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + } +} + template class OuterClass { @@ -500,6 +519,9 @@ int main() { functionTemplateExplicitSpecialization(0.0); functionTemplateWithUnnamedTemplateParameter(0.0f); + functionTemplateWithLambda(0); + functionTemplateWithCapturedStmt(0); + OuterClass::MiddleClass::InnerClass omi; omi.memberFunction(0, 0.0f); diff --git a/test/SemaCXX/predefined-expr.cpp b/test/SemaCXX/predefined-expr.cpp index e203dd4be8..257d44c600 100644 --- a/test/SemaCXX/predefined-expr.cpp +++ b/test/SemaCXX/predefined-expr.cpp @@ -16,6 +16,40 @@ auto bar() -> decltype(42) { return 0; } +// Within templates. +template +int baz() { + static_assert(sizeof(__func__) == 4, "baz"); + static_assert(sizeof(__FUNCTION__) == 4, "baz"); + static_assert(sizeof(__PRETTY_FUNCTION__) == 20, "int baz() [T = int]"); + + []() { + static_assert(sizeof(__func__) == 11, "operator()"); + static_assert(sizeof(__FUNCTION__) == 11, "operator()"); + static_assert(sizeof(__PRETTY_FUNCTION__) == 50, + "auto baz()::::operator()() const"); + return 0; + } + (); + + ^{ + // FIXME: This is obviously wrong. + static_assert(sizeof(__func__) == 1, "__baz_block_invoke"); + static_assert(sizeof(__FUNCTION__) == 1, "__baz_block_invoke"); + static_assert(sizeof(__PRETTY_FUNCTION__) == 1, "__baz_block_invoke"); + } + (); + + #pragma clang __debug captured + { + static_assert(sizeof(__func__) == 4, "baz"); + static_assert(sizeof(__FUNCTION__) == 4, "baz"); + static_assert(sizeof(__PRETTY_FUNCTION__) == 20, "int baz() [T = int]"); + } + + return 0; +} + int main() { static_assert(sizeof(__func__) == 5, "main"); static_assert(sizeof(__FUNCTION__) == 5, "main"); @@ -62,4 +96,8 @@ int main() { } } (); + + baz(); + + return 0; } -- 2.40.0