[cfe-commits] r69225 - in /cfe/trunk: include/clang/AST/Attr.h include/clang/Frontend/PCHBitCodes.h include/clang/Frontend/PCHReader.h include/clang/Frontend/PCHWriter.h lib/Frontend/PCHReader.cpp lib/Frontend/PCHWriter.cpp test/PCH/attrs.c test/PCH/attrs.h

Douglas Gregor dgregor at apple.com
Wed Apr 15 14:30:52 PDT 2009


Author: dgregor
Date: Wed Apr 15 16:30:51 2009
New Revision: 69225

URL: http://llvm.org/viewvc/llvm-project?rev=69225&view=rev
Log:
PCH support for declaration attributes

Added:
    cfe/trunk/test/PCH/attrs.c
    cfe/trunk/test/PCH/attrs.h
Modified:
    cfe/trunk/include/clang/AST/Attr.h
    cfe/trunk/include/clang/Frontend/PCHBitCodes.h
    cfe/trunk/include/clang/Frontend/PCHReader.h
    cfe/trunk/include/clang/Frontend/PCHWriter.h
    cfe/trunk/lib/Frontend/PCHReader.cpp
    cfe/trunk/lib/Frontend/PCHWriter.cpp

Modified: cfe/trunk/include/clang/AST/Attr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Attr.h?rev=69225&r1=69224&r2=69225&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Attr.h (original)
+++ cfe/trunk/include/clang/AST/Attr.h Wed Apr 15 16:30:51 2009
@@ -377,7 +377,12 @@
   virtual ~NonNullAttr() {
     delete [] ArgNums;
   }
-  
+
+  typedef const unsigned *iterator;
+  iterator begin() const { return ArgNums; }
+  iterator end() const { return ArgNums + Size; }
+  unsigned size() const { return Size; }
+
   bool isNonNull(unsigned arg) const {
     return ArgNums ? std::binary_search(ArgNums, ArgNums+Size, arg) : true;
   }  

Modified: cfe/trunk/include/clang/Frontend/PCHBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHBitCodes.h?rev=69225&r1=69224&r2=69225&view=diff

==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHBitCodes.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHBitCodes.h Wed Apr 15 16:30:51 2009
@@ -260,54 +260,59 @@
     /// constant describes a record for a specific type class in the
     /// AST.
     enum TypeCode {
+      /// \brief Attributes attached to a type.
+      /// 
+      /// Note that this has the same value as DECL_ATTR, since
+      /// attribute blocks are used for both types and declarations.
+      TYPE_ATTR                     = 1,
       /// \brief An ExtQualType record.
-      TYPE_EXT_QUAL                 = 1,
+      TYPE_EXT_QUAL                 = 2,
       /// \brief A FixedWidthIntType record.
-      TYPE_FIXED_WIDTH_INT          = 2,
+      TYPE_FIXED_WIDTH_INT          = 3,
       /// \brief A ComplexType record.
-      TYPE_COMPLEX                  = 3,
+      TYPE_COMPLEX                  = 4,
       /// \brief A PointerType record.
-      TYPE_POINTER                  = 4,
+      TYPE_POINTER                  = 5,
       /// \brief A BlockPointerType record.
-      TYPE_BLOCK_POINTER            = 5,
+      TYPE_BLOCK_POINTER            = 6,
       /// \brief An LValueReferenceType record.
-      TYPE_LVALUE_REFERENCE         = 6,
+      TYPE_LVALUE_REFERENCE         = 7,
       /// \brief An RValueReferenceType record.
-      TYPE_RVALUE_REFERENCE         = 7,
+      TYPE_RVALUE_REFERENCE         = 8,
       /// \brief A MemberPointerType record.
-      TYPE_MEMBER_POINTER           = 8,
+      TYPE_MEMBER_POINTER           = 9,
       /// \brief A ConstantArrayType record.
-      TYPE_CONSTANT_ARRAY           = 9,
+      TYPE_CONSTANT_ARRAY           = 10,
       /// \brief An IncompleteArrayType record.
-      TYPE_INCOMPLETE_ARRAY         = 10,
+      TYPE_INCOMPLETE_ARRAY         = 11,
       /// \brief A VariableArrayType record.
-      TYPE_VARIABLE_ARRAY           = 11,
+      TYPE_VARIABLE_ARRAY           = 12,
       /// \brief A VectorType record.
-      TYPE_VECTOR                   = 12,
+      TYPE_VECTOR                   = 13,
       /// \brief An ExtVectorType record.
-      TYPE_EXT_VECTOR               = 13,
+      TYPE_EXT_VECTOR               = 14,
       /// \brief A FunctionNoProtoType record.
-      TYPE_FUNCTION_NO_PROTO        = 14,
+      TYPE_FUNCTION_NO_PROTO        = 15,
       /// \brief A FunctionProtoType record.
-      TYPE_FUNCTION_PROTO           = 15,
+      TYPE_FUNCTION_PROTO           = 16,
       /// \brief A TypedefType record.
-      TYPE_TYPEDEF                  = 16,
+      TYPE_TYPEDEF                  = 17,
       /// \brief A TypeOfExprType record.
-      TYPE_TYPEOF_EXPR              = 17,
+      TYPE_TYPEOF_EXPR              = 18,
       /// \brief A TypeOfType record.
-      TYPE_TYPEOF                   = 18,
+      TYPE_TYPEOF                   = 19,
       /// \brief A RecordType record.
-      TYPE_RECORD                   = 19,
+      TYPE_RECORD                   = 20,
       /// \brief An EnumType record.
-      TYPE_ENUM                     = 20,
+      TYPE_ENUM                     = 21,
       /// \brief An ObjCInterfaceType record.
-      TYPE_OBJC_INTERFACE           = 21,
+      TYPE_OBJC_INTERFACE           = 22,
       /// \brief An ObjCQualifiedInterfaceType record.
-      TYPE_OBJC_QUALIFIED_INTERFACE = 22,
+      TYPE_OBJC_QUALIFIED_INTERFACE = 23,
       /// \brief An ObjCQualifiedIdType record.
-      TYPE_OBJC_QUALIFIED_ID        = 23,
+      TYPE_OBJC_QUALIFIED_ID        = 24,
       /// \brief An ObjCQualifiedClassType record.
-      TYPE_OBJC_QUALIFIED_CLASS     = 24
+      TYPE_OBJC_QUALIFIED_CLASS     = 25
     };
 
     /// \brief Record codes for each kind of declaration.
