r190784 - Handle PredefinedExpr with templates and lambdas

Wei Pan wei.pan at intel.com
Mon Sep 16 06:57:27 PDT 2013


Author: wpan
Date: Mon Sep 16 08:57:27 2013
New Revision: 190784

URL: http://llvm.org/viewvc/llvm-project?rev=190784&view=rev
Log:
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


Modified:
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/test/CodeGenCXX/predefined-expr.cpp
    cfe/trunk/test/SemaCXX/predefined-expr.cpp

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=190784&r1=190783&r2=190784&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Mon Sep 16 08:57:27 2013
@@ -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);

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=190784&r1=190783&r2=190784&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Sep 16 08:57:27 2013
@@ -2745,22 +2745,10 @@ ExprResult Sema::BuildDeclarationNameExp
   }
 }
 
-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(Sou
   }
 
   QualType ResTy;
-  if (cast<DeclContext>(currentDecl)->isDependentContext()) {
+  if (cast<DeclContext>(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(Sou
       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;

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=190784&r1=190783&r2=190784&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Mon Sep 16 08:57:27 2013
@@ -1149,25 +1149,7 @@ TemplateInstantiator::TransformPredefine
   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

Modified: cfe/trunk/test/CodeGenCXX/predefined-expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/predefined-expr.cpp?rev=190784&r1=190783&r2=190784&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/predefined-expr.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/predefined-expr.cpp Mon Sep 16 08:57:27 2013
@@ -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<char, NS::ClassTemplate>::staticMember() [T = char, Param = NS::ClassTemplate]\00"
 // CHECK: private unnamed_addr constant [106 x i8] c"void OuterClass<int *>::MiddleClass::InnerClass<float>::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)::<anonymous class>::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"
@@ -376,6 +378,23 @@ void functionTemplateWithUnnamedTemplate
 }
 
 template <typename T>
+void functionTemplateWithLambda(T t)
+{
+  []() {
+    printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
+  } ();
+}
+
+template <typename T>
+void functionTemplateWithCapturedStmt(T t)
+{
+  #pragma clang __debug captured
+  {
+    printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
+  }
+}
+
+template <typename T>
 class OuterClass
 {
 public:
@@ -500,6 +519,9 @@ int main() {
   functionTemplateExplicitSpecialization(0.0);
   functionTemplateWithUnnamedTemplateParameter<int, float>(0.0f);
 
+  functionTemplateWithLambda<int>(0);
+  functionTemplateWithCapturedStmt<int>(0);
+
   OuterClass<int *>::MiddleClass::InnerClass<float> omi;
   omi.memberFunction(0, 0.0f);
 

Modified: cfe/trunk/test/SemaCXX/predefined-expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/predefined-expr.cpp?rev=190784&r1=190783&r2=190784&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/predefined-expr.cpp (original)
+++ cfe/trunk/test/SemaCXX/predefined-expr.cpp Mon Sep 16 08:57:27 2013
@@ -16,6 +16,40 @@ auto bar() -> decltype(42) {
   return 0;
 }
 
+// Within templates.
+template <typename T>
+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()::<anonymous class>::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<int>();
+
+  return 0;
 }





More information about the cfe-commits mailing list