diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2017-12-21 20:50:39 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2017-12-21 20:50:39 +0000 |
commit | f391db52284c655a891c2c06787ea4e58ea7ef6a (patch) | |
tree | 8c531571d86af2d312b2c51c50990118c52d9634 /clang/lib/Sema | |
parent | 742ac98d013b77569645134441ffb05ff66052bd (diff) | |
download | bcm5719-llvm-f391db52284c655a891c2c06787ea4e58ea7ef6a.tar.gz bcm5719-llvm-f391db52284c655a891c2c06787ea4e58ea7ef6a.zip |
Don't produce redundant parentheses warning for "A (::B);" and the like.
The parentheses here are not redundant as they affect the binding of the
'::' token.
llvm-svn: 321304
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaType.cpp | 20 |
1 files changed, 19 insertions, 1 deletions
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 7a50f542a39..b45d31c6b1e 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -3137,10 +3137,14 @@ static void warnAboutRedundantParens(Sema &S, Declarator &D, QualType T) { (T->isRecordType() || T->isDependentType()) && D.getDeclSpec().getTypeQualifiers() == 0 && D.isFirstDeclarator(); + bool StartsWithDeclaratorId = true; for (auto &C : D.type_objects()) { switch (C.Kind) { - case DeclaratorChunk::Pointer: case DeclaratorChunk::Paren: + if (&C == &Paren) + continue; + case DeclaratorChunk::Pointer: + StartsWithDeclaratorId = false; continue; case DeclaratorChunk::Array: @@ -3154,6 +3158,7 @@ static void warnAboutRedundantParens(Sema &S, Declarator &D, QualType T) { // We assume that something like 'T (&x) = y;' is highly likely to not // be intended to be a temporary object. CouldBeTemporaryObject = false; + StartsWithDeclaratorId = false; continue; case DeclaratorChunk::Function: @@ -3166,6 +3171,7 @@ static void warnAboutRedundantParens(Sema &S, Declarator &D, QualType T) { case DeclaratorChunk::Pipe: // These cannot appear in expressions. CouldBeTemporaryObject = false; + StartsWithDeclaratorId = false; continue; } } @@ -3186,6 +3192,18 @@ static void warnAboutRedundantParens(Sema &S, Declarator &D, QualType T) { SourceRange ParenRange(Paren.Loc, Paren.EndLoc); if (!CouldBeTemporaryObject) { + // If we have A (::B), the parentheses affect the meaning of the program. + // Suppress the warning in that case. Don't bother looking at the DeclSpec + // here: even (e.g.) "int ::x" is visually ambiguous even though it's + // formally unambiguous. + if (StartsWithDeclaratorId && D.getCXXScopeSpec().isValid()) { + for (NestedNameSpecifier *NNS = D.getCXXScopeSpec().getScopeRep(); NNS; + NNS = NNS->getPrefix()) { + if (NNS->getKind() == NestedNameSpecifier::Global) + return; + } + } + S.Diag(Paren.Loc, diag::warn_redundant_parens_around_declarator) << ParenRange << FixItHint::CreateRemoval(Paren.Loc) << FixItHint::CreateRemoval(Paren.EndLoc); |