@@ -317,8 +322,13 @@
     /// constant describes a record for a specific declaration class
     /// in the AST.
     enum DeclCode {
+      /// \brief Attributes attached to a declaration.
+      /// 
+      /// Note that this has the same value as TYPE_ATTR, since
+      /// attribute blocks are used for both types and declarations.
+      DECL_ATTR = 1,
       /// \brief A TranslationUnitDecl record.
-      DECL_TRANSLATION_UNIT = 1,
+      DECL_TRANSLATION_UNIT,
       /// \brief A TypedefDecl record.
       DECL_TYPEDEF,
       /// \brief An EnumDecl record.

Modified: cfe/trunk/include/clang/Frontend/PCHReader.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHReader.h?rev=69225&r1=69224&r2=69225&view=diff

==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHReader.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHReader.h Wed Apr 15 16:30:51 2009
@@ -37,6 +37,7 @@
 namespace clang {
 
 class ASTContext;
+class Attr;
 class Decl;
 class DeclContext;
 class Preprocessor;
@@ -225,6 +226,12 @@
   /// \brief Read a floating-point value
   llvm::APFloat ReadAPFloat(const RecordData &Record, unsigned &Idx);
 
+  // \brief Read a string
+  std::string ReadString(const RecordData &Record, unsigned &Idx);
+
+  /// \brief Reads attributes from the current stream position.
+  Attr *ReadAttributes();
+
   /// \brief Reads an expression from the current stream position.
   Expr *ReadExpr();
 

Modified: cfe/trunk/include/clang/Frontend/PCHWriter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHWriter.h?rev=69225&r1=69224&r2=69225&view=diff

==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHWriter.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHWriter.h Wed Apr 15 16:30:51 2009
@@ -118,6 +118,9 @@
   uint64_t WriteDeclContextVisibleBlock(ASTContext &Context, DeclContext *DC);
   void WriteDeclsBlock(ASTContext &Context);
   void WriteIdentifierTable();
+  void WriteAttributeRecord(const Attr *Attr);
+
+  void AddString(const std::string &Str, RecordData &Record);
 
 public:
   /// \brief Create a new precompiled header writer that outputs to

Modified: cfe/trunk/lib/Frontend/PCHReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReader.cpp?rev=69225&r1=69224&r2=69225&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/PCHReader.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReader.cpp Wed Apr 15 16:30:51 2009
@@ -74,7 +74,8 @@
                      cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++])));
   D->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
   D->setInvalidDecl(Record[Idx++]);
-  // FIXME: hasAttrs
+  if (Record[Idx++])
+    D->addAttr(Reader.ReadAttributes());
   D->setImplicit(Record[Idx++]);
   D->setAccess((AccessSpecifier)Record[Idx++]);
 }
