diff options
author | Roman Divacky <rdivacky@FreeBSD.org> | 2009-11-05 17:18:09 +0000 |
---|---|---|
committer | Roman Divacky <rdivacky@FreeBSD.org> | 2009-11-05 17:18:09 +0000 |
commit | 8f57cb0305232cb53fff00ef151ca716766f3437 (patch) | |
tree | 8b316eca843681b024034db1125707173b9adb4a | |
parent | 51fb8b013e7734b795139f49d3b1f77c539be20a (diff) | |
download | src-8f57cb0305232cb53fff00ef151ca716766f3437.tar.gz src-8f57cb0305232cb53fff00ef151ca716766f3437.zip |
Notes
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) |