summaryrefslogtreecommitdiffstats
path: root/lib/Sema
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2017-12-21 20:50:39 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2017-12-21 20:50:39 +0000
commit0cfb502ef74bf3e9444debaad649f928179136be (patch)
treefa8cd15b0daf08df5f6753ea58c6fd797d5123c9 /lib/Sema
parentaf137029ce54502d43a9048fb8de191f94a53832 (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.cpp20
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);