@@ -1074,6 +1075,10 @@
   RecordData Record;
   unsigned Code = Stream.ReadCode();
   switch ((pch::TypeCode)Stream.ReadRecord(Code, Record)) {
+  case pch::TYPE_ATTR:
+    assert(false && "Should never jump to an attribute block");
+    return QualType();
+
   case pch::TYPE_EXT_QUAL:
     // FIXME: Deserialize ExtQualType
     assert(false && "Cannot deserialize qualified types yet");
@@ -1264,6 +1269,12 @@
   PCHDeclReader Reader(*this, Record, Idx);
 
   switch ((pch::DeclCode)Stream.ReadRecord(Code, Record)) {
+  case pch::DECL_ATTR:
+  case pch::DECL_CONTEXT_LEXICAL:
+  case pch::DECL_CONTEXT_VISIBLE:
+    assert(false && "Record cannot be de-serialized with ReadDeclRecord");
+    break;
+
   case pch::DECL_TRANSLATION_UNIT:
     assert(Index == 0 && "Translation unit must be at index 0");
     Reader.VisitTranslationUnitDecl(Context.getTranslationUnitDecl());
@@ -1372,10 +1383,6 @@
     D = Block;
     break;
   }
-
-  default:
-    assert(false && "Cannot de-serialize this kind of declaration");
-    break;
   }
 
   // If this declaration is also a declaration context, get the
@@ -1635,6 +1642,146 @@
   return llvm::APFloat(ReadAPInt(Record, Idx));
 }
 
