Update clang to r86140.

This commit is contained in:
Roman Divacky 2009-11-05 17:18:09 +00:00
parent 51fb8b013e
commit 8f57cb0305
93 changed files with 1672 additions and 1208 deletions

View File

@ -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; }

View File

@ -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;

View File

@ -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; }

View File

@ -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; }

View File

@ -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,

View File

@ -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);
};
}

View File

@ -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

View File

@ -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

View File

@ -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">;

View File

@ -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<

View File

@ -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">;

View File

@ -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)

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -30,7 +30,6 @@ class Diagnostic;
class ASTConsumer;
class IdentifierTable;
class SourceManager;
class PreprocessorFactory;
class LangOptions;
class Decl;
class Stmt;

View File

@ -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 {

View File

@ -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);

View File

@ -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:
///

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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();

View File

@ -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;

View File

@ -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);
}
}
}

View File

@ -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);

View File

@ -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 =

View File

@ -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);

View File

@ -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);
}
}
}

View File

@ -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() {

View File

@ -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.

View File

@ -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();
}

View File

@ -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;

View File

@ -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.

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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

View File

@ -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)

View File

@ -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;

View File

@ -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,

View File

@ -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) {

View File

@ -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,

View File

@ -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);
}

View File

@ -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.
///

View File

@ -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();
}

View File

@ -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:

View File

@ -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);
}

View File

@ -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,

View File

@ -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;

View File

@ -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.

View File

@ -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)

View File

@ -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,

View File

@ -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);
}

View File

@ -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(),

View File

@ -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()) {

View File

@ -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)

View File

@ -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>

View File

@ -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)

View File

@ -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

View File

@ -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}}
};

View File

@ -17,12 +17,9 @@ class xpto {
int i;
float f;
/**
NYI
~xpto() {
printf("xpto::~xpto()\n");
}
*/
};
int main() {

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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:

View File

@ -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;
}

View File

@ -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}}
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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
View 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);
}

View File

@ -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.

View File

@ -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}}
};

View File

@ -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();
}

View File

@ -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];
};

View File

@ -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];

View File

@ -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>

View File

@ -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;
}

View File

@ -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>;

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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*>();
}
};

View File

@ -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.
}

View File

@ -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);
}

View File

@ -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'.
#

View File

@ -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)

View File

@ -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])

View File

@ -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)