Update clang to r90226.

This commit is contained in:
Roman Divacky 2009-12-01 11:08:04 +00:00
parent f5bd02d290
commit 1569ce6868
521 changed files with 17125 additions and 9382 deletions

View File

@ -45,7 +45,7 @@ install-local::
for hdr in `find . -type f '!' '(' -name '*~' \
-o -name '.#*' -o -name '*.in' -o -name '*.txt' \
-o -name 'Makefile' -o -name '*.td' ')' -print \
| grep -v CVS | grep -v .svn` ; do \
| grep -v CVS | grep -v .svn | grep -v .dir` ; do \
instdir=`dirname "$(PROJ_includedir)/$$hdr"` ; \
if test \! -d "$$instdir" ; then \
$(EchoCmd) Making install directory $$instdir ; \
@ -58,7 +58,7 @@ ifneq ($(PROJ_SRC_ROOT),$(PROJ_OBJ_ROOT))
$(Verb) if test -d "$(PROJ_OBJ_ROOT)/tools/clang/include" ; then \
cd $(PROJ_OBJ_ROOT)/tools/clang/include && \
for hdr in `find . -type f '!' '(' -name 'Makefile' ')' -print \
| grep -v CVS | grep -v .tmp` ; do \
| grep -v CVS | grep -v .tmp | grep -v .dir` ; do \
$(DataInstall) $$hdr $(PROJ_includedir)/$$hdr ; \
done ; \
fi

View File

@ -31,14 +31,14 @@
1A32C17F0E1C87AD00A6B483 /* ExprConstant.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A32C17E0E1C87AD00A6B483 /* ExprConstant.cpp */; };
1A376A2D0D4AED9B002A1C52 /* CGExprConstant.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A376A2C0D4AED9B002A1C52 /* CGExprConstant.cpp */; };
1A471AB50F437BC500753CE8 /* CGBlocks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A471AB40F437BC500753CE8 /* CGBlocks.cpp */; };
1A4C41BF105B4C0B0047B5E7 /* CGCXXClass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A4C41BE105B4C0B0047B5E7 /* CGCXXClass.cpp */; };
1A4C41BF105B4C0B0047B5E7 /* CGClass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A4C41BE105B4C0B0047B5E7 /* CGClass.cpp */; };
1A535ED9107BC45E000C3AE7 /* CXXInheritance.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A535ED8107BC45E000C3AE7 /* CXXInheritance.cpp */; };
1A5D5E580E5E81010023C059 /* CGCXX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A5D5E570E5E81010023C059 /* CGCXX.cpp */; };
1A6B6CD410693FC900BB4A8F /* CodeCompleteConsumer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A6B6CD110693FC900BB4A8F /* CodeCompleteConsumer.cpp */; };
1A6B6CD510693FC900BB4A8F /* SemaCodeComplete.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A6B6CD210693FC900BB4A8F /* SemaCodeComplete.cpp */; };
1A6B6E9A1069833600BB4A8F /* CGCXXExpr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A6B6E991069833600BB4A8F /* CGCXXExpr.cpp */; };
1A6B6E9A1069833600BB4A8F /* CGExprCXX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A6B6E991069833600BB4A8F /* CGExprCXX.cpp */; };
1A6C01F7108128710072DEE4 /* CGRtti.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A6C01F6108128710072DEE4 /* CGRtti.cpp */; };
1A6FE7090FD6F85800E00CA9 /* CGCXXTemp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A6FE7080FD6F85800E00CA9 /* CGCXXTemp.cpp */; };
1A6FE7090FD6F85800E00CA9 /* CGTemporaries.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A6FE7080FD6F85800E00CA9 /* CGTemporaries.cpp */; };
1A701B640F7C8FE400FEC4D1 /* SemaAccess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A701B630F7C8FE400FEC4D1 /* SemaAccess.cpp */; };
1A7342480C7B57D500122F56 /* CGObjC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A7342470C7B57D500122F56 /* CGObjC.cpp */; };
1A81AA19108144F40094E50B /* CGVtable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A81AA18108144F40094E50B /* CGVtable.cpp */; };
@ -369,7 +369,7 @@
1A32C17E0E1C87AD00A6B483 /* ExprConstant.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = ExprConstant.cpp; path = lib/AST/ExprConstant.cpp; sourceTree = "<group>"; tabWidth = 2; };
1A376A2C0D4AED9B002A1C52 /* CGExprConstant.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGExprConstant.cpp; path = lib/CodeGen/CGExprConstant.cpp; sourceTree = "<group>"; tabWidth = 2; };
1A471AB40F437BC500753CE8 /* CGBlocks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGBlocks.cpp; path = lib/CodeGen/CGBlocks.cpp; sourceTree = "<group>"; tabWidth = 2; };
1A4C41BE105B4C0B0047B5E7 /* CGCXXClass.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGCXXClass.cpp; path = lib/CodeGen/CGCXXClass.cpp; sourceTree = "<group>"; tabWidth = 2; };
1A4C41BE105B4C0B0047B5E7 /* CGClass.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGClass.cpp; path = lib/CodeGen/CGClass.cpp; sourceTree = "<group>"; tabWidth = 2; };
1A535ED8107BC45E000C3AE7 /* CXXInheritance.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CXXInheritance.cpp; path = lib/AST/CXXInheritance.cpp; sourceTree = "<group>"; };
1A535EDB107BC47B000C3AE7 /* CanonicalType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CanonicalType.h; path = clang/AST/CanonicalType.h; sourceTree = "<group>"; };
1A5D5E570E5E81010023C059 /* CGCXX.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGCXX.cpp; path = lib/CodeGen/CGCXX.cpp; sourceTree = "<group>"; tabWidth = 2; };
@ -378,9 +378,9 @@
1A6B6CD110693FC900BB4A8F /* CodeCompleteConsumer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CodeCompleteConsumer.cpp; path = lib/Sema/CodeCompleteConsumer.cpp; sourceTree = "<group>"; tabWidth = 2; };
1A6B6CD210693FC900BB4A8F /* SemaCodeComplete.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = SemaCodeComplete.cpp; path = lib/Sema/SemaCodeComplete.cpp; sourceTree = "<group>"; tabWidth = 2; };
1A6B6CD310693FC900BB4A8F /* SemaTemplate.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = SemaTemplate.h; path = lib/Sema/SemaTemplate.h; sourceTree = "<group>"; tabWidth = 2; };
1A6B6E991069833600BB4A8F /* CGCXXExpr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGCXXExpr.cpp; path = lib/CodeGen/CGCXXExpr.cpp; sourceTree = "<group>"; tabWidth = 2; };
1A6B6E991069833600BB4A8F /* CGExprCXX.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGExprCXX.cpp; path = lib/CodeGen/CGExprCXX.cpp; sourceTree = "<group>"; tabWidth = 2; };
1A6C01F6108128710072DEE4 /* CGRtti.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGRtti.cpp; path = lib/CodeGen/CGRtti.cpp; sourceTree = "<group>"; tabWidth = 2; };
1A6FE7080FD6F85800E00CA9 /* CGCXXTemp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGCXXTemp.cpp; path = lib/CodeGen/CGCXXTemp.cpp; sourceTree = "<group>"; tabWidth = 2; };
1A6FE7080FD6F85800E00CA9 /* CGTemporaries.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGTemporaries.cpp; path = lib/CodeGen/CGTemporaries.cpp; sourceTree = "<group>"; tabWidth = 2; };
1A7019E90F79BC1100FEC4D1 /* DiagnosticAnalysisKinds.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = DiagnosticAnalysisKinds.td; sourceTree = "<group>"; };
1A7019EA0F79BC1100FEC4D1 /* DiagnosticASTKinds.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = DiagnosticASTKinds.td; sourceTree = "<group>"; };
1A7019EB0F79BC1100FEC4D1 /* DiagnosticCommonKinds.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = DiagnosticCommonKinds.td; sourceTree = "<group>"; };
@ -1265,11 +1265,10 @@
1ABC36930C7A4BDC006DB0AB /* CGBuiltin.cpp */,
35475B1F0E79973F0000BFE4 /* CGCall.cpp */,
35475B220E7997680000BFE4 /* CGCall.h */,
1A4C41BE105B4C0B0047B5E7 /* CGClass.cpp */,
1A5D5E570E5E81010023C059 /* CGCXX.cpp */,
1A649E1E0F9599DA005B965E /* CGCXX.h */,
1A4C41BE105B4C0B0047B5E7 /* CGCXXClass.cpp */,
1A6B6E991069833600BB4A8F /* CGCXXExpr.cpp */,
1A6FE7080FD6F85800E00CA9 /* CGCXXTemp.cpp */,
1A6B6E991069833600BB4A8F /* CGExprCXX.cpp */,
35A3E7000DD3874400757F74 /* CGDebugInfo.cpp */,
35A3E7010DD3874400757F74 /* CGDebugInfo.h */,
DE4264FB0C113592005A861D /* CGDecl.cpp */,
@ -1287,6 +1286,7 @@
1AFF8AE21012BFC900D248DA /* CGRecordLayoutBuilder.h */,
1A6C01F6108128710072DEE4 /* CGRtti.cpp */,
DE4772F90C10EAE5002239E8 /* CGStmt.cpp */,
1A6FE7080FD6F85800E00CA9 /* CGTemporaries.cpp */,
35475B230E7997680000BFE4 /* CGValue.h */,
1A81AA18108144F40094E50B /* CGVtable.cpp */,
1A81AA5D108278A20094E50B /* CGVtable.h */,
@ -1899,7 +1899,7 @@
1A2A54C30FD1DD1C00F4CE45 /* RewriteTest.cpp in Sources */,
1A2A54C40FD1DD1C00F4CE45 /* StmtXML.cpp in Sources */,
1A2A54C50FD1DD1C00F4CE45 /* Warnings.cpp in Sources */,
1A6FE7090FD6F85800E00CA9 /* CGCXXTemp.cpp in Sources */,
1A6FE7090FD6F85800E00CA9 /* CGTemporaries.cpp in Sources */,
BDF87CF70FD746F300BBF872 /* SemaTemplateDeduction.cpp in Sources */,
1A14D3A70FD78A3F00DA2835 /* DeclPrinter.cpp in Sources */,
DE37252E0FE481AD00CF2CC2 /* Builtins.cpp in Sources */,
@ -1922,10 +1922,10 @@
9012911D1048068D0083456D /* ASTUnit.cpp in Sources */,
90129121104812F90083456D /* CIndex.cpp in Sources */,
90F9EFAA104ABDED00D09A15 /* c-index-test.c in Sources */,
1A4C41BF105B4C0B0047B5E7 /* CGCXXClass.cpp in Sources */,
1A4C41BF105B4C0B0047B5E7 /* CGClass.cpp in Sources */,
1A6B6CD410693FC900BB4A8F /* CodeCompleteConsumer.cpp in Sources */,
1A6B6CD510693FC900BB4A8F /* SemaCodeComplete.cpp in Sources */,
1A6B6E9A1069833600BB4A8F /* CGCXXExpr.cpp in Sources */,
1A6B6E9A1069833600BB4A8F /* CGExprCXX.cpp in Sources */,
1A535ED9107BC45E000C3AE7 /* CXXInheritance.cpp in Sources */,
1A6C01F7108128710072DEE4 /* CGRtti.cpp in Sources */,
1A81AA19108144F40094E50B /* CGVtable.cpp in Sources */,

View File

@ -120,8 +120,7 @@ class ASTContext {
QualType ObjCIdTypedefType;
/// ObjCSelType - another pseudo built-in typedef type (set by Sema).
QualType ObjCSelType;
const RecordType *SelStructType;
QualType ObjCSelTypedefType;
/// ObjCProtoType - another pseudo built-in typedef type (set by Sema).
QualType ObjCProtoType;
@ -244,6 +243,7 @@ class ASTContext {
// pseudo-builtins
QualType ObjCIdRedefinitionType;
QualType ObjCClassRedefinitionType;
QualType ObjCSelRedefinitionType;
/// \brief Source ranges for all of the comments in the source file,
/// sorted in order of appearance in the translation unit.
@ -316,7 +316,7 @@ class ASTContext {
CanQualType OverloadTy;
CanQualType DependentTy;
CanQualType UndeducedAutoTy;
CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy;
CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy, ObjCBuiltinSelTy;
ASTContext(const LangOptions& LOpts, SourceManager &SM, const TargetInfo &t,
IdentifierTable &idents, SelectorTable &sels,
@ -532,8 +532,7 @@ class ASTContext {
QualType Canon = QualType());
QualType getTemplateSpecializationType(TemplateName T,
const TemplateArgumentLoc *Args,
unsigned NumArgs,
const TemplateArgumentListInfo &Args,
QualType Canon = QualType());
QualType getQualifiedNameType(NestedNameSpecifier *NNS,
@ -696,7 +695,7 @@ class ASTContext {
void setObjCIdType(QualType T);
void setObjCSelType(QualType T);
QualType getObjCSelType() const { return ObjCSelType; }
QualType getObjCSelType() const { return ObjCSelTypedefType; }
void setObjCProtoType(QualType QT);
QualType getObjCProtoType() const { return ObjCProtoType; }
@ -734,6 +733,8 @@ class ASTContext {
return getExtQualType(T, Qs);
}
DeclarationName getNameForTemplate(TemplateName Name);
TemplateName getQualifiedTemplateName(NestedNameSpecifier *NNS,
bool TemplateKeyword,
TemplateDecl *Template);
@ -796,6 +797,20 @@ class ASTContext {
return getTypeInfo(T).first;
}
/// getByteWidth - Return the size of a byte, in bits
uint64_t getByteSize() {
return getTypeSize(CharTy);
}
/// getTypeSizeInBytes - Return the size of the specified type, in bytes.
/// This method does not work on incomplete types.
uint64_t getTypeSizeInBytes(QualType T) {
return getTypeSize(T) / getByteSize();
}
uint64_t getTypeSizeInBytes(const Type *T) {
return getTypeSize(T) / getByteSize();
}
/// getTypeAlign - Return the ABI-specified alignment of a type, in bits.
/// This method does not work on incomplete types.
unsigned getTypeAlign(QualType T) {
@ -811,10 +826,7 @@ class ASTContext {
/// a data type.
unsigned getPreferredTypeAlign(const Type *T);
/// getDeclAlignInBytes - Return the alignment of the specified decl
/// that should be returned by __alignof(). Note that bitfields do
/// not have a valid alignment, so this method will assert on them.
unsigned getDeclAlignInBytes(const Decl *D);
unsigned getDeclAlignInBytes(const Decl *D, bool RefAsPointee = false);
/// getASTRecordLayout - Get or compute information about the layout of the
/// specified record (struct/union/class), which indicates its size and field
@ -1023,8 +1035,7 @@ class ASTContext {
return T == ObjCClassTypedefType;
}
bool isObjCSelType(QualType T) const {
assert(SelStructType && "isObjCSelType used before 'SEL' type is built");
return T->getAsStructureType() == SelStructType;
return T == ObjCSelTypedefType;
}
bool QualifiedIdConformsQualifiedId(QualType LHS, QualType RHS);
bool ObjCQualifiedIdTypesAreCompatible(QualType LHS, QualType RHS,

View File

@ -15,12 +15,12 @@
#define LLVM_CLANG_AST_ATTR_H
#include "llvm/Support/Casting.h"
using llvm::dyn_cast;
#include "llvm/ADT/StringRef.h"
#include <cassert>
#include <cstring>
#include <string>
#include <algorithm>
using llvm::dyn_cast;
namespace clang {
class ASTContext;
@ -49,6 +49,7 @@ class Attr {
AnalyzerNoReturn, // Clang-specific.
Annotate,
AsmLabel, // Represent GCC asm label extension.
BaseCheck,
Blocks,
CDecl,
Cleanup,
@ -59,9 +60,11 @@ class Attr {
Deprecated,
Destructor,
FastCall,
Final,
Format,
FormatArg,
GNUInline,
Hiding,
IBOutletKind, // Clang-specific. Use "Kind" suffix to not conflict with
Malloc,
NoDebug,
@ -71,6 +74,7 @@ class Attr {
NoThrow,
ObjCException,
ObjCNSObject,
Override,
CFReturnsRetained, // Clang/Checker-specific.
NSReturnsRetained, // Clang/Checker-specific.
Overloadable, // Clang-specific
@ -184,12 +188,24 @@ class PragmaPackAttr : public Attr {
class AlignedAttr : public Attr {
unsigned Alignment;
public:
AlignedAttr(unsigned alignment) : Attr(Aligned), Alignment(alignment) {}
AlignedAttr(unsigned alignment)
: Attr(Aligned), Alignment(alignment) {}
/// getAlignment - The specified alignment in bits.
unsigned getAlignment() const { return Alignment; }
/// getMaxAlignment - Get the maximum alignment of attributes on this list.
unsigned getMaxAlignment() const {
const AlignedAttr *Next = getNext<AlignedAttr>();
if (Next)
return std::max(Next->getMaxAlignment(), Alignment);
else
return Alignment;
}
virtual Attr* clone(ASTContext &C) const { return ::new (C) AlignedAttr(Alignment); }
virtual Attr* clone(ASTContext &C) const {
return ::new (C) AlignedAttr(Alignment);
}
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
@ -201,7 +217,7 @@ class AlignedAttr : public Attr {
class AnnotateAttr : public Attr {
std::string Annotation;
public:
AnnotateAttr(const std::string &ann) : Attr(Annotate), Annotation(ann) {}
AnnotateAttr(llvm::StringRef ann) : Attr(Annotate), Annotation(ann) {}
const std::string& getAnnotation() const { return Annotation; }
@ -217,7 +233,7 @@ class AnnotateAttr : public Attr {
class AsmLabelAttr : public Attr {
std::string Label;
public:
AsmLabelAttr(const std::string &L) : Attr(AsmLabel), Label(L) {}
AsmLabelAttr(llvm::StringRef L) : Attr(AsmLabel), Label(L) {}
const std::string& getLabel() const { return Label; }
@ -235,7 +251,7 @@ DEF_SIMPLE_ATTR(AlwaysInline);
class AliasAttr : public Attr {
std::string Aliasee;
public:
AliasAttr(const std::string &aliasee) : Attr(Alias), Aliasee(aliasee) {}
AliasAttr(llvm::StringRef aliasee) : Attr(Alias), Aliasee(aliasee) {}
const std::string& getAliasee() const { return Aliasee; }
@ -304,11 +320,12 @@ DEF_SIMPLE_ATTR(Malloc);
DEF_SIMPLE_ATTR(NoReturn);
DEF_SIMPLE_ATTR(AnalyzerNoReturn);
DEF_SIMPLE_ATTR(Deprecated);
DEF_SIMPLE_ATTR(Final);
class SectionAttr : public Attr {
std::string Name;
public:
SectionAttr(const std::string &N) : Attr(Section), Name(N) {}
SectionAttr(llvm::StringRef N) : Attr(Section), Name(N) {}
const std::string& getName() const { return Name; }
@ -367,11 +384,11 @@ class FormatAttr : public Attr {
std::string Type;
int formatIdx, firstArg;
public:
FormatAttr(const std::string &type, int idx, int first) : Attr(Format),
FormatAttr(llvm::StringRef type, int idx, int first) : Attr(Format),
Type(type), formatIdx(idx), firstArg(first) {}
const std::string& getType() const { return Type; }
void setType(const std::string &type) { Type = type; }
void setType(llvm::StringRef type) { Type = type; }
int getFormatIdx() const { return formatIdx; }
int getFirstArg() const { return firstArg; }
@ -544,6 +561,11 @@ class ReqdWorkGroupSizeAttr : public Attr {
DEF_SIMPLE_ATTR(CFReturnsRetained);
DEF_SIMPLE_ATTR(NSReturnsRetained);
// C++0x member checking attributes.
DEF_SIMPLE_ATTR(BaseCheck);
DEF_SIMPLE_ATTR(Hiding);
DEF_SIMPLE_ATTR(Override);
#undef DEF_SIMPLE_ATTR
} // end namespace clang

View File

@ -54,6 +54,32 @@ class DeclaratorInfo {
TypeLoc getTypeLoc() const;
};
/// UnresolvedSet - A set of unresolved declarations. This is needed
/// in a lot of places, but isn't really worth breaking into its own
/// header right now.
class UnresolvedSet {
typedef llvm::SmallVector<NamedDecl*, 4> DeclsTy;
DeclsTy Decls;
public:
void addDecl(NamedDecl *D) {
Decls.push_back(D);
}
bool replace(const NamedDecl* Old, NamedDecl *New) {
for (DeclsTy::iterator I = Decls.begin(), E = Decls.end(); I != E; ++I)
if (*I == Old)
return (*I = New, true);
return false;
}
unsigned size() const { return Decls.size(); }
typedef DeclsTy::const_iterator iterator;
iterator begin() const { return Decls.begin(); }
iterator end() const { return Decls.end(); }
};
/// TranslationUnitDecl - The top declaration context.
class TranslationUnitDecl : public Decl, public DeclContext {
ASTContext &Ctx;
@ -172,6 +198,26 @@ class NamedDecl : public Decl {
/// \brief Determine whether this declaration has linkage.
bool hasLinkage() const;
/// \brief Describes the different kinds of linkage
/// (C++ [basic.link], C99 6.2.2) that an entity may have.
enum Linkage {
/// \brief No linkage, which means that the entity is unique and
/// can only be referred to from within its scope.
NoLinkage = 0,
/// \brief Internal linkage, which indicates that the entity can
/// be referred to from within the translation unit (but not other
/// translation units).
InternalLinkage,
/// \brief External linkage, which indicates that the entity can
/// be referred to from other translation units.
ExternalLinkage
};
/// \brief Determine what kind of linkage this entity has.
Linkage getLinkage() const;
/// \brief Looks through UsingDecls and ObjCCompatibleAliasDecls for
/// the underlying named decl.
NamedDecl *getUnderlyingDecl();

View File

@ -503,12 +503,12 @@ class Decl {
/// PrettyStackTraceDecl - If a crash occurs, indicate that it happened when
/// doing something to a specific decl.
class PrettyStackTraceDecl : public llvm::PrettyStackTraceEntry {
Decl *TheDecl;
const Decl *TheDecl;
SourceLocation Loc;
SourceManager &SM;
const char *Message;
public:
PrettyStackTraceDecl(Decl *theDecl, SourceLocation L,
PrettyStackTraceDecl(const Decl *theDecl, SourceLocation L,
SourceManager &sm, const char *Msg)
: TheDecl(theDecl), Loc(L), SM(sm), Message(Msg) {}

View File

@ -376,13 +376,13 @@ class CXXRecordDecl : public RecordDecl {
/// of this C++ class (but not its inherited conversion
/// functions). Each of the entries in this overload set is a
/// CXXConversionDecl.
OverloadedFunctionDecl Conversions;
UnresolvedSet Conversions;
/// VisibleConversions - Overload set containing the conversion functions
/// of this C++ class and all those inherited conversion functions that
/// are visible in this class. Each of the entries in this overload set is
/// a CXXConversionDecl or a FunctionTemplateDecl.
OverloadedFunctionDecl VisibleConversions;
UnresolvedSet VisibleConversions;
/// \brief The template or declaration that this declaration
/// describes or was instantiated from, respectively.
@ -400,7 +400,7 @@ class CXXRecordDecl : public RecordDecl {
const llvm::SmallPtrSet<CanQualType, 8> &TopConversionsTypeSet,
const llvm::SmallPtrSet<CanQualType, 8> &HiddenConversionTypes);
void collectConversionFunctions(
llvm::SmallPtrSet<CanQualType, 8>& ConversionsTypeSet);
llvm::SmallPtrSet<CanQualType, 8>& ConversionsTypeSet) const;
protected:
CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC,
@ -581,22 +581,34 @@ class CXXRecordDecl : public RecordDecl {
/// getConversions - Retrieve the overload set containing all of the
/// conversion functions in this class.
OverloadedFunctionDecl *getConversionFunctions() {
UnresolvedSet *getConversionFunctions() {
assert((this->isDefinition() ||
cast<RecordType>(getTypeForDecl())->isBeingDefined()) &&
"getConversionFunctions() called on incomplete type");
return &Conversions;
}
const OverloadedFunctionDecl *getConversionFunctions() const {
const UnresolvedSet *getConversionFunctions() const {
assert((this->isDefinition() ||
cast<RecordType>(getTypeForDecl())->isBeingDefined()) &&
"getConversionFunctions() called on incomplete type");
return &Conversions;
}
typedef UnresolvedSet::iterator conversion_iterator;
conversion_iterator conversion_begin() const { return Conversions.begin(); }
conversion_iterator conversion_end() const { return Conversions.end(); }
/// Replaces a conversion function with a new declaration.
///
/// Returns true if the old conversion was found.
bool replaceConversion(const NamedDecl* Old, NamedDecl *New) {
return Conversions.replace(Old, New);
}
/// getVisibleConversionFunctions - get all conversion functions visible
/// in current class; including conversion function templates.
OverloadedFunctionDecl *getVisibleConversionFunctions();
const UnresolvedSet *getVisibleConversionFunctions();
/// addVisibleConversionFunction - Add a new conversion function to the
/// list of visible conversion functions.
void addVisibleConversionFunction(CXXConversionDecl *ConvDecl);
@ -1502,9 +1514,9 @@ class UsingDirectiveDecl : public NamedDecl {
SourceLocation IdentLoc;
/// NominatedNamespace - Namespace nominated by using-directive.
NamespaceDecl *NominatedNamespace;
NamedDecl *NominatedNamespace;
/// Enclosing context containing both using-directive and nomintated
/// Enclosing context containing both using-directive and nominated
/// namespace.
DeclContext *CommonAncestor;
@ -1520,12 +1532,12 @@ class UsingDirectiveDecl : public NamedDecl {
SourceRange QualifierRange,
NestedNameSpecifier *Qualifier,
SourceLocation IdentLoc,
NamespaceDecl *Nominated,
NamedDecl *Nominated,
DeclContext *CommonAncestor)
: NamedDecl(Decl::UsingDirective, DC, L, getName()),
NamespaceLoc(NamespcLoc), QualifierRange(QualifierRange),
Qualifier(Qualifier), IdentLoc(IdentLoc),
NominatedNamespace(Nominated? Nominated->getOriginalNamespace() : 0),
NominatedNamespace(Nominated),
CommonAncestor(CommonAncestor) {
}
@ -1538,8 +1550,13 @@ class UsingDirectiveDecl : public NamedDecl {
/// name of the namespace.
NestedNameSpecifier *getQualifier() const { return Qualifier; }
NamedDecl *getNominatedNamespaceAsWritten() { return NominatedNamespace; }
const NamedDecl *getNominatedNamespaceAsWritten() const {
return NominatedNamespace;
}
/// getNominatedNamespace - Returns namespace nominated by using-directive.
NamespaceDecl *getNominatedNamespace() { return NominatedNamespace; }
NamespaceDecl *getNominatedNamespace();
const NamespaceDecl *getNominatedNamespace() const {
return const_cast<UsingDirectiveDecl*>(this)->getNominatedNamespace();
@ -1562,7 +1579,7 @@ class UsingDirectiveDecl : public NamedDecl {
SourceRange QualifierRange,
NestedNameSpecifier *Qualifier,
SourceLocation IdentLoc,
NamespaceDecl *Nominated,
NamedDecl *Nominated,
DeclContext *CommonAncestor);
static bool classof(const Decl *D) {

View File

@ -955,8 +955,7 @@ class ClassTemplatePartialSpecializationDecl
TemplateParameterList *Params,
ClassTemplateDecl *SpecializedTemplate,
TemplateArgumentListBuilder &Builder,
TemplateArgumentLoc *ArgInfos,
unsigned NumArgInfos,
const TemplateArgumentListInfo &ArgInfos,
ClassTemplatePartialSpecializationDecl *PrevDecl);
/// Get the list of template parameters

View File

@ -25,6 +25,7 @@ namespace llvm {
namespace clang {
class CXXSpecialName;
class CXXOperatorIdName;
class CXXLiteralOperatorIdName;
class DeclarationNameExtra;
class IdentifierInfo;
class MultiKeywordSelector;
@ -48,6 +49,7 @@ class DeclarationName {
CXXDestructorName,
CXXConversionFunctionName,
CXXOperatorName,
CXXLiteralOperatorName,
CXXUsingDirective
};
@ -115,6 +117,12 @@ class DeclarationName {
return 0;
}
CXXLiteralOperatorIdName *getAsCXXLiteralOperatorIdName() const {
if (getNameKind() == CXXLiteralOperatorName)
return reinterpret_cast<CXXLiteralOperatorIdName *>(Ptr & ~PtrMask);
return 0;
}
// Construct a declaration name from the name of a C++ constructor,
// destructor, or conversion function.
DeclarationName(CXXSpecialName *Name)
@ -131,6 +139,12 @@ class DeclarationName {
Ptr |= StoredDeclarationNameExtra;
}
DeclarationName(CXXLiteralOperatorIdName *Name)
: Ptr(reinterpret_cast<uintptr_t>(Name)) {
assert((Ptr & PtrMask) == 0 && "Improperly aligned CXXLiteralOperatorId");
Ptr |= StoredDeclarationNameExtra;
}
/// Construct a declaration name from a raw pointer.
DeclarationName(uintptr_t Ptr) : Ptr(Ptr) { }
@ -201,7 +215,7 @@ class DeclarationName {
N.Ptr = reinterpret_cast<uintptr_t> (P);
return N;
}
static DeclarationName getFromOpaqueInteger(uintptr_t P) {
DeclarationName N;
N.Ptr = P;
@ -218,6 +232,10 @@ class DeclarationName {
/// kind of overloaded operator.
OverloadedOperatorKind getCXXOverloadedOperator() const;
/// getCXXLiteralIdentifier - If this name is the name of a literal
/// operator, retrieve the identifier associated with it.
IdentifierInfo *getCXXLiteralIdentifier() const;
/// getObjCSelector - Get the Objective-C selector stored in this
/// declaration name.
Selector getObjCSelector() const;
@ -293,7 +311,7 @@ class DeclarationNameTable {
/// getIdentifier - Create a declaration name that is a simple
/// identifier.
DeclarationName getIdentifier(IdentifierInfo *ID) {
DeclarationName getIdentifier(const IdentifierInfo *ID) {
return DeclarationName(ID);
}
@ -324,6 +342,10 @@ class DeclarationNameTable {
/// getCXXOperatorName - Get the name of the overloadable C++
/// operator corresponding to Op.
DeclarationName getCXXOperatorName(OverloadedOperatorKind Op);
/// getCXXLiteralOperatorName - Get the name of the literal operator function
/// with II as the identifier.
DeclarationName getCXXLiteralOperatorName(IdentifierInfo *II);
};
/// Insertion operator for diagnostics. This allows sending DeclarationName's

View File

@ -35,6 +35,7 @@ namespace clang {
class CXXOperatorCallExpr;
class CXXMemberCallExpr;
class TemplateArgumentLoc;
class TemplateArgumentListInfo;
/// Expr - This represents one expression. Note that Expr's are subclasses of
/// Stmt. This allows an expression to be transparently used any place a Stmt
@ -366,6 +367,10 @@ struct ExplicitTemplateArgumentList {
const TemplateArgumentLoc *getTemplateArgs() const {
return reinterpret_cast<const TemplateArgumentLoc *> (this + 1);
}
void initializeFrom(const TemplateArgumentListInfo &List);
void copyInto(TemplateArgumentListInfo &List) const;
static std::size_t sizeFor(const TemplateArgumentListInfo &List);
};
/// DeclRefExpr - [C99 6.5.1p2] - A reference to a declared variable, function,
@ -423,31 +428,24 @@ class DeclRefExpr : public Expr {
DeclRefExpr(NestedNameSpecifier *Qualifier, SourceRange QualifierRange,
NamedDecl *D, SourceLocation NameLoc,
bool HasExplicitTemplateArgumentList,
SourceLocation LAngleLoc,
const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
SourceLocation RAngleLoc,
QualType T, bool TD, bool VD);
const TemplateArgumentListInfo *TemplateArgs,
QualType T);
protected:
// FIXME: Eventually, this constructor will go away and all subclasses
// will have to provide the type- and value-dependent flags.
DeclRefExpr(StmtClass SC, NamedDecl *d, QualType t, SourceLocation l) :
Expr(SC, t), DecoratedD(d, 0), Loc(l) {}
/// \brief Computes the type- and value-dependence flags for this
/// declaration reference expression.
void computeDependence();
DeclRefExpr(StmtClass SC, NamedDecl *d, QualType t, SourceLocation l, bool TD,
bool VD) :
Expr(SC, t, TD, VD), DecoratedD(d, 0), Loc(l) {}
DeclRefExpr(StmtClass SC, NamedDecl *d, QualType t, SourceLocation l) :
Expr(SC, t, false, false), DecoratedD(d, 0), Loc(l) {
computeDependence();
}
public:
// FIXME: Eventually, this constructor will go away and all clients
// will have to provide the type- and value-dependent flags.
DeclRefExpr(NamedDecl *d, QualType t, SourceLocation l) :
Expr(DeclRefExprClass, t), DecoratedD(d, 0), Loc(l) {}
DeclRefExpr(NamedDecl *d, QualType t, SourceLocation l, bool TD, bool VD) :
Expr(DeclRefExprClass, t, TD, VD), DecoratedD(d, 0), Loc(l) {}
Expr(DeclRefExprClass, t, false, false), DecoratedD(d, 0), Loc(l) {
computeDependence();
}
/// \brief Construct an empty declaration reference expression.
explicit DeclRefExpr(EmptyShell Empty)
@ -458,19 +456,8 @@ class DeclRefExpr : public Expr {
SourceRange QualifierRange,
NamedDecl *D,
SourceLocation NameLoc,
QualType T, bool TD, bool VD);
static DeclRefExpr *Create(ASTContext &Context,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
NamedDecl *D,
SourceLocation NameLoc,
bool HasExplicitTemplateArgumentList,
SourceLocation LAngleLoc,
const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
SourceLocation RAngleLoc,
QualType T, bool TD, bool VD);
QualType T,
const TemplateArgumentListInfo *TemplateArgs = 0);
NamedDecl *getDecl() { return DecoratedD.getPointer(); }
const NamedDecl *getDecl() const { return DecoratedD.getPointer(); }
@ -508,6 +495,13 @@ class DeclRefExpr : public Expr {
bool hasExplicitTemplateArgumentList() const {
return DecoratedD.getInt() & HasExplicitTemplateArgumentListFlag;
}
/// \brief Copies the template arguments (if present) into the given
/// structure.
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
if (hasExplicitTemplateArgumentList())
getExplicitTemplateArgumentList()->copyInto(List);
}
/// \brief Retrieve the location of the left angle bracket following the
/// member name ('<'), if any.
@ -546,8 +540,7 @@ class DeclRefExpr : public Expr {
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == DeclRefExprClass ||
T->getStmtClass() == CXXConditionDeclExprClass;
return T->getStmtClass() == DeclRefExprClass;
}
static bool classof(const DeclRefExpr *) { return true; }
@ -1313,9 +1306,7 @@ class MemberExpr : public Expr {
MemberExpr(Expr *base, bool isarrow, NestedNameSpecifier *qual,
SourceRange qualrange, NamedDecl *memberdecl, SourceLocation l,
bool has_explicit, SourceLocation langle,
const TemplateArgumentLoc *targs, unsigned numtargs,
SourceLocation rangle, QualType ty);
const TemplateArgumentListInfo *targs, QualType ty);
public:
MemberExpr(Expr *base, bool isarrow, NamedDecl *memberdecl, SourceLocation l,
@ -1334,11 +1325,7 @@ class MemberExpr : public Expr {
NestedNameSpecifier *qual, SourceRange qualrange,
NamedDecl *memberdecl,
SourceLocation l,
bool has_explicit,
SourceLocation langle,
const TemplateArgumentLoc *targs,
unsigned numtargs,
SourceLocation rangle,
const TemplateArgumentListInfo *targs,
QualType ty);
void setBase(Expr *E) { Base = E; }
@ -1378,10 +1365,17 @@ class MemberExpr : public Expr {
/// \brief Determines whether this member expression actually had a C++
/// template argument list explicitly specified, e.g., x.f<int>.
bool hasExplicitTemplateArgumentList() {
bool hasExplicitTemplateArgumentList() const {
return HasExplicitTemplateArgumentList;
}
/// \brief Copies the template arguments (if present) into the given
/// structure.
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
if (hasExplicitTemplateArgumentList())
getExplicitTemplateArgumentList()->copyInto(List);
}
/// \brief Retrieve the location of the left angle bracket following the
/// member name ('<'), if any.
SourceLocation getLAngleLoc() const {
@ -1579,7 +1573,11 @@ class CastExpr : public Expr {
CK_FloatingToIntegral,
/// CK_FloatingCast - Casting between floating types of different size.
CK_FloatingCast
CK_FloatingCast,
/// CK_MemberPointerToBoolean - Member pointer to boolean
CK_MemberPointerToBoolean
};
private:

View File

@ -17,6 +17,7 @@
#include "clang/Basic/TypeTraits.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/TemplateBase.h"
namespace clang {
@ -24,6 +25,7 @@ namespace clang {
class CXXDestructorDecl;
class CXXMethodDecl;
class CXXTemporary;
class TemplateArgumentListInfo;
//===--------------------------------------------------------------------===//
// C++ Expressions.
@ -669,40 +671,6 @@ class CXXZeroInitValueExpr : public Expr {
virtual child_iterator child_end();
};
/// CXXConditionDeclExpr - Condition declaration of a if/switch/while/for
/// statement, e.g: "if (int x = f()) {...}".
/// The main difference with DeclRefExpr is that CXXConditionDeclExpr owns the
/// decl that it references.
///
class CXXConditionDeclExpr : public DeclRefExpr {
public:
CXXConditionDeclExpr(SourceLocation startLoc,
SourceLocation eqLoc, VarDecl *var)
: DeclRefExpr(CXXConditionDeclExprClass, var,
var->getType().getNonReferenceType(), startLoc,
var->getType()->isDependentType(),
/*FIXME:integral constant?*/
var->getType()->isDependentType()) {}
SourceLocation getStartLoc() const { return getLocation(); }
VarDecl *getVarDecl() { return cast<VarDecl>(getDecl()); }
const VarDecl *getVarDecl() const { return cast<VarDecl>(getDecl()); }
virtual SourceRange getSourceRange() const {
return SourceRange(getStartLoc(), getVarDecl()->getInit()->getLocEnd());
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXConditionDeclExprClass;
}
static bool classof(const CXXConditionDeclExpr *) { return true; }
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
};
/// CXXNewExpr - A new expression for memory allocation and constructor calls,
/// e.g: "new CXXNewExpr(foo)".
class CXXNewExpr : public Expr {
@ -975,52 +943,6 @@ class CXXPseudoDestructorExpr : public Expr {
virtual child_iterator child_end();
};
/// \brief Represents the name of a function that has not been
/// resolved to any declaration.
///
/// Unresolved function names occur when a function name is
/// encountered prior to an open parentheses ('(') in a C++ function
/// call, and the function name itself did not resolve to a
/// declaration. These function names can only be resolved when they
/// form the postfix-expression of a function call, so that
/// argument-dependent lookup finds declarations corresponding to
/// these functions.
/// @code
/// template<typename T> void f(T x) {
/// g(x); // g is an unresolved function name (that is also a dependent name)
/// }
/// @endcode
class UnresolvedFunctionNameExpr : public Expr {
/// The name that was present in the source
DeclarationName Name;
/// The location of this name in the source code
SourceLocation Loc;
public:
UnresolvedFunctionNameExpr(DeclarationName N, QualType T, SourceLocation L)
: Expr(UnresolvedFunctionNameExprClass, T, false, false), Name(N), Loc(L) { }
/// \brief Retrieves the name that occurred in the source code.
DeclarationName getName() const { return Name; }
/// getLocation - Retrieves the location in the source code where
/// the name occurred.
SourceLocation getLocation() const { return Loc; }
virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == UnresolvedFunctionNameExprClass;
}
static bool classof(const UnresolvedFunctionNameExpr *) { return true; }
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
};
/// UnaryTypeTraitExpr - A GCC or MS unary type trait, as used in the
/// implementation of TR1/C++0x type trait templates.
/// Example:
@ -1063,21 +985,177 @@ class UnaryTypeTraitExpr : public Expr {
virtual child_iterator child_end();
};
/// \brief A reference to a name which we were able to look up during
/// parsing but could not resolve to a specific declaration. This
/// arises in several ways:
/// * we might be waiting for argument-dependent lookup
/// * the name might resolve to an overloaded function
/// and eventually:
/// * the lookup might have included a function template
/// These never include UnresolvedUsingValueDecls, which are always
/// class members and therefore appear only in
/// UnresolvedMemberLookupExprs.
class UnresolvedLookupExpr : public Expr {
/// The results. These are undesugared, which is to say, they may
/// include UsingShadowDecls.
UnresolvedSet Results;
/// The name declared.
DeclarationName Name;
/// The qualifier given, if any.
NestedNameSpecifier *Qualifier;
/// The source range of the nested name specifier.
SourceRange QualifierRange;
/// The location of the name.
SourceLocation NameLoc;
/// True if these lookup results should be extended by
/// argument-dependent lookup if this is the operand of a function
/// call.
bool RequiresADL;
/// True if these lookup results are overloaded. This is pretty
/// trivially rederivable if we urgently need to kill this field.
bool Overloaded;
/// True if the name looked up had explicit template arguments.
/// This requires all the results to be function templates.
bool HasExplicitTemplateArgs;
UnresolvedLookupExpr(QualType T, bool Dependent,
NestedNameSpecifier *Qualifier, SourceRange QRange,
DeclarationName Name, SourceLocation NameLoc,
bool RequiresADL, bool Overloaded, bool HasTemplateArgs)
: Expr(UnresolvedLookupExprClass, T, Dependent, Dependent),
Name(Name), Qualifier(Qualifier), QualifierRange(QRange),
NameLoc(NameLoc), RequiresADL(RequiresADL), Overloaded(Overloaded),
HasExplicitTemplateArgs(HasTemplateArgs)
{}
public:
static UnresolvedLookupExpr *Create(ASTContext &C,
bool Dependent,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
DeclarationName Name,
SourceLocation NameLoc,
bool ADL, bool Overloaded) {
return new(C) UnresolvedLookupExpr(Dependent ? C.DependentTy : C.OverloadTy,
Dependent, Qualifier, QualifierRange,
Name, NameLoc, ADL, Overloaded, false);
}
static UnresolvedLookupExpr *Create(ASTContext &C,
bool Dependent,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
DeclarationName Name,
SourceLocation NameLoc,
bool ADL,
const TemplateArgumentListInfo &Args);
/// Computes whether an unresolved lookup on the given declarations
/// and optional template arguments is type- and value-dependent.
static bool ComputeDependence(NamedDecl * const *Begin,
NamedDecl * const *End,
const TemplateArgumentListInfo *Args);
void addDecl(NamedDecl *Decl) {
Results.addDecl(Decl);
}
typedef UnresolvedSet::iterator decls_iterator;
decls_iterator decls_begin() const { return Results.begin(); }
decls_iterator decls_end() const { return Results.end(); }
/// True if this declaration should be extended by
/// argument-dependent lookup.
bool requiresADL() const { return RequiresADL; }
/// True if this lookup is overloaded.
bool isOverloaded() const { return Overloaded; }
/// Fetches the name looked up.
DeclarationName getName() const { return Name; }
/// Gets the location of the name.
SourceLocation getNameLoc() const { return NameLoc; }
/// Fetches the nested-name qualifier, if one was given.
NestedNameSpecifier *getQualifier() const { return Qualifier; }
/// Fetches the range of the nested-name qualifier.
SourceRange getQualifierRange() const { return QualifierRange; }
/// Determines whether this lookup had explicit template arguments.
bool hasExplicitTemplateArgs() const { return HasExplicitTemplateArgs; }
// Note that, inconsistently with the explicit-template-argument AST
// nodes, users are *forbidden* from calling these methods on objects
// without explicit template arguments.
/// Gets a reference to the explicit template argument list.
const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const {
assert(hasExplicitTemplateArgs());
return *reinterpret_cast<const ExplicitTemplateArgumentList*>(this + 1);
}
/// \brief Copies the template arguments (if present) into the given
/// structure.
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
getExplicitTemplateArgs().copyInto(List);
}
SourceLocation getLAngleLoc() const {
return getExplicitTemplateArgs().LAngleLoc;
}
SourceLocation getRAngleLoc() const {
return getExplicitTemplateArgs().RAngleLoc;
}
TemplateArgumentLoc const *getTemplateArgs() const {
return getExplicitTemplateArgs().getTemplateArgs();
}
unsigned getNumTemplateArgs() const {
return getExplicitTemplateArgs().NumTemplateArgs;
}
virtual SourceRange getSourceRange() const {
SourceRange Range(NameLoc);
if (Qualifier) Range.setBegin(QualifierRange.getBegin());
if (hasExplicitTemplateArgs()) Range.setEnd(getRAngleLoc());
return Range;
}
virtual StmtIterator child_begin();
virtual StmtIterator child_end();
static bool classof(const Stmt *T) {
return T->getStmtClass() == UnresolvedLookupExprClass;
}
static bool classof(const UnresolvedLookupExpr *) { return true; }
};
/// \brief A qualified reference to a name whose declaration cannot
/// yet be resolved.
///
/// UnresolvedDeclRefExpr is similar to eclRefExpr in that
/// DependentScopeDeclRefExpr is similar to DeclRefExpr in that
/// it expresses a reference to a declaration such as
/// X<T>::value. The difference, however, is that an
/// UnresolvedDeclRefExpr node is used only within C++ templates when
/// DependentScopeDeclRefExpr node is used only within C++ templates when
/// the qualification (e.g., X<T>::) refers to a dependent type. In
/// this case, X<T>::value cannot resolve to a declaration because the
/// declaration will differ from on instantiation of X<T> to the
/// next. Therefore, UnresolvedDeclRefExpr keeps track of the
/// next. Therefore, DependentScopeDeclRefExpr keeps track of the
/// qualifier (X<T>::) and the name of the entity being referenced
/// ("value"). Such expressions will instantiate to a DeclRefExpr once the
/// declaration can be found.
class UnresolvedDeclRefExpr : public Expr {
class DependentScopeDeclRefExpr : public Expr {
/// The name of the entity we will be referencing.
DeclarationName Name;
@ -1090,19 +1168,30 @@ class UnresolvedDeclRefExpr : public Expr {
/// \brief The nested-name-specifier that qualifies this unresolved
/// declaration name.
NestedNameSpecifier *NNS;
NestedNameSpecifier *Qualifier;
/// \brief Whether this expr is an address of (&) operand.
/// FIXME: Stash this bit into NNS!
bool IsAddressOfOperand;
/// \brief Whether the name includes explicit template arguments.
bool HasExplicitTemplateArgs;
DependentScopeDeclRefExpr(QualType T,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
DeclarationName Name,
SourceLocation NameLoc,
bool HasExplicitTemplateArgs)
: Expr(DependentScopeDeclRefExprClass, T, true, true),
Name(Name), Loc(NameLoc),
QualifierRange(QualifierRange), Qualifier(Qualifier),
HasExplicitTemplateArgs(HasExplicitTemplateArgs)
{}
public:
UnresolvedDeclRefExpr(DeclarationName N, QualType T, SourceLocation L,
SourceRange R, NestedNameSpecifier *NNS,
bool IsAddressOfOperand)
: Expr(UnresolvedDeclRefExprClass, T, true, true),
Name(N), Loc(L), QualifierRange(R), NNS(NNS),
IsAddressOfOperand(IsAddressOfOperand) { }
static DependentScopeDeclRefExpr *Create(ASTContext &C,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
DeclarationName Name,
SourceLocation NameLoc,
const TemplateArgumentListInfo *TemplateArgs = 0);
/// \brief Retrieve the name that this expression refers to.
DeclarationName getDeclName() const { return Name; }
@ -1115,118 +1204,59 @@ class UnresolvedDeclRefExpr : public Expr {
/// \brief Retrieve the nested-name-specifier that qualifies this
/// declaration.
NestedNameSpecifier *getQualifier() const { return NNS; }
NestedNameSpecifier *getQualifier() const { return Qualifier; }
/// \brief Retrieve whether this is an address of (&) operand.
/// Determines whether this lookup had explicit template arguments.
bool hasExplicitTemplateArgs() const { return HasExplicitTemplateArgs; }
// Note that, inconsistently with the explicit-template-argument AST
// nodes, users are *forbidden* from calling these methods on objects
// without explicit template arguments.
/// Gets a reference to the explicit template argument list.
const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const {
assert(hasExplicitTemplateArgs());
return *reinterpret_cast<const ExplicitTemplateArgumentList*>(this + 1);
}
/// \brief Copies the template arguments (if present) into the given
/// structure.
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
getExplicitTemplateArgs().copyInto(List);
}
SourceLocation getLAngleLoc() const {
return getExplicitTemplateArgs().LAngleLoc;
}
SourceLocation getRAngleLoc() const {
return getExplicitTemplateArgs().RAngleLoc;
}
TemplateArgumentLoc const *getTemplateArgs() const {
return getExplicitTemplateArgs().getTemplateArgs();
}
unsigned getNumTemplateArgs() const {
return getExplicitTemplateArgs().NumTemplateArgs;
}
bool isAddressOfOperand() const { return IsAddressOfOperand; }
virtual SourceRange getSourceRange() const {
return SourceRange(QualifierRange.getBegin(), getLocation());
SourceRange Range(QualifierRange.getBegin(), getLocation());
if (hasExplicitTemplateArgs())
Range.setEnd(getRAngleLoc());
return Range;
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == UnresolvedDeclRefExprClass;
return T->getStmtClass() == DependentScopeDeclRefExprClass;
}
static bool classof(const UnresolvedDeclRefExpr *) { return true; }
static bool classof(const DependentScopeDeclRefExpr *) { return true; }
virtual StmtIterator child_begin();
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 TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs,
SourceLocation RAngleLoc);
virtual void DoDestroy(ASTContext &Context);
public:
static TemplateIdRefExpr *
Create(ASTContext &Context, QualType T,
NestedNameSpecifier *Qualifier, SourceRange QualifierRange,
TemplateName Template, SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc, const TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs, SourceLocation RAngleLoc);
/// \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 TemplateArgumentLoc *getTemplateArgs() const {
return reinterpret_cast<const TemplateArgumentLoc *>(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;
@ -1377,10 +1407,10 @@ class CXXUnresolvedConstructExpr : public Expr {
virtual child_iterator child_end();
};
/// \brief Represents a C++ member access expression where the actual member
/// referenced could not be resolved, e.g., because the base expression or the
/// member name was dependent.
class CXXUnresolvedMemberExpr : public Expr {
/// \brief Represents a C++ member access expression where the actual
/// member referenced could not be resolved because the base
/// expression or the member name was dependent.
class CXXDependentScopeMemberExpr : public Expr {
/// \brief The expression for the base pointer or class reference,
/// e.g., the \c x in x.f.
Stmt *Base;
@ -1408,7 +1438,7 @@ class CXXUnresolvedMemberExpr : public Expr {
///
/// FIXME: This member, along with the Qualifier and QualifierRange, could
/// be stuck into a structure that is optionally allocated at the end of
/// the CXXUnresolvedMemberExpr, to save space in the common case.
/// the CXXDependentScopeMemberExpr, to save space in the common case.
NamedDecl *FirstQualifierFoundInScope;
/// \brief The member to which this member expression refers, which
@ -1431,11 +1461,11 @@ class CXXUnresolvedMemberExpr : public Expr {
/// \brief Retrieve the explicit template argument list that followed the
/// member template name, if any.
const ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() const {
return const_cast<CXXUnresolvedMemberExpr *>(this)
return const_cast<CXXDependentScopeMemberExpr *>(this)
->getExplicitTemplateArgumentList();
}
CXXUnresolvedMemberExpr(ASTContext &C,
CXXDependentScopeMemberExpr(ASTContext &C,
Expr *Base, bool IsArrow,
SourceLocation OperatorLoc,
NestedNameSpecifier *Qualifier,
@ -1443,14 +1473,10 @@ class CXXUnresolvedMemberExpr : public Expr {
NamedDecl *FirstQualifierFoundInScope,
DeclarationName Member,
SourceLocation MemberLoc,
bool HasExplicitTemplateArgs,
SourceLocation LAngleLoc,
const TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs,
SourceLocation RAngleLoc);
const TemplateArgumentListInfo *TemplateArgs);
public:
CXXUnresolvedMemberExpr(ASTContext &C,
CXXDependentScopeMemberExpr(ASTContext &C,
Expr *Base, bool IsArrow,
SourceLocation OperatorLoc,
NestedNameSpecifier *Qualifier,
@ -1458,14 +1484,14 @@ class CXXUnresolvedMemberExpr : public Expr {
NamedDecl *FirstQualifierFoundInScope,
DeclarationName Member,
SourceLocation MemberLoc)
: Expr(CXXUnresolvedMemberExprClass, C.DependentTy, true, true),
: Expr(CXXDependentScopeMemberExprClass, C.DependentTy, true, true),
Base(Base), IsArrow(IsArrow), HasExplicitTemplateArgumentList(false),
OperatorLoc(OperatorLoc),
Qualifier(Qualifier), QualifierRange(QualifierRange),
FirstQualifierFoundInScope(FirstQualifierFoundInScope),
Member(Member), MemberLoc(MemberLoc) { }
static CXXUnresolvedMemberExpr *
static CXXDependentScopeMemberExpr *
Create(ASTContext &C,
Expr *Base, bool IsArrow,
SourceLocation OperatorLoc,
@ -1474,11 +1500,7 @@ class CXXUnresolvedMemberExpr : public Expr {
NamedDecl *FirstQualifierFoundInScope,
DeclarationName Member,
SourceLocation MemberLoc,
bool HasExplicitTemplateArgs,
SourceLocation LAngleLoc,
const TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs,
SourceLocation RAngleLoc);
const TemplateArgumentListInfo *TemplateArgs);
/// \brief Retrieve the base object of this member expressions,
/// e.g., the \c x in \c x.m.
@ -1529,10 +1551,17 @@ class CXXUnresolvedMemberExpr : public Expr {
/// \brief Determines whether this member expression actually had a C++
/// template argument list explicitly specified, e.g., x.f<int>.
bool hasExplicitTemplateArgumentList() {
bool hasExplicitTemplateArgumentList() const {
return HasExplicitTemplateArgumentList;
}
/// \brief Copies the template arguments (if present) into the given
/// structure.
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
if (hasExplicitTemplateArgumentList())
getExplicitTemplateArgumentList()->copyInto(List);
}
/// \brief Retrieve the location of the left angle bracket following the
/// member name ('<'), if any.
SourceLocation getLAngleLoc() const {
@ -1579,9 +1608,182 @@ class CXXUnresolvedMemberExpr : public Expr {
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXUnresolvedMemberExprClass;
return T->getStmtClass() == CXXDependentScopeMemberExprClass;
}
static bool classof(const CXXUnresolvedMemberExpr *) { return true; }
static bool classof(const CXXDependentScopeMemberExpr *) { return true; }
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
};
/// \brief Represents a C++ member access expression for which lookup
/// produced a set of overloaded functions. These are replaced with
/// MemberExprs in the final AST.
class UnresolvedMemberExpr : public Expr {
/// The results. These are undesugared, which is to say, they may
/// include UsingShadowDecls.
UnresolvedSet Results;
/// \brief The expression for the base pointer or class reference,
/// e.g., the \c x in x.f.
Stmt *Base;
/// \brief Whether this member expression used the '->' operator or
/// the '.' operator.
bool IsArrow : 1;
/// \brief Whether the lookup results contain an unresolved using
/// declaration.
bool HasUnresolvedUsing : 1;
/// \brief Whether this member expression has explicitly-specified template
/// arguments.
bool HasExplicitTemplateArgs : 1;
/// \brief The location of the '->' or '.' operator.
SourceLocation OperatorLoc;
/// \brief The nested-name-specifier that precedes the member name, if any.
NestedNameSpecifier *Qualifier;
/// \brief The source range covering the nested name specifier.
SourceRange QualifierRange;
/// \brief The member to which this member expression refers, which
/// can be a name or an overloaded operator.
DeclarationName MemberName;
/// \brief The location of the member name.
SourceLocation MemberLoc;
/// \brief Retrieve the explicit template argument list that followed the
/// member template name.
ExplicitTemplateArgumentList *getExplicitTemplateArgs() {
assert(HasExplicitTemplateArgs);
return reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1);
}
/// \brief Retrieve the explicit template argument list that followed the
/// member template name, if any.
const ExplicitTemplateArgumentList *getExplicitTemplateArgs() const {
return const_cast<UnresolvedMemberExpr*>(this)->getExplicitTemplateArgs();
}
UnresolvedMemberExpr(QualType T, bool Dependent,
bool HasUnresolvedUsing,
Expr *Base, bool IsArrow,
SourceLocation OperatorLoc,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
DeclarationName Member,
SourceLocation MemberLoc,
const TemplateArgumentListInfo *TemplateArgs);
public:
static UnresolvedMemberExpr *
Create(ASTContext &C, bool Dependent, bool HasUnresolvedUsing,
Expr *Base, bool IsArrow,
SourceLocation OperatorLoc,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
DeclarationName Member,
SourceLocation MemberLoc,
const TemplateArgumentListInfo *TemplateArgs);
/// Adds a declaration to the unresolved set. By assumption, all of
/// these happen at initialization time and properties like
/// 'Dependent' and 'HasUnresolvedUsing' take them into account.
void addDecl(NamedDecl *Decl) {
Results.addDecl(Decl);
}
typedef UnresolvedSet::iterator decls_iterator;
decls_iterator decls_begin() const { return Results.begin(); }
decls_iterator decls_end() const { return Results.end(); }
unsigned getNumDecls() const { return Results.size(); }
/// \brief Retrieve the base object of this member expressions,
/// e.g., the \c x in \c x.m.
Expr *getBase() { return cast<Expr>(Base); }
void setBase(Expr *E) { Base = E; }
/// \brief Determine whether this member expression used the '->'
/// operator; otherwise, it used the '.' operator.
bool isArrow() const { return IsArrow; }
void setArrow(bool A) { IsArrow = A; }
/// \brief Retrieve the location of the '->' or '.' operator.
SourceLocation getOperatorLoc() const { return OperatorLoc; }
void setOperatorLoc(SourceLocation L) { OperatorLoc = L; }
/// \brief Retrieve the nested-name-specifier that qualifies the member
/// name.
NestedNameSpecifier *getQualifier() const { return Qualifier; }
/// \brief Retrieve the source range covering the nested-name-specifier
/// that qualifies the member name.
SourceRange getQualifierRange() const { return QualifierRange; }
/// \brief Retrieve the name of the member that this expression
/// refers to.
DeclarationName getMemberName() const { return MemberName; }
void setMemberName(DeclarationName N) { MemberName = N; }
// \brief Retrieve the location of the name of the member that this
// expression refers to.
SourceLocation getMemberLoc() const { return MemberLoc; }
void setMemberLoc(SourceLocation L) { MemberLoc = L; }
/// \brief Determines whether this member expression actually had a C++
/// template argument list explicitly specified, e.g., x.f<int>.
bool hasExplicitTemplateArgs() const {
return HasExplicitTemplateArgs;
}
/// \brief Copies the template arguments into the given structure.
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
getExplicitTemplateArgs()->copyInto(List);
}
/// \brief Retrieve the location of the left angle bracket following
/// the member name ('<').
SourceLocation getLAngleLoc() const {
return getExplicitTemplateArgs()->LAngleLoc;
}
/// \brief Retrieve the template arguments provided as part of this
/// template-id.
const TemplateArgumentLoc *getTemplateArgs() const {
return getExplicitTemplateArgs()->getTemplateArgs();
}
/// \brief Retrieve the number of template arguments provided as
/// part of this template-id.
unsigned getNumTemplateArgs() const {
return getExplicitTemplateArgs()->NumTemplateArgs;
}
/// \brief Retrieve the location of the right angle bracket
/// following the template arguments ('>').
SourceLocation getRAngleLoc() const {
return getExplicitTemplateArgs()->RAngleLoc;
}
virtual SourceRange getSourceRange() const {
SourceRange Range = Base->getSourceRange();
if (hasExplicitTemplateArgs())
Range.setEnd(getRAngleLoc());
else
Range.setEnd(MemberLoc);
return Range;
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == UnresolvedMemberExprClass;
}
static bool classof(const UnresolvedMemberExpr *) { return true; }
// Iterators
virtual child_iterator child_begin();

View File

@ -47,6 +47,59 @@ class ASTRecordLayout {
// FieldCount - Number of fields.
unsigned FieldCount;
public:
/// PrimaryBaseInfo - Contains info about a primary base.
struct PrimaryBaseInfo {
PrimaryBaseInfo() {}
PrimaryBaseInfo(const CXXRecordDecl *Base, bool IsVirtual)
: Value(Base, IsVirtual) {}
/// Value - Points to the primary base. The single-bit value
/// will be non-zero when the primary base is virtual.
llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> Value;
/// getBase - Returns the primary base.
const CXXRecordDecl *getBase() const { return Value.getPointer(); }
/// isVirtual - Returns whether the primary base is virtual or not.
bool isVirtual() const { return Value.getInt(); }
friend bool operator==(const PrimaryBaseInfo &X, const PrimaryBaseInfo &Y) {
return X.Value == Y.Value;
}
};
/// primary_base_info_iterator - An iterator for iterating the primary base
/// class chain.
class primary_base_info_iterator {
/// Current - The current base class info.
PrimaryBaseInfo Current;
public:
primary_base_info_iterator() {}
primary_base_info_iterator(PrimaryBaseInfo Info) : Current(Info) {}
const PrimaryBaseInfo &operator*() const { return Current; }
primary_base_info_iterator& operator++() {
const CXXRecordDecl *RD = Current.getBase();
Current = RD->getASTContext().getASTRecordLayout(RD).getPrimaryBaseInfo();
return *this;
}
friend bool operator==(const primary_base_info_iterator &X,
const primary_base_info_iterator &Y) {
return X.Current == Y.Current;
}
friend bool operator!=(const primary_base_info_iterator &X,
const primary_base_info_iterator &Y) {
return !(X == Y);
}
};
private:
/// CXXRecordLayoutInfo - Contains C++ specific layout information.
struct CXXRecordLayoutInfo {
/// NonVirtualSize - The non-virtual size (in bits) of an object, which is
/// the size of the object without virtual bases.
@ -56,11 +109,9 @@ class ASTRecordLayout {
/// which is the alignment of the object without virtual bases.
uint64_t NonVirtualAlign;
/// PrimaryBase - The primary base for our vtable.
const CXXRecordDecl *PrimaryBase;
/// PrimaryBase - Wether or not the primary base was a virtual base.
bool PrimaryBaseWasVirtual;
/// PrimaryBase - The primary base info for this record.
PrimaryBaseInfo PrimaryBase;
/// BaseOffsets - Contains a map from base classes to their offset.
/// FIXME: This should really use a SmallPtrMap, once we have one in LLVM :)
llvm::DenseMap<const CXXRecordDecl *, uint64_t> BaseOffsets;
@ -68,6 +119,13 @@ class ASTRecordLayout {
/// VBaseOffsets - Contains a map from vbase classes to their offset.
/// FIXME: This should really use a SmallPtrMap, once we have one in LLVM :)
llvm::DenseMap<const CXXRecordDecl *, uint64_t> VBaseOffsets;
/// KeyFunction - The key function, according to the Itanium C++ ABI,
/// section 5.2.3:
///
/// ...the first non-pure virtual function that is not inline at the point
/// of class definition.
const CXXMethodDecl *KeyFunction;
};
/// CXXInfo - If the record layout is for a C++ record, this will have
@ -92,11 +150,12 @@ class ASTRecordLayout {
ASTRecordLayout(uint64_t size, unsigned alignment, uint64_t datasize,
const uint64_t *fieldoffsets, unsigned fieldcount,
uint64_t nonvirtualsize, unsigned nonvirtualalign,
const CXXRecordDecl *PB, bool PBVirtual,
const PrimaryBaseInfo &PrimaryBase,
const std::pair<const CXXRecordDecl *, uint64_t> *bases,
unsigned numbases,
const std::pair<const CXXRecordDecl *, uint64_t> *vbases,
unsigned numvbases)
unsigned numvbases,
const CXXMethodDecl *KeyFunction)
: Size(size), DataSize(datasize), FieldOffsets(0), Alignment(alignment),
FieldCount(fieldcount), CXXInfo(new CXXRecordLayoutInfo) {
if (FieldCount > 0) {
@ -105,14 +164,14 @@ class ASTRecordLayout {
FieldOffsets[i] = fieldoffsets[i];
}
CXXInfo->PrimaryBase = PB;
CXXInfo->PrimaryBaseWasVirtual = PBVirtual;
CXXInfo->PrimaryBase = PrimaryBase;
CXXInfo->NonVirtualSize = nonvirtualsize;
CXXInfo->NonVirtualAlign = nonvirtualalign;
for (unsigned i = 0; i != numbases; ++i)
CXXInfo->BaseOffsets[bases[i].first] = bases[i].second;
for (unsigned i = 0; i != numvbases; ++i)
CXXInfo->VBaseOffsets[vbases[i].first] = vbases[i].second;
CXXInfo->KeyFunction = KeyFunction;
}
~ASTRecordLayout() {
@ -162,17 +221,21 @@ class ASTRecordLayout {
return CXXInfo->NonVirtualAlign;
}
/// getPrimaryBase - Get the primary base.
const CXXRecordDecl *getPrimaryBase() const {
/// getPrimaryBaseInfo - Get the primary base info.
const PrimaryBaseInfo &getPrimaryBaseInfo() const {
assert(CXXInfo && "Record layout does not have C++ specific info!");
return CXXInfo->PrimaryBase;
}
/// getPrimaryBaseWasVirtual - Indicates if the primary base was virtual.
bool getPrimaryBaseWasVirtual() const {
assert(CXXInfo && "Record layout does not have C++ specific info!");
return CXXInfo->PrimaryBaseWasVirtual;
// FIXME: Migrate off of this function and use getPrimaryBaseInfo directly.
const CXXRecordDecl *getPrimaryBase() const {
return getPrimaryBaseInfo().getBase();
}
// FIXME: Migrate off of this function and use getPrimaryBaseInfo directly.
bool getPrimaryBaseWasVirtual() const {
return getPrimaryBaseInfo().isVirtual();
}
/// getBaseClassOffset - Get the offset, in bits, for the given base class.
@ -190,6 +253,25 @@ class ASTRecordLayout {
return CXXInfo->VBaseOffsets[VBase];
}
/// getKeyFunction - Get the key function.
const CXXMethodDecl *getKeyFunction() const {
assert(CXXInfo && "Record layout does not have C++ specific info!");
return CXXInfo->KeyFunction;
}
primary_base_info_iterator primary_base_begin() const {
assert(CXXInfo && "Record layout does not have C++ specific info!");
return primary_base_info_iterator(getPrimaryBaseInfo());
}
primary_base_info_iterator primary_base_end() const {
assert(CXXInfo && "Record layout does not have C++ specific info!");
return primary_base_info_iterator();
}
};
} // end namespace clang

View File

@ -15,6 +15,7 @@
#define LLVM_CLANG_AST_REDECLARABLE_H
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/Support/Casting.h"
#include <iterator>
namespace clang {
@ -91,6 +92,11 @@ class Redeclarable {
return D;
}
/// \brief Returns the most recent (re)declaration of this declaration.
decl_type *getMostRecentDeclaration() {
return getFirstDeclaration()->RedeclLink.getNext();
}
/// \brief Returns the most recent (re)declaration of this declaration.
const decl_type *getMostRecentDeclaration() const {
return getFirstDeclaration()->RedeclLink.getNext();
@ -102,8 +108,11 @@ class Redeclarable {
decl_type *First;
if (PrevDecl) {
// Point to previous.
RedeclLink = PreviousDeclLink(PrevDecl);
// Point to previous. Make sure that this is actually the most recent
// redeclaration, or we can build invalid chains. If the most recent
// redeclaration is invalid, it won't be PrevDecl, but we want it anyway.
RedeclLink = PreviousDeclLink(llvm::cast<decl_type>(
PrevDecl->getMostRecentDeclaration()));
First = PrevDecl->getFirstDeclaration();
assert(First->RedeclLink.NextIsLatest() && "Expected first");
} else {

View File

@ -171,6 +171,14 @@ class Stmt {
}
virtual ~Stmt() {}
#ifndef NDEBUG
/// \brief True if this statement's refcount is in a valid state.
/// Should be used only in assertions.
bool isRetained() const {
return (RefCount >= 1);
}
#endif
/// \brief Destroy the current statement and its children.
void Destroy(ASTContext &Ctx) {
assert(RefCount >= 1);
@ -203,7 +211,7 @@ class Stmt {
// global temp stats (until we have a per-module visitor)
static void addStmtClass(const StmtClass s);
static bool CollectingStats(bool enable=false);
static bool CollectingStats(bool Enable = false);
static void PrintStats();
/// dump - This does a local dump of the specified AST fragment. It dumps the
@ -604,22 +612,36 @@ class LabelStmt : public Stmt {
class IfStmt : public Stmt {
enum { COND, THEN, ELSE, END_EXPR };
Stmt* SubExprs[END_EXPR];
/// \brief If non-NULL, the declaration in the "if" statement.
VarDecl *Var;
SourceLocation IfLoc;
SourceLocation ElseLoc;
public:
IfStmt(SourceLocation IL, Expr *cond, Stmt *then,
IfStmt(SourceLocation IL, VarDecl *Var, Expr *cond, Stmt *then,
SourceLocation EL = SourceLocation(), Stmt *elsev = 0)
: Stmt(IfStmtClass) {
: Stmt(IfStmtClass), Var(Var), IfLoc(IL), ElseLoc(EL) {
SubExprs[COND] = reinterpret_cast<Stmt*>(cond);
SubExprs[THEN] = then;
SubExprs[ELSE] = elsev;
IfLoc = IL;
ElseLoc = EL;
}
/// \brief Build an empty if/then/else statement
explicit IfStmt(EmptyShell Empty) : Stmt(IfStmtClass, Empty) { }
/// \brief Retrieve the variable declared in this "if" statement, if any.
///
/// In the following example, "x" is the condition variable.
/// \code
/// if (int x = foo()) {
/// printf("x is %d", x);
/// }
/// \endcode
VarDecl *getConditionVariable() const { return Var; }
void setConditionVariable(VarDecl *V) { Var = V; }
const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);}
void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt *>(E); }
const Stmt *getThen() const { return SubExprs[THEN]; }
@ -658,6 +680,7 @@ class IfStmt : public Stmt {
class SwitchStmt : public Stmt {
enum { COND, BODY, END_EXPR };
Stmt* SubExprs[END_EXPR];
VarDecl *Var;
// This points to a linked list of case and default statements.
SwitchCase *FirstCase;
SourceLocation SwitchLoc;
@ -666,14 +689,28 @@ class SwitchStmt : public Stmt {
virtual void DoDestroy(ASTContext &Ctx);
public:
SwitchStmt(Expr *cond) : Stmt(SwitchStmtClass), FirstCase(0) {
SubExprs[COND] = reinterpret_cast<Stmt*>(cond);
SubExprs[BODY] = NULL;
}
SwitchStmt(VarDecl *Var, Expr *cond)
: Stmt(SwitchStmtClass), Var(Var), FirstCase(0)
{
SubExprs[COND] = reinterpret_cast<Stmt*>(cond);
SubExprs[BODY] = NULL;
}
/// \brief Build a empty switch statement.
explicit SwitchStmt(EmptyShell Empty) : Stmt(SwitchStmtClass, Empty) { }
/// \brief Retrieve the variable declared in this "switch" statement, if any.
///
/// In the following example, "x" is the condition variable.
/// \code
/// switch (int x = foo()) {
/// case 0: break;
/// // ...
/// }
/// \endcode
VarDecl *getConditionVariable() const { return Var; }
void setConditionVariable(VarDecl *V) { Var = V; }
const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);}
const Stmt *getBody() const { return SubExprs[BODY]; }
const SwitchCase *getSwitchCaseList() const { return FirstCase; }
@ -721,10 +758,13 @@ class SwitchStmt : public Stmt {
///
class WhileStmt : public Stmt {
enum { COND, BODY, END_EXPR };
VarDecl *Var;
Stmt* SubExprs[END_EXPR];
SourceLocation WhileLoc;
public:
WhileStmt(Expr *cond, Stmt *body, SourceLocation WL) : Stmt(WhileStmtClass) {
WhileStmt(VarDecl *Var, Expr *cond, Stmt *body, SourceLocation WL)
: Stmt(WhileStmtClass), Var(Var)
{
SubExprs[COND] = reinterpret_cast<Stmt*>(cond);
SubExprs[BODY] = body;
WhileLoc = WL;
@ -733,6 +773,17 @@ class WhileStmt : public Stmt {
/// \brief Build an empty while statement.
explicit WhileStmt(EmptyShell Empty) : Stmt(WhileStmtClass, Empty) { }
/// \brief Retrieve the variable declared in this "while" statement, if any.
///
/// In the following example, "x" is the condition variable.
/// \code
/// while (int x = random()) {
/// // ...
/// }
/// \endcode
VarDecl *getConditionVariable() const { return Var; }
void setConditionVariable(VarDecl *V) { Var = V; }
Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); }
const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);}
void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt*>(E); }
@ -812,26 +863,38 @@ class DoStmt : public Stmt {
class ForStmt : public Stmt {
enum { INIT, COND, INC, BODY, END_EXPR };
Stmt* SubExprs[END_EXPR]; // SubExprs[INIT] is an expression or declstmt.
VarDecl *CondVar;
SourceLocation ForLoc;
SourceLocation LParenLoc, RParenLoc;
public:
ForStmt(Stmt *Init, Expr *Cond, Expr *Inc, Stmt *Body, SourceLocation FL,
SourceLocation LP, SourceLocation RP)
: Stmt(ForStmtClass) {
ForStmt(Stmt *Init, Expr *Cond, VarDecl *CondVar, Expr *Inc, Stmt *Body,
SourceLocation FL, SourceLocation LP, SourceLocation RP)
: Stmt(ForStmtClass), CondVar(CondVar), ForLoc(FL), LParenLoc(LP),
RParenLoc(RP)
{
SubExprs[INIT] = Init;
SubExprs[COND] = reinterpret_cast<Stmt*>(Cond);
SubExprs[INC] = reinterpret_cast<Stmt*>(Inc);
SubExprs[BODY] = Body;
ForLoc = FL;
LParenLoc = LP;
RParenLoc = RP;
}
/// \brief Build an empty for statement.
explicit ForStmt(EmptyShell Empty) : Stmt(ForStmtClass, Empty) { }
Stmt *getInit() { return SubExprs[INIT]; }
/// \brief Retrieve the variable declared in this "for" statement, if any.
///
/// In the following example, "y" is the condition variable.
/// \code
/// for (int x = random(); int y = mangle(x); ++x) {
/// // ...
/// }
/// \endcode
VarDecl *getConditionVariable() const { return CondVar; }
void setConditionVariable(VarDecl *V) { CondVar = V; }
Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); }
Expr *getInc() { return reinterpret_cast<Expr*>(SubExprs[INC]); }
Stmt *getBody() { return SubExprs[BODY]; }

View File

@ -42,9 +42,9 @@ class CXXCatchStmt : public Stmt {
}
SourceLocation getCatchLoc() const { return CatchLoc; }
VarDecl *getExceptionDecl() { return ExceptionDecl; }
QualType getCaughtType();
Stmt *getHandlerBlock() { return HandlerBlock; }
VarDecl *getExceptionDecl() const { return ExceptionDecl; }
QualType getCaughtType() const;
Stmt *getHandlerBlock() const { return HandlerBlock; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXCatchStmtClass;

View File

@ -121,20 +121,19 @@ EXPR(CXXThisExpr , Expr)
EXPR(CXXThrowExpr , Expr)
EXPR(CXXDefaultArgExpr , Expr)
EXPR(CXXZeroInitValueExpr , Expr)
EXPR(CXXConditionDeclExpr , DeclRefExpr)
EXPR(CXXNewExpr , Expr)
EXPR(CXXDeleteExpr , Expr)
EXPR(CXXPseudoDestructorExpr, Expr)
EXPR(UnresolvedFunctionNameExpr , Expr)
EXPR(UnresolvedLookupExpr , Expr)
EXPR(UnaryTypeTraitExpr , Expr)
EXPR(UnresolvedDeclRefExpr , Expr)
EXPR(TemplateIdRefExpr , Expr)
EXPR(DependentScopeDeclRefExpr , Expr)
EXPR(CXXConstructExpr , Expr)
EXPR(CXXBindTemporaryExpr , Expr)
EXPR(CXXExprWithTemporaries , Expr)
EXPR(CXXTemporaryObjectExpr , CXXConstructExpr)
EXPR(CXXUnresolvedConstructExpr, Expr)
EXPR(CXXUnresolvedMemberExpr, Expr)
EXPR(CXXDependentScopeMemberExpr, Expr)
EXPR(UnresolvedMemberExpr , Expr)
// Obj-C Expressions.
EXPR(ObjCStringLiteral , Expr)

View File

@ -16,6 +16,7 @@
#define LLVM_CLANG_AST_TEMPLATEBASE_H
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/ErrorHandling.h"
#include "clang/AST/Type.h"
#include "clang/AST/TemplateName.h"
@ -437,6 +438,41 @@ class TemplateArgumentLoc {
}
};
/// A convenient class for passing around template argument
/// information. Designed to be passed by reference.
class TemplateArgumentListInfo {
llvm::SmallVector<TemplateArgumentLoc, 8> Arguments;
SourceLocation LAngleLoc;
SourceLocation RAngleLoc;
public:
TemplateArgumentListInfo() {}
TemplateArgumentListInfo(SourceLocation LAngleLoc,
SourceLocation RAngleLoc)
: LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {}
SourceLocation getLAngleLoc() const { return LAngleLoc; }
SourceLocation getRAngleLoc() const { return RAngleLoc; }
void setLAngleLoc(SourceLocation Loc) { LAngleLoc = Loc; }
void setRAngleLoc(SourceLocation Loc) { RAngleLoc = Loc; }
unsigned size() const { return Arguments.size(); }
const TemplateArgumentLoc *getArgumentArray() const {
return Arguments.data();
}
const TemplateArgumentLoc &operator[](unsigned I) const {
return Arguments[I];
}
void addArgument(const TemplateArgumentLoc &Loc) {
Arguments.push_back(Loc);
}
};
}
#endif

View File

@ -82,6 +82,7 @@ namespace clang {
class StmtIteratorBase;
class TemplateArgument;
class TemplateArgumentLoc;
class TemplateArgumentListInfo;
class QualifiedNameType;
struct PrintingPolicy;
@ -859,6 +860,7 @@ class Type {
bool isObjCQualifiedClassType() const; // Class<foo>
bool isObjCIdType() const; // id
bool isObjCClassType() const; // Class
bool isObjCSelType() const; // Class
bool isObjCBuiltinType() const; // 'id' or 'Class'
bool isTemplateTypeParmType() const; // C++ template type parameter
bool isNullPtrType() const; // C++0x nullptr_t
@ -1000,7 +1002,8 @@ class BuiltinType : public Type {
UndeducedAuto, // In C++0x, this represents the type of an auto variable
// that has not been deduced yet.
ObjCId, // This represents the ObjC 'id' type.
ObjCClass // This represents the ObjC 'Class' type.
ObjCClass, // This represents the ObjC 'Class' type.
ObjCSel // This represents the ObjC 'SEL' type.
};
private:
Kind TypeKind;
@ -1457,21 +1460,27 @@ class VariableArrayType : public ArrayType {
/// DependentSizedArrayType - This type represents an array type in
/// C++ whose size is a value-dependent expression. For example:
/// @code
///
/// \code
/// template<typename T, int Size>
/// class array {
/// T data[Size];
/// };
/// @endcode
/// \endcode
///
/// For these types, we won't actually know what the array bound is
/// until template instantiation occurs, at which point this will
/// become either a ConstantArrayType or a VariableArrayType.
class DependentSizedArrayType : public ArrayType {
ASTContext &Context;
/// SizeExpr - An assignment expression that will instantiate to the
/// \brief An assignment expression that will instantiate to the
/// size of the array.
///
/// The expression itself might be NULL, in which case the array
/// type will have its size deduced from an initializer.
Stmt *SizeExpr;
/// Brackets - The left and right array brackets.
SourceRange Brackets;
@ -2272,6 +2281,8 @@ class TemplateSpecializationType
static bool anyDependentTemplateArguments(const TemplateArgumentLoc *Args,
unsigned NumArgs);
static bool anyDependentTemplateArguments(const TemplateArgumentListInfo &);
/// \brief Print a template argument list, including the '<' and '>'
/// enclosing the template arguments.
static std::string PrintTemplateArgumentList(const TemplateArgument *Args,
@ -2282,6 +2293,9 @@ class TemplateSpecializationType
unsigned NumArgs,
const PrintingPolicy &Policy);
static std::string PrintTemplateArgumentList(const TemplateArgumentListInfo &,
const PrintingPolicy &Policy);
typedef const TemplateArgument * iterator;
iterator begin() const { return getArgs(); }
@ -2534,6 +2548,7 @@ class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode {
return getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCClass) &&
!Protocols.size();
}
/// isObjCQualifiedIdType - true for "id <p>".
bool isObjCQualifiedIdType() const {
return getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCId) &&
@ -2881,8 +2896,13 @@ inline bool Type::isObjCClassType() const {
return OPT->isObjCClassType();
return false;
}
inline bool Type::isObjCSelType() const {
if (const PointerType *OPT = getAs<PointerType>())
return OPT->getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCSel);
return false;
}
inline bool Type::isObjCBuiltinType() const {
return isObjCIdType() || isObjCClassType();
return isObjCIdType() || isObjCClassType() || isObjCSelType();
}
inline bool Type::isTemplateTypeParmType() const {
return isa<TemplateTypeParmType>(CanonicalType);

View File

@ -23,6 +23,7 @@ namespace clang {
class Stmt;
class DeclRefExpr;
class SourceManager;
class AnalysisContext;
struct LiveVariables_ValueTypes {
@ -39,8 +40,9 @@ struct LiveVariables_ValueTypes {
struct AnalysisDataTy : public StmtDeclBitVector_Types::AnalysisDataTy {
ObserverTy* Observer;
ValTy AlwaysLive;
AnalysisContext *AC;
AnalysisDataTy() : Observer(NULL) {}
AnalysisDataTy() : Observer(NULL), AC(NULL) {}
};
//===-----------------------------------------------------===//
@ -66,7 +68,7 @@ class LiveVariables : public DataflowValues<LiveVariables_ValueTypes,
public:
typedef LiveVariables_ValueTypes::ObserverTy ObserverTy;
LiveVariables(ASTContext& Ctx, CFG& cfg);
LiveVariables(AnalysisContext &AC);
/// IsLive - Return true if a variable is live at beginning of a
/// specified block.

View File

@ -14,31 +14,24 @@
#ifndef LLVM_CLANG_PATH_DIAGNOSTIC_H
#define LLVM_CLANG_PATH_DIAGNOSTIC_H
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Diagnostic.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/FoldingSet.h"
#include <vector>
#include <deque>
#include <iterator>
#include <string>
#include <algorithm>
#include <vector>
namespace clang {
class Stmt;
class Decl;
class Preprocessor;
class SourceManager;
class Stmt;
//===----------------------------------------------------------------------===//
// High-level interface for handlers of path-sensitive diagnostics.
//===----------------------------------------------------------------------===//
class PathDiagnostic;
class Stmt;
class Decl;
class Preprocessor;
class PathDiagnosticClient : public DiagnosticClient {
public:

View File

@ -19,6 +19,7 @@
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/Allocator.h"
namespace clang {
@ -38,17 +39,26 @@ class AnalysisContext {
CFG *cfg;
LiveVariables *liveness;
ParentMap *PM;
llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
llvm::BumpPtrAllocator A;
public:
AnalysisContext(const Decl *d) : D(d), cfg(0), liveness(0), PM(0) {}
AnalysisContext(const Decl *d) : D(d), cfg(0), liveness(0), PM(0),
ReferencedBlockVars(0) {}
~AnalysisContext();
ASTContext &getASTContext() { return D->getASTContext(); }
const Decl *getDecl() { return D; }
Stmt *getBody();
CFG *getCFG();
ParentMap &getParentMap();
LiveVariables *getLiveVariables();
typedef const VarDecl * const * referenced_decls_iterator;
std::pair<referenced_decls_iterator, referenced_decls_iterator>
getReferencedBlockVars(const BlockDecl *BD);
/// Return the ImplicitParamDecl* associated with 'self' if this
/// AnalysisContext wraps an ObjCMethodDecl. Returns NULL otherwise.
const ImplicitParamDecl *getSelfDecl() const;

View File

@ -309,32 +309,33 @@ class BugReporter {
void EmitReport(BugReport *R);
void EmitBasicReport(const char* BugName, const char* BugStr,
void EmitBasicReport(llvm::StringRef BugName, llvm::StringRef BugStr,
SourceLocation Loc,
SourceRange* RangeBeg, unsigned NumRanges);
void EmitBasicReport(const char* BugName, const char* BugCategory,
const char* BugStr, SourceLocation Loc,
void EmitBasicReport(llvm::StringRef BugName, llvm::StringRef BugCategory,
llvm::StringRef BugStr, SourceLocation Loc,
SourceRange* RangeBeg, unsigned NumRanges);
void EmitBasicReport(const char* BugName, const char* BugStr,
void EmitBasicReport(llvm::StringRef BugName, llvm::StringRef BugStr,
SourceLocation Loc) {
EmitBasicReport(BugName, BugStr, Loc, 0, 0);
}
void EmitBasicReport(const char* BugName, const char* BugCategory,
const char* BugStr, SourceLocation Loc) {
void EmitBasicReport(llvm::StringRef BugName, llvm::StringRef BugCategory,
llvm::StringRef BugStr, SourceLocation Loc) {
EmitBasicReport(BugName, BugCategory, BugStr, Loc, 0, 0);
}
void EmitBasicReport(const char* BugName, const char* BugStr,
void EmitBasicReport(llvm::StringRef BugName, llvm::StringRef BugStr,
SourceLocation Loc, SourceRange R) {
EmitBasicReport(BugName, BugStr, Loc, &R, 1);
}
void EmitBasicReport(const char* BugName, const char* Category,
const char* BugStr, SourceLocation Loc, SourceRange R) {
void EmitBasicReport(llvm::StringRef BugName, llvm::StringRef Category,
llvm::StringRef BugStr, SourceLocation Loc,
SourceRange R) {
EmitBasicReport(BugName, Category, BugStr, Loc, &R, 1);
}
@ -432,7 +433,7 @@ class DiagBugReport : public RangedBugReport {
std::list<std::string> Strs;
FullSourceLoc L;
public:
DiagBugReport(BugType& D, const char* desc, FullSourceLoc l) :
DiagBugReport(BugType& D, llvm::StringRef desc, FullSourceLoc l) :
RangedBugReport(D, desc, 0), L(l) {}
virtual ~DiagBugReport() {}

View File

@ -34,13 +34,13 @@ class BugType {
friend class BugReporter;
bool SuppressonSink;
public:
BugType(const char *name, const char* cat)
BugType(llvm::StringRef name, llvm::StringRef cat)
: Name(name), Category(cat), SuppressonSink(false) {}
virtual ~BugType();
// FIXME: Should these be made strings as well?
const std::string& getName() const { return Name; }
const std::string& getCategory() const { return Category; }
llvm::StringRef getName() const { return Name; }
llvm::StringRef getCategory() const { return Category; }
/// isSuppressOnSink - Returns true if bug reports associated with this bug
/// type should be suppressed if the end node of the report is post-dominated
@ -60,33 +60,15 @@ class BugType {
};
class BuiltinBug : public BugType {
GRExprEngine *Eng;
protected:
const std::string desc;
public:
BuiltinBug(const char *name, const char *description)
: BugType(name, "Logic error"), Eng(0), desc(description) {}
: BugType(name, "Logic error"), desc(description) {}
BuiltinBug(const char *name)
: BugType(name, "Logic error"), Eng(0), desc(name) {}
: BugType(name, "Logic error"), desc(name) {}
BuiltinBug(GRExprEngine *eng, const char* n, const char* d)
: BugType(n, "Logic error"), Eng(eng), desc(d) {}
BuiltinBug(GRExprEngine *eng, const char* n)
: BugType(n, "Logic error"), Eng(eng), desc(n) {}
const std::string &getDescription() const { return desc; }
virtual void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {}
void FlushReports(BugReporter& BR) { FlushReportsImpl(BR, *Eng); }
virtual void registerInitialVisitors(BugReporterContext& BRC,
const ExplodedNode* N,
BuiltinBugReport *R) {}
template <typename ITER> void Emit(BugReporter& BR, ITER I, ITER E);
llvm::StringRef getDescription() const { return desc; }
};
} // end clang namespace

View File

@ -40,24 +40,35 @@ class CheckerContext {
SaveAndRestore<ProgramPoint::Kind> OldPointKind;
SaveOr OldHasGen;
const GRState *state;
const Stmt *statement;
const unsigned size;
bool DoneEvaluating; // FIXME: This is not a permanent API change.
public:
CheckerContext(ExplodedNodeSet &dst, GRStmtNodeBuilder &builder,
GRExprEngine &eng, ExplodedNode *pred,
const void *tag, ProgramPoint::Kind K,
const GRState *st = 0)
const Stmt *stmt = 0, const GRState *st = 0)
: Dst(dst), B(builder), Eng(eng), Pred(pred),
OldSink(B.BuildSinks),
OldTag(B.Tag, tag),
OldPointKind(B.PointKind, K),
OldHasGen(B.HasGeneratedNode),
state(st) {}
state(st), statement(stmt), size(Dst.size()),
DoneEvaluating(false) {}
~CheckerContext() {
if (!B.BuildSinks && !B.HasGeneratedNode)
Dst.Add(Pred);
~CheckerContext();
// FIXME: This were added to support CallAndMessageChecker to indicating
// to GRExprEngine to "stop evaluating" a message expression under certain
// cases. This is *not* meant to be a permanent API change, and was added
// to aid in the transition of removing logic for checks from GRExprEngine.
void setDoneEvaluating() {
DoneEvaluating = true;
}
bool isDoneEvaluating() const {
return DoneEvaluating;
}
ConstraintManager &getConstraintManager() {
return Eng.getConstraintManager();
}
@ -83,27 +94,70 @@ class CheckerContext {
return getBugReporter().getSourceManager();
}
ExplodedNode *GenerateNode(const Stmt *S, bool markAsSink = false) {
return GenerateNode(S, getState(), markAsSink);
ValueManager &getValueManager() {
return Eng.getValueManager();
}
ExplodedNode *GenerateNode(const Stmt* S, const GRState *state,
bool markAsSink = false) {
ExplodedNode *node = B.generateNode(S, state, Pred);
ExplodedNode *GenerateNode(bool autoTransition = true) {
assert(statement && "Only transitions with statements currently supported");
ExplodedNode *N = GenerateNodeImpl(statement, getState(), false);
if (N && autoTransition)
Dst.Add(N);
return N;
}
ExplodedNode *GenerateNode(const Stmt *stmt, const GRState *state,
bool autoTransition = true) {
assert(state);
ExplodedNode *N = GenerateNodeImpl(stmt, state, false);
if (N && autoTransition)
addTransition(N);
return N;
}
if (markAsSink && node)
node->markAsSink();
ExplodedNode *GenerateNode(const GRState *state, bool autoTransition = true) {
assert(statement && "Only transitions with statements currently supported");
ExplodedNode *N = GenerateNodeImpl(statement, state, false);
if (N && autoTransition)
addTransition(N);
return N;
}
return node;
ExplodedNode *GenerateSink(const Stmt *stmt, const GRState *state = 0) {
return GenerateNodeImpl(stmt, state ? state : getState(), true);
}
ExplodedNode *GenerateSink(const GRState *state = 0) {
assert(statement && "Only transitions with statements currently supported");
return GenerateNodeImpl(statement, state ? state : getState(), true);
}
void addTransition(ExplodedNode *node) {
Dst.Add(node);
}
void addTransition(const GRState *state) {
assert(state);
if (state != getState() ||
(state && state != B.GetState(Pred)))
GenerateNode(state, true);
else
Dst.Add(Pred);
}
void EmitReport(BugReport *R) {
Eng.getBugReporter().EmitReport(R);
}
private:
ExplodedNode *GenerateNodeImpl(const Stmt* stmt, const GRState *state,
bool markAsSink) {
ExplodedNode *node = B.generateNode(stmt, state, Pred);
if (markAsSink && node)
node->markAsSink();
return node;
}
};
class Checker {
@ -111,18 +165,19 @@ class Checker {
friend class GRExprEngine;
// FIXME: Remove the 'tag' option.
void GR_Visit(ExplodedNodeSet &Dst,
bool GR_Visit(ExplodedNodeSet &Dst,
GRStmtNodeBuilder &Builder,
GRExprEngine &Eng,
const Stmt *S,
ExplodedNode *Pred, void *tag, bool isPrevisit) {
CheckerContext C(Dst, Builder, Eng, Pred, tag,
isPrevisit ? ProgramPoint::PreStmtKind :
ProgramPoint::PostStmtKind);
ProgramPoint::PostStmtKind, S);
if (isPrevisit)
_PreVisit(C, S);
else
_PostVisit(C, S);
return C.isDoneEvaluating();
}
// FIXME: Remove the 'tag' option.
@ -134,7 +189,7 @@ class Checker {
bool isPrevisit) {
CheckerContext C(Dst, Builder, Eng, Pred, tag,
isPrevisit ? ProgramPoint::PreStmtKind :
ProgramPoint::PostStmtKind);
ProgramPoint::PostStmtKind, StoreE);
assert(isPrevisit && "Only previsit supported for now.");
PreVisitBind(C, AssignE, StoreE, location, val);
}
@ -149,7 +204,7 @@ class Checker {
void *tag, bool isLoad) {
CheckerContext C(Dst, Builder, Eng, Pred, tag,
isLoad ? ProgramPoint::PreLoadKind :
ProgramPoint::PreStoreKind, state);
ProgramPoint::PreStoreKind, S, state);
VisitLocation(C, S, location);
}
@ -157,12 +212,12 @@ class Checker {
GRExprEngine &Eng, const Stmt *S, ExplodedNode *Pred,
SymbolReaper &SymReaper, void *tag) {
CheckerContext C(Dst, Builder, Eng, Pred, tag,
ProgramPoint::PostPurgeDeadSymbolsKind, Pred->getState());
ProgramPoint::PostPurgeDeadSymbolsKind, S);
EvalDeadSymbols(C, S, SymReaper);
}
public:
virtual ~Checker() {}
virtual ~Checker();
virtual void _PreVisit(CheckerContext &C, const Stmt *S) {}
virtual void _PostVisit(CheckerContext &C, const Stmt *S) {}
virtual void VisitLocation(CheckerContext &C, const Stmt *S, SVal location) {}
@ -172,6 +227,10 @@ class Checker {
SymbolReaper &SymReaper) {}
virtual void EvalEndPath(GREndPathNodeBuilder &B, void *tag,
GRExprEngine &Eng) {}
virtual void VisitBranchCondition(GRBranchNodeBuilder &Builder,
GRExprEngine &Eng,
Stmt *Condition, void *tag) {}
};
} // end clang namespace

View File

@ -11,7 +11,14 @@
//
//===---------------------------------------------------------------------===//
#ifdef PREVISIT
#ifndef PREVISIT
#define PREVISIT(NODE)
#endif
#ifndef POSTVISIT
#define POSTVISIT(NODE)
#endif
PREVISIT(ArraySubscriptExpr)
PREVISIT(BinaryOperator)
PREVISIT(CallExpr)
@ -19,11 +26,10 @@ PREVISIT(CastExpr)
PREVISIT(DeclStmt)
PREVISIT(ObjCMessageExpr)
PREVISIT(ReturnStmt)
#undef PREVISIT
#endif
#ifdef POSTVISIT
POSTVISIT(CallExpr)
#undef POSTVISIT
#endif
POSTVISIT(BlockExpr)
POSTVISIT(BinaryOperator)
#undef PREVISIT
#undef POSTVISIT

View File

@ -1,33 +0,0 @@
//===--- UndefinedAssignmentChecker.h ---------------------------*- C++ -*--==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This defines UndefinedAssginmentChecker, a builtin check in GRExprEngine that
// checks for assigning undefined values.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_UNDEFASSIGNMENTCHECKER
#define LLVM_CLANG_UNDEFASSIGNMENTCHECKER
#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
namespace clang {
class UndefinedAssignmentChecker
: public CheckerVisitor<UndefinedAssignmentChecker> {
BugType *BT;
public:
UndefinedAssignmentChecker() : BT(0) {}
static void *getTag();
virtual void PreVisitBind(CheckerContext &C, const Stmt *AssignE,
const Stmt *StoreE, SVal location,
SVal val);
};
}
#endif

View File

@ -352,10 +352,16 @@ class ExplodedNodeSet {
typedef ImplTy::iterator iterator;
typedef ImplTy::const_iterator const_iterator;
inline unsigned size() const { return Impl.size(); }
inline bool empty() const { return Impl.empty(); }
unsigned size() const { return Impl.size(); }
bool empty() const { return Impl.empty(); }
inline void clear() { Impl.clear(); }
void clear() { Impl.clear(); }
void insert(const ExplodedNodeSet &S) {
if (empty())
Impl = S.Impl;
else
Impl.insert(S.begin(), S.end());
}
inline iterator begin() { return Impl.begin(); }
inline iterator end() { return Impl.end(); }

View File

@ -215,7 +215,7 @@ class GRStmtNodeBuilder {
void setAuditor(GRAuditor* A) { Auditor = A; }
const GRState* GetState(ExplodedNode* Pred) const {
if ((ExplodedNode*) Pred == getBasePredecessor())
if (Pred == getBasePredecessor())
return CleanedState;
else
return Pred->getState();
@ -405,6 +405,8 @@ class GREndPathNodeBuilder {
GRCoreEngine& Eng;
CFGBlock& B;
ExplodedNode* Pred;
public:
bool HasGeneratedNode;
public:

View File

@ -87,55 +87,6 @@ class GRExprEngine : public GRSubEngine {
// destructor is called before the rest of the GRExprEngine is destroyed.
GRBugReporter BR;
public:
typedef llvm::SmallPtrSet<ExplodedNode*,2> ErrorNodes;
typedef llvm::DenseMap<ExplodedNode*, Expr*> UndefArgsTy;
/// NilReceiverStructRetExplicit - Nodes in the ExplodedGraph that resulted
/// from [x ...] with 'x' definitely being nil and the result was a 'struct'
// (an undefined value).
ErrorNodes NilReceiverStructRetExplicit;
/// NilReceiverStructRetImplicit - Nodes in the ExplodedGraph that resulted
/// from [x ...] with 'x' possibly being nil and the result was a 'struct'
// (an undefined value).
ErrorNodes NilReceiverStructRetImplicit;
/// NilReceiverLargerThanVoidPtrRetExplicit - Nodes in the ExplodedGraph that
/// resulted from [x ...] with 'x' definitely being nil and the result's size
// was larger than sizeof(void *) (an undefined value).
ErrorNodes NilReceiverLargerThanVoidPtrRetExplicit;
/// NilReceiverLargerThanVoidPtrRetImplicit - Nodes in the ExplodedGraph that
/// resulted from [x ...] with 'x' possibly being nil and the result's size
// was larger than sizeof(void *) (an undefined value).
ErrorNodes NilReceiverLargerThanVoidPtrRetImplicit;
/// UndefBranches - Nodes in the ExplodedGraph that result from
/// taking a branch based on an undefined value.
ErrorNodes UndefBranches;
/// UndefStores - Sinks in the ExplodedGraph that result from
/// making a store to an undefined lvalue.
ErrorNodes UndefStores;
/// NoReturnCalls - Sinks in the ExplodedGraph that result from
// calling a function with the attribute "noreturn".
ErrorNodes NoReturnCalls;
/// UndefResults - Nodes in the ExplodedGraph where the operands are defined
/// by the result is not. Excludes divide-by-zero errors.
ErrorNodes UndefResults;
/// UndefReceiver - Nodes in the ExplodedGraph resulting from message
/// ObjC message expressions where the receiver is undefined (uninitialized).
ErrorNodes UndefReceivers;
/// MsgExprUndefArgs - Nodes in the ExplodedGraph resulting from
/// message expressions where a pass-by-value argument has an undefined
/// value.
UndefArgsTy MsgExprUndefArgs;
public:
GRExprEngine(AnalysisManager &mgr);
@ -178,8 +129,6 @@ class GRExprEngine : public GRSubEngine {
ExplodedGraph& getGraph() { return G; }
const ExplodedGraph& getGraph() const { return G; }
void RegisterInternalChecks();
template <typename CHECKER>
void registerCheck(CHECKER *check) {
unsigned entry = Checkers.size();
@ -195,58 +144,6 @@ class GRExprEngine : public GRSubEngine {
return static_cast<CHECKER*>(lookupChecker(CHECKER::getTag()));
}
bool isNoReturnCall(const ExplodedNode* N) const {
return N->isSink() && NoReturnCalls.count(const_cast<ExplodedNode*>(N)) != 0;
}
typedef ErrorNodes::iterator undef_branch_iterator;
undef_branch_iterator undef_branches_begin() { return UndefBranches.begin(); }
undef_branch_iterator undef_branches_end() { return UndefBranches.end(); }
typedef ErrorNodes::iterator nil_receiver_struct_ret_iterator;
nil_receiver_struct_ret_iterator nil_receiver_struct_ret_begin() {
return NilReceiverStructRetExplicit.begin();
}
nil_receiver_struct_ret_iterator nil_receiver_struct_ret_end() {
return NilReceiverStructRetExplicit.end();
}
typedef ErrorNodes::iterator nil_receiver_larger_than_voidptr_ret_iterator;
nil_receiver_larger_than_voidptr_ret_iterator
nil_receiver_larger_than_voidptr_ret_begin() {
return NilReceiverLargerThanVoidPtrRetExplicit.begin();
}
nil_receiver_larger_than_voidptr_ret_iterator
nil_receiver_larger_than_voidptr_ret_end() {
return NilReceiverLargerThanVoidPtrRetExplicit.end();
}
typedef ErrorNodes::iterator undef_result_iterator;
undef_result_iterator undef_results_begin() { return UndefResults.begin(); }
undef_result_iterator undef_results_end() { return UndefResults.end(); }
typedef UndefArgsTy::iterator undef_arg_iterator;
undef_arg_iterator msg_expr_undef_arg_begin() {
return MsgExprUndefArgs.begin();
}
undef_arg_iterator msg_expr_undef_arg_end() {
return MsgExprUndefArgs.end();
}
typedef ErrorNodes::iterator undef_receivers_iterator;
undef_receivers_iterator undef_receivers_begin() {
return UndefReceivers.begin();
}
undef_receivers_iterator undef_receivers_end() {
return UndefReceivers.end();
}
void AddCheck(GRSimpleAPICheck* A, Stmt::StmtClass C);
void AddCheck(GRSimpleAPICheck* A);
@ -312,7 +209,7 @@ class GRExprEngine : public GRSubEngine {
protected:
/// CheckerVisit - Dispatcher for performing checker-specific logic
/// at specific statements.
void CheckerVisit(Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
bool CheckerVisit(Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
bool isPrevisit);
void CheckerVisitBind(const Stmt *AssignE, const Stmt *StoreE,
@ -345,6 +242,9 @@ class GRExprEngine : public GRSubEngine {
AsmStmt::inputs_iterator I,
AsmStmt::inputs_iterator E,
ExplodedNode* Pred, ExplodedNodeSet& Dst);
/// VisitBlockExpr - Transfer function logic for BlockExprs.
void VisitBlockExpr(BlockExpr *BE, ExplodedNode *Pred, ExplodedNodeSet &Dst);
/// VisitBinaryOperator - Transfer function logic for binary operators.
void VisitBinaryOperator(BinaryOperator* B, ExplodedNode* Pred,
@ -361,33 +261,38 @@ class GRExprEngine : public GRSubEngine {
unsigned ParamIdx = 0);
/// VisitCast - Transfer function logic for all casts (implicit and explicit).
void VisitCast(Expr* CastE, Expr* Ex, ExplodedNode* Pred, ExplodedNodeSet& Dst);
void VisitCast(Expr* CastE, Expr* Ex, ExplodedNode* Pred,
ExplodedNodeSet& Dst);
/// VisitCompoundLiteralExpr - Transfer function logic for compound literals.
void VisitCompoundLiteralExpr(CompoundLiteralExpr* CL, ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue);
/// VisitDeclRefExpr - Transfer function logic for DeclRefExprs.
void VisitDeclRefExpr(DeclRefExpr* DR, ExplodedNode* Pred, ExplodedNodeSet& Dst,
bool asLValue);
void VisitDeclRefExpr(DeclRefExpr* DR, ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue);
/// VisitDeclStmt - Transfer function logic for DeclStmts.
void VisitDeclStmt(DeclStmt* DS, ExplodedNode* Pred, ExplodedNodeSet& Dst);
/// VisitGuardedExpr - Transfer function logic for ?, __builtin_choose
void VisitGuardedExpr(Expr* Ex, Expr* L, Expr* R, ExplodedNode* Pred, ExplodedNodeSet& Dst);
void VisitGuardedExpr(Expr* Ex, Expr* L, Expr* R, ExplodedNode* Pred,
ExplodedNodeSet& Dst);
void VisitInitListExpr(InitListExpr* E, ExplodedNode* Pred, ExplodedNodeSet& Dst);
void VisitInitListExpr(InitListExpr* E, ExplodedNode* Pred,
ExplodedNodeSet& Dst);
/// VisitLogicalExpr - Transfer function logic for '&&', '||'
void VisitLogicalExpr(BinaryOperator* B, ExplodedNode* Pred, ExplodedNodeSet& Dst);
void VisitLogicalExpr(BinaryOperator* B, ExplodedNode* Pred,
ExplodedNodeSet& Dst);
/// VisitMemberExpr - Transfer function for member expressions.
void VisitMemberExpr(MemberExpr* M, ExplodedNode* Pred, ExplodedNodeSet& Dst,bool asLValue);
void VisitMemberExpr(MemberExpr* M, ExplodedNode* Pred, ExplodedNodeSet& Dst,
bool asLValue);
/// VisitObjCIvarRefExpr - Transfer function logic for ObjCIvarRefExprs.
void VisitObjCIvarRefExpr(ObjCIvarRefExpr* DR, ExplodedNode* Pred, ExplodedNodeSet& Dst,
bool asLValue);
void VisitObjCIvarRefExpr(ObjCIvarRefExpr* DR, ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue);
/// VisitObjCForCollectionStmt - Transfer function logic for
/// ObjCForCollectionStmt.

View File

@ -33,7 +33,6 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/raw_ostream.h"
#include <functional>
@ -264,8 +263,21 @@ class GRState : public llvm::FoldingSetNode {
const llvm::APSInt *getSymVal(SymbolRef sym);
bool scanReachableSymbols(SVal val, SymbolVisitor& visitor) const;
bool scanReachableSymbols(const SVal *I, const SVal *E,
SymbolVisitor &visitor) const;
bool scanReachableSymbols(const MemRegion * const *I,
const MemRegion * const *E,
SymbolVisitor &visitor) const;
template <typename CB> CB scanReachableSymbols(SVal val) const;
template <typename CB> CB scanReachableSymbols(const SVal *beg,
const SVal *end) const;
template <typename CB> CB
scanReachableSymbols(const MemRegion * const *beg,
const MemRegion * const *end) const;
//==---------------------------------------------------------------------==//
// Accessing the Generic Data Map (GDM).
@ -726,7 +738,21 @@ CB GRState::scanReachableSymbols(SVal val) const {
scanReachableSymbols(val, cb);
return cb;
}
template <typename CB>
CB GRState::scanReachableSymbols(const SVal *beg, const SVal *end) const {
CB cb(this);
scanReachableSymbols(beg, end, cb);
return cb;
}
template <typename CB>
CB GRState::scanReachableSymbols(const MemRegion * const *beg,
const MemRegion * const *end) const {
CB cb(this);
scanReachableSymbols(beg, end, cb);
return cb;
}
} // end clang namespace
#endif

View File

@ -35,6 +35,7 @@ namespace clang {
class MemRegionManager;
class MemSpaceRegion;
class LocationContext;
class VarRegion;
//===----------------------------------------------------------------------===//
// Base region classes.
@ -42,13 +43,16 @@ class LocationContext;
/// MemRegion - The root abstract class for all memory regions.
class MemRegion : public llvm::FoldingSetNode {
friend class MemRegionManager;
public:
enum Kind { MemSpaceRegionKind,
SymbolicRegionKind,
AllocaRegionKind,
// Typed regions.
BEG_TYPED_REGIONS,
CodeTextRegionKind,
FunctionTextRegionKind,
BlockTextRegionKind,
BlockDataRegionKind,
CompoundLiteralRegionKind,
StringRegionKind, ElementRegionKind,
// Decl Regions.
@ -237,45 +241,123 @@ class TypedRegion : public SubRegion {
}
};
/// CodeTextRegion - A region that represents code texts of a function. It wraps
/// two kinds of code texts: real function and symbolic function. Real function
/// is a function declared in the program. Symbolic function is a function
/// pointer that we don't know which function it points to.
class CodeTextRegion : public TypedRegion {
const FunctionDecl *FD;
protected:
CodeTextRegion(const MemRegion *sreg, Kind k) : TypedRegion(sreg, k) {}
public:
CodeTextRegion(const FunctionDecl* fd, const MemRegion* sreg)
: TypedRegion(sreg, CodeTextRegionKind), FD(fd) {}
QualType getValueType(ASTContext &C) const {
// Do not get the object type of a CodeTextRegion.
assert(0);
return QualType();
}
bool isBoundable() const { return false; }
static bool classof(const MemRegion* R) {
Kind k = R->getKind();
return k >= FunctionTextRegionKind && k <= BlockTextRegionKind;
}
};
/// FunctionTextRegion - A region that represents code texts of function.
class FunctionTextRegion : public CodeTextRegion {
const FunctionDecl *FD;
public:
FunctionTextRegion(const FunctionDecl* fd, const MemRegion* sreg)
: CodeTextRegion(sreg, FunctionTextRegionKind), FD(fd) {}
QualType getLocationType(ASTContext &C) const {
return C.getPointerType(FD->getType());
}
const FunctionDecl *getDecl() const {
return FD;
}
bool isBoundable() const { return false; }
virtual void dumpToStream(llvm::raw_ostream& os) const;
void Profile(llvm::FoldingSetNodeID& ID) const;
static void ProfileRegion(llvm::FoldingSetNodeID& ID, const FunctionDecl *FD,
const MemRegion*);
static bool classof(const MemRegion* R) {
return R->getKind() == CodeTextRegionKind;
return R->getKind() == FunctionTextRegionKind;
}
};
/// BlockTextRegion - A region that represents code texts of blocks (closures).
/// Blocks are represented with two kinds of regions. BlockTextRegions
/// represent the "code", while BlockDataRegions represent instances of blocks,
/// which correspond to "code+data". The distinction is important, because
/// like a closure a block captures the values of externally referenced
/// variables.
class BlockTextRegion : public CodeTextRegion {
const BlockDecl *BD;
CanQualType locTy;
public:
BlockTextRegion(const BlockDecl *bd, CanQualType lTy, const MemRegion* sreg)
: CodeTextRegion(sreg, BlockTextRegionKind), BD(bd), locTy(lTy) {}
QualType getLocationType(ASTContext &C) const {
return locTy;
}
const BlockDecl *getDecl() const {
return BD;
}
virtual void dumpToStream(llvm::raw_ostream& os) const;
void Profile(llvm::FoldingSetNodeID& ID) const;
static void ProfileRegion(llvm::FoldingSetNodeID& ID, const BlockDecl *BD,
CanQualType, const MemRegion*);
static bool classof(const MemRegion* R) {
return R->getKind() == BlockTextRegionKind;
}
};
/// BlockDataRegion - A region that represents a block instance.
/// Blocks are represented with two kinds of regions. BlockTextRegions
/// represent the "code", while BlockDataRegions represent instances of blocks,
/// which correspond to "code+data". The distinction is important, because
/// like a closure a block captures the values of externally referenced
/// variables.
/// BlockDataRegion - A region that represents code texts of blocks (closures).
class BlockDataRegion : public SubRegion {
const BlockTextRegion *BC;
const LocationContext *LC;
void *ReferencedVars;
public:
BlockDataRegion(const BlockTextRegion *bc,
const LocationContext *lc,
const MemRegion *sreg)
: SubRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc), ReferencedVars(0) {}
const BlockTextRegion *getCodeRegion() const { return BC; }
typedef const MemRegion * const * referenced_vars_iterator;
referenced_vars_iterator referenced_vars_begin() const;
referenced_vars_iterator referenced_vars_end() const;
virtual void dumpToStream(llvm::raw_ostream& os) const;
void Profile(llvm::FoldingSetNodeID& ID) const;
static void ProfileRegion(llvm::FoldingSetNodeID& ID,
const BlockTextRegion *BC,
const LocationContext *LC, const MemRegion *);
static bool classof(const MemRegion* R) {
return R->getKind() == BlockDataRegionKind;
}
private:
void LazyInitializeReferencedVars();
};
/// SymbolicRegion - A special, "non-concrete" region. Unlike other region
/// clases, SymbolicRegion represents a region that serves as an alias for
@ -577,9 +659,11 @@ class MemRegionManager {
: C(c), A(a), globals(0), stack(0), stackArguments(0), heap(0),
unknown(0), code(0) {}
~MemRegionManager() {}
~MemRegionManager();
ASTContext &getContext() { return C; }
llvm::BumpPtrAllocator &getAllocator() { return A; }
/// getStackRegion - Retrieve the memory region associated with the
/// current stack frame.
@ -656,7 +740,10 @@ class MemRegionManager {
ObjCIvarRegion *getObjCIvarRegion(const ObjCIvarDecl* ivd,
const MemRegion* superRegion);
CodeTextRegion *getCodeTextRegion(const FunctionDecl *FD);
FunctionTextRegion *getFunctionTextRegion(const FunctionDecl *FD);
BlockTextRegion *getBlockTextRegion(const BlockDecl *BD, CanQualType locTy);
BlockDataRegion *getBlockDataRegion(const BlockTextRegion *bc,
const LocationContext *lc);
template <typename RegionTy, typename A1>
RegionTy* getRegion(const A1 a1);
@ -667,6 +754,10 @@ class MemRegionManager {
template <typename RegionTy, typename A1, typename A2>
RegionTy* getRegion(const A1 a1, const A2 a2);
template <typename RegionTy, typename A1, typename A2>
RegionTy* getSubRegion(const A1 a1, const A2 a2,
const MemRegion* superRegion);
bool isGlobalsRegion(const MemRegion* R) {
assert(R);
return R == globals;
@ -745,6 +836,25 @@ RegionTy* MemRegionManager::getRegion(const A1 a1, const A2 a2) {
return R;
}
template <typename RegionTy, typename A1, typename A2>
RegionTy* MemRegionManager::getSubRegion(const A1 a1, const A2 a2,
const MemRegion *superRegion) {
llvm::FoldingSetNodeID ID;
RegionTy::ProfileRegion(ID, a1, a2, superRegion);
void* InsertPos;
RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID,
InsertPos));
if (!R) {
R = (RegionTy*) A.Allocate<RegionTy>();
new (R) RegionTy(a1, a2, superRegion);
Regions.InsertNode(R, InsertPos);
}
return R;
}
//===----------------------------------------------------------------------===//
// Traits for constructing regions.
@ -801,18 +911,21 @@ template <> struct MemRegionManagerTrait<SymbolicRegion> {
}
};
template<> struct MemRegionManagerTrait<CodeTextRegion> {
template<> struct MemRegionManagerTrait<FunctionTextRegion> {
typedef MemSpaceRegion SuperRegionTy;
static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr,
const FunctionDecl*) {
return MRMgr.getCodeRegion();
}
};
template<> struct MemRegionManagerTrait<BlockTextRegion> {
typedef MemSpaceRegion SuperRegionTy;
static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr,
SymbolRef, QualType) {
const BlockDecl*, CanQualType) {
return MRMgr.getCodeRegion();
}
};
} // end clang namespace
//===----------------------------------------------------------------------===//

View File

@ -114,6 +114,9 @@ class ValueManager {
const TypedRegion *R);
DefinedSVal getFunctionPointer(const FunctionDecl *FD);
DefinedSVal getBlockPointer(const BlockDecl *BD, CanQualType locTy,
const LocationContext *LC);
NonLoc makeCompoundVal(QualType T, llvm::ImmutableList<SVal> Vals) {
return nonloc::CompoundVal(BasicVals.getCompoundValData(T, Vals));

View File

@ -250,8 +250,8 @@ BUILTIN(__builtin_ia32_pmaddwd128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_monitor, "vv*UiUi", "")
BUILTIN(__builtin_ia32_mwait, "vUiUi", "")
BUILTIN(__builtin_ia32_lddqu, "V16ccC*", "")
BUILTIN(__builtin_ia32_palignr128, "V2LLiV2LLiV2LLii", "")
BUILTIN(__builtin_ia32_palignr, "V1LLiV1LLiV1LLis", "")
BUILTIN(__builtin_ia32_palignr128, "V2LLiV2LLiV2LLic", "")
BUILTIN(__builtin_ia32_palignr, "V1LLiV1LLiV1LLic", "")
BUILTIN(__builtin_ia32_insertps128, "V4fV4fV4fi", "")
BUILTIN(__builtin_ia32_storelv4si, "vV2i*V2LLi", "")

View File

@ -57,6 +57,9 @@ def err_drv_invalid_mfloat_abi : Error<
"invalid float ABI '%0'">;
def err_drv_I_dash_not_supported : Error<
"'%0' not supported, please use -iquote instead">;
def err_drv_unknown_argument : Error<"unknown argument: '%0'">;
def err_drv_invalid_value : Error<"invalid value '%1' in '%0'">;
def err_drv_invalid_int_value : Error<"invalid integral value '%1' in '%0'">;
def warn_drv_input_file_unused : Warning<
"%0: '%1' input unused when '%2' is present">;

View File

@ -17,6 +17,8 @@ def err_fe_invalid_ast_file : Error<"invalid AST file: '%0'">, DefaultFatal;
def err_fe_invalid_ast_action : Error<"invalid action for AST input">, DefaultFatal;
def err_fe_invalid_code_complete_file
: Error<"cannot locate code-completion file %0">, DefaultFatal;
def err_fe_stdout_binary : Error<"unable to change standard output to binary">,
DefaultFatal;
def err_fe_dependency_file_requires_MT : Error<
"-dependency-file requires at least one -MT option">;
def err_fe_incompatible_options : Error<

View File

@ -78,16 +78,19 @@ def : DiagGroup<"synth">;
// Preprocessor warnings.
def : DiagGroup<"builtin-macro-redefined">;
// Just silence warnings about common forms of -Wstrict-aliasing for now.
// Just silence warnings about -Wstrict-aliasing for now.
def : DiagGroup<"strict-aliasing=0">;
def : DiagGroup<"strict-aliasing=1">;
def : DiagGroup<"strict-aliasing=2">;
def : DiagGroup<"strict-aliasing">;
// Just silence warnings about common forms of -Wstrict-aliasing for now.
// Just silence warnings about -Wstrict-overflow for now.
def : DiagGroup<"strict-overflow=0">;
def : DiagGroup<"strict-overflow=1">;
def : DiagGroup<"strict-overflow=2">;
def : DiagGroup<"strict-overflow=3">;
def : DiagGroup<"strict-overflow=4">;
def : DiagGroup<"strict-overflow=5">;
def : DiagGroup<"strict-overflow">;
def InvalidOffsetof : DiagGroup<"invalid-offsetof">;

View File

@ -170,6 +170,8 @@ def ext_pp_counter : Extension<
def err_pp_invalid_directive : Error<"invalid preprocessing directive">;
def err_pp_hash_error : Error<"#error%0">;
def err_pp_file_not_found : Error<"'%0' file not found">, DefaultFatal;
def err_pp_error_opening_file : Error<
"error opening file '%0'">, DefaultFatal;
def err_pp_empty_filename : Error<"empty filename">;
def err_pp_include_too_deep : Error<"#include nested too deeply">;
def err_pp_expects_filename : Error<"expected \"FILENAME\" or <FILENAME>">;

View File

@ -44,7 +44,8 @@ def ext_c99_variable_decl_in_for_loop : Extension<
def ext_c99_compound_literal : Extension<
"compound literals are a C99-specific feature">;
def ext_enumerator_list_comma : Extension<
"commas at the end of enumerator lists are a %select{C99|C++0x}0-specific feature">;
"commas at the end of enumerator lists are a %select{C99|C++0x}0-specific "
"feature">;
def ext_gnu_indirect_goto : Extension<
"use of GNU indirect-goto extension">;
@ -75,6 +76,7 @@ def err_expected_ident_lbrace : Error<"expected identifier or '{'">;
def err_expected_lbrace : Error<"expected '{'">;
def err_expected_lparen : Error<"expected '('">;
def err_expected_rparen : Error<"expected ')'">;
def err_expected_lsquare : Error<"expected '['">;
def err_expected_rsquare : Error<"expected ']'">;
def err_expected_rbrace : Error<"expected '}'">;
def err_expected_greater : Error<"expected '>'">;
@ -240,11 +242,18 @@ def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">;
// C++ operator overloading
def err_operator_missing_type_specifier : Error<
"missing type specifier after 'operator'">;
def err_operator_string_not_empty : Error<
"string literal after 'operator' must be '\"\"'">;
// Classes.
def err_anon_type_definition : Error<
"declaration of anonymous %0 must be a definition">;
def err_cxx0x_attribute_forbids_arguments : Error<
"C++0x attribute '%0' cannot have an argument list">;
def err_cxx0x_attribute_requires_arguments : Error<
"C++0x attribute '%0' must have an argument list">;
def err_attributes_not_allowed : Error<"an attribute list cannot appear here">;
/// C++ Templates
def err_expected_template : Error<"expected template">;

View File

@ -443,8 +443,9 @@ def err_implicit_object_parameter_init : Error<
def note_field_decl : Note<"member is declared here">;
def note_previous_class_decl : Note<
"%0 declared here">;
def note_ctor_synthesized_at : Note<
"implicit default constructor for %0 first required here">;
def note_member_synthesized_at : Note<
"implicit default %select{constructor|copy constructor|"
"copy assignment operator|destructor}0 for %1 first required here">;
def err_missing_default_ctor : Error<
"%select{|implicit default }0constructor for %1 must explicitly initialize "
"the %select{base class|member}2 %3 which does not have a default "
@ -552,6 +553,15 @@ def err_auto_not_allowed : Error<
def err_auto_var_requires_init : Error<
"declaration of variable %0 with type %1 requires an initializer">;
// C++0x attributes
def err_repeat_attribute : Error<"'%0' attribute cannot be repeated">;
// C++0x [[final]]
def err_final_function_overridden : Error<
"declaration of %0 overrides a 'final' function">;
def err_final_base : Error<
"derivation from 'final' %0">;
// Objective-C++
def err_objc_decls_may_only_appear_in_global_scope : Error<
"Objective-C declarations may only appear in global scope">;
@ -638,8 +648,16 @@ def warn_attribute_weak_import_invalid_on_definition : Warning<
"'weak_import' attribute cannot be specified on a definition">;
def warn_attribute_wrong_decl_type : Warning<
"%0 attribute only applies to %select{function|union|"
"variable and function|function or method|parameter|parameter or Objective-C method |"
"function, method or block}1 types">;
"variable and function|function or method|parameter|"
"parameter or Objective-C method |function, method or block|"
"virtual method or class|function, method, or parameter|class|virtual method"
"|member}1 types">;
def err_attribute_wrong_decl_type : Error<
"%0 attribute only applies to %select{function|union|"
"variable and function|function or method|parameter|"
"parameter or Objective-C method |function, method or block|"
"virtual method or class|function, method, or parameter|class|virtual method"
"|member}1 types">;
def warn_gnu_inline_attribute_requires_inline : Warning<
"'gnu_inline' attribute requires function to be marked 'inline',"
" attribute ignored">;
@ -865,7 +883,7 @@ def err_addr_ovl_ambiguous : Error<
def err_template_param_shadow : Error<
"declaration of %0 shadows template parameter">;
def note_template_param_here : Note<"template parameter is declared here">;
def note_template_export_unsupported : Note<
def warn_template_export_unsupported : Warning<
"exported templates are unsupported">;
def err_template_outside_namespace_or_class_scope : Error<
"templates can only be declared in namespace or class scope">;
@ -902,7 +920,15 @@ def note_template_param_prev_default_arg : Note<
"previous default template argument defined here">;
def err_template_param_default_arg_missing : Error<
"template parameter missing a default argument">;
def err_template_parameter_default_in_function_template : Error<
"a template parameter of a function template cannot have a default argument "
"in C++98">;
def err_template_parameter_default_template_member : Error<
"cannot add a default template argument to the definition of a member of a "
"class template">;
def err_template_parameter_default_friend_template : Error<
"default template argument not permitted on a friend template">;
def err_template_variable : Error<"variable %0 declared as a template">;
def err_template_variable_noparams : Error<
"extraneous 'template<>' in declaration of variable %0">;
@ -1037,6 +1063,11 @@ def err_template_param_list_matches_nontemplate : Error<
def err_template_spec_extra_headers : Error<
"extraneous template parameter list in template specialization or "
"out-of-line template definition">;
def warn_template_spec_extra_headers : Warning<
"extraneous template parameter list in template specialization">;
def note_explicit_template_spec_does_not_need_header : Note<
"'template<>' header not required for explicitly-specialized class %0 "
"declared here">;
def err_template_qualified_declarator_no_match : Error<
"nested name specifier '%0' for declaration does not refer into a class, "
"class template or class template partial specialization">;
@ -1197,6 +1228,10 @@ def err_template_kw_refers_to_non_template : Error<
"%0 following the 'template' keyword does not refer to a template">;
def err_template_kw_refers_to_function_template : Error<
"%0 following the 'template' keyword refers to a function template">;
def err_template_kw_refers_to_class_template : Error<
"'%0%1' instantiated to a class template, not a function template">;
def note_referenced_class_template : Error<
"class template declared here">;
// C++0x Variadic Templates
def err_template_param_pack_default_arg : Error<
@ -2050,6 +2085,8 @@ def err_base_init_direct_and_virtual : Error<
"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_not_direct_base_or_virtual_multi : 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">;
@ -2275,6 +2312,15 @@ def err_typecheck_statement_requires_integer : Error<
"statement requires expression of integer type (%0 invalid)">;
def err_multiple_default_labels_defined : Error<
"multiple default labels in one switch">;
def err_switch_multiple_conversions : Error<
"multiple conversions from switch condition type %0 to an integral or "
"enumeration type">;
def note_switch_conversion : Note<
"conversion to %select{integral|enumeration}0 type %1">;
def err_switch_explicit_conversion : Error<
"switch condition type %0 requires explicit conversion to %1">;
def err_switch_incomplete_class_type : Error<
"switch condition has incomplete class type %0">;
def warn_empty_if_body : Warning<
"if statement has empty body">, InGroup<EmptyBody>;
def err_va_start_used_in_non_variadic_function : Error<

View File

@ -496,6 +496,7 @@ class DeclarationNameExtra {
#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
CXXOperator##Name,
#include "clang/Basic/OperatorKinds.def"
CXXLiteralOperator,
CXXUsingDirective,
NUM_EXTRA_KINDS
};
@ -503,10 +504,10 @@ class DeclarationNameExtra {
/// ExtraKindOrNumArgs - Either the kind of C++ special name or
/// operator-id (if the value is one of the CXX* enumerators of
/// ExtraKind), in which case the DeclarationNameExtra is also a
/// CXXSpecialName (for CXXConstructor, CXXDestructor, or
/// CXXConversionFunction) or CXXOperatorIdName, it may be also
/// name common to C++ using-directives (CXXUsingDirective), otherwise
/// it is NUM_EXTRA_KINDS+NumArgs, where NumArgs is the number of
/// CXXSpecialName, (for CXXConstructor, CXXDestructor, or
/// CXXConversionFunction) CXXOperatorIdName, or CXXLiteralOperatorName,
/// it may be also name common to C++ using-directives (CXXUsingDirective),
/// otherwise it is NUM_EXTRA_KINDS+NumArgs, where NumArgs is the number of
/// arguments in the Objective-C selector, in which case the
/// DeclarationNameExtra is also a MultiKeywordSelector.
unsigned ExtraKindOrNumArgs;

View File

@ -14,6 +14,8 @@
#ifndef LLVM_CLANG_LANGOPTIONS_H
#define LLVM_CLANG_LANGOPTIONS_H
#include <string>
namespace clang {
/// LangOptions - This class keeps track of the various options that can be
@ -101,15 +103,10 @@ class LangOptions {
// 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
/// the original input file, for example with -save-temps.
const char *MainFileName;
public:
unsigned InstantiationDepth; // Maximum template instantiation depth.
const char *ObjCConstantStringClass;
std::string ObjCConstantStringClass;
enum GCMode { NonGC, GCOnly, HybridGC };
enum StackProtectorMode { SSPOff, SSPOn, SSPReq };
@ -124,7 +121,6 @@ class LangOptions {
GNUMode = ImplicitInt = Digraphs = 0;
HexFloats = 0;
GC = ObjC1 = ObjC2 = ObjCNonFragileABI = 0;
ObjCConstantStringClass = 0;
C99 = Microsoft = CPlusPlus = CPlusPlus0x = 0;
CXXOperatorNames = PascalStrings = WritableStrings = 0;
Exceptions = Freestanding = NoBuiltin = 0;
@ -164,8 +160,6 @@ class LangOptions {
CharIsSigned = 1;
ShortWChar = 0;
MainFileName = 0;
}
GCMode getGCMode() const { return (GCMode) GC; }
@ -178,9 +172,6 @@ class LangOptions {
StackProtector = static_cast<unsigned>(m);
}
const char *getMainFileName() const { return MainFileName; }
void setMainFileName(const char *Name) { MainFileName = Name; }
VisibilityMode getVisibilityMode() const {
return (VisibilityMode) SymbolVisibility;
}

View File

@ -15,7 +15,6 @@
#define LLVM_CLANG_BASIC_ON_DISK_HASH_TABLE_H
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Compiler.h"
#include "llvm/System/DataTypes.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"

View File

@ -80,7 +80,7 @@ class TargetInfo {
};
protected:
IntType SizeType, IntMaxType, UIntMaxType, PtrDiffType, IntPtrType, WCharType,
WIntType, Char16Type, Char32Type, Int64Type;
WIntType, Char16Type, Char32Type, Int64Type, SigAtomicType;
public:
IntType getSizeType() const { return SizeType; }
IntType getIntMaxType() const { return IntMaxType; }
@ -94,6 +94,7 @@ class TargetInfo {
IntType getChar16Type() const { return Char16Type; }
IntType getChar32Type() const { return Char32Type; }
IntType getInt64Type() const { return Int64Type; }
IntType getSigAtomicType() const { return SigAtomicType; }
/// getTypeWidth - Return the width (in bits) of the specified integer type

View File

@ -17,6 +17,9 @@
#ifndef TOK
#define TOK(X)
#endif
#ifndef PUNCTUATOR
#define PUNCTUATOR(X,Y) TOK(X)
#endif
#ifndef KEYWORD
#define KEYWORD(X,Y) TOK(kw_ ## X)
#endif
@ -113,64 +116,63 @@ TOK(wide_string_literal) // L"foo"
TOK(angle_string_literal)// <foo>
// C99 6.4.6: Punctuators.
TOK(l_square) // [
TOK(r_square) // ]
TOK(l_paren) // (
TOK(r_paren) // )
TOK(l_brace) // {
TOK(r_brace) // }
TOK(period) // .
TOK(ellipsis) // ...
TOK(amp) // &
TOK(ampamp) // &&
TOK(ampequal) // &=
TOK(star) // *
TOK(starequal) // *=
TOK(plus) // +
TOK(plusplus) // ++
TOK(plusequal) // +=
TOK(minus) // -
TOK(arrow) // ->
TOK(minusminus) // --
TOK(minusequal) // -=
TOK(tilde) // ~
TOK(exclaim) // !
TOK(exclaimequal) // !=
TOK(slash) // /
TOK(slashequal) // /=
TOK(percent) // %
TOK(percentequal) // %=
TOK(less) // <
TOK(lessless) // <<
TOK(lessequal) // <=
TOK(lesslessequal) // <<=
TOK(greater) // >
TOK(greatergreater) // >>
TOK(greaterequal) // >=
TOK(greatergreaterequal) // >>=
TOK(caret) // ^
TOK(caretequal) // ^=
TOK(pipe) // |
TOK(pipepipe) // ||
TOK(pipeequal) // |=
TOK(question) // ?
TOK(colon) // :
TOK(semi) // ;
TOK(equal) // =
TOK(equalequal) // ==
TOK(comma) // ,
TOK(hash) // #
TOK(hashhash) // ##
TOK(hashat) // #@
PUNCTUATOR(l_square, "[")
PUNCTUATOR(r_square, "]")
PUNCTUATOR(l_paren, "(")
PUNCTUATOR(r_paren, ")")
PUNCTUATOR(l_brace, "{")
PUNCTUATOR(r_brace, "}")
PUNCTUATOR(period, ".")
PUNCTUATOR(ellipsis, "...")
PUNCTUATOR(amp, "&")
PUNCTUATOR(ampamp, "&&")
PUNCTUATOR(ampequal, "&=")
PUNCTUATOR(star, "*")
PUNCTUATOR(starequal, "*=")
PUNCTUATOR(plus, "+")
PUNCTUATOR(plusplus, "++")
PUNCTUATOR(plusequal, "+=")
PUNCTUATOR(minus, "-")
PUNCTUATOR(arrow, "->")
PUNCTUATOR(minusminus, "--")
PUNCTUATOR(minusequal, "-=")
PUNCTUATOR(tilde, "~")
PUNCTUATOR(exclaim, "!")
PUNCTUATOR(exclaimequal, "!=")
PUNCTUATOR(slash, "/")
PUNCTUATOR(slashequal, "/=")
PUNCTUATOR(percent, "%")
PUNCTUATOR(percentequal, "%=")
PUNCTUATOR(less, "<")
PUNCTUATOR(lessless, "<<")
PUNCTUATOR(lessequal, "<=")
PUNCTUATOR(lesslessequal, "<<=")
PUNCTUATOR(greater, ">")
PUNCTUATOR(greatergreater, ">>")
PUNCTUATOR(greaterequal, ">=")
PUNCTUATOR(greatergreaterequal, ">>=")
PUNCTUATOR(caret, "^")
PUNCTUATOR(caretequal, "^=")
PUNCTUATOR(pipe, "|")
PUNCTUATOR(pipepipe, "||")
PUNCTUATOR(pipeequal, "|=")
PUNCTUATOR(question, "?")
PUNCTUATOR(colon, ":")
PUNCTUATOR(semi, ";")
PUNCTUATOR(equal, "=")
PUNCTUATOR(equalequal, "==")
PUNCTUATOR(comma, ",")
PUNCTUATOR(hash, "#")
PUNCTUATOR(hashhash, "##")
PUNCTUATOR(hashat, "#@")
// C++ Support
TOK(periodstar) // .*
TOK(arrowstar) // ->*
TOK(coloncolon) // ::
PUNCTUATOR(periodstar, ".*")
PUNCTUATOR(arrowstar, "->*")
PUNCTUATOR(coloncolon, "::")
// Objective C support.
TOK(at) // @
PUNCTUATOR(at, "@")
// C99 6.4.1: Keywords. These turn into kw_* tokens.
// Flags allowed:
@ -415,4 +417,5 @@ ANNOTATION(template_id) // annotation for a C++ template-id that names a
#undef PPKEYWORD
#undef ALIAS
#undef KEYWORD
#undef PUNCTUATOR
#undef TOK

View File

@ -29,7 +29,9 @@ class CodeGenOptions {
OnlyAlwaysInlining // Only run the always inlining pass.
};
unsigned AsmVerbose : 1; /// -dA, -fverbose-asm.
unsigned DebugInfo : 1; /// Should generate deubg info (-g).
unsigned DisableFPElim : 1; /// Set when -fomit-frame-pointer is enabled.
unsigned DisableLLVMOpts : 1; /// Don't run any optimizations, for use in
/// getting .bc files that correspond to the
/// internal state before optimizations are
@ -38,35 +40,63 @@ class CodeGenOptions {
unsigned MergeAllConstants : 1; /// Merge identical constants.
unsigned NoCommon : 1; /// Set when -fno-common or C++ is enabled.
unsigned NoImplicitFloat : 1; /// Set when -mno-implicit-float is enabled.
unsigned NoZeroInitializedInBSS : 1; /// -fno-zero-initialized-in-bss
unsigned OptimizationLevel : 3; /// The -O[0-4] option specified.
unsigned OptimizeSize : 1; /// If -Os is specified.
unsigned SimplifyLibCalls : 1; /// Should standard library calls be treated
/// specially.
unsigned SoftFloat : 1; /// -soft-float.
unsigned TimePasses : 1; /// Set when -ftime-report is enabled.
unsigned UnitAtATime : 1; /// Unused. For mirroring GCC optimization
/// selection.
unsigned UnrollLoops : 1; /// Control whether loops are unrolled.
unsigned UnwindTables : 1; /// Emit unwind tables.
unsigned VerifyModule : 1; /// Control whether the module should be run
/// through the LLVM Verifier.
/// Inlining - The kind of inlining to perform.
/// The code model to use (-mcmodel).
std::string CodeModel;
/// Enable additional debugging information.
std::string DebugPass;
/// The ABI to use for passing floating point arguments.
std::string FloatABI;
/// The float precision limit to use, if non-empty.
std::string LimitFloatPrecision;
/// The kind of inlining to perform.
InliningMethod Inlining;
/// The user provided name for the "main file", if non-empty. This is useful
/// in situations where the input file name does not match the original input
/// file, for example with -save-temps.
std::string MainFileName;
/// The name of the relocation model to use.
std::string RelocationModel;
public:
CodeGenOptions() {
AsmVerbose = 0;
DebugInfo = 0;
DisableFPElim = 0;
DisableLLVMOpts = 0;
DisableRedZone = 0;
MergeAllConstants = 1;
NoCommon = 0;
NoImplicitFloat = 0;
NoZeroInitializedInBSS = 0;
OptimizationLevel = 0;
OptimizeSize = 0;
DebugInfo = 0;
UnitAtATime = 1;
SimplifyLibCalls = UnrollLoops = 0;
VerifyModule = 1;
UnrollLoops = 0;
SoftFloat = 0;
TimePasses = 0;
NoCommon = 0;
UnitAtATime = 1;
UnwindTables = 0;
VerifyModule = 1;
Inlining = NoInlining;
DisableRedZone = 0;
NoImplicitFloat = 0;
MergeAllConstants = 1;
DisableLLVMOpts = 0;
RelocationModel = "pic";
}
};

View File

@ -25,8 +25,67 @@ namespace llvm {
namespace clang {
namespace driver {
class Arg;
class ArgList;
class Option;
/// arg_iterator - Iterates through arguments stored inside an ArgList.
class arg_iterator {
/// The current argument.
llvm::SmallVectorImpl<Arg*>::const_iterator Current;
/// The argument list we are iterating over.
const ArgList &Args;
/// Optional filters on the arguments which will be match. Most clients
/// should never want to iterate over arguments without filters, so we won't
/// bother to factor this into two separate iterator implementations.
//
// FIXME: Make efficient; the idea is to provide efficient iteration over
// all arguments which match a particular id and then just provide an
// iterator combinator which takes multiple iterators which can be
// efficiently compared and returns them in order.
OptSpecifier Id0, Id1, Id2;
void SkipToNextArg();
public:
typedef const Arg* value_type;
typedef const Arg* reference;
typedef const Arg* pointer;
typedef std::forward_iterator_tag iterator_category;
typedef std::ptrdiff_t difference_type;
arg_iterator(llvm::SmallVectorImpl<Arg*>::const_iterator it,
const ArgList &_Args, OptSpecifier _Id0 = 0U,
OptSpecifier _Id1 = 0U, OptSpecifier _Id2 = 0U)
: Current(it), Args(_Args), Id0(_Id0), Id1(_Id1), Id2(_Id2) {
SkipToNextArg();
}
operator const Arg*() { return *Current; }
reference operator*() const { return *Current; }
pointer operator->() const { return *Current; }
arg_iterator &operator++() {
++Current;
SkipToNextArg();
return *this;
}
arg_iterator operator++(int) {
arg_iterator tmp(*this);
++(*this);
return tmp;
}
friend bool operator==(arg_iterator LHS, arg_iterator RHS) {
return LHS.Current == RHS.Current;
}
friend bool operator!=(arg_iterator LHS, arg_iterator RHS) {
return !(LHS == RHS);
}
};
/// ArgList - Ordered collection of driver arguments.
///
/// The ArgList class manages a list of Arg instances as well as
@ -62,6 +121,10 @@ namespace driver {
unsigned size() const { return Args.size(); }
/// @}
/// @name Arg Iteration
/// @{
iterator begin() { return Args.begin(); }
iterator end() { return Args.end(); }
@ -74,6 +137,18 @@ namespace driver {
const_reverse_iterator rbegin() const { return Args.rbegin(); }
const_reverse_iterator rend() const { return Args.rend(); }
arg_iterator filtered_begin(OptSpecifier Id0 = 0U, OptSpecifier Id1 = 0U,
OptSpecifier Id2 = 0U) const {
return arg_iterator(Args.begin(), *this, Id0, Id1, Id2);
}
arg_iterator filtered_end() const {
return arg_iterator(Args.end(), *this);
}
/// @}
/// @name Arg Access
/// @{
/// hasArg - Does the arg list contain any option matching \arg Id.
///
/// \arg Claim Whether the argument should be claimed, if it exists.
@ -115,17 +190,13 @@ namespace driver {
void AddLastArg(ArgStringList &Output, OptSpecifier Id0) const;
/// AddAllArgs - Render all arguments matching the given ids.
void AddAllArgs(ArgStringList &Output, OptSpecifier Id0) const;
void AddAllArgs(ArgStringList &Output, OptSpecifier Id0,
OptSpecifier Id1) const;
void AddAllArgs(ArgStringList &Output, OptSpecifier Id0, OptSpecifier Id1,
OptSpecifier Id2) const;
OptSpecifier Id1 = 0U, OptSpecifier Id2 = 0U) const;
/// AddAllArgValues - Render the argument values of all arguments
/// matching the given ids.
void AddAllArgValues(ArgStringList &Output, OptSpecifier Id0) const;
void AddAllArgValues(ArgStringList &Output, OptSpecifier Id0,
OptSpecifier Id1) const;
OptSpecifier Id1 = 0U, OptSpecifier Id2 = 0U) const;
/// AddAllArgsTranslated - Render all the arguments matching the
/// given ids, but forced to separate args and using the provided

View File

@ -17,8 +17,6 @@ namespace driver {
namespace cc1options {
enum ID {
OPT_INVALID = 0, // This is not an option ID.
OPT_INPUT, // Reserved ID for input option.
OPT_UNKNOWN, // Reserved ID for unknown option.
#define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
HELPTEXT, METAVAR) OPT_##ID,
#include "clang/Driver/CC1Options.inc"

View File

@ -14,13 +14,400 @@
// Include the common option parsing interfaces.
include "OptParser.td"
//===----------------------------------------------------------------------===//
// Target Options
//===----------------------------------------------------------------------===//
def target_abi : Separate<"-target-abi">,
HelpText<"Target a particular ABI type">;
def target_cpu : Separate<"-mcpu">,
HelpText<"Target a specific cpu type (-mcpu=help for details)">;
def target_features : Separate<"-target-feature">,
def mcpu : Separate<"-mcpu">,
HelpText<"Target a specific cpu type ('-mcpu help' for details)">;
def target_feature : Separate<"-target-feature">,
HelpText<"Target specific attributes">;
def target_triple : Separate<"-triple">,
def triple : Separate<"-triple">,
HelpText<"Specify target triple (e.g. i686-apple-darwin9)">;
def triple_EQ : Joined<"-triple=">, Alias<triple>;
//===----------------------------------------------------------------------===//
// Analyzer Options
//===----------------------------------------------------------------------===//
def analysis_CFGDump : Flag<"-cfg-dump">,
HelpText<"Display Control-Flow Graphs">;
def analysis_CFGView : Flag<"-cfg-view">,
HelpText<"View Control-Flow Graphs using GraphViz">;
def analysis_DisplayLiveVariables : Flag<"-dump-live-variables">,
HelpText<"Print results of live variable analysis">;
def analysis_SecuritySyntacticChecks : Flag<"-warn-security-syntactic">,
HelpText<"Perform quick security checks that require no data flow">;
def analysis_WarnDeadStores : Flag<"-warn-dead-stores">,
HelpText<"Warn about stores to dead variables">;
def analysis_WarnUninitVals : Flag<"-warn-uninit-values">,
HelpText<"Warn about uses of uninitialized variables">;
def analysis_WarnObjCMethSigs : Flag<"-warn-objc-methodsigs">,
HelpText<"Warn about Objective-C method signatures with type incompatibilities">;
def analysis_WarnObjCDealloc : Flag<"-warn-objc-missing-dealloc">,
HelpText<"Warn about Objective-C classes that lack a correct implementation of -dealloc">;
def analysis_WarnObjCUnusedIvars : Flag<"-warn-objc-unused-ivars">,
HelpText<"Warn about private ivars that are never used">;
def analysis_CheckerCFRef : Flag<"-checker-cfref">,
HelpText<"Run the [Core] Foundation reference count checker">;
def analysis_WarnSizeofPointer : Flag<"-warn-sizeof-pointer">,
HelpText<"Warn about unintended use of sizeof() on pointer expressions">;
def analysis_InlineCall : Flag<"-inline-call">,
HelpText<"Experimental transfer function inling callees when its definition is available.">;
def analyzer_store : Separate<"-analyzer-store">,
HelpText<"Source Code Analysis - Abstract Memory Store Models">;
def analyzer_store_EQ : Joined<"-analyzer-store=">, Alias<analyzer_store>;
def analyzer_constraints : Separate<"-analyzer-constraints">,
HelpText<"Source Code Analysis - Symbolic Constraint Engines">;
def analyzer_constraints_EQ : Joined<"-analyzer-constraints=">,
Alias<analyzer_constraints>;
def analyzer_output : Separate<"-analyzer-output">,
HelpText<"Source Code Analysis - Output Options">;
def analyzer_output_EQ : Joined<"-analyzer-output=">,
Alias<analyzer_output>;
def analyzer_opt_analyze_headers : Flag<"-analyzer-opt-analyze-headers">,
HelpText<"Force the static analyzer to analyze functions defined in header files">;
def analyzer_display_progress : Flag<"-analyzer-display-progress">,
HelpText<"Emit verbose output about the analyzer's progress">;
def analyzer_experimental_checks : Flag<"-analyzer-experimental-checks">,
HelpText<"Use experimental path-sensitive checks">;
def analyzer_experimental_internal_checks :
Flag<"-analyzer-experimental-internal-checks">,
HelpText<"Use new default path-sensitive checks currently in testing">;
def analyze_function : Separate<"-analyze-function">,
HelpText<"Run analysis on specific function">;
def analyze_function_EQ : Joined<"-analyze-function=">, Alias<analyze_function>;
def analyzer_eagerly_assume : Flag<"-analyzer-eagerly-assume">,
HelpText<"Eagerly assume the truth/falseness of some symbolic constraints">;
def analyzer_no_purge_dead : Flag<"-analyzer-no-purge-dead">,
HelpText<"Don't remove dead symbols, bindings, and constraints before processing a statement">;
def trim_egraph : Flag<"-trim-egraph">,
HelpText<"Only show error-related paths in the analysis graph">;
def analyzer_viz_egraph_graphviz : Flag<"-analyzer-viz-egraph-graphviz">,
HelpText<"Display exploded graph using GraphViz">;
def analyzer_viz_egraph_ubigraph : Flag<"-analyzer-viz-egraph-ubigraph">,
HelpText<"Display exploded graph using Ubigraph">;
//===----------------------------------------------------------------------===//
// CodeGen Options
//===----------------------------------------------------------------------===//
def disable_llvm_optzns : Flag<"-disable-llvm-optzns">,
HelpText<"Don't run LLVM optimization passes">;
def disable_red_zone : Flag<"-disable-red-zone">,
HelpText<"Do not emit code that uses the red zone.">;
def g : Flag<"-g">, HelpText<"Generate source level debug information">;
def fno_common : Flag<"-fno-common">,
HelpText<"Compile common globals like normal definitions">;
def no_implicit_float : Flag<"-no-implicit-float">,
HelpText<"Don't generate implicit floating point instructions (x86-only)">;
def fno_merge_all_constants : Flag<"-fno-merge-all-constants">,
HelpText<"Disallow merging of constants.">;
def masm_verbose : Flag<"-masm-verbose">,
HelpText<"Generate verbose assembly output">;
def mcode_model : Separate<"-mcode-model">,
HelpText<"The code model to use">;
def mdebug_pass : Separate<"-mdebug-pass">,
HelpText<"Enable additional debug output">;
def mdisable_fp_elim : Flag<"-mdisable-fp-elim">,
HelpText<"Disable frame pointer elimination optimization">;
def mfloat_abi : Flag<"-mfloat-abi">,
HelpText<"The float ABI to use">;
def mlimit_float_precision : Separate<"-mlimit-float-precision">,
HelpText<"Limit float precision to the given value">;
def mno_zero_initialized_in_bss : Flag<"-mno-zero-initialized-in-bss">,
HelpText<"Do not put zero initialized data in the BSS">;
def msoft_float : Separate<"-msoft-float">,
HelpText<"Use software floating point">;
def mrelocation_model : Separate<"-mrelocation-model">,
HelpText<"The relocation model to use">;
def munwind_tables : Flag<"-munwind-tables">,
HelpText<"Generate unwinding tables for all functions">;
def O : Joined<"-O">, HelpText<"Optimization level">;
def Os : Flag<"-Os">, HelpText<"Optimize for size">;
//===----------------------------------------------------------------------===//
// Dependency Output Options
//===----------------------------------------------------------------------===//
def dependency_file : Separate<"-dependency-file">,
HelpText<"Filename (or -) to write dependency output to">;
def sys_header_deps : Flag<"-sys-header-deps">,
HelpText<"Include system headers in dependency output">;
def MT : Separate<"-MT">, HelpText<"Specify target for dependency">;
def MP : Flag<"-MP">,
HelpText<"Create phony target for each dependency (other than main file)">;
//===----------------------------------------------------------------------===//
// Diagnostic Options
//===----------------------------------------------------------------------===//
def dump_build_information : Separate<"-dump-build-information">,
MetaVarName<"filename">,
HelpText<"output a dump of some build information to a file">;
def fno_show_column : Flag<"-fno-show-column">,
HelpText<"Do not include column number on diagnostics">;
def fno_show_source_location : Flag<"-fno-show-source-location">,
HelpText<"Do not include source location information with diagnostics">;
def fno_caret_diagnostics : Flag<"-fno-caret-diagnostics">,
HelpText<"Do not include source line and caret with diagnostics">;
def fno_diagnostics_fixit_info : Flag<"-fno-diagnostics-fixit-info">,
HelpText<"Do not include fixit information in diagnostics">;
def w : Flag<"-w">, HelpText<"Suppress all warnings">;
def pedantic : Flag<"-pedantic">;
def pedantic_errors : Flag<"-pedantic-errors">;
// This gets all -W options, including -Werror, -W[no-]system-headers, etc. The
// driver has stripped off -Wa,foo etc. The driver has also translated -W to
// -Wextra, so we don't need to worry about it.
def W : Joined<"-W">;
def fdiagnostics_print_source_range_info : Flag<"-fdiagnostics-print-source-range-info">,
HelpText<"Print source range spans in numeric form">;
def fdiagnostics_show_option : Flag<"-fdiagnostics-show-option">,
HelpText<"Print diagnostic name with mappable diagnostics">;
def fmessage_length : Separate<"-fmessage-length">, MetaVarName<"N">,
HelpText<"Format message diagnostics so that they fit within N columns or fewer, when possible.">;
def fcolor_diagnostics : Flag<"-fcolor-diagnostics">,
HelpText<"Use colors in diagnostics">;
def Wno_rewrite_macros : Flag<"-Wno-rewrite-macros">,
HelpText<"Silence ObjC rewriting warnings">;
def verify : Flag<"-verify">,
HelpText<"Verify emitted diagnostics and warnings">;
//===----------------------------------------------------------------------===//
// Frontend Options
//===----------------------------------------------------------------------===//
def code_completion_at : Separate<"-code-completion-at">,
MetaVarName<"file:line:column">,
HelpText<"Dump code-completion information at a location">;
def code_completion_at_EQ : Joined<"-code-completion-at=">,
Alias<code_completion_at>;
def no_code_completion_debug_printer : Flag<"-no-code-completion-debug-printer">,
HelpText<"Don't the \"debug\" code-completion print">;
def code_completion_macros : Flag<"-code-completion-macros">,
HelpText<"Include macros in code-completion results">;
def disable_free : Flag<"-disable-free">,
HelpText<"Disable freeing of memory on exit">;
def empty_input_only : Flag<"-empty-input-only">,
HelpText<"Force running on an empty input file">;
def x : Separate<"-x">, HelpText<"Input language type">;
def cxx_inheritance_view : Separate<"-cxx-inheritance-view">,
MetaVarName<"class name">,
HelpText<"View C++ inheritance for a specified class">;
def fixit_at : Separate<"-fixit-at">, MetaVarName<"source-location">,
HelpText<"Perform Fix-It modifications at the given source location">;
def o : Separate<"-o">, MetaVarName<"path">, HelpText<"Specify output file">;
def plugin : Separate<"-plugin">,
HelpText<"Use the named plugin action (use \"help\" to list available options)">;
def Action_Group : OptionGroup<"<action group>">;
let Group = Action_Group in {
def Eonly : Flag<"-Eonly">,
HelpText<"Just run preprocessor, no output (for timings)">;
def E : Flag<"-E">,
HelpText<"Run preprocessor, emit preprocessed file">;
def dump_raw_tokens : Flag<"-dump-raw-tokens">,
HelpText<"Lex file in raw mode and dump raw tokens">;
def analyze : Flag<"-analyze">,
HelpText<"Run static analysis engine">;
def dump_tokens : Flag<"-dump-tokens">,
HelpText<"Run preprocessor, dump internal rep of tokens">;
def parse_noop : Flag<"-parse-noop">,
HelpText<"Run parser with noop callbacks (for timings)">;
def fsyntax_only : Flag<"-fsyntax-only">,
HelpText<"Run parser and perform semantic analysis">;
def fixit : Flag<"-fixit">,
HelpText<"Apply fix-it advice to the input source">;
def parse_print_callbacks : Flag<"-parse-print-callbacks">,
HelpText<"Run parser and print each callback invoked">;
def emit_html : Flag<"-emit-html">,
HelpText<"Output input source as HTML">;
def ast_print : Flag<"-ast-print">,
HelpText<"Build ASTs and then pretty-print them">;
def ast_print_xml : Flag<"-ast-print-xml">,
HelpText<"Build ASTs and then print them in XML format">;
def ast_dump : Flag<"-ast-dump">,
HelpText<"Build ASTs and then debug dump them">;
def ast_view : Flag<"-ast-view">,
HelpText<"Build ASTs and view them with GraphViz">;
def print_decl_contexts : Flag<"-print-decl-contexts">,
HelpText<"Print DeclContexts and their Decls">;
def dump_record_layouts : Flag<"-dump-record-layouts">,
HelpText<"Dump record layout information">;
def emit_pth : Flag<"-emit-pth">,
HelpText<"Generate pre-tokenized header file">;
def emit_pch : Flag<"-emit-pch">,
HelpText<"Generate pre-compiled header file">;
def S : Flag<"-S">,
HelpText<"Emit native assembly code">;
def emit_llvm : Flag<"-emit-llvm">,
HelpText<"Build ASTs then convert to LLVM, emit .ll file">;
def emit_llvm_bc : Flag<"-emit-llvm-bc">,
HelpText<"Build ASTs then convert to LLVM, emit .bc file">;
def emit_llvm_only : Flag<"-emit-llvm-only">,
HelpText<"Build ASTs and convert to LLVM, discarding output">;
def rewrite_test : Flag<"-rewrite-test">,
HelpText<"Rewriter playground">;
def rewrite_objc : Flag<"-rewrite-objc">,
HelpText<"Rewrite ObjC into C (code rewriter example)">;
def rewrite_macros : Flag<"-rewrite-macros">,
HelpText<"Expand macros without full preprocessing">;
def rewrite_blocks : Flag<"-rewrite-blocks">,
HelpText<"Rewrite Blocks to C">;
}
def relocatable_pch : Flag<"-relocatable-pch">,
HelpText<"Whether to build a relocatable precompiled header">;
def print_stats : Flag<"-print-stats">,
HelpText<"Print performance metrics and statistics">;
def ftime_report : Flag<"-ftime-report">,
HelpText<"Print the amount of time each phase of compilation takes">;
//===----------------------------------------------------------------------===//
// Language Options
//===----------------------------------------------------------------------===//
def fno_builtin : Flag<"-fno-builtin">,
HelpText<"Disable implicit builtin knowledge of functions">;
def faltivec : Flag<"-faltivec">,
HelpText<"Enable AltiVec vector initializer syntax">;
def faccess_control : Flag<"-faccess-control">,
HelpText<"Enable C++ access control">;
def fdollars_in_identifiers : Flag<"-fdollars-in-identifiers">,
HelpText<"Allow '$' in identifiers">;
def femit_all_decls : Flag<"-femit-all-decls">,
HelpText<"Emit all declarations, even if unused">;
def fblocks : Flag<"-fblocks">,
HelpText<"enable the 'blocks' language feature">;
def fheinous_gnu_extensions : Flag<"-fheinous-gnu-extensions">;
def fexceptions : Flag<"-fexceptions">,
HelpText<"Enable support for exception handling">;
def ffreestanding : Flag<"-ffreestanding">,
HelpText<"Assert that the compilation takes place in a freestanding environment">;
def fgnu_runtime : Flag<"-fgnu-runtime">,
HelpText<"Generate output compatible with the standard GNU Objective-C runtime">;
def std_EQ : Joined<"-std=">,
HelpText<"Language standard to compile for">;
def fms_extensions : Flag<"-fms-extensions">,
HelpText<"Accept some non-standard constructs used in Microsoft header files ">;
def main_file_name : Separate<"-main-file-name">,
HelpText<"Main file name to use for debug info">;
def fno_elide_constructors : Flag<"-fno-elide-constructors">,
HelpText<"Disable C++ copy constructor elision">;
def fno_lax_vector_conversions : Flag<"-fno-lax-vector-conversions">,
HelpText<"Disallow implicit conversions between vectors with a different number of elements or different element types">;
def fno_math_errno : Flag<"-fno-math-errno">,
HelpText<"Don't require math functions to respect errno">;
def fno_signed_char : Flag<"-fno-signed-char">,
HelpText<"Char is unsigned">;
def fno_operator_names : Flag<"-fno-operator-names">,
HelpText<"Do not treat C++ operator name keywords as synonyms for operators">;
def fconstant_string_class : Separate<"-fconstant-string-class">,
MetaVarName<"class name">,
HelpText<"Specify the class to use for constant Objective-C string objects.">;
def fobjc_gc : Flag<"-fobjc-gc">,
HelpText<"Enable Objective-C garbage collection">;
def fobjc_gc_only : Flag<"-fobjc-gc-only">,
HelpText<"Use GC exclusively for Objective-C related memory management">;
def print_ivar_layout : Flag<"-print-ivar-layout">,
HelpText<"Enable Objective-C Ivar layout bitmap print trace">;
def fobjc_nonfragile_abi : Flag<"-fobjc-nonfragile-abi">,
HelpText<"enable objective-c's nonfragile abi">;
def ftrapv : Flag<"-ftrapv">,
HelpText<"Trap on integer overflow">;
def pic_level : Separate<"-pic-level">,
HelpText<"-Value for __PIC__">;
def pthread : Flag<"-pthread">,
HelpText<"Support POSIX threads in generated code">;
def fpascal_strings : Flag<"-fpascal-strings">,
HelpText<"Recognize and construct Pascal-style string literals">;
def fno_rtti : Flag<"-fno-rtti">,
HelpText<"Disable generation of rtti information">;
def fshort_wchar : Flag<"-fshort-wchar">,
HelpText<"Force wchar_t to be a short unsigned int">;
def static_define : Flag<"-static-define">,
HelpText<"Should __STATIC__ be defined">;
def stack_protector : Separate<"-stack-protector">,
HelpText<"Enable stack protectors">;
def fvisibility : Separate<"-fvisibility">,
HelpText<"Default symbol visibility">;
def ftemplate_depth : Separate<"-ftemplate-depth">,
HelpText<"Maximum depth of recursive template instantiation">;
def trigraphs : Flag<"-trigraphs">,
HelpText<"Process trigraph sequences">;
def fwritable_strings : Flag<"-fwritable-strings">,
HelpText<"Store string literals as writable data">;
//===----------------------------------------------------------------------===//
// Header Search Options
//===----------------------------------------------------------------------===//
def nostdinc : Flag<"-nostdinc">,
HelpText<"Disable standard #include directories">;
def nobuiltininc : Flag<"-nobuiltininc">,
HelpText<"Disable builtin #include directories">;
def F : JoinedOrSeparate<"-F">, MetaVarName<"directory">,
HelpText<"Add directory to framework include search path">;
def I : JoinedOrSeparate<"-I">, MetaVarName<"directory">,
HelpText<"Add directory to include search path">;
def idirafter : Separate<"-idirafter">, MetaVarName<"directory">,
HelpText<"Add directory to AFTER include search path">;
def iquote : Separate<"-iquote">, MetaVarName<"directory">,
HelpText<"Add directory to QUOTE include search path">;
def isystem : Separate<"-isystem">, MetaVarName<"directory">,
HelpText<"Add directory to SYSTEM include search path">;
def iprefix : Separate<"-iprefix">, MetaVarName<"prefix">,
HelpText<"Set the -iwithprefix/-iwithprefixbefore prefix">;
def iwithprefix : Separate<"-iwithprefix">, MetaVarName<"dir">,
HelpText<"Set directory to SYSTEM include search path with prefix">;
def iwithprefixbefore : Separate<"-iwithprefixbefore">, MetaVarName<"dir">,
HelpText<"Set directory to include search path with prefix">;
def isysroot : Separate<"-isysroot">, MetaVarName<"dir">,
HelpText<"Set the system root directory (usually /)">;
def v : Flag<"-v">, HelpText<"Enable verbose output">;
//===----------------------------------------------------------------------===//
// Preprocessor Options
//===----------------------------------------------------------------------===//
def D : JoinedOrSeparate<"-D">, MetaVarName<"macro">,
HelpText<"Predefine the specified macro">;
def include_ : Separate<"-include">, MetaVarName<"file">, EnumName<"include">,
HelpText<"Include file before parsing">;
def imacros : Separate<"-imacros">, MetaVarName<"file">,
HelpText<"Include macros from file before parsing">;
def include_pch : Separate<"-include-pch">, MetaVarName<"file">,
HelpText<"Include precompiled header file">;
def include_pth : Separate<"-include-pth">, MetaVarName<"file">,
HelpText<"Include file before parsing">;
def token_cache : Separate<"-token-cache">, MetaVarName<"path">,
HelpText<"Use specified token cache file">;
def U : JoinedOrSeparate<"-U">, MetaVarName<"macro">,
HelpText<"Undefine the specified macro">;
def undef : Flag<"-undef">, MetaVarName<"macro">,
HelpText<"undef all system defines">;
//===----------------------------------------------------------------------===//
// Preprocessed Output Options
//===----------------------------------------------------------------------===//
def P : Flag<"-P">,
HelpText<"Disable linemarker output in -E mode">;
def C : Flag<"-C">,
HelpText<"Enable comment output in -E mode">;
def CC : Flag<"-CC">,
HelpText<"Enable comment output in -E mode, even from macro expansions">;
def dM : Flag<"-dM">,
HelpText<"Print macro definitions in -E mode instead of normal output">;
def dD : Flag<"-dD">,
HelpText<"Print macro definitions in -E mode in addition to normal output">;

View File

@ -5,11 +5,11 @@ TABLEGEN_INC_FILES_COMMON = 1
include $(LEVEL)/Makefile.common
$(ObjDir)/Options.inc.tmp : Options.td OptParser.td $(ObjDir)/.dir
$(ObjDir)/Options.inc.tmp : Options.td OptParser.td $(TBLGEN) $(ObjDir)/.dir
$(Echo) "Building Clang Driver Option tables with tblgen"
$(Verb) $(TableGen) -gen-opt-parser-defs -o $(call SYSPATH, $@) $<
$(ObjDir)/CC1Options.inc.tmp : CC1Options.td OptParser.td $(ObjDir)/.dir
$(ObjDir)/CC1Options.inc.tmp : CC1Options.td OptParser.td $(TBLGEN) $(ObjDir)/.dir
$(Echo) "Building Clang CC1 Option tables with tblgen"
$(Verb) $(TableGen) -gen-opt-parser-defs -o $(call SYSPATH, $@) $<

View File

@ -14,14 +14,20 @@
// Define the kinds of options.
class OptionKind<string name, int predecence = 0> {
class OptionKind<string name, int predecence = 0, bit sentinel = 0> {
string Name = name;
// The kind precedence, kinds with lower precedence are matched first.
int Precedence = predecence;
// Indicate a sentinel option.
bit Sentinel = sentinel;
}
// An option group.
def KIND_GROUP : OptionKind<"Group">;
// The input option kind.
def KIND_INPUT : OptionKind<"Input", 1, 1>;
// The unknown option kind.
def KIND_UNKNOWN : OptionKind<"Unknown", 2, 1>;
// A flag with no values.
def KIND_FLAG : OptionKind<"Flag">;
// An option which prefixes its (single) value.
@ -114,3 +120,10 @@ class Flags<list<OptionFlag> flags> { list<OptionFlag> Flags = flags; }
class Group<OptionGroup group> { OptionGroup Group = group; }
class HelpText<string text> { string HelpText = text; }
class MetaVarName<string name> { string MetaVarName = name; }
// Predefined options.
// FIXME: Have generator validate that these appear in correct position (and
// aren't duplicated).
def INPUT : Option<"<input>", KIND_INPUT>, Flags<[DriverOption]>;
def UNKNOWN : Option<"<unknown>", KIND_UNKNOWN>;

View File

@ -22,9 +22,12 @@ namespace driver {
explicit OptSpecifier(bool); // DO NOT IMPLEMENT
public:
OptSpecifier() : ID(0) {}
/*implicit*/ OptSpecifier(unsigned _ID) : ID(_ID) {}
/*implicit*/ OptSpecifier(const Option *Opt);
bool isValid() const { return ID != 0; }
unsigned getID() const { return ID; }
bool operator==(OptSpecifier Opt) const { return ID == Opt.getID(); }

View File

@ -17,8 +17,6 @@ namespace driver {
namespace options {
enum ID {
OPT_INVALID = 0, // This is not an option ID.
OPT_INPUT, // Reserved ID for input option.
OPT_UNKNOWN, // Reserved ID for unknown option.
#define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
HELPTEXT, METAVAR) OPT_##ID,
#include "clang/Driver/Options.inc"

View File

@ -83,6 +83,7 @@ ASTConsumer *CreateBackendConsumer(BackendAction Action,
const LangOptions &Features,
const CodeGenOptions &CodeGenOpts,
const TargetOptions &TargetOpts,
bool TimePasses,
const std::string &ModuleID,
llvm::raw_ostream *OS,
llvm::LLVMContext& C);

View File

@ -22,16 +22,17 @@
#include <string>
namespace clang {
class FileManager;
class FileEntry;
class SourceManager;
class Diagnostic;
class TextDiagnosticBuffer;
class HeaderSearch;
class TargetInfo;
class Preprocessor;
class ASTContext;
class Decl;
class ASTContext;
class CompilerInvocation;
class Decl;
class Diagnostic;
class FileEntry;
class FileManager;
class HeaderSearch;
class Preprocessor;
class SourceManager;
class TargetInfo;
class TextDiagnosticBuffer;
using namespace idx;
@ -92,21 +93,35 @@ class ASTUnit {
///
/// \param Filename - The PCH file to load.
///
/// \param diagClient - The diagnostics client to use. Specify NULL
/// \param DiagClient - The diagnostics client to use. Specify NULL
/// to use a default client that emits warnings/errors to standard error.
/// The ASTUnit objects takes ownership of this object.
///
/// \param FileMgr - The FileManager to use.
///
/// \param ErrMsg - Error message to report if the PCH file could not be
/// loaded.
///
/// \returns - The initialized ASTUnit or null if the PCH failed to load.
static ASTUnit *LoadFromPCHFile(const std::string &Filename,
std::string *ErrMsg = 0,
DiagnosticClient *diagClient = NULL,
DiagnosticClient *DiagClient = NULL,
bool OnlyLocalDecls = false,
bool UseBumpAllocator = false);
/// LoadFromCompilerInvocation - Create an ASTUnit from a source file, via a
/// CompilerInvocation object.
///
/// \param CI - The compiler invocation to use; it must have exactly one input
/// source file.
///
/// \param Diags - The diagnostics engine to use for reporting errors.
//
// FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we
// shouldn't need to specify them at construction time.
static ASTUnit *LoadFromCompilerInvocation(const CompilerInvocation &CI,
Diagnostic &Diags,
bool OnlyLocalDecls = false,
bool UseBumpAllocator = false);
};
} // namespace clang

View File

@ -77,7 +77,7 @@ class AnalyzerOptions {
AnalyzeAll = 0;
AnalyzerDisplayProgress = 0;
EagerlyAssume = 0;
PurgeDead = 0;
PurgeDead = 1;
TrimGraph = 0;
VisualizeEGDot = 0;
VisualizeEGUbi = 0;

View File

@ -16,7 +16,7 @@
#define LLVM_CLANG_FRONTEND_COMMANDLINESOURCELOC_H
#include "llvm/Support/CommandLine.h"
#include <cstdio>
#include "llvm/Support/raw_ostream.h"
namespace clang {
@ -25,6 +25,23 @@ struct ParsedSourceLocation {
std::string FileName;
unsigned Line;
unsigned Column;
public:
/// Construct a parsed source location from a string; the Filename is empty on
/// error.
static ParsedSourceLocation FromString(llvm::StringRef Str) {
ParsedSourceLocation PSL;
std::pair<llvm::StringRef, llvm::StringRef> ColSplit = Str.rsplit(':');
std::pair<llvm::StringRef, llvm::StringRef> LineSplit =
ColSplit.first.rsplit(':');
// If both tail splits were valid integers, return success.
if (!ColSplit.second.getAsInteger(10, PSL.Column) &&
!LineSplit.second.getAsInteger(10, PSL.Line))
PSL.FileName = LineSplit.first;
return PSL;
}
};
}
@ -48,35 +65,13 @@ namespace llvm {
clang::ParsedSourceLocation &Val) {
using namespace clang;
const char *ExpectedFormat
= "source location must be of the form filename:line:column";
StringRef::size_type SecondColon = ArgValue.rfind(':');
if (SecondColon == std::string::npos) {
std::fprintf(stderr, "%s\n", ExpectedFormat);
Val = ParsedSourceLocation::FromString(ArgValue);
if (Val.FileName.empty()) {
errs() << "error: "
<< "source location must be of the form filename:line:column\n";
return true;
}
unsigned Column;
if (ArgValue.substr(SecondColon + 1).getAsInteger(10, Column)) {
std::fprintf(stderr, "%s\n", ExpectedFormat);
return true;
}
ArgValue = ArgValue.substr(0, SecondColon);
StringRef::size_type FirstColon = ArgValue.rfind(':');
if (FirstColon == std::string::npos) {
std::fprintf(stderr, "%s\n", ExpectedFormat);
return true;
}
unsigned Line;
if (ArgValue.substr(FirstColon + 1).getAsInteger(10, Line)) {
std::fprintf(stderr, "%s\n", ExpectedFormat);
return true;
}
Val.FileName = ArgValue.substr(0, FirstColon);
Val.Line = Line;
Val.Column = Column;
return false;
}
}

View File

@ -21,6 +21,7 @@ namespace llvm {
class LLVMContext;
class raw_ostream;
class raw_fd_ostream;
class Timer;
}
namespace clang {
@ -89,6 +90,9 @@ class CompilerInstance {
/// The code completion consumer.
llvm::OwningPtr<CodeCompleteConsumer> CompletionConsumer;
/// The frontend timer
llvm::OwningPtr<llvm::Timer> FrontendTimer;
/// The list of active output files.
std::list< std::pair<std::string, llvm::raw_ostream*> > OutputFiles;
@ -366,6 +370,17 @@ class CompilerInstance {
/// the compiler instance takes ownership of \arg Value.
void setCodeCompletionConsumer(CodeCompleteConsumer *Value);
/// }
/// @name Frontend timer
/// {
bool hasFrontendTimer() const { return FrontendTimer != 0; }
llvm::Timer &getFrontendTimer() const {
assert(FrontendTimer && "Compiler instance has no frontend timer!");
return *FrontendTimer;
}
/// }
/// @name Output Files
/// {
@ -462,6 +477,9 @@ class CompilerInstance {
bool UseDebugPrinter, bool ShowMacros,
llvm::raw_ostream &OS);
/// Create the frontend timer and replace any existing one with it.
void createFrontendTimer();
/// Create the default output file (from the invocation's options) and add it
/// to the list of tracked output files.
llvm::raw_fd_ostream *

View File

@ -31,6 +31,8 @@ namespace llvm {
namespace clang {
class Diagnostic;
/// CompilerInvocation - Helper class for holding the data necessary to invoke
/// the compiler.
///
@ -77,12 +79,18 @@ class CompilerInvocation {
/// CreateFromArgs - Create a compiler invocation from a list of input
/// options.
///
/// FIXME: Documenting error behavior.
///
/// \param Res [out] - The resulting invocation.
/// \param Args - The input argument strings.
static void CreateFromArgs(CompilerInvocation &Res,
const llvm::SmallVectorImpl<llvm::StringRef> &Args);
/// \param ArgBegin - The first element in the argument vector.
/// \param ArgEnd - The last element in the argument vector.
/// \param Argv0 - The program path (from argv[0]), for finding the builtin
/// compiler path.
/// \param MainAddr - The address of main (or some other function in the main
/// executable), for finding the builtin compiler path.
/// \param Diags - The diagnostic engine to use for errors.
static void CreateFromArgs(CompilerInvocation &Res, const char **ArgBegin,
const char **ArgEnd, const char *Argv0,
void *MainAddr,
Diagnostic &Diags);
/// toArgs - Convert the CompilerInvocation to a list of strings suitable for
/// passing to CreateFromArgs.

View File

@ -7,46 +7,46 @@
//
//===----------------------------------------------------------------------===//
//
// This file defines the XML statement database structure as written in
// <TranslationUnit> sub-nodes of the XML document.
// This file defines the XML statement database structure as written in
// <TranslationUnit> sub-nodes of the XML document.
// The semantics of the attributes and enums are mostly self-documenting
// by looking at the appropriate internally used functions and values.
// The following macros are used:
//
// NODE_XML( CLASS, NAME ) - A node of name NAME denotes a concrete
// statement of class CLASS where CLASS is a class name used internally by clang.
// After a NODE_XML the definition of all (optional) attributes of that statement
// NODE_XML( CLASS, NAME ) - A node of name NAME denotes a concrete
// statement of class CLASS where CLASS is a class name used internally by clang.
// After a NODE_XML the definition of all (optional) attributes of that statement
// node and possible sub-nodes follows.
//
// END_NODE_XML - Closes the attribute definition of the current node.
//
// ID_ATTRIBUTE_XML - Some statement nodes have an "id" attribute containing a
// string, which value uniquely identify that statement. Other nodes may refer
// ID_ATTRIBUTE_XML - Some statement nodes have an "id" attribute containing a
// string, which value uniquely identify that statement. Other nodes may refer
// by reference attributes to this value (currently used only for Label).
//
// TYPE_ATTRIBUTE_XML( FN ) - Type nodes refer to the result type id of an
// expression by a "type" attribute. FN is internally used by clang.
//
// ATTRIBUTE_XML( FN, NAME ) - An attribute named NAME. FN is internally
//
// ATTRIBUTE_XML( FN, NAME ) - An attribute named NAME. FN is internally
// used by clang. A boolean attribute have the values "0" or "1".
//
// ATTRIBUTE_SPECIAL_XML( FN, NAME ) - An attribute named NAME which deserves
// a special handling. See the appropriate documentations.
// ATTRIBUTE_SPECIAL_XML( FN, NAME ) - An attribute named NAME which deserves
// a special handling. See the appropriate documentations.
//
// ATTRIBUTE_FILE_LOCATION_XML - A bunch of attributes denoting the location of
// a statement in the source file(s).
//
// ATTRIBUTE_OPT_XML( FN, NAME ) - An optional attribute named NAME.
// Optional attributes are omitted for boolean types, if the value is false,
// for integral types, if the value is null and for strings,
// ATTRIBUTE_OPT_XML( FN, NAME ) - An optional attribute named NAME.
// Optional attributes are omitted for boolean types, if the value is false,
// for integral types, if the value is null and for strings,
// if the value is the empty string. FN is internally used by clang.
//
// ATTRIBUTE_ENUM[_OPT]_XML( FN, NAME ) - An attribute named NAME. The value
// is an enumeration defined with ENUM_XML macros immediately following after
// that macro. An optional attribute is ommited, if the particular enum is the
// is an enumeration defined with ENUM_XML macros immediately following after
// that macro. An optional attribute is ommited, if the particular enum is the
// empty string. FN is internally used by clang.
//
// ENUM_XML( VALUE, NAME ) - An enumeration element named NAME. VALUE is
//
// ENUM_XML( VALUE, NAME ) - An enumeration element named NAME. VALUE is
// internally used by clang.
//
// END_ENUM_XML - Closes the enumeration definition of the current attribute.
@ -55,7 +55,7 @@
//
// SUB_NODE_OPT_XML( CLASS ) - An optional sub-node of class CLASS or its sub-classes.
//
// SUB_NODE_SEQUENCE_XML( CLASS ) - Zero or more sub-nodes of class CLASS or
// SUB_NODE_SEQUENCE_XML( CLASS ) - Zero or more sub-nodes of class CLASS or
// its sub-classes.
//
//===----------------------------------------------------------------------===//
@ -114,8 +114,8 @@ NODE_XML(CXXMethodDecl, "CXXMethodDecl")
TYPE_ATTRIBUTE_XML(getType()->getAs<FunctionType>()->getResultType())
ATTRIBUTE_XML(getType()->getAs<FunctionType>(), "function_type")
ATTRIBUTE_OPT_XML(isInlineSpecified(), "inline")
ATTRIBUTE_OPT_XML(isStatic(), "static")
ATTRIBUTE_OPT_XML(isVirtual(), "virtual")
ATTRIBUTE_OPT_XML(isStatic(), "static")
ATTRIBUTE_OPT_XML(isVirtual(), "virtual")
ATTRIBUTE_XML(getNumParams(), "num_args")
SUB_NODE_SEQUENCE_XML(ParmVarDecl)
//SUB_NODE_OPT_XML("Body")
@ -124,7 +124,7 @@ END_NODE_XML
//NODE_XML("Body")
// SUB_NODE_XML(Stmt)
//END_NODE_XML
NODE_XML(NamespaceDecl, "Namespace")
ID_ATTRIBUTE_XML
ATTRIBUTE_FILE_LOCATION_XML
@ -152,7 +152,7 @@ NODE_XML(RecordDecl, "Record")
ATTRIBUTE_XML(getDeclContext(), "context")
ATTRIBUTE_XML(getNameAsString(), "name")
ATTRIBUTE_OPT_XML(isDefinition() == false, "forward")
ATTRIBUTE_XML(getTypeForDecl(), "type") // refers to the type this decl creates
ATTRIBUTE_XML(getTypeForDecl(), "type") // refers to the type this decl creates
SUB_NODE_SEQUENCE_XML(FieldDecl)
END_NODE_XML
@ -162,7 +162,7 @@ NODE_XML(EnumDecl, "Enum")
ATTRIBUTE_XML(getDeclContext(), "context")
ATTRIBUTE_XML(getNameAsString(), "name")
ATTRIBUTE_OPT_XML(isDefinition() == false, "forward")
ATTRIBUTE_SPECIAL_XML(getIntegerType(), "type") // is NULL in pure declarations thus deserves special handling
ATTRIBUTE_SPECIAL_XML(getIntegerType(), "type") // is NULL in pure declarations thus deserves special handling
SUB_NODE_SEQUENCE_XML(EnumConstantDecl) // only present in definition
END_NODE_XML
@ -209,7 +209,7 @@ NODE_XML(VarDecl, "Var")
ENUM_XML(VarDecl::Static, "static")
ENUM_XML(VarDecl::PrivateExtern, "__private_extern__")
END_ENUM_XML
SUB_NODE_OPT_XML(Expr) // init expr
SUB_NODE_OPT_XML(Expr) // init expr
END_NODE_XML
NODE_XML(ParmVarDecl, "ParmVar")
@ -218,7 +218,7 @@ NODE_XML(ParmVarDecl, "ParmVar")
ATTRIBUTE_XML(getDeclContext(), "context")
ATTRIBUTE_XML(getNameAsString(), "name")
TYPE_ATTRIBUTE_XML(getType())
SUB_NODE_OPT_XML(Expr) // default argument expression
SUB_NODE_OPT_XML(Expr) // default argument expression
END_NODE_XML
NODE_XML(LinkageSpecDecl, "LinkageSpec")
@ -234,7 +234,7 @@ END_NODE_XML
//===----------------------------------------------------------------------===//
#undef NODE_XML
#undef ID_ATTRIBUTE_XML
#undef ID_ATTRIBUTE_XML
#undef TYPE_ATTRIBUTE_XML
#undef ATTRIBUTE_XML
#undef ATTRIBUTE_SPECIAL_XML
@ -243,8 +243,8 @@ END_NODE_XML
#undef ATTRIBUTE_ENUM_OPT_XML
#undef ATTRIBUTE_FILE_LOCATION_XML
#undef ENUM_XML
#undef END_ENUM_XML
#undef END_NODE_XML
#undef END_ENUM_XML
#undef END_NODE_XML
#undef SUB_NODE_XML
#undef SUB_NODE_SEQUENCE_XML
#undef SUB_NODE_OPT_XML

View File

@ -14,10 +14,6 @@
#include "llvm/ADT/OwningPtr.h"
#include <string>
namespace llvm {
class Timer;
}
namespace clang {
class ASTUnit;
class ASTConsumer;
@ -29,7 +25,6 @@ class FrontendAction {
std::string CurrentFile;
llvm::OwningPtr<ASTUnit> CurrentASTUnit;
CompilerInstance *Instance;
llvm::Timer *CurrentTimer;
protected:
/// @name Implementation Action Interface
@ -111,18 +106,6 @@ class FrontendAction {
void setCurrentFile(llvm::StringRef Value, ASTUnit *AST = 0);
/// @}
/// @name Timing Utilities
/// @{
llvm::Timer *getCurrentTimer() const {
return CurrentTimer;
}
void setCurrentTimer(llvm::Timer *Value) {
CurrentTimer = Value;
}
/// @}
/// @name Supported Modes
/// @{

View File

@ -107,7 +107,7 @@ class FrontendOptions {
public:
FrontendOptions() {
DebugCodeCompletionPrinter = 0;
DebugCodeCompletionPrinter = 1;
DisableFree = 0;
EmptyInputOnly = 0;
ProgramAction = frontend::ParseSyntaxOnly;

View File

@ -0,0 +1,83 @@
//===--- LangStandard.h -----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_FRONTEND_LANGSTANDARD_H
#define LLVM_CLANG_FRONTEND_LANGSTANDARD_H
#include "llvm/ADT/StringRef.h"
namespace clang {
namespace frontend {
enum LangFeatures {
BCPLComment = (1 << 0),
C99 = (1 << 1),
CPlusPlus = (1 << 2),
CPlusPlus0x = (1 << 3),
Digraphs = (1 << 4),
GNUMode = (1 << 5),
HexFloat = (1 << 6),
ImplicitInt = (1 << 7)
};
}
/// LangStandard - Information about the properties of a particular language
/// standard.
struct LangStandard {
enum Kind {
#define LANGSTANDARD(id, name, desc, features) \
lang_##id,
#include "clang/Frontend/LangStandards.def"
lang_unspecified
};
const char *ShortName;
const char *Description;
unsigned Flags;
public:
/// getName - Get the name of this standard.
const char *getName() const { return ShortName; }
/// getDescription - Get the description of this standard.
const char *getDescription() const { return Description; }
/// hasBCPLComments - Language supports '//' comments.
bool hasBCPLComments() const { return Flags & frontend::BCPLComment; }
/// isC99 - Language is a superset of C99.
bool isC99() const { return Flags & frontend::C99; }
/// isCPlusPlus - Language is a C++ variant.
bool isCPlusPlus() const { return Flags & frontend::CPlusPlus; }
/// isCPlusPlus0x - Language is a C++0x variant.
bool isCPlusPlus0x() const { return Flags & frontend::CPlusPlus0x; }
/// hasDigraphs - Language supports digraphs.
bool hasDigraphs() const { return Flags & frontend::Digraphs; }
/// isGNUMode - Language includes GNU extensions.
bool isGNUMode() const { return Flags & frontend::GNUMode; }
/// hasHexFloats - Language supports hexadecimal float constants.
bool hasHexFloats() const { return Flags & frontend::HexFloat; }
/// hasImplicitInt - Language allows variables to be typed as int implicitly.
bool hasImplicitInt() const { return Flags & frontend::ImplicitInt; }
static const LangStandard &getLangStandardForKind(Kind K);
static const LangStandard *getLangStandardForName(llvm::StringRef Name);
};
} // end namespace clang
#endif

View File

@ -0,0 +1,83 @@
//===-- LangStandards.def - Language Standard Data --------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LANGSTANDARD
#error "LANGSTANDARD must be defined before including this file"
#endif
/// LANGSTANDARD(IDENT, NAME, DESC, FEATURES)
///
/// \param IDENT - The name of the standard as a C++ identifier.
/// \param NAME - The name of the standard.
/// \param DESC - A short description of the standard.
/// \param FEATURES - The standard features as flags, these are enums from the
/// clang::frontend namespace, which is assumed to be be available.
// C89-ish modes.
LANGSTANDARD(c89, "c89",
"ISO C 1990",
ImplicitInt)
LANGSTANDARD(c90, "c90",
"ISO C 1990",
ImplicitInt)
LANGSTANDARD(iso9899_1990, "iso9899:1990",
"ISO C 1990",
ImplicitInt)
LANGSTANDARD(c94, "iso9899:199409",
"ISO C 1990 with amendment 1",
Digraphs | ImplicitInt)
LANGSTANDARD(gnu89, "gnu89",
"ISO C 1990 with GNU extensions",
BCPLComment | Digraphs | GNUMode | ImplicitInt)
// C99-ish modes
LANGSTANDARD(c99, "c99",
"ISO C 1999",
BCPLComment | C99 | Digraphs | HexFloat)
LANGSTANDARD(c9x, "c9x",
"ISO C 1999",
BCPLComment | C99 | Digraphs | HexFloat)
LANGSTANDARD(iso9899_1999,
"iso9899:1999", "ISO C 1999",
BCPLComment | C99 | Digraphs | HexFloat)
LANGSTANDARD(iso9899_199x,
"iso9899:199x", "ISO C 1999",
BCPLComment | C99 | Digraphs | HexFloat)
LANGSTANDARD(gnu99, "gnu99",
"ISO C 1999 with GNU extensions",
BCPLComment | C99 | Digraphs | GNUMode | HexFloat | Digraphs)
LANGSTANDARD(gnu9x, "gnu9x",
"ISO C 1999 with GNU extensions",
BCPLComment | C99 | Digraphs | GNUMode | HexFloat)
// C++ modes
LANGSTANDARD(cxx98, "c++98",
"ISO C++ 1998 with amendments",
BCPLComment | CPlusPlus | Digraphs)
LANGSTANDARD(gnucxx98, "gnu++98",
"ISO C++ 1998 with " "amendments and GNU extensions",
BCPLComment | CPlusPlus | Digraphs | GNUMode)
LANGSTANDARD(cxx0x, "c++0x",
"Upcoming ISO C++ 200x with amendments",
BCPLComment | CPlusPlus | CPlusPlus0x | Digraphs)
LANGSTANDARD(gnucxx0x, "gnu++0x",
"Upcoming ISO C++ 200x with amendments and GNU extensions",
BCPLComment | CPlusPlus | CPlusPlus0x | Digraphs | GNUMode)
// OpenCL
LANGSTANDARD(opencl, "cl",
"OpenCL 1.0",
BCPLComment | C99 | Digraphs | HexFloat)
#undef LANGSTANDARD

View File

@ -336,7 +336,9 @@ namespace clang {
/// \brief The ObjC 'id' type.
PREDEF_TYPE_OBJC_ID = 26,
/// \brief The ObjC 'Class' type.
PREDEF_TYPE_OBJC_CLASS = 27
PREDEF_TYPE_OBJC_CLASS = 27,
/// \brief The ObjC 'SEL' type.
PREDEF_TYPE_OBJC_SEL = 28
};
/// \brief The number of predefined type IDs that are reserved for
@ -438,7 +440,9 @@ namespace clang {
/// \brief Block descriptor type for Blocks CodeGen
SPECIAL_TYPE_BLOCK_DESCRIPTOR = 12,
/// \brief Block extedned descriptor type for Blocks CodeGen
SPECIAL_TYPE_BLOCK_EXTENDED_DESCRIPTOR = 13
SPECIAL_TYPE_BLOCK_EXTENDED_DESCRIPTOR = 13,
/// \brief Objective-C "SEL" redefinition type
SPECIAL_TYPE_OBJC_SEL_REDEFINITION = 14
};
/// \brief Record codes for each kind of declaration.

View File

@ -14,9 +14,7 @@
#ifndef LLVM_CLANG_FRONTEND_PATH_DIAGNOSTIC_CLIENTS_H
#define LLVM_CLANG_FRONTEND_PATH_DIAGNOSTIC_CLiENTS_H
#include <memory>
#include <string>
#include "llvm/ADT/SmallVector.h"
namespace clang {

View File

@ -7,46 +7,46 @@
//
//===----------------------------------------------------------------------===//
//
// This file defines the XML statement database structure as written in
// <TranslationUnit> sub-nodes of the XML document.
// This file defines the XML statement database structure as written in
// <TranslationUnit> sub-nodes of the XML document.
// The semantics of the attributes and enums are mostly self-documenting
// by looking at the appropriate internally used functions and values.
// The following macros are used:
//
// NODE_XML( CLASS, NAME ) - A node of name NAME denotes a concrete
// statement of class CLASS where CLASS is a class name used internally by clang.
// After a NODE_XML the definition of all (optional) attributes of that statement
// NODE_XML( CLASS, NAME ) - A node of name NAME denotes a concrete
// statement of class CLASS where CLASS is a class name used internally by clang.
// After a NODE_XML the definition of all (optional) attributes of that statement
// node and possible sub-nodes follows.
//
// END_NODE_XML - Closes the attribute definition of the current node.
//
// ID_ATTRIBUTE_XML - Some statement nodes have an "id" attribute containing a
// string, which value uniquely identify that statement. Other nodes may refer
// ID_ATTRIBUTE_XML - Some statement nodes have an "id" attribute containing a
// string, which value uniquely identify that statement. Other nodes may refer
// by reference attributes to this value (currently used only for Label).
//
// TYPE_ATTRIBUTE_XML( FN ) - Type nodes refer to the result type id of an
// expression by a "type" attribute. FN is internally used by clang.
//
// ATTRIBUTE_XML( FN, NAME ) - An attribute named NAME. FN is internally
//
// ATTRIBUTE_XML( FN, NAME ) - An attribute named NAME. FN is internally
// used by clang. A boolean attribute have the values "0" or "1".
//
// ATTRIBUTE_SPECIAL_XML( FN, NAME ) - An attribute named NAME which deserves
// a special handling. See the appropriate documentations.
// ATTRIBUTE_SPECIAL_XML( FN, NAME ) - An attribute named NAME which deserves
// a special handling. See the appropriate documentations.
//
// ATTRIBUTE_FILE_LOCATION_XML - A bunch of attributes denoting the location of
// a statement in the source file(s).
//
// ATTRIBUTE_OPT_XML( FN, NAME ) - An optional attribute named NAME.
// Optional attributes are omitted for boolean types, if the value is false,
// for integral types, if the value is null and for strings,
// ATTRIBUTE_OPT_XML( FN, NAME ) - An optional attribute named NAME.
// Optional attributes are omitted for boolean types, if the value is false,
// for integral types, if the value is null and for strings,
// if the value is the empty string. FN is internally used by clang.
//
// ATTRIBUTE_ENUM[_OPT]_XML( FN, NAME ) - An attribute named NAME. The value
// is an enumeration defined with ENUM_XML macros immediately following after
// that macro. An optional attribute is ommited, if the particular enum is the
// is an enumeration defined with ENUM_XML macros immediately following after
// that macro. An optional attribute is ommited, if the particular enum is the
// empty string. FN is internally used by clang.
//
// ENUM_XML( VALUE, NAME ) - An enumeration element named NAME. VALUE is
//
// ENUM_XML( VALUE, NAME ) - An enumeration element named NAME. VALUE is
// internally used by clang.
//
// END_ENUM_XML - Closes the enumeration definition of the current attribute.
@ -55,7 +55,7 @@
//
// SUB_NODE_OPT_XML( CLASS ) - An optional sub-node of class CLASS or its sub-classes.
//
// SUB_NODE_SEQUENCE_XML( CLASS ) - Zero or more sub-nodes of class CLASS or
// SUB_NODE_SEQUENCE_XML( CLASS ) - Zero or more sub-nodes of class CLASS or
// its sub-classes.
//
//===----------------------------------------------------------------------===//
@ -94,21 +94,21 @@ END_NODE_XML
NODE_XML(CaseStmt, "CaseStmt") // case expr: body;
ATTRIBUTE_FILE_LOCATION_XML
SUB_NODE_XML(Stmt) // body
SUB_NODE_XML(Stmt) // body
SUB_NODE_XML(Expr) // expr
SUB_NODE_XML(Expr) // rhs expr in gc extension: case expr .. expr: body;
END_NODE_XML
NODE_XML(DefaultStmt, "DefaultStmt") // default: body;
ATTRIBUTE_FILE_LOCATION_XML
SUB_NODE_XML(Stmt) // body
SUB_NODE_XML(Stmt) // body
END_NODE_XML
NODE_XML(LabelStmt, "LabelStmt") // Label: body;
ID_ATTRIBUTE_XML
ATTRIBUTE_FILE_LOCATION_XML
ATTRIBUTE_XML(getName(), "name") // string
SUB_NODE_XML(Stmt) // body
SUB_NODE_XML(Stmt) // body
END_NODE_XML
NODE_XML(IfStmt, "IfStmt") // if (cond) stmt1; else stmt2;
@ -173,23 +173,23 @@ NODE_XML(AsmStmt, "AsmStmt") // GNU inline-assembly sta
// FIXME
END_NODE_XML
NODE_XML(DeclStmt, "DeclStmt") // a declaration statement
NODE_XML(DeclStmt, "DeclStmt") // a declaration statement
ATTRIBUTE_FILE_LOCATION_XML
SUB_NODE_SEQUENCE_XML(Decl)
SUB_NODE_SEQUENCE_XML(Decl)
END_NODE_XML
// C++ statements
NODE_XML(CXXTryStmt, "CXXTryStmt") // try CompoundStmt CXXCatchStmt1 CXXCatchStmt2 ..
ATTRIBUTE_FILE_LOCATION_XML
ATTRIBUTE_XML(getNumHandlers(), "num_handlers")
SUB_NODE_XML(CompoundStmt)
SUB_NODE_SEQUENCE_XML(CXXCatchStmt)
SUB_NODE_XML(CompoundStmt)
SUB_NODE_SEQUENCE_XML(CXXCatchStmt)
END_NODE_XML
NODE_XML(CXXCatchStmt, "CXXCatchStmt") // catch (decl) Stmt
ATTRIBUTE_FILE_LOCATION_XML
SUB_NODE_XML(VarDecl)
SUB_NODE_XML(Stmt)
SUB_NODE_XML(Stmt)
END_NODE_XML
// Expressions
@ -234,7 +234,7 @@ NODE_XML(StringLiteral, "StringLiteral")
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
ATTRIBUTE_SPECIAL_XML(getStrData(), "value") // string, special handling for escaping needed
ATTRIBUTE_OPT_XML(isWide(), "is_wide") // boolean
ATTRIBUTE_OPT_XML(isWide(), "is_wide") // boolean
END_NODE_XML
NODE_XML(UnaryOperator, "UnaryOperator") // op(expr) or (expr)op
@ -251,7 +251,7 @@ NODE_XML(UnaryOperator, "UnaryOperator") // op(expr) or (expr)op
ENUM_XML(UnaryOperator::Minus, "minus")
ENUM_XML(UnaryOperator::Not, "not") // bitwise not
ENUM_XML(UnaryOperator::LNot, "lnot") // boolean not
ENUM_XML(UnaryOperator::Real, "__real")
ENUM_XML(UnaryOperator::Real, "__real")
ENUM_XML(UnaryOperator::Imag, "__imag")
ENUM_XML(UnaryOperator::Extension, "__extension__")
ENUM_XML(UnaryOperator::OffsetOf, "__builtin_offsetof")
@ -314,7 +314,7 @@ END_NODE_XML
NODE_XML(SizeOfAlignOfExpr, "SizeOfAlignOfExpr") // sizeof(expr) or alignof(expr)
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
ATTRIBUTE_XML(isSizeOf(), "is_sizeof")
ATTRIBUTE_XML(isSizeOf(), "is_sizeof")
ATTRIBUTE_XML(isArgumentType(), "is_type") // "1" if expr denotes a type
ATTRIBUTE_SPECIAL_XML(getArgumentType(), "type_ref") // optional, denotes the type of expr, if is_type=="1", special handling needed since getArgumentType() could assert
SUB_NODE_OPT_XML(Expr) // expr, if is_type=="0"
@ -346,29 +346,29 @@ END_NODE_XML
NODE_XML(CStyleCastExpr, "CStyleCastExpr") // (type)expr
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
TYPE_ATTRIBUTE_XML(getType())
ATTRIBUTE_XML(getTypeAsWritten(), "type_ref") // denotes the type as written in the source code
SUB_NODE_XML(Expr) // expr
END_NODE_XML
NODE_XML(ImplicitCastExpr, "ImplicitCastExpr")
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
SUB_NODE_XML(Expr)
TYPE_ATTRIBUTE_XML(getType())
SUB_NODE_XML(Expr)
END_NODE_XML
NODE_XML(CompoundLiteralExpr, "CompoundLiteralExpr") // [C99 6.5.2.5]
NODE_XML(CompoundLiteralExpr, "CompoundLiteralExpr") // [C99 6.5.2.5]
SUB_NODE_XML(Expr) // init
END_NODE_XML
NODE_XML(ExtVectorElementExpr, "ExtVectorElementExpr")
SUB_NODE_XML(Expr) // base
SUB_NODE_XML(Expr) // base
END_NODE_XML
NODE_XML(InitListExpr, "InitListExpr") // struct foo x = { expr1, { expr2, expr3 } };
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
ATTRIBUTE_OPT_XML(getInitializedFieldInUnion(), "field_ref") // if a union is initialized, this refers to the initialized union field id
ATTRIBUTE_OPT_XML(getInitializedFieldInUnion(), "field_ref") // if a union is initialized, this refers to the initialized union field id
ATTRIBUTE_XML(getNumInits(), "num_inits") // unsigned
SUB_NODE_SEQUENCE_XML(Expr) // expr1..exprN
END_NODE_XML
@ -412,8 +412,8 @@ END_NODE_XML
NODE_XML(TypesCompatibleExpr, "TypesCompatibleExpr") // GNU builtin-in function __builtin_types_compatible_p
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
ATTRIBUTE_XML(getArgType1(), "type1_ref") // id of type1
ATTRIBUTE_XML(getArgType2(), "type2_ref") // id of type2
ATTRIBUTE_XML(getArgType1(), "type1_ref") // id of type1
ATTRIBUTE_XML(getArgType2(), "type2_ref") // id of type2
END_NODE_XML
NODE_XML(ChooseExpr, "ChooseExpr") // GNU builtin-in function __builtin_choose_expr(expr1, expr2, expr3)
@ -495,16 +495,9 @@ NODE_XML(CXXDefaultArgExpr, "CXXDefaultArgExpr")
ATTRIBUTE_XML(getParam(), "ref") // id of the parameter declaration (the expression is a subnode of the declaration)
END_NODE_XML
NODE_XML(CXXConditionDeclExpr, "CXXConditionDeclExpr")
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
SUB_NODE_XML(VarDecl) // a CXXConditionDeclExpr owns the declaration
END_NODE_XML
//===----------------------------------------------------------------------===//
#undef NODE_XML
#undef ID_ATTRIBUTE_XML
#undef ID_ATTRIBUTE_XML
#undef TYPE_ATTRIBUTE_XML
#undef ATTRIBUTE_XML
#undef ATTRIBUTE_SPECIAL_XML
@ -513,8 +506,8 @@ END_NODE_XML
#undef ATTRIBUTE_ENUM_OPT_XML
#undef ATTRIBUTE_FILE_LOCATION_XML
#undef ENUM_XML
#undef END_ENUM_XML
#undef END_NODE_XML
#undef END_ENUM_XML
#undef END_NODE_XML
#undef SUB_NODE_XML
#undef SUB_NODE_SEQUENCE_XML
#undef SUB_NODE_OPT_XML

View File

@ -41,6 +41,10 @@ class TextDiagnosticBuffer : public DiagnosticClient {
virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
const DiagnosticInfo &Info);
/// FlushDiagnostics - Flush the buffered diagnostics to an given
/// diagnostic engine.
void FlushDiagnostics(Diagnostic &Diags) const;
};
} // end namspace clang

View File

@ -78,7 +78,7 @@ class Lexer : public PreprocessorLexer {
/// with the specified preprocessor managing the lexing process. This lexer
/// assumes that the associated file buffer and Preprocessor objects will
/// outlive it, so it doesn't take ownership of either of them.
Lexer(FileID FID, Preprocessor &PP);
Lexer(FileID FID, const llvm::MemoryBuffer *InputBuffer, Preprocessor &PP);
/// Lexer constructor - Create a new raw lexer object. This object is only
/// suitable for calls to 'LexRawToken'. This lexer assumes that the text
@ -89,7 +89,8 @@ class Lexer : public PreprocessorLexer {
/// Lexer constructor - Create a new raw lexer object. This object is only
/// suitable for calls to 'LexRawToken'. This lexer assumes that the text
/// range will outlive it, so it doesn't take ownership of it.
Lexer(FileID FID, const SourceManager &SM, const LangOptions &Features);
Lexer(FileID FID, const llvm::MemoryBuffer *InputBuffer,
const SourceManager &SM, const LangOptions &Features);
/// Create_PragmaLexer: Lexer constructor - Create a new lexer object for
/// _Pragma expansion. This has a variety of magic semantics that this method

View File

@ -329,9 +329,9 @@ class Preprocessor {
void EnterMainSourceFile();
/// EnterSourceFile - Add a source file to the top of the include stack and
/// start lexing tokens from it instead of the current buffer. If isMainFile
/// is true, this is the main file for the translation unit.
void EnterSourceFile(FileID CurFileID, const DirectoryLookup *Dir);
/// start lexing tokens from it instead of the current buffer. Return true
/// on failure.
bool EnterSourceFile(FileID CurFileID, const DirectoryLookup *Dir);
/// EnterMacro - Add a Macro to the top of the include stack and start lexing
/// tokens from it instead of the current buffer. Args specifies the

View File

@ -203,11 +203,15 @@ class Action : public ActionBase {
/// this occurs when deriving from "std::vector<T>::allocator_type", where T
/// is a template parameter.
///
/// \param ObjectType if we're checking whether an identifier is a type
/// within a C++ member access expression, this will be the type of the
///
/// \returns the type referred to by this identifier, or NULL if the type
/// does not name an identifier.
virtual TypeTy *getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
Scope *S, const CXXScopeSpec *SS = 0,
bool isClassName = false) = 0;
bool isClassName = false,
TypeTy *ObjectType = 0) = 0;
/// isTagName() - This method is called *for error recovery purposes only*
/// to determine if the specified name is a valid tag name ("struct foo"). If
@ -668,6 +672,9 @@ class Action : public ActionBase {
return StmtEmpty();
}
virtual void ActOnForEachDeclStmt(DeclGroupPtrTy Decl) {
}
virtual OwningStmtResult ActOnExprStmt(FullExprArg Expr) {
return OwningStmtResult(*this, Expr->release());
}
@ -698,14 +705,39 @@ class Action : public ActionBase {
return StmtEmpty();
}
/// \brief Parsed an "if" statement.
///
/// \param IfLoc the location of the "if" keyword.
///
/// \param CondVal if the "if" condition was parsed as an expression,
/// the expression itself.
///
/// \param CondVar if the "if" condition was parsed as a condition variable,
/// the condition variable itself.
///
/// \param ThenVal the "then" statement.
///
/// \param ElseLoc the location of the "else" keyword.
///
/// \param ElseVal the "else" statement.
virtual OwningStmtResult ActOnIfStmt(SourceLocation IfLoc,
FullExprArg CondVal, StmtArg ThenVal,
FullExprArg CondVal,
DeclPtrTy CondVar,
StmtArg ThenVal,
SourceLocation ElseLoc,
StmtArg ElseVal) {
return StmtEmpty();
}
virtual OwningStmtResult ActOnStartOfSwitchStmt(ExprArg Cond) {
/// \brief Parsed the start of a "switch" statement.
///
/// \param Cond if the "switch" condition was parsed as an expression,
/// the expression itself.
///
/// \param CondVar if the "switch" condition was parsed as a condition
/// variable, the condition variable itself.
virtual OwningStmtResult ActOnStartOfSwitchStmt(FullExprArg Cond,
DeclPtrTy CondVar) {
return StmtEmpty();
}
@ -714,8 +746,18 @@ class Action : public ActionBase {
return StmtEmpty();
}
/// \brief Parsed a "while" statement.
///
/// \param Cond if the "while" condition was parsed as an expression,
/// the expression itself.
///
/// \param CondVar if the "while" condition was parsed as a condition
/// variable, the condition variable itself.
///
/// \param Body the body of the "while" loop.
virtual OwningStmtResult ActOnWhileStmt(SourceLocation WhileLoc,
FullExprArg Cond, StmtArg Body) {
FullExprArg Cond, DeclPtrTy CondVar,
StmtArg Body) {
return StmtEmpty();
}
virtual OwningStmtResult ActOnDoStmt(SourceLocation DoLoc, StmtArg Body,
@ -725,13 +767,36 @@ class Action : public ActionBase {
SourceLocation CondRParen) {
return StmtEmpty();
}
/// \brief Parsed a "for" statement.
///
/// \param ForLoc the location of the "for" keyword.
///
/// \param LParenLoc the location of the left parentheses.
///
/// \param First the statement used to initialize the for loop.
///
/// \param Second the condition to be checked during each iteration, if
/// that condition was parsed as an expression.
///
/// \param SecondArg the condition variable to be checked during each
/// iterator, if that condition was parsed as a variable declaration.
///
/// \param Third the expression that will be evaluated to "increment" any
/// values prior to the next iteration.
///
/// \param RParenLoc the location of the right parentheses.
///
/// \param Body the body of the "body" loop.
virtual OwningStmtResult ActOnForStmt(SourceLocation ForLoc,
SourceLocation LParenLoc,
StmtArg First, ExprArg Second,
ExprArg Third, SourceLocation RParenLoc,
StmtArg First, FullExprArg Second,
DeclPtrTy SecondVar, FullExprArg Third,
SourceLocation RParenLoc,
StmtArg Body) {
return StmtEmpty();
}
virtual OwningStmtResult ActOnObjCForCollectionStmt(SourceLocation ForColLoc,
SourceLocation LParenLoc,
StmtArg First, ExprArg Second,
@ -852,23 +917,12 @@ class Action : public ActionBase {
/// \brief The parser is entering a new expression evaluation context.
///
/// \param NewContext is the new expression evaluation context.
///
/// \returns the previous expression evaluation context.
virtual ExpressionEvaluationContext
PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext) {
return PotentiallyEvaluated;
}
/// \brief The parser is existing an expression evaluation context.
///
/// \param OldContext the expression evaluation context that the parser is
/// leaving.
///
/// \param NewContext the expression evaluation context that the parser is
/// returning to.
virtual void
PopExpressionEvaluationContext(ExpressionEvaluationContext OldContext,
ExpressionEvaluationContext NewContext) { }
PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext) { }
/// \brief The parser is exiting an expression evaluation context.
virtual void
PopExpressionEvaluationContext() { }
// Primary Expressions.
@ -927,9 +981,10 @@ class Action : public ActionBase {
return move(Val); // Default impl returns operand.
}
virtual OwningExprResult ActOnParenListExpr(SourceLocation L,
virtual OwningExprResult ActOnParenOrParenListExpr(SourceLocation L,
SourceLocation R,
MultiExprArg Val) {
MultiExprArg Val,
TypeTy *TypeOfCast=0) {
return ExprEmpty();
}
@ -1041,6 +1096,10 @@ class Action : public ActionBase {
return ExprEmpty();
}
virtual bool TypeIsVectorType(TypeTy *Ty) {
return false;
}
virtual OwningExprResult ActOnBinOp(Scope *S, SourceLocation TokLoc,
tok::TokenKind Kind,
ExprArg LHS, ExprArg RHS) {
@ -1371,15 +1430,22 @@ class Action : public ActionBase {
return ExprEmpty();
}
/// ActOnCXXConditionDeclarationExpr - Parsed a condition declaration of a
/// C++ if/switch/while/for statement.
/// e.g: "if (int x = f()) {...}"
virtual OwningExprResult ActOnCXXConditionDeclarationExpr(Scope *S,
SourceLocation StartLoc,
Declarator &D,
SourceLocation EqualLoc,
ExprArg AssignExprVal) {
return ExprEmpty();
/// \brief Parsed a condition declaration in a C++ if, switch, or while
/// statement.
///
/// This callback will be invoked after parsing the declaration of "x" in
///
/// \code
/// if (int x = f()) {
/// // ...
/// }
/// \endcode
///
/// \param S the scope of the if, switch, or while statement.
///
/// \param D the declarator that that describes the variable being declared.
virtual DeclResult ActOnCXXConditionDeclaration(Scope *S, Declarator &D) {
return DeclResult();
}
/// ActOnCXXNew - Parsed a C++ 'new' expression. UseGlobal is true if the
@ -1470,6 +1536,7 @@ class Action : public ActionBase {
MultiTemplateParamsArg TemplateParameterLists,
ExprTy *BitfieldWidth,
ExprTy *Init,
bool IsDefinition,
bool Deleted = false) {
return DeclPtrTy();
}
@ -1678,10 +1745,14 @@ class Action : public ActionBase {
/// \param ObjectType if this dependent template name occurs in the
/// context of a member access expression, the type of the object being
/// accessed.
///
/// \param EnteringContext whether we are entering the context of this
/// template.
virtual TemplateTy ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
const CXXScopeSpec &SS,
UnqualifiedId &Name,
TypeTy *ObjectType) {
TypeTy *ObjectType,
bool EnteringContext) {
return TemplateTy();
}
@ -2515,7 +2586,8 @@ class MinimalAction : public Action {
/// does not name an identifier.
virtual TypeTy *getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
Scope *S, const CXXScopeSpec *SS,
bool isClassName = false);
bool isClassName = false,
TypeTy *ObjectType = 0);
/// isCurrentClassName - Always returns false, because MinimalAction
/// does not support C++ classes with constructors.
@ -2578,21 +2650,15 @@ class EnterExpressionEvaluationContext {
/// \brief The action object.
Action &Actions;
/// \brief The previous expression evaluation context.
Action::ExpressionEvaluationContext PrevContext;
/// \brief The current expression evaluation context.
Action::ExpressionEvaluationContext CurContext;
public:
EnterExpressionEvaluationContext(Action &Actions,
Action::ExpressionEvaluationContext NewContext)
: Actions(Actions), CurContext(NewContext) {
PrevContext = Actions.PushExpressionEvaluationContext(NewContext);
: Actions(Actions) {
Actions.PushExpressionEvaluationContext(NewContext);
}
~EnterExpressionEvaluationContext() {
Actions.PopExpressionEvaluationContext(CurContext, PrevContext);
Actions.PopExpressionEvaluationContext();
}
};

View File

@ -33,19 +33,22 @@ namespace clang {
class AttributeList {
IdentifierInfo *AttrName;
SourceLocation AttrLoc;
IdentifierInfo *ScopeName;
SourceLocation ScopeLoc;
IdentifierInfo *ParmName;
SourceLocation ParmLoc;
ActionBase::ExprTy **Args;
unsigned NumArgs;
AttributeList *Next;
bool DeclspecAttribute;
bool DeclspecAttribute, CXX0XAttribute;
AttributeList(const AttributeList &); // DO NOT IMPLEMENT
void operator=(const AttributeList &); // DO NOT IMPLEMENT
public:
AttributeList(IdentifierInfo *AttrName, SourceLocation AttrLoc,
IdentifierInfo *ScopeName, SourceLocation ScopeLoc,
IdentifierInfo *ParmName, SourceLocation ParmLoc,
ActionBase::ExprTy **args, unsigned numargs,
AttributeList *Next, bool declspec = false);
AttributeList *Next, bool declspec = false, bool cxx0x = false);
~AttributeList();
enum Kind { // Please keep this list alphabetized.
@ -56,7 +59,9 @@ class AttributeList {
AT_always_inline,
AT_analyzer_noreturn,
AT_annotate,
AT_base_check,
AT_blocks,
AT_carries_dependency,
AT_cdecl,
AT_cleanup,
AT_const,
@ -67,9 +72,11 @@ class AttributeList {
AT_dllimport,
AT_ext_vector_type,
AT_fastcall,
AT_final,
AT_format,
AT_format_arg,
AT_gnu_inline,
AT_hiding,
AT_malloc,
AT_mode,
AT_nodebug,
@ -80,6 +87,7 @@ class AttributeList {
AT_nothrow,
AT_nsobject,
AT_objc_exception,
AT_override,
AT_cf_returns_retained, // Clang-specific.
AT_ns_returns_retained, // Clang-specific.
AT_objc_gc,
@ -106,8 +114,15 @@ class AttributeList {
IdentifierInfo *getName() const { return AttrName; }
SourceLocation getLoc() const { return AttrLoc; }
bool hasScope() const { return ScopeName; }
IdentifierInfo *getScopeName() const { return ScopeName; }
SourceLocation getScopeLoc() const { return ScopeLoc; }
IdentifierInfo *getParameterName() const { return ParmName; }
bool isDeclspecAttribute() const { return DeclspecAttribute; }
bool isCXX0XAttribute() const { return CXX0XAttribute; }
Kind getKind() const { return getKind(getName()); }
static Kind getKind(const IdentifierInfo *Name);
@ -181,6 +196,22 @@ inline AttributeList* addAttributeLists (AttributeList *Left,
return Left;
}
/// CXX0XAttributeList - A wrapper around a C++0x attribute list.
/// Stores, in addition to the list proper, whether or not an actual list was
/// (as opposed to an empty list, which may be ill-formed in some places) and
/// the source range of the list.
struct CXX0XAttributeList {
AttributeList *AttrList;
SourceRange Range;
bool HasAttr;
CXX0XAttributeList (AttributeList *attrList, SourceRange range, bool hasAttr)
: AttrList(attrList), Range(range), HasAttr (hasAttr) {
}
CXX0XAttributeList ()
: AttrList(0), Range(), HasAttr(false) {
}
};
} // end namespace clang
#endif

View File

@ -484,6 +484,8 @@ class UnqualifiedId {
IK_OperatorFunctionId,
/// \brief A conversion function name, e.g., operator int.
IK_ConversionFunctionId,
/// \brief A user-defined literal name, e.g., operator "" _i.
IK_LiteralOperatorId,
/// \brief A constructor name.
IK_ConstructorName,
/// \brief A destructor name.
@ -495,7 +497,8 @@ class UnqualifiedId {
/// \brief Anonymous union that holds extra data associated with the
/// parsed unqualified-id.
union {
/// \brief When Kind == IK_Identifier, the parsed identifier.
/// \brief When Kind == IK_Identifier, the parsed identifier, or when Kind
/// == IK_UserLiteralId, the identifier suffix.
IdentifierInfo *Identifier;
/// \brief When Kind == IK_OperatorFunctionId, the overloaded operator
@ -607,6 +610,22 @@ class UnqualifiedId {
EndLocation = EndLoc;
ConversionFunctionId = Ty;
}
/// \brief Specific that this unqualified-id was parsed as a
/// literal-operator-id.
///
/// \param Id the parsed identifier.
///
/// \param OpLoc the location of the 'operator' keyword.
///
/// \param IdLoc the location of the identifier.
void setLiteralOperatorId(const IdentifierInfo *Id, SourceLocation OpLoc,
SourceLocation IdLoc) {
Kind = IK_LiteralOperatorId;
Identifier = const_cast<IdentifierInfo *>(Id);
StartLocation = OpLoc;
EndLocation = IdLoc;
}
/// \brief Specify that this unqualified-id was parsed as a constructor name.
///

View File

@ -24,6 +24,7 @@
namespace clang {
class AttributeList;
struct CXX0XAttributeList;
class PragmaHandler;
class Scope;
class DiagnosticBuilder;
@ -753,10 +754,10 @@ class Parser {
//===--------------------------------------------------------------------===//
// C99 6.9: External Definitions.
DeclGroupPtrTy ParseExternalDeclaration();
DeclGroupPtrTy ParseExternalDeclaration(CXX0XAttributeList Attr);
bool isDeclarationAfterDeclarator();
bool isStartOfFunctionDefinition();
DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(
DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(AttributeList *Attr,
AccessSpecifier AS = AS_none);
DeclPtrTy ParseFunctionDefinition(ParsingDeclarator &D,
@ -832,10 +833,10 @@ class Parser {
OwningExprResult ParseCastExpression(bool isUnaryExpression,
bool isAddressOfOperand,
bool &NotCastExpr,
bool parseParenAsExprList);
TypeTy *TypeOfCast);
OwningExprResult ParseCastExpression(bool isUnaryExpression,
bool isAddressOfOperand = false,
bool parseParenAsExprList = false);
TypeTy *TypeOfCast = 0);
OwningExprResult ParsePostfixExpressionSuffix(OwningExprResult LHS);
OwningExprResult ParseSizeofAlignofExpression();
OwningExprResult ParseBuiltinPrimaryExpression();
@ -865,7 +866,7 @@ class Parser {
};
OwningExprResult ParseParenExpression(ParenParseOption &ExprType,
bool stopIfCastExpr,
bool parseAsExprList,
TypeTy *TypeOfCast,
TypeTy *&CastTy,
SourceLocation &RParenLoc);
@ -933,8 +934,8 @@ class Parser {
SourceLocation Start);
//===--------------------------------------------------------------------===//
// C++ if/switch/while/for condition expression.
OwningExprResult ParseCXXCondition();
// C++ if/switch/while condition expression.
bool ParseCXXCondition(OwningExprResult &ExprResult, DeclPtrTy &DeclResult);
//===--------------------------------------------------------------------===//
// C++ types
@ -994,24 +995,23 @@ class Parser {
return ParseStatementOrDeclaration(true);
}
OwningStmtResult ParseStatementOrDeclaration(bool OnlyStatement = false);
OwningStmtResult ParseLabeledStatement();
OwningStmtResult ParseCaseStatement();
OwningStmtResult ParseDefaultStatement();
OwningStmtResult ParseCompoundStatement(bool isStmtExpr = false);
OwningStmtResult ParseLabeledStatement(AttributeList *Attr);
OwningStmtResult ParseCaseStatement(AttributeList *Attr);
OwningStmtResult ParseDefaultStatement(AttributeList *Attr);
OwningStmtResult ParseCompoundStatement(AttributeList *Attr,
bool isStmtExpr = false);
OwningStmtResult ParseCompoundStatementBody(bool isStmtExpr = false);
bool ParseParenExprOrCondition(OwningExprResult &CondExp,
bool OnlyAllowCondition = false,
SourceLocation *LParenLoc = 0,
SourceLocation *RParenLoc = 0);
OwningStmtResult ParseIfStatement();
OwningStmtResult ParseSwitchStatement();
OwningStmtResult ParseWhileStatement();
OwningStmtResult ParseDoStatement();
OwningStmtResult ParseForStatement();
OwningStmtResult ParseGotoStatement();
OwningStmtResult ParseContinueStatement();
OwningStmtResult ParseBreakStatement();
OwningStmtResult ParseReturnStatement();
bool ParseParenExprOrCondition(OwningExprResult &ExprResult,
DeclPtrTy &DeclResult);
OwningStmtResult ParseIfStatement(AttributeList *Attr);
OwningStmtResult ParseSwitchStatement(AttributeList *Attr);
OwningStmtResult ParseWhileStatement(AttributeList *Attr);
OwningStmtResult ParseDoStatement(AttributeList *Attr);
OwningStmtResult ParseForStatement(AttributeList *Attr);
OwningStmtResult ParseGotoStatement(AttributeList *Attr);
OwningStmtResult ParseContinueStatement(AttributeList *Attr);
OwningStmtResult ParseBreakStatement(AttributeList *Attr);
OwningStmtResult ParseReturnStatement(AttributeList *Attr);
OwningStmtResult ParseAsmStatement(bool &msAsm);
OwningStmtResult FuzzyParseMicrosoftAsmStatement();
bool ParseAsmOperandsOpt(llvm::SmallVectorImpl<std::string> &Names,
@ -1021,7 +1021,7 @@ class Parser {
//===--------------------------------------------------------------------===//
// C++ 6: Statements and Blocks
OwningStmtResult ParseCXXTryBlock();
OwningStmtResult ParseCXXTryBlock(AttributeList *Attr);
OwningStmtResult ParseCXXTryBlockCommon(SourceLocation TryLoc);
OwningStmtResult ParseCXXCatchBlock();
@ -1045,9 +1045,11 @@ class Parser {
DSC_class // class context, enables 'friend'
};
DeclGroupPtrTy ParseDeclaration(unsigned Context, SourceLocation &DeclEnd);
DeclGroupPtrTy ParseDeclaration(unsigned Context, SourceLocation &DeclEnd,
CXX0XAttributeList Attr);
DeclGroupPtrTy ParseSimpleDeclaration(unsigned Context,
SourceLocation &DeclEnd);
SourceLocation &DeclEnd,
AttributeList *Attr);
DeclGroupPtrTy ParseDeclGroup(ParsingDeclSpec &DS, unsigned Context,
bool AllowFunctionDefinitions,
SourceLocation *DeclEnd = 0);
@ -1217,11 +1219,14 @@ class Parser {
void ParseBlockId();
// EndLoc, if non-NULL, is filled with the location of the last token of
// the attribute list.
AttributeList *ParseAttributes(SourceLocation *EndLoc = 0);
CXX0XAttributeList ParseCXX0XAttributes(SourceLocation *EndLoc = 0);
AttributeList *ParseGNUAttributes(SourceLocation *EndLoc = 0);
AttributeList *ParseMicrosoftDeclSpec(AttributeList* CurrAttr = 0);
AttributeList *ParseMicrosoftTypeAttributes(AttributeList* CurrAttr = 0);
void ParseTypeofSpecifier(DeclSpec &DS);
void ParseDecltypeSpecifier(DeclSpec &DS);
OwningExprResult ParseCXX0XAlignArgument(SourceLocation Start);
/// DeclaratorScopeObj - RAII object used in Parser::ParseDirectDeclarator to
/// enter a new C++ declarator scope and exit it when the function is
@ -1265,7 +1270,8 @@ class Parser {
typedef void (Parser::*DirectDeclParseFunction)(Declarator&);
void ParseDeclaratorInternal(Declarator &D,
DirectDeclParseFunction DirectDeclParser);
void ParseTypeQualifierListOpt(DeclSpec &DS, bool AttributesAllowed = true);
void ParseTypeQualifierListOpt(DeclSpec &DS, bool GNUAttributesAllowed = true,
bool CXX0XAttributesAllowed = true);
void ParseDirectDeclarator(Declarator &D);
void ParseParenDeclarator(Declarator &D);
void ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
@ -1278,12 +1284,17 @@ class Parser {
//===--------------------------------------------------------------------===//
// C++ 7: Declarations [dcl.dcl]
bool isCXX0XAttributeSpecifier(bool FullLookahead = false,
tok::TokenKind *After = 0);
DeclPtrTy ParseNamespace(unsigned Context, SourceLocation &DeclEnd);
DeclPtrTy ParseLinkage(unsigned Context);
DeclPtrTy ParseUsingDirectiveOrDeclaration(unsigned Context,
SourceLocation &DeclEnd);
SourceLocation &DeclEnd,
CXX0XAttributeList Attrs);
DeclPtrTy ParseUsingDirective(unsigned Context, SourceLocation UsingLoc,
SourceLocation &DeclEnd);
SourceLocation &DeclEnd,
AttributeList *Attr);
DeclPtrTy ParseUsingDeclaration(unsigned Context, SourceLocation UsingLoc,
SourceLocation &DeclEnd,
AccessSpecifier AS = AS_none);
@ -1353,6 +1364,7 @@ class Parser {
SourceLocation &RAngleLoc);
bool ParseTemplateParameterList(unsigned Depth,
TemplateParameterList &TemplateParams);
bool isStartOfTemplateTypeParameter();
DeclPtrTy ParseTemplateParameter(unsigned Depth, unsigned Position);
DeclPtrTy ParseTypeParameter(unsigned Depth, unsigned Position);
DeclPtrTy ParseTemplateTemplateParameter(unsigned Depth, unsigned Position);

View File

@ -209,7 +209,8 @@ class CodeCompletionString {
void Serialize(llvm::raw_ostream &OS) const;
/// \brief Deserialize a code-completion string from the given string.
static CodeCompletionString *Deserialize(llvm::StringRef &Str);
static CodeCompletionString *Deserialize(const char *&Str,
const char *StrEnd);
};
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
@ -221,6 +222,10 @@ class CodeCompleteConsumer {
protected:
/// \brief Whether to include macros in the code-completion results.
bool IncludeMacros;
/// \brief Whether the output format for the code-completion consumer is
/// binary.
bool OutputIsBinary;
public:
/// \brief Captures a result of code completion.
@ -394,17 +399,20 @@ class CodeCompleteConsumer {
Sema &S) const;
};
CodeCompleteConsumer() : IncludeMacros(false) { }
CodeCompleteConsumer() : IncludeMacros(false), OutputIsBinary(false) { }
explicit CodeCompleteConsumer(bool IncludeMacros)
: IncludeMacros(IncludeMacros) { }
CodeCompleteConsumer(bool IncludeMacros, bool OutputIsBinary)
: IncludeMacros(IncludeMacros), OutputIsBinary(OutputIsBinary) { }
/// \brief Whether the code-completion consumer wants to see macros.
bool includeMacros() const { return IncludeMacros; }
/// \brief Determine whether the output of this consumer is binary.
bool isOutputBinary() const { return OutputIsBinary; }
/// \brief Deregisters and destroys this code-completion consumer.
virtual ~CodeCompleteConsumer();
/// \name Code-completion callbacks
//@{
/// \brief Process the finalized code-completion results.
@ -436,7 +444,7 @@ class PrintingCodeCompleteConsumer : public CodeCompleteConsumer {
/// results to the given raw output stream.
PrintingCodeCompleteConsumer(bool IncludeMacros,
llvm::raw_ostream &OS)
: CodeCompleteConsumer(IncludeMacros), OS(OS) { }
: CodeCompleteConsumer(IncludeMacros, false), OS(OS) { }
/// \brief Prints the finalized code-completion results.
virtual void ProcessCodeCompleteResults(Sema &S, Result *Results,
@ -458,7 +466,7 @@ class CIndexCodeCompleteConsumer : public CodeCompleteConsumer {
/// results to the given raw output stream in a format readable to the CIndex
/// library.
CIndexCodeCompleteConsumer(bool IncludeMacros, llvm::raw_ostream &OS)
: CodeCompleteConsumer(IncludeMacros), OS(OS) { }
: CodeCompleteConsumer(IncludeMacros, true), OS(OS) { }
/// \brief Prints the finalized code-completion results.
virtual void ProcessCodeCompleteResults(Sema &S, Result *Results,

View File

@ -48,6 +48,7 @@ ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM,
BuiltinInfo(builtins), ExternalSource(0), PrintingPolicy(LOpts) {
ObjCIdRedefinitionType = QualType();
ObjCClassRedefinitionType = QualType();
ObjCSelRedefinitionType = QualType();
if (size_reserve > 0) Types.reserve(size_reserve);
TUDecl = TranslationUnitDecl::Create(*this);
InitBuiltinTypes();
@ -220,10 +221,12 @@ void ASTContext::InitBuiltinTypes() {
// "Builtin" typedefs set by Sema::ActOnTranslationUnitScope().
ObjCIdTypedefType = QualType();
ObjCClassTypedefType = QualType();
ObjCSelTypedefType = QualType();
// Builtin types for 'id' and 'Class'.
// Builtin types for 'id', 'Class', and 'SEL'.
InitBuiltinType(ObjCBuiltinIdTy, BuiltinType::ObjCId);
InitBuiltinType(ObjCBuiltinClassTy, BuiltinType::ObjCClass);
InitBuiltinType(ObjCBuiltinSelTy, BuiltinType::ObjCSel);
ObjCConstantStringType = QualType();
@ -517,18 +520,23 @@ const llvm::fltSemantics &ASTContext::getFloatTypeSemantics(QualType T) const {
/// getDeclAlignInBytes - Return a conservative estimate of the alignment of the
/// specified decl. Note that bitfields do not have a valid alignment, so
/// this method will assert on them.
unsigned ASTContext::getDeclAlignInBytes(const Decl *D) {
/// If @p RefAsPointee, references are treated like their underlying type
/// (for alignof), else they're treated like pointers (for CodeGen).
unsigned ASTContext::getDeclAlignInBytes(const Decl *D, bool RefAsPointee) {
unsigned Align = Target.getCharWidth();
if (const AlignedAttr* AA = D->getAttr<AlignedAttr>())
Align = std::max(Align, AA->getAlignment());
Align = std::max(Align, AA->getMaxAlignment());
if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
QualType T = VD->getType();
if (const ReferenceType* RT = T->getAs<ReferenceType>()) {
unsigned AS = RT->getPointeeType().getAddressSpace();
Align = Target.getPointerAlign(AS);
} else if (!T->isIncompleteType() && !T->isFunctionType()) {
if (RefAsPointee)
T = RT->getPointeeType();
else
T = getPointerType(RT->getPointeeType());
}
if (!T->isIncompleteType() && !T->isFunctionType()) {
// Incomplete or function types default to 1.
while (isa<VariableArrayType>(T) || isa<IncompleteArrayType>(T))
T = cast<ArrayType>(T)->getElementType();
@ -687,19 +695,21 @@ ASTContext::getTypeInfo(const Type *T) {
Align = Target.getPointerAlign(AS);
break;
}
case Type::LValueReference:
case Type::RValueReference: {
// alignof and sizeof should never enter this code path here, so we go
// the pointer route.
unsigned AS = cast<ReferenceType>(T)->getPointeeType().getAddressSpace();
Width = Target.getPointerWidth(AS);
Align = Target.getPointerAlign(AS);
break;
}
case Type::Pointer: {
unsigned AS = cast<PointerType>(T)->getPointeeType().getAddressSpace();
Width = Target.getPointerWidth(AS);
Align = Target.getPointerAlign(AS);
break;
}
case Type::LValueReference:
case Type::RValueReference:
// "When applied to a reference or a reference type, the result is the size
// of the referenced type." C++98 5.3.3p2: expr.sizeof.
// FIXME: This is wrong for struct layout: a reference in a struct has
// pointer size.
return getTypeInfo(cast<ReferenceType>(T)->getPointeeType());
case Type::MemberPointer: {
// FIXME: This is ABI dependent. We use the Itanium C++ ABI.
// http://www.codesourcery.com/public/cxx-abi/abi.html#member-pointers
@ -761,7 +771,8 @@ ASTContext::getTypeInfo(const Type *T) {
case Type::Typedef: {
const TypedefDecl *Typedef = cast<TypedefType>(T)->getDecl();
if (const AlignedAttr *Aligned = Typedef->getAttr<AlignedAttr>()) {
Align = Aligned->getAlignment();
Align = std::max(Aligned->getMaxAlignment(),
getTypeAlign(Typedef->getUnderlyingType().getTypePtr()));
Width = getTypeSize(Typedef->getUnderlyingType().getTypePtr());
} else
return getTypeInfo(Typedef->getUnderlyingType().getTypePtr());
@ -1460,16 +1471,24 @@ QualType ASTContext::getDependentSizedArrayType(QualType EltTy,
ArrayType::ArraySizeModifier ASM,
unsigned EltTypeQuals,
SourceRange Brackets) {
assert((NumElts->isTypeDependent() || NumElts->isValueDependent()) &&
assert((!NumElts || NumElts->isTypeDependent() ||
NumElts->isValueDependent()) &&
"Size must be type- or value-dependent!");
llvm::FoldingSetNodeID ID;
DependentSizedArrayType::Profile(ID, *this, getCanonicalType(EltTy), ASM,
EltTypeQuals, NumElts);
void *InsertPos = 0;
DependentSizedArrayType *Canon
= DependentSizedArrayTypes.FindNodeOrInsertPos(ID, InsertPos);
DependentSizedArrayType *Canon = 0;
if (NumElts) {
// Dependently-sized array types that do not have a specified
// number of elements will have their sizes deduced from an
// initializer.
llvm::FoldingSetNodeID ID;
DependentSizedArrayType::Profile(ID, *this, getCanonicalType(EltTy), ASM,
EltTypeQuals, NumElts);
Canon = DependentSizedArrayTypes.FindNodeOrInsertPos(ID, InsertPos);
}
DependentSizedArrayType *New;
if (Canon) {
// We already have a canonical version of this array type; use it as
@ -1483,7 +1502,9 @@ QualType ASTContext::getDependentSizedArrayType(QualType EltTy,
New = new (*this, TypeAlignment)
DependentSizedArrayType(*this, EltTy, QualType(),
NumElts, ASM, EltTypeQuals, Brackets);
DependentSizedArrayTypes.InsertNode(New, InsertPos);
if (NumElts)
DependentSizedArrayTypes.InsertNode(New, InsertPos);
} else {
QualType Canon = getDependentSizedArrayType(CanonEltTy, NumElts,
ASM, EltTypeQuals,
@ -1818,9 +1839,10 @@ QualType ASTContext::getTemplateTypeParmType(unsigned Depth, unsigned Index,
QualType
ASTContext::getTemplateSpecializationType(TemplateName Template,
const TemplateArgumentLoc *Args,
unsigned NumArgs,
const TemplateArgumentListInfo &Args,
QualType Canon) {
unsigned NumArgs = Args.size();
llvm::SmallVector<TemplateArgument, 4> ArgVec;
ArgVec.reserve(NumArgs);
for (unsigned i = 0; i != NumArgs; ++i)
@ -2320,6 +2342,22 @@ CanQualType ASTContext::getCanonicalType(QualType T) {
VAT->getBracketsRange()));
}
DeclarationName ASTContext::getNameForTemplate(TemplateName Name) {
if (TemplateDecl *TD = Name.getAsTemplateDecl())
return TD->getDeclName();
if (DependentTemplateName *DTN = Name.getAsDependentTemplateName()) {
if (DTN->isIdentifier()) {
return DeclarationNames.getIdentifier(DTN->getIdentifier());
} else {
return DeclarationNames.getCXXOperatorName(DTN->getOperator());
}
}
assert(Name.getAsOverloadedFunctionDecl());
return Name.getAsOverloadedFunctionDecl()->getDeclName();
}
TemplateName ASTContext::getCanonicalTemplateName(TemplateName Name) {
// If this template name refers to a template, the canonical
// template name merely stores the template itself.
@ -3374,9 +3412,14 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
false);
return;
}
if (const PointerType *PT = T->getAs<PointerType>()) {
if (PT->isObjCSelType()) {
S += ':';
return;
}
QualType PointeeTy = PT->getPointeeType();
bool isReadOnly = false;
// For historical/compatibility reasons, the read-only qualifier of the
// pointee gets emitted _before_ the '^'. The read-only qualifier of
@ -3407,10 +3450,6 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
S.replace(S.end()-2, S.end(), replace);
}
}
if (isObjCSelType(PointeeTy)) {
S += ':';
return;
}
if (PointeeTy->isCharType()) {
// char pointer types should be encoded as '*' unless it is a
@ -3633,21 +3672,7 @@ void ASTContext::setObjCIdType(QualType T) {
}
void ASTContext::setObjCSelType(QualType T) {
ObjCSelType = T;
const TypedefType *TT = T->getAs<TypedefType>();
if (!TT)
return;
TypedefDecl *TD = TT->getDecl();
// typedef struct objc_selector *SEL;
const PointerType *ptr = TD->getUnderlyingType()->getAs<PointerType>();
if (!ptr)
return;
const RecordType *rec = ptr->getPointeeType()->getAsStructureType();
if (!rec)
return;
SelStructType = rec;
ObjCSelTypedefType = T;
}
void ASTContext::setObjCProtoType(QualType QT) {

View File

@ -211,6 +211,203 @@ FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C, DeclContext *DC,
// NamedDecl Implementation
//===----------------------------------------------------------------------===//
static NamedDecl::Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
assert(D->getDeclContext()->getLookupContext()->isFileContext() &&
"Not a name having namespace scope");
ASTContext &Context = D->getASTContext();
// C++ [basic.link]p3:
// A name having namespace scope (3.3.6) has internal linkage if it
// is the name of
// - an object, reference, function or function template that is
// explicitly declared static; or,
// (This bullet corresponds to C99 6.2.2p3.)
if (const VarDecl *Var = dyn_cast<VarDecl>(D)) {
// Explicitly declared static.
if (Var->getStorageClass() == VarDecl::Static)
return NamedDecl::InternalLinkage;
// - an object or reference that is explicitly declared const
// and neither explicitly declared extern nor previously
// declared to have external linkage; or
// (there is no equivalent in C99)
if (Context.getLangOptions().CPlusPlus &&
Var->getType().isConstant(Context) &&
Var->getStorageClass() != VarDecl::Extern &&
Var->getStorageClass() != VarDecl::PrivateExtern) {
bool FoundExtern = false;
for (const VarDecl *PrevVar = Var->getPreviousDeclaration();
PrevVar && !FoundExtern;
PrevVar = PrevVar->getPreviousDeclaration())
if (PrevVar->getLinkage() == NamedDecl::ExternalLinkage)
FoundExtern = true;
if (!FoundExtern)
return NamedDecl::InternalLinkage;
}
} else if (isa<FunctionDecl>(D) || isa<FunctionTemplateDecl>(D)) {
const FunctionDecl *Function = 0;
if (const FunctionTemplateDecl *FunTmpl
= dyn_cast<FunctionTemplateDecl>(D))
Function = FunTmpl->getTemplatedDecl();
else
Function = cast<FunctionDecl>(D);
// Explicitly declared static.
if (Function->getStorageClass() == FunctionDecl::Static)
return NamedDecl::InternalLinkage;
} else if (const FieldDecl *Field = dyn_cast<FieldDecl>(D)) {
// - a data member of an anonymous union.
if (cast<RecordDecl>(Field->getDeclContext())->isAnonymousStructOrUnion())
return NamedDecl::InternalLinkage;
}
// C++ [basic.link]p4:
// A name having namespace scope has external linkage if it is the
// name of
//
// - an object or reference, unless it has internal linkage; or
if (const VarDecl *Var = dyn_cast<VarDecl>(D)) {
if (!Context.getLangOptions().CPlusPlus &&
(Var->getStorageClass() == VarDecl::Extern ||
Var->getStorageClass() == VarDecl::PrivateExtern)) {
// C99 6.2.2p4:
// For an identifier declared with the storage-class specifier
// extern in a scope in which a prior declaration of that
// identifier is visible, if the prior declaration specifies
// internal or external linkage, the linkage of the identifier
// at the later declaration is the same as the linkage
// specified at the prior declaration. If no prior declaration
// is visible, or if the prior declaration specifies no
// linkage, then the identifier has external linkage.
if (const VarDecl *PrevVar = Var->getPreviousDeclaration()) {
if (NamedDecl::Linkage L = PrevVar->getLinkage())
return L;
}
}
// C99 6.2.2p5:
// If the declaration of an identifier for an object has file
// scope and no storage-class specifier, its linkage is
// external.
return NamedDecl::ExternalLinkage;
}
// - a function, unless it has internal linkage; or
if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
// C99 6.2.2p5:
// If the declaration of an identifier for a function has no
// storage-class specifier, its linkage is determined exactly
// as if it were declared with the storage-class specifier
// extern.
if (!Context.getLangOptions().CPlusPlus &&
(Function->getStorageClass() == FunctionDecl::Extern ||
Function->getStorageClass() == FunctionDecl::PrivateExtern ||
Function->getStorageClass() == FunctionDecl::None)) {
// C99 6.2.2p4:
// For an identifier declared with the storage-class specifier
// extern in a scope in which a prior declaration of that
// identifier is visible, if the prior declaration specifies
// internal or external linkage, the linkage of the identifier
// at the later declaration is the same as the linkage
// specified at the prior declaration. If no prior declaration
// is visible, or if the prior declaration specifies no
// linkage, then the identifier has external linkage.
if (const FunctionDecl *PrevFunc = Function->getPreviousDeclaration()) {
if (NamedDecl::Linkage L = PrevFunc->getLinkage())
return L;
}
}
return NamedDecl::ExternalLinkage;
}
// - a named class (Clause 9), or an unnamed class defined in a
// typedef declaration in which the class has the typedef name
// for linkage purposes (7.1.3); or
// - a named enumeration (7.2), or an unnamed enumeration
// defined in a typedef declaration in which the enumeration
// has the typedef name for linkage purposes (7.1.3); or
if (const TagDecl *Tag = dyn_cast<TagDecl>(D))
if (Tag->getDeclName() || Tag->getTypedefForAnonDecl())
return NamedDecl::ExternalLinkage;
// - an enumerator belonging to an enumeration with external linkage;
if (isa<EnumConstantDecl>(D))
if (cast<NamedDecl>(D->getDeclContext())->getLinkage()
== NamedDecl::ExternalLinkage)
return NamedDecl::ExternalLinkage;
// - a template, unless it is a function template that has
// internal linkage (Clause 14);
if (isa<TemplateDecl>(D))
return NamedDecl::ExternalLinkage;
// - a namespace (7.3), unless it is declared within an unnamed
// namespace.
if (isa<NamespaceDecl>(D) && !D->isInAnonymousNamespace())
return NamedDecl::ExternalLinkage;
return NamedDecl::NoLinkage;
}
NamedDecl::Linkage NamedDecl::getLinkage() const {
// Handle linkage for namespace-scope names.
if (getDeclContext()->getLookupContext()->isFileContext())
if (Linkage L = getLinkageForNamespaceScopeDecl(this))
return L;
// C++ [basic.link]p5:
// In addition, a member function, static data member, a named
// class or enumeration of class scope, or an unnamed class or
// enumeration defined in a class-scope typedef declaration such
// that the class or enumeration has the typedef name for linkage
// purposes (7.1.3), has external linkage if the name of the class
// has external linkage.
if (getDeclContext()->isRecord() &&
(isa<CXXMethodDecl>(this) || isa<VarDecl>(this) ||
(isa<TagDecl>(this) &&
(getDeclName() || cast<TagDecl>(this)->getTypedefForAnonDecl()))) &&
cast<RecordDecl>(getDeclContext())->getLinkage() == ExternalLinkage)
return ExternalLinkage;
// C++ [basic.link]p6:
// The name of a function declared in block scope and the name of
// an object declared by a block scope extern declaration have
// linkage. If there is a visible declaration of an entity with
// linkage having the same name and type, ignoring entities
// declared outside the innermost enclosing namespace scope, the
// block scope declaration declares that same entity and receives
// the linkage of the previous declaration. If there is more than
// one such matching entity, the program is ill-formed. Otherwise,
// if no matching entity is found, the block scope entity receives
// external linkage.
if (getLexicalDeclContext()->isFunctionOrMethod()) {
if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(this)) {
if (Function->getPreviousDeclaration())
if (Linkage L = Function->getPreviousDeclaration()->getLinkage())
return L;
return ExternalLinkage;
}
if (const VarDecl *Var = dyn_cast<VarDecl>(this))
if (Var->getStorageClass() == VarDecl::Extern ||
Var->getStorageClass() == VarDecl::PrivateExtern) {
if (Var->getPreviousDeclaration())
if (Linkage L = Var->getPreviousDeclaration()->getLinkage())
return L;
return ExternalLinkage;
}
}
// C++ [basic.link]p6:
// Names not covered by these rules have no linkage.
return NoLinkage;
}
std::string NamedDecl::getQualifiedNameAsString() const {
return getQualifiedNameAsString(getASTContext().getLangOptions());
}
@ -300,13 +497,7 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD) const {
}
bool NamedDecl::hasLinkage() const {
if (const VarDecl *VD = dyn_cast<VarDecl>(this))
return VD->hasExternalStorage() || VD->isFileVarDecl();
if (isa<FunctionDecl>(this) && !isa<CXXMethodDecl>(this))
return true;
return false;
return getLinkage() != NoLinkage;
}
NamedDecl *NamedDecl::getUnderlyingDecl() {

View File

@ -55,8 +55,7 @@ const char *DeclContext::getDeclKindName() const {
}
bool Decl::CollectingStats(bool Enable) {
if (Enable)
StatSwitch = true;
if (Enable) StatSwitch = true;
return StatSwitch;
}
@ -119,7 +118,7 @@ void PrettyStackTraceDecl::print(llvm::raw_ostream &OS) const {
OS << Message;
if (NamedDecl *DN = dyn_cast_or_null<NamedDecl>(TheDecl))
if (const NamedDecl *DN = dyn_cast_or_null<NamedDecl>(TheDecl))
OS << " '" << DN->getQualifiedNameAsString() << '\'';
OS << '\n';
}
@ -130,9 +129,6 @@ void PrettyStackTraceDecl::print(llvm::raw_ostream &OS) const {
// Out-of-line virtual method providing a home for Decl.
Decl::~Decl() {
if (isOutOfSemaDC())
delete getMultipleDC();
assert(!HasAttrs && "attributes should have been freed by Destroy");
}
@ -148,7 +144,7 @@ void Decl::setLexicalDeclContext(DeclContext *DC) {
return;
if (isInSemaDC()) {
MultipleDC *MDC = new MultipleDC();
MultipleDC *MDC = new (getASTContext()) MultipleDC();
MDC->SemanticDC = getDeclContext();
MDC->LexicalDC = DC;
DeclCtx = MDC;
@ -343,9 +339,12 @@ void Decl::Destroy(ASTContext &C) {
N = Tmp;
}
if (isOutOfSemaDC())
delete (C) getMultipleDC();
this->~Decl();
C.Deallocate((void *)this);
#endif
#endif
}
Decl *Decl::castFromDeclContext (const DeclContext *D) {

View File

@ -36,8 +36,6 @@ CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC,
HasTrivialCopyConstructor(true), HasTrivialCopyAssignment(true),
HasTrivialDestructor(true), ComputedVisibleConversions(false),
Bases(0), NumBases(0), VBases(0), NumVBases(0),
Conversions(DC, DeclarationName()),
VisibleConversions(DC, DeclarationName()),
TemplateOrInstantiation() { }
CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC,
@ -299,14 +297,11 @@ void CXXRecordDecl::addedAssignmentOperator(ASTContext &Context,
void
CXXRecordDecl::collectConversionFunctions(
llvm::SmallPtrSet<CanQualType, 8>& ConversionsTypeSet)
llvm::SmallPtrSet<CanQualType, 8>& ConversionsTypeSet) const
{
OverloadedFunctionDecl *TopConversions = getConversionFunctions();
for (OverloadedFunctionDecl::function_iterator
TFunc = TopConversions->function_begin(),
TFuncEnd = TopConversions->function_end();
TFunc != TFuncEnd; ++TFunc) {
NamedDecl *TopConv = TFunc->get();
const UnresolvedSet *Cs = getConversionFunctions();
for (UnresolvedSet::iterator I = Cs->begin(), E = Cs->end(); I != E; ++I) {
NamedDecl *TopConv = *I;
CanQualType TConvType;
if (FunctionTemplateDecl *TConversionTemplate =
dyn_cast<FunctionTemplateDecl>(TopConv))
@ -336,14 +331,11 @@ CXXRecordDecl::getNestedVisibleConversionFunctions(CXXRecordDecl *RD,
bool inTopClass = (RD == this);
QualType ClassType = getASTContext().getTypeDeclType(this);
if (const RecordType *Record = ClassType->getAs<RecordType>()) {
OverloadedFunctionDecl *Conversions
const UnresolvedSet *Cs
= cast<CXXRecordDecl>(Record->getDecl())->getConversionFunctions();
for (OverloadedFunctionDecl::function_iterator
Func = Conversions->function_begin(),
FuncEnd = Conversions->function_end();
Func != FuncEnd; ++Func) {
NamedDecl *Conv = Func->get();
for (UnresolvedSet::iterator I = Cs->begin(), E = Cs->end(); I != E; ++I) {
NamedDecl *Conv = *I;
// Only those conversions not exact match of conversions in current
// class are candidateconversion routines.
CanQualType ConvType;
@ -405,8 +397,7 @@ CXXRecordDecl::getNestedVisibleConversionFunctions(CXXRecordDecl *RD,
/// getVisibleConversionFunctions - get all conversion functions visible
/// in current class; including conversion function templates.
OverloadedFunctionDecl *
CXXRecordDecl::getVisibleConversionFunctions() {
const UnresolvedSet *CXXRecordDecl::getVisibleConversionFunctions() {
// If root class, all conversions are visible.
if (bases_begin() == bases_end())
return &Conversions;
@ -425,26 +416,26 @@ void CXXRecordDecl::addVisibleConversionFunction(
CXXConversionDecl *ConvDecl) {
assert(!ConvDecl->getDescribedFunctionTemplate() &&
"Conversion function templates should cast to FunctionTemplateDecl.");
VisibleConversions.addOverload(ConvDecl);
VisibleConversions.addDecl(ConvDecl);
}
void CXXRecordDecl::addVisibleConversionFunction(
FunctionTemplateDecl *ConvDecl) {
assert(isa<CXXConversionDecl>(ConvDecl->getTemplatedDecl()) &&
"Function template is not a conversion function template");
VisibleConversions.addOverload(ConvDecl);
VisibleConversions.addDecl(ConvDecl);
}
void CXXRecordDecl::addConversionFunction(CXXConversionDecl *ConvDecl) {
assert(!ConvDecl->getDescribedFunctionTemplate() &&
"Conversion function templates should cast to FunctionTemplateDecl.");
Conversions.addOverload(ConvDecl);
Conversions.addDecl(ConvDecl);
}
void CXXRecordDecl::addConversionFunction(FunctionTemplateDecl *ConvDecl) {
assert(isa<CXXConversionDecl>(ConvDecl->getTemplatedDecl()) &&
"Function template is not a conversion function template");
Conversions.addOverload(ConvDecl);
Conversions.addDecl(ConvDecl);
}
CXXRecordDecl *CXXRecordDecl::getInstantiatedFromMemberClass() const {
@ -895,12 +886,21 @@ UsingDirectiveDecl *UsingDirectiveDecl::Create(ASTContext &C, DeclContext *DC,
SourceRange QualifierRange,
NestedNameSpecifier *Qualifier,
SourceLocation IdentLoc,
NamespaceDecl *Used,
NamedDecl *Used,
DeclContext *CommonAncestor) {
if (NamespaceDecl *NS = dyn_cast_or_null<NamespaceDecl>(Used))
Used = NS->getOriginalNamespace();
return new (C) UsingDirectiveDecl(DC, L, NamespaceLoc, QualifierRange,
Qualifier, IdentLoc, Used, CommonAncestor);
}
NamespaceDecl *UsingDirectiveDecl::getNominatedNamespace() {
if (NamespaceAliasDecl *NA =
dyn_cast_or_null<NamespaceAliasDecl>(NominatedNamespace))
return NA->getNamespace();
return cast_or_null<NamespaceDecl>(NominatedNamespace);
}
NamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
SourceLocation AliasLoc,
@ -909,6 +909,8 @@ NamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC,
NestedNameSpecifier *Qualifier,
SourceLocation IdentLoc,
NamedDecl *Namespace) {
if (NamespaceDecl *NS = dyn_cast_or_null<NamespaceDecl>(Namespace))
Namespace = NS->getOriginalNamespace();
return new (C) NamespaceAliasDecl(DC, L, AliasLoc, Alias, QualifierRange,
Qualifier, IdentLoc, Namespace);
}

View File

@ -18,19 +18,18 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/PrettyPrinter.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
namespace {
class VISIBILITY_HIDDEN DeclPrinter : public DeclVisitor<DeclPrinter> {
class DeclPrinter : public DeclVisitor<DeclPrinter> {
llvm::raw_ostream &Out;
ASTContext &Context;
PrintingPolicy Policy;
unsigned Indentation;
llvm::raw_ostream& Indent();
llvm::raw_ostream& Indent() { return Indent(Indentation); }
llvm::raw_ostream& Indent(unsigned Indentation);
void ProcessDeclGroup(llvm::SmallVectorImpl<Decl*>& Decls);
void Print(AccessSpecifier AS);
@ -154,8 +153,8 @@ void Decl::dump() const {
print(llvm::errs());
}
llvm::raw_ostream& DeclPrinter::Indent() {
for (unsigned i = 0; i < Indentation; ++i)
llvm::raw_ostream& DeclPrinter::Indent(unsigned Indentation) {
for (unsigned i = 0; i != Indentation; ++i)
Out << " ";
return Out;
}
@ -205,6 +204,8 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) {
AccessSpecifier AS = D->getAccess();
if (AS != CurAS) {
if (Indent)
this->Indent(Indentation - Policy.Indentation);
Print(AS);
Out << ":\n";
CurAS = AS;
@ -502,7 +503,7 @@ void DeclPrinter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
Out << "using namespace ";
if (D->getQualifier())
D->getQualifier()->print(Out, Policy);
Out << D->getNominatedNamespace()->getNameAsString();
Out << D->getNominatedNamespaceAsWritten()->getNameAsString();
}
void DeclPrinter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {

View File

@ -214,9 +214,7 @@ QualType ClassTemplateDecl::getInjectedClassNameType(ASTContext &Context) {
} else if (NonTypeTemplateParmDecl *NTTP =
dyn_cast<NonTypeTemplateParmDecl>(*Param)) {
Expr *E = new (Context) DeclRefExpr(NTTP, NTTP->getType(),
NTTP->getLocation(),
NTTP->getType()->isDependentType(),
/*Value-dependent=*/true);
NTTP->getLocation());
TemplateArgs.push_back(TemplateArgument(E));
} else {
TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*Param);
@ -453,8 +451,9 @@ Create(ASTContext &Context, DeclContext *DC, SourceLocation L,
TemplateParameterList *Params,
ClassTemplateDecl *SpecializedTemplate,
TemplateArgumentListBuilder &Builder,
TemplateArgumentLoc *ArgInfos, unsigned N,
const TemplateArgumentListInfo &ArgInfos,
ClassTemplatePartialSpecializationDecl *PrevDecl) {
unsigned N = ArgInfos.size();
TemplateArgumentLoc *ClonedArgs = new (Context) TemplateArgumentLoc[N];
for (unsigned I = 0; I != N; ++I)
ClonedArgs[I] = ArgInfos[I];

View File

@ -50,6 +50,17 @@ class CXXOperatorIdName : public DeclarationNameExtra {
void *FETokenInfo;
};
/// CXXLiberalOperatorName - Contains the actual identifier that makes up the
/// name.
///
/// This identifier is stored here rather than directly in DeclarationName so as
/// to allow Objective-C selectors, which are about a million times more common,
/// to consume minimal memory.
class CXXLiteralOperatorIdName : public DeclarationNameExtra {
public:
IdentifierInfo *ID;
};
bool operator<(DeclarationName LHS, DeclarationName RHS) {
if (LHS.getNameKind() != RHS.getNameKind())
return LHS.getNameKind() < RHS.getNameKind();
@ -89,6 +100,10 @@ bool operator<(DeclarationName LHS, DeclarationName RHS) {
case DeclarationName::CXXOperatorName:
return LHS.getCXXOverloadedOperator() < RHS.getCXXOverloadedOperator();
case DeclarationName::CXXLiteralOperatorName:
return LHS.getCXXLiteralIdentifier()->getName() <
RHS.getCXXLiteralIdentifier()->getName();
case DeclarationName::CXXUsingDirective:
return false;
@ -143,6 +158,9 @@ DeclarationName::NameKind DeclarationName::getNameKind() const {
case DeclarationNameExtra::CXXConversionFunction:
return CXXConversionFunctionName;
case DeclarationNameExtra::CXXLiteralOperator:
return CXXLiteralOperatorName;
case DeclarationNameExtra::CXXUsingDirective:
return CXXUsingDirective;
@ -208,6 +226,10 @@ std::string DeclarationName::getAsString() const {
return Result;
}
case CXXLiteralOperatorName: {
return "operator \"\" " + std::string(getCXXLiteralIdentifier()->getName());
}
case CXXConversionFunctionName: {
std::string Result = "operator ";
QualType Type = getCXXNameType();
@ -242,6 +264,13 @@ OverloadedOperatorKind DeclarationName::getCXXOverloadedOperator() const {
}
}
IdentifierInfo *DeclarationName::getCXXLiteralIdentifier() const {
if (CXXLiteralOperatorIdName *CXXLit = getAsCXXLiteralOperatorIdName())
return CXXLit->ID;
else
return 0;
}
Selector DeclarationName::getObjCSelector() const {
switch (getNameKind()) {
case ObjCZeroArgSelector:
@ -273,6 +302,9 @@ void *DeclarationName::getFETokenInfoAsVoid() const {
case CXXOperatorName:
return getAsCXXOperatorIdName()->FETokenInfo;
case CXXLiteralOperatorName:
return getCXXLiteralIdentifier()->getFETokenInfo<void>();
default:
assert(false && "Declaration name has no FETokenInfo");
}
@ -295,6 +327,10 @@ void DeclarationName::setFETokenInfo(void *T) {
getAsCXXOperatorIdName()->FETokenInfo = T;
break;
case CXXLiteralOperatorName:
getCXXLiteralIdentifier()->setFETokenInfo(T);
break;
default:
assert(false && "Declaration name has no FETokenInfo");
}
@ -390,6 +426,14 @@ DeclarationNameTable::getCXXOperatorName(OverloadedOperatorKind Op) {
return DeclarationName(&CXXOperatorNames[(unsigned)Op]);
}
DeclarationName
DeclarationNameTable::getCXXLiteralOperatorName(IdentifierInfo *II) {
CXXLiteralOperatorIdName *LiteralName = new CXXLiteralOperatorIdName;
LiteralName->ExtraKindOrNumArgs = DeclarationNameExtra::CXXLiteralOperator;
LiteralName->ID = II;
return DeclarationName(LiteralName);
}
unsigned
llvm::DenseMapInfo<clang::DeclarationName>::
getHashValue(clang::DeclarationName N) {

View File

@ -31,38 +31,104 @@ using namespace clang;
// Primary Expressions.
//===----------------------------------------------------------------------===//
void ExplicitTemplateArgumentList::initializeFrom(
const TemplateArgumentListInfo &Info) {
LAngleLoc = Info.getLAngleLoc();
RAngleLoc = Info.getRAngleLoc();
NumTemplateArgs = Info.size();
TemplateArgumentLoc *ArgBuffer = getTemplateArgs();
for (unsigned i = 0; i != NumTemplateArgs; ++i)
new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]);
}
void ExplicitTemplateArgumentList::copyInto(
TemplateArgumentListInfo &Info) const {
Info.setLAngleLoc(LAngleLoc);
Info.setRAngleLoc(RAngleLoc);
for (unsigned I = 0; I != NumTemplateArgs; ++I)
Info.addArgument(getTemplateArgs()[I]);
}
std::size_t ExplicitTemplateArgumentList::sizeFor(
const TemplateArgumentListInfo &Info) {
return sizeof(ExplicitTemplateArgumentList) +
sizeof(TemplateArgumentLoc) * Info.size();
}
void DeclRefExpr::computeDependence() {
TypeDependent = false;
ValueDependent = false;
NamedDecl *D = getDecl();
// (TD) C++ [temp.dep.expr]p3:
// An id-expression is type-dependent if it contains:
//
// and
//
// (VD) C++ [temp.dep.constexpr]p2:
// An identifier is value-dependent if it is:
// (TD) - an identifier that was declared with dependent type
// (VD) - a name declared with a dependent type,
if (getType()->isDependentType()) {
TypeDependent = true;
ValueDependent = true;
}
// (TD) - a conversion-function-id that specifies a dependent type
else if (D->getDeclName().getNameKind()
== DeclarationName::CXXConversionFunctionName &&
D->getDeclName().getCXXNameType()->isDependentType()) {
TypeDependent = true;
ValueDependent = true;
}
// (TD) - a template-id that is dependent,
else if (hasExplicitTemplateArgumentList() &&
TemplateSpecializationType::anyDependentTemplateArguments(
getTemplateArgs(),
getNumTemplateArgs())) {
TypeDependent = true;
ValueDependent = true;
}
// (VD) - the name of a non-type template parameter,
else if (isa<NonTypeTemplateParmDecl>(D))
ValueDependent = true;
// (VD) - a constant with integral or enumeration type and is
// initialized with an expression that is value-dependent.
else if (VarDecl *Var = dyn_cast<VarDecl>(D)) {
if (Var->getType()->isIntegralType() &&
Var->getType().getCVRQualifiers() == Qualifiers::Const &&
Var->getInit() &&
Var->getInit()->isValueDependent())
ValueDependent = true;
}
// (TD) - a nested-name-specifier or a qualified-id that names a
// member of an unknown specialization.
// (handled by DependentScopeDeclRefExpr)
}
DeclRefExpr::DeclRefExpr(NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
NamedDecl *D, SourceLocation NameLoc,
bool HasExplicitTemplateArgumentList,
SourceLocation LAngleLoc,
const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
SourceLocation RAngleLoc,
QualType T, bool TD, bool VD)
: Expr(DeclRefExprClass, T, TD, VD),
const TemplateArgumentListInfo *TemplateArgs,
QualType T)
: Expr(DeclRefExprClass, T, false, false),
DecoratedD(D,
(Qualifier? HasQualifierFlag : 0) |
(HasExplicitTemplateArgumentList?
HasExplicitTemplateArgumentListFlag : 0)),
(TemplateArgs ? HasExplicitTemplateArgumentListFlag : 0)),
Loc(NameLoc) {
assert(!isa<OverloadedFunctionDecl>(D));
if (Qualifier) {
NameQualifier *NQ = getNameQualifier();
NQ->NNS = Qualifier;
NQ->Range = QualifierRange;
}
if (HasExplicitTemplateArgumentList) {
ExplicitTemplateArgumentList *ETemplateArgs
= getExplicitTemplateArgumentList();
ETemplateArgs->LAngleLoc = LAngleLoc;
ETemplateArgs->RAngleLoc = RAngleLoc;
ETemplateArgs->NumTemplateArgs = NumExplicitTemplateArgs;
TemplateArgumentLoc *TemplateArgs = ETemplateArgs->getTemplateArgs();
for (unsigned I = 0; I < NumExplicitTemplateArgs; ++I)
new (TemplateArgs + I) TemplateArgumentLoc(ExplicitTemplateArgs[I]);
}
if (TemplateArgs)
getExplicitTemplateArgumentList()->initializeFrom(*TemplateArgs);
computeDependence();
}
DeclRefExpr *DeclRefExpr::Create(ASTContext &Context,
@ -70,39 +136,18 @@ DeclRefExpr *DeclRefExpr::Create(ASTContext &Context,
SourceRange QualifierRange,
NamedDecl *D,
SourceLocation NameLoc,
QualType T, bool TD, bool VD) {
return Create(Context, Qualifier, QualifierRange, D, NameLoc,
false, SourceLocation(), 0, 0, SourceLocation(),
T, TD, VD);
}
DeclRefExpr *DeclRefExpr::Create(ASTContext &Context,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
NamedDecl *D,
SourceLocation NameLoc,
bool HasExplicitTemplateArgumentList,
SourceLocation LAngleLoc,
const TemplateArgumentLoc *ExplicitTemplateArgs,
unsigned NumExplicitTemplateArgs,
SourceLocation RAngleLoc,
QualType T, bool TD, bool VD) {
QualType T,
const TemplateArgumentListInfo *TemplateArgs) {
std::size_t Size = sizeof(DeclRefExpr);
if (Qualifier != 0)
Size += sizeof(NameQualifier);
if (HasExplicitTemplateArgumentList)
Size += sizeof(ExplicitTemplateArgumentList) +
sizeof(TemplateArgumentLoc) * NumExplicitTemplateArgs;
if (TemplateArgs)
Size += ExplicitTemplateArgumentList::sizeFor(*TemplateArgs);
void *Mem = Context.Allocate(Size, llvm::alignof<DeclRefExpr>());
return new (Mem) DeclRefExpr(Qualifier, QualifierRange, D, NameLoc,
HasExplicitTemplateArgumentList,
LAngleLoc,
ExplicitTemplateArgs,
NumExplicitTemplateArgs,
RAngleLoc,
T, TD, VD);
TemplateArgs, T);
}
SourceRange DeclRefExpr::getSourceRange() const {
@ -427,15 +472,13 @@ QualType CallExpr::getCallReturnType() const {
MemberExpr::MemberExpr(Expr *base, bool isarrow, NestedNameSpecifier *qual,
SourceRange qualrange, NamedDecl *memberdecl,
SourceLocation l, bool has_explicit,
SourceLocation langle,
const TemplateArgumentLoc *targs, unsigned numtargs,
SourceLocation rangle, QualType ty)
SourceLocation l, const TemplateArgumentListInfo *targs,
QualType ty)
: Expr(MemberExprClass, ty,
base->isTypeDependent() || (qual && qual->isDependent()),
base->isValueDependent() || (qual && qual->isDependent())),
Base(base), MemberDecl(memberdecl), MemberLoc(l), IsArrow(isarrow),
HasQualifier(qual != 0), HasExplicitTemplateArgumentList(has_explicit) {
HasQualifier(qual != 0), HasExplicitTemplateArgumentList(targs) {
// Initialize the qualifier, if any.
if (HasQualifier) {
NameQualifier *NQ = getMemberQualifier();
@ -444,17 +487,8 @@ MemberExpr::MemberExpr(Expr *base, bool isarrow, NestedNameSpecifier *qual,
}
// Initialize the explicit template argument list, if any.
if (HasExplicitTemplateArgumentList) {
ExplicitTemplateArgumentList *ETemplateArgs
= getExplicitTemplateArgumentList();
ETemplateArgs->LAngleLoc = langle;
ETemplateArgs->RAngleLoc = rangle;
ETemplateArgs->NumTemplateArgs = numtargs;
TemplateArgumentLoc *TemplateArgs = ETemplateArgs->getTemplateArgs();
for (unsigned I = 0; I < numtargs; ++I)
new (TemplateArgs + I) TemplateArgumentLoc(targs[I]);
}
if (targs)
getExplicitTemplateArgumentList()->initializeFrom(*targs);
}
MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow,
@ -462,24 +496,18 @@ MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow,
SourceRange qualrange,
NamedDecl *memberdecl,
SourceLocation l,
bool has_explicit,
SourceLocation langle,
const TemplateArgumentLoc *targs,
unsigned numtargs,
SourceLocation rangle,
const TemplateArgumentListInfo *targs,
QualType ty) {
std::size_t Size = sizeof(MemberExpr);
if (qual != 0)
Size += sizeof(NameQualifier);
if (has_explicit)
Size += sizeof(ExplicitTemplateArgumentList) +
sizeof(TemplateArgumentLoc) * numtargs;
if (targs)
Size += ExplicitTemplateArgumentList::sizeFor(*targs);
void *Mem = C.Allocate(Size, llvm::alignof<MemberExpr>());
return new (Mem) MemberExpr(base, isarrow, qual, qualrange, memberdecl, l,
has_explicit, langle, targs, numtargs, rangle,
ty);
targs, ty);
}
const char *CastExpr::getCastKindName() const {
@ -528,6 +556,8 @@ const char *CastExpr::getCastKindName() const {
return "FloatingToIntegral";
case CastExpr::CK_FloatingCast:
return "FloatingCast";
case CastExpr::CK_MemberPointerToBoolean:
return "MemberPointerToBoolean";
}
assert(0 && "Unhandled cast kind!");
@ -640,12 +670,17 @@ OverloadedOperatorKind BinaryOperator::getOverloadedOperator(Opcode Opc) {
InitListExpr::InitListExpr(SourceLocation lbraceloc,
Expr **initExprs, unsigned numInits,
SourceLocation rbraceloc)
: Expr(InitListExprClass, QualType(),
hasAnyTypeDependentArguments(initExprs, numInits),
hasAnyValueDependentArguments(initExprs, numInits)),
: Expr(InitListExprClass, QualType(), false, false),
LBraceLoc(lbraceloc), RBraceLoc(rbraceloc), SyntacticForm(0),
UnionFieldInit(0), HadArrayRangeDesignator(false) {
UnionFieldInit(0), HadArrayRangeDesignator(false)
{
for (unsigned I = 0; I != numInits; ++I) {
if (initExprs[I]->isTypeDependent())
TypeDependent = true;
if (initExprs[I]->isValueDependent())
ValueDependent = true;
}
InitExprs.insert(InitExprs.end(), initExprs, initExprs+numInits);
}
@ -1091,10 +1126,10 @@ Expr::isLvalueResult Expr::isLvalueInternal(ASTContext &Ctx) const {
return LV_Valid;
case PredefinedExprClass:
return LV_Valid;
case UnresolvedLookupExprClass:
return LV_Valid;
case CXXDefaultArgExprClass:
return cast<CXXDefaultArgExpr>(this)->getExpr()->isLvalue(Ctx);
case CXXConditionDeclExprClass:
return LV_Valid;
case CStyleCastExprClass:
case CXXFunctionalCastExprClass:
case CXXStaticCastExprClass:
@ -1141,18 +1176,6 @@ Expr::isLvalueResult Expr::isLvalueInternal(ASTContext &Ctx) const {
return LV_Valid;
}
case TemplateIdRefExprClass: {
const TemplateIdRefExpr *TID = cast<TemplateIdRefExpr>(this);
TemplateName Template = TID->getTemplateName();
NamedDecl *ND = Template.getAsTemplateDecl();
if (!ND)
ND = Template.getAsOverloadedFunctionDecl();
if (ND && DeclCanBeLvalue(ND, Ctx))
return LV_Valid;
break;
}
default:
break;
}
@ -1491,19 +1514,18 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
case Expr::CXXNullPtrLiteralExprClass:
case Expr::CXXThisExprClass:
case Expr::CXXThrowExprClass:
case Expr::CXXConditionDeclExprClass: // FIXME: is this correct?
case Expr::CXXNewExprClass:
case Expr::CXXDeleteExprClass:
case Expr::CXXPseudoDestructorExprClass:
case Expr::UnresolvedFunctionNameExprClass:
case Expr::UnresolvedDeclRefExprClass:
case Expr::TemplateIdRefExprClass:
case Expr::UnresolvedLookupExprClass:
case Expr::DependentScopeDeclRefExprClass:
case Expr::CXXConstructExprClass:
case Expr::CXXBindTemporaryExprClass:
case Expr::CXXExprWithTemporariesClass:
case Expr::CXXTemporaryObjectExprClass:
case Expr::CXXUnresolvedConstructExprClass:
case Expr::CXXUnresolvedMemberExprClass:
case Expr::CXXDependentScopeMemberExprClass:
case Expr::UnresolvedMemberExprClass:
case Expr::ObjCStringLiteralClass:
case Expr::ObjCEncodeExprClass:
case Expr::ObjCMessageExprClass:

View File

@ -72,14 +72,6 @@ Stmt::child_iterator CXXZeroInitValueExpr::child_end() {
return child_iterator();
}
// CXXConditionDeclExpr
Stmt::child_iterator CXXConditionDeclExpr::child_begin() {
return getVarDecl();
}
Stmt::child_iterator CXXConditionDeclExpr::child_end() {
return child_iterator();
}
// CXXNewExpr
CXXNewExpr::CXXNewExpr(bool globalNew, FunctionDecl *operatorNew,
Expr **placementArgs, unsigned numPlaceArgs,
@ -121,11 +113,45 @@ Stmt::child_iterator CXXPseudoDestructorExpr::child_end() {
return &Base + 1;
}
// UnresolvedFunctionNameExpr
Stmt::child_iterator UnresolvedFunctionNameExpr::child_begin() {
// UnresolvedLookupExpr
UnresolvedLookupExpr *
UnresolvedLookupExpr::Create(ASTContext &C, bool Dependent,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange, DeclarationName Name,
SourceLocation NameLoc, bool ADL,
const TemplateArgumentListInfo &Args)
{
void *Mem = C.Allocate(sizeof(UnresolvedLookupExpr) +
ExplicitTemplateArgumentList::sizeFor(Args));
UnresolvedLookupExpr *ULE
= new (Mem) UnresolvedLookupExpr(Dependent ? C.DependentTy : C.OverloadTy,
Dependent, Qualifier, QualifierRange,
Name, NameLoc, ADL,
/*Overload*/ true,
/*ExplicitTemplateArgs*/ true);
reinterpret_cast<ExplicitTemplateArgumentList*>(ULE+1)->initializeFrom(Args);
return ULE;
}
bool UnresolvedLookupExpr::ComputeDependence(NamedDecl * const *Begin,
NamedDecl * const *End,
const TemplateArgumentListInfo *Args) {
for (NamedDecl * const *I = Begin; I != End; ++I)
if ((*I)->getDeclContext()->isDependentContext())
return true;
if (Args && TemplateSpecializationType::anyDependentTemplateArguments(*Args))
return true;
return false;
}
Stmt::child_iterator UnresolvedLookupExpr::child_begin() {
return child_iterator();
}
Stmt::child_iterator UnresolvedFunctionNameExpr::child_end() {
Stmt::child_iterator UnresolvedLookupExpr::child_end() {
return child_iterator();
}
// UnaryTypeTraitExpr
@ -136,74 +162,39 @@ Stmt::child_iterator UnaryTypeTraitExpr::child_end() {
return child_iterator();
}
// UnresolvedDeclRefExpr
StmtIterator UnresolvedDeclRefExpr::child_begin() {
// DependentScopeDeclRefExpr
DependentScopeDeclRefExpr *
DependentScopeDeclRefExpr::Create(ASTContext &C,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
DeclarationName Name,
SourceLocation NameLoc,
const TemplateArgumentListInfo *Args) {
std::size_t size = sizeof(DependentScopeDeclRefExpr);
if (Args) size += ExplicitTemplateArgumentList::sizeFor(*Args);
void *Mem = C.Allocate(size);
DependentScopeDeclRefExpr *DRE
= new (Mem) DependentScopeDeclRefExpr(C.DependentTy,
Qualifier, QualifierRange,
Name, NameLoc,
Args != 0);
if (Args)
reinterpret_cast<ExplicitTemplateArgumentList*>(DRE+1)
->initializeFrom(*Args);
return DRE;
}
StmtIterator DependentScopeDeclRefExpr::child_begin() {
return child_iterator();
}
StmtIterator UnresolvedDeclRefExpr::child_end() {
StmtIterator DependentScopeDeclRefExpr::child_end() {
return child_iterator();
}
TemplateIdRefExpr::TemplateIdRefExpr(QualType T,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
TemplateName Template,
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
const TemplateArgumentLoc *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) {
TemplateArgumentLoc *StoredTemplateArgs
= reinterpret_cast<TemplateArgumentLoc *> (this+1);
for (unsigned I = 0; I != NumTemplateArgs; ++I)
new (StoredTemplateArgs + I) TemplateArgumentLoc(TemplateArgs[I]);
}
TemplateIdRefExpr *
TemplateIdRefExpr::Create(ASTContext &Context, QualType T,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
TemplateName Template, SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
const TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs, SourceLocation RAngleLoc) {
void *Mem = Context.Allocate(sizeof(TemplateIdRefExpr) +
sizeof(TemplateArgumentLoc) * NumTemplateArgs);
return new (Mem) TemplateIdRefExpr(T, Qualifier, QualifierRange, Template,
TemplateNameLoc, LAngleLoc, TemplateArgs,
NumTemplateArgs, RAngleLoc);
}
void TemplateIdRefExpr::DoDestroy(ASTContext &Context) {
const TemplateArgumentLoc *TemplateArgs = getTemplateArgs();
for (unsigned I = 0; I != NumTemplateArgs; ++I)
if (Expr *E = TemplateArgs[I].getArgument().getAsExpr())
E->Destroy(Context);
this->~TemplateIdRefExpr();
Context.Deallocate(this);
}
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(ASTContext& C) const {
switch(UTT) {
default: assert(false && "Unknown type trait or not implemented");
@ -526,7 +517,7 @@ Stmt::child_iterator CXXUnresolvedConstructExpr::child_end() {
return child_iterator(reinterpret_cast<Stmt **>(this + 1) + NumArgs);
}
CXXUnresolvedMemberExpr::CXXUnresolvedMemberExpr(ASTContext &C,
CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(ASTContext &C,
Expr *Base, bool IsArrow,
SourceLocation OperatorLoc,
NestedNameSpecifier *Qualifier,
@ -534,33 +525,20 @@ CXXUnresolvedMemberExpr::CXXUnresolvedMemberExpr(ASTContext &C,
NamedDecl *FirstQualifierFoundInScope,
DeclarationName Member,
SourceLocation MemberLoc,
bool HasExplicitTemplateArgs,
SourceLocation LAngleLoc,
const TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs,
SourceLocation RAngleLoc)
: Expr(CXXUnresolvedMemberExprClass, C.DependentTy, true, true),
const TemplateArgumentListInfo *TemplateArgs)
: Expr(CXXDependentScopeMemberExprClass, C.DependentTy, true, true),
Base(Base), IsArrow(IsArrow),
HasExplicitTemplateArgumentList(HasExplicitTemplateArgs),
HasExplicitTemplateArgumentList(TemplateArgs),
OperatorLoc(OperatorLoc),
Qualifier(Qualifier), QualifierRange(QualifierRange),
FirstQualifierFoundInScope(FirstQualifierFoundInScope),
Member(Member), MemberLoc(MemberLoc) {
if (HasExplicitTemplateArgumentList) {
ExplicitTemplateArgumentList *ETemplateArgs
= getExplicitTemplateArgumentList();
ETemplateArgs->LAngleLoc = LAngleLoc;
ETemplateArgs->RAngleLoc = RAngleLoc;
ETemplateArgs->NumTemplateArgs = NumTemplateArgs;
TemplateArgumentLoc *SavedTemplateArgs = ETemplateArgs->getTemplateArgs();
for (unsigned I = 0; I < NumTemplateArgs; ++I)
new (SavedTemplateArgs + I) TemplateArgumentLoc(TemplateArgs[I]);
}
if (TemplateArgs)
getExplicitTemplateArgumentList()->initializeFrom(*TemplateArgs);
}
CXXUnresolvedMemberExpr *
CXXUnresolvedMemberExpr::Create(ASTContext &C,
CXXDependentScopeMemberExpr *
CXXDependentScopeMemberExpr::Create(ASTContext &C,
Expr *Base, bool IsArrow,
SourceLocation OperatorLoc,
NestedNameSpecifier *Qualifier,
@ -568,37 +546,79 @@ CXXUnresolvedMemberExpr::Create(ASTContext &C,
NamedDecl *FirstQualifierFoundInScope,
DeclarationName Member,
SourceLocation MemberLoc,
bool HasExplicitTemplateArgs,
SourceLocation LAngleLoc,
const TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs,
SourceLocation RAngleLoc) {
if (!HasExplicitTemplateArgs)
return new (C) CXXUnresolvedMemberExpr(C, Base, IsArrow, OperatorLoc,
const TemplateArgumentListInfo *TemplateArgs) {
if (!TemplateArgs)
return new (C) CXXDependentScopeMemberExpr(C, Base, IsArrow, OperatorLoc,
Qualifier, QualifierRange,
FirstQualifierFoundInScope,
Member, MemberLoc);
void *Mem = C.Allocate(sizeof(CXXUnresolvedMemberExpr) +
sizeof(ExplicitTemplateArgumentList) +
sizeof(TemplateArgumentLoc) * NumTemplateArgs,
llvm::alignof<CXXUnresolvedMemberExpr>());
return new (Mem) CXXUnresolvedMemberExpr(C, Base, IsArrow, OperatorLoc,
std::size_t size = sizeof(CXXDependentScopeMemberExpr);
if (TemplateArgs)
size += ExplicitTemplateArgumentList::sizeFor(*TemplateArgs);
void *Mem = C.Allocate(size, llvm::alignof<CXXDependentScopeMemberExpr>());
return new (Mem) CXXDependentScopeMemberExpr(C, Base, IsArrow, OperatorLoc,
Qualifier, QualifierRange,
FirstQualifierFoundInScope,
Member,
MemberLoc,
HasExplicitTemplateArgs,
LAngleLoc,
TemplateArgs,
NumTemplateArgs,
RAngleLoc);
TemplateArgs);
}
Stmt::child_iterator CXXUnresolvedMemberExpr::child_begin() {
Stmt::child_iterator CXXDependentScopeMemberExpr::child_begin() {
return child_iterator(&Base);
}
Stmt::child_iterator CXXUnresolvedMemberExpr::child_end() {
Stmt::child_iterator CXXDependentScopeMemberExpr::child_end() {
return child_iterator(&Base + 1);
}
UnresolvedMemberExpr::UnresolvedMemberExpr(QualType T, bool Dependent,
bool HasUnresolvedUsing,
Expr *Base, bool IsArrow,
SourceLocation OperatorLoc,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
DeclarationName MemberName,
SourceLocation MemberLoc,
const TemplateArgumentListInfo *TemplateArgs)
: Expr(UnresolvedMemberExprClass, T, Dependent, Dependent),
Base(Base), IsArrow(IsArrow), HasUnresolvedUsing(HasUnresolvedUsing),
HasExplicitTemplateArgs(TemplateArgs != 0),
OperatorLoc(OperatorLoc),
Qualifier(Qualifier), QualifierRange(QualifierRange),
MemberName(MemberName), MemberLoc(MemberLoc) {
if (TemplateArgs)
getExplicitTemplateArgs()->initializeFrom(*TemplateArgs);
}
UnresolvedMemberExpr *
UnresolvedMemberExpr::Create(ASTContext &C, bool Dependent,
bool HasUnresolvedUsing,
Expr *Base, bool IsArrow,
SourceLocation OperatorLoc,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
DeclarationName Member,
SourceLocation MemberLoc,
const TemplateArgumentListInfo *TemplateArgs) {
std::size_t size = sizeof(UnresolvedMemberExpr);
if (TemplateArgs)
size += ExplicitTemplateArgumentList::sizeFor(*TemplateArgs);
void *Mem = C.Allocate(size, llvm::alignof<UnresolvedMemberExpr>());
return new (Mem) UnresolvedMemberExpr(
Dependent ? C.DependentTy : C.OverloadTy,
Dependent, HasUnresolvedUsing, Base, IsArrow,
OperatorLoc, Qualifier, QualifierRange,
Member, MemberLoc, TemplateArgs);
}
Stmt::child_iterator UnresolvedMemberExpr::child_begin() {
return child_iterator(&Base);
}
Stmt::child_iterator UnresolvedMemberExpr::child_end() {
return child_iterator(&Base + 1);
}

View File

@ -19,7 +19,6 @@
#include "clang/Basic/Builtins.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/Compiler.h"
#include <cstring>
using namespace clang;
@ -153,7 +152,7 @@ static APFloat HandleIntToFloatCast(QualType DestType, QualType SrcType,
}
namespace {
class VISIBILITY_HIDDEN HasSideEffect
class HasSideEffect
: public StmtVisitor<HasSideEffect, bool> {
EvalInfo &Info;
public:
@ -210,7 +209,7 @@ class VISIBILITY_HIDDEN HasSideEffect
// LValue Evaluation
//===----------------------------------------------------------------------===//
namespace {
class VISIBILITY_HIDDEN LValueExprEvaluator
class LValueExprEvaluator
: public StmtVisitor<LValueExprEvaluator, APValue> {
EvalInfo &Info;
public:
@ -353,7 +352,7 @@ APValue LValueExprEvaluator::VisitUnaryDeref(UnaryOperator *E) {
//===----------------------------------------------------------------------===//
namespace {
class VISIBILITY_HIDDEN PointerExprEvaluator
class PointerExprEvaluator
: public StmtVisitor<PointerExprEvaluator, APValue> {
EvalInfo &Info;
public:
@ -508,7 +507,7 @@ APValue PointerExprEvaluator::VisitConditionalOperator(ConditionalOperator *E) {
//===----------------------------------------------------------------------===//
namespace {
class VISIBILITY_HIDDEN VectorExprEvaluator
class VectorExprEvaluator
: public StmtVisitor<VectorExprEvaluator, APValue> {
EvalInfo &Info;
APValue GetZeroVector(QualType VecType);
@ -702,7 +701,7 @@ APValue VectorExprEvaluator::VisitUnaryImag(const UnaryOperator *E) {
//===----------------------------------------------------------------------===//
namespace {
class VISIBILITY_HIDDEN IntExprEvaluator
class IntExprEvaluator
: public StmtVisitor<IntExprEvaluator, bool> {
EvalInfo &Info;
APValue &Result;
@ -776,7 +775,20 @@ class VISIBILITY_HIDDEN IntExprEvaluator
T1.getUnqualifiedType()),
E);
}
bool VisitDeclRefExpr(const DeclRefExpr *E);
bool CheckReferencedDecl(const Expr *E, const Decl *D);
bool VisitDeclRefExpr(const DeclRefExpr *E) {
return CheckReferencedDecl(E, E->getDecl());
}
bool VisitMemberExpr(const MemberExpr *E) {
if (CheckReferencedDecl(E, E->getMemberDecl())) {
// Conservatively assume a MemberExpr will have side-effects
Info.EvalResult.HasSideEffects = true;
return true;
}
return false;
}
bool VisitCallExpr(const CallExpr *E);
bool VisitBinaryOperator(const BinaryOperator *E);
bool VisitUnaryOperator(const UnaryOperator *E);
@ -834,12 +846,12 @@ static bool EvaluateInteger(const Expr* E, APSInt &Result, EvalInfo &Info) {
return true;
}
bool IntExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) {
bool IntExprEvaluator::CheckReferencedDecl(const Expr* E, const Decl* D) {
// Enums are integer constant exprs.
if (const EnumConstantDecl *D = dyn_cast<EnumConstantDecl>(E->getDecl())) {
if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(D)) {
// FIXME: This is an ugly hack around the fact that enums don't set their
// signedness consistently; see PR3173.
APSInt SI = D->getInitVal();
APSInt SI = ECD->getInitVal();
SI.setIsUnsigned(!E->getType()->isSignedIntegerType());
// FIXME: This is an ugly hack around the fact that enums don't
// set their width (!?!) consistently; see PR3173.
@ -851,15 +863,15 @@ bool IntExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) {
// In C, they can also be folded, although they are not ICEs.
if (Info.Ctx.getCanonicalType(E->getType()).getCVRQualifiers()
== Qualifiers::Const) {
if (const VarDecl *D = dyn_cast<VarDecl>(E->getDecl())) {
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
const VarDecl *Def = 0;
if (const Expr *Init = D->getDefinition(Def)) {
if (APValue *V = D->getEvaluatedValue())
if (const Expr *Init = VD->getDefinition(Def)) {
if (APValue *V = VD->getEvaluatedValue())
return Success(V->getInt(), E);
if (Visit(const_cast<Expr*>(Init))) {
// Cache the evaluated value in the variable declaration.
D->setEvaluatedValue(Info.Ctx, Result);
VD->setEvaluatedValue(Info.Ctx, Result);
return true;
}
@ -1244,6 +1256,13 @@ bool IntExprEvaluator::VisitConditionalOperator(const ConditionalOperator *E) {
}
unsigned IntExprEvaluator::GetAlignOfType(QualType T) {
// C++ [expr.sizeof]p2: "When applied to a reference or a reference type,
// the result is the size of the referenced type."
// C++ [expr.alignof]p3: "When alignof is applied to a reference type, the
// result shall be the alignment of the referenced type."
if (const ReferenceType *Ref = T->getAs<ReferenceType>())
T = Ref->getPointeeType();
// Get information about the alignment.
unsigned CharSize = Info.Ctx.Target.getCharWidth();
@ -1257,10 +1276,11 @@ unsigned IntExprEvaluator::GetAlignOfExpr(const Expr *E) {
// alignof decl is always accepted, even if it doesn't make sense: we default
// to 1 in those cases.
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
return Info.Ctx.getDeclAlignInBytes(DRE->getDecl());
return Info.Ctx.getDeclAlignInBytes(DRE->getDecl(), /*RefAsPointee*/true);
if (const MemberExpr *ME = dyn_cast<MemberExpr>(E))
return Info.Ctx.getDeclAlignInBytes(ME->getMemberDecl());
return Info.Ctx.getDeclAlignInBytes(ME->getMemberDecl(),
/*RefAsPointee*/true);
return GetAlignOfType(E->getType());
}
@ -1280,6 +1300,12 @@ bool IntExprEvaluator::VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E) {
}
QualType SrcTy = E->getTypeOfArgument();
// C++ [expr.sizeof]p2: "When applied to a reference or a reference type,
// the result is the size of the referenced type."
// C++ [expr.alignof]p3: "When alignof is applied to a reference type, the
// result shall be the alignment of the referenced type."
if (const ReferenceType *Ref = SrcTy->getAs<ReferenceType>())
SrcTy = Ref->getPointeeType();
// sizeof(void), __alignof__(void), sizeof(function) = 1 as a gcc
// extension.
@ -1460,7 +1486,7 @@ bool IntExprEvaluator::VisitUnaryImag(const UnaryOperator *E) {
//===----------------------------------------------------------------------===//
namespace {
class VISIBILITY_HIDDEN FloatExprEvaluator
class FloatExprEvaluator
: public StmtVisitor<FloatExprEvaluator, bool> {
EvalInfo &Info;
APFloat &Result;
@ -1652,7 +1678,7 @@ bool FloatExprEvaluator::VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *E) {
//===----------------------------------------------------------------------===//
namespace {
class VISIBILITY_HIDDEN ComplexExprEvaluator
class ComplexExprEvaluator
: public StmtVisitor<ComplexExprEvaluator, APValue> {
EvalInfo &Info;

View File

@ -14,7 +14,6 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/RecordLayout.h"
#include "clang/Basic/TargetInfo.h"
#include <llvm/ADT/SmallSet.h>
#include <llvm/Support/MathExtras.h>
@ -22,9 +21,9 @@
using namespace clang;
ASTRecordLayoutBuilder::ASTRecordLayoutBuilder(ASTContext &Ctx)
: Ctx(Ctx), Size(0), Alignment(8), Packed(false), MaxFieldAlignment(0),
DataSize(0), IsUnion(false), NonVirtualSize(0), NonVirtualAlignment(8),
PrimaryBase(0), PrimaryBaseWasVirtual(false) {}
: Ctx(Ctx), Size(0), Alignment(8), Packed(false), UnfilledBitsInLastByte(0),
MaxFieldAlignment(0), DataSize(0), IsUnion(false), NonVirtualSize(0),
NonVirtualAlignment(8) { }
/// LayoutVtable - Lay out the vtable and set PrimaryBase.
void ASTRecordLayoutBuilder::LayoutVtable(const CXXRecordDecl *RD) {
@ -34,7 +33,7 @@ void ASTRecordLayoutBuilder::LayoutVtable(const CXXRecordDecl *RD) {
}
SelectPrimaryBase(RD);
if (PrimaryBase == 0) {
if (!PrimaryBase.getBase()) {
int AS = 0;
UpdateAlignment(Ctx.Target.getPointerAlign(AS));
Size += Ctx.Target.getPointerWidth(AS);
@ -52,7 +51,7 @@ ASTRecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) {
const CXXRecordDecl *Base =
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
// Skip the PrimaryBase here, as it is laid down first.
if (Base != PrimaryBase || PrimaryBaseWasVirtual)
if (Base != PrimaryBase.getBase() || PrimaryBase.isVirtual())
LayoutBaseNonVirtually(Base, false);
}
}
@ -74,12 +73,13 @@ bool ASTRecordLayoutBuilder::IsNearlyEmpty(const CXXRecordDecl *RD) const {
}
void ASTRecordLayoutBuilder::IdentifyPrimaryBases(const CXXRecordDecl *RD) {
const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD);
const ASTRecordLayout::PrimaryBaseInfo &BaseInfo =
Ctx.getASTRecordLayout(RD).getPrimaryBaseInfo();
// If the record has a primary base class that is virtual, add it to the set
// of primary bases.
if (Layout.getPrimaryBaseWasVirtual())
IndirectPrimaryBases.insert(Layout.getPrimaryBase());
if (BaseInfo.isVirtual())
IndirectPrimaryBases.insert(BaseInfo.getBase());
// Now traverse all bases and find primary bases for them.
for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
@ -107,7 +107,7 @@ ASTRecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD,
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
if (!i->isVirtual()) {
SelectPrimaryVBase(Base, FirstPrimary);
if (PrimaryBase)
if (PrimaryBase.getBase())
return;
continue;
}
@ -115,7 +115,7 @@ ASTRecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD,
if (FirstPrimary==0)
FirstPrimary = Base;
if (!IndirectPrimaryBases.count(Base)) {
setPrimaryBase(Base, true);
setPrimaryBase(Base, /*IsVirtual=*/true);
return;
}
}
@ -141,14 +141,17 @@ void ASTRecordLayoutBuilder::SelectPrimaryBase(const CXXRecordDecl *RD) {
// base class, if one exists.
for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
e = RD->bases_end(); i != e; ++i) {
if (!i->isVirtual()) {
const CXXRecordDecl *Base =
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
if (Base->isDynamicClass()) {
// We found it.
setPrimaryBase(Base, false);
return;
}
// Ignore virtual bases.
if (i->isVirtual())
continue;
const CXXRecordDecl *Base =
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
if (Base->isDynamicClass()) {
// We found it.
PrimaryBase = ASTRecordLayout::PrimaryBaseInfo(Base, /*IsVirtual=*/false);
return;
}
}
@ -166,8 +169,8 @@ void ASTRecordLayoutBuilder::SelectPrimaryBase(const CXXRecordDecl *RD) {
// Otherwise if is the first nearly empty virtual base, if one exists,
// otherwise there is no primary base class.
if (!PrimaryBase)
setPrimaryBase(FirstPrimary, true);
if (!PrimaryBase.getBase())
setPrimaryBase(FirstPrimary, /*IsVirtual=*/true);
}
void ASTRecordLayoutBuilder::LayoutVirtualBase(const CXXRecordDecl *RD) {
@ -232,9 +235,10 @@ void ASTRecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *Class,
}
if (Base->getNumVBases()) {
const ASTRecordLayout &L = Ctx.getASTRecordLayout(Base);
const CXXRecordDecl *PB = L.getPrimaryBase();
LayoutVirtualBases(Class, Base, PB, BaseOffset, mark, IndirectPrimary);
const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(Base);
const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBaseInfo().getBase();
LayoutVirtualBases(Class, Base, PrimaryBase, BaseOffset, mark,
IndirectPrimary);
}
}
}
@ -448,17 +452,17 @@ void ASTRecordLayoutBuilder::Layout(const RecordDecl *D) {
MaxFieldAlignment = PPA->getAlignment();
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
UpdateAlignment(AA->getAlignment());
UpdateAlignment(AA->getMaxAlignment());
// If this is a C++ class, lay out the vtable and the non-virtual bases.
const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D);
if (RD) {
LayoutVtable(RD);
// PrimaryBase goes first.
if (PrimaryBase) {
if (PrimaryBaseWasVirtual)
IndirectPrimaryBases.insert(PrimaryBase);
LayoutBaseNonVirtually(PrimaryBase, PrimaryBaseWasVirtual);
if (PrimaryBase.getBase()) {
if (PrimaryBase.isVirtual())
IndirectPrimaryBases.insert(PrimaryBase.getBase());
LayoutBaseNonVirtually(PrimaryBase.getBase(), PrimaryBase.isVirtual());
}
LayoutNonVirtualBases(RD);
}
@ -470,7 +474,8 @@ void ASTRecordLayoutBuilder::Layout(const RecordDecl *D) {
if (RD) {
llvm::SmallSet<const CXXRecordDecl*, 32> mark;
LayoutVirtualBases(RD, RD, PrimaryBase, 0, mark, IndirectPrimaryBases);
LayoutVirtualBases(RD, RD, PrimaryBase.getBase(),
0, mark, IndirectPrimaryBases);
}
// Finally, round the size of the total struct up to the alignment of the
@ -498,7 +503,7 @@ void ASTRecordLayoutBuilder::Layout(const ObjCInterfaceDecl *D,
MaxFieldAlignment = PPA->getAlignment();
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
UpdateAlignment(AA->getAlignment());
UpdateAlignment(AA->getMaxAlignment());
// Layout each ivar sequentially.
llvm::SmallVector<ObjCIvarDecl*, 16> Ivars;
@ -519,84 +524,111 @@ void ASTRecordLayoutBuilder::LayoutFields(const RecordDecl *D) {
LayoutField(*Field);
}
void ASTRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
bool FieldPacked = Packed || D->hasAttr<PackedAttr>();
uint64_t FieldOffset = IsUnion ? 0 : (DataSize - UnfilledBitsInLastByte);
uint64_t FieldSize = D->getBitWidth()->EvaluateAsInt(Ctx).getZExtValue();
std::pair<uint64_t, unsigned> FieldInfo = Ctx.getTypeInfo(D->getType());
uint64_t TypeSize = FieldInfo.first;
unsigned FieldAlign = FieldInfo.second;
if (FieldPacked)
FieldAlign = 1;
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
FieldAlign = std::max(FieldAlign, AA->getMaxAlignment());
// The maximum field alignment overrides the aligned attribute.
if (MaxFieldAlignment)
FieldAlign = std::min(FieldAlign, MaxFieldAlignment);
// Check if we need to add padding to give the field the correct
// alignment.
if (FieldSize == 0 || (FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize)
FieldOffset = (FieldOffset + (FieldAlign-1)) & ~(FieldAlign-1);
// Padding members don't affect overall alignment
if (!D->getIdentifier())
FieldAlign = 1;
// Place this field at the current location.
FieldOffsets.push_back(FieldOffset);
// Update DataSize to include the last byte containing (part of) the bitfield.
if (IsUnion) {
// FIXME: I think FieldSize should be TypeSize here.
DataSize = std::max(DataSize, FieldSize);
} else {
uint64_t NewSizeInBits = FieldOffset + FieldSize;
DataSize = llvm::RoundUpToAlignment(NewSizeInBits, 8);
UnfilledBitsInLastByte = DataSize - NewSizeInBits;
}
// Update the size.
Size = std::max(Size, DataSize);
// Remember max struct/class alignment.
UpdateAlignment(FieldAlign);
}
void ASTRecordLayoutBuilder::LayoutField(const FieldDecl *D) {
bool FieldPacked = Packed;
if (D->isBitField()) {
LayoutBitField(D);
return;
}
// Reset the unfilled bits.
UnfilledBitsInLastByte = 0;
bool FieldPacked = Packed || D->hasAttr<PackedAttr>();
uint64_t FieldOffset = IsUnion ? 0 : DataSize;
uint64_t FieldSize;
unsigned FieldAlign;
FieldPacked |= D->hasAttr<PackedAttr>();
if (const Expr *BitWidthExpr = D->getBitWidth()) {
// TODO: Need to check this algorithm on other targets!
// (tested on Linux-X86)
FieldSize = BitWidthExpr->EvaluateAsInt(Ctx).getZExtValue();
std::pair<uint64_t, unsigned> FieldInfo = Ctx.getTypeInfo(D->getType());
uint64_t TypeSize = FieldInfo.first;
FieldAlign = FieldInfo.second;
if (FieldPacked)
FieldAlign = 1;
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
FieldAlign = std::max(FieldAlign, AA->getAlignment());
// The maximum field alignment overrides the aligned attribute.
if (MaxFieldAlignment)
FieldAlign = std::min(FieldAlign, MaxFieldAlignment);
// Check if we need to add padding to give the field the correct
// alignment.
if (FieldSize == 0 || (FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize)
FieldOffset = (FieldOffset + (FieldAlign-1)) & ~(FieldAlign-1);
// Padding members don't affect overall alignment
if (!D->getIdentifier())
FieldAlign = 1;
if (D->getType()->isIncompleteArrayType()) {
// This is a flexible array member; we can't directly
// query getTypeInfo about these, so we figure it out here.
// Flexible array members don't have any size, but they
// have to be aligned appropriately for their element type.
FieldSize = 0;
const ArrayType* ATy = Ctx.getAsArrayType(D->getType());
FieldAlign = Ctx.getTypeAlign(ATy->getElementType());
} else if (const ReferenceType *RT = D->getType()->getAs<ReferenceType>()) {
unsigned AS = RT->getPointeeType().getAddressSpace();
FieldSize = Ctx.Target.getPointerWidth(AS);
FieldAlign = Ctx.Target.getPointerAlign(AS);
} else {
if (D->getType()->isIncompleteArrayType()) {
// This is a flexible array member; we can't directly
// query getTypeInfo about these, so we figure it out here.
// Flexible array members don't have any size, but they
// have to be aligned appropriately for their element type.
FieldSize = 0;
const ArrayType* ATy = Ctx.getAsArrayType(D->getType());
FieldAlign = Ctx.getTypeAlign(ATy->getElementType());
} else if (const ReferenceType *RT = D->getType()->getAs<ReferenceType>()) {
unsigned AS = RT->getPointeeType().getAddressSpace();
FieldSize = Ctx.Target.getPointerWidth(AS);
FieldAlign = Ctx.Target.getPointerAlign(AS);
} else {
std::pair<uint64_t, unsigned> FieldInfo = Ctx.getTypeInfo(D->getType());
FieldSize = FieldInfo.first;
FieldAlign = FieldInfo.second;
}
if (FieldPacked)
FieldAlign = 8;
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
FieldAlign = std::max(FieldAlign, AA->getAlignment());
// The maximum field alignment overrides the aligned attribute.
if (MaxFieldAlignment)
FieldAlign = std::min(FieldAlign, MaxFieldAlignment);
// Round up the current record size to the field's alignment boundary.
FieldOffset = llvm::RoundUpToAlignment(FieldOffset, FieldAlign);
if (!IsUnion) {
while (true) {
// Check if we can place the field at this offset.
if (canPlaceFieldAtOffset(D, FieldOffset))
break;
// We couldn't place the field at the offset. Try again at a new offset.
FieldOffset += FieldAlign;
}
UpdateEmptyClassOffsets(D, FieldOffset);
}
std::pair<uint64_t, unsigned> FieldInfo = Ctx.getTypeInfo(D->getType());
FieldSize = FieldInfo.first;
FieldAlign = FieldInfo.second;
}
if (FieldPacked)
FieldAlign = 8;
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
FieldAlign = std::max(FieldAlign, AA->getMaxAlignment());
// The maximum field alignment overrides the aligned attribute.
if (MaxFieldAlignment)
FieldAlign = std::min(FieldAlign, MaxFieldAlignment);
// Round up the current record size to the field's alignment boundary.
FieldOffset = llvm::RoundUpToAlignment(FieldOffset, FieldAlign);
if (!IsUnion) {
while (true) {
// Check if we can place the field at this offset.
if (canPlaceFieldAtOffset(D, FieldOffset))
break;
// We couldn't place the field at the offset. Try again at a new offset.
FieldOffset += FieldAlign;
}
UpdateEmptyClassOffsets(D, FieldOffset);
}
// Place this field at the current location.
FieldOffsets.push_back(FieldOffset);
@ -619,7 +651,7 @@ void ASTRecordLayoutBuilder::FinishLayout() {
Size = 8;
// Finally, round the size of the record up to the alignment of the
// record itself.
Size = (Size + (Alignment-1)) & ~(Alignment-1);
Size = llvm::RoundUpToAlignment(Size, Alignment);
}
void ASTRecordLayoutBuilder::UpdateAlignment(unsigned NewAlignment) {
@ -631,6 +663,31 @@ void ASTRecordLayoutBuilder::UpdateAlignment(unsigned NewAlignment) {
Alignment = NewAlignment;
}
static const CXXMethodDecl *GetKeyFunction(const CXXRecordDecl *RD) {
if (!RD->isDynamicClass())
return 0;
for (CXXRecordDecl::method_iterator I = RD->method_begin(),
E = RD->method_end(); I != E; ++I) {
const CXXMethodDecl *MD = *I;
if (!MD->isVirtual())
continue;
if (MD->isPure())
continue;
const FunctionDecl *fn;
if (MD->getBody(fn) && !fn->isOutOfLine())
continue;
// We found it.
return MD;
}
return 0;
}
const ASTRecordLayout *
ASTRecordLayoutBuilder::ComputeLayout(ASTContext &Ctx,
const RecordDecl *D) {
@ -654,17 +711,19 @@ ASTRecordLayoutBuilder::ComputeLayout(ASTContext &Ctx,
uint64_t NonVirtualSize =
IsPODForThePurposeOfLayout ? DataSize : Builder.NonVirtualSize;
const CXXMethodDecl *KeyFunction = GetKeyFunction(cast<CXXRecordDecl>(D));
return new ASTRecordLayout(Builder.Size, Builder.Alignment, DataSize,
Builder.FieldOffsets.data(),
Builder.FieldOffsets.size(),
NonVirtualSize,
Builder.NonVirtualAlignment,
Builder.PrimaryBase,
Builder.PrimaryBaseWasVirtual,
Builder.Bases.data(),
Builder.Bases.size(),
Builder.VBases.data(),
Builder.VBases.size());
Builder.VBases.size(),
KeyFunction);
}
const ASTRecordLayout *

View File

@ -10,6 +10,7 @@
#ifndef LLVM_CLANG_AST_RECORDLAYOUTBUILDER_H
#define LLVM_CLANG_AST_RECORDLAYOUTBUILDER_H
#include "clang/AST/RecordLayout.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/System/DataTypes.h"
@ -27,12 +28,21 @@ namespace clang {
class ASTRecordLayoutBuilder {
ASTContext &Ctx;
/// Size - The current size of the record layout.
uint64_t Size;
/// Alignment - The current alignment of the record layout.
unsigned Alignment;
llvm::SmallVector<uint64_t, 16> FieldOffsets;
/// Packed - Whether the record is packed or not.
bool Packed;
/// UnfilledBitsInLastByte - If the last field laid out was a bitfield,
/// this contains the number of bits in the last byte that can be used for
/// an adjacent bitfield if necessary.
unsigned char UnfilledBitsInLastByte;
/// MaxFieldAlignment - The maximum allowed field alignment. This is set by
/// #pragma pack.
@ -45,8 +55,8 @@ class ASTRecordLayoutBuilder {
uint64_t NonVirtualSize;
unsigned NonVirtualAlignment;
const CXXRecordDecl *PrimaryBase;
bool PrimaryBaseWasVirtual;
ASTRecordLayout::PrimaryBaseInfo PrimaryBase;
typedef llvm::SmallVector<std::pair<const CXXRecordDecl *,
uint64_t>, 4> BaseOffsetsTy;
@ -74,6 +84,7 @@ class ASTRecordLayoutBuilder {
void LayoutFields(const RecordDecl *D);
void LayoutField(const FieldDecl *D);
void LayoutBitField(const FieldDecl *D);
void SelectPrimaryBase(const CXXRecordDecl *RD);
void SelectPrimaryVBase(const CXXRecordDecl *RD,
@ -84,9 +95,8 @@ class ASTRecordLayoutBuilder {
/// base class.
void IdentifyPrimaryBases(const CXXRecordDecl *RD);
void setPrimaryBase(const CXXRecordDecl *PB, bool Virtual) {
PrimaryBase = PB;
PrimaryBaseWasVirtual = Virtual;
void setPrimaryBase(const CXXRecordDecl *Base, bool IsVirtual) {
PrimaryBase = ASTRecordLayout::PrimaryBaseInfo(Base, IsVirtual);
}
bool IsNearlyEmpty(const CXXRecordDecl *RD) const;

View File

@ -88,8 +88,8 @@ void Stmt::addStmtClass(StmtClass s) {
static bool StatSwitch = false;
bool Stmt::CollectingStats(bool enable) {
if (enable) StatSwitch = true;
bool Stmt::CollectingStats(bool Enable) {
if (Enable) StatSwitch = true;
return StatSwitch;
}
@ -559,7 +559,7 @@ Stmt::child_iterator CXXCatchStmt::child_end() {
return &HandlerBlock + 1;
}
QualType CXXCatchStmt::getCaughtType() {
QualType CXXCatchStmt::getCaughtType() const {
if (ExceptionDecl)
return ExceptionDecl->getType();
return QualType();

View File

@ -17,7 +17,6 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/Support/Compiler.h"
#include <cstdio>
using namespace clang;
@ -26,7 +25,7 @@ using namespace clang;
//===----------------------------------------------------------------------===//
namespace {
class VISIBILITY_HIDDEN StmtDumper : public StmtVisitor<StmtDumper> {
class StmtDumper : public StmtVisitor<StmtDumper> {
SourceManager *SM;
FILE *F;
unsigned IndentLevel;

View File

@ -16,7 +16,6 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/PrettyPrinter.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Format.h"
using namespace clang;
@ -25,7 +24,7 @@ using namespace clang;
//===----------------------------------------------------------------------===//
namespace {
class VISIBILITY_HIDDEN StmtPrinter : public StmtVisitor<StmtPrinter> {
class StmtPrinter : public StmtVisitor<StmtPrinter> {
llvm::raw_ostream &OS;
ASTContext &Context;
unsigned IndentLevel;
@ -483,19 +482,26 @@ void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) {
Policy);
}
void StmtPrinter::VisitUnresolvedDeclRefExpr(UnresolvedDeclRefExpr *Node) {
void StmtPrinter::VisitDependentScopeDeclRefExpr(
DependentScopeDeclRefExpr *Node) {
Node->getQualifier()->print(OS, Policy);
OS << Node->getDeclName().getAsString();
if (Node->hasExplicitTemplateArgs())
OS << TemplateSpecializationType::PrintTemplateArgumentList(
Node->getTemplateArgs(),
Node->getNumTemplateArgs(),
Policy);
}
void StmtPrinter::VisitTemplateIdRefExpr(TemplateIdRefExpr *Node) {
void StmtPrinter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *Node) {
if (Node->getQualifier())
Node->getQualifier()->print(OS, Policy);
Node->getTemplateName().print(OS, Policy, true);
OS << TemplateSpecializationType::PrintTemplateArgumentList(
Node->getTemplateArgs(),
OS << Node->getName().getAsString();
if (Node->hasExplicitTemplateArgs())
OS << TemplateSpecializationType::PrintTemplateArgumentList(
Node->getTemplateArgs(),
Node->getNumTemplateArgs(),
Policy);
Policy);
}
void StmtPrinter::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) {
@ -1048,11 +1054,6 @@ void StmtPrinter::VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *Node) {
OS << Node->getType().getAsString() << "()";
}
void
StmtPrinter::VisitCXXConditionDeclExpr(CXXConditionDeclExpr *E) {
PrintRawDecl(E->getVarDecl());
}
void StmtPrinter::VisitCXXNewExpr(CXXNewExpr *E) {
if (E->isGlobalNew())
OS << "::";
@ -1118,10 +1119,6 @@ void StmtPrinter::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) {
OS << TypeS;
}
void StmtPrinter::VisitUnresolvedFunctionNameExpr(UnresolvedFunctionNameExpr *E) {
OS << E->getName().getAsString();
}
void StmtPrinter::VisitCXXConstructExpr(CXXConstructExpr *E) {
// Nothing to print.
}
@ -1146,7 +1143,8 @@ StmtPrinter::VisitCXXUnresolvedConstructExpr(
OS << ")";
}
void StmtPrinter::VisitCXXUnresolvedMemberExpr(CXXUnresolvedMemberExpr *Node) {
void StmtPrinter::VisitCXXDependentScopeMemberExpr(
CXXDependentScopeMemberExpr *Node) {
PrintExpr(Node->getBase());
OS << (Node->isArrow() ? "->" : ".");
if (NestedNameSpecifier *Qualifier = Node->getQualifier())
@ -1165,6 +1163,24 @@ void StmtPrinter::VisitCXXUnresolvedMemberExpr(CXXUnresolvedMemberExpr *Node) {
}
}
void StmtPrinter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *Node) {
PrintExpr(Node->getBase());
OS << (Node->isArrow() ? "->" : ".");
if (NestedNameSpecifier *Qualifier = Node->getQualifier())
Qualifier->print(OS, Policy);
// FIXME: this might originally have been written with 'template'
OS << Node->getMemberName().getAsString();
if (Node->hasExplicitTemplateArgs()) {
OS << TemplateSpecializationType::PrintTemplateArgumentList(
Node->getTemplateArgs(),
Node->getNumTemplateArgs(),
Policy);
}
}
static const char *getTypeTraitName(UnaryTypeTrait UTT) {
switch (UTT) {
default: assert(false && "Unknown type trait");

View File

@ -20,11 +20,10 @@
#include "clang/AST/ExprObjC.h"
#include "clang/AST/StmtVisitor.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/Support/Compiler.h"
using namespace clang;
namespace {
class VISIBILITY_HIDDEN StmtProfiler : public StmtVisitor<StmtProfiler> {
class StmtProfiler : public StmtVisitor<StmtProfiler> {
llvm::FoldingSetNodeID &ID;
ASTContext &Context;
bool Canonical;
@ -108,14 +107,17 @@ void StmtProfiler::VisitLabelStmt(LabelStmt *S) {
void StmtProfiler::VisitIfStmt(IfStmt *S) {
VisitStmt(S);
VisitDecl(S->getConditionVariable());
}
void StmtProfiler::VisitSwitchStmt(SwitchStmt *S) {
VisitStmt(S);
VisitDecl(S->getConditionVariable());
}
void StmtProfiler::VisitWhileStmt(WhileStmt *S) {
VisitStmt(S);
VisitDecl(S->getConditionVariable());
}
void StmtProfiler::VisitDoStmt(DoStmt *S) {
@ -481,10 +483,6 @@ void StmtProfiler::VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *S) {
VisitExpr(S);
}
void StmtProfiler::VisitCXXConditionDeclExpr(CXXConditionDeclExpr *S) {
VisitDeclRefExpr(S);
}
void StmtProfiler::VisitCXXDeleteExpr(CXXDeleteExpr *S) {
VisitExpr(S);
ID.AddBoolean(S->isGlobalDelete());
@ -515,9 +513,13 @@ void StmtProfiler::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *S) {
}
void
StmtProfiler::VisitUnresolvedFunctionNameExpr(UnresolvedFunctionNameExpr *S) {
StmtProfiler::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *S) {
VisitExpr(S);
VisitNestedNameSpecifier(S->getQualifier());
VisitName(S->getName());
ID.AddBoolean(S->hasExplicitTemplateArgs());
if (S->hasExplicitTemplateArgs())
VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs());
}
void StmtProfiler::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *S) {
@ -526,18 +528,14 @@ void StmtProfiler::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *S) {
VisitType(S->getQueriedType());
}
void StmtProfiler::VisitUnresolvedDeclRefExpr(UnresolvedDeclRefExpr *S) {
void
StmtProfiler::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *S) {
VisitExpr(S);
VisitName(S->getDeclName());
VisitNestedNameSpecifier(S->getQualifier());
ID.AddBoolean(S->isAddressOfOperand());
}
void StmtProfiler::VisitTemplateIdRefExpr(TemplateIdRefExpr *S) {
VisitExpr(S);
VisitNestedNameSpecifier(S->getQualifier());
VisitTemplateName(S->getTemplateName());
VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs());
ID.AddBoolean(S->hasExplicitTemplateArgs());
if (S->hasExplicitTemplateArgs())
VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs());
}
void StmtProfiler::VisitCXXExprWithTemporaries(CXXExprWithTemporaries *S) {
@ -554,11 +552,25 @@ StmtProfiler::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *S) {
VisitType(S->getTypeAsWritten());
}
void StmtProfiler::VisitCXXUnresolvedMemberExpr(CXXUnresolvedMemberExpr *S) {
void
StmtProfiler::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *S) {
VisitExpr(S);
ID.AddBoolean(S->isArrow());
VisitNestedNameSpecifier(S->getQualifier());
VisitName(S->getMember());
ID.AddBoolean(S->hasExplicitTemplateArgumentList());
if (S->hasExplicitTemplateArgumentList())
VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs());
}
void StmtProfiler::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *S) {
VisitExpr(S);
ID.AddBoolean(S->isArrow());
VisitNestedNameSpecifier(S->getQualifier());
VisitName(S->getMemberName());
ID.AddBoolean(S->hasExplicitTemplateArgs());
if (S->hasExplicitTemplateArgs())
VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs());
}
void StmtProfiler::VisitObjCStringLiteral(ObjCStringLiteral *S) {

View File

@ -30,8 +30,9 @@ void Stmt::viewAST() const {
namespace llvm {
template<>
struct DOTGraphTraits<const Stmt*> : public DefaultDOTGraphTraits {
static std::string getNodeLabel(const Stmt* Node, const Stmt* Graph,
bool ShortNames) {
DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {}
static std::string getNodeLabel(const Stmt* Node, const Stmt* Graph) {
#ifndef NDEBUG
std::string OutSStr;

View File

@ -15,6 +15,7 @@
#include "llvm/ADT/FoldingSet.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/AST/TypeLoc.h"
@ -59,8 +60,17 @@ void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
break;
case Template:
ID.AddPointer(Context.getCanonicalTemplateName(getAsTemplate())
.getAsVoidPointer());
if (TemplateTemplateParmDecl *TTP
= dyn_cast_or_null<TemplateTemplateParmDecl>(
getAsTemplate().getAsTemplateDecl())) {
ID.AddBoolean(true);
ID.AddInteger(TTP->getDepth());
ID.AddInteger(TTP->getPosition());
} else {
ID.AddBoolean(false);
ID.AddPointer(Context.getCanonicalTemplateName(getAsTemplate())
.getAsVoidPointer());
}
break;
case Integral:

View File

@ -725,6 +725,7 @@ const char *BuiltinType::getName(const LangOptions &LO) const {
case UndeducedAuto: return "auto";
case ObjCId: return "id";
case ObjCClass: return "Class";
case ObjCSel: return "SEL";
}
}
@ -865,6 +866,11 @@ static bool isDependent(const TemplateArgument &Arg) {
return false;
}
bool TemplateSpecializationType::
anyDependentTemplateArguments(const TemplateArgumentListInfo &Args) {
return anyDependentTemplateArguments(Args.getArgumentArray(), Args.size());
}
bool TemplateSpecializationType::
anyDependentTemplateArguments(const TemplateArgumentLoc *Args, unsigned N) {
for (unsigned i = 0; i != N; ++i)

View File

@ -535,6 +535,8 @@ void TypePrinter::PrintObjCObjectPointer(const ObjCObjectPointerType *T,
ObjCQIString = "id";
else if (T->isObjCClassType() || T->isObjCQualifiedClassType())
ObjCQIString = "Class";
else if (T->isObjCSelType())
ObjCQIString = "SEL";
else
ObjCQIString = T->getInterfaceDecl()->getNameAsString();
@ -599,6 +601,14 @@ static void PrintTemplateArgument(std::string &Buffer,
}
}
std::string TemplateSpecializationType::
PrintTemplateArgumentList(const TemplateArgumentListInfo &Args,
const PrintingPolicy &Policy) {
return PrintTemplateArgumentList(Args.getArgumentArray(),
Args.size(),
Policy);
}
std::string
TemplateSpecializationType::PrintTemplateArgumentList(
const TemplateArgument *Args,

View File

@ -18,21 +18,12 @@
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/ParentMap.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Analysis/Support/BumpVector.h"
#include "llvm/Support/ErrorHandling.h"
using namespace clang;
AnalysisContext::~AnalysisContext() {
delete cfg;
delete liveness;
delete PM;
}
AnalysisContextManager::~AnalysisContextManager() {
for (ContextMap::iterator I = Contexts.begin(), E = Contexts.end(); I!=E; ++I)
delete I->second;
}
void AnalysisContextManager::clear() {
for (ContextMap::iterator I = Contexts.begin(), E = Contexts.end(); I!=E; ++I)
delete I->second;
@ -73,7 +64,7 @@ LiveVariables *AnalysisContext::getLiveVariables() {
if (!c)
return 0;
liveness = new LiveVariables(D->getASTContext(), *c);
liveness = new LiveVariables(*this);
liveness->runOnCFG(*c);
liveness->runOnAllBlocks(*c, 0, true);
}
@ -157,3 +148,75 @@ ScopeContext *LocationContextManager::getScope(AnalysisContext *ctx,
}
return scope;
}
//===----------------------------------------------------------------------===//
// Lazily generated map to query the external variables referenced by a Block.
//===----------------------------------------------------------------------===//
namespace {
class FindBlockDeclRefExprsVals : public StmtVisitor<FindBlockDeclRefExprsVals>{
BumpVector<const VarDecl*> &BEVals;
BumpVectorContext &BC;
public:
FindBlockDeclRefExprsVals(BumpVector<const VarDecl*> &bevals,
BumpVectorContext &bc)
: BEVals(bevals), BC(bc) {}
void VisitStmt(Stmt *S) {
for (Stmt::child_iterator I = S->child_begin(), E = S->child_end();I!=E;++I)
if (Stmt *child = *I)
Visit(child);
}
void VisitBlockDeclRefExpr(BlockDeclRefExpr *DR) {
if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()))
BEVals.push_back(VD, BC);
}
};
} // end anonymous namespace
typedef BumpVector<const VarDecl*> DeclVec;
static DeclVec* LazyInitializeReferencedDecls(const BlockDecl *BD,
void *&Vec,
llvm::BumpPtrAllocator &A) {
if (Vec)
return (DeclVec*) Vec;
BumpVectorContext BC(A);
DeclVec *BV = (DeclVec*) A.Allocate<DeclVec>();
new (BV) DeclVec(BC, 10);
// Find the referenced variables.
FindBlockDeclRefExprsVals F(*BV, BC);
F.Visit(BD->getBody());
Vec = BV;
return BV;
}
std::pair<AnalysisContext::referenced_decls_iterator,
AnalysisContext::referenced_decls_iterator>
AnalysisContext::getReferencedBlockVars(const BlockDecl *BD) {
if (!ReferencedBlockVars)
ReferencedBlockVars = new llvm::DenseMap<const BlockDecl*,void*>();
DeclVec *V = LazyInitializeReferencedDecls(BD, (*ReferencedBlockVars)[BD], A);
return std::make_pair(V->begin(), V->end());
}
//===----------------------------------------------------------------------===//
// Cleanup.
//===----------------------------------------------------------------------===//
AnalysisContext::~AnalysisContext() {
delete cfg;
delete liveness;
delete PM;
delete ReferencedBlockVars;
}
AnalysisContextManager::~AnalysisContextManager() {
for (ContextMap::iterator I = Contexts.begin(), E = Contexts.end(); I!=E; ++I)
delete I->second;
}

View File

@ -20,7 +20,7 @@
using namespace clang;
namespace {
class VISIBILITY_HIDDEN ArrayBoundChecker :
class ArrayBoundChecker :
public CheckerVisitor<ArrayBoundChecker> {
BuiltinBug *BT;
public:
@ -62,8 +62,7 @@ void ArrayBoundChecker::VisitLocation(CheckerContext &C, const Stmt *S, SVal l){
const GRState *StInBound = state->AssumeInBound(Idx, NumElements, true);
const GRState *StOutBound = state->AssumeInBound(Idx, NumElements, false);
if (StOutBound && !StInBound) {
ExplodedNode *N = C.GenerateNode(S, StOutBound, true);
ExplodedNode *N = C.GenerateSink(StOutBound);
if (!N)
return;
@ -80,7 +79,12 @@ void ArrayBoundChecker::VisitLocation(CheckerContext &C, const Stmt *S, SVal l){
new RangedBugReport(*BT, BT->getDescription(), N);
report->addRange(S->getSourceRange());
C.EmitReport(report);
return;
}
// Array bound check succeeded. From this point forward the array bound
// should always succeed.
assert(StInBound);
C.addTransition(StInBound);
}

View File

@ -19,7 +19,7 @@
using namespace clang;
namespace {
class VISIBILITY_HIDDEN AttrNonNullChecker
class AttrNonNullChecker
: public CheckerVisitor<AttrNonNullChecker> {
BugType *BT;
public:
@ -39,7 +39,6 @@ void clang::RegisterAttrNonNullChecker(GRExprEngine &Eng) {
void AttrNonNullChecker::PreVisitCallExpr(CheckerContext &C,
const CallExpr *CE) {
const GRState *state = C.getState();
const GRState *originalState = state;
// Check if the callee has a 'nonnull' attribute.
SVal X = state->getSVal(CE->getCallee());
@ -74,7 +73,7 @@ void AttrNonNullChecker::PreVisitCallExpr(CheckerContext &C,
if (stateNull && !stateNotNull) {
// Generate an error node. Check for a null node in case
// we cache out.
if (ExplodedNode *errorNode = C.GenerateNode(CE, stateNull, true)) {
if (ExplodedNode *errorNode = C.GenerateSink(stateNull)) {
// Lazily allocate the BugType object if it hasn't already been
// created. Ownership is transferred to the BugReporter object once
@ -109,6 +108,5 @@ void AttrNonNullChecker::PreVisitCallExpr(CheckerContext &C,
// If we reach here all of the arguments passed the nonnull check.
// If 'state' has been updated generated a new node.
if (state != originalState)
C.addTransition(C.GenerateNode(CE, state));
C.addTransition(state);
}

View File

@ -1,57 +0,0 @@
//===--- BadCallChecker.h - Bad call checker --------------------*- C++ -*--==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This defines BadCallChecker, a builtin check in GRExprEngine that performs
// checks for bad callee at call sites.
//
//===----------------------------------------------------------------------===//
#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
#include "clang/Analysis/PathSensitive/BugReporter.h"
#include "GRExprEngineInternalChecks.h"
using namespace clang;
namespace {
class VISIBILITY_HIDDEN BadCallChecker : public CheckerVisitor<BadCallChecker> {
BuiltinBug *BT;
public:
BadCallChecker() : BT(0) {}
static void *getTag() {
static int x = 0;
return &x;
}
void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
};
} // end anonymous namespace
void clang::RegisterBadCallChecker(GRExprEngine &Eng) {
Eng.registerCheck(new BadCallChecker());
}
void BadCallChecker::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
const Expr *Callee = CE->getCallee()->IgnoreParens();
SVal L = C.getState()->getSVal(Callee);
if (L.isUndef() || isa<loc::ConcreteInt>(L)) {
if (ExplodedNode *N = C.GenerateNode(CE, true)) {
if (!BT)
BT = new BuiltinBug("Invalid function call",
"Called function pointer is a null or undefined pointer value");
EnhancedBugReport *R =
new EnhancedBugReport(*BT, BT->getDescription(), N);
R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
bugreporter::GetCalleeExpr(N));
C.EmitReport(R);
}
}
}

View File

@ -16,14 +16,13 @@
#include "clang/Analysis/PathSensitive/GRState.h"
#include "clang/Analysis/PathSensitive/GRStateTrait.h"
#include "clang/Analysis/PathSensitive/GRTransferFuncs.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
namespace { class VISIBILITY_HIDDEN ConstNotEq {}; }
namespace { class VISIBILITY_HIDDEN ConstEq {}; }
namespace { class ConstNotEq {}; }
namespace { class ConstEq {}; }
typedef llvm::ImmutableMap<SymbolRef,GRState::IntSetTy> ConstNotEqTy;
typedef llvm::ImmutableMap<SymbolRef,const llvm::APSInt*> ConstEqTy;
@ -46,7 +45,7 @@ struct GRStateTrait<ConstEq> : public GRStatePartialTrait<ConstEqTy> {
namespace {
// BasicConstraintManager only tracks equality and inequality constraints of
// constants and integer variables.
class VISIBILITY_HIDDEN BasicConstraintManager
class BasicConstraintManager
: public SimpleConstraintManager {
GRState::IntSetTy::Factory ISetFactory;
public:

View File

@ -22,12 +22,12 @@
#include "clang/Analysis/PathSensitive/BugReporter.h"
#include "clang/Analysis/PathSensitive/MemRegion.h"
#include "clang/Analysis/PathDiagnostic.h"
#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
#include "clang/Analysis/LocalCheckers.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/ASTContext.h"
#include "llvm/Support/Compiler.h"
using namespace clang;
@ -52,12 +52,12 @@ static const char* GetReceiverNameType(const ObjCMessageExpr* ME) {
namespace {
class VISIBILITY_HIDDEN APIMisuse : public BugType {
class APIMisuse : public BugType {
public:
APIMisuse(const char* name) : BugType(name, "API Misuse (Apple)") {}
};
class VISIBILITY_HIDDEN BasicObjCFoundationChecks : public GRSimpleAPICheck {
class BasicObjCFoundationChecks : public GRSimpleAPICheck {
APIMisuse *BT;
BugReporter& BR;
ASTContext &Ctx;
@ -87,7 +87,7 @@ class VISIBILITY_HIDDEN BasicObjCFoundationChecks : public GRSimpleAPICheck {
// by the BugReporter object 'BR' once we call BR.EmitWarning.
if (!BT) BT = new APIMisuse("nil argument");
RangedBugReport *R = new RangedBugReport(*BT, os.str().c_str(), N);
RangedBugReport *R = new RangedBugReport(*BT, os.str(), N);
R->addRange(ME->getArg(Arg)->getSourceRange());
BR.EmitReport(R);
}
@ -228,7 +228,7 @@ bool BasicObjCFoundationChecks::AuditNSString(ExplodedNode* N,
namespace {
class VISIBILITY_HIDDEN AuditCFNumberCreate : public GRSimpleAPICheck {
class AuditCFNumberCreate : public GRSimpleAPICheck {
APIMisuse* BT;
// FIXME: Either this should be refactored into GRSimpleAPICheck, or
@ -435,7 +435,7 @@ void AuditCFNumberCreate::AddError(const TypedRegion* R, const Expr* Ex,
// Lazily create the BugType object. This will be owned
// by the BugReporter object 'BR' once we call BR.EmitWarning.
if (!BT) BT = new APIMisuse("Bad use of CFNumberCreate");
RangedBugReport *report = new RangedBugReport(*BT, os.str().c_str(), N);
RangedBugReport *report = new RangedBugReport(*BT, os.str(), N);
report->addRange(Ex->getSourceRange());
BR.EmitReport(report);
}
@ -450,7 +450,7 @@ clang::CreateAuditCFNumberCreate(ASTContext& Ctx, BugReporter& BR) {
//===----------------------------------------------------------------------===//
namespace {
class VISIBILITY_HIDDEN AuditCFRetainRelease : public GRSimpleAPICheck {
class AuditCFRetainRelease : public GRSimpleAPICheck {
APIMisuse *BT;
// FIXME: Either this should be refactored into GRSimpleAPICheck, or
@ -521,6 +521,64 @@ clang::CreateAuditCFRetainRelease(ASTContext& Ctx, BugReporter& BR) {
return new AuditCFRetainRelease(Ctx, BR);
}
//===----------------------------------------------------------------------===//
// Check for sending 'retain', 'release', or 'autorelease' directly to a Class.
//===----------------------------------------------------------------------===//
namespace {
class ClassReleaseChecker :
public CheckerVisitor<ClassReleaseChecker> {
Selector releaseS;
Selector retainS;
Selector autoreleaseS;
Selector drainS;
BugType *BT;
public:
ClassReleaseChecker(ASTContext &Ctx)
: releaseS(GetNullarySelector("release", Ctx)),
retainS(GetNullarySelector("retain", Ctx)),
autoreleaseS(GetNullarySelector("autorelease", Ctx)),
drainS(GetNullarySelector("drain", Ctx)),
BT(0) {}
static void *getTag() { static int x = 0; return &x; }
void PreVisitObjCMessageExpr(CheckerContext &C, const ObjCMessageExpr *ME);
};
}
void ClassReleaseChecker::PreVisitObjCMessageExpr(CheckerContext &C,
const ObjCMessageExpr *ME) {
const IdentifierInfo *ClsName = ME->getClassName();
if (!ClsName)
return;
Selector S = ME->getSelector();
if (!(S == releaseS || S == retainS || S == autoreleaseS || S == drainS))
return;
if (!BT)
BT = new APIMisuse("message incorrectly sent to class instead of class "
"instance");
ExplodedNode *N = C.GenerateNode();
if (!N)
return;
llvm::SmallString<200> buf;
llvm::raw_svector_ostream os(buf);
os << "The '" << S.getAsString() << "' message should be sent to instances "
"of class '" << ClsName->getName()
<< "' and not the class directly";
RangedBugReport *report = new RangedBugReport(*BT, os.str(), N);
report->addRange(ME->getSourceRange());
C.EmitReport(report);
}
//===----------------------------------------------------------------------===//
// Check registration.
//===----------------------------------------------------------------------===//
@ -536,4 +594,5 @@ void clang::RegisterAppleChecks(GRExprEngine& Eng, const Decl &D) {
RegisterNSErrorChecks(BR, Eng, D);
RegisterNSAutoreleasePoolChecks(Eng);
Eng.registerCheck(new ClassReleaseChecker(Ctx));
}

Some files were not shown because too many files have changed in this diff Show More