diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExceptionSpec.cpp | 27 |
2 files changed, 29 insertions, 1 deletions
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 8fbe7833a1f..2e30c52df93 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -5281,7 +5281,8 @@ void Parser::ParseFunctionDeclarator(Declarator &D, // Parse exception-specification[opt]. bool Delayed = D.isFirstDeclarationOfMember() && - D.isFunctionDeclaratorAFunctionDeclaration(); + D.isFunctionDeclaratorAFunctionDeclaration() && + !Actions.isLibstdcxxEagerExceptionSpecHack(D); ESpecType = tryParseExceptionSpecification(Delayed, ESpecRange, DynamicExceptions, diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp index c35de6b8eda..7175c016734 100644 --- a/clang/lib/Sema/SemaExceptionSpec.cpp +++ b/clang/lib/Sema/SemaExceptionSpec.cpp @@ -35,6 +35,33 @@ static const FunctionProtoType *GetUnderlyingFunction(QualType T) return T->getAs<FunctionProtoType>(); } +/// HACK: libstdc++ has a bug where it shadows std::swap with a member +/// swap function then tries to call std::swap unqualified from the exception +/// specification of that function. This function detects whether we're in +/// such a case and turns off delay-parsing of exception specifications. +bool Sema::isLibstdcxxEagerExceptionSpecHack(const Declarator &D) { + auto *RD = dyn_cast<CXXRecordDecl>(CurContext); + + // All the problem cases are member functions named "swap" within class + // templates declared directly within namespace std. + if (!RD || RD->getEnclosingNamespaceContext() != getStdNamespace() || + !RD->getIdentifier() || !RD->getDescribedClassTemplate() || + !D.getIdentifier() || !D.getIdentifier()->isStr("swap")) + return false; + + // Only apply this hack within a system header. + if (!Context.getSourceManager().isInSystemHeader(D.getLocStart())) + return false; + + return llvm::StringSwitch<bool>(RD->getIdentifier()->getName()) + .Case("array", true) + .Case("pair", true) + .Case("priority_queue", true) + .Case("stack", true) + .Case("queue", true) + .Default(false); +} + /// CheckSpecifiedExceptionType - Check if the given type is valid in an /// exception specification. Incomplete types, or pointers to incomplete types /// other than void are not allowed. |