Update clang to r100181.

This commit is contained in:
Roman Divacky 2010-04-02 08:55:10 +00:00
parent c0c7bca4e5
commit 11d2b2d2bb
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor/clang/dist/; revision=206084
367 changed files with 11299 additions and 6621 deletions

View File

@ -92,6 +92,12 @@ install(DIRECTORY include/
PATTERN ".svn" EXCLUDE
)
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include/
DESTINATION include
FILES_MATCHING
PATTERN "*.inc"
)
add_definitions( -D_GNU_SOURCE )
option(CLANG_BUILD_EXAMPLES "Build CLANG example programs." OFF)

View File

@ -12,7 +12,6 @@
1A2193CE0F45EEB700C0713D /* Mangle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2193CC0F45EEB700C0713D /* Mangle.cpp */; };
1A2A54B50FD1DD1C00F4CE45 /* AnalysisConsumer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2A54A40FD1DD1C00F4CE45 /* AnalysisConsumer.cpp */; };
1A2A54B60FD1DD1C00F4CE45 /* ASTConsumers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2A54A50FD1DD1C00F4CE45 /* ASTConsumers.cpp */; };
1A2A54B70FD1DD1C00F4CE45 /* Backend.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2A54A60FD1DD1C00F4CE45 /* Backend.cpp */; };
1A2A54B80FD1DD1C00F4CE45 /* CacheTokens.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2A54A70FD1DD1C00F4CE45 /* CacheTokens.cpp */; };
1A2A54B90FD1DD1C00F4CE45 /* DependencyFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2A54A80FD1DD1C00F4CE45 /* DependencyFile.cpp */; };
1A2A54BA0FD1DD1C00F4CE45 /* DiagChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2A54A90FD1DD1C00F4CE45 /* DiagChecker.cpp */; };
@ -70,6 +69,8 @@
1ADF47AF0F782C3200E48A8A /* SemaTemplateInstantiateDecl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ADF47AE0F782C3200E48A8A /* SemaTemplateInstantiateDecl.cpp */; };
1AE4EE3E103B89ED00888A23 /* StmtProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AE4EE3D103B89ED00888A23 /* StmtProfile.cpp */; };
1AF1B50F109A4FB800AFAFAC /* CGException.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AF1B50E109A4FB800AFAFAC /* CGException.cpp */; };
1AFDD8721161085D00AE030A /* ASTMerge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AFDD8701161085D00AE030A /* ASTMerge.cpp */; };
1AFDD8731161085D00AE030A /* CodeGenAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AFDD8711161085D00AE030A /* CodeGenAction.cpp */; };
1AFF8AE31012BFC900D248DA /* CGRecordLayoutBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AFF8AE11012BFC900D248DA /* CGRecordLayoutBuilder.cpp */; };
3507E4C20E27FE2D00FB7B57 /* CheckObjCInstMethSignature.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3507E4C10E27FE2D00FB7B57 /* CheckObjCInstMethSignature.cpp */; };
352246E70F5C6BE000D0D279 /* HTMLDiagnostics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 352246E10F5C6BE000D0D279 /* HTMLDiagnostics.cpp */; };
@ -149,6 +150,11 @@
90FD6D85103C3D49005F5B73 /* SelectorMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90FD6D7A103C3D49005F5B73 /* SelectorMap.cpp */; };
90FD6DB6103D977E005F5B73 /* index-test.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90FD6DB5103D977E005F5B73 /* index-test.cpp */; };
BDF87CF70FD746F300BBF872 /* SemaTemplateDeduction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BDF87CF60FD746F300BBF872 /* SemaTemplateDeduction.cpp */; };
BF89C3E211595818001C2D68 /* AnalysisBasedWarnings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF89C3E111595818001C2D68 /* AnalysisBasedWarnings.cpp */; };
BF89C3E91159594A001C2D68 /* SemaObjCProperty.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF89C3E81159594A001C2D68 /* SemaObjCProperty.cpp */; };
BF89C3F911595A01001C2D68 /* SemaType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF89C3F811595A01001C2D68 /* SemaType.cpp */; };
BF89C3FB11595A37001C2D68 /* SemaCodeComplete.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF89C3FA11595A37001C2D68 /* SemaCodeComplete.cpp */; };
BF89C3FD11595A5D001C2D68 /* SemaExceptionSpec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF89C3FC11595A5D001C2D68 /* SemaExceptionSpec.cpp */; };
DE01DA490B12ADA300AC22CE /* PPCallbacks.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE01DA480B12ADA300AC22CE /* PPCallbacks.h */; };
DE06756C0C051CFE00EBBFD8 /* ParseExprCXX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE06756B0C051CFE00EBBFD8 /* ParseExprCXX.cpp */; };
DE06B73E0A8307640050E87E /* LangOptions.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE06B73D0A8307640050E87E /* LangOptions.h */; };
@ -365,7 +371,6 @@
1A2193CD0F45EEB700C0713D /* Mangle.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = Mangle.h; path = lib/CodeGen/Mangle.h; sourceTree = "<group>"; tabWidth = 2; };
1A2A54A40FD1DD1C00F4CE45 /* AnalysisConsumer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AnalysisConsumer.cpp; path = lib/Frontend/AnalysisConsumer.cpp; sourceTree = "<group>"; };
1A2A54A50FD1DD1C00F4CE45 /* ASTConsumers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = ASTConsumers.cpp; path = lib/Frontend/ASTConsumers.cpp; sourceTree = "<group>"; tabWidth = 2; };
1A2A54A60FD1DD1C00F4CE45 /* Backend.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Backend.cpp; path = lib/Frontend/Backend.cpp; sourceTree = "<group>"; };
1A2A54A70FD1DD1C00F4CE45 /* CacheTokens.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CacheTokens.cpp; path = lib/Frontend/CacheTokens.cpp; sourceTree = "<group>"; };
1A2A54A80FD1DD1C00F4CE45 /* DependencyFile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DependencyFile.cpp; path = lib/Frontend/DependencyFile.cpp; sourceTree = "<group>"; };
1A2A54A90FD1DD1C00F4CE45 /* DiagChecker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DiagChecker.cpp; path = lib/Frontend/DiagChecker.cpp; sourceTree = "<group>"; };
@ -446,8 +451,9 @@
1AE4EE3B103B89CA00888A23 /* TreeTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = TreeTransform.h; path = lib/Sema/TreeTransform.h; sourceTree = "<group>"; tabWidth = 2; };
1AE4EE3D103B89ED00888A23 /* StmtProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = StmtProfile.cpp; path = lib/AST/StmtProfile.cpp; sourceTree = "<group>"; tabWidth = 2; };
1AF1B50E109A4FB800AFAFAC /* CGException.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGException.cpp; path = lib/CodeGen/CGException.cpp; sourceTree = "<group>"; tabWidth = 2; };
1AFDD8701161085D00AE030A /* ASTMerge.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ASTMerge.cpp; path = lib/Frontend/ASTMerge.cpp; sourceTree = "<group>"; };
1AFDD8711161085D00AE030A /* CodeGenAction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CodeGenAction.cpp; path = lib/Frontend/CodeGenAction.cpp; sourceTree = "<group>"; };
1AFF8AE11012BFC900D248DA /* CGRecordLayoutBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGRecordLayoutBuilder.cpp; path = lib/CodeGen/CGRecordLayoutBuilder.cpp; sourceTree = "<group>"; tabWidth = 2; };
1AFF8AE21012BFC900D248DA /* CGRecordLayoutBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = CGRecordLayoutBuilder.h; path = lib/CodeGen/CGRecordLayoutBuilder.h; sourceTree = "<group>"; tabWidth = 2; };
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>"; };
@ -618,6 +624,15 @@
90FD6D91103C3D80005F5B73 /* Utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Utils.h; path = clang/Frontend/Utils.h; sourceTree = "<group>"; };
90FD6DB5103D977E005F5B73 /* index-test.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "index-test.cpp"; path = "tools/index-test/index-test.cpp"; sourceTree = "<group>"; };
BDF87CF60FD746F300BBF872 /* SemaTemplateDeduction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = SemaTemplateDeduction.cpp; path = lib/Sema/SemaTemplateDeduction.cpp; sourceTree = "<group>"; tabWidth = 2; };
BF89C3E0115957FF001C2D68 /* AnalysisBasedWarnings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AnalysisBasedWarnings.h; path = lib/Sema/AnalysisBasedWarnings.h; sourceTree = "<group>"; };
BF89C3E111595818001C2D68 /* AnalysisBasedWarnings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AnalysisBasedWarnings.cpp; path = lib/Sema/AnalysisBasedWarnings.cpp; sourceTree = "<group>"; };
BF89C3E311595835001C2D68 /* Lookup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Lookup.h; path = lib/Sema/Lookup.h; sourceTree = "<group>"; };
BF89C3E411595855001C2D68 /* SemaInit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SemaInit.h; path = lib/Sema/SemaInit.h; sourceTree = "<group>"; };
BF89C3E5115958A1001C2D68 /* TargetAttributesSema.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TargetAttributesSema.h; path = lib/Sema/TargetAttributesSema.h; sourceTree = "<group>"; };
BF89C3E81159594A001C2D68 /* SemaObjCProperty.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SemaObjCProperty.cpp; path = lib/Sema/SemaObjCProperty.cpp; sourceTree = "<group>"; };
BF89C3F811595A01001C2D68 /* SemaType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SemaType.cpp; path = lib/Sema/SemaType.cpp; sourceTree = "<group>"; };
BF89C3FA11595A37001C2D68 /* SemaCodeComplete.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SemaCodeComplete.cpp; path = lib/Sema/SemaCodeComplete.cpp; sourceTree = "<group>"; };
BF89C3FC11595A5D001C2D68 /* SemaExceptionSpec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SemaExceptionSpec.cpp; path = lib/Sema/SemaExceptionSpec.cpp; sourceTree = "<group>"; };
DE01DA480B12ADA300AC22CE /* PPCallbacks.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PPCallbacks.h; sourceTree = "<group>"; };
DE06756B0C051CFE00EBBFD8 /* ParseExprCXX.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = ParseExprCXX.cpp; path = lib/Parse/ParseExprCXX.cpp; sourceTree = "<group>"; tabWidth = 2; };
DE06B73D0A8307640050E87E /* LangOptions.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; path = LangOptions.h; sourceTree = "<group>"; tabWidth = 2; };
@ -948,10 +963,11 @@
352246E00F5C6BC000D0D279 /* Frontend */ = {
isa = PBXGroup;
children = (
1AFDD8701161085D00AE030A /* ASTMerge.cpp */,
9012911C1048068D0083456D /* ASTUnit.cpp */,
1A2A54A40FD1DD1C00F4CE45 /* AnalysisConsumer.cpp */,
1A2A54A50FD1DD1C00F4CE45 /* ASTConsumers.cpp */,
1A2A54A60FD1DD1C00F4CE45 /* Backend.cpp */,
1AFDD8711161085D00AE030A /* CodeGenAction.cpp */,
1A2A54A70FD1DD1C00F4CE45 /* CacheTokens.cpp */,
1ACB57DB1105820D0047B991 /* CompilerInstance.cpp */,
1ACB57DC1105820D0047B991 /* CompilerInvocation.cpp */,
@ -1257,29 +1273,36 @@
DE67E7070C020EAB00F66BC5 /* Sema */ = {
isa = PBXGroup;
children = (
BF89C3E111595818001C2D68 /* AnalysisBasedWarnings.cpp */,
BF89C3E0115957FF001C2D68 /* AnalysisBasedWarnings.h */,
35585DBD0EAFBC4500D0A97A /* CXXFieldCollector.h */,
1A6B6CD110693FC900BB4A8F /* CodeCompleteConsumer.cpp */,
3527124F0DAFE54700C76352 /* IdentifierResolver.h */,
352712500DAFE54700C76352 /* IdentifierResolver.cpp */,
DECB6D640F9AE26600F5FBC7 /* JumpDiagnostics.cpp */,
BF89C3E311595835001C2D68 /* Lookup.h */,
DE67E7190C020F4F00F66BC5 /* ParseAST.cpp */,
DE67E7140C020EDF00F66BC5 /* Sema.h */,
DE67E7160C020EE400F66BC5 /* Sema.cpp */,
1A701B630F7C8FE400FEC4D1 /* SemaAccess.cpp */,
DEB07AC70F4A427E00F5A2BE /* SemaAttr.cpp */,
DEF2F00F0C6CFED5000C4259 /* SemaChecking.cpp */,
BF89C3FA11595A37001C2D68 /* SemaCodeComplete.cpp */,
35E194670ECB82FB00F21733 /* SemaCXXScopeSpec.cpp */,
DE67E7120C020ED900F66BC5 /* SemaDecl.cpp */,
DE22BCF10E14197E0094DC60 /* SemaDeclAttr.cpp */,
35EF676F0DAD1D2C00B19414 /* SemaDeclCXX.cpp */,
DE704B250D0FBEBE009C7762 /* SemaDeclObjC.cpp */,
BF89C3FC11595A5D001C2D68 /* SemaExceptionSpec.cpp */,
DE67E7100C020ED400F66BC5 /* SemaExpr.cpp */,
DE47999B0D2EBE1A00706D2D /* SemaExprObjC.cpp */,
DE67E70E0C020ECF00F66BC5 /* SemaExprCXX.cpp */,
BF89C3E411595855001C2D68 /* SemaInit.h */,
3599299A0DE2425300A8A33E /* SemaInit.cpp */,
357EA27C0F2526F300439B60 /* SemaLookup.cpp */,
1A6B6CD210693FC900BB4A8F /* SemaCodeComplete.cpp */,
35E194680ECB82FB00F21733 /* SemaCXXCast.cpp */,
BF89C3E81159594A001C2D68 /* SemaObjCProperty.cpp */,
35585DBE0EAFBC4500D0A97A /* SemaOverload.cpp */,
35585DBF0EAFBC4500D0A97A /* SemaOverload.h */,
DE67E70C0C020ECA00F66BC5 /* SemaStmt.cpp */,
@ -1288,7 +1311,9 @@
BDF87CF60FD746F300BBF872 /* SemaTemplateDeduction.cpp */,
35544B8B0F5C803200D92AA9 /* SemaTemplateInstantiate.cpp */,
1ADF47AE0F782C3200E48A8A /* SemaTemplateInstantiateDecl.cpp */,
BF89C3F811595A01001C2D68 /* SemaType.cpp */,
1AE4EE3B103B89CA00888A23 /* TreeTransform.h */,
BF89C3E5115958A1001C2D68 /* TargetAttributesSema.h */,
);
name = Sema;
sourceTree = "<group>";
@ -1334,7 +1359,6 @@
DE38CD4F0D794D0100A273B6 /* CGObjCGNU.cpp */,
3552E7580E520DD7003A8CA5 /* CGObjCMac.cpp */,
1AFF8AE11012BFC900D248DA /* CGRecordLayoutBuilder.cpp */,
1AFF8AE21012BFC900D248DA /* CGRecordLayoutBuilder.h */,
1A6C01F6108128710072DEE4 /* CGRTTI.cpp */,
DE4772F90C10EAE5002239E8 /* CGStmt.cpp */,
1A6FE7080FD6F85800E00CA9 /* CGTemporaries.cpp */,
@ -1930,7 +1954,6 @@
DECB78170FA5882F00F5FBC7 /* PCHWriterStmt.cpp in Sources */,
1A2A54B50FD1DD1C00F4CE45 /* AnalysisConsumer.cpp in Sources */,
1A2A54B60FD1DD1C00F4CE45 /* ASTConsumers.cpp in Sources */,
1A2A54B70FD1DD1C00F4CE45 /* Backend.cpp in Sources */,
1A2A54B80FD1DD1C00F4CE45 /* CacheTokens.cpp in Sources */,
1A2A54B90FD1DD1C00F4CE45 /* DependencyFile.cpp in Sources */,
1A2A54BA0FD1DD1C00F4CE45 /* DiagChecker.cpp in Sources */,
@ -1997,6 +2020,13 @@
1A621C4511111D61009E6834 /* CIndexUSRs.cpp in Sources */,
1A621C4611111D61009E6834 /* CXCursor.cpp in Sources */,
1A96785211486FDC00F24372 /* RecordLayout.cpp in Sources */,
BF89C3E211595818001C2D68 /* AnalysisBasedWarnings.cpp in Sources */,
BF89C3E91159594A001C2D68 /* SemaObjCProperty.cpp in Sources */,
BF89C3F911595A01001C2D68 /* SemaType.cpp in Sources */,
BF89C3FB11595A37001C2D68 /* SemaCodeComplete.cpp in Sources */,
BF89C3FD11595A5D001C2D68 /* SemaExceptionSpec.cpp in Sources */,
1AFDD8721161085D00AE030A /* ASTMerge.cpp in Sources */,
1AFDD8731161085D00AE030A /* CodeGenAction.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -71,7 +71,8 @@ int main(int argc, const char **argv, char * const *envp) {
Diagnostic Diags(&DiagClient);
Driver TheDriver(Path.getBasename(), Path.getDirname(),
llvm::sys::getHostTriple(),
"a.out", /*IsProduction=*/false, Diags);
"a.out", /*IsProduction=*/false, /*CXXIsProduction=*/false,
Diags);
TheDriver.setTitle("clang interpreter");
// FIXME: This is a hack to try to force the driver to do something we can

View File

@ -17,6 +17,7 @@
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/NestedNameSpecifier.h"
@ -57,6 +58,7 @@ namespace clang {
class ObjCIvarRefExpr;
class ObjCPropertyDecl;
class RecordDecl;
class StoredDeclsMap;
class TagDecl;
class TemplateTypeParmDecl;
class TranslationUnitDecl;
@ -115,7 +117,7 @@ class ASTContext {
llvm::FoldingSet<SubstTemplateTypeParmType> SubstTemplateTypeParmTypes;
llvm::FoldingSet<TemplateSpecializationType> TemplateSpecializationTypes;
llvm::FoldingSet<QualifiedNameType> QualifiedNameTypes;
llvm::FoldingSet<TypenameType> TypenameTypes;
llvm::FoldingSet<DependentNameType> DependentNameTypes;
llvm::FoldingSet<ObjCInterfaceType> ObjCInterfaceTypes;
llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes;
llvm::FoldingSet<ElaboratedType> ElaboratedTypes;
@ -264,6 +266,9 @@ class ASTContext {
llvm::MallocAllocator MallocAlloc;
llvm::BumpPtrAllocator BumpAlloc;
/// \brief Allocator for partial diagnostics.
PartialDiagnostic::StorageAllocator DiagAllocator;
public:
const TargetInfo &Target;
IdentifierTable &Idents;
@ -289,6 +294,11 @@ class ASTContext {
if (FreeMemory)
MallocAlloc.Deallocate(Ptr);
}
PartialDiagnostic::StorageAllocator &getDiagAllocator() {
return DiagAllocator;
}
const LangOptions& getLangOptions() const { return LangOpts; }
FullSourceLoc getFullLoc(SourceLocation Loc) const {
@ -437,6 +447,11 @@ class ASTContext {
/// allowable type.
QualType getCallConvType(QualType T, CallingConv CallConv);
/// getRegParmType - Sets the specified regparm attribute to
/// the given type, which must be a FunctionType or a pointer to an
/// allowable type.
QualType getRegParmType(QualType T, unsigned RegParm);
/// getComplexType - Return the uniqued reference to the type for a complex
/// number with the specified element type.
QualType getComplexType(QualType T);
@ -554,8 +569,12 @@ class ASTContext {
/// getFunctionNoProtoType - Return a K&R style C function type like 'int()'.
///
QualType getFunctionNoProtoType(QualType ResultTy, bool NoReturn = false,
CallingConv CallConv = CC_Default);
QualType getFunctionNoProtoType(QualType ResultTy,
const FunctionType::ExtInfo &Info);
QualType getFunctionNoProtoType(QualType ResultTy) {
return getFunctionNoProtoType(ResultTy, FunctionType::ExtInfo());
}
/// getFunctionType - Return a normal function type with a typed argument
/// list. isVariadic indicates whether the argument list includes '...'.
@ -564,8 +583,7 @@ class ASTContext {
unsigned TypeQuals, bool hasExceptionSpec,
bool hasAnyExceptionSpec,
unsigned NumExs, const QualType *ExArray,
bool NoReturn,
CallingConv CallConv);
const FunctionType::ExtInfo &Info);
/// getTypeDeclType - Return the unique reference to the type for
/// the specified type declaration.
@ -612,12 +630,14 @@ class ASTContext {
QualType getQualifiedNameType(NestedNameSpecifier *NNS,
QualType NamedType);
QualType getTypenameType(NestedNameSpecifier *NNS,
const IdentifierInfo *Name,
QualType Canon = QualType());
QualType getTypenameType(NestedNameSpecifier *NNS,
const TemplateSpecializationType *TemplateId,
QualType Canon = QualType());
QualType getDependentNameType(ElaboratedTypeKeyword Keyword,
NestedNameSpecifier *NNS,
const IdentifierInfo *Name,
QualType Canon = QualType());
QualType getDependentNameType(ElaboratedTypeKeyword Keyword,
NestedNameSpecifier *NNS,
const TemplateSpecializationType *TemplateId,
QualType Canon = QualType());
QualType getElaboratedType(QualType UnderlyingType,
ElaboratedType::TagKind Tag);
@ -937,8 +957,7 @@ class ASTContext {
llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars);
void CollectNonClassIvars(const ObjCInterfaceDecl *OI,
llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars);
unsigned CountSynthesizedIvars(const ObjCInterfaceDecl *OI);
unsigned CountProtocolSynthesizedIvars(const ObjCProtocolDecl *PD);
unsigned CountNonClassIvars(const ObjCInterfaceDecl *OI);
void CollectInheritedProtocols(const Decl *CDecl,
llvm::SmallPtrSet<ObjCProtocolDecl*, 8> &Protocols);
@ -1273,9 +1292,8 @@ class ASTContext {
// FIXME: This currently contains the set of StoredDeclMaps used
// by DeclContext objects. This probably should not be in ASTContext,
// but we include it here so that ASTContext can quickly deallocate them.
std::vector<void*> SDMs;
llvm::PointerIntPair<StoredDeclsMap*,1> LastSDM;
friend class DeclContext;
void *CreateStoredDeclsMap();
void ReleaseDeclContextMaps();
};

View File

@ -19,6 +19,7 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeOrdering.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include <list>
#include <map>
@ -227,6 +228,137 @@ class CXXBasePaths {
/// object.
void swap(CXXBasePaths &Other);
};
/// \brief Uniquely identifies a virtual method within a class
/// hierarchy by the method itself and a class subobject number.
struct UniqueVirtualMethod {
UniqueVirtualMethod() : Method(0), Subobject(0), InVirtualSubobject(0) { }
UniqueVirtualMethod(CXXMethodDecl *Method, unsigned Subobject,
const CXXRecordDecl *InVirtualSubobject)
: Method(Method), Subobject(Subobject),
InVirtualSubobject(InVirtualSubobject) { }
/// \brief The overriding virtual method.
CXXMethodDecl *Method;
/// \brief The subobject in which the overriding virtual method
/// resides.
unsigned Subobject;
/// \brief The virtual base class subobject of which this overridden
/// virtual method is a part. Note that this records the closest
/// derived virtual base class subobject.
const CXXRecordDecl *InVirtualSubobject;
friend bool operator==(const UniqueVirtualMethod &X,
const UniqueVirtualMethod &Y) {
return X.Method == Y.Method && X.Subobject == Y.Subobject &&
X.InVirtualSubobject == Y.InVirtualSubobject;
}
friend bool operator!=(const UniqueVirtualMethod &X,
const UniqueVirtualMethod &Y) {
return !(X == Y);
}
};
/// \brief The set of methods that override a given virtual method in
/// each subobject where it occurs.
///
/// The first part of the pair is the subobject in which the
/// overridden virtual function occurs, while the second part of the
/// pair is the virtual method that overrides it (including the
/// subobject in which that virtual function occurs).
class OverridingMethods {
llvm::DenseMap<unsigned, llvm::SmallVector<UniqueVirtualMethod, 4> >
Overrides;
public:
// Iterate over the set of subobjects that have overriding methods.
typedef llvm::DenseMap<unsigned, llvm::SmallVector<UniqueVirtualMethod, 4> >
::iterator iterator;
typedef llvm::DenseMap<unsigned, llvm::SmallVector<UniqueVirtualMethod, 4> >
::const_iterator const_iterator;
iterator begin() { return Overrides.begin(); }
const_iterator begin() const { return Overrides.begin(); }
iterator end() { return Overrides.end(); }
const_iterator end() const { return Overrides.end(); }
unsigned size() const { return Overrides.size(); }
// Iterate over the set of overriding virtual methods in a given
// subobject.
typedef llvm::SmallVector<UniqueVirtualMethod, 4>::iterator
overriding_iterator;
typedef llvm::SmallVector<UniqueVirtualMethod, 4>::const_iterator
overriding_const_iterator;
// Add a new overriding method for a particular subobject.
void add(unsigned OverriddenSubobject, UniqueVirtualMethod Overriding);
// Add all of the overriding methods from "other" into overrides for
// this method. Used when merging the overrides from multiple base
// class subobjects.
void add(const OverridingMethods &Other);
// Replace all overriding virtual methods in all subobjects with the
// given virtual method.
void replaceAll(UniqueVirtualMethod Overriding);
};
/// \brief A mapping from each virtual member function to its set of
/// final overriders.
///
/// Within a class hierarchy for a given derived class, each virtual
/// member function in that hierarchy has one or more "final
/// overriders" (C++ [class.virtual]p2). A final overrider for a
/// virtual function "f" is the virtual function that will actually be
/// invoked when dispatching a call to "f" through the
/// vtable. Well-formed classes have a single final overrider for each
/// virtual function; in abstract classes, the final overrider for at
/// least one virtual function is a pure virtual function. Due to
/// multiple, virtual inheritance, it is possible for a class to have
/// more than one final overrider. Athough this is an error (per C++
/// [class.virtual]p2), it is not considered an error here: the final
/// overrider map can represent multiple final overriders for a
/// method, and it is up to the client to determine whether they are
/// problem. For example, the following class \c D has two final
/// overriders for the virtual function \c A::f(), one in \c C and one
/// in \c D:
///
/// \code
/// struct A { virtual void f(); };
/// struct B : virtual A { virtual void f(); };
/// struct C : virtual A { virtual void f(); };
/// struct D : B, C { };
/// \endcode
///
/// This data structure contaings a mapping from every virtual
/// function *that does not override an existing virtual function* and
/// in every subobject where that virtual function occurs to the set
/// of virtual functions that override it. Thus, the same virtual
/// function \c A::f can actually occur in multiple subobjects of type
/// \c A due to multiple inheritance, and may be overriden by
/// different virtual functions in each, as in the following example:
///
/// \code
/// struct A { virtual void f(); };
/// struct B : A { virtual void f(); };
/// struct C : A { virtual void f(); };
/// struct D : B, C { };
/// \endcode
///
/// Unlike in the previous example, where the virtual functions \c
/// B::f and \c C::f both overrode \c A::f in the same subobject of
/// type \c A, in this example the two virtual functions both override
/// \c A::f but in *different* subobjects of type A. This is
/// represented by numbering the subobjects in which the overridden
/// and the overriding virtual member functions are located. Subobject
/// 0 represents the virtua base class subobject of that type, while
/// subobject numbers greater than 0 refer to non-virtual base class
/// subobjects of that type.
class CXXFinalOverriderMap
: public llvm::DenseMap<const CXXMethodDecl *, OverridingMethods> { };
} // end namespace clang

View File

@ -165,6 +165,8 @@ class CanQual {
// (dynamic) type.
static CanQual<T> CreateUnsafe(QualType Other);
void dump() const { Stored.dump(); }
void Profile(llvm::FoldingSetNodeID &ID) const {
ID.AddPointer(getAsOpaquePtr());
}
@ -562,24 +564,21 @@ struct CanProxyAdaptor<ExtVectorType> : public CanProxyBase<ExtVectorType> {
template<>
struct CanProxyAdaptor<FunctionType> : public CanProxyBase<FunctionType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, getNoReturnAttr)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(CallingConv, getCallConv)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo)
};
template<>
struct CanProxyAdaptor<FunctionNoProtoType>
: public CanProxyBase<FunctionNoProtoType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, getNoReturnAttr)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(CallingConv, getCallConv)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo)
};
template<>
struct CanProxyAdaptor<FunctionProtoType>
: public CanProxyBase<FunctionProtoType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, getNoReturnAttr)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(CallingConv, getCallConv)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumArgs)
CanQualType getArgType(unsigned i) const {
return CanQualType::CreateUnsafe(this->getTypePtr()->getArgType(i));

View File

@ -224,18 +224,26 @@ class NamespaceDecl : public NamedDecl, public DeclContext {
// NextNamespace points to the next extended declaration.
// OrigNamespace points to the original namespace declaration.
// OrigNamespace of the first namespace decl points to itself.
NamespaceDecl *OrigNamespace, *NextNamespace;
NamespaceDecl *NextNamespace;
// The (most recently entered) anonymous namespace inside this
// namespace.
NamespaceDecl *AnonymousNamespace;
/// \brief A pointer to either the original namespace definition for
/// this namespace (if the boolean value is false) or the anonymous
/// namespace that lives just inside this namespace (if the boolean
/// value is true).
///
/// We can combine these two notions because the anonymous namespace
/// must only be stored in one of the namespace declarations (so all
/// of the namespace declarations can find it). We therefore choose
/// the original namespace declaration, since all of the namespace
/// declarations have a link directly to it; the original namespace
/// declaration itself only needs to know that it is the original
/// namespace declaration (which the boolean indicates).
llvm::PointerIntPair<NamespaceDecl *, 1, bool> OrigOrAnonNamespace;
NamespaceDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id)
: NamedDecl(Namespace, DC, L, Id), DeclContext(Namespace) {
OrigNamespace = this;
NextNamespace = 0;
AnonymousNamespace = 0;
}
: NamedDecl(Namespace, DC, L, Id), DeclContext(Namespace),
NextNamespace(0), OrigOrAnonNamespace(0, true) { }
public:
static NamespaceDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id);
@ -258,22 +266,33 @@ class NamespaceDecl : public NamedDecl, public DeclContext {
void setNextNamespace(NamespaceDecl *ND) { NextNamespace = ND; }
NamespaceDecl *getOriginalNamespace() const {
return OrigNamespace;
if (OrigOrAnonNamespace.getInt())
return const_cast<NamespaceDecl *>(this);
return OrigOrAnonNamespace.getPointer();
}
void setOriginalNamespace(NamespaceDecl *ND) {
if (ND != this) {
OrigOrAnonNamespace.setPointer(ND);
OrigOrAnonNamespace.setInt(false);
}
}
void setOriginalNamespace(NamespaceDecl *ND) { OrigNamespace = ND; }
NamespaceDecl *getAnonymousNamespace() const {
return AnonymousNamespace;
return getOriginalNamespace()->OrigOrAnonNamespace.getPointer();
}
void setAnonymousNamespace(NamespaceDecl *D) {
assert(!D || D->isAnonymousNamespace());
assert(!D || D->getParent() == this);
AnonymousNamespace = D;
getOriginalNamespace()->OrigOrAnonNamespace.setPointer(D);
}
virtual NamespaceDecl *getCanonicalDecl() { return OrigNamespace; }
const NamespaceDecl *getCanonicalDecl() const { return OrigNamespace; }
virtual NamespaceDecl *getCanonicalDecl() { return getOriginalNamespace(); }
const NamespaceDecl *getCanonicalDecl() const {
return getOriginalNamespace();
}
virtual SourceRange getSourceRange() const {
return SourceRange(getLocation(), RBracLoc);
@ -1819,12 +1838,12 @@ class RecordDecl : public TagDecl {
/// If so, this cannot be contained in arrays or other structs as a member.
bool HasFlexibleArrayMember : 1;
/// AnonymousStructOrUnion - Whether this is the type of an
/// anonymous struct or union.
/// AnonymousStructOrUnion - Whether this is the type of an anonymous struct
/// or union.
bool AnonymousStructOrUnion : 1;
/// HasObjectMember - This is true if this struct has at least one
/// member containing an object
/// HasObjectMember - This is true if this struct has at least one member
/// containing an object.
bool HasObjectMember : 1;
protected:

View File

@ -41,6 +41,8 @@ class LinkageSpecDecl;
class BlockDecl;
class DeclarationName;
class CompoundStmt;
class StoredDeclsMap;
class DependentDiagnostic;
}
namespace llvm {
@ -450,15 +452,23 @@ class Decl {
/// same entity may not (and probably don't) share this property.
void setObjectOfFriendDecl(bool PreviouslyDeclared) {
unsigned OldNS = IdentifierNamespace;
assert((OldNS == IDNS_Tag || OldNS == IDNS_Ordinary ||
OldNS == (IDNS_Tag | IDNS_Ordinary))
&& "unsupported namespace for undeclared friend");
if (!PreviouslyDeclared) IdentifierNamespace = 0;
assert((OldNS & (IDNS_Tag | IDNS_Ordinary |
IDNS_TagFriend | IDNS_OrdinaryFriend)) &&
"namespace includes neither ordinary nor tag");
assert(!(OldNS & ~(IDNS_Tag | IDNS_Ordinary |
IDNS_TagFriend | IDNS_OrdinaryFriend)) &&
"namespace includes other than ordinary or tag");
if (OldNS == IDNS_Tag)
IdentifierNamespace = 0;
if (OldNS & (IDNS_Tag | IDNS_TagFriend)) {
IdentifierNamespace |= IDNS_TagFriend;
else
if (PreviouslyDeclared) IdentifierNamespace |= IDNS_Tag;
}
if (OldNS & (IDNS_Ordinary | IDNS_OrdinaryFriend)) {
IdentifierNamespace |= IDNS_OrdinaryFriend;
if (PreviouslyDeclared) IdentifierNamespace |= IDNS_Ordinary;
}
}
enum FriendObjectKind {
@ -545,9 +555,9 @@ class DeclContext {
mutable bool ExternalVisibleStorage : 1;
/// \brief Pointer to the data structure used to lookup declarations
/// within this context, which is a DenseMap<DeclarationName,
/// StoredDeclsList>.
mutable void* LookupPtr;
/// within this context (or a DependentStoredDeclsMap if this is a
/// dependent context).
mutable StoredDeclsMap *LookupPtr;
/// FirstDecl - The first declaration stored within this declaration
/// context.
@ -674,6 +684,9 @@ class DeclContext {
/// "primary" DeclContext structure, which will contain the
/// information needed to perform name lookup into this context.
DeclContext *getPrimaryContext();
const DeclContext *getPrimaryContext() const {
return const_cast<DeclContext*>(this)->getPrimaryContext();
}
/// getLookupContext - Retrieve the innermost non-transparent
/// context of this context, which corresponds to the innermost
@ -976,10 +989,15 @@ class DeclContext {
return getUsingDirectives().second;
}
// These are all defined in DependentDiagnostic.h.
class ddiag_iterator;
inline ddiag_iterator ddiag_begin() const;
inline ddiag_iterator ddiag_end() const;
// Low-level accessors
/// \brief Retrieve the internal representation of the lookup structure.
void* getLookupPtr() const { return LookupPtr; }
StoredDeclsMap* getLookupPtr() const { return LookupPtr; }
/// \brief Whether this DeclContext has external storage containing
/// additional declarations that are lexically in this context.
@ -1013,6 +1031,9 @@ class DeclContext {
void LoadLexicalDeclsFromExternalStorage() const;
void LoadVisibleDeclsFromExternalStorage() const;
friend class DependentDiagnostic;
StoredDeclsMap *CreateStoredDeclsMap(ASTContext &C) const;
void buildLookup(DeclContext *DCtx);
void makeDeclVisibleInContextImpl(NamedDecl *D);
};

View File

@ -33,6 +33,7 @@ class CXXDestructorDecl;
class CXXMethodDecl;
class CXXRecordDecl;
class CXXMemberLookupCriteria;
class CXXFinalOverriderMap;
class FriendDecl;
/// \brief Represents any kind of function declaration, whether it is a
@ -328,6 +329,10 @@ class CXXRecordDecl : public RecordDecl {
/// instantiated or specialized.
llvm::PointerUnion<ClassTemplateDecl*, MemberSpecializationInfo*>
TemplateOrInstantiation;
#ifndef NDEBUG
void CheckConversionFunction(NamedDecl *D);
#endif
protected:
CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC,
@ -549,17 +554,26 @@ class CXXRecordDecl : public RecordDecl {
return getConversionFunctions()->replace(Old, New);
}
/// Removes a conversion function from this class. The conversion
/// function must currently be a member of this class. Furthermore,
/// this class must currently be in the process of being defined.
void removeConversion(const NamedDecl *Old);
/// getVisibleConversionFunctions - get all conversion functions visible
/// in current class; including conversion function templates.
const UnresolvedSetImpl *getVisibleConversionFunctions();
/// addConversionFunction - Add a new conversion function to the
/// list of conversion functions.
void addConversionFunction(CXXConversionDecl *ConvDecl);
/// addConversionFunction - Registers a conversion function which
/// this class declares directly.
void addConversionFunction(NamedDecl *Decl) {
#ifndef NDEBUG
CheckConversionFunction(Decl);
#endif
/// \brief Add a new conversion function template to the list of conversion
/// functions.
void addConversionFunction(FunctionTemplateDecl *ConvDecl);
// We intentionally don't use the decl's access here because it
// hasn't been set yet. That's really just a misdesign in Sema.
data().Conversions.addDecl(Decl);
}
/// isAggregate - Whether this class is an aggregate (C++
/// [dcl.init.aggr]), which is a class with no user-declared
@ -879,7 +893,12 @@ class CXXRecordDecl : public RecordDecl {
static bool FindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path,
void *UserData);
/// \brief Retrieve the final overriders for each virtual member
/// function in the class hierarchy where this class is the
/// most-derived class in the class hierarchy.
void getFinalOverriders(CXXFinalOverriderMap &FinaOverriders) const;
/// viewInheritance - Renders and displays an inheritance diagram
/// for this C++ class and all of its base classes (transitively) using
/// GraphViz.
@ -935,7 +954,7 @@ class CXXMethodDecl : public FunctionDecl {
return (CD->begin_overridden_methods() != CD->end_overridden_methods());
}
/// \brief Determine whether this is a usual deallocation function
/// (C++ [basic.stc.dynamic.deallocation]p2), which is an overloaded
/// delete or delete[] operator with a particular signature.

View File

@ -24,6 +24,8 @@
namespace clang {
class DependentDiagnostic;
/// StoredDeclsList - This is an array of decls optimized a common case of only
/// containing one entry.
struct StoredDeclsList {
@ -258,8 +260,28 @@ struct StoredDeclsList {
}
};
typedef llvm::DenseMap<DeclarationName, StoredDeclsList> StoredDeclsMap;
class StoredDeclsMap
: public llvm::DenseMap<DeclarationName, StoredDeclsList> {
public:
static void DestroyAll(StoredDeclsMap *Map, bool Dependent);
private:
friend class ASTContext; // walks the chain deleting these
friend class DeclContext;
llvm::PointerIntPair<StoredDeclsMap*, 1> Previous;
};
class DependentStoredDeclsMap : public StoredDeclsMap {
public:
DependentStoredDeclsMap() : FirstDiagnostic(0) {}
private:
friend class DependentDiagnostic;
friend class DeclContext; // iterates over diagnostics
DependentDiagnostic *FirstDiagnostic;
};
} // end namespace clang

View File

@ -36,7 +36,7 @@ namespace clang {
/// The semantic context of a friend decl is its declaring class.
class FriendDecl : public Decl {
public:
typedef llvm::PointerUnion<NamedDecl*,Type*> FriendUnion;
typedef llvm::PointerUnion<NamedDecl*,TypeSourceInfo*> FriendUnion;
private:
// The declaration that's a friend of this class.
@ -73,8 +73,8 @@ class FriendDecl : public Decl {
/// possibly dependent) type, return the type; otherwise
/// return null. This is used only for C++0x's unelaborated
/// friend type declarations.
Type *getFriendType() const {
return Friend.dyn_cast<Type*>();
TypeSourceInfo *getFriendType() const {
return Friend.dyn_cast<TypeSourceInfo*>();
}
/// If this friend declaration doesn't name an unelaborated

View File

@ -1238,7 +1238,7 @@ class ClassTemplateDecl : public TemplateDecl {
/// template <typename U> friend class Foo<T>::Nested; // friend template
class FriendTemplateDecl : public Decl {
public:
typedef llvm::PointerUnion<NamedDecl*,Type*> FriendUnion;
typedef llvm::PointerUnion<NamedDecl*,TypeSourceInfo*> FriendUnion;
private:
// The number of template parameters; always non-zero.
@ -1277,8 +1277,8 @@ class FriendTemplateDecl : public Decl {
/// If this friend declaration names a templated type (or
/// a dependent member type of a templated type), return that
/// type; otherwise return null.
Type *getFriendType() const {
return Friend.dyn_cast<Type*>();
TypeSourceInfo *getFriendType() const {
return Friend.dyn_cast<TypeSourceInfo*>();
}
/// If this friend declaration names a templated function (or

View File

@ -378,7 +378,7 @@ inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
Diagnostic::ak_declarationname);
return PD;
}
} // end namespace clang
namespace llvm {

View File

@ -0,0 +1,183 @@
//===-- DependentDiagnostic.h - Dependently-generated diagnostics -*- 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 for diagnostics which may or may
// fire based on how a template is instantiated.
//
// At the moment, the only consumer of this interface is access
// control.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_DEPENDENT_DIAGNOSTIC_H
#define LLVM_CLANG_AST_DEPENDENT_DIAGNOSTIC_H
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclContextInternals.h"
namespace clang {
class ASTContext;
class CXXRecordDecl;
class NamedDecl;
/// A dependently-generated diagnostic.
class DependentDiagnostic {
public:
enum AccessNonce { Access = 0 };
static DependentDiagnostic *Create(ASTContext &Context,
DeclContext *Parent,
AccessNonce _,
SourceLocation Loc,
bool IsMemberAccess,
AccessSpecifier AS,
NamedDecl *TargetDecl,
CXXRecordDecl *NamingClass,
const PartialDiagnostic &PDiag) {
DependentDiagnostic *DD = Create(Context, Parent, PDiag);
DD->AccessData.Loc = Loc.getRawEncoding();
DD->AccessData.IsMember = IsMemberAccess;
DD->AccessData.Access = AS;
DD->AccessData.TargetDecl = TargetDecl;
DD->AccessData.NamingClass = NamingClass;
return DD;
}
unsigned getKind() const {
return Access;
}
bool isAccessToMember() const {
assert(getKind() == Access);
return AccessData.IsMember;
}
AccessSpecifier getAccess() const {
assert(getKind() == Access);
return AccessSpecifier(AccessData.Access);
}
SourceLocation getAccessLoc() const {
assert(getKind() == Access);
return SourceLocation::getFromRawEncoding(AccessData.Loc);
}
NamedDecl *getAccessTarget() const {
assert(getKind() == Access);
return AccessData.TargetDecl;
}
NamedDecl *getAccessNamingClass() const {
assert(getKind() == Access);
return AccessData.NamingClass;
}
const PartialDiagnostic &getDiagnostic() const {
return Diag;
}
private:
DependentDiagnostic(const PartialDiagnostic &PDiag,
PartialDiagnostic::Storage *Storage)
: Diag(PDiag, Storage) {}
static DependentDiagnostic *Create(ASTContext &Context,
DeclContext *Parent,
const PartialDiagnostic &PDiag);
friend class DependentStoredDeclsMap;
friend class DeclContext::ddiag_iterator;
DependentDiagnostic *NextDiagnostic;
PartialDiagnostic Diag;
union {
struct {
unsigned Loc;
unsigned Access : 2;
unsigned IsMember : 1;
NamedDecl *TargetDecl;
CXXRecordDecl *NamingClass;
} AccessData;
};
};
///
/// An iterator over the dependent diagnostics in a dependent context.
class DeclContext::ddiag_iterator {
public:
ddiag_iterator() : Ptr(0) {}
explicit ddiag_iterator(DependentDiagnostic *Ptr) : Ptr(Ptr) {}
typedef DependentDiagnostic *value_type;
typedef DependentDiagnostic *reference;
typedef DependentDiagnostic *pointer;
typedef int difference_type;
typedef std::forward_iterator_tag iterator_category;
reference operator*() const { return Ptr; }
ddiag_iterator &operator++() {
assert(Ptr && "attempt to increment past end of diag list");
Ptr = Ptr->NextDiagnostic;
return *this;
}
ddiag_iterator operator++(int) {
ddiag_iterator tmp = *this;
++*this;
return tmp;
}
bool operator==(ddiag_iterator Other) const {
return Ptr == Other.Ptr;
}
bool operator!=(ddiag_iterator Other) const {
return Ptr != Other.Ptr;
}
ddiag_iterator &operator+=(difference_type N) {
assert(N >= 0 && "cannot rewind a DeclContext::ddiag_iterator");
while (N--)
++*this;
return *this;
}
ddiag_iterator operator+(difference_type N) const {
ddiag_iterator tmp = *this;
tmp += N;
return tmp;
}
private:
DependentDiagnostic *Ptr;
};
inline DeclContext::ddiag_iterator DeclContext::ddiag_begin() const {
assert(isDependentContext()
&& "cannot iterate dependent diagnostics of non-dependent context");
const DependentStoredDeclsMap *Map
= static_cast<DependentStoredDeclsMap*>(getPrimaryContext()->LookupPtr);
if (!Map) return ddiag_iterator();
return ddiag_iterator(Map->FirstDiagnostic);
}
inline DeclContext::ddiag_iterator DeclContext::ddiag_end() const {
return ddiag_iterator();
}
}
#endif

View File

@ -1263,6 +1263,11 @@ class CallExpr : public Expr {
/// MemberExpr - [C99 6.5.2.3] Structure and Union Members. X->F and X.F.
///
class MemberExpr : public Expr {
/// Extra data stored in some member expressions.
struct MemberNameQualifier : public NameQualifier {
NamedDecl *FoundDecl;
};
/// Base - the expression for the base pointer or structure references. In
/// X.F, this is "X".
Stmt *Base;
@ -1278,27 +1283,26 @@ class MemberExpr : public Expr {
bool IsArrow : 1;
/// \brief True if this member expression used a nested-name-specifier to
/// refer to the member, e.g., "x->Base::f". When true, a NameQualifier
/// refer to the member, e.g., "x->Base::f", or found its member via a using
/// declaration. When true, a MemberNameQualifier
/// structure is allocated immediately after the MemberExpr.
bool HasQualifier : 1;
bool HasQualifierOrFoundDecl : 1;
/// \brief True if this member expression specified a template argument list
/// explicitly, e.g., x->f<int>. When true, an ExplicitTemplateArgumentList
/// structure (and its TemplateArguments) are allocated immediately after
/// the MemberExpr or, if the member expression also has a qualifier, after
/// the NameQualifier structure.
/// the MemberNameQualifier structure.
bool HasExplicitTemplateArgumentList : 1;
/// \brief Retrieve the qualifier that preceded the member name, if any.
NameQualifier *getMemberQualifier() {
if (!HasQualifier)
return 0;
return reinterpret_cast<NameQualifier *> (this + 1);
MemberNameQualifier *getMemberQualifier() {
assert(HasQualifierOrFoundDecl);
return reinterpret_cast<MemberNameQualifier *> (this + 1);
}
/// \brief Retrieve the qualifier that preceded the member name, if any.
const NameQualifier *getMemberQualifier() const {
const MemberNameQualifier *getMemberQualifier() const {
return const_cast<MemberExpr *>(this)->getMemberQualifier();
}
@ -1308,7 +1312,7 @@ class MemberExpr : public Expr {
if (!HasExplicitTemplateArgumentList)
return 0;
if (!HasQualifier)
if (!HasQualifierOrFoundDecl)
return reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1);
return reinterpret_cast<ExplicitTemplateArgumentList *>(
@ -1321,26 +1325,22 @@ class MemberExpr : public Expr {
return const_cast<MemberExpr *>(this)->getExplicitTemplateArgumentList();
}
MemberExpr(Expr *base, bool isarrow, NestedNameSpecifier *qual,
SourceRange qualrange, ValueDecl *memberdecl, SourceLocation l,
const TemplateArgumentListInfo *targs, QualType ty);
public:
MemberExpr(Expr *base, bool isarrow, ValueDecl *memberdecl,
SourceLocation l, QualType ty)
: Expr(MemberExprClass, ty,
base->isTypeDependent(), base->isValueDependent()),
Base(base), MemberDecl(memberdecl), MemberLoc(l), IsArrow(isarrow),
HasQualifier(false), HasExplicitTemplateArgumentList(false) {}
HasQualifierOrFoundDecl(false), HasExplicitTemplateArgumentList(false) {}
/// \brief Build an empty member reference expression.
explicit MemberExpr(EmptyShell Empty)
: Expr(MemberExprClass, Empty), HasQualifier(false),
: Expr(MemberExprClass, Empty), HasQualifierOrFoundDecl(false),
HasExplicitTemplateArgumentList(false) { }
static MemberExpr *Create(ASTContext &C, Expr *base, bool isarrow,
NestedNameSpecifier *qual, SourceRange qualrange,
ValueDecl *memberdecl,
ValueDecl *memberdecl, NamedDecl *founddecl,
SourceLocation l,
const TemplateArgumentListInfo *targs,
QualType ty);
@ -1355,16 +1355,23 @@ class MemberExpr : public Expr {
ValueDecl *getMemberDecl() const { return MemberDecl; }
void setMemberDecl(ValueDecl *D) { MemberDecl = D; }
/// \brief Retrieves the declaration found by lookup.
NamedDecl *getFoundDecl() const {
if (!HasQualifierOrFoundDecl)
return getMemberDecl();
return getMemberQualifier()->FoundDecl;
}
/// \brief Determines whether this member expression actually had
/// a C++ nested-name-specifier prior to the name of the member, e.g.,
/// x->Base::foo.
bool hasQualifier() const { return HasQualifier; }
bool hasQualifier() const { return getQualifier() != 0; }
/// \brief If the member name was qualified, retrieves the source range of
/// the nested-name-specifier that precedes the member name. Otherwise,
/// returns an empty source range.
SourceRange getQualifierRange() const {
if (!HasQualifier)
if (!HasQualifierOrFoundDecl)
return SourceRange();
return getMemberQualifier()->Range;
@ -1374,7 +1381,7 @@ class MemberExpr : public Expr {
/// nested-name-specifier that precedes the member name. Otherwise, returns
/// NULL.
NestedNameSpecifier *getQualifier() const {
if (!HasQualifier)
if (!HasQualifierOrFoundDecl)
return 0;
return getMemberQualifier()->NNS;
@ -1545,6 +1552,10 @@ class CastExpr : public Expr {
/// CK_DerivedToBase - Derived to base class casts.
CK_DerivedToBase,
/// CK_UncheckedDerivedToBase - Derived to base class casts that
/// assume that the derived pointer is not null.
CK_UncheckedDerivedToBase,
/// CK_Dynamic - Dynamic cast.
CK_Dynamic,

View File

@ -1095,8 +1095,8 @@ class CXXPseudoDestructorExpr : public Expr {
: Expr(CXXPseudoDestructorExprClass,
Context.getPointerType(Context.getFunctionType(Context.VoidTy, 0, 0,
false, 0, false,
false, 0, 0, false,
CC_Default)),
false, 0, 0,
FunctionType::ExtInfo())),
/*isTypeDependent=*/(Base->isTypeDependent() ||
(DestroyedType.getTypeSourceInfo() &&
DestroyedType.getTypeSourceInfo()->getType()->isDependentType())),

View File

@ -17,6 +17,7 @@
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/Linkage.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/TemplateName.h"
#include "llvm/Support/Casting.h"
@ -678,14 +679,6 @@ class QualType {
return getObjCGCAttr() == Qualifiers::Strong;
}
/// getNoReturnAttr - Returns true if the type has the noreturn attribute,
/// 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
@ -902,6 +895,9 @@ class Type {
bool isDependentType() const { return Dependent; }
bool isOverloadableType() const;
/// \brief Determine wither this type is a C++ elaborated-type-specifier.
bool isElaboratedTypeSpecifier() const;
/// hasPointerRepresentation - Whether this type is represented
/// natively as a pointer; this includes pointers, references, block
/// pointers, and Objective-C interface, qualified id, and qualified
@ -1747,25 +1743,101 @@ class FunctionType : public Type {
/// NoReturn - Indicates if the function type is attribute noreturn.
unsigned NoReturn : 1;
/// RegParm - How many arguments to pass inreg.
unsigned RegParm : 3;
/// CallConv - The calling convention used by the function.
unsigned CallConv : 2;
// The type returned by the function.
QualType ResultType;
public:
// This class is used for passing arround the information needed to
// construct a call. It is not actually used for storage, just for
// factoring together common arguments.
// If you add a field (say Foo), other than the obvious places (both, constructors,
// compile failures), what you need to update is
// * Operetor==
// * getFoo
// * withFoo
// * functionType. Add Foo, getFoo.
// * ASTContext::getFooType
// * ASTContext::mergeFunctionTypes
// * FunctionNoProtoType::Profile
// * FunctionProtoType::Profile
// * TypePrinter::PrintFunctionProto
// * PCH read and write
// * Codegen
class ExtInfo {
public:
// Constructor with no defaults. Use this when you know that you
// have all the elements (when reading a PCH file for example).
ExtInfo(bool noReturn, unsigned regParm, CallingConv cc) :
NoReturn(noReturn), RegParm(regParm), CC(cc) {}
// Constructor with all defaults. Use when for example creating a
// function know to use defaults.
ExtInfo() : NoReturn(false), RegParm(0), CC(CC_Default) {}
bool getNoReturn() const { return NoReturn; }
unsigned getRegParm() const { return RegParm; }
CallingConv getCC() const { return CC; }
bool operator==(const ExtInfo &Other) const {
return getNoReturn() == Other.getNoReturn() &&
getRegParm() == Other.getRegParm() &&
getCC() == Other.getCC();
}
bool operator!=(const ExtInfo &Other) const {
return !(*this == Other);
}
// Note that we don't have setters. That is by design, use
// the following with methods instead of mutating these objects.
ExtInfo withNoReturn(bool noReturn) const {
return ExtInfo(noReturn, getRegParm(), getCC());
}
ExtInfo withRegParm(unsigned RegParm) const {
return ExtInfo(getNoReturn(), RegParm, getCC());
}
ExtInfo withCallingConv(CallingConv cc) const {
return ExtInfo(getNoReturn(), getRegParm(), cc);
}
private:
// True if we have __attribute__((noreturn))
bool NoReturn;
// The value passed to __attribute__((regparm(x)))
unsigned RegParm;
// The calling convention as specified via
// __attribute__((cdecl|stdcall||fastcall))
CallingConv CC;
};
protected:
FunctionType(TypeClass tc, QualType res, bool SubclassInfo,
unsigned typeQuals, QualType Canonical, bool Dependent,
bool noReturn = false, CallingConv callConv = CC_Default)
const ExtInfo &Info)
: Type(tc, Canonical, Dependent),
SubClassData(SubclassInfo), TypeQuals(typeQuals), NoReturn(noReturn),
CallConv(callConv), ResultType(res) {}
SubClassData(SubclassInfo), TypeQuals(typeQuals),
NoReturn(Info.getNoReturn()),
RegParm(Info.getRegParm()), CallConv(Info.getCC()), ResultType(res) {}
bool getSubClassData() const { return SubClassData; }
unsigned getTypeQuals() const { return TypeQuals; }
public:
QualType getResultType() const { return ResultType; }
unsigned getRegParmType() const { return RegParm; }
bool getNoReturnAttr() const { return NoReturn; }
CallingConv getCallConv() const { return (CallingConv)CallConv; }
ExtInfo getExtInfo() const {
return ExtInfo(NoReturn, RegParm, (CallingConv)CallConv);
}
static llvm::StringRef getNameForCallConv(CallingConv CC);
@ -1780,9 +1852,9 @@ class FunctionType : public Type {
/// no information available about its arguments.
class FunctionNoProtoType : public FunctionType, public llvm::FoldingSetNode {
FunctionNoProtoType(QualType Result, QualType Canonical,
bool NoReturn = false, CallingConv CallConv = CC_Default)
const ExtInfo &Info)
: FunctionType(FunctionNoProto, Result, false, 0, Canonical,
/*Dependent=*/false, NoReturn, CallConv) {}
/*Dependent=*/false, Info) {}
friend class ASTContext; // ASTContext creates these.
public:
// No additional state past what FunctionType provides.
@ -1791,12 +1863,13 @@ class FunctionNoProtoType : public FunctionType, public llvm::FoldingSetNode {
QualType desugar() const { return QualType(this, 0); }
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getResultType(), getNoReturnAttr(), getCallConv());
Profile(ID, getResultType(), getExtInfo());
}
static void Profile(llvm::FoldingSetNodeID &ID, QualType ResultType,
bool NoReturn, CallingConv CallConv) {
ID.AddInteger(CallConv);
ID.AddInteger(NoReturn);
const ExtInfo &Info) {
ID.AddInteger(Info.getCC());
ID.AddInteger(Info.getRegParm());
ID.AddInteger(Info.getNoReturn());
ID.AddPointer(ResultType.getAsOpaquePtr());
}
@ -1827,12 +1900,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,
CallingConv CallConv)
unsigned numExs, QualType Canonical,
const ExtInfo &Info)
: FunctionType(FunctionProto, Result, isVariadic, typeQuals, Canonical,
(Result->isDependentType() ||
hasAnyDependentType(ArgArray, numArgs)), NoReturn,
CallConv),
hasAnyDependentType(ArgArray, numArgs)),
Info),
NumArgs(numArgs), NumExceptions(numExs), HasExceptionSpec(hasExs),
AnyExceptionSpec(hasAnyExs) {
// Fill in the trailing argument array.
@ -1918,7 +1991,7 @@ class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode {
bool isVariadic, unsigned TypeQuals,
bool hasExceptionSpec, bool anyExceptionSpec,
unsigned NumExceptions, exception_iterator Exs,
bool NoReturn, CallingConv CallConv);
const ExtInfo &ExtInfo);
};
@ -2481,6 +2554,24 @@ class InjectedClassNameType : public Type {
static bool classof(const InjectedClassNameType *T) { return true; }
};
/// \brief The elaboration keyword that precedes a qualified type name or
/// introduces an elaborated-type-specifier.
enum ElaboratedTypeKeyword {
/// \brief No keyword precedes the qualified type name.
ETK_None,
/// \brief The "typename" keyword precedes the qualified type name, e.g.,
/// \c typename T::type.
ETK_Typename,
/// \brief The "class" keyword introduces the elaborated-type-specifier.
ETK_Class,
/// \brief The "struct" keyword introduces the elaborated-type-specifier.
ETK_Struct,
/// \brief The "union" keyword introduces the elaborated-type-specifier.
ETK_Union,
/// \brief The "enum" keyword introduces the elaborated-type-specifier.
ETK_Enum
};
/// \brief Represents a type that was referred to via a qualified
/// name, e.g., N::M::type.
///
@ -2531,19 +2622,19 @@ class QualifiedNameType : public Type, public llvm::FoldingSetNode {
static bool classof(const QualifiedNameType *T) { return true; }
};
/// \brief Represents a 'typename' specifier that names a type within
/// a dependent type, e.g., "typename T::type".
/// \brief Represents a qualified type name for which the type name is
/// dependent.
///
/// TypenameType has a very similar structure to QualifiedNameType,
/// which also involves a nested-name-specifier following by a type,
/// and (FIXME!) both can even be prefixed by the 'typename'
/// keyword. However, the two types serve very different roles:
/// QualifiedNameType is a non-semantic type that serves only as sugar
/// to show how a particular type was written in the source
/// code. TypenameType, on the other hand, only occurs when the
/// nested-name-specifier is dependent, such that we cannot resolve
/// the actual type until after instantiation.
class TypenameType : public Type, public llvm::FoldingSetNode {
/// DependentNameType represents a class of dependent types that involve a
/// dependent nested-name-specifier (e.g., "T::") followed by a (dependent)
/// name of a type. The DependentNameType may start with a "typename" (for a
/// typename-specifier), "class", "struct", "union", or "enum" (for a
/// dependent elaborated-type-specifier), or nothing (in contexts where we
/// know that we must be referring to a type, e.g., in a base class specifier).
class DependentNameType : public Type, public llvm::FoldingSetNode {
/// \brief The keyword used to elaborate this type.
ElaboratedTypeKeyword Keyword;
/// \brief The nested name specifier containing the qualifier.
NestedNameSpecifier *NNS;
@ -2553,23 +2644,28 @@ class TypenameType : public Type, public llvm::FoldingSetNode {
/// \brief The type that this typename specifier refers to.
NameType Name;
TypenameType(NestedNameSpecifier *NNS, const IdentifierInfo *Name,
QualType CanonType)
: Type(Typename, CanonType, true), NNS(NNS), Name(Name) {
DependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS,
const IdentifierInfo *Name, QualType CanonType)
: Type(DependentName, CanonType, true),
Keyword(Keyword), NNS(NNS), Name(Name) {
assert(NNS->isDependent() &&
"TypenameType requires a dependent nested-name-specifier");
"DependentNameType requires a dependent nested-name-specifier");
}
TypenameType(NestedNameSpecifier *NNS, const TemplateSpecializationType *Ty,
QualType CanonType)
: Type(Typename, CanonType, true), NNS(NNS), Name(Ty) {
DependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS,
const TemplateSpecializationType *Ty, QualType CanonType)
: Type(DependentName, CanonType, true),
Keyword(Keyword), NNS(NNS), Name(Ty) {
assert(NNS->isDependent() &&
"TypenameType requires a dependent nested-name-specifier");
"DependentNameType requires a dependent nested-name-specifier");
}
friend class ASTContext; // ASTContext creates these
public:
/// \brief Retrieve the keyword used to elaborate this type.
ElaboratedTypeKeyword getKeyword() const { return Keyword; }
/// \brief Retrieve the qualification on this type.
NestedNameSpecifier *getQualifier() const { return NNS; }
@ -2593,19 +2689,20 @@ class TypenameType : public Type, public llvm::FoldingSetNode {
QualType desugar() const { return QualType(this, 0); }
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, NNS, Name);
Profile(ID, Keyword, NNS, Name);
}
static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS,
NameType Name) {
static void Profile(llvm::FoldingSetNodeID &ID, ElaboratedTypeKeyword Keyword,
NestedNameSpecifier *NNS, NameType Name) {
ID.AddInteger(Keyword);
ID.AddPointer(NNS);
ID.AddPointer(Name.getOpaqueValue());
}
static bool classof(const Type *T) {
return T->getTypeClass() == Typename;
return T->getTypeClass() == DependentName;
}
static bool classof(const TypenameType *T) { return true; }
static bool classof(const DependentNameType *T) { return true; }
};
/// ObjCInterfaceType - Interfaces are the core concept in Objective-C for
@ -2936,37 +3033,18 @@ inline Qualifiers::GC QualType::getObjCGCAttr() const {
return Qualifiers::GCNone;
}
/// getNoReturnAttr - Returns true if the type has the noreturn attribute,
/// false otherwise.
inline bool QualType::getNoReturnAttr() const {
QualType CT = getTypePtr()->getCanonicalTypeInternal();
if (const PointerType *PT = getTypePtr()->getAs<PointerType>()) {
inline FunctionType::ExtInfo getFunctionExtInfo(const Type &t) {
if (const PointerType *PT = t.getAs<PointerType>()) {
if (const FunctionType *FT = PT->getPointeeType()->getAs<FunctionType>())
return FT->getNoReturnAttr();
} else if (const FunctionType *FT = getTypePtr()->getAs<FunctionType>())
return FT->getNoReturnAttr();
return FT->getExtInfo();
} else if (const FunctionType *FT = t.getAs<FunctionType>())
return FT->getExtInfo();
return false;
return FunctionType::ExtInfo();
}
/// 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;
inline FunctionType::ExtInfo getFunctionExtInfo(QualType t) {
return getFunctionExtInfo(*t);
}
/// isMoreQualifiedThan - Determine whether this type is more
@ -3152,6 +3230,15 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
return DB;
}
/// Insertion operator for partial diagnostics. This allows sending QualType's
/// into a diagnostic with <<.
inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
QualType T) {
PD.AddTaggedVal(reinterpret_cast<intptr_t>(T.getAsOpaquePtr()),
Diagnostic::ak_qualtype);
return PD;
}
// Helper class template that is used by Type::getAs to ensure that one does
// not try to look through a qualified type to get to an array type.
template<typename T,

View File

@ -1242,9 +1242,9 @@ class QualifiedNameTypeLoc :
};
// FIXME: locations for the typename keyword and nested name specifier.
class TypenameTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
TypenameTypeLoc,
TypenameType> {
class DependentNameTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
DependentNameTypeLoc,
DependentNameType> {
};
}

View File

@ -92,7 +92,7 @@ NON_CANONICAL_TYPE(SubstTemplateTypeParm, Type)
NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TemplateSpecialization, Type)
NON_CANONICAL_TYPE(QualifiedName, Type)
NON_CANONICAL_TYPE(InjectedClassName, Type)
DEPENDENT_TYPE(Typename, Type)
DEPENDENT_TYPE(DependentName, Type)
TYPE(ObjCInterface, Type)
TYPE(ObjCObjectPointer, Type)

View File

@ -33,7 +33,7 @@ class ParentMap;
class ImplicitParamDecl;
class LocationContextManager;
class StackFrameContext;
/// AnalysisContext contains the context data for the function or method under
/// analysis.
class AnalysisContext {
@ -41,6 +41,7 @@ class AnalysisContext {
// AnalysisContext owns the following data.
CFG *cfg;
bool builtCFG;
LiveVariables *liveness;
ParentMap *PM;
llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
@ -48,8 +49,8 @@ class AnalysisContext {
bool AddEHEdges;
public:
AnalysisContext(const Decl *d, bool addehedges = false)
: D(d), cfg(0), liveness(0), PM(0), ReferencedBlockVars(0),
AddEHEdges(addehedges) {}
: D(d), cfg(0), builtCFG(false), liveness(0), PM(0),
ReferencedBlockVars(0), AddEHEdges(addehedges) {}
~AnalysisContext();
@ -69,7 +70,7 @@ class AnalysisContext {
std::pair<referenced_decls_iterator, referenced_decls_iterator>
getReferencedBlockVars(const BlockDecl *BD);
/// Return the ImplicitParamDecl* associated with 'self' if this
/// AnalysisContext wraps an ObjCMethodDecl. Returns NULL otherwise.
const ImplicitParamDecl *getSelfDecl() const;
@ -82,7 +83,7 @@ class AnalysisContextManager {
~AnalysisContextManager();
AnalysisContext *getContext(const Decl *D);
// Discard all previously created AnalysisContexts.
void clear();
};
@ -103,7 +104,7 @@ class LocationContext : public llvm::FoldingSetNode {
public:
virtual ~LocationContext();
ContextKind getKind() const { return Kind; }
AnalysisContext *getAnalysisContext() const { return Ctx; }
@ -120,14 +121,14 @@ class LocationContext : public llvm::FoldingSetNode {
return getAnalysisContext()->getLiveVariables();
}
ParentMap &getParentMap() const {
ParentMap &getParentMap() const {
return getAnalysisContext()->getParentMap();
}
const ImplicitParamDecl *getSelfDecl() const {
return Ctx->getSelfDecl();
}
const StackFrameContext *getCurrentStackFrame() const;
const StackFrameContext *
getStackFrameForDeclContext(const DeclContext *DC) const;
@ -157,7 +158,7 @@ class StackFrameContext : public LocationContext {
friend class LocationContextManager;
StackFrameContext(AnalysisContext *ctx, const LocationContext *parent,
const Stmt *s, const CFGBlock *blk, unsigned idx)
: LocationContext(StackFrame, ctx, parent), CallSite(s), Block(blk),
: LocationContext(StackFrame, ctx, parent), CallSite(s), Block(blk),
Index(idx) {}
public:
@ -170,9 +171,9 @@ class StackFrameContext : public LocationContext {
unsigned getIndex() const { return Index; }
void Profile(llvm::FoldingSetNodeID &ID);
static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
const LocationContext *parent, const Stmt *s,
const LocationContext *parent, const Stmt *s,
const CFGBlock *blk, unsigned idx) {
ProfileCommon(ID, StackFrame, ctx, parent, s);
ID.AddPointer(blk);
@ -186,7 +187,7 @@ class StackFrameContext : public LocationContext {
class ScopeContext : public LocationContext {
const Stmt *Enter;
friend class LocationContextManager;
ScopeContext(AnalysisContext *ctx, const LocationContext *parent,
const Stmt *s)
@ -229,7 +230,7 @@ class BlockInvocationContext : public LocationContext {
const LocationContext *parent, const BlockDecl *bd) {
ProfileCommon(ID, Block, ctx, parent, bd);
}
static bool classof(const LocationContext* Ctx) {
return Ctx->getKind() == Block;
}
@ -239,7 +240,7 @@ class LocationContextManager {
llvm::FoldingSet<LocationContext> Contexts;
public:
~LocationContextManager();
const StackFrameContext *getStackFrame(AnalysisContext *ctx,
const LocationContext *parent,
const Stmt *s, const CFGBlock *blk,
@ -248,7 +249,7 @@ class LocationContextManager {
const ScopeContext *getScope(AnalysisContext *ctx,
const LocationContext *parent,
const Stmt *s);
/// Discard all previously created LocationContext objects.
void clear();
private:

View File

@ -17,7 +17,8 @@
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/ProgramPoint.h"
#include "clang/Analysis/FlowSensitive/DataflowValues.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "functional" // STL
namespace clang {
@ -28,23 +29,30 @@ namespace clang {
//===----------------------------------------------------------------------===//
class DataflowWorkListTy {
typedef llvm::SmallPtrSet<const CFGBlock*,20> BlockSet;
BlockSet wlist;
llvm::DenseMap<const CFGBlock*, unsigned char> BlockSet;
llvm::SmallVector<const CFGBlock *, 10> BlockQueue;
public:
/// enqueue - Add a block to the worklist. Blocks already on the
/// worklist are not added a second time.
void enqueue(const CFGBlock* B) { wlist.insert(B); }
void enqueue(const CFGBlock* B) {
unsigned char &x = BlockSet[B];
if (x == 1)
return;
x = 1;
BlockQueue.push_back(B);
}
/// dequeue - Remove a block from the worklist.
const CFGBlock* dequeue() {
assert (!wlist.empty());
const CFGBlock* B = *wlist.begin();
wlist.erase(B);
assert(!BlockQueue.empty());
const CFGBlock *B = BlockQueue.back();
BlockQueue.pop_back();
BlockSet[B] = 0;
return B;
}
/// isEmpty - Return true if the worklist is empty.
bool isEmpty() const { return wlist.empty(); }
bool isEmpty() const { return BlockQueue.empty(); }
};
//===----------------------------------------------------------------------===//
@ -188,10 +196,7 @@ class DataflowSolver {
/// SolveDataflowEquations - Perform the actual worklist algorithm
/// to compute dataflow values.
void SolveDataflowEquations(CFG& cfg, bool recordStmtValues) {
// Enqueue all blocks to ensure the dataflow values are computed
// for every block. Not all blocks are guaranteed to reach the exit block.
for (CFG::iterator I=cfg.begin(), E=cfg.end(); I!=E; ++I)
WorkList.enqueue(&**I);
EnqueueBlocksOnWorklist(cfg, AnalysisDirTag());
while (!WorkList.isEmpty()) {
const CFGBlock* B = WorkList.dequeue();
@ -201,6 +206,22 @@ class DataflowSolver {
}
}
void EnqueueBlocksOnWorklist(CFG &cfg, dataflow::forward_analysis_tag) {
// Enqueue all blocks to ensure the dataflow values are computed
// for every block. Not all blocks are guaranteed to reach the exit block.
for (CFG::iterator I=cfg.begin(), E=cfg.end(); I!=E; ++I)
WorkList.enqueue(&**I);
}
void EnqueueBlocksOnWorklist(CFG &cfg, dataflow::backward_analysis_tag) {
// Enqueue all blocks to ensure the dataflow values are computed
// for every block. Not all blocks are guaranteed to reach the exit block.
// Enqueue in reverse order since that will more likely match with
// the order they should ideally processed by the dataflow algorithm.
for (CFG::reverse_iterator I=cfg.rbegin(), E=cfg.rend(); I!=E; ++I)
WorkList.enqueue(&**I);
}
void ProcessMerge(CFG& cfg, const CFGBlock* B) {
ValTy& V = TF.getVal();
TF.SetTopValue(V);

View File

@ -397,13 +397,6 @@ BUILTIN(__sync_fetch_and_xor_4, "ii*i.", "n")
BUILTIN(__sync_fetch_and_xor_8, "LLiLLi*LLi.", "n")
BUILTIN(__sync_fetch_and_xor_16, "LLLiLLLi*LLLi.", "n")
BUILTIN(__sync_fetch_and_nand, "v.", "")
BUILTIN(__sync_fetch_and_nand_1, "cc*c.", "n")
BUILTIN(__sync_fetch_and_nand_2, "ss*s.", "n")
BUILTIN(__sync_fetch_and_nand_4, "ii*i.", "n")
BUILTIN(__sync_fetch_and_nand_8, "LLiLLi*LLi.", "n")
BUILTIN(__sync_fetch_and_nand_16, "LLLiLLLi*LLLi.", "n")
BUILTIN(__sync_add_and_fetch, "v.", "")
BUILTIN(__sync_add_and_fetch_1, "cc*c.", "n")
@ -440,14 +433,6 @@ BUILTIN(__sync_xor_and_fetch_4, "ii*i.", "n")
BUILTIN(__sync_xor_and_fetch_8, "LLiLLi*LLi.", "n")
BUILTIN(__sync_xor_and_fetch_16, "LLLiLLLi*LLLi.", "n")
BUILTIN(__sync_nand_and_fetch, "v.", "")
BUILTIN(__sync_nand_and_fetch_1, "cc*c.", "n")
BUILTIN(__sync_nand_and_fetch_2, "ss*s.", "n")
BUILTIN(__sync_nand_and_fetch_4, "ii*i.", "n")
BUILTIN(__sync_nand_and_fetch_8, "LLiLLi*LLi.", "n")
BUILTIN(__sync_nand_and_fetch_16, "LLLiLLLi*LLLi.", "n")
BUILTIN(__sync_bool_compare_and_swap, "v.", "")
BUILTIN(__sync_bool_compare_and_swap_1, "bcD*cc.", "n")
BUILTIN(__sync_bool_compare_and_swap_2, "bsD*ss.", "n")

View File

@ -317,4 +317,12 @@ BUILTIN(__builtin_ia32_crc32qi, "iic", "")
BUILTIN(__builtin_ia32_crc32hi, "iis", "")
BUILTIN(__builtin_ia32_crc32si, "iii", "")
BUILTIN(__builtin_ia32_crc32di, "LLiLLiLLi", "")
// AES
BUILTIN(__builtin_ia32_aesenc128, "V2LLiV2LLiV2LLi", "")
BUILTIN(__builtin_ia32_aesenclast128, "V2LLiV2LLiV2LLi", "")
BUILTIN(__builtin_ia32_aesdec128, "V2LLiV2LLiV2LLi", "")
BUILTIN(__builtin_ia32_aesdeclast128, "V2LLiV2LLiV2LLi", "")
BUILTIN(__builtin_ia32_aesimc128, "V2LLiV2LLi", "")
BUILTIN(__builtin_ia32_aeskeygenassist128, "V2LLiV2LLii", "")
#undef BUILTIN

View File

@ -1,8 +1,8 @@
macro(clang_diag_gen component)
tablegen(Diagnostic${component}Kinds.inc
-gen-clang-diags-defs -clang-component=${component})
tablegen(Diagnostic${component}Kinds.inc
-gen-clang-diags-defs -clang-component=${component})
add_custom_target(ClangDiagnostic${component}
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/Diagnostic${component}Kinds.inc)
DEPENDS Diagnostic${component}Kinds.inc)
endmacro(clang_diag_gen)
set(LLVM_TARGET_DEFINITIONS Diagnostic.td)
@ -17,4 +17,4 @@ clang_diag_gen(Sema)
tablegen(DiagnosticGroups.inc
-gen-clang-diag-groups)
add_custom_target(ClangDiagnosticGroups
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/DiagnosticGroups.inc)
DEPENDS DiagnosticGroups.inc)

View File

@ -95,7 +95,7 @@ namespace clang {
/// should also provide full recovery from such errors, such that
/// suppressing the diagnostic output can still result in successful
/// compilation.
class CodeModificationHint {
class FixItHint {
public:
/// \brief Tokens that should be removed to correct the error.
SourceRange RemoveRange;
@ -110,7 +110,7 @@ class CodeModificationHint {
/// \brief Empty code modification hint, indicating that no code
/// modification is known.
CodeModificationHint() : RemoveRange(), InsertionLoc() { }
FixItHint() : RemoveRange(), InsertionLoc() { }
bool isNull() const {
return !RemoveRange.isValid() && !InsertionLoc.isValid();
@ -118,9 +118,9 @@ class CodeModificationHint {
/// \brief Create a code modification hint that inserts the given
/// code string at a specific location.
static CodeModificationHint CreateInsertion(SourceLocation InsertionLoc,
llvm::StringRef Code) {
CodeModificationHint Hint;
static FixItHint CreateInsertion(SourceLocation InsertionLoc,
llvm::StringRef Code) {
FixItHint Hint;
Hint.InsertionLoc = InsertionLoc;
Hint.CodeToInsert = Code;
return Hint;
@ -128,17 +128,17 @@ class CodeModificationHint {
/// \brief Create a code modification hint that removes the given
/// source range.
static CodeModificationHint CreateRemoval(SourceRange RemoveRange) {
CodeModificationHint Hint;
static FixItHint CreateRemoval(SourceRange RemoveRange) {
FixItHint Hint;
Hint.RemoveRange = RemoveRange;
return Hint;
}
/// \brief Create a code modification hint that replaces the given
/// source range with the given code string.
static CodeModificationHint CreateReplacement(SourceRange RemoveRange,
llvm::StringRef Code) {
CodeModificationHint Hint;
static FixItHint CreateReplacement(SourceRange RemoveRange,
llvm::StringRef Code) {
FixItHint Hint;
Hint.RemoveRange = RemoveRange;
Hint.InsertionLoc = RemoveRange.getBegin();
Hint.CodeToInsert = Code;
@ -234,6 +234,18 @@ class Diagnostic {
void *Cookie);
void *ArgToStringCookie;
ArgToStringFnTy ArgToStringFn;
/// \brief ID of the "delayed" diagnostic, which is a (typically
/// fatal) diagnostic that had to be delayed because it was found
/// while emitting another diagnostic.
unsigned DelayedDiagID;
/// \brief First string argument for the delayed diagnostic.
std::string DelayedDiagArg1;
/// \brief Second string argument for the delayed diagnostic.
std::string DelayedDiagArg2;
public:
explicit Diagnostic(DiagnosticClient *client = 0);
~Diagnostic();
@ -377,6 +389,28 @@ class Diagnostic {
/// the diagnostic, this returns null.
static const char *getWarningOptionForDiag(unsigned DiagID);
/// \brief Enumeration describing how the the emission of a diagnostic should
/// be treated when it occurs during C++ template argument deduction.
enum SFINAEResponse {
/// \brief The diagnostic should not be reported, but it should cause
/// template argument deduction to fail.
///
/// The vast majority of errors that occur during template argument
/// deduction fall into this category.
SFINAE_SubstitutionFailure,
/// \brief The diagnostic should be suppressed entirely.
///
/// Warnings generally fall into this category.
SFINAE_Suppress,
/// \brief The diagnostic should be reported.
///
/// The diagnostic should be reported. Various fatal errors (e.g.,
/// template instantiation depth exceeded) fall into this category.
SFINAE_Report
};
/// \brief Determines whether the given built-in diagnostic ID is
/// for an error that is suppressed if it occurs during C++ template
/// argument deduction.
@ -385,7 +419,7 @@ class Diagnostic {
/// deduction fails but no diagnostic is emitted. Certain classes of
/// errors, such as those errors that involve C++ access control,
/// are not SFINAE errors.
static bool isBuiltinSFINAEDiag(unsigned DiagID);
static SFINAEResponse getDiagnosticSFINAEResponse(unsigned DiagID);
/// getDiagnosticLevel - Based on the way the client configured the Diagnostic
/// object, classify the specified diagnostic ID into a Level, consumable by
@ -400,10 +434,41 @@ class Diagnostic {
inline DiagnosticBuilder Report(FullSourceLoc Pos, unsigned DiagID);
inline DiagnosticBuilder Report(unsigned DiagID);
/// \brief Determine whethere there is already a diagnostic in flight.
bool isDiagnosticInFlight() const { return CurDiagID != ~0U; }
/// \brief Set the "delayed" diagnostic that will be emitted once
/// the current diagnostic completes.
///
/// If a diagnostic is already in-flight but the front end must
/// report a problem (e.g., with an inconsistent file system
/// state), this routine sets a "delayed" diagnostic that will be
/// emitted after the current diagnostic completes. This should
/// only be used for fatal errors detected at inconvenient
/// times. If emitting a delayed diagnostic causes a second delayed
/// diagnostic to be introduced, that second delayed diagnostic
/// will be ignored.
///
/// \param DiagID The ID of the diagnostic being delayed.
///
/// \param Arg1 A string argument that will be provided to the
/// diagnostic. A copy of this string will be stored in the
/// Diagnostic object itself.
///
/// \param Arg2 A string argument that will be provided to the
/// diagnostic. A copy of this string will be stored in the
/// Diagnostic object itself.
void SetDelayedDiagnostic(unsigned DiagID, llvm::StringRef Arg1 = "",
llvm::StringRef Arg2 = "");
/// \brief Clear out the current diagnostic.
void Clear() { CurDiagID = ~0U; }
private:
/// \brief Report the delayed diagnostic.
void ReportDelayed();
/// getDiagnosticMappingInfo - Return the mapping info currently set for the
/// specified builtin diagnostic. This returns the high bit encoding, or zero
/// if the field is completely uninitialized.
@ -454,8 +519,8 @@ class Diagnostic {
/// NumRanges - This is the number of ranges in the DiagRanges array.
unsigned char NumDiagRanges;
/// \brief The number of code modifications hints in the
/// CodeModificationHints array.
unsigned char NumCodeModificationHints;
/// FixItHints array.
unsigned char NumFixItHints;
/// DiagArgumentsKind - This is an array of ArgumentKind::ArgumentKind enum
/// values, with one for each argument. This specifies whether the argument
@ -477,11 +542,11 @@ class Diagnostic {
/// only support 10 ranges, could easily be extended if needed.
SourceRange DiagRanges[10];
enum { MaxCodeModificationHints = 3 };
enum { MaxFixItHints = 3 };
/// CodeModificationHints - If valid, provides a hint with some code
/// FixItHints - If valid, provides a hint with some code
/// to insert, remove, or modify at a particular position.
CodeModificationHint CodeModificationHints[MaxCodeModificationHints];
FixItHint FixItHints[MaxFixItHints];
/// ProcessDiag - This is the method used to report a diagnostic that is
/// finally fully formed.
@ -508,13 +573,12 @@ class Diagnostic {
/// for example.
class DiagnosticBuilder {
mutable Diagnostic *DiagObj;
mutable unsigned NumArgs, NumRanges, NumCodeModificationHints;
mutable unsigned NumArgs, NumRanges, NumFixItHints;
void operator=(const DiagnosticBuilder&); // DO NOT IMPLEMENT
friend class Diagnostic;
explicit DiagnosticBuilder(Diagnostic *diagObj)
: DiagObj(diagObj), NumArgs(0), NumRanges(0),
NumCodeModificationHints(0) {}
: DiagObj(diagObj), NumArgs(0), NumRanges(0), NumFixItHints(0) {}
public:
/// Copy constructor. When copied, this "takes" the diagnostic info from the
@ -524,7 +588,7 @@ class DiagnosticBuilder {
D.DiagObj = 0;
NumArgs = D.NumArgs;
NumRanges = D.NumRanges;
NumCodeModificationHints = D.NumCodeModificationHints;
NumFixItHints = D.NumFixItHints;
}
/// \brief Simple enumeration value used to give a name to the
@ -534,7 +598,7 @@ class DiagnosticBuilder {
/// \brief Create an empty DiagnosticBuilder object that represents
/// no actual diagnostic.
explicit DiagnosticBuilder(SuppressKind)
: DiagObj(0), NumArgs(0), NumRanges(0), NumCodeModificationHints(0) { }
: DiagObj(0), NumArgs(0), NumRanges(0), NumFixItHints(0) { }
/// \brief Force the diagnostic builder to emit the diagnostic now.
///
@ -543,29 +607,7 @@ class DiagnosticBuilder {
///
/// \returns true if a diagnostic was emitted, false if the
/// diagnostic was suppressed.
bool Emit() {
// If DiagObj is null, then its soul was stolen by the copy ctor
// or the user called Emit().
if (DiagObj == 0) return false;
// When emitting diagnostics, we set the final argument count into
// the Diagnostic object.
DiagObj->NumDiagArgs = NumArgs;
DiagObj->NumDiagRanges = NumRanges;
DiagObj->NumCodeModificationHints = NumCodeModificationHints;
// Process the diagnostic, sending the accumulated information to the
// DiagnosticClient.
bool Emitted = DiagObj->ProcessDiag();
// Clear out the current diagnostic object.
DiagObj->Clear();
// This diagnostic is dead.
DiagObj = 0;
return Emitted;
}
bool Emit();
/// Destructor - The dtor emits the diagnostic if it hasn't already
/// been emitted.
@ -605,14 +647,14 @@ class DiagnosticBuilder {
DiagObj->DiagRanges[NumRanges++] = R;
}
void AddCodeModificationHint(const CodeModificationHint &Hint) const {
void AddFixItHint(const FixItHint &Hint) const {
if (Hint.isNull())
return;
assert(NumCodeModificationHints < Diagnostic::MaxCodeModificationHints &&
"Too many code modification hints!");
assert(NumFixItHints < Diagnostic::MaxFixItHints &&
"Too many fix-it hints!");
if (DiagObj)
DiagObj->CodeModificationHints[NumCodeModificationHints++] = Hint;
DiagObj->FixItHints[NumFixItHints++] = Hint;
}
};
@ -673,8 +715,8 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
}
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
const CodeModificationHint &Hint) {
DB.AddCodeModificationHint(Hint);
const FixItHint &Hint) {
DB.AddFixItHint(Hint);
return DB;
}
@ -770,17 +812,17 @@ class DiagnosticInfo {
return DiagObj->DiagRanges[Idx];
}
unsigned getNumCodeModificationHints() const {
return DiagObj->NumCodeModificationHints;
unsigned getNumFixItHints() const {
return DiagObj->NumFixItHints;
}
const CodeModificationHint &getCodeModificationHint(unsigned Idx) const {
return DiagObj->CodeModificationHints[Idx];
const FixItHint &getFixItHint(unsigned Idx) const {
return DiagObj->FixItHints[Idx];
}
const CodeModificationHint *getCodeModificationHints() const {
return DiagObj->NumCodeModificationHints?
&DiagObj->CodeModificationHints[0] : 0;
const FixItHint *getFixItHints() const {
return DiagObj->NumFixItHints?
&DiagObj->FixItHints[0] : 0;
}
/// FormatDiagnostic - Format this diagnostic into a string, substituting the
@ -803,7 +845,7 @@ class StoredDiagnostic {
FullSourceLoc Loc;
std::string Message;
std::vector<SourceRange> Ranges;
std::vector<CodeModificationHint> FixIts;
std::vector<FixItHint> FixIts;
public:
StoredDiagnostic();
@ -823,7 +865,7 @@ class StoredDiagnostic {
range_iterator range_end() const { return Ranges.end(); }
unsigned range_size() const { return Ranges.size(); }
typedef std::vector<CodeModificationHint>::const_iterator fixit_iterator;
typedef std::vector<FixItHint>::const_iterator fixit_iterator;
fixit_iterator fixit_begin() const { return FixIts.begin(); }
fixit_iterator fixit_end() const { return FixIts.end(); }
unsigned fixit_size() const { return FixIts.size(); }

View File

@ -22,7 +22,7 @@ def err_fe_stdout_binary : Error<"unable to change standard output to binary">,
def err_fe_stderr_binary : Error<"unable to change standard error to binary">,
DefaultFatal;
def err_fe_dependency_file_requires_MT : Error<
"-dependency-file requires at least one -MT option">;
"-dependency-file requires at least one -MT or -MQ option">;
def err_fe_incompatible_options : Error<
"'%0' cannot be used with '%1'">, DefaultFatal;
def err_fe_no_fixit_and_codegen : Error<
@ -57,6 +57,9 @@ def err_fe_pch_malformed_block : Error<
"malformed block record in PCH file: '%0'">, DefaultFatal;
def err_fe_pch_error_at_end_block : Error<
"error at end of module block in PCH file: '%0'">, DefaultFatal;
def err_fe_pch_file_modified : Error<
"file '%0' has been modified since the precompiled header was built">,
DefaultFatal;
def err_fe_unable_to_open_output : Error<
"unable to open output file '%0': '%1'">;
def err_fe_unable_to_open_logfile : Error<

View File

@ -31,6 +31,7 @@ def : DiagGroup<"char-align">;
def Comment : DiagGroup<"comment">;
def : DiagGroup<"ctor-dtor-privacy">;
def : DiagGroup<"declaration-after-statement">;
def GNUDesignator : DiagGroup<"gnu-designator">;
def Deprecated : DiagGroup<"deprecated">;
def : DiagGroup<"disabled-optimization">;
def : DiagGroup<"discard-qual">;
@ -115,6 +116,7 @@ def UnusedVariable : DiagGroup<"unused-variable">;
def ReadOnlySetterAttrs : DiagGroup<"readonly-setter-attrs">;
def Reorder : DiagGroup<"reorder">;
def UndeclaredSelector : DiagGroup<"undeclared-selector">;
def Protocol : DiagGroup<"protocol">;
def SuperSubClassMismatch : DiagGroup<"super-class-method-mismatch">;
def : DiagGroup<"variadic-macros">;
def VariadicMacros : DiagGroup<"variadic-macros">;
@ -185,3 +187,6 @@ def : DiagGroup<"comments", [Comment]>; // -Wcomments = -Wcomment
// but which aren't on by default in GCC.
def NonGCC : DiagGroup<"non-gcc",
[SignCompare, Conversion, LiteralRange]>;
// A warning group for warnings about GCC extensions.
def GNU : DiagGroup<"gnu", [GNUDesignator]>;

View File

@ -50,22 +50,26 @@ def ext_enumerator_list_comma : Extension<
"feature">;
def ext_gnu_indirect_goto : Extension<
"use of GNU indirect-goto extension">;
"use of GNU indirect-goto extension">, InGroup<GNU>;
def ext_gnu_address_of_label : Extension<
"use of GNU address-of-label extension">;
"use of GNU address-of-label extension">, InGroup<GNU>;
def ext_gnu_statement_expr : Extension<
"use of GNU statement expression extension">;
"use of GNU statement expression extension">, InGroup<GNU>;
def ext_gnu_conditional_expr : Extension<
"use of GNU ?: expression extension, eliding middle term">;
"use of GNU ?: expression extension, eliding middle term">, InGroup<GNU>;
def ext_gnu_empty_initializer : Extension<
"use of GNU empty initializer extension">;
def ext_gnu_array_range : Extension<"use of GNU array range extension">;
"use of GNU empty initializer extension">, InGroup<GNU>;
def ext_gnu_array_range : Extension<"use of GNU array range extension">,
InGroup<GNUDesignator>;
def ext_gnu_missing_equal_designator : ExtWarn<
"use of GNU 'missing =' extension in designator">;
"use of GNU 'missing =' extension in designator">,
InGroup<GNUDesignator>;
def err_expected_equal_designator : Error<"expected '=' or another designator">;
def ext_gnu_old_style_field_designator : ExtWarn<
"use of GNU old-style field designator extension">;
def ext_gnu_case_range : Extension<"use of GNU case range extension">;
"use of GNU old-style field designator extension">,
InGroup<GNUDesignator>;
def ext_gnu_case_range : Extension<"use of GNU case range extension">,
InGroup<GNU>;
// Generic errors.
def err_parse_error : Error<"parse error">;

View File

@ -68,7 +68,7 @@ def err_designator_into_flexible_array_member : Error<
def note_flexible_array_member : Note<
"initialized flexible array member %0 is here">;
def ext_flexible_array_init : Extension<
"flexible array initialization is a GNU extension">;
"flexible array initialization is a GNU extension">, InGroup<GNU>;
// Declarations.
def ext_vla : Extension<
@ -268,8 +268,6 @@ def err_duplicate_ivar_declaration : Error<
"instance variable is already declared">;
def warn_on_superclass_use : Warning<
"class implementation may not have super class">;
def err_non_private_ivar_declaration : Error<
"only private ivars may be declared in implementation">;
def err_conflicting_ivar_bitwidth : Error<
"instance variable %0 has conflicting bit-field width">;
def err_conflicting_ivar_name : Error<
@ -277,7 +275,9 @@ def err_conflicting_ivar_name : Error<
def err_inconsistant_ivar_count : Error<
"inconsistent number of instance variables specified">;
def warn_incomplete_impl : Warning<"incomplete implementation">;
def warn_undef_method_impl : Warning<"method definition for %0 not found">;
def note_undef_method_impl : Note<"method definition for %0 not found">;
def note_required_for_protocol_at :
Note<"required for direct or indirect protocol %0">;
def warn_conflicting_ret_types : Warning<
"conflicting return type in implementation of %0: %1 vs %2">;
@ -350,7 +350,7 @@ def error_synthesized_ivar_yet_not_supported : Error<
" (need to declare %0 explicitly)">;
def error_property_ivar_type : Error<
"type of property %0 does not match type of ivar %1">;
"type of property %0 (%1) does not match type of ivar %2 (%3)">;
def error_ivar_in_superclass_use : Error<
"property %0 attempting to use ivar %1 declared in super class %2">;
def error_weak_property : Error<
@ -367,6 +367,8 @@ def warn_objc_property_attr_mutually_exclusive : Warning<
InGroup<ReadOnlySetterAttrs>, DefaultIgnore;
def warn_undeclared_selector : Warning<
"undeclared selector %0">, InGroup<UndeclaredSelector>, DefaultIgnore;
def warn_unimplemented_protocol_method : Warning<
"method in protocol not implemented">, InGroup<Protocol>;
// C++ declarations
def err_static_assert_expression_is_not_constant : Error<
@ -393,7 +395,11 @@ def err_abstract_type_in_decl : Error<
"%select{return|parameter|variable|field}0 type %1 is an abstract class">;
def err_allocation_of_abstract_type : Error<
"allocation of an object of abstract type %0">;
def err_multiple_final_overriders : Error<
"virtual function %q0 has more than one final overrider in %1">;
def note_final_overrider : Note<"final overrider of %q0 in %1">;
def err_type_defined_in_type_specifier : Error<
"%0 can not be defined in a type specifier">;
def err_type_defined_in_result_type : Error<
@ -432,6 +438,8 @@ def err_incompatible_exception_specs : Error<
"target exception specification is not superset of source">;
def err_deep_exception_specs_differ : Error<
"exception specifications of %select{return|argument}0 types differ">;
def warn_missing_exception_specification : Warning<
"%0 is missing exception specification '%1'">;
// C++ access checking
def err_class_redeclared_with_different_access : Error<
@ -532,6 +540,7 @@ def err_implicit_object_parameter_init : Error<
"of type %1">;
def note_field_decl : Note<"member is declared here">;
def note_ivar_decl : Note<"ivar is declared here">;
def note_bitfield_decl : Note<"bit-field is declared here">;
def note_previous_decl : Note<"%0 declared here">;
def note_member_synthesized_at : Note<
@ -776,8 +785,9 @@ def warn_redeclaration_without_attribute_prev_attribute_ignored : Warning<
def warn_attribute_ignored : Warning<"%0 attribute ignored">;
def warn_attribute_precede_definition : Warning<
"attribute declaration must precede definition">;
def warn_attribute_void_function : Warning<
"attribute %0 cannot be applied to functions without return value">;
def warn_attribute_void_function_method : Warning<
"attribute %0 cannot be applied to "
"%select{functions|Objective-C method}1 without return value">;
def warn_attribute_weak_on_field : Warning<
"__weak attribute cannot be specified on a field declaration">;
def warn_attribute_weak_on_local : Warning<
@ -1199,26 +1209,40 @@ def err_template_arg_not_integral_or_enumeral : Error<
def err_template_arg_not_ice : Error<
"non-type template argument of type %0 is not an integral constant "
"expression">;
def err_deduced_non_type_template_arg_type_mismatch : Error<
"deduced non-type template argument does not have the same type as the "
"its corresponding template parameter (%0 vs %1)">;
def err_template_arg_not_convertible : Error<
"non-type template argument of type %0 cannot be converted to a value "
"of type %1">;
def err_template_arg_negative : Error<
"non-type template argument provides negative value '%0' for unsigned "
"template parameter of type %1">;
def err_template_arg_too_large : Error<
"non-type template argument value '%0' is too large for template "
"parameter of type %1">;
def warn_template_arg_negative : Warning<
"non-type template argument with value '%0' converted to '%1' for unsigned "
"template parameter of type %2">;
def warn_template_arg_too_large : Warning<
"non-type template argument value '%0' truncated to '%1' for "
"template parameter of type %2">;
def err_template_arg_no_ref_bind : Error<
"non-type template parameter of reference type %0 cannot bind to template "
"argument of type %1">;
def err_template_arg_ref_bind_ignores_quals : Error<
"reference binding of non-type template parameter of type %0 to template "
"argument of type %1 ignores qualifiers">;
def err_template_arg_unresolved_overloaded_function : Error<
"overloaded function cannot be resolved to a non-type template parameter of "
"type %0">;
def err_template_arg_not_decl_ref : Error<
"non-type template argument does not refer to any declaration">;
def err_template_arg_not_object_or_func_form : Error<
"non-type template argument does not directly refer to an object or "
"function">;
def err_template_arg_not_address_of : Error<
"non-type template argument for template parameter of pointer type %0 must "
"have its address taken">;
def err_template_arg_address_of_non_pointer : Error<
"address taken in non-type template argument for template parameter of "
"reference type %0">;
def err_template_arg_reference_var : Error<
"non-type template argument of reference type %0 is not an object">;
def err_template_arg_field : Error<
"non-type template argument refers to non-static data member %0">;
def err_template_arg_method : Error<
@ -1251,6 +1275,8 @@ def err_template_spec_decl_function_scope : Error<
"explicit specialization of %0 in function scope">;
def err_template_spec_decl_class_scope : Error<
"explicit specialization of %0 in class scope">;
def err_template_spec_decl_friend : Error<
"cannot declare an explicit specialization in a friend">;
def err_template_spec_decl_out_of_scope_global : Error<
"%select{class template|class template partial|function template|member "
"function|static data member|member class}0 specialization of %1 must "
@ -1372,13 +1398,13 @@ def note_default_function_arg_instantiation_here : Note<
"for '%0' required here">;
def note_explicit_template_arg_substitution_here : Note<
"while substituting explicitly-specified template arguments into function "
"template %f, here">;
"template %0 %1">;
def note_function_template_deduction_instantiation_here : Note<
"while substituting deduced template arguments into function template %0, "
"here">;
"while substituting deduced template arguments into function template %0 "
"%1">;
def note_partial_spec_deduct_instantiation_here : Note<
"during template argument deduction for class template partial "
"specialization %0, here">;
"specialization %0 %1">;
def note_prior_template_arg_substitution : Note<
"while substituting prior template arguments into %select{non-type|template}0"
" template parameter%1 %2">;
@ -1537,7 +1563,8 @@ def err_forward_ref_enum : Error<
"ISO C++ forbids forward references to 'enum' types">;
def err_redefinition_of_enumerator : Error<"redefinition of enumerator %0">;
def err_duplicate_member : Error<"duplicate member %0">;
def err_misplaced_ivar : Error<"ivars may not be placed in categories">;
def err_misplaced_ivar : Error<
"ivars may not be placed in %select{categories|class extension}0">;
def ext_enum_value_not_int : Extension<
"ISO C restricts enumerator values to range of 'int' (%0 is too "
"%select{small|large}1)">;
@ -1575,6 +1602,8 @@ def err_typecheck_invalid_restrict_invalid_pointee : Error<
"pointer to function type %0 may not be 'restrict' qualified">;
def ext_typecheck_zero_array_size : Extension<
"zero size arrays are an extension">;
def err_typecheck_zero_array_size : Error<
"zero-length arrays are not permitted in C++">;
def err_at_least_one_initializer_needed_to_size_array : Error<
"at least one initializer value required to size array">;
def err_array_size_non_int : Error<"size of array has non-integer type %0">;
@ -1664,7 +1693,7 @@ def err_field_declared_as_function : Error<"field %0 declared as a function">;
def err_field_incomplete : Error<"field has incomplete type %0">;
def ext_variable_sized_type_in_struct : ExtWarn<
"field %0 with variable sized type %1 not at the end of a struct or class is"
" a GNU extension">;
" a GNU extension">, InGroup<GNU>;
def err_flexible_array_empty_struct : Error<
"flexible array %0 not allowed in otherwise empty struct">;
@ -2164,7 +2193,7 @@ def err_invalid_declarator_global_scope : Error<
def err_invalid_declarator_in_function : Error<
"definition or redeclaration of %0 not allowed inside a function">;
def err_not_tag_in_scope : Error<
"%0 does not name a tag member in the specified scope">;
"no %select{struct|union|class|enum}0 named %1 in %2">;
def err_cannot_form_pointer_to_member_of_reference_type : Error<
"cannot form a pointer-to-member to member %0 of reference type %1">;
@ -2322,7 +2351,8 @@ def warn_typecheck_cond_pointer_integer_mismatch : ExtWarn<
def err_typecheck_choose_expr_requires_constant : Error<
"'__builtin_choose_expr' requires a constant expression">;
def ext_typecheck_expression_not_constant_but_accepted : Extension<
"expression is not a constant, but is accepted as one by GNU extensions">;
"expression is not a constant, but is accepted as one by GNU extensions">,
InGroup<GNU>;
def warn_unused_expr : Warning<"expression result unused">,
InGroup<UnusedValue>;
def warn_unused_property_expr : Warning<
@ -2334,6 +2364,7 @@ def warn_unused_call : Warning<
def err_incomplete_type_used_in_type_trait_expr : Error<
"incomplete type %0 used in type trait expression">;
def err_expected_ident_or_lparen : Error<"expected identifier or '('">;
// inline asm.
def err_asm_wide_character : Error<"wide string is invalid in 'asm'">;
@ -2413,9 +2444,9 @@ def err_in_class_initializer_non_constant : Error<
// C++ anonymous unions and GNU anonymous structs/unions
def ext_anonymous_union : Extension<
"anonymous unions are a GNU extension in C">;
"anonymous unions are a GNU extension in C">, InGroup<GNU>;
def ext_anonymous_struct : Extension<
"anonymous structs are a GNU extension">;
"anonymous structs are a GNU extension">, InGroup<GNU>;
def err_anonymous_union_not_static : Error<
"anonymous unions at namespace or global scope must be declared 'static'">;
def err_anonymous_union_with_storage_spec : Error<
@ -2584,6 +2615,9 @@ def warn_printf_missing_format_string : Warning<
def warn_printf_conversion_argument_type_mismatch : Warning<
"conversion specifies type %0 but the argument has type %1">,
InGroup<Format>;
def warn_printf_positional_arg_exceeds_data_args : Warning <
"data argument position '%0' exceeds the number of data arguments (%1)">,
InGroup<Format>;
def warn_printf_zero_positional_specifier : Warning<
"position arguments in format strings start counting at 1 (not 0)">,
InGroup<Format>;

View File

@ -15,19 +15,18 @@
#ifndef LLVM_CLANG_PARTIALDIAGNOSTIC_H
#define LLVM_CLANG_PARTIALDIAGNOSTIC_H
#include "clang/AST/Type.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/System/DataTypes.h"
#include <cassert>
namespace clang {
class DeclarationName;
class PartialDiagnostic {
public:
struct Storage {
Storage() : NumDiagArgs(0), NumDiagRanges(0), NumCodeModificationHints(0) {
}
Storage() : NumDiagArgs(0), NumDiagRanges(0), NumFixItHints(0) { }
enum {
/// MaxArguments - The maximum number of arguments we can hold. We
@ -44,8 +43,8 @@ class PartialDiagnostic {
unsigned char NumDiagRanges;
/// \brief The number of code modifications hints in the
/// CodeModificationHints array.
unsigned char NumCodeModificationHints;
/// FixItHints array.
unsigned char NumFixItHints;
/// DiagArgumentsKind - This is an array of ArgumentKind::ArgumentKind enum
/// values, with one for each argument. This specifies whether the argument
@ -62,13 +61,49 @@ class PartialDiagnostic {
/// only support 10 ranges, could easily be extended if needed.
SourceRange DiagRanges[10];
enum { MaxCodeModificationHints = 3 };
enum { MaxFixItHints = 3 };
/// CodeModificationHints - If valid, provides a hint with some code
/// FixItHints - If valid, provides a hint with some code
/// to insert, remove, or modify at a particular position.
CodeModificationHint CodeModificationHints[MaxCodeModificationHints];
FixItHint FixItHints[MaxFixItHints];
};
/// \brief An allocator for Storage objects, which uses a small cache to
/// objects, used to reduce malloc()/free() traffic for partial diagnostics.
class StorageAllocator {
static const unsigned NumCached = 4;
Storage Cached[NumCached];
Storage *FreeList[NumCached];
unsigned NumFreeListEntries;
public:
StorageAllocator();
~StorageAllocator();
/// \brief Allocate new storage.
Storage *Allocate() {
if (NumFreeListEntries == 0)
return new Storage;
Storage *Result = FreeList[--NumFreeListEntries];
Result->NumDiagArgs = 0;
Result->NumDiagRanges = 0;
Result->NumFixItHints = 0;
return Result;
}
/// \brief Free the given storage object.
void Deallocate(Storage *S) {
if (S >= Cached && S <= Cached + NumCached) {
FreeList[NumFreeListEntries++] = S;
return;
}
delete S;
}
};
private:
// NOTE: Sema assumes that PartialDiagnostic is location-invariant
// in the sense that its bits can be safely memcpy'ed and destructed
// in the new location.
@ -76,22 +111,40 @@ class PartialDiagnostic {
/// DiagID - The diagnostic ID.
mutable unsigned DiagID;
/// DiagStorare - Storge for args and ranges.
/// DiagStorage - Storage for args and ranges.
mutable Storage *DiagStorage;
void AddTaggedVal(intptr_t V, Diagnostic::ArgumentKind Kind) const {
if (!DiagStorage)
DiagStorage = new Storage;
/// \brief Allocator used to allocate storage for this diagnostic.
StorageAllocator *Allocator;
/// \brief Retrieve storage for this particular diagnostic.
Storage *getStorage() const {
if (DiagStorage)
return DiagStorage;
assert(DiagStorage->NumDiagArgs < Storage::MaxArguments &&
"Too many arguments to diagnostic!");
DiagStorage->DiagArgumentsKind[DiagStorage->NumDiagArgs] = Kind;
DiagStorage->DiagArgumentsVal[DiagStorage->NumDiagArgs++] = V;
if (Allocator)
DiagStorage = Allocator->Allocate();
else {
assert(Allocator != reinterpret_cast<StorageAllocator *>(~uintptr_t(0)));
DiagStorage = new Storage;
}
return DiagStorage;
}
void freeStorage() {
if (!DiagStorage)
return;
if (Allocator)
Allocator->Deallocate(DiagStorage);
else if (Allocator != reinterpret_cast<StorageAllocator *>(~uintptr_t(0)))
delete DiagStorage;
DiagStorage = 0;
}
void AddSourceRange(const SourceRange &R) const {
if (!DiagStorage)
DiagStorage = new Storage;
DiagStorage = getStorage();
assert(DiagStorage->NumDiagRanges <
llvm::array_lengthof(DiagStorage->DiagRanges) &&
@ -99,53 +152,70 @@ class PartialDiagnostic {
DiagStorage->DiagRanges[DiagStorage->NumDiagRanges++] = R;
}
void AddCodeModificationHint(const CodeModificationHint &Hint) const {
void AddFixItHint(const FixItHint &Hint) const {
if (Hint.isNull())
return;
if (!DiagStorage)
DiagStorage = new Storage;
DiagStorage = getStorage();
assert(DiagStorage->NumCodeModificationHints <
Storage::MaxCodeModificationHints &&
assert(DiagStorage->NumFixItHints < Storage::MaxFixItHints &&
"Too many code modification hints!");
DiagStorage->CodeModificationHints[DiagStorage->NumCodeModificationHints++]
DiagStorage->FixItHints[DiagStorage->NumFixItHints++]
= Hint;
}
public:
PartialDiagnostic(unsigned DiagID)
: DiagID(DiagID), DiagStorage(0) { }
PartialDiagnostic(unsigned DiagID, StorageAllocator &Allocator)
: DiagID(DiagID), DiagStorage(0), Allocator(&Allocator) { }
PartialDiagnostic(const PartialDiagnostic &Other)
: DiagID(Other.DiagID), DiagStorage(0)
: DiagID(Other.DiagID), DiagStorage(0), Allocator(Other.Allocator)
{
if (Other.DiagStorage)
DiagStorage = new Storage(*Other.DiagStorage);
if (Other.DiagStorage) {
DiagStorage = getStorage();
*DiagStorage = *Other.DiagStorage;
}
}
PartialDiagnostic(const PartialDiagnostic &Other, Storage *DiagStorage)
: DiagID(Other.DiagID), DiagStorage(DiagStorage),
Allocator(reinterpret_cast<StorageAllocator *>(~uintptr_t(0)))
{
if (Other.DiagStorage)
*this->DiagStorage = *Other.DiagStorage;
}
PartialDiagnostic &operator=(const PartialDiagnostic &Other) {
DiagID = Other.DiagID;
if (Other.DiagStorage) {
if (DiagStorage)
*DiagStorage = *Other.DiagStorage;
else
DiagStorage = new Storage(*Other.DiagStorage);
if (!DiagStorage)
DiagStorage = getStorage();
*DiagStorage = *Other.DiagStorage;
} else {
delete DiagStorage;
DiagStorage = 0;
freeStorage();
}
return *this;
}
~PartialDiagnostic() {
delete DiagStorage;
freeStorage();
}
unsigned getDiagID() const { return DiagID; }
void AddTaggedVal(intptr_t V, Diagnostic::ArgumentKind Kind) const {
if (!DiagStorage)
DiagStorage = getStorage();
assert(DiagStorage->NumDiagArgs < Storage::MaxArguments &&
"Too many arguments to diagnostic!");
DiagStorage->DiagArgumentsKind[DiagStorage->NumDiagArgs] = Kind;
DiagStorage->DiagArgumentsVal[DiagStorage->NumDiagArgs++] = V;
}
void Emit(const DiagnosticBuilder &DB) const {
if (!DiagStorage)
return;
@ -161,17 +231,19 @@ class PartialDiagnostic {
DB.AddSourceRange(DiagStorage->DiagRanges[i]);
// Add all code modification hints
for (unsigned i = 0, e = DiagStorage->NumCodeModificationHints; i != e; ++i)
DB.AddCodeModificationHint(DiagStorage->CodeModificationHints[i]);
for (unsigned i = 0, e = DiagStorage->NumFixItHints; i != e; ++i)
DB.AddFixItHint(DiagStorage->FixItHints[i]);
}
friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
QualType T) {
PD.AddTaggedVal(reinterpret_cast<intptr_t>(T.getAsOpaquePtr()),
Diagnostic::ak_qualtype);
return PD;
/// \brief Clear out this partial diagnostic, giving it a new diagnostic ID
/// and removing all of its arguments, ranges, and fix-it hints.
void Reset(unsigned DiagID = 0) {
this->DiagID = DiagID;
freeStorage();
}
bool hasStorage() const { return DiagStorage != 0; }
friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
unsigned I) {
PD.AddTaggedVal(I, Diagnostic::ak_uint);
@ -197,20 +269,13 @@ class PartialDiagnostic {
}
friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
DeclarationName N);
friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
const CodeModificationHint &Hint) {
PD.AddCodeModificationHint(Hint);
const FixItHint &Hint) {
PD.AddFixItHint(Hint);
return PD;
}
};
inline PartialDiagnostic PDiag(unsigned DiagID = 0) {
return PartialDiagnostic(DiagID);
}
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
const PartialDiagnostic &PD) {
PD.Emit(DB);
@ -219,4 +284,4 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
} // end namespace clang
#endif
#endif

View File

@ -28,7 +28,6 @@ namespace llvm {
namespace clang {
class SourceManager;
class FileEntry;
/// FileID - This is an opaque identifier used by SourceManager which refers to
/// a source file (MemoryBuffer) along with its #include path and #line data.

View File

@ -15,17 +15,12 @@
#ifndef LLVM_CLANG_ANALYSIS_BUGREPORTER
#define LLVM_CLANG_ANALYSIS_BUGREPORTER
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Checker/BugReporter/BugType.h"
#include "clang/Checker/PathSensitive/ExplodedGraph.h"
#include "clang/Checker/PathSensitive/GRState.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/ImmutableList.h"
#include "llvm/ADT/ImmutableSet.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallString.h"
#include <list>
namespace clang {
@ -35,6 +30,8 @@ class PathDiagnosticPiece;
class PathDiagnosticClient;
class ASTContext;
class Diagnostic;
class ExplodedNode;
class ExplodedGraph;
class BugReporter;
class BugReporterContext;
class GRExprEngine;

View File

@ -14,15 +14,12 @@
#ifndef LLVM_CLANG_ANALYSIS_BUGTYPE
#define LLVM_CLANG_ANALYSIS_BUGTYPE
#include <llvm/ADT/FoldingSet.h>
#include "clang/Checker/BugReporter/BugReporter.h"
#include "llvm/ADT/FoldingSet.h"
#include <string>
namespace clang {
class BugReportEquivClass;
class BugReporter;
class BuiltinBugReport;
class BugReporterContext;
class ExplodedNode;
class GRExprEngine;

View File

@ -168,7 +168,7 @@ class PathDiagnosticPiece {
private:
const std::string str;
std::vector<CodeModificationHint> CodeModificationHints;
std::vector<FixItHint> FixItHints;
const Kind kind;
const DisplayHint Hint;
std::vector<SourceRange> ranges;
@ -203,8 +203,8 @@ class PathDiagnosticPiece {
ranges.push_back(SourceRange(B,E));
}
void addCodeModificationHint(const CodeModificationHint& Hint) {
CodeModificationHints.push_back(Hint);
void addFixItHint(const FixItHint& Hint) {
FixItHints.push_back(Hint);
}
typedef const SourceRange* range_iterator;
@ -217,15 +217,15 @@ class PathDiagnosticPiece {
return ranges_begin() + ranges.size();
}
typedef const CodeModificationHint *code_modifications_iterator;
typedef const FixItHint *fixit_iterator;
code_modifications_iterator code_modifications_begin() const {
return CodeModificationHints.empty()? 0 : &CodeModificationHints[0];
fixit_iterator fixit_begin() const {
return FixItHints.empty()? 0 : &FixItHints[0];
}
code_modifications_iterator code_modifications_end() const {
return CodeModificationHints.empty()? 0
: &CodeModificationHints[0] + CodeModificationHints.size();
fixit_iterator fixit_end() const {
return FixItHints.empty()? 0
: &FixItHints[0] + FixItHints.size();
}
static inline bool classof(const PathDiagnosticPiece* P) {

View File

@ -14,7 +14,6 @@
#ifndef LLVM_CLANG_CHECKER_DS_COCOA
#define LLVM_CLANG_CHECKER_DS_COCOA
#include "clang/Basic/IdentifierTable.h"
#include "clang/AST/Type.h"
namespace clang {

View File

@ -16,7 +16,6 @@
#ifndef LLVM_CLANG_ANALYSIS_BASICVALUEFACTORY_H
#define LLVM_CLANG_ANALYSIS_BASICVALUEFACTORY_H
#include "clang/Checker/PathSensitive/SymbolManager.h"
#include "clang/Checker/PathSensitive/SVals.h"
#include "clang/AST/ASTContext.h"
#include "llvm/ADT/FoldingSet.h"

View File

@ -14,21 +14,15 @@
#ifndef LLVM_CLANG_ANALYSIS_CHECKER
#define LLVM_CLANG_ANALYSIS_CHECKER
#include "clang/Analysis/Support/SaveAndRestore.h"
#include "clang/Checker/PathSensitive/GRCoreEngine.h"
#include "clang/Checker/PathSensitive/GRState.h"
#include "clang/Checker/PathSensitive/GRExprEngine.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
//===----------------------------------------------------------------------===//
// Checker interface.
//===----------------------------------------------------------------------===//
namespace clang {
class GRExprEngine;
class CheckerContext {
ExplodedNodeSet &Dst;

View File

@ -18,11 +18,8 @@
// typedefs.
#include "clang/Checker/PathSensitive/Store.h"
#include "llvm/ADT/ImmutableMap.h"
#include "llvm/ADT/SmallVector.h"
#include "clang/Checker/PathSensitive/SVals.h"
#include "llvm/Support/Allocator.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/ImmutableMap.h"
namespace clang {

View File

@ -9,6 +9,10 @@
//
// This file defines the template classes ExplodedNode and ExplodedGraph,
// which represent a path-sensitive, intra-procedural "exploded graph."
// See "Precise interprocedural dataflow analysis via graph reachability"
// by Reps, Horwitz, and Sagiv
// (http://portal.acm.org/citation.cfm?id=199462) for the definition of an
// exploded graph.
//
//===----------------------------------------------------------------------===//

View File

@ -22,6 +22,8 @@ namespace llvm {
namespace clang {
class StackFrameContext;
class GRBlockCounter {
void* Data;
@ -30,7 +32,8 @@ class GRBlockCounter {
public:
GRBlockCounter() : Data(0) {}
unsigned getNumVisited(unsigned BlockID) const;
unsigned getNumVisited(const StackFrameContext *CallSite,
unsigned BlockID) const;
class Factory {
void* F;
@ -39,7 +42,9 @@ class GRBlockCounter {
~Factory();
GRBlockCounter GetEmptyCounter();
GRBlockCounter IncrementCount(GRBlockCounter BC, unsigned BlockID);
GRBlockCounter IncrementCount(GRBlockCounter BC,
const StackFrameContext *CallSite,
unsigned BlockID);
};
friend class Factory;

View File

@ -82,7 +82,7 @@ class GRCoreEngine {
void ProcessStmt(CFGElement E, GRStmtNodeBuilder& Builder);
bool ProcessBlockEntrance(CFGBlock* Blk, const GRState* State,
bool ProcessBlockEntrance(CFGBlock* Blk, const ExplodedNode *Pred,
GRBlockCounter BC);
@ -174,7 +174,9 @@ class GRStmtNodeBuilder {
GRBlockCounter getBlockCounter() const { return Eng.WList->getBlockCounter();}
unsigned getCurrentBlockCount() const {
return getBlockCounter().getNumVisited(B.getBlockID());
return getBlockCounter().getNumVisited(
Pred->getLocationContext()->getCurrentStackFrame(),
B.getBlockID());
}
ExplodedNode* generateNode(PostStmt PP,const GRState* St,ExplodedNode* Pred) {
@ -434,7 +436,9 @@ class GREndPathNodeBuilder {
}
unsigned getCurrentBlockCount() const {
return getBlockCounter().getNumVisited(B.getBlockID());
return getBlockCounter().getNumVisited(
Pred->getLocationContext()->getCurrentStackFrame(),
B.getBlockID());
}
ExplodedNode* generateNode(const GRState* State, const void *tag = 0,

View File

@ -16,7 +16,6 @@
#ifndef LLVM_CLANG_ANALYSIS_GREXPRENGINE
#define LLVM_CLANG_ANALYSIS_GREXPRENGINE
#include "clang/Checker/PathSensitive/AnalysisManager.h"
#include "clang/Checker/PathSensitive/GRSubEngine.h"
#include "clang/Checker/PathSensitive/GRCoreEngine.h"
#include "clang/Checker/PathSensitive/GRState.h"
@ -28,11 +27,9 @@
#include "clang/AST/ExprCXX.h"
namespace clang {
class PathDiagnosticClient;
class Diagnostic;
class ObjCForCollectionStmt;
class Checker;
class AnalysisManager;
class Checker;
class ObjCForCollectionStmt;
class GRExprEngine : public GRSubEngine {
AnalysisManager &AMgr;
@ -153,7 +150,7 @@ class GRExprEngine : public GRSubEngine {
/// ProcessBlockEntrance - Called by GRCoreEngine when start processing
/// a CFGBlock. This method returns true if the analysis should continue
/// exploring the given path, and false otherwise.
bool ProcessBlockEntrance(CFGBlock* B, const GRState* St,
bool ProcessBlockEntrance(CFGBlock* B, const ExplodedNode *Pred,
GRBlockCounter BC);
/// ProcessBranch - Called by GRCoreEngine. Used to generate successor
@ -216,7 +213,7 @@ class GRExprEngine : public GRSubEngine {
const GRState* St,
ProgramPoint::Kind K = ProgramPoint::PostStmtKind,
const void *tag = 0);
protected:
/// CheckerVisit - Dispatcher for performing checker-specific logic
/// at specific statements.
void CheckerVisit(Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
@ -351,10 +348,21 @@ class GRExprEngine : public GRSubEngine {
void VisitCXXConstructExpr(const CXXConstructExpr *E, SVal Dest,
ExplodedNode *Pred,
ExplodedNodeSet &Dst);
void VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE, ExplodedNode *Pred,
ExplodedNodeSet &Dst);
void VisitAggExpr(const Expr *E, SVal Dest, ExplodedNode *Pred,
ExplodedNodeSet &Dst);
/// Create a C++ temporary object for an rvalue.
void CreateCXXTemporaryObject(Expr *Ex, ExplodedNode *Pred,
ExplodedNodeSet &Dst);
/// Synthesize CXXThisRegion.
const CXXThisRegion *getCXXThisRegion(const CXXMethodDecl *MD,
const StackFrameContext *SFC);
/// EvalEagerlyAssume - Given the nodes in 'Src', eagerly assume symbolic
/// expressions of the form 'x != 0' and generate new nodes (stored in Dst)
/// with those assumptions.

View File

@ -17,18 +17,9 @@
#define LLVM_CLANG_ANALYSIS_GRAPICHECKS
#include "clang/Checker/PathSensitive/GRAuditor.h"
#include "clang/Checker/PathSensitive/GRState.h"
namespace clang {
class Diagnostic;
class BugReporter;
class ASTContext;
class GRExprEngine;
class PathDiagnosticClient;
class ExplodedGraph;
class GRSimpleAPICheck : public GRAuditor {
public:
GRSimpleAPICheck() {}

View File

@ -14,30 +14,22 @@
#ifndef LLVM_CLANG_ANALYSIS_VALUESTATE_H
#define LLVM_CLANG_ANALYSIS_VALUESTATE_H
// FIXME: Reduce the number of includes.
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include "clang/Analysis/Analyses/LiveVariables.h"
#include "clang/Checker/PathSensitive/ConstraintManager.h"
#include "clang/Checker/PathSensitive/Environment.h"
#include "clang/Checker/PathSensitive/GRCoreEngine.h"
#include "clang/Checker/PathSensitive/Store.h"
#include "clang/Checker/PathSensitive/ValueManager.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/ImmutableMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/DataTypes.h"
#include <functional>
namespace llvm {
class APSInt;
class BumpPtrAllocator;
class raw_ostream;
}
namespace clang {
class ASTContext;
class GRStateManager;
class Checker;
@ -302,6 +294,8 @@ class GRState : public llvm::FoldingSetNode {
template<typename T>
const GRState *remove(typename GRStateTrait<T>::key_type K,
typename GRStateTrait<T>::context_type C) const;
template <typename T>
const GRState *remove() const;
template<typename T>
const GRState *set(typename GRStateTrait<T>::data_type D) const;
@ -464,6 +458,7 @@ class GRStateManager {
// Methods that manipulate the GDM.
const GRState* addGDM(const GRState* St, void* Key, void* Data);
const GRState *removeGDM(const GRState *state, void *Key);
// Methods that query & manipulate the Store.
@ -528,6 +523,10 @@ class GRStateManager {
GRStateTrait<T>::MakeVoidPtr(GRStateTrait<T>::Remove(st->get<T>(), K, C)));
}
template <typename T>
const GRState *remove(const GRState *st) {
return removeGDM(st, GRStateTrait<T>::GDMIndex());
}
void* FindGDMContext(void* index,
void* (*CreateContext)(llvm::BumpPtrAllocator&),
@ -702,6 +701,11 @@ const GRState *GRState::remove(typename GRStateTrait<T>::key_type K,
return getStateManager().remove<T>(this, K, C);
}
template <typename T>
const GRState *GRState::remove() const {
return getStateManager().remove<T>(this);
}
template<typename T>
const GRState *GRState::set(typename GRStateTrait<T>::data_type D) const {
return getStateManager().set<T>(this, D);

View File

@ -20,6 +20,7 @@ namespace clang {
class Stmt;
class CFGBlock;
class CFGElement;
class ExplodedNode;
class GRState;
class GRStateManager;
class GRBlockCounter;
@ -47,7 +48,7 @@ class GRSubEngine {
/// ProcessBlockEntrance - Called by GRCoreEngine when start processing
/// a CFGBlock. This method returns true if the analysis should continue
/// exploring the given path, and false otherwise.
virtual bool ProcessBlockEntrance(CFGBlock* B, const GRState* St,
virtual bool ProcessBlockEntrance(CFGBlock* B, const ExplodedNode *Pred,
GRBlockCounter BC) = 0;
/// ProcessBranch - Called by GRCoreEngine. Used to generate successor

View File

@ -15,16 +15,18 @@
#ifndef LLVM_CLANG_ANALYSIS_GRTF
#define LLVM_CLANG_ANALYSIS_GRTF
#include "clang/Checker/PathSensitive/SVals.h"
#include "clang/Checker/PathSensitive/GRCoreEngine.h"
#include "clang/Checker/PathSensitive/GRState.h"
#include "clang/Checker/PathSensitive/SVals.h"
#include <vector>
namespace clang {
class ExplodedNode;
class ExplodedNodeSet;
class GREndPathNodeBuilder;
class GRExprEngine;
class ObjCMessageExpr;
class GRStmtNodeBuilder;
class GRStmtNodeBuilderRef;
class ObjCMessageExpr;
class GRTransferFuncs {
public:

View File

@ -18,17 +18,15 @@
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include "clang/Checker/PathSensitive/SymbolManager.h"
#include "clang/Checker/PathSensitive/SVals.h"
#include "clang/AST/ASTContext.h"
#include "llvm/Support/Casting.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/ImmutableList.h"
#include "llvm/ADT/ImmutableMap.h"
#include "llvm/Support/Allocator.h"
#include <string>
namespace llvm { class raw_ostream; }
namespace llvm {
class BumpPtrAllocator;
class raw_ostream;
}
namespace clang {

View File

@ -18,9 +18,6 @@
#include "clang/Checker/PathSensitive/SVals.h"
#include "clang/Checker/PathSensitive/ValueManager.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
namespace clang {

View File

@ -17,14 +17,14 @@
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include "clang/Analysis/Analyses/LiveVariables.h"
#include "clang/Analysis/AnalysisContext.h"
#include "llvm/System/DataTypes.h"
#include "llvm/Support/Allocator.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/DenseSet.h"
namespace llvm {
class raw_ostream;
class BumpPtrAllocator;
class raw_ostream;
}
namespace clang {
@ -34,9 +34,6 @@ namespace clang {
class TypedRegion;
class VarRegion;
class StackFrameContext;
}
namespace clang {
class SymExpr : public llvm::FoldingSetNode {
public:
@ -247,6 +244,7 @@ class SymSymExpr : public SymExpr {
QualType t)
: SymExpr(SymSymKind), LHS(lhs), Op(op), RHS(rhs), T(t) {}
BinaryOperator::Opcode getOpcode() const { return Op; }
const SymExpr *getLHS() const { return LHS; }
const SymExpr *getRHS() const { return RHS; }

View File

@ -15,7 +15,6 @@
#define LLVM_CLANG_CODEGEN_CODEGENOPTIONS_H
#include <string>
#include <vector>
namespace clang {

View File

@ -156,6 +156,7 @@ def dependency_file : Separate<"-dependency-file">,
HelpText<"Filename (or -) to write dependency output to">;
def sys_header_deps : Flag<"-sys-header-deps">,
HelpText<"Include system headers in dependency output">;
def MQ : Separate<"-MQ">, HelpText<"Specify target to quote for dependency">;
def MT : Separate<"-MT">, HelpText<"Specify target for dependency">;
def MP : Flag<"-MP">,
HelpText<"Create phony target for each dependency (other than main file)">;
@ -407,6 +408,8 @@ def fwritable_strings : Flag<"-fwritable-strings">,
def nostdinc : Flag<"-nostdinc">,
HelpText<"Disable standard #include directories">;
def nostdincxx : Flag<"-nostdinc++">,
HelpText<"Disable standard #include directories for the C++ standard library">;
def nobuiltininc : Flag<"-nobuiltininc">,
HelpText<"Disable builtin #include directories">;
def F : JoinedOrSeparate<"-F">, MetaVarName<"<directory>">,

View File

@ -2,10 +2,10 @@ set(LLVM_TARGET_DEFINITIONS Options.td)
tablegen(Options.inc
-gen-opt-parser-defs)
add_custom_target(ClangDriverOptions
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/Options.inc)
DEPENDS Options.inc)
set(LLVM_TARGET_DEFINITIONS CC1Options.td)
tablegen(CC1Options.inc
-gen-opt-parser-defs)
add_custom_target(ClangCC1Options
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/CC1Options.inc)
DEPENDS CC1Options.inc)

View File

@ -64,6 +64,12 @@ class Driver {
/// The path to the compiler resource directory.
std::string ResourceDir;
/// A prefix directory used to emulated a limited subset of GCC's '-Bprefix'
/// functionality.
/// FIXME: This type of customization should be removed in favor of the
/// universal driver when it is ready.
std::string PrefixDir;
/// Default host triple.
std::string DefaultHostTriple;
@ -133,7 +139,8 @@ class Driver {
Driver(llvm::StringRef _Name, llvm::StringRef _Dir,
llvm::StringRef _DefaultHostTriple,
llvm::StringRef _DefaultImageName,
bool IsProduction, Diagnostic &_Diags);
bool IsProduction, bool CXXIsProduction,
Diagnostic &_Diags);
~Driver();
/// @name Accessors

View File

@ -118,7 +118,7 @@ def ccc_ : Joined<"-ccc-">, Group<ccc_Group>, Flags<[Unsupported]>;
def _HASH_HASH_HASH : Flag<"-###">, Flags<[DriverOption]>,
HelpText<"Print the commands to run for this compilation">;
def A : JoinedOrSeparate<"-A">;
def B : JoinedOrSeparate<"-B">, Flags<[Unsupported]>;
def B : JoinedOrSeparate<"-B">;
def CC : Flag<"-CC">;
def C : Flag<"-C">;
def D : JoinedOrSeparate<"-D">, Group<CompileOnly_Group>;
@ -470,6 +470,7 @@ def noprebind : Flag<"-noprebind">;
def noseglinkedit : Flag<"-noseglinkedit">;
def nostartfiles : Flag<"-nostartfiles">;
def nostdinc : Flag<"-nostdinc">;
def nostdincxx : Flag<"-nostdinc++">;
def nostdlib : Flag<"-nostdlib">;
def object : Flag<"-object">;
def o : JoinedOrSeparate<"-o">, Flags<[DriverOption, RenderAsInput]>,

View File

@ -71,13 +71,17 @@ class HeaderSearchOptions {
/// Include the system standard include search directories.
unsigned UseStandardIncludes : 1;
/// Include the system standard C++ library include search directories.
unsigned UseStandardCXXIncludes : 1;
/// Whether header search information should be output as for -v.
unsigned Verbose : 1;
public:
HeaderSearchOptions(llvm::StringRef _Sysroot = "/")
: Sysroot(_Sysroot), UseBuiltinIncludes(true),
UseStandardIncludes(true), Verbose(false) {}
UseStandardIncludes(true), UseStandardCXXIncludes(true),
Verbose(false) {}
/// AddPath - Add the \arg Path path to the specified \arg Group list.
void AddPath(llvm::StringRef Path, frontend::IncludeDirGroup Group,

View File

@ -69,7 +69,7 @@ class TextDiagnosticPrinter : public DiagnosticClient {
void EmitCaretDiagnostic(SourceLocation Loc,
SourceRange *Ranges, unsigned NumRanges,
SourceManager &SM,
const CodeModificationHint *Hints,
const FixItHint *Hints,
unsigned NumHints,
unsigned Columns);

View File

@ -233,7 +233,7 @@ NODE_XML(QualifiedNameType, "QualifiedNameType")
TYPE_ATTRIBUTE_XML(getNamedType())
END_NODE_XML
NODE_XML(TypenameType, "TypenameType")
NODE_XML(DependentNameType, "DependentNameType")
ID_ATTRIBUTE_XML
END_NODE_XML

View File

@ -44,6 +44,12 @@ class PPCallbacks {
SrcMgr::CharacteristicKind FileType) {
}
/// EndOfMainFile - This callback is invoked when the end of the main file is
/// reach, no subsequent callbacks will be made.
virtual void EndOfMainFile() {
}
/// Ident - This callback is invoked when a #ident or #sccs directive is read.
///
virtual void Ident(SourceLocation Loc, const std::string &str) {
@ -90,6 +96,11 @@ class PPChainedCallbacks : public PPCallbacks {
Second->FileChanged(Loc, Reason, FileType);
}
virtual void EndOfMainFile() {
First->EndOfMainFile();
Second->EndOfMainFile();
}
virtual void Ident(SourceLocation Loc, const std::string &str) {
First->Ident(Loc, str);
Second->Ident(Loc, str);

View File

@ -368,6 +368,10 @@ class Preprocessor {
/// which implicitly adds the builtin defines etc.
bool EnterMainSourceFile();
/// EndSourceFile - Inform the preprocessor callbacks that processing is
/// complete.
void EndSourceFile();
/// EnterSourceFile - Add a source file to the top of the include stack and
/// start lexing tokens from it instead of the current buffer. Return true
/// and fill in ErrorStr with the error information on failure.

View File

@ -21,6 +21,7 @@
namespace clang {
class FileEntry;
class Preprocessor;
class PreprocessorLexer {

View File

@ -1761,7 +1761,8 @@ class Action : public ActionBase {
virtual void ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
DeclPtrTy TagDecl,
SourceLocation LBrac,
SourceLocation RBrac) {
SourceLocation RBrac,
AttributeList *AttrList) {
}
//===---------------------------C++ Templates----------------------------===//

View File

@ -45,7 +45,8 @@ ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM,
sigjmp_bufDecl(0), BlockDescriptorType(0), BlockDescriptorExtendedType(0),
SourceMgr(SM), LangOpts(LOpts), FreeMemory(FreeMem), Target(t),
Idents(idents), Selectors(sels),
BuiltinInfo(builtins), ExternalSource(0), PrintingPolicy(LOpts) {
BuiltinInfo(builtins), ExternalSource(0), PrintingPolicy(LOpts),
LastSDM(0, 0) {
ObjCIdRedefinitionType = QualType();
ObjCClassRedefinitionType = QualType();
ObjCSelRedefinitionType = QualType();
@ -858,34 +859,22 @@ void ASTContext::CollectInheritedProtocols(const Decl *CDecl,
}
}
unsigned ASTContext::CountProtocolSynthesizedIvars(const ObjCProtocolDecl *PD) {
unsigned count = 0;
for (ObjCContainerDecl::prop_iterator I = PD->prop_begin(),
E = PD->prop_end(); I != E; ++I)
if ((*I)->getPropertyIvarDecl())
unsigned ASTContext::CountNonClassIvars(const ObjCInterfaceDecl *OI) {
unsigned count = 0;
// Count ivars declared in class extension.
if (const ObjCCategoryDecl *CDecl = OI->getClassExtension()) {
for (ObjCCategoryDecl::ivar_iterator I = CDecl->ivar_begin(),
E = CDecl->ivar_end(); I != E; ++I) {
++count;
// Also look into nested protocols.
for (ObjCProtocolDecl::protocol_iterator P = PD->protocol_begin(),
E = PD->protocol_end(); P != E; ++P)
count += CountProtocolSynthesizedIvars(*P);
return count;
}
unsigned ASTContext::CountSynthesizedIvars(const ObjCInterfaceDecl *OI) {
unsigned count = 0;
for (ObjCInterfaceDecl::prop_iterator I = OI->prop_begin(),
E = OI->prop_end(); I != E; ++I) {
if ((*I)->getPropertyIvarDecl())
}
}
// Count ivar defined in this class's implementation. This
// includes synthesized ivars.
if (ObjCImplementationDecl *ImplDecl = OI->getImplementation())
for (ObjCImplementationDecl::ivar_iterator I = ImplDecl->ivar_begin(),
E = ImplDecl->ivar_end(); I != E; ++I)
++count;
}
// Also look into interface's protocol list for properties declared
// in the protocol and whose ivars are synthesized.
for (ObjCInterfaceDecl::protocol_iterator P = OI->protocol_begin(),
PE = OI->protocol_end(); P != PE; ++P) {
ObjCProtocolDecl *PD = (*P);
count += CountProtocolSynthesizedIvars(PD);
}
return count;
}
@ -966,7 +955,7 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D,
// Add in synthesized ivar count if laying out an implementation.
if (Impl) {
unsigned SynthCount = CountSynthesizedIvars(D);
unsigned SynthCount = CountNonClassIvars(D);
// If there aren't any sythesized ivars then reuse the interface
// entry. Note we can't cache this because we simply free all
// entries later; however we shouldn't look up implementations
@ -1108,14 +1097,12 @@ QualType ASTContext::getObjCGCQualType(QualType T,
return getExtQualType(TypeNode, Quals);
}
static QualType getNoReturnCallConvType(ASTContext& Context, QualType T,
bool AddNoReturn,
CallingConv CallConv) {
static QualType getExtFunctionType(ASTContext& Context, QualType T,
const FunctionType::ExtInfo &Info) {
QualType ResultType;
if (const PointerType *Pointer = T->getAs<PointerType>()) {
QualType Pointee = Pointer->getPointeeType();
ResultType = getNoReturnCallConvType(Context, Pointee, AddNoReturn,
CallConv);
ResultType = getExtFunctionType(Context, Pointee, Info);
if (ResultType == Pointee)
return T;
@ -1123,19 +1110,18 @@ static QualType getNoReturnCallConvType(ASTContext& Context, QualType T,
} else if (const BlockPointerType *BlockPointer
= T->getAs<BlockPointerType>()) {
QualType Pointee = BlockPointer->getPointeeType();
ResultType = getNoReturnCallConvType(Context, Pointee, AddNoReturn,
CallConv);
ResultType = getExtFunctionType(Context, Pointee, Info);
if (ResultType == Pointee)
return T;
ResultType = Context.getBlockPointerType(ResultType);
} else if (const FunctionType *F = T->getAs<FunctionType>()) {
if (F->getNoReturnAttr() == AddNoReturn && F->getCallConv() == CallConv)
if (F->getExtInfo() == Info)
return T;
if (const FunctionNoProtoType *FNPT = dyn_cast<FunctionNoProtoType>(F)) {
ResultType = Context.getFunctionNoProtoType(FNPT->getResultType(),
AddNoReturn, CallConv);
Info);
} else {
const FunctionProtoType *FPT = cast<FunctionProtoType>(F);
ResultType
@ -1146,7 +1132,7 @@ static QualType getNoReturnCallConvType(ASTContext& Context, QualType T,
FPT->hasAnyExceptionSpec(),
FPT->getNumExceptions(),
FPT->exception_begin(),
AddNoReturn, CallConv);
Info);
}
} else
return T;
@ -1155,11 +1141,21 @@ static QualType getNoReturnCallConvType(ASTContext& Context, QualType T,
}
QualType ASTContext::getNoReturnType(QualType T, bool AddNoReturn) {
return getNoReturnCallConvType(*this, T, AddNoReturn, T.getCallConv());
FunctionType::ExtInfo Info = getFunctionExtInfo(T);
return getExtFunctionType(*this, T,
Info.withNoReturn(AddNoReturn));
}
QualType ASTContext::getCallConvType(QualType T, CallingConv CallConv) {
return getNoReturnCallConvType(*this, T, T.getNoReturnAttr(), CallConv);
FunctionType::ExtInfo Info = getFunctionExtInfo(T);
return getExtFunctionType(*this, T,
Info.withCallingConv(CallConv));
}
QualType ASTContext::getRegParmType(QualType T, unsigned RegParm) {
FunctionType::ExtInfo Info = getFunctionExtInfo(T);
return getExtFunctionType(*this, T,
Info.withRegParm(RegParm));
}
/// getComplexType - Return the uniqued reference to the type for a complex
@ -1617,12 +1613,13 @@ QualType ASTContext::getDependentSizedExtVectorType(QualType vecType,
/// getFunctionNoProtoType - Return a K&R style C function type like 'int()'.
///
QualType ASTContext::getFunctionNoProtoType(QualType ResultTy, bool NoReturn,
CallingConv CallConv) {
QualType ASTContext::getFunctionNoProtoType(QualType ResultTy,
const FunctionType::ExtInfo &Info) {
const CallingConv CallConv = Info.getCC();
// Unique functions, to guarantee there is only one function of a particular
// structure.
llvm::FoldingSetNodeID ID;
FunctionNoProtoType::Profile(ID, ResultTy, NoReturn, CallConv);
FunctionNoProtoType::Profile(ID, ResultTy, Info);
void *InsertPos = 0;
if (FunctionNoProtoType *FT =
@ -1632,8 +1629,9 @@ QualType ASTContext::getFunctionNoProtoType(QualType ResultTy, bool NoReturn,
QualType Canonical;
if (!ResultTy.isCanonical() ||
getCanonicalCallConv(CallConv) != CallConv) {
Canonical = getFunctionNoProtoType(getCanonicalType(ResultTy), NoReturn,
getCanonicalCallConv(CallConv));
Canonical =
getFunctionNoProtoType(getCanonicalType(ResultTy),
Info.withCallingConv(getCanonicalCallConv(CallConv)));
// Get the new insert position for the node we care about.
FunctionNoProtoType *NewIP =
@ -1642,7 +1640,7 @@ QualType ASTContext::getFunctionNoProtoType(QualType ResultTy, bool NoReturn,
}
FunctionNoProtoType *New = new (*this, TypeAlignment)
FunctionNoProtoType(ResultTy, Canonical, NoReturn, CallConv);
FunctionNoProtoType(ResultTy, Canonical, Info);
Types.push_back(New);
FunctionNoProtoTypes.InsertNode(New, InsertPos);
return QualType(New, 0);
@ -1654,14 +1652,15 @@ 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,
CallingConv CallConv) {
const QualType *ExArray,
const FunctionType::ExtInfo &Info) {
const CallingConv CallConv= Info.getCC();
// Unique functions, to guarantee there is only one function of a particular
// structure.
llvm::FoldingSetNodeID ID;
FunctionProtoType::Profile(ID, ResultTy, ArgArray, NumArgs, isVariadic,
TypeQuals, hasExceptionSpec, hasAnyExceptionSpec,
NumExs, ExArray, NoReturn, CallConv);
NumExs, ExArray, Info);
void *InsertPos = 0;
if (FunctionProtoType *FTP =
@ -1686,8 +1685,8 @@ QualType ASTContext::getFunctionType(QualType ResultTy,const QualType *ArgArray,
Canonical = getFunctionType(getCanonicalType(ResultTy),
CanonicalArgs.data(), NumArgs,
isVariadic, TypeQuals, false,
false, 0, 0, NoReturn,
getCanonicalCallConv(CallConv));
false, 0, 0,
Info.withCallingConv(getCanonicalCallConv(CallConv)));
// Get the new insert position for the node we care about.
FunctionProtoType *NewIP =
@ -1704,7 +1703,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, CallConv);
ExArray, NumExs, Canonical, Info);
Types.push_back(FTP);
FunctionProtoTypes.InsertNode(FTP, InsertPos);
return QualType(FTP, 0);
@ -1963,66 +1962,76 @@ ASTContext::getQualifiedNameType(NestedNameSpecifier *NNS,
return QualType(T, 0);
}
QualType ASTContext::getTypenameType(NestedNameSpecifier *NNS,
const IdentifierInfo *Name,
QualType Canon) {
QualType ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword,
NestedNameSpecifier *NNS,
const IdentifierInfo *Name,
QualType Canon) {
assert(NNS->isDependent() && "nested-name-specifier must be dependent");
if (Canon.isNull()) {
NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS);
if (CanonNNS != NNS)
Canon = getTypenameType(CanonNNS, Name);
ElaboratedTypeKeyword CanonKeyword = Keyword;
if (Keyword == ETK_None)
CanonKeyword = ETK_Typename;
if (CanonNNS != NNS || CanonKeyword != Keyword)
Canon = getDependentNameType(CanonKeyword, CanonNNS, Name);
}
llvm::FoldingSetNodeID ID;
TypenameType::Profile(ID, NNS, Name);
DependentNameType::Profile(ID, Keyword, NNS, Name);
void *InsertPos = 0;
TypenameType *T
= TypenameTypes.FindNodeOrInsertPos(ID, InsertPos);
DependentNameType *T
= DependentNameTypes.FindNodeOrInsertPos(ID, InsertPos);
if (T)
return QualType(T, 0);
T = new (*this) TypenameType(NNS, Name, Canon);
T = new (*this) DependentNameType(Keyword, NNS, Name, Canon);
Types.push_back(T);
TypenameTypes.InsertNode(T, InsertPos);
DependentNameTypes.InsertNode(T, InsertPos);
return QualType(T, 0);
}
QualType
ASTContext::getTypenameType(NestedNameSpecifier *NNS,
const TemplateSpecializationType *TemplateId,
QualType Canon) {
ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword,
NestedNameSpecifier *NNS,
const TemplateSpecializationType *TemplateId,
QualType Canon) {
assert(NNS->isDependent() && "nested-name-specifier must be dependent");
llvm::FoldingSetNodeID ID;
TypenameType::Profile(ID, NNS, TemplateId);
DependentNameType::Profile(ID, Keyword, NNS, TemplateId);
void *InsertPos = 0;
TypenameType *T
= TypenameTypes.FindNodeOrInsertPos(ID, InsertPos);
DependentNameType *T
= DependentNameTypes.FindNodeOrInsertPos(ID, InsertPos);
if (T)
return QualType(T, 0);
if (Canon.isNull()) {
NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS);
QualType CanonType = getCanonicalType(QualType(TemplateId, 0));
if (CanonNNS != NNS || CanonType != QualType(TemplateId, 0)) {
ElaboratedTypeKeyword CanonKeyword = Keyword;
if (Keyword == ETK_None)
CanonKeyword = ETK_Typename;
if (CanonNNS != NNS || CanonKeyword != Keyword ||
CanonType != QualType(TemplateId, 0)) {
const TemplateSpecializationType *CanonTemplateId
= CanonType->getAs<TemplateSpecializationType>();
assert(CanonTemplateId &&
"Canonical type must also be a template specialization type");
Canon = getTypenameType(CanonNNS, CanonTemplateId);
Canon = getDependentNameType(CanonKeyword, CanonNNS, CanonTemplateId);
}
TypenameType *CheckT
= TypenameTypes.FindNodeOrInsertPos(ID, InsertPos);
DependentNameType *CheckT
= DependentNameTypes.FindNodeOrInsertPos(ID, InsertPos);
assert(!CheckT && "Typename canonical type is broken"); (void)CheckT;
}
T = new (*this) TypenameType(NNS, TemplateId, Canon);
T = new (*this) DependentNameType(Keyword, NNS, TemplateId, Canon);
Types.push_back(T);
TypenameTypes.InsertNode(T, InsertPos);
DependentNameTypes.InsertNode(T, InsertPos);
return QualType(T, 0);
}
@ -4127,14 +4136,15 @@ bool ASTContext::canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT,
bool ASTContext::canAssignObjCInterfacesInBlockPointer(
const ObjCObjectPointerType *LHSOPT,
const ObjCObjectPointerType *RHSOPT) {
if (RHSOPT->isObjCBuiltinType())
if (RHSOPT->isObjCBuiltinType() ||
LHSOPT->isObjCIdType() || LHSOPT->isObjCQualifiedIdType())
return true;
if (LHSOPT->isObjCBuiltinType()) {
return RHSOPT->isObjCBuiltinType() || RHSOPT->isObjCQualifiedIdType();
}
if (LHSOPT->isObjCQualifiedIdType() || RHSOPT->isObjCQualifiedIdType())
if (RHSOPT->isObjCQualifiedIdType())
return ObjCQualifiedIdTypesAreCompatible(QualType(LHSOPT,0),
QualType(RHSOPT,0),
false);
@ -4315,13 +4325,22 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
if (getCanonicalType(retType) != getCanonicalType(rbase->getResultType()))
allRTypes = false;
// FIXME: double check this
bool NoReturn = lbase->getNoReturnAttr() || rbase->getNoReturnAttr();
if (NoReturn != lbase->getNoReturnAttr())
// FIXME: should we error if lbase->getRegParmAttr() != 0 &&
// rbase->getRegParmAttr() != 0 &&
// lbase->getRegParmAttr() != rbase->getRegParmAttr()?
FunctionType::ExtInfo lbaseInfo = lbase->getExtInfo();
FunctionType::ExtInfo rbaseInfo = rbase->getExtInfo();
unsigned RegParm = lbaseInfo.getRegParm() == 0 ? rbaseInfo.getRegParm() :
lbaseInfo.getRegParm();
bool NoReturn = lbaseInfo.getNoReturn() || rbaseInfo.getNoReturn();
if (NoReturn != lbaseInfo.getNoReturn() ||
RegParm != lbaseInfo.getRegParm())
allLTypes = false;
if (NoReturn != rbase->getNoReturnAttr())
if (NoReturn != rbaseInfo.getNoReturn() ||
RegParm != rbaseInfo.getRegParm())
allRTypes = false;
CallingConv lcc = lbase->getCallConv();
CallingConv rcc = rbase->getCallConv();
CallingConv lcc = lbaseInfo.getCC();
CallingConv rcc = rbaseInfo.getCC();
// Compatible functions must have compatible calling conventions
if (!isSameCallConv(lcc, rcc))
return QualType();
@ -4360,7 +4379,8 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
if (allRTypes) return rhs;
return getFunctionType(retType, types.begin(), types.size(),
lproto->isVariadic(), lproto->getTypeQuals(),
false, false, 0, 0, NoReturn, lcc);
false, false, 0, 0,
FunctionType::ExtInfo(NoReturn, RegParm, lcc));
}
if (lproto) allRTypes = false;
@ -4393,13 +4413,15 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
if (allRTypes) return rhs;
return getFunctionType(retType, proto->arg_type_begin(),
proto->getNumArgs(), proto->isVariadic(),
proto->getTypeQuals(),
false, false, 0, 0, NoReturn, lcc);
proto->getTypeQuals(),
false, false, 0, 0,
FunctionType::ExtInfo(NoReturn, RegParm, lcc));
}
if (allLTypes) return lhs;
if (allRTypes) return rhs;
return getFunctionNoProtoType(retType, NoReturn, lcc);
FunctionType::ExtInfo Info(NoReturn, RegParm, lcc);
return getFunctionNoProtoType(retType, Info);
}
QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
@ -4903,7 +4925,7 @@ QualType ASTContext::GetBuiltinType(unsigned id,
// FIXME: Should we create noreturn types?
return getFunctionType(ResType, ArgTypes.data(), ArgTypes.size(),
TypeStr[0] == '.', 0, false, false, 0, 0,
false, CC_Default);
FunctionType::ExtInfo());
}
QualType

View File

@ -73,7 +73,7 @@ namespace {
// FIXME: SubstTemplateTypeParmType
// FIXME: TemplateSpecializationType
QualType VisitQualifiedNameType(QualifiedNameType *T);
// FIXME: TypenameType
// FIXME: DependentNameType
QualType VisitObjCInterfaceType(ObjCInterfaceType *T);
QualType VisitObjCObjectPointerType(ObjCObjectPointerType *T);
@ -484,10 +484,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
Function1->getResultType(),
Function2->getResultType()))
return false;
if (Function1->getNoReturnAttr() != Function2->getNoReturnAttr())
return false;
if (Function1->getCallConv() != Function2->getCallConv())
return false;
if (Function1->getExtInfo() != Function2->getExtInfo())
return false;
break;
}
@ -620,9 +618,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
break;
}
case Type::Typename: {
const TypenameType *Typename1 = cast<TypenameType>(T1);
const TypenameType *Typename2 = cast<TypenameType>(T2);
case Type::DependentName: {
const DependentNameType *Typename1 = cast<DependentNameType>(T1);
const DependentNameType *Typename2 = cast<DependentNameType>(T2);
if (!IsStructurallyEquivalent(Context,
Typename1->getQualifier(),
Typename2->getQualifier()))
@ -1200,10 +1198,9 @@ QualType ASTNodeImporter::VisitFunctionNoProtoType(FunctionNoProtoType *T) {
QualType ToResultType = Importer.Import(T->getResultType());
if (ToResultType.isNull())
return QualType();
return Importer.getToContext().getFunctionNoProtoType(ToResultType,
T->getNoReturnAttr(),
T->getCallConv());
T->getExtInfo());
}
QualType ASTNodeImporter::VisitFunctionProtoType(FunctionProtoType *T) {
@ -1241,8 +1238,7 @@ QualType ASTNodeImporter::VisitFunctionProtoType(FunctionProtoType *T) {
T->hasAnyExceptionSpec(),
ExceptionTypes.size(),
ExceptionTypes.data(),
T->getNoReturnAttr(),
T->getCallConv());
T->getExtInfo());
}
QualType ASTNodeImporter::VisitTypedefType(TypedefType *T) {

View File

@ -9,6 +9,7 @@ add_clang_library(clangAST
AttrImpl.cpp
CXXInheritance.cpp
Decl.cpp
DeclarationName.cpp
DeclBase.cpp
DeclCXX.cpp
DeclFriend.cpp
@ -16,10 +17,9 @@ add_clang_library(clangAST
DeclObjC.cpp
DeclPrinter.cpp
DeclTemplate.cpp
DeclarationName.cpp
Expr.cpp
ExprCXX.cpp
ExprConstant.cpp
ExprCXX.cpp
FullExpr.cpp
InheritViz.cpp
NestedNameSpecifier.cpp

View File

@ -416,3 +416,240 @@ FindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier,
return false;
}
void OverridingMethods::add(unsigned OverriddenSubobject,
UniqueVirtualMethod Overriding) {
llvm::SmallVector<UniqueVirtualMethod, 4> &SubobjectOverrides
= Overrides[OverriddenSubobject];
if (std::find(SubobjectOverrides.begin(), SubobjectOverrides.end(),
Overriding) == SubobjectOverrides.end())
SubobjectOverrides.push_back(Overriding);
}
void OverridingMethods::add(const OverridingMethods &Other) {
for (const_iterator I = Other.begin(), IE = Other.end(); I != IE; ++I) {
for (overriding_const_iterator M = I->second.begin(),
MEnd = I->second.end();
M != MEnd;
++M)
add(I->first, *M);
}
}
void OverridingMethods::replaceAll(UniqueVirtualMethod Overriding) {
for (iterator I = begin(), IEnd = end(); I != IEnd; ++I) {
I->second.clear();
I->second.push_back(Overriding);
}
}
namespace {
class FinalOverriderCollector {
/// \brief The number of subobjects of a given class type that
/// occur within the class hierarchy.
llvm::DenseMap<const CXXRecordDecl *, unsigned> SubobjectCount;
/// \brief Overriders for each virtual base subobject.
llvm::DenseMap<const CXXRecordDecl *, CXXFinalOverriderMap *> VirtualOverriders;
CXXFinalOverriderMap FinalOverriders;
public:
~FinalOverriderCollector();
void Collect(const CXXRecordDecl *RD, bool VirtualBase,
const CXXRecordDecl *InVirtualSubobject,
CXXFinalOverriderMap &Overriders);
};
}
void FinalOverriderCollector::Collect(const CXXRecordDecl *RD,
bool VirtualBase,
const CXXRecordDecl *InVirtualSubobject,
CXXFinalOverriderMap &Overriders) {
unsigned SubobjectNumber = 0;
if (!VirtualBase)
SubobjectNumber
= ++SubobjectCount[cast<CXXRecordDecl>(RD->getCanonicalDecl())];
for (CXXRecordDecl::base_class_const_iterator Base = RD->bases_begin(),
BaseEnd = RD->bases_end(); Base != BaseEnd; ++Base) {
if (const RecordType *RT = Base->getType()->getAs<RecordType>()) {
const CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(RT->getDecl());
if (!BaseDecl->isPolymorphic())
continue;
if (Overriders.empty() && !Base->isVirtual()) {
// There are no other overriders of virtual member functions,
// so let the base class fill in our overriders for us.
Collect(BaseDecl, false, InVirtualSubobject, Overriders);
continue;
}
// Collect all of the overridders from the base class subobject
// and merge them into the set of overridders for this class.
// For virtual base classes, populate or use the cached virtual
// overrides so that we do not walk the virtual base class (and
// its base classes) more than once.
CXXFinalOverriderMap ComputedBaseOverriders;
CXXFinalOverriderMap *BaseOverriders = &ComputedBaseOverriders;
if (Base->isVirtual()) {
CXXFinalOverriderMap *&MyVirtualOverriders = VirtualOverriders[BaseDecl];
if (!MyVirtualOverriders) {
MyVirtualOverriders = new CXXFinalOverriderMap;
Collect(BaseDecl, true, BaseDecl, *MyVirtualOverriders);
}
BaseOverriders = MyVirtualOverriders;
} else
Collect(BaseDecl, false, InVirtualSubobject, ComputedBaseOverriders);
// Merge the overriders from this base class into our own set of
// overriders.
for (CXXFinalOverriderMap::iterator OM = BaseOverriders->begin(),
OMEnd = BaseOverriders->end();
OM != OMEnd;
++OM) {
const CXXMethodDecl *CanonOM
= cast<CXXMethodDecl>(OM->first->getCanonicalDecl());
Overriders[CanonOM].add(OM->second);
}
}
}
for (CXXRecordDecl::method_iterator M = RD->method_begin(),
MEnd = RD->method_end();
M != MEnd;
++M) {
// We only care about virtual methods.
if (!M->isVirtual())
continue;
CXXMethodDecl *CanonM = cast<CXXMethodDecl>(M->getCanonicalDecl());
if (CanonM->begin_overridden_methods()
== CanonM->end_overridden_methods()) {
// This is a new virtual function that does not override any
// other virtual function. Add it to the map of virtual
// functions for which we are tracking overridders.
// C++ [class.virtual]p2:
// For convenience we say that any virtual function overrides itself.
Overriders[CanonM].add(SubobjectNumber,
UniqueVirtualMethod(CanonM, SubobjectNumber,
InVirtualSubobject));
continue;
}
// This virtual method overrides other virtual methods, so it does
// not add any new slots into the set of overriders. Instead, we
// replace entries in the set of overriders with the new
// overrider. To do so, we dig down to the original virtual
// functions using data recursion and update all of the methods it
// overrides.
typedef std::pair<CXXMethodDecl::method_iterator,
CXXMethodDecl::method_iterator> OverriddenMethods;
llvm::SmallVector<OverriddenMethods, 4> Stack;
Stack.push_back(std::make_pair(CanonM->begin_overridden_methods(),
CanonM->end_overridden_methods()));
while (!Stack.empty()) {
OverriddenMethods OverMethods = Stack.back();
Stack.pop_back();
for (; OverMethods.first != OverMethods.second; ++OverMethods.first) {
const CXXMethodDecl *CanonOM
= cast<CXXMethodDecl>((*OverMethods.first)->getCanonicalDecl());
if (CanonOM->begin_overridden_methods()
== CanonOM->end_overridden_methods()) {
// C++ [class.virtual]p2:
// A virtual member function C::vf of a class object S is
// a final overrider unless the most derived class (1.8)
// of which S is a base class subobject (if any) declares
// or inherits another member function that overrides vf.
//
// Treating this object like the most derived class, we
// replace any overrides from base classes with this
// overriding virtual function.
Overriders[CanonOM].replaceAll(
UniqueVirtualMethod(CanonM, SubobjectNumber,
InVirtualSubobject));
continue;
}
// Continue recursion to the methods that this virtual method
// overrides.
Stack.push_back(std::make_pair(CanonOM->begin_overridden_methods(),
CanonOM->end_overridden_methods()));
}
}
}
}
FinalOverriderCollector::~FinalOverriderCollector() {
for (llvm::DenseMap<const CXXRecordDecl *, CXXFinalOverriderMap *>::iterator
VO = VirtualOverriders.begin(), VOEnd = VirtualOverriders.end();
VO != VOEnd;
++VO)
delete VO->second;
}
void
CXXRecordDecl::getFinalOverriders(CXXFinalOverriderMap &FinalOverriders) const {
FinalOverriderCollector Collector;
Collector.Collect(this, false, 0, FinalOverriders);
// Weed out any final overriders that come from virtual base class
// subobjects that were hidden by other subobjects along any path.
// This is the final-overrider variant of C++ [class.member.lookup]p10.
for (CXXFinalOverriderMap::iterator OM = FinalOverriders.begin(),
OMEnd = FinalOverriders.end();
OM != OMEnd;
++OM) {
for (OverridingMethods::iterator SO = OM->second.begin(),
SOEnd = OM->second.end();
SO != SOEnd;
++SO) {
llvm::SmallVector<UniqueVirtualMethod, 4> &Overriding = SO->second;
if (Overriding.size() < 2)
continue;
for (llvm::SmallVector<UniqueVirtualMethod, 4>::iterator
Pos = Overriding.begin(), PosEnd = Overriding.end();
Pos != PosEnd;
/* increment in loop */) {
if (!Pos->InVirtualSubobject) {
++Pos;
continue;
}
// We have an overriding method in a virtual base class
// subobject (or non-virtual base class subobject thereof);
// determine whether there exists an other overriding method
// in a base class subobject that hides the virtual base class
// subobject.
bool Hidden = false;
for (llvm::SmallVector<UniqueVirtualMethod, 4>::iterator
OP = Overriding.begin(), OPEnd = Overriding.end();
OP != OPEnd && !Hidden;
++OP) {
if (Pos == OP)
continue;
if (OP->Method->getParent()->isVirtuallyDerivedFrom(
const_cast<CXXRecordDecl *>(Pos->InVirtualSubobject)))
Hidden = true;
}
if (Hidden) {
// The current overriding function is hidden by another
// overriding function; remove this one.
Pos = Overriding.erase(Pos);
PosEnd = Overriding.end();
} else {
++Pos;
}
}
}
}
}

View File

@ -1413,10 +1413,8 @@ void TagDecl::startDefinition() {
CXXRecordDecl *D = cast<CXXRecordDecl>(this);
struct CXXRecordDecl::DefinitionData *Data =
new (getASTContext()) struct CXXRecordDecl::DefinitionData(D);
do {
D->DefinitionData = Data;
D = cast_or_null<CXXRecordDecl>(D->getPreviousDeclaration());
} while (D);
for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I)
cast<CXXRecordDecl>(*I)->DefinitionData = Data;
}
}

View File

@ -18,6 +18,7 @@
#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DependentDiagnostic.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Type.h"
@ -481,7 +482,7 @@ DeclContext::~DeclContext() {
// FIXME: Currently ~ASTContext will delete the StoredDeclsMaps because
// ~DeclContext() is not guaranteed to be called when ASTContext uses
// a BumpPtrAllocator.
// delete static_cast<StoredDeclsMap*>(LookupPtr);
// delete LookupPtr;
}
void DeclContext::DestroyDecls(ASTContext &C) {
@ -516,10 +517,16 @@ bool DeclContext::isDependentContext() const {
if (Record->getDescribedClassTemplate())
return true;
if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(this))
if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(this)) {
if (Function->getDescribedFunctionTemplate())
return true;
// Friend function declarations are dependent if their *lexical*
// context is dependent.
if (cast<Decl>(this)->getFriendObjectKind())
return getLexicalParent()->isDependentContext();
}
return getParent() && getParent()->isDependentContext();
}
@ -666,9 +673,7 @@ DeclContext::LoadVisibleDeclsFromExternalStorage() const {
// Load the declaration IDs for all of the names visible in this
// context.
assert(!LookupPtr && "Have a lookup map before de-serialization?");
StoredDeclsMap *Map =
(StoredDeclsMap*) getParentASTContext().CreateStoredDeclsMap();
LookupPtr = Map;
StoredDeclsMap *Map = CreateStoredDeclsMap(getParentASTContext());
for (unsigned I = 0, N = Decls.size(); I != N; ++I) {
(*Map)[Decls[I].Name].setFromDeclIDs(Decls[I].Declarations);
}
@ -727,10 +732,9 @@ void DeclContext::removeDecl(Decl *D) {
if (isa<NamedDecl>(D)) {
NamedDecl *ND = cast<NamedDecl>(D);
void *OpaqueMap = getPrimaryContext()->LookupPtr;
if (!OpaqueMap) return;
StoredDeclsMap *Map = getPrimaryContext()->LookupPtr;
if (!Map) return;
StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(OpaqueMap);
StoredDeclsMap::iterator Pos = Map->find(ND->getDeclName());
assert(Pos != Map->end() && "no lookup entry for decl");
Pos->second.remove(ND);
@ -808,9 +812,8 @@ DeclContext::lookup(DeclarationName Name) {
return lookup_result(0, 0);
}
StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(LookupPtr);
StoredDeclsMap::iterator Pos = Map->find(Name);
if (Pos == Map->end())
StoredDeclsMap::iterator Pos = LookupPtr->find(Name);
if (Pos == LookupPtr->end())
return lookup_result(0, 0);
return Pos->second.getLookupResult(getParentASTContext());
}
@ -878,12 +881,11 @@ void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D) {
ASTContext *C = 0;
if (!LookupPtr) {
C = &getParentASTContext();
LookupPtr = (StoredDeclsMap*) C->CreateStoredDeclsMap();
CreateStoredDeclsMap(*C);
}
// Insert this declaration into the map.
StoredDeclsMap &Map = *static_cast<StoredDeclsMap*>(LookupPtr);
StoredDeclsList &DeclNameEntries = Map[D->getDeclName()];
StoredDeclsList &DeclNameEntries = (*LookupPtr)[D->getDeclName()];
if (DeclNameEntries.isNull()) {
DeclNameEntries.setOnlyValue(D);
return;
@ -952,13 +954,69 @@ void StoredDeclsList::materializeDecls(ASTContext &Context) {
// Creation and Destruction of StoredDeclsMaps. //
//===----------------------------------------------------------------------===//
void *ASTContext::CreateStoredDeclsMap() {
StoredDeclsMap *M = new StoredDeclsMap();
SDMs.push_back(M);
StoredDeclsMap *DeclContext::CreateStoredDeclsMap(ASTContext &C) const {
assert(!LookupPtr && "context already has a decls map");
assert(getPrimaryContext() == this &&
"creating decls map on non-primary context");
StoredDeclsMap *M;
bool Dependent = isDependentContext();
if (Dependent)
M = new DependentStoredDeclsMap();
else
M = new StoredDeclsMap();
M->Previous = C.LastSDM;
C.LastSDM = llvm::PointerIntPair<StoredDeclsMap*,1>(M, Dependent);
LookupPtr = M;
return M;
}
void ASTContext::ReleaseDeclContextMaps() {
for (std::vector<void*>::iterator I = SDMs.begin(), E = SDMs.end(); I!=E; ++I)
delete (StoredDeclsMap*) *I;
// It's okay to delete DependentStoredDeclsMaps via a StoredDeclsMap
// pointer because the subclass doesn't add anything that needs to
// be deleted.
StoredDeclsMap::DestroyAll(LastSDM.getPointer(), LastSDM.getInt());
}
void StoredDeclsMap::DestroyAll(StoredDeclsMap *Map, bool Dependent) {
while (Map) {
// Advance the iteration before we invalidate memory.
llvm::PointerIntPair<StoredDeclsMap*,1> Next = Map->Previous;
if (Dependent)
delete static_cast<DependentStoredDeclsMap*>(Map);
else
delete Map;
Map = Next.getPointer();
Dependent = Next.getInt();
}
}
DependentDiagnostic *DependentDiagnostic::Create(ASTContext &C,
DeclContext *Parent,
const PartialDiagnostic &PDiag) {
assert(Parent->isDependentContext()
&& "cannot iterate dependent diagnostics of non-dependent context");
Parent = Parent->getPrimaryContext();
if (!Parent->LookupPtr)
Parent->CreateStoredDeclsMap(C);
DependentStoredDeclsMap *Map
= static_cast<DependentStoredDeclsMap*>(Parent->LookupPtr);
// Allocate the copy of the PartialDiagnostic via the ASTContext's
// BumpPtrAllocator, rather than the ASTContext itself.
PartialDiagnostic::Storage *DiagStorage = 0;
if (PDiag.hasStorage())
DiagStorage = new (C) PartialDiagnostic::Storage;
DependentDiagnostic *DD = new (C) DependentDiagnostic(PDiag, DiagStorage);
// TODO: Maybe we shouldn't reverse the order during insertion.
DD->NextDiagnostic = Map->FirstDiagnostic;
Map->FirstDiagnostic = DD;
return DD;
}

View File

@ -83,9 +83,11 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
if (data().Bases)
C.Deallocate(data().Bases);
int vbaseCount = 0;
llvm::SmallVector<const CXXBaseSpecifier*, 8> UniqueVbases;
bool hasDirectVirtualBase = false;
// The set of seen virtual base types.
llvm::SmallPtrSet<CanQualType, 8> SeenVBaseTypes;
// The virtual bases of this class.
llvm::SmallVector<const CXXBaseSpecifier *, 8> VBases;
data().Bases = new(C) CXXBaseSpecifier [NumBases];
data().NumBases = NumBases;
@ -99,58 +101,44 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
continue;
CXXRecordDecl *BaseClassDecl
= cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl());
if (Base->isVirtual())
hasDirectVirtualBase = true;
// Now go through all virtual bases of this base and add them.
for (CXXRecordDecl::base_class_iterator VBase =
BaseClassDecl->vbases_begin(),
E = BaseClassDecl->vbases_end(); VBase != E; ++VBase) {
// Add this vbase to the array of vbases for current class if it is
// not already in the list.
// FIXME. Note that we do a linear search as number of such classes are
// very few.
int i;
for (i = 0; i < vbaseCount; ++i)
if (UniqueVbases[i]->getType() == VBase->getType())
break;
if (i == vbaseCount) {
UniqueVbases.push_back(VBase);
++vbaseCount;
}
// Add this base if it's not already in the list.
if (SeenVBaseTypes.insert(C.getCanonicalType(VBase->getType())))
VBases.push_back(VBase);
}
if (Base->isVirtual()) {
// Add this base if it's not already in the list.
if (SeenVBaseTypes.insert(C.getCanonicalType(BaseType)))
VBases.push_back(Base);
}
}
if (hasDirectVirtualBase) {
// Iterate one more time through the direct bases and add the virtual
// base to the list of vritual bases for current class.
for (unsigned i = 0; i < NumBases; ++i) {
const CXXBaseSpecifier *VBase = Bases[i];
if (!VBase->isVirtual())
continue;
int j;
for (j = 0; j < vbaseCount; ++j)
if (UniqueVbases[j]->getType() == VBase->getType())
break;
if (j == vbaseCount) {
UniqueVbases.push_back(VBase);
++vbaseCount;
}
}
}
if (vbaseCount > 0) {
// build AST for inhireted, direct or indirect, virtual bases.
data().VBases = new (C) CXXBaseSpecifier [vbaseCount];
data().NumVBases = vbaseCount;
for (int i = 0; i < vbaseCount; i++) {
QualType QT = UniqueVbases[i]->getType();
// Skip dependent types; we can't do any checking on them now.
if (QT->isDependentType())
continue;
CXXRecordDecl *VBaseClassDecl
= cast<CXXRecordDecl>(QT->getAs<RecordType>()->getDecl());
data().VBases[i] =
CXXBaseSpecifier(VBaseClassDecl->getSourceRange(), true,
VBaseClassDecl->getTagKind() == RecordDecl::TK_class,
UniqueVbases[i]->getAccessSpecifier(), QT);
}
if (VBases.empty())
return;
// Create base specifier for any direct or indirect virtual bases.
data().VBases = new (C) CXXBaseSpecifier[VBases.size()];
data().NumVBases = VBases.size();
for (int I = 0, E = VBases.size(); I != E; ++I) {
QualType VBaseType = VBases[I]->getType();
// Skip dependent types; we can't do any checking on them now.
if (VBaseType->isDependentType())
continue;
CXXRecordDecl *VBaseClassDecl
= cast<CXXRecordDecl>(VBaseType->getAs<RecordType>()->getDecl());
data().VBases[I] =
CXXBaseSpecifier(VBaseClassDecl->getSourceRange(), true,
VBaseClassDecl->getTagKind() == RecordDecl::TK_class,
VBases[I]->getAccessSpecifier(), VBaseType);
}
}
@ -320,6 +308,8 @@ void CXXRecordDecl::addedAssignmentOperator(ASTContext &Context,
static CanQualType GetConversionType(ASTContext &Context, NamedDecl *Conv) {
QualType T;
if (isa<UsingShadowDecl>(Conv))
Conv = cast<UsingShadowDecl>(Conv)->getTargetDecl();
if (FunctionTemplateDecl *ConvTemp = dyn_cast<FunctionTemplateDecl>(Conv))
T = ConvTemp->getTemplatedDecl()->getResultType();
else
@ -457,26 +447,45 @@ const UnresolvedSetImpl *CXXRecordDecl::getVisibleConversionFunctions() {
return &data().VisibleConversions;
}
void CXXRecordDecl::addConversionFunction(CXXConversionDecl *ConvDecl) {
assert(!ConvDecl->getDescribedFunctionTemplate() &&
"Conversion function templates should cast to FunctionTemplateDecl.");
#ifndef NDEBUG
void CXXRecordDecl::CheckConversionFunction(NamedDecl *ConvDecl) {
assert(ConvDecl->getDeclContext() == this &&
"conversion function does not belong to this record");
// We intentionally don't use the decl's access here because it
// hasn't been set yet. That's really just a misdesign in Sema.
data().Conversions.addDecl(ConvDecl);
ConvDecl = ConvDecl->getUnderlyingDecl();
if (FunctionTemplateDecl *Temp = dyn_cast<FunctionTemplateDecl>(ConvDecl)) {
assert(isa<CXXConversionDecl>(Temp->getTemplatedDecl()));
} else {
assert(isa<CXXConversionDecl>(ConvDecl));
}
}
#endif
void CXXRecordDecl::addConversionFunction(FunctionTemplateDecl *ConvDecl) {
assert(isa<CXXConversionDecl>(ConvDecl->getTemplatedDecl()) &&
"Function template is not a conversion function template");
assert(ConvDecl->getDeclContext() == this &&
"conversion function does not belong to this record");
data().Conversions.addDecl(ConvDecl);
void CXXRecordDecl::removeConversion(const NamedDecl *ConvDecl) {
// This operation is O(N) but extremely rare. Sema only uses it to
// remove UsingShadowDecls in a class that were followed by a direct
// declaration, e.g.:
// class A : B {
// using B::operator int;
// operator int();
// };
// This is uncommon by itself and even more uncommon in conjunction
// with sufficiently large numbers of directly-declared conversions
// that asymptotic behavior matters.
UnresolvedSetImpl &Convs = *getConversionFunctions();
for (unsigned I = 0, E = Convs.size(); I != E; ++I) {
if (Convs[I].getDecl() == ConvDecl) {
Convs.erase(I);
assert(std::find(Convs.begin(), Convs.end(), ConvDecl) == Convs.end()
&& "conversion was found multiple times in unresolved set");
return;
}
}
llvm_unreachable("conversion not found in set!");
}
void CXXRecordDecl::setMethodAsVirtual(FunctionDecl *Method) {
Method->setVirtualAsWritten(true);
setAggregate(false);

View File

@ -492,44 +492,45 @@ QualType CallExpr::getCallReturnType() const {
return FnType->getResultType();
}
MemberExpr::MemberExpr(Expr *base, bool isarrow, NestedNameSpecifier *qual,
SourceRange qualrange, ValueDecl *memberdecl,
SourceLocation l, const TemplateArgumentListInfo *targs,
QualType ty)
: Expr(MemberExprClass, ty,
base->isTypeDependent() || (qual && qual->isDependent()),
base->isValueDependent() || (qual && qual->isDependent())),
Base(base), MemberDecl(memberdecl), MemberLoc(l), IsArrow(isarrow),
HasQualifier(qual != 0), HasExplicitTemplateArgumentList(targs) {
// Initialize the qualifier, if any.
if (HasQualifier) {
NameQualifier *NQ = getMemberQualifier();
NQ->NNS = qual;
NQ->Range = qualrange;
}
// Initialize the explicit template argument list, if any.
if (targs)
getExplicitTemplateArgumentList()->initializeFrom(*targs);
}
MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow,
NestedNameSpecifier *qual,
SourceRange qualrange,
ValueDecl *memberdecl,
NamedDecl *founddecl,
SourceLocation l,
const TemplateArgumentListInfo *targs,
QualType ty) {
std::size_t Size = sizeof(MemberExpr);
if (qual != 0)
Size += sizeof(NameQualifier);
bool hasQualOrFound = (qual != 0 || founddecl != memberdecl);
if (hasQualOrFound)
Size += sizeof(MemberNameQualifier);
if (targs)
Size += ExplicitTemplateArgumentList::sizeFor(*targs);
void *Mem = C.Allocate(Size, llvm::alignof<MemberExpr>());
return new (Mem) MemberExpr(base, isarrow, qual, qualrange, memberdecl, l,
targs, ty);
MemberExpr *E = new (Mem) MemberExpr(base, isarrow, memberdecl, l, ty);
if (hasQualOrFound) {
if (qual && qual->isDependent()) {
E->setValueDependent(true);
E->setTypeDependent(true);
}
E->HasQualifierOrFoundDecl = true;
MemberNameQualifier *NQ = E->getMemberQualifier();
NQ->NNS = qual;
NQ->Range = qualrange;
NQ->FoundDecl = founddecl;
}
if (targs) {
E->HasExplicitTemplateArgumentList = true;
E->getExplicitTemplateArgumentList()->initializeFrom(*targs);
}
return E;
}
const char *CastExpr::getCastKindName() const {
@ -544,6 +545,8 @@ const char *CastExpr::getCastKindName() const {
return "BaseToDerived";
case CastExpr::CK_DerivedToBase:
return "DerivedToBase";
case CastExpr::CK_UncheckedDerivedToBase:
return "UncheckedDerivedToBase";
case CastExpr::CK_Dynamic:
return "Dynamic";
case CastExpr::CK_ToUnion:
@ -914,8 +917,15 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
case CXXConstructExprClass:
return false;
case ObjCMessageExprClass:
case ObjCMessageExprClass: {
const ObjCMessageExpr *ME = cast<ObjCMessageExpr>(this);
const ObjCMethodDecl *MD = ME->getMethodDecl();
if (MD && MD->getAttr<WarnUnusedResultAttr>()) {
Loc = getExprLoc();
return true;
}
return false;
}
case ObjCImplicitSetterGetterRefExprClass: { // Dot syntax for message send.
#if 0

View File

@ -750,7 +750,7 @@ bool Type::isSpecifierType() const {
case SubstTemplateTypeParm:
case TemplateSpecialization:
case QualifiedName:
case Typename:
case DependentName:
case ObjCInterface:
case ObjCObjectPointer:
case Elaborated:
@ -760,6 +760,27 @@ bool Type::isSpecifierType() const {
}
}
bool Type::isElaboratedTypeSpecifier() const {
if (getTypeClass() == Elaborated)
return true;
if (const DependentNameType *Dependent = dyn_cast<DependentNameType>(this)) {
switch (Dependent->getKeyword()) {
case ETK_None:
case ETK_Typename:
return false;
case ETK_Class:
case ETK_Struct:
case ETK_Union:
case ETK_Enum:
return true;
}
}
return false;
}
const char *Type::getTypeClassName() const {
switch (TC) {
default: assert(0 && "Type class not in TypeNodes.def!");
@ -820,8 +841,8 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result,
unsigned NumArgs, bool isVariadic,
unsigned TypeQuals, bool hasExceptionSpec,
bool anyExceptionSpec, unsigned NumExceptions,
exception_iterator Exs, bool NoReturn,
CallingConv CallConv) {
exception_iterator Exs,
const FunctionType::ExtInfo &Info) {
ID.AddPointer(Result.getAsOpaquePtr());
for (unsigned i = 0; i != NumArgs; ++i)
ID.AddPointer(ArgTys[i].getAsOpaquePtr());
@ -833,15 +854,16 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result,
for (unsigned i = 0; i != NumExceptions; ++i)
ID.AddPointer(Exs[i].getAsOpaquePtr());
}
ID.AddInteger(NoReturn);
ID.AddInteger(CallConv);
ID.AddInteger(Info.getNoReturn());
ID.AddInteger(Info.getRegParm());
ID.AddInteger(Info.getCC());
}
void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getResultType(), arg_type_begin(), NumArgs, isVariadic(),
getTypeQuals(), hasExceptionSpec(), hasAnyExceptionSpec(),
getNumExceptions(), exception_begin(), getNoReturnAttr(),
getCallConv());
getNumExceptions(), exception_begin(),
getExtInfo());
}
void ObjCObjectPointerType::Profile(llvm::FoldingSetNodeID &ID,

View File

@ -282,7 +282,8 @@ void TypePrinter::PrintFunctionProto(const FunctionProtoType *T,
S += ")";
switch(T->getCallConv()) {
FunctionType::ExtInfo Info = T->getExtInfo();
switch(Info.getCC()) {
case CC_Default:
default: break;
case CC_C:
@ -295,9 +296,11 @@ void TypePrinter::PrintFunctionProto(const FunctionProtoType *T,
S += " __attribute__((fastcall))";
break;
}
if (T->getNoReturnAttr())
if (Info.getNoReturn())
S += " __attribute__((noreturn))";
if (Info.getRegParm())
S += " __attribute__((regparm (" +
llvm::utostr_32(Info.getRegParm()) + ")))";
if (T->hasExceptionSpec()) {
S += " throw(";
@ -564,12 +567,20 @@ void TypePrinter::PrintQualifiedName(const QualifiedNameType *T,
S = MyString + ' ' + S;
}
void TypePrinter::PrintTypename(const TypenameType *T, std::string &S) {
void TypePrinter::PrintDependentName(const DependentNameType *T, std::string &S) {
std::string MyString;
{
llvm::raw_string_ostream OS(MyString);
OS << "typename ";
switch (T->getKeyword()) {
case ETK_None: break;
case ETK_Typename: OS << "typename "; break;
case ETK_Class: OS << "class "; break;
case ETK_Struct: OS << "struct "; break;
case ETK_Union: OS << "union "; break;
case ETK_Enum: OS << "enum "; break;
}
T->getQualifier()->print(OS, Policy);
if (const IdentifierInfo *Ident = T->getIdentifier())
@ -819,4 +830,3 @@ void QualType::getAsStringInternal(std::string &S,
TypePrinter Printer(Policy);
Printer.Print(*this, S);
}

View File

@ -54,8 +54,12 @@ const ImplicitParamDecl *AnalysisContext::getSelfDecl() const {
}
CFG *AnalysisContext::getCFG() {
if (!cfg)
if (!builtCFG) {
cfg = CFG::buildCFG(D, getBody(), &D->getASTContext(), AddEHEdges);
// Even when the cfg is not successfully built, we don't
// want to try building it again.
builtCFG = true;
}
return cfg;
}
@ -126,9 +130,9 @@ LocationContextManager::getLocationContext(AnalysisContext *ctx,
llvm::FoldingSetNodeID ID;
LOC::Profile(ID, ctx, parent, d);
void *InsertPos;
LOC *L = cast_or_null<LOC>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
if (!L) {
L = new LOC(ctx, parent, d);
Contexts.InsertNode(L, InsertPos);
@ -144,7 +148,7 @@ LocationContextManager::getStackFrame(AnalysisContext *ctx,
llvm::FoldingSetNodeID ID;
StackFrameContext::Profile(ID, ctx, parent, s, blk, idx);
void *InsertPos;
StackFrameContext *L =
StackFrameContext *L =
cast_or_null<StackFrameContext>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
if (!L) {
L = new StackFrameContext(ctx, parent, s, blk, idx);
@ -253,7 +257,7 @@ class FindBlockDeclRefExprsVals : public StmtVisitor<FindBlockDeclRefExprsVals>{
IgnoredContexts.insert(BR->getBlockDecl());
Visit(BR->getBlockDecl()->getBody());
}
};
};
} // end anonymous namespace
typedef BumpVector<const VarDecl*> DeclVec;
@ -263,16 +267,16 @@ static DeclVec* LazyInitializeReferencedDecls(const BlockDecl *BD,
llvm::BumpPtrAllocator &A) {
if (Vec)
return (DeclVec*) Vec;
BumpVectorContext BC(A);
DeclVec *BV = (DeclVec*) A.Allocate<DeclVec>();
new (BV) DeclVec(BC, 10);
// Find the referenced variables.
FindBlockDeclRefExprsVals F(*BV, BC);
F.Visit(BD->getBody());
Vec = BV;
Vec = BV;
return BV;
}
@ -281,7 +285,7 @@ std::pair<AnalysisContext::referenced_decls_iterator,
AnalysisContext::getReferencedBlockVars(const BlockDecl *BD) {
if (!ReferencedBlockVars)
ReferencedBlockVars = new llvm::DenseMap<const BlockDecl*,void*>();
DeclVec *V = LazyInitializeReferencedDecls(BD, (*ReferencedBlockVars)[BD], A);
return std::make_pair(V->begin(), V->end());
}
@ -310,12 +314,12 @@ LocationContextManager::~LocationContextManager() {
void LocationContextManager::clear() {
for (llvm::FoldingSet<LocationContext>::iterator I = Contexts.begin(),
E = Contexts.end(); I != E; ) {
E = Contexts.end(); I != E; ) {
LocationContext *LC = &*I;
++I;
delete LC;
}
Contexts.clear();
}

View File

@ -571,7 +571,7 @@ static bool CanThrow(Expr *E) {
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;
if (C->getCallee()->getType().getNoReturnAttr()) {
if (getFunctionExtInfo(*C->getCallee()->getType()).getNoReturn()) {
NoReturn = true;
}

View File

@ -75,7 +75,7 @@ static OptionalAmount ParseAmount(const char *&Beg, const char *E) {
char c = *I;
if (c >= '0' && c <= '9') {
hasDigits = true;
accumulator += (accumulator * 10) + (c - '0');
accumulator = (accumulator * 10) + (c - '0');
continue;
}

View File

@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Lex/LexDiagnostic.h"
#include "clang/Parse/ParseDiagnostic.h"
@ -124,10 +125,20 @@ const char *Diagnostic::getWarningOptionForDiag(unsigned DiagID) {
return 0;
}
bool Diagnostic::isBuiltinSFINAEDiag(unsigned DiagID) {
if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
return Info->SFINAE && Info->Class == CLASS_ERROR;
return false;
Diagnostic::SFINAEResponse
Diagnostic::getDiagnosticSFINAEResponse(unsigned DiagID) {
if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) {
if (!Info->SFINAE)
return SFINAE_Report;
if (Info->Class == CLASS_ERROR)
return SFINAE_SubstitutionFailure;
// Suppress notes, warnings, and extensions;
return SFINAE_Suppress;
}
return SFINAE_Report;
}
/// getDiagClass - Return the class field of the diagnostic.
@ -222,6 +233,8 @@ Diagnostic::Diagnostic(DiagnosticClient *client) : Client(client) {
ArgToStringFn = DummyArgToStringFn;
ArgToStringCookie = 0;
DelayedDiagID = 0;
// Set all mappings to 'unset'.
DiagMappings BlankDiags(diag::DIAG_UPPER_LIMIT/2, 0);
DiagMappingsStack.push_back(BlankDiags);
@ -289,6 +302,23 @@ const char *Diagnostic::getDescription(unsigned DiagID) const {
return CustomDiagInfo->getDescription(DiagID);
}
void Diagnostic::SetDelayedDiagnostic(unsigned DiagID, llvm::StringRef Arg1,
llvm::StringRef Arg2) {
if (DelayedDiagID)
return;
DelayedDiagID = DiagID;
DelayedDiagArg1 = Arg1.str();
DelayedDiagArg2 = Arg2.str();
}
void Diagnostic::ReportDelayed() {
Report(DelayedDiagID) << DelayedDiagArg1 << DelayedDiagArg2;
DelayedDiagID = 0;
DelayedDiagArg1.clear();
DelayedDiagArg2.clear();
}
/// getDiagnosticLevel - Based on the way the client configured the Diagnostic
/// object, classify the specified diagnostic ID into a Level, consumable by
/// the DiagnosticClient.
@ -532,6 +562,35 @@ bool Diagnostic::ProcessDiag() {
return true;
}
bool DiagnosticBuilder::Emit() {
// If DiagObj is null, then its soul was stolen by the copy ctor
// or the user called Emit().
if (DiagObj == 0) return false;
// When emitting diagnostics, we set the final argument count into
// the Diagnostic object.
DiagObj->NumDiagArgs = NumArgs;
DiagObj->NumDiagRanges = NumRanges;
DiagObj->NumFixItHints = NumFixItHints;
// Process the diagnostic, sending the accumulated information to the
// DiagnosticClient.
bool Emitted = DiagObj->ProcessDiag();
// Clear out the current diagnostic object.
unsigned DiagID = DiagObj->CurDiagID;
DiagObj->Clear();
// If there was a delayed diagnostic, emit it now.
if (DiagObj->DelayedDiagID && DiagObj->DelayedDiagID != DiagID)
DiagObj->ReportDelayed();
// This diagnostic is dead.
DiagObj = 0;
return Emitted;
}
DiagnosticClient::~DiagnosticClient() {}
@ -937,9 +996,9 @@ StoredDiagnostic::StoredDiagnostic(Diagnostic::Level Level,
for (unsigned I = 0, N = Info.getNumRanges(); I != N; ++I)
Ranges.push_back(Info.getRange(I));
FixIts.reserve(Info.getNumCodeModificationHints());
for (unsigned I = 0, N = Info.getNumCodeModificationHints(); I != N; ++I)
FixIts.push_back(Info.getCodeModificationHint(I));
FixIts.reserve(Info.getNumFixItHints());
for (unsigned I = 0, N = Info.getNumFixItHints(); I != N; ++I)
FixIts.push_back(Info.getFixItHint(I));
}
StoredDiagnostic::~StoredDiagnostic() { }
@ -1172,7 +1231,7 @@ StoredDiagnostic::Deserialize(FileManager &FM, SourceManager &SM,
return Diag;
}
CodeModificationHint Hint;
FixItHint Hint;
Hint.RemoveRange = SourceRange(RemoveBegin, RemoveEnd);
Hint.InsertionLoc = InsertionLoc;
Hint.CodeToInsert.assign(Memory, Memory + InsertLen);
@ -1188,3 +1247,13 @@ StoredDiagnostic::Deserialize(FileManager &FM, SourceManager &SM,
/// DiagnosticClient should be included in the number of diagnostics
/// reported by Diagnostic.
bool DiagnosticClient::IncludeInDiagnosticCounts() const { return true; }
PartialDiagnostic::StorageAllocator::StorageAllocator() {
for (unsigned I = 0; I != NumCached; ++I)
FreeList[I] = Cached + I;
NumFreeListEntries = NumCached;
}
PartialDiagnostic::StorageAllocator::~StorageAllocator() {
assert(NumFreeListEntries == NumCached && "A partial is on the lamb");
}

View File

@ -89,16 +89,26 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(Diagnostic &Diag,
char *Ptr = const_cast<char*>(Buffer.getPointer()->getBufferStart());
for (unsigned i = 0, e = Entry->getSize(); i != e; ++i)
Ptr[i] = FillStr[i % FillStr.size()];
Diag.Report(diag::err_cannot_open_file)
<< Entry->getName() << ErrorStr;
if (Diag.isDiagnosticInFlight())
Diag.SetDelayedDiagnostic(diag::err_cannot_open_file,
Entry->getName(), ErrorStr);
else
Diag.Report(diag::err_cannot_open_file)
<< Entry->getName() << ErrorStr;
Buffer.setInt(true);
} else if (FileInfo.st_size != Entry->getSize() ||
FileInfo.st_mtime != Entry->getModificationTime() ||
FileInfo.st_ino != Entry->getInode()) {
FileInfo.st_mtime != Entry->getModificationTime()) {
// Check that the file's size, modification time, and inode are
// the same as in the file entry (which may have come from a
// stat cache).
Diag.Report(diag::err_file_modified) << Entry->getName();
if (Diag.isDiagnosticInFlight())
Diag.SetDelayedDiagnostic(diag::err_file_modified,
Entry->getName());
else
Diag.Report(diag::err_file_modified) << Entry->getName();
Buffer.setInt(true);
}
}

View File

@ -292,6 +292,7 @@ class PS3PPUTargetInfo : public OSTargetInfo<Target> {
virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
MacroBuilder &Builder) const {
// PS3 PPU defines.
Builder.defineMacro("__PPC__");
Builder.defineMacro("__PPU__");
Builder.defineMacro("__CELLOS_LV2__");
Builder.defineMacro("__ELF__");

View File

@ -14,11 +14,9 @@
//===----------------------------------------------------------------------===//
#include "GRExprEngineInternalChecks.h"
#include "clang/Checker/PathSensitive/GRExprEngine.h"
#include "clang/Checker/BugReporter/BugReporter.h"
#include "clang/Checker/PathSensitive/GRExprEngine.h"
#include "clang/Checker/PathSensitive/CheckerVisitor.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/SmallString.h"
using namespace clang;

View File

@ -0,0 +1,55 @@
//=-- AggExprVisitor.cpp - evaluating expressions of C++ class type -*- 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 AggExprVisitor class, which contains lots of boiler
// plate code for evaluating expressions of C++ class type.
//
//===----------------------------------------------------------------------===//
#include "clang/Checker/PathSensitive/GRExprEngine.h"
#include "clang/AST/StmtVisitor.h"
using namespace clang;
namespace {
class AggExprVisitor : public StmtVisitor<AggExprVisitor> {
SVal DestPtr;
ExplodedNode *Pred;
ExplodedNodeSet &DstSet;
GRExprEngine &Eng;
public:
AggExprVisitor(SVal dest, ExplodedNode *N, ExplodedNodeSet &dst,
GRExprEngine &eng)
: DestPtr(dest), Pred(N), DstSet(dst), Eng(eng) {}
void VisitCastExpr(CastExpr *E);
void VisitCXXConstructExpr(CXXConstructExpr *E);
};
}
void AggExprVisitor::VisitCastExpr(CastExpr *E) {
switch (E->getCastKind()) {
default:
assert(0 && "Unhandled cast kind");
case CastExpr::CK_NoOp:
case CastExpr::CK_ConstructorConversion:
Visit(E->getSubExpr());
break;
}
}
void AggExprVisitor::VisitCXXConstructExpr(CXXConstructExpr *E) {
Eng.VisitCXXConstructExpr(E, DestPtr, Pred, DstSet);
}
void GRExprEngine::VisitAggExpr(const Expr *E, SVal Dest, ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
AggExprVisitor(Dest, Pred, Dst, *this).Visit(const_cast<Expr *>(E));
}

View File

@ -13,9 +13,9 @@
//===----------------------------------------------------------------------===//
#include "GRExprEngineInternalChecks.h"
#include "clang/Checker/PathSensitive/GRExprEngine.h"
#include "clang/Checker/BugReporter/BugReporter.h"
#include "clang/Checker/BugReporter/BugType.h"
#include "clang/Checker/PathSensitive/CheckerVisitor.h"
#include "clang/Checker/PathSensitive/GRExprEngine.h"
using namespace clang;

View File

@ -12,9 +12,9 @@
//
//===----------------------------------------------------------------------===//
#include "clang/Checker/PathSensitive/CheckerVisitor.h"
#include "clang/Checker/BugReporter/BugReporter.h"
#include "GRExprEngineInternalChecks.h"
#include "clang/Checker/BugReporter/BugType.h"
#include "clang/Checker/PathSensitive/CheckerVisitor.h"
using namespace clang;

View File

@ -19,9 +19,8 @@
#include "clang/Checker/PathSensitive/GRSimpleAPICheck.h"
#include "clang/Checker/PathSensitive/GRExprEngine.h"
#include "clang/Checker/PathSensitive/GRState.h"
#include "clang/Checker/BugReporter/BugReporter.h"
#include "clang/Checker/BugReporter/BugType.h"
#include "clang/Checker/PathSensitive/MemRegion.h"
#include "clang/Checker/BugReporter/PathDiagnostic.h"
#include "clang/Checker/PathSensitive/CheckerVisitor.h"
#include "clang/Checker/Checkers/LocalCheckers.h"
#include "clang/AST/DeclObjC.h"

View File

@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Checker/BugReporter/BugReporter.h"
#include "clang/Checker/BugReporter/BugType.h"
#include "clang/Checker/PathSensitive/GRExprEngine.h"
#include "clang/AST/ASTContext.h"
#include "clang/Analysis/CFG.h"
@ -1139,12 +1140,9 @@ void EdgeBuilder::addContext(const Stmt *S) {
static void GenerateExtensivePathDiagnostic(PathDiagnostic& PD,
PathDiagnosticBuilder &PDB,
const ExplodedNode *N) {
EdgeBuilder EB(PD, PDB);
const ExplodedNode* NextNode = N->pred_empty()
? NULL : *(N->pred_begin());
const ExplodedNode* NextNode = N->pred_empty() ? NULL : *(N->pred_begin());
while (NextNode) {
N = NextNode;
NextNode = GetPredecessorNode(N);

View File

@ -16,6 +16,7 @@
#include "clang/AST/ExprObjC.h"
#include "clang/Checker/BugReporter/BugReporter.h"
#include "clang/Checker/BugReporter/PathDiagnostic.h"
#include "clang/Checker/PathSensitive/ExplodedGraph.h"
#include "clang/Checker/PathSensitive/GRState.h"
using namespace clang;

View File

@ -16,8 +16,7 @@
#include "clang/AST/StmtVisitor.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Checker/BugReporter/BugReporter.h"
#include "clang/Checker/BugReporter/PathDiagnostic.h"
#include "clang/Checker/BugReporter/BugType.h"
#include "clang/Checker/BugReporter/PathDiagnostic.h"
#include "clang/Checker/Checkers/LocalCheckers.h"
#include "clang/Checker/DomainSpecific/CocoaConventions.h"

View File

@ -2,6 +2,7 @@ set(LLVM_NO_RTTI 1)
add_clang_library(clangChecker
AdjustedReturnValueChecker.cpp
AggExprVisitor.cpp
ArrayBoundChecker.cpp
AttrNonNullChecker.cpp
BasicConstraintManager.cpp
@ -11,16 +12,16 @@ add_clang_library(clangChecker
BugReporter.cpp
BugReporterVisitors.cpp
BuiltinFunctionChecker.cpp
CFRefCount.cpp
CallAndMessageChecker.cpp
CallInliner.cpp
CastToStructChecker.cpp
CFRefCount.cpp
CheckDeadStores.cpp
Checker.cpp
CheckObjCDealloc.cpp
CheckObjCInstMethSignature.cpp
CheckSecuritySyntaxOnly.cpp
CheckSizeofPointer.cpp
Checker.cpp
CocoaConventions.cpp
DereferenceChecker.cpp
DivZeroChecker.cpp
@ -38,11 +39,11 @@ add_clang_library(clangChecker
MallocChecker.cpp
ManagerRegistry.cpp
MemRegion.cpp
NoReturnFunctionChecker.cpp
NSAutoreleasePoolChecker.cpp
NSErrorChecker.cpp
NoReturnFunctionChecker.cpp
OSAtomicChecker.cpp
ObjCUnusedIVarsChecker.cpp
OSAtomicChecker.cpp
PathDiagnostic.cpp
PointerArithChecker.cpp
PointerSubChecker.cpp
@ -52,18 +53,18 @@ add_clang_library(clangChecker
ReturnPointerRangeChecker.cpp
ReturnStackAddressChecker.cpp
ReturnUndefChecker.cpp
SVals.cpp
SValuator.cpp
SimpleConstraintManager.cpp
SimpleSValuator.cpp
Store.cpp
SVals.cpp
SValuator.cpp
SymbolManager.cpp
UndefBranchChecker.cpp
UndefCapturedBlockVarChecker.cpp
UndefResultChecker.cpp
UndefinedArraySubscriptChecker.cpp
UndefinedAssignmentChecker.cpp
UndefResultChecker.cpp
UnixAPIChecker.cpp
VLASizeChecker.cpp
ValueManager.cpp
VLASizeChecker.cpp
)

View File

@ -12,11 +12,11 @@
//
//===----------------------------------------------------------------------===//
#include "clang/Basic/TargetInfo.h"
#include "clang/Checker/PathSensitive/CheckerVisitor.h"
#include "clang/Checker/BugReporter/BugReporter.h"
#include "clang/AST/ParentMap.h"
#include "GRExprEngineInternalChecks.h"
#include "clang/AST/ParentMap.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Checker/BugReporter/BugType.h"
#include "clang/Checker/PathSensitive/CheckerVisitor.h"
using namespace clang;

View File

@ -13,6 +13,7 @@
//
//===----------------------------------------------------------------------===//
#include "clang/Checker/BugReporter/BugType.h"
#include "clang/Checker/PathSensitive/CheckerVisitor.h"
#include "GRExprEngineInternalChecks.h"

View File

@ -36,7 +36,7 @@ class WalkAST : public StmtVisitor<WalkAST> {
IdentifierInfo *II_random;
enum { num_setids = 6 };
IdentifierInfo *II_setid[num_setids];
const bool CheckRand;
public:
@ -214,8 +214,8 @@ void WalkAST::CheckLoopConditionForFloat(const ForStmt *FS) {
const DeclRefExpr *drCond = vdLHS == drInc->getDecl() ? drLHS : drRHS;
llvm::SmallVector<SourceRange, 2> ranges;
std::string sbuf;
llvm::raw_string_ostream os(sbuf);
llvm::SmallString<256> sbuf;
llvm::raw_svector_ostream os(sbuf);
os << "Variable '" << drCond->getDecl()->getNameAsCString()
<< "' with floating point type '" << drCond->getType().getAsString()
@ -315,7 +315,7 @@ void WalkAST::CheckCall_mktemp(const CallExpr *CE, const FunctionDecl *FD) {
const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(FD->getType());
if(!FPT)
return;
// Verify that the funcion takes a single argument.
if (FPT->getNumArgs() != 1)
return;
@ -328,17 +328,16 @@ void WalkAST::CheckCall_mktemp(const CallExpr *CE, const FunctionDecl *FD) {
// Verify that the argument is a 'char*'.
if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().CharTy)
return;
// Issue a waring.
SourceRange R = CE->getCallee()->getSourceRange();
BR.EmitBasicReport("Potential insecure temporary file in call 'mktemp'",
"Security",
"Call to function 'mktemp' is insecure as it always "
"creates or uses insecure temporary file",
"creates or uses insecure temporary file. Use 'mkstemp' instead",
CE->getLocStart(), &R, 1);
}
//===----------------------------------------------------------------------===//
// Check: Linear congruent random number generators should not be used
// Originally: <rdar://problem/63371000>
@ -386,20 +385,18 @@ void WalkAST::CheckCall_rand(const CallExpr *CE, const FunctionDecl *FD) {
return;
// Issue a warning.
std::string buf1;
llvm::raw_string_ostream os1(buf1);
llvm::SmallString<256> buf1;
llvm::raw_svector_ostream os1(buf1);
os1 << "'" << FD->getNameAsString() << "' is a poor random number generator";
std::string buf2;
llvm::raw_string_ostream os2(buf2);
llvm::SmallString<256> buf2;
llvm::raw_svector_ostream os2(buf2);
os2 << "Function '" << FD->getNameAsString()
<< "' is obsolete because it implements a poor random number generator."
<< " Use 'arc4random' instead";
SourceRange R = CE->getCallee()->getSourceRange();
BR.EmitBasicReport(os1.str(), "Security", os2.str(),
CE->getLocStart(), &R, 1);
BR.EmitBasicReport(os1.str(), "Security", os2.str(),CE->getLocStart(), &R, 1);
}
//===----------------------------------------------------------------------===//
@ -425,8 +422,7 @@ void WalkAST::CheckCall_random(const CallExpr *CE, const FunctionDecl *FD) {
"Security",
"The 'random' function produces a sequence of values that "
"an adversary may be able to predict. Use 'arc4random' "
"instead",
CE->getLocStart(), &R, 1);
"instead", CE->getLocStart(), &R, 1);
}
//===----------------------------------------------------------------------===//
@ -474,22 +470,20 @@ void WalkAST::CheckUncheckedReturnValue(CallExpr *CE) {
return;
// Issue a warning.
std::string buf1;
llvm::raw_string_ostream os1(buf1);
llvm::SmallString<256> buf1;
llvm::raw_svector_ostream os1(buf1);
os1 << "Return value is not checked in call to '" << FD->getNameAsString()
<< "'";
std::string buf2;
llvm::raw_string_ostream os2(buf2);
llvm::SmallString<256> buf2;
llvm::raw_svector_ostream os2(buf2);
os2 << "The return value from the call to '" << FD->getNameAsString()
<< "' is not checked. If an error occurs in '"
<< FD->getNameAsString()
<< "', the following code may execute with unexpected privileges";
SourceRange R = CE->getCallee()->getSourceRange();
BR.EmitBasicReport(os1.str(), "Security", os2.str(),
CE->getLocStart(), &R, 1);
BR.EmitBasicReport(os1.str(), "Security", os2.str(),CE->getLocStart(), &R, 1);
}
//===----------------------------------------------------------------------===//

View File

@ -12,11 +12,11 @@
//
//===----------------------------------------------------------------------===//
#include "GRExprEngineInternalChecks.h"
#include "clang/Checker/BugReporter/BugType.h"
#include "clang/Checker/Checkers/DereferenceChecker.h"
#include "clang/Checker/PathSensitive/Checker.h"
#include "clang/Checker/PathSensitive/GRExprEngine.h"
#include "clang/Checker/BugReporter/BugReporter.h"
#include "GRExprEngineInternalChecks.h"
using namespace clang;
@ -29,9 +29,9 @@ class DereferenceChecker : public Checker {
DereferenceChecker() : BT_null(0), BT_undef(0) {}
static void *getTag() { static int tag = 0; return &tag; }
void VisitLocation(CheckerContext &C, const Stmt *S, SVal location);
std::pair<ExplodedNode * const*, ExplodedNode * const*>
getImplicitNodes() const {
getImplicitNodes() const {
return std::make_pair(ImplicitNullDerefNodes.data(),
ImplicitNullDerefNodes.data() +
ImplicitNullDerefNodes.size());
@ -59,7 +59,7 @@ void DereferenceChecker::VisitLocation(CheckerContext &C, const Stmt *S,
if (ExplodedNode *N = C.GenerateSink()) {
if (!BT_undef)
BT_undef = new BuiltinBug("Dereference of undefined pointer value");
EnhancedBugReport *report =
new EnhancedBugReport(*BT_undef, BT_undef->getDescription(), N);
report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
@ -68,31 +68,32 @@ void DereferenceChecker::VisitLocation(CheckerContext &C, const Stmt *S,
}
return;
}
DefinedOrUnknownSVal location = cast<DefinedOrUnknownSVal>(l);
// Check for null dereferences.
// Check for null dereferences.
if (!isa<Loc>(location))
return;
const GRState *state = C.getState();
const GRState *notNullState, *nullState;
llvm::tie(notNullState, nullState) = state->Assume(location);
// The explicit NULL case.
if (nullState) {
if (!notNullState) {
if (!notNullState) {
// Generate an error node.
ExplodedNode *N = C.GenerateSink(nullState);
if (!N)
return;
// We know that 'location' cannot be non-null. This is what
// we call an "explicit" null dereference.
// we call an "explicit" null dereference.
if (!BT_null)
BT_null = new BuiltinBug("Dereference of null pointer");
llvm::SmallString<100> buf;
llvm::SmallVector<SourceRange, 2> Ranges;
switch (S->getStmtClass()) {
case Stmt::UnaryOperatorClass: {
@ -101,10 +102,26 @@ void DereferenceChecker::VisitLocation(CheckerContext &C, const Stmt *S,
if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(SU)) {
if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
llvm::raw_svector_ostream os(buf);
os << "Dereference of null pointer loaded from variable '"
<< VD->getName() << '\'';
os << "Dereference of null pointer (loaded from variable '"
<< VD->getName() << "')";
Ranges.push_back(DR->getSourceRange());
}
}
break;
}
case Stmt::MemberExprClass: {
const MemberExpr *M = cast<MemberExpr>(S);
if (M->isArrow())
if (DeclRefExpr *DR =
dyn_cast<DeclRefExpr>(M->getBase()->IgnoreParenCasts())) {
if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
llvm::raw_svector_ostream os(buf);
os << "Field access results in a dereference of a null pointer "
"(loaded from variable '" << VD->getName() << "')";
Ranges.push_back(M->getBase()->getSourceRange());
}
}
break;
}
default:
break;
@ -117,19 +134,23 @@ void DereferenceChecker::VisitLocation(CheckerContext &C, const Stmt *S,
report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
bugreporter::GetDerefExpr(N));
for (llvm::SmallVectorImpl<SourceRange>::iterator
I = Ranges.begin(), E = Ranges.end(); I!=E; ++I)
report->addRange(*I);
C.EmitReport(report);
return;
}
else {
// Otherwise, we have the case where the location could either be
// null or not-null. Record the error node as an "implicit" null
// dereference.
// dereference.
if (ExplodedNode *N = C.GenerateSink(nullState))
ImplicitNullDerefNodes.push_back(N);
}
}
// From this point forward, we know that the location is not null.
C.addTransition(notNullState);
}

View File

@ -12,8 +12,9 @@
//
//===----------------------------------------------------------------------===//
#include "clang/Checker/PathSensitive/CheckerVisitor.h"
#include "GRExprEngineInternalChecks.h"
#include "clang/Checker/BugReporter/BugType.h"
#include "clang/Checker/PathSensitive/CheckerVisitor.h"
using namespace clang;

View File

@ -10,9 +10,10 @@
// This file defined the Environment and EnvironmentManager classes.
//
//===----------------------------------------------------------------------===//
#include "clang/Analysis/AnalysisContext.h"
#include "clang/Analysis/CFG.h"
#include "clang/Checker/PathSensitive/GRState.h"
#include "clang/Analysis/Analyses/LiveVariables.h"
#include "llvm/ADT/ImmutableMap.h"
using namespace clang;

View File

@ -13,8 +13,9 @@
//
//===----------------------------------------------------------------------===//
#include "clang/Checker/PathSensitive/CheckerVisitor.h"
#include "GRExprEngineInternalChecks.h"
#include "clang/Checker/BugReporter/BugType.h"
#include "clang/Checker/PathSensitive/CheckerVisitor.h"
using namespace clang;

View File

@ -18,7 +18,34 @@
using namespace clang;
typedef llvm::ImmutableMap<unsigned,unsigned> CountMap;
namespace {
class CountKey {
const StackFrameContext *CallSite;
unsigned BlockID;
public:
CountKey(const StackFrameContext *CS, unsigned ID)
: CallSite(CS), BlockID(ID) {}
bool operator==(const CountKey &RHS) const {
return (CallSite == RHS.CallSite) && (BlockID == RHS.BlockID);
}
bool operator<(const CountKey &RHS) const {
return (CallSite == RHS.CallSite) ? (BlockID < RHS.BlockID)
: (CallSite < RHS.CallSite);
}
void Profile(llvm::FoldingSetNodeID &ID) const {
ID.AddPointer(CallSite);
ID.AddInteger(BlockID);
}
};
}
typedef llvm::ImmutableMap<CountKey, unsigned> CountMap;
static inline CountMap GetMap(void* D) {
return CountMap(static_cast<CountMap::TreeTy*>(D));
@ -28,9 +55,10 @@ static inline CountMap::Factory& GetFactory(void* F) {
return *static_cast<CountMap::Factory*>(F);
}
unsigned GRBlockCounter::getNumVisited(unsigned BlockID) const {
unsigned GRBlockCounter::getNumVisited(const StackFrameContext *CallSite,
unsigned BlockID) const {
CountMap M = GetMap(Data);
CountMap::data_type* T = M.lookup(BlockID);
CountMap::data_type* T = M.lookup(CountKey(CallSite, BlockID));
return T ? *T : 0;
}
@ -43,9 +71,12 @@ GRBlockCounter::Factory::~Factory() {
}
GRBlockCounter
GRBlockCounter::Factory::IncrementCount(GRBlockCounter BC, unsigned BlockID) {
return GRBlockCounter(GetFactory(F).Add(GetMap(BC.Data), BlockID,
BC.getNumVisited(BlockID)+1).getRoot());
GRBlockCounter::Factory::IncrementCount(GRBlockCounter BC,
const StackFrameContext *CallSite,
unsigned BlockID) {
return GRBlockCounter(GetFactory(F).Add(GetMap(BC.Data),
CountKey(CallSite, BlockID),
BC.getNumVisited(CallSite, BlockID)+1).getRoot());
}
GRBlockCounter

View File

@ -126,9 +126,9 @@ void GRCoreEngine::ProcessStmt(CFGElement E, GRStmtNodeBuilder& Builder) {
SubEngine.ProcessStmt(E, Builder);
}
bool GRCoreEngine::ProcessBlockEntrance(CFGBlock* Blk, const GRState* State,
bool GRCoreEngine::ProcessBlockEntrance(CFGBlock* Blk, const ExplodedNode *Pred,
GRBlockCounter BC) {
return SubEngine.ProcessBlockEntrance(Blk, State, BC);
return SubEngine.ProcessBlockEntrance(Blk, Pred, BC);
}
void GRCoreEngine::ProcessBranch(Stmt* Condition, Stmt* Terminator,
@ -256,7 +256,7 @@ void GRCoreEngine::HandleBlockEdge(const BlockEdge& L, ExplodedNode* Pred) {
// FIXME: Should we allow ProcessBlockEntrance to also manipulate state?
if (ProcessBlockEntrance(Blk, Pred->State, WList->getBlockCounter()))
if (ProcessBlockEntrance(Blk, Pred, WList->getBlockCounter()))
GenerateNode(BlockEntrance(Blk, Pred->getLocationContext()), Pred->State, Pred);
}
@ -265,7 +265,9 @@ void GRCoreEngine::HandleBlockEntrance(const BlockEntrance& L,
// Increment the block counter.
GRBlockCounter Counter = WList->getBlockCounter();
Counter = BCounterFactory.IncrementCount(Counter, L.getBlock()->getBlockID());
Counter = BCounterFactory.IncrementCount(Counter,
Pred->getLocationContext()->getCurrentStackFrame(),
L.getBlock()->getBlockID());
WList->setBlockCounter(Counter);
// Process the entrance of the block.

View File

@ -13,6 +13,8 @@
//
//===----------------------------------------------------------------------===//
#include "GRExprEngineInternalChecks.h"
#include "clang/Checker/BugReporter/BugType.h"
#include "clang/Checker/PathSensitive/AnalysisManager.h"
#include "clang/Checker/PathSensitive/GRExprEngine.h"
#include "clang/Checker/PathSensitive/GRExprEngineBuilders.h"
#include "clang/Checker/PathSensitive/Checker.h"
@ -582,7 +584,6 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) {
switch (S->getStmtClass()) {
// C++ stuff we don't support yet.
case Stmt::CXXMemberCallExprClass:
case Stmt::CXXNamedCastExprClass:
case Stmt::CXXStaticCastExprClass:
case Stmt::CXXDynamicCastExprClass:
@ -671,6 +672,12 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) {
break;
}
case Stmt::CXXMemberCallExprClass: {
CXXMemberCallExpr *MCE = cast<CXXMemberCallExpr>(S);
VisitCXXMemberCallExpr(MCE, Pred, Dst);
break;
}
// FIXME: ChooseExpr is really a constant. We need to fix
// the CFG do not model them as explicit control-flow.
@ -895,6 +902,11 @@ void GRExprEngine::VisitLValue(Expr* Ex, ExplodedNode* Pred,
return;
}
case Stmt::ObjCIsaExprClass:
// FIXME: Do something more intelligent with 'x->isa = ...'.
// For now, just ignore the assignment.
return;
case Stmt::ObjCPropertyRefExprClass:
case Stmt::ObjCImplicitSetterGetterRefExprClass:
// FIXME: Property assignments are lvalues, but not really "locations".
@ -944,10 +956,11 @@ void GRExprEngine::VisitLValue(Expr* Ex, ExplodedNode* Pred,
// Block entrance. (Update counters).
//===----------------------------------------------------------------------===//
bool GRExprEngine::ProcessBlockEntrance(CFGBlock* B, const GRState*,
bool GRExprEngine::ProcessBlockEntrance(CFGBlock* B, const ExplodedNode *Pred,
GRBlockCounter BC) {
return BC.getNumVisited(B->getBlockID()) < 3;
return BC.getNumVisited(Pred->getLocationContext()->getCurrentStackFrame(),
B->getBlockID()) < 3;
}
//===----------------------------------------------------------------------===//
@ -1328,6 +1341,22 @@ void GRExprEngine::ProcessCallExit(GRCallExitNodeBuilder &B) {
if (ReturnedExpr) {
SVal RetVal = state->getSVal(ReturnedExpr);
state = state->BindExpr(CE, RetVal);
// Clear the return expr GDM.
state = state->remove<ReturnExpr>();
}
// Bind the constructed object value to CXXConstructExpr.
if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(CE)) {
const CXXThisRegion *ThisR = getCXXThisRegion(CCE->getConstructor(),LocCtx);
// We might not have 'this' region in the binding if we didn't inline
// the ctor call.
SVal ThisV = state->getSVal(ThisR);
loc::MemRegionVal *V = dyn_cast<loc::MemRegionVal>(&ThisV);
if (V) {
SVal ObjVal = state->getSVal(V->getRegion());
assert(isa<nonloc::LazyCompoundVal>(ObjVal));
state = state->BindExpr(CCE, ObjVal);
}
}
B.GenerateNode(state);
@ -2282,6 +2311,7 @@ void GRExprEngine::VisitCast(CastExpr *CastE, Expr *Ex, ExplodedNode *Pred,
case CastExpr::CK_AnyPointerToObjCPointerCast:
case CastExpr::CK_AnyPointerToBlockPointerCast:
case CastExpr::CK_DerivedToBase:
case CastExpr::CK_UncheckedDerivedToBase:
// Delegate to SValuator to process.
for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I) {
ExplodedNode* N = *I;
@ -2338,8 +2368,10 @@ void GRExprEngine::VisitDeclStmt(DeclStmt *DS, ExplodedNode *Pred,
ExplodedNodeSet Tmp;
if (InitEx) {
if (const CXXConstructExpr *E = dyn_cast<CXXConstructExpr>(InitEx)) {
VisitCXXConstructExpr(E, GetState(Pred)->getLValue(VD,
QualType InitTy = InitEx->getType();
if (getContext().getLangOptions().CPlusPlus && InitTy->isRecordType()) {
// Delegate expressions of C++ record type evaluation to AggExprVisitor.
VisitAggExpr(InitEx, GetState(Pred)->getLValue(VD,
Pred->getLocationContext()), Pred, Dst);
return;
} else if (VD->getType()->isReferenceType())
@ -2908,7 +2940,8 @@ void GRExprEngine::VisitReturnStmt(ReturnStmt *RS, ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
ExplodedNodeSet Src;
if (Expr *RetE = RS->getRetValue()) {
// Record the returned expression in the state.
// Record the returned expression in the state. It will be used in
// ProcessCallExit to bind the return value to the call expr.
{
static int Tag = 0;
SaveAndRestore<const void *> OldTag(Builder->Tag, &Tag);
@ -3137,6 +3170,10 @@ void GRExprEngine::CreateCXXTemporaryObject(Expr *Ex, ExplodedNode *Pred,
void GRExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E, SVal Dest,
ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
if (E->isElidable()) {
VisitAggExpr(E->getArg(0), Dest, Pred, Dst);
return;
}
const CXXConstructorDecl *CD = E->getConstructor();
assert(CD);
@ -3190,10 +3227,7 @@ void GRExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E, SVal Dest,
Pred->getLocationContext(),
E, Builder->getBlock(), Builder->getIndex());
Type *T = CD->getParent()->getTypeForDecl();
QualType PT = getContext().getPointerType(QualType(T,0));
const CXXThisRegion *ThisR = ValMgr.getRegionManager().getCXXThisRegion(PT,
SFC);
const CXXThisRegion *ThisR = getCXXThisRegion(E->getConstructor(), SFC);
CallEnter Loc(E, CD, Pred->getLocationContext());
for (ExplodedNodeSet::iterator NI = ArgsEvaluated.begin(),
@ -3206,6 +3240,91 @@ void GRExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E, SVal Dest,
Dst.Add(N);
}
}
void GRExprEngine::VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE,
ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
// Get the method type.
const FunctionProtoType *FnType =
MCE->getCallee()->getType()->getAs<FunctionProtoType>();
assert(FnType && "Method type not available");
// Evaluate explicit arguments with a worklist.
CallExpr::arg_iterator AB = const_cast<CXXMemberCallExpr*>(MCE)->arg_begin(),
AE = const_cast<CXXMemberCallExpr*>(MCE)->arg_end();
llvm::SmallVector<CallExprWLItem, 20> WorkList;
WorkList.reserve(AE - AB);
WorkList.push_back(CallExprWLItem(AB, Pred));
ExplodedNodeSet ArgsEvaluated;
while (!WorkList.empty()) {
CallExprWLItem Item = WorkList.back();
WorkList.pop_back();
if (Item.I == AE) {
ArgsEvaluated.insert(Item.N);
continue;
}
ExplodedNodeSet Tmp;
const unsigned ParamIdx = Item.I - AB;
bool VisitAsLvalue = FnType->getArgType(ParamIdx)->isReferenceType();
if (VisitAsLvalue)
VisitLValue(*Item.I, Item.N, Tmp);
else
Visit(*Item.I, Item.N, Tmp);
++(Item.I);
for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI != NE; ++NI)
WorkList.push_back(CallExprWLItem(Item.I, *NI));
}
// Evaluate the implicit object argument.
ExplodedNodeSet AllArgsEvaluated;
const MemberExpr *ME = dyn_cast<MemberExpr>(MCE->getCallee()->IgnoreParens());
if (!ME)
return;
Expr *ObjArgExpr = ME->getBase();
for (ExplodedNodeSet::iterator I = ArgsEvaluated.begin(),
E = ArgsEvaluated.end(); I != E; ++I) {
if (ME->isArrow())
Visit(ObjArgExpr, *I, AllArgsEvaluated);
else
VisitLValue(ObjArgExpr, *I, AllArgsEvaluated);
}
const CXXMethodDecl *MD = cast<CXXMethodDecl>(ME->getMemberDecl());
assert(MD && "not a CXXMethodDecl?");
if (!MD->isThisDeclarationADefinition())
// FIXME: conservative method call evaluation.
return;
const StackFrameContext *SFC = AMgr.getStackFrame(MD,
Pred->getLocationContext(),
MCE,
Builder->getBlock(),
Builder->getIndex());
const CXXThisRegion *ThisR = getCXXThisRegion(MD, SFC);
CallEnter Loc(MCE, MD, Pred->getLocationContext());
for (ExplodedNodeSet::iterator I = AllArgsEvaluated.begin(),
E = AllArgsEvaluated.end(); I != E; ++I) {
// Set up 'this' region.
const GRState *state = GetState(*I);
state = state->bindLoc(loc::MemRegionVal(ThisR),state->getSVal(ObjArgExpr));
ExplodedNode *N = Builder->generateNode(Loc, state, *I);
if (N)
Dst.Add(N);
}
}
const CXXThisRegion *GRExprEngine::getCXXThisRegion(const CXXMethodDecl *D,
const StackFrameContext *SFC) {
Type *T = D->getParent()->getTypeForDecl();
QualType PT = getContext().getPointerType(QualType(T,0));
return ValMgr.getRegionManager().getCXXThisRegion(PT, SFC);
}
//===----------------------------------------------------------------------===//
// Checker registration/lookup.
//===----------------------------------------------------------------------===//

View File

@ -11,10 +11,10 @@
//
//===----------------------------------------------------------------------===//
#include "clang/Analysis/CFG.h"
#include "clang/Checker/PathSensitive/GRStateTrait.h"
#include "clang/Checker/PathSensitive/GRState.h"
#include "clang/Checker/PathSensitive/GRTransferFuncs.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
@ -227,6 +227,18 @@ const GRState* GRStateManager::addGDM(const GRState* St, void* Key, void* Data){
return getPersistentState(NewSt);
}
const GRState *GRStateManager::removeGDM(const GRState *state, void *Key) {
GRState::GenericDataMap OldM = state->getGDM();
GRState::GenericDataMap NewM = GDMFactory.Remove(OldM, Key);
if (NewM == OldM)
return state;
GRState NewState = *state;
NewState.GDM = NewM;
return getPersistentState(NewState);
}
//===----------------------------------------------------------------------===//
// Utility.
//===----------------------------------------------------------------------===//

View File

@ -17,7 +17,7 @@
#include "GRExprEngineInternalChecks.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Checker/BugReporter/BugReporter.h"
#include "clang/Checker/BugReporter/BugType.h"
#include "clang/Checker/PathSensitive/CheckerVisitor.h"
#include "clang/Checker/PathSensitive/GRStateTrait.h"
#include "llvm/ADT/SmallString.h"

View File

@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "GRExprEngineExperimentalChecks.h"
#include "clang/Checker/BugReporter/BugType.h"
#include "clang/Checker/PathSensitive/CheckerVisitor.h"
#include "clang/Checker/PathSensitive/GRState.h"
#include "clang/Checker/PathSensitive/GRStateTrait.h"

View File

@ -13,10 +13,10 @@
//
//===----------------------------------------------------------------------===//
#include "clang/Analysis/AnalysisContext.h"
#include "clang/Checker/PathSensitive/MemRegion.h"
#include "clang/Analysis/AnalysisContext.h"
#include "clang/Analysis/Support/BumpVector.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/StmtVisitor.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;

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