summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-09-25 04:46:05 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-09-25 04:46:05 +0000
commit88d67f341279de9752f4471f6e887c56526e18d5 (patch)
tree782f415917a00721b6726e7c568a400e4b516edd /clang
parent2603a1876967aebb2a8319dfbc9f58d049ff60e7 (diff)
downloadbcm5719-llvm-88d67f341279de9752f4471f6e887c56526e18d5.tar.gz
bcm5719-llvm-88d67f341279de9752f4471f6e887c56526e18d5.zip
Fix crash when a decltype expression in a trailing return type refers to the
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! llvm-svn: 164586
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/Sema/Sema.h6
-rw-r--r--clang/lib/Sema/Sema.cpp1
-rw-r--r--clang/lib/Sema/SemaOverload.cpp23
-rw-r--r--clang/test/SemaCXX/trailing-return-0x.cpp16
4 files changed, 46 insertions, 0 deletions
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 74114a8d323..676f52953f3 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -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;
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index bd7c8515f64..08ccfa42598 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -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),
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index fe4cac86304..e9c2c6c5f66 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -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());
diff --git a/clang/test/SemaCXX/trailing-return-0x.cpp b/clang/test/SemaCXX/trailing-return-0x.cpp
index c219b77d9e4..462b4fa3da0 100644
--- a/clang/test/SemaCXX/trailing-return-0x.cpp
+++ b/clang/test/SemaCXX/trailing-return-0x.cpp
@@ -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'}}
+ }
+}
OpenPOWER on IntegriCloud