aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoman Divacky <rdivacky@FreeBSD.org>2009-11-05 17:18:09 +0000
committerRoman Divacky <rdivacky@FreeBSD.org>2009-11-05 17:18:09 +0000
commit8f57cb0305232cb53fff00ef151ca716766f3437 (patch)
tree8b316eca843681b024034db1125707173b9adb4a
parent51fb8b013e7734b795139f49d3b1f77c539be20a (diff)
downloadsrc-8f57cb0305232cb53fff00ef151ca716766f3437.tar.gz
src-8f57cb0305232cb53fff00ef151ca716766f3437.zip
Update clang to r86140.
Notes
Notes: svn path=/vendor/clang/dist/; revision=198954
-rw-r--r--include/clang/AST/ASTConsumer.h19
-rw-r--r--include/clang/Analysis/PathDiagnostic.h14
-rw-r--r--include/clang/Analysis/PathSensitive/AnalysisManager.h7
-rw-r--r--include/clang/Analysis/PathSensitive/BugType.h4
-rw-r--r--include/clang/Analysis/PathSensitive/Checker.h8
-rw-r--r--include/clang/Analysis/PathSensitive/Checkers/UndefinedAssignmentChecker.h3
-rw-r--r--include/clang/Analysis/PathSensitive/GRExprEngine.h14
-rw-r--r--include/clang/Basic/Diagnostic.h29
-rw-r--r--include/clang/Basic/DiagnosticGroups.td2
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td3
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td16
-rw-r--r--include/clang/Frontend/ASTConsumers.h10
-rw-r--r--include/clang/Frontend/AnalysisConsumer.h5
-rw-r--r--include/clang/Frontend/InitPreprocessor.h16
-rw-r--r--include/clang/Frontend/PathDiagnosticClients.h26
-rw-r--r--include/clang/Frontend/TextDiagnosticPrinter.h8
-rw-r--r--include/clang/Frontend/Utils.h1
-rw-r--r--include/clang/Lex/Preprocessor.h20
-rw-r--r--include/clang/Parse/Action.h35
-rw-r--r--include/clang/Parse/DeclSpec.h12
-rw-r--r--include/clang/Parse/Parser.h7
-rw-r--r--include/clang/Rewrite/HTMLRewrite.h7
-rw-r--r--lib/AST/ASTContext.cpp5
-rw-r--r--lib/AST/DeclarationName.cpp50
-rw-r--r--lib/AST/RecordLayoutBuilder.cpp69
-rw-r--r--lib/AST/RecordLayoutBuilder.h9
-rw-r--r--lib/AST/Type.cpp6
-rw-r--r--lib/Analysis/GRExprEngine.cpp43
-rw-r--r--lib/Analysis/UndefinedAssignmentChecker.cpp33
-rw-r--r--lib/Analysis/VLASizeChecker.cpp6
-rw-r--r--lib/CodeGen/CGCXX.cpp30
-rw-r--r--lib/CodeGen/CGDecl.cpp10
-rw-r--r--lib/CodeGen/CodeGenFunction.cpp16
-rw-r--r--lib/CodeGen/CodeGenFunction.h37
-rw-r--r--lib/Frontend/AnalysisConsumer.cpp60
-rw-r--r--lib/Frontend/HTMLDiagnostics.cpp92
-rw-r--r--lib/Frontend/HTMLPrint.cpp36
-rw-r--r--lib/Frontend/InitPreprocessor.cpp10
-rw-r--r--lib/Frontend/PlistDiagnostics.cpp59
-rw-r--r--lib/Frontend/TextDiagnosticPrinter.cpp1
-rw-r--r--lib/Headers/stdint.h158
-rw-r--r--lib/Lex/Preprocessor.cpp8
-rw-r--r--lib/Parse/DeclSpec.cpp8
-rw-r--r--lib/Parse/MinimalAction.cpp6
-rw-r--r--lib/Parse/ParseDecl.cpp6
-rw-r--r--lib/Parse/ParseDeclCXX.cpp49
-rw-r--r--lib/Parse/ParseExprCXX.cpp135
-rw-r--r--lib/Parse/ParseTemplate.cpp9
-rw-r--r--lib/Parse/ParseTentative.cpp3
-rw-r--r--lib/Rewrite/HTMLRewrite.cpp44
-rw-r--r--lib/Sema/Sema.h15
-rw-r--r--lib/Sema/SemaCXXCast.cpp3
-rw-r--r--lib/Sema/SemaCXXScopeSpec.cpp131
-rw-r--r--lib/Sema/SemaDeclCXX.cpp148
-rw-r--r--lib/Sema/SemaExpr.cpp81
-rw-r--r--lib/Sema/SemaExprCXX.cpp10
-rw-r--r--lib/Sema/SemaOverload.cpp33
-rw-r--r--lib/Sema/SemaTemplate.cpp2
-rw-r--r--lib/Sema/SemaType.cpp75
-rw-r--r--lib/Sema/TreeTransform.h50
-rw-r--r--test/Analysis/misc-ps.m4
-rw-r--r--test/CMakeLists.txt3
-rw-r--r--test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p5-cxx0x.cpp6
-rw-r--r--test/CodeGenCXX/array-construction.cpp3
-rw-r--r--test/CodeGenCXX/ptr-to-datamember.cpp13
-rw-r--r--test/CodeGenCXX/ptr-to-member-function.cpp18
-rw-r--r--test/CodeGenCXX/virt.cpp112
-rw-r--r--test/Coverage/html-diagnostics.c6
-rw-r--r--test/Frontend/dependency-gen.c4
-rw-r--r--test/Makefile12
-rw-r--r--test/Parser/if-scope-c90.c2
-rw-r--r--test/Parser/if-scope-c99.c2
-rw-r--r--test/Preprocessor/stdint.c376
-rw-r--r--test/Sema/compare.c20
-rw-r--r--test/Sema/conditional-expr.c19
-rw-r--r--test/SemaCXX/compare.cpp15
-rw-r--r--test/SemaCXX/conditional-expr.cpp22
-rw-r--r--test/SemaCXX/constructor-initializer.cpp33
-rw-r--r--test/SemaCXX/overload-member-call.cpp12
-rw-r--r--test/SemaCXX/overloaded-operator.cpp11
-rw-r--r--test/SemaCXX/primary-base.cpp4
-rw-r--r--test/SemaTemplate/example-dynarray.cpp2
-rw-r--r--test/SemaTemplate/instantiate-complete.cpp21
-rw-r--r--test/SemaTemplate/instantiate-deeply.cpp16
-rw-r--r--test/SemaTemplate/instantiate-expr-1.cpp27
-rw-r--r--test/SemaTemplate/member-access-expr.cpp17
-rw-r--r--test/SemaTemplate/member-template-access-expr.cpp10
-rw-r--r--test/SemaTemplate/temp_arg_nontype.cpp30
-rw-r--r--test/SemaTemplate/template-id-expr.cpp17
-rw-r--r--test/lit.cfg6
-rw-r--r--tools/clang-cc/clang-cc.cpp192
-rw-r--r--utils/C++Tests/LLVM-Syntax/lit.local.cfg1
-rw-r--r--www/analyzer/latest_checker.html.incl2
93 files changed, 1657 insertions, 1193 deletions
diff --git a/include/clang/AST/ASTConsumer.h b/include/clang/AST/ASTConsumer.h
index af6bf30b6882..53bb785c49d2 100644
--- a/include/clang/AST/ASTConsumer.h
+++ b/include/clang/AST/ASTConsumer.h
@@ -38,17 +38,17 @@ public:
virtual ~ASTConsumer() {}
/// Initialize - This is called to initialize the consumer, providing the
- /// ASTContext and the Action.
+ /// ASTContext.
virtual void Initialize(ASTContext &Context) {}
/// HandleTopLevelDecl - Handle the specified top-level declaration. This is
- /// called by the parser to process every top-level Decl*. Note that D can
- /// be the head of a chain of Decls (e.g. for `int a, b` the chain will have
- /// two elements). Use Decl::getNextDeclarator() to walk the chain.
+ /// called by the parser to process every top-level Decl*. Note that D can be
+ /// the head of a chain of Decls (e.g. for `int a, b` the chain will have two
+ /// elements). Use Decl::getNextDeclarator() to walk the chain.
virtual void HandleTopLevelDecl(DeclGroupRef D);
/// HandleTranslationUnit - This method is called when the ASTs for entire
- /// translation unit have been parsed.
+ /// translation unit have been parsed.
virtual void HandleTranslationUnit(ASTContext &Ctx) {}
/// HandleTagDeclDefinition - This callback is invoked each time a TagDecl
@@ -57,9 +57,9 @@ public:
/// can be defined in declspecs).
virtual void HandleTagDeclDefinition(TagDecl *D) {}
- /// \brief Callback invoked at the end of a translation unit to
- /// notify the consumer that the given tentative definition should
- /// be completed.
+ /// CompleteTentativeDefinition - Callback invoked at the end of a translation
+ /// unit to notify the consumer that the given tentative definition should be
+ /// completed.
///
/// The variable declaration itself will be a tentative
/// definition. If it had an incomplete array type, its type will
@@ -69,8 +69,7 @@ public:
virtual void CompleteTentativeDefinition(VarDecl *D) {}
/// PrintStats - If desired, print any statistics.
- virtual void PrintStats() {
- }
+ virtual void PrintStats() {}
// Support isa/cast/dyn_cast
static bool classof(const ASTConsumer *) { return true; }
diff --git a/include/clang/Analysis/PathDiagnostic.h b/include/clang/Analysis/PathDiagnostic.h
index a08afe2bb90b..efc66776d7ca 100644
--- a/include/clang/Analysis/PathDiagnostic.h
+++ b/include/clang/Analysis/PathDiagnostic.h
@@ -43,8 +43,18 @@ class Preprocessor;
class PathDiagnosticClient : public DiagnosticClient {
public:
PathDiagnosticClient() {}
- virtual ~PathDiagnosticClient() {}
- virtual void SetPreprocessor(Preprocessor *PP) {}
+
+ virtual ~PathDiagnosticClient() {};
+
+ virtual void
+ FlushDiagnostics(llvm::SmallVectorImpl<std::string> *FilesMade = 0) = 0;
+
+ void FlushDiagnostics(llvm::SmallVectorImpl<std::string> &FilesMade) {
+ FlushDiagnostics(&FilesMade);
+ }
+
+ virtual llvm::StringRef getName() const = 0;
+
virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
const DiagnosticInfo &Info);
virtual void HandlePathDiagnostic(const PathDiagnostic* D) = 0;
diff --git a/include/clang/Analysis/PathSensitive/AnalysisManager.h b/include/clang/Analysis/PathSensitive/AnalysisManager.h
index 1a64f56ee8a4..488334623b34 100644
--- a/include/clang/Analysis/PathSensitive/AnalysisManager.h
+++ b/include/clang/Analysis/PathSensitive/AnalysisManager.h
@@ -66,6 +66,8 @@ public:
VisualizeEGDot(vizdot), VisualizeEGUbi(vizubi), PurgeDead(purge),
EagerlyAssume(eager), TrimGraph(trim) {}
+ ~AnalysisManager() { FlushDiagnostics(); }
+
void ClearContexts() {
LocCtxMgr.clear();
AnaCtxMgr.clear();
@@ -98,6 +100,11 @@ public:
virtual PathDiagnosticClient *getPathDiagnosticClient() {
return PD.get();
}
+
+ void FlushDiagnostics() {
+ if (PD.get())
+ PD->FlushDiagnostics();
+ }
bool shouldVisualizeGraphviz() const { return VisualizeEGDot; }
diff --git a/include/clang/Analysis/PathSensitive/BugType.h b/include/clang/Analysis/PathSensitive/BugType.h
index 46b3edd3172e..242b8e9afebe 100644
--- a/include/clang/Analysis/PathSensitive/BugType.h
+++ b/include/clang/Analysis/PathSensitive/BugType.h
@@ -64,10 +64,10 @@ protected:
const std::string desc;
public:
BuiltinBug(GRExprEngine *eng, const char* n, const char* d)
- : BugType(n, "Logic errors"), Eng(*eng), desc(d) {}
+ : BugType(n, "Logic error"), Eng(*eng), desc(d) {}
BuiltinBug(GRExprEngine *eng, const char* n)
- : BugType(n, "Logic errors"), Eng(*eng), desc(n) {}
+ : BugType(n, "Logic error"), Eng(*eng), desc(n) {}
const std::string &getDescription() const { return desc; }
diff --git a/include/clang/Analysis/PathSensitive/Checker.h b/include/clang/Analysis/PathSensitive/Checker.h
index 3bef08d7545f..4fc0a617ecf0 100644
--- a/include/clang/Analysis/PathSensitive/Checker.h
+++ b/include/clang/Analysis/PathSensitive/Checker.h
@@ -116,12 +116,13 @@ private:
void GR_VisitBind(ExplodedNodeSet &Dst,
GRStmtNodeBuilder &Builder, GRExprEngine &Eng,
- const Stmt *stmt, ExplodedNode *Pred, void *tag,
+ const Stmt *AssignE,
+ const Stmt *StoreE, ExplodedNode *Pred, void *tag,
SVal location, SVal val,
bool isPrevisit) {
CheckerContext C(Dst, Builder, Eng, Pred, tag, isPrevisit);
assert(isPrevisit && "Only previsit supported for now.");
- PreVisitBind(C, stmt, location, val);
+ PreVisitBind(C, AssignE, StoreE, location, val);
}
public:
@@ -135,7 +136,8 @@ public:
return Pred;
}
- virtual void PreVisitBind(CheckerContext &C, const Stmt *ST,
+ virtual void PreVisitBind(CheckerContext &C,
+ const Stmt *AssignE, const Stmt *StoreE,
SVal location, SVal val) {}
virtual ExplodedNode *CheckType(QualType T, ExplodedNode *Pred,
diff --git a/include/clang/Analysis/PathSensitive/Checkers/UndefinedAssignmentChecker.h b/include/clang/Analysis/PathSensitive/Checkers/UndefinedAssignmentChecker.h
index 7fee5011c46d..13437eb2ac03 100644
--- a/include/clang/Analysis/PathSensitive/Checkers/UndefinedAssignmentChecker.h
+++ b/include/clang/Analysis/PathSensitive/Checkers/UndefinedAssignmentChecker.h
@@ -24,7 +24,8 @@ class UndefinedAssignmentChecker
public:
UndefinedAssignmentChecker() : BT(0) {}
static void *getTag();
- virtual void PreVisitBind(CheckerContext &C, const Stmt *S, SVal location,
+ virtual void PreVisitBind(CheckerContext &C, const Stmt *AssignE,
+ const Stmt *StoreE, SVal location,
SVal val);
};
}
diff --git a/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Analysis/PathSensitive/GRExprEngine.h
index 2f2a11a83cea..25e47038d72c 100644
--- a/include/clang/Analysis/PathSensitive/GRExprEngine.h
+++ b/include/clang/Analysis/PathSensitive/GRExprEngine.h
@@ -412,7 +412,8 @@ protected:
void CheckerVisit(Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
bool isPrevisit);
- void CheckerVisitBind(Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
+ void CheckerVisitBind(const Stmt *AssignE, const Stmt *StoreE,
+ ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
SVal location, SVal val, bool isPrevisit);
@@ -566,7 +567,8 @@ protected:
/// 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, Stmt* Ex, ExplodedNode* Pred,
+ void EvalBind(ExplodedNodeSet& Dst, Stmt *AssignE,
+ Stmt* StoreE, ExplodedNode* Pred,
const GRState* St, SVal location, SVal Val,
bool atDeclInit = false);
@@ -578,14 +580,10 @@ public:
const GRState* St, SVal location,
const void *tag = 0);
-
- void EvalStore(ExplodedNodeSet& Dst, Expr* E, ExplodedNode* Pred, const GRState* St,
- SVal TargetLV, SVal Val, const void *tag = 0);
-
- void EvalStore(ExplodedNodeSet& Dst, Expr* E, Expr* StoreE, ExplodedNode* Pred,
+ void EvalStore(ExplodedNodeSet& Dst, Expr* AssignE, Expr* StoreE,
+ ExplodedNode* Pred,
const GRState* St, SVal TargetLV, SVal Val,
const void *tag = 0);
-
};
} // end clang namespace
diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h
index 005aab3fa6a1..77a2079b766d 100644
--- a/include/clang/Basic/Diagnostic.h
+++ b/include/clang/Basic/Diagnostic.h
@@ -769,17 +769,28 @@ class DiagnosticClient {
public:
virtual ~DiagnosticClient();
- /// setLangOptions - This is set by clients of diagnostics when they know the
- /// language parameters of the diagnostics that may be sent through. Note
- /// that this can change over time if a DiagClient has multiple languages sent
- /// through it. It may also be set to null (e.g. when processing command line
- /// options).
- virtual void setLangOptions(const LangOptions *LO) {}
+ /// BeginSourceFile - Callback to inform the diagnostic client that processing
+ /// of a source file is beginning.
+ ///
+ /// Note that diagnostics may be emitted outside the processing of a source
+ /// file, for example during the parsing of command line options. However,
+ /// diagnostics with source range information are required to only be emitted
+ /// in between BeginSourceFile() and EndSourceFile().
+ ///
+ /// \arg LO - The language options for the source file being processed.
+ /// \arg PP - The preprocessor object being used for the source; this optional
+ /// and may not be present, for example when processing AST source files.
+ virtual void BeginSourceFile(const LangOptions &LangOpts) {}
+
+ /// EndSourceFile - Callback to inform the diagnostic client that processing
+ /// of a source file has ended. The diagnostic client should assume that any
+ /// objects made available via \see BeginSourceFile() are inaccessible.
+ virtual void EndSourceFile() {}
/// IncludeInDiagnosticCounts - This method (whose default implementation
- /// returns true) indicates whether the diagnostics handled by this
- /// DiagnosticClient should be included in the number of diagnostics
- /// reported by Diagnostic.
+ /// returns true) indicates whether the diagnostics handled by this
+ /// DiagnosticClient should be included in the number of diagnostics reported
+ /// by Diagnostic.
virtual bool IncludeInDiagnosticCounts() const;
/// HandleDiagnostic - Handle this diagnostic, reporting it to the user or
diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td
index c34bdc111c90..8cfdd4095027 100644
--- a/include/clang/Basic/DiagnosticGroups.td
+++ b/include/clang/Basic/DiagnosticGroups.td
@@ -23,6 +23,7 @@ def : DiagGroup<"address">;
def : DiagGroup<"aggregate-return">;
def : DiagGroup<"attributes">;
def : DiagGroup<"bad-function-cast">;
+def : DiagGroup<"c++-compat">;
def : DiagGroup<"cast-align">;
def : DiagGroup<"cast-qual">;
def : DiagGroup<"char-align">;
@@ -47,6 +48,7 @@ def : DiagGroup<"invalid-pch">;
def : DiagGroup<"missing-braces">;
def : DiagGroup<"missing-declarations">;
def : DiagGroup<"missing-format-attribute">;
+def : DiagGroup<"missing-include-dirs">;
def : DiagGroup<"missing-noreturn">;
def MultiChar : DiagGroup<"multichar">;
def : DiagGroup<"nested-externs">;
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index db8d580a2cd7..e173cffdfd2b 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -166,9 +166,6 @@ def err_use_of_tag_name_without_tag : Error<
"use of tagged type %0 without '%1' tag">;
def err_expected_ident_in_using : Error<
"expected an identifier in using directive">;
-def err_using_decl_can_not_refer_to_template_spec : Error<
- "using declaration can not refer to template specialization">;
-
/// Objective-C parser diagnostics
def err_objc_no_attributes_on_category : Error<
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 99fddb581088..2309908df7b4 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -107,8 +107,14 @@ def err_using_decl_nested_name_specifier_is_not_a_base_class : Error<
"using declaration refers into '%0', which is not a base class of %1">;
def err_using_decl_can_not_refer_to_class_member : Error<
"using declaration can not refer to class member">;
- def err_using_decl_can_not_refer_to_namespace : Error<
+def err_using_decl_can_not_refer_to_namespace : Error<
"using declaration can not refer to namespace">;
+def err_using_decl_constructor : Error<
+ "using declaration can not refer to a constructor">;
+def err_using_decl_destructor : Error<
+ "using declaration can not refer to a destructor">;
+def err_using_decl_template_id : Error<
+ "using declaration can not refer to a template specialization">;
def err_invalid_thread : Error<
"'__thread' is only allowed on variable declarations">;
@@ -512,6 +518,8 @@ def err_init_reference_member_uninitialized : Error<
"reference member of type %0 uninitialized">;
def note_uninit_reference_member : Note<
"uninitialized reference member is here">;
+def warn_field_is_uninit : Warning<"field is uninitialized when used here">,
+ InGroup<DiagGroup<"uninitialized">>;
// C++0x decltype
def err_cannot_determine_declared_type_of_overloaded_function : Error<
@@ -1529,6 +1537,12 @@ def err_typecheck_vector_comparison : Error<
def err_typecheck_assign_const : Error<"read-only variable is not assignable">;
def err_stmtexpr_file_scope : Error<
"statement expression not allowed at file scope">;
+def warn_mixed_sign_comparison : Warning<
+ "comparison of integers of different signs: %0 and %1">,
+ InGroup<DiagGroup<"sign-compare">>;
+def warn_mixed_sign_conditional : Warning<
+ "operands of ? are integers of different signs: %0 and %1">,
+ InGroup<DiagGroup<"sign-compare">>;
def err_invalid_this_use : Error<
"invalid use of 'this' outside of a nonstatic member function">;
diff --git a/include/clang/Frontend/ASTConsumers.h b/include/clang/Frontend/ASTConsumers.h
index f59a0a7d481e..742813c66907 100644
--- a/include/clang/Frontend/ASTConsumers.h
+++ b/include/clang/Frontend/ASTConsumers.h
@@ -28,7 +28,6 @@ class ASTConsumer;
class Diagnostic;
class FileManager;
class Preprocessor;
-class PreprocessorFactory;
class CompileOptions;
class LangOptions;
@@ -86,10 +85,11 @@ ASTConsumer *CreateBackendConsumer(BackendAction Action,
llvm::raw_ostream *OS,
llvm::LLVMContext& C);
-// HTML printer: uses the rewriter to convert source code to HTML with
-// syntax highlighting suitable for viewing in a web-browser.
-ASTConsumer* CreateHTMLPrinter(llvm::raw_ostream *OS, Diagnostic &D,
- Preprocessor *PP, PreprocessorFactory *PPF);
+/// CreateHTMLPrinter - Create an AST consumer which rewrites source code to
+/// HTML with syntax highlighting suitable for viewing in a web-browser.
+ASTConsumer *CreateHTMLPrinter(llvm::raw_ostream *OS, Preprocessor &PP,
+ bool SyntaxHighlight = true,
+ bool HighlightMacros = true);
// PCH generator: generates a precompiled header file; this file can be
// used later with the PCHReader (clang-cc option -include-pch)
diff --git a/include/clang/Frontend/AnalysisConsumer.h b/include/clang/Frontend/AnalysisConsumer.h
index 0e4b09bd2a12..34054a7aa00e 100644
--- a/include/clang/Frontend/AnalysisConsumer.h
+++ b/include/clang/Frontend/AnalysisConsumer.h
@@ -19,7 +19,6 @@ namespace clang {
class ASTConsumer;
class Diagnostic;
class Preprocessor;
-class PreprocessorFactory;
class LangOptions;
/// Analysis - Set of available source code analyses.
@@ -69,9 +68,7 @@ struct AnalyzerOptions {
/// CreateAnalysisConsumer - Creates an ASTConsumer to run various code
/// analysis passes. (The set of analyses run is controlled by command-line
/// options.)
-ASTConsumer* CreateAnalysisConsumer(Diagnostic &diags, Preprocessor *pp,
- PreprocessorFactory *ppf,
- const LangOptions &lopts,
+ASTConsumer* CreateAnalysisConsumer(const Preprocessor &pp,
const std::string &output,
const AnalyzerOptions& Opts);
diff --git a/include/clang/Frontend/InitPreprocessor.h b/include/clang/Frontend/InitPreprocessor.h
index b29ee2728a86..415acea79a26 100644
--- a/include/clang/Frontend/InitPreprocessor.h
+++ b/include/clang/Frontend/InitPreprocessor.h
@@ -29,7 +29,16 @@ class PreprocessorInitOptions {
std::vector<std::pair<std::string, bool/*isPTH*/> > Includes;
std::vector<std::string> MacroIncludes;
+ unsigned UsePredefines : 1; /// Initialize the preprocessor with the compiler
+ /// and target specific predefines.
+
public:
+ PreprocessorInitOptions() : UsePredefines(true) {}
+
+ bool getUsePredefines() const { return UsePredefines; }
+ void setUsePredefines(bool Value) {
+ UsePredefines = Value;
+ }
void addMacroDef(const std::string &Name) {
Macros.push_back(std::make_pair(Name, false));
@@ -60,11 +69,10 @@ public:
};
/// InitializePreprocessor - Initialize the preprocessor getting it and the
-/// environment ready to process a single file. This returns true on error.
+/// environment ready to process a single file.
///
-bool InitializePreprocessor(Preprocessor &PP,
- const PreprocessorInitOptions& InitOptions,
- bool undef_macros);
+void InitializePreprocessor(Preprocessor &PP,
+ const PreprocessorInitOptions& InitOptions);
} // end namespace clang
diff --git a/include/clang/Frontend/PathDiagnosticClients.h b/include/clang/Frontend/PathDiagnosticClients.h
index 8cb6898d7598..98831ba37fe3 100644
--- a/include/clang/Frontend/PathDiagnosticClients.h
+++ b/include/clang/Frontend/PathDiagnosticClients.h
@@ -22,33 +22,13 @@ namespace clang {
class PathDiagnosticClient;
class Preprocessor;
-class PreprocessorFactory;
-
-class PathDiagnosticClientFactory {
-public:
- PathDiagnosticClientFactory() {}
- virtual ~PathDiagnosticClientFactory() {}
-
- virtual const char *getName() const = 0;
-
- virtual PathDiagnosticClient*
- createPathDiagnosticClient(llvm::SmallVectorImpl<std::string> *FilesMade) = 0;
-};
PathDiagnosticClient*
-CreateHTMLDiagnosticClient(const std::string& prefix, Preprocessor* PP = 0,
- PreprocessorFactory* PPF = 0,
- llvm::SmallVectorImpl<std::string>* FilesMade = 0);
-
-PathDiagnosticClientFactory*
-CreateHTMLDiagnosticClientFactory(const std::string& prefix,
- Preprocessor* PP = 0,
- PreprocessorFactory* PPF = 0);
+CreateHTMLDiagnosticClient(const std::string& prefix, const Preprocessor &PP);
PathDiagnosticClient*
-CreatePlistDiagnosticClient(const std::string& prefix, Preprocessor* PP,
- PreprocessorFactory* PPF,
- PathDiagnosticClientFactory *PF = 0);
+CreatePlistDiagnosticClient(const std::string& prefix, const Preprocessor &PP,
+ PathDiagnosticClient *SubPD = 0);
} // end clang namespace
#endif
diff --git a/include/clang/Frontend/TextDiagnosticPrinter.h b/include/clang/Frontend/TextDiagnosticPrinter.h
index 98e5a75c65b9..3c5c6267c632 100644
--- a/include/clang/Frontend/TextDiagnosticPrinter.h
+++ b/include/clang/Frontend/TextDiagnosticPrinter.h
@@ -39,8 +39,12 @@ class TextDiagnosticPrinter : public DiagnosticClient {
public:
TextDiagnosticPrinter(llvm::raw_ostream &os, const DiagnosticOptions &diags);
- void setLangOptions(const LangOptions *LO) {
- LangOpts = LO;
+ void BeginSourceFile(const LangOptions &LO) {
+ LangOpts = &LO;
+ }
+
+ void EndSourceFile() {
+ LangOpts = 0;
}
void PrintIncludeStack(SourceLocation Loc, const SourceManager &SM);
diff --git a/include/clang/Frontend/Utils.h b/include/clang/Frontend/Utils.h
index 9cbcf8e3e93e..3c670286545b 100644
--- a/include/clang/Frontend/Utils.h
+++ b/include/clang/Frontend/Utils.h
@@ -30,7 +30,6 @@ class Diagnostic;
class ASTConsumer;
class IdentifierTable;
class SourceManager;
-class PreprocessorFactory;
class LangOptions;
class Decl;
class Stmt;
diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h
index 35960ff328a6..2783716b89ff 100644
--- a/include/clang/Lex/Preprocessor.h
+++ b/include/clang/Lex/Preprocessor.h
@@ -96,7 +96,7 @@ class Preprocessor {
/// Identifiers - This is mapping/lookup information for all identifiers in
/// the program, including program keywords.
- IdentifierTable Identifiers;
+ mutable IdentifierTable Identifiers;
/// Selectors - This table contains all the selectors in the program. Unlike
/// IdentifierTable above, this table *isn't* populated by the preprocessor.
@@ -296,12 +296,8 @@ public:
/// pointers is preferred unless the identifier is already available as a
/// string (this avoids allocation and copying of memory to construct an
/// std::string).
- IdentifierInfo *getIdentifierInfo(const char *NameStart,
- const char *NameEnd) {
- return &Identifiers.get(NameStart, NameEnd);
- }
- IdentifierInfo *getIdentifierInfo(const char *NameStr) {
- return getIdentifierInfo(NameStr, NameStr+strlen(NameStr));
+ IdentifierInfo *getIdentifierInfo(llvm::StringRef Name) const {
+ return &Identifiers.get(Name);
}
/// AddPragmaHandler - Add the specified pragma handler to the preprocessor.
@@ -583,7 +579,7 @@ public:
/// LookUpIdentifierInfo - Given a tok::identifier token, look up the
/// identifier information for the token and install it into the token.
IdentifierInfo *LookUpIdentifierInfo(Token &Identifier,
- const char *BufPtr = 0);
+ const char *BufPtr = 0) const;
/// HandleIdentifier - This callback is invoked when the lexer reads an
/// identifier and has filled in the tokens IdentifierInfo member. This
@@ -831,14 +827,6 @@ public:
void HandleComment(SourceRange Comment);
};
-/// PreprocessorFactory - A generic factory interface for lazily creating
-/// Preprocessor objects on-demand when they are needed.
-class PreprocessorFactory {
-public:
- virtual ~PreprocessorFactory();
- virtual Preprocessor* CreatePreprocessor() = 0;
-};
-
/// \brief Abstract base class that describes a handler that will receive
/// source ranges for each of the comments encountered in the source file.
class CommentHandler {
diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h
index 073365dcede3..657a14fff082 100644
--- a/include/clang/Parse/Action.h
+++ b/include/clang/Parse/Action.h
@@ -1174,14 +1174,41 @@ public:
return DeclPtrTy();
}
- /// ActOnUsingDirective - This is called when using-directive is parsed.
+ /// \brief Parsed a C++ using-declaration.
+ ///
+ /// This callback will be invoked when the parser has parsed a C++
+ /// using-declaration, e.g.,
+ ///
+ /// \code
+ /// namespace std {
+ /// template<typename T, typename Alloc> class vector;
+ /// }
+ ///
+ /// using std::vector; // using-declaration here
+ /// \endcode
+ ///
+ /// \param CurScope the scope in which this using declaration was parsed.
+ ///
+ /// \param AS the currently-active access specifier.
+ ///
+ /// \param UsingLoc the location of the 'using' keyword.
+ ///
+ /// \param SS the nested-name-specifier that precedes the name.
+ ///
+ /// \param Name the name to which the using declaration refers.
+ ///
+ /// \param AttrList attributes applied to this using declaration, if any.
+ ///
+ /// \param IsTypeName whether this using declaration started with the
+ /// 'typename' keyword. FIXME: This will eventually be split into a
+ /// separate action.
+ ///
+ /// \returns a representation of the using declaration.
virtual DeclPtrTy ActOnUsingDeclaration(Scope *CurScope,
AccessSpecifier AS,
SourceLocation UsingLoc,
const CXXScopeSpec &SS,
- SourceLocation IdentLoc,
- IdentifierInfo *TargetName,
- OverloadedOperatorKind Op,
+ UnqualifiedId &Name,
AttributeList *AttrList,
bool IsTypeName);
diff --git a/include/clang/Parse/DeclSpec.h b/include/clang/Parse/DeclSpec.h
index dccb8bcfeb9a..d539508e973b 100644
--- a/include/clang/Parse/DeclSpec.h
+++ b/include/clang/Parse/DeclSpec.h
@@ -131,6 +131,9 @@ private:
// friend-specifier
bool Friend_specified : 1;
+ // constexpr-specifier
+ bool Constexpr_specified : 1;
+
/// TypeRep - This contains action-specific information about a specific TST.
/// For example, for a typedef or struct, it might contain the declaration for
/// these.
@@ -155,7 +158,7 @@ private:
SourceLocation TSWLoc, TSCLoc, TSSLoc, TSTLoc;
SourceLocation TQ_constLoc, TQ_restrictLoc, TQ_volatileLoc;
SourceLocation FS_inlineLoc, FS_virtualLoc, FS_explicitLoc;
- SourceLocation FriendLoc;
+ SourceLocation FriendLoc, ConstexprLoc;
DeclSpec(const DeclSpec&); // DO NOT IMPLEMENT
void operator=(const DeclSpec&); // DO NOT IMPLEMENT
@@ -174,6 +177,7 @@ public:
FS_virtual_specified(false),
FS_explicit_specified(false),
Friend_specified(false),
+ Constexpr_specified(false),
TypeRep(0),
AttrList(0),
ProtocolQualifiers(0),
@@ -309,9 +313,15 @@ public:
bool SetFriendSpec(SourceLocation Loc, const char *&PrevSpec,
unsigned &DiagID);
+ bool SetConstexprSpec(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID);
+
bool isFriendSpecified() const { return Friend_specified; }
SourceLocation getFriendSpecLoc() const { return FriendLoc; }
+ bool isConstexprSpecified() const { return Constexpr_specified; }
+ SourceLocation getConstexprSpecLoc() const { return ConstexprLoc; }
+
/// AddAttributes - contatenates two attribute lists.
/// The GCC attribute syntax allows for the following:
///
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index f34d469d9823..1ca92edc9a8b 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -1321,13 +1321,6 @@ private:
UnqualifiedId &Result);
//===--------------------------------------------------------------------===//
- // C++ 13.5: Overloaded operators [over.oper]
- // EndLoc, if non-NULL, is filled with the location of the last token of
- // the ID.
- OverloadedOperatorKind TryParseOperatorFunctionId(SourceLocation *EndLoc = 0);
- TypeTy *ParseConversionFunctionId(SourceLocation *EndLoc = 0);
-
- //===--------------------------------------------------------------------===//
// C++ 14: Templates [temp]
typedef llvm::SmallVector<DeclPtrTy, 4> TemplateParameterList;
diff --git a/include/clang/Rewrite/HTMLRewrite.h b/include/clang/Rewrite/HTMLRewrite.h
index f77e0c61c54c..88caf85e6010 100644
--- a/include/clang/Rewrite/HTMLRewrite.h
+++ b/include/clang/Rewrite/HTMLRewrite.h
@@ -23,7 +23,6 @@ namespace clang {
class Rewriter;
class RewriteBuffer;
class Preprocessor;
-class PreprocessorFactory;
namespace html {
@@ -68,14 +67,14 @@ namespace html {
/// SyntaxHighlight - Relex the specified FileID and annotate the HTML with
/// information about keywords, comments, etc.
- void SyntaxHighlight(Rewriter &R, FileID FID, Preprocessor &PP);
+ void SyntaxHighlight(Rewriter &R, FileID FID, const Preprocessor &PP);
/// HighlightMacros - This uses the macro table state from the end of the
/// file, to reexpand macros and insert (into the HTML) information about the
/// macro expansions. This won't be perfectly perfect, but it will be
/// reasonably close.
- void HighlightMacros(Rewriter &R, FileID FID, Preprocessor &PP);
- void HighlightMacros(Rewriter &R, FileID FID, PreprocessorFactory &PPF);
+ void HighlightMacros(Rewriter &R, FileID FID, const Preprocessor &PP);
+
} // end html namespace
} // end clang namespace
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index aef3d2989415..8562249479ca 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -1374,7 +1374,7 @@ QualType ASTContext::getMemberPointerType(QualType T, const Type *Cls) {
// If the pointee or class type isn't canonical, this won't be a canonical
// type either, so fill in the canonical type field.
QualType Canonical;
- if (!T.isCanonical()) {
+ if (!T.isCanonical() || !Cls->isCanonicalUnqualified()) {
Canonical = getMemberPointerType(getCanonicalType(T),getCanonicalType(Cls));
// Get the new insert position for the node we care about.
@@ -1395,7 +1395,8 @@ QualType ASTContext::getConstantArrayType(QualType EltTy,
const llvm::APInt &ArySizeIn,
ArrayType::ArraySizeModifier ASM,
unsigned EltTypeQuals) {
- assert((EltTy->isDependentType() || EltTy->isConstantSizeType()) &&
+ assert((EltTy->isDependentType() ||
+ EltTy->isIncompleteType() || EltTy->isConstantSizeType()) &&
"Constant array of VLAs is illegal!");
// Convert the array size into a canonical width matching the pointer size for
diff --git a/lib/AST/DeclarationName.cpp b/lib/AST/DeclarationName.cpp
index 56a597570dd0..8664c508615f 100644
--- a/lib/AST/DeclarationName.cpp
+++ b/lib/AST/DeclarationName.cpp
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/DeclarationName.h"
#include "clang/AST/Type.h"
+#include "clang/AST/TypeOrdering.h"
#include "clang/AST/Decl.h"
#include "clang/Basic/IdentifierTable.h"
#include "llvm/ADT/DenseMap.h"
@@ -49,11 +50,50 @@ public:
};
bool operator<(DeclarationName LHS, DeclarationName RHS) {
- if (IdentifierInfo *LhsId = LHS.getAsIdentifierInfo())
- if (IdentifierInfo *RhsId = RHS.getAsIdentifierInfo())
- return LhsId->getName() < RhsId->getName();
-
- return LHS.getAsOpaqueInteger() < RHS.getAsOpaqueInteger();
+ if (LHS.getNameKind() != RHS.getNameKind())
+ return LHS.getNameKind() < RHS.getNameKind();
+
+ switch (LHS.getNameKind()) {
+ case DeclarationName::Identifier:
+ return LHS.getAsIdentifierInfo()->getName() <
+ RHS.getAsIdentifierInfo()->getName();
+
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector: {
+ Selector LHSSelector = LHS.getObjCSelector();
+ Selector RHSSelector = RHS.getObjCSelector();
+ for (unsigned I = 0,
+ N = std::min(LHSSelector.getNumArgs(), RHSSelector.getNumArgs());
+ I != N; ++I) {
+ IdentifierInfo *LHSId = LHSSelector.getIdentifierInfoForSlot(I);
+ IdentifierInfo *RHSId = RHSSelector.getIdentifierInfoForSlot(I);
+ if (!LHSId || !RHSId)
+ return LHSId && !RHSId;
+
+ switch (LHSId->getName().compare(RHSId->getName())) {
+ case -1: return true;
+ case 1: return false;
+ default: break;
+ }
+ }
+
+ return LHSSelector.getNumArgs() < RHSSelector.getNumArgs();
+ }
+
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXConversionFunctionName:
+ return QualTypeOrdering()(LHS.getCXXNameType(), RHS.getCXXNameType());
+
+ case DeclarationName::CXXOperatorName:
+ return LHS.getCXXOverloadedOperator() < RHS.getCXXOverloadedOperator();
+
+ case DeclarationName::CXXUsingDirective:
+ return false;
+ }
+
+ return false;
}
} // end namespace clang
diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp
index 0b159c3a7bd8..021c53e9514f 100644
--- a/lib/AST/RecordLayoutBuilder.cpp
+++ b/lib/AST/RecordLayoutBuilder.cpp
@@ -174,9 +174,24 @@ void ASTRecordLayoutBuilder::LayoutVirtualBase(const CXXRecordDecl *RD) {
LayoutBaseNonVirtually(RD, true);
}
-void ASTRecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *RD,
+uint64_t ASTRecordLayoutBuilder::getBaseOffset(const CXXRecordDecl *Base) {
+ for (size_t i = 0; i < Bases.size(); ++i) {
+ if (Bases[i].first == Base)
+ return Bases[i].second;
+ }
+ for (size_t i = 0; i < VBases.size(); ++i) {
+ if (VBases[i].first == Base)
+ return VBases[i].second;
+ }
+ assert(0 && "missing base");
+ return 0;
+}
+
+
+void ASTRecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *Class,
+ const CXXRecordDecl *RD,
const CXXRecordDecl *PB,
- int64_t Offset,
+ uint64_t Offset,
llvm::SmallSet<const CXXRecordDecl*, 32> &mark,
llvm::SmallSet<const CXXRecordDecl*, 32> &IndirectPrimary) {
for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
@@ -185,20 +200,7 @@ void ASTRecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *RD,
"Cannot layout class with dependent bases.");
const CXXRecordDecl *Base =
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
-#if 0
- const ASTRecordLayout &L = Ctx.getASTRecordLayout(Base);
- const CXXRecordDecl *PB = L.getPrimaryBase();
- if (PB && L.getPrimaryBaseWasVirtual()
- && IndirectPrimary.count(PB)) {
- int64_t BaseOffset;
- // FIXME: calculate this.
- BaseOffset = (1<<63) | (1<<31);
- VBases.push_back(PB);
- VBaseOffsets.push_back(BaseOffset);
- }
-#endif
- int64_t BaseOffset = Offset;;
- // FIXME: Calculate BaseOffset.
+ uint64_t BaseOffset = Offset;
if (i->isVirtual()) {
if (Base == PB) {
// Only lay things out once.
@@ -220,11 +222,20 @@ void ASTRecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *RD,
LayoutVirtualBase(Base);
BaseOffset = VBases.back().second;
}
+ } else {
+ if (RD == Class)
+ BaseOffset = getBaseOffset(Base);
+ else {
+ const ASTRecordLayout &Layout
+ = Ctx.getASTRecordLayout(RD);
+ BaseOffset = Offset + Layout.getBaseClassOffset(Base);
+ }
}
+
if (Base->getNumVBases()) {
const ASTRecordLayout &L = Ctx.getASTRecordLayout(Base);
const CXXRecordDecl *PB = L.getPrimaryBase();
- LayoutVirtualBases(Base, PB, BaseOffset, mark, IndirectPrimary);
+ LayoutVirtualBases(Class, Base, PB, BaseOffset, mark, IndirectPrimary);
}
}
}
@@ -295,7 +306,7 @@ bool ASTRecordLayoutBuilder::canPlaceFieldAtOffset(const FieldDecl *FD,
const ASTRecordLayout &Info = Ctx.getASTRecordLayout(RD);
uint64_t NumElements = Ctx.getConstantArrayElementCount(AT);
- unsigned ElementOffset = Offset;
+ uint64_t ElementOffset = Offset;
for (uint64_t I = 0; I != NumElements; ++I) {
if (!canPlaceRecordAtOffset(RD, ElementOffset))
return false;
@@ -366,7 +377,7 @@ ASTRecordLayoutBuilder::UpdateEmptyClassOffsets(const FieldDecl *FD,
const ASTRecordLayout &Info = Ctx.getASTRecordLayout(RD);
uint64_t NumElements = Ctx.getConstantArrayElementCount(AT);
- unsigned ElementOffset = Offset;
+ uint64_t ElementOffset = Offset;
for (uint64_t I = 0; I != NumElements; ++I) {
UpdateEmptyClassOffsets(RD, ElementOffset);
@@ -419,29 +430,13 @@ uint64_t ASTRecordLayoutBuilder::LayoutBase(const CXXRecordDecl *RD) {
void ASTRecordLayoutBuilder::LayoutBaseNonVirtually(const CXXRecordDecl *RD,
bool IsVirtualBase) {
// Layout the base.
- unsigned Offset = LayoutBase(RD);
+ uint64_t Offset = LayoutBase(RD);
// Add base class offsets.
if (IsVirtualBase)
VBases.push_back(std::make_pair(RD, Offset));
else
Bases.push_back(std::make_pair(RD, Offset));
-
-#if 0
- // And now add offsets for all our primary virtual bases as well, so
- // they all have offsets.
- const ASTRecordLayout *L = &BaseInfo;
- const CXXRecordDecl *PB = L->getPrimaryBase();
- while (PB) {
- if (L->getPrimaryBaseWasVirtual()) {
- VBases.push_back(PB);
- VBaseOffsets.push_back(Size);
- }
- PB = L->getPrimaryBase();
- if (PB)
- L = &Ctx.getASTRecordLayout(PB);
- }
-#endif
}
void ASTRecordLayoutBuilder::Layout(const RecordDecl *D) {
@@ -476,7 +471,7 @@ void ASTRecordLayoutBuilder::Layout(const RecordDecl *D) {
if (RD) {
llvm::SmallSet<const CXXRecordDecl*, 32> mark;
- LayoutVirtualBases(RD, PrimaryBase, 0, mark, IndirectPrimaryBases);
+ LayoutVirtualBases(RD, RD, PrimaryBase, 0, mark, IndirectPrimaryBases);
}
// Finally, round the size of the total struct up to the alignment of the
diff --git a/lib/AST/RecordLayoutBuilder.h b/lib/AST/RecordLayoutBuilder.h
index b57b37d0df4d..077072343b1b 100644
--- a/lib/AST/RecordLayoutBuilder.h
+++ b/lib/AST/RecordLayoutBuilder.h
@@ -99,9 +99,9 @@ class ASTRecordLayoutBuilder {
void LayoutNonVirtualBases(const CXXRecordDecl *RD);
void LayoutBaseNonVirtually(const CXXRecordDecl *RD, bool IsVBase);
void LayoutVirtualBase(const CXXRecordDecl *RD);
- void LayoutVirtualBases(const CXXRecordDecl *RD, const CXXRecordDecl *PB,
- int64_t Offset,
- llvm::SmallSet<const CXXRecordDecl*, 32> &mark,
+ void LayoutVirtualBases(const CXXRecordDecl *Class, const CXXRecordDecl *RD,
+ const CXXRecordDecl *PB, uint64_t Offset,
+ llvm::SmallSet<const CXXRecordDecl*, 32> &mark,
llvm::SmallSet<const CXXRecordDecl*, 32> &IndirectPrimary);
/// canPlaceRecordAtOffset - Return whether a record (either a base class
@@ -124,6 +124,9 @@ class ASTRecordLayoutBuilder {
/// given offset.
void UpdateEmptyClassOffsets(const FieldDecl *FD, uint64_t Offset);
+ /// getBaseOffset - Get the offset of a direct base class.
+ uint64_t getBaseOffset(const CXXRecordDecl *Base);
+
/// FinishLayout - Finalize record layout. Adjust record size based on the
/// alignment.
void FinishLayout();
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 3608d34c691d..779f6808b6c1 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -550,6 +550,12 @@ bool Type::isIncompleteType() const {
// A tagged type (struct/union/enum/class) is incomplete if the decl is a
// forward declaration, but not a full definition (C99 6.2.5p22).
return !cast<TagType>(CanonicalType)->getDecl()->isDefinition();
+ case ConstantArray:
+ // An array is incomplete if its element type is incomplete
+ // (C++ [dcl.array]p1).
+ // We don't handle variable arrays (they're not allowed in C++) or
+ // dependent-sized arrays (dependent types are never treated as incomplete).
+ return cast<ArrayType>(CanonicalType)->getElementType()->isIncompleteType();
case IncompleteArray:
// An array of unknown size is an incomplete type (C99 6.2.5p22).
return true;
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp
index c71882e4d888..212fea3a6bcc 100644
--- a/lib/Analysis/GRExprEngine.cpp
+++ b/lib/Analysis/GRExprEngine.cpp
@@ -141,7 +141,8 @@ void GRExprEngine::CheckerVisit(Stmt *S, ExplodedNodeSet &Dst,
// FIXME: This is largely copy-paste from CheckerVisit(). Need to
// unify.
-void GRExprEngine::CheckerVisitBind(Stmt *S, ExplodedNodeSet &Dst,
+void GRExprEngine::CheckerVisitBind(const Stmt *AssignE, const Stmt *StoreE,
+ ExplodedNodeSet &Dst,
ExplodedNodeSet &Src,
SVal location, SVal val, bool isPrevisit) {
@@ -164,8 +165,8 @@ void GRExprEngine::CheckerVisitBind(Stmt *S, ExplodedNodeSet &Dst,
for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();
NI != NE; ++NI)
- checker->GR_VisitBind(*CurrSet, *Builder, *this, S, *NI, tag, location,
- val, isPrevisit);
+ checker->GR_VisitBind(*CurrSet, *Builder, *this, AssignE, StoreE,
+ *NI, tag, location, val, isPrevisit);
// Update which NodeSet is the current one.
PrevSet = CurrSet;
@@ -1125,7 +1126,8 @@ void GRExprEngine::VisitMemberExpr(MemberExpr* M, ExplodedNode* Pred,
/// EvalBind - Handle the semantics of binding a value to a specific location.
/// This method is used by EvalStore and (soon) VisitDeclStmt, and others.
-void GRExprEngine::EvalBind(ExplodedNodeSet& Dst, Stmt* Ex, ExplodedNode* Pred,
+void GRExprEngine::EvalBind(ExplodedNodeSet& Dst, Stmt *AssignE,
+ Stmt* StoreE, ExplodedNode* Pred,
const GRState* state, SVal location, SVal Val,
bool atDeclInit) {
@@ -1133,7 +1135,7 @@ void GRExprEngine::EvalBind(ExplodedNodeSet& Dst, Stmt* Ex, ExplodedNode* Pred,
// Do a previsit of the bind.
ExplodedNodeSet CheckedSet, Src;
Src.Add(Pred);
- CheckerVisitBind(Ex, CheckedSet, Src, location, Val, true);
+ CheckerVisitBind(AssignE, StoreE, CheckedSet, Src, location, Val, true);
for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end();
I!=E; ++I) {
@@ -1166,7 +1168,7 @@ void GRExprEngine::EvalBind(ExplodedNodeSet& Dst, Stmt* Ex, ExplodedNode* Pred,
// The next thing to do is check if the GRTransferFuncs 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.
- GRStmtNodeBuilderRef BuilderRef(Dst, *Builder, *this, *I, newState, Ex,
+ GRStmtNodeBuilderRef BuilderRef(Dst, *Builder, *this, *I, newState, StoreE,
newState != state);
getTF().EvalBind(BuilderRef, location, Val);
@@ -1179,14 +1181,16 @@ void GRExprEngine::EvalBind(ExplodedNodeSet& Dst, Stmt* Ex, ExplodedNode* Pred,
/// @param state The current simulation state
/// @param location The location to store the value
/// @param Val The value to be stored
-void GRExprEngine::EvalStore(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred,
+void GRExprEngine::EvalStore(ExplodedNodeSet& Dst, Expr *AssignE,
+ Expr* StoreE,
+ ExplodedNode* Pred,
const GRState* state, SVal location, SVal Val,
const void *tag) {
- assert (Builder && "GRStmtNodeBuilder must be defined.");
+ assert(Builder && "GRStmtNodeBuilder must be defined.");
// Evaluate the location (checks for bad dereferences).
- Pred = EvalLocation(Ex, Pred, state, location, tag);
+ Pred = EvalLocation(StoreE, Pred, state, location, tag);
if (!Pred)
return;
@@ -1199,7 +1203,7 @@ void GRExprEngine::EvalStore(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred,
SaveAndRestore<const void*> OldTag(Builder->Tag);
Builder->PointKind = ProgramPoint::PostStoreKind;
Builder->Tag = tag;
- EvalBind(Dst, Ex, Pred, state, location, Val);
+ EvalBind(Dst, AssignE, StoreE, Pred, state, location, Val);
}
void GRExprEngine::EvalLoad(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred,
@@ -1231,17 +1235,6 @@ void GRExprEngine::EvalLoad(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred,
}
}
-void GRExprEngine::EvalStore(ExplodedNodeSet& Dst, Expr* Ex, Expr* StoreE,
- ExplodedNode* Pred, const GRState* state,
- SVal location, SVal Val, const void *tag) {
-
- ExplodedNodeSet TmpDst;
- EvalStore(TmpDst, StoreE, Pred, state, location, Val, tag);
-
- for (ExplodedNodeSet::iterator I=TmpDst.begin(), E=TmpDst.end(); I!=E; ++I)
- MakeNode(Dst, Ex, *I, (*I)->getState(), ProgramPoint::PostStmtKind, tag);
-}
-
ExplodedNode* GRExprEngine::EvalLocation(Stmt* Ex, ExplodedNode* Pred,
const GRState* state, SVal location,
const void *tag) {
@@ -1402,7 +1395,7 @@ static bool EvalOSAtomicCompareAndSwap(ExplodedNodeSet& Dst,
newValueExpr->getType());
}
- Engine.EvalStore(TmpStore, theValueExpr, N, stateEqual, location,
+ Engine.EvalStore(TmpStore, NULL, theValueExpr, N, stateEqual, location,
val, OSAtomicStoreTag);
// Now bind the result of the comparison.
@@ -2147,8 +2140,8 @@ void GRExprEngine::VisitDeclStmt(DeclStmt *DS, ExplodedNode *Pred,
Builder->getCurrentBlockCount());
}
- EvalBind(Dst, DS, *I, state, loc::MemRegionVal(state->getRegion(VD, LC)),
- InitVal, true);
+ EvalBind(Dst, DS, DS, *I, state,
+ loc::MemRegionVal(state->getRegion(VD, LC)), InitVal, true);
}
else {
state = state->bindDeclWithNoInit(state->getRegion(VD, LC));
@@ -2570,7 +2563,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred,
state = state->BindExpr(U, U->isPostfix() ? V2 : Result);
// Perform the store.
- EvalStore(Dst, U, *I2, state, V1, Result);
+ EvalStore(Dst, NULL, U, *I2, state, V1, Result);
}
}
}
diff --git a/lib/Analysis/UndefinedAssignmentChecker.cpp b/lib/Analysis/UndefinedAssignmentChecker.cpp
index c5b2401f47ce..2e3ac34913ab 100644
--- a/lib/Analysis/UndefinedAssignmentChecker.cpp
+++ b/lib/Analysis/UndefinedAssignmentChecker.cpp
@@ -22,14 +22,15 @@ void *UndefinedAssignmentChecker::getTag() {
return &x;
}
-void UndefinedAssignmentChecker::PreVisitBind(CheckerContext &C,
- const Stmt *S,
+void UndefinedAssignmentChecker::PreVisitBind(CheckerContext &C,
+ const Stmt *AssignE,
+ const Stmt *StoreE,
SVal location,
SVal val) {
if (!val.isUndef())
return;
- ExplodedNode *N = C.GenerateNode(S, true);
+ ExplodedNode *N = C.GenerateNode(StoreE, true);
if (!N)
return;
@@ -40,20 +41,20 @@ void UndefinedAssignmentChecker::PreVisitBind(CheckerContext &C,
// Generate a report for this bug.
EnhancedBugReport *R = new EnhancedBugReport(*BT, BT->getName().c_str(), N);
- const Expr *ex = 0;
-
- // FIXME: This check needs to be done on the expression doing the
- // assignment, not the "store" expression.
- if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S))
- ex = B->getRHS();
- else if (const DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
- const VarDecl* VD = dyn_cast<VarDecl>(DS->getSingleDecl());
- ex = VD->getInit();
- }
- if (ex) {
- R->addRange(ex->getSourceRange());
- R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, ex);
+ if (AssignE) {
+ const Expr *ex = 0;
+
+ if (const BinaryOperator *B = dyn_cast<BinaryOperator>(AssignE))
+ ex = B->getRHS();
+ else if (const DeclStmt *DS = dyn_cast<DeclStmt>(AssignE)) {
+ const VarDecl* VD = dyn_cast<VarDecl>(DS->getSingleDecl());
+ ex = VD->getInit();
+ }
+ if (ex) {
+ R->addRange(ex->getSourceRange());
+ R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, ex);
+ }
}
C.EmitReport(R);
diff --git a/lib/Analysis/VLASizeChecker.cpp b/lib/Analysis/VLASizeChecker.cpp
index 76e4477449ed..0e731902f4bb 100644
--- a/lib/Analysis/VLASizeChecker.cpp
+++ b/lib/Analysis/VLASizeChecker.cpp
@@ -38,8 +38,8 @@ ExplodedNode *UndefSizedVLAChecker::CheckType(QualType T, ExplodedNode *Pred,
if (ExplodedNode* N = Builder.generateNode(S, state, Pred)) {
N->markAsSink();
if (!BT)
- BT = new BugType("Declare variable-length array (VLA) of undefined "
- "size", "Logic error");
+ BT = new BugType("Declared variable-length array (VLA) uses a garbage"
+ " value as its size", "Logic error");
EnhancedBugReport *R =
new EnhancedBugReport(*BT, BT->getName().c_str(), N);
@@ -81,7 +81,7 @@ ExplodedNode *ZeroSizedVLAChecker::CheckType(QualType T, ExplodedNode *Pred,
if (ExplodedNode* N = Builder.generateNode(S, zeroState, Pred)) {
N->markAsSink();
if (!BT)
- BT = new BugType("Declare variable-length array (VLA) of zero size",
+ BT = new BugType("Declared variable-length array (VLA) has zero size",
"Logic error");
EnhancedBugReport *R =
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp
index 3e854ca279b6..cf172b1a1cb6 100644
--- a/lib/CodeGen/CGCXX.cpp
+++ b/lib/CodeGen/CGCXX.cpp
@@ -291,7 +291,7 @@ CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E) {
const FunctionProtoType *FPT =
MPT->getPointeeType()->getAs<FunctionProtoType>();
const CXXRecordDecl *RD =
- cast<CXXRecordDecl>(cast<RecordType>(MPT->getClass())->getDecl());
+ cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl());
const llvm::FunctionType *FTy =
CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(RD, FPT),
@@ -810,8 +810,32 @@ llvm::Constant *CodeGenFunction::GenerateCovariantThunk(llvm::Function *Fn,
RValue RV = EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs),
Callee, CallArgs, MD);
if (nv_r || v_r) {
+ bool CanBeZero = !(ResultType->isReferenceType()
+ // FIXME: attr nonnull can't be zero either
+ /* || ResultType->hasAttr<NonNullAttr>() */ );
// Do the return result adjustment.
- RV = RValue::get(DynamicTypeAdjust(RV.getScalarVal(), nv_r, v_r));
+ if (CanBeZero) {
+ llvm::BasicBlock *NonZeroBlock = createBasicBlock();
+ llvm::BasicBlock *ZeroBlock = createBasicBlock();
+ llvm::BasicBlock *ContBlock = createBasicBlock();
+
+ const llvm::Type *Ty = RV.getScalarVal()->getType();
+ llvm::Value *Zero = llvm::Constant::getNullValue(Ty);
+ Builder.CreateCondBr(Builder.CreateICmpNE(RV.getScalarVal(), Zero),
+ NonZeroBlock, ZeroBlock);
+ EmitBlock(NonZeroBlock);
+ llvm::Value *NZ = DynamicTypeAdjust(RV.getScalarVal(), nv_r, v_r);
+ EmitBranch(ContBlock);
+ EmitBlock(ZeroBlock);
+ llvm::Value *Z = RV.getScalarVal();
+ EmitBlock(ContBlock);
+ llvm::PHINode *RVOrZero = Builder.CreatePHI(Ty);
+ RVOrZero->reserveOperandSpace(2);
+ RVOrZero->addIncoming(NZ, NonZeroBlock);
+ RVOrZero->addIncoming(Z, ZeroBlock);
+ RV = RValue::get(RVOrZero);
+ } else
+ RV = RValue::get(DynamicTypeAdjust(RV.getScalarVal(), nv_r, v_r));
}
if (!ResultType->isVoidType())
@@ -1421,6 +1445,8 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
if (FieldType->isReferenceType())
RHS = EmitReferenceBindingToExpr(RhsExpr, FieldType,
/*IsInitializer=*/true);
+ else if (FieldType->isMemberFunctionPointerType())
+ RHS = RValue::get(CGM.EmitConstantExpr(RhsExpr, FieldType, this));
else
RHS = RValue::get(EmitScalarExpr(RhsExpr, true));
EmitStoreThroughLValue(RHS, LHS, FieldType);
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index b1ceb4627712..2021ced31683 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -515,18 +515,22 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
const CXXDestructorDecl *D = ClassDecl->getDestructor(getContext());
assert(D && "EmitLocalBlockVarDecl - destructor is nul");
- CleanupScope scope(*this);
if (const ConstantArrayType *Array =
getContext().getAsConstantArrayType(Ty)) {
+ CleanupScope Scope(*this);
QualType BaseElementTy = getContext().getBaseElementType(Array);
const llvm::Type *BasePtr = ConvertType(BaseElementTy);
BasePtr = llvm::PointerType::getUnqual(BasePtr);
llvm::Value *BaseAddrPtr =
Builder.CreateBitCast(DeclPtr, BasePtr);
EmitCXXAggrDestructorCall(D, Array, BaseAddrPtr);
- }
- else
+
+ // Make sure to jump to the exit block.
+ EmitBranch(Scope.getCleanupExitBlock());
+ } else {
+ CleanupScope Scope(*this);
EmitCXXDestructorCall(D, Dtor_Complete, DeclPtr);
+ }
}
}
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index 88beadf33140..4be341311ce4 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -665,8 +665,9 @@ llvm::Value* CodeGenFunction::EmitVAListRef(const Expr* E) {
return EmitLValue(E).getAddress();
}
-void CodeGenFunction::PushCleanupBlock(llvm::BasicBlock *CleanupBlock) {
- CleanupEntries.push_back(CleanupEntry(CleanupBlock));
+void CodeGenFunction::PushCleanupBlock(llvm::BasicBlock *CleanupEntryBlock,
+ llvm::BasicBlock *CleanupExitBlock) {
+ CleanupEntries.push_back(CleanupEntry(CleanupEntryBlock, CleanupExitBlock));
}
void CodeGenFunction::EmitCleanupBlocks(size_t OldCleanupStackSize) {
@@ -680,7 +681,7 @@ void CodeGenFunction::EmitCleanupBlocks(size_t OldCleanupStackSize) {
CodeGenFunction::CleanupBlockInfo CodeGenFunction::PopCleanupBlock() {
CleanupEntry &CE = CleanupEntries.back();
- llvm::BasicBlock *CleanupBlock = CE.CleanupBlock;
+ llvm::BasicBlock *CleanupEntryBlock = CE.CleanupEntryBlock;
std::vector<llvm::BasicBlock *> Blocks;
std::swap(Blocks, CE.Blocks);
@@ -711,10 +712,11 @@ CodeGenFunction::CleanupBlockInfo CodeGenFunction::PopCleanupBlock() {
}
}
- llvm::BasicBlock *SwitchBlock = 0;
+ llvm::BasicBlock *SwitchBlock = CE.CleanupExitBlock;
llvm::BasicBlock *EndBlock = 0;
if (!BranchFixups.empty()) {
- SwitchBlock = createBasicBlock("cleanup.switch");
+ if (!SwitchBlock)
+ SwitchBlock = createBasicBlock("cleanup.switch");
EndBlock = createBasicBlock("cleanup.end");
llvm::BasicBlock *CurBB = Builder.GetInsertBlock();
@@ -745,7 +747,7 @@ CodeGenFunction::CleanupBlockInfo CodeGenFunction::PopCleanupBlock() {
llvm::BasicBlock *Dest = BI->getSuccessor(0);
// Fixup the branch instruction to point to the cleanup block.
- BI->setSuccessor(0, CleanupBlock);
+ BI->setSuccessor(0, CleanupEntryBlock);
if (CleanupEntries.empty()) {
llvm::ConstantInt *ID;
@@ -802,7 +804,7 @@ CodeGenFunction::CleanupBlockInfo CodeGenFunction::PopCleanupBlock() {
BlockScopes.erase(Blocks[i]);
}
- return CleanupBlockInfo(CleanupBlock, SwitchBlock, EndBlock);
+ return CleanupBlockInfo(CleanupEntryBlock, SwitchBlock, EndBlock);
}
void CodeGenFunction::EmitCleanupBlock() {
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 9bb219642ab4..fe8113e95332 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -108,11 +108,12 @@ public:
/// PushCleanupBlock - Push a new cleanup entry on the stack and set the
/// passed in block as the cleanup block.
- void PushCleanupBlock(llvm::BasicBlock *CleanupBlock);
+ void PushCleanupBlock(llvm::BasicBlock *CleanupEntryBlock,
+ llvm::BasicBlock *CleanupExitBlock = 0);
/// CleanupBlockInfo - A struct representing a popped cleanup block.
struct CleanupBlockInfo {
- /// CleanupBlock - the cleanup block
+ /// CleanupEntryBlock - the cleanup entry block
llvm::BasicBlock *CleanupBlock;
/// SwitchBlock - the block (if any) containing the switch instruction used
@@ -138,17 +139,24 @@ public:
class CleanupScope {
CodeGenFunction& CGF;
llvm::BasicBlock *CurBB;
- llvm::BasicBlock *CleanupBB;
-
+ llvm::BasicBlock *CleanupEntryBB;
+ llvm::BasicBlock *CleanupExitBB;
+
public:
CleanupScope(CodeGenFunction &cgf)
- : CGF(cgf), CurBB(CGF.Builder.GetInsertBlock()) {
- CleanupBB = CGF.createBasicBlock("cleanup");
- CGF.Builder.SetInsertPoint(CleanupBB);
+ : CGF(cgf), CurBB(CGF.Builder.GetInsertBlock()),
+ CleanupEntryBB(CGF.createBasicBlock("cleanup")), CleanupExitBB(0) {
+ CGF.Builder.SetInsertPoint(CleanupEntryBB);
}
+ llvm::BasicBlock *getCleanupExitBlock() {
+ if (!CleanupExitBB)
+ CleanupExitBB = CGF.createBasicBlock("cleanup.exit");
+ return CleanupExitBB;
+ }
+
~CleanupScope() {
- CGF.PushCleanupBlock(CleanupBB);
+ CGF.PushCleanupBlock(CleanupEntryBB, CleanupExitBB);
// FIXME: This is silly, move this into the builder.
if (CurBB)
CGF.Builder.SetInsertPoint(CurBB);
@@ -250,9 +258,12 @@ private:
bool DidCallStackSave;
struct CleanupEntry {
- /// CleanupBlock - The block of code that does the actual cleanup.
- llvm::BasicBlock *CleanupBlock;
+ /// CleanupEntryBlock - The block of code that does the actual cleanup.
+ llvm::BasicBlock *CleanupEntryBlock;
+ /// CleanupExitBlock - The cleanup exit block.
+ llvm::BasicBlock *CleanupExitBlock;
+
/// Blocks - Basic blocks that were emitted in the current cleanup scope.
std::vector<llvm::BasicBlock *> Blocks;
@@ -260,8 +271,10 @@ private:
/// inserted into the current function yet.
std::vector<llvm::BranchInst *> BranchFixups;
- explicit CleanupEntry(llvm::BasicBlock *cb)
- : CleanupBlock(cb) {}
+ explicit CleanupEntry(llvm::BasicBlock *CleanupEntryBlock,
+ llvm::BasicBlock *CleanupExitBlock)
+ : CleanupEntryBlock(CleanupEntryBlock),
+ CleanupExitBlock(CleanupExitBlock) {}
};
/// CleanupEntries - Stack of cleanup entries.
diff --git a/lib/Frontend/AnalysisConsumer.cpp b/lib/Frontend/AnalysisConsumer.cpp
index 049f3bd3ea14..d2831fae566a 100644
--- a/lib/Frontend/AnalysisConsumer.cpp
+++ b/lib/Frontend/AnalysisConsumer.cpp
@@ -12,23 +12,24 @@
//===----------------------------------------------------------------------===//
#include "clang/Frontend/AnalysisConsumer.h"
-#include "clang/Frontend/PathDiagnosticClients.h"
-#include "clang/Frontend/ManagerRegistry.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
-#include "clang/Analysis/CFG.h"
+#include "clang/AST/ParentMap.h"
+#include "clang/Analysis/Analyses/LiveVariables.h"
#include "clang/Analysis/Analyses/LiveVariables.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/LocalCheckers.h"
#include "clang/Analysis/PathDiagnostic.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Basic/FileManager.h"
-#include "clang/AST/ParentMap.h"
#include "clang/Analysis/PathSensitive/AnalysisManager.h"
#include "clang/Analysis/PathSensitive/BugReporter.h"
-#include "clang/Analysis/Analyses/LiveVariables.h"
-#include "clang/Analysis/LocalCheckers.h"
-#include "clang/Analysis/PathSensitive/GRTransferFuncs.h"
#include "clang/Analysis/PathSensitive/GRExprEngine.h"
+#include "clang/Analysis/PathSensitive/GRTransferFuncs.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Frontend/ManagerRegistry.h"
+#include "clang/Frontend/PathDiagnosticClients.h"
+#include "clang/Lex/Preprocessor.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Path.h"
@@ -52,12 +53,11 @@ namespace {
//===----------------------------------------------------------------------===//
static PathDiagnosticClient*
-CreatePlistHTMLDiagnosticClient(const std::string& prefix, Preprocessor* PP,
- PreprocessorFactory* PPF) {
+CreatePlistHTMLDiagnosticClient(const std::string& prefix,
+ const Preprocessor &PP) {
llvm::sys::Path F(prefix);
- PathDiagnosticClientFactory *PF =
- CreateHTMLDiagnosticClientFactory(F.getDirname(), PP, PPF);
- return CreatePlistDiagnosticClient(prefix, PP, PPF, PF);
+ PathDiagnosticClient *PD = CreateHTMLDiagnosticClient(F.getDirname(), PP);
+ return CreatePlistDiagnosticClient(prefix, PP, PD);
}
//===----------------------------------------------------------------------===//
@@ -74,11 +74,8 @@ namespace {
Actions TranslationUnitActions;
public:
- const LangOptions& LOpts;
- Diagnostic &Diags;
ASTContext* Ctx;
- Preprocessor* PP;
- PreprocessorFactory* PPF;
+ const Preprocessor &PP;
const std::string OutDir;
AnalyzerOptions Opts;
@@ -91,14 +88,11 @@ namespace {
llvm::OwningPtr<AnalysisManager> Mgr;
- AnalysisConsumer(Diagnostic &diags, Preprocessor* pp,
- PreprocessorFactory* ppf,
- const LangOptions& lopts,
+ AnalysisConsumer(const Preprocessor& pp,
const std::string& outdir,
const AnalyzerOptions& opts)
- : LOpts(lopts), Diags(diags),
- Ctx(0), PP(pp), PPF(ppf),
- OutDir(outdir), Opts(opts), PD(0) {
+ : Ctx(0), PP(pp), OutDir(outdir),
+ Opts(opts), PD(0) {
DigestAnalyzerOptions();
}
@@ -108,7 +102,7 @@ namespace {
switch (Opts.AnalysisDiagOpt) {
default:
#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE) \
- case PD_##NAME: PD = CREATEFN(OutDir, PP, PPF); break;
+ case PD_##NAME: PD = CREATEFN(OutDir, PP); break;
#include "clang/Frontend/Analyses.def"
}
}
@@ -155,7 +149,8 @@ namespace {
virtual void Initialize(ASTContext &Context) {
Ctx = &Context;
- Mgr.reset(new AnalysisManager(*Ctx, Diags, LOpts, PD,
+ Mgr.reset(new AnalysisManager(*Ctx, PP.getDiagnostics(),
+ PP.getLangOptions(), PD,
CreateStoreMgr, CreateConstraintMgr,
Opts.AnalyzerDisplayProgress,
Opts.VisualizeEGDot, Opts.VisualizeEGUbi,
@@ -263,7 +258,7 @@ void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) {
void AnalysisConsumer::HandleCode(Decl *D, Stmt* Body, Actions& actions) {
// Don't run the actions if an error has occured with parsing the file.
- if (Diags.hasErrorOccurred())
+ if (PP.getDiagnostics().hasErrorOccurred())
return;
// Don't run the actions on declarations in header files unless
@@ -443,15 +438,10 @@ static void ActionInlineCall(AnalysisManager &mgr, Decl *D) {
// AnalysisConsumer creation.
//===----------------------------------------------------------------------===//
-ASTConsumer* clang::CreateAnalysisConsumer(Diagnostic &diags, Preprocessor* pp,
- PreprocessorFactory* ppf,
- const LangOptions& lopts,
+ASTConsumer* clang::CreateAnalysisConsumer(const Preprocessor& pp,
const std::string& OutDir,
const AnalyzerOptions& Opts) {
-
- llvm::OwningPtr<AnalysisConsumer> C(new AnalysisConsumer(diags, pp, ppf,
- lopts, OutDir,
- Opts));
+ llvm::OwningPtr<AnalysisConsumer> C(new AnalysisConsumer(pp, OutDir, Opts));
for (unsigned i = 0; i < Opts.AnalysisList.size(); ++i)
switch (Opts.AnalysisList[i]) {
@@ -464,7 +454,7 @@ ASTConsumer* clang::CreateAnalysisConsumer(Diagnostic &diags, Preprocessor* pp,
}
// Last, disable the effects of '-Werror' when using the AnalysisConsumer.
- diags.setWarningsAsErrors(false);
+ pp.getDiagnostics().setWarningsAsErrors(false);
return C.take();
}
diff --git a/lib/Frontend/HTMLDiagnostics.cpp b/lib/Frontend/HTMLDiagnostics.cpp
index 9d6f96c69f5d..145d53f3fc6e 100644
--- a/lib/Frontend/HTMLDiagnostics.cpp
+++ b/lib/Frontend/HTMLDiagnostics.cpp
@@ -37,18 +37,20 @@ namespace {
class VISIBILITY_HIDDEN HTMLDiagnostics : public PathDiagnosticClient {
llvm::sys::Path Directory, FilePrefix;
bool createdDir, noDir;
- Preprocessor* PP;
+ const Preprocessor &PP;
std::vector<const PathDiagnostic*> BatchedDiags;
- llvm::SmallVectorImpl<std::string> *FilesMade;
public:
- HTMLDiagnostics(const std::string& prefix, Preprocessor* pp,
- llvm::SmallVectorImpl<std::string> *filesMade = 0);
-
- virtual ~HTMLDiagnostics();
-
- virtual void SetPreprocessor(Preprocessor *pp) { PP = pp; }
+ HTMLDiagnostics(const std::string& prefix, const Preprocessor &pp);
+
+ virtual ~HTMLDiagnostics() { FlushDiagnostics(NULL); }
+
+ virtual void FlushDiagnostics(llvm::SmallVectorImpl<std::string> *FilesMade);
virtual void HandlePathDiagnostic(const PathDiagnostic* D);
+
+ virtual llvm::StringRef getName() const {
+ return "HTMLDiagnostics";
+ }
unsigned ProcessMacroPiece(llvm::raw_ostream& os,
const PathDiagnosticMacroPiece& P,
@@ -61,59 +63,24 @@ public:
const char *HighlightStart = "<span class=\"mrange\">",
const char *HighlightEnd = "</span>");
- void ReportDiag(const PathDiagnostic& D);
+ void ReportDiag(const PathDiagnostic& D,
+ llvm::SmallVectorImpl<std::string> *FilesMade);
};
} // end anonymous namespace
-HTMLDiagnostics::HTMLDiagnostics(const std::string& prefix, Preprocessor* pp,
- llvm::SmallVectorImpl<std::string>* filesMade)
+HTMLDiagnostics::HTMLDiagnostics(const std::string& prefix,
+ const Preprocessor &pp)
: Directory(prefix), FilePrefix(prefix), createdDir(false), noDir(false),
- PP(pp), FilesMade(filesMade) {
-
+ PP(pp) {
// All html files begin with "report"
FilePrefix.appendComponent("report");
}
PathDiagnosticClient*
-clang::CreateHTMLDiagnosticClient(const std::string& prefix, Preprocessor* PP,
- PreprocessorFactory*,
- llvm::SmallVectorImpl<std::string>* FilesMade)
-{
- return new HTMLDiagnostics(prefix, PP, FilesMade);
-}
-
-//===----------------------------------------------------------------------===//
-// Factory for HTMLDiagnosticClients
-//===----------------------------------------------------------------------===//
-
-namespace {
-class VISIBILITY_HIDDEN HTMLDiagnosticsFactory
- : public PathDiagnosticClientFactory {
-
- std::string Prefix;
- Preprocessor *PP;
-public:
- HTMLDiagnosticsFactory(const std::string& prefix, Preprocessor* pp)
- : Prefix(prefix), PP(pp) {}
-
- virtual ~HTMLDiagnosticsFactory() {}
-
- const char *getName() const { return "HTMLDiagnostics"; }
-
- PathDiagnosticClient*
- createPathDiagnosticClient(llvm::SmallVectorImpl<std::string> *FilesMade) {
-
- return new HTMLDiagnostics(Prefix, PP, FilesMade);
- }
-};
-} // end anonymous namespace
-
-PathDiagnosticClientFactory*
-clang::CreateHTMLDiagnosticClientFactory(const std::string& prefix,
- Preprocessor* PP,
- PreprocessorFactory*) {
- return new HTMLDiagnosticsFactory(prefix, PP);
+clang::CreateHTMLDiagnosticClient(const std::string& prefix,
+ const Preprocessor &PP) {
+ return new HTMLDiagnostics(prefix, PP);
}
//===----------------------------------------------------------------------===//
@@ -133,16 +100,19 @@ void HTMLDiagnostics::HandlePathDiagnostic(const PathDiagnostic* D) {
BatchedDiags.push_back(D);
}
-HTMLDiagnostics::~HTMLDiagnostics() {
+void
+HTMLDiagnostics::FlushDiagnostics(llvm::SmallVectorImpl<std::string> *FilesMade)
+{
while (!BatchedDiags.empty()) {
const PathDiagnostic* D = BatchedDiags.back();
BatchedDiags.pop_back();
- ReportDiag(*D);
+ ReportDiag(*D, FilesMade);
delete D;
}
}
-void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D) {
+void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
+ llvm::SmallVectorImpl<std::string> *FilesMade){
// Create the HTML directory if it is missing.
if (!createdDir) {
createdDir = true;
@@ -195,7 +165,7 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D) {
return; // FIXME: Emit a warning?
// Create a new rewriter to generate HTML.
- Rewriter R(const_cast<SourceManager&>(SMgr), PP->getLangOptions());
+ Rewriter R(const_cast<SourceManager&>(SMgr), PP.getLangOptions());
// Process the path.
unsigned n = D.size();
@@ -215,14 +185,8 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D) {
// We might not have a preprocessor if we come from a deserialized AST file,
// for example.
- if (PP) html::SyntaxHighlight(R, FID, *PP);
-
- // FIXME: We eventually want to use PPF to create a fresh Preprocessor,
- // once we have worked out the bugs.
- //
- // if (PPF) html::HighlightMacros(R, FID, *PPF);
- //
- if (PP) html::HighlightMacros(R, FID, *PP);
+ html::SyntaxHighlight(R, FID, PP);
+ html::HighlightMacros(R, FID, PP);
// Get the full directory name of the analyzed file.
@@ -476,7 +440,7 @@ void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID,
assert(L.isFileID());
std::pair<const char*, const char*> BufferInfo = L.getBufferData();
const char* MacroName = L.getDecomposedLoc().second + BufferInfo.first;
- Lexer rawLexer(L, PP->getLangOptions(), BufferInfo.first,
+ Lexer rawLexer(L, PP.getLangOptions(), BufferInfo.first,
MacroName, BufferInfo.second);
Token TheTok;
diff --git a/lib/Frontend/HTMLPrint.cpp b/lib/Frontend/HTMLPrint.cpp
index 8d93d70e83f4..75e6184572e5 100644
--- a/lib/Frontend/HTMLPrint.cpp
+++ b/lib/Frontend/HTMLPrint.cpp
@@ -13,13 +13,14 @@
#include "clang/Frontend/ASTConsumers.h"
#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
-#include "clang/Rewrite/Rewriter.h"
-#include "clang/Rewrite/HTMLRewrite.h"
#include "clang/Basic/Diagnostic.h"
-#include "clang/Basic/SourceManager.h"
#include "clang/Basic/FileManager.h"
-#include "clang/AST/ASTContext.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Rewrite/HTMLRewrite.h"
+#include "clang/Rewrite/Rewriter.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
@@ -32,13 +33,14 @@ namespace {
class HTMLPrinter : public ASTConsumer {
Rewriter R;
llvm::raw_ostream *Out;
- Diagnostic &Diags;
- Preprocessor *PP;
- PreprocessorFactory *PPF;
+ Preprocessor &PP;
+ bool SyntaxHighlight, HighlightMacros;
+
public:
- HTMLPrinter(llvm::raw_ostream *OS, Diagnostic &D, Preprocessor *pp,
- PreprocessorFactory* ppf)
- : Out(OS), Diags(D), PP(pp), PPF(ppf) {}
+ HTMLPrinter(llvm::raw_ostream *OS, Preprocessor &pp,
+ bool _SyntaxHighlight, bool _HighlightMacros)
+ : Out(OS), PP(pp), SyntaxHighlight(_SyntaxHighlight),
+ HighlightMacros(_HighlightMacros) {}
virtual ~HTMLPrinter();
void Initialize(ASTContext &context);
@@ -46,10 +48,10 @@ namespace {
}
ASTConsumer* clang::CreateHTMLPrinter(llvm::raw_ostream *OS,
- Diagnostic &D, Preprocessor *PP,
- PreprocessorFactory* PPF) {
-
- return new HTMLPrinter(OS, D, PP, PPF);
+ Preprocessor &PP,
+ bool SyntaxHighlight,
+ bool HighlightMacros) {
+ return new HTMLPrinter(OS, PP, SyntaxHighlight, HighlightMacros);
}
void HTMLPrinter::Initialize(ASTContext &context) {
@@ -57,7 +59,7 @@ void HTMLPrinter::Initialize(ASTContext &context) {
}
HTMLPrinter::~HTMLPrinter() {
- if (Diags.hasErrorOccurred())
+ if (PP.getDiagnostics().hasErrorOccurred())
return;
// Format the file.
@@ -79,8 +81,8 @@ HTMLPrinter::~HTMLPrinter() {
// We might not have a preprocessor if we come from a deserialized AST file,
// for example.
- if (PP) html::SyntaxHighlight(R, FID, *PP);
- if (PPF) html::HighlightMacros(R, FID, *PP);
+ if (SyntaxHighlight) html::SyntaxHighlight(R, FID, PP);
+ if (HighlightMacros) html::HighlightMacros(R, FID, PP);
html::EscapeText(R, FID, false, true);
// Emit the HTML.
diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp
index ec5c1061bb93..7139e55f0b60 100644
--- a/lib/Frontend/InitPreprocessor.cpp
+++ b/lib/Frontend/InitPreprocessor.cpp
@@ -442,9 +442,8 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
/// InitializePreprocessor - Initialize the preprocessor getting it and the
/// environment ready to process a single file. This returns true on error.
///
-bool clang::InitializePreprocessor(Preprocessor &PP,
- const PreprocessorInitOptions &InitOpts,
- bool undef_macros) {
+void clang::InitializePreprocessor(Preprocessor &PP,
+ const PreprocessorInitOptions &InitOpts) {
std::vector<char> PredefineBuffer;
const char *LineDirective = "# 1 \"<built-in>\" 3\n";
@@ -452,7 +451,7 @@ bool clang::InitializePreprocessor(Preprocessor &PP,
LineDirective, LineDirective+strlen(LineDirective));
// Install things like __POWERPC__, __GNUC__, etc into the macro table.
- if (!undef_macros)
+ if (InitOpts.getUsePredefines())
InitializePredefinedMacros(PP.getTargetInfo(), PP.getLangOptions(),
PredefineBuffer);
@@ -489,7 +488,4 @@ bool clang::InitializePreprocessor(Preprocessor &PP,
// Null terminate PredefinedBuffer and add it.
PredefineBuffer.push_back(0);
PP.setPredefines(&PredefineBuffer[0]);
-
- // Once we've read this, we're done.
- return false;
}
diff --git a/lib/Frontend/PlistDiagnostics.cpp b/lib/Frontend/PlistDiagnostics.cpp
index a83dca0a5ffa..1be9ea8b8c41 100644
--- a/lib/Frontend/PlistDiagnostics.cpp
+++ b/lib/Frontend/PlistDiagnostics.cpp
@@ -29,7 +29,6 @@ typedef llvm::DenseMap<FileID, unsigned> FIDMap;
namespace clang {
class Preprocessor;
- class PreprocessorFactory;
}
namespace {
@@ -37,14 +36,20 @@ namespace {
std::vector<const PathDiagnostic*> BatchedDiags;
const std::string OutputFile;
const LangOptions &LangOpts;
- llvm::OwningPtr<PathDiagnosticClientFactory> PF;
- llvm::OwningPtr<PathDiagnosticClient> SubPDC;
- llvm::SmallVector<std::string, 1> FilesMade;
+ llvm::OwningPtr<PathDiagnosticClient> SubPD;
public:
PlistDiagnostics(const std::string& prefix, const LangOptions &LangOpts,
- PathDiagnosticClientFactory *pf);
- ~PlistDiagnostics();
+ PathDiagnosticClient *subPD);
+
+ ~PlistDiagnostics() { FlushDiagnostics(NULL); }
+
+ void FlushDiagnostics(llvm::SmallVectorImpl<std::string> *FilesMade);
+
void HandlePathDiagnostic(const PathDiagnostic* D);
+
+ virtual llvm::StringRef getName() const {
+ return "PlistDiagnostics";
+ }
PathGenerationScheme getGenerationScheme() const;
bool supportsLogicalOpControlFlow() const { return true; }
@@ -55,23 +60,18 @@ namespace {
PlistDiagnostics::PlistDiagnostics(const std::string& output,
const LangOptions &LO,
- PathDiagnosticClientFactory *pf)
- : OutputFile(output), LangOpts(LO), PF(pf) {
-
- if (PF)
- SubPDC.reset(PF->createPathDiagnosticClient(&FilesMade));
-}
+ PathDiagnosticClient *subPD)
+ : OutputFile(output), LangOpts(LO), SubPD(subPD) {}
PathDiagnosticClient*
-clang::CreatePlistDiagnosticClient(const std::string& s,
- Preprocessor *PP, PreprocessorFactory*,
- PathDiagnosticClientFactory *PF) {
- return new PlistDiagnostics(s, PP->getLangOptions(), PF);
+clang::CreatePlistDiagnosticClient(const std::string& s, const Preprocessor &PP,
+ PathDiagnosticClient *subPD) {
+ return new PlistDiagnostics(s, PP.getLangOptions(), subPD);
}
PathDiagnosticClient::PathGenerationScheme
PlistDiagnostics::getGenerationScheme() const {
- if (const PathDiagnosticClient *PD = SubPDC.get())
+ if (const PathDiagnosticClient *PD = SubPD.get())
return PD->getGenerationScheme();
return Extensive;
@@ -308,7 +308,8 @@ void PlistDiagnostics::HandlePathDiagnostic(const PathDiagnostic* D) {
BatchedDiags.push_back(D);
}
-PlistDiagnostics::~PlistDiagnostics() {
+void PlistDiagnostics::FlushDiagnostics(llvm::SmallVectorImpl<std::string>
+ *FilesMade) {
// Build up a set of FIDs that we use by scanning the locations and
// ranges of the diagnostics.
@@ -397,19 +398,16 @@ PlistDiagnostics::~PlistDiagnostics() {
EmitLocation(o, *SM, LangOpts, D->getLocation(), FM, 2);
// Output the diagnostic to the sub-diagnostic client, if any.
- if (PF) {
- if (!SubPDC.get())
- SubPDC.reset(PF->createPathDiagnosticClient(&FilesMade));
-
- FilesMade.clear();
- SubPDC->HandlePathDiagnostic(OwnedD.take());
- SubPDC.reset(0);
+ if (SubPD) {
+ SubPD->HandlePathDiagnostic(OwnedD.take());
+ llvm::SmallVector<std::string, 1> SubFilesMade;
+ SubPD->FlushDiagnostics(SubFilesMade);
- if (!FilesMade.empty()) {
- o << " <key>" << PF->getName() << "_files</key>\n";
+ if (!SubFilesMade.empty()) {
+ o << " <key>" << SubPD->getName() << "_files</key>\n";
o << " <array>\n";
- for (size_t i = 0, n = FilesMade.size(); i < n ; ++i)
- o << " <string>" << FilesMade[i] << "</string>\n";
+ for (size_t i = 0, n = SubFilesMade.size(); i < n ; ++i)
+ o << " <string>" << SubFilesMade[i] << "</string>\n";
o << " </array>\n";
}
}
@@ -422,4 +420,7 @@ PlistDiagnostics::~PlistDiagnostics() {
// Finish.
o << "</dict>\n</plist>";
+
+ if (FilesMade)
+ FilesMade->push_back(OutputFile);
}
diff --git a/lib/Frontend/TextDiagnosticPrinter.cpp b/lib/Frontend/TextDiagnosticPrinter.cpp
index b1d8800369e5..4f8c804844b0 100644
--- a/lib/Frontend/TextDiagnosticPrinter.cpp
+++ b/lib/Frontend/TextDiagnosticPrinter.cpp
@@ -268,6 +268,7 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc,
const CodeModificationHint *Hints,
unsigned NumHints,
unsigned Columns) {
+ assert(LangOpts && "Unexpected diagnostic outside source file processing");
assert(!Loc.isInvalid() && "must have a valid source location here");
// If this is a macro ID, first emit information about where this was
diff --git a/lib/Headers/stdint.h b/lib/Headers/stdint.h
index f79a0f4af557..f03c1777ab01 100644
--- a/lib/Headers/stdint.h
+++ b/lib/Headers/stdint.h
@@ -42,28 +42,23 @@
* Since we only support pow-2 targets, these map directly to exact width types.
*/
-#ifndef __int8_t_defined /* glibc does weird things with sys/types.h */
-#define __int8_t_defined
-typedef signed __INT8_TYPE__ int8_t;
-typedef __INT16_TYPE__ int16_t;
-typedef __INT32_TYPE__ int32_t;
+/* Some 16-bit targets do not have a 64-bit datatype. Only define the 64-bit
+ * typedefs if there is something to typedef them to.
+ */
#ifdef __INT64_TYPE__
+#ifndef __int8_t_defined /* glibc does weird things with sys/types.h */
typedef __INT64_TYPE__ int64_t;
#endif
+typedef unsigned __INT64_TYPE__ uint64_t;
+typedef int64_t int_least64_t;
+typedef uint64_t uint_least64_t;
+typedef int64_t int_fast64_t;
+typedef uint64_t uint_fast64_t;
#endif
-typedef unsigned __INT8_TYPE__ uint8_t;
-typedef int8_t int_least8_t;
-typedef uint8_t uint_least8_t;
-typedef int8_t int_fast8_t;
-typedef uint8_t uint_fast8_t;
-
-typedef unsigned __INT16_TYPE__ uint16_t;
-typedef int16_t int_least16_t;
-typedef uint16_t uint_least16_t;
-typedef int16_t int_fast16_t;
-typedef uint16_t uint_fast16_t;
-
+#ifndef __int8_t_defined /* glibc does weird things with sys/types.h */
+typedef __INT32_TYPE__ int32_t;
+#endif
#ifndef __uint32_t_defined /* more glibc compatibility */
#define __uint32_t_defined
typedef unsigned __INT32_TYPE__ uint32_t;
@@ -73,18 +68,31 @@ typedef uint32_t uint_least32_t;
typedef int32_t int_fast32_t;
typedef uint32_t uint_fast32_t;
-/* Some 16-bit targets do not have a 64-bit datatype. Only define the 64-bit
- * typedefs if there is something to typedef them to.
- */
-#ifdef __INT64_TYPE__
-typedef unsigned __INT64_TYPE__ uint64_t;
-typedef int64_t int_least64_t;
-typedef uint64_t uint_least64_t;
-typedef int64_t int_fast64_t;
-typedef uint64_t uint_fast64_t;
+
+#ifndef __int8_t_defined /* glibc does weird things with sys/types.h */
+typedef __INT16_TYPE__ int16_t;
#endif
+typedef unsigned __INT16_TYPE__ uint16_t;
+typedef int16_t int_least16_t;
+typedef uint16_t uint_least16_t;
+typedef int16_t int_fast16_t;
+typedef uint16_t uint_fast16_t;
+#ifndef __int8_t_defined /* glibc does weird things with sys/types.h */
+typedef signed __INT8_TYPE__ int8_t;
+#endif
+typedef unsigned __INT8_TYPE__ uint8_t;
+typedef int8_t int_least8_t;
+typedef uint8_t uint_least8_t;
+typedef int8_t int_fast8_t;
+typedef uint8_t uint_fast8_t;
+
+/* prevent glibc sys/types.h from defining conflicting types */
+#ifndef __int8_t_defined
+# define __int8_t_defined
+#endif /* __int8_t_defined */
+
/* C99 7.18.1.4 Integer types capable of holding object pointers.
*/
#ifndef __intptr_t_defined
@@ -98,6 +106,25 @@ typedef unsigned __INTPTR_TYPE__ uintptr_t;
typedef __INTMAX_TYPE__ intmax_t;
typedef __UINTMAX_TYPE__ uintmax_t;
+/* C99 7.18.4 Macros for minimum-width integer constants.
+ *
+ * Note that C++ should not check __STDC_CONSTANT_MACROS here, contrary to the
+ * claims of the C standard (see C++ 18.3.1p2, [cstdint.syn]).
+ */
+
+/* Only define the 64-bit size macros if we have 64-bit support. */
+#ifdef __INT64_TYPE__
+#define INT64_C(v) (v##LL)
+#define UINT64_C(v) (v##ULL)
+#endif
+
+#define INT32_C(v) (v)
+#define UINT32_C(v) (v##U)
+#define INT16_C(v) (v)
+#define UINT16_C(v) (v##U)
+#define INT8_C(v) (v)
+#define UINT8_C(v) (v##U)
+
/* C99 7.18.2.1 Limits of exact-width integer types.
* Fixed sized values have fixed size max/min.
* C99 7.18.2.2 Limits of minimum-width integer types.
@@ -108,36 +135,6 @@ typedef __UINTMAX_TYPE__ uintmax_t;
* claims of the C standard (see C++ 18.3.1p2, [cstdint.syn]).
*/
-#define INT8_MAX 127
-#define INT8_MIN (-128)
-#define UINT8_MAX 255
-#define INT_LEAST8_MIN INT8_MIN
-#define INT_LEAST8_MAX INT8_MAX
-#define UINT_LEAST8_MAX UINT8_MAX
-#define INT_FAST8_MIN INT8_MIN
-#define INT_FAST8_MAX INT8_MAX
-#define UINT_FAST8_MAX UINT8_MAX
-
-#define INT16_MAX 32767
-#define INT16_MIN (-32768)
-#define UINT16_MAX 65535
-#define INT_LEAST16_MIN INT16_MIN
-#define INT_LEAST16_MAX INT16_MAX
-#define UINT_LEAST16_MAX UINT16_MAX
-#define INT_FAST16_MIN INT16_MIN
-#define INT_FAST16_MAX INT16_MAX
-#define UINT_FAST16_MAX UINT16_MAX
-
-#define INT32_MAX 2147483647
-#define INT32_MIN (-2147483647-1)
-#define UINT32_MAX 4294967295U
-#define INT_LEAST32_MIN INT32_MIN
-#define INT_LEAST32_MAX INT32_MAX
-#define UINT_LEAST32_MAX UINT32_MAX
-#define INT_FAST32_MIN INT32_MIN
-#define INT_FAST32_MAX INT32_MAX
-#define UINT_FAST32_MAX UINT32_MAX
-
/* If we do not have 64-bit support, don't define the 64-bit size macros. */
#ifdef __INT64_TYPE__
#define INT64_MAX 9223372036854775807LL
@@ -151,6 +148,36 @@ typedef __UINTMAX_TYPE__ uintmax_t;
#define UINT_FAST64_MAX UINT64_MAX
#endif
+#define INT32_MAX 2147483647
+#define INT32_MIN (-2147483647-1)
+#define UINT32_MAX 4294967295U
+#define INT_LEAST32_MIN INT32_MIN
+#define INT_LEAST32_MAX INT32_MAX
+#define UINT_LEAST32_MAX UINT32_MAX
+#define INT_FAST32_MIN INT32_MIN
+#define INT_FAST32_MAX INT32_MAX
+#define UINT_FAST32_MAX UINT32_MAX
+
+#define INT16_MAX 32767
+#define INT16_MIN (-32768)
+#define UINT16_MAX 65535
+#define INT_LEAST16_MIN INT16_MIN
+#define INT_LEAST16_MAX INT16_MAX
+#define UINT_LEAST16_MAX UINT16_MAX
+#define INT_FAST16_MIN INT16_MIN
+#define INT_FAST16_MAX INT16_MAX
+#define UINT_FAST16_MAX UINT16_MAX
+
+#define INT8_MAX 127
+#define INT8_MIN (-128)
+#define UINT8_MAX 255
+#define INT_LEAST8_MIN INT8_MIN
+#define INT_LEAST8_MAX INT8_MAX
+#define UINT_LEAST8_MAX UINT8_MAX
+#define INT_FAST8_MIN INT8_MIN
+#define INT_FAST8_MAX INT8_MAX
+#define UINT_FAST8_MAX UINT8_MAX
+
/* C99 7.18.2.4 Limits of integer types capable of holding object pointers. */
/* C99 7.18.3 Limits of other integer types. */
@@ -206,25 +233,6 @@ typedef __UINTMAX_TYPE__ uintmax_t;
#define WCHAR_MIN (-__WCHAR_MAX__-1)
#endif
-/* C99 7.18.4 Macros for minimum-width integer constants.
- *
- * Note that C++ should not check __STDC_CONSTANT_MACROS here, contrary to the
- * claims of the C standard (see C++ 18.3.1p2, [cstdint.syn]).
- */
-
-#define INT8_C(v) (v)
-#define UINT8_C(v) (v##U)
-#define INT16_C(v) (v)
-#define UINT16_C(v) (v##U)
-#define INT32_C(v) (v)
-#define UINT32_C(v) (v##U)
-
-/* Only define the 64-bit size macros if we have 64-bit support. */
-#ifdef __INT64_TYPE__
-#define INT64_C(v) (v##LL)
-#define UINT64_C(v) (v##ULL)
-#endif
-
/* 7.18.4.2 Macros for greatest-width integer constants. */
#define INTMAX_C(v) (v##LL)
#define UINTMAX_C(v) (v##ULL)
diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp
index 7f3afc60764c..487b9d63c169 100644
--- a/lib/Lex/Preprocessor.cpp
+++ b/lib/Lex/Preprocessor.cpp
@@ -43,8 +43,6 @@ using namespace clang;
//===----------------------------------------------------------------------===//
-PreprocessorFactory::~PreprocessorFactory() {}
-
Preprocessor::Preprocessor(Diagnostic &diags, const LangOptions &opts,
TargetInfo &target, SourceManager &SM,
HeaderSearch &Headers,
@@ -403,7 +401,7 @@ void Preprocessor::EnterMainSourceFile() {
/// LookUpIdentifierInfo - Given a tok::identifier token, look up the
/// identifier information for the token and install it into the token.
IdentifierInfo *Preprocessor::LookUpIdentifierInfo(Token &Identifier,
- const char *BufPtr) {
+ const char *BufPtr) const {
assert(Identifier.is(tok::identifier) && "Not an identifier!");
assert(Identifier.getIdentifierInfo() == 0 && "Identinfo already exists!");
@@ -411,14 +409,14 @@ IdentifierInfo *Preprocessor::LookUpIdentifierInfo(Token &Identifier,
IdentifierInfo *II;
if (BufPtr && !Identifier.needsCleaning()) {
// No cleaning needed, just use the characters from the lexed buffer.
- II = getIdentifierInfo(BufPtr, BufPtr+Identifier.getLength());
+ II = getIdentifierInfo(llvm::StringRef(BufPtr, Identifier.getLength()));
} else {
// Cleaning needed, alloca a buffer, clean into it, then use the buffer.
llvm::SmallVector<char, 64> IdentifierBuffer;
IdentifierBuffer.resize(Identifier.getLength());
const char *TmpBuf = &IdentifierBuffer[0];
unsigned Size = getSpelling(Identifier, TmpBuf);
- II = getIdentifierInfo(TmpBuf, TmpBuf+Size);
+ II = getIdentifierInfo(llvm::StringRef(TmpBuf, Size));
}
Identifier.setIdentifierInfo(II);
return II;
diff --git a/lib/Parse/DeclSpec.cpp b/lib/Parse/DeclSpec.cpp
index 3436900027e4..0a4e036e4399 100644
--- a/lib/Parse/DeclSpec.cpp
+++ b/lib/Parse/DeclSpec.cpp
@@ -334,6 +334,14 @@ bool DeclSpec::SetFriendSpec(SourceLocation Loc, const char *&PrevSpec,
return false;
}
+bool DeclSpec::SetConstexprSpec(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID) {
+ // 'constexpr constexpr' is ok.
+ Constexpr_specified = true;
+ ConstexprLoc = Loc;
+ return false;
+}
+
void DeclSpec::setProtocolQualifiers(const ActionBase::DeclPtrTy *Protos,
unsigned NP,
SourceLocation *ProtoLocs,
diff --git a/lib/Parse/MinimalAction.cpp b/lib/Parse/MinimalAction.cpp
index 1e7d397fdf37..bf05b2baccd4 100644
--- a/lib/Parse/MinimalAction.cpp
+++ b/lib/Parse/MinimalAction.cpp
@@ -42,14 +42,12 @@ Action::DeclPtrTy Action::ActOnUsingDirective(Scope *CurScope,
return DeclPtrTy();
}
-// Defined out-of-line here because of dependecy on AttributeList
+// Defined out-of-line here because of dependency on AttributeList
Action::DeclPtrTy Action::ActOnUsingDeclaration(Scope *CurScope,
AccessSpecifier AS,
SourceLocation UsingLoc,
const CXXScopeSpec &SS,
- SourceLocation IdentLoc,
- IdentifierInfo *TargetName,
- OverloadedOperatorKind Op,
+ UnqualifiedId &Name,
AttributeList *AttrList,
bool IsTypeName) {
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index e905553fd818..99752b59507f 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -769,6 +769,7 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
/// [C++] 'virtual'
/// [C++] 'explicit'
/// 'friend': [C++ dcl.friend]
+/// 'constexpr': [C++0x dcl.constexpr]
///
void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
@@ -1070,6 +1071,11 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
}
break;
+ // constexpr
+ case tok::kw_constexpr:
+ isInvalid = DS.SetConstexprSpec(Loc, PrevSpec, DiagID);
+ break;
+
// type-specifier
case tok::kw_short:
isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec,
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 91f86864f81f..154c2923486e 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -285,6 +285,7 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context,
bool IsTypeName;
// Ignore optional 'typename'.
+ // FIXME: This is wrong; we should parse this as a typename-specifier.
if (Tok.is(tok::kw_typename)) {
ConsumeToken();
IsTypeName = true;
@@ -302,41 +303,21 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context,
SkipUntil(tok::semi);
return DeclPtrTy();
}
- if (Tok.is(tok::annot_template_id)) {
- // C++0x N2914 [namespace.udecl]p5:
- // A using-declaration shall not name a template-id.
- Diag(Tok, diag::err_using_decl_can_not_refer_to_template_spec);
- SkipUntil(tok::semi);
- return DeclPtrTy();
- }
-
- IdentifierInfo *TargetName = 0;
- OverloadedOperatorKind Op = OO_None;
- SourceLocation IdentLoc;
- if (Tok.is(tok::kw_operator)) {
- IdentLoc = Tok.getLocation();
-
- Op = TryParseOperatorFunctionId();
- if (!Op) {
- // If there was an invalid operator, skip to end of decl, and eat ';'.
- SkipUntil(tok::semi);
- return DeclPtrTy();
- }
- // FIXME: what about conversion functions?
- } else if (Tok.is(tok::identifier)) {
- // Parse identifier.
- TargetName = Tok.getIdentifierInfo();
- IdentLoc = ConsumeToken();
- } else {
- // FIXME: Use a better diagnostic here.
- Diag(Tok, diag::err_expected_ident_in_using);
-
- // If there was invalid identifier, skip to end of decl, and eat ';'.
+ // Parse the unqualified-id. We allow parsing of both constructor and
+ // destructor names and allow the action module to diagnose any semantic
+ // errors.
+ UnqualifiedId Name;
+ if (ParseUnqualifiedId(SS,
+ /*EnteringContext=*/false,
+ /*AllowDestructorName=*/true,
+ /*AllowConstructorName=*/true,
+ /*ObjectType=*/0,
+ Name)) {
SkipUntil(tok::semi);
return DeclPtrTy();
}
-
+
// Parse (optional) attributes (most likely GNU strong-using extension).
if (Tok.is(tok::kw___attribute))
AttrList = ParseAttributes();
@@ -344,10 +325,10 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context,
// Eat ';'.
DeclEnd = Tok.getLocation();
ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
- AttrList ? "attributes list" : "namespace name", tok::semi);
+ AttrList ? "attributes list" : "using declaration",
+ tok::semi);
- return Actions.ActOnUsingDeclaration(CurScope, AS, UsingLoc, SS,
- IdentLoc, TargetName, Op,
+ return Actions.ActOnUsingDeclaration(CurScope, AS, UsingLoc, SS, Name,
AttrList, IsTypeName);
}
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index a7ca0c54dbe6..a00dfb0b4c36 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -1196,141 +1196,6 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
return true;
}
-/// TryParseOperatorFunctionId - Attempts to parse a C++ overloaded
-/// operator name (C++ [over.oper]). If successful, returns the
-/// predefined identifier that corresponds to that overloaded
-/// operator. Otherwise, returns NULL and does not consume any tokens.
-///
-/// operator-function-id: [C++ 13.5]
-/// 'operator' operator
-///
-/// operator: one of
-/// new delete new[] delete[]
-/// + - * / % ^ & | ~
-/// ! = < > += -= *= /= %=
-/// ^= &= |= << >> >>= <<= == !=
-/// <= >= && || ++ -- , ->* ->
-/// () []
-OverloadedOperatorKind
-Parser::TryParseOperatorFunctionId(SourceLocation *EndLoc) {
- assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
- SourceLocation Loc;
-
- OverloadedOperatorKind Op = OO_None;
- switch (NextToken().getKind()) {
- case tok::kw_new:
- ConsumeToken(); // 'operator'
- Loc = ConsumeToken(); // 'new'
- if (Tok.is(tok::l_square)) {
- ConsumeBracket(); // '['
- Loc = Tok.getLocation();
- ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
- Op = OO_Array_New;
- } else {
- Op = OO_New;
- }
- if (EndLoc)
- *EndLoc = Loc;
- return Op;
-
- case tok::kw_delete:
- ConsumeToken(); // 'operator'
- Loc = ConsumeToken(); // 'delete'
- if (Tok.is(tok::l_square)) {
- ConsumeBracket(); // '['
- Loc = Tok.getLocation();
- ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
- Op = OO_Array_Delete;
- } else {
- Op = OO_Delete;
- }
- if (EndLoc)
- *EndLoc = Loc;
- return Op;
-
-#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
- case tok::Token: Op = OO_##Name; break;
-#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
-#include "clang/Basic/OperatorKinds.def"
-
- case tok::l_paren:
- ConsumeToken(); // 'operator'
- ConsumeParen(); // '('
- Loc = Tok.getLocation();
- ExpectAndConsume(tok::r_paren, diag::err_expected_rparen); // ')'
- if (EndLoc)
- *EndLoc = Loc;
- return OO_Call;
-
- case tok::l_square:
- ConsumeToken(); // 'operator'
- ConsumeBracket(); // '['
- Loc = Tok.getLocation();
- ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
- if (EndLoc)
- *EndLoc = Loc;
- return OO_Subscript;
-
- case tok::code_completion: {
- // Code completion for the operator name.
- Actions.CodeCompleteOperatorName(CurScope);
-
- // Consume the 'operator' token, then replace the code-completion token
- // with an 'operator' token and try again.
- SourceLocation OperatorLoc = ConsumeToken();
- Tok.setLocation(OperatorLoc);
- Tok.setKind(tok::kw_operator);
- return TryParseOperatorFunctionId(EndLoc);
- }
-
- default:
- return OO_None;
- }
-
- ConsumeToken(); // 'operator'
- Loc = ConsumeAnyToken(); // the operator itself
- if (EndLoc)
- *EndLoc = Loc;
- return Op;
-}
-
-/// ParseConversionFunctionId - Parse a C++ conversion-function-id,
-/// which expresses the name of a user-defined conversion operator
-/// (C++ [class.conv.fct]p1). Returns the type that this operator is
-/// specifying a conversion for, or NULL if there was an error.
-///
-/// conversion-function-id: [C++ 12.3.2]
-/// operator conversion-type-id
-///
-/// conversion-type-id:
-/// type-specifier-seq conversion-declarator[opt]
-///
-/// conversion-declarator:
-/// ptr-operator conversion-declarator[opt]
-Parser::TypeTy *Parser::ParseConversionFunctionId(SourceLocation *EndLoc) {
- assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
- ConsumeToken(); // 'operator'
-
- // Parse the type-specifier-seq.
- DeclSpec DS;
- if (ParseCXXTypeSpecifierSeq(DS))
- return 0;
-
- // Parse the conversion-declarator, which is merely a sequence of
- // ptr-operators.
- Declarator D(DS, Declarator::TypeNameContext);
- ParseDeclaratorInternal(D, /*DirectDeclParser=*/0);
- if (EndLoc)
- *EndLoc = D.getSourceRange().getEnd();
-
- // Finish up the type.
- Action::TypeResult Result = Actions.ActOnTypeName(CurScope, D);
- if (Result.isInvalid())
- return 0;
- else
- return Result.get();
-}
-
/// ParseCXXNewExpression - Parse a C++ new-expression. New is used to allocate
/// memory in a typesafe manner and call constructors.
///
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index 045acd86ad0f..99578837c21c 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -809,12 +809,11 @@ void Parser::AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS) {
Tok.setAnnotationValue(Type.isInvalid()? 0 : Type.get());
if (SS && SS->isNotEmpty()) // it was a C++ qualified type name.
Tok.setLocation(SS->getBeginLoc());
+ Tok.setAnnotationEndLoc(TemplateId->TemplateNameLoc);
- // We might be backtracking, in which case we need to replace the
- // template-id annotation token with the type annotation within the
- // set of cached tokens. That way, we won't try to form the same
- // class template specialization again.
- PP.ReplaceLastTokenWithAnnotation(Tok);
+ // Replace the template-id annotation token, and possible the scope-specifier
+ // that precedes it, with the typename annotation token.
+ PP.AnnotateCachedTokens(Tok);
TemplateId->Destroy();
}
diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp
index eb6e93540566..7ac297710965 100644
--- a/lib/Parse/ParseTentative.cpp
+++ b/lib/Parse/ParseTentative.cpp
@@ -503,6 +503,7 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
/// function-specifier
/// 'friend'
/// 'typedef'
+/// [C++0x] 'constexpr'
/// [GNU] attributes declaration-specifiers[opt]
///
/// storage-class-specifier:
@@ -615,9 +616,11 @@ Parser::TPResult Parser::isCXXDeclarationSpecifier() {
// function-specifier
// 'friend'
// 'typedef'
+ // 'constexpr'
case tok::kw_friend:
case tok::kw_typedef:
+ case tok::kw_constexpr:
// storage-class-specifier
case tok::kw_register:
case tok::kw_static:
diff --git a/lib/Rewrite/HTMLRewrite.cpp b/lib/Rewrite/HTMLRewrite.cpp
index 7326890ded76..b4bf419bc5f4 100644
--- a/lib/Rewrite/HTMLRewrite.cpp
+++ b/lib/Rewrite/HTMLRewrite.cpp
@@ -349,7 +349,7 @@ void html::AddHeaderFooterInternalBuiltinCSS(Rewriter& R, FileID FID,
/// information about keywords, macro expansions etc. This uses the macro
/// table state from the end of the file, so it won't be perfectly perfect,
/// but it will be reasonably close.
-void html::SyntaxHighlight(Rewriter &R, FileID FID, Preprocessor &PP) {
+void html::SyntaxHighlight(Rewriter &R, FileID FID, const Preprocessor &PP) {
RewriteBuffer &RB = R.getEditBuffer(FID);
const SourceManager &SM = PP.getSourceManager();
@@ -375,7 +375,8 @@ void html::SyntaxHighlight(Rewriter &R, FileID FID, Preprocessor &PP) {
case tok::identifier: {
// Fill in Result.IdentifierInfo, looking up the identifier in the
// identifier table.
- IdentifierInfo *II = PP.LookUpIdentifierInfo(Tok, BufferStart+TokOffs);
+ const IdentifierInfo *II =
+ PP.LookUpIdentifierInfo(Tok, BufferStart+TokOffs);
// If this is a pp-identifier, for a keyword, highlight it as such.
if (II->getTokenID() != tok::identifier)
@@ -438,7 +439,7 @@ class IgnoringDiagClient : public DiagnosticClient {
/// file, to re-expand macros and insert (into the HTML) information about the
/// macro expansions. This won't be perfectly perfect, but it will be
/// reasonably close.
-void html::HighlightMacros(Rewriter &R, FileID FID, Preprocessor& PP) {
+void html::HighlightMacros(Rewriter &R, FileID FID, const Preprocessor& PP) {
// Re-lex the raw token stream into a token buffer.
const SourceManager &SM = PP.getSourceManager();
std::vector<Token> TokenStream;
@@ -481,25 +482,29 @@ void html::HighlightMacros(Rewriter &R, FileID FID, Preprocessor& PP) {
IgnoringDiagClient TmpDC;
Diagnostic TmpDiags(&TmpDC);
- Diagnostic *OldDiags = &PP.getDiagnostics();
- PP.setDiagnostics(TmpDiags);
+ // FIXME: This is a huge hack; we reuse the input preprocessor because we want
+ // its state, but we aren't actually changing it (we hope). This should really
+ // construct a copy of the preprocessor.
+ Preprocessor &TmpPP = const_cast<Preprocessor&>(PP);
+ Diagnostic *OldDiags = &TmpPP.getDiagnostics();
+ TmpPP.setDiagnostics(TmpDiags);
// Inform the preprocessor that we don't want comments.
- PP.SetCommentRetentionState(false, false);
+ TmpPP.SetCommentRetentionState(false, false);
// Enter the tokens we just lexed. This will cause them to be macro expanded
// but won't enter sub-files (because we removed #'s).
- PP.EnterTokenStream(&TokenStream[0], TokenStream.size(), false, false);
+ TmpPP.EnterTokenStream(&TokenStream[0], TokenStream.size(), false, false);
- TokenConcatenation ConcatInfo(PP);
+ TokenConcatenation ConcatInfo(TmpPP);
// Lex all the tokens.
Token Tok;
- PP.Lex(Tok);
+ TmpPP.Lex(Tok);
while (Tok.isNot(tok::eof)) {
// Ignore non-macro tokens.
if (!Tok.getLocation().isMacroID()) {
- PP.Lex(Tok);
+ TmpPP.Lex(Tok);
continue;
}
@@ -511,19 +516,19 @@ void html::HighlightMacros(Rewriter &R, FileID FID, Preprocessor& PP) {
// Ignore tokens whose instantiation location was not the main file.
if (SM.getFileID(LLoc.first) != FID) {
- PP.Lex(Tok);
+ TmpPP.Lex(Tok);
continue;
}
assert(SM.getFileID(LLoc.second) == FID &&
"Start and end of expansion must be in the same ultimate file!");
- std::string Expansion = EscapeText(PP.getSpelling(Tok));
+ std::string Expansion = EscapeText(TmpPP.getSpelling(Tok));
unsigned LineLen = Expansion.size();
Token PrevTok = Tok;
// Okay, eat this token, getting the next one.
- PP.Lex(Tok);
+ TmpPP.Lex(Tok);
// Skip all the rest of the tokens that are part of this macro
// instantiation. It would be really nice to pop up a window with all the
@@ -545,11 +550,11 @@ void html::HighlightMacros(Rewriter &R, FileID FID, Preprocessor& PP) {
Expansion += ' ';
// Escape any special characters in the token text.
- Expansion += EscapeText(PP.getSpelling(Tok));
+ Expansion += EscapeText(TmpPP.getSpelling(Tok));
LineLen += Expansion.size();
PrevTok = Tok;
- PP.Lex(Tok);
+ TmpPP.Lex(Tok);
}
@@ -562,12 +567,5 @@ void html::HighlightMacros(Rewriter &R, FileID FID, Preprocessor& PP) {
}
// Restore diagnostics object back to its own thing.
- PP.setDiagnostics(*OldDiags);
-}
-
-void html::HighlightMacros(Rewriter &R, FileID FID,
- PreprocessorFactory &PPF) {
-
- llvm::OwningPtr<Preprocessor> PP(PPF.CreatePreprocessor());
- HighlightMacros(R, FID, *PP);
+ TmpPP.setDiagnostics(*OldDiags);
}
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 0f84b46ed405..c4de6be9eb2e 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -1609,6 +1609,9 @@ public:
void DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc,
Expr **Args, unsigned NumArgs);
+ void CheckSignCompare(Expr *LHS, Expr *RHS, SourceLocation Loc,
+ const PartialDiagnostic &PD);
+
virtual ExpressionEvaluationContext
PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext);
@@ -1667,6 +1670,8 @@ public:
OwningExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc,
unsigned OpcIn,
ExprArg InputArg);
+ OwningExprResult BuildUnaryOp(Scope *S, SourceLocation OpLoc,
+ UnaryOperator::Opcode Opc, ExprArg input);
virtual OwningExprResult ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
tok::TokenKind Op, ExprArg Input);
@@ -1792,6 +1797,9 @@ public:
virtual OwningExprResult ActOnBinOp(Scope *S, SourceLocation TokLoc,
tok::TokenKind Kind,
ExprArg LHS, ExprArg RHS);
+ OwningExprResult BuildBinOp(Scope *S, SourceLocation OpLoc,
+ BinaryOperator::Opcode Opc,
+ Expr *lhs, Expr *rhs);
OwningExprResult CreateBuiltinBinOp(SourceLocation TokLoc,
unsigned Opc, Expr *lhs, Expr *rhs);
@@ -1893,9 +1901,7 @@ public:
AccessSpecifier AS,
SourceLocation UsingLoc,
const CXXScopeSpec &SS,
- SourceLocation IdentLoc,
- IdentifierInfo *TargetName,
- OverloadedOperatorKind Op,
+ UnqualifiedId &Name,
AttributeList *AttrList,
bool IsTypeName);
@@ -3645,7 +3651,8 @@ public:
Ref_Compatible
};
- ReferenceCompareResult CompareReferenceRelationship(QualType T1, QualType T2,
+ ReferenceCompareResult CompareReferenceRelationship(SourceLocation Loc,
+ QualType T1, QualType T2,
bool& DerivedToBase);
bool CheckReferenceInit(Expr *&simpleInit_or_initList, QualType declType,
diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp
index 8bb334855d02..76faddaa0384 100644
--- a/lib/Sema/SemaCXXCast.cpp
+++ b/lib/Sema/SemaCXXCast.cpp
@@ -527,7 +527,8 @@ TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, QualType DestType,
// this is the only cast possibility, so we issue an error if we fail now.
// FIXME: Should allow casting away constness if CStyle.
bool DerivedToBase;
- if (Self.CompareReferenceRelationship(SrcExpr->getType(), R->getPointeeType(),
+ if (Self.CompareReferenceRelationship(SrcExpr->getLocStart(),
+ SrcExpr->getType(), R->getPointeeType(),
DerivedToBase) <
Sema::Ref_Compatible_With_Added_Qualification) {
msg = diag::err_bad_lvalue_to_rvalue_cast;
diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp
index 10c138c7558f..ce3fb5f83c8f 100644
--- a/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/lib/Sema/SemaCXXScopeSpec.cpp
@@ -22,6 +22,72 @@
#include "llvm/Support/raw_ostream.h"
using namespace clang;
+/// \brief Find the current instantiation that associated with the given type.
+static CXXRecordDecl *
+getCurrentInstantiationOf(ASTContext &Context, DeclContext *CurContext,
+ QualType T) {
+ if (T.isNull())
+ return 0;
+
+ T = Context.getCanonicalType(T);
+
+ for (DeclContext *Ctx = CurContext; Ctx; Ctx = Ctx->getParent()) {
+ // If we've hit a namespace or the global scope, then the
+ // nested-name-specifier can't refer to the current instantiation.
+ if (Ctx->isFileContext())
+ return 0;
+
+ // Skip non-class contexts.
+ CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Ctx);
+ if (!Record)
+ continue;
+
+ // If this record type is not dependent,
+ if (!Record->isDependentType())
+ return 0;
+
+ // C++ [temp.dep.type]p1:
+ //
+ // In the definition of a class template, a nested class of a
+ // class template, a member of a class template, or a member of a
+ // nested class of a class template, a name refers to the current
+ // instantiation if it is
+ // -- the injected-class-name (9) of the class template or
+ // nested class,
+ // -- in the definition of a primary class template, the name
+ // of the class template followed by the template argument
+ // list of the primary template (as described below)
+ // enclosed in <>,
+ // -- in the definition of a nested class of a class template,
+ // the name of the nested class referenced as a member of
+ // the current instantiation, or
+ // -- in the definition of a partial specialization, the name
+ // of the class template followed by the template argument
+ // list of the partial specialization enclosed in <>. If
+ // the nth template parameter is a parameter pack, the nth
+ // template argument is a pack expansion (14.6.3) whose
+ // pattern is the name of the parameter pack.
+ // (FIXME: parameter packs)
+ //
+ // All of these options come down to having the
+ // nested-name-specifier type that is equivalent to the
+ // injected-class-name of one of the types that is currently in
+ // our context.
+ if (Context.getCanonicalType(Context.getTypeDeclType(Record)) == T)
+ return Record;
+
+ if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
+ QualType InjectedClassName
+ = Template->getInjectedClassNameType(Context);
+ if (T == Context.getCanonicalType(InjectedClassName))
+ return Template->getTemplatedDecl();
+ }
+ // FIXME: check for class template partial specializations
+ }
+
+ return 0;
+}
+
/// \brief Compute the DeclContext that is associated with the given type.
///
/// \param T the type for which we are attempting to find a DeclContext.
@@ -33,7 +99,7 @@ DeclContext *Sema::computeDeclContext(QualType T) {
if (const TagType *Tag = T->getAs<TagType>())
return Tag->getDecl();
- return 0;
+ return ::getCurrentInstantiationOf(Context, CurContext, T);
}
/// \brief Compute the DeclContext that is associated with the given
@@ -156,68 +222,7 @@ CXXRecordDecl *Sema::getCurrentInstantiationOf(NestedNameSpecifier *NNS) {
return 0;
QualType T = QualType(NNS->getAsType(), 0);
- // If the nested name specifier does not refer to a type, then it
- // does not refer to the current instantiation.
- if (T.isNull())
- return 0;
-
- T = Context.getCanonicalType(T);
-
- for (DeclContext *Ctx = CurContext; Ctx; Ctx = Ctx->getParent()) {
- // If we've hit a namespace or the global scope, then the
- // nested-name-specifier can't refer to the current instantiation.
- if (Ctx->isFileContext())
- return 0;
-
- // Skip non-class contexts.
- CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Ctx);
- if (!Record)
- continue;
-
- // If this record type is not dependent,
- if (!Record->isDependentType())
- return 0;
-
- // C++ [temp.dep.type]p1:
- //
- // In the definition of a class template, a nested class of a
- // class template, a member of a class template, or a member of a
- // nested class of a class template, a name refers to the current
- // instantiation if it is
- // -- the injected-class-name (9) of the class template or
- // nested class,
- // -- in the definition of a primary class template, the name
- // of the class template followed by the template argument
- // list of the primary template (as described below)
- // enclosed in <>,
- // -- in the definition of a nested class of a class template,
- // the name of the nested class referenced as a member of
- // the current instantiation, or
- // -- in the definition of a partial specialization, the name
- // of the class template followed by the template argument
- // list of the partial specialization enclosed in <>. If
- // the nth template parameter is a parameter pack, the nth
- // template argument is a pack expansion (14.6.3) whose
- // pattern is the name of the parameter pack.
- // (FIXME: parameter packs)
- //
- // All of these options come down to having the
- // nested-name-specifier type that is equivalent to the
- // injected-class-name of one of the types that is currently in
- // our context.
- if (Context.getCanonicalType(Context.getTypeDeclType(Record)) == T)
- return Record;
-
- if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
- QualType InjectedClassName
- = Template->getInjectedClassNameType(Context);
- if (T == Context.getCanonicalType(InjectedClassName))
- return Template->getTemplatedDecl();
- }
- // FIXME: check for class template partial specializations
- }
-
- return 0;
+ return ::getCurrentInstantiationOf(Context, CurContext, T);
}
/// \brief Require that the context specified by SS be complete.
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index bc255137fccf..b8977cfa142d 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -971,10 +971,70 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD,
RParenLoc, ClassDecl);
}
+/// Checks an initializer expression for use of uninitialized fields, such as
+/// containing the field that is being initialized. Returns true if there is an
+/// uninitialized field was used an updates the SourceLocation parameter; false
+/// otherwise.
+static bool InitExprContainsUninitializedFields(const Stmt* S,
+ const FieldDecl* LhsField,
+ SourceLocation* L) {
+ const MemberExpr* ME = dyn_cast<MemberExpr>(S);
+ if (ME) {
+ const NamedDecl* RhsField = ME->getMemberDecl();
+ if (RhsField == LhsField) {
+ // Initializing a field with itself. Throw a warning.
+ // But wait; there are exceptions!
+ // Exception #1: The field may not belong to this record.
+ // e.g. Foo(const Foo& rhs) : A(rhs.A) {}
+ const Expr* base = ME->getBase();
+ if (base != NULL && !isa<CXXThisExpr>(base->IgnoreParenCasts())) {
+ // Even though the field matches, it does not belong to this record.
+ return false;
+ }
+ // None of the exceptions triggered; return true to indicate an
+ // uninitialized field was used.
+ *L = ME->getMemberLoc();
+ return true;
+ }
+ }
+ bool found = false;
+ for (Stmt::const_child_iterator it = S->child_begin();
+ it != S->child_end() && found == false;
+ ++it) {
+ if (isa<CallExpr>(S)) {
+ // Do not descend into function calls or constructors, as the use
+ // of an uninitialized field may be valid. One would have to inspect
+ // the contents of the function/ctor to determine if it is safe or not.
+ // i.e. Pass-by-value is never safe, but pass-by-reference and pointers
+ // may be safe, depending on what the function/ctor does.
+ continue;
+ }
+ found = InitExprContainsUninitializedFields(*it, LhsField, L);
+ }
+ return found;
+}
+
Sema::MemInitResult
Sema::BuildMemberInitializer(FieldDecl *Member, Expr **Args,
unsigned NumArgs, SourceLocation IdLoc,
SourceLocation RParenLoc) {
+ // Diagnose value-uses of fields to initialize themselves, e.g.
+ // foo(foo)
+ // where foo is not also a parameter to the constructor.
+ // TODO: implement -Wuninitialized and fold this into that framework.
+ for (unsigned i = 0; i < NumArgs; ++i) {
+ SourceLocation L;
+ if (InitExprContainsUninitializedFields(Args[i], Member, &L)) {
+ // FIXME: Return true in the case when other fields are used before being
+ // uninitialized. For example, let this field be the i'th field. When
+ // initializing the i'th field, throw a warning if any of the >= i'th
+ // fields are used, as they are not yet initialized.
+ // Right now we are only handling the case where the i'th field uses
+ // itself in its initializer.
+ Diag(L, diag::warn_field_is_uninit);
+ }
+ }
+
bool HasDependentArg = false;
for (unsigned i = 0; i < NumArgs; i++)
HasDependentArg |= Args[i]->isTypeDependent();
@@ -985,7 +1045,9 @@ Sema::BuildMemberInitializer(FieldDecl *Member, Expr **Args,
FieldType = Array->getElementType();
if (FieldType->isDependentType()) {
// Can't check init for dependent type.
- } else if (FieldType->getAs<RecordType>()) {
+ } else if (FieldType->isRecordType()) {
+ // Member is a record (struct/union/class), so pass the initializer
+ // arguments down to the record's constructor.
if (!HasDependentArg) {
ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this);
@@ -1005,6 +1067,8 @@ Sema::BuildMemberInitializer(FieldDecl *Member, Expr **Args,
}
}
} else if (NumArgs != 1 && NumArgs != 0) {
+ // The member type is not a record type (or an array of record
+ // types), so it can be only be default- or copy-initialized.
return Diag(IdLoc, diag::err_mem_initializer_mismatch)
<< Member->getDeclName() << SourceRange(IdLoc, RParenLoc);
} else if (!HasDependentArg) {
@@ -1158,7 +1222,7 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
// On seeing one dependent type, we should essentially exit this routine
// while preserving user-declared initializer list. When this routine is
// called during instantiatiation process, this routine will rebuild the
- // oderdered initializer list correctly.
+ // ordered initializer list correctly.
// If we have a dependent base initialization, we can't determine the
// association between initializers and bases; just dump the known
@@ -1293,11 +1357,16 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
continue;
}
+ if ((*Field)->getType()->isDependentType()) {
+ Fields.push_back(*Field);
+ continue;
+ }
+
QualType FT = Context.getBaseElementType((*Field)->getType());
if (const RecordType* RT = FT->getAs<RecordType>()) {
CXXConstructorDecl *Ctor =
cast<CXXRecordDecl>(RT->getDecl())->getDefaultConstructor(Context);
- if (!Ctor && !FT->isDependentType()) {
+ if (!Ctor) {
Fields.push_back(*Field);
continue;
}
@@ -1357,12 +1426,16 @@ Sema::BuildBaseOrMemberInitializers(ASTContext &C,
SetBaseOrMemberInitializers(Constructor,
Initializers, NumInitializers, Bases, Members);
- for (unsigned int i = 0; i < Bases.size(); i++)
- Diag(Bases[i]->getSourceRange().getBegin(),
- diag::err_missing_default_constructor) << 0 << Bases[i]->getType();
- for (unsigned int i = 0; i < Members.size(); i++)
- Diag(Members[i]->getLocation(), diag::err_missing_default_constructor)
- << 1 << Members[i]->getType();
+ for (unsigned int i = 0; i < Bases.size(); i++) {
+ if (!Bases[i]->getType()->isDependentType())
+ Diag(Bases[i]->getSourceRange().getBegin(),
+ diag::err_missing_default_constructor) << 0 << Bases[i]->getType();
+ }
+ for (unsigned int i = 0; i < Members.size(); i++) {
+ if (!Members[i]->getType()->isDependentType())
+ Diag(Members[i]->getLocation(), diag::err_missing_default_constructor)
+ << 1 << Members[i]->getType();
+ }
}
static void *GetKeyForTopLevelField(FieldDecl *Field) {
@@ -1405,6 +1478,7 @@ static void *GetKeyForMember(CXXBaseOrMemberInitializer *Member,
return GetKeyForBase(QualType(Member->getBaseClass(), 0));
}
+/// ActOnMemInitializers - Handle the member initializers for a constructor.
void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl,
SourceLocation ColonLoc,
MemInitTy **MemInits, unsigned NumMemInits) {
@@ -2700,22 +2774,37 @@ Sema::DeclPtrTy Sema::ActOnUsingDeclaration(Scope *S,
AccessSpecifier AS,
SourceLocation UsingLoc,
const CXXScopeSpec &SS,
- SourceLocation IdentLoc,
- IdentifierInfo *TargetName,
- OverloadedOperatorKind Op,
+ UnqualifiedId &Name,
AttributeList *AttrList,
bool IsTypeName) {
- assert((TargetName || Op) && "Invalid TargetName.");
assert(S->getFlags() & Scope::DeclScope && "Invalid Scope.");
- DeclarationName Name;
- if (TargetName)
- Name = TargetName;
- else
- Name = Context.DeclarationNames.getCXXOperatorName(Op);
-
- NamedDecl *UD = BuildUsingDeclaration(UsingLoc, SS, IdentLoc,
- Name, AttrList, IsTypeName);
+ switch (Name.getKind()) {
+ case UnqualifiedId::IK_Identifier:
+ case UnqualifiedId::IK_OperatorFunctionId:
+ case UnqualifiedId::IK_ConversionFunctionId:
+ break;
+
+ case UnqualifiedId::IK_ConstructorName:
+ Diag(Name.getSourceRange().getBegin(), diag::err_using_decl_constructor)
+ << SS.getRange();
+ return DeclPtrTy();
+
+ case UnqualifiedId::IK_DestructorName:
+ Diag(Name.getSourceRange().getBegin(), diag::err_using_decl_destructor)
+ << SS.getRange();
+ return DeclPtrTy();
+
+ case UnqualifiedId::IK_TemplateId:
+ Diag(Name.getSourceRange().getBegin(), diag::err_using_decl_template_id)
+ << SourceRange(Name.TemplateId->LAngleLoc, Name.TemplateId->RAngleLoc);
+ return DeclPtrTy();
+ }
+
+ DeclarationName TargetName = GetNameFromUnqualifiedId(Name);
+ NamedDecl *UD = BuildUsingDeclaration(UsingLoc, SS,
+ Name.getSourceRange().getBegin(),
+ TargetName, AttrList, IsTypeName);
if (UD) {
PushOnScopeChains(UD, S);
UD->setAccess(AS);
@@ -3515,14 +3604,15 @@ Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor,
/// type, and the first type (T1) is the pointee type of the reference
/// type being initialized.
Sema::ReferenceCompareResult
-Sema::CompareReferenceRelationship(QualType T1, QualType T2,
+Sema::CompareReferenceRelationship(SourceLocation Loc,
+ QualType OrigT1, QualType OrigT2,
bool& DerivedToBase) {
- assert(!T1->isReferenceType() &&
+ assert(!OrigT1->isReferenceType() &&
"T1 must be the pointee type of the reference type");
- assert(!T2->isReferenceType() && "T2 cannot be a reference type");
+ assert(!OrigT2->isReferenceType() && "T2 cannot be a reference type");
- T1 = Context.getCanonicalType(T1);
- T2 = Context.getCanonicalType(T2);
+ QualType T1 = Context.getCanonicalType(OrigT1);
+ QualType T2 = Context.getCanonicalType(OrigT2);
QualType UnqualT1 = T1.getUnqualifiedType();
QualType UnqualT2 = T2.getUnqualifiedType();
@@ -3532,7 +3622,9 @@ Sema::CompareReferenceRelationship(QualType T1, QualType T2,
// T1 is a base class of T2.
if (UnqualT1 == UnqualT2)
DerivedToBase = false;
- else if (IsDerivedFrom(UnqualT2, UnqualT1))
+ else if (!RequireCompleteType(Loc, OrigT1, PDiag()) &&
+ !RequireCompleteType(Loc, OrigT2, PDiag()) &&
+ IsDerivedFrom(UnqualT2, UnqualT1))
DerivedToBase = true;
else
return Ref_Incompatible;
@@ -3608,7 +3700,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType,
Expr::isLvalueResult InitLvalue = ForceRValue ? Expr::LV_InvalidExpression :
Init->isLvalue(Context);
ReferenceCompareResult RefRelationship
- = CompareReferenceRelationship(T1, T2, DerivedToBase);
+ = CompareReferenceRelationship(DeclLoc, T1, T2, DerivedToBase);
// Most paths end in a failed conversion.
if (ICS)
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index ac7cced2eaef..f1d6f2bb17ce 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -3340,6 +3340,8 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
if (getLangOptions().CPlusPlus)
return CXXCheckConditionalOperands(Cond, LHS, RHS, QuestionLoc);
+ CheckSignCompare(LHS, RHS, QuestionLoc, diag::warn_mixed_sign_conditional);
+
UsualUnaryConversions(Cond);
UsualUnaryConversions(LHS);
UsualUnaryConversions(RHS);
@@ -4427,6 +4429,41 @@ QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
return LHSTy;
}
+/// Implements -Wsign-compare.
+void Sema::CheckSignCompare(Expr *lex, Expr *rex, SourceLocation OpLoc,
+ const PartialDiagnostic &PD) {
+ QualType lt = lex->getType(), rt = rex->getType();
+
+ // Only warn if both operands are integral.
+ if (!lt->isIntegerType() || !rt->isIntegerType())
+ return;
+
+ // The rule is that the signed operand becomes unsigned, so isolate the
+ // signed operand.
+ Expr *signedOperand;
+ if (lt->isSignedIntegerType()) {
+ if (rt->isSignedIntegerType()) return;
+ signedOperand = lex;
+ } else {
+ if (!rt->isSignedIntegerType()) return;
+ signedOperand = rex;
+ }
+
+ // If the value is a non-negative integer constant, then the
+ // signed->unsigned conversion won't change it.
+ llvm::APSInt value;
+ if (signedOperand->isIntegerConstantExpr(value, Context)) {
+ assert(value.isSigned() && "result of signed expression not signed");
+
+ if (value.isNonNegative())
+ return;
+ }
+
+ Diag(OpLoc, PD)
+ << lex->getType() << rex->getType()
+ << lex->getSourceRange() << rex->getSourceRange();
+}
+
// C99 6.5.8, C++ [expr.rel]
QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
unsigned OpaqueOpc, bool isRelational) {
@@ -4435,6 +4472,8 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
return CheckVectorCompareOperands(lex, rex, Loc, isRelational);
+ CheckSignCompare(lex, rex, Loc, diag::warn_mixed_sign_comparison);
+
// C99 6.5.8p3 / C99 6.5.9p4
if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType())
UsualArithmeticConversions(lex, rex);
@@ -5472,6 +5511,12 @@ Action::OwningExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc,
// Emit warnings for tricky precedence issues, e.g. "bitfield & 0x4 == 0"
DiagnoseBinOpPrecedence(*this, Opc, TokLoc, lhs, rhs);
+ return BuildBinOp(S, TokLoc, Opc, lhs, rhs);
+}
+
+Action::OwningExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc,
+ BinaryOperator::Opcode Opc,
+ Expr *lhs, Expr *rhs) {
if (getLangOptions().CPlusPlus &&
(lhs->getType()->isOverloadableType() ||
rhs->getType()->isOverloadableType())) {
@@ -5482,21 +5527,22 @@ Action::OwningExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc,
FunctionSet Functions;
OverloadedOperatorKind OverOp = BinaryOperator::getOverloadedOperator(Opc);
if (OverOp != OO_None) {
- LookupOverloadedOperatorName(OverOp, S, lhs->getType(), rhs->getType(),
- Functions);
+ if (S)
+ LookupOverloadedOperatorName(OverOp, S, lhs->getType(), rhs->getType(),
+ Functions);
Expr *Args[2] = { lhs, rhs };
DeclarationName OpName
= Context.DeclarationNames.getCXXOperatorName(OverOp);
ArgumentDependentLookup(OpName, /*Operator*/true, Args, 2, Functions);
}
-
+
// Build the (potentially-overloaded, potentially-dependent)
// binary operation.
- return CreateOverloadedBinOp(TokLoc, Opc, Functions, lhs, rhs);
+ return CreateOverloadedBinOp(OpLoc, Opc, Functions, lhs, rhs);
}
-
+
// Build a built-in binary operation.
- return CreateBuiltinBinOp(TokLoc, Opc, lhs, rhs);
+ return CreateBuiltinBinOp(OpLoc, Opc, lhs, rhs);
}
Action::OwningExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
@@ -5587,12 +5633,10 @@ Action::OwningExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
return Owned(new (Context) UnaryOperator(Input, Opc, resultType, OpLoc));
}
-// Unary Operators. 'Tok' is the token for the operator.
-Action::OwningExprResult Sema::ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
- tok::TokenKind Op, ExprArg input) {
+Action::OwningExprResult Sema::BuildUnaryOp(Scope *S, SourceLocation OpLoc,
+ UnaryOperator::Opcode Opc,
+ ExprArg input) {
Expr *Input = (Expr*)input.get();
- UnaryOperator::Opcode Opc = ConvertTokenKindToUnaryOpcode(Op);
-
if (getLangOptions().CPlusPlus && Input->getType()->isOverloadableType()) {
// Find all of the overloaded operators visible from this
// point. We perform both an operator-name lookup from the local
@@ -5601,19 +5645,26 @@ Action::OwningExprResult Sema::ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
FunctionSet Functions;
OverloadedOperatorKind OverOp = UnaryOperator::getOverloadedOperator(Opc);
if (OverOp != OO_None) {
- LookupOverloadedOperatorName(OverOp, S, Input->getType(), QualType(),
- Functions);
+ if (S)
+ LookupOverloadedOperatorName(OverOp, S, Input->getType(), QualType(),
+ Functions);
DeclarationName OpName
= Context.DeclarationNames.getCXXOperatorName(OverOp);
ArgumentDependentLookup(OpName, /*Operator*/true, &Input, 1, Functions);
}
-
+
return CreateOverloadedUnaryOp(OpLoc, Opc, Functions, move(input));
}
-
+
return CreateBuiltinUnaryOp(OpLoc, Opc, move(input));
}
+// Unary Operators. 'Tok' is the token for the operator.
+Action::OwningExprResult Sema::ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
+ tok::TokenKind Op, ExprArg input) {
+ return BuildUnaryOp(S, OpLoc, ConvertTokenKindToUnaryOpcode(Op), move(input));
+}
+
/// ActOnAddrLabel - Parse the GNU address of label extension: "&&foo".
Sema::OwningExprResult Sema::ActOnAddrLabel(SourceLocation OpLoc,
SourceLocation LabLoc,
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 4868c14835f4..dc5768157356 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -1603,6 +1603,8 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
if (LHS->isTypeDependent() || RHS->isTypeDependent())
return Context.DependentTy;
+ CheckSignCompare(LHS, RHS, QuestionLoc, diag::warn_mixed_sign_conditional);
+
// C++0x 5.16p2
// If either the second or the third operand has type (cv) void, ...
QualType LTy = LHS->getType();
@@ -2030,7 +2032,13 @@ Sema::ActOnStartCXXMemberReference(Scope *S, ExprArg Base, SourceLocation OpLoc,
QualType BaseType = BaseExpr->getType();
if (BaseType->isDependentType()) {
- // FIXME: member of the current instantiation
+ // If we have a pointer to a dependent type and are using the -> operator,
+ // the object type is the type that the pointer points to. We might still
+ // have enough information about that type to do something useful.
+ if (OpKind == tok::arrow)
+ if (const PointerType *Ptr = BaseType->getAs<PointerType>())
+ BaseType = Ptr->getPointeeType();
+
ObjectType = BaseType.getAsOpaquePtr();
return move(Base);
}
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 946e28269eb6..3e6778bc4770 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -1387,8 +1387,10 @@ Sema::OverloadingResult Sema::IsUserDefinedConversion(
bool AllowExplicit, bool ForceRValue,
bool UserCast) {
if (const RecordType *ToRecordType = ToType->getAs<RecordType>()) {
- if (CXXRecordDecl *ToRecordDecl
- = dyn_cast<CXXRecordDecl>(ToRecordType->getDecl())) {
+ if (RequireCompleteType(From->getLocStart(), ToType, PDiag())) {
+ // We're not going to find any constructors.
+ } else if (CXXRecordDecl *ToRecordDecl
+ = dyn_cast<CXXRecordDecl>(ToRecordType->getDecl())) {
// C++ [over.match.ctor]p1:
// When objects of class type are direct-initialized (8.5), or
// copy-initialized from an expression of the same or a
@@ -2097,8 +2099,8 @@ Sema::TryObjectArgumentInitialization(Expr *From, CXXMethodDecl *Method) {
// First check the qualifiers. We don't care about lvalue-vs-rvalue
// with the implicit object parameter (C++ [over.match.funcs]p5).
QualType FromTypeCanon = Context.getCanonicalType(FromType);
- if (ImplicitParamType.getCVRQualifiers() != FromType.getCVRQualifiers() &&
- !ImplicitParamType.isAtLeastAsQualifiedAs(FromType))
+ if (ImplicitParamType.getCVRQualifiers() != FromTypeCanon.getCVRQualifiers() &&
+ !ImplicitParamType.isAtLeastAsQualifiedAs(FromTypeCanon))
return ICS;
// Check that we have either the same type or a derived type. It
@@ -3050,6 +3052,10 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty,
// We don't care about qualifiers on the type.
Ty = Ty.getUnqualifiedType();
+ // If we're dealing with an array type, decay to the pointer.
+ if (Ty->isArrayType())
+ Ty = SemaRef.Context.getArrayDecayedType(Ty);
+
if (const PointerType *PointerTy = Ty->getAs<PointerType>()) {
QualType PointeeTy = PointerTy->getPointeeType();
@@ -4787,11 +4793,20 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
// If either side is type-dependent, create an appropriate dependent
// expression.
if (Args[0]->isTypeDependent() || Args[1]->isTypeDependent()) {
- // .* cannot be overloaded.
- if (Opc == BinaryOperator::PtrMemD)
- return Owned(new (Context) BinaryOperator(Args[0], Args[1], Opc,
- Context.DependentTy, OpLoc));
-
+ if (Functions.empty()) {
+ // If there are no functions to store, just build a dependent
+ // BinaryOperator or CompoundAssignment.
+ if (Opc <= BinaryOperator::Assign || Opc > BinaryOperator::OrAssign)
+ return Owned(new (Context) BinaryOperator(Args[0], Args[1], Opc,
+ Context.DependentTy, OpLoc));
+
+ return Owned(new (Context) CompoundAssignOperator(Args[0], Args[1], Opc,
+ Context.DependentTy,
+ Context.DependentTy,
+ Context.DependentTy,
+ OpLoc));
+ }
+
OverloadedFunctionDecl *Overloads
= OverloadedFunctionDecl::Create(Context, CurContext, OpName);
for (FunctionSet::iterator Func = Functions.begin(),
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 3c56358d5a94..5ef370104dd9 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -1995,7 +1995,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
ArgType = Context.getCanonicalType(ArgType).getUnqualifiedType();
// Try to convert the argument to the parameter's type.
- if (ParamType == ArgType) {
+ if (Context.hasSameType(ParamType, ArgType)) {
// Okay: no conversion necessary
} else if (IsIntegralPromotion(Arg, ArgType, ParamType) ||
!ParamType->isEnumeralType()) {
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 0003b1b0c419..f003127f149f 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -22,6 +22,7 @@
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Parse/DeclSpec.h"
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/Support/ErrorHandling.h"
using namespace clang;
/// \brief Perform adjustment on the parameter type of a function.
@@ -562,9 +563,17 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
SourceLocation Loc = Brackets.getBegin();
// C99 6.7.5.2p1: If the element type is an incomplete or function type,
// reject it (e.g. void ary[7], struct foo ary[7], void ary[7]())
- if (RequireCompleteType(Loc, T,
- diag::err_illegal_decl_array_incomplete_type))
- return QualType();
+ // Not in C++, though. There we only dislike void.
+ if (getLangOptions().CPlusPlus) {
+ if (T->isVoidType()) {
+ Diag(Loc, diag::err_illegal_decl_array_incomplete_type) << T;
+ return QualType();
+ }
+ } else {
+ if (RequireCompleteType(Loc, T,
+ diag::err_illegal_decl_array_incomplete_type))
+ return QualType();
+ }
if (T->isFunctionType()) {
Diag(Loc, diag::err_illegal_decl_array_of_functions)
@@ -612,24 +621,24 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
} else if (ArraySize->isValueDependent()) {
T = Context.getDependentSizedArrayType(T, ArraySize, ASM, Quals, Brackets);
} else if (!ArraySize->isIntegerConstantExpr(ConstVal, Context) ||
- (!T->isDependentType() && !T->isConstantSizeType())) {
+ (!T->isDependentType() && !T->isIncompleteType() &&
+ !T->isConstantSizeType())) {
// Per C99, a variable array is an array with either a non-constant
// size or an element type that has a non-constant-size
T = Context.getVariableArrayType(T, ArraySize, ASM, Quals, Brackets);
} else {
// C99 6.7.5.2p1: If the expression is a constant expression, it shall
// have a value greater than zero.
- if (ConstVal.isSigned()) {
- if (ConstVal.isNegative()) {
- Diag(ArraySize->getLocStart(),
- diag::err_typecheck_negative_array_size)
- << ArraySize->getSourceRange();
- return QualType();
- } else if (ConstVal == 0) {
- // GCC accepts zero sized static arrays.
- Diag(ArraySize->getLocStart(), diag::ext_typecheck_zero_array_size)
- << ArraySize->getSourceRange();
- }
+ if (ConstVal.isSigned() && ConstVal.isNegative()) {
+ Diag(ArraySize->getLocStart(),
+ diag::err_typecheck_negative_array_size)
+ << ArraySize->getSourceRange();
+ return QualType();
+ }
+ if (ConstVal == 0) {
+ // GCC accepts zero sized static arrays.
+ Diag(ArraySize->getLocStart(), diag::ext_typecheck_zero_array_size)
+ << ArraySize->getSourceRange();
}
T = Context.getConstantArrayType(T, ConstVal, ASM, Quals);
}
@@ -1162,15 +1171,29 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
}
// The scope spec must refer to a class, or be dependent.
QualType ClsType;
- if (isDependentScopeSpecifier(DeclType.Mem.Scope())) {
+ if (isDependentScopeSpecifier(DeclType.Mem.Scope())
+ || dyn_cast_or_null<CXXRecordDecl>(
+ computeDeclContext(DeclType.Mem.Scope()))) {
NestedNameSpecifier *NNS
= (NestedNameSpecifier *)DeclType.Mem.Scope().getScopeRep();
- assert(NNS->getAsType() && "Nested-name-specifier must name a type");
- ClsType = QualType(NNS->getAsType(), 0);
- } else if (CXXRecordDecl *RD
- = dyn_cast_or_null<CXXRecordDecl>(
- computeDeclContext(DeclType.Mem.Scope()))) {
- ClsType = Context.getTagDeclType(RD);
+ NestedNameSpecifier *NNSPrefix = NNS->getPrefix();
+ switch (NNS->getKind()) {
+ case NestedNameSpecifier::Identifier:
+ ClsType = Context.getTypenameType(NNSPrefix, NNS->getAsIdentifier());
+ break;
+
+ case NestedNameSpecifier::Namespace:
+ case NestedNameSpecifier::Global:
+ llvm::llvm_unreachable("Nested-name-specifier must name a type");
+ break;
+
+ case NestedNameSpecifier::TypeSpec:
+ case NestedNameSpecifier::TypeSpecWithTemplate:
+ ClsType = QualType(NNS->getAsType(), 0);
+ if (NNSPrefix)
+ ClsType = Context.getQualifiedNameType(NNSPrefix, ClsType);
+ break;
+ }
} else {
Diag(DeclType.Mem.Scope().getBeginLoc(),
diag::err_illegal_decl_mempointer_in_nonclass)
@@ -1677,8 +1700,12 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
return false;
// If we have a class template specialization or a class member of a
- // class template specialization, try to instantiate it.
- if (const RecordType *Record = T->getAs<RecordType>()) {
+ // class template specialization, or an array with known size of such,
+ // try to instantiate it.
+ QualType MaybeTemplate = T;
+ if (const ConstantArrayType *Array = T->getAs<ConstantArrayType>())
+ MaybeTemplate = Array->getElementType();
+ if (const RecordType *Record = MaybeTemplate->getAs<RecordType>()) {
if (ClassTemplateSpecializationDecl *ClassTemplateSpec
= dyn_cast<ClassTemplateSpecializationDecl>(Record->getDecl())) {
if (ClassTemplateSpec->getSpecializationKind() == TSK_Undeclared)
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 5713da9fa590..767725a1f318 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -877,7 +877,7 @@ public:
OwningExprResult RebuildUnaryOperator(SourceLocation OpLoc,
UnaryOperator::Opcode Opc,
ExprArg SubExpr) {
- return getSema().CreateBuiltinUnaryOp(OpLoc, Opc, move(SubExpr));
+ return getSema().BuildUnaryOp(/*Scope=*/0, OpLoc, Opc, move(SubExpr));
}
/// \brief Build a new sizeof or alignof expression with a type argument.
@@ -941,7 +941,13 @@ public:
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
SourceLocation MemberLoc,
- NamedDecl *Member) {
+ NamedDecl *Member,
+ bool HasExplicitTemplateArgs,
+ SourceLocation LAngleLoc,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
+ unsigned NumExplicitTemplateArgs,
+ SourceLocation RAngleLoc,
+ NamedDecl *FirstQualifierInScope) {
if (!Member->getDeclName()) {
// We have a reference to an unnamed field.
assert(!Qualifier && "Can't have an unnamed field with a qualifier!");
@@ -963,8 +969,14 @@ public:
isArrow? tok::arrow : tok::period,
MemberLoc,
Member->getDeclName(),
+ HasExplicitTemplateArgs,
+ LAngleLoc,
+ ExplicitTemplateArgs,
+ NumExplicitTemplateArgs,
+ RAngleLoc,
/*FIXME?*/Sema::DeclPtrTy::make((Decl*)0),
- &SS);
+ &SS,
+ FirstQualifierInScope);
}
/// \brief Build a new binary operator expression.
@@ -974,15 +986,8 @@ public:
OwningExprResult RebuildBinaryOperator(SourceLocation OpLoc,
BinaryOperator::Opcode Opc,
ExprArg LHS, ExprArg RHS) {
- OwningExprResult Result
- = getSema().CreateBuiltinBinOp(OpLoc, Opc, (Expr *)LHS.get(),
- (Expr *)RHS.get());
- if (Result.isInvalid())
- return SemaRef.ExprError();
-
- LHS.release();
- RHS.release();
- return move(Result);
+ return getSema().BuildBinOp(/*Scope=*/0, OpLoc, Opc,
+ LHS.takeAs<Expr>(), RHS.takeAs<Expr>());
}
/// \brief Build a new conditional operator expression.
@@ -3656,9 +3661,20 @@ TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E,
if (!getDerived().AlwaysRebuild() &&
Base.get() == E->getBase() &&
Qualifier == E->getQualifier() &&
- Member == E->getMemberDecl())
+ Member == E->getMemberDecl() &&
+ !E->hasExplicitTemplateArgumentList())
return SemaRef.Owned(E->Retain());
+ llvm::SmallVector<TemplateArgumentLoc, 4> TransArgs;
+ if (E->hasExplicitTemplateArgumentList()) {
+ TransArgs.resize(E->getNumTemplateArgs());
+ for (unsigned I = 0, N = E->getNumTemplateArgs(); I != N; ++I) {
+ if (getDerived().TransformTemplateArgument(E->getTemplateArgs()[I],
+ TransArgs[I]))
+ return SemaRef.ExprError();
+ }
+ }
+
// FIXME: Bogus source location for the operator
SourceLocation FakeOperatorLoc
= SemaRef.PP.getLocForEndOfToken(E->getBase()->getSourceRange().getEnd());
@@ -3668,7 +3684,13 @@ TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E,
Qualifier,
E->getQualifierRange(),
E->getMemberLoc(),
- Member);
+ Member,
+ E->hasExplicitTemplateArgumentList(),
+ E->getLAngleLoc(),
+ TransArgs.data(),
+ TransArgs.size(),
+ E->getRAngleLoc(),
+ 0);
}
template<typename Derived>
diff --git a/test/Analysis/misc-ps.m b/test/Analysis/misc-ps.m
index 947b41ae794c..80e20c1ebb00 100644
--- a/test/Analysis/misc-ps.m
+++ b/test/Analysis/misc-ps.m
@@ -121,12 +121,12 @@ void check_zero_sized_VLA(int x) {
if (x)
return;
- int vla[x]; // expected-warning{{Declare variable-length array (VLA) of zero size}}
+ int vla[x]; // expected-warning{{Declared variable-length array (VLA) has zero size}}
}
void check_uninit_sized_VLA() {
int x;
- int vla[x]; // expected-warning{{Declare variable-length array (VLA) of undefined size}}
+ int vla[x]; // expected-warning{{Declared variable-length array (VLA) uses a garbage value as its size}}
}
// sizeof(void)
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index a83a1993c8f0..8b3c738ed78b 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -45,6 +45,7 @@ if(PYTHONINTERP_FOUND)
${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
COMMAND ${PYTHON_EXECUTABLE}
${LLVM_SOURCE_DIR}/utils/lit/lit.py
+ --param clang_site_config=${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
-sv ${CLANG_TEST_EXTRA_ARGS}
${CMAKE_CURRENT_BINARY_DIR}/${testdir}
DEPENDS clang clang-cc index-test c-index-test
@@ -63,6 +64,7 @@ if(PYTHONINTERP_FOUND)
${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
COMMAND ${PYTHON_EXECUTABLE}
${LLVM_SOURCE_DIR}/utils/lit/lit.py
+ --param clang_site_config=${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
-sv ${CLANG_TEST_EXTRA_ARGS}
${CMAKE_CURRENT_BINARY_DIR}
DEPENDS clang clang-cc index-test c-index-test
@@ -80,6 +82,7 @@ if(PYTHONINTERP_FOUND)
${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
COMMAND ${PYTHON_EXECUTABLE}
${LLVM_SOURCE_DIR}/utils/lit/lit.py
+ --param clang_site_config=${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
-sv ${CLANG_TEST_EXTRA_ARGS}
${CMAKE_CURRENT_SOURCE_DIR}/../utils/C++Tests
DEPENDS clang clang-cc index-test c-index-test
diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p5-cxx0x.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p5-cxx0x.cpp
index 63e5c3cd27b0..31218c41300f 100644
--- a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p5-cxx0x.cpp
+++ b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p5-cxx0x.cpp
@@ -7,6 +7,6 @@ struct A {
};
struct B : A {
- using A::f<double>; // expected-error{{using declaration can not refer to template specialization}}
- using A::X<int>; // expected-error{{using declaration can not refer to template specialization}}
-}; \ No newline at end of file
+ using A::f<double>; // expected-error{{using declaration can not refer to a template specialization}}
+ using A::X<int>; // expected-error{{using declaration can not refer to a template specialization}}
+};
diff --git a/test/CodeGenCXX/array-construction.cpp b/test/CodeGenCXX/array-construction.cpp
index b444221533d3..5b6bc2e5b511 100644
--- a/test/CodeGenCXX/array-construction.cpp
+++ b/test/CodeGenCXX/array-construction.cpp
@@ -17,12 +17,9 @@ public:
int i;
float f;
-/**
- NYI
~xpto() {
printf("xpto::~xpto()\n");
}
-*/
};
int main() {
diff --git a/test/CodeGenCXX/ptr-to-datamember.cpp b/test/CodeGenCXX/ptr-to-datamember.cpp
index a7b4cc2f7afb..ffaef32a13c9 100644
--- a/test/CodeGenCXX/ptr-to-datamember.cpp
+++ b/test/CodeGenCXX/ptr-to-datamember.cpp
@@ -32,6 +32,15 @@ public:
F Af;
};
+template <typename T> struct TT {
+ int T::t::*pti;
+};
+
+struct I {
+ typedef I t;
+ int x;
+};
+
void pr(const F& b) {
printf(" %d %f\n", b.iF, b.fF);
}
@@ -69,9 +78,12 @@ void test_aggr_pdata_1(A* pa) {
int main()
{
A a1;
+ TT<I> tt;
+ I i;
int A::* pa = &A::Ai;
float A::* pf = &A::f;
double A::* pd = &A::d;
+ tt.pti = &I::x;
printf("%d %d %d\n", &A::Ai, &A::f, &A::d);
printf("%d\n", &A::B::iB);
printf("%d\n", &A::B1::iB1);
@@ -81,6 +93,7 @@ int main()
printf("%d\n", &A::B::V::iV);
printf("%d\n", &A::B1::V::iV);
printf("%d, %f, %f \n", a1.*pa, a1.*pf, a1.*pd);
+ printf("%d\n", i.*tt.pti);
test_aggr_pdata(a1);
test_aggr_pdata_1(&a1);
}
diff --git a/test/CodeGenCXX/ptr-to-member-function.cpp b/test/CodeGenCXX/ptr-to-member-function.cpp
index 1e396e976575..15019081c062 100644
--- a/test/CodeGenCXX/ptr-to-member-function.cpp
+++ b/test/CodeGenCXX/ptr-to-member-function.cpp
@@ -9,8 +9,14 @@ extern "C" int printf(...);
struct A {
int Ai;
+bool foo(int* arg) const;
};
+bool A::foo(int* arg) const {
+ printf("A::foo(%d)\n", *arg);
+ return true;
+}
+
struct B : public A {
void bf() { printf("B::bf called\n"); }
};
@@ -40,10 +46,22 @@ void test2(X x)
g(x);
}
+struct B1 {
+ bool (A::*pmf)(int*) const;
+
+ B1(int i) : pmf(&A::foo), im(i) {
+ ((A*)this->*pmf)(&im);
+ }
+
+ int im;
+};
+
int main()
{
X x;
test2(x);
+ B1 b = B1(1);
+ B1 c = B1(2);
}
// CHECK-LP64: call __ZN1XcvM1BFvvEEv
diff --git a/test/CodeGenCXX/virt.cpp b/test/CodeGenCXX/virt.cpp
index 7911940c6dab..193a96ddd589 100644
--- a/test/CodeGenCXX/virt.cpp
+++ b/test/CodeGenCXX/virt.cpp
@@ -48,9 +48,11 @@ public:
void F::foo() { }
int j;
+void *vp;
void test2() {
F f;
static int sz = (char *)(&f.f) - (char *)(&f);
+ vp = &sz;
j = sz;
// FIXME: These should result in a frontend constant a la fold, no run time
// initializer
@@ -91,50 +93,6 @@ int main() {
// CHECK-LP64: movl $1, 12(%rax)
// CHECK-LP64: movl $2, 8(%rax)
-// FIXME: This is the wrong thunk, but until these issues are fixed, better
-// than nothing.
-// CHECK-LP64: __ZTcvn16_n72_v16_n32_N8test16_D4foo1Ev:
-// CHECK-LP64-NEXT:Leh_func_begin43:
-// CHECK-LP64-NEXT: subq $24, %rsp
-// CHECK-LP64-NEXT:Llabel43:
-// CHECK-LP64-NEXT: movq %rdi, %rax
-// CHECK-LP64-NEXT: movq %rax, 8(%rsp)
-// CHECK-LP64-NEXT: movq 8(%rsp), %rax
-// CHECK-LP64-NEXT: movq %rax, %rcx
-// CHECK-LP64-NEXT: movabsq $-16, %rdx
-// CHECK-LP64-NEXT: addq %rdx, %rcx
-// CHECK-LP64-NEXT: movq -16(%rax), %rax
-// CHECK-LP64-NEXT: movq -72(%rax), %rax
-// CHECK-LP64-NEXT: addq %rax, %rcx
-// CHECK-LP64-NEXT: movq %rcx, %rax
-// CHECK-LP64-NEXT: movq %rax, %rdi
-// CHECK-LP64-NEXT: call __ZTch0_v16_n32_N8test16_D4foo1Ev
-// CHECK-LP64-NEXT: movq %rax, 16(%rsp)
-// CHECK-LP64-NEXT: movq 16(%rsp), %rax
-// CHECK-LP64-NEXT: addq $24, %rsp
-// CHECK-LP64-NEXT: ret
-
-// CHECK-LP64: __ZTch0_v16_n32_N8test16_D4foo1Ev:
-// CHECK-LP64-NEXT:Leh_func_begin44:
-// CHECK-LP64-NEXT: subq $24, %rsp
-// CHECK-LP64-NEXT:Llabel44:
-// CHECK-LP64-NEXT: movq %rdi, %rax
-// CHECK-LP64-NEXT: movq %rax, 8(%rsp)
-// CHECK-LP64-NEXT: movq 8(%rsp), %rax
-// CHECK-LP64-NEXT: movq %rax, %rdi
-// CHECK-LP64-NEXT: call __ZN8test16_D4foo1Ev
-// CHECK-LP64-NEXT: movq %rax, %rcx
-// CHECK-LP64-NEXT: movabsq $16, %rdx
-// CHECK-LP64-NEXT: addq %rdx, %rcx
-// CHECK-LP64-NEXT: movq 16(%rax), %rax
-// CHECK-LP64-NEXT: movq -32(%rax), %rax
-// CHECK-LP64-NEXT: addq %rax, %rcx
-// CHECK-LP64-NEXT: movq %rcx, %rax
-// CHECK-LP64-NEXT: movq %rax, 16(%rsp)
-// CHECK-LP64-NEXT: movq 16(%rsp), %rax
-// CHECK-LP64-NEXT: addq $24, %rsp
-// CHECK-LP64-NEXT: ret
-
struct test12_A {
virtual void foo0() { }
virtual void foo();
@@ -207,6 +165,7 @@ void test12_foo() {
// CHECK-LPOPT64-NEXT: movq _test12_pa(%rip), %rdi
// CHECK-LPOPT64-NEXT: call __ZN8test12_A3fooEv
+
struct test6_B2 { virtual void funcB2(); char b[1000]; };
struct test6_B1 : virtual test6_B2 { virtual void funcB1(); };
@@ -1003,9 +962,12 @@ virtual void foo_B2() { }
};
struct test16_D : test16_NV1, virtual test16_B2 {
- virtual test16_D *foo1() { return 0; }
+ virtual void bar();
+ virtual test16_D *foo1();
};
+void test16_D::bar() { }
+
// CHECK-LP64: __ZTV8test16_D:
// CHECK-LP64-NEXT: .quad 32
// CHECK-LP64-NEXT: .quad 16
@@ -1013,6 +975,7 @@ struct test16_D : test16_NV1, virtual test16_B2 {
// CHECK-LP64-NEXT: .quad __ZTI8test16_D
// CHECK-LP64-NEXT: .quad __ZN10test16_NV16fooNV1Ev
// CHECK-LP64-NEXT: .quad __ZN10test16_NV17foo_NV1Ev
+// CHECK-LP64-NEXT: .quad __ZN8test16_D3barEv
// CHECK-LP64-NEXT: .quad __ZN8test16_D4foo1Ev
// CHECK-LP64-NEXT: .space 8
// CHECK-LP64-NEXT: .space 8
@@ -1056,6 +1019,7 @@ struct test16_D : test16_NV1, virtual test16_B2 {
// CHECK-LP32-NEXT: .long __ZTI8test16_D
// CHECK-LP32-NEXT: .long __ZN10test16_NV16fooNV1Ev
// CHECK-LP32-NEXT: .long __ZN10test16_NV17foo_NV1Ev
+// CHECK-LP32-NEXT: .long __ZN8test16_D3barEv
// CHECK-LP32-NEXT: .long __ZN8test16_D4foo1Ev
// CHECK-LP32-NEXT: .space 4
// CHECK-LP32-NEXT: .space 4
@@ -1093,6 +1057,37 @@ struct test16_D : test16_NV1, virtual test16_B2 {
// CHECK-LP32-NEXT: .long __ZN10test16_NV28foo_NV2bEv
+// FIXME: This is the wrong thunk, but until these issues are fixed, better
+// than nothing.
+// CHECK-LPOPT64: __ZTcvn16_n72_v16_n32_N8test16_D4foo1Ev:
+// CHECK-LPOPT64-NEXT:Leh_func_begin
+// CHECK-LPOPT64-NEXT: subq $8, %rsp
+// CHECK-LPOPT64-NEXT:Llabel
+// CHECK-LPOPT64-NEXT: movq -16(%rdi), %rax
+// CHECK-LPOPT64-NEXT: movq -72(%rax), %rax
+// CHECK-LPOPT64-NEXT: leaq -16(%rax,%rdi), %rdi
+// FIXME: We want a tail call here
+// CHECK-LPOPT64-NEXT: call __ZTch0_v16_n32_N8test16_D4foo1Ev
+// CHECK-LPOPT64-NEXT: addq $8, %rsp
+// CHECK-LPOPT64-NEXT: ret
+
+// CHECK-LPOPT64: __ZTch0_v16_n32_N8test16_D4foo1Ev:
+// CHECK-LPOPT64-NEXT:Leh_func_begin
+// CHECK-LPOPT64-NEXT: subq $8, %rsp
+// CHECK-LPOPT64-NEXT:Llabel
+// CHECK-LPOPT64-NEXT: call __ZN8test16_D4foo1Ev
+// CHECK-LPOPT64-NEXT: testq %rax, %rax
+// CHECK-LPOPT64-NEXT: je LBB102_2
+// CHECK-LPOPT64-NEXT: movq 16(%rax), %rcx
+// CHECK-LPOPT64-NEXT: movq -32(%rcx), %rcx
+// CHECK-LPOPT64-NEXT: leaq 16(%rcx,%rax), %rax
+// CHECK-LPOPT64-NEXT: addq $8, %rsp
+// CHECK-LPOPT64-NEXT: ret
+// CHECK-LPOPT64-NEXT:LBB102_2:
+// CHECK-LPOPT64-NEXT: addq $8, %rsp
+// CHECK-LPOPT64-NEXT: ret
+
+
class test17_B1 {
virtual void foo() = 0;
virtual void bar() { }
@@ -1237,6 +1232,33 @@ struct test19_D : virtual test19_B4 {
// CHECK-LP64-NEXT .quad __ZN9test19_B43fB4Ev
+class test20_V {
+ virtual void foo1();
+};
+class test20_V1 {
+ virtual void foo2();
+};
+class test20_B : virtual test20_V {
+} b;
+class test20_B1 : virtual test20_V1 {
+};
+class test20_D : public test20_B, public test20_B1 {
+} d;
+
+// CHECK-LP64: __ZTV8test20_D:
+// CHECK-LP64-NEXT: .quad 8
+// CHECK-LP64-NEXT: .space 8
+// CHECK-LP64-NEXT: .space 8
+// CHECK-LP64-NEXT: .space 8
+// CHECK-LP64-NEXT: .quad __ZTI8test20_D
+// CHECK-LP64-NEXT: .quad __ZN8test20_V4foo1Ev
+// CHECK-LP64-NEXT: .space 8
+// CHECK-LP64-NEXT: .space 8
+// CHECK-LP64-NEXT: .quad 18446744073709551608
+// CHECK-LP64-NEXT: .quad __ZTI8test20_D
+// CHECK-LP64-NEXT: .quad __ZN9test20_V14foo2Ev
+
+
// CHECK-LP64: __ZTV1B:
// CHECK-LP64-NEXT: .space 8
diff --git a/test/Coverage/html-diagnostics.c b/test/Coverage/html-diagnostics.c
index e3db1668d836..55376d0e440e 100644
--- a/test/Coverage/html-diagnostics.c
+++ b/test/Coverage/html-diagnostics.c
@@ -1,5 +1,9 @@
// RUN: rm -rf %t &&
-// RUN: clang-cc --html-diags=%t -checker-cfref %s
+// RUN: clang-cc -analyze -analyzer-output=html -checker-cfref -o %t %s &&
+// RUN: cat %t/*.html | FileCheck %s
+
+// CHECK: <h3>Annotated Source Code</h3>
+// CHECK: Dereference of null pointer
void f0(int x) {
int *p = &x;
diff --git a/test/Frontend/dependency-gen.c b/test/Frontend/dependency-gen.c
index 953869912bbb..458d8d58b2ee 100644
--- a/test/Frontend/dependency-gen.c
+++ b/test/Frontend/dependency-gen.c
@@ -1,8 +1,8 @@
// rdar://6533411
-// RUN: clang -MD -MF %t.d -c -x c -o %t.o %s &&
+// RUN: clang -MD -MF %t.d -S -x c -o %t.o %s &&
// RUN: grep '.*dependency-gen.*:' %t.d &&
// RUN: grep 'dependency-gen.c' %t.d &&
-// RUN: clang -M -x c %s -o %t.d &&
+// RUN: clang -S -M -x c %s -o %t.d &&
// RUN: grep '.*dependency-gen.*:' %t.d &&
// RUN: grep 'dependency-gen.c' %t.d
diff --git a/test/Makefile b/test/Makefile
index fdb9d8f713d9..b7cb38af8af0 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -11,6 +11,9 @@ endif
# 'lit' wants objdir paths, so it will pick up the lit.site.cfg.
TESTDIRS := $(TESTDIRS:$(PROJ_SRC_DIR)%=$(PROJ_OBJ_DIR)%)
+# Allow EXTRA_TESTDIRS to provide additional test directories.
+TESTDIRS += $(EXTRA_TESTDIRS)
+
ifndef TESTARGS
ifdef VERBOSE
TESTARGS = -v
@@ -19,16 +22,17 @@ TESTARGS = -s
endif
endif
+# Make sure any extra test suites can find the main site config.
+LIT_ARGS := --param clang_site_config=$(PROJ_OBJ_DIR)/lit.site.cfg
+
ifdef VG
- VGARG="--vg"
-else
- VGARG=
+ LIT_ARGS += "--vg"
endif
all:: lit.site.cfg
@ echo '--- Running clang tests for $(TARGET_TRIPLE) ---'
@ $(PYTHON) $(LLVM_SRC_ROOT)/utils/lit/lit.py \
- $(TESTARGS) $(TESTDIRS) $(VGARG)
+ $(LIT_ARGS) $(TESTARGS) $(TESTDIRS)
FORCE:
diff --git a/test/Parser/if-scope-c90.c b/test/Parser/if-scope-c90.c
index fdc75e9f10b0..53987dccbc37 100644
--- a/test/Parser/if-scope-c90.c
+++ b/test/Parser/if-scope-c90.c
@@ -2,7 +2,7 @@
int f (int z)
{
- if (z > sizeof (enum {a, b}))
+ if (z > (int) sizeof (enum {a, b}))
return a;
return b;
}
diff --git a/test/Parser/if-scope-c99.c b/test/Parser/if-scope-c99.c
index 37cd0e15ab8e..b4cb51ca8c4f 100644
--- a/test/Parser/if-scope-c99.c
+++ b/test/Parser/if-scope-c99.c
@@ -2,7 +2,7 @@
int f (int z)
{
- if (z > sizeof (enum {a, b}))
+ if (z > (int) sizeof (enum {a, b}))
return a;
return b; // expected-error{{use of undeclared identifier}}
}
diff --git a/test/Preprocessor/stdint.c b/test/Preprocessor/stdint.c
index e292bd3ec7e5..d47b51dbc7b7 100644
--- a/test/Preprocessor/stdint.c
+++ b/test/Preprocessor/stdint.c
@@ -1,34 +1,33 @@
// RUN: clang-cc -E -ffreestanding -triple=arm-none-none %s | FileCheck -check-prefix ARM %s &&
//
-// ARM:typedef signed char int8_t;
-// ARM:typedef short int16_t;
-// ARM:typedef int int32_t;
// ARM:typedef long long int int64_t;
+// ARM:typedef unsigned long long int uint64_t;
+// ARM:typedef int64_t int_least64_t;
+// ARM:typedef uint64_t uint_least64_t;
+// ARM:typedef int64_t int_fast64_t;
+// ARM:typedef uint64_t uint_fast64_t;
//
-// ARM:typedef unsigned char uint8_t;
-// ARM:typedef int8_t int_least8_t;
-// ARM:typedef uint8_t uint_least8_t;
-// ARM:typedef int8_t int_fast8_t;
-// ARM:typedef uint8_t uint_fast8_t;
-//
+// ARM:typedef int int32_t;
+// ARM:typedef unsigned int uint32_t;
+// ARM:typedef int32_t int_least32_t;
+// ARM:typedef uint32_t uint_least32_t;
+// ARM:typedef int32_t int_fast32_t;
+// ARM:typedef uint32_t uint_fast32_t;
+//
+// ARM:typedef short int16_t;
// ARM:typedef unsigned short uint16_t;
// ARM:typedef int16_t int_least16_t;
// ARM:typedef uint16_t uint_least16_t;
// ARM:typedef int16_t int_fast16_t;
// ARM:typedef uint16_t uint_fast16_t;
//
-// ARM:typedef unsigned int uint32_t;
-// ARM:typedef int32_t int_least32_t;
-// ARM:typedef uint32_t uint_least32_t;
-// ARM:typedef int32_t int_fast32_t;
-// ARM:typedef uint32_t uint_fast32_t;
+// ARM:typedef signed char int8_t;
+// ARM:typedef unsigned char uint8_t;
+// ARM:typedef int8_t int_least8_t;
+// ARM:typedef uint8_t uint_least8_t;
+// ARM:typedef int8_t int_fast8_t;
+// ARM:typedef uint8_t uint_fast8_t;
//
-// ARM:typedef unsigned long long int uint64_t;
-// ARM:typedef int64_t int_least64_t;
-// ARM:typedef uint64_t uint_least64_t;
-// ARM:typedef int64_t int_fast64_t;
-// ARM:typedef uint64_t uint_fast64_t;
-//
// ARM:typedef long int intptr_t;
// ARM:typedef unsigned long int uintptr_t;
//
@@ -109,35 +108,33 @@
//
// RUN: clang-cc -E -ffreestanding -triple=bfin-none-none %s | FileCheck -check-prefix BFIN %s &&
//
-// BFIN:typedef signed char int8_t;
-// BFIN:typedef short int16_t;
-// BFIN:typedef int int32_t;
-//
// BFIN:typedef long long int int64_t;
+// BFIN:typedef unsigned long long int uint64_t;
+// BFIN:typedef int64_t int_least64_t;
+// BFIN:typedef uint64_t uint_least64_t;
+// BFIN:typedef int64_t int_fast64_t;
+// BFIN:typedef uint64_t uint_fast64_t;
//
-// BFIN:typedef unsigned char uint8_t;
-// BFIN:typedef int8_t int_least8_t;
-// BFIN:typedef uint8_t uint_least8_t;
-// BFIN:typedef int8_t int_fast8_t;
-// BFIN:typedef uint8_t uint_fast8_t;
+// BFIN:typedef int int32_t;
+// BFIN:typedef unsigned int uint32_t;
+// BFIN:typedef int32_t int_least32_t;
+// BFIN:typedef uint32_t uint_least32_t;
+// BFIN:typedef int32_t int_fast32_t;
+// BFIN:typedef uint32_t uint_fast32_t;
//
+// BFIN:typedef short int16_t;
// BFIN:typedef unsigned short uint16_t;
// BFIN:typedef int16_t int_least16_t;
// BFIN:typedef uint16_t uint_least16_t;
// BFIN:typedef int16_t int_fast16_t;
// BFIN:typedef uint16_t uint_fast16_t;
//
-// BFIN:typedef unsigned int uint32_t;
-// BFIN:typedef int32_t int_least32_t;
-// BFIN:typedef uint32_t uint_least32_t;
-// BFIN:typedef int32_t int_fast32_t;
-// BFIN:typedef uint32_t uint_fast32_t;
-//
-// BFIN:typedef unsigned long long int uint64_t;
-// BFIN:typedef int64_t int_least64_t;
-// BFIN:typedef uint64_t uint_least64_t;
-// BFIN:typedef int64_t int_fast64_t;
-// BFIN:typedef uint64_t uint_fast64_t;
+// BFIN:typedef signed char int8_t;
+// BFIN:typedef unsigned char uint8_t;
+// BFIN:typedef int8_t int_least8_t;
+// BFIN:typedef uint8_t uint_least8_t;
+// BFIN:typedef int8_t int_fast8_t;
+// BFIN:typedef uint8_t uint_fast8_t;
//
// BFIN:typedef long int intptr_t;
// BFIN:typedef unsigned long int uintptr_t;
@@ -219,34 +216,33 @@
//
// RUN: clang-cc -E -ffreestanding -triple=i386-none-none %s | FileCheck -check-prefix I386 %s &&
//
-// I386:typedef signed char int8_t;
-// I386:typedef short int16_t;
-// I386:typedef int int32_t;
// I386:typedef long long int int64_t;
+// I386:typedef unsigned long long int uint64_t;
+// I386:typedef int64_t int_least64_t;
+// I386:typedef uint64_t uint_least64_t;
+// I386:typedef int64_t int_fast64_t;
+// I386:typedef uint64_t uint_fast64_t;
//
-// I386:typedef unsigned char uint8_t;
-// I386:typedef int8_t int_least8_t;
-// I386:typedef uint8_t uint_least8_t;
-// I386:typedef int8_t int_fast8_t;
-// I386:typedef uint8_t uint_fast8_t;
+// I386:typedef int int32_t;
+// I386:typedef unsigned int uint32_t;
+// I386:typedef int32_t int_least32_t;
+// I386:typedef uint32_t uint_least32_t;
+// I386:typedef int32_t int_fast32_t;
+// I386:typedef uint32_t uint_fast32_t;
//
+// I386:typedef short int16_t;
// I386:typedef unsigned short uint16_t;
// I386:typedef int16_t int_least16_t;
// I386:typedef uint16_t uint_least16_t;
// I386:typedef int16_t int_fast16_t;
// I386:typedef uint16_t uint_fast16_t;
//
-// I386:typedef unsigned int uint32_t;
-// I386:typedef int32_t int_least32_t;
-// I386:typedef uint32_t uint_least32_t;
-// I386:typedef int32_t int_fast32_t;
-// I386:typedef uint32_t uint_fast32_t;
-//
-// I386:typedef unsigned long long int uint64_t;
-// I386:typedef int64_t int_least64_t;
-// I386:typedef uint64_t uint_least64_t;
-// I386:typedef int64_t int_fast64_t;
-// I386:typedef uint64_t uint_fast64_t;
+// I386:typedef signed char int8_t;
+// I386:typedef unsigned char uint8_t;
+// I386:typedef int8_t int_least8_t;
+// I386:typedef uint8_t uint_least8_t;
+// I386:typedef int8_t int_fast8_t;
+// I386:typedef uint8_t uint_fast8_t;
//
// I386:typedef int intptr_t;
// I386:typedef unsigned int uintptr_t;
@@ -327,27 +323,26 @@
//
// RUN: clang-cc -E -ffreestanding -triple=msp430-none-none %s | FileCheck -check-prefix MSP430 %s &&
//
-// MSP430:typedef signed char int8_t;
-// MSP430:typedef short int16_t;
// MSP430:typedef long long int32_t;
+// MSP430:typedef unsigned long long uint32_t;
+// MSP430:typedef int32_t int_least32_t;
+// MSP430:typedef uint32_t uint_least32_t;
+// MSP430:typedef int32_t int_fast32_t;
+// MSP430:typedef uint32_t uint_fast32_t;
//
-// MSP430:typedef unsigned char uint8_t;
-// MSP430:typedef int8_t int_least8_t;
-// MSP430:typedef uint8_t uint_least8_t;
-// MSP430:typedef int8_t int_fast8_t;
-// MSP430:typedef uint8_t uint_fast8_t;
-//
+// MSP430:typedef short int16_t;
// MSP430:typedef unsigned short uint16_t;
// MSP430:typedef int16_t int_least16_t;
// MSP430:typedef uint16_t uint_least16_t;
// MSP430:typedef int16_t int_fast16_t;
// MSP430:typedef uint16_t uint_fast16_t;
//
-// MSP430:typedef unsigned long long uint32_t;
-// MSP430:typedef int32_t int_least32_t;
-// MSP430:typedef uint32_t uint_least32_t;
-// MSP430:typedef int32_t int_fast32_t;
-// MSP430:typedef uint32_t uint_fast32_t;
+// MSP430:typedef signed char int8_t;
+// MSP430:typedef unsigned char uint8_t;
+// MSP430:typedef int8_t int_least8_t;
+// MSP430:typedef uint8_t uint_least8_t;
+// MSP430:typedef int8_t int_fast8_t;
+// MSP430:typedef uint8_t uint_fast8_t;
//
// MSP430:typedef short intptr_t;
// MSP430:typedef unsigned short uintptr_t;
@@ -428,27 +423,26 @@
//
// RUN: clang-cc -E -ffreestanding -triple=pic16-none-none %s | FileCheck -check-prefix PIC16 %s &&
//
-// PIC16:typedef signed char int8_t;
-// PIC16:typedef short int16_t;
// PIC16:typedef long long int32_t;
+// PIC16:typedef unsigned long long uint32_t;
+// PIC16:typedef int32_t int_least32_t;
+// PIC16:typedef uint32_t uint_least32_t;
+// PIC16:typedef int32_t int_fast32_t;
+// PIC16:typedef uint32_t uint_fast32_t;
//
-// PIC16:typedef unsigned char uint8_t;
-// PIC16:typedef int8_t int_least8_t;
-// PIC16:typedef uint8_t uint_least8_t;
-// PIC16:typedef int8_t int_fast8_t;
-// PIC16:typedef uint8_t uint_fast8_t;
-//
+// PIC16:typedef short int16_t;
// PIC16:typedef unsigned short uint16_t;
// PIC16:typedef int16_t int_least16_t;
// PIC16:typedef uint16_t uint_least16_t;
// PIC16:typedef int16_t int_fast16_t;
// PIC16:typedef uint16_t uint_fast16_t;
//
-// PIC16:typedef unsigned long long uint32_t;
-// PIC16:typedef int32_t int_least32_t;
-// PIC16:typedef uint32_t uint_least32_t;
-// PIC16:typedef int32_t int_fast32_t;
-// PIC16:typedef uint32_t uint_fast32_t;
+// PIC16:typedef signed char int8_t;
+// PIC16:typedef unsigned char uint8_t;
+// PIC16:typedef int8_t int_least8_t;
+// PIC16:typedef uint8_t uint_least8_t;
+// PIC16:typedef int8_t int_fast8_t;
+// PIC16:typedef uint8_t uint_fast8_t;
//
// PIC16:typedef short intptr_t;
// PIC16:typedef unsigned short uintptr_t;
@@ -529,34 +523,33 @@
//
// RUN: clang-cc -E -ffreestanding -triple=powerpc64-none-none %s | FileCheck -check-prefix PPC64 %s &&
//
-// PPC64:typedef signed char int8_t;
-// PPC64:typedef short int16_t;
-// PPC64:typedef int int32_t;
// PPC64:typedef long int int64_t;
+// PPC64:typedef unsigned long int uint64_t;
+// PPC64:typedef int64_t int_least64_t;
+// PPC64:typedef uint64_t uint_least64_t;
+// PPC64:typedef int64_t int_fast64_t;
+// PPC64:typedef uint64_t uint_fast64_t;
//
-// PPC64:typedef unsigned char uint8_t;
-// PPC64:typedef int8_t int_least8_t;
-// PPC64:typedef uint8_t uint_least8_t;
-// PPC64:typedef int8_t int_fast8_t;
-// PPC64:typedef uint8_t uint_fast8_t;
+// PPC64:typedef int int32_t;
+// PPC64:typedef unsigned int uint32_t;
+// PPC64:typedef int32_t int_least32_t;
+// PPC64:typedef uint32_t uint_least32_t;
+// PPC64:typedef int32_t int_fast32_t;
+// PPC64:typedef uint32_t uint_fast32_t;
//
+// PPC64:typedef short int16_t;
// PPC64:typedef unsigned short uint16_t;
// PPC64:typedef int16_t int_least16_t;
// PPC64:typedef uint16_t uint_least16_t;
// PPC64:typedef int16_t int_fast16_t;
// PPC64:typedef uint16_t uint_fast16_t;
//
-// PPC64:typedef unsigned int uint32_t;
-// PPC64:typedef int32_t int_least32_t;
-// PPC64:typedef uint32_t uint_least32_t;
-// PPC64:typedef int32_t int_fast32_t;
-// PPC64:typedef uint32_t uint_fast32_t;
-//
-// PPC64:typedef unsigned long int uint64_t;
-// PPC64:typedef int64_t int_least64_t;
-// PPC64:typedef uint64_t uint_least64_t;
-// PPC64:typedef int64_t int_fast64_t;
-// PPC64:typedef uint64_t uint_fast64_t;
+// PPC64:typedef signed char int8_t;
+// PPC64:typedef unsigned char uint8_t;
+// PPC64:typedef int8_t int_least8_t;
+// PPC64:typedef uint8_t uint_least8_t;
+// PPC64:typedef int8_t int_fast8_t;
+// PPC64:typedef uint8_t uint_fast8_t;
//
// PPC64:typedef long int intptr_t;
// PPC64:typedef unsigned long int uintptr_t;
@@ -637,34 +630,34 @@
//
// RUN: clang-cc -E -ffreestanding -triple=powerpc-none-none %s | FileCheck -check-prefix PPC %s &&
//
-// PPC:typedef signed char int8_t;
-// PPC:typedef short int16_t;
-// PPC:typedef int int32_t;
+//
// PPC:typedef long long int int64_t;
+// PPC:typedef unsigned long long int uint64_t;
+// PPC:typedef int64_t int_least64_t;
+// PPC:typedef uint64_t uint_least64_t;
+// PPC:typedef int64_t int_fast64_t;
+// PPC:typedef uint64_t uint_fast64_t;
//
-// PPC:typedef unsigned char uint8_t;
-// PPC:typedef int8_t int_least8_t;
-// PPC:typedef uint8_t uint_least8_t;
-// PPC:typedef int8_t int_fast8_t;
-// PPC:typedef uint8_t uint_fast8_t;
+// PPC:typedef int int32_t;
+// PPC:typedef unsigned int uint32_t;
+// PPC:typedef int32_t int_least32_t;
+// PPC:typedef uint32_t uint_least32_t;
+// PPC:typedef int32_t int_fast32_t;
+// PPC:typedef uint32_t uint_fast32_t;
//
+// PPC:typedef short int16_t;
// PPC:typedef unsigned short uint16_t;
// PPC:typedef int16_t int_least16_t;
// PPC:typedef uint16_t uint_least16_t;
// PPC:typedef int16_t int_fast16_t;
// PPC:typedef uint16_t uint_fast16_t;
//
-// PPC:typedef unsigned int uint32_t;
-// PPC:typedef int32_t int_least32_t;
-// PPC:typedef uint32_t uint_least32_t;
-// PPC:typedef int32_t int_fast32_t;
-// PPC:typedef uint32_t uint_fast32_t;
-//
-// PPC:typedef unsigned long long int uint64_t;
-// PPC:typedef int64_t int_least64_t;
-// PPC:typedef uint64_t uint_least64_t;
-// PPC:typedef int64_t int_fast64_t;
-// PPC:typedef uint64_t uint_fast64_t;
+// PPC:typedef signed char int8_t;
+// PPC:typedef unsigned char uint8_t;
+// PPC:typedef int8_t int_least8_t;
+// PPC:typedef uint8_t uint_least8_t;
+// PPC:typedef int8_t int_fast8_t;
+// PPC:typedef uint8_t uint_fast8_t;
//
// PPC:typedef long int intptr_t;
// PPC:typedef unsigned long int uintptr_t;
@@ -745,34 +738,33 @@
//
// RUN: clang-cc -E -ffreestanding -triple=s390x-none-none %s | FileCheck -check-prefix S390X %s &&
//
-// S390X:typedef signed char int8_t;
-// S390X:typedef short int16_t;
-// S390X:typedef int int32_t;
// S390X:typedef long long int int64_t;
+// S390X:typedef unsigned long long int uint64_t;
+// S390X:typedef int64_t int_least64_t;
+// S390X:typedef uint64_t uint_least64_t;
+// S390X:typedef int64_t int_fast64_t;
+// S390X:typedef uint64_t uint_fast64_t;
//
-// S390X:typedef unsigned char uint8_t;
-// S390X:typedef int8_t int_least8_t;
-// S390X:typedef uint8_t uint_least8_t;
-// S390X:typedef int8_t int_fast8_t;
-// S390X:typedef uint8_t uint_fast8_t;
+// S390X:typedef int int32_t;
+// S390X:typedef unsigned int uint32_t;
+// S390X:typedef int32_t int_least32_t;
+// S390X:typedef uint32_t uint_least32_t;
+// S390X:typedef int32_t int_fast32_t;
+// S390X:typedef uint32_t uint_fast32_t;
//
+// S390X:typedef short int16_t;
// S390X:typedef unsigned short uint16_t;
// S390X:typedef int16_t int_least16_t;
// S390X:typedef uint16_t uint_least16_t;
// S390X:typedef int16_t int_fast16_t;
// S390X:typedef uint16_t uint_fast16_t;
//
-// S390X:typedef unsigned int uint32_t;
-// S390X:typedef int32_t int_least32_t;
-// S390X:typedef uint32_t uint_least32_t;
-// S390X:typedef int32_t int_fast32_t;
-// S390X:typedef uint32_t uint_fast32_t;
-//
-// S390X:typedef unsigned long long int uint64_t;
-// S390X:typedef int64_t int_least64_t;
-// S390X:typedef uint64_t uint_least64_t;
-// S390X:typedef int64_t int_fast64_t;
-// S390X:typedef uint64_t uint_fast64_t;
+// S390X:typedef signed char int8_t;
+// S390X:typedef unsigned char uint8_t;
+// S390X:typedef int8_t int_least8_t;
+// S390X:typedef uint8_t uint_least8_t;
+// S390X:typedef int8_t int_fast8_t;
+// S390X:typedef uint8_t uint_fast8_t;
//
// S390X:typedef long int intptr_t;
// S390X:typedef unsigned long int uintptr_t;
@@ -853,34 +845,33 @@
//
// RUN: clang-cc -E -ffreestanding -triple=sparc-none-none %s | FileCheck -check-prefix SPARC %s &&
//
-// SPARC:typedef signed char int8_t;
-// SPARC:typedef short int16_t;
-// SPARC:typedef int int32_t;
// SPARC:typedef long long int int64_t;
+// SPARC:typedef unsigned long long int uint64_t;
+// SPARC:typedef int64_t int_least64_t;
+// SPARC:typedef uint64_t uint_least64_t;
+// SPARC:typedef int64_t int_fast64_t;
+// SPARC:typedef uint64_t uint_fast64_t;
//
-// SPARC:typedef unsigned char uint8_t;
-// SPARC:typedef int8_t int_least8_t;
-// SPARC:typedef uint8_t uint_least8_t;
-// SPARC:typedef int8_t int_fast8_t;
-// SPARC:typedef uint8_t uint_fast8_t;
+// SPARC:typedef int int32_t;
+// SPARC:typedef unsigned int uint32_t;
+// SPARC:typedef int32_t int_least32_t;
+// SPARC:typedef uint32_t uint_least32_t;
+// SPARC:typedef int32_t int_fast32_t;
+// SPARC:typedef uint32_t uint_fast32_t;
//
+// SPARC:typedef short int16_t;
// SPARC:typedef unsigned short uint16_t;
// SPARC:typedef int16_t int_least16_t;
// SPARC:typedef uint16_t uint_least16_t;
// SPARC:typedef int16_t int_fast16_t;
// SPARC:typedef uint16_t uint_fast16_t;
//
-// SPARC:typedef unsigned int uint32_t;
-// SPARC:typedef int32_t int_least32_t;
-// SPARC:typedef uint32_t uint_least32_t;
-// SPARC:typedef int32_t int_fast32_t;
-// SPARC:typedef uint32_t uint_fast32_t;
-//
-// SPARC:typedef unsigned long long int uint64_t;
-// SPARC:typedef int64_t int_least64_t;
-// SPARC:typedef uint64_t uint_least64_t;
-// SPARC:typedef int64_t int_fast64_t;
-// SPARC:typedef uint64_t uint_fast64_t;
+// SPARC:typedef signed char int8_t;
+// SPARC:typedef unsigned char uint8_t;
+// SPARC:typedef int8_t int_least8_t;
+// SPARC:typedef uint8_t uint_least8_t;
+// SPARC:typedef int8_t int_fast8_t;
+// SPARC:typedef uint8_t uint_fast8_t;
//
// SPARC:typedef long int intptr_t;
// SPARC:typedef unsigned long int uintptr_t;
@@ -961,27 +952,26 @@
//
// RUN: clang-cc -E -ffreestanding -triple=tce-none-none %s | FileCheck -check-prefix TCE %s &&
//
-// TCE:typedef signed char int8_t;
-// TCE:typedef short int16_t;
// TCE:typedef int int32_t;
+// TCE:typedef unsigned int uint32_t;
+// TCE:typedef int32_t int_least32_t;
+// TCE:typedef uint32_t uint_least32_t;
+// TCE:typedef int32_t int_fast32_t;
+// TCE:typedef uint32_t uint_fast32_t;
//
-// TCE:typedef unsigned char uint8_t;
-// TCE:typedef int8_t int_least8_t;
-// TCE:typedef uint8_t uint_least8_t;
-// TCE:typedef int8_t int_fast8_t;
-// TCE:typedef uint8_t uint_fast8_t;
-//
+// TCE:typedef short int16_t;
// TCE:typedef unsigned short uint16_t;
// TCE:typedef int16_t int_least16_t;
// TCE:typedef uint16_t uint_least16_t;
// TCE:typedef int16_t int_fast16_t;
// TCE:typedef uint16_t uint_fast16_t;
//
-// TCE:typedef unsigned int uint32_t;
-// TCE:typedef int32_t int_least32_t;
-// TCE:typedef uint32_t uint_least32_t;
-// TCE:typedef int32_t int_fast32_t;
-// TCE:typedef uint32_t uint_fast32_t;
+// TCE:typedef signed char int8_t;
+// TCE:typedef unsigned char uint8_t;
+// TCE:typedef int8_t int_least8_t;
+// TCE:typedef uint8_t uint_least8_t;
+// TCE:typedef int8_t int_fast8_t;
+// TCE:typedef uint8_t uint_fast8_t;
//
// TCE:typedef int intptr_t;
// TCE:typedef unsigned int uintptr_t;
@@ -1062,34 +1052,34 @@
//
// RUN: clang-cc -E -ffreestanding -triple=x86_64-none-none %s | FileCheck -check-prefix X86_64 %s &&
//
-// X86_64:typedef signed char int8_t;
-// X86_64:typedef short int16_t;
-// X86_64:typedef int int32_t;
+//
// X86_64:typedef long int int64_t;
+// X86_64:typedef unsigned long int uint64_t;
+// X86_64:typedef int64_t int_least64_t;
+// X86_64:typedef uint64_t uint_least64_t;
+// X86_64:typedef int64_t int_fast64_t;
+// X86_64:typedef uint64_t uint_fast64_t;
//
-// X86_64:typedef unsigned char uint8_t;
-// X86_64:typedef int8_t int_least8_t;
-// X86_64:typedef uint8_t uint_least8_t;
-// X86_64:typedef int8_t int_fast8_t;
-// X86_64:typedef uint8_t uint_fast8_t;
+// X86_64:typedef int int32_t;
+// X86_64:typedef unsigned int uint32_t;
+// X86_64:typedef int32_t int_least32_t;
+// X86_64:typedef uint32_t uint_least32_t;
+// X86_64:typedef int32_t int_fast32_t;
+// X86_64:typedef uint32_t uint_fast32_t;
//
+// X86_64:typedef short int16_t;
// X86_64:typedef unsigned short uint16_t;
// X86_64:typedef int16_t int_least16_t;
// X86_64:typedef uint16_t uint_least16_t;
// X86_64:typedef int16_t int_fast16_t;
// X86_64:typedef uint16_t uint_fast16_t;
//
-// X86_64:typedef unsigned int uint32_t;
-// X86_64:typedef int32_t int_least32_t;
-// X86_64:typedef uint32_t uint_least32_t;
-// X86_64:typedef int32_t int_fast32_t;
-// X86_64:typedef uint32_t uint_fast32_t;
-//
-// X86_64:typedef unsigned long int uint64_t;
-// X86_64:typedef int64_t int_least64_t;
-// X86_64:typedef uint64_t uint_least64_t;
-// X86_64:typedef int64_t int_fast64_t;
-// X86_64:typedef uint64_t uint_fast64_t;
+// X86_64:typedef signed char int8_t;
+// X86_64:typedef unsigned char uint8_t;
+// X86_64:typedef int8_t int_least8_t;
+// X86_64:typedef uint8_t uint_least8_t;
+// X86_64:typedef int8_t int_fast8_t;
+// X86_64:typedef uint8_t uint_fast8_t;
//
// X86_64:typedef long int intptr_t;
// X86_64:typedef unsigned long int uintptr_t;
diff --git a/test/Sema/compare.c b/test/Sema/compare.c
index 87131bb62183..9cbbfba935bd 100644
--- a/test/Sema/compare.c
+++ b/test/Sema/compare.c
@@ -7,6 +7,26 @@ int test(char *C) { // nothing here should warn.
return C != 1; // expected-warning {{comparison between pointer and integer ('char *' and 'int')}}
}
+int ints(long a, unsigned long b) {
+ return (a == b) + // expected-warning {{comparison of integers of different signs}}
+ ((int)a == b) + // expected-warning {{comparison of integers of different signs}}
+ ((short)a == b) + // expected-warning {{comparison of integers of different signs}}
+ (a == (unsigned int) b) + // expected-warning {{comparison of integers of different signs}}
+ (a == (unsigned short) b); // expected-warning {{comparison of integers of different signs}}
+
+ enum Enum {B};
+ return (a == B) +
+ ((int)a == B) +
+ ((short)a == B) +
+ (a == (unsigned int) B) + // expected-warning {{comparison of integers of different signs}}
+ (a == (unsigned short) B); // expected-warning {{comparison of integers of different signs}}
+
+ // Should be able to prove all of these are non-negative.
+ return (b == (long) B) +
+ (b == (int) B) +
+ (b == (short) B);
+}
+
int equal(char *a, const char *b) {
return a == b;
}
diff --git a/test/Sema/conditional-expr.c b/test/Sema/conditional-expr.c
index 1f0a9deb5e47..3bfeae5d4c5e 100644
--- a/test/Sema/conditional-expr.c
+++ b/test/Sema/conditional-expr.c
@@ -34,6 +34,25 @@ void foo() {
typedef void *asdf;
*(0 ? (asdf) 0 : &x) = 10;
+
+ unsigned long test0 = 5;
+ test0 = test0 ? (long) test0 : test0; // expected-warning {{operands of ? are integers of different signs}}
+ test0 = test0 ? (int) test0 : test0; // expected-warning {{operands of ? are integers of different signs}}
+ test0 = test0 ? (short) test0 : test0; // expected-warning {{operands of ? are integers of different signs}}
+ test0 = test0 ? test0 : (long) test0; // expected-warning {{operands of ? are integers of different signs}}
+ test0 = test0 ? test0 : (int) test0; // expected-warning {{operands of ? are integers of different signs}}
+ test0 = test0 ? test0 : (short) test0; // expected-warning {{operands of ? are integers of different signs}}
+ test0 = test0 ? test0 : (long) 10;
+ test0 = test0 ? test0 : (int) 10;
+ test0 = test0 ? test0 : (short) 10;
+ test0 = test0 ? (long) 10 : test0;
+ test0 = test0 ? (int) 10 : test0;
+ test0 = test0 ? (short) 10 : test0;
+
+ enum Enum { EVal };
+ test0 = test0 ? EVal : test0;
+ test0 = test0 ? EVal : (int) test0; // okay: EVal is an int
+ test0 = test0 ? (unsigned) EVal : (int) test0; // expected-warning {{operands of ? are integers of different signs}}
}
int Postgresql() {
diff --git a/test/SemaCXX/compare.cpp b/test/SemaCXX/compare.cpp
new file mode 100644
index 000000000000..806b078e8df6
--- /dev/null
+++ b/test/SemaCXX/compare.cpp
@@ -0,0 +1,15 @@
+// RUN: clang-cc -fsyntax-only -pedantic -verify %s
+
+int test0(long a, unsigned long b) {
+ enum Enum {B};
+ return (a == B) + // expected-warning {{comparison of integers of different signs}}
+ ((int)a == B) + // expected-warning {{comparison of integers of different signs}}
+ ((short)a == B) + // expected-warning {{comparison of integers of different signs}}
+ (a == (unsigned int) B) + // expected-warning {{comparison of integers of different signs}}
+ (a == (unsigned short) B); // expected-warning {{comparison of integers of different signs}}
+
+ // Should be able to prove all of these are non-negative.
+ return (b == (long) B) +
+ (b == (int) B) +
+ (b == (short) B);
+}
diff --git a/test/SemaCXX/conditional-expr.cpp b/test/SemaCXX/conditional-expr.cpp
index fea3324b5fd5..da2dd67d061d 100644
--- a/test/SemaCXX/conditional-expr.cpp
+++ b/test/SemaCXX/conditional-expr.cpp
@@ -156,8 +156,8 @@ void test()
i1 = i1 ? i1 : ir1;
int *pi1 = i1 ? &i1 : 0;
pi1 = i1 ? 0 : &i1;
- i1 = i1 ? i1 : EVal;
- i1 = i1 ? EVal : i1;
+ i1 = i1 ? i1 : EVal; // expected-warning {{operands of ? are integers of different signs}} ??
+ i1 = i1 ? EVal : i1; // expected-warning {{operands of ? are integers of different signs}} ??
d1 = i1 ? 'c' : 4.0;
d1 = i1 ? 4.0 : 'c';
Base *pb = i1 ? (Base*)0 : (Derived*)0;
@@ -177,6 +177,24 @@ void test()
(void)&(i1 ? flds.b1 : flds.i1); // expected-error {{address of bit-field requested}}
(void)&(i1 ? flds.i1 : flds.b1); // expected-error {{address of bit-field requested}}
+
+ unsigned long test0 = 5;
+ test0 = test0 ? (long) test0 : test0; // expected-warning {{operands of ? are integers of different signs}}
+ test0 = test0 ? (int) test0 : test0; // expected-warning {{operands of ? are integers of different signs}}
+ test0 = test0 ? (short) test0 : test0; // expected-warning {{operands of ? are integers of different signs}}
+ test0 = test0 ? test0 : (long) test0; // expected-warning {{operands of ? are integers of different signs}}
+ test0 = test0 ? test0 : (int) test0; // expected-warning {{operands of ? are integers of different signs}}
+ test0 = test0 ? test0 : (short) test0; // expected-warning {{operands of ? are integers of different signs}}
+ test0 = test0 ? test0 : (long) 10;
+ test0 = test0 ? test0 : (int) 10;
+ test0 = test0 ? test0 : (short) 10;
+ test0 = test0 ? (long) 10 : test0;
+ test0 = test0 ? (int) 10 : test0;
+ test0 = test0 ? (short) 10 : test0;
+
+ test0 = test0 ? EVal : test0;
+ test0 = test0 ? EVal : (int) test0; // expected-warning {{operands of ? are integers of different signs}}
+
// Note the thing that this does not test: since DR446, various situations
// *must* create a separate temporary copy of class objects. This can only
// be properly tested at runtime, though.
diff --git a/test/SemaCXX/constructor-initializer.cpp b/test/SemaCXX/constructor-initializer.cpp
index b86a27d66d98..20cf35b293b6 100644
--- a/test/SemaCXX/constructor-initializer.cpp
+++ b/test/SemaCXX/constructor-initializer.cpp
@@ -122,3 +122,36 @@ struct Q {
float *pf;
};
+
+// A silly class used to demonstrate field-is-uninitialized in constructors with
+// multiple params.
+class TwoInOne { TwoInOne(TwoInOne a, TwoInOne b) {} };
+class InitializeUsingSelfTest {
+ bool A;
+ char* B;
+ int C;
+ TwoInOne D;
+ InitializeUsingSelfTest(int E)
+ : A(A), // expected-warning {{field is uninitialized when used here}}
+ B((((B)))), // expected-warning {{field is uninitialized when used here}}
+ C(A && InitializeUsingSelfTest::C), // expected-warning {{field is uninitialized when used here}}
+ D(D, // expected-warning {{field is uninitialized when used here}}
+ D) {} // expected-warning {{field is uninitialized when used here}}
+};
+
+int IntWrapper(int i) { return 0; };
+class InitializeUsingSelfExceptions {
+ int A;
+ int B;
+ InitializeUsingSelfExceptions(int B)
+ : A(IntWrapper(A)), // Due to a conservative implementation, we do not report warnings inside function/ctor calls even though it is possible to do so.
+ B(B) {} // Not a warning; B is a local variable.
+};
+
+class CopyConstructorTest {
+ bool A, B, C;
+ CopyConstructorTest(const CopyConstructorTest& rhs)
+ : A(rhs.A),
+ B(B), // expected-warning {{field is uninitialized when used here}}
+ C(rhs.C || C) { } // expected-warning {{field is uninitialized when used here}}
+};
diff --git a/test/SemaCXX/overload-member-call.cpp b/test/SemaCXX/overload-member-call.cpp
index 96e570da654b..937b65d633f9 100644
--- a/test/SemaCXX/overload-member-call.cpp
+++ b/test/SemaCXX/overload-member-call.cpp
@@ -54,3 +54,15 @@ void test(X x, const X xc, X* xp, const X* xcp, volatile X xv, volatile X* xvp)
X::h(0); // expected-error{{call to non-static member function without an object argument}}
}
+
+struct X1 {
+ int& member();
+ float& member() const;
+};
+
+struct X2 : X1 { };
+
+void test_X2(X2 *x2p, const X2 *cx2p) {
+ int &ir = x2p->member();
+ float &fr = cx2p->member();
+}
diff --git a/test/SemaCXX/overloaded-operator.cpp b/test/SemaCXX/overloaded-operator.cpp
index 0f723ad206b9..750038d4ab51 100644
--- a/test/SemaCXX/overloaded-operator.cpp
+++ b/test/SemaCXX/overloaded-operator.cpp
@@ -268,3 +268,14 @@ void circ() {
CircA a;
a->val = 0; // expected-error {{circular pointer delegation detected}}
}
+
+// PR5360: Arrays should lead to built-in candidates for subscript.
+typedef enum {
+ LastReg = 23,
+} Register;
+class RegAlloc {
+ int getPriority(Register r) {
+ return usepri[r];
+ }
+ int usepri[LastReg + 1];
+};
diff --git a/test/SemaCXX/primary-base.cpp b/test/SemaCXX/primary-base.cpp
index 62f9087bd91d..a7e18bd528a1 100644
--- a/test/SemaCXX/primary-base.cpp
+++ b/test/SemaCXX/primary-base.cpp
@@ -4,8 +4,8 @@ class B : virtual A { };
class C : B { };
-// Since A is already a primary base class, C should be the primary base class of F.
+// Since A is already a primary base class, C should be the primary base class
+// of F.
class F : virtual A, virtual C { };
int sa[sizeof(F) == sizeof(A) ? 1 : -1];
-
diff --git a/test/SemaTemplate/example-dynarray.cpp b/test/SemaTemplate/example-dynarray.cpp
index 0b8d605b623d..2b752b4f1f49 100644
--- a/test/SemaTemplate/example-dynarray.cpp
+++ b/test/SemaTemplate/example-dynarray.cpp
@@ -1,4 +1,4 @@
-// RUN: clang %s -o %t
+// RUN: clang-cc -emit-llvm-only %s
#include <stddef.h>
#include <stdlib.h>
#include <assert.h>
diff --git a/test/SemaTemplate/instantiate-complete.cpp b/test/SemaTemplate/instantiate-complete.cpp
index babc55217a95..507894a2ff69 100644
--- a/test/SemaTemplate/instantiate-complete.cpp
+++ b/test/SemaTemplate/instantiate-complete.cpp
@@ -45,3 +45,24 @@ void test_memptr(X<long> *p1, long X<long>::*pm1,
(void)(p1->*pm1);
(void)((p2->*pm2)(0));
}
+
+// Reference binding to a base
+template<typename T>
+struct X1 { };
+
+template<typename T>
+struct X2 : public T { };
+
+void refbind_base(X2<X1<int> > &x2) {
+ X1<int> &x1 = x2;
+}
+
+// Enumerate constructors for user-defined conversion.
+template<typename T>
+struct X3 {
+ X3(T);
+};
+
+void enum_constructors(X1<float> &x1) {
+ X3<X1<float> > x3 = x1;
+}
diff --git a/test/SemaTemplate/instantiate-deeply.cpp b/test/SemaTemplate/instantiate-deeply.cpp
index 27e430be5cbe..7f15bf1200f1 100644
--- a/test/SemaTemplate/instantiate-deeply.cpp
+++ b/test/SemaTemplate/instantiate-deeply.cpp
@@ -1,5 +1,4 @@
// RUN: clang-cc -fsyntax-only -Wall -verify %s
-
template<typename a> struct A {
template <typename b> struct B {
template <typename c> struct C {
@@ -20,3 +19,18 @@ template<typename a> struct A {
};
A<int>::B<int>::C<int>::D<int>::E<int> global;
+
+// PR5352
+template <typename T>
+class Foo {
+public:
+ Foo() {}
+
+ struct Bar {
+ T value;
+ };
+
+ Bar u;
+};
+
+template class Foo<int>;
diff --git a/test/SemaTemplate/instantiate-expr-1.cpp b/test/SemaTemplate/instantiate-expr-1.cpp
index 13ee3ab525ba..fb88213c401b 100644
--- a/test/SemaTemplate/instantiate-expr-1.cpp
+++ b/test/SemaTemplate/instantiate-expr-1.cpp
@@ -1,5 +1,4 @@
// RUN: clang-cc -fsyntax-only -verify %s
-
template<int I, int J>
struct Bitfields {
int simple : I; // expected-error{{bit-field 'simple' has zero width}}
@@ -69,3 +68,29 @@ void test_BitfieldNeg() {
(void)sizeof(BitfieldNeg2<int, -5>); // okay
(void)sizeof(BitfieldNeg2<int, 5>); // expected-note{{in instantiation of template class 'struct BitfieldNeg2<int, 5>' requested here}}
}
+
+template<typename T>
+void increment(T &x) {
+ (void)++x;
+}
+
+struct Incrementable {
+ Incrementable &operator++();
+};
+
+void test_increment(Incrementable inc) {
+ increment(inc);
+}
+
+template<typename T>
+void add(const T &x) {
+ (void)(x + x);
+}
+
+struct Addable {
+ Addable operator+(const Addable&) const;
+};
+
+void test_add(Addable &a) {
+ add(a);
+}
diff --git a/test/SemaTemplate/member-access-expr.cpp b/test/SemaTemplate/member-access-expr.cpp
index 0a6a6bc0990e..ad0075f564b6 100644
--- a/test/SemaTemplate/member-access-expr.cpp
+++ b/test/SemaTemplate/member-access-expr.cpp
@@ -88,3 +88,20 @@ protected:
(void)f0<0>();
}
};
+
+// Fun with template instantiation and conversions
+struct X4 {
+ int& member();
+ float& member() const;
+};
+
+template<typename T>
+struct X5 {
+ void f(T* ptr) { int& ir = ptr->member(); }
+ void g(T* ptr) { float& fr = ptr->member(); }
+};
+
+void test_X5(X5<X4> x5, X5<const X4> x5c, X4 *xp, const X4 *cxp) {
+ x5.f(xp);
+ x5c.g(cxp);
+}
diff --git a/test/SemaTemplate/member-template-access-expr.cpp b/test/SemaTemplate/member-template-access-expr.cpp
index 0238cd53c553..567c0d63b046 100644
--- a/test/SemaTemplate/member-template-access-expr.cpp
+++ b/test/SemaTemplate/member-template-access-expr.cpp
@@ -93,3 +93,13 @@ void f(X4<X3<int> > x4i) {
X2<sizeof(int)> x2;
x4i.f<X2<sizeof(int)> >(x2);
}
+
+template<typename T>
+struct X5 {
+ template<typename U>
+ void f();
+
+ void g() {
+ this->f<T*>();
+ }
+};
diff --git a/test/SemaTemplate/temp_arg_nontype.cpp b/test/SemaTemplate/temp_arg_nontype.cpp
index 534030dba0ea..a6611582f170 100644
--- a/test/SemaTemplate/temp_arg_nontype.cpp
+++ b/test/SemaTemplate/temp_arg_nontype.cpp
@@ -122,3 +122,33 @@ extern FuncPtr0<&func0> *fp0;
int func0(int, int);
extern FuncPtr0<&func0> *fp0;
+// PR5350
+namespace ns {
+ template <typename T>
+ struct Foo {
+ static const bool value = true;
+ };
+
+ template <bool b>
+ struct Bar {};
+
+ const bool value = false;
+
+ Bar<bool(ns::Foo<int>::value)> x;
+}
+
+// PR5349
+namespace ns {
+ enum E { k };
+
+ template <E e>
+ struct Baz {};
+
+ Baz<k> f1; // This works.
+ Baz<E(0)> f2; // This too.
+ Baz<static_cast<E>(0)> f3; // And this.
+
+ Baz<ns::E(0)> b1; // This doesn't work.
+ Baz<static_cast<ns::E>(0)> b2; // This neither.
+}
+
diff --git a/test/SemaTemplate/template-id-expr.cpp b/test/SemaTemplate/template-id-expr.cpp
index a0cbe4408494..dd8694afa7ea 100644
--- a/test/SemaTemplate/template-id-expr.cpp
+++ b/test/SemaTemplate/template-id-expr.cpp
@@ -1,5 +1,4 @@
// RUN: clang-cc -fsyntax-only -verify %s
-
// PR5336
template<typename FromCl>
struct isa_impl_cl {
@@ -12,3 +11,19 @@ void isa(const Y &Val) { return isa_impl_cl<Y>::template isa<X>(Val); }
class Value;
void f0(const Value &Val) { isa<Value>(Val); }
+
+// Implicit template-ids.
+template<typename T>
+struct X0 {
+ template<typename U>
+ void f1();
+
+ template<typename U>
+ void f2(U) {
+ f1<U>();
+ }
+};
+
+void test_X0_int(X0<int> xi, float f) {
+ xi.f2(f);
+}
diff --git a/test/lit.cfg b/test/lit.cfg
index 60d8df057730..9b274fed30b5 100644
--- a/test/lit.cfg
+++ b/test/lit.cfg
@@ -55,6 +55,12 @@ if config.test_exec_root is None:
# configuration hasn't been created by the build system, or we are in an
# out-of-tree build situation).
+ # Check for 'clang_site_config' user parameter, and use that if available.
+ site_cfg = lit.params.get('clang_site_config', None)
+ if site_cfg and os.path.exists(site_cfg):
+ lit.load_config(config, site_cfg)
+ raise SystemExit
+
# Try to detect the situation where we are using an out-of-tree build by
# looking for 'llvm-config'.
#
diff --git a/tools/clang-cc/clang-cc.cpp b/tools/clang-cc/clang-cc.cpp
index 671fc35d182b..26ba42d67002 100644
--- a/tools/clang-cc/clang-cc.cpp
+++ b/tools/clang-cc/clang-cc.cpp
@@ -244,11 +244,6 @@ static llvm::cl::opt<bool>
VerifyDiagnostics("verify",
llvm::cl::desc("Verify emitted diagnostics and warnings"));
-static llvm::cl::opt<std::string>
-HTMLDiag("html-diags",
- llvm::cl::desc("Generate HTML to report diagnostics"),
- llvm::cl::value_desc("HTML directory"));
-
static llvm::cl::opt<bool>
NoShowColumn("fno-show-column",
llvm::cl::desc("Do not include column number on diagnostics"));
@@ -933,12 +928,9 @@ static bool InitializeSourceManager(Preprocessor &PP,
// Preprocessor Initialization
//===----------------------------------------------------------------------===//
-// FIXME: Preprocessor builtins to support.
-// -A... - Play with #assertions
-// -undef - Undefine all predefined macros
-
static llvm::cl::opt<bool>
-undef_macros("undef", llvm::cl::value_desc("macro"), llvm::cl::desc("undef all system defines"));
+UndefMacros("undef", llvm::cl::value_desc("macro"),
+ llvm::cl::desc("undef all system defines"));
static llvm::cl::list<std::string>
D_macros("D", llvm::cl::value_desc("macro"), llvm::cl::Prefix,
@@ -1137,6 +1129,9 @@ void InitializeIncludePaths(const char *Argv0, HeaderSearch &Headers,
}
void InitializePreprocessorInitOptions(PreprocessorInitOptions &InitOpts) {
+ // Use predefines?
+ InitOpts.setUsePredefines(!UndefMacros);
+
// Add macros from the command line.
unsigned d = 0, D = D_macros.size();
unsigned u = 0, U = U_macros.size();
@@ -1195,68 +1190,48 @@ void InitializePreprocessorInitOptions(PreprocessorInitOptions &InitOpts) {
}
//===----------------------------------------------------------------------===//
-// Driver PreprocessorFactory - For lazily generating preprocessors ...
+// Preprocessor construction
//===----------------------------------------------------------------------===//
-namespace {
-class VISIBILITY_HIDDEN DriverPreprocessorFactory : public PreprocessorFactory {
- Diagnostic &Diags;
- const LangOptions &LangInfo;
- TargetInfo &Target;
- SourceManager &SourceMgr;
- HeaderSearch &HeaderInfo;
-
-public:
- DriverPreprocessorFactory(Diagnostic &diags, const LangOptions &opts,
- TargetInfo &target, SourceManager &SM,
- HeaderSearch &Headers)
- : Diags(diags), LangInfo(opts), Target(target),
- SourceMgr(SM), HeaderInfo(Headers) {}
-
-
- virtual ~DriverPreprocessorFactory() {}
-
- virtual Preprocessor* CreatePreprocessor() {
- llvm::OwningPtr<PTHManager> PTHMgr;
+static Preprocessor *
+CreatePreprocessor(Diagnostic &Diags,const LangOptions &LangInfo,
+ TargetInfo &Target, SourceManager &SourceMgr,
+ HeaderSearch &HeaderInfo) {
+ PTHManager *PTHMgr = 0;
+ if (!TokenCache.empty() && !ImplicitIncludePTH.empty()) {
+ fprintf(stderr, "error: cannot use both -token-cache and -include-pth "
+ "options\n");
+ exit(1);
+ }
- if (!TokenCache.empty() && !ImplicitIncludePTH.empty()) {
- fprintf(stderr, "error: cannot use both -token-cache and -include-pth "
- "options\n");
- exit(1);
- }
+ // Use PTH?
+ if (!TokenCache.empty() || !ImplicitIncludePTH.empty()) {
+ const std::string& x = TokenCache.empty() ? ImplicitIncludePTH:TokenCache;
+ PTHMgr = PTHManager::Create(x, &Diags,
+ TokenCache.empty() ? Diagnostic::Error
+ : Diagnostic::Warning);
+ }
- // Use PTH?
- if (!TokenCache.empty() || !ImplicitIncludePTH.empty()) {
- const std::string& x = TokenCache.empty() ? ImplicitIncludePTH:TokenCache;
- PTHMgr.reset(PTHManager::Create(x, &Diags,
- TokenCache.empty() ? Diagnostic::Error
- : Diagnostic::Warning));
- }
+ if (Diags.hasErrorOccurred())
+ exit(1);
- if (Diags.hasErrorOccurred())
- exit(1);
+ // Create the Preprocessor.
+ Preprocessor *PP = new Preprocessor(Diags, LangInfo, Target,
+ SourceMgr, HeaderInfo, PTHMgr);
- // Create the Preprocessor.
- llvm::OwningPtr<Preprocessor> PP(new Preprocessor(Diags, LangInfo, Target,
- SourceMgr, HeaderInfo,
- PTHMgr.get()));
-
- // 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.get());
- PP->setPTHManager(PTHMgr.take());
- }
+ // 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);
+ PP->setPTHManager(PTHMgr);
+ }
- PreprocessorInitOptions InitOpts;
- InitializePreprocessorInitOptions(InitOpts);
- if (InitializePreprocessor(*PP, InitOpts, undef_macros))
- return 0;
+ PreprocessorInitOptions InitOpts;
+ InitializePreprocessorInitOptions(InitOpts);
+ InitializePreprocessor(*PP, InitOpts);
- return PP.take();
- }
-};
+ return PP;
}
//===----------------------------------------------------------------------===//
@@ -1570,9 +1545,14 @@ public:
Chain2.reset(new TextDiagnosticPrinter(*BuildLogFile, DiagOpts));
}
- virtual void setLangOptions(const LangOptions *LO) {
- Chain1->setLangOptions(LO);
- Chain2->setLangOptions(LO);
+ virtual void BeginSourceFile(const LangOptions &LO) {
+ Chain1->BeginSourceFile(LO);
+ Chain2->BeginSourceFile(LO);
+ }
+
+ virtual void EndSourceFile() {
+ Chain1->EndSourceFile();
+ Chain2->EndSourceFile();
}
virtual bool IncludeInDiagnosticCounts() const {
@@ -1724,8 +1704,8 @@ static ASTConsumer *CreateConsumerAction(Preprocessor &PP,
/// ProcessInputFile - Process a single input file with the specified state.
///
-static void ProcessInputFile(Preprocessor &PP, PreprocessorFactory &PPF,
- const std::string &InFile, ProgActions PA,
+static void ProcessInputFile(Preprocessor &PP, const std::string &InFile,
+ ProgActions PA,
const llvm::StringMap<bool> &Features,
llvm::LLVMContext& Context) {
llvm::OwningPtr<llvm::raw_ostream> OS;
@@ -1750,12 +1730,11 @@ static void ProcessInputFile(Preprocessor &PP, PreprocessorFactory &PPF,
case EmitHTML:
OS.reset(ComputeOutFile(InFile, 0, true, OutPath));
- Consumer.reset(CreateHTMLPrinter(OS.get(), PP.getDiagnostics(), &PP, &PPF));
+ Consumer.reset(CreateHTMLPrinter(OS.get(), PP));
break;
case RunAnalysis:
- Consumer.reset(CreateAnalysisConsumer(PP.getDiagnostics(), &PP, &PPF,
- PP.getLangOptions(), OutputFile,
+ Consumer.reset(CreateAnalysisConsumer(PP, OutputFile,
ReadAnalyzerOptions()));
break;
@@ -1990,7 +1969,11 @@ static void ProcessInputFile(Preprocessor &PP, PreprocessorFactory &PPF,
CreateCodeCompleter, CreateCodeCompleterData);
}
- if (PA == RunPreprocessorOnly) { // Just lex as fast as we can, no output.
+ // Perform post processing actions and actions which don't use a consumer.
+ switch (PA) {
+ default: break;
+
+ case RunPreprocessorOnly: { // Just lex as fast as we can, no output.
llvm::TimeRegion Timer(ClangFrontendTimer);
Token Tok;
// Start parsing the specified input file.
@@ -1999,11 +1982,17 @@ static void ProcessInputFile(Preprocessor &PP, PreprocessorFactory &PPF,
PP.Lex(Tok);
} while (Tok.isNot(tok::eof));
ClearSourceMgr = true;
- } else if (PA == ParseNoop) { // -parse-noop
+ break;
+ }
+
+ case ParseNoop: {
llvm::TimeRegion Timer(ClangFrontendTimer);
ParseFile(PP, new MinimalAction(PP));
ClearSourceMgr = true;
- } else if (PA == PrintPreprocessedInput){ // -E mode.
+ break;
+ }
+
+ case PrintPreprocessedInput: {
llvm::TimeRegion Timer(ClangFrontendTimer);
if (DumpMacros)
DoPrintMacros(PP, OS.get());
@@ -2014,6 +2003,8 @@ static void ProcessInputFile(Preprocessor &PP, PreprocessorFactory &PPF,
ClearSourceMgr = true;
}
+ }
+
if (FixItRewrite)
FixItRewrite->WriteFixedFile(InFile, OutputFile);
@@ -2094,7 +2085,9 @@ static void ProcessASTInputFile(const std::string &InFile, ProgActions PA,
AST->getSourceManager().createMainFileIDForMemBuffer(SB);
// Stream the input AST to the consumer.
+ Diags.getClient()->BeginSourceFile(PP.getLangOptions());
ParseAST(PP, Consumer.get(), AST->getASTContext(), Stats);
+ Diags.getClient()->EndSourceFile();
// Release the consumer and the AST, in that order since the consumer may
// perform actions in its destructor which require the context.
@@ -2171,27 +2164,12 @@ int main(int argc, char **argv) {
fprintf(stderr, "-verify only works on single input files for now.\n");
return 1;
}
- if (!HTMLDiag.empty()) {
- fprintf(stderr, "-verify and -html-diags don't work together\n");
- return 1;
- }
- } else if (HTMLDiag.empty()) {
- // Print diagnostics to stderr by default.
- DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(), DiagOpts));
} else {
- DiagClient.reset(CreateHTMLDiagnosticClient(HTMLDiag));
+ DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(), DiagOpts));
}
- if (!DumpBuildInformation.empty()) {
- if (!HTMLDiag.empty()) {
- fprintf(stderr,
- "-dump-build-information and -html-diags don't work together\n");
- return 1;
- }
-
+ if (!DumpBuildInformation.empty())
SetUpBuildDumpLog(argc, argv, DiagClient);
- }
-
// Configure our handling of diagnostics.
Diagnostic Diags(DiagClient.get());
@@ -2232,7 +2210,8 @@ int main(int argc, char **argv) {
if (!InheritanceViewCls.empty()) // C++ visualization?
ProgAction = InheritanceView;
- llvm::OwningPtr<SourceManager> SourceMgr;
+ // Create the source manager.
+ SourceManager SourceMgr;
// Create a file manager object to provide access to and cache the filesystem.
FileManager FileMgr;
@@ -2252,16 +2231,12 @@ int main(int argc, char **argv) {
continue;
}
- // Create a SourceManager object. This tracks and owns all the file
- // buffers allocated to a translation unit.
- if (!SourceMgr)
- SourceMgr.reset(new SourceManager());
- else
- SourceMgr->clearIDTables();
+ // Reset the ID tables if we are reusing the SourceManager.
+ if (i)
+ SourceMgr.clearIDTables();
// Initialize language options, inferring file types from input filenames.
LangOptions LangInfo;
- DiagClient->setLangOptions(&LangInfo);
InitializeLangOptions(LangInfo, LK);
InitializeLanguageStandard(LangInfo, LK, Target.get(), Features);
@@ -2273,12 +2248,9 @@ int main(int argc, char **argv) {
InitializeIncludePaths(argv[0], HeaderInfo, FileMgr, LangInfo, Triple);
// Set up the preprocessor with these options.
- DriverPreprocessorFactory PPFactory(Diags, LangInfo, *Target,
- *SourceMgr.get(), HeaderInfo);
-
- llvm::OwningPtr<Preprocessor> PP(PPFactory.CreatePreprocessor());
- if (!PP)
- continue;
+ llvm::OwningPtr<Preprocessor> PP(CreatePreprocessor(Diags, LangInfo,
+ *Target, SourceMgr,
+ HeaderInfo));
// Handle generating dependencies, if requested.
if (!DependencyFile.empty()) {
@@ -2309,14 +2281,12 @@ int main(int argc, char **argv) {
PP->getLangOptions().NoBuiltin);
}
- if (!HTMLDiag.empty())
- ((PathDiagnosticClient*)DiagClient.get())->SetPreprocessor(PP.get());
-
// Process the source file.
- ProcessInputFile(*PP, PPFactory, InFile, ProgAction, Features, Context);
+ DiagClient->BeginSourceFile(LangInfo);
+ ProcessInputFile(*PP, InFile, ProgAction, Features, Context);
+ DiagClient->EndSourceFile();
HeaderInfo.ClearFileInfo();
- DiagClient->setLangOptions(0);
}
if (!NoCaretDiagnostics)
diff --git a/utils/C++Tests/LLVM-Syntax/lit.local.cfg b/utils/C++Tests/LLVM-Syntax/lit.local.cfg
index 69f010ef335e..8375f0920d3d 100644
--- a/utils/C++Tests/LLVM-Syntax/lit.local.cfg
+++ b/utils/C++Tests/LLVM-Syntax/lit.local.cfg
@@ -16,6 +16,7 @@ config.test_format = lit.formats.SyntaxCheckTest(compiler=root.clang,
pattern='^(.*\\.h|[^.]*)$',
extra_cxx_args=['-D__STDC_LIMIT_MACROS',
'-D__STDC_CONSTANT_MACROS',
+ '-Wno-sign-compare',
'-I%s/include' % root.llvm_src_root,
'-I%s/include' % root.llvm_obj_root])
diff --git a/www/analyzer/latest_checker.html.incl b/www/analyzer/latest_checker.html.incl
index 8ecd1bba551a..c45eebd430ff 100644
--- a/www/analyzer/latest_checker.html.incl
+++ b/www/analyzer/latest_checker.html.incl
@@ -1 +1 @@
-<b><a href="http://checker.minormatter.com/checker-226.tar.bz2">checker-226.tar.bz2</a></b> (built October 29, 2009)
+<b><a href="http://checker.minormatter.com/checker-227.tar.bz2">checker-227.tar.bz2</a></b> (built November 4, 2009)