+// \brief Read a string
+std::string PCHReader::ReadString(const RecordData &Record, unsigned &Idx) {
+  unsigned Len = Record[Idx++];
+  std::string Result(&Record[Idx], &Record[Idx] + Len);
+  Idx += Len;
+  return Result;
+}
+
+/// \brief Reads attributes from the current stream position.
+Attr *PCHReader::ReadAttributes() {
+  unsigned Code = Stream.ReadCode();
+  assert(Code == llvm::bitc::UNABBREV_RECORD && 
+         "Expected unabbreviated record"); (void)Code;
+  
+  RecordData Record;
+  unsigned Idx = 0;
+  unsigned RecCode = Stream.ReadRecord(Code, Record);
+  assert(RecCode == pch::DECL_ATTR && "Expected attribute record"); 
+  (void)RecCode;
+
+#define SIMPLE_ATTR(Name)                       \
+ case Attr::Name:                               \
+   New = ::new (Context) Name##Attr();          \
+   break
+
+#define STRING_ATTR(Name)                                       \
+ case Attr::Name:                                               \
+   New = ::new (Context) Name##Attr(ReadString(Record, Idx));   \
+   break
+
+#define UNSIGNED_ATTR(Name)                             \
+ case Attr::Name:                                       \
+   New = ::new (Context) Name##Attr(Record[Idx++]);     \
+   break
+
+  Attr *Attrs = 0;
+  while (Idx < Record.size()) {
+    Attr *New = 0;
+    Attr::Kind Kind = (Attr::Kind)Record[Idx++];
+    bool IsInherited = Record[Idx++];
+
+    switch (Kind) {
+    STRING_ATTR(Alias);
+    UNSIGNED_ATTR(Aligned);
+    SIMPLE_ATTR(AlwaysInline);
+    SIMPLE_ATTR(AnalyzerNoReturn);
+    STRING_ATTR(Annotate);
+    STRING_ATTR(AsmLabel);
+    
+    case Attr::Blocks:
+      New = ::new (Context) BlocksAttr(
+                                  (BlocksAttr::BlocksAttrTypes)Record[Idx++]);
+      break;
+      
+    case Attr::Cleanup:
+      New = ::new (Context) CleanupAttr(
+                                  cast<FunctionDecl>(GetDecl(Record[Idx++])));
+      break;
+
+    SIMPLE_ATTR(Const);
+    UNSIGNED_ATTR(Constructor);
+    SIMPLE_ATTR(DLLExport);
+    SIMPLE_ATTR(DLLImport);
+    SIMPLE_ATTR(Deprecated);
+    UNSIGNED_ATTR(Destructor);
+    SIMPLE_ATTR(FastCall);
+    
+    case Attr::Format: {
+      std::string Type = ReadString(Record, Idx);
+      unsigned FormatIdx = Record[Idx++];
+      unsigned FirstArg = Record[Idx++];
+      New = ::new (Context) FormatAttr(Type, FormatIdx, FirstArg);
+      break;
+    }
+
+    SIMPLE_ATTR(GNUCInline);
+    
+    case Attr::IBOutletKind:
+      New = ::new (Context) IBOutletAttr();
+      break;
+
+    SIMPLE_ATTR(NoReturn);
+    SIMPLE_ATTR(NoThrow);
+    SIMPLE_ATTR(Nodebug);
+    SIMPLE_ATTR(Noinline);
+    
+    case Attr::NonNull: {
+      unsigned Size = Record[Idx++];
+      llvm::SmallVector<unsigned, 16> ArgNums;
+      ArgNums.insert(ArgNums.end(), &Record[Idx], &Record[Idx] + Size);
+      Idx += Size;
+      New = ::new (Context) NonNullAttr(&ArgNums[0], Size);
+      break;
+    }
+
+    SIMPLE_ATTR(ObjCException);
+    SIMPLE_ATTR(ObjCNSObject);
+    SIMPLE_ATTR(Overloadable);
+    UNSIGNED_ATTR(Packed);
+    SIMPLE_ATTR(Pure);
+    UNSIGNED_ATTR(Regparm);
+    STRING_ATTR(Section);
+    SIMPLE_ATTR(StdCall);
+    SIMPLE_ATTR(TransparentUnion);
+    SIMPLE_ATTR(Unavailable);
+    SIMPLE_ATTR(Unused);
+    SIMPLE_ATTR(Used);
+    
+    case Attr::Visibility:
+      New = ::new (Context) VisibilityAttr(
+                              (VisibilityAttr::VisibilityTypes)Record[Idx++]);
+      break;
+
+    SIMPLE_ATTR(WarnUnusedResult);
+    SIMPLE_ATTR(Weak);
+    SIMPLE_ATTR(WeakImport);
+    }
+
+    assert(New && "Unable to decode attribute?");
+    New->setInherited(IsInherited);
+    New->setNext(Attrs);
+    Attrs = New;
+  }
+#undef UNSIGNED_ATTR
+#undef STRING_ATTR
+#undef SIMPLE_ATTR
+
+  // The list of attributes was built backwards. Reverse the list
+  // before returning it.
+  Attr *PrevAttr = 0, *NextAttr = 0;
+  while (Attrs) {
+    NextAttr = Attrs->getNext();
+    Attrs->setNext(PrevAttr);
+    PrevAttr = Attrs;
+    Attrs = NextAttr;
+  }
+
+  return PrevAttr;
+}
+
 Expr *PCHReader::ReadExpr() {
   // Within the bitstream, expressions are stored in Reverse Polish
   // Notation, with each of the subexpressions preceding the

Modified: cfe/trunk/lib/Frontend/PCHWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriter.cpp?rev=69225&r1=69224&r2=69225&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriter.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriter.cpp Wed Apr 15 16:30:51 2009
@@ -276,7 +276,7 @@
   Writer.AddDeclRef(cast_or_null<Decl>(D->getLexicalDeclContext()), Record);
   Writer.AddSourceLocation(D->getLocation(), Record);
   Record.push_back(D->isInvalidDecl());
-  // FIXME: hasAttrs
+  Record.push_back(D->hasAttrs());
   Record.push_back(D->isImplicit());
   Record.push_back(D->getAccess());
 }
@@ -1131,6 +1131,10 @@
     assert(W.Code && "Unhandled declaration kind while generating PCH");
     S.EmitRecord(W.Code, Record);
 
+    // If the declaration had any attributes, write them now.
+    if (D->hasAttrs())
+      WriteAttributeRecord(D->getAttrs());
+
     // Flush any expressions that were written as part of this declaration.
     FlushExprs();
     
@@ -1209,6 +1213,134 @@
   S.EmitRecord(pch::IDENTIFIER_OFFSET, IdentOffsets);
 }
 
