forked from OSchip/llvm-project
PCH support for a few very, very simple kinds of expressions. Hook up
expression (de-)serialization for VLAs, variable initializers, enum constant initializers, and bitfield widths. llvm-svn: 69075
This commit is contained in:
parent
a723ba97db
commit
feb84b0074
|
|
@ -807,6 +807,8 @@ public:
|
||||||
bool isAnonymousStructOrUnion() const;
|
bool isAnonymousStructOrUnion() const;
|
||||||
|
|
||||||
Expr *getBitWidth() const { return BitWidth; }
|
Expr *getBitWidth() const { return BitWidth; }
|
||||||
|
void setBitWidth(Expr *BW) { BitWidth = BW; }
|
||||||
|
|
||||||
// Implement isa/cast/dyncast/etc.
|
// Implement isa/cast/dyncast/etc.
|
||||||
static bool classof(const Decl *D) {
|
static bool classof(const Decl *D) {
|
||||||
return D->getKind() >= FieldFirst && D->getKind() <= FieldLast;
|
return D->getKind() >= FieldFirst && D->getKind() <= FieldLast;
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,9 @@ protected:
|
||||||
setType(T);
|
setType(T);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Construct an empty expression.
|
||||||
|
explicit Expr(StmtClass SC, EmptyShell) : Stmt(SC) { }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QualType getType() const { return TR; }
|
QualType getType() const { return TR; }
|
||||||
void setType(QualType t) {
|
void setType(QualType t) {
|
||||||
|
|
@ -88,6 +91,9 @@ public:
|
||||||
/// @endcode
|
/// @endcode
|
||||||
bool isValueDependent() const { return ValueDependent; }
|
bool isValueDependent() const { return ValueDependent; }
|
||||||
|
|
||||||
|
/// \brief Set whether this expression is value-dependent or not.
|
||||||
|
void setValueDependent(bool VD) { ValueDependent = VD; }
|
||||||
|
|
||||||
/// isTypeDependent - Determines whether this expression is
|
/// isTypeDependent - Determines whether this expression is
|
||||||
/// type-dependent (C++ [temp.dep.expr]), which means that its type
|
/// type-dependent (C++ [temp.dep.expr]), which means that its type
|
||||||
/// could change from one template instantiation to the next. For
|
/// could change from one template instantiation to the next. For
|
||||||
|
|
@ -101,6 +107,9 @@ public:
|
||||||
/// @endcode
|
/// @endcode
|
||||||
bool isTypeDependent() const { return TypeDependent; }
|
bool isTypeDependent() const { return TypeDependent; }
|
||||||
|
|
||||||
|
/// \brief Set whether this expression is type-dependent or not.
|
||||||
|
void setTypeDependent(bool TD) { TypeDependent = TD; }
|
||||||
|
|
||||||
/// SourceLocation tokens are not useful in isolation - they are low level
|
/// SourceLocation tokens are not useful in isolation - they are low level
|
||||||
/// value objects created/interpreted by SourceManager. We assume AST
|
/// value objects created/interpreted by SourceManager. We assume AST
|
||||||
/// clients will have a pointer to the respective SourceManager.
|
/// clients will have a pointer to the respective SourceManager.
|
||||||
|
|
@ -315,11 +324,16 @@ public:
|
||||||
DeclRefExpr(NamedDecl *d, QualType t, SourceLocation l, bool TD, bool VD) :
|
DeclRefExpr(NamedDecl *d, QualType t, SourceLocation l, bool TD, bool VD) :
|
||||||
Expr(DeclRefExprClass, t, TD, VD), D(d), Loc(l) {}
|
Expr(DeclRefExprClass, t, TD, VD), D(d), Loc(l) {}
|
||||||
|
|
||||||
|
/// \brief Construct an empty declaration reference expression.
|
||||||
|
explicit DeclRefExpr(EmptyShell Empty)
|
||||||
|
: Expr(DeclRefExprClass, Empty) { }
|
||||||
|
|
||||||
NamedDecl *getDecl() { return D; }
|
NamedDecl *getDecl() { return D; }
|
||||||
const NamedDecl *getDecl() const { return D; }
|
const NamedDecl *getDecl() const { return D; }
|
||||||
void setDecl(NamedDecl *NewD) { D = NewD; }
|
void setDecl(NamedDecl *NewD) { D = NewD; }
|
||||||
|
|
||||||
SourceLocation getLocation() const { return Loc; }
|
SourceLocation getLocation() const { return Loc; }
|
||||||
|
void setLocation(SourceLocation L) { Loc = L; }
|
||||||
virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
|
virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
|
||||||
|
|
||||||
static bool classof(const Stmt *T) {
|
static bool classof(const Stmt *T) {
|
||||||
|
|
@ -381,6 +395,10 @@ public:
|
||||||
assert(type->isIntegerType() && "Illegal type in IntegerLiteral");
|
assert(type->isIntegerType() && "Illegal type in IntegerLiteral");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Construct an empty integer literal.
|
||||||
|
explicit IntegerLiteral(EmptyShell Empty)
|
||||||
|
: Expr(IntegerLiteralClass, Empty) { }
|
||||||
|
|
||||||
IntegerLiteral* Clone(ASTContext &C) const;
|
IntegerLiteral* Clone(ASTContext &C) const;
|
||||||
|
|
||||||
const llvm::APInt &getValue() const { return Value; }
|
const llvm::APInt &getValue() const { return Value; }
|
||||||
|
|
@ -389,6 +407,9 @@ public:
|
||||||
/// \brief Retrieve the location of the literal.
|
/// \brief Retrieve the location of the literal.
|
||||||
SourceLocation getLocation() const { return Loc; }
|
SourceLocation getLocation() const { return Loc; }
|
||||||
|
|
||||||
|
void setValue(const llvm::APInt &Val) { Value = Val; }
|
||||||
|
void setLocation(SourceLocation Location) { Loc = Location; }
|
||||||
|
|
||||||
static bool classof(const Stmt *T) {
|
static bool classof(const Stmt *T) {
|
||||||
return T->getStmtClass() == IntegerLiteralClass;
|
return T->getStmtClass() == IntegerLiteralClass;
|
||||||
}
|
}
|
||||||
|
|
@ -411,6 +432,10 @@ public:
|
||||||
CharacterLiteral(unsigned value, bool iswide, QualType type, SourceLocation l)
|
CharacterLiteral(unsigned value, bool iswide, QualType type, SourceLocation l)
|
||||||
: Expr(CharacterLiteralClass, type), Value(value), Loc(l), IsWide(iswide) {
|
: Expr(CharacterLiteralClass, type), Value(value), Loc(l), IsWide(iswide) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Construct an empty character literal.
|
||||||
|
CharacterLiteral(EmptyShell Empty) : Expr(CharacterLiteralClass, Empty) { }
|
||||||
|
|
||||||
SourceLocation getLoc() const { return Loc; }
|
SourceLocation getLoc() const { return Loc; }
|
||||||
bool isWide() const { return IsWide; }
|
bool isWide() const { return IsWide; }
|
||||||
|
|
||||||
|
|
@ -418,6 +443,10 @@ public:
|
||||||
|
|
||||||
unsigned getValue() const { return Value; }
|
unsigned getValue() const { return Value; }
|
||||||
|
|
||||||
|
void setLocation(SourceLocation Location) { Loc = Location; }
|
||||||
|
void setWide(bool W) { IsWide = W; }
|
||||||
|
void setValue(unsigned Val) { Value = Val; }
|
||||||
|
|
||||||
static bool classof(const Stmt *T) {
|
static bool classof(const Stmt *T) {
|
||||||
return T->getStmtClass() == CharacterLiteralClass;
|
return T->getStmtClass() == CharacterLiteralClass;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -210,7 +210,12 @@ public:
|
||||||
const_child_iterator child_end() const {
|
const_child_iterator child_end() const {
|
||||||
return const_child_iterator(const_cast<Stmt*>(this)->child_end());
|
return const_child_iterator(const_cast<Stmt*>(this)->child_end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief A placeholder type used to construct an empty shell of a
|
||||||
|
/// type, that will be filled in later (e.g., by some
|
||||||
|
/// de-serialization).
|
||||||
|
struct EmptyShell { };
|
||||||
|
|
||||||
void Emit(llvm::Serializer& S) const;
|
void Emit(llvm::Serializer& S) const;
|
||||||
static Stmt* Create(llvm::Deserializer& D, ASTContext& C);
|
static Stmt* Create(llvm::Deserializer& D, ASTContext& C);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -359,6 +359,24 @@ namespace clang {
|
||||||
/// into a DeclContext via DeclContext::lookup.
|
/// into a DeclContext via DeclContext::lookup.
|
||||||
DECL_CONTEXT_VISIBLE
|
DECL_CONTEXT_VISIBLE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// \brief Record codes for each kind of statement or expression.
|
||||||
|
///
|
||||||
|
/// These constants describe the records that describe statements
|
||||||
|
/// or expressions. These records can occur within either the type
|
||||||
|
/// or declaration blocks, so they begin with record values of
|
||||||
|
/// 100. Each constant describes a record for a specific
|
||||||
|
/// statement or expression class in the AST.
|
||||||
|
enum StmtCode {
|
||||||
|
/// \brief A NULL expression.
|
||||||
|
EXPR_NULL = 100,
|
||||||
|
/// \brief A DeclRefExpr record.
|
||||||
|
EXPR_DECL_REF,
|
||||||
|
/// \brief An IntegerLiteral record.
|
||||||
|
EXPR_INTEGER_LITERAL,
|
||||||
|
/// \brief A CharacterLiteral record.
|
||||||
|
EXPR_CHARACTER_LITERAL
|
||||||
|
};
|
||||||
/// @}
|
/// @}
|
||||||
}
|
}
|
||||||
} // end namespace clang
|
} // end namespace clang
|
||||||
|
|
|
||||||
|
|
@ -221,6 +221,9 @@ public:
|
||||||
/// \brief Read a signed integral value
|
/// \brief Read a signed integral value
|
||||||
llvm::APSInt ReadAPSInt(const RecordData &Record, unsigned &Idx);
|
llvm::APSInt ReadAPSInt(const RecordData &Record, unsigned &Idx);
|
||||||
|
|
||||||
|
/// \brief Reads an expression from the current stream position.
|
||||||
|
Expr *ReadExpr();
|
||||||
|
|
||||||
/// \brief Retrieve the AST context that this PCH reader
|
/// \brief Retrieve the AST context that this PCH reader
|
||||||
/// supplements.
|
/// supplements.
|
||||||
ASTContext &getContext() { return Context; }
|
ASTContext &getContext() { return Context; }
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
#include "llvm/ADT/SmallVector.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
class APInt;
|
class APInt;
|
||||||
|
|
@ -43,6 +42,10 @@ class TargetInfo;
|
||||||
/// data structures. This bitstream can be de-serialized via an
|
/// data structures. This bitstream can be de-serialized via an
|
||||||
/// instance of the PCHReader class.
|
/// instance of the PCHReader class.
|
||||||
class PCHWriter {
|
class PCHWriter {
|
||||||
|
public:
|
||||||
|
typedef llvm::SmallVector<uint64_t, 64> RecordData;
|
||||||
|
|
||||||
|
private:
|
||||||
/// \brief The bitstream writer used to emit this precompiled header.
|
/// \brief The bitstream writer used to emit this precompiled header.
|
||||||
llvm::BitstreamWriter &S;
|
llvm::BitstreamWriter &S;
|
||||||
|
|
||||||
|
|
@ -100,6 +103,13 @@ class PCHWriter {
|
||||||
/// record.
|
/// record.
|
||||||
llvm::SmallVector<uint64_t, 16> ExternalDefinitions;
|
llvm::SmallVector<uint64_t, 16> ExternalDefinitions;
|
||||||
|
|
||||||
|
/// \brief Expressions that we've encountered while serializing a
|
||||||
|
/// declaration or type.
|
||||||
|
///
|
||||||
|
/// The expressions in this queue will be emitted following the
|
||||||
|
/// declaration or type.
|
||||||
|
std::queue<Expr *> ExprsToEmit;
|
||||||
|
|
||||||
void WriteTargetTriple(const TargetInfo &Target);
|
void WriteTargetTriple(const TargetInfo &Target);
|
||||||
void WriteLanguageOptions(const LangOptions &LangOpts);
|
void WriteLanguageOptions(const LangOptions &LangOpts);
|
||||||
void WriteSourceManagerBlock(SourceManager &SourceMgr);
|
void WriteSourceManagerBlock(SourceManager &SourceMgr);
|
||||||
|
|
@ -112,8 +122,6 @@ class PCHWriter {
|
||||||
void WriteIdentifierTable();
|
void WriteIdentifierTable();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef llvm::SmallVector<uint64_t, 64> RecordData;
|
|
||||||
|
|
||||||
/// \brief Create a new precompiled header writer that outputs to
|
/// \brief Create a new precompiled header writer that outputs to
|
||||||
/// the given bitstream.
|
/// the given bitstream.
|
||||||
PCHWriter(llvm::BitstreamWriter &S);
|
PCHWriter(llvm::BitstreamWriter &S);
|
||||||
|
|
@ -141,6 +149,14 @@ public:
|
||||||
|
|
||||||
/// \brief Emit a declaration name.
|
/// \brief Emit a declaration name.
|
||||||
void AddDeclarationName(DeclarationName Name, RecordData &Record);
|
void AddDeclarationName(DeclarationName Name, RecordData &Record);
|
||||||
|
|
||||||
|
/// \brief Add the given expression to the queue of expressions to
|
||||||
|
/// emit.
|
||||||
|
void AddExpr(Expr *E) { ExprsToEmit.push(E); }
|
||||||
|
|
||||||
|
/// \brief Flush all of the expressions that have been added to the
|
||||||
|
/// queue via AddExpr().
|
||||||
|
void FlushExprs();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace clang
|
} // end namespace clang
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@
|
||||||
#include "clang/AST/ASTContext.h"
|
#include "clang/AST/ASTContext.h"
|
||||||
#include "clang/AST/Decl.h"
|
#include "clang/AST/Decl.h"
|
||||||
#include "clang/AST/DeclGroup.h"
|
#include "clang/AST/DeclGroup.h"
|
||||||
|
#include "clang/AST/Expr.h"
|
||||||
|
#include "clang/AST/StmtVisitor.h"
|
||||||
#include "clang/AST/Type.h"
|
#include "clang/AST/Type.h"
|
||||||
#include "clang/Lex/MacroInfo.h"
|
#include "clang/Lex/MacroInfo.h"
|
||||||
#include "clang/Lex/Preprocessor.h"
|
#include "clang/Lex/Preprocessor.h"
|
||||||
|
|
@ -127,7 +129,8 @@ void PCHDeclReader::VisitValueDecl(ValueDecl *VD) {
|
||||||
|
|
||||||
void PCHDeclReader::VisitEnumConstantDecl(EnumConstantDecl *ECD) {
|
void PCHDeclReader::VisitEnumConstantDecl(EnumConstantDecl *ECD) {
|
||||||
VisitValueDecl(ECD);
|
VisitValueDecl(ECD);
|
||||||
// FIXME: read the initialization expression
|
if (Record[Idx++])
|
||||||
|
ECD->setInitExpr(Reader.ReadExpr());
|
||||||
ECD->setInitVal(Reader.ReadAPSInt(Record, Idx));
|
ECD->setInitVal(Reader.ReadAPSInt(Record, Idx));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -155,7 +158,8 @@ void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
|
||||||
void PCHDeclReader::VisitFieldDecl(FieldDecl *FD) {
|
void PCHDeclReader::VisitFieldDecl(FieldDecl *FD) {
|
||||||
VisitValueDecl(FD);
|
VisitValueDecl(FD);
|
||||||
FD->setMutable(Record[Idx++]);
|
FD->setMutable(Record[Idx++]);
|
||||||
// FIXME: Read the bit width.
|
if (Record[Idx++])
|
||||||
|
FD->setBitWidth(Reader.ReadExpr());
|
||||||
}
|
}
|
||||||
|
|
||||||
void PCHDeclReader::VisitVarDecl(VarDecl *VD) {
|
void PCHDeclReader::VisitVarDecl(VarDecl *VD) {
|
||||||
|
|
@ -167,6 +171,8 @@ void PCHDeclReader::VisitVarDecl(VarDecl *VD) {
|
||||||
VD->setPreviousDeclaration(
|
VD->setPreviousDeclaration(
|
||||||
cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++])));
|
cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++])));
|
||||||
VD->setTypeSpecStartLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
VD->setTypeSpecStartLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||||
|
if (Record[Idx++])
|
||||||
|
VD->setInit(Reader.ReadExpr());
|
||||||
}
|
}
|
||||||
|
|
||||||
void PCHDeclReader::VisitParmVarDecl(ParmVarDecl *PD) {
|
void PCHDeclReader::VisitParmVarDecl(ParmVarDecl *PD) {
|
||||||
|
|
@ -204,6 +210,53 @@ PCHDeclReader::VisitDeclContext(DeclContext *DC) {
|
||||||
return std::make_pair(LexicalOffset, VisibleOffset);
|
return std::make_pair(LexicalOffset, VisibleOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Statement/expression deserialization
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
namespace {
|
||||||
|
class VISIBILITY_HIDDEN PCHStmtReader
|
||||||
|
: public StmtVisitor<PCHStmtReader, void> {
|
||||||
|
PCHReader &Reader;
|
||||||
|
const PCHReader::RecordData &Record;
|
||||||
|
unsigned &Idx;
|
||||||
|
|
||||||
|
public:
|
||||||
|
PCHStmtReader(PCHReader &Reader, const PCHReader::RecordData &Record,
|
||||||
|
unsigned &Idx)
|
||||||
|
: Reader(Reader), Record(Record), Idx(Idx) { }
|
||||||
|
|
||||||
|
void VisitExpr(Expr *E);
|
||||||
|
void VisitDeclRefExpr(DeclRefExpr *E);
|
||||||
|
void VisitIntegerLiteral(IntegerLiteral *E);
|
||||||
|
void VisitCharacterLiteral(CharacterLiteral *E);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void PCHStmtReader::VisitExpr(Expr *E) {
|
||||||
|
E->setType(Reader.GetType(Record[Idx++]));
|
||||||
|
E->setTypeDependent(Record[Idx++]);
|
||||||
|
E->setValueDependent(Record[Idx++]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PCHStmtReader::VisitDeclRefExpr(DeclRefExpr *E) {
|
||||||
|
VisitExpr(E);
|
||||||
|
E->setDecl(cast<NamedDecl>(Reader.GetDecl(Record[Idx++])));
|
||||||
|
E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||||
|
}
|
||||||
|
|
||||||
|
void PCHStmtReader::VisitIntegerLiteral(IntegerLiteral *E) {
|
||||||
|
VisitExpr(E);
|
||||||
|
E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||||
|
E->setValue(Reader.ReadAPInt(Record, Idx));
|
||||||
|
}
|
||||||
|
|
||||||
|
void PCHStmtReader::VisitCharacterLiteral(CharacterLiteral *E) {
|
||||||
|
VisitExpr(E);
|
||||||
|
E->setValue(Record[Idx++]);
|
||||||
|
E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||||
|
E->setWide(Record[Idx++]);
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: use the diagnostics machinery
|
// FIXME: use the diagnostics machinery
|
||||||
static bool Error(const char *Str) {
|
static bool Error(const char *Str) {
|
||||||
std::fprintf(stderr, "%s\n", Str);
|
std::fprintf(stderr, "%s\n", Str);
|
||||||
|
|
@ -755,6 +808,26 @@ PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
|
||||||
return Success;
|
return Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
/// \brief Helper class that saves the current stream position and
|
||||||
|
/// then restores it when destroyed.
|
||||||
|
struct VISIBILITY_HIDDEN SavedStreamPosition {
|
||||||
|
explicit SavedStreamPosition(llvm::BitstreamReader &Stream)
|
||||||
|
: Stream(Stream), Offset(Stream.GetCurrentBitNo()),
|
||||||
|
EndOfStream(Stream.AtEndOfStream()){ }
|
||||||
|
|
||||||
|
~SavedStreamPosition() {
|
||||||
|
if (!EndOfStream)
|
||||||
|
Stream.JumpToBit(Offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
llvm::BitstreamReader &Stream;
|
||||||
|
uint64_t Offset;
|
||||||
|
bool EndOfStream;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief Parse the record that corresponds to a LangOptions data
|
/// \brief Parse the record that corresponds to a LangOptions data
|
||||||
/// structure.
|
/// structure.
|
||||||
///
|
///
|
||||||
|
|
@ -850,6 +923,10 @@ bool PCHReader::ParseLanguageOptions(
|
||||||
/// at the given offset in the bitstream. It is a helper routine for
|
/// at the given offset in the bitstream. It is a helper routine for
|
||||||
/// GetType, which deals with reading type IDs.
|
/// GetType, which deals with reading type IDs.
|
||||||
QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
|
QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
|
||||||
|
// Keep track of where we are in the stream, then jump back there
|
||||||
|
// after reading this type.
|
||||||
|
SavedStreamPosition SavedPosition(Stream);
|
||||||
|
|
||||||
Stream.JumpToBit(Offset);
|
Stream.JumpToBit(Offset);
|
||||||
RecordData Record;
|
RecordData Record;
|
||||||
unsigned Code = Stream.ReadCode();
|
unsigned Code = Stream.ReadCode();
|
||||||
|
|
@ -918,9 +995,11 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
|
||||||
}
|
}
|
||||||
|
|
||||||
case pch::TYPE_VARIABLE_ARRAY: {
|
case pch::TYPE_VARIABLE_ARRAY: {
|
||||||
// FIXME: implement this
|
QualType ElementType = GetType(Record[0]);
|
||||||
assert(false && "Unable to de-serialize variable-length array type");
|
ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
|
||||||
return QualType();
|
unsigned IndexTypeQuals = Record[2];
|
||||||
|
return Context.getVariableArrayType(ElementType, ReadExpr(),
|
||||||
|
ASM, IndexTypeQuals);
|
||||||
}
|
}
|
||||||
|
|
||||||
case pch::TYPE_VECTOR: {
|
case pch::TYPE_VECTOR: {
|
||||||
|
|
@ -972,9 +1051,7 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
|
||||||
return Context.getTypeDeclType(cast<TypedefDecl>(GetDecl(Record[0])));
|
return Context.getTypeDeclType(cast<TypedefDecl>(GetDecl(Record[0])));
|
||||||
|
|
||||||
case pch::TYPE_TYPEOF_EXPR:
|
case pch::TYPE_TYPEOF_EXPR:
|
||||||
// FIXME: Deserialize TypeOfExprType
|
return Context.getTypeOfExprType(ReadExpr());
|
||||||
assert(false && "Cannot de-serialize typeof(expr) from a PCH file");
|
|
||||||
return QualType();
|
|
||||||
|
|
||||||
case pch::TYPE_TYPEOF: {
|
case pch::TYPE_TYPEOF: {
|
||||||
if (Record.size() != 1) {
|
if (Record.size() != 1) {
|
||||||
|
|
@ -1032,12 +1109,17 @@ inline void PCHReader::LoadedDecl(unsigned Index, Decl *D) {
|
||||||
|
|
||||||
/// \brief Read the declaration at the given offset from the PCH file.
|
/// \brief Read the declaration at the given offset from the PCH file.
|
||||||
Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) {
|
Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) {
|
||||||
|
// Keep track of where we are in the stream, then jump back there
|
||||||
|
// after reading this declaration.
|
||||||
|
SavedStreamPosition SavedPosition(Stream);
|
||||||
|
|
||||||
Decl *D = 0;
|
Decl *D = 0;
|
||||||
Stream.JumpToBit(Offset);
|
Stream.JumpToBit(Offset);
|
||||||
RecordData Record;
|
RecordData Record;
|
||||||
unsigned Code = Stream.ReadCode();
|
unsigned Code = Stream.ReadCode();
|
||||||
unsigned Idx = 0;
|
unsigned Idx = 0;
|
||||||
PCHDeclReader Reader(*this, Record, Idx);
|
PCHDeclReader Reader(*this, Record, Idx);
|
||||||
|
|
||||||
switch ((pch::DeclCode)Stream.ReadRecord(Code, Record)) {
|
switch ((pch::DeclCode)Stream.ReadRecord(Code, Record)) {
|
||||||
case pch::DECL_TRANSLATION_UNIT:
|
case pch::DECL_TRANSLATION_UNIT:
|
||||||
assert(Index == 0 && "Translation unit must be at index 0");
|
assert(Index == 0 && "Translation unit must be at index 0");
|
||||||
|
|
@ -1237,6 +1319,10 @@ bool PCHReader::ReadDeclsLexicallyInContext(DeclContext *DC,
|
||||||
uint64_t Offset = DeclContextOffsets[DC].first;
|
uint64_t Offset = DeclContextOffsets[DC].first;
|
||||||
assert(Offset && "DeclContext has no lexical decls in storage");
|
assert(Offset && "DeclContext has no lexical decls in storage");
|
||||||
|
|
||||||
|
// Keep track of where we are in the stream, then jump back there
|
||||||
|
// after reading this context.
|
||||||
|
SavedStreamPosition SavedPosition(Stream);
|
||||||
|
|
||||||
// Load the record containing all of the declarations lexically in
|
// Load the record containing all of the declarations lexically in
|
||||||
// this context.
|
// this context.
|
||||||
Stream.JumpToBit(Offset);
|
Stream.JumpToBit(Offset);
|
||||||
|
|
@ -1258,6 +1344,10 @@ bool PCHReader::ReadDeclsVisibleInContext(DeclContext *DC,
|
||||||
uint64_t Offset = DeclContextOffsets[DC].second;
|
uint64_t Offset = DeclContextOffsets[DC].second;
|
||||||
assert(Offset && "DeclContext has no visible decls in storage");
|
assert(Offset && "DeclContext has no visible decls in storage");
|
||||||
|
|
||||||
|
// Keep track of where we are in the stream, then jump back there
|
||||||
|
// after reading this context.
|
||||||
|
SavedStreamPosition SavedPosition(Stream);
|
||||||
|
|
||||||
// Load the record containing all of the declarations visible in
|
// Load the record containing all of the declarations visible in
|
||||||
// this context.
|
// this context.
|
||||||
Stream.JumpToBit(Offset);
|
Stream.JumpToBit(Offset);
|
||||||
|
|
@ -1394,6 +1484,44 @@ llvm::APSInt PCHReader::ReadAPSInt(const RecordData &Record, unsigned &Idx) {
|
||||||
return llvm::APSInt(ReadAPInt(Record, Idx), isUnsigned);
|
return llvm::APSInt(ReadAPInt(Record, Idx), isUnsigned);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Expr *PCHReader::ReadExpr() {
|
||||||
|
RecordData Record;
|
||||||
|
unsigned Code = Stream.ReadCode();
|
||||||
|
unsigned Idx = 0;
|
||||||
|
PCHStmtReader Reader(*this, Record, Idx);
|
||||||
|
Stmt::EmptyShell Empty;
|
||||||
|
|
||||||
|
Expr *E = 0;
|
||||||
|
switch ((pch::StmtCode)Stream.ReadRecord(Code, Record)) {
|
||||||
|
case pch::EXPR_NULL:
|
||||||
|
E = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case pch::EXPR_DECL_REF:
|
||||||
|
E = new (Context) DeclRefExpr(Empty);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case pch::EXPR_INTEGER_LITERAL:
|
||||||
|
E = new (Context) IntegerLiteral(Empty);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case pch::EXPR_CHARACTER_LITERAL:
|
||||||
|
E = new (Context) CharacterLiteral(Empty);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert(false && "Unhandled expression kind");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (E)
|
||||||
|
Reader.Visit(E);
|
||||||
|
|
||||||
|
assert(Idx == Record.size() && "Invalid deserialization of expression");
|
||||||
|
|
||||||
|
return E;
|
||||||
|
}
|
||||||
|
|
||||||
DiagnosticBuilder PCHReader::Diag(unsigned DiagID) {
|
DiagnosticBuilder PCHReader::Diag(unsigned DiagID) {
|
||||||
return Diag(SourceLocation(), DiagID);
|
return Diag(SourceLocation(), DiagID);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@
|
||||||
#include "clang/AST/Decl.h"
|
#include "clang/AST/Decl.h"
|
||||||
#include "clang/AST/DeclContextInternals.h"
|
#include "clang/AST/DeclContextInternals.h"
|
||||||
#include "clang/AST/DeclVisitor.h"
|
#include "clang/AST/DeclVisitor.h"
|
||||||
|
#include "clang/AST/Expr.h"
|
||||||
|
#include "clang/AST/StmtVisitor.h"
|
||||||
#include "clang/AST/Type.h"
|
#include "clang/AST/Type.h"
|
||||||
#include "clang/Lex/MacroInfo.h"
|
#include "clang/Lex/MacroInfo.h"
|
||||||
#include "clang/Lex/Preprocessor.h"
|
#include "clang/Lex/Preprocessor.h"
|
||||||
|
|
@ -122,8 +124,7 @@ void PCHTypeWriter::VisitIncompleteArrayType(const IncompleteArrayType *T) {
|
||||||
|
|
||||||
void PCHTypeWriter::VisitVariableArrayType(const VariableArrayType *T) {
|
void PCHTypeWriter::VisitVariableArrayType(const VariableArrayType *T) {
|
||||||
VisitArrayType(T);
|
VisitArrayType(T);
|
||||||
// FIXME: Serialize array size expression.
|
Writer.AddExpr(T->getSizeExpr());
|
||||||
assert(false && "Cannot serialize variable-length arrays");
|
|
||||||
Code = pch::TYPE_VARIABLE_ARRAY;
|
Code = pch::TYPE_VARIABLE_ARRAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -163,8 +164,7 @@ void PCHTypeWriter::VisitTypedefType(const TypedefType *T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void PCHTypeWriter::VisitTypeOfExprType(const TypeOfExprType *T) {
|
void PCHTypeWriter::VisitTypeOfExprType(const TypeOfExprType *T) {
|
||||||
// FIXME: serialize the typeof expression
|
Writer.AddExpr(T->getUnderlyingExpr());
|
||||||
assert(false && "Cannot serialize typeof(expr)");
|
|
||||||
Code = pch::TYPE_TYPEOF_EXPR;
|
Code = pch::TYPE_TYPEOF_EXPR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -327,7 +327,9 @@ void PCHDeclWriter::VisitValueDecl(ValueDecl *D) {
|
||||||
|
|
||||||
void PCHDeclWriter::VisitEnumConstantDecl(EnumConstantDecl *D) {
|
void PCHDeclWriter::VisitEnumConstantDecl(EnumConstantDecl *D) {
|
||||||
VisitValueDecl(D);
|
VisitValueDecl(D);
|
||||||
// FIXME: Writer.AddExprRef(D->getInitExpr());
|
Record.push_back(D->getInitExpr()? 1 : 0);
|
||||||
|
if (D->getInitExpr())
|
||||||
|
Writer.AddExpr(D->getInitExpr());
|
||||||
Writer.AddAPSInt(D->getInitVal(), Record);
|
Writer.AddAPSInt(D->getInitVal(), Record);
|
||||||
Code = pch::DECL_ENUM_CONSTANT;
|
Code = pch::DECL_ENUM_CONSTANT;
|
||||||
}
|
}
|
||||||
|
|
@ -354,7 +356,9 @@ void PCHDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
|
||||||
void PCHDeclWriter::VisitFieldDecl(FieldDecl *D) {
|
void PCHDeclWriter::VisitFieldDecl(FieldDecl *D) {
|
||||||
VisitValueDecl(D);
|
VisitValueDecl(D);
|
||||||
Record.push_back(D->isMutable());
|
Record.push_back(D->isMutable());
|
||||||
// FIXME: Writer.AddExprRef(D->getBitWidth());
|
Record.push_back(D->getBitWidth()? 1 : 0);
|
||||||
|
if (D->getBitWidth())
|
||||||
|
Writer.AddExpr(D->getBitWidth());
|
||||||
Code = pch::DECL_FIELD;
|
Code = pch::DECL_FIELD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -366,7 +370,9 @@ void PCHDeclWriter::VisitVarDecl(VarDecl *D) {
|
||||||
Record.push_back(D->isDeclaredInCondition());
|
Record.push_back(D->isDeclaredInCondition());
|
||||||
Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
|
Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
|
||||||
Writer.AddSourceLocation(D->getTypeSpecStartLoc(), Record);
|
Writer.AddSourceLocation(D->getTypeSpecStartLoc(), Record);
|
||||||
// FIXME: emit initializer
|
Record.push_back(D->getInit()? 1 : 0);
|
||||||
|
if (D->getInit())
|
||||||
|
Writer.AddExpr(D->getInit());
|
||||||
Code = pch::DECL_VAR;
|
Code = pch::DECL_VAR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -419,6 +425,57 @@ void PCHDeclWriter::VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
|
||||||
Record.push_back(VisibleOffset);
|
Record.push_back(VisibleOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Statement/expression serialization
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
namespace {
|
||||||
|
class VISIBILITY_HIDDEN PCHStmtWriter
|
||||||
|
: public StmtVisitor<PCHStmtWriter, void> {
|
||||||
|
|
||||||
|
PCHWriter &Writer;
|
||||||
|
PCHWriter::RecordData &Record;
|
||||||
|
|
||||||
|
public:
|
||||||
|
pch::StmtCode Code;
|
||||||
|
|
||||||
|
PCHStmtWriter(PCHWriter &Writer, PCHWriter::RecordData &Record)
|
||||||
|
: Writer(Writer), Record(Record) { }
|
||||||
|
|
||||||
|
void VisitExpr(Expr *E);
|
||||||
|
void VisitDeclRefExpr(DeclRefExpr *E);
|
||||||
|
void VisitIntegerLiteral(IntegerLiteral *E);
|
||||||
|
void VisitCharacterLiteral(CharacterLiteral *E);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void PCHStmtWriter::VisitExpr(Expr *E) {
|
||||||
|
Writer.AddTypeRef(E->getType(), Record);
|
||||||
|
Record.push_back(E->isTypeDependent());
|
||||||
|
Record.push_back(E->isValueDependent());
|
||||||
|
}
|
||||||
|
|
||||||
|
void PCHStmtWriter::VisitDeclRefExpr(DeclRefExpr *E) {
|
||||||
|
VisitExpr(E);
|
||||||
|
Writer.AddDeclRef(E->getDecl(), Record);
|
||||||
|
Writer.AddSourceLocation(E->getLocation(), Record);
|
||||||
|
Code = pch::EXPR_DECL_REF;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PCHStmtWriter::VisitIntegerLiteral(IntegerLiteral *E) {
|
||||||
|
VisitExpr(E);
|
||||||
|
Writer.AddSourceLocation(E->getLocation(), Record);
|
||||||
|
Writer.AddAPInt(E->getValue(), Record);
|
||||||
|
Code = pch::EXPR_INTEGER_LITERAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PCHStmtWriter::VisitCharacterLiteral(CharacterLiteral *E) {
|
||||||
|
VisitExpr(E);
|
||||||
|
Record.push_back(E->getValue());
|
||||||
|
Writer.AddSourceLocation(E->getLoc(), Record);
|
||||||
|
Record.push_back(E->isWide());
|
||||||
|
Code = pch::EXPR_CHARACTER_LITERAL;
|
||||||
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// PCHWriter Implementation
|
// PCHWriter Implementation
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
@ -513,8 +570,6 @@ static unsigned CreateSLocFileAbbrev(llvm::BitstreamWriter &S) {
|
||||||
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location
|
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location
|
||||||
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Characteristic
|
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Characteristic
|
||||||
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Line directives
|
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Line directives
|
||||||
// FIXME: Need an actual encoding for the line directives; maybe
|
|
||||||
// this should be an array?
|
|
||||||
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name
|
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name
|
||||||
return S.EmitAbbrev(Abbrev);
|
return S.EmitAbbrev(Abbrev);
|
||||||
}
|
}
|
||||||
|
|
@ -805,6 +860,9 @@ void PCHWriter::WriteType(const Type *T) {
|
||||||
|
|
||||||
// Emit the serialized record.
|
// Emit the serialized record.
|
||||||
S.EmitRecord(W.Code, Record);
|
S.EmitRecord(W.Code, Record);
|
||||||
|
|
||||||
|
// Flush any expressions that were written as part of this type.
|
||||||
|
FlushExprs();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Write a block containing all of the types.
|
/// \brief Write a block containing all of the types.
|
||||||
|
|
@ -937,6 +995,9 @@ void PCHWriter::WriteDeclsBlock(ASTContext &Context) {
|
||||||
assert(W.Code && "Unhandled declaration kind while generating PCH");
|
assert(W.Code && "Unhandled declaration kind while generating PCH");
|
||||||
S.EmitRecord(W.Code, Record);
|
S.EmitRecord(W.Code, Record);
|
||||||
|
|
||||||
|
// Flush any expressions that were written as part of this declaration.
|
||||||
|
FlushExprs();
|
||||||
|
|
||||||
// Note external declarations so that we can add them to a record
|
// Note external declarations so that we can add them to a record
|
||||||
// in the PCH file later.
|
// in the PCH file later.
|
||||||
if (isa<FileScopeAsmDecl>(D))
|
if (isa<FileScopeAsmDecl>(D))
|
||||||
|
|
@ -1160,3 +1221,26 @@ void PCHWriter::AddDeclarationName(DeclarationName Name, RecordData &Record) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Flush all of the expressions that have been added to the
|
||||||
|
/// queue via AddExpr().
|
||||||
|
void PCHWriter::FlushExprs() {
|
||||||
|
RecordData Record;
|
||||||
|
PCHStmtWriter Writer(*this, Record);
|
||||||
|
while (!ExprsToEmit.empty()) {
|
||||||
|
Expr *E = ExprsToEmit.front();
|
||||||
|
ExprsToEmit.pop();
|
||||||
|
|
||||||
|
Record.clear();
|
||||||
|
if (!E) {
|
||||||
|
S.EmitRecord(pch::EXPR_NULL, Record);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Writer.Code = pch::EXPR_NULL;
|
||||||
|
Writer.Visit(E);
|
||||||
|
assert(Writer.Code != pch::EXPR_NULL &&
|
||||||
|
"Unhandled expression writing PCH file");
|
||||||
|
S.EmitRecord(Writer.Code, Record);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,9 @@ enum Color {
|
||||||
|
|
||||||
enum Shape {
|
enum Shape {
|
||||||
Square,
|
Square,
|
||||||
Triangle,
|
Triangle = 17,
|
||||||
Rhombus,
|
Rhombus,
|
||||||
Circle
|
Circle
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Shape aRoundShape = Circle;
|
enum Shape aRoundShape;// FIXME: = Circle;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
// Test this without pch.
|
||||||
|
// RUN: clang-cc -fblocks -include %S/exprs.h -fsyntax-only -verify %s
|
||||||
|
|
||||||
|
// Test with pch.
|
||||||
|
// RUN: clang-cc -emit-pch -fblocks -o %t %S/exprs.h &&
|
||||||
|
// RUN: clang-cc -fblocks -include-pch %t -fsyntax-only -verify %s
|
||||||
|
|
||||||
|
int integer;
|
||||||
|
long long_integer;
|
||||||
|
|
||||||
|
// DeclRefExpr
|
||||||
|
int_decl_ref *int_ptr1 = &integer;
|
||||||
|
enum_decl_ref *enum_ptr1 = &integer;
|
||||||
|
// IntegerLiteralExpr
|
||||||
|
integer_literal *int_ptr2 = &integer;
|
||||||
|
long_literal *long_ptr1 = &long_integer;
|
||||||
|
|
||||||
|
// CharacterLiteralExpr
|
||||||
|
char_literal *int_ptr3 = &integer;
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
// Header for PCH test exprs.c
|
||||||
|
|
||||||
|
// DeclRefExpr
|
||||||
|
int i = 17;
|
||||||
|
enum Enum { Enumerator = 18 };
|
||||||
|
typedef typeof(i) int_decl_ref;
|
||||||
|
typedef typeof(Enumerator) enum_decl_ref;
|
||||||
|
|
||||||
|
// IntegerLiteralExpr
|
||||||
|
typedef typeof(17) integer_literal;
|
||||||
|
typedef typeof(17l) long_literal;
|
||||||
|
|
||||||
|
// CharacterLiteralExpr
|
||||||
|
typedef typeof('a') char_literal;
|
||||||
|
|
@ -3,8 +3,7 @@
|
||||||
// RUN: clang-cc -triple x86_64-apple-darwin9 -include-pch %t.pch -emit-llvm -o %t %s &&
|
// RUN: clang-cc -triple x86_64-apple-darwin9 -include-pch %t.pch -emit-llvm -o %t %s &&
|
||||||
|
|
||||||
// RUN: grep "@x = common global i32 0" %t | count 1 &&
|
// RUN: grep "@x = common global i32 0" %t | count 1 &&
|
||||||
// FIXME below: should be i32 17, but we don't serialize y's value yet
|
// RUN: grep "@y = global i32 17" %t | count 1 &&
|
||||||
// RUN: grep "@y = common global i32 0" %t | count 1 &&
|
|
||||||
// RUN: grep "@z" %t | count 0 &&
|
// RUN: grep "@z" %t | count 0 &&
|
||||||
|
|
||||||
// RUN: grep "@x2 = global i32 19" %t | count 1 &&
|
// RUN: grep "@x2 = global i32 19" %t | count 1 &&
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
int x;
|
int x;
|
||||||
int x2;
|
int x2;
|
||||||
|
|
||||||
// FIXME: check this, once we actually serialize it
|
// Definitions
|
||||||
int y = 17;
|
int y = 17;
|
||||||
|
|
||||||
// Should not show up
|
// Should not show up
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@ int get_very_fun() {
|
||||||
return fun2->very_fun;
|
return fun2->very_fun;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int *int_ptr_fail = &fun->is_ptr; // expected-error{{address of bit-field requested}}
|
||||||
|
|
||||||
/* FIXME: DeclContexts aren't yet able to find "struct Nested" nested
|
/* FIXME: DeclContexts aren't yet able to find "struct Nested" nested
|
||||||
within "struct S", so causing the following to fail. When not using
|
within "struct S", so causing the following to fail. When not using
|
||||||
PCH, this works because Sema puts the nested struct onto the
|
PCH, this works because Sema puts the nested struct onto the
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ struct Fun;
|
||||||
struct Fun *fun;
|
struct Fun *fun;
|
||||||
|
|
||||||
struct Fun {
|
struct Fun {
|
||||||
int is_ptr;
|
int is_ptr : 1;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
void *ptr;
|
void *ptr;
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,10 @@ proto *p2 = p1;
|
||||||
// TYPE_TYPEDEF
|
// TYPE_TYPEDEF
|
||||||
int_ptr_ptr ipp = &int_value_ptr;
|
int_ptr_ptr ipp = &int_value_ptr;
|
||||||
|
|
||||||
// FIXME: TYPE_TYPEOF_EXPR
|
// TYPE_TYPEOF_EXPR
|
||||||
|
typeof_17 *t17 = &int_value;
|
||||||
|
struct S { int x, y; };
|
||||||
|
typeof_17 t17_2 = (struct S){1, 2}; // expected-error{{incompatible type initializing}}
|
||||||
|
|
||||||
// TYPE_TYPEOF
|
// TYPE_TYPEOF
|
||||||
int_ptr_ptr2 ipp2 = &int_value_ptr;
|
int_ptr_ptr2 ipp2 = &int_value_ptr;
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,8 @@ typedef float proto(float, float, ...);
|
||||||
// TYPE_TYPEDEF
|
// TYPE_TYPEDEF
|
||||||
typedef int_ptr * int_ptr_ptr;
|
typedef int_ptr * int_ptr_ptr;
|
||||||
|
|
||||||
// FIXME: TYPE_TYPEOF_EXPR
|
// TYPE_TYPEOF_EXPR
|
||||||
|
typedef typeof(17) typeof_17;
|
||||||
|
|
||||||
// TYPE_TYPEOF
|
// TYPE_TYPEOF
|
||||||
typedef typeof(int_ptr *) int_ptr_ptr2;
|
typedef typeof(int_ptr *) int_ptr_ptr2;
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,8 @@ int *ip2 = &x;
|
||||||
float *fp = &ip; // expected-warning{{incompatible pointer types}}
|
float *fp = &ip; // expected-warning{{incompatible pointer types}}
|
||||||
// FIXME:variables.h expected-note{{previous}}
|
// FIXME:variables.h expected-note{{previous}}
|
||||||
double z; // expected-error{{redefinition}}
|
double z; // expected-error{{redefinition}}
|
||||||
|
// FIXME:variables.h expected-note{{previous}}
|
||||||
|
int z2 = 18; // expected-error{{redefinition}}
|
||||||
//double VeryHappy; // FIXME: xpected-error{{redefinition}}
|
//double VeryHappy; // FIXME: xpected-error{{redefinition}}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ extern int *ip, x;
|
||||||
|
|
||||||
float z;
|
float z;
|
||||||
|
|
||||||
|
int z2 = 17;
|
||||||
|
|
||||||
#define MAKE_HAPPY(X) X##Happy
|
#define MAKE_HAPPY(X) X##Happy
|
||||||
int MAKE_HAPPY(Very);
|
int MAKE_HAPPY(Very);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue