]> granicus.if.org Git - clang/commitdiff
PCH support for functions and their parameters.
authorDouglas Gregor <dgregor@apple.com>
Mon, 13 Apr 2009 22:18:37 +0000 (22:18 +0000)
committerDouglas Gregor <dgregor@apple.com>
Mon, 13 Apr 2009 22:18:37 +0000 (22:18 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68997 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Decl.h
include/clang/Frontend/PCHBitCodes.h
include/clang/Frontend/PCHReader.h
lib/Frontend/PCHReader.cpp
lib/Frontend/PCHWriter.cpp
test/PCH/functions.c [new file with mode: 0644]
test/PCH/functions.h [new file with mode: 0644]

index 03ef88a0ec236a828a48bdef3fbc473b5d44d59c..dffc0ad6e460794aa5991b04a1dd761a65459858 100644 (file)
@@ -510,10 +510,12 @@ private:
                               Expr *DefArg)
   : ParmVarDecl(OriginalParmVar, DC, L, Id, T, S, DefArg), OriginalType(OT) {}
 public:
-    static OriginalParmVarDecl *Create(ASTContext &C, DeclContext *DC,
-                               SourceLocation L,IdentifierInfo *Id,
-                               QualType T, QualType OT,
-                               StorageClass S, Expr *DefArg);
+  static OriginalParmVarDecl *Create(ASTContext &C, DeclContext *DC,
+                                     SourceLocation L,IdentifierInfo *Id,
+                                     QualType T, QualType OT,
+                                     StorageClass S, Expr *DefArg);
+
+  void setOriginalType(QualType T) { OriginalType = T; }
 
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) { return D->getKind() == OriginalParmVar; }
@@ -603,6 +605,7 @@ public:
                               SourceLocation TSStartLoc = SourceLocation());  
   
   SourceLocation getTypeSpecStartLoc() const { return TypeSpecStartLoc; }
+  void setTypeSpecStartLoc(SourceLocation TS) { TypeSpecStartLoc = TS; }
 
   /// getBody - Retrieve the body (definition) of the function. The
   /// function body might be in any of the (re-)declarations of this
@@ -629,23 +632,24 @@ public:
   /// Whether this function is virtual, either by explicit marking, or by
   /// overriding a virtual function. Only valid on C++ member functions.
   bool isVirtual() { return IsVirtual; }
-  void setVirtual() { IsVirtual = true; }
+  void setVirtual(bool V = true) { IsVirtual = V; }
 
   /// Whether this virtual function is pure, i.e. makes the containing class
   /// abstract.
   bool isPure() const { return IsPure; }
-  void setPure() { IsPure = true; }
+  void setPure(bool P = true) { IsPure = P; }
 
   /// \brief Whether this function has a prototype, either because one
   /// was explicitly written or because it was "inherited" by merging
   /// a declaration without a prototype with a declaration that has a
   /// prototype.
   bool hasPrototype() const { return HasPrototype || InheritedPrototype; }
+  void setHasPrototype(bool P) { HasPrototype = P; }
 
   /// \brief Whether this function inherited its prototype from a
   /// previous declaration.
   bool inheritedPrototype() const { return InheritedPrototype; }
-  void setInheritedPrototype() { InheritedPrototype = true; }
+  void setInheritedPrototype(bool P = true) { InheritedPrototype = P; }
 
   /// \brief Whether this function has been deleted.
   ///
@@ -666,7 +670,7 @@ public:
   /// };
   /// @endcode
   bool isDeleted() const { return IsDeleted; }
-  void setDeleted() { IsDeleted = true; }
+  void setDeleted(bool D = true) { IsDeleted = D; }
 
   /// \brief Determines whether this is a function "main", which is
   /// the entry point into an executable program.
@@ -726,6 +730,7 @@ public:
   void setStorageClass(StorageClass SC) { SClass = SC; }
 
   bool isInline() const { return IsInline; }
+  void setInline(bool I) { IsInline = I; }
 
   /// isOverloadedOperator - Whether this function declaration
   /// represents an C++ overloaded operator, e.g., "operator+".
index 14c59712ece11caf65d589c99c41033a934a77c8..e1303056f88dff94a834cf66fd05e4dd1da11be7 100644 (file)
@@ -320,10 +320,16 @@ namespace clang {
       DECL_RECORD,
       /// \brief An EnumConstantDecl record.
       DECL_ENUM_CONSTANT,
+      /// \brief A FunctionDecl record.
+      DECL_FUNCTION,
       /// \brief A FieldDecl record.
       DECL_FIELD,
       /// \brief A VarDecl record.
       DECL_VAR,
+      /// \brief A ParmVarDecl record.
+      DECL_PARM_VAR,
+      /// \brief An OriginalParmVarDecl record.
+      DECL_ORIGINAL_PARM_VAR,
       /// \brief A record that stores the set of declarations that are
       /// lexically stored within a given DeclContext.
       ///
index 3490cb50708fb3a9197786e3e0b4931b4b5ea50f..6b67f2ef304b531dacbc5f3b531bb43817b2168a 100644 (file)
@@ -209,6 +209,10 @@ public:
 
   /// \brief Read a signed integral value
   llvm::APSInt ReadAPSInt(const RecordData &Record, unsigned &Idx);
+
+  /// \brief Retrieve the AST context that this PCH reader
+  /// supplements.
+  ASTContext &getContext() { return Context; }
 };
 
 } // end namespace clang
