forked from OSchip/llvm-project
Support accepting __gnu__ as a scoped attribute namespace that aliases to gnu.
This is useful in libstdc++ to avoid clashes with identifiers in the user's namespace. llvm-svn: 345132
This commit is contained in:
parent
c4a995c8e0
commit
ad672ffb64
|
@ -383,6 +383,11 @@ public:
|
|||
IdentifierInfo *getScopeName() const { return ScopeName; }
|
||||
SourceLocation getScopeLoc() const { return ScopeLoc; }
|
||||
|
||||
bool isGNUScope() const {
|
||||
return ScopeName &&
|
||||
(ScopeName->isStr("gnu") || ScopeName->isStr("__gnu__"));
|
||||
}
|
||||
|
||||
bool hasParsedType() const { return HasParsedType; }
|
||||
|
||||
/// Is this the Microsoft __declspec(property) attribute?
|
||||
|
|
|
@ -9,12 +9,17 @@ int clang::hasAttribute(AttrSyntax Syntax, const IdentifierInfo *Scope,
|
|||
const LangOptions &LangOpts) {
|
||||
StringRef Name = Attr->getName();
|
||||
// Normalize the attribute name, __foo__ becomes foo.
|
||||
if (Name.size() >= 4 && Name.startswith("__") && Name.endswith("__"))
|
||||
Name = Name.substr(2, Name.size() - 4);
|
||||
|
||||
#include "clang/Basic/AttrHasAttributeImpl.inc"
|
||||
|
||||
return 0;
|
||||
if (Name.size() >= 4 && Name.startswith("__") && Name.endswith("__"))
|
||||
Name = Name.substr(2, Name.size() - 4);
|
||||
|
||||
// Normalize the scope name, but only for gnu attributes.
|
||||
StringRef ScopeName = Scope ? Scope->getName() : "";
|
||||
if (ScopeName == "__gnu__")
|
||||
ScopeName = ScopeName.slice(2, ScopeName.size() - 2);
|
||||
|
||||
#include "clang/Basic/AttrHasAttributeImpl.inc"
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *attr::getSubjectMatchRuleSpelling(attr::SubjectMatchRule Rule) {
|
||||
|
|
|
@ -3865,13 +3865,14 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName,
|
|||
// Eat the left paren, then skip to the ending right paren.
|
||||
ConsumeParen();
|
||||
SkipUntil(tok::r_paren);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ScopeName && ScopeName->getName() == "gnu") {
|
||||
// GNU-scoped attributes have some special cases to handle GNU-specific
|
||||
// behaviors.
|
||||
ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ScopeName &&
|
||||
(ScopeName->getName() == "gnu" || ScopeName->getName() == "__gnu__")) {
|
||||
// GNU-scoped attributes have some special cases to handle GNU-specific
|
||||
// behaviors.
|
||||
ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
|
||||
ScopeLoc, Syntax, nullptr);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -103,14 +103,25 @@ void AttributePool::takePool(AttributePool &pool) {
|
|||
|
||||
#include "clang/Sema/AttrParsedAttrKinds.inc"
|
||||
|
||||
static StringRef normalizeAttrName(StringRef AttrName, StringRef ScopeName,
|
||||
static StringRef normalizeAttrScopeName(StringRef ScopeName,
|
||||
ParsedAttr::Syntax SyntaxUsed) {
|
||||
// We currently only normalize the "__gnu__" scope name to be "gnu".
|
||||
if ((SyntaxUsed == ParsedAttr::AS_CXX11 ||
|
||||
SyntaxUsed == ParsedAttr::AS_C2x) &&
|
||||
ScopeName == "__gnu__")
|
||||
ScopeName = ScopeName.slice(2, ScopeName.size() - 2);
|
||||
return ScopeName;
|
||||
}
|
||||
|
||||
static StringRef normalizeAttrName(StringRef AttrName,
|
||||
StringRef NormalizedScopeName,
|
||||
ParsedAttr::Syntax SyntaxUsed) {
|
||||
// Normalize the attribute name, __foo__ becomes foo. This is only allowable
|
||||
// for GNU attributes.
|
||||
// for GNU attributes, and attributes using the double square bracket syntax.
|
||||
bool IsGNU = SyntaxUsed == ParsedAttr::AS_GNU ||
|
||||
((SyntaxUsed == ParsedAttr::AS_CXX11 ||
|
||||
SyntaxUsed == ParsedAttr::AS_C2x) &&
|
||||
ScopeName == "gnu");
|
||||
NormalizedScopeName == "gnu");
|
||||
if (IsGNU && AttrName.size() >= 4 && AttrName.startswith("__") &&
|
||||
AttrName.endswith("__"))
|
||||
AttrName = AttrName.slice(2, AttrName.size() - 2);
|
||||
|
@ -125,7 +136,7 @@ ParsedAttr::Kind ParsedAttr::getKind(const IdentifierInfo *Name,
|
|||
|
||||
SmallString<64> FullName;
|
||||
if (ScopeName)
|
||||
FullName += ScopeName->getName();
|
||||
FullName += normalizeAttrScopeName(ScopeName->getName(), SyntaxUsed);
|
||||
|
||||
AttrName = normalizeAttrName(AttrName, FullName, SyntaxUsed);
|
||||
|
||||
|
@ -141,9 +152,10 @@ ParsedAttr::Kind ParsedAttr::getKind(const IdentifierInfo *Name,
|
|||
unsigned ParsedAttr::getAttributeSpellingListIndex() const {
|
||||
// Both variables will be used in tablegen generated
|
||||
// attribute spell list index matching code.
|
||||
StringRef Scope = ScopeName ? ScopeName->getName() : "";
|
||||
StringRef Name = normalizeAttrName(AttrName->getName(), Scope,
|
||||
(ParsedAttr::Syntax)SyntaxUsed);
|
||||
auto Syntax = static_cast<ParsedAttr::Syntax>(SyntaxUsed);
|
||||
StringRef Scope =
|
||||
ScopeName ? normalizeAttrScopeName(ScopeName->getName(), Syntax) : "";
|
||||
StringRef Name = normalizeAttrName(AttrName->getName(), Scope, Syntax);
|
||||
|
||||
#include "clang/Sema/AttrSpellingListIndex.inc"
|
||||
|
||||
|
|
|
@ -5831,16 +5831,14 @@ static void handleDeprecatedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
|
|||
if (AL.isDeclspecAttribute() || AL.isCXX11Attribute())
|
||||
checkAttributeAtMostNumArgs(S, AL, 1);
|
||||
else if (AL.isArgExpr(1) && AL.getArgAsExpr(1) &&
|
||||
!S.checkStringLiteralArgumentAttr(AL, 1, Replacement))
|
||||
return;
|
||||
|
||||
if (!S.getLangOpts().CPlusPlus14)
|
||||
if (AL.isCXX11Attribute() &&
|
||||
!(AL.hasScope() && AL.getScopeName()->isStr("gnu")))
|
||||
S.Diag(AL.getLoc(), diag::ext_cxx14_attr) << AL;
|
||||
|
||||
D->addAttr(::new (S.Context)
|
||||
DeprecatedAttr(AL.getRange(), S.Context, Str, Replacement,
|
||||
!S.checkStringLiteralArgumentAttr(AL, 1, Replacement))
|
||||
return;
|
||||
|
||||
if (!S.getLangOpts().CPlusPlus14 && AL.isCXX11Attribute() && !AL.isGNUScope())
|
||||
S.Diag(AL.getLoc(), diag::ext_cxx14_attr) << AL;
|
||||
|
||||
D->addAttr(::new (S.Context)
|
||||
DeprecatedAttr(AL.getRange(), S.Context, Str, Replacement,
|
||||
AL.getAttributeSpellingListIndex()));
|
||||
}
|
||||
|
||||
|
|
|
@ -7273,7 +7273,7 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
|
|||
// not appertain to a DeclaratorChunk. If we handle them as type
|
||||
// attributes, accept them in that position and diagnose the GCC
|
||||
// incompatibility.
|
||||
if (attr.getScopeName() && attr.getScopeName()->isStr("gnu")) {
|
||||
if (attr.isGNUScope()) {
|
||||
bool IsTypeAttr = attr.isTypeAttr();
|
||||
if (TAL == TAL_DeclChunk) {
|
||||
state.getSema().Diag(attr.getLoc(),
|
||||
|
|
|
@ -18,17 +18,21 @@
|
|||
// The attribute name can be bracketed with double underscores.
|
||||
// CHECK: has_clang_fallthrough_2
|
||||
#if __has_cpp_attribute(clang::__fallthrough__)
|
||||
int has_clang_fallthrough_2();
|
||||
#endif
|
||||
|
||||
// The scope cannot be bracketed with double underscores.
|
||||
// CHECK: does_not_have___clang___fallthrough
|
||||
#if !__has_cpp_attribute(__clang__::fallthrough)
|
||||
int does_not_have___clang___fallthrough();
|
||||
#endif
|
||||
|
||||
// Test that C++11, target-specific attributes behave properly.
|
||||
|
||||
int has_clang_fallthrough_2();
|
||||
#endif
|
||||
|
||||
// The scope cannot be bracketed with double underscores unless it is for gnu.
|
||||
// CHECK: does_not_have___clang___fallthrough
|
||||
#if !__has_cpp_attribute(__clang__::fallthrough)
|
||||
int does_not_have___clang___fallthrough();
|
||||
#endif
|
||||
// CHECK: has_gnu_const
|
||||
#if __has_cpp_attribute(__gnu__::__const__)
|
||||
int has_gnu_const();
|
||||
#endif
|
||||
|
||||
// Test that C++11, target-specific attributes behave properly.
|
||||
|
||||
// CHECK: does_not_have_mips16
|
||||
#if !__has_cpp_attribute(gnu::mips16)
|
||||
int does_not_have_mips16();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// RUN: %clang_cc1 -std=gnu++11 -fsyntax-only -fms-compatibility -verify %s
|
||||
|
||||
void f() {
|
||||
// GNU-style attributes are prohibited in this position.
|
||||
// RUN: %clang_cc1 -std=gnu++17 -fsyntax-only -fms-compatibility -verify %s
|
||||
|
||||
void f() {
|
||||
// GNU-style attributes are prohibited in this position.
|
||||
auto P = new int * __attribute__((vector_size(8))); // expected-error {{an attribute list cannot appear here}} \
|
||||
// expected-error {{invalid vector element type 'int *'}}
|
||||
|
||||
|
@ -40,6 +40,13 @@ void tuTest1(Tu<int> u); // expected-note {{candidate function not viable: no kn
|
|||
void tuTest2(Tu3 u); // expected-note {{candidate function not viable: no known conversion from 'int' to 'Tu3' for 1st argument}}
|
||||
void tu() {
|
||||
int x = 2;
|
||||
tuTest1(x); // expected-error {{no matching function for call to 'tuTest1'}}
|
||||
tuTest2(x); // expected-error {{no matching function for call to 'tuTest2'}}
|
||||
}
|
||||
tuTest1(x); // expected-error {{no matching function for call to 'tuTest1'}}
|
||||
tuTest2(x); // expected-error {{no matching function for call to 'tuTest2'}}
|
||||
}
|
||||
|
||||
[[gnu::__const__]] int f2() { return 12; }
|
||||
[[__gnu__::__const__]] int f3() { return 12; }
|
||||
[[using __gnu__ : __const__]] int f4() { return 12; }
|
||||
|
||||
static_assert(__has_cpp_attribute(gnu::__const__));
|
||||
static_assert(__has_cpp_attribute(__gnu__::__const__));
|
||||
|
|
|
@ -2932,15 +2932,15 @@ void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
|
|||
OS << "case AttrSyntax::" << Variety << ": {\n";
|
||||
// C++11-style attributes are further split out based on the Scope.
|
||||
for (auto I = List.cbegin(), E = List.cend(); I != E; ++I) {
|
||||
if (I != List.cbegin())
|
||||
OS << " else ";
|
||||
if (I->first.empty())
|
||||
OS << "if (!Scope || Scope->getName() == \"\") {\n";
|
||||
else
|
||||
OS << "if (Scope->getName() == \"" << I->first << "\") {\n";
|
||||
OS << " return llvm::StringSwitch<int>(Name)\n";
|
||||
GenerateHasAttrSpellingStringSwitch(I->second, OS, Spelling, I->first);
|
||||
OS << "}";
|
||||
if (I != List.cbegin())
|
||||
OS << " else ";
|
||||
if (I->first.empty())
|
||||
OS << "if (ScopeName == \"\") {\n";
|
||||
else
|
||||
OS << "if (ScopeName == \"" << I->first << "\") {\n";
|
||||
OS << " return llvm::StringSwitch<int>(Name)\n";
|
||||
GenerateHasAttrSpellingStringSwitch(I->second, OS, Spelling, I->first);
|
||||
OS << "}";
|
||||
}
|
||||
OS << "\n} break;\n";
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue