Update clang to r94309.

This commit is contained in:
Roman Divacky 2010-01-23 11:10:26 +00:00
parent ee791dde72
commit 5044f5c816
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor/clang/dist/; revision=202879
238 changed files with 9491 additions and 6632 deletions

View File

@ -21,7 +21,6 @@
1A2A54BD0FD1DD1C00F4CE45 /* HTMLPrint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2A54AC0FD1DD1C00F4CE45 /* HTMLPrint.cpp */; };
1A2A54BE0FD1DD1C00F4CE45 /* PrintParserCallbacks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2A54AD0FD1DD1C00F4CE45 /* PrintParserCallbacks.cpp */; };
1A2A54BF0FD1DD1C00F4CE45 /* PrintPreprocessedOutput.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2A54AE0FD1DD1C00F4CE45 /* PrintPreprocessedOutput.cpp */; };
1A2A54C00FD1DD1C00F4CE45 /* RewriteBlocks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2A54AF0FD1DD1C00F4CE45 /* RewriteBlocks.cpp */; };
1A2A54C10FD1DD1C00F4CE45 /* RewriteMacros.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2A54B00FD1DD1C00F4CE45 /* RewriteMacros.cpp */; };
1A2A54C20FD1DD1C00F4CE45 /* RewriteObjC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2A54B10FD1DD1C00F4CE45 /* RewriteObjC.cpp */; };
1A2A54C30FD1DD1C00F4CE45 /* RewriteTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2A54B20FD1DD1C00F4CE45 /* RewriteTest.cpp */; };
@ -44,10 +43,20 @@
1A81AA19108144F40094E50B /* CGVtable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A81AA18108144F40094E50B /* CGVtable.cpp */; };
1A869A700BA2164C008DA07A /* LiteralSupport.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 1A869A6E0BA2164C008DA07A /* LiteralSupport.h */; };
1A869AA80BA21ABA008DA07A /* LiteralSupport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A869AA70BA21ABA008DA07A /* LiteralSupport.cpp */; };
1A97825B1108BA18002B98FC /* CGVTT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A97825A1108BA18002B98FC /* CGVTT.cpp */; };
1A986AB710D0746D00A8EA9E /* CGDeclCXX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A986AB610D0746D00A8EA9E /* CGDeclCXX.cpp */; };
1AA1D91810125DE30078DEBC /* RecordLayoutBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AA1D91610125DE30078DEBC /* RecordLayoutBuilder.cpp */; };
1AA963C410D85A7300786C86 /* FullExpr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AA963C310D85A7300786C86 /* FullExpr.cpp */; };
1ABC36940C7A4BDC006DB0AB /* CGBuiltin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABC36930C7A4BDC006DB0AB /* CGBuiltin.cpp */; };
1ACB57E41105820D0047B991 /* CompilerInstance.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ACB57DB1105820D0047B991 /* CompilerInstance.cpp */; };
1ACB57E51105820D0047B991 /* CompilerInvocation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ACB57DC1105820D0047B991 /* CompilerInvocation.cpp */; };
1ACB57E61105820D0047B991 /* DeclXML.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ACB57DD1105820D0047B991 /* DeclXML.cpp */; };
1ACB57E71105820D0047B991 /* FrontendAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ACB57DE1105820D0047B991 /* FrontendAction.cpp */; };
1ACB57E81105820D0047B991 /* FrontendActions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ACB57DF1105820D0047B991 /* FrontendActions.cpp */; };
1ACB57E91105820D0047B991 /* FrontendOptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ACB57E01105820D0047B991 /* FrontendOptions.cpp */; };
1ACB57EA1105820D0047B991 /* LangStandards.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ACB57E11105820D0047B991 /* LangStandards.cpp */; };
1ACB57EB1105820D0047B991 /* TypeXML.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ACB57E21105820D0047B991 /* TypeXML.cpp */; };
1ACB57EC1105820D0047B991 /* VerifyDiagnosticsClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ACB57E31105820D0047B991 /* VerifyDiagnosticsClient.cpp */; };
1ADD795410A90C6100741BBA /* TypePrinter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ADD795110A90C6100741BBA /* TypePrinter.cpp */; };
1ADD795510A90C6100741BBA /* TypeLoc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ADD795210A90C6100741BBA /* TypeLoc.cpp */; };
1ADD795610A90C6100741BBA /* TemplateBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ADD795310A90C6100741BBA /* TemplateBase.cpp */; };
@ -59,7 +68,6 @@
3507E4C20E27FE2D00FB7B57 /* CheckObjCInstMethSignature.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3507E4C10E27FE2D00FB7B57 /* CheckObjCInstMethSignature.cpp */; };
352246E70F5C6BE000D0D279 /* HTMLDiagnostics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 352246E10F5C6BE000D0D279 /* HTMLDiagnostics.cpp */; };
352246E80F5C6BE000D0D279 /* InitHeaderSearch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 352246E20F5C6BE000D0D279 /* InitHeaderSearch.cpp */; };
352246E90F5C6BE000D0D279 /* ManagerRegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 352246E30F5C6BE000D0D279 /* ManagerRegistry.cpp */; };
352246EA0F5C6BE000D0D279 /* PlistDiagnostics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 352246E40F5C6BE000D0D279 /* PlistDiagnostics.cpp */; };
352246EB0F5C6BE000D0D279 /* TextDiagnosticBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 352246E50F5C6BE000D0D279 /* TextDiagnosticBuffer.cpp */; };
352246EC0F5C6BE000D0D279 /* TextDiagnosticPrinter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 352246E60F5C6BE000D0D279 /* TextDiagnosticPrinter.cpp */; };
@ -360,7 +368,6 @@
1A2A54AC0FD1DD1C00F4CE45 /* HTMLPrint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = HTMLPrint.cpp; path = lib/Frontend/HTMLPrint.cpp; sourceTree = "<group>"; };
1A2A54AD0FD1DD1C00F4CE45 /* PrintParserCallbacks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PrintParserCallbacks.cpp; path = lib/Frontend/PrintParserCallbacks.cpp; sourceTree = "<group>"; };
1A2A54AE0FD1DD1C00F4CE45 /* PrintPreprocessedOutput.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PrintPreprocessedOutput.cpp; path = lib/Frontend/PrintPreprocessedOutput.cpp; sourceTree = "<group>"; };
1A2A54AF0FD1DD1C00F4CE45 /* RewriteBlocks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RewriteBlocks.cpp; path = lib/Frontend/RewriteBlocks.cpp; sourceTree = "<group>"; };
1A2A54B00FD1DD1C00F4CE45 /* RewriteMacros.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RewriteMacros.cpp; path = lib/Frontend/RewriteMacros.cpp; sourceTree = "<group>"; };
1A2A54B10FD1DD1C00F4CE45 /* RewriteObjC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = RewriteObjC.cpp; path = lib/Frontend/RewriteObjC.cpp; sourceTree = "<group>"; tabWidth = 2; };
1A2A54B20FD1DD1C00F4CE45 /* RewriteTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RewriteTest.cpp; path = lib/Frontend/RewriteTest.cpp; sourceTree = "<group>"; };
@ -398,6 +405,7 @@
1A81AA5D108278A20094E50B /* CGVtable.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = CGVtable.h; path = lib/CodeGen/CGVtable.h; sourceTree = "<group>"; tabWidth = 2; };
1A869A6E0BA2164C008DA07A /* LiteralSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LiteralSupport.h; sourceTree = "<group>"; };
1A869AA70BA21ABA008DA07A /* LiteralSupport.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = LiteralSupport.cpp; sourceTree = "<group>"; };
1A97825A1108BA18002B98FC /* CGVTT.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CGVTT.cpp; path = lib/CodeGen/CGVTT.cpp; sourceTree = "<group>"; };
1A986AB610D0746D00A8EA9E /* CGDeclCXX.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGDeclCXX.cpp; path = lib/CodeGen/CGDeclCXX.cpp; sourceTree = "<group>"; tabWidth = 2; };
1AA1D91610125DE30078DEBC /* RecordLayoutBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = RecordLayoutBuilder.cpp; path = lib/AST/RecordLayoutBuilder.cpp; sourceTree = "<group>"; tabWidth = 2; };
1AA1D91710125DE30078DEBC /* RecordLayoutBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = RecordLayoutBuilder.h; path = lib/AST/RecordLayoutBuilder.h; sourceTree = "<group>"; tabWidth = 2; };
@ -405,6 +413,15 @@
1AA963C310D85A7300786C86 /* FullExpr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = FullExpr.cpp; path = lib/AST/FullExpr.cpp; sourceTree = "<group>"; tabWidth = 2; };
1AB290021045858B00FE33D8 /* PartialDiagnostic.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; path = PartialDiagnostic.h; sourceTree = "<group>"; tabWidth = 2; };
1ABC36930C7A4BDC006DB0AB /* CGBuiltin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGBuiltin.cpp; path = lib/CodeGen/CGBuiltin.cpp; sourceTree = "<group>"; tabWidth = 2; };
1ACB57DB1105820D0047B991 /* CompilerInstance.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CompilerInstance.cpp; path = lib/Frontend/CompilerInstance.cpp; sourceTree = "<group>"; };
1ACB57DC1105820D0047B991 /* CompilerInvocation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CompilerInvocation.cpp; path = lib/Frontend/CompilerInvocation.cpp; sourceTree = "<group>"; };
1ACB57DD1105820D0047B991 /* DeclXML.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DeclXML.cpp; path = lib/Frontend/DeclXML.cpp; sourceTree = "<group>"; };
1ACB57DE1105820D0047B991 /* FrontendAction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FrontendAction.cpp; path = lib/Frontend/FrontendAction.cpp; sourceTree = "<group>"; };
1ACB57DF1105820D0047B991 /* FrontendActions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FrontendActions.cpp; path = lib/Frontend/FrontendActions.cpp; sourceTree = "<group>"; };
1ACB57E01105820D0047B991 /* FrontendOptions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FrontendOptions.cpp; path = lib/Frontend/FrontendOptions.cpp; sourceTree = "<group>"; };
1ACB57E11105820D0047B991 /* LangStandards.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LangStandards.cpp; path = lib/Frontend/LangStandards.cpp; sourceTree = "<group>"; };
1ACB57E21105820D0047B991 /* TypeXML.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TypeXML.cpp; path = lib/Frontend/TypeXML.cpp; sourceTree = "<group>"; };
1ACB57E31105820D0047B991 /* VerifyDiagnosticsClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = VerifyDiagnosticsClient.cpp; path = lib/Frontend/VerifyDiagnosticsClient.cpp; sourceTree = "<group>"; };
1ADD795110A90C6100741BBA /* TypePrinter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TypePrinter.cpp; path = lib/AST/TypePrinter.cpp; sourceTree = "<group>"; };
1ADD795210A90C6100741BBA /* TypeLoc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TypeLoc.cpp; path = lib/AST/TypeLoc.cpp; sourceTree = "<group>"; };
1ADD795310A90C6100741BBA /* TemplateBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TemplateBase.cpp; path = lib/AST/TemplateBase.cpp; sourceTree = "<group>"; };
@ -418,7 +435,6 @@
3507E4C10E27FE2D00FB7B57 /* CheckObjCInstMethSignature.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CheckObjCInstMethSignature.cpp; path = lib/Analysis/CheckObjCInstMethSignature.cpp; sourceTree = "<group>"; };
352246E10F5C6BE000D0D279 /* HTMLDiagnostics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = HTMLDiagnostics.cpp; path = lib/Frontend/HTMLDiagnostics.cpp; sourceTree = "<group>"; };
352246E20F5C6BE000D0D279 /* InitHeaderSearch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = InitHeaderSearch.cpp; path = lib/Frontend/InitHeaderSearch.cpp; sourceTree = "<group>"; };
352246E30F5C6BE000D0D279 /* ManagerRegistry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ManagerRegistry.cpp; path = lib/Frontend/ManagerRegistry.cpp; sourceTree = "<group>"; };
352246E40F5C6BE000D0D279 /* PlistDiagnostics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PlistDiagnostics.cpp; path = lib/Frontend/PlistDiagnostics.cpp; sourceTree = "<group>"; };
352246E50F5C6BE000D0D279 /* TextDiagnosticBuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TextDiagnosticBuffer.cpp; path = lib/Frontend/TextDiagnosticBuffer.cpp; sourceTree = "<group>"; };
352246E60F5C6BE000D0D279 /* TextDiagnosticPrinter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TextDiagnosticPrinter.cpp; path = lib/Frontend/TextDiagnosticPrinter.cpp; sourceTree = "<group>"; };
@ -922,16 +938,22 @@
1A2A54A50FD1DD1C00F4CE45 /* ASTConsumers.cpp */,
1A2A54A60FD1DD1C00F4CE45 /* Backend.cpp */,
1A2A54A70FD1DD1C00F4CE45 /* CacheTokens.cpp */,
1ACB57DB1105820D0047B991 /* CompilerInstance.cpp */,
1ACB57DC1105820D0047B991 /* CompilerInvocation.cpp */,
1ACB57DD1105820D0047B991 /* DeclXML.cpp */,
1A2A54A80FD1DD1C00F4CE45 /* DependencyFile.cpp */,
1A2A54A90FD1DD1C00F4CE45 /* DiagChecker.cpp */,
1A2A54AA0FD1DD1C00F4CE45 /* DocumentXML.cpp */,
DEF1683F0F9548DC0098507F /* FixItRewriter.cpp */,
1ACB57DE1105820D0047B991 /* FrontendAction.cpp */,
1ACB57DF1105820D0047B991 /* FrontendActions.cpp */,
1ACB57E01105820D0047B991 /* FrontendOptions.cpp */,
1A2A54AB0FD1DD1C00F4CE45 /* GeneratePCH.cpp */,
352246E10F5C6BE000D0D279 /* HTMLDiagnostics.cpp */,
1A2A54AC0FD1DD1C00F4CE45 /* HTMLPrint.cpp */,
352246E20F5C6BE000D0D279 /* InitHeaderSearch.cpp */,
DECB6F060F9D93A800F5FBC7 /* InitPreprocessor.cpp */,
352246E30F5C6BE000D0D279 /* ManagerRegistry.cpp */,
1ACB57E11105820D0047B991 /* LangStandards.cpp */,
DEF165740F8FB3510098507F /* PCHReader.cpp */,
DECB77780FA579B000F5FBC7 /* PCHReaderDecl.cpp */,
DECB77120FA5752300F5FBC7 /* PCHReaderStmt.cpp */,
@ -943,11 +965,12 @@
1A2A54AE0FD1DD1C00F4CE45 /* PrintPreprocessedOutput.cpp */,
352246E50F5C6BE000D0D279 /* TextDiagnosticBuffer.cpp */,
352246E60F5C6BE000D0D279 /* TextDiagnosticPrinter.cpp */,
1A2A54AF0FD1DD1C00F4CE45 /* RewriteBlocks.cpp */,
1ACB57E21105820D0047B991 /* TypeXML.cpp */,
1A2A54B00FD1DD1C00F4CE45 /* RewriteMacros.cpp */,
1A2A54B10FD1DD1C00F4CE45 /* RewriteObjC.cpp */,
1A2A54B20FD1DD1C00F4CE45 /* RewriteTest.cpp */,
1A2A54B30FD1DD1C00F4CE45 /* StmtXML.cpp */,
1ACB57E31105820D0047B991 /* VerifyDiagnosticsClient.cpp */,
1A2A54B40FD1DD1C00F4CE45 /* Warnings.cpp */,
);
name = Frontend;
@ -1296,6 +1319,7 @@
35475B230E7997680000BFE4 /* CGValue.h */,
1A81AA18108144F40094E50B /* CGVtable.cpp */,
1A81AA5D108278A20094E50B /* CGVtable.h */,
1A97825A1108BA18002B98FC /* CGVTT.cpp */,
DE928B800C0A615B00231DA4 /* CodeGenFunction.h */,
DE928B820C0A616000231DA4 /* CodeGenFunction.cpp */,
DE928B7C0C0A615100231DA4 /* CodeGenModule.h */,
@ -1844,7 +1868,6 @@
DEB07AC80F4A427E00F5A2BE /* SemaAttr.cpp in Sources */,
352246E70F5C6BE000D0D279 /* HTMLDiagnostics.cpp in Sources */,
352246E80F5C6BE000D0D279 /* InitHeaderSearch.cpp in Sources */,
352246E90F5C6BE000D0D279 /* ManagerRegistry.cpp in Sources */,
352246EA0F5C6BE000D0D279 /* PlistDiagnostics.cpp in Sources */,
352246EB0F5C6BE000D0D279 /* TextDiagnosticBuffer.cpp in Sources */,
352246EC0F5C6BE000D0D279 /* TextDiagnosticPrinter.cpp in Sources */,
@ -1892,7 +1915,6 @@
1A2A54BD0FD1DD1C00F4CE45 /* HTMLPrint.cpp in Sources */,
1A2A54BE0FD1DD1C00F4CE45 /* PrintParserCallbacks.cpp in Sources */,
1A2A54BF0FD1DD1C00F4CE45 /* PrintPreprocessedOutput.cpp in Sources */,
1A2A54C00FD1DD1C00F4CE45 /* RewriteBlocks.cpp in Sources */,
1A2A54C10FD1DD1C00F4CE45 /* RewriteMacros.cpp in Sources */,
1A2A54C20FD1DD1C00F4CE45 /* RewriteObjC.cpp in Sources */,
1A2A54C30FD1DD1C00F4CE45 /* RewriteTest.cpp in Sources */,
@ -1935,6 +1957,16 @@
1A986AB710D0746D00A8EA9E /* CGDeclCXX.cpp in Sources */,
E16B523510D30B2400430AC9 /* cc1_main.cpp in Sources */,
1AA963C410D85A7300786C86 /* FullExpr.cpp in Sources */,
1ACB57E41105820D0047B991 /* CompilerInstance.cpp in Sources */,
1ACB57E51105820D0047B991 /* CompilerInvocation.cpp in Sources */,
1ACB57E61105820D0047B991 /* DeclXML.cpp in Sources */,
1ACB57E71105820D0047B991 /* FrontendAction.cpp in Sources */,
1ACB57E81105820D0047B991 /* FrontendActions.cpp in Sources */,
1ACB57E91105820D0047B991 /* FrontendOptions.cpp in Sources */,
1ACB57EA1105820D0047B991 /* LangStandards.cpp in Sources */,
1ACB57EB1105820D0047B991 /* TypeXML.cpp in Sources */,
1ACB57EC1105820D0047B991 /* VerifyDiagnosticsClient.cpp in Sources */,
1A97825B1108BA18002B98FC /* CGVTT.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

File diff suppressed because it is too large Load Diff

View File

@ -61,6 +61,7 @@ namespace clang {
class TypedefDecl;
class UsingDecl;
class UsingShadowDecl;
class UnresolvedSetIterator;
namespace Builtin { class Context; }
@ -397,6 +398,11 @@ class ASTContext {
/// BlockPointer.
QualType getNoReturnType(QualType T, bool AddNoReturn = true);
/// getCallConvType - Adds the specified calling convention attribute to
/// the given type, which must be a FunctionType or a pointer to an
/// allowable type.
QualType getCallConvType(QualType T, CallingConv CallConv);
/// getComplexType - Return the uniqued reference to the type for a complex
/// number with the specified element type.
QualType getComplexType(QualType T);
@ -513,7 +519,8 @@ class ASTContext {
/// getFunctionNoProtoType - Return a K&R style C function type like 'int()'.
///
QualType getFunctionNoProtoType(QualType ResultTy, bool NoReturn = false);
QualType getFunctionNoProtoType(QualType ResultTy, bool NoReturn = false,
CallingConv CallConv = CC_Default);
/// getFunctionType - Return a normal function type with a typed argument
/// list. isVariadic indicates whether the argument list includes '...'.
@ -522,7 +529,8 @@ class ASTContext {
unsigned TypeQuals, bool hasExceptionSpec = false,
bool hasAnyExceptionSpec = false,
unsigned NumExs = 0, const QualType *ExArray = 0,
bool NoReturn = false);
bool NoReturn = false,
CallingConv CallConv = CC_Default);
/// getTypeDeclType - Return the unique reference to the type for
/// the specified type declaration.
@ -746,8 +754,8 @@ class ASTContext {
DeclarationName getNameForTemplate(TemplateName Name);
TemplateName getOverloadedTemplateName(NamedDecl * const *Begin,
NamedDecl * const *End);
TemplateName getOverloadedTemplateName(UnresolvedSetIterator Begin,
UnresolvedSetIterator End);
TemplateName getQualifiedTemplateName(NestedNameSpecifier *NNS,
bool TemplateKeyword,

View File

@ -65,9 +65,21 @@ struct CXXBasePathElement {
/// subobject is being used.
class CXXBasePath : public llvm::SmallVector<CXXBasePathElement, 4> {
public:
CXXBasePath() : Access(AS_public) {}
/// \brief The access along this inheritance path. This is only
/// calculated when recording paths. AS_none is a special value
/// used to indicate a path which permits no legal access.
AccessSpecifier Access;
/// \brief The set of declarations found inside this base class
/// subobject.
DeclContext::lookup_result Decls;
void clear() {
llvm::SmallVectorImpl<CXXBasePathElement>::clear();
Access = AS_public;
}
};
/// BasePaths - Represents the set of paths from a derived class to
@ -131,10 +143,10 @@ class CXXBasePaths {
/// is also recorded.
bool DetectVirtual;
/// ScratchPath - A BasePath that is used by Sema::IsDerivedFrom
/// ScratchPath - A BasePath that is used by Sema::lookupInBases
/// to help build the set of paths.
CXXBasePath ScratchPath;
/// DetectedVirtual - The base class that is virtual.
const RecordType *DetectedVirtual;

View File

@ -55,32 +55,6 @@ class TypeSourceInfo {
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;

View File

@ -16,8 +16,7 @@
#include "clang/AST/Attr.h"
#include "clang/AST/Type.h"
// FIXME: Layering violation
#include "clang/Parse/AccessSpecifier.h"
#include "clang/Basic/Specifiers.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/ADT/PointerUnion.h"
@ -1017,13 +1016,8 @@ class DeclContext {
};
inline bool Decl::isTemplateParameter() const {
return getKind() == TemplateTypeParm || getKind() == NonTypeTemplateParm;
}
inline bool Decl::isDefinedOutsideFunctionOrMethod() const {
if (getDeclContext())
return !getDeclContext()->getLookupContext()->isFunctionOrMethod();
return true;
return getKind() == TemplateTypeParm || getKind() == NonTypeTemplateParm ||
getKind() == TemplateTemplateParm;
}
} // end clang.

View File

@ -16,6 +16,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/UnresolvedSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/SmallPtrSet.h"
@ -275,13 +276,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.
UnresolvedSet Conversions;
UnresolvedSet<4> 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.
UnresolvedSet VisibleConversions;
UnresolvedSet<4> VisibleConversions;
/// \brief The template or declaration that this declaration
/// describes or was instantiated from, respectively.
@ -483,20 +484,20 @@ class CXXRecordDecl : public RecordDecl {
/// getConversions - Retrieve the overload set containing all of the
/// conversion functions in this class.
UnresolvedSet *getConversionFunctions() {
UnresolvedSetImpl *getConversionFunctions() {
assert((this->isDefinition() ||
cast<RecordType>(getTypeForDecl())->isBeingDefined()) &&
"getConversionFunctions() called on incomplete type");
return &Conversions;
}
const UnresolvedSet *getConversionFunctions() const {
const UnresolvedSetImpl *getConversionFunctions() const {
assert((this->isDefinition() ||
cast<RecordType>(getTypeForDecl())->isBeingDefined()) &&
"getConversionFunctions() called on incomplete type");
return &Conversions;
}
typedef UnresolvedSet::iterator conversion_iterator;
typedef UnresolvedSetImpl::iterator conversion_iterator;
conversion_iterator conversion_begin() const { return Conversions.begin(); }
conversion_iterator conversion_end() const { return Conversions.end(); }
@ -509,7 +510,7 @@ class CXXRecordDecl : public RecordDecl {
/// getVisibleConversionFunctions - get all conversion functions visible
/// in current class; including conversion function templates.
const UnresolvedSet *getVisibleConversionFunctions();
const UnresolvedSetImpl *getVisibleConversionFunctions();
/// addVisibleConversionFunction - Add a new conversion function to the
/// list of visible conversion functions.
@ -816,6 +817,15 @@ class CXXRecordDecl : public RecordDecl {
/// GraphViz.
void viewInheritance(ASTContext& Context) const;
/// MergeAccess - Calculates the access of a decl that is reached
/// along a path.
static AccessSpecifier MergeAccess(AccessSpecifier PathAccess,
AccessSpecifier DeclAccess) {
assert(DeclAccess != AS_none);
if (DeclAccess == AS_private) return AS_none;
return (PathAccess > DeclAccess ? PathAccess : DeclAccess);
}
static bool classof(const Decl *D) {
return D->getKind() == CXXRecord ||
D->getKind() == ClassTemplateSpecialization ||

View File

@ -75,6 +75,24 @@ class ObjCList : public ObjCListBase {
}
};
/// \brief A list of Objective-C protocols, along with the source
/// locations at which they were referenced.
class ObjCProtocolList : public ObjCList<ObjCProtocolDecl> {
SourceLocation *Locations;
using ObjCList<ObjCProtocolDecl>::set;
public:
ObjCProtocolList() : ObjCList<ObjCProtocolDecl>(), Locations(0) { }
typedef const SourceLocation *loc_iterator;
loc_iterator loc_begin() const { return Locations; }
loc_iterator loc_end() const { return Locations + size(); }
void set(ObjCProtocolDecl* const* InList, unsigned Elts,
const SourceLocation *Locs, ASTContext &Ctx);
void Destroy(ASTContext &Ctx);
};
/// ObjCMethodDecl - Represents an instance or class method declaration.
@ -410,9 +428,9 @@ class ObjCInterfaceDecl : public ObjCContainerDecl {
ObjCInterfaceDecl *SuperClass;
/// Protocols referenced in interface header declaration
ObjCList<ObjCProtocolDecl> ReferencedProtocols;
ObjCProtocolList ReferencedProtocols;
/// Instance variables in the interface.
/// Instance variables in the interface. This list is completely redundant.
ObjCList<ObjCIvarDecl> IVars;
/// List of categories defined for this class.
@ -442,7 +460,7 @@ class ObjCInterfaceDecl : public ObjCContainerDecl {
SourceLocation ClassLoc = SourceLocation(),
bool ForwardDecl = false,
bool isInternal = false);
const ObjCList<ObjCProtocolDecl> &getReferencedProtocols() const {
const ObjCProtocolList &getReferencedProtocols() const {
return ReferencedProtocols;
}
@ -459,9 +477,16 @@ class ObjCInterfaceDecl : public ObjCContainerDecl {
: getClassMethod(Sel);
}
typedef ObjCList<ObjCProtocolDecl>::iterator protocol_iterator;
typedef ObjCProtocolList::iterator protocol_iterator;
protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();}
protocol_iterator protocol_end() const { return ReferencedProtocols.end(); }
typedef ObjCProtocolList::loc_iterator protocol_loc_iterator;
protocol_loc_iterator protocol_loc_begin() const {
return ReferencedProtocols.loc_begin();
}
protocol_loc_iterator protocol_loc_end() const {
return ReferencedProtocols.loc_end();
}
unsigned protocol_size() const { return ReferencedProtocols.size(); }
typedef ObjCList<ObjCIvarDecl>::iterator ivar_iterator;
@ -473,14 +498,16 @@ class ObjCInterfaceDecl : public ObjCContainerDecl {
/// setProtocolList - Set the list of protocols that this interface
/// implements.
void setProtocolList(ObjCProtocolDecl *const* List, unsigned Num,
ASTContext &C) {
ReferencedProtocols.set(List, Num, C);
const SourceLocation *Locs, ASTContext &C) {
ReferencedProtocols.set(List, Num, Locs, C);
}
/// mergeClassExtensionProtocolList - Merge class extension's protocol list
/// into the protocol list for this class.
void mergeClassExtensionProtocolList(ObjCProtocolDecl *const* List, unsigned Num,
ASTContext &C);
void mergeClassExtensionProtocolList(ObjCProtocolDecl *const* List,
unsigned Num,
const SourceLocation *Locs,
ASTContext &C);
void setIVarList(ObjCIvarDecl * const *List, unsigned Num, ASTContext &C) {
IVars.set(List, Num, C);
@ -660,7 +687,7 @@ class ObjCAtDefsFieldDecl : public FieldDecl {
///
class ObjCProtocolDecl : public ObjCContainerDecl {
/// Referenced protocols
ObjCList<ObjCProtocolDecl> ReferencedProtocols;
ObjCProtocolList ReferencedProtocols;
bool isForwardProtoDecl; // declared with @protocol.
@ -680,19 +707,26 @@ class ObjCProtocolDecl : public ObjCContainerDecl {
/// Destroy - Call destructors and release memory.
virtual void Destroy(ASTContext& C);
const ObjCList<ObjCProtocolDecl> &getReferencedProtocols() const {
const ObjCProtocolList &getReferencedProtocols() const {
return ReferencedProtocols;
}
typedef ObjCList<ObjCProtocolDecl>::iterator protocol_iterator;
typedef ObjCProtocolList::iterator protocol_iterator;
protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();}
protocol_iterator protocol_end() const { return ReferencedProtocols.end(); }
typedef ObjCProtocolList::loc_iterator protocol_loc_iterator;
protocol_loc_iterator protocol_loc_begin() const {
return ReferencedProtocols.loc_begin();
}
protocol_loc_iterator protocol_loc_end() const {
return ReferencedProtocols.loc_end();
}
unsigned protocol_size() const { return ReferencedProtocols.size(); }
/// setProtocolList - Set the list of protocols that this interface
/// implements.
void setProtocolList(ObjCProtocolDecl *const*List, unsigned Num,
ASTContext &C) {
ReferencedProtocols.set(List, Num, C);
const SourceLocation *Locs, ASTContext &C) {
ReferencedProtocols.set(List, Num, Locs, C);
}
ObjCProtocolDecl *lookupProtocolNamed(IdentifierInfo *PName);
@ -772,31 +806,45 @@ class ObjCClassDecl : public Decl {
/// @protocol NSTextInput, NSChangeSpelling, NSDraggingInfo;
///
class ObjCForwardProtocolDecl : public Decl {
ObjCList<ObjCProtocolDecl> ReferencedProtocols;
ObjCProtocolList ReferencedProtocols;
ObjCForwardProtocolDecl(DeclContext *DC, SourceLocation L,
ObjCProtocolDecl *const *Elts, unsigned nElts,
ASTContext &C);
const SourceLocation *Locs, ASTContext &C);
virtual ~ObjCForwardProtocolDecl() {}
public:
static ObjCForwardProtocolDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
ObjCProtocolDecl *const *Elts = 0,
unsigned Num = 0);
ObjCProtocolDecl *const *Elts,
unsigned Num,
const SourceLocation *Locs);
static ObjCForwardProtocolDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L) {
return Create(C, DC, L, 0, 0, 0);
}
/// Destroy - Call destructors and release memory.
virtual void Destroy(ASTContext& C);
typedef ObjCList<ObjCProtocolDecl>::iterator protocol_iterator;
typedef ObjCProtocolList::iterator protocol_iterator;
protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();}
protocol_iterator protocol_end() const { return ReferencedProtocols.end(); }
typedef ObjCProtocolList::loc_iterator protocol_loc_iterator;
protocol_loc_iterator protocol_loc_begin() const {
return ReferencedProtocols.loc_begin();
}
protocol_loc_iterator protocol_loc_end() const {
return ReferencedProtocols.loc_end();
}
unsigned protocol_size() const { return ReferencedProtocols.size(); }
/// setProtocolList - Set the list of forward protocols.
void setProtocolList(ObjCProtocolDecl *const*List, unsigned Num,
ASTContext &C) {
ReferencedProtocols.set(List, Num, C);
const SourceLocation *Locs, ASTContext &C) {
ReferencedProtocols.set(List, Num, Locs, C);
}
static bool classof(const Decl *D) {
return D->getKind() == ObjCForwardProtocol;
@ -826,22 +874,32 @@ class ObjCCategoryDecl : public ObjCContainerDecl {
ObjCInterfaceDecl *ClassInterface;
/// referenced protocols in this category.
ObjCList<ObjCProtocolDecl> ReferencedProtocols;
ObjCProtocolList ReferencedProtocols;
/// Next category belonging to this class.
/// FIXME: this should not be a singly-linked list. Move storage elsewhere.
ObjCCategoryDecl *NextClassCategory;
SourceLocation EndLoc; // marks the '>' or identifier.
/// \brief The location of the '@' in '@interface'
SourceLocation AtLoc;
ObjCCategoryDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id)
: ObjCContainerDecl(ObjCCategory, DC, L, Id),
ClassInterface(0), NextClassCategory(0){
/// \brief The location of the category name in this declaration.
SourceLocation CategoryNameLoc;
ObjCCategoryDecl(DeclContext *DC, SourceLocation AtLoc,
SourceLocation ClassNameLoc, SourceLocation CategoryNameLoc,
IdentifierInfo *Id)
: ObjCContainerDecl(ObjCCategory, DC, ClassNameLoc, Id),
ClassInterface(0), NextClassCategory(0), AtLoc(AtLoc),
CategoryNameLoc(CategoryNameLoc) {
}
public:
static ObjCCategoryDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id);
SourceLocation AtLoc,
SourceLocation ClassNameLoc,
SourceLocation CategoryNameLoc,
IdentifierInfo *Id);
ObjCInterfaceDecl *getClassInterface() { return ClassInterface; }
const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; }
@ -853,18 +911,25 @@ class ObjCCategoryDecl : public ObjCContainerDecl {
/// setProtocolList - Set the list of protocols that this interface
/// implements.
void setProtocolList(ObjCProtocolDecl *const*List, unsigned Num,
ASTContext &C) {
ReferencedProtocols.set(List, Num, C);
const SourceLocation *Locs, ASTContext &C) {
ReferencedProtocols.set(List, Num, Locs, C);
}
const ObjCList<ObjCProtocolDecl> &getReferencedProtocols() const {
const ObjCProtocolList &getReferencedProtocols() const {
return ReferencedProtocols;
}
typedef ObjCList<ObjCProtocolDecl>::iterator protocol_iterator;
typedef ObjCProtocolList::iterator protocol_iterator;
protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();}
protocol_iterator protocol_end() const { return ReferencedProtocols.end(); }
unsigned protocol_size() const { return ReferencedProtocols.size(); }
typedef ObjCProtocolList::loc_iterator protocol_loc_iterator;
protocol_loc_iterator protocol_loc_begin() const {
return ReferencedProtocols.loc_begin();
}
protocol_loc_iterator protocol_loc_end() const {
return ReferencedProtocols.loc_end();
}
ObjCCategoryDecl *getNextClassCategory() const { return NextClassCategory; }
void setNextClassCategory(ObjCCategoryDecl *Cat) {
@ -874,10 +939,16 @@ class ObjCCategoryDecl : public ObjCContainerDecl {
NextClassCategory = ClassInterface->getCategoryList();
ClassInterface->setCategoryList(this);
}
// Location information, modeled after the Stmt API.
SourceLocation getLocStart() const { return getLocation(); } // '@'interface
SourceLocation getLocEnd() const { return EndLoc; }
void setLocEnd(SourceLocation LE) { EndLoc = LE; }
SourceLocation getAtLoc() const { return AtLoc; }
void setAtLoc(SourceLocation At) { AtLoc = At; }
SourceLocation getCategoryNameLoc() const { return CategoryNameLoc; }
void setCategoryNameLoc(SourceLocation Loc) { CategoryNameLoc = Loc; }
virtual SourceRange getSourceRange() const {
return SourceRange(AtLoc, getAtEndRange().getEnd());
}
static bool classof(const Decl *D) { return D->getKind() == ObjCCategory; }
static bool classof(const ObjCCategoryDecl *D) { return true; }
@ -1133,6 +1204,7 @@ class ObjCPropertyDecl : public NamedDecl {
enum SetterKind { Assign, Retain, Copy };
enum PropertyControl { None, Required, Optional };
private:
SourceLocation AtLoc; // location of @property
QualType DeclType;
unsigned PropertyAttributes : 8;
@ -1147,8 +1219,8 @@ class ObjCPropertyDecl : public NamedDecl {
ObjCIvarDecl *PropertyIvarDecl; // Synthesize ivar for this property
ObjCPropertyDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
QualType T)
: NamedDecl(ObjCProperty, DC, L, Id), DeclType(T),
SourceLocation AtLocation, QualType T)
: NamedDecl(ObjCProperty, DC, L, Id), AtLoc(AtLocation), DeclType(T),
PropertyAttributes(OBJC_PR_noattr), PropertyImplementation(None),
GetterName(Selector()),
SetterName(Selector()),
@ -1156,8 +1228,12 @@ class ObjCPropertyDecl : public NamedDecl {
public:
static ObjCPropertyDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
IdentifierInfo *Id, QualType T,
IdentifierInfo *Id, SourceLocation AtLocation,
QualType T,
PropertyControl propControl = None);
SourceLocation getAtLoc() const { return AtLoc; }
void setAtLoc(SourceLocation L) { AtLoc = L; }
QualType getType() const { return DeclType; }
void setType(QualType T) { DeclType = T; }

View File

@ -1462,14 +1462,19 @@ class CompoundLiteralExpr : public Expr {
/// compound literal like "(int){4}". This can be null if this is a
/// synthesized compound expression.
SourceLocation LParenLoc;
/// The type as written. This can be an incomplete array type, in
/// which case the actual expression type will be different.
TypeSourceInfo *TInfo;
Stmt *Init;
bool FileScope;
public:
// FIXME: Can compound literals be value-dependent?
CompoundLiteralExpr(SourceLocation lparenloc, QualType ty, Expr *init,
bool fileScope)
: Expr(CompoundLiteralExprClass, ty, ty->isDependentType(), false),
LParenLoc(lparenloc), Init(init), FileScope(fileScope) {}
CompoundLiteralExpr(SourceLocation lparenloc, TypeSourceInfo *tinfo,
QualType T, Expr *init, bool fileScope)
: Expr(CompoundLiteralExprClass, T,
tinfo->getType()->isDependentType(), false),
LParenLoc(lparenloc), TInfo(tinfo), Init(init), FileScope(fileScope) {}
/// \brief Construct an empty compound literal.
explicit CompoundLiteralExpr(EmptyShell Empty)
@ -1485,6 +1490,9 @@ class CompoundLiteralExpr : public Expr {
SourceLocation getLParenLoc() const { return LParenLoc; }
void setLParenLoc(SourceLocation L) { LParenLoc = L; }
TypeSourceInfo *getTypeSourceInfo() const { return TInfo; }
void setTypeSourceInfo(TypeSourceInfo* tinfo) { TInfo = tinfo; }
virtual SourceRange getSourceRange() const {
// FIXME: Init should never be null.
if (!Init)
@ -1712,24 +1720,28 @@ class ImplicitCastExpr : public CastExpr {
/// expression will be an lvalue. The reference type, however, will
/// not be used as the type of the expression.
class ExplicitCastExpr : public CastExpr {
/// TypeAsWritten - The type that this expression is casting to, as
/// written in the source code.
QualType TypeAsWritten;
/// TInfo - Source type info for the (written) type
/// this expression is casting to.
TypeSourceInfo *TInfo;
protected:
ExplicitCastExpr(StmtClass SC, QualType exprTy, CastKind kind,
Expr *op, QualType writtenTy)
: CastExpr(SC, exprTy, kind, op), TypeAsWritten(writtenTy) {}
Expr *op, TypeSourceInfo *writtenTy)
: CastExpr(SC, exprTy, kind, op), TInfo(writtenTy) {}
/// \brief Construct an empty explicit cast.
ExplicitCastExpr(StmtClass SC, EmptyShell Shell)
: CastExpr(SC, Shell) { }
public:
/// getTypeInfoAsWritten - Returns the type source info for the type
/// that this expression is casting to.
TypeSourceInfo *getTypeInfoAsWritten() const { return TInfo; }
void setTypeInfoAsWritten(TypeSourceInfo *writtenTy) { TInfo = writtenTy; }
/// getTypeAsWritten - Returns the type that this expression is
/// casting to, as written in the source code.
QualType getTypeAsWritten() const { return TypeAsWritten; }
void setTypeAsWritten(QualType T) { TypeAsWritten = T; }
QualType getTypeAsWritten() const { return TInfo->getType(); }
static bool classof(const Stmt *T) {
StmtClass SC = T->getStmtClass();
@ -1750,8 +1762,9 @@ class CStyleCastExpr : public ExplicitCastExpr {
SourceLocation LPLoc; // the location of the left paren
SourceLocation RPLoc; // the location of the right paren
public:
CStyleCastExpr(QualType exprTy, CastKind kind, Expr *op, QualType writtenTy,
SourceLocation l, SourceLocation r) :
CStyleCastExpr(QualType exprTy, CastKind kind, Expr *op,
TypeSourceInfo *writtenTy,
SourceLocation l, SourceLocation r) :
ExplicitCastExpr(CStyleCastExprClass, exprTy, kind, op, writtenTy),
LPLoc(l), RPLoc(r) {}

View File

@ -16,7 +16,7 @@
#include "clang/Basic/TypeTraits.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/UnresolvedSet.h"
#include "clang/AST/TemplateBase.h"
namespace clang {
@ -118,9 +118,12 @@ class CXXNamedCastExpr : public ExplicitCastExpr {
protected:
CXXNamedCastExpr(StmtClass SC, QualType ty, CastKind kind, Expr *op,
QualType writtenTy, SourceLocation l)
TypeSourceInfo *writtenTy, SourceLocation l)
: ExplicitCastExpr(SC, ty, kind, op, writtenTy), Loc(l) {}
explicit CXXNamedCastExpr(StmtClass SC, EmptyShell Shell)
: ExplicitCastExpr(SC, Shell) { }
public:
const char *getCastName() const;
@ -154,9 +157,12 @@ class CXXNamedCastExpr : public ExplicitCastExpr {
class CXXStaticCastExpr : public CXXNamedCastExpr {
public:
CXXStaticCastExpr(QualType ty, CastKind kind, Expr *op,
QualType writtenTy, SourceLocation l)
TypeSourceInfo *writtenTy, SourceLocation l)
: CXXNamedCastExpr(CXXStaticCastExprClass, ty, kind, op, writtenTy, l) {}
explicit CXXStaticCastExpr(EmptyShell Empty)
: CXXNamedCastExpr(CXXStaticCastExprClass, Empty) { }
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXStaticCastExprClass;
}
@ -171,10 +177,13 @@ class CXXStaticCastExpr : public CXXNamedCastExpr {
/// @c dynamic_cast<Derived*>(BasePtr).
class CXXDynamicCastExpr : public CXXNamedCastExpr {
public:
CXXDynamicCastExpr(QualType ty, CastKind kind, Expr *op, QualType writtenTy,
SourceLocation l)
CXXDynamicCastExpr(QualType ty, CastKind kind, Expr *op,
TypeSourceInfo *writtenTy, SourceLocation l)
: CXXNamedCastExpr(CXXDynamicCastExprClass, ty, kind, op, writtenTy, l) {}
explicit CXXDynamicCastExpr(EmptyShell Empty)
: CXXNamedCastExpr(CXXDynamicCastExprClass, Empty) { }
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXDynamicCastExprClass;
}
@ -190,10 +199,13 @@ class CXXDynamicCastExpr : public CXXNamedCastExpr {
class CXXReinterpretCastExpr : public CXXNamedCastExpr {
public:
CXXReinterpretCastExpr(QualType ty, CastKind kind, Expr *op,
QualType writtenTy, SourceLocation l)
TypeSourceInfo *writtenTy, SourceLocation l)
: CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, kind, op,
writtenTy, l) {}
explicit CXXReinterpretCastExpr(EmptyShell Empty)
: CXXNamedCastExpr(CXXReinterpretCastExprClass, Empty) { }
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXReinterpretCastExprClass;
}
@ -207,10 +219,13 @@ class CXXReinterpretCastExpr : public CXXNamedCastExpr {
/// @c const_cast<char*>(PtrToConstChar).
class CXXConstCastExpr : public CXXNamedCastExpr {
public:
CXXConstCastExpr(QualType ty, Expr *op, QualType writtenTy,
CXXConstCastExpr(QualType ty, Expr *op, TypeSourceInfo *writtenTy,
SourceLocation l)
: CXXNamedCastExpr(CXXConstCastExprClass, ty, CK_NoOp, op, writtenTy, l) {}
explicit CXXConstCastExpr(EmptyShell Empty)
: CXXNamedCastExpr(CXXConstCastExprClass, Empty) { }
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXConstCastExprClass;
}
@ -625,15 +640,20 @@ class CXXFunctionalCastExpr : public ExplicitCastExpr {
SourceLocation TyBeginLoc;
SourceLocation RParenLoc;
public:
CXXFunctionalCastExpr(QualType ty, QualType writtenTy,
CXXFunctionalCastExpr(QualType ty, TypeSourceInfo *writtenTy,
SourceLocation tyBeginLoc, CastKind kind,
Expr *castExpr, SourceLocation rParenLoc)
: ExplicitCastExpr(CXXFunctionalCastExprClass, ty, kind, castExpr,
writtenTy),
TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {}
explicit CXXFunctionalCastExpr(EmptyShell Shell)
: ExplicitCastExpr(CXXFunctionalCastExprClass, Shell) { }
SourceLocation getTypeBeginLoc() const { return TyBeginLoc; }
void setTypeBeginLoc(SourceLocation L) { TyBeginLoc = L; }
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
virtual SourceRange getSourceRange() const {
return SourceRange(TyBeginLoc, RParenLoc);
@ -1052,7 +1072,7 @@ class UnaryTypeTraitExpr : public Expr {
class UnresolvedLookupExpr : public Expr {
/// The results. These are undesugared, which is to say, they may
/// include UsingShadowDecls.
UnresolvedSet Results;
UnresolvedSet<4> Results;
/// The name declared.
DeclarationName Name;
@ -1113,15 +1133,15 @@ class UnresolvedLookupExpr : public Expr {
/// 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,
static bool ComputeDependence(UnresolvedSetImpl::const_iterator Begin,
UnresolvedSetImpl::const_iterator End,
const TemplateArgumentListInfo *Args);
void addDecl(NamedDecl *Decl) {
Results.addDecl(Decl);
}
typedef UnresolvedSet::iterator decls_iterator;
typedef UnresolvedSetImpl::iterator decls_iterator;
decls_iterator decls_begin() const { return Results.begin(); }
decls_iterator decls_end() const { return Results.end(); }
@ -1696,7 +1716,7 @@ class CXXDependentScopeMemberExpr : public Expr {
class UnresolvedMemberExpr : public Expr {
/// The results. These are undesugared, which is to say, they may
/// include UsingShadowDecls.
UnresolvedSet Results;
UnresolvedSet<4> Results;
/// \brief The expression for the base pointer or class reference,
/// e.g., the \c x in x.f. This can be null if this is an 'unbased'
@ -1775,7 +1795,7 @@ class UnresolvedMemberExpr : public Expr {
Results.addDecl(Decl);
}
typedef UnresolvedSet::iterator decls_iterator;
typedef UnresolvedSetImpl::iterator decls_iterator;
decls_iterator decls_begin() const { return Results.begin(); }
decls_iterator decls_end() const { return Results.end(); }

View File

@ -385,6 +385,14 @@ class ExtQuals : public llvm::FoldingSetNode {
}
};
/// CallingConv - Specifies the calling convention that a function uses.
enum CallingConv {
CC_Default,
CC_C, // __attribute__((cdecl))
CC_X86StdCall, // __attribute__((stdcall))
CC_X86FastCall // __attribute__((fastcall))
};
/// QualType - For efficiency, we don't store CV-qualified types as nodes on
/// their own: instead each reference to a type stores the qualifiers. This
@ -669,6 +677,10 @@ class QualType {
/// false otherwise.
bool getNoReturnAttr() const;
/// getCallConv - Returns the calling convention of the type if the type
/// is a function type, CC_Default otherwise.
CallingConv getCallConv() const;
private:
// These methods are implemented in a separate translation unit;
// "static"-ize them to avoid creating temporary QualTypes in the
@ -1691,21 +1703,25 @@ class FunctionType : public Type {
/// NoReturn - Indicates if the function type is attribute noreturn.
unsigned NoReturn : 1;
/// CallConv - The calling convention used by the function.
unsigned CallConv : 2;
// The type returned by the function.
QualType ResultType;
protected:
FunctionType(TypeClass tc, QualType res, bool SubclassInfo,
unsigned typeQuals, QualType Canonical, bool Dependent,
bool noReturn = false)
bool noReturn = false, CallingConv callConv = CC_Default)
: Type(tc, Canonical, Dependent),
SubClassData(SubclassInfo), TypeQuals(typeQuals), NoReturn(noReturn),
ResultType(res) {}
CallConv(callConv), ResultType(res) {}
bool getSubClassData() const { return SubClassData; }
unsigned getTypeQuals() const { return TypeQuals; }
public:
QualType getResultType() const { return ResultType; }
bool getNoReturnAttr() const { return NoReturn; }
CallingConv getCallConv() const { return (CallingConv)CallConv; }
static bool classof(const Type *T) {
return T->getTypeClass() == FunctionNoProto ||
@ -1718,9 +1734,9 @@ class FunctionType : public Type {
/// no information available about its arguments.
class FunctionNoProtoType : public FunctionType, public llvm::FoldingSetNode {
FunctionNoProtoType(QualType Result, QualType Canonical,
bool NoReturn = false)
bool NoReturn = false, CallingConv CallConv = CC_Default)
: FunctionType(FunctionNoProto, Result, false, 0, Canonical,
/*Dependent=*/false, NoReturn) {}
/*Dependent=*/false, NoReturn, CallConv) {}
friend class ASTContext; // ASTContext creates these.
public:
// No additional state past what FunctionType provides.
@ -1762,10 +1778,12 @@ class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode {
FunctionProtoType(QualType Result, const QualType *ArgArray, unsigned numArgs,
bool isVariadic, unsigned typeQuals, bool hasExs,
bool hasAnyExs, const QualType *ExArray,
unsigned numExs, QualType Canonical, bool NoReturn)
unsigned numExs, QualType Canonical, bool NoReturn,
CallingConv CallConv)
: FunctionType(FunctionProto, Result, isVariadic, typeQuals, Canonical,
(Result->isDependentType() ||
hasAnyDependentType(ArgArray, numArgs)), NoReturn),
hasAnyDependentType(ArgArray, numArgs)), NoReturn,
CallConv),
NumArgs(numArgs), NumExceptions(numExs), HasExceptionSpec(hasExs),
AnyExceptionSpec(hasAnyExs) {
// Fill in the trailing argument array.
@ -2496,26 +2514,31 @@ class ObjCInterfaceType : public Type, public llvm::FoldingSetNode {
// List of protocols for this protocol conforming object type
// List is sorted on protocol name. No protocol is enterred more than once.
llvm::SmallVector<ObjCProtocolDecl*, 4> Protocols;
ObjCProtocolDecl **Protocols;
unsigned NumProtocols;
ObjCInterfaceType(QualType Canonical, ObjCInterfaceDecl *D,
ObjCProtocolDecl **Protos, unsigned NumP) :
Type(ObjCInterface, Canonical, /*Dependent=*/false),
Decl(D), Protocols(Protos, Protos+NumP) { }
ObjCInterfaceType(ASTContext &Ctx, QualType Canonical, ObjCInterfaceDecl *D,
ObjCProtocolDecl **Protos, unsigned NumP);
friend class ASTContext; // ASTContext creates these.
public:
void Destroy(ASTContext& C);
ObjCInterfaceDecl *getDecl() const { return Decl; }
/// getNumProtocols - Return the number of qualifying protocols in this
/// interface type, or 0 if there are none.
unsigned getNumProtocols() const { return Protocols.size(); }
unsigned getNumProtocols() const { return NumProtocols; }
/// qual_iterator and friends: this provides access to the (potentially empty)
/// list of protocols qualifying this interface.
typedef llvm::SmallVector<ObjCProtocolDecl*, 8>::const_iterator qual_iterator;
qual_iterator qual_begin() const { return Protocols.begin(); }
qual_iterator qual_end() const { return Protocols.end(); }
bool qual_empty() const { return Protocols.size() == 0; }
typedef ObjCProtocolDecl* const * qual_iterator;
qual_iterator qual_begin() const {
return Protocols;
}
qual_iterator qual_end() const {
return Protocols ? Protocols + NumProtocols : 0;
}
bool qual_empty() const { return NumProtocols == 0; }
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@ -2541,15 +2564,16 @@ class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode {
// List of protocols for this protocol conforming object type
// List is sorted on protocol name. No protocol is entered more than once.
llvm::SmallVector<ObjCProtocolDecl*, 8> Protocols;
ObjCProtocolDecl **Protocols;
unsigned NumProtocols;
ObjCObjectPointerType(QualType Canonical, QualType T,
ObjCProtocolDecl **Protos, unsigned NumP) :
Type(ObjCObjectPointer, Canonical, /*Dependent=*/false),
PointeeType(T), Protocols(Protos, Protos+NumP) { }
ObjCObjectPointerType(ASTContext &Ctx, QualType Canonical, QualType T,
ObjCProtocolDecl **Protos, unsigned NumP);
friend class ASTContext; // ASTContext creates these.
public:
void Destroy(ASTContext& C);
// Get the pointee type. Pointee will either be:
// - a built-in type (for 'id' and 'Class').
// - an interface type (for user-defined types).
@ -2567,35 +2591,39 @@ class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode {
/// isObjCIdType - true for "id".
bool isObjCIdType() const {
return getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCId) &&
!Protocols.size();
!NumProtocols;
}
/// isObjCClassType - true for "Class".
bool isObjCClassType() const {
return getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCClass) &&
!Protocols.size();
!NumProtocols;
}
/// isObjCQualifiedIdType - true for "id <p>".
bool isObjCQualifiedIdType() const {
return getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCId) &&
Protocols.size();
NumProtocols;
}
/// isObjCQualifiedClassType - true for "Class <p>".
bool isObjCQualifiedClassType() const {
return getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCClass) &&
Protocols.size();
NumProtocols;
}
/// qual_iterator and friends: this provides access to the (potentially empty)
/// list of protocols qualifying this interface.
typedef llvm::SmallVector<ObjCProtocolDecl*, 8>::const_iterator qual_iterator;
typedef ObjCProtocolDecl* const * qual_iterator;
qual_iterator qual_begin() const { return Protocols.begin(); }
qual_iterator qual_end() const { return Protocols.end(); }
bool qual_empty() const { return Protocols.size() == 0; }
qual_iterator qual_begin() const {
return Protocols;
}
qual_iterator qual_end() const {
return Protocols ? Protocols + NumProtocols : NULL;
}
bool qual_empty() const { return NumProtocols == 0; }
/// getNumProtocols - Return the number of qualifying protocols in this
/// interface type, or 0 if there are none.
unsigned getNumProtocols() const { return Protocols.size(); }
unsigned getNumProtocols() const { return NumProtocols; }
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@ -2797,6 +2825,26 @@ inline bool QualType::getNoReturnAttr() const {
return false;
}
/// getCallConv - Returns the calling convention of the type if the type
/// is a function type, CC_Default otherwise.
inline CallingConv QualType::getCallConv() const {
if (const PointerType *PT = getTypePtr()->getAs<PointerType>())
return PT->getPointeeType().getCallConv();
else if (const ReferenceType *RT = getTypePtr()->getAs<ReferenceType>())
return RT->getPointeeType().getCallConv();
else if (const MemberPointerType *MPT =
getTypePtr()->getAs<MemberPointerType>())
return MPT->getPointeeType().getCallConv();
else if (const BlockPointerType *BPT =
getTypePtr()->getAs<BlockPointerType>()) {
if (const FunctionType *FT = BPT->getPointeeType()->getAs<FunctionType>())
return FT->getCallConv();
} else if (const FunctionType *FT = getTypePtr()->getAs<FunctionType>())
return FT->getCallConv();
return CC_Default;
}
/// isMoreQualifiedThan - Determine whether this type is more
/// qualified than the Other type. For example, "const volatile int"
/// is more qualified than "const int", "volatile int", and

View File

@ -16,6 +16,7 @@
#include "clang/AST/Type.h"
#include "clang/AST/TemplateBase.h"
#include "clang/Basic/Specifiers.h"
namespace clang {
class ParmVarDecl;
@ -372,6 +373,111 @@ class TypeSpecTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
};
struct BuiltinLocInfo {
SourceLocation BuiltinLoc;
};
/// \brief Wrapper for source info for builtin types.
class BuiltinTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
BuiltinTypeLoc,
BuiltinType,
BuiltinLocInfo> {
public:
enum { LocalDataSize = sizeof(BuiltinLocInfo) };
SourceLocation getBuiltinLoc() const {
return getLocalData()->BuiltinLoc;
}
void setBuiltinLoc(SourceLocation Loc) {
getLocalData()->BuiltinLoc = Loc;
}
SourceLocation getNameLoc() const { return getBuiltinLoc(); }
WrittenBuiltinSpecs& getWrittenBuiltinSpecs() {
return *(static_cast<WrittenBuiltinSpecs*>(getExtraLocalData()));
}
const WrittenBuiltinSpecs& getWrittenBuiltinSpecs() const {
return *(static_cast<WrittenBuiltinSpecs*>(getExtraLocalData()));
}
bool needsExtraLocalData() const {
BuiltinType::Kind bk = getTypePtr()->getKind();
return (bk >= BuiltinType::UShort && bk <= BuiltinType::UInt128)
|| (bk >= BuiltinType::Short && bk <= BuiltinType::LongDouble)
|| bk == BuiltinType::UChar
|| bk == BuiltinType::SChar;
}
unsigned getExtraLocalDataSize() const {
return needsExtraLocalData() ? sizeof(WrittenBuiltinSpecs) : 0;
}
SourceRange getSourceRange() const {
return SourceRange(getBuiltinLoc(), getBuiltinLoc());
}
TypeSpecifierSign getWrittenSignSpec() const {
if (needsExtraLocalData())
return static_cast<TypeSpecifierSign>(getWrittenBuiltinSpecs().Sign);
else
return TSS_unspecified;
}
bool hasWrittenSignSpec() const {
return getWrittenSignSpec() != TSS_unspecified;
}
void setWrittenSignSpec(TypeSpecifierSign written) {
if (needsExtraLocalData())
getWrittenBuiltinSpecs().Sign = written;
}
TypeSpecifierWidth getWrittenWidthSpec() const {
if (needsExtraLocalData())
return static_cast<TypeSpecifierWidth>(getWrittenBuiltinSpecs().Width);
else
return TSW_unspecified;
}
bool hasWrittenWidthSpec() const {
return getWrittenWidthSpec() != TSW_unspecified;
}
void setWrittenWidthSpec(TypeSpecifierWidth written) {
if (needsExtraLocalData())
getWrittenBuiltinSpecs().Width = written;
}
TypeSpecifierType getWrittenTypeSpec() const;
bool hasWrittenTypeSpec() const {
return getWrittenTypeSpec() != TST_unspecified;
}
void setWrittenTypeSpec(TypeSpecifierType written) {
if (needsExtraLocalData())
getWrittenBuiltinSpecs().Type = written;
}
bool hasModeAttr() const {
if (needsExtraLocalData())
return getWrittenBuiltinSpecs().ModeAttr;
else
return false;
}
void setModeAttr(bool written) {
if (needsExtraLocalData())
getWrittenBuiltinSpecs().ModeAttr = written;
}
void initializeLocal(SourceLocation Loc) {
setBuiltinLoc(Loc);
if (needsExtraLocalData()) {
WrittenBuiltinSpecs &wbs = getWrittenBuiltinSpecs();
wbs.Sign = TSS_unspecified;
wbs.Width = TSW_unspecified;
wbs.Type = TST_unspecified;
wbs.ModeAttr = false;
}
}
};
/// \brief Wrapper for source info for typedefs.
class TypedefTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
TypedefTypeLoc,
@ -421,12 +527,6 @@ class EnumTypeLoc : public InheritingConcreteTypeLoc<TagTypeLoc,
EnumDecl *getDecl() const { return getTypePtr()->getDecl(); }
};
/// \brief Wrapper for source info for builtin types.
class BuiltinTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
BuiltinTypeLoc,
BuiltinType> {
};
/// \brief Wrapper for template type parameters.
class TemplateTypeParmTypeLoc :
public InheritingConcreteTypeLoc<TypeSpecTypeLoc,

View File

@ -43,6 +43,7 @@ class TypeLocVisitor {
case TypeLoc::CLASS: DISPATCH(CLASS##TypeLoc);
#include "clang/AST/TypeLocNodes.def"
}
llvm_unreachable("unexpected type loc class!");
}
#define TYPELOC(CLASS, PARENT) \

View File

@ -0,0 +1,211 @@
//===-- UnresolvedSet.h - Unresolved sets of declarations ------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the UnresolvedSet class, which is used to store
// collections of declarations in the AST.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_UNRESOLVEDSET_H
#define LLVM_CLANG_AST_UNRESOLVEDSET_H
#include <iterator>
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/SmallVector.h"
#include "clang/Basic/Specifiers.h"
namespace clang {
class NamedDecl;
/// The iterator over UnresolvedSets. Serves as both the const and
/// non-const iterator.
class UnresolvedSetIterator {
typedef llvm::PointerIntPair<NamedDecl*, 2> DeclEntry;
typedef llvm::SmallVectorImpl<DeclEntry> DeclsTy;
typedef DeclsTy::iterator IteratorTy;
IteratorTy ir;
friend class UnresolvedSetImpl;
explicit UnresolvedSetIterator(DeclsTy::iterator ir) : ir(ir) {}
explicit UnresolvedSetIterator(DeclsTy::const_iterator ir) :
ir(const_cast<DeclsTy::iterator>(ir)) {}
public:
UnresolvedSetIterator() {}
typedef std::iterator_traits<IteratorTy>::difference_type difference_type;
typedef NamedDecl *value_type;
typedef NamedDecl **pointer;
typedef NamedDecl *reference;
typedef std::iterator_traits<IteratorTy>::iterator_category iterator_category;
NamedDecl *getDecl() const { return ir->getPointer(); }
AccessSpecifier getAccess() const { return AccessSpecifier(ir->getInt()); }
NamedDecl *operator*() const { return getDecl(); }
UnresolvedSetIterator &operator++() { ++ir; return *this; }
UnresolvedSetIterator operator++(int) { return UnresolvedSetIterator(ir++); }
UnresolvedSetIterator &operator--() { --ir; return *this; }
UnresolvedSetIterator operator--(int) { return UnresolvedSetIterator(ir--); }
UnresolvedSetIterator &operator+=(difference_type d) {
ir += d; return *this;
}
UnresolvedSetIterator operator+(difference_type d) const {
return UnresolvedSetIterator(ir + d);
}
UnresolvedSetIterator &operator-=(difference_type d) {
ir -= d; return *this;
}
UnresolvedSetIterator operator-(difference_type d) const {
return UnresolvedSetIterator(ir - d);
}
value_type operator[](difference_type d) const { return *(*this + d); }
difference_type operator-(const UnresolvedSetIterator &o) const {
return ir - o.ir;
}
bool operator==(const UnresolvedSetIterator &o) const { return ir == o.ir; }
bool operator!=(const UnresolvedSetIterator &o) const { return ir != o.ir; }
bool operator<(const UnresolvedSetIterator &o) const { return ir < o.ir; }
bool operator<=(const UnresolvedSetIterator &o) const { return ir <= o.ir; }
bool operator>=(const UnresolvedSetIterator &o) const { return ir >= o.ir; }
bool operator>(const UnresolvedSetIterator &o) const { return ir > o.ir; }
};
/// 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 UnresolvedSetImpl {
typedef UnresolvedSetIterator::DeclEntry DeclEntry;
typedef UnresolvedSetIterator::DeclsTy DeclsTy;
// Don't allow direct construction, and only permit subclassing by
// UnresolvedSet.
private:
template <unsigned N> friend class UnresolvedSet;
UnresolvedSetImpl() {}
UnresolvedSetImpl(const UnresolvedSetImpl &) {}
public:
// We don't currently support assignment through this iterator, so we might
// as well use the same implementation twice.
typedef UnresolvedSetIterator iterator;
typedef UnresolvedSetIterator const_iterator;
iterator begin() { return iterator(decls().begin()); }
iterator end() { return iterator(decls().end()); }
const_iterator begin() const { return const_iterator(decls().begin()); }
const_iterator end() const { return const_iterator(decls().end()); }
void addDecl(NamedDecl *D) {
addDecl(D, AS_none);
}
void addDecl(NamedDecl *D, AccessSpecifier AS) {
decls().push_back(DeclEntry(D, AS));
}
/// Replaces the given declaration with the new one, once.
///
/// \return true if the set changed
bool replace(const NamedDecl* Old, NamedDecl *New) {
for (DeclsTy::iterator I = decls().begin(), E = decls().end(); I != E; ++I)
if (I->getPointer() == Old)
return (I->setPointer(New), true);
return false;
}
/// Replaces the declaration at the given iterator with the new one,
/// preserving the original access bits.
void replace(iterator I, NamedDecl *New) {
I.ir->setPointer(New);
}
void replace(iterator I, NamedDecl *New, AccessSpecifier AS) {
*I.ir = DeclEntry(New, AS);
}
void erase(iterator I) {
*I.ir = decls().back();
decls().pop_back();
}
void clear() { decls().clear(); }
void set_size(unsigned N) { decls().set_size(N); }
bool empty() const { return decls().empty(); }
unsigned size() const { return decls().size(); }
void append(iterator I, iterator E) {
decls().append(I.ir, E.ir);
}
/// A proxy reference for implementing operator[].
class Proxy {
DeclEntry &Ref;
friend class UnresolvedSetImpl;
Proxy(DeclEntry &Ref) : Ref(Ref) {}
public:
NamedDecl *getDecl() const { return Ref.getPointer(); }
void setDecl(NamedDecl *D) { Ref.setPointer(D); }
AccessSpecifier getAccess() const { return AccessSpecifier(Ref.getInt()); }
void setAccess(AccessSpecifier AS) const { Ref.setInt(AS); }
NamedDecl* operator->() const { return getDecl(); }
operator NamedDecl*() const { return getDecl(); }
Proxy &operator=(const Proxy &D) { Ref = D.Ref; return *this; }
};
Proxy operator[](unsigned I) { return Proxy(decls()[I]); }
/// A proxy reference for implementing operator[] const.
class ConstProxy {
const DeclEntry &Ref;
friend class UnresolvedSetImpl;
ConstProxy(const DeclEntry &Ref) : Ref(Ref) {}
public:
NamedDecl *getDecl() const { return Ref.getPointer(); }
AccessSpecifier getAccess() const { return AccessSpecifier(Ref.getInt()); }
NamedDecl *operator->() const { return getDecl(); }
operator NamedDecl*() const { return getDecl(); }
};
ConstProxy operator[](unsigned I) const { return ConstProxy(decls()[I]); }
private:
// These work because the only permitted subclass is UnresolvedSetImpl
DeclsTy &decls() {
return *reinterpret_cast<DeclsTy*>(this);
}
const DeclsTy &decls() const {
return *reinterpret_cast<const DeclsTy*>(this);
}
};
/// A set of unresolved declarations
template <unsigned InlineCapacity> class UnresolvedSet :
public UnresolvedSetImpl {
llvm::SmallVector<UnresolvedSetImpl::DeclEntry, InlineCapacity> Decls;
};
} // namespace clang
#endif

View File

@ -20,12 +20,14 @@
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Casting.h"
#include "clang/Analysis/Support/BumpVector.h"
#include "clang/Basic/SourceLocation.h"
#include <cassert>
namespace llvm {
class raw_ostream;
}
namespace clang {
class Decl;
class Stmt;
class Expr;
class CFG;
@ -33,15 +35,39 @@ namespace clang {
class LangOptions;
class ASTContext;
namespace {
// An element of the CFG for implicit descructor calls implied by the language
// rules.
class Dtor {
// Statement that introduces the variable.
Stmt *S;
// A token which ends the scope, return, goto, throw, }.
SourceLocation Loc;
public:
Dtor(Stmt *s, SourceLocation l) : S(s), Loc(l) {
}
SourceLocation getLoc() { return Loc; }
Stmt *getStmt() { return S; }
};
}
/// CFGElement - Represents a top-level expression in a basic block.
class CFGElement {
llvm::PointerIntPair<Stmt *, 1> Data;
llvm::PointerIntPair<Stmt *, 2> Data;
public:
enum Type { StartScope, EndScope };
explicit CFGElement() {}
CFGElement(Stmt *S, bool lvalue) : Data(S, lvalue ? 1 : 0) {}
CFGElement(Stmt *S, Type t) : Data(S, t == StartScope ? 2 : 3) {}
// CFGElement(Dtor *S, Type t) : Data(reinterpret_cast<Stmt*>(S), 4) {}
Stmt *getStmt() const { return Data.getPointer(); }
bool asLValue() const { return Data.getInt() == 1; }
bool asStartScope() const { return Data.getInt() == 2; }
bool asEndScope() const { return Data.getInt() == 3; }
bool asDtor() const { return Data.getInt() == 4; }
operator Stmt*() const { return getStmt(); }
operator bool() const { return getStmt() != 0; }
operator Dtor*() const { return reinterpret_cast<Dtor*>(getStmt()); }
};
/// CFGBlock - Represents a single basic block in a source-level CFG.
@ -107,7 +133,7 @@ class CFGBlock {
/// Label - An (optional) label that prefixes the executable
/// statements in the block. When this variable is non-NULL, it is
/// either an instance of LabelStmt or SwitchCase.
/// either an instance of LabelStmt, SwitchCase or CXXCatchStmt.
Stmt *Label;
/// Terminator - The terminator for a basic block that
@ -236,6 +262,12 @@ class CFGBlock {
void appendStmt(Stmt* Statement, BumpVectorContext &C, bool asLValue) {
Stmts.push_back(CFGElement(Statement, asLValue), C);
}
void StartScope(Stmt* S, BumpVectorContext &C) {
Stmts.push_back(CFGElement(S, CFGElement::StartScope), C);
}
void EndScope(Stmt* S, BumpVectorContext &C) {
Stmts.push_back(CFGElement(S, CFGElement::EndScope), C);
}
};
@ -254,7 +286,9 @@ class CFG {
/// buildCFG - Builds a CFG from an AST. The responsibility to free the
/// constructed CFG belongs to the caller.
static CFG* buildCFG(Stmt* AST, ASTContext *C);
static CFG* buildCFG(const Decl *D, Stmt* AST, ASTContext *C,
bool AddEHEdges = false,
bool AddScopes = false);
/// createBlock - Create a new block in the CFG. The CFG owns the block;
/// the caller should not directly free it.

View File

@ -46,14 +46,21 @@ class AnalysisContext {
ParentMap *PM;
llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
llvm::BumpPtrAllocator A;
bool AddEHEdges;
public:
AnalysisContext(const Decl *d) : D(d), cfg(0), liveness(0), PM(0),
ReferencedBlockVars(0) {}
AnalysisContext(const Decl *d, bool addehedges = false)
: D(d), cfg(0), liveness(0), PM(0), ReferencedBlockVars(0),
AddEHEdges(addehedges) {}
~AnalysisContext();
ASTContext &getASTContext() { return D->getASTContext(); }
const Decl *getDecl() { return D; }
/// getAddEHEdges - Return true iff we are adding exceptional edges from
/// callExprs. If this is false, then try/catch statements and blocks
/// reachable from them can appear to be dead in the CFG, analysis passes must
/// cope with that.
bool getAddEHEdges() const { return AddEHEdges; }
Stmt *getBody();
CFG *getCFG();
ParentMap &getParentMap();

View File

@ -66,6 +66,11 @@ break;
default:
assert(false && "Unsupport statement.");
return;
case Stmt::CompoundAssignOperatorClass:
static_cast<ImplClass*>(this)->PostVisitBinaryOperator(C,
static_cast<const BinaryOperator*>(S));
break;
#define POSTVISIT(NAME, FALLBACK) \
case Stmt::NAME ## Class:\
static_cast<ImplClass*>(this)->\

View File

@ -270,8 +270,8 @@ class GRExprEngine : public GRSubEngine {
ExplodedNodeSet& Dst, bool asLValue);
/// VisitCast - Transfer function logic for all casts (implicit and explicit).
void VisitCast(Expr* CastE, Expr* Ex, ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue);
void VisitCast(CastExpr *CastE, Expr *Ex, ExplodedNode *Pred,
ExplodedNodeSet &Dst, bool asLValue);
/// VisitCompoundLiteralExpr - Transfer function logic for compound literals.
void VisitCompoundLiteralExpr(CompoundLiteralExpr* CL, ExplodedNode* Pred,

View File

@ -105,7 +105,8 @@ class StoreManager {
// FIXME: Make out-of-line.
virtual DefinedOrUnknownSVal getSizeInElements(const GRState *state,
const MemRegion *region) {
const MemRegion *region,
QualType EleTy) {
return UnknownVal();
}

View File

@ -270,6 +270,7 @@ BUILTIN(__builtin_bswap64, "ULLiULLi", "nc")
BUILTIN(__builtin_constant_p, "Us.", "nc")
BUILTIN(__builtin_classify_type, "i.", "nc")
BUILTIN(__builtin___CFStringMakeConstantString, "FC*cC*", "nc")
BUILTIN(__builtin___NSStringMakeConstantString, "FC*cC*", "nc")
BUILTIN(__builtin_va_start, "vA.", "n")
BUILTIN(__builtin_va_end, "vA", "n")
BUILTIN(__builtin_va_copy, "vAA", "n")

View File

@ -79,12 +79,7 @@ BUILTIN(__builtin_ia32_pmaxub, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_pmaxsw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_pminub, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_pminsw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_punpckhbw, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_punpckhwd, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_punpckhdq, "V2iV2iV2i", "")
BUILTIN(__builtin_ia32_punpcklbw, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_punpcklwd, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_punpckldq, "V2iV2iV2i", "")
BUILTIN(__builtin_ia32_cmppd, "V2dV2dV2dc", "")
BUILTIN(__builtin_ia32_cmpsd, "V2dV2dV2dc", "")
BUILTIN(__builtin_ia32_minpd, "V2dV2dV2d", "")
@ -99,7 +94,6 @@ BUILTIN(__builtin_ia32_paddusb128, "V16cV16cV16c", "")
BUILTIN(__builtin_ia32_paddusw128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_psubusb128, "V16cV16cV16c", "")
BUILTIN(__builtin_ia32_psubusw128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_pmullw128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_pmulhw128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_pavgb128, "V16cV16cV16c", "")
BUILTIN(__builtin_ia32_pavgw128, "V8sV8sV8s", "")

View File

@ -83,5 +83,7 @@ def warn_drv_assuming_mfloat_abi_is : Warning<
"unknown platform, assuming -mfloat-abi=%0">;
def warn_ignoring_ftabstop_value : Warning<
"ignoring invalid -ftabstop value '%0', using default value %1">;
def warn_drv_missing_resource_library : Warning<
"missing resource library '%0', link may fail">;
}

View File

@ -172,9 +172,6 @@ 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': %1">, DefaultFatal;
def warn_pp_relative_include_from_framework : Warning<
"published framework headers should always #import headers within the "
"framework with framework paths">, InGroup<DiagGroup<"framework-headers">>;
def err_pp_empty_filename : Error<"empty filename">;
def err_pp_include_too_deep : Error<"#include nested too deeply">;
def err_pp_expects_filename : Error<"expected \"FILENAME\" or <FILENAME>">;

View File

@ -412,6 +412,15 @@ def err_class_redeclared_with_different_access : Error<
"%0 redeclared with '%1' access">;
def note_previous_access_declaration : Note<
"previously declared '%1' here">;
def err_access_outside_class : Error<
"access to %select{private|protected}0 member outside any class context">;
def note_access_natural : Note<"declared %select{private|protected}0 here">;
def note_access_constrained_by_path : Note<
"access to decl constrained by %select{private|protected}0 inheritance">;
def err_access_protected : Error<
"access to protected member of %0 from %1, which is not a subclass">;
def err_access_private : Error<
"access to private member of %0 from %1">;
// C++ name lookup
def err_incomplete_nested_name_spec : Error<
@ -537,8 +546,9 @@ def err_destructor_name : Error<
// C++ initialization
def err_init_conversion_failed : Error<
"cannot initialize %select{a variable|a parameter|return object|an "
"exception object|a value|a base class|a member subobject|an array element}0"
" of type %1 with an %select{rvalue|lvalue}2 of type %3">;
"exception object|a member subobject|an array element|a new value|a value|a "
"base class|an array element}0 of type %1 with an %select{rvalue|lvalue}2 of "
"type %3">;
def err_lvalue_to_rvalue_ref : Error<"rvalue reference cannot bind to lvalue">;
def err_invalid_initialization : Error<
@ -913,10 +923,24 @@ def note_ovl_candidate_arity : Note<"candidate "
"function (the implicit copy assignment operator)}0 not viable: requires"
"%select{ at least| at most|}2 %3 argument%s3, but %4 %plural{1:was|:were}4 "
"provided">;
def note_ovl_candidate_deleted : Note<
"candidate %select{function|function|constructor|"
"function |function |constructor |||}0%1 "
"has been explicitly %select{made unavailable|deleted}2">;
// Giving the index of the bad argument really clutters this message, and
// it's relatively unimportant because 1) it's generally obvious which
// argument(s) are of the given object type and 2) the fix is usually
// to complete the type, which doesn't involve changes to the call line
// anyway. If people complain, we can change it.
def note_ovl_candidate_bad_conv_incomplete : Note<"candidate "
"%select{function|function|constructor|"
"function |function |constructor |"
"constructor (the implicit default constructor)|"
"constructor (the implicit copy constructor)|"
"function (the implicit copy assignment operator)}0%1 "
"not viable: cannot convert argument of incomplete type %2 to %3">;
def note_ovl_candidate_bad_conv : Note<"candidate "
"%select{function|function|constructor|"
"function |function |constructor |"
@ -1840,6 +1864,9 @@ def err_illegal_super_cast : Error<
def warn_setter_getter_impl_required : Warning<
"property %0 requires method %1 to be defined - "
"use @synthesize, @dynamic or provide a method implementation">;
def warn_setter_getter_impl_required_in_category : Warning<
"property %0 requires method %1 to be defined - "
"use @dynamic or provide a method implementation in category">;
def note_property_impl_required : Note<
"implementation is here">;
@ -2458,8 +2485,6 @@ def warn_stringcompare : Warning<
def err_blocks_disable : Error<"blocks support disabled - compile with -fblocks"
" or pick a deployment target that supports them">;
def err_expected_block_lbrace : Error<"expected '{' in block literal">;
def err_goto_in_block : Error<
"goto not allowed in block literal">;
def err_return_in_block_expression : Error<
"return not allowed in block expression literal">;
def err_block_returns_array : Error<

View File

@ -0,0 +1,46 @@
//===--- MacroBuilder.h - CPP Macro building utility ------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the MacroBuilder utility class.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_MACROBUILDER_H
#define LLVM_CLANG_BASIC_MACROBUILDER_H
#include "llvm/ADT/Twine.h"
#include "llvm/Support/raw_ostream.h"
namespace clang {
class MacroBuilder {
llvm::raw_ostream &Out;
public:
MacroBuilder(llvm::raw_ostream &Output) : Out(Output) {}
/// Append a #define line for macro of the form "#define Name Value\n".
void defineMacro(const llvm::Twine &Name, const llvm::Twine &Value = "1") {
Out << "#define " << Name << ' ' << Value << '\n';
}
/// Append a #undef line for Name. Name should be of the form XXX
/// and we emit "#undef XXX".
void undefineMacro(const llvm::Twine &Name) {
Out << "#undef " << Name << '\n';
}
/// Directly append Str and a newline to the underlying buffer.
void append(const llvm::Twine &Str) {
Out << Str << '\n';
}
};
} // end namespace clang
#endif

View File

@ -11,14 +11,12 @@ include $(LEVEL)/Makefile.common
INPUT_TDS = $(wildcard $(PROJ_SRC_DIR)/Diagnostic*.td)
$(ObjDir)/Diagnostic%Kinds.inc.tmp : Diagnostic.td Diagnostic%Kinds.td $(TBLGEN)
$(ObjDir)/Diagnostic%Kinds.inc.tmp : Diagnostic.td Diagnostic%Kinds.td $(TBLGEN) $(ObjDir)/.dir
$(Echo) "Building Clang $(patsubst Diagnostic%Kinds.inc.tmp,%,$(@F)) diagnostic tables with tblgen"
$(Verb) -$(MKDIR) $(@D)
$(Verb) $(TableGen) -gen-clang-diags-defs -clang-component=$(patsubst Diagnostic%Kinds.inc.tmp,%,$(@F)) -o $(call SYSPATH, $@) $<
$(ObjDir)/DiagnosticGroups.inc.tmp : Diagnostic.td DiagnosticGroups.td $(INPUT_TDS) $(TBLGEN)
$(ObjDir)/DiagnosticGroups.inc.tmp : Diagnostic.td DiagnosticGroups.td $(INPUT_TDS) $(TBLGEN) $(ObjDir)/.dir
$(Echo) "Building Clang diagnostic groups with tblgen"
$(Verb) -$(MKDIR) $(@D)
$(Verb) $(TableGen) -gen-clang-diag-groups -o $(call SYSPATH, $@) $<

View File

@ -0,0 +1,82 @@
//===--- Specifiers.h - Declaration and Type Specifiers ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines various enumerations that describe declaration and
// type specifiers.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_SPECIFIERS_H
#define LLVM_CLANG_BASIC_SPECIFIERS_H
namespace clang {
/// \brief Specifies the width of a type, e.g., short, long, or long long.
enum TypeSpecifierWidth {
TSW_unspecified,
TSW_short,
TSW_long,
TSW_longlong
};
/// \brief Specifies the signedness of a type, e.g., signed or unsigned.
enum TypeSpecifierSign {
TSS_unspecified,
TSS_signed,
TSS_unsigned
};
/// \brief Specifies the kind of type.
enum TypeSpecifierType {
TST_unspecified,
TST_void,
TST_char,
TST_wchar, // C++ wchar_t
TST_char16, // C++0x char16_t
TST_char32, // C++0x char32_t
TST_int,
TST_float,
TST_double,
TST_bool, // _Bool
TST_decimal32, // _Decimal32
TST_decimal64, // _Decimal64
TST_decimal128, // _Decimal128
TST_enum,
TST_union,
TST_struct,
TST_class, // C++ class type
TST_typename, // Typedef, C++ class-name or enum name, etc.
TST_typeofType,
TST_typeofExpr,
TST_decltype, // C++0x decltype
TST_auto, // C++0x auto
TST_error // erroneous type
};
/// WrittenBuiltinSpecs - Structure that packs information about the
/// type specifiers that were written in a particular type specifier
/// sequence.
struct WrittenBuiltinSpecs {
/*DeclSpec::TST*/ unsigned Type : 5;
/*DeclSpec::TSS*/ unsigned Sign : 2;
/*DeclSpec::TSW*/ unsigned Width : 2;
bool ModeAttr : 1;
};
/// AccessSpecifier - A C++ access specifier (public, private,
/// protected), plus the special value "none" which means
/// different things in different contexts.
enum AccessSpecifier {
AS_public,
AS_protected,
AS_private,
AS_none
};
}
#endif // LLVM_CLANG_BASIC_SPECIFIERS_H

View File

@ -15,6 +15,8 @@
#ifndef LLVM_CLANG_BASIC_VERSION_H
#define LLVM_CLANG_BASIC_VERSION_H
#include "llvm/ADT/StringRef.h"
/// \brief Clang major version
#define CLANG_VERSION_MAJOR 1
@ -47,13 +49,23 @@
#endif
namespace clang {
/// \brief Retrieves the Subversion path that identifies the particular
/// Clang branch, tag, or trunk from which this Clang was built.
const char *getClangSubversionPath();
/// \brief Retrieves the repository path (e.g., Subversion path) that
/// identifies the particular Clang branch, tag, or trunk from which this
/// Clang was built.
llvm::StringRef getClangRepositoryPath();
/// \brief Retrieves the Subversion revision number from which this Clang
/// was built.
unsigned getClangSubversionRevision();
/// \brief Retrieves the repository revision number (or identifer) from which
/// this Clang was built.
llvm::StringRef getClangRevision();
/// \brief Retrieves the full repository version that is an amalgamation of
/// the information in getClangRepositoryPath() and getClangRevision().
llvm::StringRef getClangFullRepositoryVersion();
/// \brief Retrieves a string representing the complete clang version,
/// which includes the clang version number, the repository version,
/// and the vendor tag.
const char *getClangFullVersion();
}
#endif // LLVM_CLANG_BASIC_VERSION_H

View File

@ -61,6 +61,9 @@ class Driver {
/// command line.
std::string Dir;
/// The path to the compiler resource directory.
std::string ResourceDir;
/// Default host triple.
std::string DefaultHostTriple;

View File

@ -21,6 +21,11 @@
#include <string>
#include <vector>
#include <cassert>
#include <utility>
namespace llvm {
class MemoryBuffer;
}
namespace clang {
class ASTContext;
@ -111,6 +116,10 @@ class ASTUnit {
return TopLevelDecls;
}
/// \brief A mapping from a file name to the memory buffer that stores the
/// remapped contents of that file.
typedef std::pair<std::string, const llvm::MemoryBuffer *> RemappedFile;
/// \brief Create a ASTUnit from a PCH file.
///
/// \param Filename - The PCH file to load.
@ -122,7 +131,9 @@ class ASTUnit {
static ASTUnit *LoadFromPCHFile(const std::string &Filename,
Diagnostic &Diags,
bool OnlyLocalDecls = false,
bool UseBumpAllocator = false);
bool UseBumpAllocator = false,
RemappedFile *RemappedFiles = 0,
unsigned NumRemappedFiles = 0);
/// LoadFromCompilerInvocation - Create an ASTUnit from a source file, via a
/// CompilerInvocation object.
@ -158,7 +169,9 @@ class ASTUnit {
Diagnostic &Diags,
llvm::StringRef ResourceFilesPath,
bool OnlyLocalDecls = false,
bool UseBumpAllocator = false);
bool UseBumpAllocator = false,
RemappedFile *RemappedFiles = 0,
unsigned NumRemappedFiles = 0);
};
} // namespace clang

View File

@ -30,7 +30,7 @@ namespace clang {
/// designed for the previous version could not support reading
/// the new version), this number should be increased.
///
/// Version 3 of PCH files also requires that the Subversion branch and
/// Version 3 of PCH files also requires that the version control branch and
/// revision match exactly, since there is no backward compatibility of
/// PCH files at this time.
const unsigned VERSION_MAJOR = 3;
@ -219,9 +219,9 @@ namespace clang {
/// comments were encountered in the source code.
COMMENT_RANGES = 20,
/// \brief Record code for the Subversion branch and revision information
/// of the compiler used to build this PCH file.
SVN_BRANCH_REVISION = 21
/// \brief Record code for the version control branch and revision
/// information of the compiler used to build this PCH file.
VERSION_CONTROL_BRANCH_REVISION = 21
};
/// \brief Record types used within a source manager block.
@ -676,7 +676,17 @@ namespace clang {
/// \brief A CXXOperatorCallExpr record.
EXPR_CXX_OPERATOR_CALL,
/// \brief A CXXConstructExpr record.
EXPR_CXX_CONSTRUCT
EXPR_CXX_CONSTRUCT,
// \brief A CXXStaticCastExpr record.
EXPR_CXX_STATIC_CAST,
// \brief A CXXDynamicCastExpr record.
EXPR_CXX_DYNAMIC_CAST,
// \brief A CXXReinterpretCastExpr record.
EXPR_CXX_REINTERPRET_CAST,
// \brief A CXXConstCastExpr record.
EXPR_CXX_CONST_CAST,
// \brief A CXXFunctionalCastExpr record.
EXPR_CXX_FUNCTIONAL_CAST
};
/// \brief The kinds of designators that can occur in a

View File

@ -16,6 +16,10 @@
#include <utility>
#include <vector>
namespace llvm {
class MemoryBuffer;
}
namespace clang {
class Preprocessor;
@ -48,6 +52,12 @@ class PreprocessorOptions {
/// pair).
std::vector<std::pair<std::string, std::string> > RemappedFiles;
/// \brief The set of file-to-buffer remappings, which take existing files
/// on the system (the first part of each pair) and gives them the contents
/// of the specified memory buffer (the second part of each pair).
std::vector<std::pair<std::string, const llvm::MemoryBuffer *> >
RemappedFileBuffers;
typedef std::vector<std::pair<std::string, std::string> >::const_iterator
remapped_file_iterator;
remapped_file_iterator remapped_file_begin() const {
@ -57,6 +67,15 @@ class PreprocessorOptions {
return RemappedFiles.end();
}
typedef std::vector<std::pair<std::string, const llvm::MemoryBuffer *> >::
const_iterator remapped_file_buffer_iterator;
remapped_file_buffer_iterator remapped_file_buffer_begin() const {
return RemappedFileBuffers.begin();
}
remapped_file_buffer_iterator remapped_file_buffer_end() const {
return RemappedFileBuffers.end();
}
public:
PreprocessorOptions() : UsePredefines(true) {}
@ -69,6 +88,9 @@ class PreprocessorOptions {
void addRemappedFile(llvm::StringRef From, llvm::StringRef To) {
RemappedFiles.push_back(std::make_pair(From, To));
}
void addRemappedFile(llvm::StringRef From, const llvm::MemoryBuffer * To) {
RemappedFileBuffers.push_back(std::make_pair(From, To));
}
};
} // end namespace clang

View File

@ -15,7 +15,6 @@
#define LLVM_CLANG_FRONTEND_UTILS_H
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/raw_ostream.h"
namespace llvm {
@ -41,28 +40,6 @@ class Stmt;
class TargetInfo;
class FrontendOptions;
class MacroBuilder {
llvm::raw_ostream &Out;
public:
MacroBuilder(llvm::raw_ostream &Output) : Out(Output) {}
/// Append a #define line for macro of the form "#define Name Value\n".
void defineMacro(const llvm::Twine &Name, const llvm::Twine &Value = "1") {
Out << "#define " << Name << ' ' << Value << '\n';
}
/// Append a #undef line for Name. Name should be of the form XXX
/// and we emit "#undef XXX".
void undefineMacro(const llvm::Twine &Name) {
Out << "#undef " << Name << '\n';
}
/// Directly append Str and a newline to the underlying buffer.
void append(const llvm::Twine &Str) {
Out << Str << '\n';
}
};
/// Normalize \arg File for use in a user defined #include directive (in the
/// predefines buffer).
std::string NormalizeDashIncludePath(llvm::StringRef File);

View File

@ -602,7 +602,12 @@ class Preprocessor {
/// the returned source location would not be meaningful (e.g., if
/// it points into a macro), this routine returns an invalid
/// source location.
SourceLocation getLocForEndOfToken(SourceLocation Loc);
///
/// \param Offset an offset from the end of the token, where the source
/// location should refer to. The default offset (0) produces a source
/// location pointing just past the end of the token; an offset of 1 produces
/// a source location pointing to the last character in the token, etc.
SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset = 0);
/// DumpToken - Print the token to stderr, used for debugging.
///
@ -697,8 +702,7 @@ class Preprocessor {
/// return null on failure. isAngled indicates whether the file reference is
/// for system #include's or not (i.e. using <> instead of "").
const FileEntry *LookupFile(llvm::StringRef Filename,
SourceLocation FilenameTokLoc, bool isAngled,
const DirectoryLookup *FromDir,
bool isAngled, const DirectoryLookup *FromDir,
const DirectoryLookup *&CurDir);
/// GetCurLookup - The DirectoryLookup structure used to find the current
@ -884,7 +888,9 @@ class Preprocessor {
void HandlePragmaSystemHeader(Token &SysHeaderTok);
void HandlePragmaDependency(Token &DependencyTok);
void HandlePragmaComment(Token &CommentTok);
void HandleComment(SourceRange Comment);
// Return true and store the first token only if any CommentHandler
// has inserted some tokens and getCommentRetentionState() is false.
bool HandleComment(Token &Token, SourceRange Comment);
};
/// \brief Abstract base class that describes a handler that will receive
@ -893,7 +899,9 @@ class CommentHandler {
public:
virtual ~CommentHandler();
virtual void HandleComment(Preprocessor &PP, SourceRange Comment) = 0;
// The handler shall return true if it has pushed any tokens
// to be read using e.g. EnterToken or EnterTokenStream.
virtual bool HandleComment(Preprocessor &PP, SourceRange Comment) = 0;
};
} // end namespace clang

View File

@ -1,30 +0,0 @@
//===--- AccessSpecifier.h - C++ Access Specifiers -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines interfaces used for C++ access specifiers.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_PARSE_ACCESS_SPECIFIER_H
#define LLVM_CLANG_PARSE_ACCESS_SPECIFIER_H
namespace clang {
/// AccessSpecifier - A C++ access specifier (none, public, private,
/// protected).
enum AccessSpecifier {
AS_none,
AS_public,
AS_protected,
AS_private
};
} // end namespace clang
#endif

View File

@ -16,9 +16,9 @@
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Basic/TemplateKinds.h"
#include "clang/Basic/TypeTraits.h"
#include "clang/Parse/AccessSpecifier.h"
#include "clang/Parse/DeclSpec.h"
#include "clang/Parse/Ownership.h"
#include "llvm/Support/PrettyStackTrace.h"
@ -2110,6 +2110,7 @@ class Action : public ActionBase {
SourceLocation SuperLoc,
const DeclPtrTy *ProtoRefs,
unsigned NumProtoRefs,
const SourceLocation *ProtoLocs,
SourceLocation EndProtoLoc,
AttributeList *AttrList) {
return DeclPtrTy();
@ -2131,6 +2132,7 @@ class Action : public ActionBase {
SourceLocation ProtocolLoc,
const DeclPtrTy *ProtoRefs,
unsigned NumProtoRefs,
const SourceLocation *ProtoLocs,
SourceLocation EndProtoLoc,
AttributeList *AttrList) {
return DeclPtrTy();
@ -2144,6 +2146,7 @@ class Action : public ActionBase {
SourceLocation CategoryLoc,
const DeclPtrTy *ProtoRefs,
unsigned NumProtoRefs,
const SourceLocation *ProtoLocs,
SourceLocation EndProtoLoc) {
return DeclPtrTy();
}
@ -2771,6 +2774,7 @@ class MinimalAction : public Action {
SourceLocation SuperLoc,
const DeclPtrTy *ProtoRefs,
unsigned NumProtoRefs,
const SourceLocation *ProtoLocs,
SourceLocation EndProtoLoc,
AttributeList *AttrList);
};

View File

@ -17,6 +17,7 @@
#include "clang/Parse/AttributeList.h"
#include "clang/Lex/Token.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/Specifiers.h"
#include "llvm/ADT/SmallVector.h"
namespace clang {
@ -78,51 +79,50 @@ class DeclSpec {
SCS_mutable
};
// type-specifier
enum TSW {
TSW_unspecified,
TSW_short,
TSW_long,
TSW_longlong
};
// Import type specifier width enumeration and constants.
typedef TypeSpecifierWidth TSW;
static const TSW TSW_unspecified = clang::TSW_unspecified;
static const TSW TSW_short = clang::TSW_short;
static const TSW TSW_long = clang::TSW_long;
static const TSW TSW_longlong = clang::TSW_longlong;
enum TSC {
TSC_unspecified,
TSC_imaginary,
TSC_complex
};
enum TSS {
TSS_unspecified,
TSS_signed,
TSS_unsigned
};
// Import type specifier sign enumeration and constants.
typedef TypeSpecifierSign TSS;
static const TSS TSS_unspecified = clang::TSS_unspecified;
static const TSS TSS_signed = clang::TSS_signed;
static const TSS TSS_unsigned = clang::TSS_unsigned;
enum TST {
TST_unspecified,
TST_void,
TST_char,
TST_wchar, // C++ wchar_t
TST_char16, // C++0x char16_t
TST_char32, // C++0x char32_t
TST_int,
TST_float,
TST_double,
TST_bool, // _Bool
TST_decimal32, // _Decimal32
TST_decimal64, // _Decimal64
TST_decimal128, // _Decimal128
TST_enum,
TST_union,
TST_struct,
TST_class, // C++ class type
TST_typename, // Typedef, C++ class-name or enum name, etc.
TST_typeofType,
TST_typeofExpr,
TST_decltype, // C++0x decltype
TST_auto, // C++0x auto
TST_error // erroneous type
};
// Import type specifier type enumeration and constants.
typedef TypeSpecifierType TST;
static const TST TST_unspecified = clang::TST_unspecified;
static const TST TST_void = clang::TST_void;
static const TST TST_char = clang::TST_char;
static const TST TST_wchar = clang::TST_wchar;
static const TST TST_char16 = clang::TST_char16;
static const TST TST_char32 = clang::TST_char32;
static const TST TST_int = clang::TST_int;
static const TST TST_float = clang::TST_float;
static const TST TST_double = clang::TST_double;
static const TST TST_bool = clang::TST_bool;
static const TST TST_decimal32 = clang::TST_decimal32;
static const TST TST_decimal64 = clang::TST_decimal64;
static const TST TST_decimal128 = clang::TST_decimal128;
static const TST TST_enum = clang::TST_enum;
static const TST TST_union = clang::TST_union;
static const TST TST_struct = clang::TST_struct;
static const TST TST_class = clang::TST_class;
static const TST TST_typename = clang::TST_typename;
static const TST TST_typeofType = clang::TST_typeofType;
static const TST TST_typeofExpr = clang::TST_typeofExpr;
static const TST TST_decltype = clang::TST_decltype;
static const TST TST_auto = clang::TST_auto;
static const TST TST_error = clang::TST_error;
// type-qualifiers
enum TQ { // NOTE: These flags must be kept in sync with Qualifiers::TQ.
@ -199,6 +199,9 @@ class DeclSpec {
SourceLocation FS_inlineLoc, FS_virtualLoc, FS_explicitLoc;
SourceLocation FriendLoc, ConstexprLoc;
WrittenBuiltinSpecs writtenBS;
void SaveWrittenBuiltinSpecs();
DeclSpec(const DeclSpec&); // DO NOT IMPLEMENT
void operator=(const DeclSpec&); // DO NOT IMPLEMENT
public:
@ -411,6 +414,10 @@ class DeclSpec {
/// DeclSpec is guaranteed self-consistent, even if an error occurred.
void Finish(Diagnostic &D, Preprocessor &PP);
const WrittenBuiltinSpecs& getWrittenBuiltinSpecs() const {
return writtenBS;
}
/// isMissingDeclaratorOk - This checks if this DeclSpec can stand alone,
/// without a Declarator. Only tag declspecs can stand alone.
bool isMissingDeclaratorOk();

View File

@ -14,8 +14,8 @@
#ifndef LLVM_CLANG_PARSE_PARSER_H
#define LLVM_CLANG_PARSE_PARSER_H
#include "clang/Basic/Specifiers.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Parse/AccessSpecifier.h"
#include "clang/Parse/Action.h"
#include "clang/Parse/DeclSpec.h"
#include "llvm/ADT/OwningPtr.h"

View File

@ -17,7 +17,7 @@
namespace clang {
/// DeltaTree - a multiway search tree (BTree) structure with some fancy
/// features. B-Trees are are generally more memory and cache efficient than
/// features. B-Trees are generally more memory and cache efficient than
/// binary trees, because they store multiple keys/values in each node. This
/// implements a key/value mapping from index to delta, and allows fast lookup
/// on index. However, an added (important) bonus is that it can also

View File

@ -1200,43 +1200,58 @@ QualType ASTContext::getObjCGCQualType(QualType T,
return getExtQualType(TypeNode, Quals);
}
QualType ASTContext::getNoReturnType(QualType T, bool AddNoReturn) {
static QualType getNoReturnCallConvType(ASTContext& Context, QualType T,
bool AddNoReturn,
CallingConv CallConv) {
QualType ResultType;
if (const PointerType *Pointer = T->getAs<PointerType>()) {
QualType Pointee = Pointer->getPointeeType();
ResultType = getNoReturnType(Pointee, AddNoReturn);
ResultType = getNoReturnCallConvType(Context, Pointee, AddNoReturn,
CallConv);
if (ResultType == Pointee)
return T;
ResultType = getPointerType(ResultType);
ResultType = Context.getPointerType(ResultType);
} else if (const BlockPointerType *BlockPointer
= T->getAs<BlockPointerType>()) {
QualType Pointee = BlockPointer->getPointeeType();
ResultType = getNoReturnType(Pointee, AddNoReturn);
ResultType = getNoReturnCallConvType(Context, Pointee, AddNoReturn,
CallConv);
if (ResultType == Pointee)
return T;
ResultType = getBlockPointerType(ResultType);
} else if (const FunctionType *F = T->getAs<FunctionType>()) {
if (F->getNoReturnAttr() == AddNoReturn)
ResultType = Context.getBlockPointerType(ResultType);
} else if (const FunctionType *F = T->getAs<FunctionType>()) {
if (F->getNoReturnAttr() == AddNoReturn && F->getCallConv() == CallConv)
return T;
if (const FunctionNoProtoType *FNPT = dyn_cast<FunctionNoProtoType>(F)) {
ResultType = getFunctionNoProtoType(FNPT->getResultType(), AddNoReturn);
ResultType = Context.getFunctionNoProtoType(FNPT->getResultType(),
AddNoReturn, CallConv);
} else {
const FunctionProtoType *FPT = cast<FunctionProtoType>(F);
ResultType
= getFunctionType(FPT->getResultType(), FPT->arg_type_begin(),
FPT->getNumArgs(), FPT->isVariadic(),
FPT->getTypeQuals(),
FPT->hasExceptionSpec(), FPT->hasAnyExceptionSpec(),
FPT->getNumExceptions(), FPT->exception_begin(),
AddNoReturn);
= Context.getFunctionType(FPT->getResultType(), FPT->arg_type_begin(),
FPT->getNumArgs(), FPT->isVariadic(),
FPT->getTypeQuals(),
FPT->hasExceptionSpec(),
FPT->hasAnyExceptionSpec(),
FPT->getNumExceptions(),
FPT->exception_begin(),
AddNoReturn, CallConv);
}
} else
return T;
return getQualifiedType(ResultType, T.getLocalQualifiers());
return Context.getQualifiedType(ResultType, T.getLocalQualifiers());
}
QualType ASTContext::getNoReturnType(QualType T, bool AddNoReturn) {
return getNoReturnCallConvType(*this, T, AddNoReturn, T.getCallConv());
}
QualType ASTContext::getCallConvType(QualType T, CallingConv CallConv) {
return getNoReturnCallConvType(*this, T, T.getNoReturnAttr(), CallConv);
}
/// getComplexType - Return the uniqued reference to the type for a complex
@ -1679,9 +1694,16 @@ QualType ASTContext::getDependentSizedExtVectorType(QualType vecType,
return QualType(New, 0);
}
static CallingConv getCanonicalCallingConv(CallingConv CC) {
if (CC == CC_C)
return CC_Default;
return CC;
}
/// getFunctionNoProtoType - Return a K&R style C function type like 'int()'.
///
QualType ASTContext::getFunctionNoProtoType(QualType ResultTy, bool NoReturn) {
QualType ASTContext::getFunctionNoProtoType(QualType ResultTy, bool NoReturn,
CallingConv CallConv) {
// Unique functions, to guarantee there is only one function of a particular
// structure.
llvm::FoldingSetNodeID ID;
@ -1693,8 +1715,10 @@ QualType ASTContext::getFunctionNoProtoType(QualType ResultTy, bool NoReturn) {
return QualType(FT, 0);
QualType Canonical;
if (!ResultTy.isCanonical()) {
Canonical = getFunctionNoProtoType(getCanonicalType(ResultTy), NoReturn);
if (!ResultTy.isCanonical() ||
getCanonicalCallingConv(CallConv) != CallConv) {
Canonical = getFunctionNoProtoType(getCanonicalType(ResultTy), NoReturn,
getCanonicalCallingConv(CallConv));
// Get the new insert position for the node we care about.
FunctionNoProtoType *NewIP =
@ -1715,7 +1739,8 @@ QualType ASTContext::getFunctionType(QualType ResultTy,const QualType *ArgArray,
unsigned NumArgs, bool isVariadic,
unsigned TypeQuals, bool hasExceptionSpec,
bool hasAnyExceptionSpec, unsigned NumExs,
const QualType *ExArray, bool NoReturn) {
const QualType *ExArray, bool NoReturn,
CallingConv CallConv) {
// Unique functions, to guarantee there is only one function of a particular
// structure.
llvm::FoldingSetNodeID ID;
@ -1737,7 +1762,7 @@ QualType ASTContext::getFunctionType(QualType ResultTy,const QualType *ArgArray,
// If this type isn't canonical, get the canonical version of it.
// The exception spec is not part of the canonical type.
QualType Canonical;
if (!isCanonical) {
if (!isCanonical || getCanonicalCallingConv(CallConv) != CallConv) {
llvm::SmallVector<QualType, 16> CanonicalArgs;
CanonicalArgs.reserve(NumArgs);
for (unsigned i = 0; i != NumArgs; ++i)
@ -1746,7 +1771,8 @@ QualType ASTContext::getFunctionType(QualType ResultTy,const QualType *ArgArray,
Canonical = getFunctionType(getCanonicalType(ResultTy),
CanonicalArgs.data(), NumArgs,
isVariadic, TypeQuals, false,
false, 0, 0, NoReturn);
false, 0, 0, NoReturn,
getCanonicalCallingConv(CallConv));
// Get the new insert position for the node we care about.
FunctionProtoType *NewIP =
@ -1763,7 +1789,7 @@ QualType ASTContext::getFunctionType(QualType ResultTy,const QualType *ArgArray,
NumExs*sizeof(QualType), TypeAlignment);
new (FTP) FunctionProtoType(ResultTy, ArgArray, NumArgs, isVariadic,
TypeQuals, hasExceptionSpec, hasAnyExceptionSpec,
ExArray, NumExs, Canonical, NoReturn);
ExArray, NumExs, Canonical, NoReturn, CallConv);
Types.push_back(FTP);
FunctionProtoTypes.InsertNode(FTP, InsertPos);
return QualType(FTP, 0);
@ -2101,7 +2127,8 @@ QualType ASTContext::getObjCObjectPointerType(QualType InterfaceT,
// No Match;
ObjCObjectPointerType *QType = new (*this, TypeAlignment)
ObjCObjectPointerType(Canonical, InterfaceT, Protocols, NumProtocols);
ObjCObjectPointerType(*this, Canonical, InterfaceT, Protocols,
NumProtocols);
Types.push_back(QType);
ObjCObjectPointerTypes.InsertNode(QType, InsertPos);
@ -2135,7 +2162,7 @@ QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl,
}
ObjCInterfaceType *QType = new (*this, TypeAlignment)
ObjCInterfaceType(Canonical, const_cast<ObjCInterfaceDecl*>(Decl),
ObjCInterfaceType(*this, Canonical, const_cast<ObjCInterfaceDecl*>(Decl),
Protocols, NumProtocols);
Types.push_back(QType);
@ -3733,8 +3760,8 @@ void ASTContext::setObjCConstantStringInterface(ObjCInterfaceDecl *Decl) {
/// \brief Retrieve the template name that corresponds to a non-empty
/// lookup.
TemplateName ASTContext::getOverloadedTemplateName(NamedDecl * const *Begin,
NamedDecl * const *End) {
TemplateName ASTContext::getOverloadedTemplateName(UnresolvedSetIterator Begin,
UnresolvedSetIterator End) {
unsigned size = End - Begin;
assert(size > 1 && "set is not overloaded!");
@ -3743,7 +3770,7 @@ TemplateName ASTContext::getOverloadedTemplateName(NamedDecl * const *Begin,
OverloadedTemplateStorage *OT = new(memory) OverloadedTemplateStorage(size);
NamedDecl **Storage = OT->getStorage();
for (NamedDecl * const *I = Begin; I != End; ++I) {
for (UnresolvedSetIterator I = Begin; I != End; ++I) {
NamedDecl *D = *I;
assert(isa<FunctionTemplateDecl>(D) ||
(isa<UsingShadowDecl>(D) &&
@ -4211,6 +4238,10 @@ bool ASTContext::typesAreCompatible(QualType LHS, QualType RHS) {
return !mergeTypes(LHS, RHS).isNull();
}
static bool isSameCallingConvention(CallingConv lcc, CallingConv rcc) {
return (getCanonicalCallingConv(lcc) == getCanonicalCallingConv(rcc));
}
QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs) {
const FunctionType *lbase = lhs->getAs<FunctionType>();
const FunctionType *rbase = rhs->getAs<FunctionType>();
@ -4232,6 +4263,11 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs) {
allLTypes = false;
if (NoReturn != rbase->getNoReturnAttr())
allRTypes = false;
CallingConv lcc = lbase->getCallConv();
CallingConv rcc = rbase->getCallConv();
// Compatible functions must have compatible calling conventions
if (!isSameCallingConvention(lcc, rcc))
return QualType();
if (lproto && rproto) { // two C99 style function prototypes
assert(!lproto->hasExceptionSpec() && !rproto->hasExceptionSpec() &&
@ -4267,7 +4303,7 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs) {
if (allRTypes) return rhs;
return getFunctionType(retType, types.begin(), types.size(),
lproto->isVariadic(), lproto->getTypeQuals(),
NoReturn);
NoReturn, lcc);
}
if (lproto) allRTypes = false;
@ -4294,12 +4330,12 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs) {
if (allRTypes) return rhs;
return getFunctionType(retType, proto->arg_type_begin(),
proto->getNumArgs(), proto->isVariadic(),
proto->getTypeQuals(), NoReturn);
proto->getTypeQuals(), NoReturn, lcc);
}
if (allLTypes) return lhs;
if (allRTypes) return rhs;
return getFunctionNoProtoType(retType, NoReturn);
return getFunctionNoProtoType(retType, NoReturn, lcc);
}
QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) {

View File

@ -145,7 +145,11 @@ bool CXXRecordDecl::lookupInBases(BaseMatchesCallback *BaseMatches,
void *UserData,
CXXBasePaths &Paths) const {
bool FoundPath = false;
// The access of the path down to this record.
AccessSpecifier AccessToHere = Paths.ScratchPath.Access;
bool IsFirstStep = Paths.ScratchPath.empty();
ASTContext &Context = getASTContext();
for (base_class_const_iterator BaseSpec = bases_begin(),
BaseSpecEnd = bases_end(); BaseSpec != BaseSpecEnd; ++BaseSpec) {
@ -189,10 +193,31 @@ bool CXXRecordDecl::lookupInBases(BaseMatchesCallback *BaseMatches,
else
Element.SubobjectNumber = Subobjects.second;
Paths.ScratchPath.push_back(Element);
// Calculate the "top-down" access to this base class.
// The spec actually describes this bottom-up, but top-down is
// equivalent because the definition works out as follows:
// 1. Write down the access along each step in the inheritance
// chain, followed by the access of the decl itself.
// For example, in
// class A { public: int foo; };
// class B : protected A {};
// class C : public B {};
// class D : private C {};
// we would write:
// private public protected public
// 2. If 'private' appears anywhere except far-left, access is denied.
// 3. Otherwise, overall access is determined by the most restrictive
// access in the sequence.
if (IsFirstStep)
Paths.ScratchPath.Access = BaseSpec->getAccessSpecifier();
else
Paths.ScratchPath.Access
= MergeAccess(AccessToHere, BaseSpec->getAccessSpecifier());
}
if (BaseMatches(BaseSpec, Paths.ScratchPath, UserData)) {
// We've found a path that terminates that this base.
// We've found a path that terminates at this base.
FoundPath = true;
if (Paths.isRecordingPaths()) {
// We have a path. Make a copy of it before moving on.
@ -223,13 +248,18 @@ bool CXXRecordDecl::lookupInBases(BaseMatchesCallback *BaseMatches,
// Pop this base specifier off the current path (if we're
// collecting paths).
if (Paths.isRecordingPaths())
if (Paths.isRecordingPaths()) {
Paths.ScratchPath.pop_back();
}
// If we set a virtual earlier, and this isn't a path, forget it again.
if (SetVirtual && !FoundPath) {
Paths.DetectedVirtual = 0;
}
}
// Reset the scratch path access.
Paths.ScratchPath.Access = AccessToHere;
return FoundPath;
}

View File

@ -629,9 +629,13 @@ VarDecl::~VarDecl() {
}
SourceRange VarDecl::getSourceRange() const {
SourceLocation Start = getTypeSpecStartLoc();
if (Start.isInvalid())
Start = getLocation();
if (getInit())
return SourceRange(getLocation(), getInit()->getLocEnd());
return SourceRange(getLocation(), getLocation());
return SourceRange(Start, getInit()->getLocEnd());
return SourceRange(Start, getLocation());
}
bool VarDecl::isOutOfLine() const {

View File

@ -102,6 +102,17 @@ bool Decl::isFunctionOrFunctionTemplate() const {
return isa<FunctionDecl>(this) || isa<FunctionTemplateDecl>(this);
}
bool Decl::isDefinedOutsideFunctionOrMethod() const {
for (const DeclContext *DC = getDeclContext();
DC && !DC->isTranslationUnit();
DC = DC->getParent())
if (DC->isFunctionOrMethod())
return false;
return true;
}
//===----------------------------------------------------------------------===//
// PrettyStackTraceDecl Implementation
//===----------------------------------------------------------------------===//
@ -399,8 +410,13 @@ SourceLocation Decl::getBodyRBrace() const {
#ifndef NDEBUG
void Decl::CheckAccessDeclContext() const {
// If the decl is the toplevel translation unit or if we're not in a
// record decl context, we don't need to check anything.
// Suppress this check if any of the following hold:
// 1. this is the translation unit (and thus has no parent)
// 2. this is a template parameter (and thus doesn't belong to its context)
// 3. this is a ParmVarDecl (which can be in a record context during
// the brief period between its creation and the creation of the
// FunctionDecl)
// 4. the context is not a record
if (isa<TranslationUnitDecl>(this) ||
!isa<CXXRecordDecl>(getDeclContext()))
return;

View File

@ -312,8 +312,9 @@ void
CXXRecordDecl::collectConversionFunctions(
llvm::SmallPtrSet<CanQualType, 8>& ConversionsTypeSet) const
{
const UnresolvedSet *Cs = getConversionFunctions();
for (UnresolvedSet::iterator I = Cs->begin(), E = Cs->end(); I != E; ++I) {
const UnresolvedSetImpl *Cs = getConversionFunctions();
for (UnresolvedSetImpl::iterator I = Cs->begin(), E = Cs->end();
I != E; ++I) {
NamedDecl *TopConv = *I;
CanQualType TConvType;
if (FunctionTemplateDecl *TConversionTemplate =
@ -344,10 +345,11 @@ CXXRecordDecl::getNestedVisibleConversionFunctions(CXXRecordDecl *RD,
bool inTopClass = (RD == this);
QualType ClassType = getASTContext().getTypeDeclType(this);
if (const RecordType *Record = ClassType->getAs<RecordType>()) {
const UnresolvedSet *Cs
const UnresolvedSetImpl *Cs
= cast<CXXRecordDecl>(Record->getDecl())->getConversionFunctions();
for (UnresolvedSet::iterator I = Cs->begin(), E = Cs->end(); I != E; ++I) {
for (UnresolvedSetImpl::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.
@ -410,7 +412,7 @@ CXXRecordDecl::getNestedVisibleConversionFunctions(CXXRecordDecl *RD,
/// getVisibleConversionFunctions - get all conversion functions visible
/// in current class; including conversion function templates.
const UnresolvedSet *CXXRecordDecl::getVisibleConversionFunctions() {
const UnresolvedSetImpl *CXXRecordDecl::getVisibleConversionFunctions() {
// If root class, all conversions are visible.
if (bases_begin() == bases_end())
return &Conversions;

View File

@ -37,6 +37,21 @@ void ObjCListBase::set(void *const* InList, unsigned Elts, ASTContext &Ctx) {
memcpy(List, InList, sizeof(void*)*Elts);
}
void ObjCProtocolList::set(ObjCProtocolDecl* const* InList, unsigned Elts,
const SourceLocation *Locs, ASTContext &Ctx) {
if (Elts == 0)
return;
Locations = new (Ctx) SourceLocation[Elts];
memcpy(Locations, Locs, sizeof(SourceLocation) * Elts);
set(InList, Elts, Ctx);
}
void ObjCProtocolList::Destroy(ASTContext &Ctx) {
Ctx.Deallocate(Locations);
Locations = 0;
ObjCList<ObjCProtocolDecl>::Destroy(Ctx);
}
//===----------------------------------------------------------------------===//
// ObjCInterfaceDecl
@ -141,16 +156,18 @@ ObjCContainerDecl::FindPropertyVisibleInPrimaryClass(
void ObjCInterfaceDecl::mergeClassExtensionProtocolList(
ObjCProtocolDecl *const* ExtList, unsigned ExtNum,
const SourceLocation *Locs,
ASTContext &C)
{
if (ReferencedProtocols.empty()) {
ReferencedProtocols.set(ExtList, ExtNum, C);
ReferencedProtocols.set(ExtList, ExtNum, Locs, C);
return;
}
// Check for duplicate protocol in class's protocol list.
// This is (O)2. But it is extremely rare and number of protocols in
// class or its extension are very few.
llvm::SmallVector<ObjCProtocolDecl*, 8> ProtocolRefs;
llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
for (unsigned i = 0; i < ExtNum; i++) {
bool protocolExists = false;
ObjCProtocolDecl *ProtoInExtension = ExtList[i];
@ -164,18 +181,23 @@ void ObjCInterfaceDecl::mergeClassExtensionProtocolList(
}
// Do we want to warn on a protocol in extension class which
// already exist in the class? Probably not.
if (!protocolExists)
if (!protocolExists) {
ProtocolRefs.push_back(ProtoInExtension);
ProtocolLocs.push_back(Locs[i]);
}
}
if (ProtocolRefs.empty())
return;
// Merge ProtocolRefs into class's protocol list;
protocol_loc_iterator pl = protocol_loc_begin();
for (protocol_iterator p = protocol_begin(), e = protocol_end();
p != e; p++)
p != e; ++p, ++pl) {
ProtocolRefs.push_back(*p);
ProtocolLocs.push_back(*pl);
}
ReferencedProtocols.Destroy(C);
unsigned NumProtoRefs = ProtocolRefs.size();
setProtocolList((ObjCProtocolDecl**)&ProtocolRefs[0], NumProtoRefs, C);
setProtocolList(ProtocolRefs.data(), NumProtoRefs, ProtocolLocs.data(), C);
}
ObjCIvarDecl *ObjCInterfaceDecl::lookupInstanceVariable(IdentifierInfo *ID,
@ -627,9 +649,9 @@ SourceRange ObjCClassDecl::getSourceRange() const {
ObjCForwardProtocolDecl::
ObjCForwardProtocolDecl(DeclContext *DC, SourceLocation L,
ObjCProtocolDecl *const *Elts, unsigned nElts,
ASTContext &C)
const SourceLocation *Locs, ASTContext &C)
: Decl(ObjCForwardProtocol, DC, L) {
ReferencedProtocols.set(Elts, nElts, C);
ReferencedProtocols.set(Elts, nElts, Locs, C);
}
@ -637,8 +659,9 @@ ObjCForwardProtocolDecl *
ObjCForwardProtocolDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
ObjCProtocolDecl *const *Elts,
unsigned NumElts) {
return new (C) ObjCForwardProtocolDecl(DC, L, Elts, NumElts, C);
unsigned NumElts,
const SourceLocation *Locs) {
return new (C) ObjCForwardProtocolDecl(DC, L, Elts, NumElts, Locs, C);
}
void ObjCForwardProtocolDecl::Destroy(ASTContext &C) {
@ -651,9 +674,11 @@ void ObjCForwardProtocolDecl::Destroy(ASTContext &C) {
//===----------------------------------------------------------------------===//
ObjCCategoryDecl *ObjCCategoryDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
SourceLocation AtLoc,
SourceLocation ClassNameLoc,
SourceLocation CategoryNameLoc,
IdentifierInfo *Id) {
return new (C) ObjCCategoryDecl(DC, L, Id);
return new (C) ObjCCategoryDecl(DC, AtLoc, ClassNameLoc, CategoryNameLoc, Id);
}
ObjCCategoryImplDecl *ObjCCategoryDecl::getImplementation() const {
@ -765,9 +790,10 @@ ObjCCompatibleAliasDecl::Create(ASTContext &C, DeclContext *DC,
ObjCPropertyDecl *ObjCPropertyDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
IdentifierInfo *Id,
SourceLocation AtLoc,
QualType T,
PropertyControl propControl) {
return new (C) ObjCPropertyDecl(DC, L, Id, T);
return new (C) ObjCPropertyDecl(DC, L, Id, AtLoc, T);
}

View File

@ -98,10 +98,12 @@ void DeclRefExpr::computeDependence() {
// 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;
Var->getType().getCVRQualifiers() == Qualifiers::Const) {
const VarDecl *Def = 0;
if (const Expr *Init = Var->getDefinition(Def))
if (Init->isValueDependent())
ValueDependent = true;
}
}
// (TD) - a nested-name-specifier or a qualified-id that names a
// member of an unknown specialization.

View File

@ -135,10 +135,11 @@ UnresolvedLookupExpr::Create(ASTContext &C, bool Dependent,
return ULE;
}
bool UnresolvedLookupExpr::ComputeDependence(NamedDecl * const *Begin,
NamedDecl * const *End,
const TemplateArgumentListInfo *Args) {
for (NamedDecl * const *I = Begin; I != End; ++I)
bool UnresolvedLookupExpr::
ComputeDependence(UnresolvedSetImpl::const_iterator Begin,
UnresolvedSetImpl::const_iterator End,
const TemplateArgumentListInfo *Args) {
for (UnresolvedSetImpl::const_iterator I = Begin; I != End; ++I)
if ((*I)->getDeclContext()->isDependentContext())
return true;

View File

@ -506,7 +506,9 @@ APValue PointerExprEvaluator::VisitCastExpr(CastExpr* E) {
APValue PointerExprEvaluator::VisitCallExpr(CallExpr *E) {
if (E->isBuiltinCall(Info.Ctx) ==
Builtin::BI__builtin___CFStringMakeConstantString)
Builtin::BI__builtin___CFStringMakeConstantString ||
E->isBuiltinCall(Info.Ctx) ==
Builtin::BI__builtin___NSStringMakeConstantString)
return APValue(E);
return APValue();
}
@ -971,6 +973,8 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
case Builtin::BI__builtin_object_size: {
const Expr *Arg = E->getArg(0)->IgnoreParens();
Expr::EvalResult Base;
// TODO: Perhaps we should let LLVM lower this?
if (Arg->EvaluateAsAny(Base, Info.Ctx)
&& Base.Val.getKind() == APValue::LValue
&& !Base.HasSideEffects)
@ -992,7 +996,8 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
}
}
// TODO: Perhaps we should let LLVM lower this?
// If evaluating the argument has side-effects we can't determine
// the size of the object and lower it to unknown now.
if (E->getArg(0)->HasSideEffects(Info.Ctx)) {
if (E->getArg(1)->EvaluateAsInt(Info.Ctx).getZExtValue() <= 1)
return Success(-1ULL, E);

View File

@ -119,6 +119,11 @@ ASTRecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD,
return;
}
}
if (i->isVirtual()) {
SelectPrimaryVBase(Base, FirstPrimary);
if (PrimaryBase.getBase())
return;
}
}
}

View File

@ -339,6 +339,25 @@ const RecordType *Type::getAsUnionType() const {
return 0;
}
ObjCInterfaceType::ObjCInterfaceType(ASTContext &Ctx, QualType Canonical,
ObjCInterfaceDecl *D,
ObjCProtocolDecl **Protos, unsigned NumP) :
Type(ObjCInterface, Canonical, /*Dependent=*/false),
Decl(D), Protocols(0), NumProtocols(NumP)
{
if (NumProtocols) {
Protocols = new (Ctx) ObjCProtocolDecl*[NumProtocols];
memcpy(Protocols, Protos, NumProtocols * sizeof(*Protocols));
}
}
void ObjCInterfaceType::Destroy(ASTContext& C) {
if (Protocols)
C.Deallocate(Protocols);
this->~ObjCInterfaceType();
C.Deallocate(this);
}
const ObjCInterfaceType *Type::getAsObjCQualifiedInterfaceType() const {
// There is no sugar for ObjCInterfaceType's, just return the canonical
// type pointer if it is the right class. There is no typedef information to
@ -353,6 +372,26 @@ bool Type::isObjCQualifiedInterfaceType() const {
return getAsObjCQualifiedInterfaceType() != 0;
}
ObjCObjectPointerType::ObjCObjectPointerType(ASTContext &Ctx,
QualType Canonical, QualType T,
ObjCProtocolDecl **Protos,
unsigned NumP) :
Type(ObjCObjectPointer, Canonical, /*Dependent=*/false),
PointeeType(T), Protocols(NULL), NumProtocols(NumP)
{
if (NumProtocols) {
Protocols = new (Ctx) ObjCProtocolDecl*[NumProtocols];
memcpy(Protocols, Protos, NumProtocols * sizeof(*Protocols));
}
}
void ObjCObjectPointerType::Destroy(ASTContext& C) {
if (Protocols)
C.Deallocate(Protocols);
this->~ObjCObjectPointerType();
C.Deallocate(this);
}
const ObjCObjectPointerType *Type::getAsObjCQualifiedIdType() const {
// There is no sugar for ObjCQualifiedIdType's, just return the canonical
// type pointer if it is the right class.

View File

@ -14,6 +14,7 @@
#include "llvm/Support/raw_ostream.h"
#include "clang/AST/TypeLocVisitor.h"
#include "clang/AST/Expr.h"
#include "llvm/Support/ErrorHandling.h"
using namespace clang;
//===----------------------------------------------------------------------===//
@ -135,3 +136,56 @@ SourceRange TypeOfExprTypeLoc::getSourceRange() const {
return SourceRange(getTypeofLoc(),
getUnderlyingExpr()->getSourceRange().getEnd());
}
TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
if (needsExtraLocalData())
return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type);
else {
switch (getTypePtr()->getKind()) {
case BuiltinType::Void:
return TST_void;
case BuiltinType::Bool:
return TST_bool;
case BuiltinType::Char_U:
case BuiltinType::Char_S:
return TST_char;
case BuiltinType::Char16:
return TST_char16;
case BuiltinType::Char32:
return TST_char32;
case BuiltinType::WChar:
return TST_wchar;
case BuiltinType::UndeducedAuto:
return TST_auto;
case BuiltinType::UChar:
case BuiltinType::UShort:
case BuiltinType::UInt:
case BuiltinType::ULong:
case BuiltinType::ULongLong:
case BuiltinType::UInt128:
case BuiltinType::SChar:
case BuiltinType::Short:
case BuiltinType::Int:
case BuiltinType::Long:
case BuiltinType::LongLong:
case BuiltinType::Int128:
case BuiltinType::Float:
case BuiltinType::Double:
case BuiltinType::LongDouble:
llvm_unreachable("Builtin type needs extra local data!");
// Fall through, if the impossible happens.
case BuiltinType::NullPtr:
case BuiltinType::Overload:
case BuiltinType::Dependent:
case BuiltinType::ObjCId:
case BuiltinType::ObjCClass:
case BuiltinType::ObjCSel:
return TST_unspecified;
}
}
return TST_unspecified;
}

View File

@ -55,7 +55,7 @@ const ImplicitParamDecl *AnalysisContext::getSelfDecl() const {
CFG *AnalysisContext::getCFG() {
if (!cfg)
cfg = CFG::buildCFG(getBody(), &D->getASTContext());
cfg = CFG::buildCFG(D, getBody(), &D->getASTContext(), AddEHEdges);
return cfg;
}

View File

@ -57,7 +57,8 @@ void ArrayBoundChecker::VisitLocation(CheckerContext &C, const Stmt *S, SVal l){
// Get the size of the array.
DefinedOrUnknownSVal NumElements
= C.getStoreManager().getSizeInElements(state, ER->getSuperRegion());
= C.getStoreManager().getSizeInElements(state, ER->getSuperRegion(),
ER->getValueType(C.getASTContext()));
const GRState *StInBound = state->AssumeInBound(Idx, NumElements, true);
const GRState *StOutBound = state->AssumeInBound(Idx, NumElements, false);

View File

@ -14,6 +14,7 @@
#include "clang/Analysis/Support/SaveAndRestore.h"
#include "clang/Analysis/CFG.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/PrettyPrinter.h"
#include "llvm/Support/GraphWriter.h"
@ -70,6 +71,7 @@ class CFGBuilder {
CFGBlock* BreakTargetBlock;
CFGBlock* SwitchTerminatedBlock;
CFGBlock* DefaultCaseBlock;
CFGBlock* TryTerminatedBlock;
// LabelMap records the mapping from Label expressions to their blocks.
typedef llvm::DenseMap<LabelStmt*,CFGBlock*> LabelMapTy;
@ -88,10 +90,12 @@ class CFGBuilder {
explicit CFGBuilder() : cfg(new CFG()), // crew a new CFG
Block(NULL), Succ(NULL),
ContinueTargetBlock(NULL), BreakTargetBlock(NULL),
SwitchTerminatedBlock(NULL), DefaultCaseBlock(NULL) {}
SwitchTerminatedBlock(NULL), DefaultCaseBlock(NULL),
TryTerminatedBlock(NULL) {}
// buildCFG - Used by external clients to construct the CFG.
CFG* buildCFG(Stmt *Statement, ASTContext *C);
CFG* buildCFG(const Decl *D, Stmt *Statement, ASTContext *C, bool AddEHEdges,
bool AddScopes);
private:
// Visitors to walk an AST and construct the CFG.
@ -106,9 +110,9 @@ class CFGBuilder {
CFGBlock *VisitConditionalOperator(ConditionalOperator *C,
AddStmtChoice asc);
CFGBlock *VisitContinueStmt(ContinueStmt *C);
CFGBlock *VisitCXXCatchStmt(CXXCatchStmt *S) { return NYS(); }
CFGBlock *VisitCXXCatchStmt(CXXCatchStmt *S);
CFGBlock *VisitCXXThrowExpr(CXXThrowExpr *T);
CFGBlock *VisitCXXTryStmt(CXXTryStmt *S) { return NYS(); }
CFGBlock *VisitCXXTryStmt(CXXTryStmt *S);
CFGBlock *VisitDeclStmt(DeclStmt *DS);
CFGBlock *VisitDeclSubExpr(Decl* D);
CFGBlock *VisitDefaultStmt(DefaultStmt *D);
@ -139,6 +143,25 @@ class CFGBuilder {
return Block;
}
CFGBlock *StartScope(Stmt *S, CFGBlock *B) {
if (!AddScopes)
return B;
if (B == 0)
B = createBlock();
B->StartScope(S, cfg->getBumpVectorContext());
return B;
}
void EndScope(Stmt *S) {
if (!AddScopes)
return;
if (Block == 0)
Block = createBlock();
Block->EndScope(S, cfg->getBumpVectorContext());
}
void autoCreateBlock() { if (!Block) Block = createBlock(); }
CFGBlock *createBlock(bool add_successor = true);
bool FinishBlock(CFGBlock* B);
@ -186,6 +209,12 @@ class CFGBuilder {
}
bool badCFG;
// True iff EH edges on CallExprs should be added to the CFG.
bool AddEHEdges;
// True iff scope start and scope end notes should be added to the CFG.
bool AddScopes;
};
// FIXME: Add support for dependent-sized array types in C++?
@ -207,12 +236,15 @@ static VariableArrayType* FindVA(Type* t) {
/// body (compound statement). The ownership of the returned CFG is
/// transferred to the caller. If CFG construction fails, this method returns
/// NULL.
CFG* CFGBuilder::buildCFG(Stmt* Statement, ASTContext* C) {
CFG* CFGBuilder::buildCFG(const Decl *D, Stmt* Statement, ASTContext* C,
bool addehedges, bool AddScopes) {
AddEHEdges = addehedges;
Context = C;
assert(cfg.get());
if (!Statement)
return NULL;
this->AddScopes = AddScopes;
badCFG = false;
// Create an empty block that will serve as the exit block for the CFG. Since
@ -224,6 +256,11 @@ CFG* CFGBuilder::buildCFG(Stmt* Statement, ASTContext* C) {
// Visit the statements and create the CFG.
CFGBlock* B = addStmt(Statement);
if (const CXXConstructorDecl *CD = dyn_cast_or_null<CXXConstructorDecl>(D)) {
// FIXME: Add code for base initializers and member initializers.
(void)CD;
}
if (!B)
B = Succ;
@ -329,6 +366,15 @@ CFGBlock* CFGBuilder::Visit(Stmt * S, AddStmtChoice asc) {
case Stmt::ContinueStmtClass:
return VisitContinueStmt(cast<ContinueStmt>(S));
case Stmt::CXXCatchStmtClass:
return VisitCXXCatchStmt(cast<CXXCatchStmt>(S));
case Stmt::CXXThrowExprClass:
return VisitCXXThrowExpr(cast<CXXThrowExpr>(S));
case Stmt::CXXTryStmtClass:
return VisitCXXTryStmt(cast<CXXTryStmt>(S));
case Stmt::DeclStmtClass:
return VisitDeclStmt(cast<DeclStmt>(S));
@ -356,9 +402,6 @@ CFGBlock* CFGBuilder::Visit(Stmt * S, AddStmtChoice asc) {
case Stmt::ObjCAtCatchStmtClass:
return VisitObjCAtCatchStmt(cast<ObjCAtCatchStmt>(S));
case Stmt::CXXThrowExprClass:
return VisitCXXThrowExpr(cast<CXXThrowExpr>(S));
case Stmt::ObjCAtSynchronizedStmtClass:
return VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S));
@ -456,7 +499,7 @@ CFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B,
AddSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock);
AddSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock);
} else {
assert (B->getOpcode() == BinaryOperator::LAnd);
assert(B->getOpcode() == BinaryOperator::LAnd);
AddSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock);
AddSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock);
}
@ -504,6 +547,22 @@ CFGBlock *CFGBuilder::VisitBreakStmt(BreakStmt *B) {
return Block;
}
static bool CanThrow(Expr *E) {
QualType Ty = E->getType();
if (Ty->isFunctionPointerType())
Ty = Ty->getAs<PointerType>()->getPointeeType();
else if (Ty->isBlockPointerType())
Ty = Ty->getAs<BlockPointerType>()->getPointeeType();
const FunctionType *FT = Ty->getAs<FunctionType>();
if (FT) {
if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT))
if (Proto->hasEmptyExceptionSpec())
return false;
}
return true;
}
CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) {
// If this is a call to a no-return function, this stops the block here.
bool NoReturn = false;
@ -511,22 +570,47 @@ CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) {
NoReturn = true;
}
if (FunctionDecl *FD = C->getDirectCallee())
bool AddEHEdge = false;
// Languages without exceptions are assumed to not throw.
if (Context->getLangOptions().Exceptions) {
if (AddEHEdges)
AddEHEdge = true;
}
if (FunctionDecl *FD = C->getDirectCallee()) {
if (FD->hasAttr<NoReturnAttr>())
NoReturn = true;
if (FD->hasAttr<NoThrowAttr>())
AddEHEdge = false;
}
if (!NoReturn)
if (!CanThrow(C->getCallee()))
AddEHEdge = false;
if (!NoReturn && !AddEHEdge)
return VisitStmt(C, asc);
if (Block && !FinishBlock(Block))
return 0;
if (Block) {
Succ = Block;
if (!FinishBlock(Block))
return 0;
}
// Create new block with no successor for the remaining pieces.
Block = createBlock(false);
Block = createBlock(!NoReturn);
AppendStmt(Block, C, asc);
// Wire this to the exit block directly.
AddSuccessor(Block, &cfg->getExit());
if (NoReturn) {
// Wire this to the exit block directly.
AddSuccessor(Block, &cfg->getExit());
}
if (AddEHEdge) {
// Add exceptional edges.
if (TryTerminatedBlock)
AddSuccessor(Block, TryTerminatedBlock);
else
AddSuccessor(Block, &cfg->getExit());
}
return VisitChildren(C);
}
@ -561,6 +645,8 @@ CFGBlock *CFGBuilder::VisitChooseExpr(ChooseExpr *C,
CFGBlock* CFGBuilder::VisitCompoundStmt(CompoundStmt* C) {
EndScope(C);
CFGBlock* LastBlock = Block;
for (CompoundStmt::reverse_body_iterator I=C->body_rbegin(), E=C->body_rend();
@ -570,6 +656,9 @@ CFGBlock* CFGBuilder::VisitCompoundStmt(CompoundStmt* C) {
if (badCFG)
return NULL;
}
LastBlock = StartScope(C, LastBlock);
return LastBlock;
}
@ -743,7 +832,7 @@ CFGBlock* CFGBuilder::VisitIfStmt(IfStmt* I) {
CFGBlock* ThenBlock;
{
Stmt* Then = I->getThen();
assert (Then);
assert(Then);
SaveAndRestore<CFGBlock*> sv(Succ);
Block = NULL;
ThenBlock = addStmt(Then);
@ -919,12 +1008,12 @@ CFGBlock* CFGBuilder::VisitForStmt(ForStmt* F) {
// Now create the loop body.
{
assert (F->getBody());
assert(F->getBody());
// Save the current values for Block, Succ, and continue and break targets
SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ),
save_continue(ContinueTargetBlock),
save_break(BreakTargetBlock);
save_continue(ContinueTargetBlock),
save_break(BreakTargetBlock);
// Create a new block to contain the (bottom) of the loop body.
Block = NULL;
@ -1252,8 +1341,12 @@ CFGBlock* CFGBuilder::VisitCXXThrowExpr(CXXThrowExpr* T) {
// Create the new block.
Block = createBlock(false);
// The Exit block is the only successor.
AddSuccessor(Block, &cfg->getExit());
if (TryTerminatedBlock)
// The current try statement is the only successor.
AddSuccessor(Block, TryTerminatedBlock);
else
// otherwise the Exit block is the only successor.
AddSuccessor(Block, &cfg->getExit());
// Add the statement to the block. This may create new blocks if S contains
// control-flow (short-circuit operations).
@ -1301,12 +1394,12 @@ CFGBlock *CFGBuilder::VisitDoStmt(DoStmt* D) {
// Process the loop body.
CFGBlock* BodyBlock = NULL;
{
assert (D->getBody());
assert(D->getBody());
// Save the current values for Block, Succ, and continue and break targets
SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ),
save_continue(ContinueTargetBlock),
save_break(BreakTargetBlock);
save_continue(ContinueTargetBlock),
save_break(BreakTargetBlock);
// All continues within this loop should go to the condition block
ContinueTargetBlock = EntryConditionBlock;
@ -1434,7 +1527,7 @@ CFGBlock* CFGBuilder::VisitSwitchStmt(SwitchStmt* Terminator) {
// When visiting the body, the case statements should automatically get linked
// up to the switch. We also don't keep a pointer to the body, since all
// control-flow from the switch goes to case/default statements.
assert (Terminator->getBody() && "switch must contain a non-NULL body");
assert(Terminator->getBody() && "switch must contain a non-NULL body");
Block = NULL;
CFGBlock *BodyBlock = addStmt(Terminator->getBody());
if (Block) {
@ -1448,7 +1541,7 @@ CFGBlock* CFGBuilder::VisitSwitchStmt(SwitchStmt* Terminator) {
// Add the terminator and condition in the switch block.
SwitchTerminatedBlock->setTerminator(Terminator);
assert (Terminator->getCond() && "switch condition must be non-NULL");
assert(Terminator->getCond() && "switch condition must be non-NULL");
Block = SwitchTerminatedBlock;
Block = addStmt(Terminator->getCond());
@ -1528,6 +1621,82 @@ CFGBlock* CFGBuilder::VisitDefaultStmt(DefaultStmt* Terminator) {
return DefaultCaseBlock;
}
CFGBlock *CFGBuilder::VisitCXXTryStmt(CXXTryStmt *Terminator) {
// "try"/"catch" is a control-flow statement. Thus we stop processing the
// current block.
CFGBlock* TrySuccessor = NULL;
if (Block) {
if (!FinishBlock(Block))
return 0;
TrySuccessor = Block;
} else TrySuccessor = Succ;
CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock;
// Create a new block that will contain the try statement.
CFGBlock *NewTryTerminatedBlock = createBlock(false);
// Add the terminator in the try block.
NewTryTerminatedBlock->setTerminator(Terminator);
bool HasCatchAll = false;
for (unsigned h = 0; h <Terminator->getNumHandlers(); ++h) {
// The code after the try is the implicit successor.
Succ = TrySuccessor;
CXXCatchStmt *CS = Terminator->getHandler(h);
if (CS->getExceptionDecl() == 0) {
HasCatchAll = true;
}
Block = NULL;
CFGBlock *CatchBlock = VisitCXXCatchStmt(CS);
if (CatchBlock == 0)
return 0;
// Add this block to the list of successors for the block with the try
// statement.
AddSuccessor(NewTryTerminatedBlock, CatchBlock);
}
if (!HasCatchAll) {
if (PrevTryTerminatedBlock)
AddSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock);
else
AddSuccessor(NewTryTerminatedBlock, &cfg->getExit());
}
// The code after the try is the implicit successor.
Succ = TrySuccessor;
// Save the current "try" context.
SaveAndRestore<CFGBlock*> save_try(TryTerminatedBlock);
TryTerminatedBlock = NewTryTerminatedBlock;
assert(Terminator->getTryBlock() && "try must contain a non-NULL body");
Block = NULL;
Block = addStmt(Terminator->getTryBlock());
return Block;
}
CFGBlock* CFGBuilder::VisitCXXCatchStmt(CXXCatchStmt* CS) {
// CXXCatchStmt are treated like labels, so they are the first statement in a
// block.
if (CS->getHandlerBlock())
addStmt(CS->getHandlerBlock());
CFGBlock* CatchBlock = Block;
if (!CatchBlock)
CatchBlock = createBlock();
CatchBlock->setLabel(CS);
if (!FinishBlock(CatchBlock))
return 0;
// We set Block to NULL to allow lazy creation of a new block (if necessary)
Block = NULL;
return CatchBlock;
}
CFGBlock* CFGBuilder::VisitIndirectGotoStmt(IndirectGotoStmt* I) {
// Lazily create the indirect-goto dispatch block if there isn't one already.
CFGBlock* IBlock = cfg->getIndirectGotoBlock();
@ -1571,9 +1740,10 @@ CFGBlock* CFG::createBlock() {
/// buildCFG - Constructs a CFG from an AST. Ownership of the returned
/// CFG is returned to the caller.
CFG* CFG::buildCFG(Stmt* Statement, ASTContext *C) {
CFG* CFG::buildCFG(const Decl *D, Stmt* Statement, ASTContext *C,
bool AddEHEdges, bool AddScopes) {
CFGBuilder Builder;
return Builder.buildCFG(Statement, C);
return Builder.buildCFG(D, Statement, C, AddEHEdges, AddScopes);
}
//===----------------------------------------------------------------------===//
@ -1661,9 +1831,7 @@ CFG::BlkExprNumTy CFG::getBlkExprNum(const Stmt* S) {
BlkExprMapTy* M = reinterpret_cast<BlkExprMapTy*>(BlkExprMap);
BlkExprMapTy::iterator I = M->find(S);
if (I == M->end()) return CFG::BlkExprNumTy();
else return CFG::BlkExprNumTy(I->second);
return (I == M->end()) ? CFG::BlkExprNumTy() : CFG::BlkExprNumTy(I->second);
}
unsigned CFG::getNumBlkExprs() {
@ -1692,7 +1860,6 @@ CFG::~CFG() {
namespace {
class StmtPrinterHelper : public PrinterHelper {
typedef llvm::DenseMap<Stmt*,std::pair<unsigned,unsigned> > StmtMapTy;
StmtMapTy StmtMap;
signed CurrentBlock;
@ -1724,10 +1891,11 @@ class StmtPrinterHelper : public PrinterHelper {
return false;
if (CurrentBlock >= 0 && I->second.first == (unsigned) CurrentBlock
&& I->second.second == CurrentStmt)
&& I->second.second == CurrentStmt) {
return false;
}
OS << "[B" << I->second.first << "." << I->second.second << "]";
OS << "[B" << I->second.first << "." << I->second.second << "]";
return true;
}
};
@ -1741,7 +1909,6 @@ class CFGBlockTerminatorPrint
llvm::raw_ostream& OS;
StmtPrinterHelper* Helper;
PrintingPolicy Policy;
public:
CFGBlockTerminatorPrint(llvm::raw_ostream& os, StmtPrinterHelper* helper,
const PrintingPolicy &Policy)
@ -1759,22 +1926,27 @@ class CFGBlockTerminatorPrint
void VisitForStmt(ForStmt* F) {
OS << "for (" ;
if (F->getInit()) OS << "...";
if (F->getInit())
OS << "...";
OS << "; ";
if (Stmt* C = F->getCond()) C->printPretty(OS, Helper, Policy);
if (Stmt* C = F->getCond())
C->printPretty(OS, Helper, Policy);
OS << "; ";
if (F->getInc()) OS << "...";
if (F->getInc())
OS << "...";
OS << ")";
}
void VisitWhileStmt(WhileStmt* W) {
OS << "while " ;
if (Stmt* C = W->getCond()) C->printPretty(OS, Helper, Policy);
if (Stmt* C = W->getCond())
C->printPretty(OS, Helper, Policy);
}
void VisitDoStmt(DoStmt* D) {
OS << "do ... while ";
if (Stmt* C = D->getCond()) C->printPretty(OS, Helper, Policy);
if (Stmt* C = D->getCond())
C->printPretty(OS, Helper, Policy);
}
void VisitSwitchStmt(SwitchStmt* Terminator) {
@ -1782,6 +1954,10 @@ class CFGBlockTerminatorPrint
Terminator->getCond()->printPretty(OS, Helper, Policy);
}
void VisitCXXTryStmt(CXXTryStmt* CS) {
OS << "try ...";
}
void VisitConditionalOperator(ConditionalOperator* C) {
C->getCond()->printPretty(OS, Helper, Policy);
OS << " ? ... : ...";
@ -1826,7 +2002,18 @@ class CFGBlockTerminatorPrint
static void print_stmt(llvm::raw_ostream &OS, StmtPrinterHelper* Helper,
Stmt* Terminator) {
const CFGElement &E) {
Stmt *Terminator = E;
if (E.asStartScope()) {
OS << "start scope\n";
return;
}
if (E.asEndScope()) {
OS << "end scope\n";
return;
}
if (Helper) {
// special printing for statement-expressions.
if (StmtExpr* SE = dyn_cast<StmtExpr>(Terminator)) {
@ -1876,14 +2063,14 @@ static void print_block(llvm::raw_ostream& OS, const CFG* cfg,
OS << " ]\n";
// Print the label of this block.
if (Stmt* Terminator = const_cast<Stmt*>(B.getLabel())) {
if (Stmt* Label = const_cast<Stmt*>(B.getLabel())) {
if (print_edges)
OS << " ";
if (LabelStmt* L = dyn_cast<LabelStmt>(Terminator))
if (LabelStmt* L = dyn_cast<LabelStmt>(Label))
OS << L->getName();
else if (CaseStmt* C = dyn_cast<CaseStmt>(Terminator)) {
else if (CaseStmt* C = dyn_cast<CaseStmt>(Label)) {
OS << "case ";
C->getLHS()->printPretty(OS, Helper,
PrintingPolicy(Helper->getLangOpts()));
@ -1892,9 +2079,18 @@ static void print_block(llvm::raw_ostream& OS, const CFG* cfg,
C->getRHS()->printPretty(OS, Helper,
PrintingPolicy(Helper->getLangOpts()));
}
} else if (isa<DefaultStmt>(Terminator))
} else if (isa<DefaultStmt>(Label))
OS << "default";
else
else if (CXXCatchStmt *CS = dyn_cast<CXXCatchStmt>(Label)) {
OS << "catch (";
if (CS->getExceptionDecl())
CS->getExceptionDecl()->print(OS, PrintingPolicy(Helper->getLangOpts()),
0);
else
OS << "...";
OS << ")";
} else
assert(false && "Invalid label statement in CFGBlock.");
OS << ":\n";

View File

@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
//
// This files defines CastToStructChecker, a builtin checker that checks for
// assignment of a fixed address to a pointer.
// cast from non-struct pointer to struct pointer.
// This check corresponds to CWE-588.
//
//===----------------------------------------------------------------------===//

View File

@ -2173,8 +2173,8 @@ void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME,
// Transfer functions: Miscellaneous statements.
//===----------------------------------------------------------------------===//
void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue){
void GRExprEngine::VisitCast(CastExpr *CastE, Expr *Ex, ExplodedNode *Pred,
ExplodedNodeSet &Dst, bool asLValue) {
ExplodedNodeSet S1;
QualType T = CastE->getType();
QualType ExTy = Ex->getType();
@ -2191,14 +2191,6 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, ExplodedNode* Pred,
ExplodedNodeSet S2;
CheckerVisit(CastE, S2, S1, true);
// Check for casting to "void".
if (T->isVoidType()) {
assert(!asLValue);
for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I)
Dst.Add(*I);
return;
}
// If we are evaluating the cast in an lvalue context, we implicitly want
// the cast to evaluate to a location.
if (asLValue) {
@ -2207,13 +2199,51 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, ExplodedNode* Pred,
ExTy = Ctx.getPointerType(Ctx.getCanonicalType(ExTy));
}
for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I) {
ExplodedNode* N = *I;
const GRState* state = GetState(N);
SVal V = state->getSVal(Ex);
const SValuator::CastResult &Res = SVator.EvalCast(V, state, T, ExTy);
state = Res.getState()->BindExpr(CastE, Res.getSVal());
MakeNode(Dst, CastE, N, state);
switch (CastE->getCastKind()) {
case CastExpr::CK_ToVoid:
assert(!asLValue);
for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I)
Dst.Add(*I);
return;
case CastExpr::CK_NoOp:
case CastExpr::CK_FunctionToPointerDecay:
for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I) {
// Copy the SVal of Ex to CastE.
ExplodedNode *N = *I;
const GRState *state = GetState(N);
SVal V = state->getSVal(Ex);
state = state->BindExpr(CastE, V);
MakeNode(Dst, CastE, N, state);
}
return;
case CastExpr::CK_Unknown:
case CastExpr::CK_ArrayToPointerDecay:
case CastExpr::CK_BitCast:
case CastExpr::CK_IntegralCast:
case CastExpr::CK_IntegralToPointer:
case CastExpr::CK_PointerToIntegral:
case CastExpr::CK_IntegralToFloating:
case CastExpr::CK_FloatingToIntegral:
case CastExpr::CK_FloatingCast:
case CastExpr::CK_AnyPointerToObjCPointerCast:
case CastExpr::CK_AnyPointerToBlockPointerCast:
case CastExpr::CK_DerivedToBase:
// Delegate to SValuator to process.
for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I) {
ExplodedNode* N = *I;
const GRState* state = GetState(N);
SVal V = state->getSVal(Ex);
const SValuator::CastResult &Res = SVator.EvalCast(V, state, T, ExTy);
state = Res.getState()->BindExpr(CastE, Res.getSVal());
MakeNode(Dst, CastE, N, state);
}
return;
default:
llvm::errs() << "Cast kind " << CastE->getCastKind() << " not handled.\n";
assert(0);
}
}
@ -2952,13 +2982,13 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
// Perform a load (the LHS). This performs the checks for
// null dereferences, and so on.
ExplodedNodeSet Tmp3;
ExplodedNodeSet Tmp4;
SVal location = state->getSVal(LHS);
EvalLoad(Tmp3, LHS, *I2, state, location);
EvalLoad(Tmp4, LHS, *I2, state, location);
for (ExplodedNodeSet::iterator I3=Tmp3.begin(), E3=Tmp3.end(); I3!=E3;
++I3) {
state = GetState(*I3);
for (ExplodedNodeSet::iterator I4=Tmp4.begin(), E4=Tmp4.end(); I4!=E4;
++I4) {
state = GetState(*I4);
SVal V = state->getSVal(LHS);
// Get the computation type.
@ -3008,7 +3038,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
llvm::tie(state, LHSVal) = SVator.EvalCast(Result, state, LTy, CTy);
}
EvalStore(Tmp3, B, LHS, *I3, state->BindExpr(B, Result),
EvalStore(Tmp3, B, LHS, *I4, state->BindExpr(B, Result),
location, LHSVal);
}
}

View File

@ -72,7 +72,7 @@ class MallocChecker : public CheckerVisitor<MallocChecker> {
private:
void MallocMem(CheckerContext &C, const CallExpr *CE);
const GRState *MallocMemAux(CheckerContext &C, const CallExpr *CE,
const GRState *state);
const Expr *SizeEx, const GRState *state);
void FreeMem(CheckerContext &C, const CallExpr *CE);
const GRState *FreeMemAux(CheckerContext &C, const CallExpr *CE,
const GRState *state);
@ -136,18 +136,24 @@ bool MallocChecker::EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
}
void MallocChecker::MallocMem(CheckerContext &C, const CallExpr *CE) {
const GRState *state = MallocMemAux(C, CE, C.getState());
const GRState *state = MallocMemAux(C, CE, CE->getArg(0), C.getState());
C.addTransition(state);
}
const GRState *MallocChecker::MallocMemAux(CheckerContext &C,
const CallExpr *CE,
const Expr *SizeEx,
const GRState *state) {
unsigned Count = C.getNodeBuilder().getCurrentBlockCount();
ValueManager &ValMgr = C.getValueManager();
SVal RetVal = ValMgr.getConjuredSymbolVal(NULL, CE, CE->getType(), Count);
SVal Size = state->getSVal(SizeEx);
state = C.getEngine().getStoreManager().setExtent(state, RetVal.getAsRegion(),
Size);
state = state->BindExpr(CE, RetVal);
SymbolRef Sym = RetVal.getAsLocSymbol();
@ -170,7 +176,12 @@ const GRState *MallocChecker::FreeMemAux(CheckerContext &C, const CallExpr *CE,
assert(Sym);
const RefState *RS = state->get<RegionState>(Sym);
assert(RS);
// If the symbol has not been tracked, return. This is possible when free() is
// called on a pointer that does not get its pointee directly from malloc().
// Full support of this requires inter-procedural analysis.
if (!RS)
return state;
// Check double free.
if (RS->isReleased()) {
@ -211,7 +222,7 @@ void MallocChecker::ReallocMem(CheckerContext &C, const CallExpr *CE) {
if (Sym)
stateEqual = stateEqual->set<RegionState>(Sym, RefState::getReleased(CE));
const GRState *stateMalloc = MallocMemAux(C, CE, stateEqual);
const GRState *stateMalloc = MallocMemAux(C, CE, CE->getArg(1), stateEqual);
C.addTransition(stateMalloc);
}
@ -232,7 +243,8 @@ void MallocChecker::ReallocMem(CheckerContext &C, const CallExpr *CE) {
const GRState *stateFree = FreeMemAux(C, CE, stateSizeNotZero);
if (stateFree) {
// FIXME: We should copy the content of the original buffer.
const GRState *stateRealloc = MallocMemAux(C, CE, stateFree);
const GRState *stateRealloc = MallocMemAux(C, CE, CE->getArg(1),
stateFree);
C.addTransition(stateRealloc);
}
}

View File

@ -21,6 +21,7 @@
#include "clang/Analysis/Analyses/LiveVariables.h"
#include "clang/Analysis/Support/Optional.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/AST/CharUnits.h"
#include "llvm/ADT/ImmutableMap.h"
#include "llvm/ADT/ImmutableList.h"
@ -423,9 +424,9 @@ class RegionStoreManager : public StoreManager {
// Region "extents".
//===------------------------------------------------------------------===//
const GRState *setExtent(const GRState *state, const MemRegion* R, SVal Extent);
const GRState *setExtent(const GRState *state,const MemRegion* R,SVal Extent);
DefinedOrUnknownSVal getSizeInElements(const GRState *state,
const MemRegion* R);
const MemRegion* R, QualType EleTy);
//===------------------------------------------------------------------===//
// Utility methods.
@ -767,7 +768,8 @@ SVal RegionStoreManager::getLValueElement(QualType elementType, SVal Offset,
//===----------------------------------------------------------------------===//
DefinedOrUnknownSVal RegionStoreManager::getSizeInElements(const GRState *state,
const MemRegion *R) {
const MemRegion *R,
QualType EleTy) {
switch (R->getKind()) {
case MemRegion::CXXThisRegionKind:
@ -793,10 +795,25 @@ DefinedOrUnknownSVal RegionStoreManager::getSizeInElements(const GRState *state,
case MemRegion::ElementRegionKind:
case MemRegion::FieldRegionKind:
case MemRegion::ObjCIvarRegionKind:
case MemRegion::SymbolicRegionKind:
case MemRegion::CXXObjectRegionKind:
return UnknownVal();
case MemRegion::SymbolicRegionKind: {
const SVal *Size = state->get<RegionExtents>(R);
if (!Size)
return UnknownVal();
const nonloc::ConcreteInt *CI = dyn_cast<nonloc::ConcreteInt>(Size);
if (!CI)
return UnknownVal();
CharUnits RegionSize =
CharUnits::fromQuantity(CI->getValue().getSExtValue());
CharUnits EleSize = getContext().getTypeSizeInChars(EleTy);
assert(RegionSize % EleSize == 0);
return ValMgr.makeIntVal(RegionSize / EleSize, false);
}
case MemRegion::StringRegionKind: {
const StringLiteral* Str = cast<StringRegion>(R)->getStringLiteral();
// We intentionally made the size value signed because it participates in

View File

@ -65,7 +65,8 @@ void ReturnPointerRangeChecker::PreVisitReturnStmt(CheckerContext &C,
// into a common place.
DefinedOrUnknownSVal NumElements
= C.getStoreManager().getSizeInElements(state, ER->getSuperRegion());
= C.getStoreManager().getSizeInElements(state, ER->getSuperRegion(),
ER->getValueType(C.getASTContext()));
const GRState *StInBound = state->AssumeInBound(Idx, NumElements, true);
const GRState *StOutBound = state->AssumeInBound(Idx, NumElements, false);

View File

@ -17,10 +17,13 @@ BUILD_ARCHIVE = 1
CXXFLAGS = -fno-rtti
CPPFLAGS += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include
ifdef CLANG_VENDOR
CPPFLAGS += -DCLANG_VENDOR='"$(CLANG_VENDOR) "'
endif
include $(LEVEL)/Makefile.common
SVN_REVISION := $(shell cd $(PROJ_SRC_DIR)/../.. && svnversion)
SVN_REVISION := $(shell $(LLVM_SRC_ROOT)/utils/GetSourceVersion $(PROJ_SRC_DIR)/../..)
CPP.Defines += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include \
-DSVN_REVISION='"$(SVN_REVISION)"'

View File

@ -16,9 +16,9 @@
#include "clang/Basic/Builtins.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/MacroBuilder.h"
#include "clang/Basic/TargetBuiltins.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Frontend/Utils.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/STLExtras.h"

View File

@ -10,13 +10,17 @@
// This file defines several version-related utility functions for Clang.
//
//===----------------------------------------------------------------------===//
#include "clang/Basic/Version.h"
#include "llvm/Support/raw_ostream.h"
#include <cstring>
#include <cstdlib>
using namespace std;
namespace clang {
const char *getClangSubversionPath() {
llvm::StringRef getClangRepositoryPath() {
static const char *Path = 0;
if (Path)
return Path;
@ -41,13 +45,43 @@ const char *getClangSubversionPath() {
}
unsigned getClangSubversionRevision() {
llvm::StringRef getClangRevision() {
#ifndef SVN_REVISION
// Subversion was not available at build time?
return 0;
return llvm::StringRef();
#else
return strtol(SVN_REVISION, 0, 10);
static std::string revision;
if (revision.empty()) {
llvm::raw_string_ostream OS(revision);
OS << strtol(SVN_REVISION, 0, 10);
}
return revision;
#endif
}
llvm::StringRef getClangFullRepositoryVersion() {
static std::string buf;
if (buf.empty()) {
llvm::raw_string_ostream OS(buf);
OS << getClangRepositoryPath();
llvm::StringRef Revision = getClangRevision();
if (!Revision.empty())
OS << ' ' << Revision;
}
return buf;
}
const char *getClangFullVersion() {
static std::string buf;
if (buf.empty()) {
llvm::raw_string_ostream OS(buf);
#ifdef CLANG_VENDOR
OS << CLANG_VENDOR;
#endif
OS << "clang version " CLANG_VERSION_STRING " ("
<< getClangFullRepositoryVersion() << ')';
}
return buf.c_str();
}
} // end namespace clang

View File

@ -18,7 +18,6 @@
#include "llvm/Module.h"
#include "llvm/Target/TargetData.h"
#include <algorithm>
#include <cstdio>
using namespace clang;
using namespace CodeGen;
@ -221,11 +220,10 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
C = llvm::ConstantStruct::get(VMContext, Elts, false);
char Name[32];
sprintf(Name, "__block_holder_tmp_%d", CGM.getGlobalUniqueCount());
C = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true,
llvm::GlobalValue::InternalLinkage,
C, Name);
llvm::GlobalValue::InternalLinkage, C,
"__block_holder_tmp_" +
llvm::Twine(CGM.getGlobalUniqueCount()));
QualType BPT = BE->getType();
C = llvm::ConstantExpr::getBitCast(C, ConvertType(BPT));
return C;
@ -747,13 +745,12 @@ CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr,
const CGFunctionInfo &FI =
CGM.getTypes().getFunctionInfo(ResultType, Args);
std::string Name = std::string("__") + Info.Name + "_block_invoke_";
CodeGenTypes &Types = CGM.getTypes();
const llvm::FunctionType *LTy = Types.GetFunctionType(FI, IsVariadic);
llvm::Function *Fn =
llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
Name,
llvm::Twine("__") + Info.Name + "_block_invoke_",
&CGM.getModule());
CGM.SetInternalFunctionAttributes(BD, Fn, FI);
@ -875,14 +872,12 @@ GenerateCopyHelperFunction(bool BlockHasCopyDispose, const llvm::StructType *T,
// FIXME: We'd like to put these into a mergable by content, with
// internal linkage.
std::string Name = std::string("__copy_helper_block_");
CodeGenTypes &Types = CGM.getTypes();
const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false);
llvm::Function *Fn =
llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
Name,
&CGM.getModule());
"__copy_helper_block_", &CGM.getModule());
IdentifierInfo *II
= &CGM.getContext().Idents.get("__copy_helper_block_");
@ -958,14 +953,12 @@ GenerateDestroyHelperFunction(bool BlockHasCopyDispose,
// FIXME: We'd like to put these into a mergable by content, with
// internal linkage.
std::string Name = std::string("__destroy_helper_block_");
CodeGenTypes &Types = CGM.getTypes();
const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false);
llvm::Function *Fn =
llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
Name,
&CGM.getModule());
"__destroy_helper_block_", &CGM.getModule());
IdentifierInfo *II
= &CGM.getContext().Idents.get("__destroy_helper_block_");
@ -1042,7 +1035,6 @@ GeneratebyrefCopyHelperFunction(const llvm::Type *T, int flag) {
const CGFunctionInfo &FI =
CGM.getTypes().getFunctionInfo(R, Args);
std::string Name = std::string("__Block_byref_id_object_copy_");
CodeGenTypes &Types = CGM.getTypes();
const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false);
@ -1050,8 +1042,7 @@ GeneratebyrefCopyHelperFunction(const llvm::Type *T, int flag) {
// internal linkage.
llvm::Function *Fn =
llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
Name,
&CGM.getModule());
"__Block_byref_id_object_copy_", &CGM.getModule());
IdentifierInfo *II
= &CGM.getContext().Idents.get("__Block_byref_id_object_copy_");
@ -1107,7 +1098,6 @@ BlockFunction::GeneratebyrefDestroyHelperFunction(const llvm::Type *T,
const CGFunctionInfo &FI =
CGM.getTypes().getFunctionInfo(R, Args);
std::string Name = std::string("__Block_byref_id_object_dispose_");
CodeGenTypes &Types = CGM.getTypes();
const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false);
@ -1115,7 +1105,7 @@ BlockFunction::GeneratebyrefDestroyHelperFunction(const llvm::Type *T,
// internal linkage.
llvm::Function *Fn =
llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
Name,
"__Block_byref_id_object_dispose_",
&CGM.getModule());
IdentifierInfo *II

View File

@ -72,6 +72,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
switch (BuiltinID) {
default: break; // Handle intrinsics and libm functions below.
case Builtin::BI__builtin___CFStringMakeConstantString:
case Builtin::BI__builtin___NSStringMakeConstantString:
return RValue::get(CGM.EmitConstantExpr(E, E->getType(), 0));
case Builtin::BI__builtin_stdarg_start:
case Builtin::BI__builtin_va_start:
@ -556,6 +557,18 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
return RValue::get(0);
}
case Builtin::BI__builtin_llvm_memory_barrier: {
Value *C[5] = {
EmitScalarExpr(E->getArg(0)),
EmitScalarExpr(E->getArg(1)),
EmitScalarExpr(E->getArg(2)),
EmitScalarExpr(E->getArg(3)),
EmitScalarExpr(E->getArg(4))
};
Builder.CreateCall(CGM.getIntrinsic(Intrinsic::memory_barrier), C, C + 5);
return RValue::get(0);
}
// Library functions with special handling.
case Builtin::BIsqrt:
case Builtin::BIsqrtf:

View File

@ -394,10 +394,8 @@ void CodeGenFunction::EmitClassAggrCopyAssignment(llvm::Value *Dest,
if (BitwiseAssign)
EmitAggregateCopy(Dest, Src, Ty);
else {
bool hasCopyAssign = BaseClassDecl->hasConstCopyAssignment(getContext(),
MD);
assert(hasCopyAssign && "EmitClassAggrCopyAssignment - No user assign");
(void)hasCopyAssign;
BaseClassDecl->hasConstCopyAssignment(getContext(), MD);
assert(MD && "EmitClassAggrCopyAssignment - No user assign");
const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
const llvm::Type *LTy =
CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD),
@ -410,8 +408,10 @@ void CodeGenFunction::EmitClassAggrCopyAssignment(llvm::Value *Dest,
MD->getThisType(getContext())));
// Push the Src ptr.
CallArgs.push_back(std::make_pair(RValue::get(Src),
MD->getParamDecl(0)->getType()));
QualType SrcTy = MD->getParamDecl(0)->getType();
RValue SrcValue = SrcTy->isReferenceType() ? RValue::get(Src) :
RValue::getAggregate(Src);
CallArgs.push_back(std::make_pair(SrcValue, SrcTy));
QualType ResultType = MD->getType()->getAs<FunctionType>()->getResultType();
EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs),
Callee, ReturnValueSlot(), CallArgs, MD);
@ -531,10 +531,8 @@ void CodeGenFunction::EmitClassCopyAssignment(
}
const CXXMethodDecl *MD = 0;
bool ConstCopyAssignOp = BaseClassDecl->hasConstCopyAssignment(getContext(),
MD);
assert(ConstCopyAssignOp && "EmitClassCopyAssignment - missing copy assign");
(void)ConstCopyAssignOp;
BaseClassDecl->hasConstCopyAssignment(getContext(), MD);
assert(MD && "EmitClassCopyAssignment - missing copy assign");
const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
const llvm::Type *LTy =
@ -548,8 +546,10 @@ void CodeGenFunction::EmitClassCopyAssignment(
MD->getThisType(getContext())));
// Push the Src ptr.
CallArgs.push_back(std::make_pair(RValue::get(Src),
MD->getParamDecl(0)->getType()));
QualType SrcTy = MD->getParamDecl(0)->getType();
RValue SrcValue = SrcTy->isReferenceType() ? RValue::get(Src) :
RValue::getAggregate(Src);
CallArgs.push_back(std::make_pair(SrcValue, SrcTy));
QualType ResultType =
MD->getType()->getAs<FunctionType>()->getResultType();
EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs),

View File

@ -460,58 +460,15 @@ llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty,
return DbgTy;
}
/// CreateType - get structure or union type.
llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty,
llvm::DICompileUnit Unit) {
RecordDecl *Decl = Ty->getDecl();
unsigned Tag;
if (Decl->isStruct())
Tag = llvm::dwarf::DW_TAG_structure_type;
else if (Decl->isUnion())
Tag = llvm::dwarf::DW_TAG_union_type;
else {
assert(Decl->isClass() && "Unknown RecordType!");
Tag = llvm::dwarf::DW_TAG_class_type;
}
SourceManager &SM = CGM.getContext().getSourceManager();
// Get overall information about the record type for the debug info.
PresumedLoc PLoc = SM.getPresumedLoc(Decl->getLocation());
llvm::DICompileUnit DefUnit;
unsigned Line = 0;
if (!PLoc.isInvalid()) {
DefUnit = getOrCreateCompileUnit(Decl->getLocation());
Line = PLoc.getLine();
}
// Records and classes and unions can all be recursive. To handle them, we
// first generate a debug descriptor for the struct as a forward declaration.
// Then (if it is a definition) we go through and get debug info for all of
// its members. Finally, we create a descriptor for the complete type (which
// may refer to the forward decl if the struct is recursive) and replace all
// uses of the forward declaration with the final definition.
llvm::DICompositeType FwdDecl =
DebugFactory.CreateCompositeType(Tag, Unit, Decl->getName(),
DefUnit, Line, 0, 0, 0, 0,
llvm::DIType(), llvm::DIArray());
// If this is just a forward declaration, return it.
if (!Decl->getDefinition(CGM.getContext()))
return FwdDecl;
llvm::TrackingVH<llvm::MDNode> FwdDeclNode = FwdDecl.getNode();
// Otherwise, insert it into the TypeCache so that recursive uses will find
// it.
TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = FwdDecl.getNode();
// Convert all the elements.
llvm::SmallVector<llvm::DIDescriptor, 16> EltTys;
const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(Decl);
/// CollectRecordFields - A helper function to collect debug info for
/// record fields. This is used while creating debug info entry for a Record.
void CGDebugInfo::
CollectRecordFields(const RecordDecl *Decl,
llvm::DICompileUnit Unit,
llvm::SmallVectorImpl<llvm::DIDescriptor> &EltTys) {
unsigned FieldNo = 0;
SourceManager &SM = CGM.getContext().getSourceManager();
const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(Decl);
for (RecordDecl::field_iterator I = Decl->field_begin(),
E = Decl->field_end();
I != E; ++I, ++FieldNo) {
@ -560,6 +517,125 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty,
FieldOffset, 0, FieldTy);
EltTys.push_back(FieldTy);
}
}
/// CollectCXXMemberFunctions - A helper function to collect debug info for
/// C++ member functions.This is used while creating debug info entry for
/// a Record.
void CGDebugInfo::
CollectCXXMemberFunctions(const CXXRecordDecl *Decl,
llvm::DICompileUnit Unit,
llvm::SmallVectorImpl<llvm::DIDescriptor> &EltTys,
llvm::DICompositeType &RecordTy) {
SourceManager &SM = CGM.getContext().getSourceManager();
for(CXXRecordDecl::method_iterator I = Decl->method_begin(),
E = Decl->method_end(); I != E; ++I) {
CXXMethodDecl *Method = *I;
llvm::StringRef MethodName;
llvm::StringRef MethodLinkageName;
llvm::DIType MethodTy = getOrCreateType(Method->getType(), Unit);
if (CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(Method)) {
if (CDecl->isImplicit())
continue;
MethodName = Decl->getName();
// FIXME : Find linkage name.
} else if (CXXDestructorDecl *DDecl = dyn_cast<CXXDestructorDecl>(Method)) {
if (DDecl->isImplicit())
continue;
MethodName = getFunctionName(Method);
// FIXME : Find linkage name.
} else {
if (Method->isImplicit())
continue;
// regular method
MethodName = getFunctionName(Method);
MethodLinkageName = CGM.getMangledName(Method);
}
// Get the location for the method.
SourceLocation MethodDefLoc = Method->getLocation();
PresumedLoc PLoc = SM.getPresumedLoc(MethodDefLoc);
llvm::DICompileUnit MethodDefUnit;
unsigned MethodLine = 0;
if (!PLoc.isInvalid()) {
MethodDefUnit = getOrCreateCompileUnit(MethodDefLoc);
MethodLine = PLoc.getLine();
}
llvm::DISubprogram SP =
DebugFactory.CreateSubprogram(RecordTy , MethodName, MethodName,
MethodLinkageName,
MethodDefUnit, MethodLine,
MethodTy, false,
Method->isThisDeclarationADefinition(),
0 /*Virtuality*/, 0 /*VIndex*/,
llvm::DIType() /*ContainingType*/);
if (Method->isThisDeclarationADefinition())
SPCache[cast<FunctionDecl>(Method)] = llvm::WeakVH(SP.getNode());
EltTys.push_back(SP);
}
}
/// CreateType - get structure or union type.
llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty,
llvm::DICompileUnit Unit) {
RecordDecl *Decl = Ty->getDecl();
unsigned Tag;
if (Decl->isStruct())
Tag = llvm::dwarf::DW_TAG_structure_type;
else if (Decl->isUnion())
Tag = llvm::dwarf::DW_TAG_union_type;
else {
assert(Decl->isClass() && "Unknown RecordType!");
Tag = llvm::dwarf::DW_TAG_class_type;
}
SourceManager &SM = CGM.getContext().getSourceManager();
// Get overall information about the record type for the debug info.
PresumedLoc PLoc = SM.getPresumedLoc(Decl->getLocation());
llvm::DICompileUnit DefUnit;
unsigned Line = 0;
if (!PLoc.isInvalid()) {
DefUnit = getOrCreateCompileUnit(Decl->getLocation());
Line = PLoc.getLine();
}
// Records and classes and unions can all be recursive. To handle them, we
// first generate a debug descriptor for the struct as a forward declaration.
// Then (if it is a definition) we go through and get debug info for all of
// its members. Finally, we create a descriptor for the complete type (which
// may refer to the forward decl if the struct is recursive) and replace all
// uses of the forward declaration with the final definition.
// A Decl->getName() is not unique. However, the debug info descriptors
// are uniqued. The debug info descriptor describing record's context is
// necessary to keep two Decl's descriptor unique if their name match.
// FIXME : Use RecordDecl's DeclContext's descriptor. As a temp. step
// use type's name in FwdDecl.
std::string STy = QualType(Ty, 0).getAsString();
llvm::DICompositeType FwdDecl =
DebugFactory.CreateCompositeType(Tag, Unit, STy.c_str(),
DefUnit, Line, 0, 0, 0, 0,
llvm::DIType(), llvm::DIArray());
// If this is just a forward declaration, return it.
if (!Decl->getDefinition(CGM.getContext()))
return FwdDecl;
llvm::TrackingVH<llvm::MDNode> FwdDeclNode = FwdDecl.getNode();
// Otherwise, insert it into the TypeCache so that recursive uses will find
// it.
TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = FwdDecl.getNode();
// Convert all the elements.
llvm::SmallVector<llvm::DIDescriptor, 16> EltTys;
CollectRecordFields(Decl, Unit, EltTys);
if (CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(Decl))
CollectCXXMemberFunctions(CXXDecl, Unit, EltTys, FwdDecl);
llvm::DIArray Elements =
DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size());
@ -1000,18 +1076,27 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType,
const Decl *D = GD.getDecl();
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
// If there is a DISubprogram for this function available then use it.
llvm::DenseMap<const FunctionDecl *, llvm::WeakVH>::iterator
FI = SPCache.find(FD);
if (FI != SPCache.end()) {
llvm::DISubprogram SP(dyn_cast_or_null<llvm::MDNode>(FI->second));
if (!SP.isNull() && SP.isSubprogram() && SP.isDefinition()) {
RegionStack.push_back(SP.getNode());
return;
}
}
Name = getFunctionName(FD);
if (Name[0] == '\01')
if (!Name.empty() && Name[0] == '\01')
Name = Name.substr(1);
// Use mangled name as linkage name for c/c++ functions.
LinkageName = CGM.getMangledName(GD);
} else {
// Use llvm function name as linkage name.
Name = Fn->getName();
// Skip the asm prefix if it exists.
if (Name[0] == '\01')
Name = Name.substr(1);
LinkageName = Name;
if (!Name.empty() && Name[0] == '\01')
Name = Name.substr(1);
}
// It is expected that CurLoc is set before using EmitFunctionStart.

View File

@ -64,6 +64,8 @@ class CGDebugInfo {
/// constructed on demand. For example, C++ destructors, C++ operators etc..
llvm::BumpPtrAllocator FunctionNames;
llvm::DenseMap<const FunctionDecl *, llvm::WeakVH> SPCache;
/// Helper functions for getOrCreateType.
llvm::DIType CreateType(const BuiltinType *Ty, llvm::DICompileUnit U);
llvm::DIType CreateType(const ComplexType *Ty, llvm::DICompileUnit U);
@ -85,6 +87,12 @@ class CGDebugInfo {
llvm::DIType CreatePointerLikeType(unsigned Tag,
const Type *Ty, QualType PointeeTy,
llvm::DICompileUnit U);
void CollectCXXMemberFunctions(const CXXRecordDecl *Decl,
llvm::DICompileUnit U,
llvm::SmallVectorImpl<llvm::DIDescriptor> &E,
llvm::DICompositeType &T);
void CollectRecordFields(const RecordDecl *Decl, llvm::DICompileUnit U,
llvm::SmallVectorImpl<llvm::DIDescriptor> &E);
public:
CGDebugInfo(CodeGenModule &CGM);
~CGDebugInfo();

View File

@ -742,7 +742,8 @@ class ConstExprEmitter :
return CGM.GetAddrOfConstantStringFromObjCEncode(cast<ObjCEncodeExpr>(E));
case Expr::ObjCStringLiteralClass: {
ObjCStringLiteral* SL = cast<ObjCStringLiteral>(E);
llvm::Constant *C = CGM.getObjCRuntime().GenerateConstantString(SL);
llvm::Constant *C =
CGM.getObjCRuntime().GenerateConstantString(SL->getString());
return llvm::ConstantExpr::getBitCast(C, ConvertType(E->getType()));
}
case Expr::PredefinedExprClass: {
@ -764,11 +765,18 @@ class ConstExprEmitter :
}
case Expr::CallExprClass: {
CallExpr* CE = cast<CallExpr>(E);
if (CE->isBuiltinCall(CGM.getContext()) !=
Builtin::BI__builtin___CFStringMakeConstantString)
unsigned builtin = CE->isBuiltinCall(CGM.getContext());
if (builtin !=
Builtin::BI__builtin___CFStringMakeConstantString &&
builtin !=
Builtin::BI__builtin___NSStringMakeConstantString)
break;
const Expr *Arg = CE->getArg(0)->IgnoreParenCasts();
const StringLiteral *Literal = cast<StringLiteral>(Arg);
if (builtin ==
Builtin::BI__builtin___NSStringMakeConstantString) {
return CGM.getObjCRuntime().GenerateConstantString(Literal);
}
// FIXME: need to deal with UCN conversion issues.
return CGM.GetAddrOfConstantCFString(Literal);
}

View File

@ -26,7 +26,8 @@ using namespace CodeGen;
/// Emits an instance of NSConstantString representing the object.
llvm::Value *CodeGenFunction::EmitObjCStringLiteral(const ObjCStringLiteral *E)
{
llvm::Constant *C = CGM.getObjCRuntime().GenerateConstantString(E);
llvm::Constant *C =
CGM.getObjCRuntime().GenerateConstantString(E->getString());
// FIXME: This bitcast should just be made an invariant on the Runtime.
return llvm::ConstantExpr::getBitCast(C, ConvertType(E->getType()));
}

View File

@ -124,7 +124,7 @@ class CGObjCGNU : public CodeGen::CGObjCRuntime {
void EmitClassRef(const std::string &className);
public:
CGObjCGNU(CodeGen::CodeGenModule &cgm);
virtual llvm::Constant *GenerateConstantString(const ObjCStringLiteral *);
virtual llvm::Constant *GenerateConstantString(const StringLiteral *);
virtual CodeGen::RValue
GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
QualType ResultType,
@ -240,15 +240,23 @@ CGObjCGNU::CGObjCGNU(CodeGen::CodeGenModule &cgm)
Zeros[1] = Zeros[0];
NULLPtr = llvm::ConstantPointerNull::get(PtrToInt8Ty);
// Get the selector Type.
SelectorTy = cast<llvm::PointerType>(
CGM.getTypes().ConvertType(CGM.getContext().getObjCSelType()));
QualType selTy = CGM.getContext().getObjCSelType();
if (QualType() == selTy) {
SelectorTy = PtrToInt8Ty;
} else {
SelectorTy = cast<llvm::PointerType>(CGM.getTypes().ConvertType(selTy));
}
PtrToIntTy = llvm::PointerType::getUnqual(IntTy);
PtrTy = PtrToInt8Ty;
// Object type
ASTIdTy = CGM.getContext().getObjCIdType();
IdTy = cast<llvm::PointerType>(CGM.getTypes().ConvertType(ASTIdTy));
if (QualType() == ASTIdTy) {
IdTy = PtrToInt8Ty;
} else {
IdTy = cast<llvm::PointerType>(CGM.getTypes().ConvertType(ASTIdTy));
}
// IMP type
std::vector<const llvm::Type*> IMPArgs;
@ -348,12 +356,9 @@ llvm::Constant *CGObjCGNU::MakeGlobal(const llvm::ArrayType *Ty,
}
/// Generate an NSConstantString object.
//TODO: In case there are any crazy people still using the GNU runtime without
//an OpenStep implementation, this should let them select their own class for
//constant strings.
llvm::Constant *CGObjCGNU::GenerateConstantString(const ObjCStringLiteral *SL) {
std::string Str(SL->getString()->getStrData(),
SL->getString()->getByteLength());
llvm::Constant *CGObjCGNU::GenerateConstantString(const StringLiteral *SL) {
std::string Str(SL->getStrData(), SL->getByteLength());
std::vector<llvm::Constant*> Ivars;
Ivars.push_back(NULLPtr);
Ivars.push_back(MakeConstantString(Str));

View File

@ -952,7 +952,7 @@ class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
CGObjCCommonMac(CodeGen::CodeGenModule &cgm) :
CGM(cgm), VMContext(cgm.getLLVMContext()) { }
virtual llvm::Constant *GenerateConstantString(const ObjCStringLiteral *SL);
virtual llvm::Constant *GenerateConstantString(const StringLiteral *SL);
virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
const ObjCContainerDecl *CD=0);
@ -1454,8 +1454,8 @@ llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl
*/
llvm::Constant *CGObjCCommonMac::GenerateConstantString(
const ObjCStringLiteral *SL) {
return CGM.GetAddrOfConstantCFString(SL->getString());
const StringLiteral *SL) {
return CGM.GetAddrOfConstantCFString(SL);
}
/// Generates a message send where the super is the receiver. This is

View File

@ -106,7 +106,7 @@ class CGObjCRuntime {
const ObjCMethodDecl *Method) = 0;
/// Generate a constant string object.
virtual llvm::Constant *GenerateConstantString(const ObjCStringLiteral *) = 0;
virtual llvm::Constant *GenerateConstantString(const StringLiteral *) = 0;
/// Generate a category. A category contains a list of methods (and
/// accompanying metadata) and a list of protocols.

398
lib/CodeGen/CGVTT.cpp Normal file
View File

@ -0,0 +1,398 @@
//===--- CGVTT.cpp - Emit LLVM Code for C++ VTTs --------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This contains code dealing with C++ code generation of VTTs (vtable tables).
//
//===----------------------------------------------------------------------===//
#include "CodeGenModule.h"
#include "clang/AST/RecordLayout.h"
using namespace clang;
using namespace CodeGen;
#define D1(x)
namespace {
class VTTBuilder {
/// Inits - The list of values built for the VTT.
std::vector<llvm::Constant *> &Inits;
/// Class - The most derived class that this vtable is being built for.
const CXXRecordDecl *Class;
CodeGenModule &CGM; // Per-module state.
llvm::SmallSet<const CXXRecordDecl *, 32> SeenVBase;
/// BLayout - Layout for the most derived class that this vtable is being
/// built for.
const ASTRecordLayout &BLayout;
CGVtableInfo::AddrMap_t &AddressPoints;
// vtbl - A pointer to the vtable for Class.
llvm::Constant *ClassVtbl;
llvm::LLVMContext &VMContext;
/// SeenVBasesInSecondary - The seen virtual bases when building the
/// secondary virtual pointers.
llvm::SmallPtrSet<const CXXRecordDecl *, 32> SeenVBasesInSecondary;
llvm::DenseMap<const CXXRecordDecl *, uint64_t> SubVTTIndicies;
bool GenerateDefinition;
llvm::DenseMap<BaseSubobject, llvm::Constant *> CtorVtables;
llvm::DenseMap<std::pair<const CXXRecordDecl *, BaseSubobject>, uint64_t>
CtorVtableAddressPoints;
llvm::Constant *getCtorVtable(const BaseSubobject &Base) {
if (!GenerateDefinition)
return 0;
llvm::Constant *&CtorVtable = CtorVtables[Base];
if (!CtorVtable) {
// Build the vtable.
CGVtableInfo::CtorVtableInfo Info
= CGM.getVtableInfo().getCtorVtable(Class, Base);
CtorVtable = Info.Vtable;
// Add the address points for this base.
for (CGVtableInfo::AddressPointsMapTy::const_iterator I =
Info.AddressPoints.begin(), E = Info.AddressPoints.end();
I != E; ++I) {
uint64_t &AddressPoint =
CtorVtableAddressPoints[std::make_pair(Base.getBase(), I->first)];
// Check if we already have the address points for this base.
if (AddressPoint)
break;
// Otherwise, insert it.
AddressPoint = I->second;
}
}
return CtorVtable;
}
/// BuildVtablePtr - Build up a referene to the given secondary vtable
llvm::Constant *BuildVtablePtr(llvm::Constant *Vtable,
const CXXRecordDecl *VtableClass,
const CXXRecordDecl *RD,
uint64_t Offset) {
if (!GenerateDefinition)
return 0;
uint64_t AddressPoint;
if (VtableClass != Class) {
// We have a ctor vtable, look for the address point in the ctor vtable
// address points.
AddressPoint =
CtorVtableAddressPoints[std::make_pair(VtableClass,
BaseSubobject(RD, Offset))];
} else {
AddressPoint =
(*AddressPoints[VtableClass])[std::make_pair(RD, Offset)];
}
// FIXME: We can never have 0 address point. Do this for now so gepping
// retains the same structure. Later we'll just assert.
if (AddressPoint == 0)
AddressPoint = 1;
D1(printf("XXX address point for %s in %s layout %s at offset %d was %d\n",
RD->getNameAsCString(), VtblClass->getNameAsCString(),
Class->getNameAsCString(), (int)Offset, (int)AddressPoint));
llvm::Value *Idxs[] = {
llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), 0),
llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), AddressPoint)
};
llvm::Constant *Init =
llvm::ConstantExpr::getInBoundsGetElementPtr(Vtable, Idxs, 2);
const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
return llvm::ConstantExpr::getBitCast(Init, Int8PtrTy);
}
/// Secondary - Add the secondary vtable pointers to Inits. Offset is the
/// current offset in bits to the object we're working on.
void Secondary(const CXXRecordDecl *RD, llvm::Constant *vtbl,
const CXXRecordDecl *VtblClass, uint64_t Offset=0,
bool MorallyVirtual=false) {
if (RD->getNumVBases() == 0 && ! MorallyVirtual)
return;
for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
e = RD->bases_end(); i != e; ++i) {
const CXXRecordDecl *Base =
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
// We only want to visit each virtual base once.
if (i->isVirtual() && SeenVBasesInSecondary.count(Base))
continue;
// Itanium C++ ABI 2.6.2:
// Secondary virtual pointers are present for all bases with either
// virtual bases or virtual function declarations overridden along a
// virtual path.
//
// If the base class is not dynamic, we don't want to add it, nor any
// of its base classes.
if (!Base->isDynamicClass())
continue;
const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
bool NonVirtualPrimaryBase;
NonVirtualPrimaryBase = !PrimaryBaseWasVirtual && Base == PrimaryBase;
bool BaseMorallyVirtual = MorallyVirtual | i->isVirtual();
uint64_t BaseOffset;
if (!i->isVirtual()) {
const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
BaseOffset = Offset + Layout.getBaseClassOffset(Base);
} else
BaseOffset = BLayout.getVBaseClassOffset(Base);
llvm::Constant *subvtbl = vtbl;
const CXXRecordDecl *subVtblClass = VtblClass;
if ((Base->getNumVBases() || BaseMorallyVirtual)
&& !NonVirtualPrimaryBase) {
llvm::Constant *init;
if (BaseMorallyVirtual || VtblClass == Class)
init = BuildVtablePtr(vtbl, VtblClass, Base, BaseOffset);
else {
init = getCtorVtable(BaseSubobject(Base, BaseOffset));
subvtbl = init;
subVtblClass = Base;
init = BuildVtablePtr(init, Class, Base, BaseOffset);
}
Inits.push_back(init);
}
if (i->isVirtual())
SeenVBasesInSecondary.insert(Base);
Secondary(Base, subvtbl, subVtblClass, BaseOffset, BaseMorallyVirtual);
}
}
/// BuiltVTT - Add the VTT to Inits. Offset is the offset in bits to the
/// currnet object we're working on.
void BuildVTT(const CXXRecordDecl *RD, uint64_t Offset, bool MorallyVirtual) {
// Itanium C++ ABI 2.6.2:
// An array of virtual table addresses, called the VTT, is declared for
// each class type that has indirect or direct virtual base classes.
if (RD->getNumVBases() == 0)
return;
// Remember the sub-VTT index.
SubVTTIndicies[RD] = Inits.size();
llvm::Constant *Vtable;
const CXXRecordDecl *VtableClass;
// First comes the primary virtual table pointer...
if (MorallyVirtual) {
Vtable = ClassVtbl;
VtableClass = Class;
} else {
Vtable = getCtorVtable(BaseSubobject(RD, Offset));
VtableClass = RD;
}
llvm::Constant *Init = BuildVtablePtr(Vtable, VtableClass, RD, Offset);
Inits.push_back(Init);
// then the secondary VTTs....
SecondaryVTTs(RD, Offset, MorallyVirtual);
// Make sure to clear the set of seen virtual bases.
SeenVBasesInSecondary.clear();
// and last the secondary vtable pointers.
Secondary(RD, Vtable, VtableClass, Offset, MorallyVirtual);
}
/// SecondaryVTTs - Add the secondary VTTs to Inits. The secondary VTTs are
/// built from each direct non-virtual proper base that requires a VTT in
/// declaration order.
void SecondaryVTTs(const CXXRecordDecl *RD, uint64_t Offset=0,
bool MorallyVirtual=false) {
for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
e = RD->bases_end(); i != e; ++i) {
const CXXRecordDecl *Base =
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
if (i->isVirtual())
continue;
const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
uint64_t BaseOffset = Offset + Layout.getBaseClassOffset(Base);
BuildVTT(Base, BaseOffset, MorallyVirtual);
}
}
/// VirtualVTTs - Add the VTT for each proper virtual base in inheritance
/// graph preorder.
void VirtualVTTs(const CXXRecordDecl *RD) {
for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
e = RD->bases_end(); i != e; ++i) {
const CXXRecordDecl *Base =
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
if (i->isVirtual() && !SeenVBase.count(Base)) {
SeenVBase.insert(Base);
uint64_t BaseOffset = BLayout.getVBaseClassOffset(Base);
BuildVTT(Base, BaseOffset, false);
}
VirtualVTTs(Base);
}
}
public:
VTTBuilder(std::vector<llvm::Constant *> &inits, const CXXRecordDecl *c,
CodeGenModule &cgm, bool GenerateDefinition)
: Inits(inits), Class(c), CGM(cgm),
BLayout(cgm.getContext().getASTRecordLayout(c)),
AddressPoints(*cgm.getVtableInfo().AddressPoints[c]),
VMContext(cgm.getModule().getContext()),
GenerateDefinition(GenerateDefinition) {
// First comes the primary virtual table pointer for the complete class...
ClassVtbl = GenerateDefinition ? CGM.getVtableInfo().getVtable(Class) : 0;
llvm::Constant *Init = BuildVtablePtr(ClassVtbl, Class, Class, 0);
Inits.push_back(Init);
// then the secondary VTTs...
SecondaryVTTs(Class);
// Make sure to clear the set of seen virtual bases.
SeenVBasesInSecondary.clear();
// then the secondary vtable pointers...
Secondary(Class, ClassVtbl, Class);
// and last, the virtual VTTs.
VirtualVTTs(Class);
}
llvm::DenseMap<const CXXRecordDecl *, uint64_t> &getSubVTTIndicies() {
return SubVTTIndicies;
}
};
}
llvm::GlobalVariable *
CGVtableInfo::GenerateVTT(llvm::GlobalVariable::LinkageTypes Linkage,
bool GenerateDefinition,
const CXXRecordDecl *RD) {
// Only classes that have virtual bases need a VTT.
if (RD->getNumVBases() == 0)
return 0;
llvm::SmallString<256> OutName;
CGM.getMangleContext().mangleCXXVTT(RD, OutName);
llvm::StringRef Name = OutName.str();
D1(printf("vtt %s\n", RD->getNameAsCString()));
llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
if (GV == 0 || GV->isDeclaration()) {
const llvm::Type *Int8PtrTy =
llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
std::vector<llvm::Constant *> inits;
VTTBuilder b(inits, RD, CGM, GenerateDefinition);
const llvm::ArrayType *Type = llvm::ArrayType::get(Int8PtrTy, inits.size());
llvm::Constant *Init = 0;
if (GenerateDefinition)
Init = llvm::ConstantArray::get(Type, inits);
llvm::GlobalVariable *OldGV = GV;
GV = new llvm::GlobalVariable(CGM.getModule(), Type, /*isConstant=*/true,
Linkage, Init, Name);
CGM.setGlobalVisibility(GV, RD);
if (OldGV) {
GV->takeName(OldGV);
llvm::Constant *NewPtr =
llvm::ConstantExpr::getBitCast(GV, OldGV->getType());
OldGV->replaceAllUsesWith(NewPtr);
OldGV->eraseFromParent();
}
}
return GV;
}
CGVtableInfo::CtorVtableInfo
CGVtableInfo::getCtorVtable(const CXXRecordDecl *RD,
const BaseSubobject &Base) {
CtorVtableInfo Info;
Info.Vtable = GenerateVtable(llvm::GlobalValue::InternalLinkage,
/*GenerateDefinition=*/true,
RD, Base.getBase(), Base.getBaseOffset(),
Info.AddressPoints);
return Info;
}
llvm::GlobalVariable *CGVtableInfo::getVTT(const CXXRecordDecl *RD) {
return GenerateVTT(llvm::GlobalValue::ExternalLinkage,
/*GenerateDefinition=*/false, RD);
}
bool CGVtableInfo::needsVTTParameter(GlobalDecl GD) {
const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
// We don't have any virtual bases, just return early.
if (!MD->getParent()->getNumVBases())
return false;
// Check if we have a base constructor.
if (isa<CXXConstructorDecl>(MD) && GD.getCtorType() == Ctor_Base)
return true;
// Check if we have a base destructor.
if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base)
return true;
return false;
}
uint64_t CGVtableInfo::getSubVTTIndex(const CXXRecordDecl *RD,
const CXXRecordDecl *Base) {
ClassPairTy ClassPair(RD, Base);
SubVTTIndiciesTy::iterator I =
SubVTTIndicies.find(ClassPair);
if (I != SubVTTIndicies.end())
return I->second;
std::vector<llvm::Constant *> inits;
VTTBuilder Builder(inits, RD, CGM, /*GenerateDefinition=*/false);
for (llvm::DenseMap<const CXXRecordDecl *, uint64_t>::iterator I =
Builder.getSubVTTIndicies().begin(),
E = Builder.getSubVTTIndicies().end(); I != E; ++I) {
// Insert all indices.
ClassPairTy ClassPair(RD, I->first);
SubVTTIndicies.insert(std::make_pair(ClassPair, I->second));
}
I = SubVTTIndicies.find(ClassPair);
assert(I != SubVTTIndicies.end() && "Did not find index!");
return I->second;
}

View File

@ -232,8 +232,8 @@ class VtableBuilder {
return llvm::ConstantExpr::getBitCast(m, Ptr8Ty);
}
#define D1(x)
//#define D1(X) do { if (getenv("DEBUG")) { X; } } while (0)
//#define D1(x)
#define D1(X) do { if (getenv("DEBUG")) { X; } } while (0)
void GenerateVBaseOffsets(const CXXRecordDecl *RD, uint64_t Offset,
bool updateVBIndex, Index_t current_vbindex) {
@ -254,7 +254,7 @@ class VtableBuilder {
D1(printf(" vbase for %s at %d delta %d most derived %s\n",
Base->getNameAsCString(),
(int)-VCalls.size()-3, (int)BaseOffset,
Class->getNameAsCString()));
MostDerivedClass->getNameAsCString()));
}
// We also record offsets for non-virtual bases to closest enclosing
// virtual base. We do this so that we don't have to search
@ -376,13 +376,14 @@ class VtableBuilder {
CurrentVBaseOffset))
return;
D1(printf(" vfn for %s at %d\n",
dyn_cast<CXXMethodDecl>(GD.getDecl())->getNameAsCString(),
(int)Methods.size()));
// We didn't find an entry in the vtable that we could use, add a new
// entry.
Methods.AddMethod(GD);
D1(printf(" vfn for %s at %d\n", MD->getNameAsString().c_str(),
(int)Index[GD]));
VCallOffset[GD] = Offset/8;
if (MorallyVirtual) {
Index_t &idx = VCall[GD];
@ -392,7 +393,8 @@ class VtableBuilder {
idx = VCalls.size()+1;
VCalls.push_back(0);
D1(printf(" vcall for %s at %d with delta %d\n",
MD->getNameAsString().c_str(), (int)-VCalls.size()-3, 0));
dyn_cast<CXXMethodDecl>(GD.getDecl())->getNameAsCString(),
(int)-VCalls.size()-3, 0));
}
}
}
@ -429,12 +431,11 @@ class VtableBuilder {
continue;
const CXXRecordDecl *Base =
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
if (Base != PrimaryBase || PrimaryBaseWasVirtual) {
uint64_t o = Offset + Layout.getBaseClassOffset(Base);
StartNewTable();
GenerateVtableForBase(Base, o, MorallyVirtual, false,
CurrentVBaseOffset, Path);
}
uint64_t o = Offset + Layout.getBaseClassOffset(Base);
StartNewTable();
GenerateVtableForBase(Base, o, MorallyVirtual, false,
true, Base == PrimaryBase && !PrimaryBaseWasVirtual,
CurrentVBaseOffset, Path);
}
Path->pop_back();
}
@ -463,7 +464,7 @@ class VtableBuilder {
void AddAddressPoints(const CXXRecordDecl *RD, uint64_t Offset,
Index_t AddressPoint) {
D1(printf("XXX address point for %s in %s layout %s at offset %d is %d\n",
RD->getNameAsCString(), Class->getNameAsCString(),
RD->getNameAsCString(), MostDerivedClass->getNameAsCString(),
LayoutClass->getNameAsCString(), (int)Offset, (int)AddressPoint));
subAddressPoints[std::make_pair(RD, Offset)] = AddressPoint;
AddressPoints[BaseSubobject(RD, Offset)] = AddressPoint;
@ -480,7 +481,7 @@ class VtableBuilder {
BLayout.getVBaseClassOffset(RD) != Offset)
break;
D1(printf("XXX address point for %s in %s layout %s at offset %d is %d\n",
RD->getNameAsCString(), Class->getNameAsCString(),
RD->getNameAsCString(), MostDerivedClass->getNameAsCString(),
LayoutClass->getNameAsCString(), (int)Offset, (int)AddressPoint));
subAddressPoints[std::make_pair(RD, Offset)] = AddressPoint;
AddressPoints[BaseSubobject(RD, Offset)] = AddressPoint;
@ -491,6 +492,7 @@ class VtableBuilder {
void FinishGenerateVtable(const CXXRecordDecl *RD,
const ASTRecordLayout &Layout,
const CXXRecordDecl *PrimaryBase,
bool ForNPNVBases, bool WasPrimaryBase,
bool PrimaryBaseWasVirtual,
bool MorallyVirtual, int64_t Offset,
bool ForVirtualBase, int64_t CurrentVBaseOffset,
@ -503,23 +505,27 @@ class VtableBuilder {
StartNewTable();
extra = 0;
bool DeferVCalls = MorallyVirtual || ForVirtualBase;
int VCallInsertionPoint = VtableComponents.size();
if (!DeferVCalls) {
insertVCalls(VCallInsertionPoint);
} else
// FIXME: just for extra, or for all uses of VCalls.size post this?
extra = -VCalls.size();
Index_t AddressPoint = 0;
int VCallInsertionPoint = 0;
if (!ForNPNVBases || !WasPrimaryBase) {
bool DeferVCalls = MorallyVirtual || ForVirtualBase;
VCallInsertionPoint = VtableComponents.size();
if (!DeferVCalls) {
insertVCalls(VCallInsertionPoint);
} else
// FIXME: just for extra, or for all uses of VCalls.size post this?
extra = -VCalls.size();
// Add the offset to top.
VtableComponents.push_back(BuildVtable ? wrap(-((Offset-LayoutOffset)/8)) : 0);
// Add the offset to top.
VtableComponents.push_back(BuildVtable ? wrap(-((Offset-LayoutOffset)/8)) : 0);
// Add the RTTI information.
VtableComponents.push_back(rtti);
// Add the RTTI information.
VtableComponents.push_back(rtti);
Index_t AddressPoint = VtableComponents.size();
AddressPoint = VtableComponents.size();
AppendMethodsToVtable();
AppendMethodsToVtable();
}
// and then the non-virtual bases.
NonVirtualBases(RD, Layout, PrimaryBase, PrimaryBaseWasVirtual,
@ -537,7 +543,8 @@ class VtableBuilder {
insertVCalls(VCallInsertionPoint);
}
AddAddressPoints(RD, Offset, AddressPoint);
if (!ForNPNVBases || !WasPrimaryBase)
AddAddressPoints(RD, Offset, AddressPoint);
if (alloc) {
delete Path;
@ -557,13 +564,13 @@ class VtableBuilder {
// vtables are composed from the chain of primaries.
if (PrimaryBase && !PrimaryBaseWasVirtual) {
D1(printf(" doing primaries for %s most derived %s\n",
RD->getNameAsCString(), Class->getNameAsCString()));
RD->getNameAsCString(), MostDerivedClass->getNameAsCString()));
Primaries(PrimaryBase, PrimaryBaseWasVirtual|MorallyVirtual, Offset,
updateVBIndex, current_vbindex, CurrentVBaseOffset);
}
D1(printf(" doing vcall entries for %s most derived %s\n",
RD->getNameAsCString(), Class->getNameAsCString()));
RD->getNameAsCString(), MostDerivedClass->getNameAsCString()));
// And add the virtuals for the class to the primary vtable.
AddMethods(RD, MorallyVirtual, Offset, CurrentVBaseOffset);
@ -589,7 +596,7 @@ class VtableBuilder {
}
D1(printf(" doing primaries for %s most derived %s\n",
RD->getNameAsCString(), Class->getNameAsCString()));
RD->getNameAsCString(), MostDerivedClass->getNameAsCString()));
VBPrimaries(PrimaryBase, PrimaryBaseWasVirtual|MorallyVirtual, Offset,
updateVBIndex, current_vbindex, PrimaryBaseWasVirtual,
@ -597,7 +604,7 @@ class VtableBuilder {
}
D1(printf(" doing vbase entries for %s most derived %s\n",
RD->getNameAsCString(), Class->getNameAsCString()));
RD->getNameAsCString(), MostDerivedClass->getNameAsCString()));
GenerateVBaseOffsets(RD, Offset, updateVBIndex, current_vbindex);
if (RDisVirtualBase || bottom) {
@ -609,6 +616,8 @@ class VtableBuilder {
void GenerateVtableForBase(const CXXRecordDecl *RD, int64_t Offset = 0,
bool MorallyVirtual = false,
bool ForVirtualBase = false,
bool ForNPNVBases = false,
bool WasPrimaryBase = true,
int CurrentVBaseOffset = 0,
Path_t *Path = 0) {
if (!RD->isDynamicClass())
@ -626,20 +635,22 @@ class VtableBuilder {
extra = 0;
D1(printf("building entries for base %s most derived %s\n",
RD->getNameAsCString(), Class->getNameAsCString()));
RD->getNameAsCString(), MostDerivedClass->getNameAsCString()));
if (ForVirtualBase)
extra = VCalls.size();
VBPrimaries(RD, MorallyVirtual, Offset, !ForVirtualBase, 0, ForVirtualBase,
CurrentVBaseOffset, true);
if (!ForNPNVBases || !WasPrimaryBase) {
VBPrimaries(RD, MorallyVirtual, Offset, !ForVirtualBase, 0,
ForVirtualBase, CurrentVBaseOffset, true);
if (Path)
OverrideMethods(Path, MorallyVirtual, Offset, CurrentVBaseOffset);
if (Path)
OverrideMethods(Path, MorallyVirtual, Offset, CurrentVBaseOffset);
}
FinishGenerateVtable(RD, Layout, PrimaryBase, PrimaryBaseWasVirtual,
MorallyVirtual, Offset, ForVirtualBase,
CurrentVBaseOffset, Path);
FinishGenerateVtable(RD, Layout, PrimaryBase, ForNPNVBases, WasPrimaryBase,
PrimaryBaseWasVirtual, MorallyVirtual, Offset,
ForVirtualBase, CurrentVBaseOffset, Path);
}
void GenerateVtableForVBases(const CXXRecordDecl *RD,
@ -665,9 +676,9 @@ class VtableBuilder {
int64_t BaseOffset = BLayout.getVBaseClassOffset(Base);
int64_t CurrentVBaseOffset = BaseOffset;
D1(printf("vtable %s virtual base %s\n",
Class->getNameAsCString(), Base->getNameAsCString()));
GenerateVtableForBase(Base, BaseOffset, true, true, CurrentVBaseOffset,
Path);
MostDerivedClass->getNameAsCString(), Base->getNameAsCString()));
GenerateVtableForBase(Base, BaseOffset, true, true, false,
true, CurrentVBaseOffset, Path);
}
int64_t BaseOffset;
if (i->isVirtual())
@ -823,14 +834,14 @@ bool VtableBuilder::OverrideMethod(GlobalDecl GD, bool MorallyVirtual,
VCalls.push_back(0);
D1(printf(" vcall for %s at %d with delta %d most derived %s\n",
MD->getNameAsString().c_str(), (int)-idx-3,
(int)VCalls[idx-1], Class->getNameAsCString()));
(int)VCalls[idx-1], MostDerivedClass->getNameAsCString()));
} else {
NonVirtualOffset[GD] = NonVirtualOffset[OGD];
VCallOffset[GD] = VCallOffset[OGD];
VCalls[idx-1] = -VCallOffset[OGD] + OverrideOffset/8;
D1(printf(" vcall patch for %s at %d with delta %d most derived %s\n",
MD->getNameAsString().c_str(), (int)-idx-3,
(int)VCalls[idx-1], Class->getNameAsCString()));
(int)VCalls[idx-1], MostDerivedClass->getNameAsCString()));
}
int64_t NonVirtualAdjustment = NonVirtualOffset[GD];
int64_t VirtualAdjustment =
@ -1205,284 +1216,6 @@ CGVtableInfo::GenerateVtable(llvm::GlobalVariable::LinkageTypes Linkage,
return GV;
}
namespace {
class VTTBuilder {
/// Inits - The list of values built for the VTT.
std::vector<llvm::Constant *> &Inits;
/// Class - The most derived class that this vtable is being built for.
const CXXRecordDecl *Class;
CodeGenModule &CGM; // Per-module state.
llvm::SmallSet<const CXXRecordDecl *, 32> SeenVBase;
/// BLayout - Layout for the most derived class that this vtable is being
/// built for.
const ASTRecordLayout &BLayout;
CGVtableInfo::AddrMap_t &AddressPoints;
// vtbl - A pointer to the vtable for Class.
llvm::Constant *ClassVtbl;
llvm::LLVMContext &VMContext;
llvm::DenseMap<const CXXRecordDecl *, uint64_t> SubVTTIndicies;
bool GenerateDefinition;
llvm::DenseMap<BaseSubobject, llvm::Constant *> CtorVtables;
llvm::DenseMap<std::pair<const CXXRecordDecl *, BaseSubobject>, uint64_t>
CtorVtableAddressPoints;
llvm::Constant *getCtorVtable(const BaseSubobject &Base) {
if (!GenerateDefinition)
return 0;
llvm::Constant *&CtorVtable = CtorVtables[Base];
if (!CtorVtable) {
// Build the vtable.
CGVtableInfo::CtorVtableInfo Info
= CGM.getVtableInfo().getCtorVtable(Class, Base);
CtorVtable = Info.Vtable;
// Add the address points for this base.
for (CGVtableInfo::AddressPointsMapTy::const_iterator I =
Info.AddressPoints.begin(), E = Info.AddressPoints.end();
I != E; ++I) {
uint64_t &AddressPoint =
CtorVtableAddressPoints[std::make_pair(Base.getBase(), I->first)];
// Check if we already have the address points for this base.
if (AddressPoint)
break;
// Otherwise, insert it.
AddressPoint = I->second;
}
}
return CtorVtable;
}
/// BuildVtablePtr - Build up a referene to the given secondary vtable
llvm::Constant *BuildVtablePtr(llvm::Constant *Vtable,
const CXXRecordDecl *VtableClass,
const CXXRecordDecl *RD,
uint64_t Offset) {
int64_t AddressPoint =
(*AddressPoints[VtableClass])[std::make_pair(RD, Offset)];
// FIXME: We can never have 0 address point. Do this for now so gepping
// retains the same structure. Later we'll just assert.
if (AddressPoint == 0)
AddressPoint = 1;
D1(printf("XXX address point for %s in %s layout %s at offset %d was %d\n",
RD->getNameAsCString(), VtblClass->getNameAsCString(),
Class->getNameAsCString(), (int)Offset, (int)AddressPoint));
llvm::Value *Idxs[] = {
llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), 0),
llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), AddressPoint)
};
llvm::Constant *Init =
llvm::ConstantExpr::getInBoundsGetElementPtr(Vtable, Idxs, 2);
const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
return llvm::ConstantExpr::getBitCast(Init, Int8PtrTy);
}
/// Secondary - Add the secondary vtable pointers to Inits. Offset is the
/// current offset in bits to the object we're working on.
void Secondary(const CXXRecordDecl *RD, llvm::Constant *vtbl,
const CXXRecordDecl *VtblClass, uint64_t Offset=0,
bool MorallyVirtual=false) {
if (RD->getNumVBases() == 0 && ! MorallyVirtual)
return;
for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
e = RD->bases_end(); i != e; ++i) {
const CXXRecordDecl *Base =
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
bool NonVirtualPrimaryBase;
NonVirtualPrimaryBase = !PrimaryBaseWasVirtual && Base == PrimaryBase;
bool BaseMorallyVirtual = MorallyVirtual | i->isVirtual();
uint64_t BaseOffset;
if (!i->isVirtual()) {
const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
BaseOffset = Offset + Layout.getBaseClassOffset(Base);
} else
BaseOffset = BLayout.getVBaseClassOffset(Base);
llvm::Constant *subvtbl = vtbl;
const CXXRecordDecl *subVtblClass = VtblClass;
if ((Base->getNumVBases() || BaseMorallyVirtual)
&& !NonVirtualPrimaryBase) {
// FIXME: Slightly too many of these for __ZTT8test8_B2
llvm::Constant *init;
if (BaseMorallyVirtual)
init = GenerateDefinition ?
BuildVtablePtr(vtbl, VtblClass, RD, Offset) : 0;
else {
init = GenerateDefinition ?
getCtorVtable(BaseSubobject(Base, BaseOffset)) : 0;
subvtbl = init;
subVtblClass = Base;
init = GenerateDefinition ?
BuildVtablePtr(init, Class, Base, BaseOffset) : 0;
}
Inits.push_back(init);
}
Secondary(Base, subvtbl, subVtblClass, BaseOffset, BaseMorallyVirtual);
}
}
/// BuiltVTT - Add the VTT to Inits. Offset is the offset in bits to the
/// currnet object we're working on.
void BuildVTT(const CXXRecordDecl *RD, uint64_t Offset, bool MorallyVirtual) {
if (RD->getNumVBases() == 0 && !MorallyVirtual)
return;
llvm::Constant *Vtable;
const CXXRecordDecl *VtableClass;
// First comes the primary virtual table pointer...
if (MorallyVirtual) {
Vtable = GenerateDefinition ? ClassVtbl : 0;
VtableClass = Class;
} else {
Vtable = GenerateDefinition ?
getCtorVtable(BaseSubobject(RD, Offset)) : 0;
VtableClass = RD;
}
llvm::Constant *Init = GenerateDefinition ?
BuildVtablePtr(Vtable, VtableClass, RD, Offset) : 0;
Inits.push_back(Init);
// then the secondary VTTs....
SecondaryVTTs(RD, Offset, MorallyVirtual);
// and last the secondary vtable pointers.
Secondary(RD, Vtable, VtableClass, Offset, MorallyVirtual);
}
/// SecondaryVTTs - Add the secondary VTTs to Inits. The secondary VTTs are
/// built from each direct non-virtual proper base that requires a VTT in
/// declaration order.
void SecondaryVTTs(const CXXRecordDecl *RD, uint64_t Offset=0,
bool MorallyVirtual=false) {
for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
e = RD->bases_end(); i != e; ++i) {
const CXXRecordDecl *Base =
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
if (i->isVirtual())
continue;
const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
uint64_t BaseOffset = Offset + Layout.getBaseClassOffset(Base);
// Remember the sub-VTT index.
SubVTTIndicies[Base] = Inits.size();
BuildVTT(Base, BaseOffset, MorallyVirtual);
}
}
/// VirtualVTTs - Add the VTT for each proper virtual base in inheritance
/// graph preorder.
void VirtualVTTs(const CXXRecordDecl *RD) {
for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
e = RD->bases_end(); i != e; ++i) {
const CXXRecordDecl *Base =
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
if (i->isVirtual() && !SeenVBase.count(Base)) {
// Remember the sub-VTT index.
SubVTTIndicies[Base] = Inits.size();
SeenVBase.insert(Base);
uint64_t BaseOffset = BLayout.getVBaseClassOffset(Base);
BuildVTT(Base, BaseOffset, true);
}
VirtualVTTs(Base);
}
}
public:
VTTBuilder(std::vector<llvm::Constant *> &inits, const CXXRecordDecl *c,
CodeGenModule &cgm, bool GenerateDefinition)
: Inits(inits), Class(c), CGM(cgm),
BLayout(cgm.getContext().getASTRecordLayout(c)),
AddressPoints(*cgm.getVtableInfo().AddressPoints[c]),
VMContext(cgm.getModule().getContext()),
GenerateDefinition(GenerateDefinition) {
// First comes the primary virtual table pointer for the complete class...
ClassVtbl = CGM.getVtableInfo().getVtable(Class);
llvm::Constant *Init = GenerateDefinition ?
BuildVtablePtr(ClassVtbl, Class, Class, 0) : 0;
Inits.push_back(Init);
// then the secondary VTTs...
SecondaryVTTs(Class);
// then the secondary vtable pointers...
Secondary(Class, ClassVtbl, Class);
// and last, the virtual VTTs.
VirtualVTTs(Class);
}
llvm::DenseMap<const CXXRecordDecl *, uint64_t> &getSubVTTIndicies() {
return SubVTTIndicies;
}
};
}
llvm::GlobalVariable *
CGVtableInfo::GenerateVTT(llvm::GlobalVariable::LinkageTypes Linkage,
bool GenerateDefinition,
const CXXRecordDecl *RD) {
// Only classes that have virtual bases need a VTT.
if (RD->getNumVBases() == 0)
return 0;
llvm::SmallString<256> OutName;
CGM.getMangleContext().mangleCXXVTT(RD, OutName);
llvm::StringRef Name = OutName.str();
D1(printf("vtt %s\n", RD->getNameAsCString()));
llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
if (GV == 0 || GV->isDeclaration()) {
const llvm::Type *Int8PtrTy =
llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
std::vector<llvm::Constant *> inits;
VTTBuilder b(inits, RD, CGM, GenerateDefinition);
const llvm::ArrayType *Type = llvm::ArrayType::get(Int8PtrTy, inits.size());
llvm::Constant *Init = 0;
if (GenerateDefinition)
Init = llvm::ConstantArray::get(Type, inits);
llvm::GlobalVariable *OldGV = GV;
GV = new llvm::GlobalVariable(CGM.getModule(), Type, /*isConstant=*/true,
Linkage, Init, Name);
CGM.setGlobalVisibility(GV, RD);
if (OldGV) {
GV->takeName(OldGV);
llvm::Constant *NewPtr =
llvm::ConstantExpr::getBitCast(GV, OldGV->getType());
OldGV->replaceAllUsesWith(NewPtr);
OldGV->eraseFromParent();
}
}
return GV;
}
void CGVtableInfo::GenerateClassData(llvm::GlobalVariable::LinkageTypes Linkage,
const CXXRecordDecl *RD) {
llvm::GlobalVariable *&Vtable = Vtables[RD];
@ -1510,25 +1243,6 @@ llvm::GlobalVariable *CGVtableInfo::getVtable(const CXXRecordDecl *RD) {
return Vtable;
}
CGVtableInfo::CtorVtableInfo
CGVtableInfo::getCtorVtable(const CXXRecordDecl *RD,
const BaseSubobject &Base) {
CtorVtableInfo Info;
Info.Vtable = GenerateVtable(llvm::GlobalValue::InternalLinkage,
/*GenerateDefinition=*/true,
RD, Base.getBase(), Base.getBaseOffset(),
Info.AddressPoints);
return Info;
}
llvm::GlobalVariable *CGVtableInfo::getVTT(const CXXRecordDecl *RD) {
return GenerateVTT(llvm::GlobalValue::ExternalLinkage,
/*GenerateDefinition=*/false, RD);
}
void CGVtableInfo::MaybeEmitVtable(GlobalDecl GD) {
const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
const CXXRecordDecl *RD = MD->getParent();
@ -1562,47 +1276,3 @@ void CGVtableInfo::MaybeEmitVtable(GlobalDecl GD) {
}
}
bool CGVtableInfo::needsVTTParameter(GlobalDecl GD) {
const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
// We don't have any virtual bases, just return early.
if (!MD->getParent()->getNumVBases())
return false;
// Check if we have a base constructor.
if (isa<CXXConstructorDecl>(MD) && GD.getCtorType() == Ctor_Base)
return true;
// Check if we have a base destructor.
if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base)
return true;
return false;
}
uint64_t CGVtableInfo::getSubVTTIndex(const CXXRecordDecl *RD,
const CXXRecordDecl *Base) {
ClassPairTy ClassPair(RD, Base);
SubVTTIndiciesTy::iterator I =
SubVTTIndicies.find(ClassPair);
if (I != SubVTTIndicies.end())
return I->second;
std::vector<llvm::Constant *> inits;
VTTBuilder Builder(inits, RD, CGM, /*GenerateDefinition=*/false);
for (llvm::DenseMap<const CXXRecordDecl *, uint64_t>::iterator I =
Builder.getSubVTTIndicies().begin(),
E = Builder.getSubVTTIndicies().end(); I != E; ++I) {
// Insert all indices.
ClassPairTy ClassPair(RD, I->first);
SubVTTIndicies.insert(std::make_pair(ClassPair, I->second));
}
I = SubVTTIndicies.find(ClassPair);
assert(I != SubVTTIndicies.end() && "Did not find index!");
return I->second;
}

View File

@ -24,6 +24,7 @@ add_clang_library(clangCodeGen
CGStmt.cpp
CGTemporaries.cpp
CGVtable.cpp
CGVTT.cpp
CodeGenFunction.cpp
CodeGenModule.cpp
CodeGenTypes.cpp

View File

@ -67,6 +67,15 @@ CodeGenModule::~CodeGenModule() {
delete DebugInfo;
}
void CodeGenModule::createObjCRuntime() {
if (!Features.NeXTRuntime)
Runtime = CreateGNUObjCRuntime(*this);
else if (Features.ObjCNonFragileABI)
Runtime = CreateMacNonFragileABIObjCRuntime(*this);
else
Runtime = CreateMacObjCRuntime(*this);
}
void CodeGenModule::Release() {
EmitDeferred();
EmitCXXGlobalInitFunc();

View File

@ -161,6 +161,9 @@ class CodeGenModule : public BlockModule {
/// strings. This value has type int * but is actually an Obj-C class pointer.
llvm::Constant *CFConstantStringClassRef;
/// Lazily create the Objective-C runtime
void createObjCRuntime();
llvm::LLVMContext &VMContext;
public:
CodeGenModule(ASTContext &C, const CodeGenOptions &CodeGenOpts,
@ -174,7 +177,7 @@ class CodeGenModule : public BlockModule {
/// getObjCRuntime() - Return a reference to the configured
/// Objective-C runtime.
CGObjCRuntime &getObjCRuntime() {
assert(Runtime && "No Objective-C runtime has been configured.");
if (!Runtime) createObjCRuntime();
return *Runtime;
}

File diff suppressed because it is too large Load Diff

View File

@ -257,7 +257,7 @@ class DefaultABIInfo : public ABIInfo {
class DefaultTargetCodeGenInfo : public TargetCodeGenInfo {
public:
DefaultTargetCodeGenInfo():TargetCodeGenInfo(new DefaultABIInfo()) {};
DefaultTargetCodeGenInfo():TargetCodeGenInfo(new DefaultABIInfo()) {}
};
llvm::Value *DefaultABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
@ -320,7 +320,7 @@ class X86_32ABIInfo : public ABIInfo {
class X86_32TargetCodeGenInfo : public TargetCodeGenInfo {
public:
X86_32TargetCodeGenInfo(ASTContext &Context, bool d, bool p)
:TargetCodeGenInfo(new X86_32ABIInfo(Context, d, p)) {};
:TargetCodeGenInfo(new X86_32ABIInfo(Context, d, p)) {}
};
}
@ -619,7 +619,7 @@ class X86_64ABIInfo : public ABIInfo {
class X86_64TargetCodeGenInfo : public TargetCodeGenInfo {
public:
X86_64TargetCodeGenInfo():TargetCodeGenInfo(new X86_64ABIInfo()) {};
X86_64TargetCodeGenInfo():TargetCodeGenInfo(new X86_64ABIInfo()) {}
};
}
@ -1428,7 +1428,7 @@ class PIC16ABIInfo : public ABIInfo {
class PIC16TargetCodeGenInfo : public TargetCodeGenInfo {
public:
PIC16TargetCodeGenInfo():TargetCodeGenInfo(new PIC16ABIInfo()) {};
PIC16TargetCodeGenInfo():TargetCodeGenInfo(new PIC16ABIInfo()) {}
};
}
@ -1493,7 +1493,7 @@ class ARMABIInfo : public ABIInfo {
class ARMTargetCodeGenInfo : public TargetCodeGenInfo {
public:
ARMTargetCodeGenInfo(ARMABIInfo::ABIKind K)
:TargetCodeGenInfo(new ARMABIInfo(K)) {};
:TargetCodeGenInfo(new ARMABIInfo(K)) {}
};
}
@ -1754,7 +1754,7 @@ class SystemZABIInfo : public ABIInfo {
class SystemZTargetCodeGenInfo : public TargetCodeGenInfo {
public:
SystemZTargetCodeGenInfo():TargetCodeGenInfo(new SystemZABIInfo()) {};
SystemZTargetCodeGenInfo():TargetCodeGenInfo(new SystemZABIInfo()) {}
};
}
@ -1816,7 +1816,7 @@ namespace {
class MSP430TargetCodeGenInfo : public TargetCodeGenInfo {
public:
MSP430TargetCodeGenInfo():TargetCodeGenInfo(new DefaultABIInfo()) {};
MSP430TargetCodeGenInfo():TargetCodeGenInfo(new DefaultABIInfo()) {}
void SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
CodeGen::CodeGenModule &M) const;
};

View File

@ -34,7 +34,7 @@ namespace clang {
ABIInfo *Info;
public:
// WARNING: Acquires the ownership of ABIInfo.
TargetCodeGenInfo(ABIInfo *info = 0):Info(info) { };
TargetCodeGenInfo(ABIInfo *info = 0):Info(info) { }
virtual ~TargetCodeGenInfo();
/// getABIInfo() - Returns ABI info helper for the target.
@ -43,7 +43,7 @@ namespace clang {
/// SetTargetAttributes - Provides a convenient hook to handle extra
/// target-specific attributes for the given global.
virtual void SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
CodeGen::CodeGenModule &M) const { };
CodeGen::CodeGenModule &M) const { }
};
}

View File

@ -26,6 +26,7 @@
#include "clang/Basic/Version.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Path.h"
@ -66,6 +67,14 @@ Driver::Driver(llvm::StringRef _Name, llvm::StringRef _Dir,
CCCUseClangCXX = false;
}
// Compute the path to the resource directory.
llvm::sys::Path P(Dir);
P.eraseComponent(); // Remove /bin from foo/bin
P.appendComponent("lib");
P.appendComponent("clang");
P.appendComponent(CLANG_VERSION_STRING);
ResourceDir = P.str();
}
Driver::~Driver() {
@ -273,15 +282,7 @@ void Driver::PrintHelp(bool ShowHidden) const {
void Driver::PrintVersion(const Compilation &C, llvm::raw_ostream &OS) const {
// FIXME: The following handlers should use a callback mechanism, we don't
// know what the client would like to do.
#ifdef CLANG_VENDOR
OS << CLANG_VENDOR;
#endif
OS << "clang version " CLANG_VERSION_STRING " ("
<< getClangSubversionPath();
if (unsigned Revision = getClangSubversionRevision())
OS << " " << Revision;
OS << ")" << '\n';
OS << getClangFullVersion() << '\n';
const ToolChain &TC = C.getDefaultToolChain();
OS << "Target: " << TC.getTripleString() << '\n';
@ -675,7 +676,7 @@ void Driver::BuildActions(const ArgList &Args, ActionList &Actions) const {
}
// Build the pipeline for this file.
Action *Current = new InputAction(*InputArg, InputType);
llvm::OwningPtr<Action> Current(new InputAction(*InputArg, InputType));
for (unsigned i = 0; i != NumSteps; ++i) {
phases::ID Phase = types::getCompilationPhase(InputType, i);
@ -686,8 +687,7 @@ void Driver::BuildActions(const ArgList &Args, ActionList &Actions) const {
// Queue linker inputs.
if (Phase == phases::Link) {
assert(i + 1 == NumSteps && "linking must be final compilation step.");
LinkerInputs.push_back(Current);
Current = 0;
LinkerInputs.push_back(Current.take());
break;
}
@ -698,14 +698,14 @@ void Driver::BuildActions(const ArgList &Args, ActionList &Actions) const {
continue;
// Otherwise construct the appropriate action.
Current = ConstructPhaseAction(Args, Phase, Current);
Current.reset(ConstructPhaseAction(Args, Phase, Current.take()));
if (Current->getType() == types::TY_Nothing)
break;
}
// If we ended with something, add to the output list.
if (Current)
Actions.push_back(Current);
Actions.push_back(Current.take());
}
// Add a link action if necessary.

View File

@ -13,8 +13,5 @@ BUILD_ARCHIVE = 1
CXXFLAGS = -fno-rtti
CPPFLAGS += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include
ifdef CLANG_VENDOR
CPPFLAGS += -DCLANG_VENDOR='"$(CLANG_VENDOR) "'
endif
include $(LEVEL)/Makefile.common

View File

@ -47,6 +47,69 @@ Darwin::Darwin(const HostInfo &Host, const llvm::Triple& Triple,
IPhoneOSVersionMin = "3.0";
}
// FIXME: Can we tablegen this?
static const char *GetArmArchForMArch(llvm::StringRef Value) {
if (Value == "armv6k")
return "armv6";
if (Value == "armv5tej")
return "armv5";
if (Value == "xscale")
return "xscale";
if (Value == "armv4t")
return "armv4t";
if (Value == "armv7" || Value == "armv7-a" || Value == "armv7-r" ||
Value == "armv7-m" || Value == "armv7a" || Value == "armv7r" ||
Value == "armv7m")
return "armv7";
return 0;
}
// FIXME: Can we tablegen this?
static const char *GetArmArchForMCpu(llvm::StringRef Value) {
if (Value == "arm10tdmi" || Value == "arm1020t" || Value == "arm9e" ||
Value == "arm946e-s" || Value == "arm966e-s" ||
Value == "arm968e-s" || Value == "arm10e" ||
Value == "arm1020e" || Value == "arm1022e" || Value == "arm926ej-s" ||
Value == "arm1026ej-s")
return "armv5";
if (Value == "xscale")
return "xscale";
if (Value == "arm1136j-s" || Value == "arm1136jf-s" ||
Value == "arm1176jz-s" || Value == "arm1176jzf-s")
return "armv6";
if (Value == "cortex-a8" || Value == "cortex-r4" || Value == "cortex-m3")
return "armv7";
return 0;
}
llvm::StringRef Darwin::getDarwinArchName(const ArgList &Args) const {
switch (getTriple().getArch()) {
default:
return getArchName();
case llvm::Triple::arm: {
if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
if (const char *Arch = GetArmArchForMArch(A->getValue(Args)))
return Arch;
if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
if (const char *Arch = GetArmArchForMCpu(A->getValue(Args)))
return Arch;
return "arm";
}
}
}
DarwinGCC::DarwinGCC(const HostInfo &Host, const llvm::Triple& Triple,
const unsigned (&DarwinVersion)[3],
const unsigned (&_GCCVersion)[3], bool IsIPhoneOS)
@ -118,10 +181,6 @@ DarwinGCC::DarwinGCC(const HostInfo &Host, const llvm::Triple& Triple,
Path += ToolChainDir;
getProgramPaths().push_back(Path);
Path = getDriver().Dir;
Path += "/../libexec";
getProgramPaths().push_back(Path);
getProgramPaths().push_back(getDriver().Dir);
}
@ -235,13 +294,6 @@ DarwinClang::DarwinClang(const HostInfo &Host, const llvm::Triple& Triple,
bool IsIPhoneOS)
: Darwin(Host, Triple, DarwinVersion, IsIPhoneOS)
{
// Add the relative libexec dir (for clang-cc).
//
// FIXME: We should sink clang-cc into libexec/clang/<version>/.
std::string Path = getDriver().Dir;
Path += "/../libexec";
getProgramPaths().push_back(Path);
// We expect 'as', 'ld', etc. to be adjacent to our install dir.
getProgramPaths().push_back(getDriver().Dir);
}
@ -253,12 +305,10 @@ void DarwinClang::AddLinkSearchPathArgs(const ArgList &Args,
void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
// Check for static linking.
if (Args.hasArg(options::OPT_static)) {
// FIXME: We need to have compiler-rt available (perhaps as
// libclang_static.a) to link against.
// Darwin doesn't support real static executables, don't link any runtime
// libraries with -static.
if (Args.hasArg(options::OPT_static))
return;
}
// Reject -static-libgcc for now, we can deal with this when and if someone
// cares. This is useful in situations where someone wants to statically link
@ -269,12 +319,52 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
return;
}
// Otherwise link libSystem, which should have the support routines.
//
// FIXME: This is only true for 10.6 and beyond. Legacy support isn't
// critical, but it should work... we should just link in the static
// compiler-rt library.
// Otherwise link libSystem, then the dynamic runtime library, and finally any
// target specific static runtime library.
CmdArgs.push_back("-lSystem");
// Select the dynamic runtime library and the target specific static library.
const char *DarwinStaticLib = 0;
if (isIPhoneOS()) {
CmdArgs.push_back("-lgcc_s.1");
// We may need some static functions for armv6/thumb which are required to
// be in the same linkage unit as their caller.
if (getDarwinArchName(Args) == "armv6")
DarwinStaticLib = "libclang_rt.armv6.a";
} else {
unsigned MacosxVersionMin[3];
getMacosxVersionMin(Args, MacosxVersionMin);
// The dynamic runtime library was merged with libSystem for 10.6 and
// beyond; only 10.4 and 10.5 need an additional runtime library.
if (isMacosxVersionLT(MacosxVersionMin, 10, 5))
CmdArgs.push_back("-lgcc_s.10.4");
else if (isMacosxVersionLT(MacosxVersionMin, 10, 6))
CmdArgs.push_back("-lgcc_s.10.5");
// For OS X, we only need a static runtime library when targetting 10.4, to
// provide versions of the static functions which were omitted from
// 10.4.dylib.
if (isMacosxVersionLT(MacosxVersionMin, 10, 5))
DarwinStaticLib = "libclang_rt.10.4.a";
}
/// Add the target specific static library, if needed.
if (DarwinStaticLib) {
llvm::sys::Path P(getDriver().ResourceDir);
P.appendComponent("lib");
P.appendComponent("darwin");
P.appendComponent(DarwinStaticLib);
// For now, allow missing resource libraries to support developers who may
// not have compiler-rt checked out or integrated into their build.
if (!P.exists())
getDriver().Diag(clang::diag::warn_drv_missing_resource_library)
<< P.str();
else
CmdArgs.push_back(Args.MakeArgString(P.str()));
}
}
void Darwin::getMacosxVersionMin(const ArgList &Args,
@ -544,10 +634,6 @@ const char *Darwin::GetForcedPicModel() const {
Generic_GCC::Generic_GCC(const HostInfo &Host, const llvm::Triple& Triple)
: ToolChain(Host, Triple) {
std::string Path(getDriver().Dir);
Path += "/../libexec";
getProgramPaths().push_back(Path);
getProgramPaths().push_back(getDriver().Dir);
}
@ -684,11 +770,6 @@ Tool &FreeBSD::SelectTool(const Compilation &C, const JobAction &JA) const {
AuroraUX::AuroraUX(const HostInfo &Host, const llvm::Triple& Triple)
: Generic_GCC(Host, Triple) {
// Path mangling to find libexec
std::string Path(getDriver().Dir);
Path += "/../libexec";
getProgramPaths().push_back(Path);
getProgramPaths().push_back(getDriver().Dir);
getFilePaths().push_back(getDriver().Dir + "/../lib");
@ -753,10 +834,6 @@ DragonFly::DragonFly(const HostInfo &Host, const llvm::Triple& Triple)
: Generic_GCC(Host, Triple) {
// Path mangling to find libexec
std::string Path(getDriver().Dir);
Path += "/../libexec";
getProgramPaths().push_back(Path);
getProgramPaths().push_back(getDriver().Dir);
getFilePaths().push_back(getDriver().Dir + "/../lib");

View File

@ -85,6 +85,11 @@ class VISIBILITY_HIDDEN Darwin : public ToolChain {
Res[2] = DarwinVersion[1];
}
/// getDarwinArchName - Get the "Darwin" arch name for a particular compiler
/// invocation. For example, Darwin treats different ARM variations as
/// distinct architectures.
llvm::StringRef getDarwinArchName(const ArgList &Args) const;
/// getMacosxVersionMin - Get the effective -mmacosx-version-min, which is
/// either the -mmacosx-version-min, or the current version if unspecified.
void getMacosxVersionMin(const ArgList &Args, unsigned (&Res)[3]) const;

View File

@ -9,7 +9,6 @@
#include "Tools.h"
#include "clang/Basic/Version.h"
#include "clang/Driver/Action.h"
#include "clang/Driver/Arg.h"
#include "clang/Driver/ArgList.h"
@ -864,15 +863,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_nobuiltininc);
// Pass the path to compiler resource files.
//
// FIXME: Get this from a configuration object.
llvm::sys::Path P(D.Dir);
P.eraseComponent(); // Remove /bin from foo/bin
P.appendComponent("lib");
P.appendComponent("clang");
P.appendComponent(CLANG_VERSION_STRING);
CmdArgs.push_back("-resource-dir");
CmdArgs.push_back(Args.MakeArgString(P.str()));
CmdArgs.push_back(D.ResourceDir.c_str());
// Add preprocessing options like -I, -D, etc. if we are using the
// preprocessor.
@ -1857,87 +1849,17 @@ static bool isSourceSuffix(const char *Str) {
.Default(false);
}
// FIXME: Can we tablegen this?
static const char *GetArmArchForMArch(llvm::StringRef Value) {
if (Value == "armv6k")
return "armv6";
if (Value == "armv5tej")
return "armv5";
if (Value == "xscale")
return "xscale";
if (Value == "armv4t")
return "armv4t";
if (Value == "armv7" || Value == "armv7-a" || Value == "armv7-r" ||
Value == "armv7-m" || Value == "armv7a" || Value == "armv7r" ||
Value == "armv7m")
return "armv7";
return 0;
}
// FIXME: Can we tablegen this?
static const char *GetArmArchForMCpu(llvm::StringRef Value) {
if (Value == "arm10tdmi" || Value == "arm1020t" || Value == "arm9e" ||
Value == "arm946e-s" || Value == "arm966e-s" ||
Value == "arm968e-s" || Value == "arm10e" ||
Value == "arm1020e" || Value == "arm1022e" || Value == "arm926ej-s" ||
Value == "arm1026ej-s")
return "armv5";
if (Value == "xscale")
return "xscale";
if (Value == "arm1136j-s" || Value == "arm1136jf-s" ||
Value == "arm1176jz-s" || Value == "arm1176jzf-s")
return "armv6";
if (Value == "cortex-a8" || Value == "cortex-r4" || Value == "cortex-m3")
return "armv7";
return 0;
}
void darwin::DarwinTool::AddDarwinArch(const ArgList &Args,
ArgStringList &CmdArgs) const {
llvm::StringRef ArchName = getDarwinToolChain().getDarwinArchName(Args);
// Derived from darwin_arch spec.
CmdArgs.push_back("-arch");
CmdArgs.push_back(Args.MakeArgString(ArchName));
switch (getToolChain().getTriple().getArch()) {
default:
CmdArgs.push_back(Args.MakeArgString(getToolChain().getArchName()));
break;
case llvm::Triple::arm: {
if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
if (const char *Arch = GetArmArchForMArch(A->getValue(Args))) {
CmdArgs.push_back(Arch);
return;
}
}
if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
if (const char *Arch = GetArmArchForMCpu(A->getValue(Args))) {
CmdArgs.push_back(Arch);
return;
}
}
CmdArgs.push_back("arm");
// FIXME: Is this needed anymore?
if (ArchName == "arm")
CmdArgs.push_back("-force_cpusubtype_ALL");
return;
}
}
}
void darwin::DarwinTool::AddDarwinSubArch(const ArgList &Args,
ArgStringList &CmdArgs) const {
// Derived from darwin_subarch spec, not sure what the distinction
// exists for but at least for this chain it is the same.
AddDarwinArch(Args, CmdArgs);
}
void darwin::Link::AddLinkArgs(const ArgList &Args,
@ -1954,11 +1876,9 @@ void darwin::Link::AddLinkArgs(const ArgList &Args,
}
if (!Args.hasArg(options::OPT_dynamiclib)) {
if (Args.hasArg(options::OPT_force__cpusubtype__ALL)) {
AddDarwinArch(Args, CmdArgs);
CmdArgs.push_back("-force_cpusubtype_ALL");
} else
AddDarwinSubArch(Args, CmdArgs);
AddDarwinArch(Args, CmdArgs);
// FIXME: Why do this only on this path?
Args.AddLastArg(CmdArgs, options::OPT_force__cpusubtype__ALL);
Args.AddLastArg(CmdArgs, options::OPT_bundle);
Args.AddAllArgs(CmdArgs, options::OPT_bundle__loader);
@ -1992,11 +1912,7 @@ void darwin::Link::AddLinkArgs(const ArgList &Args,
Args.AddAllArgsTranslated(CmdArgs, options::OPT_current__version,
"-dylib_current_version");
if (Args.hasArg(options::OPT_force__cpusubtype__ALL)) {
AddDarwinArch(Args, CmdArgs);
// NOTE: We don't add -force_cpusubtype_ALL on this path. Ok.
} else
AddDarwinSubArch(Args, CmdArgs);
AddDarwinArch(Args, CmdArgs);
Args.AddAllArgsTranslated(CmdArgs, options::OPT_install__name,
"-dylib_install_name");

View File

@ -130,7 +130,6 @@ namespace darwin {
class VISIBILITY_HIDDEN DarwinTool : public Tool {
protected:
void AddDarwinArch(const ArgList &Args, ArgStringList &CmdArgs) const;
void AddDarwinSubArch(const ArgList &Args, ArgStringList &CmdArgs) const;
const toolchains::Darwin &getDarwinToolChain() const {
return reinterpret_cast<const toolchains::Darwin&>(getToolChain());

View File

@ -421,6 +421,11 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC,
Out << "<namespace alias> " << NAD->getNameAsString() << "\n";
break;
}
case Decl::ClassTemplate: {
ClassTemplateDecl *CTD = cast<ClassTemplateDecl>(*I);
Out << "<class template> " << CTD->getNameAsString() << '\n';
break;
}
default:
Out << "DeclKind: " << DK << '"' << I->getDeclKindName() << "\"\n";
assert(0 && "decl unhandled");

View File

@ -30,6 +30,7 @@
#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/Diagnostic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/System/Host.h"
#include "llvm/System/Path.h"
using namespace clang;
@ -103,11 +104,31 @@ const std::string &ASTUnit::getPCHFileName() {
ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename,
Diagnostic &Diags,
bool OnlyLocalDecls,
bool UseBumpAllocator) {
bool UseBumpAllocator,
RemappedFile *RemappedFiles,
unsigned NumRemappedFiles) {
llvm::OwningPtr<ASTUnit> AST(new ASTUnit(true));
AST->OnlyLocalDecls = OnlyLocalDecls;
AST->HeaderInfo.reset(new HeaderSearch(AST->getFileManager()));
for (unsigned I = 0; I != NumRemappedFiles; ++I) {
// Create the file entry for the file that we're mapping from.
const FileEntry *FromFile
= AST->getFileManager().getVirtualFile(RemappedFiles[I].first,
RemappedFiles[I].second->getBufferSize(),
0);
if (!FromFile) {
Diags.Report(diag::err_fe_remap_missing_from_file)
<< RemappedFiles[I].first;
continue;
}
// Override the contents of the "from" file with the contents of
// the "to" file.
AST->getSourceManager().overrideFileContents(FromFile,
RemappedFiles[I].second);
}
// Gather Info for preprocessor construction later on.
LangOptions LangInfo;
@ -289,7 +310,9 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin,
Diagnostic &Diags,
llvm::StringRef ResourceFilesPath,
bool OnlyLocalDecls,
bool UseBumpAllocator) {
bool UseBumpAllocator,
RemappedFile *RemappedFiles,
unsigned NumRemappedFiles) {
llvm::SmallVector<const char *, 16> Args;
Args.push_back("<clang>"); // FIXME: Remove dummy argument.
Args.insert(Args.end(), ArgBegin, ArgEnd);
@ -327,6 +350,11 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin,
(const char**) CCArgs.data()+CCArgs.size(),
Diags);
// Override any files that need remapping
for (unsigned I = 0; I != NumRemappedFiles; ++I)
CI.getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first,
RemappedFiles[I].second);
// Override the resources path.
CI.getHeaderSearchOpts().ResourceDir = ResourceFilesPath;

View File

@ -204,45 +204,47 @@ namespace llvm {
void AnalysisConsumer::HandleTopLevelSingleDecl(Decl *D) {
switch (D->getKind()) {
case Decl::Function: {
FunctionDecl* FD = cast<FunctionDecl>(D);
case Decl::Function: {
FunctionDecl* FD = cast<FunctionDecl>(D);
if (!Opts.AnalyzeSpecificFunction.empty() &&
Opts.AnalyzeSpecificFunction != FD->getIdentifier()->getName())
break;
Stmt* Body = FD->getBody();
if (Body) HandleCode(FD, Body, FunctionActions);
if (!Opts.AnalyzeSpecificFunction.empty() &&
Opts.AnalyzeSpecificFunction != FD->getIdentifier()->getName())
break;
}
case Decl::ObjCMethod: {
ObjCMethodDecl* MD = cast<ObjCMethodDecl>(D);
Stmt* Body = FD->getBody();
if (Body) HandleCode(FD, Body, FunctionActions);
break;
}
if (Opts.AnalyzeSpecificFunction.size() > 0 &&
Opts.AnalyzeSpecificFunction != MD->getSelector().getAsString())
return;
case Decl::ObjCMethod: {
ObjCMethodDecl* MD = cast<ObjCMethodDecl>(D);
Stmt* Body = MD->getBody();
if (Body) HandleCode(MD, Body, ObjCMethodActions);
break;
}
if (Opts.AnalyzeSpecificFunction.size() > 0 &&
Opts.AnalyzeSpecificFunction != MD->getSelector().getAsString())
return;
case Decl::CXXMethod: {
CXXMethodDecl *CXXMD = cast<CXXMethodDecl>(D);
Stmt* Body = MD->getBody();
if (Body) HandleCode(MD, Body, ObjCMethodActions);
break;
}
if (Opts.AnalyzeSpecificFunction.size() > 0 &&
Opts.AnalyzeSpecificFunction != CXXMD->getName())
return;
case Decl::CXXConstructor:
case Decl::CXXDestructor:
case Decl::CXXConversion:
case Decl::CXXMethod: {
CXXMethodDecl *CXXMD = cast<CXXMethodDecl>(D);
Stmt *Body = CXXMD->getBody();
if (Body)
HandleCode(CXXMD, Body, FunctionActions);
break;
}
if (Opts.AnalyzeSpecificFunction.size() > 0 &&
Opts.AnalyzeSpecificFunction != CXXMD->getName())
return;
default:
break;
Stmt *Body = CXXMD->getBody();
if (Body) HandleCode(CXXMD, Body, FunctionActions);
break;
}
default:
break;
}
}
@ -409,20 +411,20 @@ static void ActionCheckerCFRef(AnalysisConsumer &C, AnalysisManager& mgr,
Decl *D) {
switch (mgr.getLangOptions().getGCMode()) {
default:
assert (false && "Invalid GC mode.");
case LangOptions::NonGC:
ActionCheckerCFRefAux(C, mgr, D, false);
break;
default:
assert (false && "Invalid GC mode.");
case LangOptions::NonGC:
ActionCheckerCFRefAux(C, mgr, D, false);
break;
case LangOptions::GCOnly:
ActionCheckerCFRefAux(C, mgr, D, true);
break;
case LangOptions::GCOnly:
ActionCheckerCFRefAux(C, mgr, D, true);
break;
case LangOptions::HybridGC:
ActionCheckerCFRefAux(C, mgr, D, false);
ActionCheckerCFRefAux(C, mgr, D, true);
break;
case LangOptions::HybridGC:
ActionCheckerCFRefAux(C, mgr, D, false);
ActionCheckerCFRefAux(C, mgr, D, true);
break;
}
}
@ -530,11 +532,11 @@ ASTConsumer* clang::CreateAnalysisConsumer(const Preprocessor& pp,
for (unsigned i = 0; i < Opts.AnalysisList.size(); ++i)
switch (Opts.AnalysisList[i]) {
#define ANALYSIS(NAME, CMD, DESC, SCOPE)\
case NAME:\
C->add ## SCOPE ## Action(&Action ## NAME);\
break;
case NAME:\
C->add ## SCOPE ## Action(&Action ## NAME);\
break;
#include "clang/Frontend/Analyses.def"
default: break;
default: break;
}
// Last, disable the effects of '-Werror' when using the AnalysisConsumer.

View File

@ -77,25 +77,25 @@ class PTHEntryKeyVariant {
void EmitData(llvm::raw_ostream& Out) {
switch (Kind) {
case IsFE:
// Emit stat information.
::Emit32(Out, FE->getInode());
::Emit32(Out, FE->getDevice());
::Emit16(Out, FE->getFileMode());
::Emit64(Out, FE->getModificationTime());
::Emit64(Out, FE->getSize());
break;
case IsDE:
// Emit stat information.
::Emit32(Out, (uint32_t) StatBuf->st_ino);
::Emit32(Out, (uint32_t) StatBuf->st_dev);
::Emit16(Out, (uint16_t) StatBuf->st_mode);
::Emit64(Out, (uint64_t) StatBuf->st_mtime);
::Emit64(Out, (uint64_t) StatBuf->st_size);
delete StatBuf;
break;
default:
break;
case IsFE:
// Emit stat information.
::Emit32(Out, FE->getInode());
::Emit32(Out, FE->getDevice());
::Emit16(Out, FE->getFileMode());
::Emit64(Out, FE->getModificationTime());
::Emit64(Out, FE->getSize());
break;
case IsDE:
// Emit stat information.
::Emit32(Out, (uint32_t) StatBuf->st_ino);
::Emit32(Out, (uint32_t) StatBuf->st_dev);
::Emit16(Out, (uint16_t) StatBuf->st_mode);
::Emit64(Out, (uint64_t) StatBuf->st_mtime);
::Emit64(Out, (uint64_t) StatBuf->st_size);
delete StatBuf;
break;
default:
break;
}
}

View File

@ -98,14 +98,14 @@ class DocumentXML::DeclPrinter : public DeclVisitor<DocumentXML::DeclPrinter> {
const char* pAttributeName = NAME; \
const bool optional = false; \
switch (T->FN) { \
default: assert(0 && "unknown enum value");
default: assert(0 && "unknown enum value");
#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME ) \
{ \
const char* pAttributeName = NAME; \
const bool optional = true; \
switch (T->FN) { \
default: assert(0 && "unknown enum value");
default: assert(0 && "unknown enum value");
#define ENUM_XML( VALUE, NAME ) case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break;
#define END_ENUM_XML } }

View File

@ -349,10 +349,10 @@ void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID,
const char *Kind = 0;
switch (P.getKind()) {
case PathDiagnosticPiece::Event: Kind = "Event"; break;
case PathDiagnosticPiece::ControlFlow: Kind = "Control"; break;
// Setting Kind to "Control" is intentional.
case PathDiagnosticPiece::Macro: Kind = "Control"; break;
case PathDiagnosticPiece::Event: Kind = "Event"; break;
case PathDiagnosticPiece::ControlFlow: Kind = "Control"; break;
// Setting Kind to "Control" is intentional.
case PathDiagnosticPiece::Macro: Kind = "Control"; break;
}
std::string sbuf;
@ -380,14 +380,14 @@ void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID,
for (std::string::const_iterator I=Msg.begin(), E=Msg.end(); I!=E; ++I)
switch (*I) {
default:
++cnt;
continue;
case ' ':
case '\t':
case '\n':
if (cnt > max_token) max_token = cnt;
cnt = 0;
default:
++cnt;
continue;
case ' ':
case '\t':
case '\n':
if (cnt > max_token) max_token = cnt;
cnt = 0;
}
if (cnt > max_token)

View File

@ -189,10 +189,12 @@ void InitHeaderSearch::AddGnuCPlusPlusIncludePaths(llvm::StringRef Base,
void InitHeaderSearch::AddMinGWCPlusPlusIncludePaths(llvm::StringRef Base,
llvm::StringRef Arch,
llvm::StringRef Version) {
llvm::Twine localBase = Base + "/" + Arch + "/" + Version + "/include";
AddPath(localBase, System, true, false, false);
AddPath(localBase + "/c++", System, true, false, false);
AddPath(localBase + "/c++/backward", System, true, false, false);
AddPath(Base + "/" + Arch + "/" + Version + "/include",
System, true, false, false);
AddPath(Base + "/" + Arch + "/" + Version + "/include/c++",
System, true, false, false);
AddPath(Base + "/" + Arch + "/" + Version + "/include/c++/backward",
System, true, false, false);
}
// FIXME: This probably should goto to some platform utils place.
@ -206,8 +208,8 @@ void InitHeaderSearch::AddMinGWCPlusPlusIncludePaths(llvm::StringRef Base,
// I.e. "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION".
// There can be additional characters in the component. Only the numberic
// characters are compared.
bool getSystemRegistryString(const char *keyPath, const char *valueName,
char *value, size_t maxLength) {
static bool getSystemRegistryString(const char *keyPath, const char *valueName,
char *value, size_t maxLength) {
HKEY hRootKey = NULL;
HKEY hKey = NULL;
const char* subKey = NULL;
@ -312,13 +314,13 @@ bool getSystemRegistryString(const char *keyPath, const char *valueName,
}
#else // _MSC_VER
// Read registry string.
bool getSystemRegistryString(const char *, const char *, char *, size_t) {
static bool getSystemRegistryString(const char*, const char*, char*, size_t) {
return(false);
}
#endif // _MSC_VER
// Get Visual Studio installation directory.
bool getVisualStudioDir(std::string &path) {
static bool getVisualStudioDir(std::string &path) {
char vsIDEInstallDir[256];
// Try the Windows registry first.
bool hasVCDir = getSystemRegistryString(
@ -365,7 +367,7 @@ bool getVisualStudioDir(std::string &path) {
}
// Get Windows SDK installation directory.
bool getWindowsSDKDir(std::string &path) {
static bool getWindowsSDKDir(std::string &path) {
char windowsSDKInstallDir[256];
// Try the Windows registry.
bool hasSDKDir = getSystemRegistryString(
@ -508,6 +510,10 @@ void InitHeaderSearch::AddDefaultCPlusPlusIncludePaths(const llvm::Triple &tripl
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.2",
"i386-redhat-linux","", "", triple);
// Fedora 10 x86_64
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.2",
"x86_64-redhat-linux", "32", "", triple);
// Fedora 11
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.1",
"i586-redhat-linux","", "", triple);
@ -556,7 +562,7 @@ void InitHeaderSearch::AddDefaultCPlusPlusIncludePaths(const llvm::Triple &tripl
"i686-pc-linux-gnu", "", "", triple);
break;
case llvm::Triple::FreeBSD:
AddPath("/usr/include/c++/4.2", System, true, false, false);
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2", "", "", "", triple);
break;
case llvm::Triple::Solaris:
// Solaris - Fall though..

View File

@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Frontend/Utils.h"
#include "clang/Basic/MacroBuilder.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/FrontendOptions.h"
@ -137,7 +138,10 @@ static void DefineFloatMacros(MacroBuilder &Builder, llvm::StringRef Prefix,
"1.79769313486231580793728971405301e+308L",
"1.18973149535723176508575932662800702e+4932L");
llvm::Twine DefPrefix = "__" + Prefix + "_";
llvm::SmallString<32> DefPrefix;
DefPrefix = "__";
DefPrefix += Prefix;
DefPrefix += "_";
Builder.defineMacro(DefPrefix + "DENORM_MIN__", DenormMin);
Builder.defineMacro(DefPrefix + "HAS_DENORM__");
@ -420,23 +424,15 @@ static void InitializeFileRemapping(Diagnostic &Diags,
SourceManager &SourceMgr,
FileManager &FileMgr,
const PreprocessorOptions &InitOpts) {
// Remap files in the source manager.
for (PreprocessorOptions::remapped_file_iterator
Remap = InitOpts.remapped_file_begin(),
RemapEnd = InitOpts.remapped_file_end();
// Remap files in the source manager (with buffers).
for (PreprocessorOptions::remapped_file_buffer_iterator
Remap = InitOpts.remapped_file_buffer_begin(),
RemapEnd = InitOpts.remapped_file_buffer_end();
Remap != RemapEnd;
++Remap) {
// Find the file that we're mapping to.
const FileEntry *ToFile = FileMgr.getFile(Remap->second);
if (!ToFile) {
Diags.Report(diag::err_fe_remap_missing_to_file)
<< Remap->first << Remap->second;
continue;
}
// Create the file entry for the file that we're mapping from.
const FileEntry *FromFile = FileMgr.getVirtualFile(Remap->first,
ToFile->getSize(),
Remap->second->getBufferSize(),
0);
if (!FromFile) {
Diags.Report(diag::err_fe_remap_missing_from_file)
@ -444,16 +440,45 @@ static void InitializeFileRemapping(Diagnostic &Diags,
continue;
}
// Override the contents of the "from" file with the contents of
// the "to" file.
SourceMgr.overrideFileContents(FromFile, Remap->second);
}
// Remap files in the source manager (with other files).
for (PreprocessorOptions::remapped_file_iterator
Remap = InitOpts.remapped_file_begin(),
RemapEnd = InitOpts.remapped_file_end();
Remap != RemapEnd;
++Remap) {
// Find the file that we're mapping to.
const FileEntry *ToFile = FileMgr.getFile(Remap->second);
if (!ToFile) {
Diags.Report(diag::err_fe_remap_missing_to_file)
<< Remap->first << Remap->second;
continue;
}
// Create the file entry for the file that we're mapping from.
const FileEntry *FromFile = FileMgr.getVirtualFile(Remap->first,
ToFile->getSize(),
0);
if (!FromFile) {
Diags.Report(diag::err_fe_remap_missing_from_file)
<< Remap->first;
continue;
}
// Load the contents of the file we're mapping to.
std::string ErrorStr;
const llvm::MemoryBuffer *Buffer
= llvm::MemoryBuffer::getFile(ToFile->getName(), &ErrorStr);
= llvm::MemoryBuffer::getFile(ToFile->getName(), &ErrorStr);
if (!Buffer) {
Diags.Report(diag::err_fe_error_opening)
<< Remap->second << ErrorStr;
<< Remap->second << ErrorStr;
continue;
}
// Override the contents of the "from" file with the contents of
// the "to" file.
SourceMgr.overrideFileContents(FromFile, Buffer);

View File

@ -1399,17 +1399,10 @@ PCHReader::ReadPCHBlock() {
NumComments = BlobLen / sizeof(SourceRange);
break;
case pch::SVN_BRANCH_REVISION: {
unsigned CurRevision = getClangSubversionRevision();
if (Record[0] && CurRevision && Record[0] != CurRevision) {
Diag(Record[0] < CurRevision? diag::warn_pch_version_too_old
: diag::warn_pch_version_too_new);
return IgnorePCH;
}
const char *CurBranch = getClangSubversionPath();
if (strncmp(CurBranch, BlobStart, BlobLen)) {
std::string PCHBranch(BlobStart, BlobLen);
case pch::VERSION_CONTROL_BRANCH_REVISION: {
llvm::StringRef CurBranch = getClangFullRepositoryVersion();
llvm::StringRef PCHBranch(BlobStart, BlobLen);
if (CurBranch != PCHBranch) {
Diag(diag::warn_pch_different_branch) << PCHBranch << CurBranch;
return IgnorePCH;
}
@ -1909,18 +1902,20 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
}
case pch::TYPE_FUNCTION_NO_PROTO: {
if (Record.size() != 2) {
if (Record.size() != 3) {
Error("incorrect encoding of no-proto function type");
return QualType();
}
QualType ResultType = GetType(Record[0]);
return Context->getFunctionNoProtoType(ResultType, Record[1]);
return Context->getFunctionNoProtoType(ResultType, Record[1],
(CallingConv)Record[2]);
}
case pch::TYPE_FUNCTION_PROTO: {
QualType ResultType = GetType(Record[0]);
bool NoReturn = Record[1];
unsigned Idx = 2;
CallingConv CallConv = (CallingConv)Record[2];
unsigned Idx = 3;
unsigned NumParams = Record[Idx++];
llvm::SmallVector<QualType, 16> ParamTypes;
for (unsigned I = 0; I != NumParams; ++I)
@ -1936,7 +1931,7 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
return Context->getFunctionType(ResultType, ParamTypes.data(), NumParams,
isVariadic, Quals, hasExceptionSpec,
hasAnyExceptionSpec, NumExceptions,
Exceptions.data(), NoReturn);
Exceptions.data(), NoReturn, CallConv);
}
case pch::TYPE_UNRESOLVED_USING:
@ -2040,7 +2035,13 @@ void TypeLocReader::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
// nothing to do
}
void TypeLocReader::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
TL.setBuiltinLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
if (TL.needsExtraLocalData()) {
TL.setWrittenTypeSpec(static_cast<DeclSpec::TST>(Record[Idx++]));
TL.setWrittenSignSpec(static_cast<DeclSpec::TSS>(Record[Idx++]));
TL.setWrittenWidthSpec(static_cast<DeclSpec::TSW>(Record[Idx++]));
TL.setModeAttr(Record[Idx++]);
}
}
void TypeLocReader::VisitComplexTypeLoc(ComplexTypeLoc TL) {
TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));

View File

@ -223,7 +223,12 @@ void PCHDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
Protocols.reserve(NumProtocols);
for (unsigned I = 0; I != NumProtocols; ++I)
Protocols.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++])));
ID->setProtocolList(Protocols.data(), NumProtocols, *Reader.getContext());
llvm::SmallVector<SourceLocation, 16> ProtoLocs;
ProtoLocs.reserve(NumProtocols);
for (unsigned I = 0; I != NumProtocols; ++I)
ProtoLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++]));
ID->setProtocolList(Protocols.data(), NumProtocols, ProtoLocs.data(),
*Reader.getContext());
unsigned NumIvars = Record[Idx++];
llvm::SmallVector<ObjCIvarDecl *, 16> IVars;
IVars.reserve(NumIvars);
@ -253,7 +258,12 @@ void PCHDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) {
ProtoRefs.reserve(NumProtoRefs);
for (unsigned I = 0; I != NumProtoRefs; ++I)
ProtoRefs.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++])));
PD->setProtocolList(ProtoRefs.data(), NumProtoRefs, *Reader.getContext());
llvm::SmallVector<SourceLocation, 16> ProtoLocs;
ProtoLocs.reserve(NumProtoRefs);
for (unsigned I = 0; I != NumProtoRefs; ++I)
ProtoLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++]));
PD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(),
*Reader.getContext());
}
void PCHDeclReader::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *FD) {
@ -282,7 +292,12 @@ void PCHDeclReader::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *FPD) {
ProtoRefs.reserve(NumProtoRefs);
for (unsigned I = 0; I != NumProtoRefs; ++I)
ProtoRefs.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++])));
FPD->setProtocolList(ProtoRefs.data(), NumProtoRefs, *Reader.getContext());
llvm::SmallVector<SourceLocation, 16> ProtoLocs;
ProtoLocs.reserve(NumProtoRefs);
for (unsigned I = 0; I != NumProtoRefs; ++I)
ProtoLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++]));
FPD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(),
*Reader.getContext());
}
void PCHDeclReader::VisitObjCCategoryDecl(ObjCCategoryDecl *CD) {
@ -293,9 +308,15 @@ void PCHDeclReader::VisitObjCCategoryDecl(ObjCCategoryDecl *CD) {
ProtoRefs.reserve(NumProtoRefs);
for (unsigned I = 0; I != NumProtoRefs; ++I)
ProtoRefs.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++])));
CD->setProtocolList(ProtoRefs.data(), NumProtoRefs, *Reader.getContext());
llvm::SmallVector<SourceLocation, 16> ProtoLocs;
ProtoLocs.reserve(NumProtoRefs);
for (unsigned I = 0; I != NumProtoRefs; ++I)
ProtoLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++]));
CD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(),
*Reader.getContext());
CD->setNextClassCategory(cast_or_null<ObjCCategoryDecl>(Reader.GetDecl(Record[Idx++])));
CD->setLocEnd(SourceLocation::getFromRawEncoding(Record[Idx++]));
CD->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
CD->setCategoryNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
void PCHDeclReader::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *CAD) {
@ -305,6 +326,7 @@ void PCHDeclReader::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *CAD) {
void PCHDeclReader::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
VisitNamedDecl(D);
D->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
D->setType(Reader.GetType(Record[Idx++]));
// FIXME: stable encoding
D->setPropertyAttributes(
@ -671,7 +693,8 @@ Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) {
D = ObjCForwardProtocolDecl::Create(*Context, 0, SourceLocation());
break;
case pch::DECL_OBJC_CATEGORY:
D = ObjCCategoryDecl::Create(*Context, 0, SourceLocation(), 0);
D = ObjCCategoryDecl::Create(*Context, 0, SourceLocation(),
SourceLocation(), SourceLocation(), 0);
break;
case pch::DECL_OBJC_CATEGORY_IMPL:
D = ObjCCategoryImplDecl::Create(*Context, 0, SourceLocation(), 0, 0);
@ -683,7 +706,8 @@ Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) {
D = ObjCCompatibleAliasDecl::Create(*Context, 0, SourceLocation(), 0, 0);
break;
case pch::DECL_OBJC_PROPERTY:
D = ObjCPropertyDecl::Create(*Context, 0, SourceLocation(), 0, QualType());
D = ObjCPropertyDecl::Create(*Context, 0, SourceLocation(), 0, SourceLocation(),
QualType());
break;
case pch::DECL_OBJC_PROPERTY_IMPL:
D = ObjCPropertyImplDecl::Create(*Context, 0, SourceLocation(),

View File

@ -117,6 +117,12 @@ namespace {
unsigned VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E);
unsigned VisitCXXConstructExpr(CXXConstructExpr *E);
unsigned VisitCXXNamedCastExpr(CXXNamedCastExpr *E);
unsigned VisitCXXStaticCastExpr(CXXStaticCastExpr *E);
unsigned VisitCXXDynamicCastExpr(CXXDynamicCastExpr *E);
unsigned VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *E);
unsigned VisitCXXConstCastExpr(CXXConstCastExpr *E);
unsigned VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E);
};
}
@ -513,7 +519,7 @@ unsigned PCHStmtReader::VisitImplicitCastExpr(ImplicitCastExpr *E) {
unsigned PCHStmtReader::VisitExplicitCastExpr(ExplicitCastExpr *E) {
VisitCastExpr(E);
E->setTypeAsWritten(Reader.GetType(Record[Idx++]));
E->setTypeInfoAsWritten(Reader.GetTypeSourceInfo(Record, Idx));
return 1;
}
@ -527,6 +533,7 @@ unsigned PCHStmtReader::VisitCStyleCastExpr(CStyleCastExpr *E) {
unsigned PCHStmtReader::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
VisitExpr(E);
E->setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
E->setTypeSourceInfo(Reader.GetTypeSourceInfo(Record, Idx));
E->setInitializer(cast<Expr>(StmtStack.back()));
E->setFileScope(Record[Idx++]);
return 1;
@ -868,6 +875,35 @@ unsigned PCHStmtReader::VisitCXXConstructExpr(CXXConstructExpr *E) {
return E->getNumArgs();
}
unsigned PCHStmtReader::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) {
unsigned num = VisitExplicitCastExpr(E);
E->setOperatorLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
return num;
}
unsigned PCHStmtReader::VisitCXXStaticCastExpr(CXXStaticCastExpr *E) {
return VisitCXXNamedCastExpr(E);
}
unsigned PCHStmtReader::VisitCXXDynamicCastExpr(CXXDynamicCastExpr *E) {
return VisitCXXNamedCastExpr(E);
}
unsigned PCHStmtReader::VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *E) {
return VisitCXXNamedCastExpr(E);
}
unsigned PCHStmtReader::VisitCXXConstCastExpr(CXXConstCastExpr *E) {
return VisitCXXNamedCastExpr(E);
}
unsigned PCHStmtReader::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E) {
unsigned num = VisitExplicitCastExpr(E);
E->setTypeBeginLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
return num;
}
// Within the bitstream, expressions are stored in Reverse Polish
// Notation, with each of the subexpressions preceding the
// expression they are stored in. To evaluate expressions, we
@ -1176,6 +1212,28 @@ Stmt *PCHReader::ReadStmt(llvm::BitstreamCursor &Cursor) {
S = new (Context) CXXConstructExpr(Empty, *Context,
Record[PCHStmtReader::NumExprFields + 2]);
break;
case pch::EXPR_CXX_STATIC_CAST:
S = new (Context) CXXStaticCastExpr(Empty);
break;
case pch::EXPR_CXX_DYNAMIC_CAST:
S = new (Context) CXXDynamicCastExpr(Empty);
break;
case pch::EXPR_CXX_REINTERPRET_CAST:
S = new (Context) CXXReinterpretCastExpr(Empty);
break;
case pch::EXPR_CXX_CONST_CAST:
S = new (Context) CXXConstCastExpr(Empty);
break;
case pch::EXPR_CXX_FUNCTIONAL_CAST:
S = new (Context) CXXFunctionalCastExpr(Empty);
break;
}
// We hit a STMT_STOP, so we're done with this expression.

View File

@ -139,6 +139,8 @@ void PCHTypeWriter::VisitExtVectorType(const ExtVectorType *T) {
void PCHTypeWriter::VisitFunctionType(const FunctionType *T) {
Writer.AddTypeRef(T->getResultType(), Record);
Record.push_back(T->getNoReturnAttr());
// FIXME: need to stabilize encoding of calling convention...
Record.push_back(T->getCallConv());
}
void PCHTypeWriter::VisitFunctionNoProtoType(const FunctionNoProtoType *T) {
@ -275,7 +277,13 @@ void TypeLocWriter::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
// nothing to do
}
void TypeLocWriter::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
Writer.AddSourceLocation(TL.getNameLoc(), Record);
Writer.AddSourceLocation(TL.getBuiltinLoc(), Record);
if (TL.needsExtraLocalData()) {
Record.push_back(TL.getWrittenTypeSpec());
Record.push_back(TL.getWrittenSignSpec());
Record.push_back(TL.getWrittenWidthSpec());
Record.push_back(TL.hasModeAttr());
}
}
void TypeLocWriter::VisitComplexTypeLoc(ComplexTypeLoc TL) {
Writer.AddSourceLocation(TL.getNameLoc(), Record);
@ -535,7 +543,7 @@ void PCHWriter::WriteBlockInfoBlock() {
RECORD(STAT_CACHE);
RECORD(EXT_VECTOR_DECLS);
RECORD(COMMENT_RANGES);
RECORD(SVN_BRANCH_REVISION);
RECORD(VERSION_CONTROL_BRANCH_REVISION);
// SourceManager Block.
BLOCK(SOURCE_MANAGER_BLOCK);
@ -699,16 +707,15 @@ void PCHWriter::WriteMetadata(ASTContext &Context, const char *isysroot) {
Stream.EmitRecordWithBlob(FileAbbrevCode, Record, MainFileNameStr);
}
// Subversion branch/version information.
BitCodeAbbrev *SvnAbbrev = new BitCodeAbbrev();
SvnAbbrev->Add(BitCodeAbbrevOp(pch::SVN_BRANCH_REVISION));
SvnAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // SVN revision
SvnAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // SVN branch/tag
unsigned SvnAbbrevCode = Stream.EmitAbbrev(SvnAbbrev);
// Repository branch/version information.
BitCodeAbbrev *RepoAbbrev = new BitCodeAbbrev();
RepoAbbrev->Add(BitCodeAbbrevOp(pch::VERSION_CONTROL_BRANCH_REVISION));
RepoAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // SVN branch/tag
unsigned RepoAbbrevCode = Stream.EmitAbbrev(RepoAbbrev);
Record.clear();
Record.push_back(pch::SVN_BRANCH_REVISION);
Record.push_back(getClangSubversionRevision());
Stream.EmitRecordWithBlob(SvnAbbrevCode, Record, getClangSubversionPath());
Record.push_back(pch::VERSION_CONTROL_BRANCH_REVISION);
Stream.EmitRecordWithBlob(RepoAbbrevCode, Record,
getClangFullRepositoryVersion());
}
/// \brief Write the LangOptions structure.
@ -1263,7 +1270,7 @@ void PCHWriter::WriteType(QualType T) {
// For all of the concrete, non-dependent types, call the
// appropriate visitor function.
#define TYPE(Class, Base) \
case Type::Class: W.Visit##Class##Type(cast<Class##Type>(T)); break;
case Type::Class: W.Visit##Class##Type(cast<Class##Type>(T)); break;
#define ABSTRACT_TYPE(Class, Base)
#define DEPENDENT_TYPE(Class, Base)
#include "clang/AST/TypeNodes.def"

View File

@ -223,6 +223,10 @@ void PCHDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
PEnd = D->protocol_end();
P != PEnd; ++P)
Writer.AddDeclRef(*P, Record);
for (ObjCInterfaceDecl::protocol_loc_iterator PL = D->protocol_loc_begin(),
PLEnd = D->protocol_loc_end();
PL != PLEnd; ++PL)
Writer.AddSourceLocation(*PL, Record);
Record.push_back(D->ivar_size());
for (ObjCInterfaceDecl::ivar_iterator I = D->ivar_begin(),
IEnd = D->ivar_end(); I != IEnd; ++I)
@ -251,6 +255,10 @@ void PCHDeclWriter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) {
for (ObjCProtocolDecl::protocol_iterator
I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I)
Writer.AddDeclRef(*I, Record);
for (ObjCProtocolDecl::protocol_loc_iterator PL = D->protocol_loc_begin(),
PLEnd = D->protocol_loc_end();
PL != PLEnd; ++PL)
Writer.AddSourceLocation(*PL, Record);
Code = pch::DECL_OBJC_PROTOCOL;
}
@ -272,9 +280,13 @@ void PCHDeclWriter::VisitObjCClassDecl(ObjCClassDecl *D) {
void PCHDeclWriter::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) {
VisitDecl(D);
Record.push_back(D->protocol_size());
for (ObjCProtocolDecl::protocol_iterator
for (ObjCForwardProtocolDecl::protocol_iterator
I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I)
Writer.AddDeclRef(*I, Record);
for (ObjCForwardProtocolDecl::protocol_loc_iterator
PL = D->protocol_loc_begin(), PLEnd = D->protocol_loc_end();
PL != PLEnd; ++PL)
Writer.AddSourceLocation(*PL, Record);
Code = pch::DECL_OBJC_FORWARD_PROTOCOL;
}
@ -282,11 +294,16 @@ void PCHDeclWriter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) {
VisitObjCContainerDecl(D);
Writer.AddDeclRef(D->getClassInterface(), Record);
Record.push_back(D->protocol_size());
for (ObjCProtocolDecl::protocol_iterator
for (ObjCCategoryDecl::protocol_iterator
I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I)
Writer.AddDeclRef(*I, Record);
for (ObjCCategoryDecl::protocol_loc_iterator
PL = D->protocol_loc_begin(), PLEnd = D->protocol_loc_end();
PL != PLEnd; ++PL)
Writer.AddSourceLocation(*PL, Record);
Writer.AddDeclRef(D->getNextClassCategory(), Record);
Writer.AddSourceLocation(D->getLocEnd(), Record);
Writer.AddSourceLocation(D->getAtLoc(), Record);
Writer.AddSourceLocation(D->getCategoryNameLoc(), Record);
Code = pch::DECL_OBJC_CATEGORY;
}
@ -298,6 +315,7 @@ void PCHDeclWriter::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D) {
void PCHDeclWriter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
VisitNamedDecl(D);
Writer.AddSourceLocation(D->getAtLoc(), Record);
Writer.AddTypeRef(D->getType(), Record);
// FIXME: stable encoding
Record.push_back((unsigned)D->getPropertyAttributes());

View File

@ -112,6 +112,12 @@ namespace {
// C++ Statements
void VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E);
void VisitCXXConstructExpr(CXXConstructExpr *E);
void VisitCXXNamedCastExpr(CXXNamedCastExpr *E);
void VisitCXXStaticCastExpr(CXXStaticCastExpr *E);
void VisitCXXDynamicCastExpr(CXXDynamicCastExpr *E);
void VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *E);
void VisitCXXConstCastExpr(CXXConstCastExpr *E);
void VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E);
};
}
@ -477,7 +483,7 @@ void PCHStmtWriter::VisitImplicitCastExpr(ImplicitCastExpr *E) {
void PCHStmtWriter::VisitExplicitCastExpr(ExplicitCastExpr *E) {
VisitCastExpr(E);
Writer.AddTypeRef(E->getTypeAsWritten(), Record);
Writer.AddTypeSourceInfo(E->getTypeInfoAsWritten(), Record);
}
void PCHStmtWriter::VisitCStyleCastExpr(CStyleCastExpr *E) {
@ -490,6 +496,7 @@ void PCHStmtWriter::VisitCStyleCastExpr(CStyleCastExpr *E) {
void PCHStmtWriter::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
VisitExpr(E);
Writer.AddSourceLocation(E->getLParenLoc(), Record);
Writer.AddTypeSourceInfo(E->getTypeSourceInfo(), Record);
Writer.WriteSubStmt(E->getInitializer());
Record.push_back(E->isFileScope());
Code = pch::EXPR_COMPOUND_LITERAL;
@ -795,6 +802,38 @@ void PCHStmtWriter::VisitCXXConstructExpr(CXXConstructExpr *E) {
Code = pch::EXPR_CXX_CONSTRUCT;
}
void PCHStmtWriter::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) {
VisitExplicitCastExpr(E);
Writer.AddSourceLocation(E->getOperatorLoc(), Record);
}
void PCHStmtWriter::VisitCXXStaticCastExpr(CXXStaticCastExpr *E) {
VisitCXXNamedCastExpr(E);
Code = pch::EXPR_CXX_STATIC_CAST;
}
void PCHStmtWriter::VisitCXXDynamicCastExpr(CXXDynamicCastExpr *E) {
VisitCXXNamedCastExpr(E);
Code = pch::EXPR_CXX_DYNAMIC_CAST;
}
void PCHStmtWriter::VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *E) {
VisitCXXNamedCastExpr(E);
Code = pch::EXPR_CXX_REINTERPRET_CAST;
}
void PCHStmtWriter::VisitCXXConstCastExpr(CXXConstCastExpr *E) {
VisitCXXNamedCastExpr(E);
Code = pch::EXPR_CXX_CONST_CAST;
}
void PCHStmtWriter::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E) {
VisitExplicitCastExpr(E);
Writer.AddSourceLocation(E->getTypeBeginLoc(), Record);
Writer.AddSourceLocation(E->getRParenLoc(), Record);
Code = pch::EXPR_CXX_FUNCTIONAL_CAST;
}
//===----------------------------------------------------------------------===//
// PCHWriter Implementation
//===----------------------------------------------------------------------===//

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