index adb4e5f6d7731f451cb209d1fabac56502251dcc..a5e29dcdcd416c8f76225ee2188b3b27fe282db7 100644 (file)
@@ -53,8 +53,11 @@ namespace {
     void VisitRecordDecl(RecordDecl *RD);
     void VisitValueDecl(ValueDecl *VD);
     void VisitEnumConstantDecl(EnumConstantDecl *ECD);
+    void VisitFunctionDecl(FunctionDecl *FD);
     void VisitFieldDecl(FieldDecl *FD);
     void VisitVarDecl(VarDecl *VD);
+    void VisitParmVarDecl(ParmVarDecl *PD);
+    void VisitOriginalParmVarDecl(OriginalParmVarDecl *PD);
 
     std::pair<uint64_t, uint64_t> VisitDeclContext(DeclContext *DC);
   };
@@ -125,6 +128,27 @@ void PCHDeclReader::VisitEnumConstantDecl(EnumConstantDecl *ECD) {
   ECD->setInitVal(Reader.ReadAPSInt(Record, Idx));
 }
 
+void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
+  VisitValueDecl(FD);
+  // FIXME: function body
+  FD->setPreviousDeclaration(
+                   cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++])));
+  FD->setStorageClass((FunctionDecl::StorageClass)Record[Idx++]);
+  FD->setInline(Record[Idx++]);
+  FD->setVirtual(Record[Idx++]);
+  FD->setPure(Record[Idx++]);
+  FD->setInheritedPrototype(Record[Idx++]);
+  FD->setHasPrototype(Record[Idx++]);
+  FD->setDeleted(Record[Idx++]);
+  FD->setTypeSpecStartLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  unsigned NumParams = Record[Idx++];
+  llvm::SmallVector<ParmVarDecl *, 16> Params;
+  Params.reserve(NumParams);
+  for (unsigned I = 0; I != NumParams; ++I)
+    Params.push_back(cast<ParmVarDecl>(Reader.GetDecl(Record[Idx++])));
+  FD->setParams(Reader.getContext(), &Params[0], NumParams);
+}
+
 void PCHDeclReader::VisitFieldDecl(FieldDecl *FD) {
   VisitValueDecl(FD);
   FD->setMutable(Record[Idx++]);
@@ -142,6 +166,17 @@ void PCHDeclReader::VisitVarDecl(VarDecl *VD) {
   VD->setTypeSpecStartLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
 }
 
+void PCHDeclReader::VisitParmVarDecl(ParmVarDecl *PD) {
+  VisitVarDecl(PD);
+  PD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record[Idx++]);
+  // FIXME: default argument
+}
+
+void PCHDeclReader::VisitOriginalParmVarDecl(OriginalParmVarDecl *PD) {
+  VisitParmVarDecl(PD);
+  PD->setOriginalType(Reader.GetType(Record[Idx++]));
+}
+
 std::pair<uint64_t, uint64_t> 
 PCHDeclReader::VisitDeclContext(DeclContext *DC) {
   uint64_t LexicalOffset = Record[Idx++];
@@ -1021,6 +1056,16 @@ Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) {
     D = ECD;
     break;
   }
+  
+  case pch::DECL_FUNCTION: {
+    FunctionDecl *Function = FunctionDecl::Create(Context, 0, SourceLocation(),
+                                                  DeclarationName(), 
+                                                  QualType());
+    LoadedDecl(Index, Function);
+    Reader.VisitFunctionDecl(Function);
+    D = Function;
+    break;
+  }
 
   case pch::DECL_FIELD: {
     FieldDecl *Field = FieldDecl::Create(Context, 0, SourceLocation(), 0,
@@ -1040,6 +1085,26 @@ Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) {
     break;
   }
 
+  case pch::DECL_PARM_VAR: {
+    ParmVarDecl *Parm = ParmVarDecl::Create(Context, 0, SourceLocation(), 0,
+                                            QualType(), VarDecl::None, 0);
+    LoadedDecl(Index, Parm);
+    Reader.VisitParmVarDecl(Parm);
+    D = Parm;
+    break;
+  }
+
+  case pch::DECL_ORIGINAL_PARM_VAR: {
+    OriginalParmVarDecl *Parm 
+      = OriginalParmVarDecl::Create(Context, 0, SourceLocation(), 0,
+                                    QualType(), QualType(), VarDecl::None, 
+                                    0);
+    LoadedDecl(Index, Parm);
+    Reader.VisitOriginalParmVarDecl(Parm);
+    D = Parm;
+    break;
+  }
+
   default:
     assert(false && "Cannot de-serialize this kind of declaration");
     break;
index 6758a506998d4747bc9aacf900c99cf37b0e84f1..8384177621895f459957db7e82f7f5e385ede248 100644 (file)
@@ -257,8 +257,11 @@ namespace {
     void VisitRecordDecl(RecordDecl *D);
     void VisitValueDecl(ValueDecl *D);
     void VisitEnumConstantDecl(EnumConstantDecl *D);
+    void VisitFunctionDecl(FunctionDecl *D);
     void VisitFieldDecl(FieldDecl *D);
     void VisitVarDecl(VarDecl *D);
+    void VisitParmVarDecl(ParmVarDecl *D);
+    void VisitOriginalParmVarDecl(OriginalParmVarDecl *D);
     void VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset, 
                           uint64_t VisibleOffset);
   };
