forked from OSchip/llvm-project
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
This commit is contained in:
parent
742ac98d01
commit
f391db5228
|
@ -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);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// RUN: %clang_cc1 -verify -fsyntax-only -triple i386-linux -pedantic-errors -fcxx-exceptions -fexceptions %s
|
||||
// RUN: %clang_cc1 -verify -fsyntax-only -triple i386-linux -pedantic-errors -fcxx-exceptions -fexceptions -std=c++98 %s
|
||||
// RUN: %clang_cc1 -verify -fsyntax-only -triple i386-linux -pedantic-errors -fcxx-exceptions -fexceptions -std=c++11 %s
|
||||
// RUN: %clang_cc1 -verify -fsyntax-only -triple i386-linux -Wredundant-parens -pedantic-errors -fcxx-exceptions -fexceptions %s
|
||||
// RUN: %clang_cc1 -verify -fsyntax-only -triple i386-linux -Wredundant-parens -pedantic-errors -fcxx-exceptions -fexceptions -std=c++98 %s
|
||||
// RUN: %clang_cc1 -verify -fsyntax-only -triple i386-linux -Wredundant-parens -pedantic-errors -fcxx-exceptions -fexceptions -std=c++11 %s
|
||||
|
||||
const char const *x10; // expected-error {{duplicate 'const' declaration specifier}}
|
||||
|
||||
|
@ -83,7 +83,7 @@ namespace Commas {
|
|||
|
||||
int global1,
|
||||
__attribute__(()) global2,
|
||||
(global5),
|
||||
(global5), // expected-warning {{redundant parentheses surrounding declarator}}
|
||||
*global6,
|
||||
&global7 = global1,
|
||||
&&global8 = static_cast<int&&>(global1),
|
||||
|
@ -263,6 +263,25 @@ namespace DuplicateFriend {
|
|||
};
|
||||
}
|
||||
|
||||
namespace NNS {
|
||||
struct A {};
|
||||
namespace B { extern A C1, C2, *C3, C4[], C5; }
|
||||
// Do not produce a redundant parentheses warning here; removing these parens
|
||||
// changes the meaning of the program.
|
||||
A (::NNS::B::C1);
|
||||
A (NNS::B::C2); // expected-warning {{redundant parentheses surrounding declarator}}
|
||||
A (*::NNS::B::C3); // expected-warning {{redundant parentheses surrounding declarator}}
|
||||
A (::NNS::B::C4[2]);
|
||||
// Removing one of these sets of parentheses would be reasonable.
|
||||
A ((::NNS::B::C5)); // expected-warning {{redundant parentheses surrounding declarator}}
|
||||
|
||||
void f() {
|
||||
// FIXME: A vexing-parse warning here would be useful.
|
||||
A(::NNS::B::C1); // expected-error {{definition or redeclaration}}
|
||||
A(NNS::B::C1); // expected-warning {{redundant paren}} expected-error {{definition or redeclaration}}
|
||||
}
|
||||
}
|
||||
|
||||
// PR8380
|
||||
extern "" // expected-error {{unknown linkage language}}
|
||||
test6a { ;// expected-error {{C++ requires a type specifier for all declarations}}
|
||||
|
|
Loading…
Reference in New Issue