[cfe-commits] r89543 - in /cfe/trunk: include/clang/AST/ include/clang/Basic/ include/clang/Parse/ lib/AST/ lib/CodeGen/ lib/Frontend/ lib/Parse/ lib/Sema/ test/Parser/ test/SemaCXX/
Sean Hunt
rideau3 at gmail.com
Sat Nov 21 00:43:18 PST 2009
Author: coppro
Date: Sat Nov 21 02:43:09 2009
New Revision: 89543
URL: http://llvm.org/viewvc/llvm-project?rev=89543&view=rev
Log:
Added rudimentary C++0x attribute support.
The following attributes are currently supported in C++0x attribute
lists (and in GNU ones as well):
- align() - semantics believed to be conformant to n3000, except for
redeclarations and what entities it may apply to
- final - semantics believed to be conformant to CWG issue 817's proposed
wording, except for redeclarations
- noreturn - semantics believed to be conformant to n3000, except for
redeclarations
- carries_dependency - currently ignored (this is an optimization hint)
Added:
cfe/trunk/test/Parser/cxx0x-attributes.cpp
cfe/trunk/test/SemaCXX/attr-cxx0x.cpp
Modified:
cfe/trunk/include/clang/AST/Attr.h
cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/include/clang/Parse/AttributeList.h
cfe/trunk/include/clang/Parse/Parser.h
cfe/trunk/lib/AST/ASTContext.cpp
cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
cfe/trunk/lib/CodeGen/CodeGenModule.cpp
cfe/trunk/lib/Frontend/PCHReaderDecl.cpp
cfe/trunk/lib/Frontend/PCHWriter.cpp
cfe/trunk/lib/Parse/AttributeList.cpp
cfe/trunk/lib/Parse/ParseDecl.cpp
cfe/trunk/lib/Parse/ParseDeclCXX.cpp
cfe/trunk/lib/Parse/ParseExpr.cpp
cfe/trunk/lib/Parse/ParseExprCXX.cpp
cfe/trunk/lib/Parse/ParseObjc.cpp
cfe/trunk/lib/Parse/ParseStmt.cpp
cfe/trunk/lib/Parse/ParseTemplate.cpp
cfe/trunk/lib/Parse/ParseTentative.cpp
cfe/trunk/lib/Parse/Parser.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaDeclAttr.cpp
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
Modified: cfe/trunk/include/clang/AST/Attr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Attr.h?rev=89543&r1=89542&r2=89543&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Attr.h (original)
+++ cfe/trunk/include/clang/AST/Attr.h Sat Nov 21 02:43:09 2009
@@ -59,6 +59,7 @@
Deprecated,
Destructor,
FastCall,
+ Final,
Format,
FormatArg,
GNUInline,
@@ -184,12 +185,24 @@
class AlignedAttr : public Attr {
unsigned Alignment;
public:
- AlignedAttr(unsigned alignment) : Attr(Aligned), Alignment(alignment) {}
+ AlignedAttr(unsigned alignment)
+ : Attr(Aligned), Alignment(alignment) {}
/// getAlignment - The specified alignment in bits.
unsigned getAlignment() const { return Alignment; }
+
+ /// getMaxAlignment - Get the maximum alignment of attributes on this list.
+ unsigned getMaxAlignment() const {
+ const AlignedAttr *Next = getNext<AlignedAttr>();
+ if (Next)
+ return std::max(Next->getMaxAlignment(), Alignment);
+ else
+ return Alignment;
+ }
- virtual Attr* clone(ASTContext &C) const { return ::new (C) AlignedAttr(Alignment); }
+ virtual Attr* clone(ASTContext &C) const {
+ return ::new (C) AlignedAttr(Alignment);
+ }
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
@@ -304,6 +317,7 @@
DEF_SIMPLE_ATTR(NoReturn);
DEF_SIMPLE_ATTR(AnalyzerNoReturn);
DEF_SIMPLE_ATTR(Deprecated);
+DEF_SIMPLE_ATTR(Final);
class SectionAttr : public Attr {
std::string Name;
Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=89543&r1=89542&r2=89543&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Sat Nov 21 02:43:09 2009
@@ -75,6 +75,7 @@
def err_expected_lbrace : Error<"expected '{'">;
def err_expected_lparen : Error<"expected '('">;
def err_expected_rparen : Error<"expected ')'">;
+def err_expected_lsquare : Error<"expected '['">;
def err_expected_rsquare : Error<"expected ']'">;
def err_expected_rbrace : Error<"expected '}'">;
def err_expected_greater : Error<"expected '>'">;
@@ -245,6 +246,11 @@
def err_anon_type_definition : Error<
"declaration of anonymous %0 must be a definition">;
+def err_cxx0x_attribute_forbids_arguments : Error<
+ "C++0x attribute '%0' cannot have an argument list">;
+def err_cxx0x_attribute_requires_arguments : Error<
+ "C++0x attribute '%0' must have an argument list">;
+def err_attributes_not_allowed : Error<"an attribute list cannot appear here">;
/// C++ Templates
def err_expected_template : Error<"expected template">;
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=89543&r1=89542&r2=89543&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sat Nov 21 02:43:09 2009
@@ -551,6 +551,12 @@
"|class member|exception declaration|template parameter|block literal}0">;
def err_auto_var_requires_init : Error<
"declaration of variable %0 with type %1 requires an initializer">;
+
+// C++0x [[final]]
+def err_final_function_overridden : Error<
+ "declaration of %0 overrides a 'final' function">;
+def err_final_base : Error<
+ "derivation from 'final' %0">;
// Objective-C++
def err_objc_decls_may_only_appear_in_global_scope : Error<
@@ -638,8 +644,14 @@
"'weak_import' attribute cannot be specified on a definition">;
def warn_attribute_wrong_decl_type : Warning<
"%0 attribute only applies to %select{function|union|"
- "variable and function|function or method|parameter|parameter or Objective-C method |"
- "function, method or block}1 types">;
+ "variable and function|function or method|parameter|"
+ "parameter or Objective-C method |function, method or block|"
+ "virtual method or class|function, method, or parameter}1 types">;
+def err_attribute_wrong_decl_type : Error<
+ "%0 attribute only applies to %select{function|union|"
+ "variable and function|function or method|parameter|"
+ "parameter or Objective-C method |function, method or block|"
+ "virtual method or class|function, method, or parameter}1 types">;
def warn_gnu_inline_attribute_requires_inline : Warning<
"'gnu_inline' attribute requires function to be marked 'inline',"
" attribute ignored">;
Modified: cfe/trunk/include/clang/Parse/AttributeList.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/AttributeList.h?rev=89543&r1=89542&r2=89543&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/AttributeList.h (original)
+++ cfe/trunk/include/clang/Parse/AttributeList.h Sat Nov 21 02:43:09 2009
@@ -33,19 +33,22 @@
class AttributeList {
IdentifierInfo *AttrName;
SourceLocation AttrLoc;
+ IdentifierInfo *ScopeName;
+ SourceLocation ScopeLoc;
IdentifierInfo *ParmName;
SourceLocation ParmLoc;
ActionBase::ExprTy **Args;
unsigned NumArgs;
AttributeList *Next;
- bool DeclspecAttribute;
+ bool DeclspecAttribute, CXX0XAttribute;
AttributeList(const AttributeList &); // DO NOT IMPLEMENT
void operator=(const AttributeList &); // DO NOT IMPLEMENT
public:
AttributeList(IdentifierInfo *AttrName, SourceLocation AttrLoc,
+ IdentifierInfo *ScopeName, SourceLocation ScopeLoc,
IdentifierInfo *ParmName, SourceLocation ParmLoc,
ActionBase::ExprTy **args, unsigned numargs,
- AttributeList *Next, bool declspec = false);
+ AttributeList *Next, bool declspec = false, bool cxx0x = false);
~AttributeList();
enum Kind { // Please keep this list alphabetized.
@@ -57,6 +60,7 @@
AT_analyzer_noreturn,
AT_annotate,
AT_blocks,
+ AT_carries_dependency,
AT_cdecl,
AT_cleanup,
AT_const,
@@ -67,6 +71,7 @@
AT_dllimport,
AT_ext_vector_type,
AT_fastcall,
+ AT_final,
AT_format,
AT_format_arg,
AT_gnu_inline,
@@ -106,8 +111,15 @@
IdentifierInfo *getName() const { return AttrName; }
SourceLocation getLoc() const { return AttrLoc; }
+
+ bool hasScope() const { return ScopeName; }
+ IdentifierInfo *getScopeName() const { return ScopeName; }
+ SourceLocation getScopeLoc() const { return ScopeLoc; }
+
IdentifierInfo *getParameterName() const { return ParmName; }
+
bool isDeclspecAttribute() const { return DeclspecAttribute; }
+ bool isCXX0XAttribute() const { return CXX0XAttribute; }
Kind getKind() const { return getKind(getName()); }
static Kind getKind(const IdentifierInfo *Name);
@@ -181,6 +193,22 @@
return Left;
}
+/// CXX0XAttributeList - A wrapper around a C++0x attribute list.
+/// Stores, in addition to the list proper, whether or not an actual list was
+/// (as opposed to an empty list, which may be ill-formed in some places) and
+/// the source range of the list.
+struct CXX0XAttributeList {
+ AttributeList *AttrList;
+ SourceRange Range;
+ bool HasAttr;
+ CXX0XAttributeList (AttributeList *attrList, SourceRange range, bool hasAttr)
+ : AttrList(attrList), Range(range), HasAttr (hasAttr) {
+ }
+ CXX0XAttributeList ()
+ : AttrList(0), Range(), HasAttr(false) {
+ }
+};
+
} // end namespace clang
#endif
Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=89543&r1=89542&r2=89543&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Sat Nov 21 02:43:09 2009
@@ -24,6 +24,7 @@
namespace clang {
class AttributeList;
+ struct CXX0XAttributeList;
class PragmaHandler;
class Scope;
class DiagnosticBuilder;
@@ -753,10 +754,10 @@
//===--------------------------------------------------------------------===//
// C99 6.9: External Definitions.
- DeclGroupPtrTy ParseExternalDeclaration();
+ DeclGroupPtrTy ParseExternalDeclaration(CXX0XAttributeList Attr);
bool isDeclarationAfterDeclarator();
bool isStartOfFunctionDefinition();
- DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(
+ DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(AttributeList *Attr,
AccessSpecifier AS = AS_none);
DeclPtrTy ParseFunctionDefinition(ParsingDeclarator &D,
@@ -994,24 +995,25 @@
return ParseStatementOrDeclaration(true);
}
OwningStmtResult ParseStatementOrDeclaration(bool OnlyStatement = false);
- OwningStmtResult ParseLabeledStatement();
- OwningStmtResult ParseCaseStatement();
- OwningStmtResult ParseDefaultStatement();
- OwningStmtResult ParseCompoundStatement(bool isStmtExpr = false);
+ OwningStmtResult ParseLabeledStatement(AttributeList *Attr);
+ OwningStmtResult ParseCaseStatement(AttributeList *Attr);
+ OwningStmtResult ParseDefaultStatement(AttributeList *Attr);
+ OwningStmtResult ParseCompoundStatement(AttributeList *Attr,
+ bool isStmtExpr = false);
OwningStmtResult ParseCompoundStatementBody(bool isStmtExpr = false);
bool ParseParenExprOrCondition(OwningExprResult &CondExp,
bool OnlyAllowCondition = false,
SourceLocation *LParenLoc = 0,
SourceLocation *RParenLoc = 0);
- OwningStmtResult ParseIfStatement();
- OwningStmtResult ParseSwitchStatement();
- OwningStmtResult ParseWhileStatement();
- OwningStmtResult ParseDoStatement();
- OwningStmtResult ParseForStatement();
- OwningStmtResult ParseGotoStatement();
- OwningStmtResult ParseContinueStatement();
- OwningStmtResult ParseBreakStatement();
- OwningStmtResult ParseReturnStatement();
+ OwningStmtResult ParseIfStatement(AttributeList *Attr);
+ OwningStmtResult ParseSwitchStatement(AttributeList *Attr);
+ OwningStmtResult ParseWhileStatement(AttributeList *Attr);
+ OwningStmtResult ParseDoStatement(AttributeList *Attr);
+ OwningStmtResult ParseForStatement(AttributeList *Attr);
+ OwningStmtResult ParseGotoStatement(AttributeList *Attr);
+ OwningStmtResult ParseContinueStatement(AttributeList *Attr);
+ OwningStmtResult ParseBreakStatement(AttributeList *Attr);
+ OwningStmtResult ParseReturnStatement(AttributeList *Attr);
OwningStmtResult ParseAsmStatement(bool &msAsm);
OwningStmtResult FuzzyParseMicrosoftAsmStatement();
bool ParseAsmOperandsOpt(llvm::SmallVectorImpl<std::string> &Names,
@@ -1021,7 +1023,7 @@
//===--------------------------------------------------------------------===//
// C++ 6: Statements and Blocks
- OwningStmtResult ParseCXXTryBlock();
+ OwningStmtResult ParseCXXTryBlock(AttributeList *Attr);
OwningStmtResult ParseCXXTryBlockCommon(SourceLocation TryLoc);
OwningStmtResult ParseCXXCatchBlock();
@@ -1045,9 +1047,11 @@
DSC_class // class context, enables 'friend'
};
- DeclGroupPtrTy ParseDeclaration(unsigned Context, SourceLocation &DeclEnd);
+ DeclGroupPtrTy ParseDeclaration(unsigned Context, SourceLocation &DeclEnd,
+ CXX0XAttributeList Attr);
DeclGroupPtrTy ParseSimpleDeclaration(unsigned Context,
- SourceLocation &DeclEnd);
+ SourceLocation &DeclEnd,
+ AttributeList *Attr);
DeclGroupPtrTy ParseDeclGroup(ParsingDeclSpec &DS, unsigned Context,
bool AllowFunctionDefinitions,
SourceLocation *DeclEnd = 0);
@@ -1217,11 +1221,14 @@
void ParseBlockId();
// EndLoc, if non-NULL, is filled with the location of the last token of
// the attribute list.
- AttributeList *ParseAttributes(SourceLocation *EndLoc = 0);
+ CXX0XAttributeList ParseCXX0XAttributes(SourceLocation *EndLoc = 0);
+ AttributeList *ParseGNUAttributes(SourceLocation *EndLoc = 0);
AttributeList *ParseMicrosoftDeclSpec(AttributeList* CurrAttr = 0);
AttributeList *ParseMicrosoftTypeAttributes(AttributeList* CurrAttr = 0);
void ParseTypeofSpecifier(DeclSpec &DS);
void ParseDecltypeSpecifier(DeclSpec &DS);
+
+ OwningExprResult ParseCXX0XAlignArgument(SourceLocation Start);
/// DeclaratorScopeObj - RAII object used in Parser::ParseDirectDeclarator to
/// enter a new C++ declarator scope and exit it when the function is
@@ -1265,7 +1272,8 @@
typedef void (Parser::*DirectDeclParseFunction)(Declarator&);
void ParseDeclaratorInternal(Declarator &D,
DirectDeclParseFunction DirectDeclParser);
- void ParseTypeQualifierListOpt(DeclSpec &DS, bool AttributesAllowed = true);
+ void ParseTypeQualifierListOpt(DeclSpec &DS, bool GNUAttributesAllowed = true,
+ bool CXX0XAttributesAllowed = true);
void ParseDirectDeclarator(Declarator &D);
void ParseParenDeclarator(Declarator &D);
void ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
@@ -1278,12 +1286,17 @@
//===--------------------------------------------------------------------===//
// C++ 7: Declarations [dcl.dcl]
+ bool isCXX0XAttributeSpecifier(bool FullLookahead = false,
+ tok::TokenKind *After = 0);
+
DeclPtrTy ParseNamespace(unsigned Context, SourceLocation &DeclEnd);
DeclPtrTy ParseLinkage(unsigned Context);
DeclPtrTy ParseUsingDirectiveOrDeclaration(unsigned Context,
- SourceLocation &DeclEnd);
+ SourceLocation &DeclEnd,
+ CXX0XAttributeList Attrs);
DeclPtrTy ParseUsingDirective(unsigned Context, SourceLocation UsingLoc,
- SourceLocation &DeclEnd);
+ SourceLocation &DeclEnd,
+ AttributeList *Attr);
DeclPtrTy ParseUsingDeclaration(unsigned Context, SourceLocation UsingLoc,
SourceLocation &DeclEnd,
AccessSpecifier AS = AS_none);
Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=89543&r1=89542&r2=89543&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Sat Nov 21 02:43:09 2009
@@ -521,7 +521,7 @@
unsigned Align = Target.getCharWidth();
if (const AlignedAttr* AA = D->getAttr<AlignedAttr>())
- Align = std::max(Align, AA->getAlignment());
+ Align = std::max(Align, AA->getMaxAlignment());
if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
QualType T = VD->getType();
@@ -761,7 +761,8 @@
case Type::Typedef: {
const TypedefDecl *Typedef = cast<TypedefType>(T)->getDecl();
if (const AlignedAttr *Aligned = Typedef->getAttr<AlignedAttr>()) {
- Align = Aligned->getAlignment();
+ Align = std::max(Aligned->getMaxAlignment(),
+ getTypeAlign(Typedef->getUnderlyingType().getTypePtr()));
Width = getTypeSize(Typedef->getUnderlyingType().getTypePtr());
} else
return getTypeInfo(Typedef->getUnderlyingType().getTypePtr());
Modified: cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayoutBuilder.cpp?rev=89543&r1=89542&r2=89543&view=diff
==============================================================================
--- cfe/trunk/lib/AST/RecordLayoutBuilder.cpp (original)
+++ cfe/trunk/lib/AST/RecordLayoutBuilder.cpp Sat Nov 21 02:43:09 2009
@@ -448,7 +448,7 @@
MaxFieldAlignment = PPA->getAlignment();
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
- UpdateAlignment(AA->getAlignment());
+ UpdateAlignment(AA->getMaxAlignment());
// If this is a C++ class, lay out the vtable and the non-virtual bases.
const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D);
@@ -498,7 +498,7 @@
MaxFieldAlignment = PPA->getAlignment();
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
- UpdateAlignment(AA->getAlignment());
+ UpdateAlignment(AA->getMaxAlignment());
// Layout each ivar sequentially.
llvm::SmallVector<ObjCIvarDecl*, 16> Ivars;
@@ -539,8 +539,9 @@
if (FieldPacked)
FieldAlign = 1;
- if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
- FieldAlign = std::max(FieldAlign, AA->getAlignment());
+ if (const AlignedAttr *AA = D->getAttr<AlignedAttr>()) {
+ FieldAlign = std::max(FieldAlign, AA->getMaxAlignment());
+ }
// The maximum field alignment overrides the aligned attribute.
if (MaxFieldAlignment)
FieldAlign = std::min(FieldAlign, MaxFieldAlignment);
@@ -574,8 +575,9 @@
if (FieldPacked)
FieldAlign = 8;
- if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
- FieldAlign = std::max(FieldAlign, AA->getAlignment());
+ if (const AlignedAttr *AA = D->getAttr<AlignedAttr>()) {
+ FieldAlign = std::max(FieldAlign, AA->getMaxAlignment());
+ }
// The maximum field alignment overrides the aligned attribute.
if (MaxFieldAlignment)
FieldAlign = std::min(FieldAlign, MaxFieldAlignment);
Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=89543&r1=89542&r2=89543&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Sat Nov 21 02:43:09 2009
@@ -353,8 +353,12 @@
else if (Features.getStackProtectorMode() == LangOptions::SSPReq)
F->addFnAttr(llvm::Attribute::StackProtectReq);
- if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
- F->setAlignment(AA->getAlignment()/8);
+ if (const AlignedAttr *AA = D->getAttr<AlignedAttr>()) {
+ unsigned width = Context.Target.getCharWidth();
+ F->setAlignment(AA->getAlignment() / width);
+ while ((AA = AA->getNext<AlignedAttr>()))
+ F->setAlignment(std::max(F->getAlignment(), AA->getAlignment() / width));
+ }
// C++ ABI requires 2-byte alignment for member functions.
if (F->getAlignment() < 2 && isa<CXXMethodDecl>(D))
F->setAlignment(2);
Modified: cfe/trunk/lib/Frontend/PCHReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReaderDecl.cpp?rev=89543&r1=89542&r2=89543&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHReaderDecl.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReaderDecl.cpp Sat Nov 21 02:43:09 2009
@@ -461,6 +461,7 @@
SIMPLE_ATTR(Deprecated);
UNSIGNED_ATTR(Destructor);
SIMPLE_ATTR(FastCall);
+ SIMPLE_ATTR(Final);
case Attr::Format: {
std::string Type = ReadString(Record, Idx);
Modified: cfe/trunk/lib/Frontend/PCHWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriter.cpp?rev=89543&r1=89542&r2=89543&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriter.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriter.cpp Sat Nov 21 02:43:09 2009
@@ -1792,6 +1792,7 @@
break;
case Attr::FastCall:
+ case Attr::Final:
break;
case Attr::Format: {
Modified: cfe/trunk/lib/Parse/AttributeList.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/AttributeList.cpp?rev=89543&r1=89542&r2=89543&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/AttributeList.cpp (original)
+++ cfe/trunk/lib/Parse/AttributeList.cpp Sat Nov 21 02:43:09 2009
@@ -17,11 +17,13 @@
using namespace clang;
AttributeList::AttributeList(IdentifierInfo *aName, SourceLocation aLoc,
+ IdentifierInfo *sName, SourceLocation sLoc,
IdentifierInfo *pName, SourceLocation pLoc,
ActionBase::ExprTy **ExprList, unsigned numArgs,
- AttributeList *n, bool declspec)
- : AttrName(aName), AttrLoc(aLoc), ParmName(pName), ParmLoc(pLoc),
- NumArgs(numArgs), Next(n), DeclspecAttribute(declspec) {
+ AttributeList *n, bool declspec, bool cxx0x)
+ : AttrName(aName), AttrLoc(aLoc), ScopeName(sName), ScopeLoc(sLoc),
+ ParmName(pName), ParmLoc(pLoc), NumArgs(numArgs), Next(n),
+ DeclspecAttribute(declspec), CXX0XAttribute(cxx0x) {
if (numArgs == 0)
Args = 0;
@@ -59,6 +61,8 @@
.Case("mode", AT_mode)
.Case("used", AT_used)
.Case("alias", AT_alias)
+ .Case("align", AT_aligned)
+ .Case("final", AT_final)
.Case("cdecl", AT_cdecl)
.Case("const", AT_const)
.Case("packed", AT_packed)
@@ -103,6 +107,7 @@
.Case("transparent_union", AT_transparent_union)
.Case("analyzer_noreturn", AT_analyzer_noreturn)
.Case("warn_unused_result", AT_warn_unused_result)
+ .Case("carries_dependency", AT_carries_dependency)
.Case("ns_returns_retained", AT_ns_returns_retained)
.Case("cf_returns_retained", AT_cf_returns_retained)
.Case("reqd_work_group_size", AT_reqd_wg_size)
Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=89543&r1=89542&r2=89543&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Sat Nov 21 02:43:09 2009
@@ -1,3 +1,4 @@
+
//===--- ParseDecl.cpp - Declaration Parsing ------------------------------===//
//
// The LLVM Compiler Infrastructure
@@ -45,7 +46,7 @@
return Actions.ActOnTypeName(CurScope, DeclaratorInfo);
}
-/// ParseAttributes - Parse a non-empty attributes list.
+/// ParseGNUAttributes - Parse a non-empty attributes list.
///
/// [GNU] attributes:
/// attribute
@@ -81,8 +82,8 @@
/// attributes are very simple in practice. Until we find a bug, I don't see
/// a pressing need to implement the 2 token lookahead.
-AttributeList *Parser::ParseAttributes(SourceLocation *EndLoc) {
- assert(Tok.is(tok::kw___attribute) && "Not an attribute list!");
+AttributeList *Parser::ParseGNUAttributes(SourceLocation *EndLoc) {
+ assert(Tok.is(tok::kw___attribute) && "Not a GNU attribute list!");
AttributeList *CurrAttr = 0;
@@ -121,7 +122,7 @@
if (Tok.is(tok::r_paren)) {
// __attribute__(( mode(byte) ))
ConsumeParen(); // ignore the right paren loc for now
- CurrAttr = new AttributeList(AttrName, AttrNameLoc,
+ CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc,
ParmName, ParmLoc, 0, 0, CurrAttr);
} else if (Tok.is(tok::comma)) {
ConsumeToken();
@@ -145,8 +146,10 @@
}
if (ArgExprsOk && Tok.is(tok::r_paren)) {
ConsumeParen(); // ignore the right paren loc for now
- CurrAttr = new AttributeList(AttrName, AttrNameLoc, ParmName,
- ParmLoc, ArgExprs.take(), ArgExprs.size(), CurrAttr);
+ CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0,
+ AttrNameLoc, ParmName, ParmLoc,
+ ArgExprs.take(), ArgExprs.size(),
+ CurrAttr);
}
}
} else { // not an identifier
@@ -155,7 +158,7 @@
// parse a possibly empty comma separated list of expressions
// __attribute__(( nonnull() ))
ConsumeParen(); // ignore the right paren loc for now
- CurrAttr = new AttributeList(AttrName, AttrNameLoc,
+ CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc,
0, SourceLocation(), 0, 0, CurrAttr);
break;
case tok::kw_char:
@@ -175,7 +178,7 @@
// If it's a builtin type name, eat it and expect a rparen
// __attribute__(( vec_type_hint(char) ))
ConsumeToken();
- CurrAttr = new AttributeList(AttrName, AttrNameLoc,
+ CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc,
0, SourceLocation(), 0, 0, CurrAttr);
if (Tok.is(tok::r_paren))
ConsumeParen();
@@ -203,20 +206,21 @@
if (ArgExprsOk && Tok.is(tok::r_paren)) {
ConsumeParen(); // ignore the right paren loc for now
CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0,
- SourceLocation(), ArgExprs.take(), ArgExprs.size(),
+ AttrNameLoc, 0, SourceLocation(), ArgExprs.take(),
+ ArgExprs.size(),
CurrAttr);
}
break;
}
}
} else {
- CurrAttr = new AttributeList(AttrName, AttrNameLoc,
+ CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc,
0, SourceLocation(), 0, 0, CurrAttr);
}
}
if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen))
SkipUntil(tok::r_paren, false);
- SourceLocation Loc = Tok.getLocation();;
+ SourceLocation Loc = Tok.getLocation();
if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen)) {
SkipUntil(tok::r_paren, false);
}
@@ -254,15 +258,15 @@
OwningExprResult ArgExpr(ParseAssignmentExpression());
if (!ArgExpr.isInvalid()) {
ExprTy* ExprList = ArgExpr.take();
- CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0,
+ CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
SourceLocation(), &ExprList, 1,
CurrAttr, true);
}
if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen))
SkipUntil(tok::r_paren, false);
} else {
- CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, SourceLocation(),
- 0, 0, CurrAttr, true);
+ CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc,
+ 0, SourceLocation(), 0, 0, CurrAttr, true);
}
}
if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen))
@@ -281,7 +285,7 @@
if (Tok.is(tok::kw___ptr64) || Tok.is(tok::kw___w64))
// FIXME: Support these properly!
continue;
- CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0,
+ CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
SourceLocation(), 0, 0, CurrAttr, true);
}
return CurrAttr;
@@ -304,26 +308,36 @@
/// others... [FIXME]
///
Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context,
- SourceLocation &DeclEnd) {
+ SourceLocation &DeclEnd,
+ CXX0XAttributeList Attr) {
DeclPtrTy SingleDecl;
switch (Tok.getKind()) {
case tok::kw_template:
case tok::kw_export:
+ if (Attr.HasAttr)
+ Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
+ << Attr.Range;
SingleDecl = ParseDeclarationStartingWithTemplate(Context, DeclEnd);
break;
case tok::kw_namespace:
+ if (Attr.HasAttr)
+ Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
+ << Attr.Range;
SingleDecl = ParseNamespace(Context, DeclEnd);
break;
case tok::kw_using:
- SingleDecl = ParseUsingDirectiveOrDeclaration(Context, DeclEnd);
+ SingleDecl = ParseUsingDirectiveOrDeclaration(Context, DeclEnd, Attr);
break;
case tok::kw_static_assert:
+ if (Attr.HasAttr)
+ Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
+ << Attr.Range;
SingleDecl = ParseStaticAssertDeclaration(DeclEnd);
break;
default:
- return ParseSimpleDeclaration(Context, DeclEnd);
+ return ParseSimpleDeclaration(Context, DeclEnd, Attr.AttrList);
}
-
+
// This routine returns a DeclGroup, if the thing we parsed only contains a
// single decl, convert it now.
return Actions.ConvertDeclToDeclGroup(SingleDecl);
@@ -337,9 +351,12 @@
/// If RequireSemi is false, this does not check for a ';' at the end of the
/// declaration.
Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(unsigned Context,
- SourceLocation &DeclEnd) {
+ SourceLocation &DeclEnd,
+ AttributeList *Attr) {
// Parse the common declaration-specifiers piece.
ParsingDeclSpec DS(*this);
+ if (Attr)
+ DS.AddAttributes(Attr);
ParseDeclarationSpecifiers(DS);
// C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
@@ -422,7 +439,7 @@
// short x, __attribute__((common)) var; -> declarator
if (Tok.is(tok::kw___attribute)) {
SourceLocation Loc;
- AttributeList *AttrList = ParseAttributes(&Loc);
+ AttributeList *AttrList = ParseGNUAttributes(&Loc);
D.AddAttributes(AttrList, Loc);
}
@@ -491,7 +508,7 @@
// If attributes are present, parse them.
if (Tok.is(tok::kw___attribute)) {
SourceLocation Loc;
- AttributeList *AttrList = ParseAttributes(&Loc);
+ AttributeList *AttrList = ParseGNUAttributes(&Loc);
D.AddAttributes(AttrList, Loc);
}
@@ -988,7 +1005,7 @@
// GNU attributes support.
case tok::kw___attribute:
- DS.AddAttributes(ParseAttributes());
+ DS.AddAttributes(ParseGNUAttributes());
continue;
// Microsoft declspec support.
@@ -1522,7 +1539,7 @@
// Attributes are only allowed here on successive declarators.
if (!FirstDeclarator && Tok.is(tok::kw___attribute)) {
SourceLocation Loc;
- AttributeList *AttrList = ParseAttributes(&Loc);
+ AttributeList *AttrList = ParseGNUAttributes(&Loc);
DeclaratorInfo.D.AddAttributes(AttrList, Loc);
}
@@ -1543,7 +1560,7 @@
// If attributes exist after the declarator, parse them.
if (Tok.is(tok::kw___attribute)) {
SourceLocation Loc;
- AttributeList *AttrList = ParseAttributes(&Loc);
+ AttributeList *AttrList = ParseGNUAttributes(&Loc);
DeclaratorInfo.D.AddAttributes(AttrList, Loc);
}
@@ -1667,7 +1684,7 @@
AttributeList *AttrList = 0;
// If attributes exist after struct contents, parse them.
if (Tok.is(tok::kw___attribute))
- AttrList = ParseAttributes();
+ AttrList = ParseGNUAttributes();
Actions.ActOnFields(CurScope,
RecordLoc, TagDecl, FieldDecls.data(), FieldDecls.size(),
@@ -1702,7 +1719,7 @@
AttributeList *Attr = 0;
// If attributes exist after tag, parse them.
if (Tok.is(tok::kw___attribute))
- Attr = ParseAttributes();
+ Attr = ParseGNUAttributes();
CXXScopeSpec SS;
if (getLang().CPlusPlus && ParseOptionalCXXScopeSpecifier(SS, 0, false)) {
@@ -1833,7 +1850,7 @@
AttributeList *Attr = 0;
// If attributes exist after the identifier list, parse them.
if (Tok.is(tok::kw___attribute))
- Attr = ParseAttributes();
+ Attr = ParseGNUAttributes(); // FIXME: where do they do?
Actions.ActOnEnumBody(StartLoc, LBraceLoc, RBraceLoc, EnumDecl,
EnumConstantDecls.data(), EnumConstantDecls.size(),
@@ -2049,8 +2066,20 @@
/// [GNU] attributes [ only if AttributesAllowed=true ]
/// type-qualifier-list type-qualifier
/// [GNU] type-qualifier-list attributes [ only if AttributesAllowed=true ]
+/// [C++0x] attribute-specifier[opt] is allowed before cv-qualifier-seq
+/// if CXX0XAttributesAllowed = true
///
-void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, bool AttributesAllowed) {
+void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, bool GNUAttributesAllowed,
+ bool CXX0XAttributesAllowed) {
+ if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
+ SourceLocation Loc = Tok.getLocation();
+ CXX0XAttributeList Attr = ParseCXX0XAttributes();
+ if (CXX0XAttributesAllowed)
+ DS.AddAttributes(Attr.AttrList);
+ else
+ Diag(Loc, diag::err_attributes_not_allowed);
+ }
+
while (1) {
bool isInvalid = false;
const char *PrevSpec = 0;
@@ -2075,14 +2104,14 @@
case tok::kw___cdecl:
case tok::kw___stdcall:
case tok::kw___fastcall:
- if (AttributesAllowed) {
+ if (GNUAttributesAllowed) {
DS.AddAttributes(ParseMicrosoftTypeAttributes());
continue;
}
goto DoneWithTypeQuals;
case tok::kw___attribute:
- if (AttributesAllowed) {
- DS.AddAttributes(ParseAttributes());
+ if (GNUAttributesAllowed) {
+ DS.AddAttributes(ParseGNUAttributes());
continue; // do *not* consume the next token!
}
// otherwise, FALL THROUGH!
@@ -2221,7 +2250,8 @@
//
// [GNU] Retricted references are allowed.
// [GNU] Attributes on references are allowed.
- ParseTypeQualifierListOpt(DS);
+ // [C++0x] Attributes on references are not allowed.
+ ParseTypeQualifierListOpt(DS, true, false);
D.ExtendWithDeclSpec(DS);
if (DS.getTypeQualifiers() != DeclSpec::TQ_unspecified) {
@@ -2362,6 +2392,14 @@
assert(D.isPastIdentifier() &&
"Haven't past the location of the identifier yet?");
+ // Don't parse attributes unless we have an identifier.
+ if (D.getIdentifier() && getLang().CPlusPlus
+ && isCXX0XAttributeSpecifier(true)) {
+ SourceLocation AttrEndLoc;
+ CXX0XAttributeList Attr = ParseCXX0XAttributes();
+ D.AddAttributes(Attr.AttrList, AttrEndLoc);
+ }
+
while (1) {
if (Tok.is(tok::l_paren)) {
// The paren may be part of a C++ direct initializer, eg. "int x(1);".
@@ -2413,7 +2451,7 @@
AttributeList *AttrList = 0;
bool RequiresArg = false;
if (Tok.is(tok::kw___attribute)) {
- AttrList = ParseAttributes();
+ AttrList = ParseGNUAttributes();
// We require that the argument list (if this is a non-grouping paren) be
// present even if the attribute list was empty.
@@ -2618,7 +2656,7 @@
// Parse GNU attributes, if present.
if (Tok.is(tok::kw___attribute)) {
SourceLocation Loc;
- AttributeList *AttrList = ParseAttributes(&Loc);
+ AttributeList *AttrList = ParseGNUAttributes(&Loc);
ParmDecl.AddAttributes(AttrList, Loc);
}
@@ -2722,6 +2760,7 @@
bool hasAnyExceptionSpec = false;
llvm::SmallVector<TypeTy*, 2> Exceptions;
llvm::SmallVector<SourceRange, 2> ExceptionRanges;
+
if (getLang().CPlusPlus) {
// Parse cv-qualifier-seq[opt].
ParseTypeQualifierListOpt(DS, false /*no attributes*/);
@@ -2842,6 +2881,12 @@
// This code does a fast path to handle some of the most obvious cases.
if (Tok.getKind() == tok::r_square) {
SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc);
+ //FIXME: Use these
+ CXX0XAttributeList Attr;
+ if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier(true)) {
+ Attr = ParseCXX0XAttributes();
+ }
+
// Remember that we parsed the empty array type.
OwningExprResult NumElements(Actions);
D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, 0,
@@ -2855,6 +2900,11 @@
ConsumeToken();
SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc);
+ //FIXME: Use these
+ CXX0XAttributeList Attr;
+ if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
+ Attr = ParseCXX0XAttributes();
+ }
// If there was an error parsing the assignment-expression, recover.
if (ExprRes.isInvalid())
@@ -2922,6 +2972,12 @@
SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc);
+ //FIXME: Use these
+ CXX0XAttributeList Attr;
+ if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
+ Attr = ParseCXX0XAttributes();
+ }
+
// Remember that we parsed a array type, and remember its features.
D.AddTypeInfo(DeclaratorChunk::getArray(DS.getTypeQualifiers(),
StaticLoc.isValid(), isStar,
Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=89543&r1=89542&r2=89543&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Sat Nov 21 02:43:09 2009
@@ -69,7 +69,7 @@
attrTok = Tok;
// FIXME: save these somewhere.
- AttrList = ParseAttributes();
+ AttrList = ParseGNUAttributes();
}
if (Tok.is(tok::equal)) {
@@ -97,8 +97,12 @@
PP.getSourceManager(),
"parsing namespace");
- while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof))
- ParseExternalDeclaration();
+ while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
+ CXX0XAttributeList Attr;
+ if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
+ Attr = ParseCXX0XAttributes();
+ ParseExternalDeclaration(Attr);
+ }
// Leave the namespace scope.
NamespaceScope.Exit();
@@ -175,15 +179,27 @@
Tok.is(tok::l_brace)? Tok.getLocation()
: SourceLocation());
+ CXX0XAttributeList Attr;
+ if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
+ Attr = ParseCXX0XAttributes();
+ }
+
if (Tok.isNot(tok::l_brace)) {
- ParseDeclarationOrFunctionDefinition();
+ ParseDeclarationOrFunctionDefinition(Attr.AttrList);
return Actions.ActOnFinishLinkageSpecification(CurScope, LinkageSpec,
SourceLocation());
}
+ if (Attr.HasAttr)
+ Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
+ << Attr.Range;
+
SourceLocation LBrace = ConsumeBrace();
while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
- ParseExternalDeclaration();
+ CXX0XAttributeList Attr;
+ if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
+ Attr = ParseCXX0XAttributes();
+ ParseExternalDeclaration(Attr);
}
SourceLocation RBrace = MatchRHSPunctuation(tok::r_brace, LBrace);
@@ -193,7 +209,8 @@
/// ParseUsingDirectiveOrDeclaration - Parse C++ using using-declaration or
/// using-directive. Assumes that current token is 'using'.
Parser::DeclPtrTy Parser::ParseUsingDirectiveOrDeclaration(unsigned Context,
- SourceLocation &DeclEnd) {
+ SourceLocation &DeclEnd,
+ CXX0XAttributeList Attr) {
assert(Tok.is(tok::kw_using) && "Not using token");
// Eat 'using'.
@@ -206,9 +223,14 @@
if (Tok.is(tok::kw_namespace))
// Next token after 'using' is 'namespace' so it must be using-directive
- return ParseUsingDirective(Context, UsingLoc, DeclEnd);
+ return ParseUsingDirective(Context, UsingLoc, DeclEnd, Attr.AttrList);
+
+ if (Attr.HasAttr)
+ Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
+ << Attr.Range;
// Otherwise, it must be using-declaration.
+ // Ignore illegal attributes (the caller should already have issued an error.
return ParseUsingDeclaration(Context, UsingLoc, DeclEnd);
}
@@ -224,7 +246,8 @@
///
Parser::DeclPtrTy Parser::ParseUsingDirective(unsigned Context,
SourceLocation UsingLoc,
- SourceLocation &DeclEnd) {
+ SourceLocation &DeclEnd,
+ AttributeList *Attr) {
assert(Tok.is(tok::kw_namespace) && "Not 'namespace' token");
// Eat 'namespace'.
@@ -239,7 +262,6 @@
// Parse (optional) nested-name-specifier.
ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
- AttributeList *AttrList = 0;
IdentifierInfo *NamespcName = 0;
SourceLocation IdentLoc = SourceLocation();
@@ -257,17 +279,20 @@
IdentLoc = ConsumeToken();
// Parse (optional) attributes (most likely GNU strong-using extension).
- if (Tok.is(tok::kw___attribute))
- AttrList = ParseAttributes();
+ bool GNUAttr = false;
+ if (Tok.is(tok::kw___attribute)) {
+ GNUAttr = true;
+ Attr = addAttributeLists(Attr, ParseGNUAttributes());
+ }
// Eat ';'.
DeclEnd = Tok.getLocation();
ExpectAndConsume(tok::semi,
- AttrList ? diag::err_expected_semi_after_attribute_list :
+ GNUAttr ? diag::err_expected_semi_after_attribute_list :
diag::err_expected_semi_after_namespace_name, "", tok::semi);
return Actions.ActOnUsingDirective(CurScope, UsingLoc, NamespcLoc, SS,
- IdentLoc, NamespcName, AttrList);
+ IdentLoc, NamespcName, Attr);
}
/// ParseUsingDeclaration - Parse C++ using-declaration. Assumes that
@@ -323,7 +348,7 @@
// Parse (optional) attributes (most likely GNU strong-using extension).
if (Tok.is(tok::kw___attribute))
- AttrList = ParseAttributes();
+ AttrList = ParseGNUAttributes();
// Eat ';'.
DeclEnd = Tok.getLocation();
@@ -538,14 +563,20 @@
ConsumeToken();
}
- AttributeList *Attr = 0;
+ AttributeList *AttrList = 0;
// If attributes exist after tag, parse them.
if (Tok.is(tok::kw___attribute))
- Attr = ParseAttributes();
+ AttrList = ParseGNUAttributes();
// If declspecs exist after tag, parse them.
if (Tok.is(tok::kw___declspec))
- Attr = ParseMicrosoftDeclSpec(Attr);
+ AttrList = ParseMicrosoftDeclSpec(AttrList);
+
+ // If C++0x attributes exist here, parse them.
+ // FIXME: Are we consistent with the ordering of parsing of different
+ // styles of attributes?
+ if (isCXX0XAttributeSpecifier())
+ AttrList = addAttributeLists(AttrList, ParseCXX0XAttributes().AttrList);
if (TagType == DeclSpec::TST_struct && Tok.is(tok::kw___is_pod)) {
// GNU libstdc++ 4.2 uses __is_pod as the name of a struct template, but
@@ -683,7 +714,6 @@
Diag(StartLoc, diag::err_anon_type_definition)
<< DeclSpec::getSpecifierName(TagType);
- // Skip the rest of this declarator, up until the comma or semicolon.
SkipUntil(tok::comma, true);
if (TemplateId)
@@ -720,7 +750,7 @@
TemplateId->LAngleLoc,
TemplateArgsPtr,
TemplateId->RAngleLoc,
- Attr);
+ AttrList);
} else if (TUK == Action::TUK_Reference) {
TypeResult
= Actions.ActOnTemplateIdType(TemplateTy::make(TemplateId->Template),
@@ -775,7 +805,7 @@
TemplateId->LAngleLoc,
TemplateArgsPtr,
TemplateId->RAngleLoc,
- Attr,
+ AttrList,
Action::MultiTemplateParamsArg(Actions,
TemplateParams? &(*TemplateParams)[0] : 0,
TemplateParams? TemplateParams->size() : 0));
@@ -793,7 +823,7 @@
TemplateInfo.ExternLoc,
TemplateInfo.TemplateLoc,
TagType, StartLoc, SS, Name,
- NameLoc, Attr);
+ NameLoc, AttrList);
} else {
if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation &&
TUK == Action::TUK_Definition) {
@@ -804,7 +834,7 @@
// Declaration or definition of a class type
TagOrTempResult = Actions.ActOnTag(CurScope, TagType, TUK, StartLoc, SS,
- Name, NameLoc, Attr, AS,
+ Name, NameLoc, AttrList, AS,
Action::MultiTemplateParamsArg(Actions,
TemplateParams? &(*TemplateParams)[0] : 0,
TemplateParams? TemplateParams->size() : 0),
@@ -1055,8 +1085,18 @@
return ParseCXXClassMemberDeclaration(AS, TemplateInfo);
}
+ CXX0XAttributeList AttrList;
+ // Optional C++0x attribute-specifier
+ if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
+ AttrList = ParseCXX0XAttributes();
+ }
+
if (Tok.is(tok::kw_using)) {
// FIXME: Check for template aliases
+
+ if (AttrList.HasAttr)
+ Diag(AttrList.Range.getBegin(), diag::err_attributes_not_allowed)
+ << AttrList.Range;
// Eat 'using'.
SourceLocation UsingLoc = ConsumeToken();
@@ -1077,6 +1117,7 @@
// decl-specifier-seq:
// Parse the common declaration-specifiers piece.
ParsingDeclSpec DS(*this);
+ DS.AddAttributes(AttrList.AttrList);
ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC_class);
Action::MultiTemplateParamsArg TemplateParams(Actions,
@@ -1139,7 +1180,6 @@
bool Deleted = false;
while (1) {
-
// member-declarator:
// declarator pure-specifier[opt]
// declarator constant-initializer[opt]
@@ -1177,7 +1217,7 @@
// If attributes exist after the declarator, parse them.
if (Tok.is(tok::kw___attribute)) {
SourceLocation Loc;
- AttributeList *AttrList = ParseAttributes(&Loc);
+ AttributeList *AttrList = ParseGNUAttributes(&Loc);
DeclaratorInfo.AddAttributes(AttrList, Loc);
}
@@ -1227,7 +1267,7 @@
// Attributes are only allowed on the second declarator.
if (Tok.is(tok::kw___attribute)) {
SourceLocation Loc;
- AttributeList *AttrList = ParseAttributes(&Loc);
+ AttributeList *AttrList = ParseGNUAttributes(&Loc);
DeclaratorInfo.AddAttributes(AttrList, Loc);
}
@@ -1326,7 +1366,7 @@
AttributeList *AttrList = 0;
// If attributes exist after class contents, parse them.
if (Tok.is(tok::kw___attribute))
- AttrList = ParseAttributes(); // FIXME: where should I put them?
+ AttrList = ParseGNUAttributes(); // FIXME: where should I put them?
Actions.ActOnFinishCXXMemberSpecification(CurScope, RecordLoc, TagDecl,
LBraceLoc, RBraceLoc);
@@ -1573,3 +1613,170 @@
ClassStack.top()->NestedClasses.push_back(Victim);
Victim->TemplateScope = CurScope->getParent()->isTemplateParamScope();
}
+
+/// ParseCXX0XAttributes - Parse a C++0x attribute-specifier. Currently only
+/// parses standard attributes.
+///
+/// [C++0x] attribute-specifier:
+/// '[' '[' attribute-list ']' ']'
+///
+/// [C++0x] attribute-list:
+/// attribute[opt]
+/// attribute-list ',' attribute[opt]
+///
+/// [C++0x] attribute:
+/// attribute-token attribute-argument-clause[opt]
+///
+/// [C++0x] attribute-token:
+/// identifier
+/// attribute-scoped-token
+///
+/// [C++0x] attribute-scoped-token:
+/// attribute-namespace '::' identifier
+///
+/// [C++0x] attribute-namespace:
+/// identifier
+///
+/// [C++0x] attribute-argument-clause:
+/// '(' balanced-token-seq ')'
+///
+/// [C++0x] balanced-token-seq:
+/// balanced-token
+/// balanced-token-seq balanced-token
+///
+/// [C++0x] balanced-token:
+/// '(' balanced-token-seq ')'
+/// '[' balanced-token-seq ']'
+/// '{' balanced-token-seq '}'
+/// any token but '(', ')', '[', ']', '{', or '}'
+CXX0XAttributeList Parser::ParseCXX0XAttributes(SourceLocation *EndLoc) {
+ assert(Tok.is(tok::l_square) && NextToken().is(tok::l_square)
+ && "Not a C++0x attribute list");
+
+ SourceLocation StartLoc = Tok.getLocation(), Loc;
+ AttributeList *CurrAttr = 0;
+
+ ConsumeBracket();
+ ConsumeBracket();
+
+ if (Tok.is(tok::comma)) {
+ Diag(Tok.getLocation(), diag::err_expected_ident);
+ ConsumeToken();
+ }
+
+ while (Tok.is(tok::identifier) || Tok.is(tok::comma)) {
+ // attribute not present
+ if (Tok.is(tok::comma)) {
+ ConsumeToken();
+ continue;
+ }
+
+ IdentifierInfo *ScopeName = 0, *AttrName = Tok.getIdentifierInfo();
+ SourceLocation ScopeLoc, AttrLoc = ConsumeToken();
+
+ // scoped attribute
+ if (Tok.is(tok::coloncolon)) {
+ ConsumeToken();
+
+ if (!Tok.is(tok::identifier)) {
+ Diag(Tok.getLocation(), diag::err_expected_ident);
+ SkipUntil(tok::r_square, tok::comma, true, true);
+ continue;
+ }
+
+ ScopeName = AttrName;
+ ScopeLoc = AttrLoc;
+
+ AttrName = Tok.getIdentifierInfo();
+ AttrLoc = ConsumeToken();
+ }
+
+ bool AttrParsed = false;
+ // No scoped names are supported; ideally we could put all non-standard
+ // attributes into namespaces.
+ if (!ScopeName) {
+ switch(AttributeList::getKind(AttrName))
+ {
+ // No arguments
+ case AttributeList::AT_noreturn:
+ case AttributeList::AT_final:
+ case AttributeList::AT_carries_dependency: {
+ if (Tok.is(tok::l_paren)) {
+ Diag(Tok.getLocation(), diag::err_cxx0x_attribute_forbids_arguments)
+ << AttrName->getName();
+ break;
+ }
+
+ CurrAttr = new AttributeList(AttrName, AttrLoc, 0, AttrLoc, 0,
+ SourceLocation(), 0, 0, CurrAttr, false,
+ true);
+ AttrParsed = true;
+ break;
+ }
+
+ // One argument; must be a type-id or assignment-expression
+ case AttributeList::AT_aligned: {
+ if (Tok.isNot(tok::l_paren)) {
+ Diag(Tok.getLocation(), diag::err_cxx0x_attribute_requires_arguments)
+ << AttrName->getName();
+ break;
+ }
+ SourceLocation ParamLoc = ConsumeParen();
+
+ OwningExprResult ArgExpr = ParseCXX0XAlignArgument(ParamLoc);
+
+ MatchRHSPunctuation(tok::r_paren, ParamLoc);
+
+ ExprVector ArgExprs(Actions);
+ ArgExprs.push_back(ArgExpr.release());
+ CurrAttr = new AttributeList(AttrName, AttrLoc, 0, AttrLoc,
+ 0, ParamLoc, ArgExprs.take(), 1, CurrAttr,
+ false, true);
+
+ AttrParsed = true;
+ break;
+ }
+
+ // Silence warnings
+ default: break;
+ }
+ }
+
+ // Skip the entire parameter clause, if any
+ if (!AttrParsed && Tok.is(tok::l_paren)) {
+ ConsumeParen();
+ // SkipUntil maintains the balancedness of tokens.
+ SkipUntil(tok::r_paren, false);
+ }
+ }
+
+ if (ExpectAndConsume(tok::r_square, diag::err_expected_rsquare))
+ SkipUntil(tok::r_square, false);
+ Loc = Tok.getLocation();
+ if (ExpectAndConsume(tok::r_square, diag::err_expected_rsquare))
+ SkipUntil(tok::r_square, false);
+
+ CXX0XAttributeList Attr (CurrAttr, SourceRange(StartLoc, Loc), true);
+ return Attr;
+}
+
+/// ParseCXX0XAlignArgument - Parse the argument to C++0x's [[align]]
+/// attribute.
+///
+/// FIXME: Simply returns an alignof() expression if the argument is a
+/// type. Ideally, the type should be propagated directly into Sema.
+///
+/// [C++0x] 'align' '(' type-id ')'
+/// [C++0x] 'align' '(' assignment-expression ')'
+Parser::OwningExprResult Parser::ParseCXX0XAlignArgument(SourceLocation Start) {
+ if (isTypeIdInParens()) {
+ EnterExpressionEvaluationContext Unevaluated(Actions,
+ Action::Unevaluated);
+ SourceLocation TypeLoc = Tok.getLocation();
+ TypeTy *Ty = ParseTypeName().get();
+ SourceRange TypeRange(Start, Tok.getLocation());
+ return Actions.ActOnSizeOfAlignOfExpr(TypeLoc, false, true, Ty,
+ TypeRange);
+ } else
+ return ParseConstantExpression();
+}
Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=89543&r1=89542&r2=89543&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Sat Nov 21 02:43:09 2009
@@ -1315,7 +1315,7 @@
if (ExprType >= CompoundStmt && Tok.is(tok::l_brace)) {
Diag(Tok, diag::ext_gnu_statement_expr);
- OwningStmtResult Stmt(ParseCompoundStatement(true));
+ OwningStmtResult Stmt(ParseCompoundStatement(0, true));
ExprType = CompoundStmt;
// If the substmt parsed correctly, build the AST node.
@@ -1503,7 +1503,7 @@
if (Tok.is(tok::kw___attribute)) {
SourceLocation Loc;
- AttributeList *AttrList = ParseAttributes(&Loc);
+ AttributeList *AttrList = ParseGNUAttributes(&Loc);
DeclaratorInfo.AddAttributes(AttrList, Loc);
}
@@ -1565,7 +1565,7 @@
if (Tok.is(tok::kw___attribute)) {
SourceLocation Loc;
- AttributeList *AttrList = ParseAttributes(&Loc);
+ AttributeList *AttrList = ParseGNUAttributes(&Loc);
ParamInfo.AddAttributes(AttrList, Loc);
}
@@ -1586,7 +1586,7 @@
if (Tok.is(tok::kw___attribute)) {
SourceLocation Loc;
- AttributeList *AttrList = ParseAttributes(&Loc);
+ AttributeList *AttrList = ParseGNUAttributes(&Loc);
ParamInfo.AddAttributes(AttrList, Loc);
}
Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=89543&r1=89542&r2=89543&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Sat Nov 21 02:43:09 2009
@@ -568,7 +568,7 @@
// If attributes are present, parse them.
if (Tok.is(tok::kw___attribute)) {
SourceLocation Loc;
- AttributeList *AttrList = ParseAttributes(&Loc);
+ AttributeList *AttrList = ParseGNUAttributes(&Loc);
DeclaratorInfo.AddAttributes(AttrList, Loc);
}
Modified: cfe/trunk/lib/Parse/ParseObjc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseObjc.cpp?rev=89543&r1=89542&r2=89543&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseObjc.cpp (original)
+++ cfe/trunk/lib/Parse/ParseObjc.cpp Sat Nov 21 02:43:09 2009
@@ -282,7 +282,7 @@
// FIXME: as the name implies, this rule allows function definitions.
// We could pass a flag or check for functions during semantic analysis.
- allTUVariables.push_back(ParseDeclarationOrFunctionDefinition());
+ allTUVariables.push_back(ParseDeclarationOrFunctionDefinition(0));
continue;
}
@@ -759,7 +759,7 @@
// If attributes exist after the method, parse them.
AttributeList *MethodAttrs = 0;
if (getLang().ObjC2 && Tok.is(tok::kw___attribute))
- MethodAttrs = ParseAttributes();
+ MethodAttrs = ParseGNUAttributes();
Selector Sel = PP.getSelectorTable().getNullarySelector(SelIdent);
DeclPtrTy Result
@@ -791,7 +791,7 @@
// If attributes exist before the argument name, parse them.
ArgInfo.ArgAttrs = 0;
if (getLang().ObjC2 && Tok.is(tok::kw___attribute))
- ArgInfo.ArgAttrs = ParseAttributes();
+ ArgInfo.ArgAttrs = ParseGNUAttributes();
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected_ident); // missing argument name.
@@ -835,7 +835,7 @@
// If attributes exist after the method, parse them.
AttributeList *MethodAttrs = 0;
if (getLang().ObjC2 && Tok.is(tok::kw___attribute))
- MethodAttrs = ParseAttributes();
+ MethodAttrs = ParseGNUAttributes();
if (KeyIdents.size() == 0)
return DeclPtrTy();
Modified: cfe/trunk/lib/Parse/ParseStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmt.cpp?rev=89543&r1=89542&r2=89543&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseStmt.cpp (original)
+++ cfe/trunk/lib/Parse/ParseStmt.cpp Sat Nov 21 02:43:09 2009
@@ -78,6 +78,10 @@
const char *SemiError = 0;
OwningStmtResult Res(Actions);
+ CXX0XAttributeList Attr;
+ if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
+ Attr = ParseCXX0XAttributes();
+
// Cases in this switch statement should fall through if the parser expects
// the token to end in a semicolon (in which case SemiError should be set),
// or they directly 'return;' if not.
@@ -98,14 +102,15 @@
case tok::identifier:
if (NextToken().is(tok::colon)) { // C99 6.8.1: labeled-statement
// identifier ':' statement
- return ParseLabeledStatement();
+ return ParseLabeledStatement(Attr.AttrList);
}
// PASS THROUGH.
default: {
if ((getLang().CPlusPlus || !OnlyStatement) && isDeclarationStatement()) {
SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
- DeclGroupPtrTy Decl = ParseDeclaration(Declarator::BlockContext, DeclEnd);
+ DeclGroupPtrTy Decl = ParseDeclaration(Declarator::BlockContext, DeclEnd,
+ Attr);
return Actions.ActOnDeclStmt(Decl, DeclStart, DeclEnd);
}
@@ -114,6 +119,7 @@
return StmtError();
}
+ // FIXME: Use the attributes
// expression[opt] ';'
OwningExprResult Expr(ParseExpression());
if (Expr.isInvalid()) {
@@ -129,47 +135,50 @@
}
case tok::kw_case: // C99 6.8.1: labeled-statement
- return ParseCaseStatement();
+ return ParseCaseStatement(Attr.AttrList);
case tok::kw_default: // C99 6.8.1: labeled-statement
- return ParseDefaultStatement();
+ return ParseDefaultStatement(Attr.AttrList);
case tok::l_brace: // C99 6.8.2: compound-statement
- return ParseCompoundStatement();
+ return ParseCompoundStatement(Attr.AttrList);
case tok::semi: // C99 6.8.3p3: expression[opt] ';'
return Actions.ActOnNullStmt(ConsumeToken());
case tok::kw_if: // C99 6.8.4.1: if-statement
- return ParseIfStatement();
+ return ParseIfStatement(Attr.AttrList);
case tok::kw_switch: // C99 6.8.4.2: switch-statement
- return ParseSwitchStatement();
+ return ParseSwitchStatement(Attr.AttrList);
case tok::kw_while: // C99 6.8.5.1: while-statement
- return ParseWhileStatement();
+ return ParseWhileStatement(Attr.AttrList);
case tok::kw_do: // C99 6.8.5.2: do-statement
- Res = ParseDoStatement();
+ Res = ParseDoStatement(Attr.AttrList);
SemiError = "do/while";
break;
case tok::kw_for: // C99 6.8.5.3: for-statement
- return ParseForStatement();
+ return ParseForStatement(Attr.AttrList);
case tok::kw_goto: // C99 6.8.6.1: goto-statement
- Res = ParseGotoStatement();
+ Res = ParseGotoStatement(Attr.AttrList);
SemiError = "goto";
break;
case tok::kw_continue: // C99 6.8.6.2: continue-statement
- Res = ParseContinueStatement();
+ Res = ParseContinueStatement(Attr.AttrList);
SemiError = "continue";
break;
case tok::kw_break: // C99 6.8.6.3: break-statement
- Res = ParseBreakStatement();
+ Res = ParseBreakStatement(Attr.AttrList);
SemiError = "break";
break;
case tok::kw_return: // C99 6.8.6.4: return-statement
- Res = ParseReturnStatement();
+ Res = ParseReturnStatement(Attr.AttrList);
SemiError = "return";
break;
case tok::kw_asm: {
+ if (Attr.HasAttr)
+ Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
+ << Attr.Range;
bool msAsm = false;
Res = ParseAsmStatement(msAsm);
if (msAsm) return move(Res);
@@ -178,7 +187,7 @@
}
case tok::kw_try: // C++ 15: try-block
- return ParseCXXTryBlock();
+ return ParseCXXTryBlock(Attr.AttrList);
}
// If we reached this code, the statement must end in a semicolon.
@@ -202,7 +211,7 @@
/// identifier ':' statement
/// [GNU] identifier ':' attributes[opt] statement
///
-Parser::OwningStmtResult Parser::ParseLabeledStatement() {
+Parser::OwningStmtResult Parser::ParseLabeledStatement(AttributeList *Attr) {
assert(Tok.is(tok::identifier) && Tok.getIdentifierInfo() &&
"Not an identifier!");
@@ -215,10 +224,8 @@
SourceLocation ColonLoc = ConsumeToken();
// Read label attributes, if present.
- Action::AttrTy *AttrList = 0;
if (Tok.is(tok::kw___attribute))
- // TODO: save these somewhere.
- AttrList = ParseAttributes();
+ Attr = addAttributeLists(Attr, ParseGNUAttributes());
OwningStmtResult SubStmt(ParseStatement());
@@ -236,8 +243,9 @@
/// 'case' constant-expression ':' statement
/// [GNU] 'case' constant-expression '...' constant-expression ':' statement
///
-Parser::OwningStmtResult Parser::ParseCaseStatement() {
+Parser::OwningStmtResult Parser::ParseCaseStatement(AttributeList *Attr) {
assert(Tok.is(tok::kw_case) && "Not a case stmt!");
+ // FIXME: Use attributes?
// It is very very common for code to contain many case statements recursively
// nested, as in (but usually without indentation):
@@ -354,7 +362,8 @@
/// 'default' ':' statement
/// Note that this does not parse the 'statement' at the end.
///
-Parser::OwningStmtResult Parser::ParseDefaultStatement() {
+Parser::OwningStmtResult Parser::ParseDefaultStatement(AttributeList *Attr) {
+ //FIXME: Use attributes?
assert(Tok.is(tok::kw_default) && "Not a default stmt!");
SourceLocation DefaultLoc = ConsumeToken(); // eat the 'default'.
@@ -408,7 +417,9 @@
/// [OMP] barrier-directive
/// [OMP] flush-directive
///
-Parser::OwningStmtResult Parser::ParseCompoundStatement(bool isStmtExpr) {
+Parser::OwningStmtResult Parser::ParseCompoundStatement(AttributeList *Attr,
+ bool isStmtExpr) {
+ //FIXME: Use attributes?
assert(Tok.is(tok::l_brace) && "Not a compount stmt!");
// Enter a scope to hold everything within the compound stmt. Compound
@@ -449,6 +460,10 @@
while (Tok.is(tok::kw___extension__))
ConsumeToken();
+ CXX0XAttributeList Attr;
+ if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
+ Attr = ParseCXX0XAttributes();
+
// If this is the start of a declaration, parse it as such.
if (isDeclarationStatement()) {
// __extension__ silences extension warnings in the subdeclaration.
@@ -456,7 +471,8 @@
ExtensionRAIIObject O(Diags);
SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
- DeclGroupPtrTy Res = ParseDeclaration(Declarator::BlockContext,DeclEnd);
+ DeclGroupPtrTy Res = ParseDeclaration(Declarator::BlockContext, DeclEnd,
+ Attr);
R = Actions.ActOnDeclStmt(Res, DeclStart, DeclEnd);
} else {
// Otherwise this was a unary __extension__ marker.
@@ -467,6 +483,7 @@
continue;
}
+ // FIXME: Use attributes?
// Eat the semicolon at the end of stmt and convert the expr into a
// statement.
ExpectAndConsume(tok::semi, diag::err_expected_semi_after_expr);
@@ -537,7 +554,8 @@
/// [C++] 'if' '(' condition ')' statement
/// [C++] 'if' '(' condition ')' statement 'else' statement
///
-Parser::OwningStmtResult Parser::ParseIfStatement() {
+Parser::OwningStmtResult Parser::ParseIfStatement(AttributeList *Attr) {
+ // FIXME: Use attributes?
assert(Tok.is(tok::kw_if) && "Not an if stmt!");
SourceLocation IfLoc = ConsumeToken(); // eat the 'if'.
@@ -659,7 +677,8 @@
/// switch-statement:
/// 'switch' '(' expression ')' statement
/// [C++] 'switch' '(' condition ')' statement
-Parser::OwningStmtResult Parser::ParseSwitchStatement() {
+Parser::OwningStmtResult Parser::ParseSwitchStatement(AttributeList *Attr) {
+ // FIXME: Use attributes?
assert(Tok.is(tok::kw_switch) && "Not a switch stmt!");
SourceLocation SwitchLoc = ConsumeToken(); // eat the 'switch'.
@@ -734,7 +753,8 @@
/// while-statement: [C99 6.8.5.1]
/// 'while' '(' expression ')' statement
/// [C++] 'while' '(' condition ')' statement
-Parser::OwningStmtResult Parser::ParseWhileStatement() {
+Parser::OwningStmtResult Parser::ParseWhileStatement(AttributeList *Attr) {
+ // FIXME: Use attributes?
assert(Tok.is(tok::kw_while) && "Not a while stmt!");
SourceLocation WhileLoc = Tok.getLocation();
ConsumeToken(); // eat the 'while'.
@@ -805,7 +825,8 @@
/// do-statement: [C99 6.8.5.2]
/// 'do' statement 'while' '(' expression ')' ';'
/// Note: this lets the caller parse the end ';'.
-Parser::OwningStmtResult Parser::ParseDoStatement() {
+Parser::OwningStmtResult Parser::ParseDoStatement(AttributeList *Attr) {
+ // FIXME: Use attributes?
assert(Tok.is(tok::kw_do) && "Not a do stmt!");
SourceLocation DoLoc = ConsumeToken(); // eat the 'do'.
@@ -880,7 +901,8 @@
/// [C++] expression-statement
/// [C++] simple-declaration
///
-Parser::OwningStmtResult Parser::ParseForStatement() {
+Parser::OwningStmtResult Parser::ParseForStatement(AttributeList *Attr) {
+ // FIXME: Use attributes?
assert(Tok.is(tok::kw_for) && "Not a for stmt!");
SourceLocation ForLoc = ConsumeToken(); // eat the 'for'.
@@ -937,8 +959,13 @@
if (!C99orCXXorObjC) // Use of C99-style for loops in C90 mode?
Diag(Tok, diag::ext_c99_variable_decl_in_for_loop);
+ AttributeList *AttrList = 0;
+ if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
+ AttrList = ParseCXX0XAttributes().AttrList;
+
SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
- DeclGroupPtrTy DG = ParseSimpleDeclaration(Declarator::ForContext, DeclEnd);
+ DeclGroupPtrTy DG = ParseSimpleDeclaration(Declarator::ForContext, DeclEnd,
+ AttrList);
FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());
if (Tok.is(tok::semi)) { // for (int x = 4;
@@ -1036,7 +1063,8 @@
///
/// Note: this lets the caller parse the end ';'.
///
-Parser::OwningStmtResult Parser::ParseGotoStatement() {
+Parser::OwningStmtResult Parser::ParseGotoStatement(AttributeList *Attr) {
+ // FIXME: Use attributes?
assert(Tok.is(tok::kw_goto) && "Not a goto stmt!");
SourceLocation GotoLoc = ConsumeToken(); // eat the 'goto'.
@@ -1069,7 +1097,8 @@
///
/// Note: this lets the caller parse the end ';'.
///
-Parser::OwningStmtResult Parser::ParseContinueStatement() {
+Parser::OwningStmtResult Parser::ParseContinueStatement(AttributeList *Attr) {
+ // FIXME: Use attributes?
SourceLocation ContinueLoc = ConsumeToken(); // eat the 'continue'.
return Actions.ActOnContinueStmt(ContinueLoc, CurScope);
}
@@ -1080,7 +1109,8 @@
///
/// Note: this lets the caller parse the end ';'.
///
-Parser::OwningStmtResult Parser::ParseBreakStatement() {
+Parser::OwningStmtResult Parser::ParseBreakStatement(AttributeList *Attr) {
+ // FIXME: Use attributes?
SourceLocation BreakLoc = ConsumeToken(); // eat the 'break'.
return Actions.ActOnBreakStmt(BreakLoc, CurScope);
}
@@ -1088,7 +1118,8 @@
/// ParseReturnStatement
/// jump-statement:
/// 'return' expression[opt] ';'
-Parser::OwningStmtResult Parser::ParseReturnStatement() {
+Parser::OwningStmtResult Parser::ParseReturnStatement(AttributeList *Attr) {
+ // FIXME: Use attributes?
assert(Tok.is(tok::kw_return) && "Not a return stmt!");
SourceLocation ReturnLoc = ConsumeToken(); // eat the 'return'.
@@ -1164,7 +1195,7 @@
}
DeclSpec DS;
SourceLocation Loc = Tok.getLocation();
- ParseTypeQualifierListOpt(DS);
+ ParseTypeQualifierListOpt(DS, true, false);
// GNU asms accept, but warn, about type-qualifiers other than volatile.
if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
@@ -1372,7 +1403,8 @@
/// try-block:
/// 'try' compound-statement handler-seq
///
-Parser::OwningStmtResult Parser::ParseCXXTryBlock() {
+Parser::OwningStmtResult Parser::ParseCXXTryBlock(AttributeList* Attr) {
+ // FIXME: Add attributes?
assert(Tok.is(tok::kw_try) && "Expected 'try'");
SourceLocation TryLoc = ConsumeToken();
@@ -1394,11 +1426,17 @@
Parser::OwningStmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc) {
if (Tok.isNot(tok::l_brace))
return StmtError(Diag(Tok, diag::err_expected_lbrace));
- OwningStmtResult TryBlock(ParseCompoundStatement());
+ // FIXME: Possible draft standard bug: attribute-specifier should be allowed?
+ OwningStmtResult TryBlock(ParseCompoundStatement(0));
if (TryBlock.isInvalid())
return move(TryBlock);
StmtVector Handlers(Actions);
+ if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
+ CXX0XAttributeList Attr = ParseCXX0XAttributes();
+ Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
+ << Attr.Range;
+ }
if (Tok.isNot(tok::kw_catch))
return StmtError(Diag(Tok, diag::err_expected_catch));
while (Tok.is(tok::kw_catch)) {
@@ -1458,7 +1496,8 @@
if (Tok.isNot(tok::l_brace))
return StmtError(Diag(Tok, diag::err_expected_lbrace));
- OwningStmtResult Block(ParseCompoundStatement());
+ // FIXME: Possible draft standard bug: attribute-specifier should be allowed?
+ OwningStmtResult Block(ParseCompoundStatement(0));
if (Block.isInvalid())
return move(Block);
Modified: cfe/trunk/lib/Parse/ParseTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTemplate.cpp?rev=89543&r1=89542&r2=89543&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseTemplate.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTemplate.cpp Sat Nov 21 02:43:09 2009
@@ -192,6 +192,10 @@
// Parse the declaration specifiers.
ParsingDeclSpec DS(*this);
+
+ if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
+ DS.AddAttributes(ParseCXX0XAttributes().AttrList);
+
ParseDeclarationSpecifiers(DS, TemplateInfo, AS);
if (Tok.is(tok::semi)) {
Modified: cfe/trunk/lib/Parse/ParseTentative.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTentative.cpp?rev=89543&r1=89542&r2=89543&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseTentative.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTentative.cpp Sat Nov 21 02:43:09 2009
@@ -55,12 +55,11 @@
// using-declaration
// using-directive
case tok::kw_using:
- return true;
- case tok::kw_static_assert:
// static_assert-declaration
+ case tok::kw_static_assert:
return true;
- default:
// simple-declaration
+ default:
return isCXXSimpleDeclaration();
}
}
@@ -351,6 +350,89 @@
return TPR == TPResult::True();
}
+/// isCXX0XAttributeSpecifier - returns true if this is a C++0x
+/// attribute-specifier. By default, unless in Obj-C++, only a cursory check is
+/// performed that will simply return true if a [[ is seen. Currently C++ has no
+/// syntactical ambiguities from this check, but it may inhibit error recovery.
+/// If CheckClosing is true, a check is made for closing ]] brackets.
+///
+/// If given, After is set to the token after the attribute-specifier so that
+/// appropriate parsing decisions can be made; it is left untouched if false is
+/// returned.
+///
+/// FIXME: If an error is in the closing ]] brackets, the program assumes
+/// the absence of an attribute-specifier, which can cause very yucky errors
+/// to occur.
+///
+/// [C++0x] attribute-specifier:
+/// '[' '[' attribute-list ']' ']'
+///
+/// [C++0x] attribute-list:
+/// attribute[opt]
+/// attribute-list ',' attribute[opt]
+///
+/// [C++0x] attribute:
+/// attribute-token attribute-argument-clause[opt]
+///
+/// [C++0x] attribute-token:
+/// identifier
+/// attribute-scoped-token
+///
+/// [C++0x] attribute-scoped-token:
+/// attribute-namespace '::' identifier
+///
+/// [C++0x] attribute-namespace:
+/// identifier
+///
+/// [C++0x] attribute-argument-clause:
+/// '(' balanced-token-seq ')'
+///
+/// [C++0x] balanced-token-seq:
+/// balanced-token
+/// balanced-token-seq balanced-token
+///
+/// [C++0x] balanced-token:
+/// '(' balanced-token-seq ')'
+/// '[' balanced-token-seq ']'
+/// '{' balanced-token-seq '}'
+/// any token but '(', ')', '[', ']', '{', or '}'
+bool Parser::isCXX0XAttributeSpecifier (bool CheckClosing,
+ tok::TokenKind *After) {
+ if (Tok.isNot(tok::l_square) || NextToken().isNot(tok::l_square))
+ return false;
+
+ // No tentative parsing if we don't need to look for ]]
+ if (!CheckClosing && !getLang().ObjC1)
+ return true;
+
+ struct TentativeReverter {
+ TentativeParsingAction PA;
+
+ TentativeReverter (Parser& P)
+ : PA(P)
+ {}
+ ~TentativeReverter () {
+ PA.Revert();
+ }
+ } R(*this);
+
+ // Opening brackets were checked for above.
+ ConsumeBracket();
+ ConsumeBracket();
+
+ // SkipUntil will handle balanced tokens, which are guaranteed in attributes.
+ SkipUntil(tok::r_square, false);
+
+ if (Tok.isNot(tok::r_square))
+ return false;
+ ConsumeBracket();
+
+ if (After)
+ *After = Tok.getKind();
+
+ return true;
+}
+
/// declarator:
/// direct-declarator
/// ptr-operator declarator
Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=89543&r1=89542&r2=89543&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Sat Nov 21 02:43:09 2009
@@ -355,7 +355,10 @@
return true;
}
- Result = ParseExternalDeclaration();
+ CXX0XAttributeList Attr;
+ if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
+ Attr = ParseCXX0XAttributes();
+ Result = ParseExternalDeclaration(Attr);
return false;
}
@@ -396,7 +399,7 @@
/// ';'
///
/// [C++0x/GNU] 'extern' 'template' declaration
-Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration() {
+Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(CXX0XAttributeList Attr) {
DeclPtrTy SingleDecl;
switch (Tok.getKind()) {
case tok::semi:
@@ -418,9 +421,13 @@
// __extension__ silences extension warnings in the subexpression.
ExtensionRAIIObject O(Diags); // Use RAII to do this.
ConsumeToken();
- return ParseExternalDeclaration();
+ return ParseExternalDeclaration(Attr);
}
case tok::kw_asm: {
+ if (Attr.HasAttr)
+ Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
+ << Attr.Range;
+
OwningExprResult Result(ParseSimpleAsm());
ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
@@ -449,7 +456,7 @@
case tok::code_completion:
Actions.CodeCompleteOrdinaryName(CurScope);
ConsumeToken();
- return ParseExternalDeclaration();
+ return ParseExternalDeclaration(Attr);
case tok::kw_using:
case tok::kw_namespace:
case tok::kw_typedef:
@@ -459,7 +466,7 @@
// A function definition cannot start with a these keywords.
{
SourceLocation DeclEnd;
- return ParseDeclaration(Declarator::FileContext, DeclEnd);
+ return ParseDeclaration(Declarator::FileContext, DeclEnd, Attr);
}
case tok::kw_extern:
if (getLang().CPlusPlus && NextToken().is(tok::kw_template)) {
@@ -477,7 +484,7 @@
default:
// We can't tell whether this is a function-definition or declaration yet.
- return ParseDeclarationOrFunctionDefinition();
+ return ParseDeclarationOrFunctionDefinition(Attr.AttrList);
}
// This routine returns a DeclGroup, if the thing we parsed only contains a
@@ -525,9 +532,13 @@
/// [OMP] threadprivate-directive [TODO]
///
Parser::DeclGroupPtrTy
-Parser::ParseDeclarationOrFunctionDefinition(AccessSpecifier AS) {
+Parser::ParseDeclarationOrFunctionDefinition(AttributeList *Attr,
+ AccessSpecifier AS) {
// Parse the common declaration-specifiers piece.
ParsingDeclSpec DS(*this);
+ if (Attr)
+ DS.AddAttributes(Attr);
+
ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS);
// C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
@@ -719,7 +730,7 @@
// If attributes are present, parse them.
if (Tok.is(tok::kw___attribute))
// FIXME: attach attributes too.
- AttrList = ParseAttributes();
+ AttrList = ParseGNUAttributes();
// Ask the actions module to compute the type for this declarator.
Action::DeclPtrTy Param =
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=89543&r1=89542&r2=89543&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Sat Nov 21 02:43:09 2009
@@ -2149,6 +2149,11 @@
bool CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,
const CXXMethodDecl *Old);
+ /// CheckOverridingFunctionAttributes - Checks whether attributes are
+ /// incompatible or prevent overriding.
+ bool CheckOverridingFunctionAttributes(const CXXMethodDecl *New,
+ const CXXMethodDecl *Old);
+
//===--------------------------------------------------------------------===//
// C++ Access Control
//
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=89543&r1=89542&r2=89543&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Sat Nov 21 02:43:09 2009
@@ -2613,7 +2613,8 @@
E = Paths.found_decls_end(); I != E; ++I) {
if (CXXMethodDecl *OldMD = dyn_cast<CXXMethodDecl>(*I)) {
if (!CheckOverridingFunctionReturnType(MD, OldMD) &&
- !CheckOverridingFunctionExceptionSpec(MD, OldMD))
+ !CheckOverridingFunctionExceptionSpec(MD, OldMD) &&
+ !CheckOverridingFunctionAttributes(MD, OldMD))
MD->addOverriddenMethod(OldMD);
}
}
@@ -2883,7 +2884,6 @@
NewFD->setAccess(AS_public);
}
-
if (CXXMethodDecl *NewMD = dyn_cast<CXXMethodDecl>(NewFD))
AddOverriddenMethods(cast<CXXRecordDecl>(DC), NewMD);
Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=89543&r1=89542&r2=89543&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Sat Nov 21 02:43:09 2009
@@ -464,7 +464,9 @@
if (!isFunctionOrMethod(d) && !isa<BlockDecl>(d)) {
ValueDecl *VD = dyn_cast<ValueDecl>(d);
if (VD == 0 || !VD->getType()->isBlockPointerType()) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ S.Diag(Attr.getLoc(),
+ Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type
+ : diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << 0 /*function*/;
return false;
}
@@ -484,6 +486,15 @@
d->addAttr(::new (S.Context) AnalyzerNoReturnAttr());
}
+static void HandleDependencyAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ if (!isFunctionOrMethod(d) && !isa<ParmVarDecl>(d)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
+ << Attr.getName() << 8; /*function, method, or parameter*/
+ return;
+ }
+ // FIXME: Actually store the attribute on the declaration
+}
+
static void HandleUnusedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
// check the attribute arguments.
if (Attr.getNumArgs() != 0) {
@@ -1516,6 +1527,10 @@
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
return;
}
+
+ //FIXME: The C++0x version of this attribute has more limited applicabilty
+ // than GNU's, and should error out when it is used to specify a
+ // weaker alignment, rather than being silently ignored.
unsigned Align = 0;
if (Attr.getNumArgs() == 0) {
@@ -1794,6 +1809,29 @@
d->addAttr(::new (S.Context) RegparmAttr(NumParams.getZExtValue()));
}
+static void HandleFinalAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ // check the attribute arguments.
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return;
+ }
+
+ if (!isa<CXXRecordDecl>(d)
+ && (!isa<CXXMethodDecl>(d) || !cast<CXXMethodDecl>(d)->isVirtual())) {
+ S.Diag(Attr.getLoc(),
+ Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type
+ : diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << 7 /*virtual method or class*/;
+ return;
+ }
+
+ // FIXME: Check that it's not specified more than once in an attribute-
+ // specifier and that it conforms to the C++0x rules for
+ // redeclarations.
+
+ d->addAttr(::new (S.Context) FinalAttr());
+}
+
//===----------------------------------------------------------------------===//
// Checker-specific attribute handlers.
//===----------------------------------------------------------------------===//
@@ -1841,7 +1879,8 @@
/// ProcessDeclAttribute - Apply the specific attribute to the specified decl if
/// the attribute applies to decls. If the attribute is a type attribute, just
-/// silently ignore it.
+/// silently ignore it if a GNU attribute. FIXME: Applying a C++0x attribute to
+/// the wrong thing is illegal (C++0x [dcl.attr.grammar]/4).
static void ProcessDeclAttribute(Scope *scope, Decl *D,
const AttributeList &Attr, Sema &S) {
if (Attr.isDeclspecAttribute())
@@ -1861,6 +1900,8 @@
case AttributeList::AT_analyzer_noreturn:
HandleAnalyzerNoReturnAttr (D, Attr, S); break;
case AttributeList::AT_annotate: HandleAnnotateAttr (D, Attr, S); break;
+ case AttributeList::AT_carries_dependency:
+ HandleDependencyAttr (D, Attr, S); break;
case AttributeList::AT_cdecl: HandleCDeclAttr (D, Attr, S); break;
case AttributeList::AT_constructor: HandleConstructorAttr(D, Attr, S); break;
case AttributeList::AT_deprecated: HandleDeprecatedAttr(D, Attr, S); break;
@@ -1871,9 +1912,10 @@
HandleExtVectorTypeAttr(scope, D, Attr, S);
break;
case AttributeList::AT_fastcall: HandleFastCallAttr (D, Attr, S); break;
+ case AttributeList::AT_final: HandleFinalAttr (D, Attr, S); break;
case AttributeList::AT_format: HandleFormatAttr (D, Attr, S); break;
case AttributeList::AT_format_arg: HandleFormatArgAttr (D, Attr, S); break;
- case AttributeList::AT_gnu_inline: HandleGNUInlineAttr(D, Attr, S); break;
+ case AttributeList::AT_gnu_inline: HandleGNUInlineAttr (D, Attr, S); break;
case AttributeList::AT_mode: HandleModeAttr (D, Attr, S); break;
case AttributeList::AT_malloc: HandleMallocAttr (D, Attr, S); break;
case AttributeList::AT_nonnull: HandleNonNullAttr (D, Attr, S); break;
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=89543&r1=89542&r2=89543&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Sat Nov 21 02:43:09 2009
@@ -489,6 +489,13 @@
Class->setEmpty(false);
if (CXXBaseDecl->isPolymorphic())
Class->setPolymorphic(true);
+ // C++0x CWG Issue #817 indicates that [[final]] classes shouldn't be bases.
+ if (CXXBaseDecl->hasAttr<FinalAttr>()) {
+ Diag(BaseLoc, diag::err_final_base) << BaseType.getAsString();
+ Diag(CXXBaseDecl->getLocation(), diag::note_previous_class_decl)
+ << BaseType.getAsString();
+ return 0;
+ }
// C++ [dcl.init.aggr]p1:
// An aggregate is [...] a class with [...] no base classes [...].
@@ -4896,6 +4903,19 @@
return false;
}
+bool Sema::CheckOverridingFunctionAttributes(const CXXMethodDecl *New,
+ const CXXMethodDecl *Old)
+{
+ if (Old->hasAttr<FinalAttr>()) {
+ Diag(New->getLocation(), diag::err_final_function_overridden)
+ << New->getDeclName();
+ Diag(Old->getLocation(), diag::note_overridden_virtual_function);
+ return true;
+ }
+
+ return false;
+}
+
/// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse an
/// initializer for the declaration 'Dcl'.
/// After this method is called, according to [C++ 3.4.1p13], if 'Dcl' is a
Added: cfe/trunk/test/Parser/cxx0x-attributes.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx0x-attributes.cpp?rev=89543&view=auto
==============================================================================
--- cfe/trunk/test/Parser/cxx0x-attributes.cpp (added)
+++ cfe/trunk/test/Parser/cxx0x-attributes.cpp Sat Nov 21 02:43:09 2009
@@ -0,0 +1,61 @@
+// RUN: clang-cc -fsyntax-only -verify -std=c++0x %s
+
+// Declaration syntax checks
+[[]] int before_attr;
+int after_attr [[]];
+int * [[]] ptr_attr;
+int array_attr [1] [[]];
+[[align(8)]] int aligned_attr;
+[[test::valid(for 42 [very] **** '+' symbols went on a trip; the end.)]]
+ int garbage_attr;
+void fn_attr () [[]];
+class [[]] class_attr {};
+extern "C++" [[]] int extern_attr;
+template <typename T> [[]] void template_attr ();
+
+int comma_attr [[,]]; // expected-error {{expected identifier}}
+int scope_attr [[foo::]]; // expected-error {{expected identifier}}
+int & [[]] ref_attr = after_attr; // expected-error {{an attribute list cannot appear here}}
+class foo {
+ void after_const_attr () const [[]]; // expected-error {{expected expression}}
+};
+extern "C++" [[]] { } // expected-error {{an attribute list cannot appear here}}
+[[]] template <typename T> void before_template_attr (); // expected-error {{an attribute list cannot appear here}}
+[[]] namespace ns { int i; } // expected-error {{an attribute list cannot appear here}}
+[[]] static_assert(true, ""); //expected-error {{an attribute list cannot appear here}}
+[[]] asm(""); // expected-error {{an attribute list cannot appear here}}
+
+[[]] using ns::i; // expected-error {{an attribute list cannot appear here}}
+[[]] using namespace ns;
+
+// Argument tests
+[[final()]] int final_params; // expected-error {{C++0x attribute 'final' cannot have an argument list}}
+[[align]] int aligned_no_params; // expected-error {{C++0x attribute 'align' must have an argument list}}
+[[align(i)]] int aligned_nonconst; // expected-error {{'aligned' attribute requires integer constant}}
+
+// Statement tests
+void foo () {
+ [[]] ;
+ [[]] { }
+ [[]] if (0) { }
+ [[]] for (;;);
+ [[]] do {
+ [[]] continue;
+ } while (0);
+ [[]] while (0);
+
+ [[]] switch (i) {
+ [[]] case 0:
+ [[]] default:
+ [[]] break;
+ }
+
+ [[]] goto there;
+ [[]] there:
+
+ [[]] try {
+ } [[]] catch (...) { // expected-error {{an attribute list cannot appear here}}
+ }
+
+ [[]] return;
+}
Added: cfe/trunk/test/SemaCXX/attr-cxx0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/attr-cxx0x.cpp?rev=89543&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/attr-cxx0x.cpp (added)
+++ cfe/trunk/test/SemaCXX/attr-cxx0x.cpp Sat Nov 21 02:43:09 2009
@@ -0,0 +1,24 @@
+// RUN: clang-cc -fsyntax-only -verify -std=c++0x %s
+
+int final_fail [[final]]; //expected-error {{'final' attribute only applies to virtual method or class types}}
+
+struct [[final]] final_base { }; // expected-note {{struct final_base declared here}}
+struct final_child : final_base { }; // expected-error {{derivation from 'final' struct final_base}}
+
+struct final_member { virtual void quux [[final]] (); }; // expected-note {{overridden virtual function is here}}
+struct final_override : final_member { virtual void quux (); }; // expected-error {{declaration of 'quux' overrides a 'final' function}}
+
+int align_illegal [[align(3)]]; //expected-error {{requested alignment is not a power of 2}}
+char align_big [[align(int)]];
+int align_small [[align(1)]];
+int align_multiple [[align(1), align(8), align(1)]];
+
+struct align_member {
+ int member [[align(8)]];
+};
+
+static_assert(alignof(align_big) == alignof(int), "k's alignment is wrong");
+static_assert(alignof(align_small) == alignof(int), "j's alignment is wrong");
+static_assert(alignof(align_multiple) == 8, "l's alignment is wrong");
+static_assert(alignof(align_member) == 8, "quuux's alignment is wrong");
+static_assert(sizeof(align_member) == 8, "quuux's size is wrong");
More information about the cfe-commits
mailing list