diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-04-13 22:18:37 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-04-13 22:18:37 +0000 |
commit | 3a2f7e42514ddbec983c61826ce85d3071e23e8e (patch) | |
tree | aed92dce2f9f61e77479495cb419c57e7dc956cf | |
parent | 0f59312e7b625fa5821a63db65377d4b3b667e99 (diff) |
PCH support for functions and their parameters.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68997 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/AST/Decl.h | 21 | ||||
-rw-r--r-- | include/clang/Frontend/PCHBitCodes.h | 6 | ||||
-rw-r--r-- | include/clang/Frontend/PCHReader.h | 4 | ||||
-rw-r--r-- | lib/Frontend/PCHReader.cpp | 65 | ||||
-rw-r--r-- | lib/Frontend/PCHWriter.cpp | 39 | ||||
-rw-r--r-- | test/PCH/functions.c | 20 | ||||
-rw-r--r-- | test/PCH/functions.h | 6 |
7 files changed, 152 insertions, 9 deletions
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 03ef88a0ec..dffc0ad6e4 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -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+". diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h index 14c59712ec..e1303056f8 100644 --- a/include/clang/Frontend/PCHBitCodes.h +++ b/include/clang/Frontend/PCHBitCodes.h @@ -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. /// diff --git a/include/clang/Frontend/PCHReader.h b/include/clang/Frontend/PCHReader.h index 3490cb5070..6b67f2ef30 100644 --- a/include/clang/Frontend/PCHReader.h +++ b/include/clang/Frontend/PCHReader.h @@ -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 diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index adb4e5f6d7..a5e29dcdcd 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -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; diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 6758a50699..8384177621 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -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 index 0000000000..9042796924 --- /dev/null +++ b/test/PCH/functions.c @@ -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 index 0000000000..bc28ad7321 --- /dev/null +++ b/test/PCH/functions.h @@ -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 *); |