Update clang to r86140.
This commit is contained in:
parent
51fb8b013e
commit
8f57cb0305
@ -38,17 +38,17 @@ class ASTConsumer {
|
||||
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 @@ class ASTConsumer {
|
||||
/// 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 @@ class ASTConsumer {
|
||||
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; }
|
||||
|
@ -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;
|
||||
|
@ -66,6 +66,8 @@ class AnalysisManager : public BugReporterData {
|
||||
VisualizeEGDot(vizdot), VisualizeEGUbi(vizubi), PurgeDead(purge),
|
||||
EagerlyAssume(eager), TrimGraph(trim) {}
|
||||
|
||||
~AnalysisManager() { FlushDiagnostics(); }
|
||||
|
||||
void ClearContexts() {
|
||||
LocCtxMgr.clear();
|
||||
AnaCtxMgr.clear();
|
||||
@ -98,6 +100,11 @@ class AnalysisManager : public BugReporterData {
|
||||
virtual PathDiagnosticClient *getPathDiagnosticClient() {
|
||||
return PD.get();
|
||||
}
|
||||
|
||||
void FlushDiagnostics() {
|
||||
if (PD.get())
|
||||
PD->FlushDiagnostics();
|
||||
}
|
||||
|
||||
bool shouldVisualizeGraphviz() const { return VisualizeEGDot; }
|
||||
|
||||
|
@ -64,10 +64,10 @@ class BuiltinBug : public BugType {
|
||||
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; }
|
||||
|
||||
|
@ -116,12 +116,13 @@ class Checker {
|
||||
|
||||
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 @@ class Checker {
|
||||
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,
|
||||
|
@ -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);
|
||||
};
|
||||
}
|
||||
|
@ -412,7 +412,8 @@ class GRExprEngine : public GRSubEngine {
|
||||
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 @@ class GRExprEngine : public GRSubEngine {
|
||||
|
||||
/// 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 @@ class GRExprEngine : public GRSubEngine {
|
||||
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
|
||||
|
@ -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
|
||||
|
@ -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">;
|
||||
|
@ -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<
|
||||
|
@ -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">;
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 @@ class PreprocessorInitOptions {
|
||||
};
|
||||
|
||||
/// 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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -30,7 +30,6 @@ class Diagnostic;
|
||||
class ASTConsumer;
|
||||
class IdentifierTable;
|
||||
class SourceManager;
|
||||
class PreprocessorFactory;
|
||||
class LangOptions;
|
||||
class Decl;
|
||||
class Stmt;
|
||||
|
@ -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 @@ class Preprocessor {
|
||||
/// 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 @@ class Preprocessor {
|
||||
/// 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 @@ class Preprocessor {
|
||||
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 {
|
||||
|
@ -1174,14 +1174,41 @@ class Action : public ActionBase {
|
||||
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);
|
||||
|
||||
|
@ -131,6 +131,9 @@ class DeclSpec {
|
||||
// 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 @@ class DeclSpec {
|
||||
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 @@ class DeclSpec {
|
||||
FS_virtual_specified(false),
|
||||
FS_explicit_specified(false),
|
||||
Friend_specified(false),
|
||||
Constexpr_specified(false),
|
||||
TypeRep(0),
|
||||
AttrList(0),
|
||||
ProtocolQualifiers(0),
|
||||
@ -309,9 +313,15 @@ class DeclSpec {
|
||||
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:
|
||||
///
|
||||
|
@ -1320,13 +1320,6 @@ class Parser {
|
||||
TypeTy *ObjectType,
|
||||
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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 @@ class CXXOperatorIdName : public DeclarationNameExtra {
|
||||
};
|
||||
|
||||
bool operator<(DeclarationName LHS, DeclarationName RHS) {
|
||||
if (IdentifierInfo *LhsId = LHS.getAsIdentifierInfo())
|
||||
if (IdentifierInfo *RhsId = RHS.getAsIdentifierInfo())
|
||||
return LhsId->getName() < RhsId->getName();
|
||||
if (LHS.getNameKind() != RHS.getNameKind())
|
||||
return LHS.getNameKind() < RHS.getNameKind();
|
||||
|
||||
switch (LHS.getNameKind()) {
|
||||
case DeclarationName::Identifier:
|
||||
return LHS.getAsIdentifierInfo()->getName() <
|
||||
RHS.getAsIdentifierInfo()->getName();
|
||||
|
||||
return LHS.getAsOpaqueInteger() < RHS.getAsOpaqueInteger();
|
||||
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
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 (AssignE) {
|
||||
const Expr *ex = 0;
|
||||
|
||||
if (ex) {
|
||||
R->addRange(ex->getSourceRange());
|
||||
R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, ex);
|
||||
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);
|
||||
|
@ -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 =
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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() {
|
||||
|
@ -108,11 +108,12 @@ class CodeGenFunction : public BlockFunction {
|
||||
|
||||
/// 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 @@ class CodeGenFunction : public BlockFunction {
|
||||
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 @@ class CodeGenFunction : public BlockFunction {
|
||||
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 @@ class CodeGenFunction : public BlockFunction {
|
||||
/// 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.
|
||||
|
@ -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/Analysis/Analyses/LiveVariables.h"
|
||||
#include "clang/Analysis/PathDiagnostic.h"
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
#include "clang/Basic/FileManager.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/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();
|
||||
}
|
||||
|
@ -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 @@ class VISIBILITY_HIDDEN HTMLDiagnostics : public PathDiagnosticClient {
|
||||
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;
|
||||
|
@ -13,13 +13,14 @@
|
||||
|
||||
#include "clang/Frontend/ASTConsumers.h"
|
||||
#include "clang/AST/ASTConsumer.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/AST/Decl.h"
|
||||
#include "clang/Basic/Diagnostic.h"
|
||||
#include "clang/Basic/FileManager.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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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));
|
||||
if (SubPD) {
|
||||
SubPD->HandlePathDiagnostic(OwnedD.take());
|
||||
llvm::SmallVector<std::string, 1> SubFilesMade;
|
||||
SubPD->FlushDiagnostics(SubFilesMade);
|
||||
|
||||
FilesMade.clear();
|
||||
SubPDC->HandlePathDiagnostic(OwnedD.take());
|
||||
SubPDC.reset(0);
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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,17 +68,30 @@ 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;
|
||||
#endif
|
||||
|
||||
#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.
|
||||
*/
|
||||
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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) {
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
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 ';'.
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
///
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -1609,6 +1609,9 @@ class Sema : public Action {
|
||||
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 @@ class Sema : public Action {
|
||||
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 @@ class Sema : public Action {
|
||||
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 @@ class Sema : public Action {
|
||||
AccessSpecifier AS,
|
||||
SourceLocation UsingLoc,
|
||||
const CXXScopeSpec &SS,
|
||||
SourceLocation IdentLoc,
|
||||
IdentifierInfo *TargetName,
|
||||
OverloadedOperatorKind Op,
|
||||
UnqualifiedId &Name,
|
||||
AttributeList *AttrList,
|
||||
bool IsTypeName);
|
||||
|
||||
@ -3645,7 +3651,8 @@ class Sema : public Action {
|
||||
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,
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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(),
|
||||
|
@ -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()) {
|
||||
|
@ -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)
|
||||
|
@ -877,7 +877,7 @@ class TreeTransform {
|
||||
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 @@ class TreeTransform {
|
||||
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 @@ class TreeTransform {
|
||||
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 @@ class TreeTransform {
|
||||
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>
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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}}
|
||||
};
|
||||
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}}
|
||||
};
|
||||
|
@ -17,12 +17,9 @@ class xpto {
|
||||
int i;
|
||||
float f;
|
||||
|
||||
/**
|
||||
NYI
|
||||
~xpto() {
|
||||
printf("xpto::~xpto()\n");
|
||||
}
|
||||
*/
|
||||
};
|
||||
|
||||
int main() {
|
||||
|
@ -32,6 +32,15 @@ class A : public B, public B1 {
|
||||
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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -48,9 +48,11 @@ class F : virtual public D1, virtual public D {
|
||||
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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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}}
|
||||
}
|
||||
|
@ -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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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() {
|
||||
|
15
test/SemaCXX/compare.cpp
Normal file
15
test/SemaCXX/compare.cpp
Normal file
@ -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);
|
||||
}
|
@ -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.
|
||||
|
@ -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}}
|
||||
};
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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];
|
||||
};
|
||||
|
@ -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];
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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>;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -88,3 +88,20 @@ class X3 {
|
||||
(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);
|
||||
}
|
||||
|
@ -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*>();
|
||||
}
|
||||
};
|
||||
|
@ -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.
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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'.
|
||||
#
|
||||
|
@ -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;
|
||||
|
||||
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.reset(PTHManager::Create(x, &Diags,
|
||||
TokenCache.empty() ? Diagnostic::Error
|
||||
: Diagnostic::Warning));
|
||||
}
|
||||
|
||||
if (Diags.hasErrorOccurred())
|
||||
exit(1);
|
||||
|
||||
// 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());
|
||||
}
|
||||
|
||||
PreprocessorInitOptions InitOpts;
|
||||
InitializePreprocessorInitOptions(InitOpts);
|
||||
if (InitializePreprocessor(*PP, InitOpts, undef_macros))
|
||||
return 0;
|
||||
|
||||
return PP.take();
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
if (Diags.hasErrorOccurred())
|
||||
exit(1);
|
||||
|
||||
// Create the Preprocessor.
|
||||
Preprocessor *PP = new Preprocessor(Diags, LangInfo, Target,
|
||||
SourceMgr, HeaderInfo, PTHMgr);
|
||||
|
||||
// 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);
|
||||
InitializePreprocessor(*PP, InitOpts);
|
||||
|
||||
return PP;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -1570,9 +1545,14 @@ class LoggingDiagnosticClient : public DiagnosticClient {
|
||||
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)
|
||||
|
@ -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])
|
||||
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user