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 | 0cfb502ef74bf3e9444debaad649f928179136be (patch) | |
tree | fa8cd15b0daf08df5f6753ea58c6fd797d5123c9 /lib/Sema | |
parent | af137029ce54502d43a9048fb8de191f94a53832 (diff) |
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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@321304 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/SemaType.cpp | 20 |
1 files changed, 19 insertions, 1 deletions
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 7a50f542a3..b45d31c6b1 100644 --- a/lib/Sema/SemaType.cpp +++ b/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); |