@@ -327,6 +330,25 @@ void PCHDeclWriter::VisitEnumConstantDecl(EnumConstantDecl *D) {
   Code = pch::DECL_ENUM_CONSTANT;
 }
 
+void PCHDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
+  VisitValueDecl(D);
+  // FIXME: function body
+  Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
+  Record.push_back(D->getStorageClass()); // FIXME: stable encoding
+  Record.push_back(D->isInline());
+  Record.push_back(D->isVirtual());
+  Record.push_back(D->isPure());
+  Record.push_back(D->inheritedPrototype());
+  Record.push_back(D->hasPrototype() && !D->inheritedPrototype());
+  Record.push_back(D->isDeleted());
+  Writer.AddSourceLocation(D->getTypeSpecStartLoc(), Record);
+  Record.push_back(D->param_size());
+  for (FunctionDecl::param_iterator P = D->param_begin(), PEnd = D->param_end();
+       P != PEnd; ++P)
+    Writer.AddDeclRef(*P, Record);
+  Code = pch::DECL_FUNCTION;
+}
+
 void PCHDeclWriter::VisitFieldDecl(FieldDecl *D) {
   VisitValueDecl(D);
   Record.push_back(D->isMutable());
@@ -336,7 +358,7 @@ void PCHDeclWriter::VisitFieldDecl(FieldDecl *D) {
 
 void PCHDeclWriter::VisitVarDecl(VarDecl *D) {
   VisitValueDecl(D);
-  Record.push_back(D->getStorageClass());
+  Record.push_back(D->getStorageClass()); // FIXME: stable encoding
   Record.push_back(D->isThreadSpecified());
   Record.push_back(D->hasCXXDirectInitializer());
   Record.push_back(D->isDeclaredInCondition());
@@ -346,6 +368,21 @@ void PCHDeclWriter::VisitVarDecl(VarDecl *D) {
   Code = pch::DECL_VAR;
 }
 
+void PCHDeclWriter::VisitParmVarDecl(ParmVarDecl *D) {
+  VisitVarDecl(D);
+  Record.push_back(D->getObjCDeclQualifier()); // FIXME: stable encoding
+  // FIXME: emit default argument
+  // FIXME: why isn't the "default argument" just stored as the initializer
+  // in VarDecl?
+  Code = pch::DECL_PARM_VAR;
+}
+
+void PCHDeclWriter::VisitOriginalParmVarDecl(OriginalParmVarDecl *D) {
+  VisitParmVarDecl(D);
+  Writer.AddTypeRef(D->getOriginalType(), Record);
+  Code = pch::DECL_ORIGINAL_PARM_VAR;
+}
+
 /// \brief Emit the DeclContext part of a declaration context decl.
 ///
 /// \param LexicalOffset the offset at which the DECL_CONTEXT_LEXICAL
diff --git a/test/PCH/functions.c b/test/PCH/functions.c
new file mode 100644 (file)
index 0000000..9042796
--- /dev/null
@@ -0,0 +1,20 @@
+// Test this without pch.
+// RUN: clang-cc -include %S/functions.h -fsyntax-only -verify %s
+
+// Test with pch.
+// RUN: clang-cc -emit-pch -o %t %S/functions.h &&
+// RUN: clang-cc -include-pch %t -fsyntax-only -verify %s 
+
+int f0(int x0, int y0, ...) { return x0 + y0; }
+
+float *test_f1(int val, double x, double y) {
+  if (val > 5)
+    return f1(x, y);
+  else
+    return f1(x); // expected-error{{too few arguments to function call}}
+}
+
+void test_g0(int *x, float * y) {
+  g0(y); // expected-warning{{incompatible pointer types passing 'float *', expected 'int *'}}
+  g0(x); 
+}
diff --git a/test/PCH/functions.h b/test/PCH/functions.h
new file mode 100644 (file)
index 0000000..bc28ad7
--- /dev/null
@@ -0,0 +1,6 @@
+/* For use with the functions.c test */
+
+int f0(int x, int y, ...);
+float *f1(float x, float y);
+
+void g0(int *);