Update clang to r94309.
This commit is contained in:
parent
ee791dde72
commit
5044f5c816
@ -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
@ -61,6 +61,7 @@ namespace clang {
|
||||
class TypedefDecl;
|
||||
class UsingDecl;
|
||||
class UsingShadowDecl;
|
||||
class UnresolvedSetIterator;
|
||||
|
||||
namespace Builtin { class Context; }
|
||||
|
||||
@ -397,6 +398,11 @@ public:
|
||||
/// 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 @@ public:
|
||||
|
||||
/// 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 @@ public:
|
||||
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 @@ public:
|
||||
|
||||
DeclarationName getNameForTemplate(TemplateName Name);
|
||||
|
||||
TemplateName getOverloadedTemplateName(NamedDecl * const *Begin,
|
||||
NamedDecl * const *End);
|
||||
TemplateName getOverloadedTemplateName(UnresolvedSetIterator Begin,
|
||||
UnresolvedSetIterator End);
|
||||
|
||||
TemplateName getQualifiedTemplateName(NestedNameSpecifier *NNS,
|
||||
bool TemplateKeyword,
|
||||
|
@ -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;
|
||||
|
||||
|
@ -55,32 +55,6 @@ public:
|
||||
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;
|
||||
|
@ -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 @@ private:
|
||||
};
|
||||
|
||||
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.
|
||||
|
@ -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 @@ public:
|
||||
|
||||
/// 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 @@ public:
|
||||
|
||||
/// 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 @@ public:
|
||||
/// 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 ||
|
||||
|
@ -75,6 +75,24 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/// \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 @@ public:
|
||||
SourceLocation ClassLoc = SourceLocation(),
|
||||
bool ForwardDecl = false,
|
||||
bool isInternal = false);
|
||||
const ObjCList<ObjCProtocolDecl> &getReferencedProtocols() const {
|
||||
const ObjCProtocolList &getReferencedProtocols() const {
|
||||
return ReferencedProtocols;
|
||||
}
|
||||
|
||||
@ -459,9 +477,16 @@ public:
|
||||
: 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 @@ public:
|
||||
/// 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 @@ public:
|
||||
///
|
||||
class ObjCProtocolDecl : public ObjCContainerDecl {
|
||||
/// Referenced protocols
|
||||
ObjCList<ObjCProtocolDecl> ReferencedProtocols;
|
||||
ObjCProtocolList ReferencedProtocols;
|
||||
|
||||
bool isForwardProtoDecl; // declared with @protocol.
|
||||
|
||||
@ -680,19 +707,26 @@ public:
|
||||
/// 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 @@ public:
|
||||
/// @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 @@ public:
|
||||
/// 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 @@ public:
|
||||
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 @@ public:
|
||||
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 @@ private:
|
||||
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 @@ private:
|
||||
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; }
|
||||
|
||||
|
@ -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 @@ public:
|
||||
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 @@ public:
|
||||
/// 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) {}
|
||||
|
||||
|
@ -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 @@ private:
|
||||
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
/// @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 @@ public:
|
||||
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 @@ public:
|
||||
/// @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 @@ public:
|
||||
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 @@ public:
|
||||
|
||||
/// 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 @@ public:
|
||||
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 @@ public:
|
||||
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(); }
|
||||
|
||||
|
@ -385,6 +385,14 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/// 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 @@ public:
|
||||
/// 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 @@ public:
|
||||
/// 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 @@ public:
|
||||
/// 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
|
||||
|
@ -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 @@ public:
|
||||
};
|
||||
|
||||
|
||||
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 @@ public:
|
||||
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,
|
||||
|
@ -43,6 +43,7 @@ public:
|
||||
case TypeLoc::CLASS: DISPATCH(CLASS##TypeLoc);
|
||||
#include "clang/AST/TypeLocNodes.def"
|
||||
}
|
||||
llvm_unreachable("unexpected type loc class!");
|
||||
}
|
||||
|
||||
#define TYPELOC(CLASS, PARENT) \
|
||||
|
211
include/clang/AST/UnresolvedSet.h
Normal file
211
include/clang/AST/UnresolvedSet.h
Normal 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
|
@ -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 @@ public:
|
||||
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 @@ public:
|
||||
|
||||
/// 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.
|
||||
|
@ -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();
|
||||
|
@ -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)->\
|
||||
|
@ -270,8 +270,8 @@ protected:
|
||||
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,
|
||||
|
@ -105,7 +105,8 @@ public:
|
||||
|
||||
// FIXME: Make out-of-line.
|
||||
virtual DefinedOrUnknownSVal getSizeInElements(const GRState *state,
|
||||
const MemRegion *region) {
|
||||
const MemRegion *region,
|
||||
QualType EleTy) {
|
||||
return UnknownVal();
|
||||
}
|
||||
|
||||
|
@ -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")
|
||||
|
@ -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", "")
|
||||
|
@ -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">;
|
||||
|
||||
}
|
||||
|
@ -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>">;
|
||||
|
@ -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<
|
||||
|
46
include/clang/Basic/MacroBuilder.h
Normal file
46
include/clang/Basic/MacroBuilder.h
Normal 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
|
@ -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, $@) $<
|
||||
|
||||
|
||||
|
82
include/clang/Basic/Specifiers.h
Normal file
82
include/clang/Basic/Specifiers.h
Normal 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
|
@ -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
|
||||
|
@ -61,6 +61,9 @@ public:
|
||||
/// command line.
|
||||
std::string Dir;
|
||||
|
||||
/// The path to the compiler resource directory.
|
||||
std::string ResourceDir;
|
||||
|
||||
/// Default host triple.
|
||||
std::string DefaultHostTriple;
|
||||
|
||||
|
@ -21,6 +21,11 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
#include <utility>
|
||||
|
||||
namespace llvm {
|
||||
class MemoryBuffer;
|
||||
}
|
||||
|
||||
namespace clang {
|
||||
class ASTContext;
|
||||
@ -111,6 +116,10 @@ public:
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
Diagnostic &Diags,
|
||||
llvm::StringRef ResourceFilesPath,
|
||||
bool OnlyLocalDecls = false,
|
||||
bool UseBumpAllocator = false);
|
||||
bool UseBumpAllocator = false,
|
||||
RemappedFile *RemappedFiles = 0,
|
||||
unsigned NumRemappedFiles = 0);
|
||||
};
|
||||
|
||||
} // namespace clang
|
||||
|
@ -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
|
||||
|
@ -16,6 +16,10 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
class MemoryBuffer;
|
||||
}
|
||||
|
||||
namespace clang {
|
||||
|
||||
class Preprocessor;
|
||||
@ -48,6 +52,12 @@ public:
|
||||
/// 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 @@ public:
|
||||
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 @@ public:
|
||||
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
|
||||
|
@ -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);
|
||||
|
@ -602,7 +602,12 @@ public:
|
||||
/// 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 @@ public:
|
||||
/// 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 @@ public:
|
||||
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
|
||||
|
@ -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
|
@ -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 @@ public:
|
||||
SourceLocation SuperLoc,
|
||||
const DeclPtrTy *ProtoRefs,
|
||||
unsigned NumProtoRefs,
|
||||
const SourceLocation *ProtoLocs,
|
||||
SourceLocation EndProtoLoc,
|
||||
AttributeList *AttrList) {
|
||||
return DeclPtrTy();
|
||||
@ -2131,6 +2132,7 @@ public:
|
||||
SourceLocation ProtocolLoc,
|
||||
const DeclPtrTy *ProtoRefs,
|
||||
unsigned NumProtoRefs,
|
||||
const SourceLocation *ProtoLocs,
|
||||
SourceLocation EndProtoLoc,
|
||||
AttributeList *AttrList) {
|
||||
return DeclPtrTy();
|
||||
@ -2144,6 +2146,7 @@ public:
|
||||
SourceLocation CategoryLoc,
|
||||
const DeclPtrTy *ProtoRefs,
|
||||
unsigned NumProtoRefs,
|
||||
const SourceLocation *ProtoLocs,
|
||||
SourceLocation EndProtoLoc) {
|
||||
return DeclPtrTy();
|
||||
}
|
||||
@ -2771,6 +2774,7 @@ public:
|
||||
SourceLocation SuperLoc,
|
||||
const DeclPtrTy *ProtoRefs,
|
||||
unsigned NumProtoRefs,
|
||||
const SourceLocation *ProtoLocs,
|
||||
SourceLocation EndProtoLoc,
|
||||
AttributeList *AttrList);
|
||||
};
|
||||
|
@ -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 @@ public:
|
||||
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 @@ private:
|
||||
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 @@ public:
|
||||
/// 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();
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -119,6 +119,11 @@ ASTRecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD,
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (i->isVirtual()) {
|
||||
SelectPrimaryVBase(Base, FirstPrimary);
|
||||
if (PrimaryBase.getBase())
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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 @@ public:
|
||||
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 @@ private:
|
||||
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 @@ private:
|
||||
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 @@ private:
|
||||
}
|
||||
|
||||
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 @@ tryAgain:
|
||||
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 @@ tryAgain:
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
|
||||
|
||||
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";
|
||||
|
@ -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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ public:
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -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 @@ public:
|
||||
// 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
|
||||
|
@ -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);
|
||||
|
@ -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)"'
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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),
|
||||
|
@ -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.
|
||||
|
@ -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();
|
||||
|
@ -742,7 +742,8 @@ public:
|
||||
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 @@ public:
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
@ -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()));
|
||||
}
|
||||
|
@ -124,7 +124,7 @@ private:
|
||||
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));
|
||||
|
@ -952,7 +952,7 @@ public:
|
||||
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
|
||||
|
@ -106,7 +106,7 @@ public:
|
||||
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
398
lib/CodeGen/CGVTT.cpp
Normal 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;
|
||||
}
|
@ -232,8 +232,8 @@ public:
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
|
||||
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 @@ public:
|
||||
insertVCalls(VCallInsertionPoint);
|
||||
}
|
||||
|
||||
AddAddressPoints(RD, Offset, AddressPoint);
|
||||
if (!ForNPNVBases || !WasPrimaryBase)
|
||||
AddAddressPoints(RD, Offset, AddressPoint);
|
||||
|
||||
if (alloc) {
|
||||
delete Path;
|
||||
@ -557,13 +564,13 @@ public:
|
||||
// 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 @@ public:
|
||||
}
|
||||
|
||||
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 @@ public:
|
||||
}
|
||||
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
|
||||
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 @@ public:
|
||||
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;
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ add_clang_library(clangCodeGen
|
||||
CGStmt.cpp
|
||||
CGTemporaries.cpp
|
||||
CGVtable.cpp
|
||||
CGVTT.cpp
|
||||
CodeGenFunction.cpp
|
||||
CodeGenModule.cpp
|
||||
CodeGenTypes.cpp
|
||||
|
@ -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();
|
||||
|
@ -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 @@ public:
|
||||
/// 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
@ -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 @@ public:
|
||||
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 @@ public:
|
||||
|
||||
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 @@ private:
|
||||
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;
|
||||
};
|
||||
|
@ -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 { }
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
|
@ -85,6 +85,11 @@ public:
|
||||
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;
|
||||
|
@ -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");
|
||||
|
@ -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());
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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.
|
||||
|
@ -77,25 +77,25 @@ public:
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -98,14 +98,14 @@ public:
|
||||
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 } }
|
||||
|
@ -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)
|
||||
|
@ -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..
|
||||
|
@ -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);
|
||||
|
@ -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++]));
|
||||
|
@ -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(),
|
||||
|
@ -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.
|
||||
|
@ -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"
|
||||
|
@ -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());
|
||||
|
@ -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
Loading…
x
Reference in New Issue
Block a user