]> granicus.if.org Git - clang/commitdiff
Fix crash when a decltype expression in a trailing return type refers to the
authorRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 25 Sep 2012 04:46:05 +0000 (04:46 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 25 Sep 2012 04:46:05 +0000 (04:46 +0000)
function being instantiated. An error recovery codepath was recursively
performing name lookup (and triggering an unbounded stack of template
instantiations which blew out the stack before hitting the depth limit).

Patch by Wei Pan!

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@164586 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Sema/Sema.h
lib/Sema/Sema.cpp
lib/Sema/SemaOverload.cpp
test/SemaCXX/trailing-return-0x.cpp

index 74114a8d32325e23627671c912187a989650cbdd..676f52953f376db33a69369a61c4f9599e9d9947 100644 (file)
@@ -234,6 +234,12 @@ public:
   /// VisContext - Manages the stack for \#pragma GCC visibility.
   void *VisContext; // Really a "PragmaVisStack*"
 
+  /// \brief Flag indicating if Sema is building a recovery call expression.
+  ///
+  /// This flag is used to avoid building recovery call expressions
+  /// if Sema is already doing so, which would cause infinite recursions.
+  bool IsBuildingRecoveryCallExpr;
+
   /// ExprNeedsCleanups - True if the current evaluation context
   /// requires cleanups to be run at its conclusion.
   bool ExprNeedsCleanups;
index bd7c8515f64d413abbea057d376ddce7664eca65..08ccfa42598711aa90c287ee7af33875b8608ce6 100644 (file)
@@ -90,6 +90,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
     CollectStats(false), ExternalSource(0), CodeCompleter(CodeCompleter),
     CurContext(0), OriginalLexicalContext(0),
     PackContext(0), MSStructPragmaOn(false), VisContext(0),
+    IsBuildingRecoveryCallExpr(false),
     ExprNeedsCleanups(false), LateTemplateParser(0), OpaqueParser(0),
     IdResolver(pp), StdInitializerList(0), CXXTypeInfoDecl(0), MSVCGuidDecl(0),
     NSNumberDecl(0),
index fe4cac863049cd2cb1c64a2907288e76bcf38489..e9c2c6c5f666183e92265ca6d58c9737b897c218 100644 (file)
@@ -9655,6 +9655,20 @@ class NoTypoCorrectionCCC : public CorrectionCandidateCallback {
     return false;
   }
 };
+
+class BuildRecoveryCallExprRAII {
+  Sema &SemaRef;
+public:
+  BuildRecoveryCallExprRAII(Sema &S) : SemaRef(S) {
+    assert(SemaRef.IsBuildingRecoveryCallExpr == false);
+    SemaRef.IsBuildingRecoveryCallExpr = true;
+  }
+
+  ~BuildRecoveryCallExprRAII() {
+    SemaRef.IsBuildingRecoveryCallExpr = false;
+  }
+};
+
 }
 
 /// Attempts to recover from a call where no functions were found.
@@ -9667,6 +9681,15 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
                       llvm::MutableArrayRef<Expr *> Args,
                       SourceLocation RParenLoc,
                       bool EmptyLookup, bool AllowTypoCorrection) {
+  // Do not try to recover if it is already building a recovery call.
+  // This stops infinite loops for template instantiations like
+  //
+  // template <typename T> auto foo(T t) -> decltype(foo(t)) {}
+  // template <typename T> auto foo(T t) -> decltype(foo(&t)) {}
+  //
+  if (SemaRef.IsBuildingRecoveryCallExpr)
+    return ExprError();
+  BuildRecoveryCallExprRAII RCE(SemaRef);
 
   CXXScopeSpec SS;
   SS.Adopt(ULE->getQualifierLoc());
index c219b77d9e4d520b6fd36d12f3bb7b505884ad8a..462b4fa3da0999e28dc90783e1dca65c8733b33b 100644 (file)
@@ -69,3 +69,19 @@ X<int> xx;
 only<int> p2 = xx.f(0L);
 only<double> p3 = xx.g(0L, 1.0);
 only<double> p4 = xx.get_nested<double>().h(0L, 1.0, 3.14f);
+
+namespace PR12053 {
+  template <typename T>
+  auto f1(T t) -> decltype(f1(t)) {} // expected-note{{candidate template ignored}}
+  
+  void test_f1() {
+    f1(0); // expected-error{{no matching function for call to 'f1'}}
+  }
+  
+  template <typename T>
+  auto f2(T t) -> decltype(f2(&t)) {} // expected-note{{candidate template ignored}}
+  
+  void test_f2() {
+    f2(0); // expected-error{{no matching function for call to 'f2'}}
+  }
+}