Import Clang r74788.
This commit is contained in:
parent
4ebdf5c4f5
commit
5362a71c02
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/vendor/clang/dist/; revision=195341 svn path=/vendor/clang/clang-r74788/; revision=195343; tag=vendor/clang/clang-r74788
@ -141,10 +141,19 @@ class ASTContext {
|
||||
/// this ASTContext object.
|
||||
LangOptions LangOpts;
|
||||
|
||||
/// \brief Whether we have already loaded comment source ranges from an
|
||||
/// external source.
|
||||
bool LoadedExternalComments;
|
||||
|
||||
/// MallocAlloc/BumpAlloc - The allocator objects used to create AST objects.
|
||||
bool FreeMemory;
|
||||
llvm::MallocAllocator MallocAlloc;
|
||||
llvm::BumpPtrAllocator BumpAlloc;
|
||||
|
||||
/// \brief Mapping from declarations to their comments, once we have
|
||||
/// already looked up the comment associated with a given declaration.
|
||||
llvm::DenseMap<const Decl *, std::string> DeclComments;
|
||||
|
||||
public:
|
||||
TargetInfo &Target;
|
||||
IdentifierTable &Idents;
|
||||
@ -154,6 +163,10 @@ class ASTContext {
|
||||
llvm::OwningPtr<ExternalASTSource> ExternalSource;
|
||||
clang::PrintingPolicy PrintingPolicy;
|
||||
|
||||
/// \brief Source ranges for all of the comments in the source file,
|
||||
/// sorted in order of appearance in the translation unit.
|
||||
std::vector<SourceRange> Comments;
|
||||
|
||||
SourceManager& getSourceManager() { return SourceMgr; }
|
||||
const SourceManager& getSourceManager() const { return SourceMgr; }
|
||||
void *Allocate(unsigned Size, unsigned Align = 8) {
|
||||
@ -178,7 +191,8 @@ class ASTContext {
|
||||
|
||||
TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl; }
|
||||
|
||||
|
||||
const char *getCommentForDecl(const Decl *D);
|
||||
|
||||
// Builtin Types.
|
||||
QualType VoidTy;
|
||||
QualType BoolTy;
|
||||
@ -351,12 +365,6 @@ class ASTContext {
|
||||
ObjCProtocolDecl **ProtocolList,
|
||||
unsigned NumProtocols);
|
||||
|
||||
/// getObjCQualifiedIdType - Return an ObjCQualifiedIdType for a
|
||||
/// given 'id' and conforming protocol list.
|
||||
QualType getObjCQualifiedIdType(ObjCProtocolDecl **ProtocolList,
|
||||
unsigned NumProtocols);
|
||||
|
||||
|
||||
/// getTypeOfType - GCC extension.
|
||||
QualType getTypeOfExprType(Expr *e);
|
||||
QualType getTypeOfType(QualType t);
|
||||
|
@ -17,17 +17,20 @@
|
||||
|
||||
#include "llvm/ADT/GraphTraits.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
|
||||
namespace llvm {
|
||||
class raw_ostream;
|
||||
}
|
||||
namespace clang {
|
||||
class Stmt;
|
||||
class Expr;
|
||||
class CFG;
|
||||
class PrinterHelper;
|
||||
class BlockEdge;
|
||||
class LangOptions;
|
||||
|
||||
/// CFGBlock - Represents a single basic block in a source-level CFG.
|
||||
/// It consists of:
|
||||
@ -181,9 +184,9 @@ class CFGBlock {
|
||||
|
||||
unsigned getBlockID() const { return BlockID; }
|
||||
|
||||
void dump(const CFG* cfg) const;
|
||||
void print(llvm::raw_ostream& OS, const CFG* cfg) const;
|
||||
void printTerminator(llvm::raw_ostream& OS) const;
|
||||
void dump(const CFG *cfg, const LangOptions &LO) const;
|
||||
void print(llvm::raw_ostream &OS, const CFG* cfg, const LangOptions &LO) const;
|
||||
void printTerminator(llvm::raw_ostream &OS, const LangOptions &LO) const;
|
||||
};
|
||||
|
||||
|
||||
@ -283,9 +286,9 @@ class CFG {
|
||||
// CFG Debugging: Pretty-Printing and Visualization.
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
||||
void viewCFG() const;
|
||||
void print(llvm::raw_ostream& OS) const;
|
||||
void dump() const;
|
||||
void viewCFG(const LangOptions &LO) const;
|
||||
void print(llvm::raw_ostream& OS, const LangOptions &LO) const;
|
||||
void dump(const LangOptions &LO) const;
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Internal: constructors and data.
|
||||
|
@ -26,13 +26,19 @@ class Stmt;
|
||||
class CompoundStmt;
|
||||
class StringLiteral;
|
||||
class TemplateArgumentList;
|
||||
class FunctionTemplateSpecializationInfo;
|
||||
|
||||
/// TranslationUnitDecl - The top declaration context.
|
||||
class TranslationUnitDecl : public Decl, public DeclContext {
|
||||
TranslationUnitDecl()
|
||||
ASTContext &Ctx;
|
||||
|
||||
explicit TranslationUnitDecl(ASTContext &ctx)
|
||||
: Decl(TranslationUnit, 0, SourceLocation()),
|
||||
DeclContext(TranslationUnit) {}
|
||||
DeclContext(TranslationUnit),
|
||||
Ctx(ctx) {}
|
||||
public:
|
||||
ASTContext &getASTContext() const { return Ctx; }
|
||||
|
||||
static TranslationUnitDecl *Create(ASTContext &C);
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) { return D->getKind() == TranslationUnit; }
|
||||
@ -621,15 +627,8 @@ class FunctionDecl : public ValueDecl, public DeclContext {
|
||||
enum StorageClass {
|
||||
None, Extern, Static, PrivateExtern
|
||||
};
|
||||
private:
|
||||
/// \brief Provides information about a function template specialization,
|
||||
/// which is a FunctionDecl that has been explicitly specialization or
|
||||
/// instantiated from a function template.
|
||||
struct TemplateSpecializationInfo {
|
||||
FunctionTemplateDecl *Template;
|
||||
const TemplateArgumentList *TemplateArguments;
|
||||
};
|
||||
|
||||
private:
|
||||
/// ParamInfo - new[]'d array of pointers to VarDecls for the formal
|
||||
/// parameters of this function. This is null if a prototype or if there are
|
||||
/// no formals.
|
||||
@ -684,7 +683,8 @@ class FunctionDecl : public ValueDecl, public DeclContext {
|
||||
/// the template being specialized and the template arguments involved in
|
||||
/// that specialization.
|
||||
llvm::PointerUnion3<FunctionTemplateDecl*, FunctionDecl*,
|
||||
TemplateSpecializationInfo*> TemplateOrSpecialization;
|
||||
FunctionTemplateSpecializationInfo*>
|
||||
TemplateOrSpecialization;
|
||||
|
||||
protected:
|
||||
FunctionDecl(Kind DK, DeclContext *DC, SourceLocation L,
|
||||
@ -724,11 +724,11 @@ class FunctionDecl : public ValueDecl, public DeclContext {
|
||||
/// function. The variant that accepts a FunctionDecl pointer will
|
||||
/// set that function declaration to the actual declaration
|
||||
/// containing the body (if there is one).
|
||||
Stmt *getBody(ASTContext &Context, const FunctionDecl *&Definition) const;
|
||||
Stmt *getBody(const FunctionDecl *&Definition) const;
|
||||
|
||||
virtual Stmt *getBody(ASTContext &Context) const {
|
||||
virtual Stmt *getBody() const {
|
||||
const FunctionDecl* Definition;
|
||||
return getBody(Context, Definition);
|
||||
return getBody(Definition);
|
||||
}
|
||||
|
||||
/// \brief If the function has a body that is immediately available,
|
||||
@ -809,9 +809,7 @@ class FunctionDecl : public ValueDecl, public DeclContext {
|
||||
return PreviousDeclaration;
|
||||
}
|
||||
|
||||
void setPreviousDeclaration(FunctionDecl * PrevDecl) {
|
||||
PreviousDeclaration = PrevDecl;
|
||||
}
|
||||
void setPreviousDeclaration(FunctionDecl * PrevDecl);
|
||||
|
||||
unsigned getBuiltinID(ASTContext &Context) const;
|
||||
|
||||
@ -940,27 +938,14 @@ class FunctionDecl : public ValueDecl, public DeclContext {
|
||||
///
|
||||
/// If this function declaration is not a function template specialization,
|
||||
/// returns NULL.
|
||||
FunctionTemplateDecl *getPrimaryTemplate() const {
|
||||
if (TemplateSpecializationInfo *Info
|
||||
= TemplateOrSpecialization.dyn_cast<TemplateSpecializationInfo*>()) {
|
||||
return Info->Template;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
FunctionTemplateDecl *getPrimaryTemplate() const;
|
||||
|
||||
/// \brief Retrieve the template arguments used to produce this function
|
||||
/// template specialization from the primary template.
|
||||
///
|
||||
/// If this function declaration is not a function template specialization,
|
||||
/// returns NULL.
|
||||
const TemplateArgumentList *getTemplateSpecializationArgs() const {
|
||||
if (TemplateSpecializationInfo *Info
|
||||
= TemplateOrSpecialization.dyn_cast<TemplateSpecializationInfo*>()) {
|
||||
return Info->TemplateArguments;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const TemplateArgumentList *getTemplateSpecializationArgs() const;
|
||||
|
||||
/// \brief Specify that this function declaration is actually a function
|
||||
/// template specialization.
|
||||
@ -974,8 +959,17 @@ class FunctionDecl : public ValueDecl, public DeclContext {
|
||||
/// function template specialization from the template.
|
||||
void setFunctionTemplateSpecialization(ASTContext &Context,
|
||||
FunctionTemplateDecl *Template,
|
||||
const TemplateArgumentList *TemplateArgs);
|
||||
|
||||
const TemplateArgumentList *TemplateArgs,
|
||||
void *InsertPos);
|
||||
|
||||
/// \brief Determine whether this is an explicit specialization of a
|
||||
/// function template or a member function of a class template.
|
||||
bool isExplicitSpecialization() const;
|
||||
|
||||
/// \brief Note that this is an explicit specialization of a function template
|
||||
/// or a member function of a class template.
|
||||
void setExplicitSpecialization(bool ES);
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() >= FunctionFirst && D->getKind() <= FunctionLast;
|
||||
@ -1268,12 +1262,12 @@ class EnumDecl : public TagDecl {
|
||||
// enumeration.
|
||||
typedef specific_decl_iterator<EnumConstantDecl> enumerator_iterator;
|
||||
|
||||
enumerator_iterator enumerator_begin(ASTContext &Context) const {
|
||||
return enumerator_iterator(this->decls_begin(Context));
|
||||
enumerator_iterator enumerator_begin() const {
|
||||
return enumerator_iterator(this->decls_begin());
|
||||
}
|
||||
|
||||
enumerator_iterator enumerator_end(ASTContext &Context) const {
|
||||
return enumerator_iterator(this->decls_end(Context));
|
||||
enumerator_iterator enumerator_end() const {
|
||||
return enumerator_iterator(this->decls_end());
|
||||
}
|
||||
|
||||
/// getIntegerType - Return the integer type this enum decl corresponds to.
|
||||
@ -1376,17 +1370,17 @@ class RecordDecl : public TagDecl {
|
||||
// data members, functions, constructors, destructors, etc.
|
||||
typedef specific_decl_iterator<FieldDecl> field_iterator;
|
||||
|
||||
field_iterator field_begin(ASTContext &Context) const {
|
||||
return field_iterator(decls_begin(Context));
|
||||
field_iterator field_begin() const {
|
||||
return field_iterator(decls_begin());
|
||||
}
|
||||
field_iterator field_end(ASTContext &Context) const {
|
||||
return field_iterator(decls_end(Context));
|
||||
field_iterator field_end() const {
|
||||
return field_iterator(decls_end());
|
||||
}
|
||||
|
||||
// field_empty - Whether there are any fields (non-static data
|
||||
// members) in this record.
|
||||
bool field_empty(ASTContext &Context) const {
|
||||
return field_begin(Context) == field_end(Context);
|
||||
bool field_empty() const {
|
||||
return field_begin() == field_end();
|
||||
}
|
||||
|
||||
/// completeDefinition - Notes that the definition of this type is
|
||||
@ -1448,8 +1442,8 @@ class BlockDecl : public Decl, public DeclContext {
|
||||
bool IsVariadic() const { return isVariadic; }
|
||||
void setIsVariadic(bool value) { isVariadic = value; }
|
||||
|
||||
CompoundStmt *getBody() const { return (CompoundStmt*) Body; }
|
||||
Stmt *getBody(ASTContext &C) const { return (Stmt*) Body; }
|
||||
CompoundStmt *getCompoundBody() const { return (CompoundStmt*) Body; }
|
||||
Stmt *getBody() const { return (Stmt*) Body; }
|
||||
void setBody(CompoundStmt *B) { Body = (Stmt*) B; }
|
||||
|
||||
// Iterator access to formal parameters.
|
||||
|
@ -213,6 +213,13 @@ class Decl {
|
||||
const DeclContext *getDeclContext() const {
|
||||
return const_cast<Decl*>(this)->getDeclContext();
|
||||
}
|
||||
|
||||
TranslationUnitDecl *getTranslationUnitDecl();
|
||||
const TranslationUnitDecl *getTranslationUnitDecl() const {
|
||||
return const_cast<Decl*>(this)->getTranslationUnitDecl();
|
||||
}
|
||||
|
||||
ASTContext &getASTContext() const;
|
||||
|
||||
void setAccess(AccessSpecifier AS) {
|
||||
Access = AS;
|
||||
@ -225,23 +232,23 @@ class Decl {
|
||||
}
|
||||
|
||||
bool hasAttrs() const { return HasAttrs; }
|
||||
void addAttr(ASTContext &Context, Attr *attr);
|
||||
const Attr *getAttrs(ASTContext &Context) const {
|
||||
void addAttr(Attr *attr);
|
||||
const Attr *getAttrs() const {
|
||||
if (!HasAttrs) return 0; // common case, no attributes.
|
||||
return getAttrsImpl(Context); // Uncommon case, out of line hash lookup.
|
||||
return getAttrsImpl(); // Uncommon case, out of line hash lookup.
|
||||
}
|
||||
void swapAttrs(ASTContext &Context, Decl *D);
|
||||
void invalidateAttrs(ASTContext &Context);
|
||||
void swapAttrs(Decl *D);
|
||||
void invalidateAttrs();
|
||||
|
||||
template<typename T> const T *getAttr(ASTContext &Context) const {
|
||||
for (const Attr *attr = getAttrs(Context); attr; attr = attr->getNext())
|
||||
template<typename T> const T *getAttr() const {
|
||||
for (const Attr *attr = getAttrs(); attr; attr = attr->getNext())
|
||||
if (const T *V = dyn_cast<T>(attr))
|
||||
return V;
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename T> bool hasAttr(ASTContext &Context) const {
|
||||
return getAttr<T>(Context) != 0;
|
||||
template<typename T> bool hasAttr() const {
|
||||
return getAttr<T>() != 0;
|
||||
}
|
||||
|
||||
/// setInvalidDecl - Indicates the Decl had a semantic error. This
|
||||
@ -307,14 +314,14 @@ class Decl {
|
||||
/// getBody - If this Decl represents a declaration for a body of code,
|
||||
/// such as a function or method definition, this method returns the
|
||||
/// top-level Stmt* of that body. Otherwise this method returns null.
|
||||
virtual Stmt* getBody(ASTContext &Context) const { return 0; }
|
||||
virtual Stmt* getBody() const { return 0; }
|
||||
|
||||
/// getCompoundBody - Returns getBody(), dyn_casted to a CompoundStmt.
|
||||
CompoundStmt* getCompoundBody(ASTContext &Context) const;
|
||||
CompoundStmt* getCompoundBody() const;
|
||||
|
||||
/// getBodyRBrace - Gets the right brace of the body, if a body exists.
|
||||
/// This works whether the body is a CompoundStmt or a CXXTryStmt.
|
||||
SourceLocation getBodyRBrace(ASTContext &Context) const;
|
||||
SourceLocation getBodyRBrace() const;
|
||||
|
||||
// global temp stats (until we have a per-module visitor)
|
||||
static void addDeclKind(Kind k);
|
||||
@ -340,18 +347,16 @@ class Decl {
|
||||
/// Destroy - Call destructors and release memory.
|
||||
virtual void Destroy(ASTContext& C);
|
||||
|
||||
void print(llvm::raw_ostream &Out, ASTContext &Context,
|
||||
void print(llvm::raw_ostream &Out, unsigned Indentation = 0);
|
||||
void print(llvm::raw_ostream &Out, const PrintingPolicy &Policy,
|
||||
unsigned Indentation = 0);
|
||||
void print(llvm::raw_ostream &Out, ASTContext &Context,
|
||||
const PrintingPolicy &Policy, unsigned Indentation = 0);
|
||||
static void printGroup(Decl** Begin, unsigned NumDecls,
|
||||
llvm::raw_ostream &Out, ASTContext &Context,
|
||||
const PrintingPolicy &Policy,
|
||||
llvm::raw_ostream &Out, const PrintingPolicy &Policy,
|
||||
unsigned Indentation = 0);
|
||||
void dump(ASTContext &Context);
|
||||
void dump();
|
||||
|
||||
private:
|
||||
const Attr *getAttrsImpl(ASTContext &Context) const;
|
||||
const Attr *getAttrsImpl() const;
|
||||
|
||||
};
|
||||
|
||||
@ -454,7 +459,11 @@ class DeclContext {
|
||||
const DeclContext *getLexicalParent() const {
|
||||
return const_cast<DeclContext*>(this)->getLexicalParent();
|
||||
}
|
||||
|
||||
|
||||
ASTContext &getParentASTContext() const {
|
||||
return cast<Decl>(this)->getASTContext();
|
||||
}
|
||||
|
||||
bool isFunctionOrMethod() const {
|
||||
switch (DeclKind) {
|
||||
case Decl::Block:
|
||||
@ -592,9 +601,9 @@ class DeclContext {
|
||||
|
||||
/// decls_begin/decls_end - Iterate over the declarations stored in
|
||||
/// this context.
|
||||
decl_iterator decls_begin(ASTContext &Context) const;
|
||||
decl_iterator decls_end(ASTContext &Context) const;
|
||||
bool decls_empty(ASTContext &Context) const;
|
||||
decl_iterator decls_begin() const;
|
||||
decl_iterator decls_end() const;
|
||||
bool decls_empty() const;
|
||||
|
||||
/// specific_decl_iterator - Iterates over a subrange of
|
||||
/// declarations stored in a DeclContext, providing only those that
|
||||
@ -750,7 +759,7 @@ class DeclContext {
|
||||
///
|
||||
/// If D is also a NamedDecl, it will be made visible within its
|
||||
/// semantic context via makeDeclVisibleInContext.
|
||||
void addDecl(ASTContext &Context, Decl *D);
|
||||
void addDecl(Decl *D);
|
||||
|
||||
/// lookup_iterator - An iterator that provides access to the results
|
||||
/// of looking up a name within this context.
|
||||
@ -769,8 +778,8 @@ class DeclContext {
|
||||
/// the declarations with this name, with object, function, member,
|
||||
/// and enumerator names preceding any tag name. Note that this
|
||||
/// routine will not look into parent contexts.
|
||||
lookup_result lookup(ASTContext &Context, DeclarationName Name);
|
||||
lookup_const_result lookup(ASTContext &Context, DeclarationName Name) const;
|
||||
lookup_result lookup(DeclarationName Name);
|
||||
lookup_const_result lookup(DeclarationName Name) const;
|
||||
|
||||
/// @brief Makes a declaration visible within this context.
|
||||
///
|
||||
@ -786,7 +795,7 @@ class DeclContext {
|
||||
/// visible from this context, as determined by
|
||||
/// NamedDecl::declarationReplaces, the previous declaration will be
|
||||
/// replaced with D.
|
||||
void makeDeclVisibleInContext(ASTContext &Context, NamedDecl *D);
|
||||
void makeDeclVisibleInContext(NamedDecl *D);
|
||||
|
||||
/// udir_iterator - Iterates through the using-directives stored
|
||||
/// within this context.
|
||||
@ -794,14 +803,14 @@ class DeclContext {
|
||||
|
||||
typedef std::pair<udir_iterator, udir_iterator> udir_iterator_range;
|
||||
|
||||
udir_iterator_range getUsingDirectives(ASTContext &Context) const;
|
||||
udir_iterator_range getUsingDirectives() const;
|
||||
|
||||
udir_iterator using_directives_begin(ASTContext &Context) const {
|
||||
return getUsingDirectives(Context).first;
|
||||
udir_iterator using_directives_begin() const {
|
||||
return getUsingDirectives().first;
|
||||
}
|
||||
|
||||
udir_iterator using_directives_end(ASTContext &Context) const {
|
||||
return getUsingDirectives(Context).second;
|
||||
udir_iterator using_directives_end() const {
|
||||
return getUsingDirectives().second;
|
||||
}
|
||||
|
||||
// Low-level accessors
|
||||
@ -836,11 +845,11 @@ class DeclContext {
|
||||
#include "clang/AST/DeclNodes.def"
|
||||
|
||||
private:
|
||||
void LoadLexicalDeclsFromExternalStorage(ASTContext &Context) const;
|
||||
void LoadVisibleDeclsFromExternalStorage(ASTContext &Context) const;
|
||||
void LoadLexicalDeclsFromExternalStorage() const;
|
||||
void LoadVisibleDeclsFromExternalStorage() const;
|
||||
|
||||
void buildLookup(ASTContext &Context, DeclContext *DCtx);
|
||||
void makeDeclVisibleInContextImpl(ASTContext &Context, NamedDecl *D);
|
||||
void buildLookup(DeclContext *DCtx);
|
||||
void makeDeclVisibleInContextImpl(NamedDecl *D);
|
||||
};
|
||||
|
||||
inline bool Decl::isTemplateParameter() const {
|
||||
|
@ -32,6 +32,8 @@ class ClassTemplateSpecializationDecl;
|
||||
class AnyFunctionDecl {
|
||||
NamedDecl *Function;
|
||||
|
||||
AnyFunctionDecl(NamedDecl *ND) : Function(ND) { }
|
||||
|
||||
public:
|
||||
AnyFunctionDecl(FunctionDecl *FD) : Function(FD) { }
|
||||
AnyFunctionDecl(FunctionTemplateDecl *FTD);
|
||||
@ -42,6 +44,10 @@ class AnyFunctionDecl {
|
||||
|
||||
/// \brief Retrieve the underlying function or function template.
|
||||
NamedDecl *get() const { return Function; }
|
||||
|
||||
static AnyFunctionDecl getFromNamedDecl(NamedDecl *ND) {
|
||||
return AnyFunctionDecl(ND);
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
@ -57,6 +63,22 @@ namespace llvm {
|
||||
};
|
||||
template<> struct simplify_type< ::clang::AnyFunctionDecl>
|
||||
: public simplify_type<const ::clang::AnyFunctionDecl> {};
|
||||
|
||||
// Provide PointerLikeTypeTraits for non-cvr pointers.
|
||||
template<>
|
||||
class PointerLikeTypeTraits< ::clang::AnyFunctionDecl> {
|
||||
public:
|
||||
static inline void *getAsVoidPointer(::clang::AnyFunctionDecl F) {
|
||||
return F.get();
|
||||
}
|
||||
static inline ::clang::AnyFunctionDecl getFromVoidPointer(void *P) {
|
||||
return ::clang::AnyFunctionDecl::getFromNamedDecl(
|
||||
static_cast< ::clang::NamedDecl*>(P));
|
||||
}
|
||||
|
||||
enum { NumLowBitsAvailable = 2 };
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
namespace clang {
|
||||
@ -91,24 +113,10 @@ class OverloadedFunctionDecl : public NamedDecl {
|
||||
static OverloadedFunctionDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
DeclarationName N);
|
||||
|
||||
/// addOverload - Add an overloaded function FD to this set of
|
||||
/// overloaded functions.
|
||||
void addOverload(FunctionDecl *FD) {
|
||||
assert((FD->getDeclName() == getDeclName() ||
|
||||
isa<CXXConversionDecl>(FD) || isa<CXXConstructorDecl>(FD)) &&
|
||||
"Overloaded functions must have the same name");
|
||||
Functions.push_back(FD);
|
||||
/// \brief Add a new overloaded function or function template to the set
|
||||
/// of overloaded function templates.
|
||||
void addOverload(AnyFunctionDecl F);
|
||||
|
||||
// An overloaded function declaration always has the location of
|
||||
// the most-recently-added function declaration.
|
||||
if (FD->getLocation().isValid())
|
||||
this->setLocation(FD->getLocation());
|
||||
}
|
||||
|
||||
/// addOverload - Add an overloaded function template FTD to this set of
|
||||
/// overloaded functions.
|
||||
void addOverload(FunctionTemplateDecl *FTD);
|
||||
|
||||
function_iterator function_begin() { return Functions.begin(); }
|
||||
function_iterator function_end() { return Functions.end(); }
|
||||
function_const_iterator function_begin() const { return Functions.begin(); }
|
||||
@ -289,8 +297,11 @@ class CXXRecordDecl : public RecordDecl {
|
||||
CXXRecordDecl* PrevDecl=0,
|
||||
bool DelayTypeCreation = false);
|
||||
|
||||
virtual void Destroy(ASTContext& C);
|
||||
|
||||
/// setBases - Sets the base classes of this struct or class.
|
||||
void setBases(CXXBaseSpecifier const * const *Bases, unsigned NumBases);
|
||||
void setBases(ASTContext &C,
|
||||
CXXBaseSpecifier const * const *Bases, unsigned NumBases);
|
||||
|
||||
/// getNumBases - Retrieves the number of base classes of this
|
||||
/// class.
|
||||
@ -580,15 +591,20 @@ class CXXBaseOrMemberInitializer {
|
||||
/// Args - The arguments used to initialize the base or member.
|
||||
Expr **Args;
|
||||
unsigned NumArgs;
|
||||
|
||||
/// IdLoc - Location of the id in ctor-initializer list.
|
||||
SourceLocation IdLoc;
|
||||
|
||||
public:
|
||||
/// CXXBaseOrMemberInitializer - Creates a new base-class initializer.
|
||||
explicit
|
||||
CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs);
|
||||
CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs,
|
||||
SourceLocation L);
|
||||
|
||||
/// CXXBaseOrMemberInitializer - Creates a new member initializer.
|
||||
explicit
|
||||
CXXBaseOrMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs);
|
||||
CXXBaseOrMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs,
|
||||
SourceLocation L);
|
||||
|
||||
/// ~CXXBaseOrMemberInitializer - Destroy the base or member initializer.
|
||||
~CXXBaseOrMemberInitializer();
|
||||
@ -601,6 +617,10 @@ class CXXBaseOrMemberInitializer {
|
||||
/// arguments.
|
||||
typedef Expr * const * arg_const_iterator;
|
||||
|
||||
/// getBaseOrMember - get the generic 'member' representing either the field
|
||||
/// or a base class.
|
||||
void* getBaseOrMember() const { return reinterpret_cast<void*>(BaseOrMember); }
|
||||
|
||||
/// isBaseInitializer - Returns true when this initializer is
|
||||
/// initializing a base class.
|
||||
bool isBaseInitializer() const { return (BaseOrMember & 0x1) != 0; }
|
||||
@ -641,6 +661,8 @@ class CXXBaseOrMemberInitializer {
|
||||
return 0;
|
||||
}
|
||||
|
||||
SourceLocation getSourceLocation() const { return IdLoc; }
|
||||
|
||||
/// begin() - Retrieve an iterator to the first initializer argument.
|
||||
arg_iterator begin() { return Args; }
|
||||
/// begin() - Retrieve an iterator to the first initializer argument.
|
||||
@ -677,16 +699,22 @@ class CXXConstructorDecl : public CXXMethodDecl {
|
||||
/// @c !Implicit && ImplicitlyDefined.
|
||||
bool ImplicitlyDefined : 1;
|
||||
|
||||
/// FIXME: Add support for base and member initializers.
|
||||
|
||||
/// Support for base and member initializers.
|
||||
/// BaseOrMemberInitializers - The arguments used to initialize the base
|
||||
/// or member.
|
||||
CXXBaseOrMemberInitializer **BaseOrMemberInitializers;
|
||||
unsigned NumBaseOrMemberInitializers;
|
||||
|
||||
CXXConstructorDecl(CXXRecordDecl *RD, SourceLocation L,
|
||||
DeclarationName N, QualType T,
|
||||
bool isExplicit, bool isInline, bool isImplicitlyDeclared)
|
||||
: CXXMethodDecl(CXXConstructor, RD, L, N, T, false, isInline),
|
||||
Explicit(isExplicit), ImplicitlyDefined(false) {
|
||||
Explicit(isExplicit), ImplicitlyDefined(false),
|
||||
BaseOrMemberInitializers(0), NumBaseOrMemberInitializers(0) {
|
||||
setImplicit(isImplicitlyDeclared);
|
||||
}
|
||||
|
||||
virtual void Destroy(ASTContext& C);
|
||||
|
||||
public:
|
||||
static CXXConstructorDecl *Create(ASTContext &C, CXXRecordDecl *RD,
|
||||
SourceLocation L, DeclarationName N,
|
||||
@ -702,7 +730,8 @@ class CXXConstructorDecl : public CXXMethodDecl {
|
||||
/// already been defined.
|
||||
bool isImplicitlyDefined(ASTContext &C) const {
|
||||
assert(isThisDeclarationADefinition() &&
|
||||
"Can only get the implicit-definition flag once the constructor has been defined");
|
||||
"Can only get the implicit-definition flag once the "
|
||||
"constructor has been defined");
|
||||
return ImplicitlyDefined;
|
||||
}
|
||||
|
||||
@ -710,10 +739,41 @@ class CXXConstructorDecl : public CXXMethodDecl {
|
||||
/// implicitly defined or not.
|
||||
void setImplicitlyDefined(bool ID) {
|
||||
assert(isThisDeclarationADefinition() &&
|
||||
"Can only set the implicit-definition flag once the constructor has been defined");
|
||||
"Can only set the implicit-definition flag once the constructor "
|
||||
"has been defined");
|
||||
ImplicitlyDefined = ID;
|
||||
}
|
||||
|
||||
/// init_iterator - Iterates through the member/base initializer list.
|
||||
typedef CXXBaseOrMemberInitializer **init_iterator;
|
||||
|
||||
/// init_const_iterator - Iterates through the memberbase initializer list.
|
||||
typedef CXXBaseOrMemberInitializer * const * init_const_iterator;
|
||||
|
||||
/// begin() - Retrieve an iterator to the first initializer.
|
||||
init_iterator begin() { return BaseOrMemberInitializers; }
|
||||
/// begin() - Retrieve an iterator to the first initializer.
|
||||
init_const_iterator begin() const { return BaseOrMemberInitializers; }
|
||||
|
||||
/// end() - Retrieve an iterator past the last initializer.
|
||||
init_iterator end() {
|
||||
return BaseOrMemberInitializers + NumBaseOrMemberInitializers;
|
||||
}
|
||||
/// end() - Retrieve an iterator past the last initializer.
|
||||
init_const_iterator end() const {
|
||||
return BaseOrMemberInitializers + NumBaseOrMemberInitializers;
|
||||
}
|
||||
|
||||
/// getNumArgs - Determine the number of arguments used to
|
||||
/// initialize the member or base.
|
||||
unsigned getNumBaseOrMemberInitializers() const {
|
||||
return NumBaseOrMemberInitializers;
|
||||
}
|
||||
|
||||
void setBaseOrMemberInitializers(ASTContext &C,
|
||||
CXXBaseOrMemberInitializer **Initializers,
|
||||
unsigned NumInitializers);
|
||||
|
||||
/// isDefaultConstructor - Whether this constructor is a default
|
||||
/// constructor (C++ [class.ctor]p5), which can be used to
|
||||
/// default-initialize a class of this type.
|
||||
|
@ -242,10 +242,10 @@ class ObjCMethodDecl : public NamedDecl, public DeclContext {
|
||||
return ImplementationControl(DeclImplementation);
|
||||
}
|
||||
|
||||
virtual Stmt *getBody(ASTContext &C) const {
|
||||
virtual Stmt *getBody() const {
|
||||
return (Stmt*) Body;
|
||||
}
|
||||
CompoundStmt *getBody() { return (CompoundStmt*)Body; }
|
||||
CompoundStmt *getCompoundBody() { return (CompoundStmt*)Body; }
|
||||
void setBody(Stmt *B) { Body = B; }
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
@ -291,55 +291,52 @@ class ObjCContainerDecl : public NamedDecl, public DeclContext {
|
||||
|
||||
// Iterator access to properties.
|
||||
typedef specific_decl_iterator<ObjCPropertyDecl> prop_iterator;
|
||||
prop_iterator prop_begin(ASTContext &Context) const {
|
||||
return prop_iterator(decls_begin(Context));
|
||||
prop_iterator prop_begin() const {
|
||||
return prop_iterator(decls_begin());
|
||||
}
|
||||
prop_iterator prop_end(ASTContext &Context) const {
|
||||
return prop_iterator(decls_end(Context));
|
||||
prop_iterator prop_end() const {
|
||||
return prop_iterator(decls_end());
|
||||
}
|
||||
|
||||
// Iterator access to instance/class methods.
|
||||
typedef specific_decl_iterator<ObjCMethodDecl> method_iterator;
|
||||
method_iterator meth_begin(ASTContext &Context) const {
|
||||
return method_iterator(decls_begin(Context));
|
||||
method_iterator meth_begin() const {
|
||||
return method_iterator(decls_begin());
|
||||
}
|
||||
method_iterator meth_end(ASTContext &Context) const {
|
||||
return method_iterator(decls_end(Context));
|
||||
method_iterator meth_end() const {
|
||||
return method_iterator(decls_end());
|
||||
}
|
||||
|
||||
typedef filtered_decl_iterator<ObjCMethodDecl,
|
||||
&ObjCMethodDecl::isInstanceMethod>
|
||||
instmeth_iterator;
|
||||
instmeth_iterator instmeth_begin(ASTContext &Context) const {
|
||||
return instmeth_iterator(decls_begin(Context));
|
||||
instmeth_iterator instmeth_begin() const {
|
||||
return instmeth_iterator(decls_begin());
|
||||
}
|
||||
instmeth_iterator instmeth_end(ASTContext &Context) const {
|
||||
return instmeth_iterator(decls_end(Context));
|
||||
instmeth_iterator instmeth_end() const {
|
||||
return instmeth_iterator(decls_end());
|
||||
}
|
||||
|
||||
typedef filtered_decl_iterator<ObjCMethodDecl,
|
||||
&ObjCMethodDecl::isClassMethod>
|
||||
classmeth_iterator;
|
||||
classmeth_iterator classmeth_begin(ASTContext &Context) const {
|
||||
return classmeth_iterator(decls_begin(Context));
|
||||
classmeth_iterator classmeth_begin() const {
|
||||
return classmeth_iterator(decls_begin());
|
||||
}
|
||||
classmeth_iterator classmeth_end(ASTContext &Context) const {
|
||||
return classmeth_iterator(decls_end(Context));
|
||||
classmeth_iterator classmeth_end() const {
|
||||
return classmeth_iterator(decls_end());
|
||||
}
|
||||
|
||||
// Get the local instance/class method declared in this interface.
|
||||
ObjCMethodDecl *getInstanceMethod(ASTContext &Context, Selector Sel) const;
|
||||
ObjCMethodDecl *getClassMethod(ASTContext &Context, Selector Sel) const;
|
||||
ObjCIvarDecl *getIvarDecl(ASTContext &Context, IdentifierInfo *Id) const;
|
||||
ObjCMethodDecl *getInstanceMethod(Selector Sel) const;
|
||||
ObjCMethodDecl *getClassMethod(Selector Sel) const;
|
||||
ObjCIvarDecl *getIvarDecl(IdentifierInfo *Id) const;
|
||||
|
||||
ObjCMethodDecl *
|
||||
getMethod(ASTContext &Context, Selector Sel, bool isInstance) const {
|
||||
return isInstance ? getInstanceMethod(Context, Sel)
|
||||
: getClassMethod(Context, Sel);
|
||||
ObjCMethodDecl *getMethod(Selector Sel, bool isInstance) const {
|
||||
return isInstance ? getInstanceMethod(Sel) : getClassMethod(Sel);
|
||||
}
|
||||
|
||||
ObjCPropertyDecl *FindPropertyDeclaration(ASTContext &Context,
|
||||
IdentifierInfo *PropertyId) const;
|
||||
ObjCPropertyDecl *FindPropertyDeclaration(IdentifierInfo *PropertyId) const;
|
||||
|
||||
// Marks the end of the container.
|
||||
SourceLocation getAtEndLoc() const { return AtEndLoc; }
|
||||
@ -474,19 +471,17 @@ class ObjCInterfaceDecl : public ObjCContainerDecl {
|
||||
return false;
|
||||
}
|
||||
|
||||
ObjCIvarDecl *lookupInstanceVariable(ASTContext &Context,
|
||||
IdentifierInfo *IVarName,
|
||||
ObjCIvarDecl *lookupInstanceVariable(IdentifierInfo *IVarName,
|
||||
ObjCInterfaceDecl *&ClassDeclared);
|
||||
ObjCIvarDecl *lookupInstanceVariable(ASTContext &Context,
|
||||
IdentifierInfo *IVarName) {
|
||||
ObjCIvarDecl *lookupInstanceVariable(IdentifierInfo *IVarName) {
|
||||
ObjCInterfaceDecl *ClassDeclared;
|
||||
return lookupInstanceVariable(Context, IVarName, ClassDeclared);
|
||||
return lookupInstanceVariable(IVarName, ClassDeclared);
|
||||
}
|
||||
|
||||
// Lookup a method. First, we search locally. If a method isn't
|
||||
// found, we search referenced protocols and class categories.
|
||||
ObjCMethodDecl *lookupInstanceMethod(ASTContext &Context, Selector Sel);
|
||||
ObjCMethodDecl *lookupClassMethod(ASTContext &Context, Selector Sel);
|
||||
ObjCMethodDecl *lookupInstanceMethod(Selector Sel);
|
||||
ObjCMethodDecl *lookupClassMethod(Selector Sel);
|
||||
ObjCInterfaceDecl *lookupInheritedClass(const IdentifierInfo *ICName);
|
||||
|
||||
// Location information, modeled after the Stmt API.
|
||||
@ -648,8 +643,8 @@ class ObjCProtocolDecl : public ObjCContainerDecl {
|
||||
|
||||
// Lookup a method. First, we search locally. If a method isn't
|
||||
// found, we search referenced protocols and class categories.
|
||||
ObjCMethodDecl *lookupInstanceMethod(ASTContext &Context, Selector Sel);
|
||||
ObjCMethodDecl *lookupClassMethod(ASTContext &Context, Selector Sel);
|
||||
ObjCMethodDecl *lookupInstanceMethod(Selector Sel);
|
||||
ObjCMethodDecl *lookupClassMethod(Selector Sel);
|
||||
|
||||
bool isForwardDecl() const { return isForwardProtoDecl; }
|
||||
void setForwardDecl(bool val) { isForwardProtoDecl = val; }
|
||||
@ -831,61 +826,57 @@ class ObjCImplDecl : public NamedDecl, public DeclContext {
|
||||
ObjCInterfaceDecl *getClassInterface() { return ClassInterface; }
|
||||
void setClassInterface(ObjCInterfaceDecl *IFace) { ClassInterface = IFace; }
|
||||
|
||||
void addInstanceMethod(ASTContext &Context, ObjCMethodDecl *method) {
|
||||
void addInstanceMethod(ObjCMethodDecl *method) {
|
||||
// FIXME: Context should be set correctly before we get here.
|
||||
method->setLexicalDeclContext(this);
|
||||
addDecl(Context, method);
|
||||
addDecl(method);
|
||||
}
|
||||
void addClassMethod(ASTContext &Context, ObjCMethodDecl *method) {
|
||||
void addClassMethod(ObjCMethodDecl *method) {
|
||||
// FIXME: Context should be set correctly before we get here.
|
||||
method->setLexicalDeclContext(this);
|
||||
addDecl(Context, method);
|
||||
addDecl(method);
|
||||
}
|
||||
|
||||
// Get the local instance/class method declared in this interface.
|
||||
ObjCMethodDecl *getInstanceMethod(ASTContext &Context, Selector Sel) const;
|
||||
ObjCMethodDecl *getClassMethod(ASTContext &Context, Selector Sel) const;
|
||||
ObjCMethodDecl *getMethod(ASTContext &Context, Selector Sel,
|
||||
bool isInstance) const {
|
||||
return isInstance ? getInstanceMethod(Context, Sel)
|
||||
: getClassMethod(Context, Sel);
|
||||
ObjCMethodDecl *getInstanceMethod(Selector Sel) const;
|
||||
ObjCMethodDecl *getClassMethod(Selector Sel) const;
|
||||
ObjCMethodDecl *getMethod(Selector Sel, bool isInstance) const {
|
||||
return isInstance ? getInstanceMethod(Sel)
|
||||
: getClassMethod(Sel);
|
||||
}
|
||||
|
||||
void addPropertyImplementation(ASTContext &Context,
|
||||
ObjCPropertyImplDecl *property);
|
||||
void addPropertyImplementation(ObjCPropertyImplDecl *property);
|
||||
|
||||
ObjCPropertyImplDecl *FindPropertyImplDecl(ASTContext &Context,
|
||||
IdentifierInfo *propertyId) const;
|
||||
ObjCPropertyImplDecl *FindPropertyImplIvarDecl(ASTContext &Context,
|
||||
IdentifierInfo *ivarId) const;
|
||||
ObjCPropertyImplDecl *FindPropertyImplDecl(IdentifierInfo *propertyId) const;
|
||||
ObjCPropertyImplDecl *FindPropertyImplIvarDecl(IdentifierInfo *ivarId) const;
|
||||
|
||||
// Iterator access to properties.
|
||||
typedef specific_decl_iterator<ObjCPropertyImplDecl> propimpl_iterator;
|
||||
propimpl_iterator propimpl_begin(ASTContext &Context) const {
|
||||
return propimpl_iterator(decls_begin(Context));
|
||||
propimpl_iterator propimpl_begin() const {
|
||||
return propimpl_iterator(decls_begin());
|
||||
}
|
||||
propimpl_iterator propimpl_end(ASTContext &Context) const {
|
||||
return propimpl_iterator(decls_end(Context));
|
||||
propimpl_iterator propimpl_end() const {
|
||||
return propimpl_iterator(decls_end());
|
||||
}
|
||||
|
||||
typedef filtered_decl_iterator<ObjCMethodDecl,
|
||||
&ObjCMethodDecl::isInstanceMethod>
|
||||
instmeth_iterator;
|
||||
instmeth_iterator instmeth_begin(ASTContext &Context) const {
|
||||
return instmeth_iterator(decls_begin(Context));
|
||||
instmeth_iterator instmeth_begin() const {
|
||||
return instmeth_iterator(decls_begin());
|
||||
}
|
||||
instmeth_iterator instmeth_end(ASTContext &Context) const {
|
||||
return instmeth_iterator(decls_end(Context));
|
||||
instmeth_iterator instmeth_end() const {
|
||||
return instmeth_iterator(decls_end());
|
||||
}
|
||||
|
||||
typedef filtered_decl_iterator<ObjCMethodDecl,
|
||||
&ObjCMethodDecl::isClassMethod>
|
||||
classmeth_iterator;
|
||||
classmeth_iterator classmeth_begin(ASTContext &Context) const {
|
||||
return classmeth_iterator(decls_begin(Context));
|
||||
classmeth_iterator classmeth_begin() const {
|
||||
return classmeth_iterator(decls_begin());
|
||||
}
|
||||
classmeth_iterator classmeth_end(ASTContext &Context) const {
|
||||
return classmeth_iterator(decls_end(Context));
|
||||
classmeth_iterator classmeth_end() const {
|
||||
return classmeth_iterator(decls_end());
|
||||
}
|
||||
|
||||
// Location information, modeled after the Stmt API.
|
||||
@ -1002,17 +993,17 @@ class ObjCImplementationDecl : public ObjCImplDecl {
|
||||
void setSuperClass(ObjCInterfaceDecl * superCls) { SuperClass = superCls; }
|
||||
|
||||
typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator;
|
||||
ivar_iterator ivar_begin(ASTContext &Context) const {
|
||||
return ivar_iterator(decls_begin(Context));
|
||||
ivar_iterator ivar_begin() const {
|
||||
return ivar_iterator(decls_begin());
|
||||
}
|
||||
ivar_iterator ivar_end(ASTContext &Context) const {
|
||||
return ivar_iterator(decls_end(Context));
|
||||
ivar_iterator ivar_end() const {
|
||||
return ivar_iterator(decls_end());
|
||||
}
|
||||
unsigned ivar_size(ASTContext &Context) const {
|
||||
return std::distance(ivar_begin(Context), ivar_end(Context));
|
||||
unsigned ivar_size() const {
|
||||
return std::distance(ivar_begin(), ivar_end());
|
||||
}
|
||||
bool ivar_empty(ASTContext &Context) const {
|
||||
return ivar_begin(Context) == ivar_end(Context);
|
||||
bool ivar_empty() const {
|
||||
return ivar_begin() == ivar_end();
|
||||
}
|
||||
|
||||
static bool classof(const Decl *D) {
|
||||
|
@ -100,6 +100,352 @@ class TemplateParameterList {
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Represents a template argument within a class template
|
||||
/// specialization.
|
||||
class TemplateArgument {
|
||||
union {
|
||||
uintptr_t TypeOrValue;
|
||||
struct {
|
||||
char Value[sizeof(llvm::APSInt)];
|
||||
void *Type;
|
||||
} Integer;
|
||||
struct {
|
||||
TemplateArgument *Args;
|
||||
unsigned NumArgs;
|
||||
bool CopyArgs;
|
||||
} Args;
|
||||
};
|
||||
|
||||
/// \brief Location of the beginning of this template argument.
|
||||
SourceLocation StartLoc;
|
||||
|
||||
public:
|
||||
/// \brief The type of template argument we're storing.
|
||||
enum ArgKind {
|
||||
Null = 0,
|
||||
/// The template argument is a type. Its value is stored in the
|
||||
/// TypeOrValue field.
|
||||
Type = 1,
|
||||
/// The template argument is a declaration
|
||||
Declaration = 2,
|
||||
/// The template argument is an integral value stored in an llvm::APSInt.
|
||||
Integral = 3,
|
||||
/// The template argument is a value- or type-dependent expression
|
||||
/// stored in an Expr*.
|
||||
Expression = 4,
|
||||
|
||||
/// The template argument is actually a parameter pack. Arguments are stored
|
||||
/// in the Args struct.
|
||||
Pack = 5
|
||||
} Kind;
|
||||
|
||||
/// \brief Construct an empty, invalid template argument.
|
||||
TemplateArgument() : TypeOrValue(0), StartLoc(), Kind(Null) { }
|
||||
|
||||
/// \brief Construct a template type argument.
|
||||
TemplateArgument(SourceLocation Loc, QualType T) : Kind(Type) {
|
||||
TypeOrValue = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
|
||||
StartLoc = Loc;
|
||||
}
|
||||
|
||||
/// \brief Construct a template argument that refers to a
|
||||
/// declaration, which is either an external declaration or a
|
||||
/// template declaration.
|
||||
TemplateArgument(SourceLocation Loc, Decl *D) : Kind(Declaration) {
|
||||
// FIXME: Need to be sure we have the "canonical" declaration!
|
||||
TypeOrValue = reinterpret_cast<uintptr_t>(D);
|
||||
StartLoc = Loc;
|
||||
}
|
||||
|
||||
/// \brief Construct an integral constant template argument.
|
||||
TemplateArgument(SourceLocation Loc, const llvm::APSInt &Value,
|
||||
QualType Type)
|
||||
: Kind(Integral) {
|
||||
new (Integer.Value) llvm::APSInt(Value);
|
||||
Integer.Type = Type.getAsOpaquePtr();
|
||||
StartLoc = Loc;
|
||||
}
|
||||
|
||||
/// \brief Construct a template argument that is an expression.
|
||||
///
|
||||
/// This form of template argument only occurs in template argument
|
||||
/// lists used for dependent types and for expression; it will not
|
||||
/// occur in a non-dependent, canonical template argument list.
|
||||
TemplateArgument(Expr *E);
|
||||
|
||||
/// \brief Copy constructor for a template argument.
|
||||
TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) {
|
||||
if (Kind == Integral) {
|
||||
new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
|
||||
Integer.Type = Other.Integer.Type;
|
||||
} else if (Kind == Pack) {
|
||||
Args.NumArgs = Other.Args.NumArgs;
|
||||
Args.Args = new TemplateArgument[Args.NumArgs];
|
||||
for (unsigned I = 0; I != Args.NumArgs; ++I)
|
||||
Args.Args[I] = Other.Args.Args[I];
|
||||
}
|
||||
else
|
||||
TypeOrValue = Other.TypeOrValue;
|
||||
StartLoc = Other.StartLoc;
|
||||
}
|
||||
|
||||
TemplateArgument& operator=(const TemplateArgument& Other) {
|
||||
// FIXME: Does not provide the strong guarantee for exception
|
||||
// safety.
|
||||
using llvm::APSInt;
|
||||
|
||||
// FIXME: Handle Packs
|
||||
assert(Kind != Pack && "FIXME: Handle packs");
|
||||
assert(Other.Kind != Pack && "FIXME: Handle packs");
|
||||
|
||||
if (Kind == Other.Kind && Kind == Integral) {
|
||||
// Copy integral values.
|
||||
*this->getAsIntegral() = *Other.getAsIntegral();
|
||||
Integer.Type = Other.Integer.Type;
|
||||
} else {
|
||||
// Destroy the current integral value, if that's what we're holding.
|
||||
if (Kind == Integral)
|
||||
getAsIntegral()->~APSInt();
|
||||
|
||||
Kind = Other.Kind;
|
||||
|
||||
if (Other.Kind == Integral) {
|
||||
new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
|
||||
Integer.Type = Other.Integer.Type;
|
||||
} else
|
||||
TypeOrValue = Other.TypeOrValue;
|
||||
}
|
||||
StartLoc = Other.StartLoc;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
~TemplateArgument() {
|
||||
using llvm::APSInt;
|
||||
|
||||
if (Kind == Integral)
|
||||
getAsIntegral()->~APSInt();
|
||||
else if (Kind == Pack && Args.CopyArgs)
|
||||
delete[] Args.Args;
|
||||
}
|
||||
|
||||
/// \brief Return the kind of stored template argument.
|
||||
ArgKind getKind() const { return Kind; }
|
||||
|
||||
/// \brief Determine whether this template argument has no value.
|
||||
bool isNull() const { return Kind == Null; }
|
||||
|
||||
/// \brief Retrieve the template argument as a type.
|
||||
QualType getAsType() const {
|
||||
if (Kind != Type)
|
||||
return QualType();
|
||||
|
||||
return QualType::getFromOpaquePtr(
|
||||
reinterpret_cast<void*>(TypeOrValue));
|
||||
}
|
||||
|
||||
/// \brief Retrieve the template argument as a declaration.
|
||||
Decl *getAsDecl() const {
|
||||
if (Kind != Declaration)
|
||||
return 0;
|
||||
return reinterpret_cast<Decl *>(TypeOrValue);
|
||||
}
|
||||
|
||||
/// \brief Retrieve the template argument as an integral value.
|
||||
llvm::APSInt *getAsIntegral() {
|
||||
if (Kind != Integral)
|
||||
return 0;
|
||||
return reinterpret_cast<llvm::APSInt*>(&Integer.Value[0]);
|
||||
}
|
||||
|
||||
const llvm::APSInt *getAsIntegral() const {
|
||||
return const_cast<TemplateArgument*>(this)->getAsIntegral();
|
||||
}
|
||||
|
||||
/// \brief Retrieve the type of the integral value.
|
||||
QualType getIntegralType() const {
|
||||
if (Kind != Integral)
|
||||
return QualType();
|
||||
|
||||
return QualType::getFromOpaquePtr(Integer.Type);
|
||||
}
|
||||
|
||||
void setIntegralType(QualType T) {
|
||||
assert(Kind == Integral &&
|
||||
"Cannot set the integral type of a non-integral template argument");
|
||||
Integer.Type = T.getAsOpaquePtr();
|
||||
};
|
||||
|
||||
/// \brief Retrieve the template argument as an expression.
|
||||
Expr *getAsExpr() const {
|
||||
if (Kind != Expression)
|
||||
return 0;
|
||||
|
||||
return reinterpret_cast<Expr *>(TypeOrValue);
|
||||
}
|
||||
|
||||
/// \brief Iterator that traverses the elements of a template argument pack.
|
||||
typedef const TemplateArgument * pack_iterator;
|
||||
|
||||
/// \brief Iterator referencing the first argument of a template argument
|
||||
/// pack.
|
||||
pack_iterator pack_begin() const {
|
||||
assert(Kind == Pack);
|
||||
return Args.Args;
|
||||
}
|
||||
|
||||
/// \brief Iterator referencing one past the last argument of a template
|
||||
/// argument pack.
|
||||
pack_iterator pack_end() const {
|
||||
assert(Kind == Pack);
|
||||
return Args.Args + Args.NumArgs;
|
||||
}
|
||||
|
||||
/// \brief The number of template arguments in the given template argument
|
||||
/// pack.
|
||||
unsigned pack_size() const {
|
||||
assert(Kind == Pack);
|
||||
return Args.NumArgs;
|
||||
}
|
||||
|
||||
/// \brief Retrieve the location where the template argument starts.
|
||||
SourceLocation getLocation() const { return StartLoc; }
|
||||
|
||||
/// \brief Construct a template argument pack.
|
||||
void setArgumentPack(TemplateArgument *Args, unsigned NumArgs, bool CopyArgs);
|
||||
|
||||
/// \brief Used to insert TemplateArguments into FoldingSets.
|
||||
void Profile(llvm::FoldingSetNodeID &ID) const {
|
||||
ID.AddInteger(Kind);
|
||||
switch (Kind) {
|
||||
case Null:
|
||||
break;
|
||||
|
||||
case Type:
|
||||
getAsType().Profile(ID);
|
||||
break;
|
||||
|
||||
case Declaration:
|
||||
ID.AddPointer(getAsDecl()); // FIXME: Must be canonical!
|
||||
break;
|
||||
|
||||
case Integral:
|
||||
getAsIntegral()->Profile(ID);
|
||||
getIntegralType().Profile(ID);
|
||||
break;
|
||||
|
||||
case Expression:
|
||||
// FIXME: We need a canonical representation of expressions.
|
||||
ID.AddPointer(getAsExpr());
|
||||
break;
|
||||
|
||||
case Pack:
|
||||
ID.AddInteger(Args.NumArgs);
|
||||
for (unsigned I = 0; I != Args.NumArgs; ++I)
|
||||
Args.Args[I].Profile(ID);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief A helper class for making template argument lists.
|
||||
class TemplateArgumentListBuilder {
|
||||
TemplateArgument *StructuredArgs;
|
||||
unsigned MaxStructuredArgs;
|
||||
unsigned NumStructuredArgs;
|
||||
|
||||
TemplateArgument *FlatArgs;
|
||||
unsigned MaxFlatArgs;
|
||||
unsigned NumFlatArgs;
|
||||
|
||||
bool AddingToPack;
|
||||
unsigned PackBeginIndex;
|
||||
|
||||
public:
|
||||
TemplateArgumentListBuilder(const TemplateParameterList *Parameters,
|
||||
unsigned NumTemplateArgs)
|
||||
: StructuredArgs(0), MaxStructuredArgs(Parameters->size()),
|
||||
NumStructuredArgs(0), FlatArgs(0),
|
||||
MaxFlatArgs(std::max(MaxStructuredArgs, NumTemplateArgs)), NumFlatArgs(0),
|
||||
AddingToPack(false), PackBeginIndex(0) { }
|
||||
|
||||
void Append(const TemplateArgument& Arg);
|
||||
void BeginPack();
|
||||
void EndPack();
|
||||
|
||||
void ReleaseArgs();
|
||||
|
||||
unsigned flatSize() const {
|
||||
return NumFlatArgs;
|
||||
}
|
||||
const TemplateArgument *getFlatArguments() const {
|
||||
return FlatArgs;
|
||||
}
|
||||
|
||||
unsigned structuredSize() const {
|
||||
// If we don't have any structured args, just reuse the flat size.
|
||||
if (!StructuredArgs)
|
||||
return flatSize();
|
||||
|
||||
return NumStructuredArgs;
|
||||
}
|
||||
const TemplateArgument *getStructuredArguments() const {
|
||||
// If we don't have any structured args, just reuse the flat args.
|
||||
if (!StructuredArgs)
|
||||
return getFlatArguments();
|
||||
|
||||
return StructuredArgs;
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief A template argument list.
|
||||
///
|
||||
/// FIXME: In the future, this class will be extended to support
|
||||
/// variadic templates and member templates, which will make some of
|
||||
/// the function names below make more sense.
|
||||
class TemplateArgumentList {
|
||||
/// \brief The template argument list.
|
||||
///
|
||||
/// The integer value will be non-zero to indicate that this
|
||||
/// template argument list does not own the pointer.
|
||||
llvm::PointerIntPair<const TemplateArgument *, 1> FlatArguments;
|
||||
|
||||
/// \brief The number of template arguments in this template
|
||||
/// argument list.
|
||||
unsigned NumFlatArguments;
|
||||
|
||||
llvm::PointerIntPair<const TemplateArgument *, 1> StructuredArguments;
|
||||
unsigned NumStructuredArguments;
|
||||
|
||||
public:
|
||||
TemplateArgumentList(ASTContext &Context,
|
||||
TemplateArgumentListBuilder &Builder,
|
||||
bool TakeArgs);
|
||||
|
||||
~TemplateArgumentList();
|
||||
|
||||
/// \brief Retrieve the template argument at a given index.
|
||||
const TemplateArgument &get(unsigned Idx) const {
|
||||
assert(Idx < NumFlatArguments && "Invalid template argument index");
|
||||
return getFlatArgumentList()[Idx];
|
||||
}
|
||||
|
||||
/// \brief Retrieve the template argument at a given index.
|
||||
const TemplateArgument &operator[](unsigned Idx) const { return get(Idx); }
|
||||
|
||||
/// \brief Retrieve the number of template arguments in this
|
||||
/// template argument list.
|
||||
unsigned size() const { return NumFlatArguments; }
|
||||
|
||||
/// \brief Retrieve the number of template arguments in the
|
||||
/// flattened template argument list.
|
||||
unsigned flat_size() const { return NumFlatArguments; }
|
||||
|
||||
/// \brief Retrieve the flattened template argument list.
|
||||
const TemplateArgument *getFlatArgumentList() const {
|
||||
return FlatArguments.getPointer();
|
||||
}
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Kinds of Templates
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -154,18 +500,110 @@ class TemplateDecl : public NamedDecl {
|
||||
TemplateParameterList* TemplateParams;
|
||||
};
|
||||
|
||||
/// \brief Provides information about a function template specialization,
|
||||
/// which is a FunctionDecl that has been explicitly specialization or
|
||||
/// instantiated from a function template.
|
||||
class FunctionTemplateSpecializationInfo : public llvm::FoldingSetNode {
|
||||
public:
|
||||
/// \brief The function template specialization that this structure
|
||||
/// describes.
|
||||
FunctionDecl *Function;
|
||||
|
||||
/// \brief The function template from which this function template
|
||||
/// specialization was generated.
|
||||
///
|
||||
/// The bit will be 0 for an implicit instantiation, 1 for an explicit
|
||||
/// specialization.
|
||||
llvm::PointerIntPair<FunctionTemplateDecl *, 1> Template;
|
||||
|
||||
/// \brief The template arguments used to produce the function template
|
||||
/// specialization from the function template.
|
||||
const TemplateArgumentList *TemplateArguments;
|
||||
|
||||
/// \brief Retrieve the template from which this function was specialized.
|
||||
FunctionTemplateDecl *getTemplate() const { return Template.getPointer(); }
|
||||
|
||||
/// \brief Determine whether this is an explicit specialization.
|
||||
bool isExplicitSpecialization() const { return Template.getInt(); }
|
||||
|
||||
/// \brief Set whether this is an explicit specialization or an implicit
|
||||
/// instantiation.
|
||||
void setExplicitSpecialization(bool ES) {
|
||||
Template.setInt(ES);
|
||||
}
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) {
|
||||
Profile(ID, TemplateArguments->getFlatArgumentList(),
|
||||
TemplateArguments->flat_size());
|
||||
}
|
||||
|
||||
static void
|
||||
Profile(llvm::FoldingSetNodeID &ID, const TemplateArgument *TemplateArgs,
|
||||
unsigned NumTemplateArgs) {
|
||||
ID.AddInteger(NumTemplateArgs);
|
||||
for (unsigned Arg = 0; Arg != NumTemplateArgs; ++Arg)
|
||||
TemplateArgs[Arg].Profile(ID);
|
||||
}
|
||||
};
|
||||
|
||||
/// Declaration of a template function.
|
||||
class FunctionTemplateDecl : public TemplateDecl {
|
||||
class FunctionTemplateDecl : public TemplateDecl {
|
||||
protected:
|
||||
/// \brief Data that is common to all of the declarations of a given
|
||||
/// function template.
|
||||
struct Common {
|
||||
/// \brief The function template specializations for this function
|
||||
/// template, including explicit specializations and instantiations.
|
||||
llvm::FoldingSet<FunctionTemplateSpecializationInfo> Specializations;
|
||||
};
|
||||
|
||||
/// \brief A pointer to the previous declaration (if this is a redeclaration)
|
||||
/// or to the data that is common to all declarations of this function
|
||||
/// template.
|
||||
llvm::PointerUnion<Common*, FunctionTemplateDecl*> CommonOrPrev;
|
||||
|
||||
/// \brief Retrieves the "common" pointer shared by all
|
||||
/// (re-)declarations of the same function template. Calling this routine
|
||||
/// may implicitly allocate memory for the common pointer.
|
||||
Common *getCommonPtr();
|
||||
|
||||
FunctionTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
|
||||
TemplateParameterList *Params, NamedDecl *Decl)
|
||||
: TemplateDecl(FunctionTemplate, DC, L, Name, Params, Decl) { }
|
||||
: TemplateDecl(FunctionTemplate, DC, L, Name, Params, Decl),
|
||||
CommonOrPrev((Common*)0) { }
|
||||
|
||||
public:
|
||||
/// Get the underling function declaration of the template.
|
||||
void Destroy(ASTContext &C);
|
||||
|
||||
/// Get the underlying function declaration of the template.
|
||||
FunctionDecl *getTemplatedDecl() const {
|
||||
return static_cast<FunctionDecl*>(TemplatedDecl);
|
||||
}
|
||||
|
||||
/// \brief Retrieve the set of function template specializations of this
|
||||
/// function template.
|
||||
llvm::FoldingSet<FunctionTemplateSpecializationInfo> &getSpecializations() {
|
||||
return getCommonPtr()->Specializations;
|
||||
}
|
||||
|
||||
/// \brief Retrieve the previous declaration of this function template, or
|
||||
/// NULL if no such declaration exists.
|
||||
const FunctionTemplateDecl *getPreviousDeclaration() const {
|
||||
return CommonOrPrev.dyn_cast<FunctionTemplateDecl*>();
|
||||
}
|
||||
|
||||
/// \brief Retrieve the previous declaration of this function template, or
|
||||
/// NULL if no such declaration exists.
|
||||
FunctionTemplateDecl *getPreviousDeclaration() {
|
||||
return CommonOrPrev.dyn_cast<FunctionTemplateDecl*>();
|
||||
}
|
||||
|
||||
/// \brief Set the previous declaration of this function template.
|
||||
void setPreviousDeclaration(FunctionTemplateDecl *Prev) {
|
||||
if (Prev)
|
||||
CommonOrPrev = Prev;
|
||||
}
|
||||
|
||||
/// Create a template function node.
|
||||
static FunctionTemplateDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation L,
|
||||
@ -396,352 +834,6 @@ class TemplateTemplateParmDecl
|
||||
static bool classof(const TemplateTemplateParmDecl *D) { return true; }
|
||||
};
|
||||
|
||||
/// \brief Represents a template argument within a class template
|
||||
/// specialization.
|
||||
class TemplateArgument {
|
||||
union {
|
||||
uintptr_t TypeOrValue;
|
||||
struct {
|
||||
char Value[sizeof(llvm::APSInt)];
|
||||
void *Type;
|
||||
} Integer;
|
||||
struct {
|
||||
TemplateArgument *Args;
|
||||
unsigned NumArgs;
|
||||
bool CopyArgs;
|
||||
} Args;
|
||||
};
|
||||
|
||||
/// \brief Location of the beginning of this template argument.
|
||||
SourceLocation StartLoc;
|
||||
|
||||
public:
|
||||
/// \brief The type of template argument we're storing.
|
||||
enum ArgKind {
|
||||
Null = 0,
|
||||
/// The template argument is a type. Its value is stored in the
|
||||
/// TypeOrValue field.
|
||||
Type = 1,
|
||||
/// The template argument is a declaration
|
||||
Declaration = 2,
|
||||
/// The template argument is an integral value stored in an llvm::APSInt.
|
||||
Integral = 3,
|
||||
/// The template argument is a value- or type-dependent expression
|
||||
/// stored in an Expr*.
|
||||
Expression = 4,
|
||||
|
||||
/// The template argument is actually a parameter pack. Arguments are stored
|
||||
/// in the Args struct.
|
||||
Pack = 5
|
||||
} Kind;
|
||||
|
||||
/// \brief Construct an empty, invalid template argument.
|
||||
TemplateArgument() : TypeOrValue(0), StartLoc(), Kind(Null) { }
|
||||
|
||||
/// \brief Construct a template type argument.
|
||||
TemplateArgument(SourceLocation Loc, QualType T) : Kind(Type) {
|
||||
TypeOrValue = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
|
||||
StartLoc = Loc;
|
||||
}
|
||||
|
||||
/// \brief Construct a template argument that refers to a
|
||||
/// declaration, which is either an external declaration or a
|
||||
/// template declaration.
|
||||
TemplateArgument(SourceLocation Loc, Decl *D) : Kind(Declaration) {
|
||||
// FIXME: Need to be sure we have the "canonical" declaration!
|
||||
TypeOrValue = reinterpret_cast<uintptr_t>(D);
|
||||
StartLoc = Loc;
|
||||
}
|
||||
|
||||
/// \brief Construct an integral constant template argument.
|
||||
TemplateArgument(SourceLocation Loc, const llvm::APSInt &Value,
|
||||
QualType Type)
|
||||
: Kind(Integral) {
|
||||
new (Integer.Value) llvm::APSInt(Value);
|
||||
Integer.Type = Type.getAsOpaquePtr();
|
||||
StartLoc = Loc;
|
||||
}
|
||||
|
||||
/// \brief Construct a template argument that is an expression.
|
||||
///
|
||||
/// This form of template argument only occurs in template argument
|
||||
/// lists used for dependent types and for expression; it will not
|
||||
/// occur in a non-dependent, canonical template argument list.
|
||||
TemplateArgument(Expr *E);
|
||||
|
||||
/// \brief Copy constructor for a template argument.
|
||||
TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) {
|
||||
if (Kind == Integral) {
|
||||
new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
|
||||
Integer.Type = Other.Integer.Type;
|
||||
} else if (Kind == Pack) {
|
||||
Args.NumArgs = Other.Args.NumArgs;
|
||||
Args.Args = new TemplateArgument[Args.NumArgs];
|
||||
for (unsigned I = 0; I != Args.NumArgs; ++I)
|
||||
Args.Args[I] = Other.Args.Args[I];
|
||||
}
|
||||
else
|
||||
TypeOrValue = Other.TypeOrValue;
|
||||
StartLoc = Other.StartLoc;
|
||||
}
|
||||
|
||||
TemplateArgument& operator=(const TemplateArgument& Other) {
|
||||
// FIXME: Does not provide the strong guarantee for exception
|
||||
// safety.
|
||||
using llvm::APSInt;
|
||||
|
||||
// FIXME: Handle Packs
|
||||
assert(Kind != Pack && "FIXME: Handle packs");
|
||||
assert(Other.Kind != Pack && "FIXME: Handle packs");
|
||||
|
||||
if (Kind == Other.Kind && Kind == Integral) {
|
||||
// Copy integral values.
|
||||
*this->getAsIntegral() = *Other.getAsIntegral();
|
||||
Integer.Type = Other.Integer.Type;
|
||||
} else {
|
||||
// Destroy the current integral value, if that's what we're holding.
|
||||
if (Kind == Integral)
|
||||
getAsIntegral()->~APSInt();
|
||||
|
||||
Kind = Other.Kind;
|
||||
|
||||
if (Other.Kind == Integral) {
|
||||
new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
|
||||
Integer.Type = Other.Integer.Type;
|
||||
} else
|
||||
TypeOrValue = Other.TypeOrValue;
|
||||
}
|
||||
StartLoc = Other.StartLoc;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
~TemplateArgument() {
|
||||
using llvm::APSInt;
|
||||
|
||||
if (Kind == Integral)
|
||||
getAsIntegral()->~APSInt();
|
||||
else if (Kind == Pack && Args.CopyArgs)
|
||||
delete[] Args.Args;
|
||||
}
|
||||
|
||||
/// \brief Return the kind of stored template argument.
|
||||
ArgKind getKind() const { return Kind; }
|
||||
|
||||
/// \brief Determine whether this template argument has no value.
|
||||
bool isNull() const { return Kind == Null; }
|
||||
|
||||
/// \brief Retrieve the template argument as a type.
|
||||
QualType getAsType() const {
|
||||
if (Kind != Type)
|
||||
return QualType();
|
||||
|
||||
return QualType::getFromOpaquePtr(
|
||||
reinterpret_cast<void*>(TypeOrValue));
|
||||
}
|
||||
|
||||
/// \brief Retrieve the template argument as a declaration.
|
||||
Decl *getAsDecl() const {
|
||||
if (Kind != Declaration)
|
||||
return 0;
|
||||
return reinterpret_cast<Decl *>(TypeOrValue);
|
||||
}
|
||||
|
||||
/// \brief Retrieve the template argument as an integral value.
|
||||
llvm::APSInt *getAsIntegral() {
|
||||
if (Kind != Integral)
|
||||
return 0;
|
||||
return reinterpret_cast<llvm::APSInt*>(&Integer.Value[0]);
|
||||
}
|
||||
|
||||
const llvm::APSInt *getAsIntegral() const {
|
||||
return const_cast<TemplateArgument*>(this)->getAsIntegral();
|
||||
}
|
||||
|
||||
/// \brief Retrieve the type of the integral value.
|
||||
QualType getIntegralType() const {
|
||||
if (Kind != Integral)
|
||||
return QualType();
|
||||
|
||||
return QualType::getFromOpaquePtr(Integer.Type);
|
||||
}
|
||||
|
||||
void setIntegralType(QualType T) {
|
||||
assert(Kind == Integral &&
|
||||
"Cannot set the integral type of a non-integral template argument");
|
||||
Integer.Type = T.getAsOpaquePtr();
|
||||
};
|
||||
|
||||
/// \brief Retrieve the template argument as an expression.
|
||||
Expr *getAsExpr() const {
|
||||
if (Kind != Expression)
|
||||
return 0;
|
||||
|
||||
return reinterpret_cast<Expr *>(TypeOrValue);
|
||||
}
|
||||
|
||||
/// \brief Iterator that traverses the elements of a template argument pack.
|
||||
typedef const TemplateArgument * pack_iterator;
|
||||
|
||||
/// \brief Iterator referencing the first argument of a template argument
|
||||
/// pack.
|
||||
pack_iterator pack_begin() const {
|
||||
assert(Kind == Pack);
|
||||
return Args.Args;
|
||||
}
|
||||
|
||||
/// \brief Iterator referencing one past the last argument of a template
|
||||
/// argument pack.
|
||||
pack_iterator pack_end() const {
|
||||
assert(Kind == Pack);
|
||||
return Args.Args + Args.NumArgs;
|
||||
}
|
||||
|
||||
/// \brief The number of template arguments in the given template argument
|
||||
/// pack.
|
||||
unsigned pack_size() const {
|
||||
assert(Kind == Pack);
|
||||
return Args.NumArgs;
|
||||
}
|
||||
|
||||
/// \brief Retrieve the location where the template argument starts.
|
||||
SourceLocation getLocation() const { return StartLoc; }
|
||||
|
||||
/// \brief Construct a template argument pack.
|
||||
void setArgumentPack(TemplateArgument *Args, unsigned NumArgs, bool CopyArgs);
|
||||
|
||||
/// \brief Used to insert TemplateArguments into FoldingSets.
|
||||
void Profile(llvm::FoldingSetNodeID &ID) const {
|
||||
ID.AddInteger(Kind);
|
||||
switch (Kind) {
|
||||
case Null:
|
||||
break;
|
||||
|
||||
case Type:
|
||||
getAsType().Profile(ID);
|
||||
break;
|
||||
|
||||
case Declaration:
|
||||
ID.AddPointer(getAsDecl()); // FIXME: Must be canonical!
|
||||
break;
|
||||
|
||||
case Integral:
|
||||
getAsIntegral()->Profile(ID);
|
||||
getIntegralType().Profile(ID);
|
||||
break;
|
||||
|
||||
case Expression:
|
||||
// FIXME: We need a canonical representation of expressions.
|
||||
ID.AddPointer(getAsExpr());
|
||||
break;
|
||||
|
||||
case Pack:
|
||||
ID.AddInteger(Args.NumArgs);
|
||||
for (unsigned I = 0; I != Args.NumArgs; ++I)
|
||||
Args.Args[I].Profile(ID);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief A helper class for making template argument lists.
|
||||
class TemplateArgumentListBuilder {
|
||||
TemplateArgument *StructuredArgs;
|
||||
unsigned MaxStructuredArgs;
|
||||
unsigned NumStructuredArgs;
|
||||
|
||||
TemplateArgument *FlatArgs;
|
||||
unsigned MaxFlatArgs;
|
||||
unsigned NumFlatArgs;
|
||||
|
||||
bool AddingToPack;
|
||||
unsigned PackBeginIndex;
|
||||
|
||||
public:
|
||||
TemplateArgumentListBuilder(const TemplateParameterList *Parameters,
|
||||
unsigned NumTemplateArgs)
|
||||
: StructuredArgs(0), MaxStructuredArgs(Parameters->size()),
|
||||
NumStructuredArgs(0), FlatArgs(0),
|
||||
MaxFlatArgs(std::max(MaxStructuredArgs, NumTemplateArgs)), NumFlatArgs(0),
|
||||
AddingToPack(false), PackBeginIndex(0) { }
|
||||
|
||||
void Append(const TemplateArgument& Arg);
|
||||
void BeginPack();
|
||||
void EndPack();
|
||||
|
||||
void ReleaseArgs();
|
||||
|
||||
unsigned flatSize() const {
|
||||
return NumFlatArgs;
|
||||
}
|
||||
const TemplateArgument *getFlatArguments() const {
|
||||
return FlatArgs;
|
||||
}
|
||||
|
||||
unsigned structuredSize() const {
|
||||
// If we don't have any structured args, just reuse the flat size.
|
||||
if (!StructuredArgs)
|
||||
return flatSize();
|
||||
|
||||
return NumStructuredArgs;
|
||||
}
|
||||
const TemplateArgument *getStructuredArguments() const {
|
||||
// If we don't have any structured args, just reuse the flat args.
|
||||
if (!StructuredArgs)
|
||||
return getFlatArguments();
|
||||
|
||||
return StructuredArgs;
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief A template argument list.
|
||||
///
|
||||
/// FIXME: In the future, this class will be extended to support
|
||||
/// variadic templates and member templates, which will make some of
|
||||
/// the function names below make more sense.
|
||||
class TemplateArgumentList {
|
||||
/// \brief The template argument list.
|
||||
///
|
||||
/// The integer value will be non-zero to indicate that this
|
||||
/// template argument list does not own the pointer.
|
||||
llvm::PointerIntPair<const TemplateArgument *, 1> FlatArguments;
|
||||
|
||||
/// \brief The number of template arguments in this template
|
||||
/// argument list.
|
||||
unsigned NumFlatArguments;
|
||||
|
||||
llvm::PointerIntPair<const TemplateArgument *, 1> StructuredArguments;
|
||||
unsigned NumStructuredArguments;
|
||||
|
||||
public:
|
||||
TemplateArgumentList(ASTContext &Context,
|
||||
TemplateArgumentListBuilder &Builder,
|
||||
bool TakeArgs);
|
||||
|
||||
~TemplateArgumentList();
|
||||
|
||||
/// \brief Retrieve the template argument at a given index.
|
||||
const TemplateArgument &get(unsigned Idx) const {
|
||||
assert(Idx < NumFlatArguments && "Invalid template argument index");
|
||||
return getFlatArgumentList()[Idx];
|
||||
}
|
||||
|
||||
/// \brief Retrieve the template argument at a given index.
|
||||
const TemplateArgument &operator[](unsigned Idx) const { return get(Idx); }
|
||||
|
||||
/// \brief Retrieve the number of template arguments in this
|
||||
/// template argument list.
|
||||
unsigned size() const { return NumFlatArguments; }
|
||||
|
||||
/// \brief Retrieve the number of template arguments in the
|
||||
/// flattened template argument list.
|
||||
unsigned flat_size() const { return NumFlatArguments; }
|
||||
|
||||
/// \brief Retrieve the flattened template argument list.
|
||||
const TemplateArgument *getFlatArgumentList() const {
|
||||
return FlatArguments.getPointer();
|
||||
}
|
||||
};
|
||||
|
||||
// \brief Describes the kind of template specialization that a
|
||||
// particular template specialization declaration represents.
|
||||
enum TemplateSpecializationKind {
|
||||
|
@ -124,7 +124,7 @@ class Expr : public Stmt {
|
||||
/// with location to warn on and the source range[s] to report with the
|
||||
/// warning.
|
||||
bool isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
|
||||
SourceRange &R2, ASTContext &Context) const;
|
||||
SourceRange &R2) const;
|
||||
|
||||
/// isLvalue - C99 6.3.2.1: an lvalue is an expression with an object type or
|
||||
/// incomplete type other than void. Nonarray expressions that can be lvalues:
|
||||
@ -467,9 +467,9 @@ class FloatingLiteral : public Expr {
|
||||
bool IsExact : 1;
|
||||
SourceLocation Loc;
|
||||
public:
|
||||
FloatingLiteral(const llvm::APFloat &V, bool* isexact,
|
||||
FloatingLiteral(const llvm::APFloat &V, bool isexact,
|
||||
QualType Type, SourceLocation L)
|
||||
: Expr(FloatingLiteralClass, Type), Value(V), IsExact(*isexact), Loc(L) {}
|
||||
: Expr(FloatingLiteralClass, Type), Value(V), IsExact(isexact), Loc(L) {}
|
||||
|
||||
/// \brief Construct an empty floating-point literal.
|
||||
explicit FloatingLiteral(EmptyShell Empty)
|
||||
@ -2433,9 +2433,6 @@ class BlockExpr : public Expr {
|
||||
const Stmt *getBody() const;
|
||||
Stmt *getBody();
|
||||
|
||||
const Stmt *getBody(ASTContext &C) const { return getBody(); }
|
||||
Stmt *getBody(ASTContext &C) { return getBody(); }
|
||||
|
||||
virtual SourceRange getSourceRange() const {
|
||||
return SourceRange(getCaretLocation(), getBody()->getLocEnd());
|
||||
}
|
||||
|
@ -1017,6 +1017,100 @@ class UnresolvedDeclRefExpr : public Expr {
|
||||
virtual StmtIterator child_end();
|
||||
};
|
||||
|
||||
/// \brief An expression that refers to a C++ template-id, such as
|
||||
/// @c isa<FunctionDecl>.
|
||||
class TemplateIdRefExpr : public Expr {
|
||||
/// \brief If this template-id was qualified-id, e.g., @c std::sort<int>,
|
||||
/// this nested name specifier contains the @c std::.
|
||||
NestedNameSpecifier *Qualifier;
|
||||
|
||||
/// \brief If this template-id was a qualified-id, e.g., @c std::sort<int>,
|
||||
/// this covers the source code range of the @c std::.
|
||||
SourceRange QualifierRange;
|
||||
|
||||
/// \brief The actual template to which this template-id refers.
|
||||
TemplateName Template;
|
||||
|
||||
/// \brief The source location of the template name.
|
||||
SourceLocation TemplateNameLoc;
|
||||
|
||||
/// \brief The source location of the left angle bracket ('<');
|
||||
SourceLocation LAngleLoc;
|
||||
|
||||
/// \brief The source location of the right angle bracket ('>');
|
||||
SourceLocation RAngleLoc;
|
||||
|
||||
/// \brief The number of template arguments in TemplateArgs.
|
||||
unsigned NumTemplateArgs;
|
||||
|
||||
TemplateIdRefExpr(QualType T,
|
||||
NestedNameSpecifier *Qualifier, SourceRange QualifierRange,
|
||||
TemplateName Template, SourceLocation TemplateNameLoc,
|
||||
SourceLocation LAngleLoc,
|
||||
const TemplateArgument *TemplateArgs,
|
||||
unsigned NumTemplateArgs,
|
||||
SourceLocation RAngleLoc);
|
||||
|
||||
public:
|
||||
static TemplateIdRefExpr *
|
||||
Create(ASTContext &Context, QualType T,
|
||||
NestedNameSpecifier *Qualifier, SourceRange QualifierRange,
|
||||
TemplateName Template, SourceLocation TemplateNameLoc,
|
||||
SourceLocation LAngleLoc, const TemplateArgument *TemplateArgs,
|
||||
unsigned NumTemplateArgs, SourceLocation RAngleLoc);
|
||||
|
||||
void Destroy(ASTContext &Context);
|
||||
|
||||
/// \brief Retrieve the nested name specifier used to qualify the name of
|
||||
/// this template-id, e.g., the "std::sort" in @c std::sort<int>, or NULL
|
||||
/// if this template-id was an unqualified-id.
|
||||
NestedNameSpecifier *getQualifier() const { return Qualifier; }
|
||||
|
||||
/// \brief Retrieve the source range describing the nested name specifier
|
||||
/// used to qualified the name of this template-id, if the name was qualified.
|
||||
SourceRange getQualifierRange() const { return QualifierRange; }
|
||||
|
||||
/// \brief Retrieve the name of the template referenced, e.g., "sort" in
|
||||
/// @c std::sort<int>;
|
||||
TemplateName getTemplateName() const { return Template; }
|
||||
|
||||
/// \brief Retrieve the location of the name of the template referenced, e.g.,
|
||||
/// the location of "sort" in @c std::sort<int>.
|
||||
SourceLocation getTemplateNameLoc() const { return TemplateNameLoc; }
|
||||
|
||||
/// \brief Retrieve the location of the left angle bracket following the
|
||||
/// template name ('<').
|
||||
SourceLocation getLAngleLoc() const { return LAngleLoc; }
|
||||
|
||||
/// \brief Retrieve the template arguments provided as part of this
|
||||
/// template-id.
|
||||
const TemplateArgument *getTemplateArgs() const {
|
||||
return reinterpret_cast<const TemplateArgument *>(this + 1);
|
||||
}
|
||||
|
||||
/// \brief Retrieve the number of template arguments provided as part of this
|
||||
/// template-id.
|
||||
unsigned getNumTemplateArgs() const { return NumTemplateArgs; }
|
||||
|
||||
/// \brief Retrieve the location of the right angle bracket following the
|
||||
/// template arguments ('>').
|
||||
SourceLocation getRAngleLoc() const { return RAngleLoc; }
|
||||
|
||||
virtual SourceRange getSourceRange() const {
|
||||
return SourceRange(Qualifier? QualifierRange.getBegin() : TemplateNameLoc,
|
||||
RAngleLoc);
|
||||
}
|
||||
|
||||
// Iterators
|
||||
virtual child_iterator child_begin();
|
||||
virtual child_iterator child_end();
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == TemplateIdRefExprClass;
|
||||
}
|
||||
static bool classof(const TemplateIdRefExpr *) { return true; }
|
||||
};
|
||||
|
||||
class CXXExprWithTemporaries : public Expr {
|
||||
Stmt *SubExpr;
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "clang/AST/Type.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
namespace clang {
|
||||
|
||||
class ASTConsumer;
|
||||
@ -57,6 +58,14 @@ class ExternalASTSource {
|
||||
|
||||
virtual ~ExternalASTSource();
|
||||
|
||||
/// \brief Reads the source ranges that correspond to comments from
|
||||
/// an external AST source.
|
||||
///
|
||||
/// \param Comments the contents of this vector will be
|
||||
/// replaced with the sorted set of source ranges corresponding to
|
||||
/// comments in the source code.
|
||||
virtual void ReadComments(std::vector<SourceRange> &Comments) = 0;
|
||||
|
||||
/// \brief Resolve a type ID into a type, potentially building a new
|
||||
/// type.
|
||||
virtual QualType GetType(uint32_t ID) = 0;
|
||||
|
@ -28,6 +28,7 @@ class NamespaceDecl;
|
||||
class IdentifierInfo;
|
||||
class PrintingPolicy;
|
||||
class Type;
|
||||
class LangOptions;
|
||||
|
||||
/// \brief Represents a C++ nested name specifier, such as
|
||||
/// "::std::vector<int>::".
|
||||
@ -175,7 +176,7 @@ class NestedNameSpecifier : public llvm::FoldingSetNode {
|
||||
|
||||
/// \brief Dump the nested name specifier to standard output to aid
|
||||
/// in debugging.
|
||||
void dump();
|
||||
void dump(const LangOptions &LO);
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ namespace clang {
|
||||
|
||||
class Stmt;
|
||||
class TagDecl;
|
||||
class LangOptions;
|
||||
|
||||
class PrinterHelper {
|
||||
public:
|
||||
@ -33,16 +34,15 @@ class PrinterHelper {
|
||||
/// declarations should be printed.
|
||||
struct PrintingPolicy {
|
||||
/// \brief Create a default printing policy for C.
|
||||
PrintingPolicy()
|
||||
: Indentation(2), CPlusPlus(false), SuppressSpecifiers(false),
|
||||
PrintingPolicy(const LangOptions &LO)
|
||||
: Indentation(2), LangOpts(LO), SuppressSpecifiers(false),
|
||||
SuppressTag(false), SuppressTagKind(false), Dump(false) { }
|
||||
|
||||
/// \brief The number of spaces to use to indent each line.
|
||||
unsigned Indentation : 8;
|
||||
|
||||
/// \brief Whether we're printing C++ code (otherwise, we're
|
||||
/// printing C code).
|
||||
bool CPlusPlus : 1;
|
||||
/// \brief What language we're printing.
|
||||
const LangOptions &LangOpts;
|
||||
|
||||
/// \brief Whether we should suppress printing of the actual specifiers for
|
||||
/// the given type or declaration.
|
||||
|
@ -187,14 +187,14 @@ class Stmt {
|
||||
/// dumpPretty/printPretty - These two methods do a "pretty print" of the AST
|
||||
/// back to its original source language syntax.
|
||||
void dumpPretty(ASTContext& Context) const;
|
||||
void printPretty(llvm::raw_ostream &OS, PrinterHelper *Helper = 0,
|
||||
const PrintingPolicy &Policy = PrintingPolicy(),
|
||||
void printPretty(llvm::raw_ostream &OS, PrinterHelper *Helper,
|
||||
const PrintingPolicy &Policy,
|
||||
unsigned Indentation = 0) const {
|
||||
printPretty(OS, *(ASTContext*)0, Helper, Policy, Indentation);
|
||||
}
|
||||
void printPretty(llvm::raw_ostream &OS, ASTContext& Context,
|
||||
PrinterHelper *Helper = 0,
|
||||
const PrintingPolicy &Policy = PrintingPolicy(),
|
||||
void printPretty(llvm::raw_ostream &OS, ASTContext &Context,
|
||||
PrinterHelper *Helper,
|
||||
const PrintingPolicy &Policy,
|
||||
unsigned Indentation = 0) const;
|
||||
|
||||
/// viewAST - Visualize an AST rooted at this Stmt* using GraphViz. Only
|
||||
|
@ -9,7 +9,7 @@
|
||||
//
|
||||
// This file defines the AST Node info database.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
#ifndef FIRST_STMT
|
||||
#define FIRST_STMT(CLASS)
|
||||
@ -123,6 +123,7 @@ EXPR(UnresolvedFunctionNameExpr , Expr)
|
||||
EXPR(UnaryTypeTraitExpr , Expr)
|
||||
EXPR(QualifiedDeclRefExpr , DeclRefExpr)
|
||||
EXPR(UnresolvedDeclRefExpr , Expr)
|
||||
EXPR(TemplateIdRefExpr , Expr)
|
||||
EXPR(CXXConstructExpr , Expr)
|
||||
EXPR(CXXBindTemporaryExpr , Expr)
|
||||
EXPR(CXXExprWithTemporaries , Expr)
|
||||
|
@ -188,7 +188,8 @@ class QualType {
|
||||
getAsStringInternal(S, Policy);
|
||||
return S;
|
||||
}
|
||||
void getAsStringInternal(std::string &Str, const PrintingPolicy &Policy) const;
|
||||
void getAsStringInternal(std::string &Str,
|
||||
const PrintingPolicy &Policy) const;
|
||||
|
||||
void dump(const char *s) const;
|
||||
void dump() const;
|
||||
@ -375,6 +376,7 @@ class Type {
|
||||
bool isFunctionProtoType() const { return getAsFunctionProtoType() != 0; }
|
||||
bool isPointerType() const;
|
||||
bool isBlockPointerType() const;
|
||||
bool isVoidPointerType() const;
|
||||
bool isReferenceType() const;
|
||||
bool isLValueReferenceType() const;
|
||||
bool isRValueReferenceType() const;
|
||||
@ -585,7 +587,7 @@ class BuiltinType : public Type {
|
||||
TypeKind(K) {}
|
||||
|
||||
Kind getKind() const { return TypeKind; }
|
||||
const char *getName(bool CPlusPlus) const;
|
||||
const char *getName(const LangOptions &LO) const;
|
||||
|
||||
virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const;
|
||||
|
||||
|
@ -62,7 +62,6 @@ class MemRegion : public llvm::FoldingSetNode {
|
||||
ASTContext &getContext() const;
|
||||
|
||||
public:
|
||||
// virtual MemExtent getExtent(MemRegionManager& mrm) const = 0;
|
||||
virtual void Profile(llvm::FoldingSetNodeID& ID) const = 0;
|
||||
|
||||
virtual MemRegionManager* getMemRegionManager() const = 0;
|
||||
@ -73,17 +72,25 @@ class MemRegion : public llvm::FoldingSetNode {
|
||||
|
||||
bool hasStackStorage() const;
|
||||
|
||||
bool hasParametersStorage() const;
|
||||
|
||||
bool hasGlobalsStorage() const;
|
||||
|
||||
bool hasGlobalsOrParametersStorage() const;
|
||||
|
||||
bool hasHeapStorage() const;
|
||||
|
||||
bool hasHeapOrStackStorage() const;
|
||||
|
||||
virtual void print(llvm::raw_ostream& os) const;
|
||||
virtual void print(llvm::raw_ostream& os) const;
|
||||
|
||||
void printStdErr() const;
|
||||
|
||||
Kind getKind() const { return kind; }
|
||||
|
||||
template<typename RegionTy> const RegionTy* getAs() const;
|
||||
|
||||
virtual bool isBoundable() const { return true; }
|
||||
virtual bool isBoundable() const { return false; }
|
||||
|
||||
static bool classof(const MemRegion*) { return true; }
|
||||
};
|
||||
@ -104,8 +111,6 @@ class MemSpaceRegion : public MemRegion {
|
||||
}
|
||||
|
||||
public:
|
||||
//RegionExtent getExtent() const { return UndefinedExtent(); }
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID& ID) const;
|
||||
|
||||
bool isBoundable() const { return false; }
|
||||
@ -315,6 +320,8 @@ class StringRegion : public TypedRegion {
|
||||
return Str->getType();
|
||||
}
|
||||
|
||||
bool isBoundable() const { return false; }
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID& ID) const {
|
||||
ProfileRegion(ID, Str, superRegion);
|
||||
}
|
||||
@ -384,7 +391,9 @@ class CompoundLiteralRegion : public TypedRegion {
|
||||
QualType getValueType(ASTContext& C) const {
|
||||
return C.getCanonicalType(CL->getType());
|
||||
}
|
||||
|
||||
|
||||
bool isBoundable() const { return !CL->isFileScope(); }
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID& ID) const;
|
||||
|
||||
void print(llvm::raw_ostream& os) const;
|
||||
@ -584,15 +593,17 @@ class MemRegionManager {
|
||||
llvm::BumpPtrAllocator& A;
|
||||
llvm::FoldingSet<MemRegion> Regions;
|
||||
|
||||
MemSpaceRegion* globals;
|
||||
MemSpaceRegion* stack;
|
||||
MemSpaceRegion* heap;
|
||||
MemSpaceRegion* unknown;
|
||||
MemSpaceRegion* code;
|
||||
MemSpaceRegion *globals;
|
||||
MemSpaceRegion *stack;
|
||||
MemSpaceRegion *stackArguments;
|
||||
MemSpaceRegion *heap;
|
||||
MemSpaceRegion *unknown;
|
||||
MemSpaceRegion *code;
|
||||
|
||||
public:
|
||||
MemRegionManager(ASTContext &c, llvm::BumpPtrAllocator& a)
|
||||
: C(c), A(a), globals(0), stack(0), heap(0), unknown(0), code(0) {}
|
||||
: C(c), A(a), globals(0), stack(0), stackArguments(0), heap(0),
|
||||
unknown(0), code(0) {}
|
||||
|
||||
~MemRegionManager() {}
|
||||
|
||||
@ -600,24 +611,28 @@ class MemRegionManager {
|
||||
|
||||
/// getStackRegion - Retrieve the memory region associated with the
|
||||
/// current stack frame.
|
||||
MemSpaceRegion* getStackRegion();
|
||||
MemSpaceRegion *getStackRegion();
|
||||
|
||||
/// getStackArgumentsRegion - Retrieve the memory region associated with
|
||||
/// function/method arguments of the current stack frame.
|
||||
MemSpaceRegion *getStackArgumentsRegion();
|
||||
|
||||
/// getGlobalsRegion - Retrieve the memory region associated with
|
||||
/// all global variables.
|
||||
MemSpaceRegion* getGlobalsRegion();
|
||||
MemSpaceRegion *getGlobalsRegion();
|
||||
|
||||
/// getHeapRegion - Retrieve the memory region associated with the
|
||||
/// generic "heap".
|
||||
MemSpaceRegion* getHeapRegion();
|
||||
MemSpaceRegion *getHeapRegion();
|
||||
|
||||
/// getUnknownRegion - Retrieve the memory region associated with unknown
|
||||
/// memory space.
|
||||
MemSpaceRegion* getUnknownRegion();
|
||||
MemSpaceRegion *getUnknownRegion();
|
||||
|
||||
MemSpaceRegion* getCodeRegion();
|
||||
MemSpaceRegion *getCodeRegion();
|
||||
|
||||
/// getAllocaRegion - Retrieve a region associated with a call to alloca().
|
||||
AllocaRegion* getAllocaRegion(const Expr* Ex, unsigned Cnt);
|
||||
AllocaRegion *getAllocaRegion(const Expr* Ex, unsigned Cnt);
|
||||
|
||||
/// getCompoundLiteralRegion - Retrieve the region associated with a
|
||||
/// given CompoundLiteral.
|
||||
@ -785,8 +800,12 @@ template <> struct MemRegionManagerTrait<VarRegion> {
|
||||
typedef MemRegion SuperRegionTy;
|
||||
static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr,
|
||||
const VarDecl *d) {
|
||||
return d->hasLocalStorage() ? MRMgr.getStackRegion()
|
||||
: MRMgr.getGlobalsRegion();
|
||||
if (d->hasLocalStorage()) {
|
||||
return isa<ParmVarDecl>(d) || isa<ImplicitParamDecl>(d)
|
||||
? MRMgr.getStackArgumentsRegion() : MRMgr.getStackRegion();
|
||||
}
|
||||
|
||||
return MRMgr.getGlobalsRegion();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -110,6 +110,8 @@ class SVal {
|
||||
/// getAsSymbolicExpression - If this Sval wraps a symbolic expression then
|
||||
/// return that expression. Otherwise return NULL.
|
||||
const SymExpr *getAsSymbolicExpression() const;
|
||||
|
||||
const MemRegion *getAsRegion() const;
|
||||
|
||||
void print(llvm::raw_ostream& OS) const;
|
||||
void printStdErr() const;
|
||||
|
@ -67,12 +67,17 @@ class ValueManager {
|
||||
const void* SymbolTag = 0) {
|
||||
return SymMgr.getConjuredSymbol(E, VisitCount, SymbolTag);
|
||||
}
|
||||
|
||||
|
||||
/// makeZeroVal - Construct an SVal representing '0' for the specified type.
|
||||
SVal makeZeroVal(QualType T);
|
||||
|
||||
/// GetRegionValueSymbolVal - make a unique symbol for value of R.
|
||||
SVal getRegionValueSymbolVal(const MemRegion* R, QualType T = QualType());
|
||||
/// getRegionValueSymbolVal - make a unique symbol for value of R.
|
||||
SVal getRegionValueSymbolVal(const MemRegion *R, QualType T = QualType());
|
||||
|
||||
SVal getRegionValueSymbolValOrUnknown(const MemRegion *R, QualType T) {
|
||||
return SymMgr.canSymbolicate(T) ? getRegionValueSymbolVal(R, T)
|
||||
: UnknownVal();
|
||||
}
|
||||
|
||||
SVal getConjuredSymbolVal(const Expr *E, unsigned Count);
|
||||
SVal getConjuredSymbolVal(const Expr* E, QualType T, unsigned Count);
|
||||
|
@ -45,6 +45,10 @@ def err_drv_no_linker_llvm_support : Error<
|
||||
"'%0': unable to pass LLVM bit-code files to linker">;
|
||||
def err_drv_clang_unsupported : Error<
|
||||
"the clang compiler does not support '%0'">;
|
||||
def err_drv_command_failed : Error<
|
||||
"%0 command failed with exit code %1 (use -v to see invocation)">;
|
||||
def err_drv_command_signalled : Error<
|
||||
"%0 command failed due to signal %1 (use -v to see invocation)">;
|
||||
|
||||
def warn_drv_input_file_unused : Warning<
|
||||
"%0: '%1' input unused when '%2' is present">;
|
||||
|
@ -287,6 +287,8 @@ def err_distant_exception_spec : Error<
|
||||
def err_incomplete_in_exception_spec : Error<
|
||||
"%select{|pointer to |reference to }1incomplete type %0 is not allowed "
|
||||
"in exception specification">;
|
||||
def err_mismatched_exception_spec : Error<
|
||||
"exception specification in declaration does not match previous declaration">;
|
||||
|
||||
// C++ access checking
|
||||
def err_class_redeclared_with_different_access : Error<
|
||||
@ -398,6 +400,10 @@ def err_init_reference_member_uninitialized : Error<
|
||||
def note_uninit_reference_member : Note<
|
||||
"uninitialized reference member is here">;
|
||||
|
||||
// C++0x decltype
|
||||
def err_cannot_determine_declared_type_of_overloaded_function : Error<
|
||||
"can't determine the declared type of an overloaded function">;
|
||||
|
||||
// C++0x auto
|
||||
def err_auto_variable_cannot_appear_in_own_initializer : Error<
|
||||
"variable %0 declared with 'auto' type cannot appear in its own initializer">;
|
||||
@ -835,6 +841,12 @@ def note_function_template_spec_here : Note<
|
||||
|
||||
def note_default_arg_instantiation_here : Note<
|
||||
"in instantiation of default argument for '%0' required here">;
|
||||
def note_explicit_template_arg_substitution_here : Note<
|
||||
"while substituting explicitly-specified template arguments into function "
|
||||
"template %f, here">;
|
||||
def note_function_template_deduction_instantiation_here : Note<
|
||||
"while substituting deduced template arguments into function template %0, "
|
||||
"here">;
|
||||
def note_partial_spec_deduct_instantiation_here : Note<
|
||||
"during template argument deduction for class template partial "
|
||||
"specialization %0, here">;
|
||||
@ -1070,6 +1082,8 @@ def err_array_star_outside_prototype : Error<
|
||||
"star modifier used outside of function prototype">;
|
||||
def err_illegal_decl_pointer_to_reference : Error<
|
||||
"'%0' declared as a pointer to a reference">;
|
||||
def err_illegal_decl_mempointer_to_reference : Error<
|
||||
"'%0' declared as a member pointer to a reference">;
|
||||
def err_illegal_decl_mempointer_to_void : Error<
|
||||
"'%0' declared as a member pointer to void">;
|
||||
def err_illegal_decl_mempointer_in_nonclass : Error<
|
||||
@ -1207,6 +1221,10 @@ def err_typecheck_sub_ptr_object : Error<
|
||||
"subtraction of pointer %0 requires pointee to be a complete object type">;
|
||||
def err_typecheck_sub_ptr_compatible : Error<
|
||||
"%0 and %1 are not pointers to compatible types">;
|
||||
def ext_typecheck_ordered_comparison_of_pointer_integer : ExtWarn<
|
||||
"ordered comparison between pointer and integer (%0 and %1)">;
|
||||
def ext_typecheck_ordered_comparison_of_function_pointers : ExtWarn<
|
||||
"ordered comparison of function pointers (%0 and %1)">;
|
||||
def ext_typecheck_comparison_of_pointer_integer : ExtWarn<
|
||||
"comparison between pointer and integer (%0 and %1)">;
|
||||
def ext_typecheck_comparison_of_distinct_pointers : ExtWarn<
|
||||
@ -1579,6 +1597,12 @@ def err_overload_multiple_match : Error<
|
||||
def err_only_constructors_take_base_inits : Error<
|
||||
"only constructors take base initializers">;
|
||||
|
||||
def error_multiple_mem_initialization : Error <
|
||||
"multiple initializations given for non-static member '%0'">;
|
||||
|
||||
def error_multiple_base_initialization : Error <
|
||||
"multiple initializations given for base %0">;
|
||||
|
||||
def err_mem_init_not_member_or_class : Error<
|
||||
"member initializer %0 does not name a non-static data member or base "
|
||||
"class">;
|
||||
@ -1588,6 +1612,8 @@ def err_base_init_does_not_name_class : Error<
|
||||
def err_base_init_direct_and_virtual : Error<
|
||||
"base class initializer %0 names both a direct base class and an "
|
||||
"inherited virtual base class">;
|
||||
def err_not_direct_base_or_virtual : Error<
|
||||
"type %0 is not a direct or virtual base of '%1'">;
|
||||
|
||||
def err_in_class_initializer_non_integral_type : Error<
|
||||
"in-class initializer has non-integral, non-enumeration type %0">;
|
||||
|
@ -22,6 +22,7 @@ class LangOptions {
|
||||
public:
|
||||
unsigned Trigraphs : 1; // Trigraphs in source files.
|
||||
unsigned BCPLComment : 1; // BCPL-style '//' comments.
|
||||
unsigned Bool : 1; // 'bool', 'true', 'false' keywords.
|
||||
unsigned DollarIdents : 1; // '$' allowed in identifiers.
|
||||
unsigned AsmPreprocessor : 1; // Preprocessor in asm mode.
|
||||
unsigned GNUMode : 1; // True in gnu99 mode false in c99 mode (etc)
|
||||
@ -84,12 +85,16 @@ class LangOptions {
|
||||
|
||||
unsigned OpenCL : 1; // OpenCL C99 language extensions.
|
||||
|
||||
|
||||
private:
|
||||
unsigned GC : 2; // Objective-C Garbage Collection modes. We declare
|
||||
// this enum as unsigned because MSVC insists on making enums
|
||||
// signed. Set/Query this value using accessors.
|
||||
unsigned GC : 2; // Objective-C Garbage Collection modes. We
|
||||
// declare this enum as unsigned because MSVC
|
||||
// insists on making enums signed. Set/Query
|
||||
// this value using accessors.
|
||||
unsigned SymbolVisibility : 3; // Symbol's visibility.
|
||||
unsigned StackProtector : 2; // Whether stack protectors are on. We declare
|
||||
// this enum as unsigned because MSVC insists
|
||||
// on making enums signed. Set/Query this
|
||||
// value using accessors.
|
||||
|
||||
/// The user provided name for the "main file", if non-null. This is
|
||||
/// useful in situations where the input file name does not match
|
||||
@ -100,6 +105,7 @@ class LangOptions {
|
||||
unsigned InstantiationDepth; // Maximum template instantiation depth.
|
||||
|
||||
enum GCMode { NonGC, GCOnly, HybridGC };
|
||||
enum StackProtectorMode { SSPOff, SSPOn, SSPReq };
|
||||
enum VisibilityMode {
|
||||
Default,
|
||||
Protected,
|
||||
@ -107,7 +113,7 @@ class LangOptions {
|
||||
};
|
||||
|
||||
LangOptions() {
|
||||
Trigraphs = BCPLComment = DollarIdents = AsmPreprocessor = 0;
|
||||
Trigraphs = BCPLComment = Bool = DollarIdents = AsmPreprocessor = 0;
|
||||
GNUMode = ImplicitInt = Digraphs = 0;
|
||||
HexFloats = 0;
|
||||
GC = ObjC1 = ObjC2 = ObjCNonFragileABI = 0;
|
||||
@ -116,7 +122,7 @@ class LangOptions {
|
||||
Exceptions = NeXTRuntime = Freestanding = NoBuiltin = 0;
|
||||
LaxVectorConversions = 1;
|
||||
HeinousExtensions = 0;
|
||||
AltiVec = OpenCL = 0;
|
||||
AltiVec = OpenCL = StackProtector = 0;
|
||||
|
||||
SymbolVisibility = (unsigned) Default;
|
||||
|
||||
@ -152,6 +158,13 @@ class LangOptions {
|
||||
GCMode getGCMode() const { return (GCMode) GC; }
|
||||
void setGCMode(GCMode m) { GC = (unsigned) m; }
|
||||
|
||||
StackProtectorMode getStackProtectorMode() const {
|
||||
return static_cast<StackProtectorMode>(StackProtector);
|
||||
}
|
||||
void setStackProtectorMode(StackProtectorMode m) {
|
||||
StackProtector = static_cast<unsigned>(m);
|
||||
}
|
||||
|
||||
const char *getMainFileName() const { return MainFileName; }
|
||||
void setMainFileName(const char *Name) { MainFileName = Name; }
|
||||
|
||||
|
@ -76,7 +76,8 @@ class TargetInfo {
|
||||
UnsignedLongLong
|
||||
};
|
||||
protected:
|
||||
IntType SizeType, IntMaxType, UIntMaxType, PtrDiffType, IntPtrType, WCharType;
|
||||
IntType SizeType, IntMaxType, UIntMaxType, PtrDiffType, IntPtrType, WCharType,
|
||||
Int64Type;
|
||||
public:
|
||||
IntType getSizeType() const { return SizeType; }
|
||||
IntType getIntMaxType() const { return IntMaxType; }
|
||||
@ -86,6 +87,7 @@ class TargetInfo {
|
||||
}
|
||||
IntType getIntPtrType() const { return IntPtrType; }
|
||||
IntType getWCharType() const { return WCharType; }
|
||||
IntType getInt64Type() const { return Int64Type; }
|
||||
|
||||
/// getPointerWidth - Return the width of pointers on this target, for the
|
||||
/// specified address space.
|
||||
|
@ -224,7 +224,7 @@ KEYWORD(__func__ , KEYALL)
|
||||
|
||||
// C++ 2.11p1: Keywords.
|
||||
KEYWORD(asm , KEYCXX|KEYGNU)
|
||||
KEYWORD(bool , KEYCXX|BOOLSUPPORT)
|
||||
KEYWORD(bool , BOOLSUPPORT)
|
||||
KEYWORD(catch , KEYCXX)
|
||||
KEYWORD(class , KEYCXX)
|
||||
KEYWORD(const_cast , KEYCXX)
|
||||
@ -232,7 +232,7 @@ KEYWORD(delete , KEYCXX)
|
||||
KEYWORD(dynamic_cast , KEYCXX)
|
||||
KEYWORD(explicit , KEYCXX)
|
||||
KEYWORD(export , KEYCXX)
|
||||
KEYWORD(false , KEYCXX|BOOLSUPPORT)
|
||||
KEYWORD(false , BOOLSUPPORT)
|
||||
KEYWORD(friend , KEYCXX)
|
||||
KEYWORD(mutable , KEYCXX)
|
||||
KEYWORD(namespace , KEYCXX)
|
||||
@ -246,7 +246,7 @@ KEYWORD(static_cast , KEYCXX)
|
||||
KEYWORD(template , KEYCXX)
|
||||
KEYWORD(this , KEYCXX)
|
||||
KEYWORD(throw , KEYCXX)
|
||||
KEYWORD(true , KEYCXX|BOOLSUPPORT)
|
||||
KEYWORD(true , BOOLSUPPORT)
|
||||
KEYWORD(try , KEYCXX)
|
||||
KEYWORD(typename , KEYCXX)
|
||||
KEYWORD(typeid , KEYCXX)
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <string>
|
||||
|
||||
namespace llvm {
|
||||
class LLVMContext;
|
||||
class Module;
|
||||
}
|
||||
|
||||
@ -34,7 +35,8 @@ namespace clang {
|
||||
|
||||
CodeGenerator *CreateLLVMCodeGen(Diagnostic &Diags,
|
||||
const std::string &ModuleName,
|
||||
const CompileOptions &CO);
|
||||
const CompileOptions &CO,
|
||||
llvm::LLVMContext& C);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -75,6 +75,8 @@ class Action {
|
||||
public:
|
||||
virtual ~Action();
|
||||
|
||||
const char *getClassName() const { return Action::getClassName(getKind()); }
|
||||
|
||||
ActionClass getKind() const { return Kind; }
|
||||
types::ID getType() const { return Type; }
|
||||
|
||||
|
@ -83,6 +83,8 @@ namespace driver {
|
||||
/// \arg Claim Whether the argument should be claimed, if it exists.
|
||||
Arg *getLastArg(options::ID Id, bool Claim=true) const;
|
||||
Arg *getLastArg(options::ID Id0, options::ID Id1, bool Claim=true) const;
|
||||
Arg *getLastArg(options::ID Id0, options::ID Id1, options::ID Id2,
|
||||
bool Claim=true) const;
|
||||
|
||||
/// getArgString - Return the input argument string at \arg Index.
|
||||
virtual const char *getArgString(unsigned Index) const = 0;
|
||||
|
@ -32,10 +32,10 @@ namespace driver {
|
||||
/// invocation.
|
||||
class Compilation {
|
||||
/// The driver we were created by.
|
||||
Driver &TheDriver;
|
||||
const Driver &TheDriver;
|
||||
|
||||
/// The default tool chain.
|
||||
ToolChain &DefaultToolChain;
|
||||
const ToolChain &DefaultToolChain;
|
||||
|
||||
/// The original (untranslated) input argument list.
|
||||
InputArgList *Args;
|
||||
@ -56,7 +56,8 @@ class Compilation {
|
||||
ArgStringList ResultFiles;
|
||||
|
||||
public:
|
||||
Compilation(Driver &D, ToolChain &DefaultToolChain, InputArgList *Args);
|
||||
Compilation(const Driver &D, const ToolChain &DefaultToolChain,
|
||||
InputArgList *Args);
|
||||
~Compilation();
|
||||
|
||||
const Driver &getDriver() const { return TheDriver; }
|
||||
@ -69,6 +70,11 @@ class Compilation {
|
||||
const ActionList &getActions() const { return Actions; }
|
||||
|
||||
JobList &getJobs() { return Jobs; }
|
||||
const JobList &getJobs() const { return Jobs; }
|
||||
|
||||
const ArgStringList &getTempFiles() const { return TempFiles; }
|
||||
|
||||
const ArgStringList &getResultFiles() const { return ResultFiles; }
|
||||
|
||||
/// getArgsForToolChain - Return the derived argument list for the
|
||||
/// tool chain \arg TC (or the default tool chain, if TC is not
|
||||
@ -89,11 +95,6 @@ class Compilation {
|
||||
return Name;
|
||||
}
|
||||
|
||||
/// Execute - Execute the compilation jobs and return an
|
||||
/// appropriate exit code.
|
||||
int Execute() const;
|
||||
|
||||
private:
|
||||
/// CleanupFileList - Remove the files in the given list.
|
||||
///
|
||||
/// \param IssueErrors - Report failures as errors.
|
||||
@ -103,22 +104,26 @@ class Compilation {
|
||||
|
||||
/// PrintJob - Print one job in -### format.
|
||||
///
|
||||
/// OS - The stream to print on.
|
||||
/// J - The job to print.
|
||||
/// Terminator - A string to print at the end of the line.
|
||||
/// Quote - Should separate arguments be quoted.
|
||||
/// \param OS - The stream to print on.
|
||||
/// \param J - The job to print.
|
||||
/// \param Terminator - A string to print at the end of the line.
|
||||
/// \param Quote - Should separate arguments be quoted.
|
||||
void PrintJob(llvm::raw_ostream &OS, const Job &J,
|
||||
const char *Terminator, bool Quote) const;
|
||||
|
||||
/// ExecuteCommand - Execute an actual command.
|
||||
///
|
||||
/// \param FailingCommand - For non-zero results, this will be set to the
|
||||
/// Command which failed, if any.
|
||||
/// \return The result code of the subprocess.
|
||||
int ExecuteCommand(const Command &C) const;
|
||||
int ExecuteCommand(const Command &C, const Command *&FailingCommand) const;
|
||||
|
||||
/// ExecuteJob - Execute a single job.
|
||||
///
|
||||
/// \param FailingCommand - For non-zero results, this will be set to the
|
||||
/// Command which failed.
|
||||
/// \return The accumulated result code of the job.
|
||||
int ExecuteJob(const Job &J) const;
|
||||
int ExecuteJob(const Job &J, const Command *&FailingCommand) const;
|
||||
};
|
||||
|
||||
} // end namespace driver
|
||||
|
@ -161,6 +161,14 @@ class Driver {
|
||||
/// \arg C - The compilation that is being built.
|
||||
void BuildJobs(Compilation &C) const;
|
||||
|
||||
/// ExecuteCompilation - Execute the compilation according to the command line
|
||||
/// arguments and return an appropriate exit code.
|
||||
///
|
||||
/// This routine handles additional processing that must be done in addition
|
||||
/// to just running the subprocesses, for example reporting errors, removing
|
||||
/// temporary files, etc.
|
||||
int ExecuteCompilation(const Compilation &C) const;
|
||||
|
||||
/// @}
|
||||
/// @name Helper Methods
|
||||
/// @{
|
||||
|
@ -69,6 +69,8 @@ class HostInfo {
|
||||
|
||||
const HostInfo *createDarwinHostInfo(const Driver &D,
|
||||
const llvm::Triple& Triple);
|
||||
const HostInfo *createOpenBSDHostInfo(const Driver &D,
|
||||
const llvm::Triple& Triple);
|
||||
const HostInfo *createFreeBSDHostInfo(const Driver &D,
|
||||
const llvm::Triple& Triple);
|
||||
const HostInfo *createDragonFlyHostInfo(const Driver &D,
|
||||
|
@ -52,6 +52,9 @@ class Job {
|
||||
/// Command - An executable path/name and argument vector to
|
||||
/// execute.
|
||||
class Command : public Job {
|
||||
/// Source - The action which caused the creation of this job.
|
||||
const Action &Source;
|
||||
|
||||
/// The executable to run.
|
||||
const char *Executable;
|
||||
|
||||
@ -60,9 +63,14 @@ class Command : public Job {
|
||||
ArgStringList Arguments;
|
||||
|
||||
public:
|
||||
Command(const char *_Executable, const ArgStringList &_Arguments);
|
||||
Command(const Action &_Source, const char *_Executable,
|
||||
const ArgStringList &_Arguments);
|
||||
|
||||
/// getSource - Return the Action which caused the creation of this job.
|
||||
const Action &getSource() const { return Source; }
|
||||
|
||||
const char *getExecutable() const { return Executable; }
|
||||
|
||||
const ArgStringList &getArguments() const { return Arguments; }
|
||||
|
||||
static bool classof(const Job *J) {
|
||||
|
@ -420,7 +420,7 @@ OPTION("-fno-math-errno", fno_math_errno, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fno-pascal-strings", fno_pascal_strings, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fno-show-column", fno_show_column, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fno-show-source-location", fno_show_source_location, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fno-stack-protector", fno_stack_protector, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fno-stack-protector", fno_stack_protector, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fno-strict-aliasing", fno_strict_aliasing, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fno-unit-at-a-time", fno_unit_at_a_time, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fno-unwind-tables", fno_unwind_tables, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
@ -450,7 +450,8 @@ OPTION("-framework", framework, Separate, INVALID, INVALID, "l", 0, 0, 0)
|
||||
OPTION("-fshow-source-location", fshow_source_location, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fsigned-bitfields", fsigned_bitfields, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fsigned-char", fsigned_char, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fstack-protector", fstack_protector, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fstack-protector-all", fstack_protector_all, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fstack-protector", fstack_protector, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fstrict-aliasing", fstrict_aliasing, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fsyntax-only", fsyntax_only, Flag, INVALID, INVALID, "d", 0, 0, 0)
|
||||
OPTION("-ftemplate-depth-", ftemplate_depth_, Joined, f_Group, INVALID, "", 0, 0, 0)
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
namespace llvm {
|
||||
class Module;
|
||||
class LLVMContext;
|
||||
namespace sys { class Path; }
|
||||
}
|
||||
namespace clang {
|
||||
@ -79,7 +80,8 @@ ASTConsumer *CreateBackendConsumer(BackendAction Action,
|
||||
const LangOptions &Features,
|
||||
const CompileOptions &CompileOpts,
|
||||
const std::string &ModuleID,
|
||||
llvm::raw_ostream *OS);
|
||||
llvm::raw_ostream *OS,
|
||||
llvm::LLVMContext& C);
|
||||
|
||||
// HTML printer: uses the rewriter to convert source code to HTML with
|
||||
// syntax highlighting suitable for viewing in a web-browser.
|
||||
|
@ -218,7 +218,11 @@ namespace clang {
|
||||
|
||||
/// \brief Record code for the original file that was used to
|
||||
/// generate the precompiled header.
|
||||
ORIGINAL_FILE_NAME = 20
|
||||
ORIGINAL_FILE_NAME = 20,
|
||||
|
||||
/// \brief Record code for the sorted array of source ranges where
|
||||
/// comments were encountered in the source code.
|
||||
COMMENT_RANGES = 21
|
||||
};
|
||||
|
||||
/// \brief Record types used within a source manager block.
|
||||
|
@ -279,6 +279,12 @@ class PCHReader
|
||||
/// been loaded.
|
||||
llvm::SmallVector<Selector, 16> SelectorsLoaded;
|
||||
|
||||
/// \brief A sorted array of source ranges containing comments.
|
||||
SourceRange *Comments;
|
||||
|
||||
/// \brief The number of source ranges in the Comments array.
|
||||
unsigned NumComments;
|
||||
|
||||
/// \brief The set of external definitions stored in the the PCH
|
||||
/// file.
|
||||
llvm::SmallVector<uint64_t, 16> ExternalDefinitions;
|
||||
@ -452,6 +458,14 @@ class PCHReader
|
||||
/// build prior to including the precompiled header.
|
||||
const std::string &getSuggestedPredefines() { return SuggestedPredefines; }
|
||||
|
||||
/// \brief Reads the source ranges that correspond to comments from
|
||||
/// an external AST source.
|
||||
///
|
||||
/// \param Comments the contents of this vector will be
|
||||
/// replaced with the sorted set of source ranges corresponding to
|
||||
/// comments in the source code.
|
||||
virtual void ReadComments(std::vector<SourceRange> &Comments);
|
||||
|
||||
/// \brief Resolve a type ID into a type, potentially building a new
|
||||
/// type.
|
||||
virtual QualType GetType(pch::TypeID ID);
|
||||
|
@ -166,6 +166,7 @@ class PCHWriter {
|
||||
void WriteSourceManagerBlock(SourceManager &SourceMgr,
|
||||
const Preprocessor &PP);
|
||||
void WritePreprocessor(const Preprocessor &PP);
|
||||
void WriteComments(ASTContext &Context);
|
||||
void WriteType(const Type *T);
|
||||
void WriteTypesBlock(ASTContext &Context);
|
||||
uint64_t WriteDeclContextLexicalBlock(ASTContext &Context, DeclContext *DC);
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include <vector>
|
||||
|
||||
namespace clang {
|
||||
|
||||
@ -35,6 +36,7 @@ class FileEntry;
|
||||
class HeaderSearch;
|
||||
class PragmaNamespace;
|
||||
class PragmaHandler;
|
||||
class CommentHandler;
|
||||
class ScratchBuffer;
|
||||
class TargetInfo;
|
||||
class PPCallbacks;
|
||||
@ -109,6 +111,10 @@ class Preprocessor {
|
||||
/// with this preprocessor.
|
||||
PragmaNamespace *PragmaHandlers;
|
||||
|
||||
/// \brief Tracks all of the comment handlers that the client registered
|
||||
/// with this preprocessor.
|
||||
std::vector<CommentHandler *> CommentHandlers;
|
||||
|
||||
/// CurLexer - This is the current top of the stack that we're lexing from if
|
||||
/// not expanding a macro and we are lexing directly from source code.
|
||||
/// Only one of CurLexer, CurPTHLexer, or CurTokenLexer will be non-null.
|
||||
@ -301,6 +307,14 @@ class Preprocessor {
|
||||
/// to remove a handler that has not been registered.
|
||||
void RemovePragmaHandler(const char *Namespace, PragmaHandler *Handler);
|
||||
|
||||
/// \brief Add the specified comment handler to the preprocessor.
|
||||
void AddCommentHandler(CommentHandler *Handler);
|
||||
|
||||
/// \brief Remove the specified comment handler.
|
||||
///
|
||||
/// It is an error to remove a handler that has not been registered.
|
||||
void RemoveCommentHandler(CommentHandler *Handler);
|
||||
|
||||
/// EnterMainSourceFile - Enter the specified FileID as the main source file,
|
||||
/// which implicitly adds the builtin defines etc.
|
||||
void EnterMainSourceFile();
|
||||
@ -791,6 +805,7 @@ class Preprocessor {
|
||||
void HandlePragmaSystemHeader(Token &SysHeaderTok);
|
||||
void HandlePragmaDependency(Token &DependencyTok);
|
||||
void HandlePragmaComment(Token &CommentTok);
|
||||
void HandleComment(SourceRange Comment);
|
||||
};
|
||||
|
||||
/// PreprocessorFactory - A generic factory interface for lazily creating
|
||||
@ -801,6 +816,15 @@ class PreprocessorFactory {
|
||||
virtual Preprocessor* CreatePreprocessor() = 0;
|
||||
};
|
||||
|
||||
/// \brief Abstract base class that describes a handler that will receive
|
||||
/// source ranges for each of the comments encountered in the source file.
|
||||
class CommentHandler {
|
||||
public:
|
||||
virtual ~CommentHandler();
|
||||
|
||||
virtual void HandleComment(Preprocessor &PP, SourceRange Comment) = 0;
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
||||
|
@ -152,6 +152,10 @@ class Action : public ActionBase {
|
||||
/// an empty string if not. This is used for pretty crash reporting.
|
||||
virtual std::string getDeclName(DeclPtrTy D) { return ""; }
|
||||
|
||||
/// \brief Invoked for each comment in the source code, providing the source
|
||||
/// range that contains the comment.
|
||||
virtual void ActOnComment(SourceRange Comment) { }
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Declaration Tracking Callbacks.
|
||||
//===--------------------------------------------------------------------===//
|
||||
@ -1203,7 +1207,9 @@ class Action : public ActionBase {
|
||||
|
||||
virtual MemInitResult ActOnMemInitializer(DeclPtrTy ConstructorDecl,
|
||||
Scope *S,
|
||||
const CXXScopeSpec &SS,
|
||||
IdentifierInfo *MemberOrBase,
|
||||
TypeTy *TemplateTypeTy,
|
||||
SourceLocation IdLoc,
|
||||
SourceLocation LParenLoc,
|
||||
ExprTy **Args, unsigned NumArgs,
|
||||
@ -1379,6 +1385,24 @@ class Action : public ActionBase {
|
||||
return TypeResult();
|
||||
};
|
||||
|
||||
/// \brief Form a reference to a template-id (that will refer to a function)
|
||||
/// from a template and a list of template arguments.
|
||||
///
|
||||
/// This action forms an expression that references the given template-id,
|
||||
/// possibly checking well-formedness of the template arguments. It does not
|
||||
/// imply the declaration of any entity.
|
||||
///
|
||||
/// \param Template A template whose specialization results in a
|
||||
/// function or a dependent template.
|
||||
virtual OwningExprResult ActOnTemplateIdExpr(TemplateTy Template,
|
||||
SourceLocation TemplateNameLoc,
|
||||
SourceLocation LAngleLoc,
|
||||
ASTTemplateArgsPtr TemplateArgs,
|
||||
SourceLocation *TemplateArgLocs,
|
||||
SourceLocation RAngleLoc) {
|
||||
return ExprError();
|
||||
}
|
||||
|
||||
/// \brief Form a dependent template name.
|
||||
///
|
||||
/// This action forms a dependent template name given the template
|
||||
|
@ -574,6 +574,19 @@ namespace clang {
|
||||
#if !defined(DISABLE_SMART_POINTERS)
|
||||
friend class moving::ASTMultiMover<Destroyer>;
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
// Last tested with Visual Studio 2008.
|
||||
// Visual C++ appears to have a bug where it does not recognise
|
||||
// the return value from ASTMultiMover<Destroyer>::opeator-> as
|
||||
// being a pointer to ASTMultiPtr. However, the diagnostics
|
||||
// suggest it has the right name, simply that the pointer type
|
||||
// is not convertible to itself.
|
||||
// Either way, a classic C-style hard cast resolves any issue.
|
||||
static ASTMultiPtr* hack(moving::ASTMultiMover<Destroyer> & source) {
|
||||
return (ASTMultiPtr*)source.operator->();
|
||||
}
|
||||
#endif
|
||||
|
||||
ASTMultiPtr(ASTMultiPtr&); // DO NOT IMPLEMENT
|
||||
// Reference member prevents copy assignment.
|
||||
|
||||
@ -594,7 +607,13 @@ namespace clang {
|
||||
: Actions(actions), Nodes(nodes), Count(count) {}
|
||||
/// Move constructor
|
||||
ASTMultiPtr(moving::ASTMultiMover<Destroyer> mover)
|
||||
#if defined(_MSC_VER)
|
||||
// Apply the visual C++ hack supplied above.
|
||||
// Last tested with Visual Studio 2008.
|
||||
: Actions(hack(mover)->Actions), Nodes(hack(mover)->Nodes), Count(hack(mover)->Count) {
|
||||
#else
|
||||
: Actions(mover->Actions), Nodes(mover->Nodes), Count(mover->Count) {
|
||||
#endif
|
||||
mover.release();
|
||||
}
|
||||
#else
|
||||
|
@ -82,7 +82,8 @@ class Parser {
|
||||
llvm::OwningPtr<PragmaHandler> PackHandler;
|
||||
llvm::OwningPtr<PragmaHandler> UnusedHandler;
|
||||
llvm::OwningPtr<PragmaHandler> WeakHandler;
|
||||
|
||||
llvm::OwningPtr<clang::CommentHandler> CommentHandler;
|
||||
|
||||
/// Whether the '>' token acts as an operator or not. This will be
|
||||
/// true except when we are parsing an expression within a C++
|
||||
/// template argument list, where the '>' closes the template
|
||||
|
@ -37,12 +37,12 @@ ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM,
|
||||
bool FreeMem, unsigned size_reserve) :
|
||||
GlobalNestedNameSpecifier(0), CFConstantStringTypeDecl(0),
|
||||
ObjCFastEnumerationStateTypeDecl(0), SourceMgr(SM), LangOpts(LOpts),
|
||||
FreeMemory(FreeMem), Target(t), Idents(idents), Selectors(sels),
|
||||
BuiltinInfo(builtins), ExternalSource(0) {
|
||||
LoadedExternalComments(false), FreeMemory(FreeMem), Target(t),
|
||||
Idents(idents), Selectors(sels),
|
||||
BuiltinInfo(builtins), ExternalSource(0), PrintingPolicy(LOpts) {
|
||||
if (size_reserve > 0) Types.reserve(size_reserve);
|
||||
InitBuiltinTypes();
|
||||
TUDecl = TranslationUnitDecl::Create(*this);
|
||||
PrintingPolicy.CPlusPlus = LangOpts.CPlusPlus;
|
||||
}
|
||||
|
||||
ASTContext::~ASTContext() {
|
||||
@ -203,6 +203,207 @@ void ASTContext::InitBuiltinTypes() {
|
||||
InitBuiltinType(NullPtrTy, BuiltinType::NullPtr);
|
||||
}
|
||||
|
||||
namespace {
|
||||
class BeforeInTranslationUnit
|
||||
: std::binary_function<SourceRange, SourceRange, bool> {
|
||||
SourceManager *SourceMgr;
|
||||
|
||||
public:
|
||||
explicit BeforeInTranslationUnit(SourceManager *SM) : SourceMgr(SM) { }
|
||||
|
||||
bool operator()(SourceRange X, SourceRange Y) {
|
||||
return SourceMgr->isBeforeInTranslationUnit(X.getBegin(), Y.getBegin());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// \brief Determine whether the given comment is a Doxygen-style comment.
|
||||
///
|
||||
/// \param Start the start of the comment text.
|
||||
///
|
||||
/// \param End the end of the comment text.
|
||||
///
|
||||
/// \param Member whether we want to check whether this is a member comment
|
||||
/// (which requires a < after the Doxygen-comment delimiter). Otherwise,
|
||||
/// we only return true when we find a non-member comment.
|
||||
static bool
|
||||
isDoxygenComment(SourceManager &SourceMgr, SourceRange Comment,
|
||||
bool Member = false) {
|
||||
const char *BufferStart
|
||||
= SourceMgr.getBufferData(SourceMgr.getFileID(Comment.getBegin())).first;
|
||||
const char *Start = BufferStart + SourceMgr.getFileOffset(Comment.getBegin());
|
||||
const char* End = BufferStart + SourceMgr.getFileOffset(Comment.getEnd());
|
||||
|
||||
if (End - Start < 4)
|
||||
return false;
|
||||
|
||||
assert(Start[0] == '/' && "Not a comment?");
|
||||
if (Start[1] == '*' && !(Start[2] == '!' || Start[2] == '*'))
|
||||
return false;
|
||||
if (Start[1] == '/' && !(Start[2] == '!' || Start[2] == '/'))
|
||||
return false;
|
||||
|
||||
return (Start[3] == '<') == Member;
|
||||
}
|
||||
|
||||
/// \brief Retrieve the comment associated with the given declaration, if
|
||||
/// it has one.
|
||||
const char *ASTContext::getCommentForDecl(const Decl *D) {
|
||||
if (!D)
|
||||
return 0;
|
||||
|
||||
// Check whether we have cached a comment string for this declaration
|
||||
// already.
|
||||
llvm::DenseMap<const Decl *, std::string>::iterator Pos
|
||||
= DeclComments.find(D);
|
||||
if (Pos != DeclComments.end())
|
||||
return Pos->second.c_str();
|
||||
|
||||
// If we have an external AST source and have not yet loaded comments from
|
||||
// that source, do so now.
|
||||
if (ExternalSource && !LoadedExternalComments) {
|
||||
std::vector<SourceRange> LoadedComments;
|
||||
ExternalSource->ReadComments(LoadedComments);
|
||||
|
||||
if (!LoadedComments.empty())
|
||||
Comments.insert(Comments.begin(), LoadedComments.begin(),
|
||||
LoadedComments.end());
|
||||
|
||||
LoadedExternalComments = true;
|
||||
}
|
||||
|
||||
// If there are no comments anywhere, we won't find anything.
|
||||
if (Comments.empty())
|
||||
return 0;
|
||||
|
||||
// If the declaration doesn't map directly to a location in a file, we
|
||||
// can't find the comment.
|
||||
SourceLocation DeclStartLoc = D->getLocStart();
|
||||
if (DeclStartLoc.isInvalid() || !DeclStartLoc.isFileID())
|
||||
return 0;
|
||||
|
||||
// Find the comment that occurs just before this declaration.
|
||||
std::vector<SourceRange>::iterator LastComment
|
||||
= std::lower_bound(Comments.begin(), Comments.end(),
|
||||
SourceRange(DeclStartLoc),
|
||||
BeforeInTranslationUnit(&SourceMgr));
|
||||
|
||||
// Decompose the location for the start of the declaration and find the
|
||||
// beginning of the file buffer.
|
||||
std::pair<FileID, unsigned> DeclStartDecomp
|
||||
= SourceMgr.getDecomposedLoc(DeclStartLoc);
|
||||
const char *FileBufferStart
|
||||
= SourceMgr.getBufferData(DeclStartDecomp.first).first;
|
||||
|
||||
// First check whether we have a comment for a member.
|
||||
if (LastComment != Comments.end() &&
|
||||
!isa<TagDecl>(D) && !isa<NamespaceDecl>(D) &&
|
||||
isDoxygenComment(SourceMgr, *LastComment, true)) {
|
||||
std::pair<FileID, unsigned> LastCommentEndDecomp
|
||||
= SourceMgr.getDecomposedLoc(LastComment->getEnd());
|
||||
if (DeclStartDecomp.first == LastCommentEndDecomp.first &&
|
||||
SourceMgr.getLineNumber(DeclStartDecomp.first, DeclStartDecomp.second)
|
||||
== SourceMgr.getLineNumber(LastCommentEndDecomp.first,
|
||||
LastCommentEndDecomp.second)) {
|
||||
// The Doxygen member comment comes after the declaration starts and
|
||||
// is on the same line and in the same file as the declaration. This
|
||||
// is the comment we want.
|
||||
std::string &Result = DeclComments[D];
|
||||
Result.append(FileBufferStart +
|
||||
SourceMgr.getFileOffset(LastComment->getBegin()),
|
||||
FileBufferStart + LastCommentEndDecomp.second + 1);
|
||||
return Result.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
if (LastComment == Comments.begin())
|
||||
return 0;
|
||||
--LastComment;
|
||||
|
||||
// Decompose the end of the comment.
|
||||
std::pair<FileID, unsigned> LastCommentEndDecomp
|
||||
= SourceMgr.getDecomposedLoc(LastComment->getEnd());
|
||||
|
||||
// If the comment and the declaration aren't in the same file, then they
|
||||
// aren't related.
|
||||
if (DeclStartDecomp.first != LastCommentEndDecomp.first)
|
||||
return 0;
|
||||
|
||||
// Check that we actually have a Doxygen comment.
|
||||
if (!isDoxygenComment(SourceMgr, *LastComment))
|
||||
return 0;
|
||||
|
||||
// Compute the starting line for the declaration and for the end of the
|
||||
// comment (this is expensive).
|
||||
unsigned DeclStartLine
|
||||
= SourceMgr.getLineNumber(DeclStartDecomp.first, DeclStartDecomp.second);
|
||||
unsigned CommentEndLine
|
||||
= SourceMgr.getLineNumber(LastCommentEndDecomp.first,
|
||||
LastCommentEndDecomp.second);
|
||||
|
||||
// If the comment does not end on the line prior to the declaration, then
|
||||
// the comment is not associated with the declaration at all.
|
||||
if (CommentEndLine + 1 != DeclStartLine)
|
||||
return 0;
|
||||
|
||||
// We have a comment, but there may be more comments on the previous lines.
|
||||
// Keep looking so long as the comments are still Doxygen comments and are
|
||||
// still adjacent.
|
||||
unsigned ExpectedLine
|
||||
= SourceMgr.getSpellingLineNumber(LastComment->getBegin()) - 1;
|
||||
std::vector<SourceRange>::iterator FirstComment = LastComment;
|
||||
while (FirstComment != Comments.begin()) {
|
||||
// Look at the previous comment
|
||||
--FirstComment;
|
||||
std::pair<FileID, unsigned> Decomp
|
||||
= SourceMgr.getDecomposedLoc(FirstComment->getEnd());
|
||||
|
||||
// If this previous comment is in a different file, we're done.
|
||||
if (Decomp.first != DeclStartDecomp.first) {
|
||||
++FirstComment;
|
||||
break;
|
||||
}
|
||||
|
||||
// If this comment is not a Doxygen comment, we're done.
|
||||
if (!isDoxygenComment(SourceMgr, *FirstComment)) {
|
||||
++FirstComment;
|
||||
break;
|
||||
}
|
||||
|
||||
// If the line number is not what we expected, we're done.
|
||||
unsigned Line = SourceMgr.getLineNumber(Decomp.first, Decomp.second);
|
||||
if (Line != ExpectedLine) {
|
||||
++FirstComment;
|
||||
break;
|
||||
}
|
||||
|
||||
// Set the next expected line number.
|
||||
ExpectedLine
|
||||
= SourceMgr.getSpellingLineNumber(FirstComment->getBegin()) - 1;
|
||||
}
|
||||
|
||||
// The iterator range [FirstComment, LastComment] contains all of the
|
||||
// BCPL comments that, together, are associated with this declaration.
|
||||
// Form a single comment block string for this declaration that concatenates
|
||||
// all of these comments.
|
||||
std::string &Result = DeclComments[D];
|
||||
while (FirstComment != LastComment) {
|
||||
std::pair<FileID, unsigned> DecompStart
|
||||
= SourceMgr.getDecomposedLoc(FirstComment->getBegin());
|
||||
std::pair<FileID, unsigned> DecompEnd
|
||||
= SourceMgr.getDecomposedLoc(FirstComment->getEnd());
|
||||
Result.append(FileBufferStart + DecompStart.second,
|
||||
FileBufferStart + DecompEnd.second + 1);
|
||||
++FirstComment;
|
||||
}
|
||||
|
||||
// Append the last comment line.
|
||||
Result.append(FileBufferStart +
|
||||
SourceMgr.getFileOffset(LastComment->getBegin()),
|
||||
FileBufferStart + LastCommentEndDecomp.second + 1);
|
||||
return Result.c_str();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Type Sizing and Analysis
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -226,7 +427,7 @@ const llvm::fltSemantics &ASTContext::getFloatTypeSemantics(QualType T) const {
|
||||
unsigned ASTContext::getDeclAlignInBytes(const Decl *D) {
|
||||
unsigned Align = Target.getCharWidth();
|
||||
|
||||
if (const AlignedAttr* AA = D->getAttr<AlignedAttr>(*this))
|
||||
if (const AlignedAttr* AA = D->getAttr<AlignedAttr>())
|
||||
Align = std::max(Align, AA->getAlignment());
|
||||
|
||||
if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
|
||||
@ -449,7 +650,7 @@ ASTContext::getTypeInfo(const Type *T) {
|
||||
|
||||
case Type::Typedef: {
|
||||
const TypedefDecl *Typedef = cast<TypedefType>(T)->getDecl();
|
||||
if (const AlignedAttr *Aligned = Typedef->getAttr<AlignedAttr>(*this)) {
|
||||
if (const AlignedAttr *Aligned = Typedef->getAttr<AlignedAttr>()) {
|
||||
Align = Aligned->getAlignment();
|
||||
Width = getTypeSize(Typedef->getUnderlyingType().getTypePtr());
|
||||
} else
|
||||
@ -513,7 +714,7 @@ void ASTRecordLayout::LayoutField(const FieldDecl *FD, unsigned FieldNo,
|
||||
|
||||
// FIXME: Should this override struct packing? Probably we want to
|
||||
// take the minimum?
|
||||
if (const PackedAttr *PA = FD->getAttr<PackedAttr>(Context))
|
||||
if (const PackedAttr *PA = FD->getAttr<PackedAttr>())
|
||||
FieldPacking = PA->getAlignment();
|
||||
|
||||
if (const Expr *BitWidthExpr = FD->getBitWidth()) {
|
||||
@ -533,7 +734,7 @@ void ASTRecordLayout::LayoutField(const FieldDecl *FD, unsigned FieldNo,
|
||||
FieldAlign = FieldInfo.second;
|
||||
if (FieldPacking)
|
||||
FieldAlign = std::min(FieldAlign, FieldPacking);
|
||||
if (const AlignedAttr *AA = FD->getAttr<AlignedAttr>(Context))
|
||||
if (const AlignedAttr *AA = FD->getAttr<AlignedAttr>())
|
||||
FieldAlign = std::max(FieldAlign, AA->getAlignment());
|
||||
|
||||
// Check if we need to add padding to give the field the correct
|
||||
@ -573,7 +774,7 @@ void ASTRecordLayout::LayoutField(const FieldDecl *FD, unsigned FieldNo,
|
||||
// is smaller than the specified packing?
|
||||
if (FieldPacking)
|
||||
FieldAlign = std::min(FieldAlign, std::max(8U, FieldPacking));
|
||||
if (const AlignedAttr *AA = FD->getAttr<AlignedAttr>(Context))
|
||||
if (const AlignedAttr *AA = FD->getAttr<AlignedAttr>())
|
||||
FieldAlign = std::max(FieldAlign, AA->getAlignment());
|
||||
|
||||
// Round up the current record size to the field's alignment boundary.
|
||||
@ -631,8 +832,8 @@ void ASTContext::ShallowCollectObjCIvars(const ObjCInterfaceDecl *OI,
|
||||
|
||||
void ASTContext::CollectProtocolSynthesizedIvars(const ObjCProtocolDecl *PD,
|
||||
llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars) {
|
||||
for (ObjCContainerDecl::prop_iterator I = PD->prop_begin(*this),
|
||||
E = PD->prop_end(*this); I != E; ++I)
|
||||
for (ObjCContainerDecl::prop_iterator I = PD->prop_begin(),
|
||||
E = PD->prop_end(); I != E; ++I)
|
||||
if (ObjCIvarDecl *Ivar = (*I)->getPropertyIvarDecl())
|
||||
Ivars.push_back(Ivar);
|
||||
|
||||
@ -647,8 +848,8 @@ void ASTContext::CollectProtocolSynthesizedIvars(const ObjCProtocolDecl *PD,
|
||||
///
|
||||
void ASTContext::CollectSynthesizedIvars(const ObjCInterfaceDecl *OI,
|
||||
llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars) {
|
||||
for (ObjCInterfaceDecl::prop_iterator I = OI->prop_begin(*this),
|
||||
E = OI->prop_end(*this); I != E; ++I) {
|
||||
for (ObjCInterfaceDecl::prop_iterator I = OI->prop_begin(),
|
||||
E = OI->prop_end(); I != E; ++I) {
|
||||
if (ObjCIvarDecl *Ivar = (*I)->getPropertyIvarDecl())
|
||||
Ivars.push_back(Ivar);
|
||||
}
|
||||
@ -663,8 +864,8 @@ void ASTContext::CollectSynthesizedIvars(const ObjCInterfaceDecl *OI,
|
||||
|
||||
unsigned ASTContext::CountProtocolSynthesizedIvars(const ObjCProtocolDecl *PD) {
|
||||
unsigned count = 0;
|
||||
for (ObjCContainerDecl::prop_iterator I = PD->prop_begin(*this),
|
||||
E = PD->prop_end(*this); I != E; ++I)
|
||||
for (ObjCContainerDecl::prop_iterator I = PD->prop_begin(),
|
||||
E = PD->prop_end(); I != E; ++I)
|
||||
if ((*I)->getPropertyIvarDecl())
|
||||
++count;
|
||||
|
||||
@ -678,8 +879,8 @@ unsigned ASTContext::CountProtocolSynthesizedIvars(const ObjCProtocolDecl *PD) {
|
||||
unsigned ASTContext::CountSynthesizedIvars(const ObjCInterfaceDecl *OI)
|
||||
{
|
||||
unsigned count = 0;
|
||||
for (ObjCInterfaceDecl::prop_iterator I = OI->prop_begin(*this),
|
||||
E = OI->prop_end(*this); I != E; ++I) {
|
||||
for (ObjCInterfaceDecl::prop_iterator I = OI->prop_begin(),
|
||||
E = OI->prop_end(); I != E; ++I) {
|
||||
if ((*I)->getPropertyIvarDecl())
|
||||
++count;
|
||||
}
|
||||
@ -739,10 +940,10 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D,
|
||||
}
|
||||
|
||||
unsigned StructPacking = 0;
|
||||
if (const PackedAttr *PA = D->getAttr<PackedAttr>(*this))
|
||||
if (const PackedAttr *PA = D->getAttr<PackedAttr>())
|
||||
StructPacking = PA->getAlignment();
|
||||
|
||||
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>(*this))
|
||||
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
|
||||
NewEntry->SetAlignment(std::max(NewEntry->getAlignment(),
|
||||
AA->getAlignment()));
|
||||
|
||||
@ -786,23 +987,22 @@ const ASTRecordLayout &ASTContext::getASTRecordLayout(const RecordDecl *D) {
|
||||
Entry = NewEntry;
|
||||
|
||||
// FIXME: Avoid linear walk through the fields, if possible.
|
||||
NewEntry->InitializeLayout(std::distance(D->field_begin(*this),
|
||||
D->field_end(*this)));
|
||||
NewEntry->InitializeLayout(std::distance(D->field_begin(), D->field_end()));
|
||||
bool IsUnion = D->isUnion();
|
||||
|
||||
unsigned StructPacking = 0;
|
||||
if (const PackedAttr *PA = D->getAttr<PackedAttr>(*this))
|
||||
if (const PackedAttr *PA = D->getAttr<PackedAttr>())
|
||||
StructPacking = PA->getAlignment();
|
||||
|
||||
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>(*this))
|
||||
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
|
||||
NewEntry->SetAlignment(std::max(NewEntry->getAlignment(),
|
||||
AA->getAlignment()));
|
||||
|
||||
// Layout each field, for now, just sequentially, respecting alignment. In
|
||||
// the future, this will need to be tweakable by targets.
|
||||
unsigned FieldIdx = 0;
|
||||
for (RecordDecl::field_iterator Field = D->field_begin(*this),
|
||||
FieldEnd = D->field_end(*this);
|
||||
for (RecordDecl::field_iterator Field = D->field_begin(),
|
||||
FieldEnd = D->field_end();
|
||||
Field != FieldEnd; (void)++Field, ++FieldIdx)
|
||||
NewEntry->LayoutField(*Field, FieldIdx, IsUnion, StructPacking, *this);
|
||||
|
||||
@ -1636,13 +1836,6 @@ QualType ASTContext::getObjCQualifiedInterfaceType(ObjCInterfaceDecl *Decl,
|
||||
return QualType(QType, 0);
|
||||
}
|
||||
|
||||
/// getObjCQualifiedIdType - Return an ObjCQualifiedIdType for the 'id' decl
|
||||
/// and the conforming protocol list.
|
||||
QualType ASTContext::getObjCQualifiedIdType(ObjCProtocolDecl **Protocols,
|
||||
unsigned NumProtocols) {
|
||||
return getObjCObjectPointerType(0, Protocols, NumProtocols);
|
||||
}
|
||||
|
||||
/// getTypeOfExprType - Unlike many "get<Type>" functions, we can't unique
|
||||
/// TypeOfExprType AST's (since expression's are never shared). For example,
|
||||
/// multiple declarations that refer to "typeof(x)" all contain different
|
||||
@ -1813,6 +2006,12 @@ Decl *ASTContext::getCanonicalDecl(Decl *D) {
|
||||
return const_cast<FunctionDecl *>(Function);
|
||||
}
|
||||
|
||||
if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D)) {
|
||||
while (FunTmpl->getPreviousDeclaration())
|
||||
FunTmpl = FunTmpl->getPreviousDeclaration();
|
||||
return FunTmpl;
|
||||
}
|
||||
|
||||
if (const VarDecl *Var = dyn_cast<VarDecl>(D)) {
|
||||
while (Var->getPreviousDeclaration())
|
||||
Var = Var->getPreviousDeclaration();
|
||||
@ -2143,7 +2342,7 @@ QualType ASTContext::getCFConstantStringType() {
|
||||
SourceLocation(), 0,
|
||||
FieldTypes[i], /*BitWidth=*/0,
|
||||
/*Mutable=*/false);
|
||||
CFConstantStringTypeDecl->addDecl(*this, Field);
|
||||
CFConstantStringTypeDecl->addDecl(Field);
|
||||
}
|
||||
|
||||
CFConstantStringTypeDecl->completeDefinition(*this);
|
||||
@ -2179,7 +2378,7 @@ QualType ASTContext::getObjCFastEnumerationStateType()
|
||||
SourceLocation(), 0,
|
||||
FieldTypes[i], /*BitWidth=*/0,
|
||||
/*Mutable=*/false);
|
||||
ObjCFastEnumerationStateTypeDecl->addDecl(*this, Field);
|
||||
ObjCFastEnumerationStateTypeDecl->addDecl(Field);
|
||||
}
|
||||
|
||||
ObjCFastEnumerationStateTypeDecl->completeDefinition(*this);
|
||||
@ -2306,7 +2505,7 @@ void ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD,
|
||||
if (const ObjCCategoryImplDecl *CID =
|
||||
dyn_cast<ObjCCategoryImplDecl>(Container)) {
|
||||
for (ObjCCategoryImplDecl::propimpl_iterator
|
||||
i = CID->propimpl_begin(*this), e = CID->propimpl_end(*this);
|
||||
i = CID->propimpl_begin(), e = CID->propimpl_end();
|
||||
i != e; ++i) {
|
||||
ObjCPropertyImplDecl *PID = *i;
|
||||
if (PID->getPropertyDecl() == PD) {
|
||||
@ -2320,7 +2519,7 @@ void ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD,
|
||||
} else {
|
||||
const ObjCImplementationDecl *OID=cast<ObjCImplementationDecl>(Container);
|
||||
for (ObjCCategoryImplDecl::propimpl_iterator
|
||||
i = OID->propimpl_begin(*this), e = OID->propimpl_end(*this);
|
||||
i = OID->propimpl_begin(), e = OID->propimpl_end();
|
||||
i != e; ++i) {
|
||||
ObjCPropertyImplDecl *PID = *i;
|
||||
if (PID->getPropertyDecl() == PD) {
|
||||
@ -2611,8 +2810,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
|
||||
}
|
||||
if (ExpandStructures) {
|
||||
S += '=';
|
||||
for (RecordDecl::field_iterator Field = RDecl->field_begin(*this),
|
||||
FieldEnd = RDecl->field_end(*this);
|
||||
for (RecordDecl::field_iterator Field = RDecl->field_begin(),
|
||||
FieldEnd = RDecl->field_end();
|
||||
Field != FieldEnd; ++Field) {
|
||||
if (FD) {
|
||||
S += '"';
|
||||
@ -2834,7 +3033,7 @@ QualType ASTContext::getFromTargetType(unsigned Type) const {
|
||||
bool ASTContext::isObjCNSObjectType(QualType Ty) const {
|
||||
if (TypedefType *TDT = dyn_cast<TypedefType>(Ty)) {
|
||||
if (TypedefDecl *TD = TDT->getDecl())
|
||||
if (TD->getAttr<ObjCNSObjectAttr>(*const_cast<ASTContext*>(this)))
|
||||
if (TD->getAttr<ObjCNSObjectAttr>())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -3578,7 +3777,7 @@ static QualType DecodeTypeFromStr(const char *&Str, ASTContext &Context,
|
||||
case 'P': {
|
||||
IdentifierInfo *II = &Context.Idents.get("FILE");
|
||||
DeclContext::lookup_result Lookup
|
||||
= Context.getTranslationUnitDecl()->lookup(Context, II);
|
||||
= Context.getTranslationUnitDecl()->lookup(II);
|
||||
if (Lookup.first != Lookup.second && isa<TypeDecl>(*Lookup.first)) {
|
||||
Type = Context.getTypeDeclType(cast<TypeDecl>(*Lookup.first));
|
||||
break;
|
||||
|
@ -556,7 +556,7 @@ CFGBlock* CFGBuilder::VisitNullStmt(NullStmt* Statement) {
|
||||
|
||||
CFGBlock* CFGBuilder::VisitCompoundStmt(CompoundStmt* C) {
|
||||
|
||||
CFGBlock* LastBlock = NULL;
|
||||
CFGBlock* LastBlock = Block;
|
||||
|
||||
for (CompoundStmt::reverse_body_iterator I=C->body_rbegin(), E=C->body_rend();
|
||||
I != E; ++I ) {
|
||||
@ -1484,10 +1484,11 @@ class VISIBILITY_HIDDEN StmtPrinterHelper : public PrinterHelper {
|
||||
StmtMapTy StmtMap;
|
||||
signed CurrentBlock;
|
||||
unsigned CurrentStmt;
|
||||
|
||||
const LangOptions &LangOpts;
|
||||
public:
|
||||
|
||||
StmtPrinterHelper(const CFG* cfg) : CurrentBlock(0), CurrentStmt(0) {
|
||||
StmtPrinterHelper(const CFG* cfg, const LangOptions &LO)
|
||||
: CurrentBlock(0), CurrentStmt(0), LangOpts(LO) {
|
||||
for (CFG::const_iterator I = cfg->begin(), E = cfg->end(); I != E; ++I ) {
|
||||
unsigned j = 1;
|
||||
for (CFGBlock::const_iterator BI = I->begin(), BEnd = I->end() ;
|
||||
@ -1498,6 +1499,7 @@ class VISIBILITY_HIDDEN StmtPrinterHelper : public PrinterHelper {
|
||||
|
||||
virtual ~StmtPrinterHelper() {}
|
||||
|
||||
const LangOptions &getLangOpts() const { return LangOpts; }
|
||||
void setBlockID(signed i) { CurrentBlock = i; }
|
||||
void setStmtID(unsigned i) { CurrentStmt = i; }
|
||||
|
||||
@ -1516,7 +1518,10 @@ class VISIBILITY_HIDDEN StmtPrinterHelper : public PrinterHelper {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
|
||||
namespace {
|
||||
class VISIBILITY_HIDDEN CFGBlockTerminatorPrint
|
||||
: public StmtVisitor<CFGBlockTerminatorPrint,void> {
|
||||
|
||||
@ -1526,7 +1531,7 @@ class VISIBILITY_HIDDEN CFGBlockTerminatorPrint
|
||||
|
||||
public:
|
||||
CFGBlockTerminatorPrint(llvm::raw_ostream& os, StmtPrinterHelper* helper,
|
||||
const PrintingPolicy &Policy = PrintingPolicy())
|
||||
const PrintingPolicy &Policy)
|
||||
: OS(os), Helper(helper), Policy(Policy) {}
|
||||
|
||||
void VisitIfStmt(IfStmt* I) {
|
||||
@ -1602,9 +1607,11 @@ class VISIBILITY_HIDDEN CFGBlockTerminatorPrint
|
||||
E->printPretty(OS, Helper, Policy);
|
||||
}
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
|
||||
|
||||
void print_stmt(llvm::raw_ostream&OS, StmtPrinterHelper* Helper, Stmt* Terminator) {
|
||||
static void print_stmt(llvm::raw_ostream &OS, StmtPrinterHelper* Helper,
|
||||
Stmt* Terminator) {
|
||||
if (Helper) {
|
||||
// special printing for statement-expressions.
|
||||
if (StmtExpr* SE = dyn_cast<StmtExpr>(Terminator)) {
|
||||
@ -1629,14 +1636,15 @@ void print_stmt(llvm::raw_ostream&OS, StmtPrinterHelper* Helper, Stmt* Terminato
|
||||
}
|
||||
}
|
||||
|
||||
Terminator->printPretty(OS, Helper, /*FIXME:*/PrintingPolicy());
|
||||
Terminator->printPretty(OS, Helper, PrintingPolicy(Helper->getLangOpts()));
|
||||
|
||||
// Expressions need a newline.
|
||||
if (isa<Expr>(Terminator)) OS << '\n';
|
||||
}
|
||||
|
||||
void print_block(llvm::raw_ostream& OS, const CFG* cfg, const CFGBlock& B,
|
||||
StmtPrinterHelper* Helper, bool print_edges) {
|
||||
static void print_block(llvm::raw_ostream& OS, const CFG* cfg,
|
||||
const CFGBlock& B,
|
||||
StmtPrinterHelper* Helper, bool print_edges) {
|
||||
|
||||
if (Helper) Helper->setBlockID(B.getBlockID());
|
||||
|
||||
@ -1662,10 +1670,12 @@ void print_block(llvm::raw_ostream& OS, const CFG* cfg, const CFGBlock& B,
|
||||
OS << L->getName();
|
||||
else if (CaseStmt* C = dyn_cast<CaseStmt>(Terminator)) {
|
||||
OS << "case ";
|
||||
C->getLHS()->printPretty(OS, Helper, /*FIXME:*/PrintingPolicy());
|
||||
C->getLHS()->printPretty(OS, Helper,
|
||||
PrintingPolicy(Helper->getLangOpts()));
|
||||
if (C->getRHS()) {
|
||||
OS << " ... ";
|
||||
C->getRHS()->printPretty(OS, Helper, /*FIXME:*/PrintingPolicy());
|
||||
C->getRHS()->printPretty(OS, Helper,
|
||||
PrintingPolicy(Helper->getLangOpts()));
|
||||
}
|
||||
}
|
||||
else if (isa<DefaultStmt>(Terminator))
|
||||
@ -1703,7 +1713,8 @@ void print_block(llvm::raw_ostream& OS, const CFG* cfg, const CFGBlock& B,
|
||||
|
||||
if (Helper) Helper->setBlockID(-1);
|
||||
|
||||
CFGBlockTerminatorPrint TPrinter(OS, Helper, /*FIXME*/PrintingPolicy());
|
||||
CFGBlockTerminatorPrint TPrinter(OS, Helper,
|
||||
PrintingPolicy(Helper->getLangOpts()));
|
||||
TPrinter.Visit(const_cast<Stmt*>(B.getTerminator()));
|
||||
OS << '\n';
|
||||
}
|
||||
@ -1741,15 +1752,13 @@ void print_block(llvm::raw_ostream& OS, const CFG* cfg, const CFGBlock& B,
|
||||
}
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
/// dump - A simple pretty printer of a CFG that outputs to stderr.
|
||||
void CFG::dump() const { print(llvm::errs()); }
|
||||
void CFG::dump(const LangOptions &LO) const { print(llvm::errs(), LO); }
|
||||
|
||||
/// print - A simple pretty printer of a CFG that outputs to an ostream.
|
||||
void CFG::print(llvm::raw_ostream& OS) const {
|
||||
|
||||
StmtPrinterHelper Helper(this);
|
||||
void CFG::print(llvm::raw_ostream &OS, const LangOptions &LO) const {
|
||||
StmtPrinterHelper Helper(this, LO);
|
||||
|
||||
// Print the entry block.
|
||||
print_block(OS, this, getEntry(), &Helper, true);
|
||||
@ -1769,18 +1778,22 @@ void CFG::print(llvm::raw_ostream& OS) const {
|
||||
}
|
||||
|
||||
/// dump - A simply pretty printer of a CFGBlock that outputs to stderr.
|
||||
void CFGBlock::dump(const CFG* cfg) const { print(llvm::errs(), cfg); }
|
||||
void CFGBlock::dump(const CFG* cfg, const LangOptions &LO) const {
|
||||
print(llvm::errs(), cfg, LO);
|
||||
}
|
||||
|
||||
/// print - A simple pretty printer of a CFGBlock that outputs to an ostream.
|
||||
/// Generally this will only be called from CFG::print.
|
||||
void CFGBlock::print(llvm::raw_ostream& OS, const CFG* cfg) const {
|
||||
StmtPrinterHelper Helper(cfg);
|
||||
void CFGBlock::print(llvm::raw_ostream& OS, const CFG* cfg,
|
||||
const LangOptions &LO) const {
|
||||
StmtPrinterHelper Helper(cfg, LO);
|
||||
print_block(OS, cfg, *this, &Helper, true);
|
||||
}
|
||||
|
||||
/// printTerminator - A simple pretty printer of the terminator of a CFGBlock.
|
||||
void CFGBlock::printTerminator(llvm::raw_ostream& OS) const {
|
||||
CFGBlockTerminatorPrint TPrinter(OS,NULL);
|
||||
void CFGBlock::printTerminator(llvm::raw_ostream &OS,
|
||||
const LangOptions &LO) const {
|
||||
CFGBlockTerminatorPrint TPrinter(OS, NULL, PrintingPolicy(LO));
|
||||
TPrinter.Visit(const_cast<Stmt*>(getTerminator()));
|
||||
}
|
||||
|
||||
@ -1872,9 +1885,9 @@ bool CFGBlock::hasBinaryBranchTerminator() const {
|
||||
static StmtPrinterHelper* GraphHelper;
|
||||
#endif
|
||||
|
||||
void CFG::viewCFG() const {
|
||||
void CFG::viewCFG(const LangOptions &LO) const {
|
||||
#ifndef NDEBUG
|
||||
StmtPrinterHelper H(this);
|
||||
StmtPrinterHelper H(this, LO);
|
||||
GraphHelper = &H;
|
||||
llvm::ViewGraph(this,"CFG");
|
||||
GraphHelper = NULL;
|
||||
|
@ -41,7 +41,7 @@ void Attr::Destroy(ASTContext &C) {
|
||||
|
||||
|
||||
TranslationUnitDecl *TranslationUnitDecl::Create(ASTContext &C) {
|
||||
return new (C) TranslationUnitDecl();
|
||||
return new (C) TranslationUnitDecl(C);
|
||||
}
|
||||
|
||||
NamespaceDecl *NamespaceDecl::Create(ASTContext &C, DeclContext *DC,
|
||||
@ -226,8 +226,7 @@ std::string NamedDecl::getQualifiedNameAsString() const {
|
||||
if (const ClassTemplateSpecializationDecl *Spec
|
||||
= dyn_cast<ClassTemplateSpecializationDecl>(Ctx)) {
|
||||
const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
|
||||
PrintingPolicy Policy;
|
||||
Policy.CPlusPlus = true;
|
||||
PrintingPolicy Policy(getASTContext().getLangOptions());
|
||||
std::string TemplateArgsStr
|
||||
= TemplateSpecializationType::PrintTemplateArgumentList(
|
||||
TemplateArgs.getFlatArgumentList(),
|
||||
@ -372,20 +371,15 @@ void FunctionDecl::Destroy(ASTContext& C) {
|
||||
|
||||
C.Deallocate(ParamInfo);
|
||||
|
||||
if (TemplateSpecializationInfo *Info
|
||||
= TemplateOrSpecialization.dyn_cast<TemplateSpecializationInfo*>())
|
||||
C.Deallocate(Info);
|
||||
|
||||
Decl::Destroy(C);
|
||||
}
|
||||
|
||||
|
||||
Stmt *FunctionDecl::getBody(ASTContext &Context,
|
||||
const FunctionDecl *&Definition) const {
|
||||
Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const {
|
||||
for (const FunctionDecl *FD = this; FD != 0; FD = FD->PreviousDeclaration) {
|
||||
if (FD->Body) {
|
||||
Definition = FD;
|
||||
return FD->Body.get(Context.getExternalSource());
|
||||
return FD->Body.get(getASTContext().getExternalSource());
|
||||
}
|
||||
}
|
||||
|
||||
@ -417,14 +411,14 @@ bool FunctionDecl::isExternC(ASTContext &Context) const {
|
||||
// In C, any non-static, non-overloadable function has external
|
||||
// linkage.
|
||||
if (!Context.getLangOptions().CPlusPlus)
|
||||
return getStorageClass() != Static && !getAttr<OverloadableAttr>(Context);
|
||||
return getStorageClass() != Static && !getAttr<OverloadableAttr>();
|
||||
|
||||
for (const DeclContext *DC = getDeclContext(); !DC->isTranslationUnit();
|
||||
DC = DC->getParent()) {
|
||||
if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) {
|
||||
if (Linkage->getLanguage() == LinkageSpecDecl::lang_c)
|
||||
return getStorageClass() != Static &&
|
||||
!getAttr<OverloadableAttr>(Context);
|
||||
!getAttr<OverloadableAttr>();
|
||||
|
||||
break;
|
||||
}
|
||||
@ -489,7 +483,7 @@ unsigned FunctionDecl::getBuiltinID(ASTContext &Context) const {
|
||||
if (isa<LinkageSpecDecl>(getDeclContext()) &&
|
||||
cast<LinkageSpecDecl>(getDeclContext())->getLanguage()
|
||||
== LinkageSpecDecl::lang_c &&
|
||||
!getAttr<OverloadableAttr>(Context))
|
||||
!getAttr<OverloadableAttr>())
|
||||
return BuiltinID;
|
||||
|
||||
// Not a builtin
|
||||
@ -540,12 +534,12 @@ unsigned FunctionDecl::getMinRequiredArguments() const {
|
||||
}
|
||||
|
||||
bool FunctionDecl::hasActiveGNUInlineAttribute(ASTContext &Context) const {
|
||||
if (!isInline() || !hasAttr<GNUInlineAttr>(Context))
|
||||
if (!isInline() || !hasAttr<GNUInlineAttr>())
|
||||
return false;
|
||||
|
||||
for (const FunctionDecl *FD = getPreviousDeclaration(); FD;
|
||||
FD = FD->getPreviousDeclaration()) {
|
||||
if (FD->isInline() && !FD->hasAttr<GNUInlineAttr>(Context))
|
||||
if (FD->isInline() && !FD->hasAttr<GNUInlineAttr>())
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -557,12 +551,24 @@ bool FunctionDecl::isExternGNUInline(ASTContext &Context) const {
|
||||
return false;
|
||||
|
||||
for (const FunctionDecl *FD = this; FD; FD = FD->getPreviousDeclaration())
|
||||
if (FD->getStorageClass() == Extern && FD->hasAttr<GNUInlineAttr>(Context))
|
||||
if (FD->getStorageClass() == Extern && FD->hasAttr<GNUInlineAttr>())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) {
|
||||
PreviousDeclaration = PrevDecl;
|
||||
|
||||
if (FunctionTemplateDecl *FunTmpl = getDescribedFunctionTemplate()) {
|
||||
FunctionTemplateDecl *PrevFunTmpl
|
||||
= PrevDecl? PrevDecl->getDescribedFunctionTemplate() : 0;
|
||||
assert((!PrevDecl || PrevFunTmpl) && "Function/function template mismatch");
|
||||
FunTmpl->setPreviousDeclaration(PrevFunTmpl);
|
||||
}
|
||||
}
|
||||
|
||||
/// getOverloadedOperator - Which C++ overloaded operator this
|
||||
/// function represents, if any.
|
||||
OverloadedOperatorKind FunctionDecl::getOverloadedOperator() const {
|
||||
@ -572,18 +578,64 @@ OverloadedOperatorKind FunctionDecl::getOverloadedOperator() const {
|
||||
return OO_None;
|
||||
}
|
||||
|
||||
FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const {
|
||||
if (FunctionTemplateSpecializationInfo *Info
|
||||
= TemplateOrSpecialization
|
||||
.dyn_cast<FunctionTemplateSpecializationInfo*>()) {
|
||||
return Info->Template.getPointer();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const TemplateArgumentList *
|
||||
FunctionDecl::getTemplateSpecializationArgs() const {
|
||||
if (FunctionTemplateSpecializationInfo *Info
|
||||
= TemplateOrSpecialization
|
||||
.dyn_cast<FunctionTemplateSpecializationInfo*>()) {
|
||||
return Info->TemplateArguments;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
FunctionDecl::setFunctionTemplateSpecialization(ASTContext &Context,
|
||||
FunctionTemplateDecl *Template,
|
||||
const TemplateArgumentList *TemplateArgs) {
|
||||
TemplateSpecializationInfo *Info
|
||||
= TemplateOrSpecialization.dyn_cast<TemplateSpecializationInfo*>();
|
||||
const TemplateArgumentList *TemplateArgs,
|
||||
void *InsertPos) {
|
||||
FunctionTemplateSpecializationInfo *Info
|
||||
= TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>();
|
||||
if (!Info)
|
||||
Info = new (Context) TemplateSpecializationInfo;
|
||||
Info = new (Context) FunctionTemplateSpecializationInfo;
|
||||
|
||||
Info->Template = Template;
|
||||
Info->Function = this;
|
||||
Info->Template.setPointer(Template);
|
||||
Info->Template.setInt(0); // Implicit instantiation, unless told otherwise
|
||||
Info->TemplateArguments = TemplateArgs;
|
||||
TemplateOrSpecialization = Info;
|
||||
|
||||
// Insert this function template specialization into the set of known
|
||||
// function template specialiations.
|
||||
Template->getSpecializations().InsertNode(Info, InsertPos);
|
||||
}
|
||||
|
||||
bool FunctionDecl::isExplicitSpecialization() const {
|
||||
// FIXME: check this property for explicit specializations of member
|
||||
// functions of class templates.
|
||||
FunctionTemplateSpecializationInfo *Info
|
||||
= TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>();
|
||||
if (!Info)
|
||||
return false;
|
||||
|
||||
return Info->isExplicitSpecialization();
|
||||
}
|
||||
|
||||
void FunctionDecl::setExplicitSpecialization(bool ES) {
|
||||
// FIXME: set this property for explicit specializations of member functions
|
||||
// of class templates.
|
||||
FunctionTemplateSpecializationInfo *Info
|
||||
= TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>();
|
||||
if (Info)
|
||||
Info->setExplicitSpecialization(ES);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -157,6 +157,25 @@ void Decl::setLexicalDeclContext(DeclContext *DC) {
|
||||
}
|
||||
}
|
||||
|
||||
TranslationUnitDecl *Decl::getTranslationUnitDecl() {
|
||||
if (TranslationUnitDecl *TUD = dyn_cast<TranslationUnitDecl>(this))
|
||||
return TUD;
|
||||
|
||||
DeclContext *DC = getDeclContext();
|
||||
assert(DC && "This decl is not contained in a translation unit!");
|
||||
|
||||
while (!DC->isTranslationUnit()) {
|
||||
DC = DC->getParent();
|
||||
assert(DC && "This decl is not contained in a translation unit!");
|
||||
}
|
||||
|
||||
return cast<TranslationUnitDecl>(DC);
|
||||
}
|
||||
|
||||
ASTContext &Decl::getASTContext() const {
|
||||
return getTranslationUnitDecl()->getASTContext();
|
||||
}
|
||||
|
||||
unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
|
||||
switch (DeclKind) {
|
||||
default:
|
||||
@ -226,8 +245,8 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
|
||||
}
|
||||
}
|
||||
|
||||
void Decl::addAttr(ASTContext &Context, Attr *NewAttr) {
|
||||
Attr *&ExistingAttr = Context.getDeclAttrs(this);
|
||||
void Decl::addAttr(Attr *NewAttr) {
|
||||
Attr *&ExistingAttr = getASTContext().getDeclAttrs(this);
|
||||
|
||||
NewAttr->setNext(ExistingAttr);
|
||||
ExistingAttr = NewAttr;
|
||||
@ -235,19 +254,19 @@ void Decl::addAttr(ASTContext &Context, Attr *NewAttr) {
|
||||
HasAttrs = true;
|
||||
}
|
||||
|
||||
void Decl::invalidateAttrs(ASTContext &Context) {
|
||||
void Decl::invalidateAttrs() {
|
||||
if (!HasAttrs) return;
|
||||
|
||||
HasAttrs = false;
|
||||
Context.eraseDeclAttrs(this);
|
||||
getASTContext().eraseDeclAttrs(this);
|
||||
}
|
||||
|
||||
const Attr *Decl::getAttrsImpl(ASTContext &Context) const {
|
||||
const Attr *Decl::getAttrsImpl() const {
|
||||
assert(HasAttrs && "getAttrs() should verify this!");
|
||||
return Context.getDeclAttrs(this);
|
||||
return getASTContext().getDeclAttrs(this);
|
||||
}
|
||||
|
||||
void Decl::swapAttrs(ASTContext &Context, Decl *RHS) {
|
||||
void Decl::swapAttrs(Decl *RHS) {
|
||||
bool HasLHSAttr = this->HasAttrs;
|
||||
bool HasRHSAttr = RHS->HasAttrs;
|
||||
|
||||
@ -256,7 +275,9 @@ void Decl::swapAttrs(ASTContext &Context, Decl *RHS) {
|
||||
|
||||
// If 'this' has no attrs, swap the other way.
|
||||
if (!HasLHSAttr)
|
||||
return RHS->swapAttrs(Context, this);
|
||||
return RHS->swapAttrs(this);
|
||||
|
||||
ASTContext &Context = getASTContext();
|
||||
|
||||
// Handle the case when both decls have attrs.
|
||||
if (HasRHSAttr) {
|
||||
@ -276,7 +297,7 @@ void Decl::Destroy(ASTContext &C) {
|
||||
// Free attributes for this decl.
|
||||
if (HasAttrs) {
|
||||
C.getDeclAttrs(this)->Destroy(C);
|
||||
invalidateAttrs(C);
|
||||
invalidateAttrs();
|
||||
HasAttrs = false;
|
||||
}
|
||||
|
||||
@ -339,12 +360,12 @@ DeclContext *Decl::castToDeclContext(const Decl *D) {
|
||||
}
|
||||
}
|
||||
|
||||
CompoundStmt* Decl::getCompoundBody(ASTContext &Context) const {
|
||||
return dyn_cast_or_null<CompoundStmt>(getBody(Context));
|
||||
CompoundStmt* Decl::getCompoundBody() const {
|
||||
return dyn_cast_or_null<CompoundStmt>(getBody());
|
||||
}
|
||||
|
||||
SourceLocation Decl::getBodyRBrace(ASTContext &Context) const {
|
||||
Stmt *Body = getBody(Context);
|
||||
SourceLocation Decl::getBodyRBrace() const {
|
||||
Stmt *Body = getBody();
|
||||
if (!Body)
|
||||
return SourceLocation();
|
||||
if (CompoundStmt *CS = dyn_cast<CompoundStmt>(Body))
|
||||
@ -388,7 +409,7 @@ DeclContext::~DeclContext() {
|
||||
}
|
||||
|
||||
void DeclContext::DestroyDecls(ASTContext &C) {
|
||||
for (decl_iterator D = decls_begin(C); D != decls_end(C); )
|
||||
for (decl_iterator D = decls_begin(); D != decls_end(); )
|
||||
(*D++)->Destroy(C);
|
||||
}
|
||||
|
||||
@ -479,8 +500,8 @@ DeclContext *DeclContext::getNextContext() {
|
||||
/// \brief Load the declarations within this lexical storage from an
|
||||
/// external source.
|
||||
void
|
||||
DeclContext::LoadLexicalDeclsFromExternalStorage(ASTContext &Context) const {
|
||||
ExternalASTSource *Source = Context.getExternalSource();
|
||||
DeclContext::LoadLexicalDeclsFromExternalStorage() const {
|
||||
ExternalASTSource *Source = getParentASTContext().getExternalSource();
|
||||
assert(hasExternalLexicalStorage() && Source && "No external storage?");
|
||||
|
||||
llvm::SmallVector<uint32_t, 64> Decls;
|
||||
@ -517,9 +538,9 @@ DeclContext::LoadLexicalDeclsFromExternalStorage(ASTContext &Context) const {
|
||||
}
|
||||
|
||||
void
|
||||
DeclContext::LoadVisibleDeclsFromExternalStorage(ASTContext &Context) const {
|
||||
DeclContext::LoadVisibleDeclsFromExternalStorage() const {
|
||||
DeclContext *This = const_cast<DeclContext *>(this);
|
||||
ExternalASTSource *Source = Context.getExternalSource();
|
||||
ExternalASTSource *Source = getParentASTContext().getExternalSource();
|
||||
assert(hasExternalVisibleStorage() && Source && "No external storage?");
|
||||
|
||||
llvm::SmallVector<VisibleDeclaration, 64> Decls;
|
||||
@ -539,30 +560,30 @@ DeclContext::LoadVisibleDeclsFromExternalStorage(ASTContext &Context) const {
|
||||
}
|
||||
}
|
||||
|
||||
DeclContext::decl_iterator DeclContext::decls_begin(ASTContext &Context) const {
|
||||
DeclContext::decl_iterator DeclContext::decls_begin() const {
|
||||
if (hasExternalLexicalStorage())
|
||||
LoadLexicalDeclsFromExternalStorage(Context);
|
||||
LoadLexicalDeclsFromExternalStorage();
|
||||
|
||||
// FIXME: Check whether we need to load some declarations from
|
||||
// external storage.
|
||||
return decl_iterator(FirstDecl);
|
||||
}
|
||||
|
||||
DeclContext::decl_iterator DeclContext::decls_end(ASTContext &Context) const {
|
||||
DeclContext::decl_iterator DeclContext::decls_end() const {
|
||||
if (hasExternalLexicalStorage())
|
||||
LoadLexicalDeclsFromExternalStorage(Context);
|
||||
LoadLexicalDeclsFromExternalStorage();
|
||||
|
||||
return decl_iterator();
|
||||
}
|
||||
|
||||
bool DeclContext::decls_empty(ASTContext &Context) const {
|
||||
bool DeclContext::decls_empty() const {
|
||||
if (hasExternalLexicalStorage())
|
||||
LoadLexicalDeclsFromExternalStorage(Context);
|
||||
LoadLexicalDeclsFromExternalStorage();
|
||||
|
||||
return !FirstDecl;
|
||||
}
|
||||
|
||||
void DeclContext::addDecl(ASTContext &Context, Decl *D) {
|
||||
void DeclContext::addDecl(Decl *D) {
|
||||
assert(D->getLexicalDeclContext() == this &&
|
||||
"Decl inserted into wrong lexical context");
|
||||
assert(!D->getNextDeclInContext() && D != LastDecl &&
|
||||
@ -576,44 +597,44 @@ void DeclContext::addDecl(ASTContext &Context, Decl *D) {
|
||||
}
|
||||
|
||||
if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
|
||||
ND->getDeclContext()->makeDeclVisibleInContext(Context, ND);
|
||||
ND->getDeclContext()->makeDeclVisibleInContext(ND);
|
||||
}
|
||||
|
||||
/// buildLookup - Build the lookup data structure with all of the
|
||||
/// declarations in DCtx (and any other contexts linked to it or
|
||||
/// transparent contexts nested within it).
|
||||
void DeclContext::buildLookup(ASTContext &Context, DeclContext *DCtx) {
|
||||
void DeclContext::buildLookup(DeclContext *DCtx) {
|
||||
for (; DCtx; DCtx = DCtx->getNextContext()) {
|
||||
for (decl_iterator D = DCtx->decls_begin(Context),
|
||||
DEnd = DCtx->decls_end(Context);
|
||||
for (decl_iterator D = DCtx->decls_begin(),
|
||||
DEnd = DCtx->decls_end();
|
||||
D != DEnd; ++D) {
|
||||
// Insert this declaration into the lookup structure
|
||||
if (NamedDecl *ND = dyn_cast<NamedDecl>(*D))
|
||||
makeDeclVisibleInContextImpl(Context, ND);
|
||||
makeDeclVisibleInContextImpl(ND);
|
||||
|
||||
// If this declaration is itself a transparent declaration context,
|
||||
// add its members (recursively).
|
||||
if (DeclContext *InnerCtx = dyn_cast<DeclContext>(*D))
|
||||
if (InnerCtx->isTransparentContext())
|
||||
buildLookup(Context, InnerCtx->getPrimaryContext());
|
||||
buildLookup(InnerCtx->getPrimaryContext());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DeclContext::lookup_result
|
||||
DeclContext::lookup(ASTContext &Context, DeclarationName Name) {
|
||||
DeclContext::lookup(DeclarationName Name) {
|
||||
DeclContext *PrimaryContext = getPrimaryContext();
|
||||
if (PrimaryContext != this)
|
||||
return PrimaryContext->lookup(Context, Name);
|
||||
return PrimaryContext->lookup(Name);
|
||||
|
||||
if (hasExternalVisibleStorage())
|
||||
LoadVisibleDeclsFromExternalStorage(Context);
|
||||
LoadVisibleDeclsFromExternalStorage();
|
||||
|
||||
/// If there is no lookup data structure, build one now by walking
|
||||
/// all of the linked DeclContexts (in declaration order!) and
|
||||
/// inserting their values.
|
||||
if (!LookupPtr) {
|
||||
buildLookup(Context, this);
|
||||
buildLookup(this);
|
||||
|
||||
if (!LookupPtr)
|
||||
return lookup_result(0, 0);
|
||||
@ -623,12 +644,12 @@ DeclContext::lookup(ASTContext &Context, DeclarationName Name) {
|
||||
StoredDeclsMap::iterator Pos = Map->find(Name);
|
||||
if (Pos == Map->end())
|
||||
return lookup_result(0, 0);
|
||||
return Pos->second.getLookupResult(Context);
|
||||
return Pos->second.getLookupResult(getParentASTContext());
|
||||
}
|
||||
|
||||
DeclContext::lookup_const_result
|
||||
DeclContext::lookup(ASTContext &Context, DeclarationName Name) const {
|
||||
return const_cast<DeclContext*>(this)->lookup(Context, Name);
|
||||
DeclContext::lookup(DeclarationName Name) const {
|
||||
return const_cast<DeclContext*>(this)->lookup(Name);
|
||||
}
|
||||
|
||||
DeclContext *DeclContext::getLookupContext() {
|
||||
@ -647,7 +668,7 @@ DeclContext *DeclContext::getEnclosingNamespaceContext() {
|
||||
return Ctx->getPrimaryContext();
|
||||
}
|
||||
|
||||
void DeclContext::makeDeclVisibleInContext(ASTContext &Context, NamedDecl *D) {
|
||||
void DeclContext::makeDeclVisibleInContext(NamedDecl *D) {
|
||||
// FIXME: This feels like a hack. Should DeclarationName support
|
||||
// template-ids, or is there a better way to keep specializations
|
||||
// from being visible?
|
||||
@ -656,7 +677,7 @@ void DeclContext::makeDeclVisibleInContext(ASTContext &Context, NamedDecl *D) {
|
||||
|
||||
DeclContext *PrimaryContext = getPrimaryContext();
|
||||
if (PrimaryContext != this) {
|
||||
PrimaryContext->makeDeclVisibleInContext(Context, D);
|
||||
PrimaryContext->makeDeclVisibleInContext(D);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -664,16 +685,15 @@ void DeclContext::makeDeclVisibleInContext(ASTContext &Context, NamedDecl *D) {
|
||||
// into it. Otherwise, be lazy and don't build that structure until
|
||||
// someone asks for it.
|
||||
if (LookupPtr)
|
||||
makeDeclVisibleInContextImpl(Context, D);
|
||||
makeDeclVisibleInContextImpl(D);
|
||||
|
||||
// If we are a transparent context, insert into our parent context,
|
||||
// too. This operation is recursive.
|
||||
if (isTransparentContext())
|
||||
getParent()->makeDeclVisibleInContext(Context, D);
|
||||
getParent()->makeDeclVisibleInContext(D);
|
||||
}
|
||||
|
||||
void DeclContext::makeDeclVisibleInContextImpl(ASTContext &Context,
|
||||
NamedDecl *D) {
|
||||
void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D) {
|
||||
// Skip unnamed declarations.
|
||||
if (!D->getDeclName())
|
||||
return;
|
||||
@ -698,7 +718,7 @@ void DeclContext::makeDeclVisibleInContextImpl(ASTContext &Context,
|
||||
// If it is possible that this is a redeclaration, check to see if there is
|
||||
// already a decl for which declarationReplaces returns true. If there is
|
||||
// one, just replace it and return.
|
||||
if (DeclNameEntries.HandleRedeclaration(Context, D))
|
||||
if (DeclNameEntries.HandleRedeclaration(getParentASTContext(), D))
|
||||
return;
|
||||
|
||||
// Put this declaration into the appropriate slot.
|
||||
@ -708,8 +728,8 @@ void DeclContext::makeDeclVisibleInContextImpl(ASTContext &Context,
|
||||
/// Returns iterator range [First, Last) of UsingDirectiveDecls stored within
|
||||
/// this context.
|
||||
DeclContext::udir_iterator_range
|
||||
DeclContext::getUsingDirectives(ASTContext &Context) const {
|
||||
lookup_const_result Result = lookup(Context, UsingDirectiveDecl::getName());
|
||||
DeclContext::getUsingDirectives() const {
|
||||
lookup_const_result Result = lookup(UsingDirectiveDecl::getName());
|
||||
return udir_iterator_range(reinterpret_cast<udir_iterator>(Result.first),
|
||||
reinterpret_cast<udir_iterator>(Result.second));
|
||||
}
|
||||
|
@ -44,11 +44,16 @@ CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC,
|
||||
}
|
||||
|
||||
CXXRecordDecl::~CXXRecordDecl() {
|
||||
delete [] Bases;
|
||||
}
|
||||
|
||||
void CXXRecordDecl::Destroy(ASTContext &C) {
|
||||
C.Deallocate(Bases);
|
||||
this->RecordDecl::Destroy(C);
|
||||
}
|
||||
|
||||
void
|
||||
CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
|
||||
CXXRecordDecl::setBases(ASTContext &C,
|
||||
CXXBaseSpecifier const * const *Bases,
|
||||
unsigned NumBases) {
|
||||
// C++ [dcl.init.aggr]p1:
|
||||
// An aggregate is an array or a class (clause 9) with [...]
|
||||
@ -56,10 +61,9 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
|
||||
Aggregate = false;
|
||||
|
||||
if (this->Bases)
|
||||
delete [] this->Bases;
|
||||
C.Deallocate(this->Bases);
|
||||
|
||||
// FIXME: allocate using the ASTContext
|
||||
this->Bases = new CXXBaseSpecifier[NumBases];
|
||||
this->Bases = new(C) CXXBaseSpecifier [NumBases];
|
||||
this->NumBases = NumBases;
|
||||
for (unsigned i = 0; i < NumBases; ++i)
|
||||
this->Bases[i] = *Bases[i];
|
||||
@ -78,7 +82,7 @@ CXXConstructorDecl *CXXRecordDecl::getCopyConstructor(ASTContext &Context,
|
||||
Context.getCanonicalType(ClassType));
|
||||
unsigned FoundTQs;
|
||||
DeclContext::lookup_const_iterator Con, ConEnd;
|
||||
for (llvm::tie(Con, ConEnd) = this->lookup(Context, ConstructorName);
|
||||
for (llvm::tie(Con, ConEnd) = this->lookup(ConstructorName);
|
||||
Con != ConEnd; ++Con) {
|
||||
if (cast<CXXConstructorDecl>(*Con)->isCopyConstructor(Context,
|
||||
FoundTQs)) {
|
||||
@ -97,7 +101,7 @@ bool CXXRecordDecl::hasConstCopyAssignment(ASTContext &Context) const {
|
||||
DeclarationName OpName =Context.DeclarationNames.getCXXOperatorName(OO_Equal);
|
||||
|
||||
DeclContext::lookup_const_iterator Op, OpEnd;
|
||||
for (llvm::tie(Op, OpEnd) = this->lookup(Context, OpName);
|
||||
for (llvm::tie(Op, OpEnd) = this->lookup(OpName);
|
||||
Op != OpEnd; ++Op) {
|
||||
// C++ [class.copy]p9:
|
||||
// A user-declared copy assignment operator is a non-static non-template
|
||||
@ -201,7 +205,7 @@ CXXRecordDecl::getDefaultConstructor(ASTContext &Context) {
|
||||
Context.getCanonicalType(ClassType.getUnqualifiedType()));
|
||||
|
||||
DeclContext::lookup_const_iterator Con, ConEnd;
|
||||
for (llvm::tie(Con, ConEnd) = lookup(Context, ConstructorName);
|
||||
for (llvm::tie(Con, ConEnd) = lookup(ConstructorName);
|
||||
Con != ConEnd; ++Con) {
|
||||
CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
|
||||
if (Constructor->isDefaultConstructor())
|
||||
@ -218,7 +222,7 @@ CXXRecordDecl::getDestructor(ASTContext &Context) {
|
||||
= Context.DeclarationNames.getCXXDestructorName(ClassType);
|
||||
|
||||
DeclContext::lookup_iterator I, E;
|
||||
llvm::tie(I, E) = lookup(Context, Name);
|
||||
llvm::tie(I, E) = lookup(Name);
|
||||
assert(I != E && "Did not find a destructor!");
|
||||
|
||||
const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(*I);
|
||||
@ -294,8 +298,9 @@ QualType CXXMethodDecl::getThisType(ASTContext &C) const {
|
||||
}
|
||||
|
||||
CXXBaseOrMemberInitializer::
|
||||
CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs)
|
||||
: Args(0), NumArgs(0) {
|
||||
CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs,
|
||||
SourceLocation L)
|
||||
: Args(0), NumArgs(0), IdLoc(L) {
|
||||
BaseOrMember = reinterpret_cast<uintptr_t>(BaseType.getTypePtr());
|
||||
assert((BaseOrMember & 0x01) == 0 && "Invalid base class type pointer");
|
||||
BaseOrMember |= 0x01;
|
||||
@ -309,8 +314,9 @@ CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs)
|
||||
}
|
||||
|
||||
CXXBaseOrMemberInitializer::
|
||||
CXXBaseOrMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs)
|
||||
: Args(0), NumArgs(0) {
|
||||
CXXBaseOrMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs,
|
||||
SourceLocation L)
|
||||
: Args(0), NumArgs(0), IdLoc(L) {
|
||||
BaseOrMember = reinterpret_cast<uintptr_t>(Member);
|
||||
assert((BaseOrMember & 0x01) == 0 && "Invalid member pointer");
|
||||
|
||||
@ -405,6 +411,27 @@ CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
|
||||
isImplicitlyDeclared);
|
||||
}
|
||||
|
||||
void
|
||||
CXXConstructorDecl::setBaseOrMemberInitializers(
|
||||
ASTContext &C,
|
||||
CXXBaseOrMemberInitializer **Initializers,
|
||||
unsigned NumInitializers) {
|
||||
if (NumInitializers > 0) {
|
||||
NumBaseOrMemberInitializers = NumInitializers;
|
||||
BaseOrMemberInitializers =
|
||||
new (C, 8) CXXBaseOrMemberInitializer*[NumInitializers];
|
||||
for (unsigned Idx = 0; Idx < NumInitializers; ++Idx)
|
||||
BaseOrMemberInitializers[Idx] = Initializers[Idx];
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CXXConstructorDecl::Destroy(ASTContext& C) {
|
||||
C.Deallocate(BaseOrMemberInitializers);
|
||||
this->~CXXMethodDecl();
|
||||
C.Deallocate((void *)this);
|
||||
}
|
||||
|
||||
CXXConversionDecl *
|
||||
CXXConversionDecl::Create(ASTContext &C, CXXRecordDecl *RD,
|
||||
SourceLocation L, DeclarationName N,
|
||||
@ -420,13 +447,9 @@ OverloadedFunctionDecl::Create(ASTContext &C, DeclContext *DC,
|
||||
return new (C) OverloadedFunctionDecl(DC, N);
|
||||
}
|
||||
|
||||
void OverloadedFunctionDecl::addOverload(FunctionTemplateDecl *FTD) {
|
||||
Functions.push_back(FTD);
|
||||
|
||||
// An overloaded function declaration always has the location of
|
||||
// the most-recently-added function declaration.
|
||||
if (FTD->getLocation().isValid())
|
||||
this->setLocation(FTD->getLocation());
|
||||
void OverloadedFunctionDecl::addOverload(AnyFunctionDecl F) {
|
||||
Functions.push_back(F);
|
||||
this->setLocation(F.get()->getLocation());
|
||||
}
|
||||
|
||||
LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,
|
||||
|
@ -45,10 +45,9 @@ void ObjCListBase::set(void *const* InList, unsigned Elts, ASTContext &Ctx) {
|
||||
/// getIvarDecl - This method looks up an ivar in this ContextDecl.
|
||||
///
|
||||
ObjCIvarDecl *
|
||||
ObjCContainerDecl::getIvarDecl(ASTContext &Context, IdentifierInfo *Id) const {
|
||||
ObjCContainerDecl::getIvarDecl(IdentifierInfo *Id) const {
|
||||
lookup_const_iterator Ivar, IvarEnd;
|
||||
for (llvm::tie(Ivar, IvarEnd) = lookup(Context, Id);
|
||||
Ivar != IvarEnd; ++Ivar) {
|
||||
for (llvm::tie(Ivar, IvarEnd) = lookup(Id); Ivar != IvarEnd; ++Ivar) {
|
||||
if (ObjCIvarDecl *ivar = dyn_cast<ObjCIvarDecl>(*Ivar))
|
||||
return ivar;
|
||||
}
|
||||
@ -57,7 +56,7 @@ ObjCContainerDecl::getIvarDecl(ASTContext &Context, IdentifierInfo *Id) const {
|
||||
|
||||
// Get the local instance method declared in this interface.
|
||||
ObjCMethodDecl *
|
||||
ObjCContainerDecl::getInstanceMethod(ASTContext &Context, Selector Sel) const {
|
||||
ObjCContainerDecl::getInstanceMethod(Selector Sel) const {
|
||||
// Since instance & class methods can have the same name, the loop below
|
||||
// ensures we get the correct method.
|
||||
//
|
||||
@ -67,8 +66,7 @@ ObjCContainerDecl::getInstanceMethod(ASTContext &Context, Selector Sel) const {
|
||||
// @end
|
||||
//
|
||||
lookup_const_iterator Meth, MethEnd;
|
||||
for (llvm::tie(Meth, MethEnd) = lookup(Context, Sel);
|
||||
Meth != MethEnd; ++Meth) {
|
||||
for (llvm::tie(Meth, MethEnd) = lookup(Sel); Meth != MethEnd; ++Meth) {
|
||||
ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(*Meth);
|
||||
if (MD && MD->isInstanceMethod())
|
||||
return MD;
|
||||
@ -78,7 +76,7 @@ ObjCContainerDecl::getInstanceMethod(ASTContext &Context, Selector Sel) const {
|
||||
|
||||
// Get the local class method declared in this interface.
|
||||
ObjCMethodDecl *
|
||||
ObjCContainerDecl::getClassMethod(ASTContext &Context, Selector Sel) const {
|
||||
ObjCContainerDecl::getClassMethod(Selector Sel) const {
|
||||
// Since instance & class methods can have the same name, the loop below
|
||||
// ensures we get the correct method.
|
||||
//
|
||||
@ -88,8 +86,7 @@ ObjCContainerDecl::getClassMethod(ASTContext &Context, Selector Sel) const {
|
||||
// @end
|
||||
//
|
||||
lookup_const_iterator Meth, MethEnd;
|
||||
for (llvm::tie(Meth, MethEnd) = lookup(Context, Sel);
|
||||
Meth != MethEnd; ++Meth) {
|
||||
for (llvm::tie(Meth, MethEnd) = lookup(Sel); Meth != MethEnd; ++Meth) {
|
||||
ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(*Meth);
|
||||
if (MD && MD->isClassMethod())
|
||||
return MD;
|
||||
@ -102,10 +99,8 @@ ObjCContainerDecl::getClassMethod(ASTContext &Context, Selector Sel) const {
|
||||
/// FIXME: Convert to DeclContext lookup...
|
||||
///
|
||||
ObjCPropertyDecl *
|
||||
ObjCContainerDecl::FindPropertyDeclaration(ASTContext &Context,
|
||||
IdentifierInfo *PropertyId) const {
|
||||
for (prop_iterator I = prop_begin(Context), E = prop_end(Context);
|
||||
I != E; ++I)
|
||||
ObjCContainerDecl::FindPropertyDeclaration(IdentifierInfo *PropertyId) const {
|
||||
for (prop_iterator I = prop_begin(), E = prop_end(); I != E; ++I)
|
||||
if ((*I)->getIdentifier() == PropertyId)
|
||||
return *I;
|
||||
|
||||
@ -113,8 +108,7 @@ ObjCContainerDecl::FindPropertyDeclaration(ASTContext &Context,
|
||||
if (PID) {
|
||||
for (ObjCProtocolDecl::protocol_iterator I = PID->protocol_begin(),
|
||||
E = PID->protocol_end(); I != E; ++I)
|
||||
if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(Context,
|
||||
PropertyId))
|
||||
if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId))
|
||||
return P;
|
||||
}
|
||||
|
||||
@ -122,37 +116,33 @@ ObjCContainerDecl::FindPropertyDeclaration(ASTContext &Context,
|
||||
// Look through categories.
|
||||
for (ObjCCategoryDecl *Category = OID->getCategoryList();
|
||||
Category; Category = Category->getNextClassCategory()) {
|
||||
if (ObjCPropertyDecl *P = Category->FindPropertyDeclaration(Context,
|
||||
PropertyId))
|
||||
if (ObjCPropertyDecl *P = Category->FindPropertyDeclaration(PropertyId))
|
||||
return P;
|
||||
}
|
||||
// Look through protocols.
|
||||
for (ObjCInterfaceDecl::protocol_iterator I = OID->protocol_begin(),
|
||||
E = OID->protocol_end(); I != E; ++I) {
|
||||
if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(Context,
|
||||
PropertyId))
|
||||
if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId))
|
||||
return P;
|
||||
}
|
||||
if (OID->getSuperClass())
|
||||
return OID->getSuperClass()->FindPropertyDeclaration(Context,
|
||||
PropertyId);
|
||||
return OID->getSuperClass()->FindPropertyDeclaration(PropertyId);
|
||||
} else if (const ObjCCategoryDecl *OCD = dyn_cast<ObjCCategoryDecl>(this)) {
|
||||
// Look through protocols.
|
||||
for (ObjCInterfaceDecl::protocol_iterator I = OCD->protocol_begin(),
|
||||
E = OCD->protocol_end(); I != E; ++I) {
|
||||
if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(Context,
|
||||
PropertyId))
|
||||
if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId))
|
||||
return P;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ObjCIvarDecl *ObjCInterfaceDecl::lookupInstanceVariable(
|
||||
ASTContext &Context, IdentifierInfo *ID, ObjCInterfaceDecl *&clsDeclared) {
|
||||
ObjCIvarDecl *ObjCInterfaceDecl::lookupInstanceVariable(IdentifierInfo *ID,
|
||||
ObjCInterfaceDecl *&clsDeclared) {
|
||||
ObjCInterfaceDecl* ClassDecl = this;
|
||||
while (ClassDecl != NULL) {
|
||||
if (ObjCIvarDecl *I = ClassDecl->getIvarDecl(Context, ID)) {
|
||||
if (ObjCIvarDecl *I = ClassDecl->getIvarDecl(ID)) {
|
||||
clsDeclared = ClassDecl;
|
||||
return I;
|
||||
}
|
||||
@ -177,13 +167,12 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::lookupInheritedClass(
|
||||
|
||||
/// lookupInstanceMethod - This method returns an instance method by looking in
|
||||
/// the class, its categories, and its super classes (using a linear search).
|
||||
ObjCMethodDecl *ObjCInterfaceDecl::lookupInstanceMethod(ASTContext &Context,
|
||||
Selector Sel) {
|
||||
ObjCMethodDecl *ObjCInterfaceDecl::lookupInstanceMethod(Selector Sel) {
|
||||
ObjCInterfaceDecl* ClassDecl = this;
|
||||
ObjCMethodDecl *MethodDecl = 0;
|
||||
|
||||
while (ClassDecl != NULL) {
|
||||
if ((MethodDecl = ClassDecl->getInstanceMethod(Context, Sel)))
|
||||
if ((MethodDecl = ClassDecl->getInstanceMethod(Sel)))
|
||||
return MethodDecl;
|
||||
|
||||
// Didn't find one yet - look through protocols.
|
||||
@ -191,13 +180,13 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupInstanceMethod(ASTContext &Context,
|
||||
ClassDecl->getReferencedProtocols();
|
||||
for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
|
||||
E = Protocols.end(); I != E; ++I)
|
||||
if ((MethodDecl = (*I)->lookupInstanceMethod(Context, Sel)))
|
||||
if ((MethodDecl = (*I)->lookupInstanceMethod(Sel)))
|
||||
return MethodDecl;
|
||||
|
||||
// Didn't find one yet - now look through categories.
|
||||
ObjCCategoryDecl *CatDecl = ClassDecl->getCategoryList();
|
||||
while (CatDecl) {
|
||||
if ((MethodDecl = CatDecl->getInstanceMethod(Context, Sel)))
|
||||
if ((MethodDecl = CatDecl->getInstanceMethod(Sel)))
|
||||
return MethodDecl;
|
||||
|
||||
// Didn't find one yet - look through protocols.
|
||||
@ -205,7 +194,7 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupInstanceMethod(ASTContext &Context,
|
||||
CatDecl->getReferencedProtocols();
|
||||
for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
|
||||
E = Protocols.end(); I != E; ++I)
|
||||
if ((MethodDecl = (*I)->lookupInstanceMethod(Context, Sel)))
|
||||
if ((MethodDecl = (*I)->lookupInstanceMethod(Sel)))
|
||||
return MethodDecl;
|
||||
CatDecl = CatDecl->getNextClassCategory();
|
||||
}
|
||||
@ -216,25 +205,24 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupInstanceMethod(ASTContext &Context,
|
||||
|
||||
// lookupClassMethod - This method returns a class method by looking in the
|
||||
// class, its categories, and its super classes (using a linear search).
|
||||
ObjCMethodDecl *ObjCInterfaceDecl::lookupClassMethod(ASTContext &Context,
|
||||
Selector Sel) {
|
||||
ObjCMethodDecl *ObjCInterfaceDecl::lookupClassMethod(Selector Sel) {
|
||||
ObjCInterfaceDecl* ClassDecl = this;
|
||||
ObjCMethodDecl *MethodDecl = 0;
|
||||
|
||||
while (ClassDecl != NULL) {
|
||||
if ((MethodDecl = ClassDecl->getClassMethod(Context, Sel)))
|
||||
if ((MethodDecl = ClassDecl->getClassMethod(Sel)))
|
||||
return MethodDecl;
|
||||
|
||||
// Didn't find one yet - look through protocols.
|
||||
for (ObjCInterfaceDecl::protocol_iterator I = ClassDecl->protocol_begin(),
|
||||
E = ClassDecl->protocol_end(); I != E; ++I)
|
||||
if ((MethodDecl = (*I)->lookupClassMethod(Context, Sel)))
|
||||
if ((MethodDecl = (*I)->lookupClassMethod(Sel)))
|
||||
return MethodDecl;
|
||||
|
||||
// Didn't find one yet - now look through categories.
|
||||
ObjCCategoryDecl *CatDecl = ClassDecl->getCategoryList();
|
||||
while (CatDecl) {
|
||||
if ((MethodDecl = CatDecl->getClassMethod(Context, Sel)))
|
||||
if ((MethodDecl = CatDecl->getClassMethod(Sel)))
|
||||
return MethodDecl;
|
||||
|
||||
// Didn't find one yet - look through protocols.
|
||||
@ -242,7 +230,7 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupClassMethod(ASTContext &Context,
|
||||
CatDecl->getReferencedProtocols();
|
||||
for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
|
||||
E = Protocols.end(); I != E; ++I)
|
||||
if ((MethodDecl = (*I)->lookupClassMethod(Context, Sel)))
|
||||
if ((MethodDecl = (*I)->lookupClassMethod(Sel)))
|
||||
return MethodDecl;
|
||||
CatDecl = CatDecl->getNextClassCategory();
|
||||
}
|
||||
@ -446,30 +434,28 @@ ObjCProtocolDecl *ObjCProtocolDecl::lookupProtocolNamed(IdentifierInfo *Name) {
|
||||
|
||||
// lookupInstanceMethod - Lookup a instance method in the protocol and protocols
|
||||
// it inherited.
|
||||
ObjCMethodDecl *ObjCProtocolDecl::lookupInstanceMethod(ASTContext &Context,
|
||||
Selector Sel) {
|
||||
ObjCMethodDecl *ObjCProtocolDecl::lookupInstanceMethod(Selector Sel) {
|
||||
ObjCMethodDecl *MethodDecl = NULL;
|
||||
|
||||
if ((MethodDecl = getInstanceMethod(Context, Sel)))
|
||||
if ((MethodDecl = getInstanceMethod(Sel)))
|
||||
return MethodDecl;
|
||||
|
||||
for (protocol_iterator I = protocol_begin(), E = protocol_end(); I != E; ++I)
|
||||
if ((MethodDecl = (*I)->lookupInstanceMethod(Context, Sel)))
|
||||
if ((MethodDecl = (*I)->lookupInstanceMethod(Sel)))
|
||||
return MethodDecl;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// lookupInstanceMethod - Lookup a class method in the protocol and protocols
|
||||
// it inherited.
|
||||
ObjCMethodDecl *ObjCProtocolDecl::lookupClassMethod(ASTContext &Context,
|
||||
Selector Sel) {
|
||||
ObjCMethodDecl *ObjCProtocolDecl::lookupClassMethod(Selector Sel) {
|
||||
ObjCMethodDecl *MethodDecl = NULL;
|
||||
|
||||
if ((MethodDecl = getClassMethod(Context, Sel)))
|
||||
if ((MethodDecl = getClassMethod(Sel)))
|
||||
return MethodDecl;
|
||||
|
||||
for (protocol_iterator I = protocol_begin(), E = protocol_end(); I != E; ++I)
|
||||
if ((MethodDecl = (*I)->lookupClassMethod(Context, Sel)))
|
||||
if ((MethodDecl = (*I)->lookupClassMethod(Sel)))
|
||||
return MethodDecl;
|
||||
return NULL;
|
||||
}
|
||||
@ -555,11 +541,10 @@ ObjCCategoryImplDecl::Create(ASTContext &C, DeclContext *DC,
|
||||
}
|
||||
|
||||
|
||||
void ObjCImplDecl::addPropertyImplementation(ASTContext &Context,
|
||||
ObjCPropertyImplDecl *property) {
|
||||
void ObjCImplDecl::addPropertyImplementation(ObjCPropertyImplDecl *property) {
|
||||
// FIXME: The context should be correct before we get here.
|
||||
property->setLexicalDeclContext(this);
|
||||
addDecl(Context, property);
|
||||
addDecl(property);
|
||||
}
|
||||
|
||||
/// FindPropertyImplIvarDecl - This method lookup the ivar in the list of
|
||||
@ -567,9 +552,8 @@ void ObjCImplDecl::addPropertyImplementation(ASTContext &Context,
|
||||
/// the implemented property that uses it.
|
||||
///
|
||||
ObjCPropertyImplDecl *ObjCImplDecl::
|
||||
FindPropertyImplIvarDecl(ASTContext &Context, IdentifierInfo *ivarId) const {
|
||||
for (propimpl_iterator i = propimpl_begin(Context), e = propimpl_end(Context);
|
||||
i != e; ++i){
|
||||
FindPropertyImplIvarDecl(IdentifierInfo *ivarId) const {
|
||||
for (propimpl_iterator i = propimpl_begin(), e = propimpl_end(); i != e; ++i){
|
||||
ObjCPropertyImplDecl *PID = *i;
|
||||
if (PID->getPropertyIvarDecl() &&
|
||||
PID->getPropertyIvarDecl()->getIdentifier() == ivarId)
|
||||
@ -583,9 +567,8 @@ FindPropertyImplIvarDecl(ASTContext &Context, IdentifierInfo *ivarId) const {
|
||||
/// category @implementation block.
|
||||
///
|
||||
ObjCPropertyImplDecl *ObjCImplDecl::
|
||||
FindPropertyImplDecl(ASTContext &Context, IdentifierInfo *Id) const {
|
||||
for (propimpl_iterator i = propimpl_begin(Context), e = propimpl_end(Context);
|
||||
i != e; ++i){
|
||||
FindPropertyImplDecl(IdentifierInfo *Id) const {
|
||||
for (propimpl_iterator i = propimpl_begin(), e = propimpl_end(); i != e; ++i){
|
||||
ObjCPropertyImplDecl *PID = *i;
|
||||
if (PID->getPropertyDecl()->getIdentifier() == Id)
|
||||
return PID;
|
||||
@ -596,8 +579,7 @@ FindPropertyImplDecl(ASTContext &Context, IdentifierInfo *Id) const {
|
||||
// getInstanceMethod - This method returns an instance method by looking in
|
||||
// the class implementation. Unlike interfaces, we don't look outside the
|
||||
// implementation.
|
||||
ObjCMethodDecl *ObjCImplDecl::getInstanceMethod(ASTContext &Context,
|
||||
Selector Sel) const {
|
||||
ObjCMethodDecl *ObjCImplDecl::getInstanceMethod(Selector Sel) const {
|
||||
// Since instance & class methods can have the same name, the loop below
|
||||
// ensures we get the correct method.
|
||||
//
|
||||
@ -607,7 +589,7 @@ ObjCMethodDecl *ObjCImplDecl::getInstanceMethod(ASTContext &Context,
|
||||
// @end
|
||||
//
|
||||
lookup_const_iterator Meth, MethEnd;
|
||||
for (llvm::tie(Meth, MethEnd) = lookup(Context, Sel);
|
||||
for (llvm::tie(Meth, MethEnd) = lookup(Sel);
|
||||
Meth != MethEnd; ++Meth) {
|
||||
ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(*Meth);
|
||||
if (MD && MD->isInstanceMethod())
|
||||
@ -619,8 +601,7 @@ ObjCMethodDecl *ObjCImplDecl::getInstanceMethod(ASTContext &Context,
|
||||
// getClassMethod - This method returns an instance method by looking in
|
||||
// the class implementation. Unlike interfaces, we don't look outside the
|
||||
// implementation.
|
||||
ObjCMethodDecl *ObjCImplDecl::getClassMethod(ASTContext &Context,
|
||||
Selector Sel) const {
|
||||
ObjCMethodDecl *ObjCImplDecl::getClassMethod(Selector Sel) const {
|
||||
// Since instance & class methods can have the same name, the loop below
|
||||
// ensures we get the correct method.
|
||||
//
|
||||
@ -630,7 +611,7 @@ ObjCMethodDecl *ObjCImplDecl::getClassMethod(ASTContext &Context,
|
||||
// @end
|
||||
//
|
||||
lookup_const_iterator Meth, MethEnd;
|
||||
for (llvm::tie(Meth, MethEnd) = lookup(Context, Sel);
|
||||
for (llvm::tie(Meth, MethEnd) = lookup(Sel);
|
||||
Meth != MethEnd; ++Meth) {
|
||||
ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(*Meth);
|
||||
if (MD && MD->isClassMethod())
|
||||
|
@ -74,14 +74,13 @@ namespace {
|
||||
};
|
||||
}
|
||||
|
||||
void Decl::print(llvm::raw_ostream &Out, ASTContext &Context,
|
||||
unsigned Indentation) {
|
||||
print(Out, Context, Context.PrintingPolicy, Indentation);
|
||||
void Decl::print(llvm::raw_ostream &Out, unsigned Indentation) {
|
||||
print(Out, getASTContext().PrintingPolicy, Indentation);
|
||||
}
|
||||
|
||||
void Decl::print(llvm::raw_ostream &Out, ASTContext &Context,
|
||||
const PrintingPolicy &Policy, unsigned Indentation) {
|
||||
DeclPrinter Printer(Out, Context, Policy, Indentation);
|
||||
void Decl::print(llvm::raw_ostream &Out, const PrintingPolicy &Policy,
|
||||
unsigned Indentation) {
|
||||
DeclPrinter Printer(Out, getASTContext(), Policy, Indentation);
|
||||
Printer.Visit(this);
|
||||
}
|
||||
|
||||
@ -97,6 +96,8 @@ static QualType GetBaseType(QualType T) {
|
||||
BaseType = ATy->getElementType();
|
||||
else if (const FunctionType* FTy = BaseType->getAsFunctionType())
|
||||
BaseType = FTy->getResultType();
|
||||
else if (const VectorType *VTy = BaseType->getAsVectorType())
|
||||
BaseType = VTy->getElementType();
|
||||
else
|
||||
assert(0 && "Unknown declarator!");
|
||||
}
|
||||
@ -112,11 +113,10 @@ static QualType getDeclType(Decl* D) {
|
||||
}
|
||||
|
||||
void Decl::printGroup(Decl** Begin, unsigned NumDecls,
|
||||
llvm::raw_ostream &Out, ASTContext &Context,
|
||||
const PrintingPolicy &Policy,
|
||||
llvm::raw_ostream &Out, const PrintingPolicy &Policy,
|
||||
unsigned Indentation) {
|
||||
if (NumDecls == 1) {
|
||||
(*Begin)->print(Out, Context, Policy, Indentation);
|
||||
(*Begin)->print(Out, Policy, Indentation);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -127,7 +127,7 @@ void Decl::printGroup(Decl** Begin, unsigned NumDecls,
|
||||
|
||||
PrintingPolicy SubPolicy(Policy);
|
||||
if (TD && TD->isDefinition()) {
|
||||
TD->print(Out, Context, Policy, Indentation);
|
||||
TD->print(Out, Policy, Indentation);
|
||||
Out << " ";
|
||||
SubPolicy.SuppressTag = true;
|
||||
}
|
||||
@ -142,12 +142,12 @@ void Decl::printGroup(Decl** Begin, unsigned NumDecls,
|
||||
SubPolicy.SuppressSpecifiers = true;
|
||||
}
|
||||
|
||||
(*Begin)->print(Out, Context, SubPolicy, Indentation);
|
||||
(*Begin)->print(Out, SubPolicy, Indentation);
|
||||
}
|
||||
}
|
||||
|
||||
void Decl::dump(ASTContext &Context) {
|
||||
print(llvm::errs(), Context);
|
||||
void Decl::dump() {
|
||||
print(llvm::errs());
|
||||
}
|
||||
|
||||
llvm::raw_ostream& DeclPrinter::Indent() {
|
||||
@ -158,8 +158,7 @@ llvm::raw_ostream& DeclPrinter::Indent() {
|
||||
|
||||
void DeclPrinter::ProcessDeclGroup(llvm::SmallVectorImpl<Decl*>& Decls) {
|
||||
this->Indent();
|
||||
Decl::printGroup(Decls.data(), Decls.size(), Out, Context,
|
||||
Policy, Indentation);
|
||||
Decl::printGroup(Decls.data(), Decls.size(), Out, Policy, Indentation);
|
||||
Out << ";\n";
|
||||
Decls.clear();
|
||||
|
||||
@ -174,8 +173,7 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) {
|
||||
Indentation += Policy.Indentation;
|
||||
|
||||
llvm::SmallVector<Decl*, 2> Decls;
|
||||
for (DeclContext::decl_iterator D = DC->decls_begin(Context),
|
||||
DEnd = DC->decls_end(Context);
|
||||
for (DeclContext::decl_iterator D = DC->decls_begin(), DEnd = DC->decls_end();
|
||||
D != DEnd; ++D) {
|
||||
if (!Policy.Dump) {
|
||||
// Skip over implicit declarations in pretty-printing mode.
|
||||
@ -364,7 +362,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
|
||||
} else
|
||||
Out << ' ';
|
||||
|
||||
D->getBody(Context)->printPretty(Out, Context, 0, SubPolicy, Indentation);
|
||||
D->getBody()->printPretty(Out, Context, 0, SubPolicy, Indentation);
|
||||
Out << '\n';
|
||||
}
|
||||
}
|
||||
@ -504,7 +502,7 @@ void DeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
|
||||
VisitDeclContext(D);
|
||||
Indent() << "}";
|
||||
} else
|
||||
Visit(*D->decls_begin(Context));
|
||||
Visit(*D->decls_begin());
|
||||
}
|
||||
|
||||
void DeclPrinter::VisitTemplateDecl(TemplateDecl *D) {
|
||||
|
@ -81,11 +81,36 @@ FunctionTemplateDecl *FunctionTemplateDecl::Create(ASTContext &C,
|
||||
DeclContext *DC,
|
||||
SourceLocation L,
|
||||
DeclarationName Name,
|
||||
TemplateParameterList *Params,
|
||||
TemplateParameterList *Params,
|
||||
NamedDecl *Decl) {
|
||||
return new (C) FunctionTemplateDecl(DC, L, Name, Params, Decl);
|
||||
}
|
||||
|
||||
void FunctionTemplateDecl::Destroy(ASTContext &C) {
|
||||
if (Common *CommonPtr = CommonOrPrev.dyn_cast<Common*>()) {
|
||||
for (llvm::FoldingSet<FunctionTemplateSpecializationInfo>::iterator
|
||||
Spec = CommonPtr->Specializations.begin(),
|
||||
SpecEnd = CommonPtr->Specializations.end();
|
||||
Spec != SpecEnd; ++Spec)
|
||||
C.Deallocate(&*Spec);
|
||||
}
|
||||
|
||||
Decl::Destroy(C);
|
||||
}
|
||||
|
||||
FunctionTemplateDecl::Common *FunctionTemplateDecl::getCommonPtr() {
|
||||
// Find the first declaration of this function template.
|
||||
FunctionTemplateDecl *First = this;
|
||||
while (First->getPreviousDeclaration())
|
||||
First = First->getPreviousDeclaration();
|
||||
|
||||
if (First->CommonOrPrev.isNull()) {
|
||||
// FIXME: Allocate with the ASTContext
|
||||
First->CommonOrPrev = new Common;
|
||||
}
|
||||
return First->CommonOrPrev.get<Common*>();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ClassTemplateDecl Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -41,8 +41,7 @@ CharacterLiteral* CharacterLiteral::Clone(ASTContext &C) const {
|
||||
}
|
||||
|
||||
FloatingLiteral* FloatingLiteral::Clone(ASTContext &C) const {
|
||||
bool exact = IsExact;
|
||||
return new (C) FloatingLiteral(Value, &exact, getType(), Loc);
|
||||
return new (C) FloatingLiteral(Value, IsExact, getType(), Loc);
|
||||
}
|
||||
|
||||
ImaginaryLiteral* ImaginaryLiteral::Clone(ASTContext &C) const {
|
||||
@ -456,7 +455,7 @@ Stmt *BlockExpr::getBody() {
|
||||
/// with location to warn on and the source range[s] to report with the
|
||||
/// warning.
|
||||
bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
|
||||
SourceRange &R2, ASTContext &Context) const {
|
||||
SourceRange &R2) const {
|
||||
// Don't warn if the expr is type dependent. The type could end up
|
||||
// instantiating to void.
|
||||
if (isTypeDependent())
|
||||
@ -469,7 +468,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
|
||||
return true;
|
||||
case ParenExprClass:
|
||||
return cast<ParenExpr>(this)->getSubExpr()->
|
||||
isUnusedResultAWarning(Loc, R1, R2, Context);
|
||||
isUnusedResultAWarning(Loc, R1, R2);
|
||||
case UnaryOperatorClass: {
|
||||
const UnaryOperator *UO = cast<UnaryOperator>(this);
|
||||
|
||||
@ -492,7 +491,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
|
||||
return false;
|
||||
break;
|
||||
case UnaryOperator::Extension:
|
||||
return UO->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Context);
|
||||
return UO->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2);
|
||||
}
|
||||
Loc = UO->getOperatorLoc();
|
||||
R1 = UO->getSubExpr()->getSourceRange();
|
||||
@ -502,8 +501,8 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
|
||||
const BinaryOperator *BO = cast<BinaryOperator>(this);
|
||||
// Consider comma to have side effects if the LHS or RHS does.
|
||||
if (BO->getOpcode() == BinaryOperator::Comma)
|
||||
return BO->getRHS()->isUnusedResultAWarning(Loc, R1, R2, Context) ||
|
||||
BO->getLHS()->isUnusedResultAWarning(Loc, R1, R2, Context);
|
||||
return BO->getRHS()->isUnusedResultAWarning(Loc, R1, R2) ||
|
||||
BO->getLHS()->isUnusedResultAWarning(Loc, R1, R2);
|
||||
|
||||
if (BO->isAssignmentOp())
|
||||
return false;
|
||||
@ -520,9 +519,9 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
|
||||
// warning, warn about them.
|
||||
const ConditionalOperator *Exp = cast<ConditionalOperator>(this);
|
||||
if (Exp->getLHS() &&
|
||||
Exp->getLHS()->isUnusedResultAWarning(Loc, R1, R2, Context))
|
||||
Exp->getLHS()->isUnusedResultAWarning(Loc, R1, R2))
|
||||
return true;
|
||||
return Exp->getRHS()->isUnusedResultAWarning(Loc, R1, R2, Context);
|
||||
return Exp->getRHS()->isUnusedResultAWarning(Loc, R1, R2);
|
||||
}
|
||||
|
||||
case MemberExprClass:
|
||||
@ -555,8 +554,8 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
|
||||
// If the callee has attribute pure, const, or warn_unused_result, warn
|
||||
// about it. void foo() { strlen("bar"); } should warn.
|
||||
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CalleeDRE->getDecl()))
|
||||
if (FD->getAttr<WarnUnusedResultAttr>(Context) ||
|
||||
FD->getAttr<PureAttr>(Context) || FD->getAttr<ConstAttr>(Context)) {
|
||||
if (FD->getAttr<WarnUnusedResultAttr>() ||
|
||||
FD->getAttr<PureAttr>() || FD->getAttr<ConstAttr>()) {
|
||||
Loc = CE->getCallee()->getLocStart();
|
||||
R1 = CE->getCallee()->getSourceRange();
|
||||
|
||||
@ -579,7 +578,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
|
||||
const CompoundStmt *CS = cast<StmtExpr>(this)->getSubStmt();
|
||||
if (!CS->body_empty())
|
||||
if (const Expr *E = dyn_cast<Expr>(CS->body_back()))
|
||||
return E->isUnusedResultAWarning(Loc, R1, R2, Context);
|
||||
return E->isUnusedResultAWarning(Loc, R1, R2);
|
||||
|
||||
Loc = cast<StmtExpr>(this)->getLParenLoc();
|
||||
R1 = getSourceRange();
|
||||
@ -590,7 +589,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
|
||||
// the cast is unused.
|
||||
if (getType()->isVoidType())
|
||||
return cast<CastExpr>(this)->getSubExpr()
|
||||
->isUnusedResultAWarning(Loc, R1, R2, Context);
|
||||
->isUnusedResultAWarning(Loc, R1, R2);
|
||||
Loc = cast<CStyleCastExpr>(this)->getLParenLoc();
|
||||
R1 = cast<CStyleCastExpr>(this)->getSubExpr()->getSourceRange();
|
||||
return true;
|
||||
@ -599,7 +598,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
|
||||
// the cast is unused.
|
||||
if (getType()->isVoidType())
|
||||
return cast<CastExpr>(this)->getSubExpr()
|
||||
->isUnusedResultAWarning(Loc, R1, R2, Context);
|
||||
->isUnusedResultAWarning(Loc, R1, R2);
|
||||
Loc = cast<CXXFunctionalCastExpr>(this)->getTypeBeginLoc();
|
||||
R1 = cast<CXXFunctionalCastExpr>(this)->getSubExpr()->getSourceRange();
|
||||
return true;
|
||||
@ -607,11 +606,11 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
|
||||
case ImplicitCastExprClass:
|
||||
// Check the operand, since implicit casts are inserted by Sema
|
||||
return cast<ImplicitCastExpr>(this)
|
||||
->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Context);
|
||||
->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2);
|
||||
|
||||
case CXXDefaultArgExprClass:
|
||||
return cast<CXXDefaultArgExpr>(this)
|
||||
->getExpr()->isUnusedResultAWarning(Loc, R1, R2, Context);
|
||||
->getExpr()->isUnusedResultAWarning(Loc, R1, R2);
|
||||
|
||||
case CXXNewExprClass:
|
||||
// FIXME: In theory, there might be new expressions that don't have side
|
||||
@ -620,7 +619,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
|
||||
return false;
|
||||
case CXXExprWithTemporariesClass:
|
||||
return cast<CXXExprWithTemporaries>(this)
|
||||
->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Context);
|
||||
->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
#include "clang/Basic/IdentifierTable.h"
|
||||
#include "clang/AST/DeclCXX.h"
|
||||
#include "clang/AST/DeclTemplate.h"
|
||||
#include "clang/AST/ExprCXX.h"
|
||||
using namespace clang;
|
||||
|
||||
@ -153,6 +154,65 @@ StmtIterator UnresolvedDeclRefExpr::child_end() {
|
||||
return child_iterator();
|
||||
}
|
||||
|
||||
TemplateIdRefExpr::TemplateIdRefExpr(QualType T,
|
||||
NestedNameSpecifier *Qualifier,
|
||||
SourceRange QualifierRange,
|
||||
TemplateName Template,
|
||||
SourceLocation TemplateNameLoc,
|
||||
SourceLocation LAngleLoc,
|
||||
const TemplateArgument *TemplateArgs,
|
||||
unsigned NumTemplateArgs,
|
||||
SourceLocation RAngleLoc)
|
||||
: Expr(TemplateIdRefExprClass, T,
|
||||
(Template.isDependent() ||
|
||||
TemplateSpecializationType::anyDependentTemplateArguments(
|
||||
TemplateArgs, NumTemplateArgs)),
|
||||
(Template.isDependent() ||
|
||||
TemplateSpecializationType::anyDependentTemplateArguments(
|
||||
TemplateArgs, NumTemplateArgs))),
|
||||
Qualifier(Qualifier), QualifierRange(QualifierRange), Template(Template),
|
||||
TemplateNameLoc(TemplateNameLoc), LAngleLoc(LAngleLoc),
|
||||
RAngleLoc(RAngleLoc), NumTemplateArgs(NumTemplateArgs)
|
||||
|
||||
{
|
||||
TemplateArgument *StoredTemplateArgs
|
||||
= reinterpret_cast<TemplateArgument *> (this+1);
|
||||
for (unsigned I = 0; I != NumTemplateArgs; ++I)
|
||||
new (StoredTemplateArgs + I) TemplateArgument(TemplateArgs[I]);
|
||||
}
|
||||
|
||||
TemplateIdRefExpr *
|
||||
TemplateIdRefExpr::Create(ASTContext &Context, QualType T,
|
||||
NestedNameSpecifier *Qualifier,
|
||||
SourceRange QualifierRange,
|
||||
TemplateName Template, SourceLocation TemplateNameLoc,
|
||||
SourceLocation LAngleLoc,
|
||||
const TemplateArgument *TemplateArgs,
|
||||
unsigned NumTemplateArgs, SourceLocation RAngleLoc) {
|
||||
void *Mem = Context.Allocate(sizeof(TemplateIdRefExpr) +
|
||||
sizeof(TemplateArgument) * NumTemplateArgs);
|
||||
return new (Mem) TemplateIdRefExpr(T, Qualifier, QualifierRange, Template,
|
||||
TemplateNameLoc, LAngleLoc, TemplateArgs,
|
||||
NumTemplateArgs, RAngleLoc);
|
||||
}
|
||||
|
||||
void TemplateIdRefExpr::Destroy(ASTContext &Context) {
|
||||
const TemplateArgument *TemplateArgs = getTemplateArgs();
|
||||
for (unsigned I = 0; I != NumTemplateArgs; ++I)
|
||||
if (Expr *E = TemplateArgs[I].getAsExpr())
|
||||
E->Destroy(Context);
|
||||
}
|
||||
|
||||
Stmt::child_iterator TemplateIdRefExpr::child_begin() {
|
||||
// FIXME: Walk the expressions in the template arguments (?)
|
||||
return Stmt::child_iterator();
|
||||
}
|
||||
|
||||
Stmt::child_iterator TemplateIdRefExpr::child_end() {
|
||||
// FIXME: Walk the expressions in the template arguments (?)
|
||||
return Stmt::child_iterator();
|
||||
}
|
||||
|
||||
bool UnaryTypeTraitExpr::EvaluateTrait() const {
|
||||
switch(UTT) {
|
||||
default: assert(false && "Unknown type trait or not implemented");
|
||||
|
@ -242,8 +242,8 @@ APValue LValueExprEvaluator::VisitMemberExpr(MemberExpr *E) {
|
||||
|
||||
// FIXME: This is linear time.
|
||||
unsigned i = 0;
|
||||
for (RecordDecl::field_iterator Field = RD->field_begin(Info.Ctx),
|
||||
FieldEnd = RD->field_end(Info.Ctx);
|
||||
for (RecordDecl::field_iterator Field = RD->field_begin(),
|
||||
FieldEnd = RD->field_end();
|
||||
Field != FieldEnd; (void)++Field, ++i) {
|
||||
if (*Field == FD)
|
||||
break;
|
||||
@ -485,6 +485,11 @@ static bool EvaluateVector(const Expr* E, APValue& Result, EvalInfo &Info) {
|
||||
}
|
||||
|
||||
APValue VectorExprEvaluator::VisitCastExpr(const CastExpr* E) {
|
||||
const VectorType *VTy = E->getType()->getAsVectorType();
|
||||
QualType EltTy = VTy->getElementType();
|
||||
unsigned NElts = VTy->getNumElements();
|
||||
unsigned EltWidth = Info.Ctx.getTypeSize(EltTy);
|
||||
|
||||
const Expr* SE = E->getSubExpr();
|
||||
QualType SETy = SE->getType();
|
||||
APValue Result = APValue();
|
||||
@ -494,20 +499,62 @@ APValue VectorExprEvaluator::VisitCastExpr(const CastExpr* E) {
|
||||
return this->Visit(const_cast<Expr*>(SE));
|
||||
} else if (SETy->isIntegerType()) {
|
||||
APSInt IntResult;
|
||||
if (EvaluateInteger(SE, IntResult, Info))
|
||||
Result = APValue(IntResult);
|
||||
if (!EvaluateInteger(SE, IntResult, Info))
|
||||
return APValue();
|
||||
Result = APValue(IntResult);
|
||||
} else if (SETy->isRealFloatingType()) {
|
||||
APFloat F(0.0);
|
||||
if (EvaluateFloat(SE, F, Info))
|
||||
Result = APValue(F);
|
||||
if (!EvaluateFloat(SE, F, Info))
|
||||
return APValue();
|
||||
Result = APValue(F);
|
||||
} else
|
||||
return APValue();
|
||||
|
||||
// For casts of a scalar to ExtVector, convert the scalar to the element type
|
||||
// and splat it to all elements.
|
||||
if (E->getType()->isExtVectorType()) {
|
||||
if (EltTy->isIntegerType() && Result.isInt())
|
||||
Result = APValue(HandleIntToIntCast(EltTy, SETy, Result.getInt(),
|
||||
Info.Ctx));
|
||||
else if (EltTy->isIntegerType())
|
||||
Result = APValue(HandleFloatToIntCast(EltTy, SETy, Result.getFloat(),
|
||||
Info.Ctx));
|
||||
else if (EltTy->isRealFloatingType() && Result.isInt())
|
||||
Result = APValue(HandleIntToFloatCast(EltTy, SETy, Result.getInt(),
|
||||
Info.Ctx));
|
||||
else if (EltTy->isRealFloatingType())
|
||||
Result = APValue(HandleFloatToFloatCast(EltTy, SETy, Result.getFloat(),
|
||||
Info.Ctx));
|
||||
else
|
||||
return APValue();
|
||||
|
||||
// Splat and create vector APValue.
|
||||
llvm::SmallVector<APValue, 4> Elts(NElts, Result);
|
||||
return APValue(&Elts[0], Elts.size());
|
||||
}
|
||||
|
||||
if (Result.isInt() || Result.isFloat()) {
|
||||
unsigned NumElts = E->getType()->getAsVectorType()->getNumElements();
|
||||
llvm::SmallVector<APValue, 4> Elts(NumElts, Result);
|
||||
Result = APValue(&Elts[0], Elts.size());
|
||||
// For casts of a scalar to regular gcc-style vector type, bitcast the scalar
|
||||
// to the vector. To construct the APValue vector initializer, bitcast the
|
||||
// initializing value to an APInt, and shift out the bits pertaining to each
|
||||
// element.
|
||||
APSInt Init;
|
||||
Init = Result.isInt() ? Result.getInt() : Result.getFloat().bitcastToAPInt();
|
||||
|
||||
llvm::SmallVector<APValue, 4> Elts;
|
||||
for (unsigned i = 0; i != NElts; ++i) {
|
||||
APSInt Tmp = Init;
|
||||
Tmp.extOrTrunc(EltWidth);
|
||||
|
||||
if (EltTy->isIntegerType())
|
||||
Elts.push_back(APValue(Tmp));
|
||||
else if (EltTy->isRealFloatingType())
|
||||
Elts.push_back(APValue(APFloat(Tmp)));
|
||||
else
|
||||
return APValue();
|
||||
|
||||
Init >>= EltWidth;
|
||||
}
|
||||
return Result;
|
||||
return APValue(&Elts[0], Elts.size());
|
||||
}
|
||||
|
||||
APValue
|
||||
|
@ -153,8 +153,6 @@ void NestedNameSpecifier::Destroy(ASTContext &Context) {
|
||||
Context.Deallocate((void *)this);
|
||||
}
|
||||
|
||||
void NestedNameSpecifier::dump() {
|
||||
PrintingPolicy Policy;
|
||||
Policy.CPlusPlus = true;
|
||||
print(llvm::errs(), Policy);
|
||||
void NestedNameSpecifier::dump(const LangOptions &LO) {
|
||||
print(llvm::errs(), PrintingPolicy(LO));
|
||||
}
|
||||
|
@ -41,7 +41,6 @@ namespace {
|
||||
const char *LastLocFilename;
|
||||
unsigned LastLocLine;
|
||||
|
||||
PrintingPolicy Policy;
|
||||
public:
|
||||
StmtDumper(SourceManager *sm, FILE *f, unsigned maxDepth)
|
||||
: SM(sm), F(f), IndentLevel(0-1), MaxDepth(maxDepth) {
|
||||
@ -226,7 +225,8 @@ void StmtDumper::DumpDeclarator(Decl *D) {
|
||||
}
|
||||
|
||||
std::string Name = VD->getNameAsString();
|
||||
VD->getType().getAsStringInternal(Name, Policy);
|
||||
VD->getType().getAsStringInternal(Name,
|
||||
PrintingPolicy(VD->getASTContext().getLangOptions()));
|
||||
fprintf(F, "%s", Name.c_str());
|
||||
|
||||
// If this is a vardecl with an initializer, emit it.
|
||||
|
@ -35,7 +35,7 @@ namespace {
|
||||
|
||||
public:
|
||||
StmtPrinter(llvm::raw_ostream &os, ASTContext &C, PrinterHelper* helper,
|
||||
const PrintingPolicy &Policy = PrintingPolicy(),
|
||||
const PrintingPolicy &Policy,
|
||||
unsigned Indentation = 0)
|
||||
: OS(os), Context(C), IndentLevel(Indentation), Helper(helper),
|
||||
Policy(Policy) {}
|
||||
@ -114,7 +114,7 @@ void StmtPrinter::PrintRawCompoundStmt(CompoundStmt *Node) {
|
||||
}
|
||||
|
||||
void StmtPrinter::PrintRawDecl(Decl *D) {
|
||||
D->print(OS, Context, Policy, IndentLevel);
|
||||
D->print(OS, Policy, IndentLevel);
|
||||
}
|
||||
|
||||
void StmtPrinter::PrintRawDeclStmt(DeclStmt *S) {
|
||||
@ -123,8 +123,7 @@ void StmtPrinter::PrintRawDeclStmt(DeclStmt *S) {
|
||||
for ( ; Begin != End; ++Begin)
|
||||
Decls.push_back(*Begin);
|
||||
|
||||
Decl::printGroup(Decls.data(), Decls.size(), OS, Context, Policy,
|
||||
IndentLevel);
|
||||
Decl::printGroup(Decls.data(), Decls.size(), OS, Policy, IndentLevel);
|
||||
}
|
||||
|
||||
void StmtPrinter::VisitNullStmt(NullStmt *Node) {
|
||||
@ -491,6 +490,18 @@ void StmtPrinter::VisitUnresolvedDeclRefExpr(UnresolvedDeclRefExpr *Node) {
|
||||
OS << Node->getDeclName().getAsString();
|
||||
}
|
||||
|
||||
void StmtPrinter::VisitTemplateIdRefExpr(TemplateIdRefExpr *Node) {
|
||||
if (Node->getQualifier())
|
||||
Node->getQualifier()->print(OS, Policy);
|
||||
Node->getTemplateName().print(OS, Policy, true);
|
||||
OS << '<';
|
||||
OS << TemplateSpecializationType::PrintTemplateArgumentList(
|
||||
Node->getTemplateArgs(),
|
||||
Node->getNumTemplateArgs(),
|
||||
Policy);
|
||||
OS << '>';
|
||||
}
|
||||
|
||||
void StmtPrinter::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) {
|
||||
if (Node->getBase()) {
|
||||
PrintExpr(Node->getBase());
|
||||
@ -861,7 +872,7 @@ void StmtPrinter::VisitDesignatedInitExpr(DesignatedInitExpr *Node) {
|
||||
}
|
||||
|
||||
void StmtPrinter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *Node) {
|
||||
if (Policy.CPlusPlus)
|
||||
if (Policy.LangOpts.CPlusPlus)
|
||||
OS << "/*implicit*/" << Node->getType().getAsString(Policy) << "()";
|
||||
else {
|
||||
OS << "/*implicit*/(" << Node->getType().getAsString(Policy) << ")";
|
||||
@ -1216,7 +1227,8 @@ void StmtPrinter::VisitBlockDeclRefExpr(BlockDeclRefExpr *Node) {
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void Stmt::dumpPretty(ASTContext& Context) const {
|
||||
printPretty(llvm::errs(), Context, 0, PrintingPolicy());
|
||||
printPretty(llvm::errs(), Context, 0,
|
||||
PrintingPolicy(Context.getLangOptions()));
|
||||
}
|
||||
|
||||
void Stmt::printPretty(llvm::raw_ostream &OS, ASTContext& Context,
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "clang/AST/DeclTemplate.h"
|
||||
#include "clang/AST/NestedNameSpecifier.h"
|
||||
#include "clang/AST/PrettyPrinter.h"
|
||||
#include "clang/Basic/LangOptions.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
using namespace clang;
|
||||
|
||||
@ -59,7 +60,8 @@ TemplateName::print(llvm::raw_ostream &OS, const PrintingPolicy &Policy,
|
||||
}
|
||||
|
||||
void TemplateName::dump() const {
|
||||
PrintingPolicy Policy;
|
||||
Policy.CPlusPlus = true;
|
||||
print(llvm::errs(), Policy);
|
||||
LangOptions LO; // FIXME!
|
||||
LO.CPlusPlus = true;
|
||||
LO.Bool = true;
|
||||
print(llvm::errs(), PrintingPolicy(LO));
|
||||
}
|
||||
|
@ -185,6 +185,12 @@ bool Type::isStructureType() const {
|
||||
return RT->getDecl()->isStruct();
|
||||
return false;
|
||||
}
|
||||
bool Type::isVoidPointerType() const {
|
||||
if (const PointerType *PT = getAsPointerType())
|
||||
return PT->getPointeeType()->isVoidType();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Type::isUnionType() const {
|
||||
if (const RecordType *RT = getAsRecordType())
|
||||
return RT->getDecl()->isUnion();
|
||||
@ -938,11 +944,11 @@ bool Type::isSpecifierType() const {
|
||||
}
|
||||
}
|
||||
|
||||
const char *BuiltinType::getName(bool CPlusPlus) const {
|
||||
const char *BuiltinType::getName(const LangOptions &LO) const {
|
||||
switch (getKind()) {
|
||||
default: assert(0 && "Unknown builtin type!");
|
||||
case Void: return "void";
|
||||
case Bool: return CPlusPlus? "bool" : "_Bool";
|
||||
case Bool: return LO.Bool ? "bool" : "_Bool";
|
||||
case Char_S: return "char";
|
||||
case Char_U: return "char";
|
||||
case SChar: return "signed char";
|
||||
@ -1160,9 +1166,9 @@ TemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID,
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void QualType::dump(const char *msg) const {
|
||||
PrintingPolicy Policy;
|
||||
std::string R = "identifier";
|
||||
getAsStringInternal(R, Policy);
|
||||
LangOptions LO;
|
||||
getAsStringInternal(R, PrintingPolicy(LO));
|
||||
if (msg)
|
||||
fprintf(stderr, "%s: %s\n", msg, R.c_str());
|
||||
else
|
||||
@ -1174,7 +1180,8 @@ void QualType::dump() const {
|
||||
|
||||
void Type::dump() const {
|
||||
std::string S = "identifier";
|
||||
getAsStringInternal(S, PrintingPolicy());
|
||||
LangOptions LO;
|
||||
getAsStringInternal(S, PrintingPolicy(LO));
|
||||
fprintf(stderr, "%s\n", S.c_str());
|
||||
}
|
||||
|
||||
@ -1193,7 +1200,8 @@ static void AppendTypeQualList(std::string &S, unsigned TypeQuals) {
|
||||
|
||||
std::string QualType::getAsString() const {
|
||||
std::string S;
|
||||
getAsStringInternal(S, PrintingPolicy());
|
||||
LangOptions LO;
|
||||
getAsStringInternal(S, PrintingPolicy(LO));
|
||||
return S;
|
||||
}
|
||||
|
||||
@ -1224,11 +1232,11 @@ QualType::getAsStringInternal(std::string &S,
|
||||
void BuiltinType::getAsStringInternal(std::string &S,
|
||||
const PrintingPolicy &Policy) const {
|
||||
if (S.empty()) {
|
||||
S = getName(Policy.CPlusPlus);
|
||||
S = getName(Policy.LangOpts);
|
||||
} else {
|
||||
// Prefix the basic type, e.g. 'int X'.
|
||||
S = ' ' + S;
|
||||
S = getName(Policy.CPlusPlus) + S;
|
||||
S = getName(Policy.LangOpts) + S;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1470,7 +1478,7 @@ void FunctionProtoType::getAsStringInternal(std::string &S, const PrintingPolicy
|
||||
if (getNumArgs())
|
||||
S += ", ";
|
||||
S += "...";
|
||||
} else if (getNumArgs() == 0 && !Policy.CPlusPlus) {
|
||||
} else if (getNumArgs() == 0 && !Policy.LangOpts.CPlusPlus) {
|
||||
// Do not emit int() if we have a proto, emit 'int(void)'.
|
||||
S += "void";
|
||||
}
|
||||
|
@ -198,7 +198,7 @@ SVal BasicStoreManager::getLValueElement(const GRState *state,
|
||||
return Base;
|
||||
|
||||
Loc BaseL = cast<Loc>(Base);
|
||||
const TypedRegion* BaseR = 0;
|
||||
const MemRegion* BaseR = 0;
|
||||
|
||||
switch(BaseL.getSubKind()) {
|
||||
case loc::GotoLabelKind:
|
||||
@ -216,17 +216,11 @@ SVal BasicStoreManager::getLValueElement(const GRState *state,
|
||||
return Base;
|
||||
}
|
||||
|
||||
|
||||
if (const TypedRegion *TR = dyn_cast<TypedRegion>(R)) {
|
||||
BaseR = TR;
|
||||
if (isa<TypedRegion>(R) || isa<SymbolicRegion>(R)) {
|
||||
BaseR = R;
|
||||
break;
|
||||
}
|
||||
|
||||
if (const SymbolicRegion* SR = dyn_cast<SymbolicRegion>(R)) {
|
||||
SymbolRef Sym = SR->getSymbol();
|
||||
BaseR = MRMgr.getTypedViewRegion(Sym->getType(getContext()), SR);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@ -242,9 +236,10 @@ SVal BasicStoreManager::getLValueElement(const GRState *state,
|
||||
return Base;
|
||||
}
|
||||
|
||||
if (BaseR)
|
||||
if (BaseR) {
|
||||
return ValMgr.makeLoc(MRMgr.getElementRegion(elementType, UnknownVal(),
|
||||
BaseR, getContext()));
|
||||
}
|
||||
else
|
||||
return UnknownVal();
|
||||
}
|
||||
@ -319,54 +314,50 @@ SVal BasicStoreManager::Retrieve(const GRState *state, Loc loc, QualType T) {
|
||||
}
|
||||
|
||||
Store BasicStoreManager::BindInternal(Store store, Loc loc, SVal V) {
|
||||
switch (loc.getSubKind()) {
|
||||
case loc::MemRegionKind: {
|
||||
const MemRegion* R = cast<loc::MemRegionVal>(loc).getRegion();
|
||||
ASTContext &C = StateMgr.getContext();
|
||||
|
||||
// Special case: handle store of pointer values (Loc) to pointers via
|
||||
// a cast to intXX_t*, void*, etc. This is needed to handle
|
||||
// OSCompareAndSwap32Barrier/OSCompareAndSwap64Barrier.
|
||||
if (isa<Loc>(V) || isa<nonloc::LocAsInteger>(V))
|
||||
if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
|
||||
// FIXME: Should check for index 0.
|
||||
QualType T = ER->getLocationType(C);
|
||||
|
||||
if (isHigherOrderRawPtr(T, C))
|
||||
R = ER->getSuperRegion();
|
||||
}
|
||||
|
||||
if (!(isa<VarRegion>(R) || isa<ObjCIvarRegion>(R)))
|
||||
return store;
|
||||
|
||||
// We only track bindings to self.ivar.
|
||||
if (const ObjCIvarRegion *IVR = dyn_cast<ObjCIvarRegion>(R))
|
||||
if (IVR->getSuperRegion() != SelfRegion)
|
||||
return store;
|
||||
|
||||
if (nonloc::LocAsInteger *X = dyn_cast<nonloc::LocAsInteger>(&V)) {
|
||||
// Only convert 'V' to a location iff the underlying region type
|
||||
// is a location as well.
|
||||
// FIXME: We are allowing a store of an arbitrary location to
|
||||
// a pointer. We may wish to flag a type error here if the types
|
||||
// are incompatible. This may also cause lots of breakage
|
||||
// elsewhere. Food for thought.
|
||||
if (const TypedRegion *TyR = dyn_cast<TypedRegion>(R)) {
|
||||
if (TyR->isBoundable() &&
|
||||
Loc::IsLocType(TyR->getValueType(C)))
|
||||
V = X->getLoc();
|
||||
}
|
||||
}
|
||||
if (isa<loc::ConcreteInt>(loc))
|
||||
return store;
|
||||
|
||||
BindingsTy B = GetBindings(store);
|
||||
return V.isUnknown()
|
||||
? VBFactory.Remove(B, R).getRoot()
|
||||
: VBFactory.Add(B, R, V).getRoot();
|
||||
}
|
||||
default:
|
||||
assert ("SetSVal for given Loc type not yet implemented.");
|
||||
const MemRegion* R = cast<loc::MemRegionVal>(loc).getRegion();
|
||||
ASTContext &C = StateMgr.getContext();
|
||||
|
||||
// Special case: handle store of pointer values (Loc) to pointers via
|
||||
// a cast to intXX_t*, void*, etc. This is needed to handle
|
||||
// OSCompareAndSwap32Barrier/OSCompareAndSwap64Barrier.
|
||||
if (isa<Loc>(V) || isa<nonloc::LocAsInteger>(V))
|
||||
if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
|
||||
// FIXME: Should check for index 0.
|
||||
QualType T = ER->getLocationType(C);
|
||||
|
||||
if (isHigherOrderRawPtr(T, C))
|
||||
R = ER->getSuperRegion();
|
||||
}
|
||||
|
||||
if (!(isa<VarRegion>(R) || isa<ObjCIvarRegion>(R)))
|
||||
return store;
|
||||
|
||||
// We only track bindings to self.ivar.
|
||||
if (const ObjCIvarRegion *IVR = dyn_cast<ObjCIvarRegion>(R))
|
||||
if (IVR->getSuperRegion() != SelfRegion)
|
||||
return store;
|
||||
|
||||
if (nonloc::LocAsInteger *X = dyn_cast<nonloc::LocAsInteger>(&V)) {
|
||||
// Only convert 'V' to a location iff the underlying region type
|
||||
// is a location as well.
|
||||
// FIXME: We are allowing a store of an arbitrary location to
|
||||
// a pointer. We may wish to flag a type error here if the types
|
||||
// are incompatible. This may also cause lots of breakage
|
||||
// elsewhere. Food for thought.
|
||||
if (const TypedRegion *TyR = dyn_cast<TypedRegion>(R)) {
|
||||
if (TyR->isBoundable() &&
|
||||
Loc::IsLocType(TyR->getValueType(C)))
|
||||
V = X->getLoc();
|
||||
}
|
||||
}
|
||||
|
||||
BindingsTy B = GetBindings(store);
|
||||
return V.isUnknown()
|
||||
? VBFactory.Remove(B, R).getRoot()
|
||||
: VBFactory.Add(B, R, V).getRoot();
|
||||
}
|
||||
|
||||
Store BasicStoreManager::Remove(Store store, Loc loc) {
|
||||
@ -521,7 +512,7 @@ Store BasicStoreManager::getInitialStore() {
|
||||
|
||||
// Scan the method for ivar references. While this requires an
|
||||
// entire AST scan, the cost should not be high in practice.
|
||||
St = scanForIvars(MD->getBody(getContext()), PD, St);
|
||||
St = scanForIvars(MD->getBody(), PD, St);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -537,10 +528,9 @@ Store BasicStoreManager::getInitialStore() {
|
||||
// Initialize globals and parameters to symbolic values.
|
||||
// Initialize local variables to undefined.
|
||||
const MemRegion *R = ValMgr.getRegionManager().getVarRegion(VD);
|
||||
SVal X = (VD->hasGlobalStorage() || isa<ParmVarDecl>(VD) ||
|
||||
isa<ImplicitParamDecl>(VD))
|
||||
? ValMgr.getRegionValueSymbolVal(R)
|
||||
: UndefinedVal();
|
||||
SVal X = R->hasGlobalsOrParametersStorage()
|
||||
? ValMgr.getRegionValueSymbolVal(R)
|
||||
: UndefinedVal();
|
||||
|
||||
St = BindInternal(St, ValMgr.makeLoc(R), X);
|
||||
}
|
||||
@ -594,7 +584,7 @@ Store BasicStoreManager::BindDeclInternal(Store store, const VarDecl* VD,
|
||||
} else {
|
||||
// Process local scalar variables.
|
||||
QualType T = VD->getType();
|
||||
if (Loc::IsLocType(T) || T->isIntegerType()) {
|
||||
if (ValMgr.getSymbolManager().canSymbolicate(T)) {
|
||||
SVal V = InitVal ? *InitVal : UndefinedVal();
|
||||
store = BindInternal(store, getLoc(VD), V);
|
||||
}
|
||||
|
@ -146,7 +146,7 @@ class VISIBILITY_HIDDEN PathDiagnosticBuilder : public BugReporterContext {
|
||||
|
||||
ParentMap& getParentMap() {
|
||||
if (PM.get() == 0)
|
||||
PM.reset(new ParentMap(getCodeDecl().getBody(getASTContext())));
|
||||
PM.reset(new ParentMap(getCodeDecl().getBody()));
|
||||
return *PM.get();
|
||||
}
|
||||
|
||||
@ -182,8 +182,7 @@ PathDiagnosticBuilder::ExecutionContinues(const ExplodedNode<GRState>* N) {
|
||||
if (Stmt *S = GetNextStmt(N))
|
||||
return PathDiagnosticLocation(S, getSourceManager());
|
||||
|
||||
return FullSourceLoc(getCodeDecl().getBodyRBrace(getASTContext()),
|
||||
getSourceManager());
|
||||
return FullSourceLoc(getCodeDecl().getBodyRBrace(), getSourceManager());
|
||||
}
|
||||
|
||||
PathDiagnosticLocation
|
||||
@ -893,7 +892,7 @@ class VISIBILITY_HIDDEN EdgeBuilder {
|
||||
// statement (if it doesn't already exist).
|
||||
// FIXME: Should handle CXXTryStmt if analyser starts supporting C++.
|
||||
if (const CompoundStmt *CS =
|
||||
PDB.getCodeDecl().getCompoundBody(PDB.getASTContext()))
|
||||
PDB.getCodeDecl().getCompoundBody())
|
||||
if (!CS->body_empty()) {
|
||||
SourceLocation Loc = (*CS->body_begin())->getLocStart();
|
||||
rawAddEdge(PathDiagnosticLocation(Loc, PDB.getSourceManager()));
|
||||
|
@ -156,13 +156,13 @@ static bool followsFundamentalRule(Selector S) {
|
||||
}
|
||||
|
||||
static const ObjCMethodDecl*
|
||||
ResolveToInterfaceMethodDecl(const ObjCMethodDecl *MD, ASTContext &Context) {
|
||||
ResolveToInterfaceMethodDecl(const ObjCMethodDecl *MD) {
|
||||
ObjCInterfaceDecl *ID =
|
||||
const_cast<ObjCInterfaceDecl*>(MD->getClassInterface());
|
||||
|
||||
return MD->isInstanceMethod()
|
||||
? ID->lookupInstanceMethod(Context, MD->getSelector())
|
||||
: ID->lookupClassMethod(Context, MD->getSelector());
|
||||
? ID->lookupInstanceMethod(MD->getSelector())
|
||||
: ID->lookupClassMethod(MD->getSelector());
|
||||
}
|
||||
|
||||
namespace {
|
||||
@ -827,8 +827,7 @@ class VISIBILITY_HIDDEN RetainSummaryManager {
|
||||
QualType ResultTy = MD->getResultType();
|
||||
|
||||
// Resolve the method decl last.
|
||||
if (const ObjCMethodDecl *InterfaceMD =
|
||||
ResolveToInterfaceMethodDecl(MD, Ctx))
|
||||
if (const ObjCMethodDecl *InterfaceMD = ResolveToInterfaceMethodDecl(MD))
|
||||
MD = InterfaceMD;
|
||||
|
||||
if (MD->isInstanceMethod())
|
||||
@ -1248,15 +1247,15 @@ RetainSummaryManager::updateSummaryFromAnnotations(RetainSummary &Summ,
|
||||
|
||||
// Determine if there is a special return effect for this method.
|
||||
if (isTrackedObjCObjectType(RetTy)) {
|
||||
if (FD->getAttr<NSReturnsRetainedAttr>(Ctx)) {
|
||||
if (FD->getAttr<NSReturnsRetainedAttr>()) {
|
||||
Summ.setRetEffect(ObjCAllocRetE);
|
||||
}
|
||||
else if (FD->getAttr<CFReturnsRetainedAttr>(Ctx)) {
|
||||
else if (FD->getAttr<CFReturnsRetainedAttr>()) {
|
||||
Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true));
|
||||
}
|
||||
}
|
||||
else if (RetTy->getAsPointerType()) {
|
||||
if (FD->getAttr<CFReturnsRetainedAttr>(Ctx)) {
|
||||
if (FD->getAttr<CFReturnsRetainedAttr>()) {
|
||||
Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true));
|
||||
}
|
||||
}
|
||||
@ -1270,10 +1269,10 @@ RetainSummaryManager::updateSummaryFromAnnotations(RetainSummary &Summ,
|
||||
|
||||
// Determine if there is a special return effect for this method.
|
||||
if (isTrackedObjCObjectType(MD->getResultType())) {
|
||||
if (MD->getAttr<NSReturnsRetainedAttr>(Ctx)) {
|
||||
if (MD->getAttr<NSReturnsRetainedAttr>()) {
|
||||
Summ.setRetEffect(ObjCAllocRetE);
|
||||
}
|
||||
else if (MD->getAttr<CFReturnsRetainedAttr>(Ctx)) {
|
||||
else if (MD->getAttr<CFReturnsRetainedAttr>()) {
|
||||
Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true));
|
||||
}
|
||||
}
|
||||
@ -2632,7 +2631,7 @@ CFRefLeakReport::getEndPath(BugReporterContext& BRC,
|
||||
|
||||
if (!L.isValid()) {
|
||||
const Decl &D = BRC.getCodeDecl();
|
||||
L = PathDiagnosticLocation(D.getBodyRBrace(BRC.getASTContext()), SMgr);
|
||||
L = PathDiagnosticLocation(D.getBodyRBrace(), SMgr);
|
||||
}
|
||||
|
||||
std::string sbuf;
|
||||
@ -2796,7 +2795,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
|
||||
// to identify conjured symbols by an expression pair: the enclosing
|
||||
// expression (the context) and the expression itself. This should
|
||||
// disambiguate conjured symbols.
|
||||
|
||||
unsigned Count = Builder.getCurrentBlockCount();
|
||||
const TypedRegion* R = dyn_cast<TypedRegion>(MR->getRegion());
|
||||
|
||||
if (R) {
|
||||
@ -2833,7 +2832,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
|
||||
|
||||
if (R->isBoundable()) {
|
||||
// Set the value of the variable to be a conjured symbol.
|
||||
unsigned Count = Builder.getCurrentBlockCount();
|
||||
|
||||
QualType T = R->getValueType(Ctx);
|
||||
|
||||
if (Loc::IsLocType(T) || (T->isIntegerType() && T->isScalarType())){
|
||||
@ -2857,20 +2856,31 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
|
||||
state->getStateManager().getRegionManager();
|
||||
|
||||
// Iterate through the fields and construct new symbols.
|
||||
for (RecordDecl::field_iterator FI=RD->field_begin(Ctx),
|
||||
FE=RD->field_end(Ctx); FI!=FE; ++FI) {
|
||||
for (RecordDecl::field_iterator FI=RD->field_begin(),
|
||||
FE=RD->field_end(); FI!=FE; ++FI) {
|
||||
|
||||
// For now just handle scalar fields.
|
||||
FieldDecl *FD = *FI;
|
||||
QualType FT = FD->getType();
|
||||
|
||||
const FieldRegion* FR = MRMgr.getFieldRegion(FD, R);
|
||||
|
||||
if (Loc::IsLocType(FT) ||
|
||||
(FT->isIntegerType() && FT->isScalarType())) {
|
||||
const FieldRegion* FR = MRMgr.getFieldRegion(FD, R);
|
||||
|
||||
SVal V = ValMgr.getConjuredSymbolVal(*I, FT, Count);
|
||||
state = state->bindLoc(ValMgr.makeLoc(FR), V);
|
||||
}
|
||||
}
|
||||
else if (FT->isStructureType()) {
|
||||
// set the default value of the struct field to conjured
|
||||
// symbol. Note that the type of the symbol is irrelavant.
|
||||
// We cannot use the type of the struct otherwise ValMgr won't
|
||||
// give us the conjured symbol.
|
||||
StoreManager& StoreMgr =
|
||||
Eng.getStateManager().getStoreManager();
|
||||
SVal V = ValMgr.getConjuredSymbolVal(*I,
|
||||
Eng.getContext().IntTy,
|
||||
Count);
|
||||
state = StoreMgr.setDefaultValue(state, FR, V);
|
||||
}
|
||||
}
|
||||
} else if (const ArrayType *AT = Ctx.getAsArrayType(T)) {
|
||||
// Set the default value of the array to conjured symbol.
|
||||
@ -2884,6 +2894,15 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (isa<AllocaRegion>(MR->getRegion())) {
|
||||
// Invalidate the alloca region by setting its default value to
|
||||
// conjured symbol. The type of the symbol is irrelavant.
|
||||
SVal V = ValMgr.getConjuredSymbolVal(*I, Eng.getContext().IntTy,
|
||||
Count);
|
||||
StoreManager& StoreMgr =
|
||||
Eng.getStateManager().getStoreManager();
|
||||
state = StoreMgr.setDefaultValue(state, MR->getRegion(), V);
|
||||
}
|
||||
else
|
||||
state = state->bindLoc(*MR, UnknownVal());
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ class VISIBILITY_HIDDEN DeadStoreObs : public LiveVariables::ObserverTy {
|
||||
const LiveVariables::AnalysisDataTy& AD,
|
||||
const LiveVariables::ValTy& Live) {
|
||||
|
||||
if (VD->hasLocalStorage() && !Live(VD, AD) && !VD->getAttr<UnusedAttr>(Ctx))
|
||||
if (VD->hasLocalStorage() && !Live(VD, AD) && !VD->getAttr<UnusedAttr>())
|
||||
Report(VD, dsk, Ex->getSourceRange().getBegin(),
|
||||
Val->getSourceRange());
|
||||
}
|
||||
@ -190,7 +190,7 @@ class VISIBILITY_HIDDEN DeadStoreObs : public LiveVariables::ObserverTy {
|
||||
// A dead initialization is a variable that is dead after it
|
||||
// is initialized. We don't flag warnings for those variables
|
||||
// marked 'unused'.
|
||||
if (!Live(V, AD) && V->getAttr<UnusedAttr>(Ctx) == 0) {
|
||||
if (!Live(V, AD) && V->getAttr<UnusedAttr>() == 0) {
|
||||
// Special case: check for initializations with constants.
|
||||
//
|
||||
// e.g. : int x = 0;
|
||||
|
@ -109,7 +109,7 @@ void clang::CheckObjCDealloc(ObjCImplementationDecl* D,
|
||||
QualType T = ID->getType();
|
||||
|
||||
if (!Ctx.isObjCObjectPointerType(T) ||
|
||||
ID->getAttr<IBOutletAttr>(Ctx)) // Skip IBOutlets.
|
||||
ID->getAttr<IBOutletAttr>()) // Skip IBOutlets.
|
||||
continue;
|
||||
|
||||
containsPointerIvar = true;
|
||||
@ -147,8 +147,8 @@ void clang::CheckObjCDealloc(ObjCImplementationDecl* D,
|
||||
ObjCMethodDecl* MD = 0;
|
||||
|
||||
// Scan the instance methods for "dealloc".
|
||||
for (ObjCImplementationDecl::instmeth_iterator I = D->instmeth_begin(Ctx),
|
||||
E = D->instmeth_end(Ctx); I!=E; ++I) {
|
||||
for (ObjCImplementationDecl::instmeth_iterator I = D->instmeth_begin(),
|
||||
E = D->instmeth_end(); I!=E; ++I) {
|
||||
|
||||
if ((*I)->getSelector() == S) {
|
||||
MD = *I;
|
||||
@ -172,7 +172,7 @@ void clang::CheckObjCDealloc(ObjCImplementationDecl* D,
|
||||
}
|
||||
|
||||
// dealloc found. Scan for missing [super dealloc].
|
||||
if (MD->getBody(Ctx) && !scan_dealloc(MD->getBody(Ctx), S)) {
|
||||
if (MD->getBody() && !scan_dealloc(MD->getBody(), S)) {
|
||||
|
||||
const char* name = LOpts.getGCMode() == LangOptions::NonGC
|
||||
? "missing [super dealloc]"
|
||||
@ -198,8 +198,8 @@ void clang::CheckObjCDealloc(ObjCImplementationDecl* D,
|
||||
|
||||
// Scan for missing and extra releases of ivars used by implementations
|
||||
// of synthesized properties
|
||||
for (ObjCImplementationDecl::propimpl_iterator I = D->propimpl_begin(Ctx),
|
||||
E = D->propimpl_end(Ctx); I!=E; ++I) {
|
||||
for (ObjCImplementationDecl::propimpl_iterator I = D->propimpl_begin(),
|
||||
E = D->propimpl_end(); I!=E; ++I) {
|
||||
|
||||
// We can only check the synthesized properties
|
||||
if((*I)->getPropertyImplementation() != ObjCPropertyImplDecl::Synthesize)
|
||||
@ -223,7 +223,7 @@ void clang::CheckObjCDealloc(ObjCImplementationDecl* D,
|
||||
|
||||
// ivar must be released if and only if the kind of setter was not 'assign'
|
||||
bool requiresRelease = PD->getSetterKind() != ObjCPropertyDecl::Assign;
|
||||
if(scan_ivar_release(MD->getBody(Ctx), ID, PD, RS, SelfII, Ctx)
|
||||
if(scan_ivar_release(MD->getBody(), ID, PD, RS, SelfII, Ctx)
|
||||
!= requiresRelease) {
|
||||
const char *name;
|
||||
const char* category = "Memory (Core Foundation/Objective-C)";
|
||||
|
@ -86,8 +86,8 @@ void clang::CheckObjCInstMethSignature(ObjCImplementationDecl* ID,
|
||||
MapTy IMeths;
|
||||
unsigned NumMethods = 0;
|
||||
|
||||
for (ObjCImplementationDecl::instmeth_iterator I=ID->instmeth_begin(Ctx),
|
||||
E=ID->instmeth_end(Ctx); I!=E; ++I) {
|
||||
for (ObjCImplementationDecl::instmeth_iterator I=ID->instmeth_begin(),
|
||||
E=ID->instmeth_end(); I!=E; ++I) {
|
||||
|
||||
ObjCMethodDecl* M = *I;
|
||||
IMeths[M->getSelector()] = M;
|
||||
@ -97,8 +97,8 @@ void clang::CheckObjCInstMethSignature(ObjCImplementationDecl* ID,
|
||||
// Now recurse the class hierarchy chain looking for methods with the
|
||||
// same signatures.
|
||||
while (C && NumMethods) {
|
||||
for (ObjCInterfaceDecl::instmeth_iterator I=C->instmeth_begin(Ctx),
|
||||
E=C->instmeth_end(Ctx); I!=E; ++I) {
|
||||
for (ObjCInterfaceDecl::instmeth_iterator I=C->instmeth_begin(),
|
||||
E=C->instmeth_end(); I!=E; ++I) {
|
||||
|
||||
ObjCMethodDecl* M = *I;
|
||||
Selector S = M->getSelector();
|
||||
|
@ -59,9 +59,6 @@ void clang::CheckObjCUnusedIvar(ObjCImplementationDecl* D, BugReporter& BR) {
|
||||
ObjCInterfaceDecl* ID = D->getClassInterface();
|
||||
IvarUsageMap M;
|
||||
|
||||
|
||||
ASTContext &Ctx = BR.getContext();
|
||||
|
||||
// Iterate over the ivars.
|
||||
for (ObjCInterfaceDecl::ivar_iterator I=ID->ivar_begin(), E=ID->ivar_end();
|
||||
I!=E; ++I) {
|
||||
@ -73,7 +70,7 @@ void clang::CheckObjCUnusedIvar(ObjCImplementationDecl* D, BugReporter& BR) {
|
||||
continue;
|
||||
|
||||
// Skip IB Outlets.
|
||||
if (ID->getAttr<IBOutletAttr>(Ctx))
|
||||
if (ID->getAttr<IBOutletAttr>())
|
||||
continue;
|
||||
|
||||
M[ID] = Unused;
|
||||
@ -83,14 +80,14 @@ void clang::CheckObjCUnusedIvar(ObjCImplementationDecl* D, BugReporter& BR) {
|
||||
return;
|
||||
|
||||
// Now scan the methods for accesses.
|
||||
for (ObjCImplementationDecl::instmeth_iterator I = D->instmeth_begin(Ctx),
|
||||
E = D->instmeth_end(Ctx); I!=E; ++I)
|
||||
Scan(M, (*I)->getBody(Ctx));
|
||||
for (ObjCImplementationDecl::instmeth_iterator I = D->instmeth_begin(),
|
||||
E = D->instmeth_end(); I!=E; ++I)
|
||||
Scan(M, (*I)->getBody());
|
||||
|
||||
// Scan for @synthesized property methods that act as setters/getters
|
||||
// to an ivar.
|
||||
for (ObjCImplementationDecl::propimpl_iterator I = D->propimpl_begin(Ctx),
|
||||
E = D->propimpl_end(Ctx); I!=E; ++I)
|
||||
for (ObjCImplementationDecl::propimpl_iterator I = D->propimpl_begin(),
|
||||
E = D->propimpl_end(); I!=E; ++I)
|
||||
Scan(M, *I);
|
||||
|
||||
// Find ivars that are unused.
|
||||
|
@ -143,8 +143,19 @@ EnvironmentManager::RemoveDeadBindings(Environment Env, Stmt* Loc,
|
||||
SVal X = I.getData();
|
||||
|
||||
// If the block expr's value is a memory region, then mark that region.
|
||||
if (isa<loc::MemRegionVal>(X))
|
||||
DRoots.push_back(cast<loc::MemRegionVal>(X).getRegion());
|
||||
if (isa<loc::MemRegionVal>(X)) {
|
||||
const MemRegion* R = cast<loc::MemRegionVal>(X).getRegion();
|
||||
DRoots.push_back(R);
|
||||
// Mark the super region of the RX as live.
|
||||
// e.g.: int x; char *y = (char*) &x; if (*y) ...
|
||||
// 'y' => element region. 'x' is its super region.
|
||||
// We only add one level super region for now.
|
||||
|
||||
// FIXME: maybe multiple level of super regions should be added.
|
||||
if (const SubRegion *SR = dyn_cast<SubRegion>(R)) {
|
||||
DRoots.push_back(SR->getSuperRegion());
|
||||
}
|
||||
}
|
||||
|
||||
// Mark all symbols in the block expr's value live.
|
||||
MarkLiveCallback cb(SymReaper);
|
||||
|
@ -1437,8 +1437,8 @@ void GRExprEngine::VisitCallRec(CallExpr* CE, NodeTy* Pred,
|
||||
SaveAndRestore<bool> OldSink(Builder->BuildSinks);
|
||||
const FunctionDecl* FD = L.getAsFunctionDecl();
|
||||
if (FD) {
|
||||
if (FD->getAttr<NoReturnAttr>(getContext()) ||
|
||||
FD->getAttr<AnalyzerNoReturnAttr>(getContext()))
|
||||
if (FD->getAttr<NoReturnAttr>() ||
|
||||
FD->getAttr<AnalyzerNoReturnAttr>())
|
||||
Builder->BuildSinks = true;
|
||||
else {
|
||||
// HACK: Some functions are not marked noreturn, and don't return.
|
||||
@ -3154,7 +3154,8 @@ struct VISIBILITY_HIDDEN DOTGraphTraits<GRExprEngine::NodeTy*> :
|
||||
SourceLocation SLoc = S->getLocStart();
|
||||
|
||||
Out << S->getStmtClassName() << ' ' << (void*) S << ' ';
|
||||
S->printPretty(Out);
|
||||
LangOptions LO; // FIXME.
|
||||
S->printPretty(Out, 0, PrintingPolicy(LO));
|
||||
|
||||
if (SLoc.isFileID()) {
|
||||
Out << "\\lline="
|
||||
@ -3208,7 +3209,8 @@ struct VISIBILITY_HIDDEN DOTGraphTraits<GRExprEngine::NodeTy*> :
|
||||
SourceLocation SLoc = T->getLocStart();
|
||||
|
||||
Out << "\\|Terminator: ";
|
||||
E.getSrc()->printTerminator(Out);
|
||||
LangOptions LO; // FIXME.
|
||||
E.getSrc()->printTerminator(Out, LO);
|
||||
|
||||
if (SLoc.isFileID()) {
|
||||
Out << "\\lline="
|
||||
@ -3223,11 +3225,12 @@ struct VISIBILITY_HIDDEN DOTGraphTraits<GRExprEngine::NodeTy*> :
|
||||
if (Label) {
|
||||
if (CaseStmt* C = dyn_cast<CaseStmt>(Label)) {
|
||||
Out << "\\lcase ";
|
||||
C->getLHS()->printPretty(Out);
|
||||
LangOptions LO; // FIXME.
|
||||
C->getLHS()->printPretty(Out, 0, PrintingPolicy(LO));
|
||||
|
||||
if (Stmt* RHS = C->getRHS()) {
|
||||
Out << " .. ";
|
||||
RHS->printPretty(Out);
|
||||
RHS->printPretty(Out, 0, PrintingPolicy(LO));
|
||||
}
|
||||
|
||||
Out << ":";
|
||||
|
@ -566,7 +566,7 @@ class VISIBILITY_HIDDEN CheckAttrNonNull : public GRSimpleAPICheck {
|
||||
if (!FD)
|
||||
return false;
|
||||
|
||||
const NonNullAttr* Att = FD->getAttr<NonNullAttr>(BR.getContext());
|
||||
const NonNullAttr* Att = FD->getAttr<NonNullAttr>();
|
||||
|
||||
if (!Att)
|
||||
return false;
|
||||
|
@ -166,7 +166,8 @@ void GRState::print(llvm::raw_ostream& Out, const char* nl,
|
||||
else { Out << nl; }
|
||||
|
||||
Out << " (" << (void*) I.getKey() << ") ";
|
||||
I.getKey()->printPretty(Out);
|
||||
LangOptions LO; // FIXME.
|
||||
I.getKey()->printPretty(Out, 0, PrintingPolicy(LO));
|
||||
Out << " : ";
|
||||
I.getData().print(Out);
|
||||
}
|
||||
@ -183,7 +184,8 @@ void GRState::print(llvm::raw_ostream& Out, const char* nl,
|
||||
else { Out << nl; }
|
||||
|
||||
Out << " (" << (void*) I.getKey() << ") ";
|
||||
I.getKey()->printPretty(Out);
|
||||
LangOptions LO; // FIXME.
|
||||
I.getKey()->printPretty(Out, 0, PrintingPolicy(LO));
|
||||
Out << " : ";
|
||||
I.getData().print(Out);
|
||||
}
|
||||
|
@ -135,9 +135,10 @@ void TransferFuncs::Visit(Stmt *S) {
|
||||
StmtVisitor<TransferFuncs,void>::Visit(S);
|
||||
|
||||
}
|
||||
else
|
||||
else {
|
||||
// For block-level expressions, mark that they are live.
|
||||
LiveState(S,AD) = Alive;
|
||||
}
|
||||
}
|
||||
|
||||
void TransferFuncs::VisitTerminator(CFGBlock* B) {
|
||||
|
@ -143,6 +143,10 @@ void CodeTextRegion::Profile(llvm::FoldingSetNodeID& ID) const {
|
||||
// Region pretty-printing.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void MemRegion::printStdErr() const {
|
||||
print(llvm::errs());
|
||||
}
|
||||
|
||||
std::string MemRegion::getString() const {
|
||||
std::string s;
|
||||
llvm::raw_string_ostream os(s);
|
||||
@ -184,7 +188,8 @@ void FieldRegion::print(llvm::raw_ostream& os) const {
|
||||
}
|
||||
|
||||
void StringRegion::print(llvm::raw_ostream& os) const {
|
||||
Str->printPretty(os);
|
||||
LangOptions LO; // FIXME.
|
||||
Str->printPretty(os, 0, PrintingPolicy(LO));
|
||||
}
|
||||
|
||||
void SymbolicRegion::print(llvm::raw_ostream& os) const {
|
||||
@ -218,6 +223,10 @@ MemSpaceRegion* MemRegionManager::getStackRegion() {
|
||||
return LazyAllocate(stack);
|
||||
}
|
||||
|
||||
MemSpaceRegion* MemRegionManager::getStackArgumentsRegion() {
|
||||
return LazyAllocate(stackArguments);
|
||||
}
|
||||
|
||||
MemSpaceRegion* MemRegionManager::getGlobalsRegion() {
|
||||
return LazyAllocate(globals);
|
||||
}
|
||||
@ -327,8 +336,10 @@ const MemSpaceRegion *MemRegion::getMemorySpace() const {
|
||||
}
|
||||
|
||||
bool MemRegion::hasStackStorage() const {
|
||||
if (const MemSpaceRegion *MS = getMemorySpace())
|
||||
return MS == getMemRegionManager()->getStackRegion();
|
||||
if (const MemSpaceRegion *MS = getMemorySpace()) {
|
||||
MemRegionManager *Mgr = getMemRegionManager();
|
||||
return MS == Mgr->getStackRegion() || MS == Mgr->getStackArgumentsRegion();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -343,10 +354,35 @@ bool MemRegion::hasHeapStorage() const {
|
||||
bool MemRegion::hasHeapOrStackStorage() const {
|
||||
if (const MemSpaceRegion *MS = getMemorySpace()) {
|
||||
MemRegionManager *Mgr = getMemRegionManager();
|
||||
return MS == Mgr->getHeapRegion() || MS == Mgr->getStackRegion();
|
||||
return MS == Mgr->getHeapRegion()
|
||||
|| MS == Mgr->getStackRegion()
|
||||
|| MS == Mgr->getStackArgumentsRegion();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool MemRegion::hasGlobalsStorage() const {
|
||||
if (const MemSpaceRegion *MS = getMemorySpace())
|
||||
return MS == getMemRegionManager()->getGlobalsRegion();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MemRegion::hasParametersStorage() const {
|
||||
if (const MemSpaceRegion *MS = getMemorySpace())
|
||||
return MS == getMemRegionManager()->getStackArgumentsRegion();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MemRegion::hasGlobalsOrParametersStorage() const {
|
||||
if (const MemSpaceRegion *MS = getMemorySpace()) {
|
||||
MemRegionManager *Mgr = getMemRegionManager();
|
||||
return MS == Mgr->getGlobalsRegion()
|
||||
|| MS == Mgr->getStackArgumentsRegion();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// View handling.
|
||||
|
@ -347,9 +347,6 @@ class VISIBILITY_HIDDEN RegionStoreManager : public StoreManager {
|
||||
|
||||
// FIXME: Remove.
|
||||
ASTContext& getContext() { return StateMgr.getContext(); }
|
||||
|
||||
// FIXME: Use ValueManager?
|
||||
SymbolManager& getSymbolManager() { return StateMgr.getSymbolManager(); }
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
@ -822,12 +819,6 @@ SVal RegionStoreManager::Retrieve(const GRState *state, Loc L, QualType T) {
|
||||
const TypedRegion *R = cast<TypedRegion>(MR);
|
||||
assert(R && "bad region");
|
||||
|
||||
if (const FieldRegion* FR = dyn_cast<FieldRegion>(R))
|
||||
return RetrieveField(state, FR);
|
||||
|
||||
if (const ElementRegion* ER = dyn_cast<ElementRegion>(R))
|
||||
return RetrieveElement(state, ER);
|
||||
|
||||
// FIXME: We should eventually handle funny addressing. e.g.:
|
||||
//
|
||||
// int x = ...;
|
||||
@ -848,6 +839,12 @@ SVal RegionStoreManager::Retrieve(const GRState *state, Loc L, QualType T) {
|
||||
// FIXME: handle Vector types.
|
||||
if (RTy->isVectorType())
|
||||
return UnknownVal();
|
||||
|
||||
if (const FieldRegion* FR = dyn_cast<FieldRegion>(R))
|
||||
return RetrieveField(state, FR);
|
||||
|
||||
if (const ElementRegion* ER = dyn_cast<ElementRegion>(R))
|
||||
return RetrieveElement(state, ER);
|
||||
|
||||
RegionBindingsTy B = GetRegionBindings(state->getStore());
|
||||
RegionBindingsTy::data_type* V = B.lookup(R);
|
||||
@ -882,14 +879,8 @@ SVal RegionStoreManager::Retrieve(const GRState *state, Loc L, QualType T) {
|
||||
if (VD == SelfDecl)
|
||||
return loc::MemRegionVal(getSelfRegion(0));
|
||||
|
||||
if (isa<ParmVarDecl>(VD) || isa<ImplicitParamDecl>(VD) ||
|
||||
VD->hasGlobalStorage()) {
|
||||
QualType VTy = VD->getType();
|
||||
if (Loc::IsLocType(VTy) || VTy->isIntegerType())
|
||||
return ValMgr.getRegionValueSymbolVal(VR);
|
||||
else
|
||||
return UnknownVal();
|
||||
}
|
||||
if (VR->hasGlobalsOrParametersStorage())
|
||||
return ValMgr.getRegionValueSymbolValOrUnknown(VR, VD->getType());
|
||||
}
|
||||
|
||||
if (R->hasHeapOrStackStorage()) {
|
||||
@ -907,23 +898,21 @@ SVal RegionStoreManager::Retrieve(const GRState *state, Loc L, QualType T) {
|
||||
RTy = T->getAsPointerType()->getPointeeType();
|
||||
}
|
||||
|
||||
// All other integer values are symbolic.
|
||||
if (Loc::IsLocType(RTy) || RTy->isIntegerType())
|
||||
return ValMgr.getRegionValueSymbolVal(R, RTy);
|
||||
else
|
||||
return UnknownVal();
|
||||
// All other values are symbolic.
|
||||
return ValMgr.getRegionValueSymbolValOrUnknown(R, RTy);
|
||||
}
|
||||
|
||||
SVal RegionStoreManager::RetrieveElement(const GRState* state,
|
||||
const ElementRegion* R) {
|
||||
// Check if the region has a binding.
|
||||
RegionBindingsTy B = GetRegionBindings(state->getStore());
|
||||
const SVal* V = B.lookup(R);
|
||||
if (V)
|
||||
if (const SVal* V = B.lookup(R))
|
||||
return *V;
|
||||
|
||||
const MemRegion* superR = R->getSuperRegion();
|
||||
|
||||
// Check if the region is an element region of a string literal.
|
||||
if (const StringRegion *StrR=dyn_cast<StringRegion>(R->getSuperRegion())) {
|
||||
if (const StringRegion *StrR=dyn_cast<StringRegion>(superR)) {
|
||||
const StringLiteral *Str = StrR->getStringLiteral();
|
||||
SVal Idx = R->getIndex();
|
||||
if (nonloc::ConcreteInt *CI = dyn_cast<nonloc::ConcreteInt>(&Idx)) {
|
||||
@ -937,18 +926,38 @@ SVal RegionStoreManager::RetrieveElement(const GRState* state,
|
||||
}
|
||||
}
|
||||
|
||||
const MemRegion* SuperR = R->getSuperRegion();
|
||||
const SVal* D = state->get<RegionDefaultValue>(SuperR);
|
||||
|
||||
if (D) {
|
||||
// Check if the super region has a default value.
|
||||
if (const SVal *D = state->get<RegionDefaultValue>(superR)) {
|
||||
if (D->hasConjuredSymbol())
|
||||
return ValMgr.getRegionValueSymbolVal(R);
|
||||
else
|
||||
return *D;
|
||||
}
|
||||
|
||||
if (R->hasHeapOrStackStorage())
|
||||
// Check if the super region has a binding.
|
||||
if (B.lookup(superR)) {
|
||||
// We do not extract the bit value from super region for now.
|
||||
return UnknownVal();
|
||||
}
|
||||
|
||||
if (R->hasHeapStorage()) {
|
||||
// FIXME: If the region has heap storage and we know nothing special
|
||||
// about its bindings, should we instead return UnknownVal? Seems like
|
||||
// we should only return UndefinedVal in the cases where we know the value
|
||||
// will be undefined.
|
||||
return UndefinedVal();
|
||||
}
|
||||
|
||||
if (R->hasStackStorage() && !R->hasParametersStorage()) {
|
||||
// Currently we don't reason specially about Clang-style vectors. Check
|
||||
// if superR is a vector and if so return Unknown.
|
||||
if (const TypedRegion *typedSuperR = dyn_cast<TypedRegion>(superR)) {
|
||||
if (typedSuperR->getValueType(getContext())->isVectorType())
|
||||
return UnknownVal();
|
||||
}
|
||||
|
||||
return UndefinedVal();
|
||||
}
|
||||
|
||||
QualType Ty = R->getValueType(getContext());
|
||||
|
||||
@ -957,10 +966,7 @@ SVal RegionStoreManager::RetrieveElement(const GRState* state,
|
||||
if (const QualType *p = state->get<RegionCasts>(R))
|
||||
Ty = (*p)->getAsPointerType()->getPointeeType();
|
||||
|
||||
if (Loc::IsLocType(Ty) || Ty->isIntegerType())
|
||||
return ValMgr.getRegionValueSymbolVal(R, Ty);
|
||||
else
|
||||
return UnknownVal();
|
||||
return ValMgr.getRegionValueSymbolValOrUnknown(R, Ty);
|
||||
}
|
||||
|
||||
SVal RegionStoreManager::RetrieveField(const GRState* state,
|
||||
@ -969,13 +975,11 @@ SVal RegionStoreManager::RetrieveField(const GRState* state,
|
||||
|
||||
// Check if the region has a binding.
|
||||
RegionBindingsTy B = GetRegionBindings(state->getStore());
|
||||
const SVal* V = B.lookup(R);
|
||||
if (V)
|
||||
if (const SVal* V = B.lookup(R))
|
||||
return *V;
|
||||
|
||||
const MemRegion* SuperR = R->getSuperRegion();
|
||||
const SVal* D = state->get<RegionDefaultValue>(SuperR);
|
||||
if (D) {
|
||||
const MemRegion* superR = R->getSuperRegion();
|
||||
if (const SVal* D = state->get<RegionDefaultValue>(superR)) {
|
||||
if (D->hasConjuredSymbol())
|
||||
return ValMgr.getRegionValueSymbolVal(R);
|
||||
|
||||
@ -988,7 +992,11 @@ SVal RegionStoreManager::RetrieveField(const GRState* state,
|
||||
assert(0 && "Unknown default value");
|
||||
}
|
||||
|
||||
if (R->hasHeapOrStackStorage())
|
||||
// FIXME: Is this correct? Should it be UnknownVal?
|
||||
if (R->hasHeapStorage())
|
||||
return UndefinedVal();
|
||||
|
||||
if (R->hasStackStorage() && !R->hasParametersStorage())
|
||||
return UndefinedVal();
|
||||
|
||||
// If the region is already cast to another type, use that type to create the
|
||||
@ -998,11 +1006,8 @@ SVal RegionStoreManager::RetrieveField(const GRState* state,
|
||||
Ty = tmp->getAsPointerType()->getPointeeType();
|
||||
}
|
||||
|
||||
// All other integer values are symbolic.
|
||||
if (Loc::IsLocType(Ty) || Ty->isIntegerType())
|
||||
return ValMgr.getRegionValueSymbolVal(R, Ty);
|
||||
else
|
||||
return UnknownVal();
|
||||
// All other values are symbolic.
|
||||
return ValMgr.getRegionValueSymbolValOrUnknown(R, Ty);
|
||||
}
|
||||
|
||||
SVal RegionStoreManager::RetrieveStruct(const GRState *state,
|
||||
@ -1018,8 +1023,7 @@ SVal RegionStoreManager::RetrieveStruct(const GRState *state,
|
||||
|
||||
// FIXME: We shouldn't use a std::vector. If RecordDecl doesn't have a
|
||||
// reverse iterator, we should implement one.
|
||||
std::vector<FieldDecl *> Fields(RD->field_begin(getContext()),
|
||||
RD->field_end(getContext()));
|
||||
std::vector<FieldDecl *> Fields(RD->field_begin(), RD->field_end());
|
||||
|
||||
for (std::vector<FieldDecl *>::reverse_iterator Field = Fields.rbegin(),
|
||||
FieldEnd = Fields.rend();
|
||||
@ -1074,6 +1078,9 @@ Store RegionStoreManager::Remove(Store store, Loc L) {
|
||||
}
|
||||
|
||||
const GRState *RegionStoreManager::Bind(const GRState *state, Loc L, SVal V) {
|
||||
if (isa<loc::ConcreteInt>(L))
|
||||
return state;
|
||||
|
||||
// If we get here, the location should be a region.
|
||||
const MemRegion* R = cast<loc::MemRegionVal>(L).getRegion();
|
||||
|
||||
@ -1204,8 +1211,7 @@ RegionStoreManager::BindStruct(const GRState *state, const TypedRegion* R,
|
||||
|
||||
RecordDecl::field_iterator FI, FE;
|
||||
|
||||
for (FI = RD->field_begin(getContext()), FE = RD->field_end(getContext());
|
||||
FI != FE; ++FI, ++VI) {
|
||||
for (FI = RD->field_begin(), FE = RD->field_end(); FI != FE; ++FI, ++VI) {
|
||||
|
||||
if (VI == VE)
|
||||
break;
|
||||
@ -1357,8 +1363,9 @@ Store RegionStoreManager::RemoveDeadBindings(const GRState *state, Stmt* Loc,
|
||||
IntermediateRoots.pop_back();
|
||||
|
||||
if (const VarRegion* VR = dyn_cast<VarRegion>(R)) {
|
||||
if (SymReaper.isLive(Loc, VR->getDecl()))
|
||||
if (SymReaper.isLive(Loc, VR->getDecl())) {
|
||||
RegionRoots.push_back(VR); // This is a live "root".
|
||||
}
|
||||
}
|
||||
else if (const SymbolicRegion* SR = dyn_cast<SymbolicRegion>(R)) {
|
||||
if (SymReaper.isLive(SR->getSymbol()))
|
||||
@ -1366,19 +1373,19 @@ Store RegionStoreManager::RemoveDeadBindings(const GRState *state, Stmt* Loc,
|
||||
}
|
||||
else {
|
||||
// Get the super region for R.
|
||||
const MemRegion* SuperR = cast<SubRegion>(R)->getSuperRegion();
|
||||
const MemRegion* superR = cast<SubRegion>(R)->getSuperRegion();
|
||||
|
||||
// Get the current set of subregions for SuperR.
|
||||
const SubRegionsTy* SRptr = SubRegMap.lookup(SuperR);
|
||||
const SubRegionsTy* SRptr = SubRegMap.lookup(superR);
|
||||
SubRegionsTy SRs = SRptr ? *SRptr : SubRegF.GetEmptySet();
|
||||
|
||||
// Add R to the subregions of SuperR.
|
||||
SubRegMap = SubRegMapF.Add(SubRegMap, SuperR, SubRegF.Add(SRs, R));
|
||||
SubRegMap = SubRegMapF.Add(SubRegMap, superR, SubRegF.Add(SRs, R));
|
||||
|
||||
// Super region may be VarRegion or subregion of another VarRegion. Add it
|
||||
// to the work list.
|
||||
if (isa<SubRegion>(SuperR))
|
||||
IntermediateRoots.push_back(SuperR);
|
||||
if (isa<SubRegion>(superR))
|
||||
IntermediateRoots.push_back(superR);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1409,9 +1416,19 @@ Store RegionStoreManager::RemoveDeadBindings(const GRState *state, Stmt* Loc,
|
||||
SVal X = *Xptr;
|
||||
UpdateLiveSymbols(X, SymReaper); // Update the set of live symbols.
|
||||
|
||||
// If X is a region, then add it the RegionRoots.
|
||||
if (loc::MemRegionVal* RegionX = dyn_cast<loc::MemRegionVal>(&X))
|
||||
RegionRoots.push_back(RegionX->getRegion());
|
||||
// If X is a region, then add it to the RegionRoots.
|
||||
if (const MemRegion *RX = X.getAsRegion()) {
|
||||
RegionRoots.push_back(RX);
|
||||
|
||||
// Mark the super region of the RX as live.
|
||||
// e.g.: int x; char *y = (char*) &x; if (*y) ...
|
||||
// 'y' => element region. 'x' is its super region.
|
||||
// We only add one level super region for now.
|
||||
// FIXME: maybe multiple level of super regions should be added.
|
||||
if (const SubRegion *SR = dyn_cast<SubRegion>(RX)) {
|
||||
RegionRoots.push_back(SR->getSuperRegion());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get the subregions of R. These are RegionRoots as well since they
|
||||
@ -1422,6 +1439,7 @@ Store RegionStoreManager::RemoveDeadBindings(const GRState *state, Stmt* Loc,
|
||||
|
||||
for (SubRegionsTy::iterator I=SR.begin(), E=SR.end(); I!=E; ++I)
|
||||
RegionRoots.push_back(*I);
|
||||
|
||||
}
|
||||
|
||||
// We have now scanned the store, marking reachable regions and symbols
|
||||
@ -1429,7 +1447,6 @@ Store RegionStoreManager::RemoveDeadBindings(const GRState *state, Stmt* Loc,
|
||||
// as well as update DSymbols with the set symbols that are now dead.
|
||||
for (RegionBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
|
||||
const MemRegion* R = I.getKey();
|
||||
|
||||
// If this region live? Is so, none of its symbols are dead.
|
||||
if (Marked.count(R))
|
||||
continue;
|
||||
|
@ -114,6 +114,13 @@ const SymExpr *SVal::getAsSymbolicExpression() const {
|
||||
return getAsSymbol();
|
||||
}
|
||||
|
||||
const MemRegion *SVal::getAsRegion() const {
|
||||
if (const loc::MemRegionVal *X = dyn_cast<loc::MemRegionVal>(this))
|
||||
return X->getRegion();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool SVal::symbol_iterator::operator==(const symbol_iterator &X) const {
|
||||
return itr == X.itr;
|
||||
}
|
||||
|
@ -88,10 +88,10 @@ StoreManager::CastRegion(const GRState* state, const MemRegion* R,
|
||||
|
||||
// If the super region is an element region, strip it away.
|
||||
// FIXME: Is this the right thing to do in all cases?
|
||||
const TypedRegion *Base = isa<ElementRegion>(TR) ?
|
||||
cast<TypedRegion>(TR->getSuperRegion()) : TR;
|
||||
const MemRegion *Base = isa<ElementRegion>(TR) ? TR->getSuperRegion()
|
||||
: TR;
|
||||
ElementRegion* ER = MRMgr.getElementRegion(Pointee, Idx, Base,
|
||||
StateMgr.getContext());
|
||||
StateMgr.getContext());
|
||||
return CastResult(state, ER);
|
||||
}
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ static void AddKeyword(const char *Keyword, unsigned KWLen,
|
||||
else if (LangOpts.C99 && (Flags & KEYC99)) AddResult = 2;
|
||||
else if (LangOpts.GNUMode && (Flags & KEYGNU)) AddResult = 1;
|
||||
else if (LangOpts.Microsoft && (Flags & KEYMS)) AddResult = 1;
|
||||
else if (LangOpts.OpenCL && (Flags & BOOLSUPPORT)) AddResult = 2;
|
||||
else if (LangOpts.Bool && (Flags & BOOLSUPPORT)) AddResult = 2;
|
||||
|
||||
// Don't add this keyword if disabled in this language.
|
||||
if (AddResult == 0) return;
|
||||
|
@ -41,6 +41,7 @@ TargetInfo::TargetInfo(const std::string &T) : Triple(T) {
|
||||
UIntMaxType = UnsignedLongLong;
|
||||
IntPtrType = SignedLong;
|
||||
WCharType = SignedInt;
|
||||
Int64Type = SignedLongLong;
|
||||
FloatFormat = &llvm::APFloat::IEEEsingle;
|
||||
DoubleFormat = &llvm::APFloat::IEEEdouble;
|
||||
LongDoubleFormat = &llvm::APFloat::IEEEdouble;
|
||||
|
@ -61,55 +61,24 @@ static void DefineStd(std::vector<char> &Buf, const char *MacroName,
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Defines specific to certain operating systems.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
static void getSolarisDefines(const LangOptions &Opts, std::vector<char> &Defs) {
|
||||
DefineStd(Defs, "sun", Opts);
|
||||
DefineStd(Defs, "unix", Opts);
|
||||
Define(Defs, "__ELF__");
|
||||
Define(Defs, "__svr4__");
|
||||
Define(Defs, "__SVR4");
|
||||
}
|
||||
|
||||
static void getFreeBSDDefines(const LangOptions &Opts, bool is64Bit,
|
||||
const char *Triple, std::vector<char> &Defs) {
|
||||
// FreeBSD defines; list based off of gcc output
|
||||
|
||||
const char *FreeBSD = strstr(Triple, "-freebsd");
|
||||
FreeBSD += strlen("-freebsd");
|
||||
char release[] = "X";
|
||||
release[0] = FreeBSD[0];
|
||||
char version[] = "X00001";
|
||||
version[0] = FreeBSD[0];
|
||||
|
||||
Define(Defs, "__FreeBSD__", release);
|
||||
Define(Defs, "__FreeBSD_cc_version", version);
|
||||
Define(Defs, "__KPRINTF_ATTRIBUTE__");
|
||||
DefineStd(Defs, "unix", Opts);
|
||||
Define(Defs, "__ELF__", "1");
|
||||
if (is64Bit) {
|
||||
Define(Defs, "__LP64__");
|
||||
namespace {
|
||||
template<typename TgtInfo>
|
||||
class OSTargetInfo : public TgtInfo {
|
||||
protected:
|
||||
virtual void getOSDefines(const LangOptions &Opts, const char *Triple,
|
||||
std::vector<char> &Defines) const=0;
|
||||
public:
|
||||
OSTargetInfo(const std::string& triple) : TgtInfo(triple) {}
|
||||
virtual void getTargetDefines(const LangOptions &Opts,
|
||||
std::vector<char> &Defines) const {
|
||||
TgtInfo::getTargetDefines(Opts, Defines);
|
||||
getOSDefines(Opts, TgtInfo::getTargetTriple(), Defines);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
static void getDragonFlyDefines(const LangOptions &Opts,
|
||||
std::vector<char> &Defs) {
|
||||
// DragonFly defines; list based off of gcc output
|
||||
Define(Defs, "__DragonFly__");
|
||||
Define(Defs, "__DragonFly_cc_version", "100001");
|
||||
Define(Defs, "__ELF__");
|
||||
Define(Defs, "__KPRINTF_ATTRIBUTE__");
|
||||
Define(Defs, "__tune_i386__");
|
||||
DefineStd(Defs, "unix", Opts);
|
||||
}
|
||||
|
||||
static void getLinuxDefines(const LangOptions &Opts, std::vector<char> &Defs) {
|
||||
// Linux defines; list based off of gcc output
|
||||
DefineStd(Defs, "unix", Opts);
|
||||
DefineStd(Defs, "linux", Opts);
|
||||
Define(Defs, "__gnu_linux__");
|
||||
Define(Defs, "__ELF__", "1");
|
||||
}
|
||||
|
||||
namespace {
|
||||
/// getDarwinNumber - Parse the 'darwin number' out of the specific targe
|
||||
/// triple. For example, if we have darwin8.5 return 8,5,0. If any entry is
|
||||
/// not defined, return 0's. Return true if we have -darwin in the string or
|
||||
@ -235,15 +204,160 @@ static void GetDarwinLanguageOptions(LangOptions &Opts,
|
||||
if (!getDarwinNumber(Triple, Maj, Min, Rev))
|
||||
return;
|
||||
|
||||
// Blocks default to on for 10.6 (darwin10) and beyond.
|
||||
// As does nonfragile-abi for 64bit mode
|
||||
if (Maj > 9)
|
||||
// Blocks and stack protectors default to on for 10.6 (darwin10) and beyond.
|
||||
if (Maj > 9) {
|
||||
Opts.Blocks = 1;
|
||||
Opts.setStackProtectorMode(LangOptions::SSPOn);
|
||||
}
|
||||
|
||||
// Non-fragile ABI (in 64-bit mode) default to on for 10.5 (darwin9) and
|
||||
// beyond.
|
||||
if (Maj >= 9 && Opts.ObjC1 && !strncmp(Triple, "x86_64", 6))
|
||||
Opts.ObjCNonFragileABI = 1;
|
||||
}
|
||||
|
||||
template<typename Target>
|
||||
class DarwinTargetInfo : public OSTargetInfo<Target> {
|
||||
protected:
|
||||
virtual void getOSDefines(const LangOptions &Opts, const char *Triple,
|
||||
std::vector<char> &Defines) const {
|
||||
getDarwinDefines(Defines, Opts);
|
||||
getDarwinOSXDefines(Defines, Triple);
|
||||
}
|
||||
|
||||
/// getDefaultLangOptions - Allow the target to specify default settings for
|
||||
/// various language options. These may be overridden by command line
|
||||
/// options.
|
||||
virtual void getDefaultLangOptions(LangOptions &Opts) {
|
||||
TargetInfo::getDefaultLangOptions(Opts);
|
||||
GetDarwinLanguageOptions(Opts, TargetInfo::getTargetTriple());
|
||||
}
|
||||
public:
|
||||
DarwinTargetInfo(const std::string& triple) :
|
||||
OSTargetInfo<Target>(triple) {
|
||||
this->TLSSupported = false;
|
||||
}
|
||||
|
||||
virtual const char *getCFStringSymbolPrefix() const {
|
||||
return "\01L_unnamed_cfstring_";
|
||||
}
|
||||
|
||||
virtual const char *getStringSymbolPrefix(bool IsConstant) const {
|
||||
return IsConstant ? "\01LC" : "\01lC";
|
||||
}
|
||||
|
||||
virtual const char *getUnicodeStringSymbolPrefix() const {
|
||||
return "__utf16_string_";
|
||||
}
|
||||
|
||||
virtual const char *getUnicodeStringSection() const {
|
||||
return "__TEXT,__ustring";
|
||||
}
|
||||
};
|
||||
|
||||
// DragonFlyBSD Target
|
||||
template<typename Target>
|
||||
class DragonFlyBSDTargetInfo : public OSTargetInfo<Target> {
|
||||
protected:
|
||||
virtual void getOSDefines(const LangOptions &Opts, const char *Triple,
|
||||
std::vector<char> &Defs) const {
|
||||
// DragonFly defines; list based off of gcc output
|
||||
Define(Defs, "__DragonFly__");
|
||||
Define(Defs, "__DragonFly_cc_version", "100001");
|
||||
Define(Defs, "__ELF__");
|
||||
Define(Defs, "__KPRINTF_ATTRIBUTE__");
|
||||
Define(Defs, "__tune_i386__");
|
||||
DefineStd(Defs, "unix", Opts);
|
||||
}
|
||||
public:
|
||||
DragonFlyBSDTargetInfo(const std::string &triple)
|
||||
: OSTargetInfo<Target>(triple) {}
|
||||
};
|
||||
|
||||
// FreeBSD Target
|
||||
template<typename Target>
|
||||
class FreeBSDTargetInfo : public OSTargetInfo<Target> {
|
||||
protected:
|
||||
virtual void getOSDefines(const LangOptions &Opts, const char *Triple,
|
||||
std::vector<char> &Defs) const {
|
||||
// FreeBSD defines; list based off of gcc output
|
||||
|
||||
const char *FreeBSD = strstr(Triple, "-freebsd");
|
||||
FreeBSD += strlen("-freebsd");
|
||||
char release[] = "X";
|
||||
release[0] = FreeBSD[0];
|
||||
char version[] = "X00001";
|
||||
version[0] = FreeBSD[0];
|
||||
|
||||
Define(Defs, "__FreeBSD__", release);
|
||||
Define(Defs, "__FreeBSD_cc_version", version);
|
||||
Define(Defs, "__KPRINTF_ATTRIBUTE__");
|
||||
DefineStd(Defs, "unix", Opts);
|
||||
Define(Defs, "__ELF__", "1");
|
||||
}
|
||||
public:
|
||||
FreeBSDTargetInfo(const std::string &triple)
|
||||
: OSTargetInfo<Target>(triple) {}
|
||||
};
|
||||
|
||||
// Linux target
|
||||
template<typename Target>
|
||||
class LinuxTargetInfo : public OSTargetInfo<Target> {
|
||||
protected:
|
||||
virtual void getOSDefines(const LangOptions &Opts, const char *Triple,
|
||||
std::vector<char> &Defs) const {
|
||||
// Linux defines; list based off of gcc output
|
||||
DefineStd(Defs, "unix", Opts);
|
||||
DefineStd(Defs, "linux", Opts);
|
||||
Define(Defs, "__gnu_linux__");
|
||||
Define(Defs, "__ELF__", "1");
|
||||
}
|
||||
public:
|
||||
LinuxTargetInfo(const std::string& triple)
|
||||
: OSTargetInfo<Target>(triple) {
|
||||
this->UserLabelPrefix = "";
|
||||
}
|
||||
};
|
||||
|
||||
// OpenBSD Target
|
||||
template<typename Target>
|
||||
class OpenBSDTargetInfo : public OSTargetInfo<Target> {
|
||||
protected:
|
||||
virtual void getOSDefines(const LangOptions &Opts, const char *Triple,
|
||||
std::vector<char> &Defs) const {
|
||||
// OpenBSD defines; list based off of gcc output
|
||||
|
||||
Define(Defs, "__OpenBSD__", "1");
|
||||
DefineStd(Defs, "unix", Opts);
|
||||
Define(Defs, "__ELF__", "1");
|
||||
}
|
||||
public:
|
||||
OpenBSDTargetInfo(const std::string &triple)
|
||||
: OSTargetInfo<Target>(triple) {}
|
||||
};
|
||||
|
||||
// Solaris target
|
||||
template<typename Target>
|
||||
class SolarisTargetInfo : public OSTargetInfo<Target> {
|
||||
protected:
|
||||
virtual void getOSDefines(const LangOptions &Opts, const char *Triple,
|
||||
std::vector<char> &Defs) const {
|
||||
DefineStd(Defs, "sun", Opts);
|
||||
DefineStd(Defs, "unix", Opts);
|
||||
Define(Defs, "__ELF__");
|
||||
Define(Defs, "__svr4__");
|
||||
Define(Defs, "__SVR4");
|
||||
}
|
||||
public:
|
||||
SolarisTargetInfo(const std::string& triple)
|
||||
: OSTargetInfo<Target>(triple) {
|
||||
this->UserLabelPrefix = "";
|
||||
this->WCharType = this->SignedLong;
|
||||
// FIXME: WIntType should be SignedLong
|
||||
}
|
||||
};
|
||||
} // end anonymous namespace.
|
||||
|
||||
/// GetWindowsLanguageOptions - Set the default language options for Windows.
|
||||
static void GetWindowsLanguageOptions(LangOptions &Opts,
|
||||
const char *Triple) {
|
||||
@ -435,55 +549,15 @@ class PPC64TargetInfo : public PPCTargetInfo {
|
||||
public:
|
||||
PPC64TargetInfo(const std::string& triple) : PPCTargetInfo(triple) {
|
||||
LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
|
||||
IntMaxType = SignedLong;
|
||||
UIntMaxType = UnsignedLong;
|
||||
Int64Type = SignedLong;
|
||||
DescriptionString = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
|
||||
"i64:64:64-f32:32:32-f64:64:64-v128:128:128";
|
||||
}
|
||||
};
|
||||
} // end anonymous namespace.
|
||||
|
||||
|
||||
namespace {
|
||||
class DarwinPPCTargetInfo : public PPC32TargetInfo {
|
||||
public:
|
||||
DarwinPPCTargetInfo(const std::string& triple) : PPC32TargetInfo(triple) {}
|
||||
virtual void getTargetDefines(const LangOptions &Opts,
|
||||
std::vector<char> &Defines) const {
|
||||
PPC32TargetInfo::getTargetDefines(Opts, Defines);
|
||||
getDarwinDefines(Defines, Opts);
|
||||
getDarwinOSXDefines(Defines, getTargetTriple());
|
||||
}
|
||||
|
||||
/// getDefaultLangOptions - Allow the target to specify default settings for
|
||||
/// various language options. These may be overridden by command line
|
||||
/// options.
|
||||
virtual void getDefaultLangOptions(LangOptions &Opts) {
|
||||
PPC32TargetInfo::getDefaultLangOptions(Opts);
|
||||
GetDarwinLanguageOptions(Opts, getTargetTriple());
|
||||
}
|
||||
};
|
||||
} // end anonymous namespace.
|
||||
|
||||
namespace {
|
||||
class DarwinPPC64TargetInfo : public PPC64TargetInfo {
|
||||
public:
|
||||
DarwinPPC64TargetInfo(const std::string& triple) : PPC64TargetInfo(triple) {}
|
||||
virtual void getTargetDefines(const LangOptions &Opts,
|
||||
std::vector<char> &Defines) const {
|
||||
PPC64TargetInfo::getTargetDefines(Opts, Defines);
|
||||
getDarwinDefines(Defines, Opts);
|
||||
getDarwinOSXDefines(Defines, getTargetTriple());
|
||||
}
|
||||
|
||||
/// getDefaultLangOptions - Allow the target to specify default settings for
|
||||
/// various language options. These may be overridden by command line
|
||||
/// options.
|
||||
virtual void getDefaultLangOptions(LangOptions &Opts) {
|
||||
PPC64TargetInfo::getDefaultLangOptions(Opts);
|
||||
GetDarwinLanguageOptions(Opts, getTargetTriple());
|
||||
}
|
||||
};
|
||||
} // end anonymous namespace.
|
||||
|
||||
namespace {
|
||||
// Namespace for x86 abstract base class
|
||||
const Builtin::Info BuiltinInfo[] = {
|
||||
@ -815,10 +889,10 @@ class X86_32TargetInfo : public X86TargetInfo {
|
||||
} // end anonymous namespace
|
||||
|
||||
namespace {
|
||||
// x86-32 Darwin (OS X) target
|
||||
class DarwinI386TargetInfo : public X86_32TargetInfo {
|
||||
class DarwinI386TargetInfo : public DarwinTargetInfo<X86_32TargetInfo> {
|
||||
public:
|
||||
DarwinI386TargetInfo(const std::string& triple) : X86_32TargetInfo(triple) {
|
||||
DarwinI386TargetInfo(const std::string& triple) :
|
||||
DarwinTargetInfo<X86_32TargetInfo>(triple) {
|
||||
LongDoubleWidth = 128;
|
||||
LongDoubleAlign = 128;
|
||||
SizeType = UnsignedLong;
|
||||
@ -826,103 +900,11 @@ class DarwinI386TargetInfo : public X86_32TargetInfo {
|
||||
DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
|
||||
"i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-"
|
||||
"a0:0:64-f80:128:128";
|
||||
TLSSupported = false;
|
||||
}
|
||||
|
||||
virtual const char *getStringSymbolPrefix(bool IsConstant) const {
|
||||
return IsConstant ? "\01LC" : "\01lC";
|
||||
}
|
||||
|
||||
virtual const char *getUnicodeStringSymbolPrefix() const {
|
||||
return "__utf16_string_";
|
||||
}
|
||||
|
||||
virtual const char *getUnicodeStringSection() const {
|
||||
return "__TEXT,__ustring";
|
||||
}
|
||||
|
||||
virtual const char *getCFStringSymbolPrefix() const {
|
||||
return "\01LC";
|
||||
}
|
||||
|
||||
virtual void getTargetDefines(const LangOptions &Opts,
|
||||
std::vector<char> &Defines) const {
|
||||
X86_32TargetInfo::getTargetDefines(Opts, Defines);
|
||||
getDarwinDefines(Defines, Opts);
|
||||
getDarwinOSXDefines(Defines, getTargetTriple());
|
||||
}
|
||||
|
||||
/// getDefaultLangOptions - Allow the target to specify default settings for
|
||||
/// various language options. These may be overridden by command line
|
||||
/// options.
|
||||
virtual void getDefaultLangOptions(LangOptions &Opts) {
|
||||
X86_32TargetInfo::getDefaultLangOptions(Opts);
|
||||
GetDarwinLanguageOptions(Opts, getTargetTriple());
|
||||
}
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
namespace {
|
||||
// x86-32 FreeBSD target
|
||||
class FreeBSDX86_32TargetInfo : public X86_32TargetInfo {
|
||||
public:
|
||||
FreeBSDX86_32TargetInfo(const std::string& triple) :
|
||||
X86_32TargetInfo(triple) { }
|
||||
virtual void getTargetDefines(const LangOptions &Opts,
|
||||
std::vector<char> &Defines) const {
|
||||
X86_32TargetInfo::getTargetDefines(Opts, Defines);
|
||||
getFreeBSDDefines(Opts, 0, getTargetTriple(), Defines);
|
||||
}
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
namespace {
|
||||
// x86-32 DragonFly target
|
||||
class DragonFlyX86_32TargetInfo : public X86_32TargetInfo {
|
||||
public:
|
||||
DragonFlyX86_32TargetInfo(const std::string& triple) :
|
||||
X86_32TargetInfo(triple) { }
|
||||
virtual void getTargetDefines(const LangOptions &Opts,
|
||||
std::vector<char> &Defines) const {
|
||||
X86_32TargetInfo::getTargetDefines(Opts, Defines);
|
||||
getDragonFlyDefines(Opts, Defines);
|
||||
}
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
namespace {
|
||||
// x86-32 Linux target
|
||||
class LinuxX86_32TargetInfo : public X86_32TargetInfo {
|
||||
public:
|
||||
LinuxX86_32TargetInfo(const std::string& triple) : X86_32TargetInfo(triple) {
|
||||
UserLabelPrefix = "";
|
||||
}
|
||||
virtual void getTargetDefines(const LangOptions &Opts,
|
||||
std::vector<char> &Defines) const {
|
||||
X86_32TargetInfo::getTargetDefines(Opts, Defines);
|
||||
getLinuxDefines(Opts, Defines);
|
||||
}
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
namespace {
|
||||
// x86-32 Solaris target
|
||||
class SolarisX86_32TargetInfo : public X86_32TargetInfo {
|
||||
public:
|
||||
SolarisX86_32TargetInfo(const std::string& triple) : X86_32TargetInfo(triple) {
|
||||
UserLabelPrefix = "";
|
||||
WCharType = SignedLong;
|
||||
// FIXME: WIntType should be SignedLong
|
||||
}
|
||||
virtual void getTargetDefines(const LangOptions &Opts,
|
||||
std::vector<char> &Defines) const {
|
||||
X86_32TargetInfo::getTargetDefines(Opts, Defines);
|
||||
getSolarisDefines(Opts, Defines);
|
||||
}
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
|
||||
namespace {
|
||||
// x86-32 Windows target
|
||||
class WindowsX86_32TargetInfo : public X86_32TargetInfo {
|
||||
@ -961,11 +943,11 @@ class X86_64TargetInfo : public X86TargetInfo {
|
||||
public:
|
||||
X86_64TargetInfo(const std::string &triple) : X86TargetInfo(triple) {
|
||||
LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
|
||||
DoubleAlign = LongLongAlign = 64;
|
||||
LongDoubleWidth = 128;
|
||||
LongDoubleAlign = 128;
|
||||
IntMaxType = SignedLong;
|
||||
UIntMaxType = UnsignedLong;
|
||||
Int64Type = SignedLong;
|
||||
RegParmMax = 6;
|
||||
|
||||
DescriptionString = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
|
||||
@ -978,95 +960,22 @@ class X86_64TargetInfo : public X86TargetInfo {
|
||||
" unsigned fp_offset;"
|
||||
" void* overflow_arg_area;"
|
||||
" void* reg_save_area;"
|
||||
"} __builtin_va_list[1];";
|
||||
"} __va_list_tag;"
|
||||
"typedef __va_list_tag __builtin_va_list[1];";
|
||||
}
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
namespace {
|
||||
// x86-64 FreeBSD target
|
||||
class FreeBSDX86_64TargetInfo : public X86_64TargetInfo {
|
||||
class DarwinX86_64TargetInfo : public DarwinTargetInfo<X86_64TargetInfo> {
|
||||
public:
|
||||
FreeBSDX86_64TargetInfo(const std::string &triple)
|
||||
: X86_64TargetInfo(triple) {}
|
||||
virtual void getTargetDefines(const LangOptions &Opts,
|
||||
std::vector<char> &Defines) const {
|
||||
X86_64TargetInfo::getTargetDefines(Opts, Defines);
|
||||
getFreeBSDDefines(Opts, 1, getTargetTriple(), Defines);
|
||||
DarwinX86_64TargetInfo(const std::string& triple)
|
||||
: DarwinTargetInfo<X86_64TargetInfo>(triple) {
|
||||
Int64Type = SignedLongLong;
|
||||
}
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
namespace {
|
||||
// x86-64 Linux target
|
||||
class LinuxX86_64TargetInfo : public X86_64TargetInfo {
|
||||
public:
|
||||
LinuxX86_64TargetInfo(const std::string& triple) : X86_64TargetInfo(triple) {
|
||||
UserLabelPrefix = "";
|
||||
}
|
||||
virtual void getTargetDefines(const LangOptions &Opts,
|
||||
std::vector<char> &Defines) const {
|
||||
X86_64TargetInfo::getTargetDefines(Opts, Defines);
|
||||
getLinuxDefines(Opts, Defines);
|
||||
}
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
namespace {
|
||||
// x86-64 Solaris target
|
||||
class SolarisX86_64TargetInfo : public X86_64TargetInfo {
|
||||
public:
|
||||
SolarisX86_64TargetInfo(const std::string& triple) : X86_64TargetInfo(triple) {
|
||||
UserLabelPrefix = "";
|
||||
}
|
||||
virtual void getTargetDefines(const LangOptions &Opts,
|
||||
std::vector<char> &Defines) const {
|
||||
X86_64TargetInfo::getTargetDefines(Opts, Defines);
|
||||
getSolarisDefines(Opts, Defines);
|
||||
}
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
namespace {
|
||||
// x86-64 Darwin (OS X) target
|
||||
class DarwinX86_64TargetInfo : public X86_64TargetInfo {
|
||||
public:
|
||||
DarwinX86_64TargetInfo(const std::string& triple) : X86_64TargetInfo(triple) {
|
||||
TLSSupported = false;
|
||||
}
|
||||
|
||||
virtual const char *getStringSymbolPrefix(bool IsConstant) const {
|
||||
return IsConstant ? "\01LC" : "\01lC";
|
||||
}
|
||||
|
||||
virtual const char *getUnicodeStringSymbolPrefix() const {
|
||||
return "__utf16_string_";
|
||||
}
|
||||
|
||||
virtual const char *getUnicodeStringSection() const {
|
||||
return "__TEXT,__ustring";
|
||||
}
|
||||
|
||||
virtual const char *getCFStringSymbolPrefix() const {
|
||||
return "\01L_unnamed_cfstring_";
|
||||
}
|
||||
|
||||
virtual void getTargetDefines(const LangOptions &Opts,
|
||||
std::vector<char> &Defines) const {
|
||||
X86_64TargetInfo::getTargetDefines(Opts, Defines);
|
||||
getDarwinDefines(Defines, Opts);
|
||||
getDarwinOSXDefines(Defines, getTargetTriple());
|
||||
}
|
||||
|
||||
/// getDefaultLangOptions - Allow the target to specify default settings for
|
||||
/// various language options. These may be overridden by command line
|
||||
/// options.
|
||||
virtual void getDefaultLangOptions(LangOptions &Opts) {
|
||||
GetDarwinLanguageOptions(Opts, getTargetTriple());
|
||||
}
|
||||
};
|
||||
} // end anonymous namespace.
|
||||
|
||||
namespace {
|
||||
class ARMTargetInfo : public TargetInfo {
|
||||
enum {
|
||||
@ -1171,34 +1080,21 @@ class ARMTargetInfo : public TargetInfo {
|
||||
|
||||
|
||||
namespace {
|
||||
class DarwinARMTargetInfo : public ARMTargetInfo {
|
||||
public:
|
||||
DarwinARMTargetInfo(const std::string& triple) : ARMTargetInfo(triple) {
|
||||
TLSSupported = false;
|
||||
class DarwinARMTargetInfo :
|
||||
public DarwinTargetInfo<ARMTargetInfo> {
|
||||
protected:
|
||||
virtual void getOSDefines(const LangOptions &Opts, const char *Triple,
|
||||
std::vector<char> &Defines) const {
|
||||
getDarwinDefines(Defines, Opts);
|
||||
getDarwinIPhoneOSDefines(Defines, Triple);
|
||||
}
|
||||
|
||||
virtual void getTargetDefines(const LangOptions &Opts,
|
||||
std::vector<char> &Defines) const {
|
||||
ARMTargetInfo::getTargetDefines(Opts, Defines);
|
||||
getDarwinDefines(Defines, Opts);
|
||||
getDarwinIPhoneOSDefines(Defines, getTargetTriple());
|
||||
}
|
||||
public:
|
||||
DarwinARMTargetInfo(const std::string& triple)
|
||||
: DarwinTargetInfo<ARMTargetInfo>(triple) {}
|
||||
};
|
||||
} // end anonymous namespace.
|
||||
|
||||
namespace {
|
||||
// arm FreeBSD target
|
||||
class FreeBSDARMTargetInfo : public ARMTargetInfo {
|
||||
public:
|
||||
FreeBSDARMTargetInfo(const std::string& triple) : ARMTargetInfo(triple) {}
|
||||
virtual void getTargetDefines(const LangOptions &Opts,
|
||||
std::vector<char> &Defines) const {
|
||||
ARMTargetInfo::getTargetDefines(Opts, Defines);
|
||||
getFreeBSDDefines(Opts, 0, getTargetTriple(), Defines);
|
||||
}
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
namespace {
|
||||
class SparcV8TargetInfo : public TargetInfo {
|
||||
static const TargetInfo::GCCRegAlias GCCRegAliases[];
|
||||
@ -1296,21 +1192,12 @@ void SparcV8TargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases,
|
||||
} // end anonymous namespace.
|
||||
|
||||
namespace {
|
||||
class SolarisSparcV8TargetInfo : public SparcV8TargetInfo {
|
||||
class SolarisSparcV8TargetInfo : public SolarisTargetInfo<SparcV8TargetInfo> {
|
||||
public:
|
||||
SolarisSparcV8TargetInfo(const std::string& triple) :
|
||||
SparcV8TargetInfo(triple) {
|
||||
SolarisTargetInfo<SparcV8TargetInfo>(triple) {
|
||||
SizeType = UnsignedInt;
|
||||
PtrDiffType = SignedInt;
|
||||
WCharType = SignedLong;
|
||||
// FIXME: WIntType should be SignedLong
|
||||
UserLabelPrefix = "";
|
||||
}
|
||||
|
||||
virtual void getTargetDefines(const LangOptions &Opts,
|
||||
std::vector<char> &Defines) const {
|
||||
SparcV8TargetInfo::getTargetDefines(Opts, Defines);
|
||||
getSolarisDefines(Opts, Defines);
|
||||
}
|
||||
};
|
||||
} // end anonymous namespace.
|
||||
@ -1454,6 +1341,7 @@ TargetInfo* TargetInfo::CreateTargetInfo(const std::string &T) {
|
||||
// Additions and corrections are welcome.
|
||||
bool isDarwin = T.find("-darwin") != std::string::npos;
|
||||
bool isDragonFly = T.find("-dragonfly") != std::string::npos;
|
||||
bool isOpenBSD = T.find("-openbsd") != std::string::npos;
|
||||
bool isFreeBSD = T.find("-freebsd") != std::string::npos;
|
||||
bool isSolaris = T.find("-solaris") != std::string::npos;
|
||||
bool isLinux = T.find("-linux") != std::string::npos;
|
||||
@ -1463,13 +1351,13 @@ TargetInfo* TargetInfo::CreateTargetInfo(const std::string &T) {
|
||||
|
||||
if (T.find("ppc-") == 0 || T.find("powerpc-") == 0) {
|
||||
if (isDarwin)
|
||||
return new DarwinPPCTargetInfo(T);
|
||||
return new DarwinTargetInfo<PPCTargetInfo>(T);
|
||||
return new PPC32TargetInfo(T);
|
||||
}
|
||||
|
||||
if (T.find("ppc64-") == 0 || T.find("powerpc64-") == 0) {
|
||||
if (isDarwin)
|
||||
return new DarwinPPC64TargetInfo(T);
|
||||
return new DarwinTargetInfo<PPC64TargetInfo>(T);
|
||||
return new PPC64TargetInfo(T);
|
||||
}
|
||||
|
||||
@ -1477,7 +1365,7 @@ TargetInfo* TargetInfo::CreateTargetInfo(const std::string &T) {
|
||||
if (isDarwin)
|
||||
return new DarwinARMTargetInfo(T);
|
||||
if (isFreeBSD)
|
||||
return new FreeBSDARMTargetInfo(T);
|
||||
return new FreeBSDTargetInfo<ARMTargetInfo>(T);
|
||||
return new ARMTargetInfo(T);
|
||||
}
|
||||
|
||||
@ -1491,11 +1379,13 @@ TargetInfo* TargetInfo::CreateTargetInfo(const std::string &T) {
|
||||
if (isDarwin)
|
||||
return new DarwinX86_64TargetInfo(T);
|
||||
if (isLinux)
|
||||
return new LinuxX86_64TargetInfo(T);
|
||||
return new LinuxTargetInfo<X86_64TargetInfo>(T);
|
||||
if (isOpenBSD)
|
||||
return new OpenBSDTargetInfo<X86_64TargetInfo>(T);
|
||||
if (isFreeBSD)
|
||||
return new FreeBSDX86_64TargetInfo(T);
|
||||
return new FreeBSDTargetInfo<X86_64TargetInfo>(T);
|
||||
if (isSolaris)
|
||||
return new SolarisX86_64TargetInfo(T);
|
||||
return new SolarisTargetInfo<X86_64TargetInfo>(T);
|
||||
return new X86_64TargetInfo(T);
|
||||
}
|
||||
|
||||
@ -1509,13 +1399,15 @@ TargetInfo* TargetInfo::CreateTargetInfo(const std::string &T) {
|
||||
if (isDarwin)
|
||||
return new DarwinI386TargetInfo(T);
|
||||
if (isLinux)
|
||||
return new LinuxX86_32TargetInfo(T);
|
||||
return new LinuxTargetInfo<X86_32TargetInfo>(T);
|
||||
if (isDragonFly)
|
||||
return new DragonFlyX86_32TargetInfo(T);
|
||||
return new DragonFlyBSDTargetInfo<X86_32TargetInfo>(T);
|
||||
if (isOpenBSD)
|
||||
return new OpenBSDTargetInfo<X86_32TargetInfo>(T);
|
||||
if (isFreeBSD)
|
||||
return new FreeBSDX86_32TargetInfo(T);
|
||||
return new FreeBSDTargetInfo<X86_32TargetInfo>(T);
|
||||
if (isSolaris)
|
||||
return new SolarisX86_32TargetInfo(T);
|
||||
return new SolarisTargetInfo<X86_32TargetInfo>(T);
|
||||
if (isWindows)
|
||||
return new WindowsX86_32TargetInfo(T);
|
||||
return new X86_32TargetInfo(T);
|
||||
|
@ -522,7 +522,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
|
||||
case Builtin::BIsqrtf:
|
||||
case Builtin::BIsqrtl: {
|
||||
// Rewrite sqrt to intrinsic if allowed.
|
||||
if (!FD->hasAttr<ConstAttr>(getContext()))
|
||||
if (!FD->hasAttr<ConstAttr>())
|
||||
break;
|
||||
Value *Arg0 = EmitScalarExpr(E->getArg(0));
|
||||
const llvm::Type *ArgType = Arg0->getType();
|
||||
@ -534,7 +534,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
|
||||
case Builtin::BIpowf:
|
||||
case Builtin::BIpowl: {
|
||||
// Rewrite sqrt to intrinsic if allowed.
|
||||
if (!FD->hasAttr<ConstAttr>(getContext()))
|
||||
if (!FD->hasAttr<ConstAttr>())
|
||||
break;
|
||||
Value *Base = EmitScalarExpr(E->getArg(0));
|
||||
Value *Exponent = EmitScalarExpr(E->getArg(1));
|
||||
|
@ -323,8 +323,8 @@ static bool canGenerateCXXstructor(const CXXRecordDecl *RD,
|
||||
if (RD->getNumBases() > 0)
|
||||
return false;
|
||||
|
||||
for (CXXRecordDecl::field_iterator I = RD->field_begin(Context),
|
||||
E = RD->field_end(Context); I != E; ++I) {
|
||||
for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
|
||||
I != E; ++I) {
|
||||
// We don't support ctors for fields that aren't POD.
|
||||
if (!I->getType()->isPODType())
|
||||
return false;
|
||||
|
@ -142,8 +142,8 @@ void CodeGenTypes::GetExpandedTypes(QualType Ty,
|
||||
assert(!RD->hasFlexibleArrayMember() &&
|
||||
"Cannot expand structure with flexible array.");
|
||||
|
||||
for (RecordDecl::field_iterator i = RD->field_begin(Context),
|
||||
e = RD->field_end(Context); i != e; ++i) {
|
||||
for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
|
||||
i != e; ++i) {
|
||||
const FieldDecl *FD = *i;
|
||||
assert(!FD->isBitField() &&
|
||||
"Cannot expand structure with bit-field members.");
|
||||
@ -167,8 +167,8 @@ CodeGenFunction::ExpandTypeFromArgs(QualType Ty, LValue LV,
|
||||
assert(LV.isSimple() &&
|
||||
"Unexpected non-simple lvalue during struct expansion.");
|
||||
llvm::Value *Addr = LV.getAddress();
|
||||
for (RecordDecl::field_iterator i = RD->field_begin(getContext()),
|
||||
e = RD->field_end(getContext()); i != e; ++i) {
|
||||
for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
|
||||
i != e; ++i) {
|
||||
FieldDecl *FD = *i;
|
||||
QualType FT = FD->getType();
|
||||
|
||||
@ -194,8 +194,8 @@ CodeGenFunction::ExpandTypeToArgs(QualType Ty, RValue RV,
|
||||
RecordDecl *RD = RT->getDecl();
|
||||
assert(RV.isAggregate() && "Unexpected rvalue during struct expansion");
|
||||
llvm::Value *Addr = RV.getAggregateAddr();
|
||||
for (RecordDecl::field_iterator i = RD->field_begin(getContext()),
|
||||
e = RD->field_end(getContext()); i != e; ++i) {
|
||||
for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
|
||||
i != e; ++i) {
|
||||
FieldDecl *FD = *i;
|
||||
QualType FT = FD->getType();
|
||||
|
||||
@ -377,13 +377,13 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
|
||||
|
||||
// FIXME: handle sseregparm someday...
|
||||
if (TargetDecl) {
|
||||
if (TargetDecl->hasAttr<NoThrowAttr>(getContext()))
|
||||
if (TargetDecl->hasAttr<NoThrowAttr>())
|
||||
FuncAttrs |= llvm::Attribute::NoUnwind;
|
||||
if (TargetDecl->hasAttr<NoReturnAttr>(getContext()))
|
||||
if (TargetDecl->hasAttr<NoReturnAttr>())
|
||||
FuncAttrs |= llvm::Attribute::NoReturn;
|
||||
if (TargetDecl->hasAttr<ConstAttr>(getContext()))
|
||||
if (TargetDecl->hasAttr<ConstAttr>())
|
||||
FuncAttrs |= llvm::Attribute::ReadNone;
|
||||
else if (TargetDecl->hasAttr<PureAttr>(getContext()))
|
||||
else if (TargetDecl->hasAttr<PureAttr>())
|
||||
FuncAttrs |= llvm::Attribute::ReadOnly;
|
||||
}
|
||||
|
||||
@ -392,6 +392,11 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
|
||||
if (CompileOpts.NoImplicitFloat)
|
||||
FuncAttrs |= llvm::Attribute::NoImplicitFloat;
|
||||
|
||||
if (Features.getStackProtectorMode() == LangOptions::SSPOn)
|
||||
FuncAttrs |= llvm::Attribute::StackProtect;
|
||||
else if (Features.getStackProtectorMode() == LangOptions::SSPReq)
|
||||
FuncAttrs |= llvm::Attribute::StackProtectReq;
|
||||
|
||||
QualType RetTy = FI.getReturnType();
|
||||
unsigned Index = 1;
|
||||
const ABIArgInfo &RetAI = FI.getReturnInfo();
|
||||
@ -433,7 +438,7 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
|
||||
signed RegParm = 0;
|
||||
if (TargetDecl)
|
||||
if (const RegparmAttr *RegParmAttr
|
||||
= TargetDecl->getAttr<RegparmAttr>(getContext()))
|
||||
= TargetDecl->getAttr<RegparmAttr>())
|
||||
RegParm = RegParmAttr->getNumParams();
|
||||
|
||||
unsigned PointerWidth = getContext().Target.getPointerWidth(0);
|
||||
|
@ -151,7 +151,7 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT,
|
||||
uint64_t Offset = 0;
|
||||
|
||||
return DebugFactory.CreateBasicType(Unit,
|
||||
BT->getName(M->getContext().getLangOptions().CPlusPlus),
|
||||
BT->getName(M->getContext().getLangOptions()),
|
||||
Unit, 0, Size, Align,
|
||||
Offset, /*flags*/ 0, Encoding);
|
||||
}
|
||||
@ -437,8 +437,8 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty,
|
||||
const ASTRecordLayout &RL = M->getContext().getASTRecordLayout(Decl);
|
||||
|
||||
unsigned FieldNo = 0;
|
||||
for (RecordDecl::field_iterator I = Decl->field_begin(M->getContext()),
|
||||
E = Decl->field_end(M->getContext());
|
||||
for (RecordDecl::field_iterator I = Decl->field_begin(),
|
||||
E = Decl->field_end();
|
||||
I != E; ++I, ++FieldNo) {
|
||||
FieldDecl *Field = *I;
|
||||
llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit);
|
||||
@ -638,8 +638,7 @@ llvm::DIType CGDebugInfo::CreateType(const EnumType *Ty,
|
||||
|
||||
// Create DIEnumerator elements for each enumerator.
|
||||
for (EnumDecl::enumerator_iterator
|
||||
Enum = Decl->enumerator_begin(M->getContext()),
|
||||
EnumEnd = Decl->enumerator_end(M->getContext());
|
||||
Enum = Decl->enumerator_begin(), EnumEnd = Decl->enumerator_end();
|
||||
Enum != EnumEnd; ++Enum) {
|
||||
Enumerators.push_back(DebugFactory.CreateEnumerator(Enum->getNameAsString(),
|
||||
Enum->getInitVal().getZExtValue()));
|
||||
|
@ -60,7 +60,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
|
||||
/// EmitBlockVarDecl - This method handles emission of any variable declaration
|
||||
/// inside a function, including static vars etc.
|
||||
void CodeGenFunction::EmitBlockVarDecl(const VarDecl &D) {
|
||||
if (D.hasAttr<AsmLabelAttr>(getContext()))
|
||||
if (D.hasAttr<AsmLabelAttr>())
|
||||
CGM.ErrorUnsupported(&D, "__asm__");
|
||||
|
||||
switch (D.getStorageClass()) {
|
||||
@ -171,7 +171,7 @@ void CodeGenFunction::EmitStaticBlockVarDecl(const VarDecl &D) {
|
||||
}
|
||||
|
||||
// FIXME: Merge attribute handling.
|
||||
if (const AnnotateAttr *AA = D.getAttr<AnnotateAttr>(getContext())) {
|
||||
if (const AnnotateAttr *AA = D.getAttr<AnnotateAttr>()) {
|
||||
SourceManager &SM = CGM.getContext().getSourceManager();
|
||||
llvm::Constant *Ann =
|
||||
CGM.EmitAnnotateAttr(GV, AA,
|
||||
@ -179,10 +179,10 @@ void CodeGenFunction::EmitStaticBlockVarDecl(const VarDecl &D) {
|
||||
CGM.AddAnnotation(Ann);
|
||||
}
|
||||
|
||||
if (const SectionAttr *SA = D.getAttr<SectionAttr>(getContext()))
|
||||
if (const SectionAttr *SA = D.getAttr<SectionAttr>())
|
||||
GV->setSection(SA->getName());
|
||||
|
||||
if (D.hasAttr<UsedAttr>(getContext()))
|
||||
if (D.hasAttr<UsedAttr>())
|
||||
CGM.AddUsedGlobal(GV);
|
||||
|
||||
// We may have to cast the constant because of the initializer
|
||||
@ -244,7 +244,7 @@ const llvm::Type *CodeGenFunction::BuildByRefType(QualType Ty,
|
||||
/// These turn into simple stack objects, or GlobalValues depending on target.
|
||||
void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
|
||||
QualType Ty = D.getType();
|
||||
bool isByRef = D.hasAttr<BlocksAttr>(getContext());
|
||||
bool isByRef = D.hasAttr<BlocksAttr>();
|
||||
bool needsDispose = false;
|
||||
unsigned Align = 0;
|
||||
|
||||
@ -414,7 +414,7 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
|
||||
}
|
||||
|
||||
// Handle the cleanup attribute
|
||||
if (const CleanupAttr *CA = D.getAttr<CleanupAttr>(getContext())) {
|
||||
if (const CleanupAttr *CA = D.getAttr<CleanupAttr>()) {
|
||||
const FunctionDecl *FD = CA->getFunctionDecl();
|
||||
|
||||
llvm::Constant* F = CGM.GetAddrOfFunction(GlobalDecl(FD));
|
||||
|
@ -670,7 +670,7 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
|
||||
isa<ImplicitParamDecl>(VD))) {
|
||||
LValue LV;
|
||||
bool NonGCable = VD->hasLocalStorage() &&
|
||||
!VD->hasAttr<BlocksAttr>(getContext());
|
||||
!VD->hasAttr<BlocksAttr>();
|
||||
if (VD->hasExternalStorage()) {
|
||||
llvm::Value *V = CGM.GetAddrOfGlobalVar(VD);
|
||||
if (VD->getType()->isReferenceType())
|
||||
@ -686,7 +686,7 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
|
||||
// local static?
|
||||
if (!NonGCable)
|
||||
attr = getContext().getObjCGCAttrKind(E->getType());
|
||||
if (VD->hasAttr<BlocksAttr>(getContext())) {
|
||||
if (VD->hasAttr<BlocksAttr>()) {
|
||||
bool needsCopyDispose = BlockRequiresCopying(VD->getType());
|
||||
const llvm::Type *PtrStructTy = V->getType();
|
||||
const llvm::Type *Ty = PtrStructTy;
|
||||
|
@ -436,8 +436,8 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
|
||||
#ifndef NDEBUG
|
||||
// Make sure that it's really an empty and not a failure of
|
||||
// semantic analysis.
|
||||
for (RecordDecl::field_iterator Field = SD->field_begin(CGF.getContext()),
|
||||
FieldEnd = SD->field_end(CGF.getContext());
|
||||
for (RecordDecl::field_iterator Field = SD->field_begin(),
|
||||
FieldEnd = SD->field_end();
|
||||
Field != FieldEnd; ++Field)
|
||||
assert(Field->isUnnamedBitfield() && "Only unnamed bitfields allowed");
|
||||
#endif
|
||||
@ -461,8 +461,8 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
|
||||
|
||||
// Here we iterate over the fields; this makes it simpler to both
|
||||
// default-initialize fields and skip over unnamed fields.
|
||||
for (RecordDecl::field_iterator Field = SD->field_begin(CGF.getContext()),
|
||||
FieldEnd = SD->field_end(CGF.getContext());
|
||||
for (RecordDecl::field_iterator Field = SD->field_begin(),
|
||||
FieldEnd = SD->field_end();
|
||||
Field != FieldEnd; ++Field) {
|
||||
// We're done once we hit the flexible array member
|
||||
if (Field->getType()->isIncompleteArrayType())
|
||||
|
@ -199,8 +199,8 @@ class VISIBILITY_HIDDEN ConstExprEmitter :
|
||||
// Copy initializer elements. Skip padding fields.
|
||||
unsigned EltNo = 0; // Element no in ILE
|
||||
bool RewriteType = false;
|
||||
for (RecordDecl::field_iterator Field = RD->field_begin(CGM.getContext()),
|
||||
FieldEnd = RD->field_end(CGM.getContext());
|
||||
for (RecordDecl::field_iterator Field = RD->field_begin(),
|
||||
FieldEnd = RD->field_end();
|
||||
EltNo < ILE->getNumInits() && Field != FieldEnd; ++Field) {
|
||||
if (Field->isBitField()) {
|
||||
if (!Field->getIdentifier())
|
||||
@ -263,8 +263,8 @@ class VISIBILITY_HIDDEN ConstExprEmitter :
|
||||
// Make sure that it's really an empty and not a failure of
|
||||
// semantic analysis.
|
||||
RecordDecl *RD = ILE->getType()->getAsRecordType()->getDecl();
|
||||
for (RecordDecl::field_iterator Field = RD->field_begin(CGM.getContext()),
|
||||
FieldEnd = RD->field_end(CGM.getContext());
|
||||
for (RecordDecl::field_iterator Field = RD->field_begin(),
|
||||
FieldEnd = RD->field_end();
|
||||
Field != FieldEnd; ++Field)
|
||||
assert(Field->isUnnamedBitfield() && "Only unnamed bitfields allowed");
|
||||
#endif
|
||||
|
@ -126,11 +126,11 @@ void CodeGenFunction::StartObjCMethod(const ObjCMethodDecl *OMD,
|
||||
/// its pointer, name, and types registered in the class struture.
|
||||
void CodeGenFunction::GenerateObjCMethod(const ObjCMethodDecl *OMD) {
|
||||
// Check if we should generate debug info for this method.
|
||||
if (CGM.getDebugInfo() && !OMD->hasAttr<NodebugAttr>(getContext()))
|
||||
if (CGM.getDebugInfo() && !OMD->hasAttr<NodebugAttr>())
|
||||
DebugInfo = CGM.getDebugInfo();
|
||||
StartObjCMethod(OMD, OMD->getClassInterface());
|
||||
EmitStmt(OMD->getBody(getContext()));
|
||||
FinishFunction(OMD->getBodyRBrace(getContext()));
|
||||
EmitStmt(OMD->getBody());
|
||||
FinishFunction(OMD->getBodyRBrace());
|
||||
}
|
||||
|
||||
// FIXME: I wasn't sure about the synthesis approach. If we end up generating an
|
||||
|
@ -180,7 +180,7 @@ void CGObjCGNU::EmitClassRef(const std::string &className){
|
||||
std::string symbolName = "__objc_class_name_" + className;
|
||||
llvm::GlobalVariable *ClassSymbol = TheModule.getGlobalVariable(symbolName);
|
||||
if (!ClassSymbol) {
|
||||
ClassSymbol = new llvm::GlobalVariable(LongTy, false,
|
||||
ClassSymbol = new llvm::GlobalVariable(LongTy, false,
|
||||
llvm::GlobalValue::ExternalLinkage, 0, symbolName, &TheModule);
|
||||
}
|
||||
new llvm::GlobalVariable(ClassSymbol->getType(), true,
|
||||
@ -739,8 +739,8 @@ void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) {
|
||||
Protocols.push_back((*PI)->getNameAsString());
|
||||
llvm::SmallVector<llvm::Constant*, 16> InstanceMethodNames;
|
||||
llvm::SmallVector<llvm::Constant*, 16> InstanceMethodTypes;
|
||||
for (ObjCProtocolDecl::instmeth_iterator iter = PD->instmeth_begin(Context),
|
||||
E = PD->instmeth_end(Context); iter != E; iter++) {
|
||||
for (ObjCProtocolDecl::instmeth_iterator iter = PD->instmeth_begin(),
|
||||
E = PD->instmeth_end(); iter != E; iter++) {
|
||||
std::string TypeStr;
|
||||
Context.getObjCEncodingForMethodDecl(*iter, TypeStr);
|
||||
InstanceMethodNames.push_back(
|
||||
@ -751,8 +751,8 @@ void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) {
|
||||
llvm::SmallVector<llvm::Constant*, 16> ClassMethodNames;
|
||||
llvm::SmallVector<llvm::Constant*, 16> ClassMethodTypes;
|
||||
for (ObjCProtocolDecl::classmeth_iterator
|
||||
iter = PD->classmeth_begin(Context),
|
||||
endIter = PD->classmeth_end(Context) ; iter != endIter ; iter++) {
|
||||
iter = PD->classmeth_begin(), endIter = PD->classmeth_end();
|
||||
iter != endIter ; iter++) {
|
||||
std::string TypeStr;
|
||||
Context.getObjCEncodingForMethodDecl((*iter),TypeStr);
|
||||
ClassMethodNames.push_back(
|
||||
@ -794,8 +794,7 @@ void CGObjCGNU::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
|
||||
llvm::SmallVector<Selector, 16> InstanceMethodSels;
|
||||
llvm::SmallVector<llvm::Constant*, 16> InstanceMethodTypes;
|
||||
for (ObjCCategoryImplDecl::instmeth_iterator
|
||||
iter = OCD->instmeth_begin(CGM.getContext()),
|
||||
endIter = OCD->instmeth_end(CGM.getContext());
|
||||
iter = OCD->instmeth_begin(), endIter = OCD->instmeth_end();
|
||||
iter != endIter ; iter++) {
|
||||
InstanceMethodSels.push_back((*iter)->getSelector());
|
||||
std::string TypeStr;
|
||||
@ -807,8 +806,7 @@ void CGObjCGNU::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
|
||||
llvm::SmallVector<Selector, 16> ClassMethodSels;
|
||||
llvm::SmallVector<llvm::Constant*, 16> ClassMethodTypes;
|
||||
for (ObjCCategoryImplDecl::classmeth_iterator
|
||||
iter = OCD->classmeth_begin(CGM.getContext()),
|
||||
endIter = OCD->classmeth_end(CGM.getContext());
|
||||
iter = OCD->classmeth_begin(), endIter = OCD->classmeth_end();
|
||||
iter != endIter ; iter++) {
|
||||
ClassMethodSels.push_back((*iter)->getSelector());
|
||||
std::string TypeStr;
|
||||
@ -861,9 +859,14 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
|
||||
std::string ClassName = ClassDecl->getNameAsString();
|
||||
// Emit the symbol that is used to generate linker errors if this class is
|
||||
// referenced in other modules but not declared.
|
||||
new llvm::GlobalVariable(LongTy, false, llvm::GlobalValue::ExternalLinkage,
|
||||
llvm::ConstantInt::get(LongTy, 0), "__objc_class_name_" + ClassName,
|
||||
&TheModule);
|
||||
std::string classSymbolName = "__objc_class_name_" + ClassName;
|
||||
if (llvm::GlobalVariable *symbol =
|
||||
TheModule.getGlobalVariable(classSymbolName)) {
|
||||
symbol->setInitializer(llvm::ConstantInt::get(LongTy, 0));
|
||||
} else {
|
||||
new llvm::GlobalVariable(LongTy, false, llvm::GlobalValue::ExternalLinkage,
|
||||
llvm::ConstantInt::get(LongTy, 0), classSymbolName, &TheModule);
|
||||
}
|
||||
|
||||
// Get the size of instances.
|
||||
int instanceSize = Context.getASTObjCImplementationLayout(OID).getSize() / 8;
|
||||
@ -906,8 +909,7 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
|
||||
llvm::SmallVector<Selector, 16> InstanceMethodSels;
|
||||
llvm::SmallVector<llvm::Constant*, 16> InstanceMethodTypes;
|
||||
for (ObjCImplementationDecl::instmeth_iterator
|
||||
iter = OID->instmeth_begin(CGM.getContext()),
|
||||
endIter = OID->instmeth_end(CGM.getContext());
|
||||
iter = OID->instmeth_begin(), endIter = OID->instmeth_end();
|
||||
iter != endIter ; iter++) {
|
||||
InstanceMethodSels.push_back((*iter)->getSelector());
|
||||
std::string TypeStr;
|
||||
@ -915,8 +917,7 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
|
||||
InstanceMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr));
|
||||
}
|
||||
for (ObjCImplDecl::propimpl_iterator
|
||||
iter = OID->propimpl_begin(CGM.getContext()),
|
||||
endIter = OID->propimpl_end(CGM.getContext());
|
||||
iter = OID->propimpl_begin(), endIter = OID->propimpl_end();
|
||||
iter != endIter ; iter++) {
|
||||
ObjCPropertyDecl *property = (*iter)->getPropertyDecl();
|
||||
if (ObjCMethodDecl *getter = property->getGetterMethodDecl()) {
|
||||
@ -937,8 +938,7 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
|
||||
llvm::SmallVector<Selector, 16> ClassMethodSels;
|
||||
llvm::SmallVector<llvm::Constant*, 16> ClassMethodTypes;
|
||||
for (ObjCImplementationDecl::classmeth_iterator
|
||||
iter = OID->classmeth_begin(CGM.getContext()),
|
||||
endIter = OID->classmeth_end(CGM.getContext());
|
||||
iter = OID->classmeth_begin(), endIter = OID->classmeth_end();
|
||||
iter != endIter ; iter++) {
|
||||
ClassMethodSels.push_back((*iter)->getSelector());
|
||||
std::string TypeStr;
|
||||
@ -1163,9 +1163,8 @@ llvm::Function *CGObjCGNU::ModuleInitFunction() {
|
||||
|
||||
// Create the load function calling the runtime entry point with the module
|
||||
// structure
|
||||
std::vector<const llvm::Type*> VoidArgs;
|
||||
llvm::Function * LoadFunction = llvm::Function::Create(
|
||||
llvm::FunctionType::get(llvm::Type::VoidTy, VoidArgs, false),
|
||||
llvm::FunctionType::get(llvm::Type::VoidTy, false),
|
||||
llvm::GlobalValue::InternalLinkage, ".objc_load_function",
|
||||
&TheModule);
|
||||
llvm::BasicBlock *EntryBB = llvm::BasicBlock::Create("entry", LoadFunction);
|
||||
@ -1250,7 +1249,7 @@ void CGObjCGNU::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
|
||||
// Pointer to the personality function
|
||||
llvm::Constant *Personality =
|
||||
CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::Int32Ty,
|
||||
std::vector<const llvm::Type*>(), true),
|
||||
true),
|
||||
"__gnu_objc_personality_v0");
|
||||
Personality = llvm::ConstantExpr::getBitCast(Personality, PtrTy);
|
||||
std::vector<const llvm::Type*> Params;
|
||||
|
@ -690,7 +690,6 @@ class ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper {
|
||||
llvm::Value *getEHPersonalityPtr() {
|
||||
llvm::Constant *Personality =
|
||||
CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::Int32Ty,
|
||||
std::vector<const llvm::Type*>(),
|
||||
true),
|
||||
"__objc_personality_v0");
|
||||
return llvm::ConstantExpr::getBitCast(Personality, Int8PtrTy);
|
||||
@ -705,9 +704,8 @@ class ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper {
|
||||
}
|
||||
|
||||
llvm::Constant *getObjCEndCatchFn() {
|
||||
std::vector<const llvm::Type*> Params;
|
||||
return CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::VoidTy,
|
||||
Params, false),
|
||||
false),
|
||||
"objc_end_catch");
|
||||
|
||||
}
|
||||
@ -1360,7 +1358,7 @@ static llvm::Constant *getConstantGEP(llvm::Constant *C,
|
||||
/// class has the __objc_exception__ attribute.
|
||||
static bool hasObjCExceptionAttribute(ASTContext &Context,
|
||||
const ObjCInterfaceDecl *OID) {
|
||||
if (OID->hasAttr<ObjCExceptionAttr>(Context))
|
||||
if (OID->hasAttr<ObjCExceptionAttr>())
|
||||
return true;
|
||||
if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
|
||||
return hasObjCExceptionAttribute(Context, Super);
|
||||
@ -1585,8 +1583,7 @@ llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
|
||||
std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
|
||||
std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
|
||||
for (ObjCProtocolDecl::instmeth_iterator
|
||||
i = PD->instmeth_begin(CGM.getContext()),
|
||||
e = PD->instmeth_end(CGM.getContext()); i != e; ++i) {
|
||||
i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
|
||||
ObjCMethodDecl *MD = *i;
|
||||
llvm::Constant *C = GetMethodDescriptionConstant(MD);
|
||||
if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
|
||||
@ -1597,8 +1594,7 @@ llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
|
||||
}
|
||||
|
||||
for (ObjCProtocolDecl::classmeth_iterator
|
||||
i = PD->classmeth_begin(CGM.getContext()),
|
||||
e = PD->classmeth_end(CGM.getContext()); i != e; ++i) {
|
||||
i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
|
||||
ObjCMethodDecl *MD = *i;
|
||||
llvm::Constant *C = GetMethodDescriptionConstant(MD);
|
||||
if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
|
||||
@ -1772,8 +1768,8 @@ llvm::Constant *CGObjCCommonMac::EmitPropertyList(const std::string &Name,
|
||||
const ObjCContainerDecl *OCD,
|
||||
const ObjCCommonTypesHelper &ObjCTypes) {
|
||||
std::vector<llvm::Constant*> Properties, Prop(2);
|
||||
for (ObjCContainerDecl::prop_iterator I = OCD->prop_begin(CGM.getContext()),
|
||||
E = OCD->prop_end(CGM.getContext()); I != E; ++I) {
|
||||
for (ObjCContainerDecl::prop_iterator I = OCD->prop_begin(),
|
||||
E = OCD->prop_end(); I != E; ++I) {
|
||||
const ObjCPropertyDecl *PD = *I;
|
||||
Prop[0] = GetPropertyName(PD->getIdentifier());
|
||||
Prop[1] = GetPropertyTypeString(PD, Container);
|
||||
@ -1865,14 +1861,12 @@ void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
|
||||
|
||||
std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
|
||||
for (ObjCCategoryImplDecl::instmeth_iterator
|
||||
i = OCD->instmeth_begin(CGM.getContext()),
|
||||
e = OCD->instmeth_end(CGM.getContext()); i != e; ++i) {
|
||||
i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
|
||||
// Instance methods should always be defined.
|
||||
InstanceMethods.push_back(GetMethodConstant(*i));
|
||||
}
|
||||
for (ObjCCategoryImplDecl::classmeth_iterator
|
||||
i = OCD->classmeth_begin(CGM.getContext()),
|
||||
e = OCD->classmeth_end(CGM.getContext()); i != e; ++i) {
|
||||
i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
|
||||
// Class methods should always be defined.
|
||||
ClassMethods.push_back(GetMethodConstant(*i));
|
||||
}
|
||||
@ -1969,21 +1963,18 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
|
||||
|
||||
std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
|
||||
for (ObjCImplementationDecl::instmeth_iterator
|
||||
i = ID->instmeth_begin(CGM.getContext()),
|
||||
e = ID->instmeth_end(CGM.getContext()); i != e; ++i) {
|
||||
i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
|
||||
// Instance methods should always be defined.
|
||||
InstanceMethods.push_back(GetMethodConstant(*i));
|
||||
}
|
||||
for (ObjCImplementationDecl::classmeth_iterator
|
||||
i = ID->classmeth_begin(CGM.getContext()),
|
||||
e = ID->classmeth_end(CGM.getContext()); i != e; ++i) {
|
||||
i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
|
||||
// Class methods should always be defined.
|
||||
ClassMethods.push_back(GetMethodConstant(*i));
|
||||
}
|
||||
|
||||
for (ObjCImplementationDecl::propimpl_iterator
|
||||
i = ID->propimpl_begin(CGM.getContext()),
|
||||
e = ID->propimpl_end(CGM.getContext()); i != e; ++i) {
|
||||
i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
|
||||
ObjCPropertyImplDecl *PID = *i;
|
||||
|
||||
if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) {
|
||||
@ -2983,8 +2974,7 @@ void CGObjCCommonMac::BuildAggrIvarRecordLayout(const RecordType *RT,
|
||||
bool &HasUnion) {
|
||||
const RecordDecl *RD = RT->getDecl();
|
||||
// FIXME - Use iterator.
|
||||
llvm::SmallVector<FieldDecl*, 16> Fields(RD->field_begin(CGM.getContext()),
|
||||
RD->field_end(CGM.getContext()));
|
||||
llvm::SmallVector<FieldDecl*, 16> Fields(RD->field_begin(), RD->field_end());
|
||||
const llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0));
|
||||
const llvm::StructLayout *RecLayout =
|
||||
CGM.getTargetData().getStructLayout(cast<llvm::StructType>(Ty));
|
||||
@ -3528,9 +3518,9 @@ ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
|
||||
RecordDecl *RD = RecordDecl::Create(Ctx, TagDecl::TK_struct, 0,
|
||||
SourceLocation(),
|
||||
&Ctx.Idents.get("_objc_super"));
|
||||
RD->addDecl(Ctx, FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
|
||||
RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
|
||||
Ctx.getObjCIdType(), 0, false));
|
||||
RD->addDecl(Ctx, FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
|
||||
RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
|
||||
Ctx.getObjCClassType(), 0, false));
|
||||
RD->completeDefinition(Ctx);
|
||||
|
||||
@ -3987,9 +3977,9 @@ ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModul
|
||||
RecordDecl *RD = RecordDecl::Create(Ctx, TagDecl::TK_struct, 0,
|
||||
SourceLocation(),
|
||||
&Ctx.Idents.get("_message_ref_t"));
|
||||
RD->addDecl(Ctx, FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
|
||||
RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
|
||||
Ctx.VoidPtrTy, 0, false));
|
||||
RD->addDecl(Ctx, FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
|
||||
RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
|
||||
Ctx.getObjCSelType(), 0, false));
|
||||
RD->completeDefinition(Ctx);
|
||||
|
||||
@ -4190,22 +4180,19 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
|
||||
if (flags & CLS_META) {
|
||||
MethodListName += "CLASS_METHODS_" + ID->getNameAsString();
|
||||
for (ObjCImplementationDecl::classmeth_iterator
|
||||
i = ID->classmeth_begin(CGM.getContext()),
|
||||
e = ID->classmeth_end(CGM.getContext()); i != e; ++i) {
|
||||
i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
|
||||
// Class methods should always be defined.
|
||||
Methods.push_back(GetMethodConstant(*i));
|
||||
}
|
||||
} else {
|
||||
MethodListName += "INSTANCE_METHODS_" + ID->getNameAsString();
|
||||
for (ObjCImplementationDecl::instmeth_iterator
|
||||
i = ID->instmeth_begin(CGM.getContext()),
|
||||
e = ID->instmeth_end(CGM.getContext()); i != e; ++i) {
|
||||
i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
|
||||
// Instance methods should always be defined.
|
||||
Methods.push_back(GetMethodConstant(*i));
|
||||
}
|
||||
for (ObjCImplementationDecl::propimpl_iterator
|
||||
i = ID->propimpl_begin(CGM.getContext()),
|
||||
e = ID->propimpl_end(CGM.getContext()); i != e; ++i) {
|
||||
i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
|
||||
ObjCPropertyImplDecl *PID = *i;
|
||||
|
||||
if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize){
|
||||
@ -4298,7 +4285,7 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassMetaData(
|
||||
|
||||
bool
|
||||
CGObjCNonFragileABIMac::ImplementationIsNonLazy(const ObjCImplDecl *OD) const {
|
||||
return OD->getClassMethod(CGM.getContext(), GetNullarySelector("load")) != 0;
|
||||
return OD->getClassMethod(GetNullarySelector("load")) != 0;
|
||||
}
|
||||
|
||||
void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID,
|
||||
@ -4478,8 +4465,7 @@ void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
|
||||
"_$_" + OCD->getNameAsString();
|
||||
|
||||
for (ObjCCategoryImplDecl::instmeth_iterator
|
||||
i = OCD->instmeth_begin(CGM.getContext()),
|
||||
e = OCD->instmeth_end(CGM.getContext()); i != e; ++i) {
|
||||
i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
|
||||
// Instance methods should always be defined.
|
||||
Methods.push_back(GetMethodConstant(*i));
|
||||
}
|
||||
@ -4493,8 +4479,7 @@ void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
|
||||
OCD->getNameAsString();
|
||||
Methods.clear();
|
||||
for (ObjCCategoryImplDecl::classmeth_iterator
|
||||
i = OCD->classmeth_begin(CGM.getContext()),
|
||||
e = OCD->classmeth_end(CGM.getContext()); i != e; ++i) {
|
||||
i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
|
||||
// Class methods should always be defined.
|
||||
Methods.push_back(GetMethodConstant(*i));
|
||||
}
|
||||
@ -4782,9 +4767,7 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
|
||||
std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
|
||||
std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
|
||||
for (ObjCProtocolDecl::instmeth_iterator
|
||||
i = PD->instmeth_begin(CGM.getContext()),
|
||||
e = PD->instmeth_end(CGM.getContext());
|
||||
i != e; ++i) {
|
||||
i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
|
||||
ObjCMethodDecl *MD = *i;
|
||||
llvm::Constant *C = GetMethodDescriptionConstant(MD);
|
||||
if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
|
||||
@ -4795,9 +4778,7 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
|
||||
}
|
||||
|
||||
for (ObjCProtocolDecl::classmeth_iterator
|
||||
i = PD->classmeth_begin(CGM.getContext()),
|
||||
e = PD->classmeth_end(CGM.getContext());
|
||||
i != e; ++i) {
|
||||
i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
|
||||
ObjCMethodDecl *MD = *i;
|
||||
llvm::Constant *C = GetMethodDescriptionConstant(MD);
|
||||
if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
|
||||
|
@ -199,7 +199,7 @@ void CodeGenFunction::StartFunction(const Decl *D, QualType RetTy,
|
||||
void CodeGenFunction::GenerateCode(const FunctionDecl *FD,
|
||||
llvm::Function *Fn) {
|
||||
// Check if we should generate debug info for this function.
|
||||
if (CGM.getDebugInfo() && !FD->hasAttr<NodebugAttr>(getContext()))
|
||||
if (CGM.getDebugInfo() && !FD->hasAttr<NodebugAttr>())
|
||||
DebugInfo = CGM.getDebugInfo();
|
||||
|
||||
FunctionArgList Args;
|
||||
@ -226,7 +226,7 @@ void CodeGenFunction::GenerateCode(const FunctionDecl *FD,
|
||||
}
|
||||
|
||||
// FIXME: Support CXXTryStmt here, too.
|
||||
if (const CompoundStmt *S = FD->getCompoundBody(getContext())) {
|
||||
if (const CompoundStmt *S = FD->getCompoundBody()) {
|
||||
StartFunction(FD, FD->getResultType(), Fn, Args, S->getLBracLoc());
|
||||
EmitStmt(S);
|
||||
FinishFunction(S->getRBracLoc());
|
||||
|
@ -102,7 +102,7 @@ CodeGenModule::getDeclVisibilityMode(const Decl *D) const {
|
||||
if (VD->getStorageClass() == VarDecl::PrivateExtern)
|
||||
return LangOptions::Hidden;
|
||||
|
||||
if (const VisibilityAttr *attr = D->getAttr<VisibilityAttr>(getContext())) {
|
||||
if (const VisibilityAttr *attr = D->getAttr<VisibilityAttr>()) {
|
||||
switch (attr->getVisibility()) {
|
||||
default: assert(0 && "Unknown visibility!");
|
||||
case VisibilityAttr::DefaultVisibility:
|
||||
@ -243,12 +243,20 @@ void CodeGenModule::EmitAnnotations() {
|
||||
static CodeGenModule::GVALinkage
|
||||
GetLinkageForFunction(ASTContext &Context, const FunctionDecl *FD,
|
||||
const LangOptions &Features) {
|
||||
// The kind of external linkage this function will have, if it is not
|
||||
// inline or static.
|
||||
CodeGenModule::GVALinkage External = CodeGenModule::GVA_StrongExternal;
|
||||
if (Context.getLangOptions().CPlusPlus &&
|
||||
(FD->getPrimaryTemplate() || FD->getInstantiatedFromMemberFunction()) &&
|
||||
!FD->isExplicitSpecialization())
|
||||
External = CodeGenModule::GVA_TemplateInstantiation;
|
||||
|
||||
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
|
||||
// C++ member functions defined inside the class are always inline.
|
||||
if (MD->isInline() || !MD->isOutOfLine())
|
||||
return CodeGenModule::GVA_CXXInline;
|
||||
|
||||
return CodeGenModule::GVA_StrongExternal;
|
||||
return External;
|
||||
}
|
||||
|
||||
// "static" functions get internal linkage.
|
||||
@ -256,7 +264,7 @@ GetLinkageForFunction(ASTContext &Context, const FunctionDecl *FD,
|
||||
return CodeGenModule::GVA_Internal;
|
||||
|
||||
if (!FD->isInline())
|
||||
return CodeGenModule::GVA_StrongExternal;
|
||||
return External;
|
||||
|
||||
// If the inline function explicitly has the GNU inline attribute on it, or if
|
||||
// this is C89 mode, we use to GNU semantics.
|
||||
@ -273,7 +281,7 @@ GetLinkageForFunction(ASTContext &Context, const FunctionDecl *FD,
|
||||
if (FD->isExternGNUInline(Context))
|
||||
return CodeGenModule::GVA_C99Inline;
|
||||
// Normal inline is a strong symbol.
|
||||
return CodeGenModule::GVA_StrongExternal;
|
||||
return External;
|
||||
}
|
||||
|
||||
// The definition of inline changes based on the language. Note that we
|
||||
@ -298,15 +306,15 @@ void CodeGenModule::SetFunctionDefinitionAttributes(const FunctionDecl *D,
|
||||
|
||||
if (Linkage == GVA_Internal) {
|
||||
GV->setLinkage(llvm::Function::InternalLinkage);
|
||||
} else if (D->hasAttr<DLLExportAttr>(getContext())) {
|
||||
} else if (D->hasAttr<DLLExportAttr>()) {
|
||||
GV->setLinkage(llvm::Function::DLLExportLinkage);
|
||||
} else if (D->hasAttr<WeakAttr>(getContext())) {
|
||||
} else if (D->hasAttr<WeakAttr>()) {
|
||||
GV->setLinkage(llvm::Function::WeakAnyLinkage);
|
||||
} else if (Linkage == GVA_C99Inline) {
|
||||
// In C99 mode, 'inline' functions are guaranteed to have a strong
|
||||
// definition somewhere else, so we can use available_externally linkage.
|
||||
GV->setLinkage(llvm::Function::AvailableExternallyLinkage);
|
||||
} else if (Linkage == GVA_CXXInline) {
|
||||
} else if (Linkage == GVA_CXXInline || Linkage == GVA_TemplateInstantiation) {
|
||||
// In C++, the compiler has to emit a definition in every translation unit
|
||||
// that references the function. We should use linkonce_odr because
|
||||
// a) if all references in this translation unit are optimized away, we
|
||||
@ -333,10 +341,10 @@ void CodeGenModule::SetLLVMFunctionAttributes(const Decl *D,
|
||||
AttributeList.size()));
|
||||
|
||||
// Set the appropriate calling convention for the Function.
|
||||
if (D->hasAttr<FastCallAttr>(getContext()))
|
||||
if (D->hasAttr<FastCallAttr>())
|
||||
F->setCallingConv(llvm::CallingConv::X86_FastCall);
|
||||
|
||||
if (D->hasAttr<StdCallAttr>(getContext()))
|
||||
if (D->hasAttr<StdCallAttr>())
|
||||
F->setCallingConv(llvm::CallingConv::X86_StdCall);
|
||||
}
|
||||
|
||||
@ -345,10 +353,10 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
|
||||
if (!Features.Exceptions && !Features.ObjCNonFragileABI)
|
||||
F->addFnAttr(llvm::Attribute::NoUnwind);
|
||||
|
||||
if (D->hasAttr<AlwaysInlineAttr>(getContext()))
|
||||
if (D->hasAttr<AlwaysInlineAttr>())
|
||||
F->addFnAttr(llvm::Attribute::AlwaysInline);
|
||||
|
||||
if (D->hasAttr<NoinlineAttr>(getContext()))
|
||||
if (D->hasAttr<NoinlineAttr>())
|
||||
F->addFnAttr(llvm::Attribute::NoInline);
|
||||
}
|
||||
|
||||
@ -356,10 +364,10 @@ void CodeGenModule::SetCommonAttributes(const Decl *D,
|
||||
llvm::GlobalValue *GV) {
|
||||
setGlobalVisibility(GV, D);
|
||||
|
||||
if (D->hasAttr<UsedAttr>(getContext()))
|
||||
if (D->hasAttr<UsedAttr>())
|
||||
AddUsedGlobal(GV);
|
||||
|
||||
if (const SectionAttr *SA = D->getAttr<SectionAttr>(getContext()))
|
||||
if (const SectionAttr *SA = D->getAttr<SectionAttr>())
|
||||
GV->setSection(SA->getName());
|
||||
}
|
||||
|
||||
@ -383,10 +391,10 @@ void CodeGenModule::SetFunctionAttributes(const FunctionDecl *FD,
|
||||
// Only a few attributes are set on declarations; these may later be
|
||||
// overridden by a definition.
|
||||
|
||||
if (FD->hasAttr<DLLImportAttr>(getContext())) {
|
||||
if (FD->hasAttr<DLLImportAttr>()) {
|
||||
F->setLinkage(llvm::Function::DLLImportLinkage);
|
||||
} else if (FD->hasAttr<WeakAttr>(getContext()) ||
|
||||
FD->hasAttr<WeakImportAttr>(getContext())) {
|
||||
} else if (FD->hasAttr<WeakAttr>() ||
|
||||
FD->hasAttr<WeakImportAttr>()) {
|
||||
// "extern_weak" is overloaded in LLVM; we probably should have
|
||||
// separate linkage types for this.
|
||||
F->setLinkage(llvm::Function::ExternalWeakLinkage);
|
||||
@ -394,7 +402,7 @@ void CodeGenModule::SetFunctionAttributes(const FunctionDecl *FD,
|
||||
F->setLinkage(llvm::Function::ExternalLinkage);
|
||||
}
|
||||
|
||||
if (const SectionAttr *SA = FD->getAttr<SectionAttr>(getContext()))
|
||||
if (const SectionAttr *SA = FD->getAttr<SectionAttr>())
|
||||
F->setSection(SA->getName());
|
||||
}
|
||||
|
||||
@ -508,13 +516,13 @@ llvm::Constant *CodeGenModule::EmitAnnotateAttr(llvm::GlobalValue *GV,
|
||||
bool CodeGenModule::MayDeferGeneration(const ValueDecl *Global) {
|
||||
// Never defer when EmitAllDecls is specified or the decl has
|
||||
// attribute used.
|
||||
if (Features.EmitAllDecls || Global->hasAttr<UsedAttr>(getContext()))
|
||||
if (Features.EmitAllDecls || Global->hasAttr<UsedAttr>())
|
||||
return false;
|
||||
|
||||
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Global)) {
|
||||
// Constructors and destructors should never be deferred.
|
||||
if (FD->hasAttr<ConstructorAttr>(getContext()) ||
|
||||
FD->hasAttr<DestructorAttr>(getContext()))
|
||||
if (FD->hasAttr<ConstructorAttr>() ||
|
||||
FD->hasAttr<DestructorAttr>())
|
||||
return false;
|
||||
|
||||
GVALinkage Linkage = GetLinkageForFunction(getContext(), FD, Features);
|
||||
@ -538,7 +546,7 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {
|
||||
|
||||
// If this is an alias definition (which otherwise looks like a declaration)
|
||||
// emit it now.
|
||||
if (Global->hasAttr<AliasAttr>(getContext()))
|
||||
if (Global->hasAttr<AliasAttr>())
|
||||
return EmitAliasDefinition(Global);
|
||||
|
||||
// Ignore declarations, they will be emitted on their first use.
|
||||
@ -727,8 +735,8 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMGlobal(const char *MangledName,
|
||||
if (D->getStorageClass() == VarDecl::PrivateExtern)
|
||||
GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
|
||||
|
||||
if (D->hasAttr<WeakAttr>(getContext()) ||
|
||||
D->hasAttr<WeakImportAttr>(getContext()))
|
||||
if (D->hasAttr<WeakAttr>() ||
|
||||
D->hasAttr<WeakImportAttr>())
|
||||
GV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
|
||||
|
||||
GV->setThreadLocal(D->isThreadSpecified());
|
||||
@ -848,7 +856,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
|
||||
cast<llvm::GlobalValue>(Entry)->eraseFromParent();
|
||||
}
|
||||
|
||||
if (const AnnotateAttr *AA = D->getAttr<AnnotateAttr>(getContext())) {
|
||||
if (const AnnotateAttr *AA = D->getAttr<AnnotateAttr>()) {
|
||||
SourceManager &SM = Context.getSourceManager();
|
||||
AddAnnotation(EmitAnnotateAttr(GV, AA,
|
||||
SM.getInstantiationLineNumber(D->getLocation())));
|
||||
@ -861,11 +869,11 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
|
||||
// Set the llvm linkage type as appropriate.
|
||||
if (D->getStorageClass() == VarDecl::Static)
|
||||
GV->setLinkage(llvm::Function::InternalLinkage);
|
||||
else if (D->hasAttr<DLLImportAttr>(getContext()))
|
||||
else if (D->hasAttr<DLLImportAttr>())
|
||||
GV->setLinkage(llvm::Function::DLLImportLinkage);
|
||||
else if (D->hasAttr<DLLExportAttr>(getContext()))
|
||||
else if (D->hasAttr<DLLExportAttr>())
|
||||
GV->setLinkage(llvm::Function::DLLExportLinkage);
|
||||
else if (D->hasAttr<WeakAttr>(getContext()))
|
||||
else if (D->hasAttr<WeakAttr>())
|
||||
GV->setLinkage(llvm::GlobalVariable::WeakAnyLinkage);
|
||||
else if (!CompileOpts.NoCommon &&
|
||||
(!D->hasExternalStorage() && !D->getInit()))
|
||||
@ -1028,14 +1036,14 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD) {
|
||||
SetFunctionDefinitionAttributes(D, Fn);
|
||||
SetLLVMFunctionAttributesForDefinition(D, Fn);
|
||||
|
||||
if (const ConstructorAttr *CA = D->getAttr<ConstructorAttr>(getContext()))
|
||||
if (const ConstructorAttr *CA = D->getAttr<ConstructorAttr>())
|
||||
AddGlobalCtor(Fn, CA->getPriority());
|
||||
if (const DestructorAttr *DA = D->getAttr<DestructorAttr>(getContext()))
|
||||
if (const DestructorAttr *DA = D->getAttr<DestructorAttr>())
|
||||
AddGlobalDtor(Fn, DA->getPriority());
|
||||
}
|
||||
|
||||
void CodeGenModule::EmitAliasDefinition(const ValueDecl *D) {
|
||||
const AliasAttr *AA = D->getAttr<AliasAttr>(getContext());
|
||||
const AliasAttr *AA = D->getAttr<AliasAttr>();
|
||||
assert(AA && "Not an alias?");
|
||||
|
||||
const llvm::Type *DeclTy = getTypes().ConvertTypeForMem(D->getType());
|
||||
@ -1091,16 +1099,16 @@ void CodeGenModule::EmitAliasDefinition(const ValueDecl *D) {
|
||||
// Set attributes which are particular to an alias; this is a
|
||||
// specialization of the attributes which may be set on a global
|
||||
// variable/function.
|
||||
if (D->hasAttr<DLLExportAttr>(getContext())) {
|
||||
if (D->hasAttr<DLLExportAttr>()) {
|
||||
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
|
||||
// The dllexport attribute is ignored for undefined symbols.
|
||||
if (FD->getBody(getContext()))
|
||||
if (FD->getBody())
|
||||
GA->setLinkage(llvm::Function::DLLExportLinkage);
|
||||
} else {
|
||||
GA->setLinkage(llvm::Function::DLLExportLinkage);
|
||||
}
|
||||
} else if (D->hasAttr<WeakAttr>(getContext()) ||
|
||||
D->hasAttr<WeakImportAttr>(getContext())) {
|
||||
} else if (D->hasAttr<WeakAttr>() ||
|
||||
D->hasAttr<WeakImportAttr>()) {
|
||||
GA->setLinkage(llvm::Function::WeakAnyLinkage);
|
||||
}
|
||||
|
||||
@ -1254,7 +1262,7 @@ GetAddrOfConstantCFString(const StringLiteral *Literal) {
|
||||
cast<llvm::StructType>(getTypes().ConvertType(CFTy));
|
||||
|
||||
std::vector<llvm::Constant*> Fields;
|
||||
RecordDecl::field_iterator Field = CFRD->field_begin(getContext());
|
||||
RecordDecl::field_iterator Field = CFRD->field_begin();
|
||||
|
||||
// Class pointer.
|
||||
FieldDecl *CurField = *Field++;
|
||||
@ -1424,8 +1432,7 @@ llvm::Constant *CodeGenModule::GetAddrOfConstantCString(const std::string &str,
|
||||
void CodeGenModule::EmitObjCPropertyImplementations(const
|
||||
ObjCImplementationDecl *D) {
|
||||
for (ObjCImplementationDecl::propimpl_iterator
|
||||
i = D->propimpl_begin(getContext()),
|
||||
e = D->propimpl_end(getContext()); i != e; ++i) {
|
||||
i = D->propimpl_begin(), e = D->propimpl_end(); i != e; ++i) {
|
||||
ObjCPropertyImplDecl *PID = *i;
|
||||
|
||||
// Dynamic is just for type-checking.
|
||||
@ -1437,11 +1444,11 @@ void CodeGenModule::EmitObjCPropertyImplementations(const
|
||||
// we want, that just indicates if the decl came from a
|
||||
// property. What we want to know is if the method is defined in
|
||||
// this implementation.
|
||||
if (!D->getInstanceMethod(getContext(), PD->getGetterName()))
|
||||
if (!D->getInstanceMethod(PD->getGetterName()))
|
||||
CodeGenFunction(*this).GenerateObjCGetter(
|
||||
const_cast<ObjCImplementationDecl *>(D), PID);
|
||||
if (!PD->isReadOnly() &&
|
||||
!D->getInstanceMethod(getContext(), PD->getSetterName()))
|
||||
!D->getInstanceMethod(PD->getSetterName()))
|
||||
CodeGenFunction(*this).GenerateObjCSetter(
|
||||
const_cast<ObjCImplementationDecl *>(D), PID);
|
||||
}
|
||||
@ -1450,8 +1457,7 @@ void CodeGenModule::EmitObjCPropertyImplementations(const
|
||||
|
||||
/// EmitNamespace - Emit all declarations in a namespace.
|
||||
void CodeGenModule::EmitNamespace(const NamespaceDecl *ND) {
|
||||
for (RecordDecl::decl_iterator I = ND->decls_begin(getContext()),
|
||||
E = ND->decls_end(getContext());
|
||||
for (RecordDecl::decl_iterator I = ND->decls_begin(), E = ND->decls_end();
|
||||
I != E; ++I)
|
||||
EmitTopLevelDecl(*I);
|
||||
}
|
||||
@ -1463,8 +1469,7 @@ void CodeGenModule::EmitLinkageSpec(const LinkageSpecDecl *LSD) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (RecordDecl::decl_iterator I = LSD->decls_begin(getContext()),
|
||||
E = LSD->decls_end(getContext());
|
||||
for (RecordDecl::decl_iterator I = LSD->decls_begin(), E = LSD->decls_end();
|
||||
I != E; ++I)
|
||||
EmitTopLevelDecl(*I);
|
||||
}
|
||||
@ -1477,9 +1482,19 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
|
||||
if (Diags.hasErrorOccurred())
|
||||
return;
|
||||
|
||||
// Ignore dependent declarations.
|
||||
if (D->getDeclContext() && D->getDeclContext()->isDependentContext())
|
||||
return;
|
||||
|
||||
switch (D->getKind()) {
|
||||
case Decl::CXXMethod:
|
||||
case Decl::Function:
|
||||
// Skip function templates
|
||||
if (cast<FunctionDecl>(D)->getDescribedFunctionTemplate())
|
||||
return;
|
||||
|
||||
// Fall through
|
||||
|
||||
case Decl::Var:
|
||||
EmitGlobal(GlobalDecl(cast<ValueDecl>(D)));
|
||||
break;
|
||||
@ -1490,6 +1505,8 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
|
||||
break;
|
||||
// No code generation needed.
|
||||
case Decl::Using:
|
||||
case Decl::ClassTemplate:
|
||||
case Decl::FunctionTemplate:
|
||||
break;
|
||||
case Decl::CXXConstructor:
|
||||
EmitCXXConstructors(cast<CXXConstructorDecl>(D));
|
||||
@ -1530,7 +1547,7 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
|
||||
case Decl::ObjCMethod: {
|
||||
ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(D);
|
||||
// If this is not a prototype, emit the body.
|
||||
if (OMD->getBody(getContext()))
|
||||
if (OMD->getBody())
|
||||
CodeGenFunction(*this).GenerateObjCMethod(OMD);
|
||||
break;
|
||||
}
|
||||
|
@ -373,7 +373,8 @@ class CodeGenModule : public BlockModule {
|
||||
GVA_Internal,
|
||||
GVA_C99Inline,
|
||||
GVA_CXXInline,
|
||||
GVA_StrongExternal
|
||||
GVA_StrongExternal,
|
||||
GVA_TemplateInstantiation
|
||||
};
|
||||
|
||||
private:
|
||||
|
@ -449,7 +449,7 @@ const llvm::Type *CodeGenTypes::ConvertTagDeclType(const TagDecl *TD) {
|
||||
const RecordDecl *RD = cast<const RecordDecl>(TD);
|
||||
|
||||
// There isn't any extra information for empty structures/unions.
|
||||
if (RD->field_empty(getContext())) {
|
||||
if (RD->field_empty()) {
|
||||
ResultType = llvm::StructType::get(std::vector<const llvm::Type*>());
|
||||
} else {
|
||||
// Layout fields.
|
||||
@ -532,8 +532,8 @@ void RecordOrganizer::layoutStructFields(const ASTRecordLayout &RL) {
|
||||
std::vector<const llvm::Type*> LLVMFields;
|
||||
|
||||
unsigned curField = 0;
|
||||
for (RecordDecl::field_iterator Field = RD.field_begin(CGT.getContext()),
|
||||
FieldEnd = RD.field_end(CGT.getContext());
|
||||
for (RecordDecl::field_iterator Field = RD.field_begin(),
|
||||
FieldEnd = RD.field_end();
|
||||
Field != FieldEnd; ++Field) {
|
||||
uint64_t offset = RL.getFieldOffset(curField);
|
||||
const llvm::Type *Ty = CGT.ConvertTypeForMemRecursive(Field->getType());
|
||||
@ -578,8 +578,8 @@ void RecordOrganizer::layoutStructFields(const ASTRecordLayout &RL) {
|
||||
/// all fields are added.
|
||||
void RecordOrganizer::layoutUnionFields(const ASTRecordLayout &RL) {
|
||||
unsigned curField = 0;
|
||||
for (RecordDecl::field_iterator Field = RD.field_begin(CGT.getContext()),
|
||||
FieldEnd = RD.field_end(CGT.getContext());
|
||||
for (RecordDecl::field_iterator Field = RD.field_begin(),
|
||||
FieldEnd = RD.field_end();
|
||||
Field != FieldEnd; ++Field) {
|
||||
// The offset should usually be zero, but bitfields could be strange
|
||||
uint64_t offset = RL.getFieldOffset(curField);
|
||||
|
@ -87,7 +87,7 @@ static bool isInCLinkageSpecification(const Decl *D) {
|
||||
bool CXXNameMangler::mangleFunctionDecl(const FunctionDecl *FD) {
|
||||
// Clang's "overloadable" attribute extension to C/C++ implies
|
||||
// name mangling (always).
|
||||
if (!FD->hasAttr<OverloadableAttr>(Context)) {
|
||||
if (!FD->hasAttr<OverloadableAttr>()) {
|
||||
// C functions are not mangled, and "main" is never mangled.
|
||||
if (!Context.getLangOptions().CPlusPlus || FD->isMain())
|
||||
return false;
|
||||
@ -111,7 +111,7 @@ bool CXXNameMangler::mangleFunctionDecl(const FunctionDecl *FD) {
|
||||
bool CXXNameMangler::mangle(const NamedDecl *D) {
|
||||
// Any decl can be declared with __asm("foo") on it, and this takes
|
||||
// precedence over all other naming in the .o file.
|
||||
if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>(Context)) {
|
||||
if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) {
|
||||
// If we have an asm name, then we use it as the mangling.
|
||||
Out << '\01'; // LLVM IR Marker for __asm("foo")
|
||||
Out << ALA->getLabel();
|
||||
@ -170,7 +170,29 @@ void CXXNameMangler::mangleGuardVariable(const VarDecl *D)
|
||||
void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) {
|
||||
// <encoding> ::= <function name> <bare-function-type>
|
||||
mangleName(FD);
|
||||
mangleBareFunctionType(FD->getType()->getAsFunctionType(), false);
|
||||
|
||||
// Whether the mangling of a function type includes the return type depends
|
||||
// on the context and the nature of the function. The rules for deciding
|
||||
// whether the return type is included are:
|
||||
//
|
||||
// 1. Template functions (names or types) have return types encoded, with
|
||||
// the exceptions listed below.
|
||||
// 2. Function types not appearing as part of a function name mangling,
|
||||
// e.g. parameters, pointer types, etc., have return type encoded, with the
|
||||
// exceptions listed below.
|
||||
// 3. Non-template function names do not have return types encoded.
|
||||
//
|
||||
// The exceptions mentioned in (1) and (2) above, for which the return
|
||||
// type is never included, are
|
||||
// 1. Constructors.
|
||||
// 2. Destructors.
|
||||
// 3. Conversion operator functions, e.g. operator int.
|
||||
bool MangleReturnType = false;
|
||||
if (FD->getPrimaryTemplate() &&
|
||||
!(isa<CXXConstructorDecl>(FD) || isa<CXXDestructorDecl>(FD) ||
|
||||
isa<CXXConversionDecl>(FD)))
|
||||
MangleReturnType = true;
|
||||
mangleBareFunctionType(FD->getType()->getAsFunctionType(), MangleReturnType);
|
||||
}
|
||||
|
||||
static bool isStdNamespace(const DeclContext *DC) {
|
||||
@ -253,6 +275,12 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND) {
|
||||
assert(false && "Can't mangle a using directive name!");
|
||||
break;
|
||||
}
|
||||
|
||||
if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
|
||||
if (const TemplateArgumentList *TemplateArgs
|
||||
= Function->getTemplateSpecializationArgs())
|
||||
mangleTemplateArgumentList(*TemplateArgs);
|
||||
}
|
||||
}
|
||||
|
||||
void CXXNameMangler::mangleSourceName(const IdentifierInfo *II) {
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "clang/Basic/Diagnostic.h"
|
||||
#include "clang/Basic/TargetInfo.h"
|
||||
#include "llvm/LLVMContext.h"
|
||||
#include "llvm/Module.h"
|
||||
#include "llvm/Target/TargetData.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
@ -37,8 +38,8 @@ namespace {
|
||||
llvm::OwningPtr<CodeGen::CodeGenModule> Builder;
|
||||
public:
|
||||
CodeGeneratorImpl(Diagnostic &diags, const std::string& ModuleName,
|
||||
const CompileOptions &CO)
|
||||
: Diags(diags), CompileOpts(CO), M(new llvm::Module(ModuleName)) {}
|
||||
const CompileOptions &CO, llvm::LLVMContext& C)
|
||||
: Diags(diags), CompileOpts(CO), M(new llvm::Module(ModuleName, C)) {}
|
||||
|
||||
virtual ~CodeGeneratorImpl() {}
|
||||
|
||||
@ -95,6 +96,7 @@ namespace {
|
||||
|
||||
CodeGenerator *clang::CreateLLVMCodeGen(Diagnostic &Diags,
|
||||
const std::string& ModuleName,
|
||||
const CompileOptions &CO) {
|
||||
return new CodeGeneratorImpl(Diags, ModuleName, CO);
|
||||
const CompileOptions &CO,
|
||||
llvm::LLVMContext& C) {
|
||||
return new CodeGeneratorImpl(Diags, ModuleName, CO, C);
|
||||
}
|
||||
|
@ -74,8 +74,8 @@ static bool isEmptyRecord(ASTContext &Context, QualType T) {
|
||||
const RecordDecl *RD = RT->getDecl();
|
||||
if (RD->hasFlexibleArrayMember())
|
||||
return false;
|
||||
for (RecordDecl::field_iterator i = RD->field_begin(Context),
|
||||
e = RD->field_end(Context); i != e; ++i)
|
||||
for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
|
||||
i != e; ++i)
|
||||
if (!isEmptyField(Context, *i))
|
||||
return false;
|
||||
return true;
|
||||
@ -99,8 +99,8 @@ static const Type *isSingleElementStruct(QualType T, ASTContext &Context) {
|
||||
return 0;
|
||||
|
||||
const Type *Found = 0;
|
||||
for (RecordDecl::field_iterator i = RD->field_begin(Context),
|
||||
e = RD->field_end(Context); i != e; ++i) {
|
||||
for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
|
||||
i != e; ++i) {
|
||||
const FieldDecl *FD = *i;
|
||||
QualType FT = FD->getType();
|
||||
|
||||
@ -142,8 +142,8 @@ static bool is32Or64BitBasicType(QualType Ty, ASTContext &Context) {
|
||||
|
||||
static bool areAllFields32Or64BitBasicType(const RecordDecl *RD,
|
||||
ASTContext &Context) {
|
||||
for (RecordDecl::field_iterator i = RD->field_begin(Context),
|
||||
e = RD->field_end(Context); i != e; ++i) {
|
||||
for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
|
||||
i != e; ++i) {
|
||||
const FieldDecl *FD = *i;
|
||||
|
||||
if (!is32Or64BitBasicType(FD->getType(), Context))
|
||||
@ -160,8 +160,8 @@ static bool areAllFields32Or64BitBasicType(const RecordDecl *RD,
|
||||
}
|
||||
|
||||
static bool typeContainsSSEVector(const RecordDecl *RD, ASTContext &Context) {
|
||||
for (RecordDecl::field_iterator i = RD->field_begin(Context),
|
||||
e = RD->field_end(Context); i != e; ++i) {
|
||||
for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
|
||||
i != e; ++i) {
|
||||
const FieldDecl *FD = *i;
|
||||
|
||||
if (FD->getType()->isVectorType() &&
|
||||
@ -269,8 +269,8 @@ bool X86_32ABIInfo::shouldReturnTypeInRegister(QualType Ty,
|
||||
|
||||
// Structure types are passed in register if all fields would be
|
||||
// passed in a register.
|
||||
for (RecordDecl::field_iterator i = RT->getDecl()->field_begin(Context),
|
||||
e = RT->getDecl()->field_end(Context); i != e; ++i) {
|
||||
for (RecordDecl::field_iterator i = RT->getDecl()->field_begin(),
|
||||
e = RT->getDecl()->field_end(); i != e; ++i) {
|
||||
const FieldDecl *FD = *i;
|
||||
|
||||
// Empty fields are ignored.
|
||||
@ -707,8 +707,8 @@ void X86_64ABIInfo::classify(QualType Ty,
|
||||
// Reset Lo class, this will be recomputed.
|
||||
Current = NoClass;
|
||||
unsigned idx = 0;
|
||||
for (RecordDecl::field_iterator i = RD->field_begin(Context),
|
||||
e = RD->field_end(Context); i != e; ++i, ++idx) {
|
||||
for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
|
||||
i != e; ++i, ++idx) {
|
||||
uint64_t Offset = OffsetBase + Layout.getFieldOffset(idx);
|
||||
bool BitField = i->isBitField();
|
||||
|
||||
|
@ -49,6 +49,35 @@ Arg *ArgList::getLastArg(options::ID Id0, options::ID Id1, bool Claim) const {
|
||||
return Res;
|
||||
}
|
||||
|
||||
Arg *ArgList::getLastArg(options::ID Id0, options::ID Id1, options::ID Id2,
|
||||
bool Claim) const {
|
||||
Arg *Res = 0;
|
||||
Arg *A0 = getLastArg(Id0, false);
|
||||
Arg *A1 = getLastArg(Id1, false);
|
||||
Arg *A2 = getLastArg(Id2, false);
|
||||
|
||||
int A0Idx = A0 ? A0->getIndex() : -1;
|
||||
int A1Idx = A1 ? A1->getIndex() : -1;
|
||||
int A2Idx = A2 ? A2->getIndex() : -1;
|
||||
|
||||
if (A0Idx > A1Idx) {
|
||||
if (A0Idx > A2Idx)
|
||||
Res = A0;
|
||||
else if (A2Idx != -1)
|
||||
Res = A2;
|
||||
} else {
|
||||
if (A1Idx > A2Idx)
|
||||
Res = A1;
|
||||
else if (A2Idx != -1)
|
||||
Res = A2;
|
||||
}
|
||||
|
||||
if (Claim && Res)
|
||||
Res->claim();
|
||||
|
||||
return Res;
|
||||
}
|
||||
|
||||
bool ArgList::hasFlag(options::ID Pos, options::ID Neg, bool Default) const {
|
||||
if (Arg *A = getLastArg(Pos, Neg))
|
||||
return A->getOption().matches(Pos);
|
||||
|
@ -21,8 +21,8 @@
|
||||
#include <errno.h>
|
||||
using namespace clang::driver;
|
||||
|
||||
Compilation::Compilation(Driver &D,
|
||||
ToolChain &_DefaultToolChain,
|
||||
Compilation::Compilation(const Driver &D,
|
||||
const ToolChain &_DefaultToolChain,
|
||||
InputArgList *_Args)
|
||||
: TheDriver(D), DefaultToolChain(_DefaultToolChain), Args(_Args) {
|
||||
}
|
||||
@ -105,7 +105,8 @@ bool Compilation::CleanupFileList(const ArgStringList &Files,
|
||||
return Success;
|
||||
}
|
||||
|
||||
int Compilation::ExecuteCommand(const Command &C) const {
|
||||
int Compilation::ExecuteCommand(const Command &C,
|
||||
const Command *&FailingCommand) const {
|
||||
llvm::sys::Path Prog(C.getExecutable());
|
||||
const char **Argv = new const char*[C.getArguments().size() + 2];
|
||||
Argv[0] = C.getExecutable();
|
||||
@ -126,49 +127,31 @@ int Compilation::ExecuteCommand(const Command &C) const {
|
||||
getDriver().Diag(clang::diag::err_drv_command_failure) << Error;
|
||||
}
|
||||
|
||||
if (Res)
|
||||
FailingCommand = &C;
|
||||
|
||||
delete[] Argv;
|
||||
return Res;
|
||||
}
|
||||
|
||||
int Compilation::ExecuteJob(const Job &J) const {
|
||||
int Compilation::ExecuteJob(const Job &J,
|
||||
const Command *&FailingCommand) const {
|
||||
if (const Command *C = dyn_cast<Command>(&J)) {
|
||||
return ExecuteCommand(*C);
|
||||
return ExecuteCommand(*C, FailingCommand);
|
||||
} else if (const PipedJob *PJ = dyn_cast<PipedJob>(&J)) {
|
||||
// Piped commands with a single job are easy.
|
||||
if (PJ->size() == 1)
|
||||
return ExecuteCommand(**PJ->begin());
|
||||
return ExecuteCommand(**PJ->begin(), FailingCommand);
|
||||
|
||||
FailingCommand = *PJ->begin();
|
||||
getDriver().Diag(clang::diag::err_drv_unsupported_opt) << "-pipe";
|
||||
return 1;
|
||||
} else {
|
||||
const JobList *Jobs = cast<JobList>(&J);
|
||||
for (JobList::const_iterator
|
||||
it = Jobs->begin(), ie = Jobs->end(); it != ie; ++it)
|
||||
if (int Res = ExecuteJob(**it))
|
||||
if (int Res = ExecuteJob(**it, FailingCommand))
|
||||
return Res;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int Compilation::Execute() const {
|
||||
// Just print if -### was present.
|
||||
if (getArgs().hasArg(options::OPT__HASH_HASH_HASH)) {
|
||||
PrintJob(llvm::errs(), Jobs, "\n", true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// If there were errors building the compilation, quit now.
|
||||
if (getDriver().getDiags().getNumErrors())
|
||||
return 1;
|
||||
|
||||
int Res = ExecuteJob(Jobs);
|
||||
|
||||
// Remove temp files.
|
||||
CleanupFileList(TempFiles);
|
||||
|
||||
// If the compilation failed, remove result files as well.
|
||||
if (Res != 0 && !getArgs().hasArg(options::OPT_save_temps))
|
||||
CleanupFileList(ResultFiles, true);
|
||||
|
||||
return Res;
|
||||
}
|
||||
|
@ -217,6 +217,54 @@ Compilation *Driver::BuildCompilation(int argc, const char **argv) {
|
||||
return C;
|
||||
}
|
||||
|
||||
int Driver::ExecuteCompilation(const Compilation &C) const {
|
||||
// Just print if -### was present.
|
||||
if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)) {
|
||||
C.PrintJob(llvm::errs(), C.getJobs(), "\n", true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// If there were errors building the compilation, quit now.
|
||||
if (getDiags().getNumErrors())
|
||||
return 1;
|
||||
|
||||
const Command *FailingCommand = 0;
|
||||
int Res = C.ExecuteJob(C.getJobs(), FailingCommand);
|
||||
|
||||
// Remove temp files.
|
||||
C.CleanupFileList(C.getTempFiles());
|
||||
|
||||
// If the compilation failed, remove result files as well.
|
||||
if (Res != 0 && !C.getArgs().hasArg(options::OPT_save_temps))
|
||||
C.CleanupFileList(C.getResultFiles(), true);
|
||||
|
||||
// Print extra information about abnormal failures, if possible.
|
||||
if (Res) {
|
||||
// This is ad-hoc, but we don't want to be excessively noisy. If the result
|
||||
// status was 1, assume the command failed normally. In particular, if it
|
||||
// was the compiler then assume it gave a reasonable error code. Failures in
|
||||
// other tools are less common, and they generally have worse diagnostics,
|
||||
// so always print the diagnostic there.
|
||||
const Action &Source = FailingCommand->getSource();
|
||||
bool IsFriendlyTool = (isa<PreprocessJobAction>(Source) ||
|
||||
isa<PrecompileJobAction>(Source) ||
|
||||
isa<AnalyzeJobAction>(Source) ||
|
||||
isa<CompileJobAction>(Source));
|
||||
|
||||
if (!IsFriendlyTool || Res != 1) {
|
||||
// FIXME: See FIXME above regarding result code interpretation.
|
||||
if (Res < 0)
|
||||
Diag(clang::diag::err_drv_command_signalled)
|
||||
<< Source.getClassName() << -Res;
|
||||
else
|
||||
Diag(clang::diag::err_drv_command_failed)
|
||||
<< Source.getClassName() << Res;
|
||||
}
|
||||
}
|
||||
|
||||
return Res;
|
||||
}
|
||||
|
||||
void Driver::PrintOptions(const ArgList &Args) const {
|
||||
unsigned i = 0;
|
||||
for (ArgList::const_iterator it = Args.begin(), ie = Args.end();
|
||||
@ -1205,6 +1253,8 @@ const HostInfo *Driver::GetHostInfo(const char *TripleStr) const {
|
||||
return createDarwinHostInfo(*this, Triple);
|
||||
case llvm::Triple::DragonFly:
|
||||
return createDragonFlyHostInfo(*this, Triple);
|
||||
case llvm::Triple::OpenBSD:
|
||||
return createOpenBSDHostInfo(*this, Triple);
|
||||
case llvm::Triple::FreeBSD:
|
||||
return createFreeBSDHostInfo(*this, Triple);
|
||||
case llvm::Triple::Linux:
|
||||
|
@ -234,6 +234,57 @@ ToolChain *UnknownHostInfo::getToolChain(const ArgList &Args,
|
||||
return TC;
|
||||
}
|
||||
|
||||
// OpenBSD Host Info
|
||||
|
||||
/// OpenBSDHostInfo - OpenBSD host information implementation.
|
||||
class OpenBSDHostInfo : public HostInfo {
|
||||
/// Cache of tool chains we have created.
|
||||
mutable llvm::StringMap<ToolChain*> ToolChains;
|
||||
|
||||
public:
|
||||
OpenBSDHostInfo(const Driver &D, const llvm::Triple& Triple)
|
||||
: HostInfo(D, Triple) {}
|
||||
~OpenBSDHostInfo();
|
||||
|
||||
virtual bool useDriverDriver() const;
|
||||
|
||||
virtual types::ID lookupTypeForExtension(const char *Ext) const {
|
||||
return types::lookupTypeForExtension(Ext);
|
||||
}
|
||||
|
||||
virtual ToolChain *getToolChain(const ArgList &Args,
|
||||
const char *ArchName) const;
|
||||
};
|
||||
|
||||
OpenBSDHostInfo::~OpenBSDHostInfo() {
|
||||
for (llvm::StringMap<ToolChain*>::iterator
|
||||
it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it)
|
||||
delete it->second;
|
||||
}
|
||||
|
||||
bool OpenBSDHostInfo::useDriverDriver() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
ToolChain *OpenBSDHostInfo::getToolChain(const ArgList &Args,
|
||||
const char *ArchName) const {
|
||||
assert(!ArchName &&
|
||||
"Unexpected arch name on platform without driver driver support.");
|
||||
|
||||
std::string Arch = getArchName();
|
||||
ArchName = Arch.c_str();
|
||||
|
||||
ToolChain *&TC = ToolChains[ArchName];
|
||||
if (!TC) {
|
||||
llvm::Triple TCTriple(getTriple());
|
||||
TCTriple.setArchName(ArchName);
|
||||
|
||||
TC = new toolchains::OpenBSD(*this, TCTriple);
|
||||
}
|
||||
|
||||
return TC;
|
||||
}
|
||||
|
||||
// FreeBSD Host Info
|
||||
|
||||
/// FreeBSDHostInfo - FreeBSD host information implementation.
|
||||
@ -416,6 +467,12 @@ clang::driver::createDarwinHostInfo(const Driver &D,
|
||||
return new DarwinHostInfo(D, Triple);
|
||||
}
|
||||
|
||||
const HostInfo *
|
||||
clang::driver::createOpenBSDHostInfo(const Driver &D,
|
||||
const llvm::Triple& Triple) {
|
||||
return new OpenBSDHostInfo(D, Triple);
|
||||
}
|
||||
|
||||
const HostInfo *
|
||||
clang::driver::createFreeBSDHostInfo(const Driver &D,
|
||||
const llvm::Triple& Triple) {
|
||||
|
@ -14,8 +14,10 @@ using namespace clang::driver;
|
||||
|
||||
Job::~Job() {}
|
||||
|
||||
Command::Command(const char *_Executable, const ArgStringList &_Arguments)
|
||||
: Job(CommandClass), Executable(_Executable), Arguments(_Arguments) {
|
||||
Command::Command(const Action &_Source, const char *_Executable,
|
||||
const ArgStringList &_Arguments)
|
||||
: Job(CommandClass), Source(_Source), Executable(_Executable),
|
||||
Arguments(_Arguments) {
|
||||
}
|
||||
|
||||
PipedJob::PipedJob() : Job(PipedJobClass) {}
|
||||
|
@ -384,6 +384,36 @@ DerivedArgList *Generic_GCC::TranslateArgs(InputArgList &Args) const {
|
||||
return new DerivedArgList(Args, true);
|
||||
}
|
||||
|
||||
/// OpenBSD - OpenBSD tool chain which can call as(1) and ld(1) directly.
|
||||
|
||||
OpenBSD::OpenBSD(const HostInfo &Host, const llvm::Triple& Triple)
|
||||
: Generic_GCC(Host, Triple) {
|
||||
getFilePaths().push_back(getHost().getDriver().Dir + "/../lib");
|
||||
getFilePaths().push_back("/usr/lib");
|
||||
}
|
||||
|
||||
Tool &OpenBSD::SelectTool(const Compilation &C, const JobAction &JA) const {
|
||||
Action::ActionClass Key;
|
||||
if (getHost().getDriver().ShouldUseClangCompiler(C, JA, getArchName()))
|
||||
Key = Action::AnalyzeJobClass;
|
||||
else
|
||||
Key = JA.getKind();
|
||||
|
||||
Tool *&T = Tools[Key];
|
||||
if (!T) {
|
||||
switch (Key) {
|
||||
case Action::AssembleJobClass:
|
||||
T = new tools::openbsd::Assemble(*this); break;
|
||||
case Action::LinkJobClass:
|
||||
T = new tools::openbsd::Link(*this); break;
|
||||
default:
|
||||
T = &Generic_GCC::SelectTool(C, JA);
|
||||
}
|
||||
}
|
||||
|
||||
return *T;
|
||||
}
|
||||
|
||||
/// FreeBSD - FreeBSD tool chain which can call as(1) and ld(1) directly.
|
||||
|
||||
FreeBSD::FreeBSD(const HostInfo &Host, const llvm::Triple& Triple, bool Lib32)
|
||||
|
@ -107,6 +107,13 @@ class VISIBILITY_HIDDEN Darwin_GCC : public Generic_GCC {
|
||||
virtual const char *GetDefaultRelocationModel() const { return "pic"; }
|
||||
};
|
||||
|
||||
class VISIBILITY_HIDDEN OpenBSD : public Generic_GCC {
|
||||
public:
|
||||
OpenBSD(const HostInfo &Host, const llvm::Triple& Triple);
|
||||
|
||||
virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const;
|
||||
};
|
||||
|
||||
class VISIBILITY_HIDDEN FreeBSD : public Generic_GCC {
|
||||
public:
|
||||
FreeBSD(const HostInfo &Host, const llvm::Triple& Triple, bool Lib32);
|
||||
|
@ -498,6 +498,18 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
Args.AddLastArg(CmdArgs, options::OPT_fvisibility_EQ);
|
||||
Args.AddLastArg(CmdArgs, options::OPT_fwritable_strings);
|
||||
|
||||
// Forward stack protector flags.
|
||||
if (Arg *A = Args.getLastArg(options::OPT_fno_stack_protector,
|
||||
options::OPT_fstack_protector_all,
|
||||
options::OPT_fstack_protector)) {
|
||||
if (A->getOption().matches(options::OPT_fno_stack_protector))
|
||||
CmdArgs.push_back("--stack-protector=0");
|
||||
else if (A->getOption().matches(options::OPT_fstack_protector))
|
||||
CmdArgs.push_back("--stack-protector=1");
|
||||
else
|
||||
CmdArgs.push_back("--stack-protector=2");
|
||||
}
|
||||
|
||||
// Forward -f options with positive and negative forms; we translate
|
||||
// these by hand.
|
||||
|
||||
@ -616,7 +628,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
|
||||
const char *Exec =
|
||||
Args.MakeArgString(getToolChain().GetProgramPath(C, "clang-cc").c_str());
|
||||
Dest.addCommand(new Command(Exec, CmdArgs));
|
||||
Dest.addCommand(new Command(JA, Exec, CmdArgs));
|
||||
|
||||
// Explicitly warn that these options are unsupported, even though
|
||||
// we are allowing compilation to continue.
|
||||
@ -747,7 +759,7 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
getToolChain().getHost().getDriver().CCCGenericGCCName.c_str();
|
||||
const char *Exec =
|
||||
Args.MakeArgString(getToolChain().GetProgramPath(C, GCCName).c_str());
|
||||
Dest.addCommand(new Command(Exec, CmdArgs));
|
||||
Dest.addCommand(new Command(JA, Exec, CmdArgs));
|
||||
}
|
||||
|
||||
void gcc::Preprocess::RenderExtraToolArgs(ArgStringList &CmdArgs) const {
|
||||
@ -1123,7 +1135,7 @@ void darwin::Preprocess::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
const char *CC1Name = getCC1Name(Inputs[0].getType());
|
||||
const char *Exec =
|
||||
Args.MakeArgString(getToolChain().GetProgramPath(C, CC1Name).c_str());
|
||||
Dest.addCommand(new Command(Exec, CmdArgs));
|
||||
Dest.addCommand(new Command(JA, Exec, CmdArgs));
|
||||
}
|
||||
|
||||
void darwin::Compile::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
@ -1211,7 +1223,7 @@ void darwin::Compile::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
const char *CC1Name = getCC1Name(Inputs[0].getType());
|
||||
const char *Exec =
|
||||
Args.MakeArgString(getToolChain().GetProgramPath(C, CC1Name).c_str());
|
||||
Dest.addCommand(new Command(Exec, CmdArgs));
|
||||
Dest.addCommand(new Command(JA, Exec, CmdArgs));
|
||||
}
|
||||
|
||||
void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
@ -1264,7 +1276,7 @@ void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
|
||||
const char *Exec =
|
||||
Args.MakeArgString(getToolChain().GetProgramPath(C, "as").c_str());
|
||||
Dest.addCommand(new Command(Exec, CmdArgs));
|
||||
Dest.addCommand(new Command(JA, Exec, CmdArgs));
|
||||
}
|
||||
|
||||
/// Helper routine for seeing if we should use dsymutil; this is a
|
||||
@ -1688,7 +1700,7 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
|
||||
const char *Exec =
|
||||
Args.MakeArgString(getToolChain().GetProgramPath(C, "ld").c_str());
|
||||
Dest.addCommand(new Command(Exec, CmdArgs));
|
||||
Dest.addCommand(new Command(JA, Exec, CmdArgs));
|
||||
|
||||
// Find the first non-empty base input (we want to ignore linker
|
||||
// inputs).
|
||||
@ -1718,7 +1730,7 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
Args.MakeArgString(getToolChain().GetProgramPath(C, "dsymutil").c_str());
|
||||
ArgStringList CmdArgs;
|
||||
CmdArgs.push_back(Output.getFilename());
|
||||
C.getJobs().addCommand(new Command(Exec, CmdArgs));
|
||||
C.getJobs().addCommand(new Command(JA, Exec, CmdArgs));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1744,9 +1756,121 @@ void darwin::Lipo::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
}
|
||||
const char *Exec =
|
||||
Args.MakeArgString(getToolChain().GetProgramPath(C, "lipo").c_str());
|
||||
Dest.addCommand(new Command(Exec, CmdArgs));
|
||||
Dest.addCommand(new Command(JA, Exec, CmdArgs));
|
||||
}
|
||||
|
||||
void openbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
Job &Dest, const InputInfo &Output,
|
||||
const InputInfoList &Inputs,
|
||||
const ArgList &Args,
|
||||
const char *LinkingOutput) const
|
||||
{
|
||||
ArgStringList CmdArgs;
|
||||
|
||||
Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
|
||||
options::OPT_Xassembler);
|
||||
|
||||
CmdArgs.push_back("-o");
|
||||
if (Output.isPipe())
|
||||
CmdArgs.push_back("-");
|
||||
else
|
||||
CmdArgs.push_back(Output.getFilename());
|
||||
|
||||
for (InputInfoList::const_iterator
|
||||
it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
|
||||
const InputInfo &II = *it;
|
||||
if (II.isPipe())
|
||||
CmdArgs.push_back("-");
|
||||
else
|
||||
CmdArgs.push_back(II.getFilename());
|
||||
}
|
||||
|
||||
const char *Exec =
|
||||
Args.MakeArgString(getToolChain().GetProgramPath(C, "as").c_str());
|
||||
Dest.addCommand(new Command(JA, Exec, CmdArgs));
|
||||
}
|
||||
|
||||
void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
Job &Dest, const InputInfo &Output,
|
||||
const InputInfoList &Inputs,
|
||||
const ArgList &Args,
|
||||
const char *LinkingOutput) const {
|
||||
const Driver &D = getToolChain().getHost().getDriver();
|
||||
ArgStringList CmdArgs;
|
||||
|
||||
if (Args.hasArg(options::OPT_static)) {
|
||||
CmdArgs.push_back("-Bstatic");
|
||||
} else {
|
||||
CmdArgs.push_back("--eh-frame-hdr");
|
||||
if (Args.hasArg(options::OPT_shared)) {
|
||||
CmdArgs.push_back("-Bshareable");
|
||||
} else {
|
||||
CmdArgs.push_back("-dynamic-linker");
|
||||
CmdArgs.push_back("/usr/libexec/ld.so");
|
||||
}
|
||||
}
|
||||
|
||||
if (Output.isPipe()) {
|
||||
CmdArgs.push_back("-o");
|
||||
CmdArgs.push_back("-");
|
||||
} else if (Output.isFilename()) {
|
||||
CmdArgs.push_back("-o");
|
||||
CmdArgs.push_back(Output.getFilename());
|
||||
} else {
|
||||
assert(Output.isNothing() && "Invalid output.");
|
||||
}
|
||||
|
||||
if (!Args.hasArg(options::OPT_nostdlib) &&
|
||||
!Args.hasArg(options::OPT_nostartfiles)) {
|
||||
if (!Args.hasArg(options::OPT_shared)) {
|
||||
CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crt0.o").c_str()));
|
||||
CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbegin.o").c_str()));
|
||||
} else {
|
||||
CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbeginS.o").c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
Args.AddAllArgs(CmdArgs, options::OPT_L);
|
||||
Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
|
||||
Args.AddAllArgs(CmdArgs, options::OPT_e);
|
||||
|
||||
for (InputInfoList::const_iterator
|
||||
it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
|
||||
const InputInfo &II = *it;
|
||||
|
||||
// Don't try to pass LLVM inputs to a generic gcc.
|
||||
if (II.getType() == types::TY_LLVMBC)
|
||||
D.Diag(clang::diag::err_drv_no_linker_llvm_support)
|
||||
<< getToolChain().getTripleString().c_str();
|
||||
|
||||
if (II.isPipe())
|
||||
CmdArgs.push_back("-");
|
||||
else if (II.isFilename())
|
||||
CmdArgs.push_back(II.getFilename());
|
||||
else
|
||||
II.getInputArg().renderAsInput(Args, CmdArgs);
|
||||
}
|
||||
|
||||
if (!Args.hasArg(options::OPT_nostdlib) &&
|
||||
!Args.hasArg(options::OPT_nodefaultlibs)) {
|
||||
|
||||
if (Args.hasArg(options::OPT_pthread))
|
||||
CmdArgs.push_back("-pthread");
|
||||
CmdArgs.push_back("-lc");
|
||||
}
|
||||
|
||||
if (!Args.hasArg(options::OPT_nostdlib) &&
|
||||
!Args.hasArg(options::OPT_nostartfiles)) {
|
||||
if (!Args.hasArg(options::OPT_shared))
|
||||
CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtend.o").c_str()));
|
||||
else
|
||||
CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtendS.o").c_str()));
|
||||
}
|
||||
|
||||
const char *Exec =
|
||||
Args.MakeArgString(getToolChain().GetProgramPath(C, "ld").c_str());
|
||||
Dest.addCommand(new Command(JA, Exec, CmdArgs));
|
||||
}
|
||||
|
||||
void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
Job &Dest, const InputInfo &Output,
|
||||
@ -1781,7 +1905,7 @@ void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
|
||||
const char *Exec =
|
||||
Args.MakeArgString(getToolChain().GetProgramPath(C, "as").c_str());
|
||||
Dest.addCommand(new Command(Exec, CmdArgs));
|
||||
Dest.addCommand(new Command(JA, Exec, CmdArgs));
|
||||
}
|
||||
|
||||
void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
@ -1892,7 +2016,7 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
|
||||
const char *Exec =
|
||||
Args.MakeArgString(getToolChain().GetProgramPath(C, "ld").c_str());
|
||||
Dest.addCommand(new Command(Exec, CmdArgs));
|
||||
Dest.addCommand(new Command(JA, Exec, CmdArgs));
|
||||
}
|
||||
|
||||
/// DragonFly Tools
|
||||
@ -1931,7 +2055,7 @@ void dragonfly::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
|
||||
const char *Exec =
|
||||
Args.MakeArgString(getToolChain().GetProgramPath(C, "as").c_str());
|
||||
Dest.addCommand(new Command(Exec, CmdArgs));
|
||||
Dest.addCommand(new Command(JA, Exec, CmdArgs));
|
||||
}
|
||||
|
||||
void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
@ -2055,5 +2179,5 @@ void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
|
||||
const char *Exec =
|
||||
Args.MakeArgString(getToolChain().GetProgramPath(C, "ld").c_str());
|
||||
Dest.addCommand(new Command(Exec, CmdArgs));
|
||||
Dest.addCommand(new Command(JA, Exec, CmdArgs));
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user