+/// \brief Write a record containing the given attributes.
+void PCHWriter::WriteAttributeRecord(const Attr *Attr) {
+  RecordData Record;
+  for (; Attr; Attr = Attr->getNext()) {
+    Record.push_back(Attr->getKind()); // FIXME: stable encoding
+    Record.push_back(Attr->isInherited());
+    switch (Attr->getKind()) {
+    case Attr::Alias:
+      AddString(cast<AliasAttr>(Attr)->getAliasee(), Record);
+      break;
+
+    case Attr::Aligned:
+      Record.push_back(cast<AlignedAttr>(Attr)->getAlignment());
+      break;
+
+    case Attr::AlwaysInline:
+      break;
+     
+    case Attr::AnalyzerNoReturn:
+      break;
+
+    case Attr::Annotate:
+      AddString(cast<AnnotateAttr>(Attr)->getAnnotation(), Record);
+      break;
+
+    case Attr::AsmLabel:
+      AddString(cast<AsmLabelAttr>(Attr)->getLabel(), Record);
+      break;
+
+    case Attr::Blocks:
+      Record.push_back(cast<BlocksAttr>(Attr)->getType()); // FIXME: stable
+      break;
+
+    case Attr::Cleanup:
+      AddDeclRef(cast<CleanupAttr>(Attr)->getFunctionDecl(), Record);
+      break;
+
+    case Attr::Const:
+      break;
+
+    case Attr::Constructor:
+      Record.push_back(cast<ConstructorAttr>(Attr)->getPriority());
+      break;
+
+    case Attr::DLLExport:
+    case Attr::DLLImport:
+    case Attr::Deprecated:
+      break;
+
+    case Attr::Destructor:
+      Record.push_back(cast<DestructorAttr>(Attr)->getPriority());
+      break;
+
+    case Attr::FastCall:
+      break;
+
+    case Attr::Format: {
+      const FormatAttr *Format = cast<FormatAttr>(Attr);
+      AddString(Format->getType(), Record);
+      Record.push_back(Format->getFormatIdx());
+      Record.push_back(Format->getFirstArg());
+      break;
+    }
+
+    case Attr::GNUCInline:
+    case Attr::IBOutletKind:
+    case Attr::NoReturn:
+    case Attr::NoThrow:
+    case Attr::Nodebug:
+    case Attr::Noinline:
+      break;
+
+    case Attr::NonNull: {
+      const NonNullAttr *NonNull = cast<NonNullAttr>(Attr);
+      Record.push_back(NonNull->size());
+      Record.insert(Record.end(), NonNull->begin(), NonNull->end());
+      break;
+    }
+
+    case Attr::ObjCException:
+    case Attr::ObjCNSObject:
+    case Attr::Overloadable:
+      break;
+
+    case Attr::Packed:
+      Record.push_back(cast<PackedAttr>(Attr)->getAlignment());
+      break;
+
+    case Attr::Pure:
+      break;
+
+    case Attr::Regparm:
+      Record.push_back(cast<RegparmAttr>(Attr)->getNumParams());
+      break;
+
+    case Attr::Section:
+      AddString(cast<SectionAttr>(Attr)->getName(), Record);
+      break;
+
+    case Attr::StdCall:
+    case Attr::TransparentUnion:
+    case Attr::Unavailable:
+    case Attr::Unused:
+    case Attr::Used:
+      break;
+
+    case Attr::Visibility:
+      // FIXME: stable encoding
+      Record.push_back(cast<VisibilityAttr>(Attr)->getVisibility()); 
+      break;
+
+    case Attr::WarnUnusedResult:
+    case Attr::Weak:
+    case Attr::WeakImport:
+      break;
+    }
+  }
+
+  assert((int)pch::DECL_ATTR == (int)pch::TYPE_ATTR && 
+         "DECL_ATTR/TYPE_ATTR mismatch");
+  S.EmitRecord(pch::DECL_ATTR, Record);
+}
+
+void PCHWriter::AddString(const std::string &Str, RecordData &Record) {
+  Record.push_back(Str.size());
+  Record.insert(Record.end(), Str.begin(), Str.end());
+}
+
 PCHWriter::PCHWriter(llvm::BitstreamWriter &S) 
   : S(S), NextTypeID(pch::NUM_PREDEF_TYPE_IDS) { }
 

Added: cfe/trunk/test/PCH/attrs.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/attrs.c?rev=69225&view=auto

==============================================================================
--- cfe/trunk/test/PCH/attrs.c (added)
+++ cfe/trunk/test/PCH/attrs.c Wed Apr 15 16:30:51 2009
@@ -0,0 +1,8 @@
+// Test this without pch.
+// RUN: clang-cc -include %S/attrs.h -fsyntax-only -verify %s
+
+// Test with pch.
+// RUN: clang-cc -emit-pch -o %t %S/attrs.h &&
+// RUN: clang-cc -include-pch %t -fsyntax-only -verify %s 
+// expected-note{{previous overload}}
+double f(double); // expected-error{{overloadable}}

Added: cfe/trunk/test/PCH/attrs.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/attrs.h?rev=69225&view=auto

==============================================================================
--- cfe/trunk/test/PCH/attrs.h (added)
+++ cfe/trunk/test/PCH/attrs.h Wed Apr 15 16:30:51 2009
@@ -0,0 +1,7 @@
+// Header for PCH test exprs.c
+
+
+
+
+
+int f(int) __attribute__((overloadable));





More information about the cfe-commits mailing list