]> granicus.if.org Git - clang/commitdiff
Fix assertion on C++ attributes in fillAttributedTypeLoc
authorAlexander Musman <alexander.musman@gmail.com>
Fri, 29 May 2015 11:24:32 +0000 (11:24 +0000)
committerAlexander Musman <alexander.musman@gmail.com>
Fri, 29 May 2015 11:24:32 +0000 (11:24 +0000)
this fixes http://llvm.org/PR17424
fillAttributedTypeLoc() function is only called with AttributeLists of either
DeclarationChunk (which is used for each type in a declarator being parsed) or
DeclSpec (which captures information about declaration specifiers).
As C++11 attributes actually appertain to declarators, they are moved straight
to the declarator’s attr list in distributeFunctionTypeAttrFromDeclSpec()
function.
'Put them wherever you like' semantics is not supported for C++11 attributes
(but is allowed for GNU attributes, for example). So when we meet an attribute
while parsing the declaration, we cannot be sure if it appertains to either
DeclarationChunk or DeclSpec.

This investigation correlates with the history of changes of SemaType.cpp:
• Asserts in fillAttributedTypeLoc() were added on 3 Mar 2011 in r126986
(http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-
        20110228/039638.html);
• Distributing C++11 attrs to the declarator was added on 14 Jan 2013
in r172504 (http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-
        20130114/071830.html).
Considering all written above I changed asserts in fillAttributedTypeLoc()
to nullptr checks.

This fixes PR17424 and related assertion on
[[gnu::fastcall]] void __stdcall foo();

Author: Alexey Frolov

Differential Revision: http://reviews.llvm.org/D9288

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@238550 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaType.cpp
test/SemaCXX/cxx11-gnu-attrs.cpp

index 91859be9cad544a09e52b8dd11773d5a968c2c23..628eb734cdd61e93181af7ee80dd013fff8db80d 100644 (file)
@@ -3500,16 +3500,27 @@ static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) {
 }
 
 static void fillAttributedTypeLoc(AttributedTypeLoc TL,
-                                  const AttributeList *attrs) {
-  AttributedType::Kind kind = TL.getAttrKind();
-
-  assert(attrs && "no type attributes in the expected location!");
-  AttributeList::Kind parsedKind = getAttrListKind(kind);
-  while (attrs->getKind() != parsedKind) {
+                                  const AttributeList *attrs,
+                                  const AttributeList *DeclAttrs = nullptr) {
+  // DeclAttrs and attrs cannot be both empty.
+  assert((attrs || DeclAttrs) &&
+         "no type attributes in the expected location!");
+
+  AttributeList::Kind parsedKind = getAttrListKind(TL.getAttrKind());
+  // Try to search for an attribute of matching kind in attrs list.
+  while (attrs && attrs->getKind() != parsedKind)
     attrs = attrs->getNext();
-    assert(attrs && "no matching attribute in expected location!");
+  if (!attrs) {
+    // No matching type attribute in attrs list found.
+    // Try searching through C++11 attributes in the declarator attribute list.
+    while (DeclAttrs && (!DeclAttrs->isCXX11Attribute() ||
+                         DeclAttrs->getKind() != parsedKind))
+      DeclAttrs = DeclAttrs->getNext();
+    attrs = DeclAttrs;
   }
 
+  assert(attrs && "no matching type attribute in expected location!");
+
   TL.setAttrNameLoc(attrs->getLoc());
   if (TL.hasAttrExprOperand()) {
     assert(attrs->isArgExpr(0) && "mismatched attribute operand kind");
@@ -3863,6 +3874,7 @@ Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
                                      TypeSourceInfo *ReturnTypeInfo) {
   TypeSourceInfo *TInfo = Context.CreateTypeSourceInfo(T);
   UnqualTypeLoc CurrTL = TInfo->getTypeLoc().getUnqualifiedLoc();
+  const AttributeList *DeclAttrs = D.getAttributes();
 
   // Handle parameter packs whose type is a pack expansion.
   if (isa<PackExpansionType>(T)) {
@@ -3879,7 +3891,7 @@ Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
     }
 
     while (AttributedTypeLoc TL = CurrTL.getAs<AttributedTypeLoc>()) {
-      fillAttributedTypeLoc(TL, D.getTypeObject(i).getAttrs());
+      fillAttributedTypeLoc(TL, D.getTypeObject(i).getAttrs(), DeclAttrs);
       CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
     }
 
index ac9cc55b9fcb04cebcc54ba9975e2ccf934d493c..d20617815e6a0086ca8421eabb95dfca8ff51174 100644 (file)
@@ -8,6 +8,19 @@ int [[gnu::unused]] attr_on_type;
 // expected-error@-1 {{'unused' attribute cannot be applied to types}}
 int *[[gnu::unused]] attr_on_ptr;
 // expected-warning@-1 {{attribute 'unused' ignored, because it cannot be applied to a type}}
+[[gnu::fastcall]] void pr17424_1();
+// expected-warning@-1 {{calling convention 'fastcall' ignored for this target}}
+[[gnu::fastcall]] [[gnu::stdcall]] void pr17424_2();
+// expected-warning@-1 {{calling convention 'fastcall' ignored for this target}}
+// expected-warning@-2 {{calling convention 'stdcall' ignored for this target}}
+[[gnu::fastcall]] __stdcall void pr17424_3();
+// expected-warning@-1 {{calling convention 'fastcall' ignored for this target}}
+// expected-warning@-2 {{calling convention '__stdcall' ignored for this target}}
+[[gnu::fastcall]] void pr17424_4() [[gnu::stdcall]];
+// expected-warning@-1 {{calling convention 'fastcall' ignored for this target}}
+// expected-warning@-2 {{attribute 'stdcall' ignored, because it cannot be applied to a type}}
+void pr17424_5 [[gnu::fastcall]]();
+// expected-warning@-1 {{calling convention 'fastcall' ignored for this target}}
 
 // Valid cases.