Merged in mainline Clang on August 29, 2011.
llvm-svn: 138733
diff --git a/safecode/tools/clang/include/clang/ARCMigrate/FileRemapper.h b/safecode/tools/clang/include/clang/ARCMigrate/FileRemapper.h
index 8a4e132..181e130 100644
--- a/safecode/tools/clang/include/clang/ARCMigrate/FileRemapper.h
+++ b/safecode/tools/clang/include/clang/ARCMigrate/FileRemapper.h
@@ -65,7 +65,7 @@
const FileEntry *getOriginalFile(StringRef filePath);
void resetTarget(Target &targ);
- bool report(const std::string &err, Diagnostic &Diag);
+ bool report(const Twine &err, Diagnostic &Diag);
std::string getRemapInfoFile(StringRef outputDir);
};
diff --git a/safecode/tools/clang/include/clang/AST/DeclBase.h b/safecode/tools/clang/include/clang/AST/DeclBase.h
index 042c50f..8dc15de 100644
--- a/safecode/tools/clang/include/clang/AST/DeclBase.h
+++ b/safecode/tools/clang/include/clang/AST/DeclBase.h
@@ -1322,6 +1322,12 @@
ExternalVisibleStorage = ES;
}
+ /// \brief Determine whether the given declaration is stored in the list of
+ /// declarations lexically within this context.
+ bool isDeclInLexicalTraversal(const Decl *D) const {
+ return D && (D->NextDeclInContext || D == FirstDecl || D == LastDecl);
+ }
+
static bool classof(const Decl *D);
static bool classof(const DeclContext *D) { return true; }
#define DECL(NAME, BASE)
diff --git a/safecode/tools/clang/include/clang/AST/DeclObjC.h b/safecode/tools/clang/include/clang/AST/DeclObjC.h
index 6f03443..e639606 100644
--- a/safecode/tools/clang/include/clang/AST/DeclObjC.h
+++ b/safecode/tools/clang/include/clang/AST/DeclObjC.h
@@ -918,29 +918,23 @@
ObjCInterfaceDecl *getInterface() const { return ID; }
};
private:
- ObjCClassRef *ForwardDecls;
- unsigned NumDecls;
+ ObjCClassRef *ForwardDecl;
ObjCClassDecl(DeclContext *DC, SourceLocation L,
- ObjCInterfaceDecl *const *Elts, const SourceLocation *Locs,
- unsigned nElts, ASTContext &C);
+ ObjCInterfaceDecl *const Elt, const SourceLocation Loc,
+ ASTContext &C);
public:
static ObjCClassDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L,
- ObjCInterfaceDecl *const *Elts = 0,
- const SourceLocation *Locs = 0,
- unsigned nElts = 0);
+ ObjCInterfaceDecl *const Elt = 0,
+ const SourceLocation Locs = SourceLocation());
+
+ ObjCInterfaceDecl *getForwardInterfaceDecl() { return ForwardDecl->getInterface(); }
+ ObjCClassRef *getForwardDecl() { return ForwardDecl; }
+ void setClass(ASTContext &C, ObjCInterfaceDecl*const Cls,
+ const SourceLocation Locs);
virtual SourceRange getSourceRange() const;
- typedef const ObjCClassRef* iterator;
- iterator begin() const { return ForwardDecls; }
- iterator end() const { return ForwardDecls + NumDecls; }
- unsigned size() const { return NumDecls; }
-
- /// setClassList - Set the list of forward classes.
- void setClassList(ASTContext &C, ObjCInterfaceDecl*const*List,
- const SourceLocation *Locs, unsigned Num);
-
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const ObjCClassDecl *D) { return true; }
static bool classofKind(Kind K) { return K == ObjCClass; }
diff --git a/safecode/tools/clang/include/clang/Basic/Builtins.def b/safecode/tools/clang/include/clang/Basic/Builtins.def
index d12a04d..50cf872 100644
--- a/safecode/tools/clang/include/clang/Basic/Builtins.def
+++ b/safecode/tools/clang/include/clang/Basic/Builtins.def
@@ -389,7 +389,7 @@
BUILTIN(__builtin_classify_type, "i.", "nct")
BUILTIN(__builtin___CFStringMakeConstantString, "FC*cC*", "nc")
BUILTIN(__builtin___NSStringMakeConstantString, "FC*cC*", "nc")
-BUILTIN(__builtin_va_start, "vA.", "n")
+BUILTIN(__builtin_va_start, "vA.", "nt")
BUILTIN(__builtin_va_end, "vA", "n")
BUILTIN(__builtin_va_copy, "vAA", "n")
BUILTIN(__builtin_stdarg_start, "vA.", "n")
diff --git a/safecode/tools/clang/include/clang/Basic/DiagnosticCommonKinds.td b/safecode/tools/clang/include/clang/Basic/DiagnosticCommonKinds.td
index 4b5de36..62d8525 100644
--- a/safecode/tools/clang/include/clang/Basic/DiagnosticCommonKinds.td
+++ b/safecode/tools/clang/include/clang/Basic/DiagnosticCommonKinds.td
@@ -59,7 +59,8 @@
"cannot define a function with non-namespace scope in a friend declaration">;
def err_deleted_non_function : Error<
"only functions can have deleted definitions">;
-
+def warn_module_not_found : Warning<"module '%0' not found">, DefaultFatal;
+
// Sema && Lex
def ext_longlong : Extension<
"'long long' is an extension when C99 mode is not enabled">,
diff --git a/safecode/tools/clang/include/clang/Basic/DiagnosticGroups.td b/safecode/tools/clang/include/clang/Basic/DiagnosticGroups.td
index add2ac3..a552542 100644
--- a/safecode/tools/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/safecode/tools/clang/include/clang/Basic/DiagnosticGroups.td
@@ -235,11 +235,12 @@
DiagCategory<"Unused Entity Issue">;
// Format settings.
+def FormatInvalidSpecifier : DiagGroup<"format-invalid-specifier">;
def FormatSecurity : DiagGroup<"format-security">;
def FormatY2K : DiagGroup<"format-y2k">;
def Format : DiagGroup<"format",
[FormatExtraArgs, FormatZeroLength, NonNull,
- FormatSecurity, FormatY2K]>,
+ FormatSecurity, FormatY2K, FormatInvalidSpecifier]>,
DiagCategory<"Format String Issue">;
def FormatNonLiteral : DiagGroup<"format-nonliteral", [FormatSecurity]>;
def Format2 : DiagGroup<"format=2",
diff --git a/safecode/tools/clang/include/clang/Basic/DiagnosticParseKinds.td b/safecode/tools/clang/include/clang/Basic/DiagnosticParseKinds.td
index 27b4f85..9a6e754 100644
--- a/safecode/tools/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/safecode/tools/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -569,5 +569,11 @@
def err_seh___finally_block : Error<
"%0 only allowed in __finally block">;
+// Modules
+def err_module_expected_ident : Error<
+ "expected a module name after '__import__'">;
+def err_module_expected_semi : Error<
+ "expected a semicolon name after module name">;
+
} // end of Parse Issue category.
} // end of Parser diagnostics
diff --git a/safecode/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td b/safecode/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 3d8fbd3..7bf2dc4 100644
--- a/safecode/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/safecode/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -573,6 +573,9 @@
def warn_objc_missing_super_dealloc : Warning<
"method possibly missing a [super dealloc] call">,
InGroup<ObjCMissingSuperCalls>;
+def warn_objc_missing_super_finalize : Warning<
+ "method possibly missing a [super finalize] call">,
+ InGroup<ObjCMissingSuperCalls>;
def warn_undeclared_selector : Warning<
"undeclared selector %0">, InGroup<UndeclaredSelector>, DefaultIgnore;
def warn_implicit_atomic_property : Warning<
@@ -2851,7 +2854,8 @@
"existing ivar %1 for strong property %0 may not be "
"%select{|__unsafe_unretained||__weak}2">;
def err_arc_assign_property_ownership : Error<
- "existing ivar %1 for unsafe_unretained property %0 must be __unsafe_unretained">;
+ "existing ivar %1 for property %0 with %select{unsafe_unretained| assign}2 "
+ "attribute must be __unsafe_unretained">;
def err_arc_inconsistent_property_ownership : Error<
"%select{strong|weak|unsafe_unretained}1 property %0 may not also be "
"declared %select{|__unsafe_unretained|__strong|__weak|__autoreleasing}2">;
@@ -3371,10 +3375,11 @@
def warn_setter_getter_impl_required : Warning<
"property %0 requires method %1 to be defined - "
- "use @synthesize, @dynamic or provide a method implementation">;
+ "use @synthesize, @dynamic or provide a method implementation "
+ "in this class implementation">;
def warn_setter_getter_impl_required_in_category : Warning<
"property %0 requires method %1 to be defined - "
- "use @dynamic or provide a method implementation in category">;
+ "use @dynamic or provide a method implementation in this category">;
def note_property_impl_required : Note<
"implementation is here">;
def note_parameter_named_here : Note<
@@ -4231,7 +4236,7 @@
def warn_printf_data_arg_not_used : Warning<
"data argument not used by format string">, InGroup<FormatExtraArgs>;
def warn_format_invalid_conversion : Warning<
- "invalid conversion specifier '%0'">, InGroup<Format>;
+ "invalid conversion specifier '%0'">, InGroup<FormatInvalidSpecifier>;
def warn_printf_incomplete_specifier : Warning<
"incomplete format specifier">, InGroup<Format>;
def warn_missing_format_string : Warning<
diff --git a/safecode/tools/clang/include/clang/Basic/IdentifierTable.h b/safecode/tools/clang/include/clang/Basic/IdentifierTable.h
index 017af5c..bd0b539 100644
--- a/safecode/tools/clang/include/clang/Basic/IdentifierTable.h
+++ b/safecode/tools/clang/include/clang/Basic/IdentifierTable.h
@@ -487,6 +487,7 @@
// selector with the given name.
OMF_autorelease,
OMF_dealloc,
+ OMF_finalize,
OMF_release,
OMF_retain,
OMF_retainCount,
diff --git a/safecode/tools/clang/include/clang/Basic/TokenKinds.def b/safecode/tools/clang/include/clang/Basic/TokenKinds.def
index e0b22b7..ccc2e61 100644
--- a/safecode/tools/clang/include/clang/Basic/TokenKinds.def
+++ b/safecode/tools/clang/include/clang/Basic/TokenKinds.def
@@ -397,6 +397,7 @@
// Apple Extension.
KEYWORD(__private_extern__ , KEYALL)
+KEYWORD(__import__ , KEYALL)
// Microsoft Extension.
KEYWORD(__declspec , KEYALL)
diff --git a/safecode/tools/clang/include/clang/Driver/CC1Options.td b/safecode/tools/clang/include/clang/Driver/CC1Options.td
index 8ba8c4f..9535add 100644
--- a/safecode/tools/clang/include/clang/Driver/CC1Options.td
+++ b/safecode/tools/clang/include/clang/Driver/CC1Options.td
@@ -404,9 +404,6 @@
def arcmt_migrate_emit_arc_errors : Flag<"-arcmt-migrate-emit-errors">,
HelpText<"Emit ARC errors even if the migrator can fix them">;
-def import_module : Separate<"-import-module">,
- HelpText<"Import a module definition file">;
-
def working_directory : JoinedOrSeparate<"-working-directory">,
HelpText<"Resolve file paths relative to the specified directory">;
def working_directory_EQ : Joined<"-working-directory=">,
diff --git a/safecode/tools/clang/include/clang/Driver/Driver.h b/safecode/tools/clang/include/clang/Driver/Driver.h
index e979146..bcb75b3 100644
--- a/safecode/tools/clang/include/clang/Driver/Driver.h
+++ b/safecode/tools/clang/include/clang/Driver/Driver.h
@@ -373,11 +373,11 @@
const char *BaseInput,
bool AtTopLevel) const;
- /// GetTemporaryPath - Return the pathname of a temporary file to
- /// use as part of compilation; the file will have the given suffix.
+ /// GetTemporaryPath - Return the pathname of a temporary file to use
+ /// as part of compilation; the file will have the given prefix and suffix.
///
/// GCC goes to extra lengths here to be a bit more robust.
- std::string GetTemporaryPath(const char *Suffix) const;
+ std::string GetTemporaryPath(StringRef Prefix, const char *Suffix) const;
/// GetHostInfo - Construct a new host info object for the given
/// host triple.
diff --git a/safecode/tools/clang/include/clang/Frontend/ASTUnit.h b/safecode/tools/clang/include/clang/Frontend/ASTUnit.h
index 190ab85..731ce38 100644
--- a/safecode/tools/clang/include/clang/Frontend/ASTUnit.h
+++ b/safecode/tools/clang/include/clang/Frontend/ASTUnit.h
@@ -18,6 +18,7 @@
#include "clang/Serialization/ASTBitCodes.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/CodeCompleteConsumer.h"
+#include "clang/Lex/ModuleLoader.h"
#include "clang/Lex/PreprocessingRecord.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/FileManager.h"
@@ -66,7 +67,7 @@
/// \brief Utility class for loading a ASTContext from an AST file.
///
-class ASTUnit {
+class ASTUnit : public ModuleLoader {
public:
typedef std::map<FileID, std::vector<PreprocessedEntity *> >
PreprocessedEntitiesByFileMap;
@@ -696,6 +697,13 @@
///
/// \returns True if an error occurred, false otherwise.
bool serialize(raw_ostream &OS);
+
+ virtual ModuleKey loadModule(SourceLocation ImportLoc,
+ IdentifierInfo &ModuleName,
+ SourceLocation ModuleNameLoc) {
+ // ASTUnit doesn't know how to load modules (not that this matters).
+ return 0;
+ }
};
} // namespace clang
diff --git a/safecode/tools/clang/include/clang/Frontend/CompilerInstance.h b/safecode/tools/clang/include/clang/Frontend/CompilerInstance.h
index 3f97f1a..88f8976 100644
--- a/safecode/tools/clang/include/clang/Frontend/CompilerInstance.h
+++ b/safecode/tools/clang/include/clang/Frontend/CompilerInstance.h
@@ -11,6 +11,7 @@
#define LLVM_CLANG_FRONTEND_COMPILERINSTANCE_H_
#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Lex/ModuleLoader.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/OwningPtr.h"
@@ -56,7 +57,7 @@
/// in to the compiler instance for everything. When possible, utility functions
/// come in two forms; a short form that reuses the CompilerInstance objects,
/// and a long form that takes explicit instances of any required objects.
-class CompilerInstance {
+class CompilerInstance : public ModuleLoader {
/// The options used in this compiler instance.
llvm::IntrusiveRefCntPtr<CompilerInvocation> Invocation;
@@ -498,20 +499,6 @@
/// and replace any existing one with it.
void createPreprocessor();
- /// Create a Preprocessor object.
- ///
- /// Note that this also creates a new HeaderSearch object which will be owned
- /// by the resulting Preprocessor.
- ///
- /// \return The new object on success, or null on failure.
- static Preprocessor *createPreprocessor(Diagnostic &, const LangOptions &,
- const PreprocessorOptions &,
- const HeaderSearchOptions &,
- const DependencyOutputOptions &,
- const TargetInfo &,
- const FrontendOptions &,
- SourceManager &, FileManager &);
-
/// Create the AST context.
void createASTContext();
@@ -626,6 +613,10 @@
const FrontendOptions &Opts);
/// }
+
+ virtual ModuleKey loadModule(SourceLocation ImportLoc,
+ IdentifierInfo &ModuleName,
+ SourceLocation ModuleNameLoc);
};
} // end namespace clang
diff --git a/safecode/tools/clang/include/clang/Frontend/FrontendOptions.h b/safecode/tools/clang/include/clang/Frontend/FrontendOptions.h
index ec75b59..4876ceb 100644
--- a/safecode/tools/clang/include/clang/Frontend/FrontendOptions.h
+++ b/safecode/tools/clang/include/clang/Frontend/FrontendOptions.h
@@ -119,9 +119,6 @@
/// \brief The list of AST files to merge.
std::vector<std::string> ASTMergeFiles;
- /// \brief The list of modules to import.
- std::vector<std::string> Modules;
-
/// \brief A list of arguments to forward to LLVM's option processing; this
/// should only be used for debugging and experimental features.
std::vector<std::string> LLVMArgs;
diff --git a/safecode/tools/clang/include/clang/Lex/ModuleLoader.h b/safecode/tools/clang/include/clang/Lex/ModuleLoader.h
new file mode 100644
index 0000000..72ec0e3
--- /dev/null
+++ b/safecode/tools/clang/include/clang/Lex/ModuleLoader.h
@@ -0,0 +1,55 @@
+//===--- ModuleLoader.h - Module Loader Interface ---------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the ModuleLoader interface, which is responsible for
+// loading named modules.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_LEX_MODULE_LOADER_H
+#define LLVM_CLANG_LEX_MODULE_LOADER_H
+
+#include "clang/Basic/SourceLocation.h"
+
+namespace clang {
+
+class IdentifierInfo;
+
+/// \brief An opaque key that is used to describe the module and can be
+/// interpreted by the module loader itself.
+typedef void *ModuleKey;
+
+/// \brief Abstract interface for a module loader.
+///
+/// This abstract interface describes a module loader, which is responsible
+/// for resolving a module name (e.g., "std") to an actual module file, and
+/// then loading that module.
+class ModuleLoader {
+public:
+ virtual ~ModuleLoader();
+
+ /// \brief Attempt to load the given module.
+ ///
+ /// This routine attempts to load the module described by the given
+ /// parameters.
+ ///
+ /// \param ImportLoc The location of the 'import' keyword.
+ /// \param ModuleName The name of the module to be loaded.
+ /// \param ModuleNameLoc The location of the module name.
+ ///
+ /// \returns If successful, a non-NULL module key describing this module.
+ /// Otherwise, returns NULL to indicate that the module could not be
+ /// loaded.
+ virtual ModuleKey loadModule(SourceLocation ImportLoc,
+ IdentifierInfo &ModuleName,
+ SourceLocation ModuleNameLoc) = 0;
+};
+
+}
+
+#endif
diff --git a/safecode/tools/clang/include/clang/Lex/Preprocessor.h b/safecode/tools/clang/include/clang/Lex/Preprocessor.h
index a956454..b14c7e8 100644
--- a/safecode/tools/clang/include/clang/Lex/Preprocessor.h
+++ b/safecode/tools/clang/include/clang/Lex/Preprocessor.h
@@ -49,6 +49,7 @@
class CodeCompletionHandler;
class DirectoryLookup;
class PreprocessingRecord;
+class ModuleLoader;
/// Preprocessor - This object engages in a tight little dance with the lexer to
/// efficiently preprocess tokens. Lexers know only about tokens within a
@@ -63,10 +64,12 @@
SourceManager &SourceMgr;
ScratchBuffer *ScratchBuf;
HeaderSearch &HeaderInfo;
+ ModuleLoader &TheModuleLoader;
/// \brief External source of macros.
ExternalPreprocessorSource *ExternalSource;
+
/// PTH - An optional PTHManager object used for getting tokens from
/// a token cache rather than lexing the original source file.
llvm::OwningPtr<PTHManager> PTH;
@@ -115,6 +118,9 @@
/// \brief Whether we have already loaded macros from the external source.
mutable bool ReadMacrosFromExternalSource : 1;
+ /// \brief Tracks the depth of Lex() Calls.
+ unsigned LexDepth;
+
/// Identifiers - This is mapping/lookup information for all identifiers in
/// the program, including program keywords.
mutable IdentifierTable Identifiers;
@@ -294,6 +300,7 @@
Preprocessor(Diagnostic &diags, const LangOptions &opts,
const TargetInfo &target,
SourceManager &SM, HeaderSearch &Headers,
+ ModuleLoader &TheModuleLoader,
IdentifierInfoLookup *IILookup = 0,
bool OwnsHeaderSearch = false);
@@ -325,6 +332,9 @@
return ExternalSource;
}
+ /// \brief Retrieve the module loader associated with this preprocessor.
+ ModuleLoader &getModuleLoader() const { return TheModuleLoader; }
+
/// SetCommentRetentionState - Control whether or not the preprocessor retains
/// comments in output.
void SetCommentRetentionState(bool KeepComments, bool KeepMacroComments) {
@@ -524,6 +534,7 @@
/// Lex - To lex a token from the preprocessor, just pull a token from the
/// current lexer or macro object.
void Lex(Token &Result) {
+ ++LexDepth;
if (CurLexer)
CurLexer->Lex(Result);
else if (CurPTHLexer)
@@ -532,6 +543,11 @@
CurTokenLexer->Lex(Result);
else
CachingLex(Result);
+ --LexDepth;
+
+ // If we have the __import__ keyword, handle the module import now.
+ if (Result.getKind() == tok::kw___import__ && LexDepth == 0)
+ HandleModuleImport(Result);
}
/// LexNonComment - Lex a token. If it's a comment, keep lexing until we get
@@ -1008,6 +1024,9 @@
/// the macro should not be expanded return true, otherwise return false.
bool HandleMacroExpandedIdentifier(Token &Tok, MacroInfo *MI);
+ /// \brief Handle a module import directive.
+ void HandleModuleImport(Token &Import);
+
/// \brief Cache macro expanded tokens for TokenLexers.
//
/// Works like a stack; a TokenLexer adds the macro expanded tokens that is
diff --git a/safecode/tools/clang/include/clang/Parse/Parser.h b/safecode/tools/clang/include/clang/Parse/Parser.h
index 1215e2d..f74a1e4 100644
--- a/safecode/tools/clang/include/clang/Parse/Parser.h
+++ b/safecode/tools/clang/include/clang/Parse/Parser.h
@@ -1060,8 +1060,8 @@
ExprResult ParseAsmStringLiteral();
// Objective-C External Declarations
- Decl *ParseObjCAtDirectives();
- Decl *ParseObjCAtClassDeclaration(SourceLocation atLoc);
+ Parser::DeclGroupPtrTy ParseObjCAtDirectives();
+ Parser::DeclGroupPtrTy ParseObjCAtClassDeclaration(SourceLocation atLoc);
Decl *ParseObjCAtInterfaceDeclaration(SourceLocation atLoc,
ParsedAttributes &prefixAttrs);
void ParseObjCClassInstanceVariables(Decl *interfaceDecl,
@@ -1916,6 +1916,10 @@
SourceLocation &DeclEnd);
//===--------------------------------------------------------------------===//
+ // Modules
+ DeclGroupPtrTy ParseModuleImport();
+
+ //===--------------------------------------------------------------------===//
// GNU G++: Type Traits [Type-Traits.html in the GCC manual]
ExprResult ParseUnaryTypeTrait();
ExprResult ParseBinaryTypeTrait();
diff --git a/safecode/tools/clang/include/clang/Sema/Sema.h b/safecode/tools/clang/include/clang/Sema/Sema.h
index adf2702..f6d5edc 100644
--- a/safecode/tools/clang/include/clang/Sema/Sema.h
+++ b/safecode/tools/clang/include/clang/Sema/Sema.h
@@ -493,6 +493,9 @@
/// A flag that is set when parsing a -dealloc method and no [super dealloc]
/// call was found yet.
bool ObjCShouldCallSuperDealloc;
+ /// A flag that is set when parsing a -finalize method and no [super finalize]
+ /// call was found yet.
+ bool ObjCShouldCallSuperFinalize;
/// \brief The set of declarations that have been referenced within
/// a potentially evaluated expression.
@@ -1073,6 +1076,17 @@
SourceLocation AsmLoc,
SourceLocation RParenLoc);
+ /// \brief The parser has processed a module import declaration.
+ ///
+ /// \param ImportLoc The location of the '__import__' keyword.
+ ///
+ /// \param ModuleName The name of the module.
+ ///
+ /// \param ModuleNameLoc The location of the module name.
+ DeclResult ActOnModuleImport(SourceLocation ImportLoc,
+ IdentifierInfo &ModuleName,
+ SourceLocation ModuleNameLoc);
+
/// Scope actions.
void ActOnPopScope(SourceLocation Loc, Scope *S);
void ActOnTranslationUnitScope(Scope *S);
@@ -4999,7 +5013,7 @@
IdentifierInfo *CatName,
SourceLocation CatLoc);
- Decl *ActOnForwardClassDeclaration(SourceLocation Loc,
+ DeclGroupPtrTy ActOnForwardClassDeclaration(SourceLocation Loc,
IdentifierInfo **IdentList,
SourceLocation *IdentLocs,
unsigned NumElts);
diff --git a/safecode/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/safecode/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
index 1c1b985..61b06bb 100644
--- a/safecode/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
+++ b/safecode/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
@@ -42,7 +42,6 @@
class BugReporter;
class BugReporterContext;
class ExprEngine;
-class ProgramState;
class BugType;
//===----------------------------------------------------------------------===//
diff --git a/safecode/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h b/safecode/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h
index 62b531b..78067cd 100644
--- a/safecode/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h
+++ b/safecode/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h
@@ -14,7 +14,6 @@
#ifndef LLVM_CLANG_ANALYSIS_BUGTYPE
#define LLVM_CLANG_ANALYSIS_BUGTYPE
-#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "llvm/ADT/FoldingSet.h"
#include <string>
@@ -22,6 +21,7 @@
namespace ento {
+class BugReporter;
class ExplodedNode;
class ExprEngine;
diff --git a/safecode/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/safecode/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
index bfac65b..1afa546 100644
--- a/safecode/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
+++ b/safecode/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
@@ -52,13 +52,19 @@
virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
const DiagnosticInfo &Info);
- virtual void HandlePathDiagnostic(const PathDiagnostic* D) = 0;
+ void HandlePathDiagnostic(const PathDiagnostic* D);
enum PathGenerationScheme { Minimal, Extensive };
virtual PathGenerationScheme getGenerationScheme() const { return Minimal; }
virtual bool supportsLogicalOpControlFlow() const { return false; }
virtual bool supportsAllBlockEdges() const { return false; }
virtual bool useVerboseDescription() const { return true; }
+
+protected:
+ /// The actual logic for handling path diagnostics, as implemented
+ /// by subclasses of PathDiagnosticClient.
+ virtual void HandlePathDiagnosticImpl(const PathDiagnostic* D) = 0;
+
};
//===----------------------------------------------------------------------===//
diff --git a/safecode/tools/clang/include/clang/StaticAnalyzer/Core/Checker.h b/safecode/tools/clang/include/clang/StaticAnalyzer/Core/Checker.h
index c93924d..268c85b 100644
--- a/safecode/tools/clang/include/clang/StaticAnalyzer/Core/Checker.h
+++ b/safecode/tools/clang/include/clang/StaticAnalyzer/Core/Checker.h
@@ -262,10 +262,10 @@
_checkRegionChanges(void *checker,
const ProgramState *state,
const StoreManager::InvalidatedSymbols *invalidated,
- const MemRegion * const *Begin,
- const MemRegion * const *End) {
+ ArrayRef<const MemRegion *> Explicits,
+ ArrayRef<const MemRegion *> Regions) {
return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated,
- Begin, End);
+ Explicits, Regions);
}
template <typename CHECKER>
static bool _wantsRegionChangeUpdate(void *checker,
@@ -338,6 +338,10 @@
class CheckerBase : public ProgramPointTag {
public:
StringRef getTagDescription() const;
+
+ /// See CheckerManager::runCheckersForPrintState.
+ virtual void printState(raw_ostream &Out, const ProgramState *State,
+ const char *NL, const char *Sep) const { }
};
template <typename CHECK1, typename CHECK2=check::_VoidCheck,
diff --git a/safecode/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h b/safecode/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
index ffbeced..db94b81 100644
--- a/safecode/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
+++ b/safecode/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
@@ -238,11 +238,19 @@
bool wantsRegionChangeUpdate(const ProgramState *state);
/// \brief Run checkers for region changes.
+ ///
+ /// This corresponds to the check::RegionChanges callback.
+ /// \param state The current program state.
+ /// \param invalidated A set of all symbols potentially touched by the change.
+ /// \param ExplicitRegions The regions explicitly requested for invalidation.
+ /// For example, in the case of a function call, these would be arguments.
+ /// \param Regions The transitive closure of accessible regions,
+ /// i.e. all regions that may have been touched by this change.
const ProgramState *
runCheckersForRegionChanges(const ProgramState *state,
const StoreManager::InvalidatedSymbols *invalidated,
- const MemRegion * const *Begin,
- const MemRegion * const *End);
+ ArrayRef<const MemRegion *> ExplicitRegions,
+ ArrayRef<const MemRegion *> Regions);
/// \brief Run checkers for handling assumptions on symbolic values.
const ProgramState *runCheckersForEvalAssume(const ProgramState *state,
@@ -259,6 +267,17 @@
AnalysisManager &mgr,
BugReporter &BR);
+ /// \brief Run checkers for debug-printing a ProgramState.
+ ///
+ /// Unlike most other callbacks, any checker can simply implement the virtual
+ /// method CheckerBase::printState if it has custom data to print.
+ /// \param Out The output stream
+ /// \param State The state being printed
+ /// \param NL The preferred representation of a newline.
+ /// \param Sep The preferred separator between different kinds of data.
+ void runCheckersForPrintState(raw_ostream &Out, const ProgramState *State,
+ const char *NL, const char *Sep);
+
//===----------------------------------------------------------------------===//
// Internal registration functions for AST traversing.
//===----------------------------------------------------------------------===//
@@ -305,8 +324,8 @@
typedef CheckerFn<const ProgramState * (const ProgramState *,
const StoreManager::InvalidatedSymbols *symbols,
- const MemRegion * const *begin,
- const MemRegion * const *end)>
+ ArrayRef<const MemRegion *> ExplicitRegions,
+ ArrayRef<const MemRegion *> Regions)>
CheckRegionChangesFunc;
typedef CheckerFn<bool (const ProgramState *)> WantsRegionChangeUpdateFunc;
diff --git a/safecode/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h b/safecode/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
index 4c03974..3f6ddde 100644
--- a/safecode/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
+++ b/safecode/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
@@ -14,8 +14,8 @@
#ifndef LLVM_CLANG_GR_CONSTRAINT_MANAGER_H
#define LLVM_CLANG_GR_CONSTRAINT_MANAGER_H
-// FIXME: Typedef LiveSymbolsTy/DeadSymbolsTy at a more appropriate place.
-#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
namespace llvm {
class APSInt;
@@ -28,7 +28,6 @@
class ProgramState;
class ProgramStateManager;
class SubEngine;
-class SVal;
class ConstraintManager {
public:
diff --git a/safecode/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/safecode/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
index fceafd7..9351827 100644
--- a/safecode/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
+++ b/safecode/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
@@ -19,7 +19,6 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/WorkList.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h"
#include "llvm/ADT/OwningPtr.h"
namespace clang {
diff --git a/safecode/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h b/safecode/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h
index 802fb87..2463e23 100644
--- a/safecode/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h
+++ b/safecode/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h
@@ -14,7 +14,6 @@
#ifndef LLVM_CLANG_GR_ENVIRONMENT_H
#define LLVM_CLANG_GR_ENVIRONMENT_H
-#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "llvm/ADT/ImmutableMap.h"
diff --git a/safecode/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/safecode/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
index 1bdd572..2c0a935 100644
--- a/safecode/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ b/safecode/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -21,7 +21,6 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/TransferFuncs.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/AST/Type.h"
#include "clang/AST/ExprObjC.h"
@@ -35,6 +34,8 @@
namespace ento {
class AnalysisManager;
+class CallOrObjCMessage;
+class ObjCMessage;
class ExprEngine : public SubEngine {
AnalysisManager &AMgr;
@@ -192,8 +193,12 @@
const ProgramState *
processRegionChanges(const ProgramState *state,
const StoreManager::InvalidatedSymbols *invalidated,
- const MemRegion * const *Begin,
- const MemRegion * const *End);
+ ArrayRef<const MemRegion *> ExplicitRegions,
+ ArrayRef<const MemRegion *> Regions);
+
+ /// printState - Called by ProgramStateManager to print checker-specific data.
+ void printState(raw_ostream &Out, const ProgramState *State,
+ const char *NL, const char *Sep);
virtual ProgramStateManager& getStateManager() { return StateMgr; }
@@ -410,14 +415,17 @@
void evalObjCMessage(ExplodedNodeSet &Dst, const ObjCMessage &msg,
ExplodedNode *Pred, const ProgramState *state);
+ const ProgramState *invalidateArguments(const ProgramState *State,
+ const CallOrObjCMessage &Call,
+ const LocationContext *LC);
+
const ProgramState *MarkBranch(const ProgramState *St, const Stmt *Terminator,
bool branchTaken);
/// evalBind - Handle the semantics of binding a value to a specific location.
/// This method is used by evalStore, VisitDeclStmt, and others.
void evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE, ExplodedNode *Pred,
- const ProgramState *St, SVal location, SVal Val,
- bool atDeclInit = false);
+ SVal location, SVal Val, bool atDeclInit = false);
public:
// FIXME: 'tag' should be removed, and a LocationContext should be used
diff --git a/safecode/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h b/safecode/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h
index 247534d..bff94bc 100644
--- a/safecode/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h
+++ b/safecode/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h
@@ -18,6 +18,8 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/AST/ExprObjC.h"
+#include "clang/AST/ExprCXX.h"
+#include "llvm/ADT/PointerUnion.h"
namespace clang {
namespace ento {
@@ -86,6 +88,21 @@
return 0;
}
+ SVal getInstanceReceiverSVal(const ProgramState *State,
+ const LocationContext *LC) const {
+ assert(isValid() && "This ObjCMessage is uninitialized!");
+ if (!isInstanceMessage())
+ return UndefinedVal();
+ if (const Expr *Ex = getInstanceReceiver())
+ return State->getSValAsScalarOrLoc(Ex);
+
+ // An instance message with no expression means we are sending to super.
+ // In this case the object reference is the same as 'self'.
+ const ImplicitParamDecl *SelfDecl = LC->getSelfDecl();
+ assert(SelfDecl && "No message receiver Expr, but not in an ObjC method");
+ return State->getSVal(State->getRegion(SelfDecl, LC));
+ }
+
bool isInstanceMessage() const {
assert(isValid() && "This ObjCMessage is uninitialized!");
if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
@@ -96,7 +113,7 @@
}
const ObjCMethodDecl *getMethodDecl() const;
-
+
const ObjCInterfaceDecl *getReceiverInterface() const;
SourceLocation getSuperLoc() const {
@@ -106,45 +123,58 @@
return cast<ObjCPropertyRefExpr>(MsgOrPropE)->getReceiverLocation();
}
- SourceRange getSourceRange() const {
- assert(isValid() && "This ObjCMessage is uninitialized!");
+ SourceRange getSourceRange() const {
+ assert(isValid() && "This ObjCMessage is uninitialized!");
return MsgOrPropE->getSourceRange();
}
- unsigned getNumArgs() const {
- assert(isValid() && "This ObjCMessage is uninitialized!");
- if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
- return msgE->getNumArgs();
- return isPropertySetter() ? 1 : 0;
- }
+ unsigned getNumArgs() const {
+ assert(isValid() && "This ObjCMessage is uninitialized!");
+ if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
+ return msgE->getNumArgs();
+ return isPropertySetter() ? 1 : 0;
+ }
- SVal getArgSVal(unsigned i, const ProgramState *state) const {
- assert(isValid() && "This ObjCMessage is uninitialized!");
- assert(i < getNumArgs() && "Invalid index for argument");
- if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
- return state->getSVal(msgE->getArg(i));
- assert(isPropertySetter());
- return SetterArgV;
- }
+ SVal getArgSVal(unsigned i, const ProgramState *state) const {
+ assert(isValid() && "This ObjCMessage is uninitialized!");
+ assert(i < getNumArgs() && "Invalid index for argument");
+ if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
+ return state->getSVal(msgE->getArg(i));
+ assert(isPropertySetter());
+ return SetterArgV;
+ }
- QualType getArgType(unsigned i) const {
- assert(isValid() && "This ObjCMessage is uninitialized!");
- assert(i < getNumArgs() && "Invalid index for argument");
- if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
- return msgE->getArg(i)->getType();
- assert(isPropertySetter());
- return cast<ObjCPropertyRefExpr>(MsgOrPropE)->getType();
- }
-
- const Expr *getArgExpr(unsigned i) const;
+ QualType getArgType(unsigned i) const {
+ assert(isValid() && "This ObjCMessage is uninitialized!");
+ assert(i < getNumArgs() && "Invalid index for argument");
+ if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
+ return msgE->getArg(i)->getType();
+ assert(isPropertySetter());
+ return cast<ObjCPropertyRefExpr>(MsgOrPropE)->getType();
+ }
- SourceRange getArgSourceRange(unsigned i) const {
- assert(isValid() && "This ObjCMessage is uninitialized!");
- assert(i < getNumArgs() && "Invalid index for argument");
- if (const Expr *argE = getArgExpr(i))
- return argE->getSourceRange();
- return OriginE->getSourceRange();
- }
+ const Expr *getArgExpr(unsigned i) const;
+
+ SourceRange getArgSourceRange(unsigned i) const {
+ assert(isValid() && "This ObjCMessage is uninitialized!");
+ assert(i < getNumArgs() && "Invalid index for argument");
+ if (const Expr *argE = getArgExpr(i))
+ return argE->getSourceRange();
+ return OriginE->getSourceRange();
+ }
+
+ SourceRange getReceiverSourceRange() const {
+ assert(isValid() && "This ObjCMessage is uninitialized!");
+ if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
+ return msgE->getReceiverRange();
+
+ const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE);
+ if (propE->isObjectReceiver())
+ return propE->getBase()->getSourceRange();
+
+ // FIXME: This isn't a range.
+ return propE->getReceiverLocation();
+ }
};
class ObjCPropertyGetter : public ObjCMessage {
@@ -165,64 +195,89 @@
}
};
-/// \brief Common wrapper for a call expression or an ObjC message, mainly to
-/// provide a common interface for handling their arguments.
+/// \brief Common wrapper for a call expression, ObjC message, or C++
+/// constructor, mainly to provide a common interface for their arguments.
class CallOrObjCMessage {
- const CallExpr *CallE;
+ llvm::PointerUnion<const CallExpr *, const CXXConstructExpr *> CallE;
ObjCMessage Msg;
const ProgramState *State;
public:
CallOrObjCMessage(const CallExpr *callE, const ProgramState *state)
: CallE(callE), State(state) {}
+ CallOrObjCMessage(const CXXConstructExpr *consE, const ProgramState *state)
+ : CallE(consE), State(state) {}
CallOrObjCMessage(const ObjCMessage &msg, const ProgramState *state)
- : CallE(0), Msg(msg), State(state) {}
+ : CallE((CallExpr *)0), Msg(msg), State(state) {}
QualType getResultType(ASTContext &ctx) const;
bool isFunctionCall() const {
- return (bool) CallE;
+ return CallE && CallE.is<const CallExpr *>();
}
-
+
+ bool isCXXConstructExpr() const {
+ return CallE && CallE.is<const CXXConstructExpr *>();
+ }
+
+ bool isObjCMessage() const {
+ return !CallE;
+ }
+
bool isCXXCall() const {
- return CallE && isa<CXXMemberCallExpr>(CallE);
+ const CallExpr *ActualCallE = CallE.dyn_cast<const CallExpr *>();
+ return ActualCallE && isa<CXXMemberCallExpr>(ActualCallE);
}
const Expr *getOriginExpr() const {
- if (isFunctionCall())
- return CallE;
- return Msg.getOriginExpr();
+ if (!CallE)
+ return Msg.getOriginExpr();
+ if (const CXXConstructExpr *Ctor =
+ CallE.dyn_cast<const CXXConstructExpr *>())
+ return Ctor;
+ return CallE.get<const CallExpr *>();
}
SVal getFunctionCallee() const;
SVal getCXXCallee() const;
+ SVal getInstanceMessageReceiver(const LocationContext *LC) const;
unsigned getNumArgs() const {
- if (CallE) return CallE->getNumArgs();
- return Msg.getNumArgs();
+ if (!CallE)
+ return Msg.getNumArgs();
+ if (const CXXConstructExpr *Ctor =
+ CallE.dyn_cast<const CXXConstructExpr *>())
+ return Ctor->getNumArgs();
+ return CallE.get<const CallExpr *>()->getNumArgs();
}
SVal getArgSVal(unsigned i) const {
assert(i < getNumArgs());
- if (CallE)
- return State->getSVal(CallE->getArg(i));
- return Msg.getArgSVal(i, State);
+ if (!CallE)
+ return Msg.getArgSVal(i, State);
+ return State->getSVal(getArg(i));
}
- SVal getArgSValAsScalarOrLoc(unsigned i) const;
-
const Expr *getArg(unsigned i) const {
assert(i < getNumArgs());
- if (CallE)
- return CallE->getArg(i);
- return Msg.getArgExpr(i);
+ if (!CallE)
+ return Msg.getArgExpr(i);
+ if (const CXXConstructExpr *Ctor =
+ CallE.dyn_cast<const CXXConstructExpr *>())
+ return Ctor->getArg(i);
+ return CallE.get<const CallExpr *>()->getArg(i);
}
SourceRange getArgSourceRange(unsigned i) const {
assert(i < getNumArgs());
if (CallE)
- return CallE->getArg(i)->getSourceRange();
+ return getArg(i)->getSourceRange();
return Msg.getArgSourceRange(i);
}
+
+ SourceRange getReceiverSourceRange() const {
+ assert(isObjCMessage());
+ return Msg.getReceiverSourceRange();
+ }
};
}
diff --git a/safecode/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/safecode/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
index 40aedf3..c83792c 100644
--- a/safecode/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
+++ b/safecode/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
@@ -216,23 +216,13 @@
const ProgramState *unbindLoc(Loc LV) const;
- /// invalidateRegion - Returns the state with bindings for the given region
- /// cleared from the store. See invalidateRegions.
- const ProgramState *invalidateRegion(const MemRegion *R,
- const Expr *E, unsigned BlockCount,
- StoreManager::InvalidatedSymbols *IS = NULL)
- const {
- return invalidateRegions(&R, &R+1, E, BlockCount, IS, false);
- }
-
/// invalidateRegions - Returns the state with bindings for the given regions
/// cleared from the store. The regions are provided as a continuous array
/// from Begin to End. Optionally invalidates global regions as well.
- const ProgramState *invalidateRegions(const MemRegion * const *Begin,
- const MemRegion * const *End,
+ const ProgramState *invalidateRegions(ArrayRef<const MemRegion *> Regions,
const Expr *E, unsigned BlockCount,
- StoreManager::InvalidatedSymbols *IS,
- bool invalidateGlobals) const;
+ StoreManager::InvalidatedSymbols *IS = 0,
+ bool invalidateGlobals = false) const;
/// enterStackFrame - Returns the state for entry to the given stack frame,
/// preserving the current state.
@@ -342,14 +332,6 @@
return ProgramStateTrait<T>::Contains(ProgramStateTrait<T>::MakeData(d), key);
}
- // State pretty-printing.
- class Printer {
- public:
- virtual ~Printer() {}
- virtual void Print(raw_ostream &Out, const ProgramState *state,
- const char* nl, const char* sep) = 0;
- };
-
// Pretty-printing.
void print(raw_ostream &Out, CFG &C, const char *nl = "\n",
const char *sep = "") const;
@@ -368,11 +350,11 @@
--refCount;
}
- const ProgramState *invalidateRegionsImpl(const MemRegion * const *Begin,
- const MemRegion * const *End,
- const Expr *E, unsigned BlockCount,
- StoreManager::InvalidatedSymbols &IS,
- bool invalidateGlobals) const;
+ const ProgramState *
+ invalidateRegionsImpl(ArrayRef<const MemRegion *> Regions,
+ const Expr *E, unsigned BlockCount,
+ StoreManager::InvalidatedSymbols &IS,
+ bool invalidateGlobals) const;
};
class ProgramStateSet {
@@ -414,7 +396,6 @@
class ProgramStateManager {
friend class ProgramState;
- friend class ExprEngine; // FIXME: Remove.
private:
/// Eng - The SubEngine that owns this state manager.
SubEngine *Eng; /* Can be null. */
@@ -428,10 +409,6 @@
typedef llvm::DenseMap<void*,std::pair<void*,void (*)(void*)> > GDMContextsTy;
GDMContextsTy GDMContexts;
- /// Printers - A set of printer objects used for pretty-printing a ProgramState.
- /// ProgramStateManager owns these objects.
- std::vector<ProgramState::Printer*> Printers;
-
/// StateSet - FoldingSet containing all the states created for analyzing
/// a particular function. This is used to unique states.
llvm::FoldingSet<ProgramState> StateSet;
diff --git a/safecode/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h b/safecode/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
index 71c865c..a688d7f 100644
--- a/safecode/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
+++ b/safecode/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
@@ -187,12 +187,11 @@
/// even if they do not currently have bindings. Pass \c NULL if this
/// information will not be used.
virtual StoreRef invalidateRegions(Store store,
- const MemRegion * const *Begin,
- const MemRegion * const *End,
+ ArrayRef<const MemRegion *> Regions,
const Expr *E, unsigned Count,
InvalidatedSymbols &IS,
bool invalidateGlobals,
- InvalidatedRegions *Regions) = 0;
+ InvalidatedRegions *Invalidated) = 0;
/// enterStackFrame - Let the StoreManager to do something when execution
/// engine is about to execute into a callee.
diff --git a/safecode/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h b/safecode/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
index ef0cdc4..ae212bc 100644
--- a/safecode/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
+++ b/safecode/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
@@ -99,16 +99,20 @@
virtual const ProgramState *
processRegionChanges(const ProgramState *state,
const StoreManager::InvalidatedSymbols *invalidated,
- const MemRegion* const *Begin,
- const MemRegion* const *End) = 0;
+ ArrayRef<const MemRegion *> ExplicitRegions,
+ ArrayRef<const MemRegion *> Regions) = 0;
inline const ProgramState *
processRegionChange(const ProgramState *state,
const MemRegion* MR) {
- return processRegionChanges(state, 0, &MR, &MR+1);
+ return processRegionChanges(state, 0, MR, MR);
}
+ /// printState - Called by ProgramStateManager to print checker-specific data.
+ virtual void printState(raw_ostream &Out, const ProgramState *State,
+ const char *NL, const char *Sep) = 0;
+
/// Called by CoreEngine when the analysis worklist is either empty or the
// maximum number of analysis steps have been reached.
virtual void processEndWorklist(bool hasWorkRemaining) = 0;
diff --git a/safecode/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/TransferFuncs.h b/safecode/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/TransferFuncs.h
index 35f680b..a82fd26 100644
--- a/safecode/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/TransferFuncs.h
+++ b/safecode/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/TransferFuncs.h
@@ -36,7 +36,6 @@
TransferFuncs() {}
virtual ~TransferFuncs() {}
- virtual void RegisterPrinters(std::vector<ProgramState::Printer*>& Printers) {}
virtual void RegisterChecks(ExprEngine& Eng) {}
diff --git a/safecode/tools/clang/lib/ARCMigrate/FileRemapper.cpp b/safecode/tools/clang/lib/ARCMigrate/FileRemapper.cpp
index 55ba371..604893e 100644
--- a/safecode/tools/clang/lib/ARCMigrate/FileRemapper.cpp
+++ b/safecode/tools/clang/lib/ARCMigrate/FileRemapper.cpp
@@ -59,38 +59,38 @@
return false;
std::vector<std::pair<const FileEntry *, const FileEntry *> > pairs;
+
+ llvm::OwningPtr<llvm::MemoryBuffer> fileBuf;
+ if (llvm::error_code ec = llvm::MemoryBuffer::getFile(infoFile.c_str(),
+ fileBuf))
+ return report("Error opening file: " + infoFile, Diag);
+
+ SmallVector<StringRef, 64> lines;
+ fileBuf->getBuffer().split(lines, "\n");
- std::ifstream fin(infoFile.c_str());
- if (!fin.good())
- return report(std::string("Error opening file: ") + infoFile, Diag);
-
- while (true) {
- std::string fromFilename, toFilename;
- uint64_t timeModified;
-
- fin >> fromFilename >> timeModified >> toFilename;
- if (fin.eof())
- break;
- if (!fin.good())
- return report(std::string("Error in format of file: ") + infoFile, Diag);
-
+ for (unsigned idx = 0; idx+3 <= lines.size(); idx += 3) {
+ StringRef fromFilename = lines[idx];
+ unsigned long long timeModified;
+ lines[idx+1].getAsInteger(10, timeModified);
+ StringRef toFilename = lines[idx+2];
+
const FileEntry *origFE = FileMgr->getFile(fromFilename);
if (!origFE) {
if (ignoreIfFilesChanged)
continue;
- return report(std::string("File does not exist: ") + fromFilename, Diag);
+ return report("File does not exist: " + fromFilename, Diag);
}
const FileEntry *newFE = FileMgr->getFile(toFilename);
if (!newFE) {
if (ignoreIfFilesChanged)
continue;
- return report(std::string("File does not exist: ") + toFilename, Diag);
+ return report("File does not exist: " + toFilename, Diag);
}
if ((uint64_t)origFE->getModificationTime() != timeModified) {
if (ignoreIfFilesChanged)
continue;
- return report(std::string("File was modified: ") + fromFilename, Diag);
+ return report("File was modified: " + fromFilename, Diag);
}
pairs.push_back(std::make_pair(origFE, newFE));
@@ -107,8 +107,7 @@
bool existed;
if (fs::create_directory(outputDir, existed) != llvm::errc::success)
- return report(std::string("Could not create directory: ") + outputDir.str(),
- Diag);
+ return report("Could not create directory: " + outputDir, Diag);
std::string errMsg;
std::string infoFile = getRemapInfoFile(outputDir);
@@ -138,8 +137,7 @@
tempPath += path::extension(origFE->getName());
int fd;
if (fs::unique_file(tempPath.str(), fd, tempPath) != llvm::errc::success)
- return report(std::string("Could not create file: ") + tempPath.c_str(),
- Diag);
+ return report("Could not create file: " + tempPath.str(), Diag);
llvm::raw_fd_ostream newOut(fd, /*shouldClose=*/true);
llvm::MemoryBuffer *mem = I->second.get<llvm::MemoryBuffer *>();
@@ -165,20 +163,15 @@
const FileEntry *origFE = I->first;
if (const FileEntry *newFE = I->second.dyn_cast<const FileEntry *>()) {
if (fs::copy_file(newFE->getName(), origFE->getName(),
- fs::copy_option::overwrite_if_exists) != llvm::errc::success) {
- std::string err = "Could not copy file '";
- llvm::raw_string_ostream os(err);
- os << "Could not copy file '" << newFE->getName() << "' to file '"
- << origFE->getName() << "'";
- os.flush();
- return report(err, Diag);
- }
+ fs::copy_option::overwrite_if_exists) != llvm::errc::success)
+ return report(StringRef("Could not copy file '") + newFE->getName() +
+ "' to file '" + origFE->getName() + "'", Diag);
} else {
bool fileExists = false;
fs::exists(origFE->getName(), fileExists);
if (!fileExists)
- return report(std::string("File does not exist: ") + origFE->getName(),
+ return report(StringRef("File does not exist: ") + origFE->getName(),
Diag);
std::string errMsg;
@@ -283,9 +276,10 @@
}
}
-bool FileRemapper::report(const std::string &err, Diagnostic &Diag) {
+bool FileRemapper::report(const Twine &err, Diagnostic &Diag) {
+ llvm::SmallString<128> buf;
unsigned ID = Diag.getDiagnosticIDs()->getCustomDiagID(DiagnosticIDs::Error,
- err);
+ err.toStringRef(buf));
Diag.Report(ID);
return true;
}
diff --git a/safecode/tools/clang/lib/AST/ASTImporter.cpp b/safecode/tools/clang/lib/AST/ASTImporter.cpp
index 8b8308a..b6e3e62 100644
--- a/safecode/tools/clang/lib/AST/ASTImporter.cpp
+++ b/safecode/tools/clang/lib/AST/ASTImporter.cpp
@@ -3529,25 +3529,14 @@
// Import the location of this declaration.
SourceLocation Loc = Importer.Import(D->getLocation());
-
- SmallVector<ObjCInterfaceDecl *, 4> Interfaces;
- SmallVector<SourceLocation, 4> Locations;
- for (ObjCClassDecl::iterator From = D->begin(), FromEnd = D->end();
- From != FromEnd; ++From) {
- ObjCInterfaceDecl *ToIface
- = cast_or_null<ObjCInterfaceDecl>(Importer.Import(From->getInterface()));
- if (!ToIface)
- continue;
-
- Interfaces.push_back(ToIface);
- Locations.push_back(Importer.Import(From->getLocation()));
- }
-
+ ObjCClassDecl::ObjCClassRef *From = D->getForwardDecl();
+ ObjCInterfaceDecl *ToIface
+ = cast_or_null<ObjCInterfaceDecl>(Importer.Import(From->getInterface()));
ObjCClassDecl *ToClass = ObjCClassDecl::Create(Importer.getToContext(), DC,
- Loc,
- Interfaces.data(),
- Locations.data(),
- Interfaces.size());
+ Loc,
+ ToIface,
+ Importer.Import(From->getLocation()));
+
ToClass->setLexicalDeclContext(LexicalDC);
LexicalDC->addDecl(ToClass);
Importer.Imported(D, ToClass);
diff --git a/safecode/tools/clang/lib/AST/DeclBase.cpp b/safecode/tools/clang/lib/AST/DeclBase.cpp
index 8b1acb1..27e437c 100644
--- a/safecode/tools/clang/lib/AST/DeclBase.cpp
+++ b/safecode/tools/clang/lib/AST/DeclBase.cpp
@@ -841,6 +841,22 @@
// Notify that we have a DeclContext that is initializing.
ExternalASTSource::Deserializing ADeclContext(Source);
+ // We may have already loaded just the fields of this record, in which case
+ // we remove all of the fields from the list. The fields will be reloaded
+ // from the external source as part of re-establishing the context.
+ if (const RecordDecl *RD = dyn_cast<RecordDecl>(this)) {
+ if (RD->LoadedFieldsFromExternalStorage) {
+ while (FirstDecl && isa<FieldDecl>(FirstDecl)) {
+ Decl *Next = FirstDecl->NextDeclInContext;
+ FirstDecl->NextDeclInContext = 0;
+ FirstDecl = Next;
+ }
+
+ if (!FirstDecl)
+ LastDecl = 0;
+ }
+ }
+
// Load the external declarations, if any.
SmallVector<Decl*, 64> Decls;
ExternalLexicalStorage = false;
@@ -856,14 +872,6 @@
if (Decls.empty())
return;
- // We may have already loaded just the fields of this record, in which case
- // don't add the decls, just replace the FirstDecl/LastDecl chain.
- if (const RecordDecl *RD = dyn_cast<RecordDecl>(this))
- if (RD->LoadedFieldsFromExternalStorage) {
- llvm::tie(FirstDecl, LastDecl) = BuildDeclChain(Decls);
- return;
- }
-
// Splice the newly-read declarations into the beginning of the list
// of declarations.
Decl *ExternalFirst, *ExternalLast;
@@ -1022,12 +1030,10 @@
if (D->getDeclContext() == DCtx)
makeDeclVisibleInContextImpl(ND);
- // Insert any forward-declared Objective-C interfaces into the lookup
+ // Insert any forward-declared Objective-C interface into the lookup
// data structure.
if (ObjCClassDecl *Class = dyn_cast<ObjCClassDecl>(*D))
- for (ObjCClassDecl::iterator I = Class->begin(), IEnd = Class->end();
- I != IEnd; ++I)
- makeDeclVisibleInContextImpl(I->getInterface());
+ makeDeclVisibleInContextImpl(Class->getForwardInterfaceDecl());
// If this declaration is itself a transparent declaration context or
// inline namespace, add its members (recursively).
diff --git a/safecode/tools/clang/lib/AST/DeclObjC.cpp b/safecode/tools/clang/lib/AST/DeclObjC.cpp
index 813501f..09638fe 100644
--- a/safecode/tools/clang/lib/AST/DeclObjC.cpp
+++ b/safecode/tools/clang/lib/AST/DeclObjC.cpp
@@ -446,6 +446,7 @@
// These selectors have a conventional meaning only for instance methods.
case OMF_dealloc:
+ case OMF_finalize:
case OMF_retain:
case OMF_release:
case OMF_autorelease:
@@ -851,36 +852,31 @@
//===----------------------------------------------------------------------===//
ObjCClassDecl::ObjCClassDecl(DeclContext *DC, SourceLocation L,
- ObjCInterfaceDecl *const *Elts,
- const SourceLocation *Locs,
- unsigned nElts,
+ ObjCInterfaceDecl *const Elt,
+ const SourceLocation Loc,
ASTContext &C)
: Decl(ObjCClass, DC, L) {
- setClassList(C, Elts, Locs, nElts);
-}
-
-void ObjCClassDecl::setClassList(ASTContext &C, ObjCInterfaceDecl*const*List,
- const SourceLocation *Locs, unsigned Num) {
- ForwardDecls = (ObjCClassRef*) C.Allocate(sizeof(ObjCClassRef)*Num,
- llvm::alignOf<ObjCClassRef>());
- for (unsigned i = 0; i < Num; ++i)
- new (&ForwardDecls[i]) ObjCClassRef(List[i], Locs[i]);
-
- NumDecls = Num;
+ setClass(C, Elt, Loc);
}
ObjCClassDecl *ObjCClassDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
- ObjCInterfaceDecl *const *Elts,
- const SourceLocation *Locs,
- unsigned nElts) {
- return new (C) ObjCClassDecl(DC, L, Elts, Locs, nElts, C);
+ ObjCInterfaceDecl *const Elt,
+ const SourceLocation Loc) {
+ return new (C) ObjCClassDecl(DC, L, Elt, Loc, C);
}
+void ObjCClassDecl::setClass(ASTContext &C, ObjCInterfaceDecl*const Cls,
+ const SourceLocation Loc) {
+
+ ForwardDecl = (ObjCClassRef*) C.Allocate(sizeof(ObjCClassRef),
+ llvm::alignOf<ObjCClassRef>());
+ new (ForwardDecl) ObjCClassRef(Cls, Loc);
+}
+
SourceRange ObjCClassDecl::getSourceRange() const {
// FIXME: We should include the semicolon
- assert(NumDecls);
- return SourceRange(getLocation(), ForwardDecls[NumDecls-1].getLocation());
+ return SourceRange(getLocation(), ForwardDecl->getLocation());
}
//===----------------------------------------------------------------------===//
diff --git a/safecode/tools/clang/lib/AST/DeclPrinter.cpp b/safecode/tools/clang/lib/AST/DeclPrinter.cpp
index a1aff5d..3a95d13 100644
--- a/safecode/tools/clang/lib/AST/DeclPrinter.cpp
+++ b/safecode/tools/clang/lib/AST/DeclPrinter.cpp
@@ -812,11 +812,7 @@
void DeclPrinter::VisitObjCClassDecl(ObjCClassDecl *D) {
Out << "@class ";
- for (ObjCClassDecl::iterator I = D->begin(), E = D->end();
- I != E; ++I) {
- if (I != D->begin()) Out << ", ";
- Out << I->getInterface();
- }
+ Out << D->getForwardInterfaceDecl();
}
void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) {
diff --git a/safecode/tools/clang/lib/AST/DumpXML.cpp b/safecode/tools/clang/lib/AST/DumpXML.cpp
index dd0147c..2568ada 100644
--- a/safecode/tools/clang/lib/AST/DumpXML.cpp
+++ b/safecode/tools/clang/lib/AST/DumpXML.cpp
@@ -742,8 +742,7 @@
// ObjCClassDecl
void visitObjCClassDeclChildren(ObjCClassDecl *D) {
- for (ObjCClassDecl::iterator I = D->begin(), E = D->end(); I != E; ++I)
- visitDeclRef(I->getInterface());
+ visitDeclRef(D->getForwardInterfaceDecl());
}
// ObjCInterfaceDecl
diff --git a/safecode/tools/clang/lib/Analysis/CocoaConventions.cpp b/safecode/tools/clang/lib/Analysis/CocoaConventions.cpp
index ea60f26..3926ce5 100644
--- a/safecode/tools/clang/lib/Analysis/CocoaConventions.cpp
+++ b/safecode/tools/clang/lib/Analysis/CocoaConventions.cpp
@@ -40,6 +40,7 @@
case OMF_None:
case OMF_autorelease:
case OMF_dealloc:
+ case OMF_finalize:
case OMF_release:
case OMF_retain:
case OMF_retainCount:
diff --git a/safecode/tools/clang/lib/Basic/IdentifierTable.cpp b/safecode/tools/clang/lib/Basic/IdentifierTable.cpp
index edf2e99..792b0c9 100644
--- a/safecode/tools/clang/lib/Basic/IdentifierTable.cpp
+++ b/safecode/tools/clang/lib/Basic/IdentifierTable.cpp
@@ -392,6 +392,7 @@
if (sel.isUnarySelector()) {
if (name == "autorelease") return OMF_autorelease;
if (name == "dealloc") return OMF_dealloc;
+ if (name == "finalize") return OMF_finalize;
if (name == "release") return OMF_release;
if (name == "retain") return OMF_retain;
if (name == "retainCount") return OMF_retainCount;
diff --git a/safecode/tools/clang/lib/CodeGen/CGCall.cpp b/safecode/tools/clang/lib/CodeGen/CGCall.cpp
index 846e1aa..f7cb549 100644
--- a/safecode/tools/clang/lib/CodeGen/CGCall.cpp
+++ b/safecode/tools/clang/lib/CodeGen/CGCall.cpp
@@ -1431,9 +1431,14 @@
return emitWritebackArg(*this, args, CRE);
}
- if (type->isReferenceType())
+ assert(type->isReferenceType() == E->isGLValue() &&
+ "reference binding to unmaterialized r-value!");
+
+ if (E->isGLValue()) {
+ assert(E->getObjectKind() == OK_Ordinary);
return args.add(EmitReferenceBindingToExpr(E, /*InitializedDecl=*/0),
type);
+ }
if (hasAggregateLLVMType(type) && !E->getType()->isAnyComplexType() &&
isa<ImplicitCastExpr>(E) &&
diff --git a/safecode/tools/clang/lib/CodeGen/CGException.cpp b/safecode/tools/clang/lib/CodeGen/CGException.cpp
index 0605f62..5d6f572 100644
--- a/safecode/tools/clang/lib/CodeGen/CGException.cpp
+++ b/safecode/tools/clang/lib/CodeGen/CGException.cpp
@@ -477,7 +477,6 @@
return;
}
- CGBuilderTy::InsertPoint savedIP = CGF.Builder.saveIP();
CGF.EmitBlockAfterUses(dispatchBlock);
// If this isn't a catch-all filter, we need to check whether we got
diff --git a/safecode/tools/clang/lib/CodeGen/CGExpr.cpp b/safecode/tools/clang/lib/CodeGen/CGExpr.cpp
index 59b8fef..d26d787 100644
--- a/safecode/tools/clang/lib/CodeGen/CGExpr.cpp
+++ b/safecode/tools/clang/lib/CodeGen/CGExpr.cpp
@@ -2150,8 +2150,7 @@
LValue CodeGenFunction::EmitMaterializeTemporaryExpr(
const MaterializeTemporaryExpr *E) {
- RValue RV = EmitReferenceBindingToExpr(E->GetTemporaryExpr(),
- /*InitializedDecl=*/0);
+ RValue RV = EmitReferenceBindingToExpr(E, /*InitializedDecl=*/0);
return MakeAddrLValue(RV.getScalarVal(), E->getType());
}
diff --git a/safecode/tools/clang/lib/Driver/Driver.cpp b/safecode/tools/clang/lib/Driver/Driver.cpp
index 2baed75..534984b 100644
--- a/safecode/tools/clang/lib/Driver/Driver.cpp
+++ b/safecode/tools/clang/lib/Driver/Driver.cpp
@@ -1354,8 +1354,10 @@
// Output to a temporary file?
if ((!AtTopLevel && !C.getArgs().hasArg(options::OPT_save_temps)) ||
CCGenDiagnostics) {
+ StringRef Name = llvm::sys::path::filename(BaseInput);
+ std::pair<StringRef, StringRef> Split = Name.split('.');
std::string TmpName =
- GetTemporaryPath(types::getTypeTempSuffix(JA.getType()));
+ GetTemporaryPath(Split.first, types::getTypeTempSuffix(JA.getType()));
return C.addTempFile(C.getArgs().MakeArgString(TmpName.c_str()));
}
@@ -1388,9 +1390,11 @@
// If we're saving temps and the temp filename conflicts with the input
// filename, then avoid overwriting input file.
if (!AtTopLevel && C.getArgs().hasArg(options::OPT_save_temps) &&
- NamedOutput == BaseName) {
+ NamedOutput == BaseName) {
+ StringRef Name = llvm::sys::path::filename(BaseInput);
+ std::pair<StringRef, StringRef> Split = Name.split('.');
std::string TmpName =
- GetTemporaryPath(types::getTypeTempSuffix(JA.getType()));
+ GetTemporaryPath(Split.first, types::getTypeTempSuffix(JA.getType()));
return C.addTempFile(C.getArgs().MakeArgString(TmpName.c_str()));
}
@@ -1475,7 +1479,8 @@
return Name;
}
-std::string Driver::GetTemporaryPath(const char *Suffix) const {
+std::string Driver::GetTemporaryPath(StringRef Prefix, const char *Suffix)
+ const {
// FIXME: This is lame; sys::Path should provide this function (in particular,
// it should know how to find the temporary files dir).
std::string Error;
@@ -1487,7 +1492,7 @@
if (!TmpDir)
TmpDir = "/tmp";
llvm::sys::Path P(TmpDir);
- P.appendComponent("cc");
+ P.appendComponent(Prefix);
if (P.makeUnique(false, &Error)) {
Diag(clang::diag::err_drv_unable_to_make_temp) << Error;
return "";
diff --git a/safecode/tools/clang/lib/Driver/Tools.cpp b/safecode/tools/clang/lib/Driver/Tools.cpp
index 697ff69..2dbc18a 100644
--- a/safecode/tools/clang/lib/Driver/Tools.cpp
+++ b/safecode/tools/clang/lib/Driver/Tools.cpp
@@ -2464,103 +2464,121 @@
it != ie;) {
StringRef Option = *it;
+ bool RemoveOption = false;
- // We only remove warning options.
- if (!Option.startswith("-W")) {
- ++it;
+ // Remove -faltivec
+ if (Option.equals("-faltivec")) {
+ it = CmdArgs.erase(it);
+ ie = CmdArgs.end();
continue;
}
- if (Option.startswith("-Wno-"))
- Option = Option.substr(5);
- else
- Option = Option.substr(2);
-
- bool RemoveOption = llvm::StringSwitch<bool>(Option)
- .Case("address-of-temporary", true)
- .Case("ambiguous-member-template", true)
- .Case("analyzer-incompatible-plugin", true)
- .Case("array-bounds", true)
- .Case("array-bounds-pointer-arithmetic", true)
- .Case("bind-to-temporary-copy", true)
- .Case("bitwise-op-parentheses", true)
- .Case("bool-conversions", true)
- .Case("builtin-macro-redefined", true)
- .Case("c++-hex-floats", true)
- .Case("c++0x-compat", true)
- .Case("c++0x-extensions", true)
- .Case("c++0x-narrowing", true)
- .Case("c++0x-static-nonintegral-init", true)
- .Case("conditional-uninitialized", true)
- .Case("constant-conversion", true)
- .Case("CFString-literal", true)
- .Case("constant-logical-operand", true)
- .Case("custom-atomic-properties", true)
- .Case("default-arg-special-member", true)
- .Case("delegating-ctor-cycles", true)
- .Case("delete-non-virtual-dtor", true)
- .Case("deprecated-implementations", true)
- .Case("deprecated-writable-strings", true)
- .Case("distributed-object-modifiers", true)
- .Case("duplicate-method-arg", true)
- .Case("dynamic-class-memaccess", true)
- .Case("enum-compare", true)
- .Case("exit-time-destructors", true)
- .Case("gnu", true)
- .Case("gnu-designator", true)
- .Case("header-hygiene", true)
- .Case("idiomatic-parentheses", true)
- .Case("ignored-qualifiers", true)
- .Case("implicit-atomic-properties", true)
- .Case("incompatible-pointer-types", true)
- .Case("incomplete-implementation", true)
- .Case("initializer-overrides", true)
- .Case("invalid-noreturn", true)
- .Case("invalid-token-paste", true)
- .Case("literal-conversion", true)
- .Case("literal-range", true)
- .Case("local-type-template-args", true)
- .Case("logical-op-parentheses", true)
- .Case("method-signatures", true)
- .Case("microsoft", true)
- .Case("mismatched-tags", true)
- .Case("missing-method-return-type", true)
- .Case("non-pod-varargs", true)
- .Case("nonfragile-abi2", true)
- .Case("null-arithmetic", true)
- .Case("null-dereference", true)
- .Case("out-of-line-declaration", true)
- .Case("overriding-method-mismatch", true)
- .Case("readonly-setter-attrs", true)
- .Case("return-stack-address", true)
- .Case("self-assign", true)
- .Case("semicolon-before-method-body", true)
- .Case("sentinel", true)
- .Case("shift-overflow", true)
- .Case("shift-sign-overflow", true)
- .Case("sign-conversion", true)
- .Case("sizeof-array-argument", true)
- .Case("sizeof-pointer-memaccess", true)
- .Case("string-compare", true)
- .Case("super-class-method-mismatch", true)
- .Case("tautological-compare", true)
- .Case("typedef-redefinition", true)
- .Case("typename-missing", true)
- .Case("undefined-reinterpret-cast", true)
- .Case("unknown-warning-option", true)
- .Case("unnamed-type-template-args", true)
- .Case("unneeded-internal-declaration", true)
- .Case("unneeded-member-function", true)
- .Case("unused-comparison", true)
- .Case("unused-exception-parameter", true)
- .Case("unused-member-function", true)
- .Case("unused-result", true)
- .Case("vector-conversions", true)
- .Case("vla", true)
- .Case("used-but-marked-unused", true)
- .Case("weak-vtables", true)
- .Default(false);
-
+ // Handle machine specific options.
+ if (Option.startswith("-m")) {
+ RemoveOption = llvm::StringSwitch<bool>(Option)
+ .Case("-mthumb", true)
+ .Case("-mno-thumb", true)
+ .Case("-mno-fused-madd", true)
+ .Case("-mlong-branch", true)
+ .Case("-mlongcall", true)
+ .Case("-mcpu=G4", true)
+ .Case("-mcpu=G5", true)
+ .Default(false);
+ }
+
+ // Handle warning options.
+ if (Option.startswith("-W")) {
+ // Remove -W/-Wno- to reduce the number of cases.
+ if (Option.startswith("-Wno-"))
+ Option = Option.substr(5);
+ else
+ Option = Option.substr(2);
+
+ RemoveOption = llvm::StringSwitch<bool>(Option)
+ .Case("address-of-temporary", true)
+ .Case("ambiguous-member-template", true)
+ .Case("analyzer-incompatible-plugin", true)
+ .Case("array-bounds", true)
+ .Case("array-bounds-pointer-arithmetic", true)
+ .Case("bind-to-temporary-copy", true)
+ .Case("bitwise-op-parentheses", true)
+ .Case("bool-conversions", true)
+ .Case("builtin-macro-redefined", true)
+ .Case("c++-hex-floats", true)
+ .Case("c++0x-compat", true)
+ .Case("c++0x-extensions", true)
+ .Case("c++0x-narrowing", true)
+ .Case("c++0x-static-nonintegral-init", true)
+ .Case("conditional-uninitialized", true)
+ .Case("constant-conversion", true)
+ .Case("CFString-literal", true)
+ .Case("constant-logical-operand", true)
+ .Case("custom-atomic-properties", true)
+ .Case("default-arg-special-member", true)
+ .Case("delegating-ctor-cycles", true)
+ .Case("delete-non-virtual-dtor", true)
+ .Case("deprecated-implementations", true)
+ .Case("deprecated-writable-strings", true)
+ .Case("distributed-object-modifiers", true)
+ .Case("duplicate-method-arg", true)
+ .Case("dynamic-class-memaccess", true)
+ .Case("enum-compare", true)
+ .Case("exit-time-destructors", true)
+ .Case("gnu", true)
+ .Case("gnu-designator", true)
+ .Case("header-hygiene", true)
+ .Case("idiomatic-parentheses", true)
+ .Case("ignored-qualifiers", true)
+ .Case("implicit-atomic-properties", true)
+ .Case("incompatible-pointer-types", true)
+ .Case("incomplete-implementation", true)
+ .Case("initializer-overrides", true)
+ .Case("invalid-noreturn", true)
+ .Case("invalid-token-paste", true)
+ .Case("literal-conversion", true)
+ .Case("literal-range", true)
+ .Case("local-type-template-args", true)
+ .Case("logical-op-parentheses", true)
+ .Case("method-signatures", true)
+ .Case("microsoft", true)
+ .Case("mismatched-tags", true)
+ .Case("missing-method-return-type", true)
+ .Case("non-pod-varargs", true)
+ .Case("nonfragile-abi2", true)
+ .Case("null-arithmetic", true)
+ .Case("null-dereference", true)
+ .Case("out-of-line-declaration", true)
+ .Case("overriding-method-mismatch", true)
+ .Case("readonly-setter-attrs", true)
+ .Case("return-stack-address", true)
+ .Case("self-assign", true)
+ .Case("semicolon-before-method-body", true)
+ .Case("sentinel", true)
+ .Case("shift-overflow", true)
+ .Case("shift-sign-overflow", true)
+ .Case("sign-conversion", true)
+ .Case("sizeof-array-argument", true)
+ .Case("sizeof-pointer-memaccess", true)
+ .Case("string-compare", true)
+ .Case("super-class-method-mismatch", true)
+ .Case("tautological-compare", true)
+ .Case("typedef-redefinition", true)
+ .Case("typename-missing", true)
+ .Case("undefined-reinterpret-cast", true)
+ .Case("unknown-warning-option", true)
+ .Case("unnamed-type-template-args", true)
+ .Case("unneeded-internal-declaration", true)
+ .Case("unneeded-member-function", true)
+ .Case("unused-comparison", true)
+ .Case("unused-exception-parameter", true)
+ .Case("unused-member-function", true)
+ .Case("unused-result", true)
+ .Case("vector-conversions", true)
+ .Case("vla", true)
+ .Case("used-but-marked-unused", true)
+ .Case("weak-vtables", true)
+ .Default(false);
+ } // if (Option.startswith("-W"))
if (RemoveOption) {
it = CmdArgs.erase(it);
ie = CmdArgs.end();
@@ -2969,7 +2987,7 @@
// NOTE: gcc uses a temp .s file for this, but there doesn't seem
// to be a good reason.
const char *TmpPath = C.getArgs().MakeArgString(
- D.GetTemporaryPath("s"));
+ D.GetTemporaryPath("cc", "s"));
C.addTempFile(TmpPath);
CmdArgs.push_back(TmpPath);
@@ -3111,7 +3129,7 @@
// dsymutil step.
if (Version[0] >= 116 && D.IsUsingLTO(Args)) {
const char *TmpPath = C.getArgs().MakeArgString(
- D.GetTemporaryPath(types::getTypeTempSuffix(types::TY_Object)));
+ D.GetTemporaryPath("cc", types::getTypeTempSuffix(types::TY_Object)));
C.addTempFile(TmpPath);
CmdArgs.push_back("-object_path_lto");
CmdArgs.push_back(TmpPath);
diff --git a/safecode/tools/clang/lib/Frontend/ASTUnit.cpp b/safecode/tools/clang/lib/Frontend/ASTUnit.cpp
index 4a5a29a..cc96d48 100644
--- a/safecode/tools/clang/lib/Frontend/ASTUnit.cpp
+++ b/safecode/tools/clang/lib/Frontend/ASTUnit.cpp
@@ -616,7 +616,7 @@
AST->Target = TargetInfo::CreateTargetInfo(AST->getDiagnostics(),
TargetOpts);
AST->PP = new Preprocessor(AST->getDiagnostics(), LangInfo, *AST->Target,
- AST->getSourceManager(), HeaderInfo);
+ AST->getSourceManager(), HeaderInfo, *AST);
Preprocessor &PP = *AST->PP;
PP.setPredefines(Reader->getSuggestedPredefines());
@@ -707,9 +707,7 @@
}
if (ObjCClassDecl *Class = dyn_cast<ObjCClassDecl>(D)) {
- for (ObjCClassDecl::iterator I = Class->begin(), IEnd = Class->end();
- I != IEnd; ++I)
- AddTopLevelDeclarationToHash(I->getInterface(), Hash);
+ AddTopLevelDeclarationToHash(Class->getForwardInterfaceDecl(), Hash);
return;
}
}
diff --git a/safecode/tools/clang/lib/Frontend/CompilerInstance.cpp b/safecode/tools/clang/lib/Frontend/CompilerInstance.cpp
index ec8b6dc..f53d0b0 100644
--- a/safecode/tools/clang/lib/Frontend/CompilerInstance.cpp
+++ b/safecode/tools/clang/lib/Frontend/CompilerInstance.cpp
@@ -191,52 +191,38 @@
// Preprocessor
void CompilerInstance::createPreprocessor() {
- PP = createPreprocessor(getDiagnostics(), getLangOpts(),
- getPreprocessorOpts(), getHeaderSearchOpts(),
- getDependencyOutputOpts(), getTarget(),
- getFrontendOpts(), getSourceManager(),
- getFileManager());
-}
-
-Preprocessor *
-CompilerInstance::createPreprocessor(Diagnostic &Diags,
- const LangOptions &LangInfo,
- const PreprocessorOptions &PPOpts,
- const HeaderSearchOptions &HSOpts,
- const DependencyOutputOptions &DepOpts,
- const TargetInfo &Target,
- const FrontendOptions &FEOpts,
- SourceManager &SourceMgr,
- FileManager &FileMgr) {
+ const PreprocessorOptions &PPOpts = getPreprocessorOpts();
+
// Create a PTH manager if we are using some form of a token cache.
PTHManager *PTHMgr = 0;
if (!PPOpts.TokenCache.empty())
- PTHMgr = PTHManager::Create(PPOpts.TokenCache, Diags);
-
+ PTHMgr = PTHManager::Create(PPOpts.TokenCache, getDiagnostics());
+
// Create the Preprocessor.
- HeaderSearch *HeaderInfo = new HeaderSearch(FileMgr);
- Preprocessor *PP = new Preprocessor(Diags, LangInfo, Target,
- SourceMgr, *HeaderInfo, PTHMgr,
- /*OwnsHeaderSearch=*/true);
-
+ HeaderSearch *HeaderInfo = new HeaderSearch(getFileManager());
+ PP = new Preprocessor(getDiagnostics(), getLangOpts(), getTarget(),
+ getSourceManager(), *HeaderInfo, *this, PTHMgr,
+ /*OwnsHeaderSearch=*/true);
+
// Note that this is different then passing PTHMgr to Preprocessor's ctor.
// That argument is used as the IdentifierInfoLookup argument to
// IdentifierTable's ctor.
if (PTHMgr) {
- PTHMgr->setPreprocessor(PP);
+ PTHMgr->setPreprocessor(&*PP);
PP->setPTHManager(PTHMgr);
}
-
+
if (PPOpts.DetailedRecord)
PP->createPreprocessingRecord(
- PPOpts.DetailedRecordIncludesNestedMacroExpansions);
+ PPOpts.DetailedRecordIncludesNestedMacroExpansions);
- InitializePreprocessor(*PP, PPOpts, HSOpts, FEOpts);
-
+ InitializePreprocessor(*PP, PPOpts, getHeaderSearchOpts(), getFrontendOpts());
+
// Handle generating dependencies, if requested.
+ const DependencyOutputOptions &DepOpts = getDependencyOutputOpts();
if (!DepOpts.OutputFile.empty())
AttachDependencyFileGen(*PP, DepOpts);
-
+
// Handle generating header include information, if requested.
if (DepOpts.ShowHeaderIncludes)
AttachHeaderIncludeGen(*PP);
@@ -247,8 +233,6 @@
AttachHeaderIncludeGen(*PP, /*ShowAllHeaders=*/true, OutputPath,
/*ShowDepth=*/false);
}
-
- return PP;
}
// ASTContext
@@ -640,4 +624,68 @@
return !getDiagnostics().getClient()->getNumErrors();
}
+ModuleKey CompilerInstance::loadModule(SourceLocation ImportLoc,
+ IdentifierInfo &ModuleName,
+ SourceLocation ModuleNameLoc) {
+ // Determine what file we're searching from.
+ SourceManager &SourceMgr = getSourceManager();
+ SourceLocation ExpandedImportLoc = SourceMgr.getExpansionLoc(ImportLoc);
+ const FileEntry *CurFile
+ = SourceMgr.getFileEntryForID(SourceMgr.getFileID(ExpandedImportLoc));
+ if (!CurFile)
+ CurFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
+
+ // Search for a module with the given name.
+ std::string Filename = ModuleName.getName().str();
+ Filename += ".pcm";
+ const DirectoryLookup *CurDir = 0;
+ const FileEntry *ModuleFile
+ = PP->getHeaderSearchInfo().LookupFile(Filename, /*isAngled=*/false,
+ /*FromDir=*/0, CurDir, CurFile,
+ /*SearchPath=*/0,
+ /*RelativePath=*/0);
+ if (!ModuleFile) {
+ getDiagnostics().Report(ModuleNameLoc, diag::warn_module_not_found)
+ << ModuleName.getName()
+ << SourceRange(ImportLoc, ModuleNameLoc);
+ return 0;
+ }
+
+ // If we don't already have an ASTReader, create one now.
+ if (!ModuleManager) {
+ std::string Sysroot = getHeaderSearchOpts().Sysroot;
+ const PreprocessorOptions &PPOpts = getPreprocessorOpts();
+ ModuleManager = new ASTReader(getPreprocessor(), &*Context,
+ Sysroot.empty() ? "" : Sysroot.c_str(),
+ PPOpts.DisablePCHValidation,
+ PPOpts.DisableStatCache);
+ ModuleManager->setDeserializationListener(
+ getASTConsumer().GetASTDeserializationListener());
+ getASTContext().setASTMutationListener(
+ getASTConsumer().GetASTMutationListener());
+ llvm::OwningPtr<ExternalASTSource> Source;
+ Source.reset(ModuleManager);
+ getASTContext().setExternalSource(Source);
+ ModuleManager->InitializeSema(getSema());
+ }
+
+ // Try to load the module we found.
+ switch (ModuleManager->ReadAST(ModuleFile->getName(),
+ serialization::MK_Module)) {
+ case ASTReader::Success:
+ break;
+
+ case ASTReader::IgnorePCH:
+ // FIXME: The ASTReader will already have complained, but can we showhorn
+ // that diagnostic information into a more useful form?
+ return 0;
+
+ case ASTReader::Failure:
+ // Already complained.
+ return 0;
+ }
+
+ // FIXME: The module file's FileEntry makes a poor key indeed!
+ return (ModuleKey)ModuleFile;
+}
diff --git a/safecode/tools/clang/lib/Frontend/CompilerInvocation.cpp b/safecode/tools/clang/lib/Frontend/CompilerInvocation.cpp
index 54d69cc..0e54e9c 100644
--- a/safecode/tools/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/safecode/tools/clang/lib/Frontend/CompilerInvocation.cpp
@@ -498,10 +498,6 @@
Res.push_back("-ast-merge");
Res.push_back(Opts.ASTMergeFiles[i]);
}
- for (unsigned i = 0, e = Opts.Modules.size(); i != e; ++i) {
- Res.push_back("-import-module");
- Res.push_back(Opts.Modules[i]);
- }
for (unsigned i = 0, e = Opts.LLVMArgs.size(); i != e; ++i) {
Res.push_back("-mllvm");
Res.push_back(Opts.LLVMArgs[i]);
@@ -776,10 +772,6 @@
Res.push_back("-include");
Res.push_back(Opts.Includes[i]);
}
- for (unsigned i = 0, e = Opts.Modules.size(); i != e; ++i) {
- Res.push_back("-import_module");
- Res.push_back(Opts.Modules[i]);
- }
for (unsigned i = 0, e = Opts.MacroIncludes.size(); i != e; ++i) {
Res.push_back("-imacros");
Res.push_back(Opts.MacroIncludes[i]);
@@ -1285,7 +1277,6 @@
Opts.ASTMergeFiles = Args.getAllArgValues(OPT_ast_merge);
Opts.LLVMArgs = Args.getAllArgValues(OPT_mllvm);
Opts.FixWhatYouCan = Args.hasArg(OPT_fix_what_you_can);
- Opts.Modules = Args.getAllArgValues(OPT_import_module);
Opts.ARCMTAction = FrontendOptions::ARCMT_None;
if (const Arg *A = Args.getLastArg(OPT_arcmt_check,
@@ -1816,12 +1807,6 @@
Opts.ChainedIncludes.push_back(A->getValue(Args));
}
- for (arg_iterator it = Args.filtered_begin(OPT_import_module),
- ie = Args.filtered_end(); it != ie; ++it) {
- const Arg *A = *it;
- Opts.Modules.push_back(A->getValue(Args));
- }
-
// Include 'altivec.h' if -faltivec option present
if (Args.hasArg(OPT_faltivec))
Opts.Includes.push_back("altivec.h");
diff --git a/safecode/tools/clang/lib/Lex/Lexer.cpp b/safecode/tools/clang/lib/Lex/Lexer.cpp
index 1ec50cd..64b8744 100644
--- a/safecode/tools/clang/lib/Lex/Lexer.cpp
+++ b/safecode/tools/clang/lib/Lex/Lexer.cpp
@@ -1277,6 +1277,7 @@
// preprocessor, which may macro expand it or something.
if (II->isHandleIdentifierCase())
PP->HandleIdentifier(Result);
+
return;
}
diff --git a/safecode/tools/clang/lib/Lex/Preprocessor.cpp b/safecode/tools/clang/lib/Lex/Preprocessor.cpp
index 24d36cd..51908bd 100644
--- a/safecode/tools/clang/lib/Lex/Preprocessor.cpp
+++ b/safecode/tools/clang/lib/Lex/Preprocessor.cpp
@@ -35,6 +35,7 @@
#include "clang/Lex/ScratchBuffer.h"
#include "clang/Lex/LexDiagnostic.h"
#include "clang/Lex/CodeCompletionHandler.h"
+#include "clang/Lex/ModuleLoader.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/TargetInfo.h"
@@ -50,12 +51,12 @@
Preprocessor::Preprocessor(Diagnostic &diags, const LangOptions &opts,
const TargetInfo &target, SourceManager &SM,
- HeaderSearch &Headers,
+ HeaderSearch &Headers, ModuleLoader &TheModuleLoader,
IdentifierInfoLookup* IILookup,
bool OwnsHeaders)
: Diags(&diags), Features(opts), Target(target),FileMgr(Headers.getFileMgr()),
- SourceMgr(SM),
- HeaderInfo(Headers), ExternalSource(0),
+ SourceMgr(SM), HeaderInfo(Headers), TheModuleLoader(TheModuleLoader),
+ ExternalSource(0),
Identifiers(opts, IILookup), BuiltinInfo(Target), CodeComplete(0),
CodeCompletionFile(0), SkipMainFilePreamble(0, true), CurPPLexer(0),
CurDirLookup(0), Callbacks(0), MacroArgCache(0), Record(0), MIChainHead(0),
@@ -87,6 +88,8 @@
// We haven't read anything from the external source.
ReadMacrosFromExternalSource = false;
+ LexDepth = 0;
+
// "Poison" __VA_ARGS__, which can only appear in the expansion of a macro.
// This gets unpoisoned where it is allowed.
(Ident__VA_ARGS__ = getIdentifierInfo("__VA_ARGS__"))->setIsPoisoned();
@@ -507,6 +510,27 @@
Diag(Identifier, diag::ext_token_used);
}
+void Preprocessor::HandleModuleImport(Token &Import) {
+ // The token sequence
+ //
+ // __import__ identifier
+ //
+ // indicates a module import directive. We load the module and then
+ // leave the token sequence for the parser.
+ Token ModuleNameTok = LookAhead(0);
+ if (ModuleNameTok.getKind() != tok::identifier)
+ return;
+
+ (void)TheModuleLoader.loadModule(Import.getLocation(),
+ *ModuleNameTok.getIdentifierInfo(),
+ ModuleNameTok.getLocation());
+
+ // FIXME: Transmogrify __import__ into some kind of AST-only __import__ that
+ // is not recognized by the preprocessor but is recognized by the parser.
+ // It would also be useful to stash the ModuleKey somewhere, so we don't try
+ // to load the module twice.
+}
+
void Preprocessor::AddCommentHandler(CommentHandler *Handler) {
assert(Handler && "NULL comment handler");
assert(std::find(CommentHandlers.begin(), CommentHandlers.end(), Handler) ==
@@ -535,6 +559,8 @@
return true;
}
+ModuleLoader::~ModuleLoader() { }
+
CommentHandler::~CommentHandler() { }
CodeCompletionHandler::~CodeCompletionHandler() { }
diff --git a/safecode/tools/clang/lib/Parse/ParseInit.cpp b/safecode/tools/clang/lib/Parse/ParseInit.cpp
index 2c9278a..ad7bcb2 100644
--- a/safecode/tools/clang/lib/Parse/ParseInit.cpp
+++ b/safecode/tools/clang/lib/Parse/ParseInit.cpp
@@ -90,7 +90,7 @@
assert(Tok.is(tok::colon) && "MayBeDesignationStart not working properly!");
SourceLocation ColonLoc = ConsumeToken();
- Diag(Tok, diag::ext_gnu_old_style_field_designator)
+ Diag(NameLoc, diag::ext_gnu_old_style_field_designator)
<< FixItHint::CreateReplacement(SourceRange(NameLoc, ColonLoc),
NewSyntax.str());
diff --git a/safecode/tools/clang/lib/Parse/ParseObjc.cpp b/safecode/tools/clang/lib/Parse/ParseObjc.cpp
index 684d8ed..17c962e 100644
--- a/safecode/tools/clang/lib/Parse/ParseObjc.cpp
+++ b/safecode/tools/clang/lib/Parse/ParseObjc.cpp
@@ -29,47 +29,59 @@
/// [OBJC] objc-protocol-definition
/// [OBJC] objc-method-definition
/// [OBJC] '@' 'end'
-Decl *Parser::ParseObjCAtDirectives() {
+Parser::DeclGroupPtrTy Parser::ParseObjCAtDirectives() {
SourceLocation AtLoc = ConsumeToken(); // the "@"
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCAtDirective(getCurScope());
ConsumeCodeCompletionToken();
}
-
+
+ Decl *SingleDecl = 0;
switch (Tok.getObjCKeywordID()) {
case tok::objc_class:
return ParseObjCAtClassDeclaration(AtLoc);
+ break;
case tok::objc_interface: {
ParsedAttributes attrs(AttrFactory);
- return ParseObjCAtInterfaceDeclaration(AtLoc, attrs);
+ SingleDecl = ParseObjCAtInterfaceDeclaration(AtLoc, attrs);
+ break;
}
case tok::objc_protocol: {
ParsedAttributes attrs(AttrFactory);
- return ParseObjCAtProtocolDeclaration(AtLoc, attrs);
+ SingleDecl = ParseObjCAtProtocolDeclaration(AtLoc, attrs);
+ break;
}
case tok::objc_implementation:
- return ParseObjCAtImplementationDeclaration(AtLoc);
+ SingleDecl = ParseObjCAtImplementationDeclaration(AtLoc);
+ break;
case tok::objc_end:
- return ParseObjCAtEndDeclaration(AtLoc);
+ SingleDecl = ParseObjCAtEndDeclaration(AtLoc);
+ break;
case tok::objc_compatibility_alias:
- return ParseObjCAtAliasDeclaration(AtLoc);
+ SingleDecl = ParseObjCAtAliasDeclaration(AtLoc);
+ break;
case tok::objc_synthesize:
- return ParseObjCPropertySynthesize(AtLoc);
+ SingleDecl = ParseObjCPropertySynthesize(AtLoc);
+ break;
case tok::objc_dynamic:
- return ParseObjCPropertyDynamic(AtLoc);
+ SingleDecl = ParseObjCPropertyDynamic(AtLoc);
+ break;
default:
Diag(AtLoc, diag::err_unexpected_at);
SkipUntil(tok::semi);
- return 0;
+ SingleDecl = 0;
+ break;
}
+ return Actions.ConvertDeclToDeclGroup(SingleDecl);
}
///
/// objc-class-declaration:
/// '@' 'class' identifier-list ';'
///
-Decl *Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
+Parser::DeclGroupPtrTy
+Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
ConsumeToken(); // the identifier "class"
SmallVector<IdentifierInfo *, 8> ClassNames;
SmallVector<SourceLocation, 8> ClassLocs;
@@ -79,7 +91,7 @@
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected_ident);
SkipUntil(tok::semi);
- return 0;
+ return Actions.ConvertDeclToDeclGroup(0);
}
ClassNames.push_back(Tok.getIdentifierInfo());
ClassLocs.push_back(Tok.getLocation());
@@ -93,7 +105,7 @@
// Consume the ';'.
if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@class"))
- return 0;
+ return Actions.ConvertDeclToDeclGroup(0);
return Actions.ActOnForwardClassDeclaration(atLoc, ClassNames.data(),
ClassLocs.data(),
diff --git a/safecode/tools/clang/lib/Parse/Parser.cpp b/safecode/tools/clang/lib/Parse/Parser.cpp
index 0da2b43..43e0f03 100644
--- a/safecode/tools/clang/lib/Parse/Parser.cpp
+++ b/safecode/tools/clang/lib/Parse/Parser.cpp
@@ -593,10 +593,7 @@
break;
}
case tok::at:
- // @ is not a legal token unless objc is enabled, no need to check for ObjC.
- /// FIXME: ParseObjCAtDirectives should return a DeclGroup for things like
- /// @class foo, bar;
- SingleDecl = ParseObjCAtDirectives();
+ return ParseObjCAtDirectives();
break;
case tok::minus:
case tok::plus:
@@ -679,6 +676,9 @@
ParseMicrosoftIfExistsExternalDeclaration();
return DeclGroupPtrTy();
+ case tok::kw___import__:
+ return ParseModuleImport();
+
default:
dont_know:
// We can't tell whether this is a function-definition or declaration yet.
@@ -1541,3 +1541,24 @@
}
ConsumeBrace();
}
+
+Parser::DeclGroupPtrTy Parser::ParseModuleImport() {
+ assert(Tok.is(tok::kw___import__) && "Improper start to module import");
+ SourceLocation ImportLoc = ConsumeToken();
+
+ // Parse the module name.
+ if (!Tok.is(tok::identifier)) {
+ Diag(Tok, diag::err_module_expected_ident);
+ SkipUntil(tok::semi);
+ return DeclGroupPtrTy();
+ }
+
+ IdentifierInfo &ModuleName = *Tok.getIdentifierInfo();
+ SourceLocation ModuleNameLoc = ConsumeToken();
+ DeclResult Import = Actions.ActOnModuleImport(ImportLoc, ModuleName, ModuleNameLoc);
+ ExpectAndConsumeSemi(diag::err_module_expected_semi);
+ if (Import.isInvalid())
+ return DeclGroupPtrTy();
+
+ return Actions.ConvertDeclToDeclGroup(Import.get());
+}
diff --git a/safecode/tools/clang/lib/Rewrite/RewriteObjC.cpp b/safecode/tools/clang/lib/Rewrite/RewriteObjC.cpp
index 3ba7e90..ba51806 100644
--- a/safecode/tools/clang/lib/Rewrite/RewriteObjC.cpp
+++ b/safecode/tools/clang/lib/Rewrite/RewriteObjC.cpp
@@ -161,8 +161,13 @@
// Top Level Driver code.
virtual void HandleTopLevelDecl(DeclGroupRef D) {
- for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
+ for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) {
+ if (isa<ObjCClassDecl>((*I))) {
+ RewriteForwardClassDecl(D);
+ break;
+ }
HandleTopLevelSingleDecl(*I);
+ }
}
void HandleTopLevelSingleDecl(Decl *D);
void HandleDeclInMainFile(Decl *D);
@@ -241,7 +246,7 @@
// Syntactic Rewriting.
void RewriteInclude();
- void RewriteForwardClassDecl(ObjCClassDecl *Dcl);
+ void RewriteForwardClassDecl(DeclGroupRef D);
void RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
ObjCImplementationDecl *IMD,
ObjCCategoryImplDecl *CID);
@@ -886,30 +891,28 @@
InsertText(onePastSemiLoc, Setr);
}
-void RewriteObjC::RewriteForwardClassDecl(ObjCClassDecl *ClassDecl) {
- // Get the start location and compute the semi location.
- SourceLocation startLoc = ClassDecl->getLocation();
- const char *startBuf = SM->getCharacterData(startLoc);
- const char *semiPtr = strchr(startBuf, ';');
-
- // Translate to typedef's that forward reference structs with the same name
- // as the class. As a convenience, we include the original declaration
- // as a comment.
+void RewriteObjC::RewriteForwardClassDecl(DeclGroupRef D) {
+ SourceLocation startLoc;
std::string typedefString;
- typedefString += "// @class ";
- for (ObjCClassDecl::iterator I = ClassDecl->begin(), E = ClassDecl->end();
- I != E; ++I) {
- ObjCInterfaceDecl *ForwardDecl = I->getInterface();
- typedefString += ForwardDecl->getNameAsString();
- if (I+1 != E)
- typedefString += ", ";
- else
+ const char *startBuf = 0;
+ const char *semiPtr = 0;
+ for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) {
+ ObjCClassDecl *ClassDecl = cast<ObjCClassDecl>(*I);
+ ObjCInterfaceDecl *ForwardDecl = ClassDecl->getForwardInterfaceDecl();
+ if (I == D.begin()) {
+ // Get the start location and compute the semi location.
+ startLoc = ClassDecl->getLocation();
+ startBuf = SM->getCharacterData(startLoc);
+ semiPtr = strchr(startBuf, ';');
+ typedefString += "// @class ";
+ typedefString += ForwardDecl->getNameAsString();
typedefString += ";\n";
- }
+ }
+ // Translate to typedef's that forward reference structs with the same name
+ // as the class. As a convenience, we include the original declaration
+ // as a comment.
- for (ObjCClassDecl::iterator I = ClassDecl->begin(), E = ClassDecl->end();
- I != E; ++I) {
- ObjCInterfaceDecl *ForwardDecl = I->getInterface();
+
typedefString += "#ifndef _REWRITER_typedef_";
typedefString += ForwardDecl->getNameAsString();
typedefString += "\n";
@@ -5887,8 +5890,8 @@
ClassImplementation.push_back(CI);
else if (ObjCCategoryImplDecl *CI = dyn_cast<ObjCCategoryImplDecl>(D))
CategoryImplementation.push_back(CI);
- else if (ObjCClassDecl *CD = dyn_cast<ObjCClassDecl>(D))
- RewriteForwardClassDecl(CD);
+ else if (isa<ObjCClassDecl>(D))
+ assert(false && "RewriteObjC::HandleDeclInMainFile - ObjCClassDecl");
else if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
RewriteObjCQualifiedInterfaceTypes(VD);
if (isTopLevelBlockPointerType(VD->getType()))
diff --git a/safecode/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp b/safecode/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp
index 51b04a7..6c07418 100644
--- a/safecode/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/safecode/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -508,8 +508,10 @@
else if (VariableTy->isEnumeralType())
return;
else if (VariableTy->isPointerType() || VariableTy->isMemberPointerType()) {
+ if (S.Context.getLangOptions().CPlusPlus0x)
+ initialization = " = nullptr";
// Check if 'NULL' is defined.
- if (S.PP.getMacroInfo(&S.getASTContext().Idents.get("NULL")))
+ else if (S.PP.getMacroInfo(&S.getASTContext().Idents.get("NULL")))
initialization = " = NULL";
else
initialization = " = 0";
diff --git a/safecode/tools/clang/lib/Sema/Sema.cpp b/safecode/tools/clang/lib/Sema/Sema.cpp
index d3ace9d..7bd0a4a 100644
--- a/safecode/tools/clang/lib/Sema/Sema.cpp
+++ b/safecode/tools/clang/lib/Sema/Sema.cpp
@@ -85,6 +85,7 @@
IdResolver(pp.getLangOptions()), CXXTypeInfoDecl(0), MSVCGuidDecl(0),
GlobalNewDeleteDeclared(false),
ObjCShouldCallSuperDealloc(false),
+ ObjCShouldCallSuperFinalize(false),
TUKind(TUKind),
NumSFINAEErrors(0), SuppressAccessChecking(false),
AccessCheckingSFINAE(false), InNonInstantiationSFINAEContext(false),
diff --git a/safecode/tools/clang/lib/Sema/SemaChecking.cpp b/safecode/tools/clang/lib/Sema/SemaChecking.cpp
index 530f812..30c247f 100644
--- a/safecode/tools/clang/lib/Sema/SemaChecking.cpp
+++ b/safecode/tools/clang/lib/Sema/SemaChecking.cpp
@@ -12,6 +12,7 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/Sema/Initialization.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/ScopeInfo.h"
@@ -396,6 +397,30 @@
return false;
}
+/// checkBuiltinArgument - Given a call to a builtin function, perform
+/// normal type-checking on the given argument, updating the call in
+/// place. This is useful when a builtin function requires custom
+/// type-checking for some of its arguments but not necessarily all of
+/// them.
+///
+/// Returns true on error.
+static bool checkBuiltinArgument(Sema &S, CallExpr *E, unsigned ArgIndex) {
+ FunctionDecl *Fn = E->getDirectCallee();
+ assert(Fn && "builtin call without direct callee!");
+
+ ParmVarDecl *Param = Fn->getParamDecl(ArgIndex);
+ InitializedEntity Entity =
+ InitializedEntity::InitializeParameter(S.Context, Param);
+
+ ExprResult Arg = E->getArg(0);
+ Arg = S.PerformCopyInitialization(Entity, SourceLocation(), Arg);
+ if (Arg.isInvalid())
+ return true;
+
+ E->setArg(ArgIndex, Arg.take());
+ return false;
+}
+
/// SemaBuiltinAtomicOverloaded - We have a call to a function like
/// __sync_fetch_and_add, which is an overloaded function based on the pointer
/// type of its first argument. The main ActOnCallExpr routines have already
@@ -661,6 +686,10 @@
<< 0 /*function call*/ << 2 << TheCall->getNumArgs();
}
+ // Type-check the first argument normally.
+ if (checkBuiltinArgument(*this, TheCall, 0))
+ return true;
+
// Determine whether the current function is variadic or not.
BlockScopeInfo *CurBlock = getCurBlock();
bool isVariadic;
diff --git a/safecode/tools/clang/lib/Sema/SemaCodeComplete.cpp b/safecode/tools/clang/lib/Sema/SemaCodeComplete.cpp
index ef54fbc..5e19148 100644
--- a/safecode/tools/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/safecode/tools/clang/lib/Sema/SemaCodeComplete.cpp
@@ -5405,12 +5405,11 @@
// Record any forward-declared interfaces we find.
if (ObjCClassDecl *Forward = dyn_cast<ObjCClassDecl>(*D)) {
- for (ObjCClassDecl::iterator C = Forward->begin(), CEnd = Forward->end();
- C != CEnd; ++C)
- if ((!OnlyForwardDeclarations || C->getInterface()->isForwardDecl()) &&
- (!OnlyUnimplemented || !C->getInterface()->getImplementation()))
- Results.AddResult(Result(C->getInterface(), 0), CurContext,
- 0, false);
+ ObjCInterfaceDecl *IDecl = Forward->getForwardInterfaceDecl();
+ if ((!OnlyForwardDeclarations || IDecl->isForwardDecl()) &&
+ (!OnlyUnimplemented || !IDecl->getImplementation()))
+ Results.AddResult(Result(IDecl, 0), CurContext,
+ 0, false);
}
}
}
diff --git a/safecode/tools/clang/lib/Sema/SemaDecl.cpp b/safecode/tools/clang/lib/Sema/SemaDecl.cpp
index 9f43aa2..2f2ba7f 100644
--- a/safecode/tools/clang/lib/Sema/SemaDecl.cpp
+++ b/safecode/tools/clang/lib/Sema/SemaDecl.cpp
@@ -38,6 +38,7 @@
// FIXME: layering (ideally, Sema shouldn't be dependent on Lex API's)
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/ModuleLoader.h"
#include "llvm/ADT/Triple.h"
#include <algorithm>
#include <cstring>
@@ -6673,12 +6674,18 @@
Diag(MD->getLocEnd(), diag::warn_objc_missing_super_dealloc);
ObjCShouldCallSuperDealloc = false;
}
+ if (ObjCShouldCallSuperFinalize) {
+ Diag(MD->getLocEnd(), diag::warn_objc_missing_super_finalize);
+ ObjCShouldCallSuperFinalize = false;
+ }
} else {
return 0;
}
assert(!ObjCShouldCallSuperDealloc && "This should only be set for "
"ObjC methods, which should have been handled in the block above.");
+ assert(!ObjCShouldCallSuperFinalize && "This should only be set for "
+ "ObjC methods, which should have been handled in the block above.");
// Verify and clean out per-function state.
if (Body) {
@@ -9294,6 +9301,19 @@
return New;
}
+DeclResult Sema::ActOnModuleImport(SourceLocation ImportLoc,
+ IdentifierInfo &ModuleName,
+ SourceLocation ModuleNameLoc) {
+ ModuleKey Module = PP.getModuleLoader().loadModule(ImportLoc,
+ ModuleName, ModuleNameLoc);
+ if (!Module)
+ return true;
+
+ // FIXME: Actually create a declaration to describe the module import.
+ (void)Module;
+ return DeclResult((Decl *)0);
+}
+
void Sema::ActOnPragmaWeakID(IdentifierInfo* Name,
SourceLocation PragmaLoc,
SourceLocation NameLoc) {
diff --git a/safecode/tools/clang/lib/Sema/SemaDeclObjC.cpp b/safecode/tools/clang/lib/Sema/SemaDeclObjC.cpp
index af14aa4..9b6166b 100644
--- a/safecode/tools/clang/lib/Sema/SemaDeclObjC.cpp
+++ b/safecode/tools/clang/lib/Sema/SemaDeclObjC.cpp
@@ -162,6 +162,7 @@
switch (family) {
case OMF_None:
case OMF_dealloc:
+ case OMF_finalize:
case OMF_retain:
case OMF_release:
case OMF_autorelease:
@@ -267,6 +268,7 @@
case OMF_None:
case OMF_dealloc:
+ case OMF_finalize:
case OMF_alloc:
case OMF_init:
case OMF_mutableCopy:
@@ -287,14 +289,16 @@
dyn_cast<NamedDecl>(IMD),
MDecl->getLocation(), 0);
- // If this is "dealloc", set some bit here.
+ // If this is "dealloc" or "finalize", set some bit here.
// Then in ActOnSuperMessage() (SemaExprObjC), set it back to false.
// Finally, in ActOnFinishFunctionBody() (SemaDecl), warn if flag is set.
// Only do this if the current class actually has a superclass.
- if (IC->getSuperClass())
+ if (IC->getSuperClass()) {
ObjCShouldCallSuperDealloc =
!Context.getLangOptions().ObjCAutoRefCount &&
MDecl->getMethodFamily() == OMF_dealloc;
+ ObjCShouldCallSuperFinalize = MDecl->getMethodFamily() == OMF_finalize;
+ }
}
}
@@ -1256,6 +1260,7 @@
case OMF_release:
case OMF_autorelease:
case OMF_dealloc:
+ case OMF_finalize:
case OMF_retainCount:
case OMF_self:
case OMF_performSelector:
@@ -1657,13 +1662,12 @@
}
/// ActOnForwardClassDeclaration -
-Decl *
+Sema::DeclGroupPtrTy
Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
IdentifierInfo **IdentList,
SourceLocation *IdentLocs,
unsigned NumElts) {
- SmallVector<ObjCInterfaceDecl*, 32> Interfaces;
-
+ SmallVector<Decl *, 8> DeclsInGroup;
for (unsigned i = 0; i != NumElts; ++i) {
// Check for another declaration kind with the same name.
NamedDecl *PrevDecl
@@ -1708,17 +1712,14 @@
PushOnScopeChains(IDecl, TUScope, false);
CurContext->makeDeclVisibleInContext(IDecl, true);
}
-
- Interfaces.push_back(IDecl);
+ ObjCClassDecl *CDecl = ObjCClassDecl::Create(Context, CurContext, AtClassLoc,
+ IDecl, IdentLocs[i]);
+ CurContext->addDecl(CDecl);
+ CheckObjCDeclScope(CDecl);
+ DeclsInGroup.push_back(CDecl);
}
-
- assert(Interfaces.size() == NumElts);
- ObjCClassDecl *CDecl = ObjCClassDecl::Create(Context, CurContext, AtClassLoc,
- Interfaces.data(), IdentLocs,
- Interfaces.size());
- CurContext->addDecl(CDecl);
- CheckObjCDeclScope(CDecl);
- return CDecl;
+
+ return BuildDeclaratorGroup(DeclsInGroup.data(), DeclsInGroup.size(), false);
}
static bool tryMatchRecordTypes(ASTContext &Context,
@@ -2641,6 +2642,7 @@
case OMF_None:
case OMF_copy:
case OMF_dealloc:
+ case OMF_finalize:
case OMF_mutableCopy:
case OMF_release:
case OMF_retainCount:
diff --git a/safecode/tools/clang/lib/Sema/SemaExpr.cpp b/safecode/tools/clang/lib/Sema/SemaExpr.cpp
index 19cd118..6327ee7 100644
--- a/safecode/tools/clang/lib/Sema/SemaExpr.cpp
+++ b/safecode/tools/clang/lib/Sema/SemaExpr.cpp
@@ -443,6 +443,24 @@
if (Ty->isSpecificBuiltinType(BuiltinType::Float))
E = ImpCastExprToType(E, Context.DoubleTy, CK_FloatingCast).take();
+ // C++ performs lvalue-to-rvalue conversion as a default argument
+ // promotion. If we still have a gl-value after usual unary
+ // conversion, we must have an l-value of class type, so we need to
+ // initialize a temporary. For compatibility reasons, however, we
+ // don't want to do this in unevaluated contexts; otherwise we
+ // reject metaprograms which work by passing uncopyable l-values to
+ // variadic functions.
+ if (getLangOptions().CPlusPlus && E->isGLValue() &&
+ ExprEvalContexts.back().Context != Unevaluated) {
+ ExprResult Temp = PerformCopyInitialization(
+ InitializedEntity::InitializeTemporary(E->getType()),
+ E->getExprLoc(),
+ Owned(E));
+ if (Temp.isInvalid())
+ return ExprError();
+ E = Temp.get();
+ }
+
return Owned(E);
}
@@ -460,19 +478,13 @@
return ExprError();
E = ExprRes.take();
- // __builtin_va_start takes the second argument as a "varargs" argument, but
- // it doesn't actually do anything with it. It doesn't need to be non-pod
- // etc.
- if (FDecl && FDecl->getBuiltinID() == Builtin::BI__builtin_va_start)
- return Owned(E);
-
// Don't allow one to pass an Objective-C interface to a vararg.
if (E->getType()->isObjCObjectType() &&
DiagRuntimeBehavior(E->getLocStart(), 0,
PDiag(diag::err_cannot_pass_objc_interface_to_vararg)
<< E->getType() << CT))
return ExprError();
-
+
if (!E->getType().isPODType(Context)) {
// C++0x [expr.call]p7:
// Passing a potentially-evaluated argument of class type (Clause 9)
@@ -517,8 +529,7 @@
ExprResult Comma = ActOnBinOp(TUScope, E->getLocStart(), tok::comma,
Call.get(), E);
if (Comma.isInvalid())
- return ExprError();
-
+ return ExprError();
E = Comma.get();
}
}
@@ -7408,7 +7419,7 @@
S.Context.getTypeDeclType(cast<RecordDecl>(Ctx)).getTypePtr());
}
}
- } else if (!isa<FunctionDecl>(dcl))
+ } else if (!isa<FunctionDecl>(dcl) && !isa<NonTypeTemplateParmDecl>(dcl))
assert(0 && "Unknown/unexpected decl type");
}
diff --git a/safecode/tools/clang/lib/Sema/SemaExprObjC.cpp b/safecode/tools/clang/lib/Sema/SemaExprObjC.cpp
index db5de4c..402e54c 100644
--- a/safecode/tools/clang/lib/Sema/SemaExprObjC.cpp
+++ b/safecode/tools/clang/lib/Sema/SemaExprObjC.cpp
@@ -203,6 +203,7 @@
case OMF_None:
case OMF_alloc:
case OMF_copy:
+ case OMF_finalize:
case OMF_init:
case OMF_mutableCopy:
case OMF_new:
@@ -977,6 +978,8 @@
if (Method->isInstanceMethod()) {
if (Sel.getMethodFamily() == OMF_dealloc)
ObjCShouldCallSuperDealloc = false;
+ if (Sel.getMethodFamily() == OMF_finalize)
+ ObjCShouldCallSuperFinalize = false;
// Since we are in an instance method, this is an instance
// message to the superclass instance.
@@ -1418,6 +1421,7 @@
case OMF_None:
case OMF_alloc:
case OMF_copy:
+ case OMF_finalize:
case OMF_mutableCopy:
case OMF_new:
case OMF_self:
diff --git a/safecode/tools/clang/lib/Sema/SemaLookup.cpp b/safecode/tools/clang/lib/Sema/SemaLookup.cpp
index 240eb5f..7df0498 100644
--- a/safecode/tools/clang/lib/Sema/SemaLookup.cpp
+++ b/safecode/tools/clang/lib/Sema/SemaLookup.cpp
@@ -2670,14 +2670,11 @@
}
}
} else if (ObjCClassDecl *Class = dyn_cast<ObjCClassDecl>(*D)) {
- for (ObjCClassDecl::iterator I = Class->begin(), IEnd = Class->end();
- I != IEnd; ++I) {
- ObjCInterfaceDecl *IFace = I->getInterface();
+ ObjCInterfaceDecl *IFace = Class->getForwardInterfaceDecl();
if (Result.isAcceptableDecl(IFace)) {
Consumer.FoundDecl(IFace, Visited.checkHidden(IFace), InBaseClass);
Visited.add(IFace);
}
- }
}
// Visit transparent contexts and inline namespaces inside this context.
diff --git a/safecode/tools/clang/lib/Sema/SemaObjCProperty.cpp b/safecode/tools/clang/lib/Sema/SemaObjCProperty.cpp
index 46f6456..f4743ac 100644
--- a/safecode/tools/clang/lib/Sema/SemaObjCProperty.cpp
+++ b/safecode/tools/clang/lib/Sema/SemaObjCProperty.cpp
@@ -487,7 +487,9 @@
case Qualifiers::OCL_Strong:
S.Diag(propertyImplLoc, diag::err_arc_assign_property_ownership)
<< property->getDeclName()
- << ivar->getDeclName();
+ << ivar->getDeclName()
+ << ((property->getPropertyAttributesAsWritten()
+ & ObjCPropertyDecl::OBJC_PR_assign) != 0);
break;
}
@@ -1314,23 +1316,23 @@
PropImplMap.count(Prop) || Prop->hasAttr<UnavailableAttr>())
continue;
if (!InsMap.count(Prop->getGetterName())) {
- Diag(Prop->getLocation(),
+ Diag(IMPDecl->getLocation(),
isa<ObjCCategoryDecl>(CDecl) ?
diag::warn_setter_getter_impl_required_in_category :
diag::warn_setter_getter_impl_required)
<< Prop->getDeclName() << Prop->getGetterName();
- Diag(IMPDecl->getLocation(),
- diag::note_property_impl_required);
+ Diag(Prop->getLocation(),
+ diag::note_property_declare);
}
if (!Prop->isReadOnly() && !InsMap.count(Prop->getSetterName())) {
- Diag(Prop->getLocation(),
+ Diag(IMPDecl->getLocation(),
isa<ObjCCategoryDecl>(CDecl) ?
diag::warn_setter_getter_impl_required_in_category :
diag::warn_setter_getter_impl_required)
<< Prop->getDeclName() << Prop->getSetterName();
- Diag(IMPDecl->getLocation(),
- diag::note_property_impl_required);
+ Diag(Prop->getLocation(),
+ diag::note_property_declare);
}
}
}
diff --git a/safecode/tools/clang/lib/Sema/SemaOverload.cpp b/safecode/tools/clang/lib/Sema/SemaOverload.cpp
index 84d16ab..e3c5f83 100644
--- a/safecode/tools/clang/lib/Sema/SemaOverload.cpp
+++ b/safecode/tools/clang/lib/Sema/SemaOverload.cpp
@@ -8525,8 +8525,7 @@
<< UnaryOperator::getOpcodeStr(Opc)
<< Input->getType()
<< Input->getSourceRange();
- CandidateSet.NoteCandidates(*this, OCD_ViableCandidates,
- Args, NumArgs,
+ CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args, NumArgs,
UnaryOperator::getOpcodeStr(Opc), OpLoc);
return ExprError();
@@ -8536,7 +8535,8 @@
<< UnaryOperator::getOpcodeStr(Opc)
<< getDeletedOrUnavailableSuffix(Best->Function)
<< Input->getSourceRange();
- CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
+ CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs,
+ UnaryOperator::getOpcodeStr(Opc), OpLoc);
return ExprError();
}
@@ -8831,7 +8831,8 @@
<< BinaryOperator::getOpcodeStr(Opc)
<< getDeletedOrUnavailableSuffix(Best->Function)
<< Args[0]->getSourceRange() << Args[1]->getSourceRange();
- CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, 2);
+ CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, 2,
+ BinaryOperator::getOpcodeStr(Opc), OpLoc);
return ExprError();
}
diff --git a/safecode/tools/clang/lib/Serialization/ASTReader.cpp b/safecode/tools/clang/lib/Serialization/ASTReader.cpp
index 540b9ef..2817d86 100644
--- a/safecode/tools/clang/lib/Serialization/ASTReader.cpp
+++ b/safecode/tools/clang/lib/Serialization/ASTReader.cpp
@@ -528,7 +528,6 @@
unsigned NumFactoryMethods = ReadUnalignedLE16(d);
// Load instance methods
- ObjCMethodList *Prev = 0;
for (unsigned I = 0; I != NumInstanceMethods; ++I) {
if (ObjCMethodDecl *Method
= Reader.GetLocalDeclAs<ObjCMethodDecl>(F, ReadUnalignedLE32(d)))
@@ -536,7 +535,6 @@
}
// Load factory methods
- Prev = 0;
for (unsigned I = 0; I != NumFactoryMethods; ++I) {
if (ObjCMethodDecl *Method
= Reader.GetLocalDeclAs<ObjCMethodDecl>(F, ReadUnalignedLE32(d)))
@@ -1753,7 +1751,6 @@
// Read all of the records and blocks for the ASt file.
RecordData Record;
- bool First = true;
while (!Stream.AtEndOfStream()) {
unsigned Code = Stream.ReadCode();
if (Code == llvm::bitc::END_BLOCK) {
@@ -1827,7 +1824,6 @@
}
break;
}
- First = false;
continue;
}
@@ -2468,7 +2464,6 @@
KnownNamespaces.push_back(getGlobalDeclID(F, Record[I]));
break;
}
- First = false;
}
Error("premature end of bitstream in AST file");
return Failure;
@@ -2553,7 +2548,7 @@
= static_cast<IdentifierLookupVisitor *>(UserData);
ASTIdentifierLookupTable *IdTable
- = (ASTIdentifierLookupTable *)M.IdentifierLookupTable;
+ = (ASTIdentifierLookupTable *)M.IdentifierLookupTable;
if (!IdTable)
return false;
@@ -2786,7 +2781,7 @@
void ASTReader::InitializeContext(ASTContext &Ctx) {
Context = &Ctx;
assert(Context && "Passed null context!");
-
+
assert(PP && "Forgot to set Preprocessor ?");
PP->getIdentifierTable().setExternalIdentifierLookup(this);
PP->setExternalSource(this);
@@ -4163,6 +4158,7 @@
ASTReader &Reader;
const DeclContext *DC;
bool (*isKindWeWant)(Decl::Kind);
+
SmallVectorImpl<Decl*> &Decls;
bool PredefsVisited[NUM_PREDEF_DECL_IDS];
@@ -4204,9 +4200,10 @@
This->PredefsVisited[ID->second] = true;
}
- Decl *D = This->Reader.GetLocalDecl(M, ID->second);
- assert(D && "Null decl in lexical decls");
- This->Decls.push_back(D);
+ if (Decl *D = This->Reader.GetLocalDecl(M, ID->second)) {
+ if (!This->DC->isDeclInLexicalTraversal(D))
+ This->Decls.push_back(D);
+ }
}
return false;
diff --git a/safecode/tools/clang/lib/Serialization/ASTReaderDecl.cpp b/safecode/tools/clang/lib/Serialization/ASTReaderDecl.cpp
index 6e7cbbf..4fa9b2c 100644
--- a/safecode/tools/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/safecode/tools/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -123,8 +123,8 @@
ClassTemplateSpecializationDecl *D);
void VisitClassTemplatePartialSpecializationDecl(
ClassTemplatePartialSpecializationDecl *D);
- void VisitClassScopeFunctionSpecializationDecl(
- ClassScopeFunctionSpecializationDecl *D);
+ void VisitClassScopeFunctionSpecializationDecl(
+ ClassScopeFunctionSpecializationDecl *D);
void VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
void VisitValueDecl(ValueDecl *VD);
void VisitEnumConstantDecl(EnumConstantDecl *ECD);
@@ -573,17 +573,9 @@
void ASTDeclReader::VisitObjCClassDecl(ObjCClassDecl *CD) {
VisitDecl(CD);
- unsigned NumClassRefs = Record[Idx++];
- SmallVector<ObjCInterfaceDecl *, 16> ClassRefs;
- ClassRefs.reserve(NumClassRefs);
- for (unsigned I = 0; I != NumClassRefs; ++I)
- ClassRefs.push_back(ReadDeclAs<ObjCInterfaceDecl>(Record, Idx));
- SmallVector<SourceLocation, 16> SLocs;
- SLocs.reserve(NumClassRefs);
- for (unsigned I = 0; I != NumClassRefs; ++I)
- SLocs.push_back(ReadSourceLocation(Record, Idx));
- CD->setClassList(*Reader.getContext(), ClassRefs.data(), SLocs.data(),
- NumClassRefs);
+ ObjCInterfaceDecl *ClassRef = ReadDeclAs<ObjCInterfaceDecl>(Record, Idx);
+ SourceLocation SLoc = ReadSourceLocation(Record, Idx);
+ CD->setClass(*Reader.getContext(), ClassRef, SLoc);
}
void ASTDeclReader::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *FPD) {
@@ -1211,8 +1203,8 @@
}
}
-void ASTDeclReader::VisitClassScopeFunctionSpecializationDecl(
- ClassScopeFunctionSpecializationDecl *D) {
+void ASTDeclReader::VisitClassScopeFunctionSpecializationDecl(
+ ClassScopeFunctionSpecializationDecl *D) {
VisitDecl(D);
D->Specialization = ReadDeclAs<CXXMethodDecl>(Record, Idx);
}
diff --git a/safecode/tools/clang/lib/Serialization/ASTWriterDecl.cpp b/safecode/tools/clang/lib/Serialization/ASTWriterDecl.cpp
index a0f7da2..b5d4d8f 100644
--- a/safecode/tools/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/safecode/tools/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -65,8 +65,8 @@
ClassTemplateSpecializationDecl *D);
void VisitClassTemplatePartialSpecializationDecl(
ClassTemplatePartialSpecializationDecl *D);
- void VisitClassScopeFunctionSpecializationDecl(
- ClassScopeFunctionSpecializationDecl *D);
+ void VisitClassScopeFunctionSpecializationDecl(
+ ClassScopeFunctionSpecializationDecl *D);
void VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
void VisitValueDecl(ValueDecl *D);
void VisitEnumConstantDecl(EnumConstantDecl *D);
@@ -503,11 +503,8 @@
void ASTDeclWriter::VisitObjCClassDecl(ObjCClassDecl *D) {
VisitDecl(D);
- Record.push_back(D->size());
- for (ObjCClassDecl::iterator I = D->begin(), IEnd = D->end(); I != IEnd; ++I)
- Writer.AddDeclRef(I->getInterface(), Record);
- for (ObjCClassDecl::iterator I = D->begin(), IEnd = D->end(); I != IEnd; ++I)
- Writer.AddSourceLocation(I->getLocation(), Record);
+ Writer.AddDeclRef(D->getForwardInterfaceDecl(), Record);
+ Writer.AddSourceLocation(D->getForwardDecl()->getLocation(), Record);
Code = serialization::DECL_OBJC_CLASS;
}
@@ -1107,8 +1104,8 @@
Code = serialization::DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION;
}
-void ASTDeclWriter::VisitClassScopeFunctionSpecializationDecl(
- ClassScopeFunctionSpecializationDecl *D) {
+void ASTDeclWriter::VisitClassScopeFunctionSpecializationDecl(
+ ClassScopeFunctionSpecializationDecl *D) {
VisitDecl(D);
Writer.AddDeclRef(D->getSpecialization(), Record);
Code = serialization::DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION;
diff --git a/safecode/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/safecode/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
index d043e2d..718d9f3 100644
--- a/safecode/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
+++ b/safecode/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -47,8 +47,8 @@
const ProgramState *
checkRegionChanges(const ProgramState *state,
const StoreManager::InvalidatedSymbols *,
- const MemRegion * const *Begin,
- const MemRegion * const *End) const;
+ ArrayRef<const MemRegion *> ExplicitRegions,
+ ArrayRef<const MemRegion *> Regions) const;
typedef void (CStringChecker::*FnCheck)(CheckerContext &,
const CallExpr *) const;
@@ -786,7 +786,7 @@
// Invalidate this region.
unsigned Count = C.getNodeBuilder().getCurrentBlockCount();
- return state->invalidateRegion(R, E, Count, NULL);
+ return state->invalidateRegions(R, E, Count);
}
// If we have a non-region value by chance, just remove the binding.
@@ -1757,8 +1757,8 @@
const ProgramState *
CStringChecker::checkRegionChanges(const ProgramState *state,
const StoreManager::InvalidatedSymbols *,
- const MemRegion * const *Begin,
- const MemRegion * const *End) const {
+ ArrayRef<const MemRegion *> ExplicitRegions,
+ ArrayRef<const MemRegion *> Regions) const {
CStringLength::EntryMap Entries = state->get<CStringLength>();
if (Entries.isEmpty())
return state;
@@ -1767,8 +1767,9 @@
llvm::SmallPtrSet<const MemRegion *, 32> SuperRegions;
// First build sets for the changed regions and their super-regions.
- for ( ; Begin != End; ++Begin) {
- const MemRegion *MR = *Begin;
+ for (ArrayRef<const MemRegion *>::iterator
+ I = Regions.begin(), E = Regions.end(); I != E; ++I) {
+ const MemRegion *MR = *I;
Invalidated.insert(MR);
SuperRegions.insert(MR);
diff --git a/safecode/tools/clang/lib/StaticAnalyzer/Core/CFRefCount.cpp b/safecode/tools/clang/lib/StaticAnalyzer/Core/CFRefCount.cpp
index 4154205..a38c450 100644
--- a/safecode/tools/clang/lib/StaticAnalyzer/Core/CFRefCount.cpp
+++ b/safecode/tools/clang/lib/StaticAnalyzer/Core/CFRefCount.cpp
@@ -41,50 +41,6 @@
using llvm::StrInStrNoCase;
namespace {
-class InstanceReceiver {
- ObjCMessage Msg;
- const LocationContext *LC;
-public:
- InstanceReceiver() : LC(0) { }
- InstanceReceiver(const ObjCMessage &msg,
- const LocationContext *lc = 0) : Msg(msg), LC(lc) {}
-
- bool isValid() const {
- return Msg.isValid() && Msg.isInstanceMessage();
- }
- operator bool() const {
- return isValid();
- }
-
- SVal getSValAsScalarOrLoc(const ProgramState *state) {
- assert(isValid());
- // We have an expression for the receiver? Fetch the value
- // of that expression.
- if (const Expr *Ex = Msg.getInstanceReceiver())
- return state->getSValAsScalarOrLoc(Ex);
-
- // Otherwise we are sending a message to super. In this case the
- // object reference is the same as 'self'.
- if (const ImplicitParamDecl *SelfDecl = LC->getSelfDecl())
- return state->getSVal(state->getRegion(SelfDecl, LC));
-
- return UnknownVal();
- }
-
- SourceRange getSourceRange() const {
- assert(isValid());
- if (const Expr *Ex = Msg.getInstanceReceiver())
- return Ex->getSourceRange();
-
- // Otherwise we are sending a message to super.
- SourceLocation L = Msg.getSuperLoc();
- assert(L.isValid());
- return SourceRange(L, L);
- }
-};
-}
-
-namespace {
class GenericNodeBuilderRefCount {
StmtNodeBuilder *SNB;
const Stmt *S;
@@ -299,7 +255,7 @@
void RefVal::print(raw_ostream &Out) const {
if (!T.isNull())
- Out << "Tracked Type:" << T.getAsString() << '\n';
+ Out << "Tracked " << T.getAsString() << '/';
switch (getKind()) {
default: assert(false);
@@ -1629,14 +1585,6 @@
class CFRefCount : public TransferFuncs {
public:
- class BindingsPrinter : public ProgramState::Printer {
- public:
- virtual void Print(raw_ostream &Out,
- const ProgramState *state,
- const char* nl,
- const char* sep);
- };
-
const LangOptions& LOpts;
const bool GCEnabled;
@@ -1645,82 +1593,12 @@
: LOpts(lopts), GCEnabled(gcenabled) {}
void RegisterChecks(ExprEngine &Eng);
-
- virtual void RegisterPrinters(std::vector<ProgramState::Printer*>& Printers) {
- Printers.push_back(new BindingsPrinter());
- }
const LangOptions& getLangOptions() const { return LOpts; }
-
- // Calls.
-
- void evalCallOrMessage(ExplodedNodeSet &Dst, ExprEngine &Eng,
- StmtNodeBuilder &Builder,
- const CallOrObjCMessage &callOrMsg,
- InstanceReceiver Receiver, const MemRegion *Callee,
- ExplodedNode *Pred, const ProgramState *state);
-
- virtual void evalCall(ExplodedNodeSet &Dst,
- ExprEngine& Eng,
- StmtNodeBuilder& Builder,
- const CallExpr *CE, SVal L,
- ExplodedNode *Pred);
-
-
- virtual void evalObjCMessage(ExplodedNodeSet &Dst,
- ExprEngine& Engine,
- StmtNodeBuilder& Builder,
- ObjCMessage msg,
- ExplodedNode *Pred,
- const ProgramState *state);
};
} // end anonymous namespace
-static void PrintPool(raw_ostream &Out,
- SymbolRef Sym,
- const ProgramState *state) {
- Out << ' ';
- if (Sym)
- Out << Sym->getSymbolID();
- else
- Out << "<pool>";
- Out << ":{";
-
- // Get the contents of the pool.
- if (const ARCounts *cnts = state->get<AutoreleasePoolContents>(Sym))
- for (ARCounts::iterator J=cnts->begin(), EJ=cnts->end(); J != EJ; ++J)
- Out << '(' << J.getKey() << ',' << J.getData() << ')';
-
- Out << '}';
-}
-
-void CFRefCount::BindingsPrinter::Print(raw_ostream &Out,
- const ProgramState *state,
- const char* nl, const char* sep) {
-
- RefBindings B = state->get<RefBindings>();
-
- if (!B.isEmpty())
- Out << sep << nl;
-
- for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
- Out << (*I).first << " : ";
- (*I).second.print(Out);
- Out << nl;
- }
-
- // Print the autorelease stack.
- Out << sep << nl << "AR pool stack:";
- ARStack stack = state->get<AutoreleaseStack>();
-
- PrintPool(Out, SymbolRef(), state); // Print the caller's pool.
- for (ARStack::iterator I=stack.begin(), E=stack.end(); I!=E; ++I)
- PrintPool(Out, *I, state);
-
- Out << nl;
-}
-
//===----------------------------------------------------------------------===//
// Error reporting.
//===----------------------------------------------------------------------===//
@@ -2439,163 +2317,6 @@
return RetTy;
}
-
-// HACK: Symbols that have ref-count state that are referenced directly
-// (not as structure or array elements, or via bindings) by an argument
-// should not have their ref-count state stripped after we have
-// done an invalidation pass.
-//
-// FIXME: This is a global to currently share between CFRefCount and
-// RetainReleaseChecker. Eventually all functionality in CFRefCount should
-// be migrated to RetainReleaseChecker, and we can make this a non-global.
-llvm::DenseSet<SymbolRef> WhitelistedSymbols;
-namespace {
-struct ResetWhiteList {
- ResetWhiteList() {}
- ~ResetWhiteList() { WhitelistedSymbols.clear(); }
-};
-}
-
-void CFRefCount::evalCallOrMessage(ExplodedNodeSet &Dst, ExprEngine &Eng,
- StmtNodeBuilder &Builder,
- const CallOrObjCMessage &callOrMsg,
- InstanceReceiver Receiver,
- const MemRegion *Callee,
- ExplodedNode *Pred,
- const ProgramState *state) {
-
- SmallVector<const MemRegion*, 10> RegionsToInvalidate;
-
- // Use RAII to make sure the whitelist is properly cleared.
- ResetWhiteList resetWhiteList;
-
- // Invalidate all instance variables of the receiver of a message.
- // FIXME: We should be able to do better with inter-procedural analysis.
- if (Receiver) {
- SVal V = Receiver.getSValAsScalarOrLoc(state);
- if (SymbolRef Sym = V.getAsLocSymbol()) {
- if (state->get<RefBindings>(Sym))
- WhitelistedSymbols.insert(Sym);
- }
- if (const MemRegion *region = V.getAsRegion())
- RegionsToInvalidate.push_back(region);
- }
-
- // Invalidate all instance variables for the callee of a C++ method call.
- // FIXME: We should be able to do better with inter-procedural analysis.
- // FIXME: we can probably do better for const versus non-const methods.
- if (callOrMsg.isCXXCall()) {
- if (const MemRegion *callee = callOrMsg.getCXXCallee().getAsRegion())
- RegionsToInvalidate.push_back(callee);
- }
-
- for (unsigned idx = 0, e = callOrMsg.getNumArgs(); idx != e; ++idx) {
- SVal V = callOrMsg.getArgSValAsScalarOrLoc(idx);
-
- // If we are passing a location wrapped as an integer, unwrap it and
- // invalidate the values referred by the location.
- if (nonloc::LocAsInteger *Wrapped = dyn_cast<nonloc::LocAsInteger>(&V))
- V = Wrapped->getLoc();
- else if (!isa<Loc>(V))
- continue;
-
- if (SymbolRef Sym = V.getAsLocSymbol())
- if (state->get<RefBindings>(Sym))
- WhitelistedSymbols.insert(Sym);
-
- if (const MemRegion *R = V.getAsRegion()) {
- // Invalidate the value of the variable passed by reference.
-
- // Are we dealing with an ElementRegion? If the element type is
- // a basic integer type (e.g., char, int) and the underying region
- // is a variable region then strip off the ElementRegion.
- // FIXME: We really need to think about this for the general case
- // as sometimes we are reasoning about arrays and other times
- // about (char*), etc., is just a form of passing raw bytes.
- // e.g., void *p = alloca(); foo((char*)p);
- if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
- // Checking for 'integral type' is probably too promiscuous, but
- // we'll leave it in for now until we have a systematic way of
- // handling all of these cases. Eventually we need to come up
- // with an interface to StoreManager so that this logic can be
- // approriately delegated to the respective StoreManagers while
- // still allowing us to do checker-specific logic (e.g.,
- // invalidating reference counts), probably via callbacks.
- if (ER->getElementType()->isIntegralOrEnumerationType()) {
- const MemRegion *superReg = ER->getSuperRegion();
- if (isa<VarRegion>(superReg) || isa<FieldRegion>(superReg) ||
- isa<ObjCIvarRegion>(superReg))
- R = cast<TypedRegion>(superReg);
- }
- // FIXME: What about layers of ElementRegions?
- }
-
- // Mark this region for invalidation. We batch invalidate regions
- // below for efficiency.
- RegionsToInvalidate.push_back(R);
- } else {
- // Nuke all other arguments passed by reference.
- // FIXME: is this necessary or correct? This handles the non-Region
- // cases. Is it ever valid to store to these?
- state = state->unbindLoc(cast<Loc>(V));
- }
- }
-
- // Block calls result in all captured values passed-via-reference to be
- // invalidated.
- if (const BlockDataRegion *BR = dyn_cast_or_null<BlockDataRegion>(Callee))
- RegionsToInvalidate.push_back(BR);
-
- // Invalidate designated regions using the batch invalidation API.
-
- // FIXME: We can have collisions on the conjured symbol if the
- // expression *I also creates conjured symbols. We probably want
- // to identify conjured symbols by an expression pair: the enclosing
- // expression (the context) and the expression itself. This should
- // disambiguate conjured symbols.
- unsigned Count = Builder.getCurrentBlockCount();
- StoreManager::InvalidatedSymbols IS;
-
- const Expr *Ex = callOrMsg.getOriginExpr();
-
- // NOTE: Even if RegionsToInvalidate is empty, we must still invalidate
- // global variables.
- // NOTE: RetainReleaseChecker handles the actual invalidation of symbols.
- state =
- state->invalidateRegions(RegionsToInvalidate.data(),
- RegionsToInvalidate.data() +
- RegionsToInvalidate.size(),
- Ex, Count, &IS,
- /* invalidateGlobals = */
- Eng.doesInvalidateGlobals(callOrMsg));
-
- Builder.MakeNode(Dst, Ex, Pred, state);
-}
-
-
-void CFRefCount::evalCall(ExplodedNodeSet &Dst,
- ExprEngine& Eng,
- StmtNodeBuilder& Builder,
- const CallExpr *CE, SVal L,
- ExplodedNode *Pred) {
-
- evalCallOrMessage(Dst, Eng, Builder, CallOrObjCMessage(CE, Pred->getState()),
- InstanceReceiver(), L.getAsRegion(), Pred,
- Pred->getState());
-}
-
-void CFRefCount::evalObjCMessage(ExplodedNodeSet &Dst,
- ExprEngine& Eng,
- StmtNodeBuilder& Builder,
- ObjCMessage msg,
- ExplodedNode *Pred,
- const ProgramState *state) {
-
- evalCallOrMessage(Dst, Eng, Builder, CallOrObjCMessage(msg, Pred->getState()),
- InstanceReceiver(msg, Pred->getLocationContext()),
- /* Callee = */ 0, Pred, state);
-}
-
//===----------------------------------------------------------------------===//
// Pieces of the retain/release checker implemented using a CheckerVisitor.
// More pieces of the retain/release checker will be migrated to this interface
@@ -2611,6 +2332,7 @@
check::PostStmt<BlockExpr>,
check::PostStmt<CastExpr>,
check::PostStmt<CallExpr>,
+ check::PostStmt<CXXConstructExpr>,
check::PostObjCMessage,
check::PreStmt<ReturnStmt>,
check::RegionChanges,
@@ -2693,7 +2415,6 @@
switch (GCMode) {
case LangOptions::HybridGC:
llvm_unreachable("GC mode not set yet!");
- return true;
case LangOptions::NonGC:
return false;
case LangOptions::GCOnly:
@@ -2701,7 +2422,6 @@
}
llvm_unreachable("Invalid/unknown GC mode.");
- return false;
}
bool isARCorGCEnabled(ASTContext &Ctx) const {
@@ -2767,24 +2487,29 @@
}
}
+ void printState(raw_ostream &Out, const ProgramState *State,
+ const char *NL, const char *Sep) const;
+
void checkBind(SVal loc, SVal val, CheckerContext &C) const;
void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const;
void checkPostStmt(const CastExpr *CE, CheckerContext &C) const;
void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
+ void checkPostStmt(const CXXConstructExpr *CE, CheckerContext &C) const;
void checkPostObjCMessage(const ObjCMessage &Msg, CheckerContext &C) const;
void checkSummary(const RetainSummary &Summ, const CallOrObjCMessage &Call,
- InstanceReceiver Receiver, CheckerContext &C) const;
+ CheckerContext &C) const;
bool evalCall(const CallExpr *CE, CheckerContext &C) const;
const ProgramState *evalAssume(const ProgramState *state, SVal Cond,
bool Assumption) const;
- const ProgramState *checkRegionChanges(const ProgramState *state,
- const StoreManager::InvalidatedSymbols *invalidated,
- const MemRegion * const *begin,
- const MemRegion * const *end) const;
+ const ProgramState *
+ checkRegionChanges(const ProgramState *state,
+ const StoreManager::InvalidatedSymbols *invalidated,
+ ArrayRef<const MemRegion *> ExplicitRegions,
+ ArrayRef<const MemRegion *> Regions) const;
bool wantsRegionChangeUpdate(const ProgramState *state) const {
return true;
@@ -2914,11 +2639,18 @@
const ProgramState *
RetainReleaseChecker::checkRegionChanges(const ProgramState *state,
const StoreManager::InvalidatedSymbols *invalidated,
- const MemRegion * const *begin,
- const MemRegion * const *end) const {
+ ArrayRef<const MemRegion *> ExplicitRegions,
+ ArrayRef<const MemRegion *> Regions) const {
if (!invalidated)
return state;
+ llvm::SmallPtrSet<SymbolRef, 8> WhitelistedSymbols;
+ for (ArrayRef<const MemRegion *>::iterator I = ExplicitRegions.begin(),
+ E = ExplicitRegions.end(); I != E; ++I) {
+ if (const SymbolicRegion *SR = (*I)->StripCasts()->getAs<SymbolicRegion>())
+ WhitelistedSymbols.insert(SR->getSymbol());
+ }
+
for (StoreManager::InvalidatedSymbols::const_iterator I=invalidated->begin(),
E = invalidated->end(); I!=E; ++I) {
SymbolRef sym = *I;
@@ -3035,7 +2767,24 @@
if (!Summ)
return;
- checkSummary(*Summ, CallOrObjCMessage(CE, state), InstanceReceiver(), C);
+ checkSummary(*Summ, CallOrObjCMessage(CE, state), C);
+}
+
+void RetainReleaseChecker::checkPostStmt(const CXXConstructExpr *CE,
+ CheckerContext &C) const {
+ const CXXConstructorDecl *Ctor = CE->getConstructor();
+ if (!Ctor)
+ return;
+
+ RetainSummaryManager &Summaries = getSummaryManager(C.getASTContext());
+ RetainSummary *Summ = Summaries.getSummary(Ctor);
+
+ // If we didn't get a summary, this constructor doesn't affect retain counts.
+ if (!Summ)
+ return;
+
+ const ProgramState *state = C.getState();
+ checkSummary(*Summ, CallOrObjCMessage(CE, state), C);
}
void RetainReleaseChecker::checkPostObjCMessage(const ObjCMessage &Msg,
@@ -3057,13 +2806,11 @@
if (!Summ)
return;
- checkSummary(*Summ, CallOrObjCMessage(Msg, state),
- InstanceReceiver(Msg, Pred->getLocationContext()), C);
+ checkSummary(*Summ, CallOrObjCMessage(Msg, state), C);
}
void RetainReleaseChecker::checkSummary(const RetainSummary &Summ,
const CallOrObjCMessage &CallOrMsg,
- InstanceReceiver Receiver,
CheckerContext &C) const {
const ProgramState *state = C.getState();
@@ -3073,7 +2820,7 @@
SymbolRef ErrorSym = 0;
for (unsigned idx = 0, e = CallOrMsg.getNumArgs(); idx != e; ++idx) {
- SVal V = CallOrMsg.getArgSValAsScalarOrLoc(idx);
+ SVal V = CallOrMsg.getArgSVal(idx);
if (SymbolRef Sym = V.getAsLocSymbol()) {
if (RefBindings::data_type *T = state->get<RefBindings>(Sym)) {
@@ -3089,13 +2836,15 @@
// Evaluate the effect on the message receiver.
bool ReceiverIsTracked = false;
- if (!hasErr && Receiver) {
- if (SymbolRef Sym = Receiver.getSValAsScalarOrLoc(state).getAsLocSymbol()) {
+ if (!hasErr && CallOrMsg.isObjCMessage()) {
+ const LocationContext *LC = C.getPredecessor()->getLocationContext();
+ SVal Receiver = CallOrMsg.getInstanceMessageReceiver(LC);
+ if (SymbolRef Sym = Receiver.getAsLocSymbol()) {
if (const RefVal *T = state->get<RefBindings>(Sym)) {
ReceiverIsTracked = true;
state = updateSymbol(state, Sym, *T, Summ.getReceiverEffect(), hasErr);
if (hasErr) {
- ErrorRange = Receiver.getSourceRange();
+ ErrorRange = CallOrMsg.getReceiverSourceRange();
ErrorSym = Sym;
}
}
@@ -3436,7 +3185,7 @@
// Invalidate the argument region.
unsigned Count = C.getNodeBuilder().getCurrentBlockCount();
- state = state->invalidateRegion(ArgRegion, CE, Count);
+ state = state->invalidateRegions(ArgRegion, CE, Count);
// Restore the refcount status of the argument.
if (Binding)
@@ -3821,6 +3570,62 @@
}
//===----------------------------------------------------------------------===//
+// Debug printing of refcount bindings and autorelease pools.
+//===----------------------------------------------------------------------===//
+
+static void PrintPool(raw_ostream &Out, SymbolRef Sym,
+ const ProgramState *State) {
+ Out << ' ';
+ if (Sym)
+ Out << Sym->getSymbolID();
+ else
+ Out << "<pool>";
+ Out << ":{";
+
+ // Get the contents of the pool.
+ if (const ARCounts *Cnts = State->get<AutoreleasePoolContents>(Sym))
+ for (ARCounts::iterator I = Cnts->begin(), E = Cnts->end(); I != E; ++I)
+ Out << '(' << I.getKey() << ',' << I.getData() << ')';
+
+ Out << '}';
+}
+
+bool UsesAutorelease(const ProgramState *state) {
+ // A state uses autorelease if it allocated an autorelease pool or if it has
+ // objects in the caller's autorelease pool.
+ return !state->get<AutoreleaseStack>().isEmpty() ||
+ state->get<AutoreleasePoolContents>(SymbolRef());
+}
+
+void RetainReleaseChecker::printState(raw_ostream &Out,
+ const ProgramState *State,
+ const char *NL, const char *Sep) const {
+
+ RefBindings B = State->get<RefBindings>();
+
+ if (!B.isEmpty())
+ Out << Sep << NL;
+
+ for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
+ Out << I->first << " : ";
+ I->second.print(Out);
+ Out << NL;
+ }
+
+ // Print the autorelease stack.
+ if (UsesAutorelease(State)) {
+ Out << Sep << NL << "AR pool stack:";
+ ARStack Stack = State->get<AutoreleaseStack>();
+
+ PrintPool(Out, SymbolRef(), State); // Print the caller's pool.
+ for (ARStack::iterator I = Stack.begin(), E = Stack.end(); I != E; ++I)
+ PrintPool(Out, *I, State);
+
+ Out << NL;
+ }
+}
+
+//===----------------------------------------------------------------------===//
// Transfer function creation for external clients.
//===----------------------------------------------------------------------===//
diff --git a/safecode/tools/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp b/safecode/tools/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
index bcba98f..3e451fd 100644
--- a/safecode/tools/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ b/safecode/tools/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -346,14 +346,15 @@
const ProgramState *
CheckerManager::runCheckersForRegionChanges(const ProgramState *state,
const StoreManager::InvalidatedSymbols *invalidated,
- const MemRegion * const *Begin,
- const MemRegion * const *End) {
+ ArrayRef<const MemRegion *> ExplicitRegions,
+ ArrayRef<const MemRegion *> Regions) {
for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) {
// If any checker declares the state infeasible (or if it starts that way),
// bail out.
if (!state)
return NULL;
- state = RegionChangesCheckers[i].CheckFn(state, invalidated, Begin, End);
+ state = RegionChangesCheckers[i].CheckFn(state, invalidated,
+ ExplicitRegions, Regions);
}
return state;
}
@@ -425,6 +426,14 @@
EndOfTranslationUnitCheckers[i](TU, mgr, BR);
}
+void CheckerManager::runCheckersForPrintState(raw_ostream &Out,
+ const ProgramState *State,
+ const char *NL, const char *Sep) {
+ for (llvm::DenseMap<CheckerTag, CheckerRef>::iterator
+ I = CheckerTags.begin(), E = CheckerTags.end(); I != E; ++I)
+ I->second->printState(Out, State, NL, Sep);
+}
+
//===----------------------------------------------------------------------===//
// Internal registration functions for AST traversing.
//===----------------------------------------------------------------------===//
diff --git a/safecode/tools/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/safecode/tools/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 6c318f7..9dd2884 100644
--- a/safecode/tools/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/safecode/tools/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -67,7 +67,6 @@
// FIXME: Eventually remove the TF object entirely.
TF->RegisterChecks(*this);
- TF->RegisterPrinters(getStateManager().Printers);
if (mgr.shouldEagerlyTrimExplodedGraph()) {
// Enable eager node reclaimation when constructing the ExplodedGraph.
@@ -172,17 +171,8 @@
/// evalAssume - Called by ConstraintManager. Used to call checker-specific
/// logic for handling assumptions on symbolic values.
const ProgramState *ExprEngine::processAssume(const ProgramState *state,
- SVal cond,
- bool assumption) {
-
- state = getCheckerManager().runCheckersForEvalAssume(state, cond,
- assumption);
-
- // If the state is infeasible at this point, bail out.
- if (!state)
- return NULL;
-
- return TF->evalAssume(state, cond, assumption);
+ SVal cond, bool assumption) {
+ return getCheckerManager().runCheckersForEvalAssume(state, cond, assumption);
}
bool ExprEngine::wantsRegionChangeUpdate(const ProgramState *state) {
@@ -192,10 +182,15 @@
const ProgramState *
ExprEngine::processRegionChanges(const ProgramState *state,
const StoreManager::InvalidatedSymbols *invalidated,
- const MemRegion * const *Begin,
- const MemRegion * const *End) {
+ ArrayRef<const MemRegion *> Explicits,
+ ArrayRef<const MemRegion *> Regions) {
return getCheckerManager().runCheckersForRegionChanges(state, invalidated,
- Begin, End);
+ Explicits, Regions);
+}
+
+void ExprEngine::printState(raw_ostream &Out, const ProgramState *State,
+ const char *NL, const char *Sep) {
+ getCheckerManager().runCheckersForPrintState(Out, State, NL, Sep);
}
void ExprEngine::processEndWorklist(bool hasWorkRemaining) {
@@ -279,23 +274,15 @@
// Call checkers with the non-cleaned state so that they could query the
// values of the soon to be dead symbols.
- // FIXME: This should soon be removed.
- ExplodedNodeSet Tmp2;
- getTF().evalDeadSymbols(Tmp2, *this, *Builder, EntryNode,
- EntryState, SymReaper);
- if (Tmp2.empty()) {
- Builder->MakeNode(Tmp2, currentStmt, EntryNode, EntryState);
- }
-
- ExplodedNodeSet Tmp3;
- getCheckerManager().runCheckersForDeadSymbols(Tmp3, Tmp2,
+ ExplodedNodeSet CheckedSet;
+ getCheckerManager().runCheckersForDeadSymbols(CheckedSet, EntryNode,
SymReaper, currentStmt, *this);
- // For each node in Tmp3, generate CleanedNodes that have the environment,
- // the store, and the constraints cleaned up but have the user supplied
- // states as the predecessors.
- for (ExplodedNodeSet::const_iterator I = Tmp3.begin(), E = Tmp3.end();
- I != E; ++I) {
+ // For each node in CheckedSet, generate CleanedNodes that have the
+ // environment, the store, and the constraints cleaned up but have the
+ // user-supplied states as the predecessors.
+ for (ExplodedNodeSet::const_iterator
+ I = CheckedSet.begin(), E = CheckedSet.end(); I != E; ++I) {
const ProgramState *CheckerState = (*I)->getState();
// The constraint manager has not been cleaned up yet, so clean up now.
@@ -1067,7 +1054,6 @@
/// ProcessEndPath - Called by CoreEngine. Used to generate end-of-path
/// nodes when the control reaches the end of a function.
void ExprEngine::processEndOfFunction(EndOfFunctionNodeBuilder& builder) {
- getTF().evalEndPath(*this, builder);
StateMgr.EndPath(builder.getState());
getCheckerManager().runCheckersForEndPath(builder, *this);
}
@@ -1294,55 +1280,29 @@
/// evalBind - Handle the semantics of binding a value to a specific location.
/// This method is used by evalStore and (soon) VisitDeclStmt, and others.
void ExprEngine::evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE,
- ExplodedNode *Pred, const ProgramState *state,
- SVal location, SVal Val, bool atDeclInit) {
-
+ ExplodedNode *Pred,
+ SVal location, SVal Val, bool atDeclInit) {
// Do a previsit of the bind.
- ExplodedNodeSet CheckedSet, Src;
- Src.Add(Pred);
- getCheckerManager().runCheckersForBind(CheckedSet, Src, location, Val, StoreE,
- *this);
+ ExplodedNodeSet CheckedSet;
+ getCheckerManager().runCheckersForBind(CheckedSet, Pred, location, Val,
+ StoreE, *this);
for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end();
I!=E; ++I) {
- if (Pred != *I)
- state = (*I)->getState();
-
- const ProgramState *newState = 0;
+ const ProgramState *state = (*I)->getState();
if (atDeclInit) {
const VarRegion *VR =
cast<VarRegion>(cast<loc::MemRegionVal>(location).getRegion());
- newState = state->bindDecl(VR, Val);
- }
- else {
- if (location.isUnknown()) {
- // We know that the new state will be the same as the old state since
- // the location of the binding is "unknown". Consequently, there
- // is no reason to just create a new node.
- newState = state;
- }
- else {
- // We are binding to a value other than 'unknown'. Perform the binding
- // using the StoreManager.
- newState = state->bindLoc(cast<Loc>(location), Val);
- }
+ state = state->bindDecl(VR, Val);
+ } else {
+ state = state->bindLoc(location, Val);
}
- // The next thing to do is check if the TransferFuncs object wants to
- // update the state based on the new binding. If the GRTransferFunc object
- // doesn't do anything, just auto-propagate the current state.
-
- // NOTE: We use 'AssignE' for the location of the PostStore if 'AssignE'
- // is non-NULL. Checkers typically care about
-
- StmtNodeBuilderRef BuilderRef(Dst, *Builder, *this, *I, newState, StoreE,
- true);
-
- getTF().evalBind(BuilderRef, location, Val);
+ MakeNode(Dst, StoreE, *I, state);
}
}
@@ -1386,7 +1346,7 @@
ProgramPoint::PostStoreKind);
for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI)
- evalBind(Dst, StoreE, *NI, (*NI)->getState(), location, Val);
+ evalBind(Dst, StoreE, *NI, location, Val);
}
void ExprEngine::evalLoad(ExplodedNodeSet &Dst, const Expr *Ex,
diff --git a/safecode/tools/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/safecode/tools/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index a4e640c..47debad 100644
--- a/safecode/tools/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/safecode/tools/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -361,8 +361,7 @@
Builder->getCurrentBlockCount());
}
- evalBind(Dst, DS, N, state,
- loc::MemRegionVal(state->getRegion(VD, LC)), InitVal, true);
+ evalBind(Dst, DS, N, state->getLValue(VD, LC), InitVal, true);
}
else {
MakeNode(Dst, DS, N, state->bindDeclWithNoInit(state->getRegion(VD, LC)));
diff --git a/safecode/tools/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/safecode/tools/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
index d34afba..de3b312 100644
--- a/safecode/tools/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ b/safecode/tools/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -198,17 +198,6 @@
#endif
// Default semantics: invalidate all regions passed as arguments.
- SmallVector<const MemRegion*, 10> regionsToInvalidate;
-
- // FIXME: We can have collisions on the conjured symbol if the
- // expression *I also creates conjured symbols. We probably want
- // to identify conjured symbols by an expression pair: the enclosing
- // expression (the context) and the expression itself. This should
- // disambiguate conjured symbols.
- unsigned blockCount = Builder->getCurrentBlockCount();
-
- // NOTE: Even if RegionsToInvalidate is empty, we must still invalidate
- // global variables.
ExplodedNodeSet destCall;
for (ExplodedNodeSet::iterator
@@ -216,25 +205,10 @@
i != e; ++i)
{
ExplodedNode *Pred = *i;
+ const LocationContext *LC = Pred->getLocationContext();
const ProgramState *state = Pred->getState();
- // Accumulate list of regions that are invalidated.
- for (CXXConstructExpr::const_arg_iterator
- ai = E->arg_begin(), ae = E->arg_end();
- ai != ae; ++ai)
- {
- SVal val = state->getSVal(*ai);
- if (const MemRegion *region = val.getAsRegion())
- regionsToInvalidate.push_back(region);
- }
-
- // Invalidate the regions.
- state = state->invalidateRegions(regionsToInvalidate.data(),
- regionsToInvalidate.data() +
- regionsToInvalidate.size(),
- E, blockCount, 0,
- /* invalidateGlobals = */ true);
-
+ state = invalidateArguments(state, CallOrObjCMessage(E, state), LC);
Builder->MakeNode(destCall, E, Pred, state);
}
@@ -317,17 +291,13 @@
if (ObjTy->isRecordType()) {
regionsToInvalidate.push_back(EleReg);
// Invalidate the regions.
- state = state->invalidateRegions(regionsToInvalidate.data(),
- regionsToInvalidate.data() +
- regionsToInvalidate.size(),
+ state = state->invalidateRegions(regionsToInvalidate,
CNE, blockCount, 0,
/* invalidateGlobals = */ true);
} else {
// Invalidate the regions.
- state = state->invalidateRegions(regionsToInvalidate.data(),
- regionsToInvalidate.data() +
- regionsToInvalidate.size(),
+ state = state->invalidateRegions(regionsToInvalidate,
CNE, blockCount, 0,
/* invalidateGlobals = */ true);
diff --git a/safecode/tools/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/safecode/tools/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
index e49d376..6d377b9 100644
--- a/safecode/tools/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
+++ b/safecode/tools/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
@@ -13,6 +13,7 @@
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
#include "clang/AST/DeclCXX.h"
#include "clang/Analysis/Support/SaveAndRestore.h"
@@ -63,6 +64,100 @@
B.generateNode(state);
}
+const ProgramState *
+ExprEngine::invalidateArguments(const ProgramState *State,
+ const CallOrObjCMessage &Call,
+ const LocationContext *LC) {
+ SmallVector<const MemRegion *, 8> RegionsToInvalidate;
+
+ if (Call.isObjCMessage()) {
+ // Invalidate all instance variables of the receiver of an ObjC message.
+ // FIXME: We should be able to do better with inter-procedural analysis.
+ if (const MemRegion *MR = Call.getInstanceMessageReceiver(LC).getAsRegion())
+ RegionsToInvalidate.push_back(MR);
+
+ } else if (Call.isCXXCall()) {
+ // Invalidate all instance variables for the callee of a C++ method call.
+ // FIXME: We should be able to do better with inter-procedural analysis.
+ // FIXME: We can probably do better for const versus non-const methods.
+ if (const MemRegion *Callee = Call.getCXXCallee().getAsRegion())
+ RegionsToInvalidate.push_back(Callee);
+
+ } else if (Call.isFunctionCall()) {
+ // Block calls invalidate all captured-by-reference values.
+ if (const MemRegion *Callee = Call.getFunctionCallee().getAsRegion()) {
+ if (isa<BlockDataRegion>(Callee))
+ RegionsToInvalidate.push_back(Callee);
+ }
+ }
+
+ for (unsigned idx = 0, e = Call.getNumArgs(); idx != e; ++idx) {
+ SVal V = Call.getArgSVal(idx);
+
+ // If we are passing a location wrapped as an integer, unwrap it and
+ // invalidate the values referred by the location.
+ if (nonloc::LocAsInteger *Wrapped = dyn_cast<nonloc::LocAsInteger>(&V))
+ V = Wrapped->getLoc();
+ else if (!isa<Loc>(V))
+ continue;
+
+ if (const MemRegion *R = V.getAsRegion()) {
+ // Invalidate the value of the variable passed by reference.
+
+ // Are we dealing with an ElementRegion? If the element type is
+ // a basic integer type (e.g., char, int) and the underying region
+ // is a variable region then strip off the ElementRegion.
+ // FIXME: We really need to think about this for the general case
+ // as sometimes we are reasoning about arrays and other times
+ // about (char*), etc., is just a form of passing raw bytes.
+ // e.g., void *p = alloca(); foo((char*)p);
+ if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
+ // Checking for 'integral type' is probably too promiscuous, but
+ // we'll leave it in for now until we have a systematic way of
+ // handling all of these cases. Eventually we need to come up
+ // with an interface to StoreManager so that this logic can be
+ // approriately delegated to the respective StoreManagers while
+ // still allowing us to do checker-specific logic (e.g.,
+ // invalidating reference counts), probably via callbacks.
+ if (ER->getElementType()->isIntegralOrEnumerationType()) {
+ const MemRegion *superReg = ER->getSuperRegion();
+ if (isa<VarRegion>(superReg) || isa<FieldRegion>(superReg) ||
+ isa<ObjCIvarRegion>(superReg))
+ R = cast<TypedRegion>(superReg);
+ }
+ // FIXME: What about layers of ElementRegions?
+ }
+
+ // Mark this region for invalidation. We batch invalidate regions
+ // below for efficiency.
+ RegionsToInvalidate.push_back(R);
+ } else {
+ // Nuke all other arguments passed by reference.
+ // FIXME: is this necessary or correct? This handles the non-Region
+ // cases. Is it ever valid to store to these?
+ State = State->unbindLoc(cast<Loc>(V));
+ }
+ }
+
+ // Invalidate designated regions using the batch invalidation API.
+
+ // FIXME: We can have collisions on the conjured symbol if the
+ // expression *I also creates conjured symbols. We probably want
+ // to identify conjured symbols by an expression pair: the enclosing
+ // expression (the context) and the expression itself. This should
+ // disambiguate conjured symbols.
+ assert(Builder && "Invalidating arguments outside of a statement context");
+ unsigned Count = Builder->getCurrentBlockCount();
+ StoreManager::InvalidatedSymbols IS;
+
+ // NOTE: Even if RegionsToInvalidate is empty, we may still invalidate
+ // global variables.
+ return State->invalidateRegions(RegionsToInvalidate,
+ Call.getOriginExpr(), Count,
+ &IS, doesInvalidateGlobals(Call));
+
+}
+
void ExprEngine::VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred,
ExplodedNodeSet &dst) {
// Perform the previsit of the CallExpr.
@@ -108,22 +203,15 @@
unsigned Count = Builder.getCurrentBlockCount();
SVal RetVal = SVB.getConjuredSymbolVal(0, CE, ResultTy, Count);
- // Generate a new ExplodedNode with the return value set.
+ // Generate a new state with the return value set.
state = state->BindExpr(CE, RetVal);
- Pred = Builder.generateNode(CE, state, Pred);
- // Then handle everything else.
- unsigned oldSize = Dst.size();
- SaveOr OldHasGen(Builder.hasGeneratedNode);
-
- // Dispatch to transfer function logic to handle the rest of the call.
- Eng.getTF().evalCall(Dst, Eng, Builder, CE, L, Pred);
-
- // Handle the case where no nodes where generated. Auto-generate that
- // contains the updated state if we aren't generating sinks.
- if (!Builder.BuildSinks && Dst.size() == oldSize &&
- !Builder.hasGeneratedNode)
- Eng.MakeNode(Dst, CE, Pred, state);
+ // Invalidate the arguments.
+ const LocationContext *LC = Pred->getLocationContext();
+ state = Eng.invalidateArguments(state, CallOrObjCMessage(CE, state), LC);
+
+ // And make the result node.
+ Eng.MakeNode(Dst, CE, Pred, state);
}
};
@@ -161,25 +249,5 @@
Src.Add(Pred);
}
- ExplodedNodeSet CheckedSet;
- getCheckerManager().runCheckersForPreStmt(CheckedSet, Src, RS, *this);
-
- for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end();
- I != E; ++I) {
-
- assert(Builder && "StmtNodeBuilder must be defined.");
-
- Pred = *I;
- unsigned size = Dst.size();
-
- SaveAndRestore<bool> OldSink(Builder->BuildSinks);
- SaveOr OldHasGen(Builder->hasGeneratedNode);
-
- getTF().evalReturn(Dst, *this, *Builder, RS, Pred);
-
- // Handle the case where no nodes where generated.
- if (!Builder->BuildSinks && Dst.size() == size &&
- !Builder->hasGeneratedNode)
- MakeNode(Dst, RS, Pred, Pred->getState());
- }
+ getCheckerManager().runCheckersForPreStmt(Dst, Src, RS, *this);
}
diff --git a/safecode/tools/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp b/safecode/tools/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
index 6cfe8cd..1a68657 100644
--- a/safecode/tools/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
+++ b/safecode/tools/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
@@ -142,7 +142,6 @@
ExplodedNode *Pred = *DI;
bool RaisesException = false;
- unsigned oldSize = dstEval.size();
SaveAndRestore<bool> OldSink(Builder->BuildSinks);
SaveOr OldHasGen(Builder->hasGeneratedNode);
@@ -225,12 +224,8 @@
// Dispatch to plug-in transfer function.
evalObjCMessage(dstEval, msg, Pred, Pred->getState());
}
-
- // Handle the case where no nodes where generated. Auto-generate that
- // contains the updated state if we aren't generating sinks.
- if (!Builder->BuildSinks && dstEval.size() == oldSize &&
- !Builder->hasGeneratedNode)
- MakeNode(dstEval, msg.getOriginExpr(), Pred, Pred->getState());
+
+ assert(Builder->BuildSinks || Builder->hasGeneratedNode);
}
// Finally, perform the post-condition check of the ObjCMessageExpr and store
@@ -273,7 +268,11 @@
// Bind the return value.
state = state->BindExpr(currentStmt, ReturnValue);
- // Now we can handle the other aspects of the message.
- getTF().evalObjCMessage(Dst, *this, *Builder, msg, Pred, state);
+ // Invalidate the arguments (and the receiver)
+ const LocationContext *LC = Pred->getLocationContext();
+ state = invalidateArguments(state, CallOrObjCMessage(msg, state), LC);
+
+ // And create the new node.
+ MakeNode(Dst, msg.getOriginExpr(), Pred, state);
}
diff --git a/safecode/tools/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp b/safecode/tools/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
index 68a6618..2b377d0 100644
--- a/safecode/tools/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
+++ b/safecode/tools/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
@@ -47,7 +47,7 @@
virtual void FlushDiagnostics(SmallVectorImpl<std::string> *FilesMade);
- virtual void HandlePathDiagnostic(const PathDiagnostic* D);
+ virtual void HandlePathDiagnosticImpl(const PathDiagnostic* D);
virtual StringRef getName() const {
return "HTMLDiagnostics";
@@ -88,7 +88,7 @@
// Report processing.
//===----------------------------------------------------------------------===//
-void HTMLDiagnostics::HandlePathDiagnostic(const PathDiagnostic* D) {
+void HTMLDiagnostics::HandlePathDiagnosticImpl(const PathDiagnostic* D) {
if (!D)
return;
diff --git a/safecode/tools/clang/lib/StaticAnalyzer/Core/ObjCMessage.cpp b/safecode/tools/clang/lib/StaticAnalyzer/Core/ObjCMessage.cpp
index 40ed83b..112c468 100644
--- a/safecode/tools/clang/lib/StaticAnalyzer/Core/ObjCMessage.cpp
+++ b/safecode/tools/clang/lib/StaticAnalyzer/Core/ObjCMessage.cpp
@@ -112,18 +112,22 @@
QualType resultTy;
bool isLVal = false;
- if (CallE) {
- isLVal = CallE->isLValue();
- const Expr *Callee = CallE->getCallee();
- if (const FunctionDecl *FD = State->getSVal(Callee).getAsFunctionDecl())
- resultTy = FD->getResultType();
- else
- resultTy = CallE->getType();
- }
- else {
+ if (isObjCMessage()) {
isLVal = isa<ObjCMessageExpr>(Msg.getOriginExpr()) &&
Msg.getOriginExpr()->isLValue();
resultTy = Msg.getResultType(ctx);
+ } else if (const CXXConstructExpr *Ctor =
+ CallE.dyn_cast<const CXXConstructExpr *>()) {
+ resultTy = Ctor->getType();
+ } else {
+ const CallExpr *FunctionCall = CallE.get<const CallExpr *>();
+
+ isLVal = FunctionCall->isLValue();
+ const Expr *Callee = FunctionCall->getCallee();
+ if (const FunctionDecl *FD = State->getSVal(Callee).getAsFunctionDecl())
+ resultTy = FD->getResultType();
+ else
+ resultTy = FunctionCall->getType();
}
if (isLVal)
@@ -132,25 +136,23 @@
return resultTy;
}
-SVal CallOrObjCMessage::getArgSValAsScalarOrLoc(unsigned i) const {
- assert(i < getNumArgs());
- if (CallE) return State->getSValAsScalarOrLoc(CallE->getArg(i));
- QualType argT = Msg.getArgType(i);
- if (Loc::isLocType(argT) || argT->isIntegerType())
- return Msg.getArgSVal(i, State);
- return UnknownVal();
-}
-
SVal CallOrObjCMessage::getFunctionCallee() const {
assert(isFunctionCall());
assert(!isCXXCall());
- const Expr *callee = CallE->getCallee()->IgnoreParens();
- return State->getSVal(callee);
+ const Expr *Fun = CallE.get<const CallExpr *>()->getCallee()->IgnoreParens();
+ return State->getSVal(Fun);
}
SVal CallOrObjCMessage::getCXXCallee() const {
assert(isCXXCall());
+ const CallExpr *ActualCall = CallE.get<const CallExpr *>();
const Expr *callee =
- cast<CXXMemberCallExpr>(CallE)->getImplicitObjectArgument();
+ cast<CXXMemberCallExpr>(ActualCall)->getImplicitObjectArgument();
return State->getSVal(callee);
}
+
+SVal
+CallOrObjCMessage::getInstanceMessageReceiver(const LocationContext *LC) const {
+ assert(isObjCMessage());
+ return Msg.getInstanceReceiverSVal(State, LC);
+}
diff --git a/safecode/tools/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp b/safecode/tools/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
index 7f95c95..e56f157 100644
--- a/safecode/tools/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
+++ b/safecode/tools/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
@@ -117,6 +117,13 @@
HandlePathDiagnostic(D);
}
+void PathDiagnosticClient::HandlePathDiagnostic(const PathDiagnostic *D) {
+ // For now this simply forwards to HandlePathDiagnosticImpl. In the future
+ // we can use this indirection to control for multi-threaded access to
+ // the PathDiagnosticClient from multiple bug reporters.
+ HandlePathDiagnosticImpl(D);
+}
+
//===----------------------------------------------------------------------===//
// PathDiagnosticLocation methods.
//===----------------------------------------------------------------------===//
diff --git a/safecode/tools/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp b/safecode/tools/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
index cae5bc9..3133be7 100644
--- a/safecode/tools/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
+++ b/safecode/tools/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
@@ -74,7 +74,7 @@
void FlushDiagnostics(SmallVectorImpl<std::string> *FilesMade);
- void HandlePathDiagnostic(const PathDiagnostic* D);
+ void HandlePathDiagnosticImpl(const PathDiagnostic* D);
virtual StringRef getName() const {
return "PlistDiagnostics";
@@ -321,7 +321,7 @@
}
}
-void PlistDiagnostics::HandlePathDiagnostic(const PathDiagnostic* D) {
+void PlistDiagnostics::HandlePathDiagnosticImpl(const PathDiagnostic* D) {
if (!D)
return;
diff --git a/safecode/tools/clang/lib/StaticAnalyzer/Core/ProgramState.cpp b/safecode/tools/clang/lib/StaticAnalyzer/Core/ProgramState.cpp
index 046de0d..54da7b5 100644
--- a/safecode/tools/clang/lib/StaticAnalyzer/Core/ProgramState.cpp
+++ b/safecode/tools/clang/lib/StaticAnalyzer/Core/ProgramState.cpp
@@ -51,10 +51,6 @@
}
ProgramStateManager::~ProgramStateManager() {
- for (std::vector<ProgramState::Printer*>::iterator I=Printers.begin(),
- E=Printers.end(); I!=E; ++I)
- delete *I;
-
for (GDMContextsTy::iterator I=GDMContexts.begin(), E=GDMContexts.end();
I!=E; ++I)
I->second.second(I->second.first);
@@ -136,41 +132,38 @@
new_state;
}
-const ProgramState *ProgramState::invalidateRegions(const MemRegion * const *Begin,
- const MemRegion * const *End,
- const Expr *E, unsigned Count,
- StoreManager::InvalidatedSymbols *IS,
- bool invalidateGlobals) const {
+const ProgramState *
+ProgramState::invalidateRegions(ArrayRef<const MemRegion *> Regions,
+ const Expr *E, unsigned Count,
+ StoreManager::InvalidatedSymbols *IS,
+ bool invalidateGlobals) const {
if (!IS) {
StoreManager::InvalidatedSymbols invalidated;
- return invalidateRegionsImpl(Begin, End, E, Count,
- invalidated, invalidateGlobals);
+ return invalidateRegionsImpl(Regions, E, Count,
+ invalidated, invalidateGlobals);
}
- return invalidateRegionsImpl(Begin, End, E, Count, *IS, invalidateGlobals);
+ return invalidateRegionsImpl(Regions, E, Count, *IS, invalidateGlobals);
}
const ProgramState *
-ProgramState::invalidateRegionsImpl(const MemRegion * const *Begin,
- const MemRegion * const *End,
- const Expr *E, unsigned Count,
- StoreManager::InvalidatedSymbols &IS,
- bool invalidateGlobals) const {
+ProgramState::invalidateRegionsImpl(ArrayRef<const MemRegion *> Regions,
+ const Expr *E, unsigned Count,
+ StoreManager::InvalidatedSymbols &IS,
+ bool invalidateGlobals) const {
ProgramStateManager &Mgr = getStateManager();
SubEngine* Eng = Mgr.getOwningEngine();
if (Eng && Eng->wantsRegionChangeUpdate(this)) {
- StoreManager::InvalidatedRegions Regions;
+ StoreManager::InvalidatedRegions Invalidated;
const StoreRef &newStore
- = Mgr.StoreMgr->invalidateRegions(getStore(), Begin, End, E, Count, IS,
- invalidateGlobals, &Regions);
+ = Mgr.StoreMgr->invalidateRegions(getStore(), Regions, E, Count, IS,
+ invalidateGlobals, &Invalidated);
const ProgramState *newState = makeWithStore(newStore);
- return Eng->processRegionChanges(newState, &IS,
- &Regions.front(),
- &Regions.back()+1);
+ return Eng->processRegionChanges(newState, &IS, Regions, Invalidated);
}
const StoreRef &newStore =
- Mgr.StoreMgr->invalidateRegions(getStore(), Begin, End, E, Count, IS,
+ Mgr.StoreMgr->invalidateRegions(getStore(), Regions, E, Count, IS,
invalidateGlobals, NULL);
return makeWithStore(newStore);
}
@@ -392,11 +385,11 @@
return (bool) (((uintptr_t) S) & 0x1);
}
-void ProgramState::print(raw_ostream &Out, CFG &C, const char* nl,
- const char* sep) const {
+void ProgramState::print(raw_ostream &Out, CFG &C,
+ const char *NL, const char *Sep) const {
// Print the store.
ProgramStateManager &Mgr = getStateManager();
- Mgr.getStoreManager().print(getStore(), Out, nl, sep);
+ Mgr.getStoreManager().print(getStore(), Out, NL, Sep);
// Print Subexpression bindings.
bool isFirst = true;
@@ -407,10 +400,11 @@
continue;
if (isFirst) {
- Out << nl << nl << "Sub-Expressions:" << nl;
+ Out << NL << NL << "Sub-Expressions:" << NL;
isFirst = false;
+ } else {
+ Out << NL;
}
- else { Out << nl; }
Out << " (" << (void*) I.getKey() << ") ";
LangOptions LO; // FIXME.
@@ -426,10 +420,11 @@
continue;
if (isFirst) {
- Out << nl << nl << "Block-level Expressions:" << nl;
+ Out << NL << NL << "Block-level Expressions:" << NL;
isFirst = false;
+ } else {
+ Out << NL;
}
- else { Out << nl; }
Out << " (" << (void*) I.getKey() << ") ";
LangOptions LO; // FIXME.
@@ -445,10 +440,11 @@
continue;
if (isFirst) {
- Out << nl << nl << "Load/store locations:" << nl;
+ Out << NL << NL << "Load/store locations:" << NL;
isFirst = false;
+ } else {
+ Out << NL;
}
- else { Out << nl; }
const Stmt *S = (Stmt*) (((uintptr_t) I.getKey()) & ((uintptr_t) ~0x1));
@@ -458,13 +454,10 @@
Out << " : " << I.getData();
}
- Mgr.getConstraintManager().print(this, Out, nl, sep);
+ Mgr.getConstraintManager().print(this, Out, NL, Sep);
// Print checker-specific data.
- for (std::vector<Printer*>::iterator I = Mgr.Printers.begin(),
- E = Mgr.Printers.end(); I != E; ++I) {
- (*I)->Print(Out, this, nl, sep);
- }
+ Mgr.getOwningEngine()->printState(Out, this, NL, Sep);
}
void ProgramState::printDOT(raw_ostream &Out, CFG &C) const {
diff --git a/safecode/tools/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/safecode/tools/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
index 30028c7..04c274d 100644
--- a/safecode/tools/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ b/safecode/tools/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -236,13 +236,11 @@
// Binding values to regions.
//===-------------------------------------------------------------------===//
- StoreRef invalidateRegions(Store store,
- const MemRegion * const *Begin,
- const MemRegion * const *End,
+ StoreRef invalidateRegions(Store store, ArrayRef<const MemRegion *> Regions,
const Expr *E, unsigned Count,
InvalidatedSymbols &IS,
bool invalidateGlobals,
- InvalidatedRegions *Regions);
+ InvalidatedRegions *Invalidated);
public: // Made public for helper classes.
@@ -721,21 +719,21 @@
}
StoreRef RegionStoreManager::invalidateRegions(Store store,
- const MemRegion * const *I,
- const MemRegion * const *E,
+ ArrayRef<const MemRegion *> Regions,
const Expr *Ex, unsigned Count,
InvalidatedSymbols &IS,
bool invalidateGlobals,
- InvalidatedRegions *Regions) {
+ InvalidatedRegions *Invalidated) {
invalidateRegionsWorker W(*this, StateMgr,
RegionStoreManager::GetRegionBindings(store),
- Ex, Count, IS, Regions, invalidateGlobals);
+ Ex, Count, IS, Invalidated, invalidateGlobals);
// Scan the bindings and generate the clusters.
W.GenerateClusters();
- // Add I .. E to the worklist.
- for ( ; I != E; ++I)
+ // Add the regions to the worklist.
+ for (ArrayRef<const MemRegion *>::iterator
+ I = Regions.begin(), E = Regions.end(); I != E; ++I)
W.AddToWorkList(*I);
W.RunWorkList();
@@ -755,8 +753,8 @@
// Even if there are no bindings in the global scope, we still need to
// record that we touched it.
- if (Regions)
- Regions->push_back(GS);
+ if (Invalidated)
+ Invalidated->push_back(GS);
}
return StoreRef(B.getRootWithoutRetain(), *this);
diff --git a/safecode/tools/clang/lib/StaticAnalyzer/Core/TextPathDiagnostics.cpp b/safecode/tools/clang/lib/StaticAnalyzer/Core/TextPathDiagnostics.cpp
index c4665ef..e91b48d 100644
--- a/safecode/tools/clang/lib/StaticAnalyzer/Core/TextPathDiagnostics.cpp
+++ b/safecode/tools/clang/lib/StaticAnalyzer/Core/TextPathDiagnostics.cpp
@@ -31,7 +31,7 @@
TextPathDiagnostics(const std::string& output, Diagnostic &diag)
: OutputFile(output), Diag(diag) {}
- void HandlePathDiagnostic(const PathDiagnostic* D);
+ void HandlePathDiagnosticImpl(const PathDiagnostic* D);
void FlushDiagnostics(SmallVectorImpl<std::string> *FilesMade) { }
@@ -53,7 +53,7 @@
return new TextPathDiagnostics(out, PP.getDiagnostics());
}
-void TextPathDiagnostics::HandlePathDiagnostic(const PathDiagnostic* D) {
+void TextPathDiagnostics::HandlePathDiagnosticImpl(const PathDiagnostic* D) {
if (!D)
return;
diff --git a/safecode/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/safecode/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
index 24f19cd..4b5a882 100644
--- a/safecode/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
+++ b/safecode/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
@@ -162,6 +162,7 @@
virtual void HandleTranslationUnit(ASTContext &C);
void HandleDeclContext(ASTContext &C, DeclContext *dc);
+ void HandleDeclContextDecl(ASTContext &C, Decl *D);
void HandleCode(Decl *D);
};
@@ -172,61 +173,67 @@
//===----------------------------------------------------------------------===//
void AnalysisConsumer::HandleDeclContext(ASTContext &C, DeclContext *dc) {
- BugReporter BR(*Mgr);
for (DeclContext::decl_iterator I = dc->decls_begin(), E = dc->decls_end();
I != E; ++I) {
- Decl *D = *I;
+ HandleDeclContextDecl(C, *I);
+ }
+}
+
+void AnalysisConsumer::HandleDeclContextDecl(ASTContext &C, Decl *D) {
+ { // Handle callbacks for arbitrary decls.
+ BugReporter BR(*Mgr);
checkerMgr->runCheckersOnASTDecl(D, *Mgr, BR);
+ }
- switch (D->getKind()) {
- case Decl::Namespace: {
- HandleDeclContext(C, cast<NamespaceDecl>(D));
- break;
- }
- case Decl::CXXConstructor:
- case Decl::CXXDestructor:
- case Decl::CXXConversion:
- case Decl::CXXMethod:
- case Decl::Function: {
- FunctionDecl *FD = cast<FunctionDecl>(D);
- // We skip function template definitions, as their semantics is
- // only determined when they are instantiated.
- if (FD->isThisDeclarationADefinition() &&
- !FD->isDependentContext()) {
- if (!Opts.AnalyzeSpecificFunction.empty() &&
- FD->getDeclName().getAsString() != Opts.AnalyzeSpecificFunction)
- break;
- DisplayFunction(FD);
- HandleCode(FD);
- }
- break;
- }
-
- case Decl::ObjCCategoryImpl:
- case Decl::ObjCImplementation: {
- ObjCImplDecl *ID = cast<ObjCImplDecl>(*I);
- HandleCode(ID);
-
- for (ObjCContainerDecl::method_iterator MI = ID->meth_begin(),
- ME = ID->meth_end(); MI != ME; ++MI) {
- checkerMgr->runCheckersOnASTDecl(*MI, *Mgr, BR);
-
- if ((*MI)->isThisDeclarationADefinition()) {
- if (!Opts.AnalyzeSpecificFunction.empty() &&
- Opts.AnalyzeSpecificFunction !=
- (*MI)->getSelector().getAsString())
- break;
- DisplayFunction(*MI);
- HandleCode(*MI);
- }
- }
- break;
- }
-
- default:
- break;
+ switch (D->getKind()) {
+ case Decl::Namespace: {
+ HandleDeclContext(C, cast<NamespaceDecl>(D));
+ break;
}
- }
+ case Decl::CXXConstructor:
+ case Decl::CXXDestructor:
+ case Decl::CXXConversion:
+ case Decl::CXXMethod:
+ case Decl::Function: {
+ FunctionDecl *FD = cast<FunctionDecl>(D);
+ // We skip function template definitions, as their semantics is
+ // only determined when they are instantiated.
+ if (FD->isThisDeclarationADefinition() &&
+ !FD->isDependentContext()) {
+ if (!Opts.AnalyzeSpecificFunction.empty() &&
+ FD->getDeclName().getAsString() != Opts.AnalyzeSpecificFunction)
+ break;
+ DisplayFunction(FD);
+ HandleCode(FD);
+ }
+ break;
+ }
+
+ case Decl::ObjCCategoryImpl:
+ case Decl::ObjCImplementation: {
+ ObjCImplDecl *ID = cast<ObjCImplDecl>(D);
+ HandleCode(ID);
+
+ for (ObjCContainerDecl::method_iterator MI = ID->meth_begin(),
+ ME = ID->meth_end(); MI != ME; ++MI) {
+ BugReporter BR(*Mgr);
+ checkerMgr->runCheckersOnASTDecl(*MI, *Mgr, BR);
+
+ if ((*MI)->isThisDeclarationADefinition()) {
+ if (!Opts.AnalyzeSpecificFunction.empty() &&
+ Opts.AnalyzeSpecificFunction !=
+ (*MI)->getSelector().getAsString())
+ break;
+ DisplayFunction(*MI);
+ HandleCode(*MI);
+ }
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
}
void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) {
diff --git a/safecode/tools/clang/test/ARCMT/migrate-space-in-path.m b/safecode/tools/clang/test/ARCMT/migrate-space-in-path.m
new file mode 100644
index 0000000..8f45cc7
--- /dev/null
+++ b/safecode/tools/clang/test/ARCMT/migrate-space-in-path.m
@@ -0,0 +1,9 @@
+// XFAIL: win32
+
+// RUN: mkdir -p %t/"with space"
+// RUN: cp %S/Inputs/* %t/"with space"
+// RUN: %clang_cc1 -arcmt-migrate -arcmt-migrate-directory %t.migrate %t/"with space"/test1.m.in -x objective-c -fobjc-nonfragile-abi
+// RUN: %clang_cc1 -arcmt-migrate -arcmt-migrate-directory %t.migrate %t/"with space"/test2.m.in -x objective-c -fobjc-nonfragile-abi
+// RUN: c-arcmt-test -arcmt-migrate-directory %t.migrate | arcmt-test -verify-transformed-files %t/"with space"/test1.m.in.result %t/"with space"/test2.m.in.result %t/"with space"/test.h.result
+// RUN: rm -rf %t.migrate
+// RUN: rm -rf %t
diff --git a/safecode/tools/clang/test/Analysis/objc-arc.m b/safecode/tools/clang/test/Analysis/objc-arc.m
index 6b22fd0..8e18877 100644
--- a/safecode/tools/clang/test/Analysis/objc-arc.m
+++ b/safecode/tools/clang/test/Analysis/objc-arc.m
@@ -147,3 +147,9 @@
(void) x;
}
+// Previously this resulted in a "return of stack address" warning.
+id test_return() {
+ id x = (__bridge_transfer id) CFCreateString();
+ return x; // no-warning
+}
+
diff --git a/safecode/tools/clang/test/CXX/special/class.temporary/p1.cpp b/safecode/tools/clang/test/CXX/special/class.temporary/p1.cpp
new file mode 100644
index 0000000..07890eb
--- /dev/null
+++ b/safecode/tools/clang/test/CXX/special/class.temporary/p1.cpp
@@ -0,0 +1,58 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+namespace test0 {
+ struct A {
+ A() = default;
+ int x;
+ int y;
+
+ A(const A&) = delete; // expected-note {{function has been explicitly marked deleted here}}
+ };
+
+ void foo(...);
+
+ void test() {
+ A a;
+ foo(a); // expected-error {{call to deleted constructor of 'test0::A'}}
+ }
+}
+
+namespace test1 {
+ struct A {
+ A() = default;
+ int x;
+ int y;
+
+ private:
+ A(const A&) = default; // expected-note {{declared private here}}
+ };
+
+ void foo(...);
+
+ void test() {
+ A a;
+ // FIXME: this error about variadics is bogus
+ foo(a); // expected-error {{calling a private constructor of class 'test1::A'}} expected-error {{cannot pass object of non-trivial type 'test1::A' through variadic function}}
+ }
+}
+
+// Don't enforce this in an unevaluated context.
+namespace test2 {
+ struct A {
+ A(const A&) = delete; // expected-note {{marked deleted here}}
+ };
+
+ typedef char one[1];
+ typedef char two[2];
+
+ one &meta(bool);
+ two &meta(...);
+
+ void a(A &a) {
+ char check[sizeof(meta(a)) == 2 ? 1 : -1];
+ }
+
+ void b(A &a) {
+ meta(a); // expected-error {{call to deleted constructor}}
+ }
+}
diff --git a/safecode/tools/clang/test/CodeGenCXX/varargs.cpp b/safecode/tools/clang/test/CodeGenCXX/varargs.cpp
index d469ae4..af34336 100644
--- a/safecode/tools/clang/test/CodeGenCXX/varargs.cpp
+++ b/safecode/tools/clang/test/CodeGenCXX/varargs.cpp
@@ -1,17 +1,43 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck %s
+
// rdar://7309675
// PR4678
+namespace test0 {
+ // test1 should be compmiled to be a varargs function in the IR even
+ // though there is no way to do a va_begin. Otherwise, the optimizer
+ // will warn about 'dropped arguments' at the call site.
-// test1 should be compmiled to be a varargs function in the IR even
-// though there is no way to do a va_begin. Otherwise, the optimizer
-// will warn about 'dropped arguments' at the call site.
+ // CHECK: define i32 @_ZN5test05test1Ez(...)
+ int test1(...) {
+ return -1;
+ }
-// CHECK: define i32 @_Z5test1z(...)
-int test1(...) {
- return -1;
+ // CHECK: call i32 (...)* @_ZN5test05test1Ez(i32 0)
+ void test() {
+ test1(0);
+ }
}
-// CHECK: call i32 (...)* @_Z5test1z(i32 0)
-void test() {
- test1(0);
+namespace test1 {
+ struct A {
+ int x;
+ int y;
+ };
+
+ void foo(...);
+
+ void test() {
+ A x;
+ foo(x);
+ }
+ // CHECK: define void @_ZN5test14testEv()
+ // CHECK: [[X:%.*]] = alloca [[A:%.*]], align 4
+ // CHECK-NEXT: [[TMP:%.*]] = alloca [[A]], align 4
+ // CHECK-NEXT: [[T0:%.*]] = bitcast [[A]]* [[TMP]] to i8*
+ // CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[X]] to i8*
+ // CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[T0]], i8* [[T1]], i64 8, i32 4, i1 false)
+ // CHECK-NEXT: [[T0:%.*]] = bitcast [[A]]* [[TMP]] to i64*
+ // CHECK-NEXT: [[T1:%.*]] = load i64* [[T0]], align 1
+ // CHECK-NEXT: call void (...)* @_ZN5test13fooEz(i64 [[T1]])
+ // CHECK-NEXT: ret void
}
diff --git a/safecode/tools/clang/test/CodeGenObjCXX/arc-references.mm b/safecode/tools/clang/test/CodeGenObjCXX/arc-references.mm
index 3d0313d..b1a12e4 100644
--- a/safecode/tools/clang/test/CodeGenObjCXX/arc-references.mm
+++ b/safecode/tools/clang/test/CodeGenObjCXX/arc-references.mm
@@ -61,8 +61,9 @@
// CHECK: define void @_Z5test5RU8__strongP11objc_object
void test5(__strong id &x) {
- // CHECK: [[OBJ_ID:%[a-zA-Z0-9]+]] = call i8* @objc_retain
- // CHECK-NEXT: [[OBJ_A:%[a-zA-Z0-9]+]] = bitcast i8* [[OBJ_ID]] to [[A:%[a-zA-Z0-9]+]]*
+ // CHECK: [[REFTMP:%.*]] = alloca {{%.*}}*, align 8
+ // CHECK: [[OBJ_ID:%.*]] = call i8* @objc_retain(
+ // CHECK-NEXT: [[OBJ_A:%.*]] = bitcast i8* [[OBJ_ID]] to [[A:%[a-zA-Z0-9]+]]*
// CHECK-NEXT: store [[A]]* [[OBJ_A]], [[A]]** [[REFTMP:%[a-zA-Z0-9]+]]
// CHECK-NEXT: call void @_Z4sinkOU8__strongP1A
sink(x);
diff --git a/safecode/tools/clang/test/Driver/apple-kext-i386.cpp b/safecode/tools/clang/test/Driver/apple-kext-i386.cpp
index 80c8bfc..aebe33f 100644
--- a/safecode/tools/clang/test/Driver/apple-kext-i386.cpp
+++ b/safecode/tools/clang/test/Driver/apple-kext-i386.cpp
@@ -16,8 +16,8 @@
// CHECK-MKERNEL: "-mkernel"
// RUN: %clang -ccc-host-triple i386-apple-darwin10 \
-// RUN: -Wno-self-assign -Wc++0x-extensions \
-// RUN: -Wno-microsoft -Wmicrosoft \
+// RUN: -Wno-self-assign -Wc++0x-extensions -Wno-microsoft -Wmicrosoft -Wvla \
+// RUN: -faltivec -mthumb -mcpu=G4 -mlongcall -mno-longcall -msoft-float \
// RUN: -fapple-kext -### -fsyntax-only %s 2> %t
// RUN: FileCheck --check-prefix=CHECK-UNSUPPORTED < %t %s
@@ -26,3 +26,10 @@
// CHECK-UNSUPPORTED-NOT: "-Wc++0x-extensions"
// CHECK-UNSUPPORTED-NOT: "-Wno-microsoft"
// CHECK-UNSUPPORTED-NOT: "-Wmicrosoft"
+// CHECK-UNSUPPORTED-NOT: "-Wvla"
+// CHECK-UNSUPPORTED-NOT: "-faltivec"
+// CHECK-UNSUPPORTED-NOT: "-mthumb"
+// CHECK-UNSUPPORTED-NOT: "-mlongcall"
+// CHECK-UNSUPPORTED: "-mno-longcall"
+// CHECK-UNSUPPORTED: "-msoft-float"
+
diff --git a/safecode/tools/clang/test/Misc/warning-flags.c b/safecode/tools/clang/test/Misc/warning-flags.c
index b89ce41..e29fbea 100644
--- a/safecode/tools/clang/test/Misc/warning-flags.c
+++ b/safecode/tools/clang/test/Misc/warning-flags.c
@@ -17,7 +17,7 @@
The list of warnings below should NEVER grow. It should gradually shrink to 0.
-CHECK: Warnings without flags (312):
+CHECK: Warnings without flags (313):
CHECK-NEXT: auto_storage_class
CHECK-NEXT: backslash_newline_space
CHECK-NEXT: charize_microsoft_ext
@@ -230,6 +230,7 @@
CHECK-NEXT: warn_missing_dependent_template_keyword
CHECK-NEXT: warn_missing_exception_specification
CHECK-NEXT: warn_missing_whitespace_after_macro_name
+CHECK-NEXT: warn_module_not_found
CHECK-NEXT: warn_multiple_method_decl
CHECK-NEXT: warn_no_constructor_for_refconst
CHECK-NEXT: warn_nonnull_pointers_only
diff --git a/safecode/tools/clang/test/Modules/Inputs/diamond_bottom.h b/safecode/tools/clang/test/Modules/Inputs/diamond_bottom.h
index 40afc9b..6351d02 100644
--- a/safecode/tools/clang/test/Modules/Inputs/diamond_bottom.h
+++ b/safecode/tools/clang/test/Modules/Inputs/diamond_bottom.h
@@ -1 +1,4 @@
+__import__ diamond_left;
+__import__ diamond_right;
+
char bottom(char *x);
diff --git a/safecode/tools/clang/test/Modules/Inputs/diamond_left.h b/safecode/tools/clang/test/Modules/Inputs/diamond_left.h
index 9758b85..8da494c 100644
--- a/safecode/tools/clang/test/Modules/Inputs/diamond_left.h
+++ b/safecode/tools/clang/test/Modules/Inputs/diamond_left.h
@@ -1,3 +1,5 @@
+__import__ diamond_top;
+
float left(float *);
int top_left(char *c);
diff --git a/safecode/tools/clang/test/Modules/Inputs/diamond_right.h b/safecode/tools/clang/test/Modules/Inputs/diamond_right.h
index 9adeb6a..2efa277 100644
--- a/safecode/tools/clang/test/Modules/Inputs/diamond_right.h
+++ b/safecode/tools/clang/test/Modules/Inputs/diamond_right.h
@@ -1,3 +1,5 @@
+__import__ diamond_top;
+
double right(double *);
struct left_and_right {
diff --git a/safecode/tools/clang/test/Modules/Inputs/load_failure.h b/safecode/tools/clang/test/Modules/Inputs/load_failure.h
new file mode 100644
index 0000000..5bcb44d
--- /dev/null
+++ b/safecode/tools/clang/test/Modules/Inputs/load_failure.h
@@ -0,0 +1 @@
+int fail(int);
diff --git a/safecode/tools/clang/test/Modules/diamond.c b/safecode/tools/clang/test/Modules/diamond.c
index f9b283a..94381f2 100644
--- a/safecode/tools/clang/test/Modules/diamond.c
+++ b/safecode/tools/clang/test/Modules/diamond.c
@@ -1,4 +1,10 @@
+
+
+
// in diamond-bottom.h: expected-note{{passing argument to parameter 'x' here}}
+
+__import__ diamond_bottom;
+
void test_diamond(int i, float f, double d, char c) {
top(&i);
left(&f);
@@ -14,8 +20,8 @@
lr.left = 17;
}
-// RUN: %clang_cc1 -emit-pch -o %t_top.h.pch %S/Inputs/diamond_top.h
-// RUN: %clang_cc1 -import-module %t_top.h.pch -emit-pch -o %t_left.h.pch %S/Inputs/diamond_left.h
-// RUN: %clang_cc1 -import-module %t_top.h.pch -emit-pch -o %t_right.h.pch %S/Inputs/diamond_right.h
-// RUN: %clang_cc1 -import-module %t_left.h.pch -import-module %t_right.h.pch -emit-pch -o %t_bottom.h.pch %S/Inputs/diamond_bottom.h
-// RUN: %clang_cc1 -import-module %t_bottom.h.pch -verify %s
+// RUN: %clang_cc1 -emit-module -o %T/diamond_top.pcm %S/Inputs/diamond_top.h
+// RUN: %clang_cc1 -I %T -emit-module -o %T/diamond_left.pcm %S/Inputs/diamond_left.h
+// RUN: %clang_cc1 -I %T -emit-module -o %T/diamond_right.pcm %S/Inputs/diamond_right.h
+// RUN: %clang_cc1 -I %T -emit-module -o %T/diamond_bottom.pcm %S/Inputs/diamond_bottom.h
+// RUN: %clang_cc1 -I %T %s -verify
diff --git a/safecode/tools/clang/test/Modules/load_failure.c b/safecode/tools/clang/test/Modules/load_failure.c
new file mode 100644
index 0000000..5b5df38
--- /dev/null
+++ b/safecode/tools/clang/test/Modules/load_failure.c
@@ -0,0 +1,17 @@
+#ifdef NONEXISTENT
+__import__ load_nonexistent;
+#endif
+
+#ifdef FAILURE
+__import__ load_failure;
+#endif
+
+// RUN: %clang_cc1 -x c++ -emit-module -o %T/load_failure.pcm %S/Inputs/load_failure.h
+// RUN: %clang_cc1 -I %T %s -DNONEXISTENT 2>&1 | FileCheck -check-prefix=CHECK-NONEXISTENT %s
+// CHECK-NONEXISTENT: load_failure.c:2:12: fatal error: module 'load_nonexistent' not found
+
+// RUN: %clang_cc1 -I %T %s -DFAILURE 2>&1 | FileCheck -check-prefix=CHECK-FAILURE %s
+// FIXME: Clean up diagnostic text below and give it a location
+// CHECK-FAILURE: error: C99 support was disabled in PCH file but is currently enabled
+
+
diff --git a/safecode/tools/clang/test/Modules/lookup.cpp b/safecode/tools/clang/test/Modules/lookup.cpp
index e9f52b7..cae6621 100644
--- a/safecode/tools/clang/test/Modules/lookup.cpp
+++ b/safecode/tools/clang/test/Modules/lookup.cpp
@@ -1,3 +1,9 @@
+
+#define import __import__
+import lookup_left_cxx;
+#define IMPORT(X) __import__ X
+IMPORT(lookup_right_cxx);
+
void test(int i, float f) {
// unqualified lookup
f0(&i);
@@ -8,10 +14,10 @@
::f0(&f);
}
-// RUN: %clang_cc1 -emit-module -x c++ -verify -o %t_lookup_left.h.pch %S/Inputs/lookup_left.hpp
-// RUN: %clang_cc1 -emit-module -x c++ -o %t_lookup_right.h.pch %S/Inputs/lookup_right.hpp
-// RUN: %clang_cc1 -x c++ -import-module %t_lookup_left.h.pch -import-module %t_lookup_right.h.pch -verify %s
-// RUN: %clang_cc1 -ast-print -x c++ -import-module %t_lookup_left.h.pch -import-module %t_lookup_right.h.pch %s | FileCheck -check-prefix=CHECK-PRINT %s
+// RUN: %clang_cc1 -emit-module -x c++ -verify -o %T/lookup_left_cxx.pcm %S/Inputs/lookup_left.hpp
+// RUN: %clang_cc1 -emit-module -x c++ -o %T/lookup_right_cxx.pcm %S/Inputs/lookup_right.hpp
+// RUN: %clang_cc1 -x c++ -I %T %s -verify
+// RUN: %clang_cc1 -ast-print -x c++ -I %T %s | FileCheck -check-prefix=CHECK-PRINT %s
// CHECK-PRINT: int *f0(int *);
// CHECK-PRINT: float *f0(float *);
diff --git a/safecode/tools/clang/test/Modules/lookup.m b/safecode/tools/clang/test/Modules/lookup.m
index 85f1dd9..48d0ba9 100644
--- a/safecode/tools/clang/test/Modules/lookup.m
+++ b/safecode/tools/clang/test/Modules/lookup.m
@@ -1,15 +1,17 @@
// lookup_left.h: expected-note{{using}}
// lookup_right.h: expected-note{{also found}}
+__import__ lookup_left_objc;
+__import__ lookup_right_objc;
void test(id x) {
[x method]; // expected-warning{{multiple methods named 'method' found}}
}
-// RUN: %clang_cc1 -emit-module -x objective-c -o %t_lookup_left.h.pch %S/Inputs/lookup_left.h
-// RUN: %clang_cc1 -emit-module -x objective-c -o %t_lookup_right.h.pch %S/Inputs/lookup_right.h
-// RUN: %clang_cc1 -x objective-c -import-module %t_lookup_left.h.pch -import-module %t_lookup_right.h.pch -verify %s
-// RUN: %clang_cc1 -ast-print -x objective-c -import-module %t_lookup_left.h.pch -import-module %t_lookup_right.h.pch %s | FileCheck -check-prefix=CHECK-PRINT %s
+// RUN: %clang_cc1 -emit-module -x objective-c -o %T/lookup_left_objc.pcm %S/Inputs/lookup_left.h
+// RUN: %clang_cc1 -emit-module -x objective-c -o %T/lookup_right_objc.pcm %S/Inputs/lookup_right.h
+// RUN: %clang_cc1 -x objective-c -I %T -verify %s
+// RUN: %clang_cc1 -ast-print -x objective-c -I %T %s | FileCheck -check-prefix=CHECK-PRINT %s
// CHECK-PRINT: - (int) method;
// CHECK-PRINT: - (double) method
diff --git a/safecode/tools/clang/test/Rewriter/rewrite-forward-class.m b/safecode/tools/clang/test/Rewriter/rewrite-forward-class.m
index 5a50f53..1d3af6f 100644
--- a/safecode/tools/clang/test/Rewriter/rewrite-forward-class.m
+++ b/safecode/tools/clang/test/Rewriter/rewrite-forward-class.m
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -rewrite-objc -o - %s
+// RUN: %clang_cc1 -x objective-c -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-address-of-temporary -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
// rdar://6969189
@class XX;
@@ -6,3 +7,29 @@
@class ISyncClient, SMSession, ISyncManager, ISyncSession, SMDataclassInfo, SMClientInfo,
DMCConfiguration, DMCStatusEntry;
+@interface QQ
+
+@end
+
+@interface SMDataclassInfo : QQ
+- (XX*) Meth;
+- (DMCStatusEntry*)Meth2;
+@end
+
+@implementation SMDataclassInfo
+- (XX*) Meth { return 0; }
+- (DMCStatusEntry*)Meth2 { return 0; }
+@end
+
+@interface YY
+{
+ ISyncClient *p1;
+ ISyncSession *p2;
+}
+@property (copy) ISyncClient *p1;
+@end
+
+@implementation YY
+@synthesize p1;
+@end
+
diff --git a/safecode/tools/clang/test/Sema/format-strings.c b/safecode/tools/clang/test/Sema/format-strings.c
index b47d3ca..20c665b 100644
--- a/safecode/tools/clang/test/Sema/format-strings.c
+++ b/safecode/tools/clang/test/Sema/format-strings.c
@@ -372,3 +372,13 @@
printf("%c", x); // no-warning
printf("%hhu", y); // no-warning
}
+
+// Test suppression of individual warnings.
+
+void test_suppress_invalid_specifier() {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
+ printf("%@", 12); // no-warning
+#pragma clang diagnostic pop
+}
+
diff --git a/safecode/tools/clang/test/SemaCXX/deleted-operator.cpp b/safecode/tools/clang/test/SemaCXX/deleted-operator.cpp
new file mode 100644
index 0000000..1c8a537
--- /dev/null
+++ b/safecode/tools/clang/test/SemaCXX/deleted-operator.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s
+
+struct PR10757 {
+ bool operator~() = delete; // expected-note {{explicitly deleted}}
+ bool operator==(const PR10757&) = delete; // expected-note {{explicitly deleted}}
+ operator float();
+};
+int PR10757f() {
+ PR10757 a1;
+ // FIXME: We get a ridiculous number of "built-in candidate" notes here...
+ if(~a1) {} // expected-error {{overload resolution selected deleted operator}} expected-note 6 {{built-in candidate}}
+ if(a1==a1) {} // expected-error {{overload resolution selected deleted operator}} expected-note 81 {{built-in candidate}}
+}
diff --git a/safecode/tools/clang/test/SemaObjC/arc-property-lifetime.m b/safecode/tools/clang/test/SemaObjC/arc-property-lifetime.m
index b1c84c7..88321e2 100644
--- a/safecode/tools/clang/test/SemaObjC/arc-property-lifetime.m
+++ b/safecode/tools/clang/test/SemaObjC/arc-property-lifetime.m
@@ -79,7 +79,7 @@
@implementation Gorf
@synthesize x;
-@synthesize y; // expected-error {{existing ivar 'y' for unsafe_unretained property 'y' must be __unsafe_unretained}}
+@synthesize y; // expected-error {{existing ivar 'y' for property 'y' with assign attribute must be __unsafe_unretained}}
@synthesize z;
@end
@@ -94,7 +94,7 @@
@implementation Gorf2
@synthesize x;
-@synthesize y; // expected-error {{existing ivar 'y' for unsafe_unretained property 'y' must be __unsafe_unretained}}
+@synthesize y; // expected-error {{existing ivar 'y' for property 'y' with unsafe_unretained attribute must be __unsafe_unretained}}
@synthesize z;
@end
diff --git a/safecode/tools/clang/test/SemaObjC/default-synthesize.m b/safecode/tools/clang/test/SemaObjC/default-synthesize.m
index 33e3bd6..c9454d2 100644
--- a/safecode/tools/clang/test/SemaObjC/default-synthesize.m
+++ b/safecode/tools/clang/test/SemaObjC/default-synthesize.m
@@ -97,10 +97,10 @@
// rdar://7920807
@interface C @end
@interface C (Category)
-@property int p; // expected-warning {{property 'p' requires method 'p' to be defined }} \
- // expected-warning {{property 'p' requires method 'setP:' to be defined}}
+@property int p; // expected-note 2 {{property declared here}}
@end
-@implementation C (Category) // expected-note 2 {{implementation is here}}
+@implementation C (Category) // expected-warning {{property 'p' requires method 'p' to be defined}} \
+ // expected-warning {{property 'p' requires method 'setP:' to be defined}}
@end
// Don't complain if a property is already @synthesized by usr.
diff --git a/safecode/tools/clang/test/SemaObjC/property-category-1.m b/safecode/tools/clang/test/SemaObjC/property-category-1.m
index 26e7313..6382826 100644
--- a/safecode/tools/clang/test/SemaObjC/property-category-1.m
+++ b/safecode/tools/clang/test/SemaObjC/property-category-1.m
@@ -37,7 +37,7 @@
///
@interface I0
-@property(readonly) int p0; // expected-warning {{property 'p0' requires method 'p0' to be defined}}
+@property(readonly) int p0; // expected-note {{property declared here}}
@end
@interface I0 (Cat0)
@@ -46,7 +46,7 @@
@interface I0 (Cat1)
@end
-@implementation I0 // expected-note {{implementation is here}}
+@implementation I0 // expected-warning {{property 'p0' requires method 'p0' to be define}}
- (void) foo {
self.p0 = 0; // expected-error {{assigning to property with 'readonly' attribute not allowed}}
}
diff --git a/safecode/tools/clang/test/SemaObjC/property-category-2.m b/safecode/tools/clang/test/SemaObjC/property-category-2.m
index e63672b..ecc3681 100644
--- a/safecode/tools/clang/test/SemaObjC/property-category-2.m
+++ b/safecode/tools/clang/test/SemaObjC/property-category-2.m
@@ -4,8 +4,7 @@
@protocol MyProtocol
@property float myFloat;
-@property float anotherFloat; // expected-warning {{property 'anotherFloat' requires method 'anotherFloat' to be defined - use @dynamic}} \
- // expected-warning {{property 'anotherFloat' requires method 'setAnotherFloat:' to be defined }}
+@property float anotherFloat; // expected-note 2 {{property declared}}
@end
@interface MyObject { float anotherFloat; }
@@ -14,7 +13,8 @@
@interface MyObject (CAT) <MyProtocol>
@end
-@implementation MyObject (CAT) // expected-note 2 {{implementation is here}}
+@implementation MyObject (CAT) // expected-warning {{property 'anotherFloat' requires method}} \
+ // expected-warning {{property 'anotherFloat' requires method 'setAnotherFloat:'}}
@dynamic myFloat; // OK
@synthesize anotherFloat; // expected-error {{@synthesize not allowed in a category's implementation}}
@end
diff --git a/safecode/tools/clang/test/SemaObjC/property-category-impl.m b/safecode/tools/clang/test/SemaObjC/property-category-impl.m
index 9979497..21fdf1b 100644
--- a/safecode/tools/clang/test/SemaObjC/property-category-impl.m
+++ b/safecode/tools/clang/test/SemaObjC/property-category-impl.m
@@ -24,8 +24,8 @@
@end
@interface MyClass (public)
-@property(readwrite) int foo; // expected-warning {{property 'foo' requires method 'setFoo:' to be defined }}
+@property(readwrite) int foo; // expected-note {{property declared here}}
@end
-@implementation MyClass (public)// expected-note {{implementation is here}}
+@implementation MyClass (public)// expected-warning {{property 'foo' requires method 'setFoo:' to be defined }}
@end
diff --git a/safecode/tools/clang/test/SemaObjC/property.m b/safecode/tools/clang/test/SemaObjC/property.m
index 4d00bd2..62291bb 100644
--- a/safecode/tools/clang/test/SemaObjC/property.m
+++ b/safecode/tools/clang/test/SemaObjC/property.m
@@ -11,8 +11,7 @@
@end
@interface I(CAT)
-@property int d1; // expected-warning {{property 'd1' requires method 'd1' to be defined }} \
- // expected-warning {{property 'd1' requires method 'setD1:' to be defined }}
+@property int d1; // expected-note 2 {{property declared here}}
@end
@implementation I
@@ -23,7 +22,8 @@
@synthesize name; // OK! property with same name as an accessible ivar of same name
@end
-@implementation I(CAT) // expected-note 2 {{implementation is here}}
+@implementation I(CAT) // expected-warning {{property 'd1' requires method 'd1' to be defined }} \
+ // expected-warning {{property 'd1' requires method 'setD1:' to be defined }}
@synthesize d1; // expected-error {{@synthesize not allowed in a category's implementation}}
@dynamic bad; // expected-error {{property implementation must have its declaration in the category 'CAT'}}
@end
diff --git a/safecode/tools/clang/test/SemaObjC/super-class-protocol-conformance.m b/safecode/tools/clang/test/SemaObjC/super-class-protocol-conformance.m
index bf19c83..32d5392 100644
--- a/safecode/tools/clang/test/SemaObjC/super-class-protocol-conformance.m
+++ b/safecode/tools/clang/test/SemaObjC/super-class-protocol-conformance.m
@@ -4,7 +4,7 @@
@interface NSObject @end
@protocol TopProtocol
- @property (readonly) id myString; // expected-warning {{property 'myString' requires method 'myString' to be defined}}
+ @property (readonly) id myString; // expected-note {{property}}
@end
@protocol SubProtocol <TopProtocol>
@@ -21,7 +21,7 @@
@implementation SubClass1 @end // Test1 - No Warning
-@implementation TopClass // expected-note {{implementation is here}}
+@implementation TopClass // expected-warning {{property 'myString' requires method 'myString' to be defined}}
@end
@implementation SubClass // Test3 - No Warning
@@ -39,11 +39,11 @@
@implementation SubClass4 @end // Test 5 - No Warning
@protocol NewProtocol
- @property (readonly) id myNewString; // expected-warning {{property 'myNewString' requires method 'myNewString' to be defined}}
+ @property (readonly) id myNewString; // expected-note {{property}}
@end
@interface SubClass5 : SubClass4 <NewProtocol> @end
-@implementation SubClass5 @end // expected-note {{implementation is here}}
+@implementation SubClass5 @end // expected-warning {{property 'myNewString' requires method 'myNewString' to be defined}}
// Radar 8035776
@@ -54,10 +54,10 @@
@end
@protocol ProtocolWithProperty <SuperProtocol>
-@property (readonly, assign) id invalidationBacktrace; // expected-warning {{property 'invalidationBacktrace' requires method 'invalidationBacktrace' to be defined}}
+@property (readonly, assign) id invalidationBacktrace; // expected-note {{property}}
@end
@interface INTF : Super <ProtocolWithProperty>
@end
-@implementation INTF @end // expected-note {{implementation is here}}
+@implementation INTF @end // expected-warning{{property 'invalidationBacktrace' requires method 'invalidationBacktrace' to be defined}}
diff --git a/safecode/tools/clang/test/SemaObjC/unimplemented-protocol-prop.m b/safecode/tools/clang/test/SemaObjC/unimplemented-protocol-prop.m
index d3de50e..0805202 100644
--- a/safecode/tools/clang/test/SemaObjC/unimplemented-protocol-prop.m
+++ b/safecode/tools/clang/test/SemaObjC/unimplemented-protocol-prop.m
@@ -2,14 +2,12 @@
@protocol PROTOCOL0
@required
-@property float MyProperty0; // expected-warning {{property 'MyProperty0' requires method 'MyProperty0' to be defined }} \
- // expected-warning {{property 'MyProperty0' requires method 'setMyProperty0:' to be defined}}
+@property float MyProperty0; // expected-note 2 {{property declared}}
@end
@protocol PROTOCOL<PROTOCOL0>
@required
-@property float MyProperty; // expected-warning {{property 'MyProperty' requires method 'MyProperty' to be defined}} \
- // expected-warning {{property 'MyProperty' requires method 'setMyProperty:' to be defined}}
+@property float MyProperty; // expected-note 2 {{property declared}}
@optional
@property float OptMyProperty;
@end
@@ -17,4 +15,7 @@
@interface I <PROTOCOL>
@end
-@implementation I @end // expected-note 4 {{implementation is here}}
+@implementation I @end // expected-warning {{property 'MyProperty0' requires method 'MyProperty0' to be defined}} \
+ // expected-warning {{property 'MyProperty0' requires method 'setMyProperty0:' to be defined}}\
+ // expected-warning {{property 'MyProperty' requires method 'MyProperty' to be defined}} \
+ // expected-warning {{property 'MyProperty' requires method 'setMyProperty:' to be defined}}
diff --git a/safecode/tools/clang/test/SemaObjC/warn-missing-super.m b/safecode/tools/clang/test/SemaObjC/warn-missing-super.m
index 19c6b62..ff0c415 100644
--- a/safecode/tools/clang/test/SemaObjC/warn-missing-super.m
+++ b/safecode/tools/clang/test/SemaObjC/warn-missing-super.m
@@ -8,31 +8,43 @@
- (void)dealloc {
// Root class, shouldn't warn
}
+- (void)finalize {
+ // Root class, shouldn't warn
+}
@end
@interface Subclass1 : NSObject
- (void)dealloc;
+- (void)finalize;
@end
@implementation Subclass1
- (void)dealloc {
}
+- (void)finalize {
+}
@end
@interface Subclass2 : NSObject
- (void)dealloc;
+- (void)finalize;
@end
@implementation Subclass2
- (void)dealloc {
[super dealloc]; // Shouldn't warn
}
+- (void)finalize {
+ [super finalize]; // Shouldn't warn
+}
@end
// RUN: %clang_cc1 -fsyntax-only %s 2>&1 | FileCheck %s
-// CHECK: warn-missing-super.m:19:1: warning: method possibly missing a [super dealloc] call
-// CHECK: 1 warning generated.
+// CHECK: warn-missing-super.m:23:1: warning: method possibly missing a [super dealloc] call
+// CHECK: warn-missing-super.m:25:1: warning: method possibly missing a [super finalize] call
+// CHECK: 2 warnings generated.
// RUN: %clang_cc1 -fsyntax-only -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi -fobjc-arc %s 2>&1 | FileCheck --check-prefix=CHECK-ARC %s
-// CHECK-ARC: warn-missing-super.m:28:4: error: ARC forbids explicit message send of 'dealloc'
-// CHECK-ARC: 1 error generated.
+// CHECK-ARC: warn-missing-super.m:25:1: warning: method possibly missing a [super finalize] call
+// CHECK-ARC: warn-missing-super.m:35:4: error: ARC forbids explicit message send of 'dealloc'
+// CHECK-ARC: 1 warning and 1 error generated.
diff --git a/safecode/tools/clang/test/SemaTemplate/temp_arg_nontype.cpp b/safecode/tools/clang/test/SemaTemplate/temp_arg_nontype.cpp
index f90bb11..e93cfa3 100644
--- a/safecode/tools/clang/test/SemaTemplate/temp_arg_nontype.cpp
+++ b/safecode/tools/clang/test/SemaTemplate/temp_arg_nontype.cpp
@@ -320,3 +320,6 @@
}
}
+
+template <int& I> struct PR10766 { static int *ip; };
+template <int& I> int* PR10766<I>::ip = &I;
diff --git a/safecode/tools/clang/test/lit.cfg b/safecode/tools/clang/test/lit.cfg
index 850c0cf..8062aa7 100644
--- a/safecode/tools/clang/test/lit.cfg
+++ b/safecode/tools/clang/test/lit.cfg
@@ -165,7 +165,10 @@
###
# Set available features we allow tests to conditionalize on.
-config.available_features.add('crash-recovery')
+#
+# As of 2011.08, crash-recovery tests still do not pass on FreeBSD.
+if platform.system() not in ['FreeBSD']:
+ config.available_features.add('crash-recovery')
# Shell execution
if platform.system() not in ['Windows'] or lit.getBashPath() != '':
diff --git a/safecode/tools/clang/tools/libclang/CIndex.cpp b/safecode/tools/clang/tools/libclang/CIndex.cpp
index c7e492e..c9b1fa8 100644
--- a/safecode/tools/clang/tools/libclang/CIndex.cpp
+++ b/safecode/tools/clang/tools/libclang/CIndex.cpp
@@ -1100,10 +1100,9 @@
}
bool CursorVisitor::VisitObjCClassDecl(ObjCClassDecl *D) {
- for (ObjCClassDecl::iterator C = D->begin(), CEnd = D->end(); C != CEnd; ++C)
- if (Visit(MakeCursorObjCClassRef(C->getInterface(), C->getLocation(), TU)))
+ if (Visit(MakeCursorObjCClassRef(D->getForwardInterfaceDecl(),
+ D->getForwardDecl()->getLocation(), TU)))
return true;
-
return false;
}
@@ -4219,8 +4218,8 @@
Decl *D = Storage.get<Decl*>();
if (UsingDecl *Using = dyn_cast<UsingDecl>(D))
return Using->shadow_size();
- if (ObjCClassDecl *Classes = dyn_cast<ObjCClassDecl>(D))
- return Classes->size();
+ if (isa<ObjCClassDecl>(D))
+ return 1;
if (ObjCForwardProtocolDecl *Protocols =dyn_cast<ObjCForwardProtocolDecl>(D))
return Protocols->protocol_size();
@@ -4250,10 +4249,8 @@
std::advance(Pos, index);
return MakeCXCursor(cast<UsingShadowDecl>(*Pos)->getTargetDecl(), TU);
}
-
if (ObjCClassDecl *Classes = dyn_cast<ObjCClassDecl>(D))
- return MakeCXCursor(Classes->begin()[index].getInterface(), TU);
-
+ return MakeCXCursor(Classes->getForwardInterfaceDecl(), TU);
if (ObjCForwardProtocolDecl *Protocols = dyn_cast<ObjCForwardProtocolDecl>(D))
return MakeCXCursor(Protocols->protocol_begin()[index], TU);
diff --git a/safecode/tools/clang/tools/scan-build/scan-build b/safecode/tools/clang/tools/scan-build/scan-build
index f835ca3..dae86f4 100755
--- a/safecode/tools/clang/tools/scan-build/scan-build
+++ b/safecode/tools/clang/tools/scan-build/scan-build
@@ -61,7 +61,7 @@
Diag ("The analyzer encountered problems on some source files.\n");
Diag ("Preprocessed versions of these sources were deposited in '$Dir/failures'.\n");
Diag ("Please consider submitting a bug report using these files:\n");
- Diag (" http://clang.llvm.org/StaticAnalysisUsage.html#filingbugs\n")
+ Diag (" http://clang-analyzer.llvm.org/filing_bugs.html\n")
}
sub DieDiag {
@@ -802,7 +802,7 @@
}
print OUT "</table>\n";
}
- print OUT "<p>Please consider submitting preprocessed files as <a href=\"http://clang.llvm.org/StaticAnalysisUsage.html#filingbugs\">bug reports</a>. <!-- REPORTCRASHES --> </p>\n";
+ print OUT "<p>Please consider submitting preprocessed files as <a href=\"http://clang-analyzer.llvm.org/filing_bugs.html\">bug reports</a>. <!-- REPORTCRASHES --> </p>\n";
}
print OUT "</body></html>\n";