[cfe-commits] [patch] C++0x Attributes

Douglas Gregor dgregor at apple.com
Tue Oct 20 21:28:40 PDT 2009


On Oct 15, 2009, at 8:04 PM, Sean Hunt wrote:
> Attached is my first "ready" version of the C++0x attributes patch.  
> It's certainly not complete (and there's lots of FIXMEs), but the  
> code works, and adds some neat new features like [[final]] to clang.

Nifty.

@@ -2197,7 +2209,7 @@
def ext_return_has_void_expr : Extension<
   "void %select{function|method}1 %0 should not return void  
expression">;
def warn_noreturn_function_has_return_expr : Warning<
-  "function %0 declared 'noreturn' should not return">, DefaultError,
+  "function %0 declared 'noreturn' should not return">,

I'm still going to ask that this be separated; feel free to go ahead  
and commit this change by itself.

@@ -239,6 +240,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' can't have an argument list">;

"cannot"

Index: include/clang/AST/Attr.h
===================================================================
--- include/clang/AST/Attr.h	(revision 84241)
+++ include/clang/AST/Attr.h	(working copy)
@@ -58,6 +58,7 @@
     Deprecated,
     Destructor,
     FastCall,
+    Final,
     Format,
     FormatArg,
     GNUInline,

So carries_dependency isn't getting into the AST; that's fine.

Index: lib/CodeGen/CodeGenModule.cpp
===================================================================
--- lib/CodeGen/CodeGenModule.cpp	(revision 84241)
+++ lib/CodeGen/CodeGenModule.cpp	(working copy)
@@ -347,8 +347,11 @@
   if (D->hasAttr<NoInlineAttr>())
     F->addFnAttr(llvm::Attribute::NoInline);

-  if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
+  if (const AlignedAttr *AA = D->getAttr<AlignedAttr>()) {
     F->setAlignment(AA->getAlignment()/8);
+    while ((AA = AA->getNext<AlignedAttr>()))
+      F->setAlignment(std::max(F->getAlignment(), AA->getAlignment()/ 
8));
+  }

Do we really want to hardcode that 8? :)

Index: lib/Sema/SemaDeclCXX.cpp
===================================================================
--- lib/Sema/SemaDeclCXX.cpp	(revision 84241)
+++ lib/Sema/SemaDeclCXX.cpp	(working copy)
@@ -478,6 +478,11 @@
     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();
+    return 0;
+  }


It'd be nice to have a note here that points to the declaration of the  
base (CXXBaseDecl->getLocation()).

+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
+}
+

@@ -531,8 +535,11 @@

     if (FieldPacked)
       FieldAlign = 1;
-    if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
-      FieldAlign = std::max(FieldAlign, AA->getAlignment());
+    if (const AlignedAttr *AA = D->getAttr<AlignedAttr>()) {
+      do {
+        FieldAlign = std::max(FieldAlign, AA->getAlignment());
+      } while (AA->getNext<AlignedAttr>());
+    }

I see at least four loops of this kind... could you abstract out the  
"compute alignment for a decl based on an initial value and its  
attributes" code?

+CXX0XAttributeList Parser::ParseCXX0XAttributes(SourceLocation  
*EndLoc) {

In this function, the parsing of "aligned" is rather large and deeply  
nested; could you move it to a separate function?

Index: lib/Parse/ParseDeclCXX.cpp
===================================================================
--- lib/Parse/ParseDeclCXX.cpp	(revision 84241)
+++ lib/Parse/ParseDeclCXX.cpp	(working copy)
@@ -68,7 +68,7 @@
     attrTok = Tok;

     // FIXME: save these somewhere.
-    AttrList = ParseAttributes();
+    AttrList = ParseGNUAttributes();
   }

   if (Tok.is(tok::equal)) {
@@ -96,8 +96,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);
+  }

I find it a little bit odd that we parse the attributes at this level,  
rather than parsing them inside ParseExternalDeclaration. Any  
particular reason for this decision?

+  tok::TokenKind AfterTok = Tok.getKind();
+  bool HasAttr = false;
+
+  // Check to see if there is an optional attribute-specifier (C++0x  
only).
+  // We have to know now so that we can look ahead and see if we  
actually want
+  // to parse it.
+  if (getLang().CPlusPlus0x)
+    HasAttr = isCXX0XAttributeSpecifier(&AfterTok);

This is in ParseClassSpecifier, and there's good news here: CWG  
discussed issue 962 today, and the attributes for class and enum  
specifiers will be moving to the same place where GNU puts them,  
between the class-key/"enum" keyword and the identifier. That will  
eliminate the need for lookahead here (yay!).

Speaking of lookahead... we seem to be calling  
isCXX0XAttributeSpecifier() in a bunch of places where "[[" will  
always end up starting at attribute, which means we're doing a bunch  
of unnecessary lookahead. As attributes become more popular, this  
could actually matter. Could we have a bool argument to  
isCXX0XAttributeSpecifier to tell it whether it should just look for  
the prefix "[[" vs. having to look for the full attribute-specifier?

@@ -391,8 +394,8 @@
/// [C++0x] empty-declaration:
///           ';'
///
-/// [C++0x/GNU] 'extern' 'template' declaration
-Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration() {
+/// [C++0x/GNU] 'extern' 'temp;ate' declaration
+Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration 
(CXX0XAttributeList Attr) {

Typo "temp;ate".

We seem to be missing test cases? Otherwise, this is looking very good.

	- Doug



More information about the cfe-commits mailing list