}
def FallThrough : Attr {
- let Spellings = ["clang___fallthrough"];
- let Subjects = [CaseStmt, DefaultStmt];
+ let Namespaces = ["clang"];
+ let Spellings = ["fallthrough"];
+ let Subjects = [NullStmt];
}
def FastCall : InheritableAttr {
def VirtualInheritance : InheritableAttr {
let Spellings = ["__virtual_inheritance"];
-}
\ No newline at end of file
+}
/// 4: __attribute__(( aligned(16) )). ParmName is unused, Args/Num used.
///
class AttributeList { // TODO: This should really be called ParsedAttribute
+public:
+ /// The style used to specify an attribute.
+ enum Syntax {
+ AS_GNU,
+ AS_CXX11,
+ AS_Declspec
+ };
private:
IdentifierInfo *AttrName;
IdentifierInfo *ScopeName;
/// The expressions themselves are stored after the object.
unsigned NumArgs : 16;
- /// True if Microsoft style: declspec(foo).
- unsigned DeclspecAttribute : 1;
-
- /// True if C++0x-style: [[foo]].
- unsigned CXX0XAttribute : 1;
+ /// Corresponds to the Syntax enum.
+ unsigned SyntaxUsed : 2;
/// True if already diagnosed as invalid.
mutable unsigned Invalid : 1;
IdentifierInfo *scopeName, SourceLocation scopeLoc,
IdentifierInfo *parmName, SourceLocation parmLoc,
Expr **args, unsigned numArgs,
- bool declspec, bool cxx0x)
+ Syntax syntaxUsed)
: AttrName(attrName), ScopeName(scopeName), ParmName(parmName),
AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc),
- NumArgs(numArgs),
- DeclspecAttribute(declspec), CXX0XAttribute(cxx0x), Invalid(false),
+ NumArgs(numArgs), SyntaxUsed(syntaxUsed), Invalid(false),
UsedAsTypeAttr(false), IsAvailability(false),
NextInPosition(0), NextInPool(0) {
if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(Expr*));
- AttrKind = getKind(getName(), getScopeName());
+ AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
}
AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
const AvailabilityChange &obsoleted,
SourceLocation unavailable,
const Expr *messageExpr,
- bool declspec, bool cxx0x)
+ Syntax syntaxUsed)
: AttrName(attrName), ScopeName(scopeName), ParmName(parmName),
AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc),
- NumArgs(0), DeclspecAttribute(declspec), CXX0XAttribute(cxx0x),
+ NumArgs(0), SyntaxUsed(syntaxUsed),
Invalid(false), UsedAsTypeAttr(false), IsAvailability(true),
UnavailableLoc(unavailable), MessageExpr(messageExpr),
NextInPosition(0), NextInPool(0) {
new (&getAvailabilitySlot(IntroducedSlot)) AvailabilityChange(introduced);
new (&getAvailabilitySlot(DeprecatedSlot)) AvailabilityChange(deprecated);
new (&getAvailabilitySlot(ObsoletedSlot)) AvailabilityChange(obsoleted);
- AttrKind = getKind(getName(), getScopeName());
+ AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
}
friend class AttributePool;
IdentifierInfo *getParameterName() const { return ParmName; }
SourceLocation getParameterLoc() const { return ParmLoc; }
- bool isDeclspecAttribute() const { return DeclspecAttribute; }
- bool isCXX0XAttribute() const { return CXX0XAttribute; }
+ bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec; }
+ bool isCXX0XAttribute() const { return SyntaxUsed == AS_CXX11; }
bool isInvalid() const { return Invalid; }
void setInvalid(bool b = true) const { Invalid = b; }
void setUsedAsTypeAttr() { UsedAsTypeAttr = true; }
Kind getKind() const { return Kind(AttrKind); }
- static Kind getKind(const IdentifierInfo *Name, const IdentifierInfo *Scope);
+ static Kind getKind(const IdentifierInfo *Name, const IdentifierInfo *Scope,
+ Syntax SyntaxUsed);
AttributeList *getNext() const { return NextInPosition; }
void setNext(AttributeList *N) { NextInPosition = N; }
IdentifierInfo *scopeName, SourceLocation scopeLoc,
IdentifierInfo *parmName, SourceLocation parmLoc,
Expr **args, unsigned numArgs,
- bool declspec = false, bool cxx0x = false) {
+ AttributeList::Syntax syntax) {
void *memory = allocate(sizeof(AttributeList)
+ numArgs * sizeof(Expr*));
return add(new (memory) AttributeList(attrName, attrRange,
scopeName, scopeLoc,
parmName, parmLoc,
- args, numArgs,
- declspec, cxx0x));
+ args, numArgs, syntax));
}
AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange,
const AvailabilityChange &obsoleted,
SourceLocation unavailable,
const Expr *MessageExpr,
- bool declspec = false, bool cxx0x = false) {
+ AttributeList::Syntax syntax) {
void *memory = allocate(AttributeFactory::AvailabilityAllocSize);
return add(new (memory) AttributeList(attrName, attrRange,
scopeName, scopeLoc,
parmName, parmLoc,
introduced, deprecated, obsoleted,
- unavailable, MessageExpr,
- declspec, cxx0x));
+ unavailable, MessageExpr, syntax));
}
AttributeList *createIntegerAttribute(ASTContext &C, IdentifierInfo *Name,
IdentifierInfo *scopeName, SourceLocation scopeLoc,
IdentifierInfo *parmName, SourceLocation parmLoc,
Expr **args, unsigned numArgs,
- bool declspec = false, bool cxx0x = false) {
+ AttributeList::Syntax syntax) {
AttributeList *attr =
pool.create(attrName, attrRange, scopeName, scopeLoc, parmName, parmLoc,
- args, numArgs, declspec, cxx0x);
+ args, numArgs, syntax);
add(attr);
return attr;
}
const AvailabilityChange &obsoleted,
SourceLocation unavailable,
const Expr *MessageExpr,
- bool declspec = false, bool cxx0x = false) {
+ AttributeList::Syntax syntax) {
AttributeList *attr =
pool.create(attrName, attrRange, scopeName, scopeLoc, parmName, parmLoc,
introduced, deprecated, obsoleted, unavailable,
- MessageExpr,
- declspec, cxx0x);
+ MessageExpr, syntax);
add(attr);
return attr;
}
}
} else {
attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc,
- 0, SourceLocation(), 0, 0);
+ 0, SourceLocation(), 0, 0, AttributeList::AS_GNU);
}
}
if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen))
if (!ExpectAndConsume(tok::r_paren, diag::err_expected_rparen)) {
AttributeList *attr =
Attrs.addNew(AttrName, SourceRange(AttrNameLoc, RParen), 0, AttrNameLoc,
- ParmName, ParmLoc, ArgExprs.take(), ArgExprs.size());
+ ParmName, ParmLoc, ArgExprs.take(), ArgExprs.size(),
+ AttributeList::AS_GNU);
if (BuiltinType && attr->getKind() == AttributeList::AT_iboutletcollection)
Diag(Tok, diag::err_iboutletcollection_builtintype);
}
if (!ArgExpr.isInvalid()) {
Expr *ExprList = ArgExpr.take();
attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
- SourceLocation(), &ExprList, 1, true);
+ SourceLocation(), &ExprList, 1,
+ AttributeList::AS_Declspec);
}
if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen))
SkipUntil(tok::r_paren, false);
} else {
attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc,
- 0, SourceLocation(), 0, 0, true);
+ 0, SourceLocation(), 0, 0, AttributeList::AS_Declspec);
}
}
if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen))
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
SourceLocation AttrNameLoc = ConsumeToken();
attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
- SourceLocation(), 0, 0, true);
+ SourceLocation(), 0, 0, AttributeList::AS_Declspec);
}
}
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
SourceLocation AttrNameLoc = ConsumeToken();
attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
- SourceLocation(), 0, 0, true);
+ SourceLocation(), 0, 0, AttributeList::AS_Declspec);
}
}
SourceLocation AttrNameLoc = ConsumeToken();
attrs.addNew(PP.getIdentifierInfo("opencl_kernel_function"),
AttrNameLoc, 0, AttrNameLoc, 0,
- SourceLocation(), 0, 0, false);
+ SourceLocation(), 0, 0, AttributeList::AS_GNU);
}
}
Changes[Deprecated],
Changes[Obsoleted],
UnavailableLoc, MessageExpr.take(),
- false, false);
+ AttributeList::AS_GNU);
}
// Match the ')'.
if (ArgExprsOk && !T.consumeClose()) {
Attrs.addNew(&AttrName, AttrNameLoc, 0, AttrNameLoc, 0, SourceLocation(),
- ArgExprs.take(), ArgExprs.size());
+ ArgExprs.take(), ArgExprs.size(), AttributeList::AS_GNU);
}
if (EndLoc)
*EndLoc = T.getCloseLocation();
ExprVector ArgExprs(Actions);
ArgExprs.push_back(ArgExpr.release());
Attrs.addNew(PP.getIdentifierInfo("aligned"), KWLoc, 0, KWLoc,
- 0, T.getOpenLocation(), ArgExprs.take(), 1, false, true);
+ 0, T.getOpenLocation(), ArgExprs.take(), 1,
+ AttributeList::AS_CXX11);
}
/// ParseDeclarationSpecifiers
isInvalid = DS.SetFunctionSpecInline(Loc, PrevSpec, DiagID);
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
SourceLocation AttrNameLoc = ConsumeToken();
+ // FIXME: This does not work correctly if it is set to be a declspec
+ // attribute, and a GNU attribute is simply incorrect.
DS.getAttributes().addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
- SourceLocation(), 0, 0);
+ SourceLocation(), 0, 0, AttributeList::AS_GNU);
continue;
}
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
SourceLocation AttrNameLoc = ConsumeToken();
attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
- SourceLocation(), 0, 0, false);
+ SourceLocation(), 0, 0, AttributeList::AS_GNU);
}
}
}
bool AttrParsed = false;
- switch (AttributeList::getKind(AttrName, ScopeName)) {
+ switch (AttributeList::getKind(AttrName, ScopeName,
+ AttributeList::AS_CXX11)) {
// No arguments
case AttributeList::AT_carries_dependency:
// FIXME: implement generic support of attributes with C++11 syntax
// see Parse/ParseDecl.cpp: ParseGNUAttributes
- case AttributeList::AT_clang___fallthrough:
+ case AttributeList::AT_fallthrough:
case AttributeList::AT_noreturn: {
if (Tok.is(tok::l_paren)) {
Diag(Tok.getLocation(), diag::err_cxx11_attribute_forbids_arguments)
SourceRange(ScopeLoc.isValid() ? ScopeLoc : AttrLoc,
AttrLoc),
ScopeName, ScopeLoc, 0,
- SourceLocation(), 0, 0, false, true);
+ SourceLocation(), 0, 0, AttributeList::AS_CXX11);
AttrParsed = true;
break;
}
SourceLocation TokLoc, int Arg) {
Expr *IArg = IntegerLiteral::Create(C, llvm::APInt(32, (uint64_t) Arg),
C.IntTy, TokLoc);
- return create(Name, TokLoc, 0, TokLoc, 0, TokLoc, &IArg, 1, 0);
+ return create(Name, TokLoc, 0, TokLoc, 0, TokLoc, &IArg, 1,
+ AttributeList::AS_GNU);
}
#include "clang/Sema/AttrParsedAttrKinds.inc"
AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name,
- const IdentifierInfo *ScopeName) {
+ const IdentifierInfo *ScopeName,
+ Syntax SyntaxUsed) {
StringRef AttrName = Name->getName();
// Normalize the attribute name, __foo__ becomes foo.
AttrName.size() >= 4)
AttrName = AttrName.substr(2, AttrName.size() - 4);
- // FIXME: implement attribute namespacing correctly.
SmallString<64> Buf;
if (ScopeName)
- AttrName = ((Buf += ScopeName->getName()) += "___") += AttrName;
-
- return ::getAttrKind(AttrName);
+ Buf += ScopeName->getName();
+ // Ensure that in the case of C++11 attributes, we look for '::foo' if it is
+ // unscoped.
+ if (ScopeName || SyntaxUsed == AS_CXX11)
+ Buf += "::";
+ Buf += AttrName;
+
+ return ::getAttrKind(Buf);
}
static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const AttributeList &A,
SourceRange Range) {
switch (A.getKind()) {
- case AttributeList::AT_clang___fallthrough:
+ case AttributeList::AT_fallthrough:
return handleFallThroughAttr(S, St, A, Range);
default:
// if we're here, then we parsed an attribute, but didn't recognize it as a
.create(&S.Context.Idents.get("objc_ownership"), SourceLocation(),
/*scope*/ 0, SourceLocation(),
&S.Context.Idents.get(attrStr), SourceLocation(),
- /*args*/ 0, 0,
- /*declspec*/ false, /*C++0x*/ false);
+ /*args*/ 0, 0, AttributeList::AS_GNU);
spliceAttrIntoList(*attr, chunk.getAttrListRef());
// TODO: mark whether we did this inference?
}
return n;
}
+
+void unscoped(int n) {
+ switch (n % 2) {
+ case 0:
+ // FIXME: This should be typo-corrected, probably.
+ [[fallthrough]];
+ case 2: // expected-warning{{unannotated fall-through}} expected-note{{clang::fallthrough}} expected-note{{break;}}
+ [[clang::fallthrough]];
+ case 1:
+ break;
+ }
+}
//
//===----------------------------------------------------------------------===//
+#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/StringMatcher.h"
if (SemaHandler || Ignored) {
std::vector<StringRef> Spellings =
getValueAsListOfStrings(Attr, "Spellings");
+ std::vector<StringRef> Namespaces =
+ getValueAsListOfStrings(Attr, "Namespaces");
for (std::vector<StringRef>::const_iterator I = Spellings.begin(),
E = Spellings.end(); I != E; ++I) {
: Spellings.front());
StringRef Spelling = NormalizeAttrSpelling(*I);
+ for (std::vector<StringRef>::const_iterator NI = Namespaces.begin(),
+ NE = Namespaces.end(); NI != NE; ++NI) {
+ SmallString<64> Buf;
+ Buf += *NI;
+ Buf += "::";
+ Buf += Spelling;
+
+ if (SemaHandler)
+ Matches.push_back(
+ StringMatcher::StringPair(
+ Buf.str(),
+ "return AttributeList::AT_" + AttrName.str() + ";"));
+ else
+ Matches.push_back(
+ StringMatcher::StringPair(
+ Buf.str(),
+ "return AttributeList::IgnoredAttribute;"));
+ }
+
if (SemaHandler)
Matches.push_back(
StringMatcher::StringPair(
Spelling,
- std::string("return AttributeList::AT_")+AttrName.str() + ";"));
+ "return AttributeList::AT_" + AttrName.str() + ";"));
else
Matches.push_back(
StringMatcher::StringPair(
Spelling,
- std::string("return AttributeList::IgnoredAttribute;")));
+ "return AttributeList::IgnoredAttribute;"));
}
}
}