diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2014-11-14 00:37:55 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2014-11-14 00:37:55 +0000 |
commit | 6403e937d65dbd3c48ff52f1df6eb579f76d53e6 (patch) | |
tree | 8b5742ce3adb89dce49f19144294716dcccec416 /clang/lib/Sema/SemaExceptionSpec.cpp | |
parent | 283bc2ed28f423c29ab57a2b491d2ebdb53a4b12 (diff) | |
download | bcm5719-llvm-6403e937d65dbd3c48ff52f1df6eb579f76d53e6.tar.gz bcm5719-llvm-6403e937d65dbd3c48ff52f1df6eb579f76d53e6.zip |
PR21565 Add an egregious hack to support broken libstdc++ headers that declare
a member named 'swap' and then expect unqualified lookup for the name 'swap' in
its exception specification to find anything else.
Without delay-parsed exception specifications, this was ill-formed (NDR) by
[basic.scope.class]p1, rule 2. With delay-parsed exception specifications, the
call to 'swap' unambiguously finds the function being declared, which then
fails because the arguments don't work for that function.
llvm-svn: 221955
Diffstat (limited to 'clang/lib/Sema/SemaExceptionSpec.cpp')
-rw-r--r-- | clang/lib/Sema/SemaExceptionSpec.cpp | 27 |
1 files changed, 27 insertions, 0 deletions
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. |