зеркало из https://github.com/microsoft/clang-1.git
PCH support for functions and their parameters.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68997 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
0f59312e7b
Коммит
3a2f7e4251
|
@ -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+".
|
||||
|
|
|
@ -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.
|
||||
///
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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 *);
|
Загрузка…
Ссылка в новой задаче