Update clang to r90226.
This commit is contained in:
parent
f5bd02d290
commit
1569ce6868
4
Makefile
4
Makefile
@ -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
|
||||
|
@ -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 */,
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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) {}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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]; }
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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() {}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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(); }
|
||||
|
@ -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:
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -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));
|
||||
|
@ -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", "")
|
||||
|
@ -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">;
|
||||
|
@ -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<
|
||||
|
@ -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">;
|
||||
|
@ -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>">;
|
||||
|
@ -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">;
|
||||
|
@ -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<
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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";
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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">;
|
||||
|
@ -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, $@) $<
|
||||
|
||||
|
@ -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>;
|
||||
|
@ -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(); }
|
||||
|
@ -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"
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -77,7 +77,7 @@ class AnalyzerOptions {
|
||||
AnalyzeAll = 0;
|
||||
AnalyzerDisplayProgress = 0;
|
||||
EagerlyAssume = 0;
|
||||
PurgeDead = 0;
|
||||
PurgeDead = 1;
|
||||
TrimGraph = 0;
|
||||
VisualizeEGDot = 0;
|
||||
VisualizeEGUbi = 0;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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 *
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
/// @{
|
||||
|
@ -107,7 +107,7 @@ class FrontendOptions {
|
||||
|
||||
public:
|
||||
FrontendOptions() {
|
||||
DebugCodeCompletionPrinter = 0;
|
||||
DebugCodeCompletionPrinter = 1;
|
||||
DisableFree = 0;
|
||||
EmptyInputOnly = 0;
|
||||
ProgramAction = frontend::ParseSyntaxOnly;
|
||||
|
83
include/clang/Frontend/LangStandard.h
Normal file
83
include/clang/Frontend/LangStandard.h
Normal 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
|
83
include/clang/Frontend/LangStandards.def
Normal file
83
include/clang/Frontend/LangStandards.def
Normal 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
|
@ -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.
|
||||
|
@ -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 {
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
///
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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) {
|
||||
|
205
lib/AST/Decl.cpp
205
lib/AST/Decl.cpp
@ -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() {
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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];
|
||||
|
@ -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) {
|
||||
|
214
lib/AST/Expr.cpp
214
lib/AST/Expr.cpp
@ -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:
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 *
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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:
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user