aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/clang-c/Index.h97
-rw-r--r--include/clang/AST/ASTContext.h74
-rw-r--r--include/clang/AST/CanonicalType.h19
-rw-r--r--include/clang/AST/Decl.h91
-rw-r--r--include/clang/AST/DeclGroup.h2
-rw-r--r--include/clang/AST/DeclNodes.def1
-rw-r--r--include/clang/AST/DeclObjC.h14
-rw-r--r--include/clang/AST/DeclTemplate.h380
-rw-r--r--include/clang/AST/Expr.h272
-rw-r--r--include/clang/AST/ExprCXX.h58
-rw-r--r--include/clang/AST/RecordLayout.h2
-rw-r--r--include/clang/AST/Redeclarable.h5
-rw-r--r--include/clang/AST/StmtIterator.h2
-rw-r--r--include/clang/AST/StmtNodes.def1
-rw-r--r--include/clang/AST/TemplateBase.h366
-rw-r--r--include/clang/AST/TemplateName.h81
-rw-r--r--include/clang/AST/Type.h8
-rw-r--r--include/clang/AST/TypeLoc.h135
-rw-r--r--include/clang/Analysis/CallGraph.h3
-rw-r--r--include/clang/Analysis/PathSensitive/AnalysisContext.h13
-rw-r--r--include/clang/Analysis/PathSensitive/BugReporter.h33
-rw-r--r--include/clang/Analysis/PathSensitive/BugType.h86
-rw-r--r--include/clang/Analysis/PathSensitive/Checker.h38
-rw-r--r--include/clang/Analysis/PathSensitive/Checkers/AttrNonNullChecker.h28
-rw-r--r--include/clang/Analysis/PathSensitive/Checkers/BadCallChecker.h30
-rw-r--r--include/clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h53
-rw-r--r--include/clang/Analysis/PathSensitive/Checkers/DivZeroChecker.h28
-rw-r--r--include/clang/Analysis/PathSensitive/Checkers/UndefinedArgChecker.h34
-rw-r--r--include/clang/Analysis/PathSensitive/Checkers/UndefinedAssignmentChecker.h32
-rw-r--r--include/clang/Analysis/PathSensitive/Checkers/VLASizeChecker.h39
-rw-r--r--include/clang/Analysis/PathSensitive/GRExprEngine.h85
-rw-r--r--include/clang/Analysis/PathSensitive/GRState.h19
-rw-r--r--include/clang/Analysis/PathSensitive/GRTransferFuncs.h5
-rw-r--r--include/clang/Analysis/PathSensitive/Store.h7
-rw-r--r--include/clang/Analysis/PathSensitive/SymbolManager.h2
-rw-r--r--include/clang/Analysis/ProgramPoint.h2
-rw-r--r--include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h2
-rw-r--r--include/clang/Basic/Builtins.def2
-rw-r--r--include/clang/Basic/DiagnosticCommonKinds.td4
-rw-r--r--include/clang/Basic/DiagnosticDriverKinds.td2
-rw-r--r--include/clang/Basic/DiagnosticFrontendKinds.td3
-rw-r--r--include/clang/Basic/DiagnosticLexKinds.td3
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td13
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td44
-rw-r--r--include/clang/Basic/OnDiskHashTable.h2
-rw-r--r--include/clang/Basic/OperatorKinds.h5
-rw-r--r--include/clang/Basic/PartialDiagnostic.h18
-rw-r--r--include/clang/Basic/SourceManager.h2
-rw-r--r--include/clang/Basic/TargetInfo.h6
-rw-r--r--include/clang/Driver/Options.def4
-rw-r--r--include/clang/Frontend/ASTUnit.h10
-rw-r--r--include/clang/Frontend/CompileOptions.h4
-rw-r--r--include/clang/Frontend/DeclXML.def4
-rw-r--r--include/clang/Frontend/DiagnosticOptions.h49
-rw-r--r--include/clang/Frontend/InitHeaderSearch.h10
-rw-r--r--include/clang/Frontend/InitPreprocessor.h3
-rw-r--r--include/clang/Frontend/PCHBitCodes.h4
-rw-r--r--include/clang/Frontend/PCHReader.h9
-rw-r--r--include/clang/Frontend/PCHWriter.h4
-rw-r--r--include/clang/Frontend/TextDiagnosticPrinter.h31
-rw-r--r--include/clang/Index/Utils.h3
-rw-r--r--include/clang/Lex/LiteralSupport.h2
-rw-r--r--include/clang/Lex/Preprocessor.h68
-rw-r--r--include/clang/Lex/Token.h8
-rw-r--r--include/clang/Parse/Action.h323
-rw-r--r--include/clang/Parse/DeclSpec.h363
-rw-r--r--include/clang/Parse/Parser.h142
-rw-r--r--include/clang/Sema/CodeCompleteConsumer.h13
68 files changed, 2224 insertions, 1081 deletions
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h
index 44cbe0efff81..1a58f44ff4c2 100644
--- a/include/clang-c/Index.h
+++ b/include/clang-c/Index.h
@@ -16,10 +16,23 @@
#ifndef CLANG_C_INDEX_H
#define CLANG_C_INDEX_H
+#include <sys/stat.h>
+
#ifdef __cplusplus
extern "C" {
#endif
+/* MSVC DLL import/export. */
+#ifdef _MSC_VER
+ #ifdef _CINDEX_LIB_
+ #define CINDEX_LINKAGE __declspec(dllexport)
+ #else
+ #define CINDEX_LINKAGE __declspec(dllimport)
+ #endif
+#else
+ #define CINDEX_LINKAGE
+#endif
+
/*
Clang indeX abstractions. The backing store for the following API's will be
clangs AST file (currently based on PCH). AST files are created as follows:
@@ -33,6 +46,7 @@ typedef void *CXIndex; /* An indexing instance. */
typedef void *CXTranslationUnit; /* A translation unit instance. */
+typedef void *CXFile; /* A source file */
typedef void *CXDecl; /* A specific declaration within a translation unit. */
typedef void *CXStmt; /* A specific statement within a function/method */
@@ -138,22 +152,22 @@ typedef void *CXEntity;
* -include-pch) allows 'excludeDeclsFromPCH' to remove redundant callbacks
* (which gives the indexer the same performance benefit as the compiler).
*/
-CXIndex clang_createIndex(int excludeDeclarationsFromPCH,
+CINDEX_LINKAGE CXIndex clang_createIndex(int excludeDeclarationsFromPCH,
int displayDiagnostics);
-void clang_disposeIndex(CXIndex);
+CINDEX_LINKAGE void clang_disposeIndex(CXIndex);
-const char *clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit);
+CINDEX_LINKAGE const char *clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit);
/*
* \brief Create a translation unit from an AST file (-emit-ast).
*/
-CXTranslationUnit clang_createTranslationUnit(
+CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnit(
CXIndex, const char *ast_filename
);
/**
* \brief Destroy the specified CXTranslationUnit object.
*/
-void clang_disposeTranslationUnit(CXTranslationUnit);
+CINDEX_LINKAGE void clang_disposeTranslationUnit(CXTranslationUnit);
/**
* \brief Return the CXTranslationUnit for a given source file and the provided
@@ -170,7 +184,7 @@ void clang_disposeTranslationUnit(CXTranslationUnit);
* '-o <output file>' (both '-o' and '<output file>' are ignored)
*
*/
-CXTranslationUnit clang_createTranslationUnitFromSourceFile(
+CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnitFromSourceFile(
CXIndex CIdx,
const char *source_filename /* specify NULL if the source file is in clang_command_line_args */,
int num_clang_command_line_args,
@@ -197,7 +211,7 @@ CXTranslationUnit clang_createTranslationUnitFromSourceFile(
typedef void *CXClientData;
typedef void (*CXTranslationUnitIterator)(CXTranslationUnit, CXCursor,
CXClientData);
-void clang_loadTranslationUnit(CXTranslationUnit, CXTranslationUnitIterator,
+CINDEX_LINKAGE void clang_loadTranslationUnit(CXTranslationUnit, CXTranslationUnitIterator,
CXClientData);
/*
@@ -227,23 +241,30 @@ void clang_loadTranslationUnit(CXTranslationUnit, CXTranslationUnitIterator,
*/
typedef void (*CXDeclIterator)(CXDecl, CXCursor, CXClientData);
-void clang_loadDeclaration(CXDecl, CXDeclIterator, CXClientData);
+CINDEX_LINKAGE void clang_loadDeclaration(CXDecl, CXDeclIterator, CXClientData);
+
+/*
+ * CXFile Operations.
+ */
+CINDEX_LINKAGE const char *clang_getFileName(CXFile SFile);
+CINDEX_LINKAGE time_t clang_getFileTime(CXFile SFile);
/*
* CXEntity Operations.
*/
-const char *clang_getDeclarationName(CXEntity);
-const char *clang_getURI(CXEntity);
-CXEntity clang_getEntity(const char *URI);
+CINDEX_LINKAGE const char *clang_getDeclarationName(CXEntity);
+CINDEX_LINKAGE const char *clang_getURI(CXEntity);
+CINDEX_LINKAGE CXEntity clang_getEntity(const char *URI);
/*
* CXDecl Operations.
*/
-CXCursor clang_getCursorFromDecl(CXDecl);
-CXEntity clang_getEntityFromDecl(CXDecl);
-const char *clang_getDeclSpelling(CXDecl);
-unsigned clang_getDeclLine(CXDecl);
-unsigned clang_getDeclColumn(CXDecl);
-const char *clang_getDeclSource(CXDecl);
+CINDEX_LINKAGE CXCursor clang_getCursorFromDecl(CXDecl);
+CINDEX_LINKAGE CXEntity clang_getEntityFromDecl(CXDecl);
+CINDEX_LINKAGE const char *clang_getDeclSpelling(CXDecl);
+CINDEX_LINKAGE unsigned clang_getDeclLine(CXDecl);
+CINDEX_LINKAGE unsigned clang_getDeclColumn(CXDecl);
+CINDEX_LINKAGE const char *clang_getDeclSource(CXDecl); /* deprecate */
+CINDEX_LINKAGE CXFile clang_getDeclSourceFile(CXDecl);
/*
* CXCursor Operations.
@@ -252,38 +273,24 @@ const char *clang_getDeclSource(CXDecl);
Usage: clang_getCursor() will translate a source/line/column position
into an AST cursor (to derive semantic information from the source code).
*/
-CXCursor clang_getCursor(CXTranslationUnit, const char *source_name,
+CINDEX_LINKAGE CXCursor clang_getCursor(CXTranslationUnit, const char *source_name,
unsigned line, unsigned column);
-/**
- Usage: clang_getCursorWithHint() provides the same functionality as
- clang_getCursor() except that it takes an option 'hint' argument.
- The 'hint' is a temporary CXLookupHint object (whose lifetime is managed by
- the caller) that should be initialized with clang_initCXLookupHint().
-
- FIXME: Add a better comment once getCursorWithHint() has more functionality.
- */
-typedef CXCursor CXLookupHint;
-CXCursor clang_getCursorWithHint(CXTranslationUnit, const char *source_name,
- unsigned line, unsigned column,
- CXLookupHint *hint);
-
-void clang_initCXLookupHint(CXLookupHint *hint);
-
-enum CXCursorKind clang_getCursorKind(CXCursor);
-unsigned clang_isDeclaration(enum CXCursorKind);
-unsigned clang_isReference(enum CXCursorKind);
-unsigned clang_isDefinition(enum CXCursorKind);
-unsigned clang_isInvalid(enum CXCursorKind);
+CINDEX_LINKAGE enum CXCursorKind clang_getCursorKind(CXCursor);
+CINDEX_LINKAGE unsigned clang_isDeclaration(enum CXCursorKind);
+CINDEX_LINKAGE unsigned clang_isReference(enum CXCursorKind);
+CINDEX_LINKAGE unsigned clang_isDefinition(enum CXCursorKind);
+CINDEX_LINKAGE unsigned clang_isInvalid(enum CXCursorKind);
-unsigned clang_getCursorLine(CXCursor);
-unsigned clang_getCursorColumn(CXCursor);
-const char *clang_getCursorSource(CXCursor);
-const char *clang_getCursorSpelling(CXCursor);
+CINDEX_LINKAGE unsigned clang_getCursorLine(CXCursor);
+CINDEX_LINKAGE unsigned clang_getCursorColumn(CXCursor);
+CINDEX_LINKAGE const char *clang_getCursorSpelling(CXCursor);
+CINDEX_LINKAGE const char *clang_getCursorSource(CXCursor); /* deprecate */
+CINDEX_LINKAGE CXFile clang_getCursorSourceFile(CXCursor);
/* for debug/testing */
-const char *clang_getCursorKindSpelling(enum CXCursorKind Kind);
-void clang_getDefinitionSpellingAndExtent(CXCursor,
+CINDEX_LINKAGE const char *clang_getCursorKindSpelling(enum CXCursorKind Kind);
+CINDEX_LINKAGE void clang_getDefinitionSpellingAndExtent(CXCursor,
const char **startBuf,
const char **endBuf,
unsigned *startLine,
@@ -296,7 +303,7 @@ void clang_getDefinitionSpellingAndExtent(CXCursor,
* declaration.
* If CXCursorKind == Cursor_Declaration, then this will return the declaration.
*/
-CXDecl clang_getCursorDecl(CXCursor);
+CINDEX_LINKAGE CXDecl clang_getCursorDecl(CXCursor);
#ifdef __cplusplus
}
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 30896c91a143..7392170be995 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -16,6 +16,7 @@
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/OperatorKinds.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/NestedNameSpecifier.h"
@@ -301,22 +302,22 @@ public:
const char *getCommentForDecl(const Decl *D);
// Builtin Types.
- QualType VoidTy;
- QualType BoolTy;
- QualType CharTy;
- QualType WCharTy; // [C++ 3.9.1p5], integer type in C99.
- QualType Char16Ty; // [C++0x 3.9.1p5], integer type in C99.
- QualType Char32Ty; // [C++0x 3.9.1p5], integer type in C99.
- QualType SignedCharTy, ShortTy, IntTy, LongTy, LongLongTy, Int128Ty;
- QualType UnsignedCharTy, UnsignedShortTy, UnsignedIntTy, UnsignedLongTy;
- QualType UnsignedLongLongTy, UnsignedInt128Ty;
- QualType FloatTy, DoubleTy, LongDoubleTy;
- QualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy;
- QualType VoidPtrTy, NullPtrTy;
- QualType OverloadTy;
- QualType DependentTy;
- QualType UndeducedAutoTy;
- QualType ObjCBuiltinIdTy, ObjCBuiltinClassTy;
+ CanQualType VoidTy;
+ CanQualType BoolTy;
+ CanQualType CharTy;
+ CanQualType WCharTy; // [C++ 3.9.1p5], integer type in C99.
+ CanQualType Char16Ty; // [C++0x 3.9.1p5], integer type in C99.
+ CanQualType Char32Ty; // [C++0x 3.9.1p5], integer type in C99.
+ CanQualType SignedCharTy, ShortTy, IntTy, LongTy, LongLongTy, Int128Ty;
+ CanQualType UnsignedCharTy, UnsignedShortTy, UnsignedIntTy, UnsignedLongTy;
+ CanQualType UnsignedLongLongTy, UnsignedInt128Ty;
+ CanQualType FloatTy, DoubleTy, LongDoubleTy;
+ CanQualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy;
+ CanQualType VoidPtrTy, NullPtrTy;
+ CanQualType OverloadTy;
+ CanQualType DependentTy;
+ CanQualType UndeducedAutoTy;
+ CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy;
ASTContext(const LangOptions& LOpts, SourceManager &SM, TargetInfo &t,
IdentifierTable &idents, SelectorTable &sels,
@@ -387,10 +388,16 @@ public:
/// getComplexType - Return the uniqued reference to the type for a complex
/// number with the specified element type.
QualType getComplexType(QualType T);
+ CanQualType getComplexType(CanQualType T) {
+ return CanQualType::CreateUnsafe(getComplexType((QualType) T));
+ }
/// getPointerType - Return the uniqued reference to the type for a pointer to
/// the specified type.
QualType getPointerType(QualType T);
+ CanQualType getPointerType(CanQualType T) {
+ return CanQualType::CreateUnsafe(getPointerType((QualType) T));
+ }
/// getBlockPointerType - Return the uniqued reference to the type for a block
/// of the specified type.
@@ -525,6 +532,11 @@ public:
unsigned NumArgs,
QualType Canon = QualType());
+ QualType getTemplateSpecializationType(TemplateName T,
+ const TemplateArgumentLoc *Args,
+ unsigned NumArgs,
+ QualType Canon = QualType());
+
QualType getQualifiedNameType(NestedNameSpecifier *NNS,
QualType NamedType);
QualType getTypenameType(NestedNameSpecifier *NNS,
@@ -728,6 +740,8 @@ public:
TemplateName getDependentTemplateName(NestedNameSpecifier *NNS,
const IdentifierInfo *Name);
+ TemplateName getDependentTemplateName(NestedNameSpecifier *NNS,
+ OverloadedOperatorKind Operator);
enum GetBuiltinTypeError {
GE_None, //< No error
@@ -739,7 +753,7 @@ public:
QualType GetBuiltinType(unsigned ID, GetBuiltinTypeError &Error);
private:
- QualType getFromTargetType(unsigned Type) const;
+ CanQualType getFromTargetType(unsigned Type) const;
//===--------------------------------------------------------------------===//
// Type Predicates.
@@ -826,6 +840,8 @@ public:
llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars);
unsigned CountSynthesizedIvars(const ObjCInterfaceDecl *OI);
unsigned CountProtocolSynthesizedIvars(const ObjCProtocolDecl *PD);
+ void CollectInheritedProtocols(const Decl *CDecl,
+ llvm::SmallVectorImpl<ObjCProtocolDecl*> &Protocols);
//===--------------------------------------------------------------------===//
// Type Operators
@@ -1013,7 +1029,9 @@ public:
bool canAssignObjCInterfaces(const ObjCInterfaceType *LHS,
const ObjCInterfaceType *RHS);
bool areComparableObjCPointerTypes(QualType LHS, QualType RHS);
-
+ QualType areCommonBaseCompatible(const ObjCObjectPointerType *LHSOPT,
+ const ObjCObjectPointerType *RHSOPT);
+
// Functions for calculating composite types
QualType mergeTypes(QualType, QualType);
QualType mergeFunctionTypes(QualType, QualType);
@@ -1085,12 +1103,18 @@ public:
/// should be calculated based on the type.
DeclaratorInfo *CreateDeclaratorInfo(QualType T, unsigned Size = 0);
+ /// \brief Allocate a DeclaratorInfo where all locations have been
+ /// initialized to a given location, which defaults to the empty
+ /// location.
+ DeclaratorInfo *
+ getTrivialDeclaratorInfo(QualType T, SourceLocation Loc = SourceLocation());
+
private:
ASTContext(const ASTContext&); // DO NOT IMPLEMENT
void operator=(const ASTContext&); // DO NOT IMPLEMENT
void InitBuiltinTypes();
- void InitBuiltinType(QualType &R, BuiltinType::Kind K);
+ void InitBuiltinType(CanQualType &R, BuiltinType::Kind K);
// Return the ObjC type encoding for a given type.
void getObjCEncodingForTypeImpl(QualType t, std::string &S,
@@ -1103,6 +1127,18 @@ private:
const ASTRecordLayout &getObjCLayout(const ObjCInterfaceDecl *D,
const ObjCImplementationDecl *Impl);
};
+
+/// @brief Utility function for constructing a nullary selector.
+static inline Selector GetNullarySelector(const char* name, ASTContext& Ctx) {
+ IdentifierInfo* II = &Ctx.Idents.get(name);
+ return Ctx.Selectors.getSelector(0, &II);
+}
+
+/// @brief Utility function for constructing an unary selector.
+static inline Selector GetUnarySelector(const char* name, ASTContext& Ctx) {
+ IdentifierInfo* II = &Ctx.Idents.get(name);
+ return Ctx.Selectors.getSelector(1, &II);
+}
} // end namespace clang
diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h
index 8b84bc267997..a7750517090e 100644
--- a/include/clang/AST/CanonicalType.h
+++ b/include/clang/AST/CanonicalType.h
@@ -64,15 +64,6 @@ public:
CanQual(const CanQual<U>& Other,
typename llvm::enable_if<llvm::is_base_of<T, U>, int>::type = 0);
- /// \brief Implicit conversion to the underlying pointer.
- ///
- /// Also provides the ability to use canonical types in a boolean context,
- /// e.g.,
- /// @code
- /// if (CanQual<PointerType> Ptr = T->getAs<PointerType>()) { ... }
- /// @endcode
- operator const T*() const { return getTypePtr(); }
-
/// \brief Retrieve the underlying type pointer, which refers to a
/// canonical type.
T *getTypePtr() const { return cast_or_null<T>(Stored.getTypePtr()); }
@@ -80,6 +71,10 @@ public:
/// \brief Implicit conversion to a qualified type.
operator QualType() const { return Stored; }
+ bool isNull() const {
+ return Stored.isNull();
+ }
+
/// \brief Retrieve a canonical type pointer with a different static type,
/// upcasting or downcasting as needed.
///
@@ -125,8 +120,10 @@ public:
/// \brief Retrieve the unqualified form of this type.
CanQual<T> getUnqualifiedType() const;
- CanQual<T> getQualifiedType(unsigned TQs) const {
- return CanQual<T>::CreateUnsafe(QualType(getTypePtr(), TQs));
+ /// \brief Retrieves a version of this type with const applied.
+ /// Note that this does not always yield a canonical type.
+ QualType withConst() const {
+ return Stored.withConst();
}
/// \brief Determines whether this canonical type is more qualified than
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index 72ce0d852cfc..813e83accdb1 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -605,6 +605,9 @@ public:
/// \brief Determine whether this is or was instantiated from an out-of-line
/// definition of a static data member.
bool isOutOfLine() const;
+
+ /// \brief If this is a static data member, find its out-of-line definition.
+ VarDecl *getOutOfLineDefinition();
/// \brief If this variable is an instantiated static data member of a
/// class template specialization, returns the templated static data member
@@ -768,7 +771,11 @@ public:
Init = (UnparsedDefaultArgument *)0;
}
- QualType getOriginalType() const;
+ QualType getOriginalType() const {
+ if (getDeclaratorInfo())
+ return getDeclaratorInfo()->getType();
+ return getType();
+ }
/// setOwningFunction - Sets the function declaration that owns this
/// ParmVarDecl. Since ParmVarDecls are often created before the
@@ -778,41 +785,11 @@ public:
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
- return (D->getKind() == ParmVar ||
- D->getKind() == OriginalParmVar);
+ return (D->getKind() == ParmVar);
}
static bool classof(const ParmVarDecl *D) { return true; }
};
-/// OriginalParmVarDecl - Represent a parameter to a function, when
-/// the type of the parameter has been promoted. This node represents the
-/// parameter to the function with its original type.
-///
-class OriginalParmVarDecl : public ParmVarDecl {
- friend class ParmVarDecl;
-protected:
- QualType OriginalType;
-private:
- OriginalParmVarDecl(DeclContext *DC, SourceLocation L,
- IdentifierInfo *Id, QualType T,
- DeclaratorInfo *DInfo,
- QualType OT, StorageClass S,
- Expr *DefArg)
- : ParmVarDecl(OriginalParmVar, DC, L, Id, T, DInfo, S, DefArg),
- OriginalType(OT) {}
-public:
- static OriginalParmVarDecl *Create(ASTContext &C, DeclContext *DC,
- SourceLocation L,IdentifierInfo *Id,
- QualType T, DeclaratorInfo *DInfo,
- QualType OT, StorageClass S, Expr *DefArg);
-
- void setOriginalType(QualType T) { OriginalType = T; }
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Decl *D) { return D->getKind() == OriginalParmVar; }
- static bool classof(const OriginalParmVarDecl *D) { return true; }
-};
-
/// FunctionDecl - An instance of this class is created to represent a
/// function declaration or definition.
///
@@ -1067,9 +1044,18 @@ public:
StorageClass getStorageClass() const { return StorageClass(SClass); }
void setStorageClass(StorageClass SC) { SClass = SC; }
- bool isInline() const { return IsInline; }
- void setInline(bool I) { IsInline = I; }
+ /// \brief Determine whether the "inline" keyword was specified for this
+ /// function.
+ bool isInlineSpecified() const { return IsInline; }
+
+ /// Set whether the "inline" keyword was specified for this function.
+ void setInlineSpecified(bool I) { IsInline = I; }
+ /// \brief Determine whether this function should be inlined, because it is
+ /// either marked "inline" or is a member function of a C++ class that
+ /// was defined in the class body.
+ bool isInlined() const;
+
bool isInlineDefinitionExternallyVisible() const;
/// isOverloadedOperator - Whether this function declaration
@@ -1146,7 +1132,17 @@ public:
return TemplateOrSpecialization.
dyn_cast<FunctionTemplateSpecializationInfo*>();
}
-
+
+ /// \brief Determines whether this function is a function template
+ /// specialization or a member of a class template specialization that can
+ /// be implicitly instantiated.
+ bool isImplicitlyInstantiable() const;
+
+ /// \brief Retrieve the function declaration from which this function could
+ /// be instantiated, if it is an instantiation (rather than a non-template
+ /// or a specialization, for example).
+ FunctionDecl *getTemplateInstantiationPattern() const;
+
/// \brief Retrieve the primary template that this function template
/// specialization either specializes or was instantiated from.
///
@@ -1199,7 +1195,7 @@ public:
/// instantiated from a template; otherwie, returns an invalid source
/// location.
SourceLocation getPointOfInstantiation() const;
-
+
/// \brief Determine whether this is or was instantiated from an out-of-line
/// definition of a member function.
bool isOutOfLine() const;
@@ -1337,20 +1333,29 @@ public:
class TypedefDecl : public TypeDecl {
/// UnderlyingType - This is the type the typedef is set to.
- QualType UnderlyingType;
+ DeclaratorInfo *DInfo;
+
TypedefDecl(DeclContext *DC, SourceLocation L,
- IdentifierInfo *Id, QualType T)
- : TypeDecl(Typedef, DC, L, Id), UnderlyingType(T) {}
+ IdentifierInfo *Id, DeclaratorInfo *DInfo)
+ : TypeDecl(Typedef, DC, L, Id), DInfo(DInfo) {}
virtual ~TypedefDecl() {}
public:
static TypedefDecl *Create(ASTContext &C, DeclContext *DC,
- SourceLocation L,IdentifierInfo *Id,
- QualType T);
+ SourceLocation L, IdentifierInfo *Id,
+ DeclaratorInfo *DInfo);
+
+ DeclaratorInfo *getTypeDeclaratorInfo() const {
+ return DInfo;
+ }
- QualType getUnderlyingType() const { return UnderlyingType; }
- void setUnderlyingType(QualType newType) { UnderlyingType = newType; }
+ QualType getUnderlyingType() const {
+ return DInfo->getType();
+ }
+ void setTypeDeclaratorInfo(DeclaratorInfo *newType) {
+ DInfo = newType;
+ }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return D->getKind() == Typedef; }
diff --git a/include/clang/AST/DeclGroup.h b/include/clang/AST/DeclGroup.h
index 790ea3ca0662..e1fae8f2ae67 100644
--- a/include/clang/AST/DeclGroup.h
+++ b/include/clang/AST/DeclGroup.h
@@ -14,7 +14,7 @@
#ifndef LLVM_CLANG_AST_DECLGROUP_H
#define LLVM_CLANG_AST_DECLGROUP_H
-#include "llvm/Support/DataTypes.h"
+#include "llvm/System/DataTypes.h"
#include <cassert>
namespace clang {
diff --git a/include/clang/AST/DeclNodes.def b/include/clang/AST/DeclNodes.def
index 79a0d368288c..3ef3cc3f0975 100644
--- a/include/clang/AST/DeclNodes.def
+++ b/include/clang/AST/DeclNodes.def
@@ -103,7 +103,6 @@ ABSTRACT_DECL(Named, Decl)
DECL(Var, DeclaratorDecl)
DECL(ImplicitParam, VarDecl)
DECL(ParmVar, VarDecl)
- DECL(OriginalParmVar, ParmVarDecl)
DECL(NonTypeTemplateParm, VarDecl)
DECL(Template, NamedDecl)
DECL(FunctionTemplate, TemplateDecl)
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h
index 729a2f138303..bcd28eab039f 100644
--- a/include/clang/AST/DeclObjC.h
+++ b/include/clang/AST/DeclObjC.h
@@ -347,6 +347,8 @@ public:
ObjCIvarDecl *getIvarDecl(IdentifierInfo *Id) const;
ObjCPropertyDecl *FindPropertyDeclaration(IdentifierInfo *PropertyId) const;
+ ObjCPropertyDecl *FindPropertyVisibleInPrimaryClass(
+ IdentifierInfo *PropertyId) const;
// Marks the end of the container.
SourceLocation getAtEndLoc() const { return AtEndLoc; }
@@ -862,7 +864,7 @@ public:
};
class ObjCImplDecl : public ObjCContainerDecl {
- /// Class interface for this category implementation
+ /// Class interface for this class/category implementation
ObjCInterfaceDecl *ClassInterface;
protected:
@@ -935,14 +937,20 @@ public:
SourceLocation L, IdentifierInfo *Id,
ObjCInterfaceDecl *classInterface);
- /// getIdentifier - Get the identifier that names the class
+ /// getIdentifier - Get the identifier that names the category
/// interface associated with this implementation.
+ /// FIXME: This is a bad API, we are overriding the NamedDecl::getIdentifier()
+ /// to mean something different. For example:
+ /// ((NamedDecl *)SomeCategoryImplDecl)->getIdentifier()
+ /// returns the class interface name, whereas
+ /// ((ObjCCategoryImplDecl *)SomeCategoryImplDecl)->getIdentifier()
+ /// returns the category name.
IdentifierInfo *getIdentifier() const {
return Id;
}
void setIdentifier(IdentifierInfo *II) { Id = II; }
- ObjCCategoryDecl *getCategoryClass() const;
+ ObjCCategoryDecl *getCategoryDecl() const;
/// getName - Get the name of identifier for the class interface associated
/// with this implementation as a StringRef.
diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h
index 8d44676124fb..f1a27933a1b3 100644
--- a/include/clang/AST/DeclTemplate.h
+++ b/include/clang/AST/DeclTemplate.h
@@ -15,8 +15,7 @@
#define LLVM_CLANG_AST_DECLTEMPLATE_H
#include "clang/AST/DeclCXX.h"
-#include "llvm/ADT/APSInt.h"
-#include "llvm/ADT/FoldingSet.h"
+#include "clang/AST/TemplateBase.h"
#include "llvm/ADT/PointerUnion.h"
#include <limits>
@@ -91,6 +90,13 @@ public:
/// arguments or if there is a parameter pack.
unsigned getMinRequiredArguments() const;
+ /// \brief Get the depth of this template parameter list in the set of
+ /// template parameter lists.
+ ///
+ /// The first template parameter list in a declaration will have depth 0,
+ /// the second template parameter list will have depth 1, etc.
+ unsigned getDepth() const;
+
SourceLocation getTemplateLoc() const { return TemplateLoc; }
SourceLocation getLAngleLoc() const { return LAngleLoc; }
SourceLocation getRAngleLoc() const { return RAngleLoc; }
@@ -100,251 +106,6 @@ public:
}
};
-/// \brief Represents a template argument within a class template
-/// specialization.
-class TemplateArgument {
- union {
- uintptr_t TypeOrValue;
- struct {
- char Value[sizeof(llvm::APSInt)];
- void *Type;
- } Integer;
- struct {
- TemplateArgument *Args;
- unsigned NumArgs;
- bool CopyArgs;
- } Args;
- };
-
- /// \brief Location of the beginning of this template argument.
- SourceLocation StartLoc;
-
-public:
- /// \brief The type of template argument we're storing.
- enum ArgKind {
- Null = 0,
- /// The template argument is a type. Its value is stored in the
- /// TypeOrValue field.
- Type = 1,
- /// The template argument is a declaration
- Declaration = 2,
- /// The template argument is an integral value stored in an llvm::APSInt.
- Integral = 3,
- /// The template argument is a value- or type-dependent expression
- /// stored in an Expr*.
- Expression = 4,
-
- /// The template argument is actually a parameter pack. Arguments are stored
- /// in the Args struct.
- Pack = 5
- } Kind;
-
- /// \brief Construct an empty, invalid template argument.
- TemplateArgument() : TypeOrValue(0), StartLoc(), Kind(Null) { }
-
- /// \brief Construct a template type argument.
- TemplateArgument(SourceLocation Loc, QualType T) : Kind(Type) {
- TypeOrValue = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
- StartLoc = Loc;
- }
-
- /// \brief Construct a template argument that refers to a
- /// declaration, which is either an external declaration or a
- /// template declaration.
- TemplateArgument(SourceLocation Loc, Decl *D) : Kind(Declaration) {
- // FIXME: Need to be sure we have the "canonical" declaration!
- TypeOrValue = reinterpret_cast<uintptr_t>(D);
- StartLoc = Loc;
- }
-
- /// \brief Construct an integral constant template argument.
- TemplateArgument(SourceLocation Loc, const llvm::APSInt &Value,
- QualType Type)
- : Kind(Integral) {
- new (Integer.Value) llvm::APSInt(Value);
- Integer.Type = Type.getAsOpaquePtr();
- StartLoc = Loc;
- }
-
- /// \brief Construct a template argument that is an expression.
- ///
- /// This form of template argument only occurs in template argument
- /// lists used for dependent types and for expression; it will not
- /// occur in a non-dependent, canonical template argument list.
- TemplateArgument(Expr *E);
-
- /// \brief Copy constructor for a template argument.
- TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) {
- if (Kind == Integral) {
- new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
- Integer.Type = Other.Integer.Type;
- } else if (Kind == Pack) {
- Args.NumArgs = Other.Args.NumArgs;
- Args.Args = new TemplateArgument[Args.NumArgs];
- for (unsigned I = 0; I != Args.NumArgs; ++I)
- Args.Args[I] = Other.Args.Args[I];
- }
- else
- TypeOrValue = Other.TypeOrValue;
- StartLoc = Other.StartLoc;
- }
-
- TemplateArgument& operator=(const TemplateArgument& Other) {
- // FIXME: Does not provide the strong guarantee for exception
- // safety.
- using llvm::APSInt;
-
- // FIXME: Handle Packs
- assert(Kind != Pack && "FIXME: Handle packs");
- assert(Other.Kind != Pack && "FIXME: Handle packs");
-
- if (Kind == Other.Kind && Kind == Integral) {
- // Copy integral values.
- *this->getAsIntegral() = *Other.getAsIntegral();
- Integer.Type = Other.Integer.Type;
- } else {
- // Destroy the current integral value, if that's what we're holding.
- if (Kind == Integral)
- getAsIntegral()->~APSInt();
-
- Kind = Other.Kind;
-
- if (Other.Kind == Integral) {
- new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
- Integer.Type = Other.Integer.Type;
- } else
- TypeOrValue = Other.TypeOrValue;
- }
- StartLoc = Other.StartLoc;
-
- return *this;
- }
-
- ~TemplateArgument() {
- using llvm::APSInt;
-
- if (Kind == Integral)
- getAsIntegral()->~APSInt();
- else if (Kind == Pack && Args.CopyArgs)
- delete[] Args.Args;
- }
-
- /// \brief Return the kind of stored template argument.
- ArgKind getKind() const { return Kind; }
-
- /// \brief Determine whether this template argument has no value.
- bool isNull() const { return Kind == Null; }
-
- /// \brief Retrieve the template argument as a type.
- QualType getAsType() const {
- if (Kind != Type)
- return QualType();
-
- return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue));
- }
-
- /// \brief Retrieve the template argument as a declaration.
- Decl *getAsDecl() const {
- if (Kind != Declaration)
- return 0;
- return reinterpret_cast<Decl *>(TypeOrValue);
- }
-
- /// \brief Retrieve the template argument as an integral value.
- llvm::APSInt *getAsIntegral() {
- if (Kind != Integral)
- return 0;
- return reinterpret_cast<llvm::APSInt*>(&Integer.Value[0]);
- }
-
- const llvm::APSInt *getAsIntegral() const {
- return const_cast<TemplateArgument*>(this)->getAsIntegral();
- }
-
- /// \brief Retrieve the type of the integral value.
- QualType getIntegralType() const {
- if (Kind != Integral)
- return QualType();
-
- return QualType::getFromOpaquePtr(Integer.Type);
- }
-
- void setIntegralType(QualType T) {
- assert(Kind == Integral &&
- "Cannot set the integral type of a non-integral template argument");
- Integer.Type = T.getAsOpaquePtr();
- };
-
- /// \brief Retrieve the template argument as an expression.
- Expr *getAsExpr() const {
- if (Kind != Expression)
- return 0;
-
- return reinterpret_cast<Expr *>(TypeOrValue);
- }
-
- /// \brief Iterator that traverses the elements of a template argument pack.
- typedef const TemplateArgument * pack_iterator;
-
- /// \brief Iterator referencing the first argument of a template argument
- /// pack.
- pack_iterator pack_begin() const {
- assert(Kind == Pack);
- return Args.Args;
- }
-
- /// \brief Iterator referencing one past the last argument of a template
- /// argument pack.
- pack_iterator pack_end() const {
- assert(Kind == Pack);
- return Args.Args + Args.NumArgs;
- }
-
- /// \brief The number of template arguments in the given template argument
- /// pack.
- unsigned pack_size() const {
- assert(Kind == Pack);
- return Args.NumArgs;
- }
-
- /// \brief Retrieve the location where the template argument starts.
- SourceLocation getLocation() const { return StartLoc; }
-
- /// \brief Construct a template argument pack.
- void setArgumentPack(TemplateArgument *Args, unsigned NumArgs, bool CopyArgs);
-
- /// \brief Used to insert TemplateArguments into FoldingSets.
- void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context) const {
- ID.AddInteger(Kind);
- switch (Kind) {
- case Null:
- break;
-
- case Type:
- getAsType().Profile(ID);
- break;
-
- case Declaration:
- ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0);
- break;
-
- case Integral:
- getAsIntegral()->Profile(ID);
- getIntegralType().Profile(ID);
- break;
-
- case Expression:
- getAsExpr()->Profile(ID, Context, true);
- break;
-
- case Pack:
- ID.AddInteger(Args.NumArgs);
- for (unsigned I = 0; I != Args.NumArgs; ++I)
- Args.Args[I].Profile(ID, Context);
- }
- }
-};
-
/// \brief A helper class for making template argument lists.
class TemplateArgumentListBuilder {
TemplateArgument *StructuredArgs;
@@ -811,11 +572,8 @@ class TemplateTypeParmDecl : public TypeDecl {
/// \brief Whether this is a parameter pack.
bool ParameterPack : 1;
- /// \brief The location of the default argument, if any.
- SourceLocation DefaultArgumentLoc;
-
/// \brief The default template argument, if any.
- QualType DefaultArgument;
+ DeclaratorInfo *DefaultArgument;
TemplateTypeParmDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
bool Typename, QualType Type, bool ParameterPack)
@@ -837,13 +595,16 @@ public:
/// \brief Determine whether this template parameter has a default
/// argument.
- bool hasDefaultArgument() const { return !DefaultArgument.isNull(); }
+ bool hasDefaultArgument() const { return DefaultArgument != 0; }
/// \brief Retrieve the default argument, if any.
- QualType getDefaultArgument() const { return DefaultArgument; }
+ QualType getDefaultArgument() const { return DefaultArgument->getType(); }
- /// \brief Retrieve the location of the default argument, if any.
- SourceLocation getDefaultArgumentLoc() const { return DefaultArgumentLoc; }
+ /// \brief Retrieves the default argument's source information, if any.
+ DeclaratorInfo *getDefaultArgumentInfo() const { return DefaultArgument; }
+
+ /// \brief Retrieves the location of the default argument declaration.
+ SourceLocation getDefaultArgumentLoc() const;
/// \brief Determines whether the default argument was inherited
/// from a previous declaration of this template.
@@ -852,13 +613,23 @@ public:
/// \brief Set the default argument for this template parameter, and
/// whether that default argument was inherited from another
/// declaration.
- void setDefaultArgument(QualType DefArg, SourceLocation DefArgLoc,
- bool Inherited) {
+ void setDefaultArgument(DeclaratorInfo *DefArg, bool Inherited) {
DefaultArgument = DefArg;
- DefaultArgumentLoc = DefArgLoc;
InheritedDefault = Inherited;
}
+ /// \brief Removes the default argument of this template parameter.
+ void removeDefaultArgument() {
+ DefaultArgument = 0;
+ InheritedDefault = false;
+ }
+
+ /// \brief Retrieve the depth of the template parameter.
+ unsigned getDepth() const;
+
+ /// \brief Retrieve the index of the template parameter.
+ unsigned getIndex() const;
+
/// \brief Returns whether this is a parameter pack.
bool isParameterPack() const { return ParameterPack; }
@@ -1150,17 +921,32 @@ class ClassTemplatePartialSpecializationDecl
/// \brief The list of template parameters
TemplateParameterList* TemplateParams;
+ /// \brief The source info for the template arguments as written.
+ TemplateArgumentLoc *ArgsAsWritten;
+ unsigned NumArgsAsWritten;
+
+ /// \brief The class template partial specialization from which this
+ /// class template partial specialization was instantiated.
+ ///
+ /// The boolean value will be true to indicate that this class template
+ /// partial specialization was specialized at this level.
+ llvm::PointerIntPair<ClassTemplatePartialSpecializationDecl *, 1, bool>
+ InstantiatedFromMember;
+
ClassTemplatePartialSpecializationDecl(ASTContext &Context,
DeclContext *DC, SourceLocation L,
TemplateParameterList *Params,
ClassTemplateDecl *SpecializedTemplate,
TemplateArgumentListBuilder &Builder,
+ TemplateArgumentLoc *ArgInfos,
+ unsigned NumArgInfos,
ClassTemplatePartialSpecializationDecl *PrevDecl)
: ClassTemplateSpecializationDecl(Context,
ClassTemplatePartialSpecialization,
DC, L, SpecializedTemplate, Builder,
PrevDecl),
- TemplateParams(Params) { }
+ TemplateParams(Params), ArgsAsWritten(ArgInfos),
+ NumArgsAsWritten(NumArgInfos), InstantiatedFromMember(0, false) { }
public:
static ClassTemplatePartialSpecializationDecl *
@@ -1168,6 +954,8 @@ public:
TemplateParameterList *Params,
ClassTemplateDecl *SpecializedTemplate,
TemplateArgumentListBuilder &Builder,
+ TemplateArgumentLoc *ArgInfos,
+ unsigned NumArgInfos,
ClassTemplatePartialSpecializationDecl *PrevDecl);
/// Get the list of template parameters
@@ -1175,6 +963,80 @@ public:
return TemplateParams;
}
+ /// Get the template arguments as written.
+ TemplateArgumentLoc *getTemplateArgsAsWritten() const {
+ return ArgsAsWritten;
+ }
+
+ /// Get the number of template arguments as written.
+ unsigned getNumTemplateArgsAsWritten() const {
+ return NumArgsAsWritten;
+ }
+
+ /// \brief Retrieve the member class template partial specialization from
+ /// which this particular class template partial specialization was
+ /// instantiated.
+ ///
+ /// \code
+ /// template<typename T>
+ /// struct Outer {
+ /// template<typename U> struct Inner;
+ /// template<typename U> struct Inner<U*> { }; // #1
+ /// };
+ ///
+ /// Outer<float>::Inner<int*> ii;
+ /// \endcode
+ ///
+ /// In this example, the instantiation of \c Outer<float>::Inner<int*> will
+ /// end up instantiating the partial specialization
+ /// \c Outer<float>::Inner<U*>, which itself was instantiated from the class
+ /// template partial specialization \c Outer<T>::Inner<U*>. Given
+ /// \c Outer<float>::Inner<U*>, this function would return
+ /// \c Outer<T>::Inner<U*>.
+ ClassTemplatePartialSpecializationDecl *getInstantiatedFromMember() {
+ ClassTemplatePartialSpecializationDecl *First
+ = cast<ClassTemplatePartialSpecializationDecl>(getFirstDeclaration());
+ return First->InstantiatedFromMember.getPointer();
+ }
+
+ void setInstantiatedFromMember(
+ ClassTemplatePartialSpecializationDecl *PartialSpec) {
+ ClassTemplatePartialSpecializationDecl *First
+ = cast<ClassTemplatePartialSpecializationDecl>(getFirstDeclaration());
+ First->InstantiatedFromMember.setPointer(PartialSpec);
+ }
+
+ /// \brief Determines whether this class template partial specialization
+ /// template was a specialization of a member partial specialization.
+ ///
+ /// In the following example, the member template partial specialization
+ /// \c X<int>::Inner<T*> is a member specialization.
+ ///
+ /// \code
+ /// template<typename T>
+ /// struct X {
+ /// template<typename U> struct Inner;
+ /// template<typename U> struct Inner<U*>;
+ /// };
+ ///
+ /// template<> template<typename T>
+ /// struct X<int>::Inner<T*> { /* ... */ };
+ /// \endcode
+ bool isMemberSpecialization() {
+ ClassTemplatePartialSpecializationDecl *First
+ = cast<ClassTemplatePartialSpecializationDecl>(getFirstDeclaration());
+ return First->InstantiatedFromMember.getInt();
+ }
+
+ /// \brief Note that this member template is a specialization.
+ void setMemberSpecialization() {
+ ClassTemplatePartialSpecializationDecl *First
+ = cast<ClassTemplatePartialSpecializationDecl>(getFirstDeclaration());
+ assert(First->InstantiatedFromMember.getPointer() &&
+ "Only member templates can be member template specializations");
+ return First->InstantiatedFromMember.setInt(true);
+ }
+
// FIXME: Add Profile support!
static bool classof(const Decl *D) {
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index 0d09ea325c31..2a87f5883588 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -34,6 +34,7 @@ namespace clang {
class BlockDecl;
class CXXOperatorCallExpr;
class CXXMemberCallExpr;
+ class TemplateArgumentLoc;
/// Expr - This represents one expression. Note that Expr's are subclasses of
/// Stmt. This allows an expression to be transparently used any place a Stmt
@@ -134,7 +135,7 @@ public:
/// with location to warn on and the source range[s] to report with the
/// warning.
bool isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
- SourceRange &R2) const;
+ SourceRange &R2, ASTContext &Ctx) const;
/// isLvalue - C99 6.3.2.1: an lvalue is an expression with an object type or
/// incomplete type other than void. Nonarray expressions that can be lvalues:
@@ -241,6 +242,10 @@ public:
/// in Result.
bool Evaluate(EvalResult &Result, ASTContext &Ctx) const;
+ /// EvaluateAsAny - The same as Evaluate, except that it also succeeds on
+ /// stack based objects.
+ bool EvaluateAsAny(EvalResult &Result, ASTContext &Ctx) const;
+
/// isEvaluatable - Call Evaluate to see if this expression can be constant
/// folded, but discard the result.
bool isEvaluatable(ASTContext &Ctx) const;
@@ -322,47 +327,221 @@ public:
// Primary Expressions.
//===----------------------------------------------------------------------===//
+/// \brief Represents the qualifier that may precede a C++ name, e.g., the
+/// "std::" in "std::sort".
+struct NameQualifier {
+ /// \brief The nested name specifier.
+ NestedNameSpecifier *NNS;
+
+ /// \brief The source range covered by the nested name specifier.
+ SourceRange Range;
+};
+
+/// \brief Represents an explicit template argument list in C++, e.g.,
+/// the "<int>" in "sort<int>".
+struct ExplicitTemplateArgumentList {
+ /// \brief The source location of the left angle bracket ('<');
+ SourceLocation LAngleLoc;
+
+ /// \brief The source location of the right angle bracket ('>');
+ SourceLocation RAngleLoc;
+
+ /// \brief The number of template arguments in TemplateArgs.
+ /// The actual template arguments (if any) are stored after the
+ /// ExplicitTemplateArgumentList structure.
+ unsigned NumTemplateArgs;
+
+ /// \brief Retrieve the template arguments
+ TemplateArgumentLoc *getTemplateArgs() {
+ return reinterpret_cast<TemplateArgumentLoc *> (this + 1);
+ }
+
+ /// \brief Retrieve the template arguments
+ const TemplateArgumentLoc *getTemplateArgs() const {
+ return reinterpret_cast<const TemplateArgumentLoc *> (this + 1);
+ }
+};
+
/// DeclRefExpr - [C99 6.5.1p2] - A reference to a declared variable, function,
/// enum, etc.
class DeclRefExpr : public Expr {
- NamedDecl *D;
+ enum {
+ // Flag on DecoratedD that specifies when this declaration reference
+ // expression has a C++ nested-name-specifier.
+ HasQualifierFlag = 0x01,
+ // Flag on DecoratedD that specifies when this declaration reference
+ // expression has an explicit C++ template argument list.
+ HasExplicitTemplateArgumentListFlag = 0x02
+ };
+
+ // DecoratedD - The declaration that we are referencing, plus two bits to
+ // indicate whether (1) the declaration's name was explicitly qualified and
+ // (2) the declaration's name was followed by an explicit template
+ // argument list.
+ llvm::PointerIntPair<NamedDecl *, 2> DecoratedD;
+
+ // Loc - The location of the declaration name itself.
SourceLocation Loc;
+ /// \brief Retrieve the qualifier that preceded the declaration name, if any.
+ NameQualifier *getNameQualifier() {
+ if ((DecoratedD.getInt() & HasQualifierFlag) == 0)
+ return 0;
+
+ return reinterpret_cast<NameQualifier *> (this + 1);
+ }
+
+ /// \brief Retrieve the qualifier that preceded the member name, if any.
+ const NameQualifier *getNameQualifier() const {
+ return const_cast<DeclRefExpr *>(this)->getNameQualifier();
+ }
+
+ /// \brief Retrieve the explicit template argument list that followed the
+ /// member template name, if any.
+ ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() {
+ if ((DecoratedD.getInt() & HasExplicitTemplateArgumentListFlag) == 0)
+ return 0;
+
+ if ((DecoratedD.getInt() & HasQualifierFlag) == 0)
+ return reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1);
+
+ return reinterpret_cast<ExplicitTemplateArgumentList *>(
+ getNameQualifier() + 1);
+ }
+
+ /// \brief Retrieve the explicit template argument list that followed the
+ /// member template name, if any.
+ const ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() const {
+ return const_cast<DeclRefExpr *>(this)->getExplicitTemplateArgumentList();
+ }
+
+ DeclRefExpr(NestedNameSpecifier *Qualifier, SourceRange QualifierRange,
+ NamedDecl *D, SourceLocation NameLoc,
+ bool HasExplicitTemplateArgumentList,
+ SourceLocation LAngleLoc,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
+ unsigned NumExplicitTemplateArgs,
+ SourceLocation RAngleLoc,
+ QualType T, bool TD, bool VD);
+
protected:
// FIXME: Eventually, this constructor will go away and all subclasses
// will have to provide the type- and value-dependent flags.
DeclRefExpr(StmtClass SC, NamedDecl *d, QualType t, SourceLocation l) :
- Expr(SC, t), D(d), Loc(l) {}
+ Expr(SC, t), DecoratedD(d, 0), Loc(l) {}
DeclRefExpr(StmtClass SC, NamedDecl *d, QualType t, SourceLocation l, bool TD,
bool VD) :
- Expr(SC, t, TD, VD), D(d), Loc(l) {}
+ Expr(SC, t, TD, VD), DecoratedD(d, 0), Loc(l) {}
public:
// FIXME: Eventually, this constructor will go away and all clients
// will have to provide the type- and value-dependent flags.
DeclRefExpr(NamedDecl *d, QualType t, SourceLocation l) :
- Expr(DeclRefExprClass, t), D(d), Loc(l) {}
+ Expr(DeclRefExprClass, t), DecoratedD(d, 0), Loc(l) {}
DeclRefExpr(NamedDecl *d, QualType t, SourceLocation l, bool TD, bool VD) :
- Expr(DeclRefExprClass, t, TD, VD), D(d), Loc(l) {}
+ Expr(DeclRefExprClass, t, TD, VD), DecoratedD(d, 0), Loc(l) {}
/// \brief Construct an empty declaration reference expression.
explicit DeclRefExpr(EmptyShell Empty)
: Expr(DeclRefExprClass, Empty) { }
- NamedDecl *getDecl() { return D; }
- const NamedDecl *getDecl() const { return D; }
- void setDecl(NamedDecl *NewD) { D = NewD; }
+ static DeclRefExpr *Create(ASTContext &Context,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ NamedDecl *D,
+ SourceLocation NameLoc,
+ QualType T, bool TD, bool VD);
+
+ static DeclRefExpr *Create(ASTContext &Context,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ NamedDecl *D,
+ SourceLocation NameLoc,
+ bool HasExplicitTemplateArgumentList,
+ SourceLocation LAngleLoc,
+ const TemplateArgumentLoc *ExplicitTemplateArgs,
+ unsigned NumExplicitTemplateArgs,
+ SourceLocation RAngleLoc,
+ QualType T, bool TD, bool VD);
+
+ NamedDecl *getDecl() { return DecoratedD.getPointer(); }
+ const NamedDecl *getDecl() const { return DecoratedD.getPointer(); }
+ void setDecl(NamedDecl *NewD) { DecoratedD.setPointer(NewD); }
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
- virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
+ virtual SourceRange getSourceRange() const;
+ /// \brief Determine whether this declaration reference was preceded by a
+ /// C++ nested-name-specifier, e.g., \c N::foo.
+ bool hasQualifier() const { return DecoratedD.getInt() & HasQualifierFlag; }
+
+ /// \brief If the name was qualified, retrieves the source range of
+ /// the nested-name-specifier that precedes the name. Otherwise,
+ /// returns an empty source range.
+ SourceRange getQualifierRange() const {
+ if (!hasQualifier())
+ return SourceRange();
+
+ return getNameQualifier()->Range;
+ }
+
+ /// \brief If the name was qualified, retrieves the nested-name-specifier
+ /// that precedes the name. Otherwise, returns NULL.
+ NestedNameSpecifier *getQualifier() const {
+ if (!hasQualifier())
+ return 0;
+
+ return getNameQualifier()->NNS;
+ }
+
+ /// \brief Determines whether this member expression actually had a C++
+ /// template argument list explicitly specified, e.g., x.f<int>.
+ bool hasExplicitTemplateArgumentList() const {
+ return DecoratedD.getInt() & HasExplicitTemplateArgumentListFlag;
+ }
+
+ /// \brief Retrieve the location of the left angle bracket following the
+ /// member name ('<'), if any.
+ SourceLocation getLAngleLoc() const {
+ if (!hasExplicitTemplateArgumentList())
+ return SourceLocation();
+
+ return getExplicitTemplateArgumentList()->LAngleLoc;
+ }
+
+ /// \brief Retrieve the template arguments provided as part of this
+ /// template-id.
+ const TemplateArgumentLoc *getTemplateArgs() const {
+ if (!hasExplicitTemplateArgumentList())
+ return 0;
+
+ return getExplicitTemplateArgumentList()->getTemplateArgs();
+ }
+
+ /// \brief Retrieve the number of template arguments provided as part of this
+ /// template-id.
+ unsigned getNumTemplateArgs() const {
+ if (!hasExplicitTemplateArgumentList())
+ return 0;
+
+ return getExplicitTemplateArgumentList()->NumTemplateArgs;
+ }
+
+ /// \brief Retrieve the location of the right angle bracket following the
+ /// template arguments ('>').
+ SourceLocation getRAngleLoc() const {
+ if (!hasExplicitTemplateArgumentList())
+ return SourceLocation();
+
+ return getExplicitTemplateArgumentList()->RAngleLoc;
+ }
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == DeclRefExprClass ||
- T->getStmtClass() == CXXConditionDeclExprClass ||
- T->getStmtClass() == QualifiedDeclRefExprClass;
+ T->getStmtClass() == CXXConditionDeclExprClass;
}
static bool classof(const DeclRefExpr *) { return true; }
@@ -797,7 +976,7 @@ class SizeOfAlignOfExpr : public Expr {
bool isSizeof : 1; // true if sizeof, false if alignof.
bool isType : 1; // true if operand is a type, false if an expression
union {
- void *Ty;
+ DeclaratorInfo *Ty;
Stmt *Ex;
} Argument;
SourceLocation OpLoc, RParenLoc;
@@ -806,15 +985,15 @@ protected:
virtual void DoDestroy(ASTContext& C);
public:
- SizeOfAlignOfExpr(bool issizeof, QualType T,
+ SizeOfAlignOfExpr(bool issizeof, DeclaratorInfo *DInfo,
QualType resultType, SourceLocation op,
SourceLocation rp) :
Expr(SizeOfAlignOfExprClass, resultType,
false, // Never type-dependent (C++ [temp.dep.expr]p3).
// Value-dependent if the argument is type-dependent.
- T->isDependentType()),
+ DInfo->getType()->isDependentType()),
isSizeof(issizeof), isType(true), OpLoc(op), RParenLoc(rp) {
- Argument.Ty = T.getAsOpaquePtr();
+ Argument.Ty = DInfo;
}
SizeOfAlignOfExpr(bool issizeof, Expr *E,
@@ -837,8 +1016,11 @@ public:
bool isArgumentType() const { return isType; }
QualType getArgumentType() const {
+ return getArgumentTypeInfo()->getType();
+ }
+ DeclaratorInfo *getArgumentTypeInfo() const {
assert(isArgumentType() && "calling getArgumentType() when arg is expr");
- return QualType::getFromOpaquePtr(Argument.Ty);
+ return Argument.Ty;
}
Expr *getArgumentExpr() {
assert(!isArgumentType() && "calling getArgumentExpr() when arg is type");
@@ -849,8 +1031,8 @@ public:
}
void setArgument(Expr *E) { Argument.Ex = E; isType = false; }
- void setArgument(QualType T) {
- Argument.Ty = T.getAsOpaquePtr();
+ void setArgument(DeclaratorInfo *DInfo) {
+ Argument.Ty = DInfo;
isType = true;
}
@@ -1062,41 +1244,6 @@ public:
virtual child_iterator child_end();
};
-/// \brief Represents the qualifier that may precede a C++ name, e.g., the
-/// "std::" in "std::sort".
-struct NameQualifier {
- /// \brief The nested name specifier.
- NestedNameSpecifier *NNS;
-
- /// \brief The source range covered by the nested name specifier.
- SourceRange Range;
-};
-
-/// \brief Represents an explicit template argument list in C++, e.g.,
-/// the "<int>" in "sort<int>".
-struct ExplicitTemplateArgumentList {
- /// \brief The source location of the left angle bracket ('<');
- SourceLocation LAngleLoc;
-
- /// \brief The source location of the right angle bracket ('>');
- SourceLocation RAngleLoc;
-
- /// \brief The number of template arguments in TemplateArgs.
- /// The actual template arguments (if any) are stored after the
- /// ExplicitTemplateArgumentList structure.
- unsigned NumTemplateArgs;
-
- /// \brief Retrieve the template arguments
- TemplateArgument *getTemplateArgs() {
- return reinterpret_cast<TemplateArgument *> (this + 1);
- }
-
- /// \brief Retrieve the template arguments
- const TemplateArgument *getTemplateArgs() const {
- return reinterpret_cast<const TemplateArgument *> (this + 1);
- }
-};
-
/// MemberExpr - [C99 6.5.2.3] Structure and Union Members. X->F and X.F.
///
class MemberExpr : public Expr {
@@ -1161,7 +1308,7 @@ class MemberExpr : public Expr {
MemberExpr(Expr *base, bool isarrow, NestedNameSpecifier *qual,
SourceRange qualrange, NamedDecl *memberdecl, SourceLocation l,
bool has_explicit, SourceLocation langle,
- const TemplateArgument *targs, unsigned numtargs,
+ const TemplateArgumentLoc *targs, unsigned numtargs,
SourceLocation rangle, QualType ty);
public:
@@ -1183,7 +1330,7 @@ public:
SourceLocation l,
bool has_explicit,
SourceLocation langle,
- const TemplateArgument *targs,
+ const TemplateArgumentLoc *targs,
unsigned numtargs,
SourceLocation rangle,
QualType ty);
@@ -1240,7 +1387,7 @@ public:
/// \brief Retrieve the template arguments provided as part of this
/// template-id.
- const TemplateArgument *getTemplateArgs() const {
+ const TemplateArgumentLoc *getTemplateArgs() const {
if (!HasExplicitTemplateArgumentList)
return 0;
@@ -1388,6 +1535,10 @@ public:
/// member pointer in derived class.
CK_BaseToDerivedMemberPointer,
+ /// CK_DerivedToBaseMemberPointer - Member pointer in derived class to
+ /// member pointer in base class.
+ CK_DerivedToBaseMemberPointer,
+
/// CK_UserDefinedConversion - Conversion using a user defined type
/// conversion function.
CK_UserDefinedConversion,
@@ -1687,7 +1838,9 @@ public:
bool isAdditiveOp() const { return Opc == Add || Opc == Sub; }
static bool isShiftOp(Opcode Opc) { return Opc == Shl || Opc == Shr; }
bool isShiftOp() const { return isShiftOp(Opc); }
- bool isBitwiseOp() const { return Opc >= And && Opc <= Or; }
+
+ static bool isBitwiseOp(Opcode Opc) { return Opc >= And && Opc <= Or; }
+ bool isBitwiseOp() const { return isBitwiseOp(Opc); }
static bool isRelationalOp(Opcode Opc) { return Opc >= LT && Opc <= GE; }
bool isRelationalOp() const { return isRelationalOp(Opc); }
@@ -1695,6 +1848,9 @@ public:
static bool isEqualityOp(Opcode Opc) { return Opc == EQ || Opc == NE; }
bool isEqualityOp() const { return isEqualityOp(Opc); }
+ static bool isComparisonOp(Opcode Opc) { return Opc >= LT && Opc <= NE; }
+ bool isComparisonOp() const { return isComparisonOp(Opc); }
+
static bool isLogicalOp(Opcode Opc) { return Opc == LAnd || Opc == LOr; }
bool isLogicalOp() const { return isLogicalOp(Opc); }
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
index 3f66b1f40bfc..5931a3fcf984 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/include/clang/AST/ExprCXX.h
@@ -1061,46 +1061,11 @@ public:
virtual child_iterator child_end();
};
-/// QualifiedDeclRefExpr - A reference to a declared variable,
-/// function, enum, etc., that includes a qualification, e.g.,
-/// "N::foo".
-class QualifiedDeclRefExpr : public DeclRefExpr {
- /// QualifierRange - The source range that covers the
- /// nested-name-specifier.
- SourceRange QualifierRange;
-
- /// \brief The nested-name-specifier that qualifies this declaration
- /// name.
- NestedNameSpecifier *NNS;
-
-public:
- QualifiedDeclRefExpr(NamedDecl *d, QualType t, SourceLocation l, bool TD,
- bool VD, SourceRange R, NestedNameSpecifier *NNS)
- : DeclRefExpr(QualifiedDeclRefExprClass, d, t, l, TD, VD),
- QualifierRange(R), NNS(NNS) { }
-
- /// \brief Retrieve the source range of the nested-name-specifier.
- SourceRange getQualifierRange() const { return QualifierRange; }
-
- /// \brief Retrieve the nested-name-specifier that qualifies this
- /// declaration.
- NestedNameSpecifier *getQualifier() const { return NNS; }
-
- virtual SourceRange getSourceRange() const {
- return SourceRange(QualifierRange.getBegin(), getLocation());
- }
-
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == QualifiedDeclRefExprClass;
- }
- static bool classof(const QualifiedDeclRefExpr *) { return true; }
-};
-
/// \brief A qualified reference to a name whose declaration cannot
/// yet be resolved.
///
-/// UnresolvedDeclRefExpr is similar to QualifiedDeclRefExpr in that
-/// it expresses a qualified reference to a declaration such as
+/// UnresolvedDeclRefExpr is similar to eclRefExpr in that
+/// it expresses a reference to a declaration such as
/// X<T>::value. The difference, however, is that an
/// UnresolvedDeclRefExpr node is used only within C++ templates when
/// the qualification (e.g., X<T>::) refers to a dependent type. In
@@ -1108,8 +1073,8 @@ public:
/// declaration will differ from on instantiation of X<T> to the
/// next. Therefore, UnresolvedDeclRefExpr keeps track of the
/// qualifier (X<T>::) and the name of the entity being referenced
-/// ("value"). Such expressions will instantiate to
-/// QualifiedDeclRefExprs.
+/// ("value"). Such expressions will instantiate to a DeclRefExpr once the
+/// declaration can be found.
class UnresolvedDeclRefExpr : public Expr {
/// The name of the entity we will be referencing.
DeclarationName Name;
@@ -1126,6 +1091,7 @@ class UnresolvedDeclRefExpr : public Expr {
NestedNameSpecifier *NNS;
/// \brief Whether this expr is an address of (&) operand.
+ /// FIXME: Stash this bit into NNS!
bool IsAddressOfOperand;
public:
@@ -1195,7 +1161,7 @@ class TemplateIdRefExpr : public Expr {
NestedNameSpecifier *Qualifier, SourceRange QualifierRange,
TemplateName Template, SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
- const TemplateArgument *TemplateArgs,
+ const TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs,
SourceLocation RAngleLoc);
@@ -1206,7 +1172,7 @@ public:
Create(ASTContext &Context, QualType T,
NestedNameSpecifier *Qualifier, SourceRange QualifierRange,
TemplateName Template, SourceLocation TemplateNameLoc,
- SourceLocation LAngleLoc, const TemplateArgument *TemplateArgs,
+ SourceLocation LAngleLoc, const TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs, SourceLocation RAngleLoc);
/// \brief Retrieve the nested name specifier used to qualify the name of
@@ -1232,8 +1198,8 @@ public:
/// \brief Retrieve the template arguments provided as part of this
/// template-id.
- const TemplateArgument *getTemplateArgs() const {
- return reinterpret_cast<const TemplateArgument *>(this + 1);
+ const TemplateArgumentLoc *getTemplateArgs() const {
+ return reinterpret_cast<const TemplateArgumentLoc *>(this + 1);
}
/// \brief Retrieve the number of template arguments provided as part of this
@@ -1477,7 +1443,7 @@ class CXXUnresolvedMemberExpr : public Expr {
SourceLocation MemberLoc,
bool HasExplicitTemplateArgs,
SourceLocation LAngleLoc,
- const TemplateArgument *TemplateArgs,
+ const TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs,
SourceLocation RAngleLoc);
@@ -1508,7 +1474,7 @@ public:
SourceLocation MemberLoc,
bool HasExplicitTemplateArgs,
SourceLocation LAngleLoc,
- const TemplateArgument *TemplateArgs,
+ const TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs,
SourceLocation RAngleLoc);
@@ -1576,7 +1542,7 @@ public:
/// \brief Retrieve the template arguments provided as part of this
/// template-id.
- const TemplateArgument *getTemplateArgs() const {
+ const TemplateArgumentLoc *getTemplateArgs() const {
if (!HasExplicitTemplateArgumentList)
return 0;
diff --git a/include/clang/AST/RecordLayout.h b/include/clang/AST/RecordLayout.h
index 7490b1d66b3e..5f318ba0b33b 100644
--- a/include/clang/AST/RecordLayout.h
+++ b/include/clang/AST/RecordLayout.h
@@ -14,7 +14,7 @@
#ifndef LLVM_CLANG_AST_LAYOUTINFO_H
#define LLVM_CLANG_AST_LAYOUTINFO_H
-#include "llvm/Support/DataTypes.h"
+#include "llvm/System/DataTypes.h"
namespace clang {
class ASTContext;
diff --git a/include/clang/AST/Redeclarable.h b/include/clang/AST/Redeclarable.h
index 458af1f14423..1e6871ff3b9c 100644
--- a/include/clang/AST/Redeclarable.h
+++ b/include/clang/AST/Redeclarable.h
@@ -88,6 +88,11 @@ public:
return D;
}
+ /// \brief Returns the most recent (re)declaration of this declaration.
+ const decl_type *getMostRecentDeclaration() const {
+ return getFirstDeclaration()->RedeclLink.getNext();
+ }
+
/// \brief Set the previous declaration. If PrevDecl is NULL, set this as the
/// first and only declaration.
void setPreviousDeclaration(decl_type *PrevDecl) {
diff --git a/include/clang/AST/StmtIterator.h b/include/clang/AST/StmtIterator.h
index 2d523fffce74..f1aa2cd50f0f 100644
--- a/include/clang/AST/StmtIterator.h
+++ b/include/clang/AST/StmtIterator.h
@@ -14,7 +14,7 @@
#ifndef LLVM_CLANG_AST_STMT_ITR_H
#define LLVM_CLANG_AST_STMT_ITR_H
-#include "llvm/Support/DataTypes.h"
+#include "llvm/System/DataTypes.h"
#include <cassert>
#include <iterator>
diff --git a/include/clang/AST/StmtNodes.def b/include/clang/AST/StmtNodes.def
index 8d7e4b5fc0a3..034029a16971 100644
--- a/include/clang/AST/StmtNodes.def
+++ b/include/clang/AST/StmtNodes.def
@@ -127,7 +127,6 @@ EXPR(CXXDeleteExpr , Expr)
EXPR(CXXPseudoDestructorExpr, Expr)
EXPR(UnresolvedFunctionNameExpr , Expr)
EXPR(UnaryTypeTraitExpr , Expr)
-EXPR(QualifiedDeclRefExpr , DeclRefExpr)
EXPR(UnresolvedDeclRefExpr , Expr)
EXPR(TemplateIdRefExpr , Expr)
EXPR(CXXConstructExpr , Expr)
diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h
new file mode 100644
index 000000000000..bb14c62d7770
--- /dev/null
+++ b/include/clang/AST/TemplateBase.h
@@ -0,0 +1,366 @@
+//===-- TemplateBase.h - Core classes for C++ templates ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides definitions which are common for all kinds of
+// template representation.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_TEMPLATEBASE_H
+#define LLVM_CLANG_AST_TEMPLATEBASE_H
+
+#include "llvm/ADT/APSInt.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "clang/AST/Type.h"
+
+namespace llvm {
+ class FoldingSetNodeID;
+}
+
+namespace clang {
+
+class Decl;
+class Expr;
+class DeclaratorInfo;
+
+/// \brief Represents a template argument within a class template
+/// specialization.
+class TemplateArgument {
+ union {
+ uintptr_t TypeOrValue;
+ struct {
+ char Value[sizeof(llvm::APSInt)];
+ void *Type;
+ } Integer;
+ struct {
+ TemplateArgument *Args;
+ unsigned NumArgs;
+ bool CopyArgs;
+ } Args;
+ };
+
+public:
+ /// \brief The type of template argument we're storing.
+ enum ArgKind {
+ Null = 0,
+ /// The template argument is a type. Its value is stored in the
+ /// TypeOrValue field.
+ Type = 1,
+ /// The template argument is a declaration
+ Declaration = 2,
+ /// The template argument is an integral value stored in an llvm::APSInt.
+ Integral = 3,
+ /// The template argument is a value- or type-dependent expression
+ /// stored in an Expr*.
+ Expression = 4,
+
+ /// The template argument is actually a parameter pack. Arguments are stored
+ /// in the Args struct.
+ Pack = 5
+ } Kind;
+
+ /// \brief Construct an empty, invalid template argument.
+ TemplateArgument() : TypeOrValue(0), Kind(Null) { }
+
+ /// \brief Construct a template type argument.
+ TemplateArgument(QualType T) : Kind(Type) {
+ TypeOrValue = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
+ }
+
+ /// \brief Construct a template argument that refers to a
+ /// declaration, which is either an external declaration or a
+ /// template declaration.
+ TemplateArgument(Decl *D) : Kind(Declaration) {
+ // FIXME: Need to be sure we have the "canonical" declaration!
+ TypeOrValue = reinterpret_cast<uintptr_t>(D);
+ }
+
+ /// \brief Construct an integral constant template argument.
+ TemplateArgument(const llvm::APSInt &Value, QualType Type)
+ : Kind(Integral) {
+ new (Integer.Value) llvm::APSInt(Value);
+ Integer.Type = Type.getAsOpaquePtr();
+ }
+
+ /// \brief Construct a template argument that is an expression.
+ ///
+ /// This form of template argument only occurs in template argument
+ /// lists used for dependent types and for expression; it will not
+ /// occur in a non-dependent, canonical template argument list.
+ TemplateArgument(Expr *E) : Kind(Expression) {
+ TypeOrValue = reinterpret_cast<uintptr_t>(E);
+ }
+
+ /// \brief Copy constructor for a template argument.
+ TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) {
+ if (Kind == Integral) {
+ new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
+ Integer.Type = Other.Integer.Type;
+ } else if (Kind == Pack) {
+ Args.NumArgs = Other.Args.NumArgs;
+ Args.Args = new TemplateArgument[Args.NumArgs];
+ for (unsigned I = 0; I != Args.NumArgs; ++I)
+ Args.Args[I] = Other.Args.Args[I];
+ }
+ else
+ TypeOrValue = Other.TypeOrValue;
+ }
+
+ TemplateArgument& operator=(const TemplateArgument& Other) {
+ // FIXME: Does not provide the strong guarantee for exception
+ // safety.
+ using llvm::APSInt;
+
+ // FIXME: Handle Packs
+ assert(Kind != Pack && "FIXME: Handle packs");
+ assert(Other.Kind != Pack && "FIXME: Handle packs");
+
+ if (Kind == Other.Kind && Kind == Integral) {
+ // Copy integral values.
+ *this->getAsIntegral() = *Other.getAsIntegral();
+ Integer.Type = Other.Integer.Type;
+ } else {
+ // Destroy the current integral value, if that's what we're holding.
+ if (Kind == Integral)
+ getAsIntegral()->~APSInt();
+
+ Kind = Other.Kind;
+
+ if (Other.Kind == Integral) {
+ new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
+ Integer.Type = Other.Integer.Type;
+ } else
+ TypeOrValue = Other.TypeOrValue;
+ }
+
+ return *this;
+ }
+
+ ~TemplateArgument() {
+ using llvm::APSInt;
+
+ if (Kind == Integral)
+ getAsIntegral()->~APSInt();
+ else if (Kind == Pack && Args.CopyArgs)
+ delete[] Args.Args;
+ }
+
+ /// \brief Return the kind of stored template argument.
+ ArgKind getKind() const { return Kind; }
+
+ /// \brief Determine whether this template argument has no value.
+ bool isNull() const { return Kind == Null; }
+
+ /// \brief Retrieve the template argument as a type.
+ QualType getAsType() const {
+ if (Kind != Type)
+ return QualType();
+
+ return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue));
+ }
+
+ /// \brief Retrieve the template argument as a declaration.
+ Decl *getAsDecl() const {
+ if (Kind != Declaration)
+ return 0;
+ return reinterpret_cast<Decl *>(TypeOrValue);
+ }
+
+ /// \brief Retrieve the template argument as an integral value.
+ llvm::APSInt *getAsIntegral() {
+ if (Kind != Integral)
+ return 0;
+ return reinterpret_cast<llvm::APSInt*>(&Integer.Value[0]);
+ }
+
+ const llvm::APSInt *getAsIntegral() const {
+ return const_cast<TemplateArgument*>(this)->getAsIntegral();
+ }
+
+ /// \brief Retrieve the type of the integral value.
+ QualType getIntegralType() const {
+ if (Kind != Integral)
+ return QualType();
+
+ return QualType::getFromOpaquePtr(Integer.Type);
+ }
+
+ void setIntegralType(QualType T) {
+ assert(Kind == Integral &&
+ "Cannot set the integral type of a non-integral template argument");
+ Integer.Type = T.getAsOpaquePtr();
+ };
+
+ /// \brief Retrieve the template argument as an expression.
+ Expr *getAsExpr() const {
+ if (Kind != Expression)
+ return 0;
+
+ return reinterpret_cast<Expr *>(TypeOrValue);
+ }
+
+ /// \brief Iterator that traverses the elements of a template argument pack.
+ typedef const TemplateArgument * pack_iterator;
+
+ /// \brief Iterator referencing the first argument of a template argument
+ /// pack.
+ pack_iterator pack_begin() const {
+ assert(Kind == Pack);
+ return Args.Args;
+ }
+
+ /// \brief Iterator referencing one past the last argument of a template
+ /// argument pack.
+ pack_iterator pack_end() const {
+ assert(Kind == Pack);
+ return Args.Args + Args.NumArgs;
+ }
+
+ /// \brief The number of template arguments in the given template argument
+ /// pack.
+ unsigned pack_size() const {
+ assert(Kind == Pack);
+ return Args.NumArgs;
+ }
+
+ /// \brief Construct a template argument pack.
+ void setArgumentPack(TemplateArgument *Args, unsigned NumArgs, bool CopyArgs);
+
+ /// \brief Used to insert TemplateArguments into FoldingSets.
+ void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context) const;
+};
+
+/// Location information for a TemplateArgument.
+struct TemplateArgumentLocInfo {
+private:
+ union {
+ Expr *Expression;
+ DeclaratorInfo *Declarator;
+ };
+
+#ifndef NDEBUG
+ enum Kind {
+ K_None,
+ K_DeclaratorInfo,
+ K_Expression
+ } Kind;
+#endif
+
+public:
+ TemplateArgumentLocInfo()
+ : Expression(0)
+#ifndef NDEBUG
+ , Kind(K_None)
+#endif
+ {}
+
+ TemplateArgumentLocInfo(DeclaratorInfo *DInfo)
+ : Declarator(DInfo)
+#ifndef NDEBUG
+ , Kind(K_DeclaratorInfo)
+#endif
+ {}
+
+ TemplateArgumentLocInfo(Expr *E)
+ : Expression(E)
+#ifndef NDEBUG
+ , Kind(K_Expression)
+#endif
+ {}
+
+ DeclaratorInfo *getAsDeclaratorInfo() const {
+ assert(Kind == K_DeclaratorInfo);
+ return Declarator;
+ }
+
+ Expr *getAsExpr() const {
+ assert(Kind == K_Expression);
+ return Expression;
+ }
+
+#ifndef NDEBUG
+ void validateForArgument(const TemplateArgument &Arg) {
+ switch (Arg.getKind()) {
+ case TemplateArgument::Type:
+ assert(Kind == K_DeclaratorInfo);
+ break;
+ case TemplateArgument::Expression:
+ case TemplateArgument::Declaration:
+ assert(Kind == K_Expression);
+ break;
+ case TemplateArgument::Integral:
+ case TemplateArgument::Pack:
+ assert(Kind == K_None);
+ break;
+ case TemplateArgument::Null:
+ llvm::llvm_unreachable("source info for null template argument?");
+ }
+ }
+#endif
+};
+
+/// Location wrapper for a TemplateArgument. TemplateArgument is to
+/// TemplateArgumentLoc as Type is to TypeLoc.
+class TemplateArgumentLoc {
+ TemplateArgument Argument;
+ TemplateArgumentLocInfo LocInfo;
+
+public:
+ TemplateArgumentLoc() {}
+
+ TemplateArgumentLoc(const TemplateArgument &Argument,
+ TemplateArgumentLocInfo Opaque)
+ : Argument(Argument), LocInfo(Opaque) {
+ }
+
+ TemplateArgumentLoc(const TemplateArgument &Argument, DeclaratorInfo *DInfo)
+ : Argument(Argument), LocInfo(DInfo) {
+ assert(Argument.getKind() == TemplateArgument::Type);
+ }
+
+ TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E)
+ : Argument(Argument), LocInfo(E) {
+ assert(Argument.getKind() == TemplateArgument::Expression);
+ }
+
+ /// \brief - Fetches the start location of the argument.
+ SourceLocation getLocation() const {
+ return getSourceRange().getBegin();
+ }
+
+ /// \brief - Fetches the full source range of the argument.
+ SourceRange getSourceRange() const;
+
+ const TemplateArgument &getArgument() const {
+ return Argument;
+ }
+
+ TemplateArgumentLocInfo getLocInfo() const {
+ return LocInfo;
+ }
+
+ DeclaratorInfo *getSourceDeclaratorInfo() const {
+ assert(Argument.getKind() == TemplateArgument::Type);
+ return LocInfo.getAsDeclaratorInfo();
+ }
+
+ Expr *getSourceExpression() const {
+ assert(Argument.getKind() == TemplateArgument::Expression);
+ return LocInfo.getAsExpr();
+ }
+
+ Expr *getSourceDeclExpression() const {
+ assert(Argument.getKind() == TemplateArgument::Declaration);
+ return LocInfo.getAsExpr();
+ }
+};
+
+}
+
+#endif
diff --git a/include/clang/AST/TemplateName.h b/include/clang/AST/TemplateName.h
index 66ff34cf1e31..8ef8fb51416c 100644
--- a/include/clang/AST/TemplateName.h
+++ b/include/clang/AST/TemplateName.h
@@ -16,6 +16,7 @@
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/PointerUnion.h"
+#include "clang/Basic/OperatorKinds.h"
namespace llvm {
class raw_ostream;
@@ -224,10 +225,24 @@ public:
class DependentTemplateName : public llvm::FoldingSetNode {
/// \brief The nested name specifier that qualifies the template
/// name.
- NestedNameSpecifier *Qualifier;
+ ///
+ /// The bit stored in this qualifier describes whether the \c Name field
+ /// is interpreted as an IdentifierInfo pointer (when clear) or as an
+ /// overloaded operator kind (when set).
+ llvm::PointerIntPair<NestedNameSpecifier *, 1, bool> Qualifier;
/// \brief The dependent template name.
- const IdentifierInfo *Name;
+ union {
+ /// \brief The identifier template name.
+ ///
+ /// Only valid when the bit on \c Qualifier is clear.
+ const IdentifierInfo *Identifier;
+
+ /// \brief The overloaded operator name.
+ ///
+ /// Only valid when the bit on \c Qualifier is set.
+ OverloadedOperatorKind Operator;
+ };
/// \brief The canonical template name to which this dependent
/// template name refers.
@@ -240,30 +255,70 @@ class DependentTemplateName : public llvm::FoldingSetNode {
friend class ASTContext;
DependentTemplateName(NestedNameSpecifier *Qualifier,
- const IdentifierInfo *Name)
- : Qualifier(Qualifier), Name(Name), CanonicalTemplateName(this) { }
+ const IdentifierInfo *Identifier)
+ : Qualifier(Qualifier, false), Identifier(Identifier),
+ CanonicalTemplateName(this) { }
DependentTemplateName(NestedNameSpecifier *Qualifier,
- const IdentifierInfo *Name,
+ const IdentifierInfo *Identifier,
TemplateName Canon)
- : Qualifier(Qualifier), Name(Name), CanonicalTemplateName(Canon) { }
+ : Qualifier(Qualifier, false), Identifier(Identifier),
+ CanonicalTemplateName(Canon) { }
+ DependentTemplateName(NestedNameSpecifier *Qualifier,
+ OverloadedOperatorKind Operator)
+ : Qualifier(Qualifier, true), Operator(Operator),
+ CanonicalTemplateName(this) { }
+
+ DependentTemplateName(NestedNameSpecifier *Qualifier,
+ OverloadedOperatorKind Operator,
+ TemplateName Canon)
+ : Qualifier(Qualifier, true), Operator(Operator),
+ CanonicalTemplateName(Canon) { }
+
public:
/// \brief Return the nested name specifier that qualifies this name.
- NestedNameSpecifier *getQualifier() const { return Qualifier; }
+ NestedNameSpecifier *getQualifier() const { return Qualifier.getPointer(); }
- /// \brief Return the name to which this dependent template name
- /// refers.
- const IdentifierInfo *getName() const { return Name; }
+ /// \brief Determine whether this template name refers to an identifier.
+ bool isIdentifier() const { return !Qualifier.getInt(); }
+ /// \brief Returns the identifier to which this template name refers.
+ const IdentifierInfo *getIdentifier() const {
+ assert(isIdentifier() && "Template name isn't an identifier?");
+ return Identifier;
+ }
+
+ /// \brief Determine whether this template name refers to an overloaded
+ /// operator.
+ bool isOverloadedOperator() const { return Qualifier.getInt(); }
+
+ /// \brief Return the overloaded operator to which this template name refers.
+ OverloadedOperatorKind getOperator() const {
+ assert(isOverloadedOperator() &&
+ "Template name isn't an overloaded operator?");
+ return Operator;
+ }
+
void Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, getQualifier(), getName());
+ if (isIdentifier())
+ Profile(ID, getQualifier(), getIdentifier());
+ else
+ Profile(ID, getQualifier(), getOperator());
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS,
+ const IdentifierInfo *Identifier) {
+ ID.AddPointer(NNS);
+ ID.AddBoolean(false);
+ ID.AddPointer(Identifier);
}
static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS,
- const IdentifierInfo *Name) {
+ OverloadedOperatorKind Operator) {
ID.AddPointer(NNS);
- ID.AddPointer(Name);
+ ID.AddBoolean(true);
+ ID.AddInteger(Operator);
}
};
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index db02a68a984d..daa814739182 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -81,6 +81,7 @@ namespace clang {
class SourceLocation;
class StmtIteratorBase;
class TemplateArgument;
+ class TemplateArgumentLoc;
class QualifiedNameType;
struct PrintingPolicy;
@@ -2275,12 +2276,19 @@ public:
static bool anyDependentTemplateArguments(const TemplateArgument *Args,
unsigned NumArgs);
+ static bool anyDependentTemplateArguments(const TemplateArgumentLoc *Args,
+ unsigned NumArgs);
+
/// \brief Print a template argument list, including the '<' and '>'
/// enclosing the template arguments.
static std::string PrintTemplateArgumentList(const TemplateArgument *Args,
unsigned NumArgs,
const PrintingPolicy &Policy);
+ static std::string PrintTemplateArgumentList(const TemplateArgumentLoc *Args,
+ unsigned NumArgs,
+ const PrintingPolicy &Policy);
+
typedef const TemplateArgument * iterator;
iterator begin() const { return getArgs(); }
diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h
index 1d7181b531f8..da7857822e9c 100644
--- a/include/clang/AST/TypeLoc.h
+++ b/include/clang/AST/TypeLoc.h
@@ -15,6 +15,7 @@
#define LLVM_CLANG_AST_TYPELOC_H
#include "clang/AST/Type.h"
+#include "clang/AST/TemplateBase.h"
namespace clang {
class ParmVarDecl;
@@ -82,6 +83,19 @@ public:
return Data;
}
+ /// \brief Get the full source range.
+ SourceRange getFullSourceRange() const {
+ SourceLocation End = getSourceRange().getEnd();
+ TypeLoc Cur = *this;
+ while (true) {
+ TypeLoc Next = Cur.getNextTypeLoc();
+ if (Next.isNull()) break;
+ Cur = Next;
+ }
+ return SourceRange(Cur.getSourceRange().getBegin(), End);
+ }
+
+ /// \brief Get the local source range.
SourceRange getSourceRange() const {
return getSourceRangeImpl(*this);
}
@@ -761,6 +775,10 @@ public:
getLocalData()->RBracketLoc = Loc;
}
+ SourceRange getBracketsRange() const {
+ return SourceRange(getLBracketLoc(), getRBracketLoc());
+ }
+
Expr *getSizeExpr() const {
return getLocalData()->Size;
}
@@ -810,6 +828,118 @@ class VariableArrayTypeLoc :
VariableArrayType> {
};
+
+// Location information for a TemplateName. Rudimentary for now.
+struct TemplateNameLocInfo {
+ SourceLocation NameLoc;
+};
+
+struct TemplateSpecializationLocInfo : TemplateNameLocInfo {
+ SourceLocation LAngleLoc;
+ SourceLocation RAngleLoc;
+};
+
+class TemplateSpecializationTypeLoc :
+ public ConcreteTypeLoc<UnqualTypeLoc,
+ TemplateSpecializationTypeLoc,
+ TemplateSpecializationType,
+ TemplateSpecializationLocInfo> {
+public:
+ SourceLocation getLAngleLoc() const {
+ return getLocalData()->LAngleLoc;
+ }
+ void setLAngleLoc(SourceLocation Loc) {
+ getLocalData()->LAngleLoc = Loc;
+ }
+
+ SourceLocation getRAngleLoc() const {
+ return getLocalData()->RAngleLoc;
+ }
+ void setRAngleLoc(SourceLocation Loc) {
+ getLocalData()->RAngleLoc = Loc;
+ }
+
+ unsigned getNumArgs() const {
+ return getTypePtr()->getNumArgs();
+ }
+ void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) {
+#ifndef NDEBUG
+ AI.validateForArgument(getTypePtr()->getArg(i));
+#endif
+ getArgInfos()[i] = AI;
+ }
+ TemplateArgumentLocInfo getArgLocInfo(unsigned i) const {
+ return getArgInfos()[i];
+ }
+
+ TemplateArgumentLoc getArgLoc(unsigned i) const {
+ return TemplateArgumentLoc(getTypePtr()->getArg(i), getArgLocInfo(i));
+ }
+
+ SourceLocation getTemplateNameLoc() const {
+ return getLocalData()->NameLoc;
+ }
+ void setTemplateNameLoc(SourceLocation Loc) {
+ getLocalData()->NameLoc = Loc;
+ }
+
+ /// \brief - Copy the location information from the given info.
+ void copy(TemplateSpecializationTypeLoc Loc) {
+ unsigned size = getFullDataSize();
+ assert(size == Loc.getFullDataSize());
+
+ // We're potentially copying Expr references here. We don't
+ // bother retaining them because DeclaratorInfos live forever, so
+ // as long as the Expr was retained when originally written into
+ // the TypeLoc, we're okay.
+ memcpy(Data, Loc.Data, size);
+ }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(getTemplateNameLoc(), getRAngleLoc());
+ }
+
+ void initializeLocal(SourceLocation Loc) {
+ setLAngleLoc(Loc);
+ setRAngleLoc(Loc);
+ setTemplateNameLoc(Loc);
+
+ for (unsigned i = 0, e = getNumArgs(); i != e; ++i) {
+ TemplateArgumentLocInfo Info;
+#ifndef NDEBUG
+ // If asserts are enabled, be sure to initialize the argument
+ // loc with the right kind of pointer.
+ switch (getTypePtr()->getArg(i).getKind()) {
+ case TemplateArgument::Expression:
+ case TemplateArgument::Declaration:
+ Info = TemplateArgumentLocInfo((Expr*) 0);
+ break;
+
+ case TemplateArgument::Type:
+ Info = TemplateArgumentLocInfo((DeclaratorInfo*) 0);
+ break;
+
+ case TemplateArgument::Integral:
+ case TemplateArgument::Pack:
+ case TemplateArgument::Null:
+ // K_None is fine.
+ break;
+ }
+#endif
+ getArgInfos()[i] = Info;
+ }
+ }
+
+ unsigned getExtraLocalDataSize() const {
+ return getNumArgs() * sizeof(TemplateArgumentLocInfo);
+ }
+
+private:
+ TemplateArgumentLocInfo *getArgInfos() const {
+ return static_cast<TemplateArgumentLocInfo*>(getExtraLocalData());
+ }
+};
+
// None of these types have proper implementations yet.
class VectorTypeLoc : public TypeSpecTypeLoc<VectorTypeLoc, VectorType> {
@@ -861,11 +991,6 @@ class ElaboratedTypeLoc : public TypeSpecTypeLoc<ElaboratedTypeLoc,
ElaboratedType> {
};
-class TemplateSpecializationTypeLoc
- : public TypeSpecTypeLoc<TemplateSpecializationTypeLoc,
- TemplateSpecializationType> {
-};
-
class QualifiedNameTypeLoc : public TypeSpecTypeLoc<QualifiedNameTypeLoc,
QualifiedNameType> {
};
diff --git a/include/clang/Analysis/CallGraph.h b/include/clang/Analysis/CallGraph.h
index fabeea38d597..5edfe6fea8db 100644
--- a/include/clang/Analysis/CallGraph.h
+++ b/include/clang/Analysis/CallGraph.h
@@ -17,7 +17,6 @@
#include "clang/Index/ASTLocation.h"
#include "clang/Index/Entity.h"
#include "clang/Index/Program.h"
-#include "clang/Frontend/ASTUnit.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/STLExtras.h"
@@ -87,7 +86,7 @@ public:
CallGraphNode *getExternalCallingNode() { return ExternalCallingNode; }
- void addTU(ASTUnit &AST);
+ void addTU(ASTContext &AST);
idx::Program &getProgram() { return Prog; }
diff --git a/include/clang/Analysis/PathSensitive/AnalysisContext.h b/include/clang/Analysis/PathSensitive/AnalysisContext.h
index 8e02ccf38209..66e850a91444 100644
--- a/include/clang/Analysis/PathSensitive/AnalysisContext.h
+++ b/include/clang/Analysis/PathSensitive/AnalysisContext.h
@@ -80,6 +80,8 @@ protected:
: Kind(k), Ctx(ctx), Parent(parent) {}
public:
+ virtual ~LocationContext() {}
+
ContextKind getKind() const { return Kind; }
AnalysisContext *getAnalysisContext() const { return Ctx; }
@@ -102,7 +104,7 @@ public:
return Ctx->getSelfDecl();
}
- void Profile(llvm::FoldingSetNodeID &ID) {
+ virtual void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, Kind, Ctx, Parent);
}
@@ -119,10 +121,13 @@ public:
StackFrameContext(AnalysisContext *ctx, const LocationContext *parent,
const Stmt *s)
: LocationContext(StackFrame, ctx, parent), CallSite(s) {}
+
+ virtual ~StackFrameContext() {}
+
Stmt const *getCallSite() const { return CallSite; }
- void Profile(llvm::FoldingSetNodeID &ID) {
+ virtual void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getAnalysisContext(), getParent(), CallSite);
}
@@ -141,8 +146,10 @@ public:
ScopeContext(AnalysisContext *ctx, const LocationContext *parent,
const Stmt *s)
: LocationContext(Scope, ctx, parent), Enter(s) {}
+
+ virtual ~ScopeContext() {}
- void Profile(llvm::FoldingSetNodeID &ID) {
+ virtual void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getAnalysisContext(), getParent(), Enter);
}
diff --git a/include/clang/Analysis/PathSensitive/BugReporter.h b/include/clang/Analysis/PathSensitive/BugReporter.h
index 1434fce811d1..914118cb430d 100644
--- a/include/clang/Analysis/PathSensitive/BugReporter.h
+++ b/include/clang/Analysis/PathSensitive/BugReporter.h
@@ -19,6 +19,7 @@
#include "clang/Basic/SourceLocation.h"
#include "clang/Analysis/PathSensitive/GRState.h"
#include "clang/Analysis/PathSensitive/ExplodedGraph.h"
+#include "clang/Analysis/PathSensitive/BugType.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallString.h"
@@ -183,38 +184,6 @@ public:
const_iterator end() const { return const_iterator(Reports.end()); }
};
-class BugType {
-private:
- const std::string Name;
- const std::string Category;
- llvm::FoldingSet<BugReportEquivClass> EQClasses;
- friend class BugReporter;
- bool SuppressonSink;
-public:
- BugType(const char *name, const char* cat)
- : Name(name), Category(cat), SuppressonSink(false) {}
- virtual ~BugType();
-
- // FIXME: Should these be made strings as well?
- const std::string& getName() const { return Name; }
- const std::string& getCategory() const { return Category; }
-
- /// isSuppressOnSink - Returns true if bug reports associated with this bug
- /// type should be suppressed if the end node of the report is post-dominated
- /// by a sink node.
- bool isSuppressOnSink() const { return SuppressonSink; }
- void setSuppressOnSink(bool x) { SuppressonSink = x; }
-
- virtual void FlushReports(BugReporter& BR);
-
- typedef llvm::FoldingSet<BugReportEquivClass>::iterator iterator;
- iterator begin() { return EQClasses.begin(); }
- iterator end() { return EQClasses.end(); }
-
- typedef llvm::FoldingSet<BugReportEquivClass>::const_iterator const_iterator;
- const_iterator begin() const { return EQClasses.begin(); }
- const_iterator end() const { return EQClasses.end(); }
-};
//===----------------------------------------------------------------------===//
// Specialized subclasses of BugReport.
diff --git a/include/clang/Analysis/PathSensitive/BugType.h b/include/clang/Analysis/PathSensitive/BugType.h
new file mode 100644
index 000000000000..46b3edd3172e
--- /dev/null
+++ b/include/clang/Analysis/PathSensitive/BugType.h
@@ -0,0 +1,86 @@
+//===--- BugType.h - Bug Information Desciption ----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines BugType, a class representing a bug type.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_BUGTYPE
+#define LLVM_CLANG_ANALYSIS_BUGTYPE
+
+#include <llvm/ADT/FoldingSet.h>
+#include <string>
+
+namespace clang {
+
+class BugReportEquivClass;
+class BugReporter;
+class BuiltinBugReport;
+class BugReporterContext;
+class GRExprEngine;
+
+class BugType {
+private:
+ const std::string Name;
+ const std::string Category;
+ llvm::FoldingSet<BugReportEquivClass> EQClasses;
+ friend class BugReporter;
+ bool SuppressonSink;
+public:
+ BugType(const char *name, const char* cat)
+ : Name(name), Category(cat), SuppressonSink(false) {}
+ virtual ~BugType();
+
+ // FIXME: Should these be made strings as well?
+ const std::string& getName() const { return Name; }
+ const std::string& getCategory() const { return Category; }
+
+ /// isSuppressOnSink - Returns true if bug reports associated with this bug
+ /// type should be suppressed if the end node of the report is post-dominated
+ /// by a sink node.
+ bool isSuppressOnSink() const { return SuppressonSink; }
+ void setSuppressOnSink(bool x) { SuppressonSink = x; }
+
+ virtual void FlushReports(BugReporter& BR);
+
+ typedef llvm::FoldingSet<BugReportEquivClass>::iterator iterator;
+ iterator begin() { return EQClasses.begin(); }
+ iterator end() { return EQClasses.end(); }
+
+ typedef llvm::FoldingSet<BugReportEquivClass>::const_iterator const_iterator;
+ const_iterator begin() const { return EQClasses.begin(); }
+ const_iterator end() const { return EQClasses.end(); }
+};
+
+class BuiltinBug : public BugType {
+ GRExprEngine &Eng;
+protected:
+ const std::string desc;
+public:
+ BuiltinBug(GRExprEngine *eng, const char* n, const char* d)
+ : BugType(n, "Logic errors"), Eng(*eng), desc(d) {}
+
+ BuiltinBug(GRExprEngine *eng, const char* n)
+ : BugType(n, "Logic errors"), Eng(*eng), desc(n) {}
+
+ const std::string &getDescription() const { return desc; }
+
+ virtual void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {}
+
+ void FlushReports(BugReporter& BR) { FlushReportsImpl(BR, Eng); }
+
+ virtual void registerInitialVisitors(BugReporterContext& BRC,
+ const ExplodedNode* N,
+ BuiltinBugReport *R) {}
+
+ template <typename ITER> void Emit(BugReporter& BR, ITER I, ITER E);
+};
+
+} // end clang namespace
+#endif
diff --git a/include/clang/Analysis/PathSensitive/Checker.h b/include/clang/Analysis/PathSensitive/Checker.h
index 4e00d69cdba1..3bef08d7545f 100644
--- a/include/clang/Analysis/PathSensitive/Checker.h
+++ b/include/clang/Analysis/PathSensitive/Checker.h
@@ -72,6 +72,10 @@ public:
ASTContext &getASTContext() {
return Eng.getContext();
}
+
+ BugReporter &getBugReporter() {
+ return Eng.getBugReporter();
+ }
ExplodedNode *GenerateNode(const Stmt *S, bool markAsSink = false) {
return GenerateNode(S, getState(), markAsSink);
@@ -104,16 +108,42 @@ private:
GRStmtNodeBuilder &Builder,
GRExprEngine &Eng,
const Stmt *stmt,
- ExplodedNode *Pred, bool isPrevisit) {
- CheckerContext C(Dst, Builder, Eng, Pred, getTag(), isPrevisit);
+ ExplodedNode *Pred, void *tag, bool isPrevisit) {
+ CheckerContext C(Dst, Builder, Eng, Pred, tag, isPrevisit);
assert(isPrevisit && "Only previsit supported for now.");
_PreVisit(C, stmt);
}
+ void GR_VisitBind(ExplodedNodeSet &Dst,
+ GRStmtNodeBuilder &Builder, GRExprEngine &Eng,
+ const Stmt *stmt, 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);
+ }
+
public:
virtual ~Checker() {}
- virtual void _PreVisit(CheckerContext &C, const Stmt *stmt) = 0;
- virtual const void *getTag() = 0;
+ virtual void _PreVisit(CheckerContext &C, const Stmt *ST) {}
+
+ // This is a previsit which takes a node returns a node.
+ virtual ExplodedNode *CheckLocation(const Stmt *S, ExplodedNode *Pred,
+ const GRState *state, SVal V,
+ GRExprEngine &Eng) {
+ return Pred;
+ }
+
+ virtual void PreVisitBind(CheckerContext &C, const Stmt *ST,
+ SVal location, SVal val) {}
+
+ virtual ExplodedNode *CheckType(QualType T, ExplodedNode *Pred,
+ const GRState *state, Stmt *S,
+ GRExprEngine &Eng) {
+ return Pred;
+ }
+
};
} // end clang namespace
diff --git a/include/clang/Analysis/PathSensitive/Checkers/AttrNonNullChecker.h b/include/clang/Analysis/PathSensitive/Checkers/AttrNonNullChecker.h
new file mode 100644
index 000000000000..007ec093b2e0
--- /dev/null
+++ b/include/clang/Analysis/PathSensitive/Checkers/AttrNonNullChecker.h
@@ -0,0 +1,28 @@
+//===--- AttrNonNullChecker.h - Undefined arguments checker ----*- C++ -*--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines AttrNonNullChecker, a builtin check in GRExprEngine that
+// performs checks for arguments declared to have nonnull attribute.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
+
+namespace clang {
+
+class AttrNonNullChecker : public CheckerVisitor<AttrNonNullChecker> {
+ BugType *BT;
+
+public:
+ AttrNonNullChecker() : BT(0) {}
+ static void *getTag();
+ void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
+};
+
+}
diff --git a/include/clang/Analysis/PathSensitive/Checkers/BadCallChecker.h b/include/clang/Analysis/PathSensitive/Checkers/BadCallChecker.h
new file mode 100644
index 000000000000..70f3c44165e0
--- /dev/null
+++ b/include/clang/Analysis/PathSensitive/Checkers/BadCallChecker.h
@@ -0,0 +1,30 @@
+//===--- BadCallChecker.h - Bad call checker --------------------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines BadCallChecker, a builtin check in GRExprEngine that performs
+// checks for bad callee at call sites.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
+
+namespace clang {
+
+class BadCallChecker : public CheckerVisitor<BadCallChecker> {
+ BuiltinBug *BT;
+
+public:
+ BadCallChecker() : BT(0) {}
+
+ static void *getTag();
+
+ void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
+};
+
+}
diff --git a/include/clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h b/include/clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h
new file mode 100644
index 000000000000..688cf641491d
--- /dev/null
+++ b/include/clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h
@@ -0,0 +1,53 @@
+//== NullDerefChecker.h - Null dereference checker --------------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines NullDerefChecker and UndefDerefChecker, two builtin checks
+// in GRExprEngine that check for null and undefined pointers at loads
+// and stores.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_DEREFCHECKER
+#define LLVM_CLANG_DEREFCHECKER
+
+#include "clang/Analysis/PathSensitive/Checker.h"
+#include "clang/Analysis/PathSensitive/BugType.h"
+
+namespace clang {
+
+class ExplodedNode;
+
+class NullDerefChecker : public Checker {
+ BuiltinBug *BT;
+ llvm::SmallVector<ExplodedNode*, 2> ImplicitNullDerefNodes;
+
+public:
+ NullDerefChecker() : BT(0) {}
+ ExplodedNode *CheckLocation(const Stmt *S, ExplodedNode *Pred,
+ const GRState *state, SVal V,GRExprEngine &Eng);
+
+ static void *getTag();
+ typedef llvm::SmallVectorImpl<ExplodedNode*>::iterator iterator;
+ iterator implicit_nodes_begin() { return ImplicitNullDerefNodes.begin(); }
+ iterator implicit_nodes_end() { return ImplicitNullDerefNodes.end(); }
+};
+
+class UndefDerefChecker : public Checker {
+ BuiltinBug *BT;
+public:
+ UndefDerefChecker() : BT(0) {}
+
+ ExplodedNode *CheckLocation(const Stmt *S, ExplodedNode *Pred,
+ const GRState *state, SVal V, GRExprEngine &Eng);
+
+ static void *getTag();
+};
+
+} // end clang namespace
+#endif
diff --git a/include/clang/Analysis/PathSensitive/Checkers/DivZeroChecker.h b/include/clang/Analysis/PathSensitive/Checkers/DivZeroChecker.h
new file mode 100644
index 000000000000..317e43a0e62e
--- /dev/null
+++ b/include/clang/Analysis/PathSensitive/Checkers/DivZeroChecker.h
@@ -0,0 +1,28 @@
+//== DivZeroChecker.h - Division by zero checker ----------------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines DivZeroChecker, a builtin check in GRExprEngine that performs
+// checks for division by zeros.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
+
+namespace clang {
+
+class DivZeroChecker : public CheckerVisitor<DivZeroChecker> {
+ BuiltinBug *BT;
+public:
+ DivZeroChecker() : BT(0) {}
+
+ static void *getTag();
+ void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
+};
+
+}
diff --git a/include/clang/Analysis/PathSensitive/Checkers/UndefinedArgChecker.h b/include/clang/Analysis/PathSensitive/Checkers/UndefinedArgChecker.h
new file mode 100644
index 000000000000..7f4e7d524f6c
--- /dev/null
+++ b/include/clang/Analysis/PathSensitive/Checkers/UndefinedArgChecker.h
@@ -0,0 +1,34 @@
+//===--- UndefinedArgChecker.h - Undefined arguments checker ----*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines BadCallChecker, a builtin check in GRExprEngine that performs
+// checks for undefined arguments.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_UNDEFARGCHECKER
+#define LLVM_CLANG_UNDEFARGCHECKER
+
+#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
+
+namespace clang {
+
+class UndefinedArgChecker : public CheckerVisitor<UndefinedArgChecker> {
+ BugType *BT;
+
+public:
+ UndefinedArgChecker() : BT(0) {}
+
+ static void *getTag();
+
+ void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
+};
+
+}
+#endif
diff --git a/include/clang/Analysis/PathSensitive/Checkers/UndefinedAssignmentChecker.h b/include/clang/Analysis/PathSensitive/Checkers/UndefinedAssignmentChecker.h
new file mode 100644
index 000000000000..7fee5011c46d
--- /dev/null
+++ b/include/clang/Analysis/PathSensitive/Checkers/UndefinedAssignmentChecker.h
@@ -0,0 +1,32 @@
+//===--- UndefinedAssignmentChecker.h ---------------------------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines UndefinedAssginmentChecker, a builtin check in GRExprEngine that
+// checks for assigning undefined values.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_UNDEFASSIGNMENTCHECKER
+#define LLVM_CLANG_UNDEFASSIGNMENTCHECKER
+
+#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
+
+namespace clang {
+class UndefinedAssignmentChecker
+ : public CheckerVisitor<UndefinedAssignmentChecker> {
+ BugType *BT;
+public:
+ UndefinedAssignmentChecker() : BT(0) {}
+ static void *getTag();
+ virtual void PreVisitBind(CheckerContext &C, const Stmt *S, SVal location,
+ SVal val);
+};
+}
+#endif
+
diff --git a/include/clang/Analysis/PathSensitive/Checkers/VLASizeChecker.h b/include/clang/Analysis/PathSensitive/Checkers/VLASizeChecker.h
new file mode 100644
index 000000000000..b339b3d30141
--- /dev/null
+++ b/include/clang/Analysis/PathSensitive/Checkers/VLASizeChecker.h
@@ -0,0 +1,39 @@
+//=== VLASizeChecker.h - Undefined dereference checker ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines two VLASizeCheckers, a builtin check in GRExprEngine that
+// performs checks for declaration of VLA of undefined or zero size.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/Checker.h"
+
+namespace clang {
+
+class UndefSizedVLAChecker : public Checker {
+ BugType *BT;
+
+public:
+ UndefSizedVLAChecker() : BT(0) {}
+ static void *getTag();
+ ExplodedNode *CheckType(QualType T, ExplodedNode *Pred,
+ const GRState *state, Stmt *S, GRExprEngine &Eng);
+};
+
+class ZeroSizedVLAChecker : public Checker {
+ BugType *BT;
+
+public:
+ ZeroSizedVLAChecker() : BT(0) {}
+ static void *getTag();
+ ExplodedNode *CheckType(QualType T, ExplodedNode *Pred,
+ const GRState *state, Stmt *S, GRExprEngine &Eng);
+};
+
+}
diff --git a/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Analysis/PathSensitive/GRExprEngine.h
index e5c61e68c77c..2f2a11a83cea 100644
--- a/include/clang/Analysis/PathSensitive/GRExprEngine.h
+++ b/include/clang/Analysis/PathSensitive/GRExprEngine.h
@@ -75,7 +75,12 @@ class GRExprEngine : public GRSubEngine {
Selector RaiseSel;
llvm::OwningPtr<GRSimpleAPICheck> BatchAuditor;
- std::vector<Checker*> Checkers;
+
+ typedef llvm::DenseMap<void *, unsigned> CheckerMap;
+ CheckerMap CheckerM;
+
+ typedef std::vector<std::pair<void *, Checker*> >CheckersOrdered;
+ CheckersOrdered Checkers;
/// BR - The BugReporter associated with this engine. It is important that
// this object be placed at the very end of member variables so that its
@@ -126,18 +131,6 @@ public:
// calling a function with the attribute "noreturn".
ErrorNodes NoReturnCalls;
- /// ImplicitNullDeref - Nodes in the ExplodedGraph that result from
- /// taking a dereference on a symbolic pointer that MAY be NULL.
- ErrorNodes ImplicitNullDeref;
-
- /// ExplicitNullDeref - Nodes in the ExplodedGraph that result from
- /// taking a dereference on a symbolic pointer that MUST be NULL.
- ErrorNodes ExplicitNullDeref;
-
- /// UndefDeref - Nodes in the ExplodedGraph that result from
- /// taking a dereference on an undefined value.
- ErrorNodes UndefDeref;
-
/// ImplicitBadSizedVLA - Nodes in the ExplodedGraph that result from
/// constructing a zero-sized VLA where the size may be zero.
ErrorNodes ImplicitBadSizedVLA;
@@ -158,10 +151,6 @@ public:
/// ObjC message expressions where the receiver is undefined (uninitialized).
ErrorNodes UndefReceivers;
- /// UndefArg - Nodes in the ExplodedGraph resulting from calls to functions
- /// where a pass-by-value argument has an undefined value.
- UndefArgsTy UndefArgs;
-
/// MsgExprUndefArgs - Nodes in the ExplodedGraph resulting from
/// message expressions where a pass-by-value argument has an undefined
/// value.
@@ -195,6 +184,8 @@ public:
BugReporter& getBugReporter() { return BR; }
+ GRStmtNodeBuilder &getBuilder() { assert(Builder); return *Builder; }
+
/// setTransferFunctions
void setTransferFunctions(GRTransferFuncs* tf);
@@ -217,8 +208,19 @@ public:
void RegisterInternalChecks();
- void registerCheck(Checker *check) {
- Checkers.push_back(check);
+ template <typename CHECKER>
+ void registerCheck(CHECKER *check) {
+ unsigned entry = Checkers.size();
+ void *tag = CHECKER::getTag();
+ Checkers.push_back(std::make_pair(tag, check));
+ CheckerM[tag] = entry;
+ }
+
+ Checker *lookupChecker(void *tag) const;
+
+ template <typename CHECKER>
+ CHECKER *getChecker() const {
+ return static_cast<CHECKER*>(lookupChecker(CHECKER::getTag()));
}
bool isRetStackAddr(const ExplodedNode* N) const {
@@ -234,15 +236,15 @@ public:
}
bool isImplicitNullDeref(const ExplodedNode* N) const {
- return N->isSink() && ImplicitNullDeref.count(const_cast<ExplodedNode*>(N)) != 0;
+ return false;
}
bool isExplicitNullDeref(const ExplodedNode* N) const {
- return N->isSink() && ExplicitNullDeref.count(const_cast<ExplodedNode*>(N)) != 0;
+ return false;
}
bool isUndefDeref(const ExplodedNode* N) const {
- return N->isSink() && UndefDeref.count(const_cast<ExplodedNode*>(N)) != 0;
+ return false;
}
bool isNoReturnCall(const ExplodedNode* N) const {
@@ -254,13 +256,11 @@ public:
}
bool isBadCall(const ExplodedNode* N) const {
- return N->isSink() && BadCalls.count(const_cast<ExplodedNode*>(N)) != 0;
+ return false;
}
bool isUndefArg(const ExplodedNode* N) const {
- return N->isSink() &&
- (UndefArgs.find(const_cast<ExplodedNode*>(N)) != UndefArgs.end() ||
- MsgExprUndefArgs.find(const_cast<ExplodedNode*>(N)) != MsgExprUndefArgs.end());
+ return false;
}
bool isUndefReceiver(const ExplodedNode* N) const {
@@ -279,17 +279,6 @@ public:
undef_branch_iterator undef_branches_begin() { return UndefBranches.begin(); }
undef_branch_iterator undef_branches_end() { return UndefBranches.end(); }
- typedef ErrorNodes::iterator null_deref_iterator;
- null_deref_iterator null_derefs_begin() { return ExplicitNullDeref.begin(); }
- null_deref_iterator null_derefs_end() { return ExplicitNullDeref.end(); }
-
- null_deref_iterator implicit_null_derefs_begin() {
- return ImplicitNullDeref.begin();
- }
- null_deref_iterator implicit_null_derefs_end() {
- return ImplicitNullDeref.end();
- }
-
typedef ErrorNodes::iterator nil_receiver_struct_ret_iterator;
nil_receiver_struct_ret_iterator nil_receiver_struct_ret_begin() {
@@ -312,10 +301,6 @@ public:
return NilReceiverLargerThanVoidPtrRetExplicit.end();
}
- typedef ErrorNodes::iterator undef_deref_iterator;
- undef_deref_iterator undef_derefs_begin() { return UndefDeref.begin(); }
- undef_deref_iterator undef_derefs_end() { return UndefDeref.end(); }
-
typedef ErrorNodes::iterator undef_result_iterator;
undef_result_iterator undef_results_begin() { return UndefResults.begin(); }
undef_result_iterator undef_results_end() { return UndefResults.end(); }
@@ -325,9 +310,6 @@ public:
bad_calls_iterator bad_calls_end() { return BadCalls.end(); }
typedef UndefArgsTy::iterator undef_arg_iterator;
- undef_arg_iterator undef_arg_begin() { return UndefArgs.begin(); }
- undef_arg_iterator undef_arg_end() { return UndefArgs.end(); }
-
undef_arg_iterator msg_expr_undef_arg_begin() {
return MsgExprUndefArgs.begin();
}
@@ -427,7 +409,12 @@ public:
protected:
/// CheckerVisit - Dispatcher for performing checker-specific logic
/// at specific statements.
- void CheckerVisit(Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src, bool isPrevisit);
+ void CheckerVisit(Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
+ bool isPrevisit);
+
+ void CheckerVisitBind(Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
+ SVal location, SVal val, bool isPrevisit);
+
/// Visit - Transfer function logic for all statements. Dispatches to
/// other functions that handle specific kinds of statements.
@@ -456,7 +443,8 @@ protected:
ExplodedNode* Pred, ExplodedNodeSet& Dst);
/// VisitBinaryOperator - Transfer function logic for binary operators.
- void VisitBinaryOperator(BinaryOperator* B, ExplodedNode* Pred, ExplodedNodeSet& Dst);
+ void VisitBinaryOperator(BinaryOperator* B, ExplodedNode* Pred,
+ ExplodedNodeSet& Dst, bool asLValue);
/// VisitCall - Transfer function for function calls.
@@ -578,8 +566,9 @@ protected:
/// EvalBind - Handle the semantics of binding a value to a specific location.
/// This method is used by EvalStore, VisitDeclStmt, and others.
- void EvalBind(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred,
- const GRState* St, SVal location, SVal Val);
+ void EvalBind(ExplodedNodeSet& Dst, Stmt* Ex, ExplodedNode* Pred,
+ const GRState* St, SVal location, SVal Val,
+ bool atDeclInit = false);
public:
void EvalLoad(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred,
diff --git a/include/clang/Analysis/PathSensitive/GRState.h b/include/clang/Analysis/PathSensitive/GRState.h
index d8b9d560ccd8..8678ca9b5b9b 100644
--- a/include/clang/Analysis/PathSensitive/GRState.h
+++ b/include/clang/Analysis/PathSensitive/GRState.h
@@ -26,7 +26,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/Analysis/Analyses/LiveVariables.h"
#include "llvm/Support/Casting.h"
-#include "llvm/Support/DataTypes.h"
+#include "llvm/System/DataTypes.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/ImmutableMap.h"
@@ -219,11 +219,9 @@ public:
const GRState *BindExpr(const Stmt *S, SVal V, bool Invalidate = true) const;
- const GRState *bindDecl(const VarDecl *VD, const LocationContext *LC,
- SVal V) const;
+ const GRState *bindDecl(const VarRegion *VR, SVal V) const;
- const GRState *bindDeclWithNoInit(const VarDecl *VD,
- const LocationContext *LC) const;
+ const GRState *bindDeclWithNoInit(const VarRegion *VR) const;
const GRState *bindLoc(Loc location, SVal V) const;
@@ -602,15 +600,12 @@ inline const GRState *GRState::bindCompoundLiteral(const CompoundLiteralExpr* CL
return getStateManager().StoreMgr->BindCompoundLiteral(this, CL, V);
}
-inline const GRState *GRState::bindDecl(const VarDecl* VD,
- const LocationContext *LC,
- SVal IVal) const {
- return getStateManager().StoreMgr->BindDecl(this, VD, LC, IVal);
+inline const GRState *GRState::bindDecl(const VarRegion* VR, SVal IVal) const {
+ return getStateManager().StoreMgr->BindDecl(this, VR, IVal);
}
-inline const GRState *GRState::bindDeclWithNoInit(const VarDecl* VD,
- const LocationContext *LC) const {
- return getStateManager().StoreMgr->BindDeclWithNoInit(this, VD, LC);
+inline const GRState *GRState::bindDeclWithNoInit(const VarRegion* VR) const {
+ return getStateManager().StoreMgr->BindDeclWithNoInit(this, VR);
}
inline const GRState *GRState::bindLoc(Loc LV, SVal V) const {
diff --git a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h b/include/clang/Analysis/PathSensitive/GRTransferFuncs.h
index 5f7b2cb0e327..40c1ed3224f4 100644
--- a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h
+++ b/include/clang/Analysis/PathSensitive/GRTransferFuncs.h
@@ -23,7 +23,6 @@
namespace clang {
class GRExprEngine;
-class BugReporter;
class ObjCMessageExpr;
class GRStmtNodeBuilderRef;
@@ -33,7 +32,7 @@ public:
virtual ~GRTransferFuncs() {}
virtual void RegisterPrinters(std::vector<GRState::Printer*>& Printers) {}
- virtual void RegisterChecks(BugReporter& BR) {}
+ virtual void RegisterChecks(GRExprEngine& Eng) {}
// Calls.
@@ -78,7 +77,7 @@ public:
virtual const GRState* EvalAssume(const GRState *state,
SVal Cond, bool Assumption) {
return state;
- }
+ }
};
GRTransferFuncs *CreateCallInliner(ASTContext &ctx);
diff --git a/include/clang/Analysis/PathSensitive/Store.h b/include/clang/Analysis/PathSensitive/Store.h
index 7a462c579f9f..6ca2e9e9aa68 100644
--- a/include/clang/Analysis/PathSensitive/Store.h
+++ b/include/clang/Analysis/PathSensitive/Store.h
@@ -134,12 +134,11 @@ public:
SymbolReaper& SymReaper,
llvm::SmallVectorImpl<const MemRegion*>& RegionRoots) = 0;
- virtual const GRState *BindDecl(const GRState *ST, const VarDecl *VD,
- const LocationContext *LC, SVal initVal) = 0;
+ virtual const GRState *BindDecl(const GRState *ST, const VarRegion *VR,
+ SVal initVal) = 0;
virtual const GRState *BindDeclWithNoInit(const GRState *ST,
- const VarDecl *VD,
- const LocationContext *LC) = 0;
+ const VarRegion *VR) = 0;
typedef llvm::DenseSet<SymbolRef> InvalidatedSymbols;
diff --git a/include/clang/Analysis/PathSensitive/SymbolManager.h b/include/clang/Analysis/PathSensitive/SymbolManager.h
index d3996c6330a2..167a102e94ec 100644
--- a/include/clang/Analysis/PathSensitive/SymbolManager.h
+++ b/include/clang/Analysis/PathSensitive/SymbolManager.h
@@ -18,7 +18,7 @@
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include "clang/Analysis/Analyses/LiveVariables.h"
-#include "llvm/Support/DataTypes.h"
+#include "llvm/System/DataTypes.h"
#include "llvm/Support/Allocator.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/DenseSet.h"
diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h
index 666e45b847cf..7aaae9c86653 100644
--- a/include/clang/Analysis/ProgramPoint.h
+++ b/include/clang/Analysis/ProgramPoint.h
@@ -16,7 +16,7 @@
#define LLVM_CLANG_ANALYSIS_PROGRAM_POINT
#include "clang/Analysis/CFG.h"
-#include "llvm/Support/DataTypes.h"
+#include "llvm/System/DataTypes.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/Support/Casting.h"
diff --git a/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h b/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h
index 3826d3a3acd6..afc63616e9fc 100644
--- a/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h
+++ b/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h
@@ -57,7 +57,6 @@ public:
DISPATCH_CASE(Function,FunctionDecl)
DISPATCH_CASE(Var,VarDecl)
DISPATCH_CASE(ParmVar,ParmVarDecl) // FIXME: (same)
- DISPATCH_CASE(OriginalParmVar,OriginalParmVarDecl) // FIXME: (same)
DISPATCH_CASE(ImplicitParam,ImplicitParamDecl)
DISPATCH_CASE(EnumConstant,EnumConstantDecl)
DISPATCH_CASE(Typedef,TypedefDecl)
@@ -70,7 +69,6 @@ public:
DEFAULT_DISPATCH(VarDecl)
DEFAULT_DISPATCH(FunctionDecl)
- DEFAULT_DISPATCH_VARDECL(OriginalParmVarDecl)
DEFAULT_DISPATCH_VARDECL(ParmVarDecl)
DEFAULT_DISPATCH(ImplicitParamDecl)
DEFAULT_DISPATCH(EnumConstantDecl)
diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def
index 27997858c00c..98c703d94e92 100644
--- a/include/clang/Basic/Builtins.def
+++ b/include/clang/Basic/Builtins.def
@@ -329,7 +329,7 @@ BUILTIN(__builtin___printf_chk, "iicC*.", "Fp:1:")
BUILTIN(__builtin___vfprintf_chk, "iP*icC*a", "FP:2:")
BUILTIN(__builtin___vprintf_chk, "iicC*a", "FP:1:")
-BUILTIN(__builtin_expect, "iii" , "nc")
+BUILTIN(__builtin_expect, "LiLiLi" , "nc")
BUILTIN(__builtin_prefetch, "vvC*.", "nc")
BUILTIN(__builtin_abort, "v", "Fnr")
BUILTIN(__builtin_trap, "v", "nr")
diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td
index cbf9cdbc1599..bb251ad73bd8 100644
--- a/include/clang/Basic/DiagnosticCommonKinds.td
+++ b/include/clang/Basic/DiagnosticCommonKinds.td
@@ -52,8 +52,4 @@ def warn_integer_too_large_for_signed : Warning<
def note_invalid_subexpr_in_ice : Note<
"subexpression not valid in an integer constant expression">;
-// clang-cc
-def err_pp_I_dash_not_supported : Error<
- "-I- not supported, please use -iquote instead">;
-
}
diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td
index dfdf0ff2e733..e2f11041dce2 100644
--- a/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/include/clang/Basic/DiagnosticDriverKinds.td
@@ -55,6 +55,8 @@ def err_drv_command_signalled : Error<
"%0 command failed due to signal %1 (use -v to see invocation)">;
def err_drv_invalid_mfloat_abi : Error<
"invalid float ABI '%0'">;
+def err_drv_I_dash_not_supported : Error<
+ "'%0' not supported, please use -iquote instead">;
def warn_drv_input_file_unused : Warning<
"%0: '%1' input unused when '%2' is present">;
diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td
index e5c73270fdfc..ae8b92394443 100644
--- a/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -12,6 +12,7 @@ let Component = "Frontend" in {
def err_fe_unknown_triple : Error<
"unknown target triple '%0', please use -triple or -arch">;
def err_fe_unknown_target_abi : Error<"unknown target ABI '%0'">;
+def err_fe_error_opening : Error<"error opening '%0': %1">;
def err_fe_error_reading : Error<"error reading '%0'">;
def err_fe_error_reading_stdin : Error<"error reading stdin">;
def err_fe_error_backend : Error<"error in backend: %0">, DefaultFatal;
@@ -19,6 +20,8 @@ def err_fe_invalid_ast_file : Error<"invalid AST file: '%0'">, DefaultFatal;
def err_fe_invalid_ast_action : Error<"invalid action for AST input">, DefaultFatal;
def err_fe_invalid_code_complete_file
: Error<"cannot locate code-completion file %0">, DefaultFatal;
+def err_fe_dependency_file_requires_MT : Error<
+ "-dependency-file requires at least one -MT option">;
def note_fixit_applied : Note<"FIX-IT applied suggested code changes">;
def note_fixit_in_macro : Note<
diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td
index 3f132c0dabfa..bbc551373d96 100644
--- a/include/clang/Basic/DiagnosticLexKinds.td
+++ b/include/clang/Basic/DiagnosticLexKinds.td
@@ -194,7 +194,8 @@ def err_pp_expected_eol : Error<
"expected end of line in preprocessor expression">;
def err_pp_defined_requires_identifier : Error<
"operator 'defined' requires an identifier">;
-def err_pp_missing_rparen : Error<"missing ')' after 'defined'">;
+def err_pp_missing_lparen : Error<"missing '(' after '%0'">;
+def err_pp_missing_rparen : Error<"missing ')' after '%0'">;
def err_pp_colon_without_question : Error<"':' without preceding '?'">;
def err_pp_division_by_zero : Error<
"division by zero in preprocessor expression">;
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index 19b0ea3932a5..db8d580a2cd7 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -117,6 +117,8 @@ def err_expected_semi_after_static_assert : Error<
"expected ';' after static_assert">;
def err_expected_semi_for : Error<"expected ';' in 'for' statement specifier">;
def err_expected_colon_after : Error<"expected ':' after %0">;
+def err_pointer_to_member_type : Error<
+ "invalid use of pointer to member type after %0">;
def err_label_end_of_compound_statement : Error<
"label at end of compound statement: expected statement">;
def err_expected_string_literal : Error<"expected string literal">;
@@ -124,6 +126,7 @@ def err_expected_asm_operand : Error<
"expected string literal or '[' for asm operand">;
def err_expected_selector_for_method : Error<
"expected selector for Objective-C method">;
+def err_expected_property_name : Error<"expected property name">;
def err_unexpected_at : Error<"unexpected '@' in program">;
@@ -213,7 +216,8 @@ def err_declaration_does_not_declare_param : Error<
def err_no_matching_param : Error<"parameter named %0 is missing">;
/// C++ parser diagnostics
-def err_expected_unqualified_id : Error<"expected unqualified-id">;
+def err_expected_unqualified_id : Error<
+ "expected %select{identifier|unqualified-id}0">;
def err_func_def_no_params : Error<
"function definition does not declare parameters">;
def err_expected_lparen_after_type : Error<
@@ -230,6 +234,8 @@ def err_expected_catch : Error<"expected catch">;
def err_expected_lbrace_or_comma : Error<"expected '{' or ','">;
def err_using_namespace_in_class : Error<
"'using namespace' in class not allowed">;
+def err_ident_in_pseudo_dtor_not_a_type : Error<
+ "identifier %0 in pseudo-destructor expression does not name a type">;
// C++ derived classes
def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">;
@@ -279,6 +285,9 @@ def err_typename_refers_to_non_type_template : Error<
"typename specifier refers to a non-template">;
def err_expected_type_name_after_typename : Error<
"expected an identifier or template-id after '::'">;
+def err_explicit_spec_non_template : Error<
+ "explicit %select{specialization|instantiation}0 of non-template "
+ "%select{class|struct|union}1 %2">;
def err_variadic_templates : Error<
"variadic templates are only allowed in C++0x">;
@@ -286,7 +295,7 @@ def err_variadic_templates : Error<
// C++ declarations
def err_friend_decl_defines_class : Error<
"cannot define a type in a friend declaration">;
-
+
// Language specific pragmas
// - Generic warnings
def warn_pragma_expected_lparen : Warning<
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 7a87e244f77c..99fddb581088 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -264,13 +264,19 @@ def warn_objc_property_copy_missing_on_block : Warning<
"'copy' attribute must be specified for the block property "
"when -fobjc-gc-only is specified">;
def err_use_continuation_class : Error<
- "attribute of property in continuation class of %0 can only be 'readwrite'">;
+ "property declaration in continuation class of %0 is to change a 'readonly' "
+ "property to 'readwrite'">;
def err_continuation_class : Error<"continuation class has no primary class">;
def err_property_type : Error<"property cannot have array or function type %0">;
def error_missing_property_context : Error<
"missing context for property implementation declaration">;
def error_bad_property_decl : Error<
"property implementation must have its declaration in interface %0">;
+def error_category_property : Error<
+ "property declared in category %0 cannot be implemented in "
+ "class implementation">;
+def note_property_declare : Note<
+ "property declared here">;
def error_synthesize_category_decl : Error<
"@synthesize not allowed in a category's implementation">;
def error_missing_property_interface : Error<
@@ -613,6 +619,10 @@ def warn_attribute_wrong_decl_type : Warning<
def warn_gnu_inline_attribute_requires_inline : Warning<
"'gnu_inline' attribute requires function to be marked 'inline',"
" attribute ignored">;
+def err_cconv_knr : Error<
+ "function with no prototype cannot use '%0' calling convention">;
+def err_cconv_varargs : Error<
+ "variadic function cannot use '%0' calling convention">;
def warn_attribute_ignored_for_field_of_type : Warning<
"%0 attribute ignored for field of type %1">;
@@ -1014,7 +1024,11 @@ def note_partial_spec_unused_parameter : Note<
def err_partial_spec_ordering_ambiguous : Error<
"ambiguous partial specializations of %0">;
def note_partial_spec_match : Note<"partial specialization matches %0">;
-
+def err_partial_spec_redeclared : Error<
+ "class template partial specialization %0 cannot be redeclared">;
+def note_prev_partial_spec_here : Note<
+ "previous declaration of class template partial specialization %0 is here">;
+
// C++ Function template specializations
def err_function_template_spec_no_match : Error<
"no function template matches function template specialization %0">;
@@ -1326,17 +1340,17 @@ def err_flexible_array_init_nonempty : Error<
def err_flexible_array_init_needs_braces : Error<
"flexible array requires brace-enclosed initializer">;
def err_illegal_decl_array_of_functions : Error<
- "'%0' declared as array of functions">;
+ "'%0' declared as array of functions of type %1">;
def err_illegal_decl_array_incomplete_type : Error<
"array has incomplete element type %0">;
def err_illegal_decl_array_of_references : Error<
- "'%0' declared as array of references">;
+ "'%0' declared as array of references of type %1">;
def err_array_star_outside_prototype : Error<
"star modifier used outside of function prototype">;
def err_illegal_decl_pointer_to_reference : Error<
- "'%0' declared as a pointer to a reference">;
+ "'%0' declared as a pointer to a reference of type %1">;
def err_illegal_decl_mempointer_to_reference : Error<
- "'%0' declared as a member pointer to a reference">;
+ "'%0' declared as a member pointer to a reference of type %1">;
def err_illegal_decl_mempointer_to_void : Error<
"'%0' declared as a member pointer to void">;
def err_illegal_decl_mempointer_in_nonclass : Error<
@@ -1368,6 +1382,8 @@ def err_alignof_incomplete_type : Error<
"invalid application of '__alignof' to an incomplete type %0">;
def err_sizeof_alignof_bitfield : Error<
"invalid application of '%select{sizeof|__alignof}0' to bit-field">;
+def err_offsetof_incomplete_type : Error<
+ "offsetof of incomplete type %0">;
def err_offsetof_record_type : Error<
"offsetof requires struct, union, or class type, %0 invalid">;
def err_offsetof_array_type : Error<"offsetof requires array type, %0 invalid">;
@@ -1385,6 +1401,10 @@ def warn_shift_negative : Warning<
def warn_shift_gt_typewidth : Warning<
"shift count >= width of type">;
+def warn_precedence_bitwise_rel : Warning<
+ "%0 has lower precedence than %1; %1 will be evaluated first">,
+ InGroup<Parentheses>;
+
def err_sizeof_nonfragile_interface : Error<
"invalid application of '%select{alignof|sizeof}1' to interface %0 in "
"non-fragile ABI">;
@@ -1661,7 +1681,9 @@ def err_bad_new_type : Error<
def err_new_incomplete_type : Error<
"allocation of incomplete type %0">;
def err_new_array_nonconst : Error<
- "only the first dimension of an allocated array may be non-const">;
+ "only the first dimension of an allocated array may have dynamic size">;
+def err_new_paren_array_nonconst : Error<
+ "when type is in parentheses, array cannot have dynamic size">;
def err_array_size_not_integral : Error<
"array size expression must have integral or enumerated type, not %0">;
def err_new_uninitialized_const : Error<
@@ -1709,8 +1731,6 @@ def err_throw_incomplete_ptr : Error<
def err_return_in_constructor_handler : Error<
"return in the catch of a function try block of a constructor is illegal">;
-def err_ident_in_pseudo_dtor_not_a_type : Error<
- "identifier %0 in pseudo-destructor expression does not name a type">;
def err_operator_arrow_circular : Error<
"circular pointer delegation detected">;
def err_pseudo_dtor_base_not_scalar : Error<
@@ -2130,6 +2150,10 @@ def warn_ret_stack_addr : Warning<
"address of stack memory associated with local variable %0 returned">;
def warn_ret_stack_ref : Warning<
"reference to stack memory associated with local variable %0 returned">;
+def warn_ret_addr_label : Warning<
+ "returning address of label, which is local">;
+def err_ret_local_block : Error<
+ "returning block that lives on the local stack">;
// For non-floating point, expressions of the form x == x or x != x
@@ -2153,8 +2177,6 @@ def err_return_in_block_expression : Error<
def err_block_returns_array : Error<
"block declared as returning an array">;
-def err_ret_local_block : Error<
- "returning block that lives on the local stack">;
// CFString checking
def err_cfstring_literal_not_string_constant : Error<
diff --git a/include/clang/Basic/OnDiskHashTable.h b/include/clang/Basic/OnDiskHashTable.h
index 2184bf3c457c..6b60f2eec097 100644
--- a/include/clang/Basic/OnDiskHashTable.h
+++ b/include/clang/Basic/OnDiskHashTable.h
@@ -16,7 +16,7 @@
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Compiler.h"
-#include "llvm/Support/DataTypes.h"
+#include "llvm/System/DataTypes.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Host.h"
diff --git a/include/clang/Basic/OperatorKinds.h b/include/clang/Basic/OperatorKinds.h
index 790b75ba3af3..c0a95051a72d 100644
--- a/include/clang/Basic/OperatorKinds.h
+++ b/include/clang/Basic/OperatorKinds.h
@@ -26,7 +26,10 @@ enum OverloadedOperatorKind {
NUM_OVERLOADED_OPERATORS
};
-
+/// \brief Retrieve the spelling of the given overloaded operator, without
+/// the preceding "operator" keyword.
+const char *getOperatorSpelling(OverloadedOperatorKind Operator);
+
} // end namespace clang
#endif
diff --git a/include/clang/Basic/PartialDiagnostic.h b/include/clang/Basic/PartialDiagnostic.h
index e8cc564c8a20..9960d5beb5c1 100644
--- a/include/clang/Basic/PartialDiagnostic.h
+++ b/include/clang/Basic/PartialDiagnostic.h
@@ -109,7 +109,7 @@ public:
// Add all arguments.
for (unsigned i = 0, e = DiagStorage->NumDiagArgs; i != e; ++i) {
DB.AddTaggedVal(DiagStorage->DiagArgumentsVal[i],
- (Diagnostic::ArgumentKind)DiagStorage->DiagArgumentsKind[i]);
+ (Diagnostic::ArgumentKind)DiagStorage->DiagArgumentsKind[i]);
}
// Add all ranges.
@@ -129,13 +129,25 @@ public:
PD.AddTaggedVal(I, Diagnostic::ak_uint);
return PD;
}
-
+
+ friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
+ int I) {
+ PD.AddTaggedVal(I, Diagnostic::ak_sint);
+ return PD;
+ }
+
+ friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
+ const char *S) {
+ PD.AddTaggedVal(reinterpret_cast<intptr_t>(S), Diagnostic::ak_c_string);
+ return PD;
+ }
+
friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
const SourceRange &R) {
PD.AddSourceRange(R);
return PD;
}
-
+
friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
DeclarationName N);
};
diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h
index 8a69cba066b3..7e9ac531017e 100644
--- a/include/clang/Basic/SourceManager.h
+++ b/include/clang/Basic/SourceManager.h
@@ -16,7 +16,7 @@
#include "clang/Basic/SourceLocation.h"
#include "llvm/Support/Allocator.h"
-#include "llvm/Support/DataTypes.h"
+#include "llvm/System/DataTypes.h"
#include "llvm/ADT/DenseMap.h"
#include <vector>
#include <cassert>
diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h
index b88e2aaba383..e61ef9265cfb 100644
--- a/include/clang/Basic/TargetInfo.h
+++ b/include/clang/Basic/TargetInfo.h
@@ -17,7 +17,7 @@
// FIXME: Daniel isn't smart enough to use a prototype for this.
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/Triple.h"
-#include "llvm/Support/DataTypes.h"
+#include "llvm/System/DataTypes.h"
#include <cassert>
#include <vector>
#include <string>
@@ -103,9 +103,9 @@ public:
/// enum. For example, SignedInt -> getIntWidth().
unsigned getTypeWidth(IntType T) const;
- /// getTypeSigned - Return whether an integer types is signed. Returns true if
+ /// isTypeSigned - Return whether an integer types is signed. Returns true if
/// the type is signed; false otherwise.
- bool getTypeSigned(IntType T) const;
+ bool isTypeSigned(IntType T) const;
/// getPointerWidth - Return the width of pointers on this target, for the
/// specified address space.
diff --git a/include/clang/Driver/Options.def b/include/clang/Driver/Options.def
index 4084be6c0b42..5370114ee824 100644
--- a/include/clang/Driver/Options.def
+++ b/include/clang/Driver/Options.def
@@ -404,6 +404,7 @@ OPTION("-flax-vector-conversions", flax_vector_conversions, Flag, f_Group, INVAL
OPTION("-flimited-precision=", flimited_precision_EQ, Joined, f_Group, INVALID, "", 0, 0, 0)
OPTION("-flto", flto, Flag, f_Group, INVALID, "", 0, 0, 0)
OPTION("-fmath-errno", fmath_errno, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fmerge-all-constants", fmerge_all_constants, Flag, f_Group, INVALID, "", 0, 0, 0)
OPTION("-fmessage-length=", fmessage_length_EQ, Joined, f_Group, INVALID, "", 0, 0, 0)
OPTION("-fms-extensions", fms_extensions, Flag, f_Group, INVALID, "", 0, 0, 0)
OPTION("-fmudflapth", fmudflapth, Flag, f_Group, INVALID, "", 0, 0, 0)
@@ -428,6 +429,7 @@ OPTION("-fno-inline-functions", fno_inline_functions, Flag, clang_ignored_f_Grou
OPTION("-fno-inline", fno_inline, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0)
OPTION("-fno-keep-inline-functions", fno_keep_inline_functions, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0)
OPTION("-fno-math-errno", fno_math_errno, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fno-merge-all-constants", fno_merge_all_constants, Flag, f_Group, INVALID, "", 0, 0, 0)
OPTION("-fno-omit-frame-pointer", fno_omit_frame_pointer, Flag, f_Group, INVALID, "", 0, 0, 0)
OPTION("-fno-pascal-strings", fno_pascal_strings, Flag, f_Group, INVALID, "", 0, 0, 0)
OPTION("-fno-rtti", fno_rtti, Flag, f_Group, INVALID, "", 0, 0, 0)
@@ -559,6 +561,7 @@ OPTION("-m", m_Joined, Joined, m_Group, INVALID, "", 0, 0, 0)
OPTION("-no-cpp-precomp", no_cpp_precomp, Flag, INVALID, INVALID, "", 0, 0, 0)
OPTION("-no-integrated-cpp", no_integrated_cpp, Flag, INVALID, INVALID, "d", 0, 0, 0)
OPTION("-no_dead_strip_inits_and_terms", no__dead__strip__inits__and__terms, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-nobuiltininc", nobuiltininc, Flag, INVALID, INVALID, "", 0, 0, 0)
OPTION("-nodefaultlibs", nodefaultlibs, Flag, INVALID, INVALID, "", 0, 0, 0)
OPTION("-nofixprebinding", nofixprebinding, Flag, INVALID, INVALID, "", 0, 0, 0)
OPTION("-nolibc", nolibc, Flag, INVALID, INVALID, "", 0, 0, 0)
@@ -566,7 +569,6 @@ OPTION("-nomultidefs", nomultidefs, Flag, INVALID, INVALID, "", 0, 0, 0)
OPTION("-noprebind", noprebind, Flag, INVALID, INVALID, "", 0, 0, 0)
OPTION("-noseglinkedit", noseglinkedit, Flag, INVALID, INVALID, "", 0, 0, 0)
OPTION("-nostartfiles", nostartfiles, Flag, INVALID, INVALID, "", 0, 0, 0)
-OPTION("-nostdclanginc", nostdclanginc, Flag, INVALID, INVALID, "", 0, 0, 0)
OPTION("-nostdinc", nostdinc, Flag, INVALID, INVALID, "", 0, 0, 0)
OPTION("-nostdlib", nostdlib, Flag, INVALID, INVALID, "", 0, 0, 0)
OPTION("-object", object, Flag, INVALID, INVALID, "", 0, 0, 0)
diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h
index 9573777b5f6f..7dfabbadd8fd 100644
--- a/include/clang/Frontend/ASTUnit.h
+++ b/include/clang/Frontend/ASTUnit.h
@@ -18,6 +18,7 @@
#include "llvm/ADT/OwningPtr.h"
#include "clang/Frontend/TextDiagnosticBuffer.h"
#include "clang/Basic/FileManager.h"
+#include "clang/Index/ASTLocation.h"
#include <string>
namespace clang {
@@ -32,6 +33,8 @@ namespace clang {
class ASTContext;
class Decl;
+using namespace idx;
+
/// \brief Utility class for loading a ASTContext from a PCH file.
///
class ASTUnit {
@@ -50,9 +53,11 @@ class ASTUnit {
// FIXME: This is temporary; eventually, CIndex will always do this.
bool OnlyLocalDecls;
+ // Critical optimization when using clang_getCursor().
+ ASTLocation LastLoc;
+
ASTUnit(const ASTUnit&); // DO NOT IMPLEMENT
ASTUnit &operator=(const ASTUnit &); // DO NOT IMPLEMENT
- ASTUnit();
public:
ASTUnit(DiagnosticClient *diagClient = NULL);
@@ -80,6 +85,9 @@ public:
bool getOnlyLocalDecls() const { return OnlyLocalDecls; }
+ void setLastASTLocation(ASTLocation ALoc) { LastLoc = ALoc; }
+ ASTLocation getLastASTLocation() const { return LastLoc; }
+
/// \brief Create a ASTUnit from a PCH file.
///
/// \param Filename - The PCH file to load.
diff --git a/include/clang/Frontend/CompileOptions.h b/include/clang/Frontend/CompileOptions.h
index 508af537b1fa..ad53a8d592ba 100644
--- a/include/clang/Frontend/CompileOptions.h
+++ b/include/clang/Frontend/CompileOptions.h
@@ -43,7 +43,8 @@ public:
unsigned NoCommon : 1; /// Set when -fno-common or C++ is enabled.
unsigned DisableRedZone : 1; /// Set when -mno-red-zone is enabled.
unsigned NoImplicitFloat : 1; /// Set when -mno-implicit-float is enabled.
-
+ unsigned MergeAllConstants : 1; // Merge identical constants.
+
/// Inlining - The kind of inlining to perform.
InliningMethod Inlining;
@@ -67,6 +68,7 @@ public:
Inlining = NoInlining;
DisableRedZone = 0;
NoImplicitFloat = 0;
+ MergeAllConstants = 1;
}
};
diff --git a/include/clang/Frontend/DeclXML.def b/include/clang/Frontend/DeclXML.def
index 36323c260c9a..8b80d1dc11d8 100644
--- a/include/clang/Frontend/DeclXML.def
+++ b/include/clang/Frontend/DeclXML.def
@@ -99,7 +99,7 @@ NODE_XML(FunctionDecl, "Function")
ENUM_XML(FunctionDecl::Static, "static")
ENUM_XML(FunctionDecl::PrivateExtern, "__private_extern__")
END_ENUM_XML
- ATTRIBUTE_OPT_XML(isInline(), "inline")
+ ATTRIBUTE_OPT_XML(isInlineSpecified(), "inline")
//ATTRIBUTE_OPT_XML(isVariadic(), "variadic") // in the type reference
ATTRIBUTE_XML(getNumParams(), "num_args")
SUB_NODE_SEQUENCE_XML(ParmVarDecl)
@@ -113,7 +113,7 @@ NODE_XML(CXXMethodDecl, "CXXMethodDecl")
ATTRIBUTE_XML(getNameAsString(), "name")
TYPE_ATTRIBUTE_XML(getType()->getAs<FunctionType>()->getResultType())
ATTRIBUTE_XML(getType()->getAs<FunctionType>(), "function_type")
- ATTRIBUTE_OPT_XML(isInline(), "inline")
+ ATTRIBUTE_OPT_XML(isInlineSpecified(), "inline")
ATTRIBUTE_OPT_XML(isStatic(), "static")
ATTRIBUTE_OPT_XML(isVirtual(), "virtual")
ATTRIBUTE_XML(getNumParams(), "num_args")
diff --git a/include/clang/Frontend/DiagnosticOptions.h b/include/clang/Frontend/DiagnosticOptions.h
new file mode 100644
index 000000000000..58673e4dad6b
--- /dev/null
+++ b/include/clang/Frontend/DiagnosticOptions.h
@@ -0,0 +1,49 @@
+//===--- DiagnosticOptions.h ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_DIAGNOSTICOPTIONS_H
+#define LLVM_CLANG_FRONTEND_DIAGNOSTICOPTIONS_H
+
+#include <string>
+#include <vector>
+
+namespace clang {
+
+/// DiagnosticOptions - Options for controlling the compiler diagnostics
+/// engine.
+class DiagnosticOptions {
+public:
+ unsigned ShowColumn : 1; /// Show column number on diagnostics.
+ unsigned ShowLocation : 1; /// Show source location information.
+ unsigned ShowCarets : 1; /// Show carets in diagnostics.
+ unsigned ShowFixits : 1; /// Show fixit information.
+ unsigned ShowSourceRanges : 1; /// Show source ranges in numeric form.
+ unsigned ShowOptionNames : 1; /// Show the diagnostic name for mappable
+ /// diagnostics.
+ unsigned ShowColors : 1; /// Show diagnostics with ANSI color sequences.
+
+ /// Column limit for formatting message diagnostics, or 0 if unused.
+ unsigned MessageLength;
+
+public:
+ DiagnosticOptions() {
+ ShowColumn = 1;
+ ShowLocation = 1;
+ ShowCarets = 1;
+ ShowFixits = 1;
+ ShowSourceRanges = 0;
+ ShowOptionNames = 0;
+ ShowColors = 0;
+ MessageLength = 0;
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Frontend/InitHeaderSearch.h b/include/clang/Frontend/InitHeaderSearch.h
index a90b4eaf9e2b..48c426825262 100644
--- a/include/clang/Frontend/InitHeaderSearch.h
+++ b/include/clang/Frontend/InitHeaderSearch.h
@@ -73,6 +73,16 @@ public:
/// variables such as CPATH.
void AddDefaultEnvVarPaths(const LangOptions &Lang);
+ // AddDefaultCIncludePaths - Add paths that should always be searched.
+ void AddDefaultCIncludePaths(const llvm::Triple &triple);
+
+ // AddDefaultCPlusPlusIncludePaths - Add paths that should be searched when
+ // compiling c++.
+ void AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple);
+
+ // AddDefaultFrameworkIncludePaths - Add the framework paths. Used on darwin.
+ void AddDefaultFrameworkIncludePaths(const llvm::Triple &triple);
+
/// AddDefaultSystemIncludePaths - Adds the default system include paths so
/// that e.g. stdio.h is found.
void AddDefaultSystemIncludePaths(const LangOptions &Lang,
diff --git a/include/clang/Frontend/InitPreprocessor.h b/include/clang/Frontend/InitPreprocessor.h
index eb03602dc57b..b29ee2728a86 100644
--- a/include/clang/Frontend/InitPreprocessor.h
+++ b/include/clang/Frontend/InitPreprocessor.h
@@ -63,7 +63,8 @@ public:
/// environment ready to process a single file. This returns true on error.
///
bool InitializePreprocessor(Preprocessor &PP,
- const PreprocessorInitOptions& InitOptions);
+ const PreprocessorInitOptions& InitOptions,
+ bool undef_macros);
} // end namespace clang
diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h
index 1e953d671226..b2bb9a13771d 100644
--- a/include/clang/Frontend/PCHBitCodes.h
+++ b/include/clang/Frontend/PCHBitCodes.h
@@ -18,7 +18,7 @@
#define LLVM_CLANG_FRONTEND_PCHBITCODES_H
#include "llvm/Bitcode/BitCodes.h"
-#include "llvm/Support/DataTypes.h"
+#include "llvm/System/DataTypes.h"
namespace clang {
namespace pch {
@@ -496,8 +496,6 @@ namespace clang {
DECL_IMPLICIT_PARAM,
/// \brief A ParmVarDecl record.
DECL_PARM_VAR,
- /// \brief An OriginalParmVarDecl record.
- DECL_ORIGINAL_PARM_VAR,
/// \brief A FileScopeAsmDecl record.
DECL_FILE_SCOPE_ASM,
/// \brief A BlockDecl record.
diff --git a/include/clang/Frontend/PCHReader.h b/include/clang/Frontend/PCHReader.h
index cc16970b0040..cc8b3a03e3e8 100644
--- a/include/clang/Frontend/PCHReader.h
+++ b/include/clang/Frontend/PCHReader.h
@@ -19,6 +19,7 @@
#include "clang/Sema/ExternalSemaSource.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Type.h"
+#include "clang/AST/TemplateBase.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/SourceManager.h"
@@ -29,7 +30,7 @@
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Bitcode/BitstreamReader.h"
-#include "llvm/Support/DataTypes.h"
+#include "llvm/System/DataTypes.h"
#include <deque>
#include <map>
#include <string>
@@ -542,6 +543,12 @@ public:
/// comments in the source code.
virtual void ReadComments(std::vector<SourceRange> &Comments);
+ /// \brief Reads a TemplateArgumentLocInfo appropriate for the
+ /// given TemplateArgument kind.
+ TemplateArgumentLocInfo
+ GetTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind,
+ const RecordData &Record, unsigned &Idx);
+
/// \brief Reads a declarator info from the given record.
virtual DeclaratorInfo *GetDeclaratorInfo(const RecordData &Record,
unsigned &Idx);
diff --git a/include/clang/Frontend/PCHWriter.h b/include/clang/Frontend/PCHWriter.h
index 728e138d9e7c..22427eb67103 100644
--- a/include/clang/Frontend/PCHWriter.h
+++ b/include/clang/Frontend/PCHWriter.h
@@ -275,6 +275,10 @@ public:
/// \brief Emits a reference to a declarator info.
void AddDeclaratorInfo(DeclaratorInfo *DInfo, RecordData &Record);
+ /// \brief Emits a template argument location.
+ void AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg,
+ RecordData &Record);
+
/// \brief Emit a reference to a declaration.
void AddDeclRef(const Decl *D, RecordData &Record);
diff --git a/include/clang/Frontend/TextDiagnosticPrinter.h b/include/clang/Frontend/TextDiagnosticPrinter.h
index 0fd8d44f72bc..98e5a75c65b9 100644
--- a/include/clang/Frontend/TextDiagnosticPrinter.h
+++ b/include/clang/Frontend/TextDiagnosticPrinter.h
@@ -23,42 +23,21 @@ namespace llvm {
}
namespace clang {
-class SourceManager;
+class DiagnosticOptions;
class LangOptions;
+class SourceManager;
class TextDiagnosticPrinter : public DiagnosticClient {
llvm::raw_ostream &OS;
const LangOptions *LangOpts;
+ const DiagnosticOptions *DiagOpts;
+
SourceLocation LastWarningLoc;
FullSourceLoc LastLoc;
bool LastCaretDiagnosticWasNote;
- bool ShowColumn;
- bool CaretDiagnostics;
- bool ShowLocation;
- bool PrintRangeInfo;
- bool PrintDiagnosticOption;
- bool PrintFixItInfo;
- unsigned MessageLength;
- bool UseColors;
-
public:
- TextDiagnosticPrinter(llvm::raw_ostream &os,
- bool showColumn = true,
- bool caretDiagnistics = true, bool showLocation = true,
- bool printRangeInfo = true,
- bool printDiagnosticOption = true,
- bool printFixItInfo = true,
- unsigned messageLength = 0,
- bool useColors = false)
- : OS(os), LangOpts(0),
- LastCaretDiagnosticWasNote(false), ShowColumn(showColumn),
- CaretDiagnostics(caretDiagnistics), ShowLocation(showLocation),
- PrintRangeInfo(printRangeInfo),
- PrintDiagnosticOption(printDiagnosticOption),
- PrintFixItInfo(printFixItInfo),
- MessageLength(messageLength),
- UseColors(useColors) {}
+ TextDiagnosticPrinter(llvm::raw_ostream &os, const DiagnosticOptions &diags);
void setLangOptions(const LangOptions *LO) {
LangOpts = LO;
diff --git a/include/clang/Index/Utils.h b/include/clang/Index/Utils.h
index 36cf56dea203..f8e01f728648 100644
--- a/include/clang/Index/Utils.h
+++ b/include/clang/Index/Utils.h
@@ -18,7 +18,6 @@
namespace clang {
class ASTContext;
class SourceLocation;
- class Decl;
namespace idx {
class ASTLocation;
@@ -28,7 +27,7 @@ namespace idx {
/// \returns the resolved ASTLocation or an invalid ASTLocation if the source
/// location could not be resolved.
ASTLocation ResolveLocationInAST(ASTContext &Ctx, SourceLocation Loc,
- Decl *RelativeToDecl = 0);
+ ASTLocation *LastLoc = 0);
} // end namespace idx
diff --git a/include/clang/Lex/LiteralSupport.h b/include/clang/Lex/LiteralSupport.h
index 97656f7d39d6..c4ab5aebf721 100644
--- a/include/clang/Lex/LiteralSupport.h
+++ b/include/clang/Lex/LiteralSupport.h
@@ -17,7 +17,7 @@
#include <string>
#include "llvm/ADT/SmallString.h"
-#include "llvm/Support/DataTypes.h"
+#include "llvm/System/DataTypes.h"
namespace llvm {
class APInt;
diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h
index 0765ac391be3..35960ff328a6 100644
--- a/include/clang/Lex/Preprocessor.h
+++ b/include/clang/Lex/Preprocessor.h
@@ -75,6 +75,8 @@ class Preprocessor {
IdentifierInfo *Ident_Pragma, *Ident__VA_ARGS__; // _Pragma, __VA_ARGS__
IdentifierInfo *Ident__has_feature; // __has_feature
IdentifierInfo *Ident__has_builtin; // __has_builtin
+ IdentifierInfo *Ident__has_include; // __has_include
+ IdentifierInfo *Ident__has_include_next; // __has_include_next
SourceLocation DATELoc, TIMELoc;
unsigned CounterValue; // Next __COUNTER__ value.
@@ -244,7 +246,12 @@ public:
return CurPPLexer == L;
}
- /// getCurrentLexer - Return the current file lexer being lexed from. Note
+ /// getCurrentLexer - Return the current lexer being lexed from. Note
+ /// that this ignores any potentially active macro expansions and _Pragma
+ /// expansions going on at the time.
+ PreprocessorLexer *getCurrentLexer() const { return CurPPLexer; }
+
+ /// getCurrentFileLexer - Return the current file lexer being lexed from. Note
/// that this ignores any potentially active macro expansions and _Pragma
/// expansions going on at the time.
PreprocessorLexer *getCurrentFileLexer() const;
@@ -622,6 +629,43 @@ public:
/// SourceLocation.
MacroInfo* AllocateMacroInfo(SourceLocation L);
+ /// GetIncludeFilenameSpelling - Turn the specified lexer token into a fully
+ /// checked and spelled filename, e.g. as an operand of #include. This returns
+ /// true if the input filename was in <>'s or false if it were in ""'s. The
+ /// caller is expected to provide a buffer that is large enough to hold the
+ /// spelling of the filename, but is also expected to handle the case when
+ /// this method decides to use a different buffer.
+ bool GetIncludeFilenameSpelling(SourceLocation Loc,
+ const char *&BufStart, const char *&BufEnd);
+
+ /// LookupFile - Given a "foo" or <foo> reference, look up the indicated file,
+ /// return null on failure. isAngled indicates whether the file reference is
+ /// for system #include's or not (i.e. using <> instead of "").
+ const FileEntry *LookupFile(const char *FilenameStart,const char *FilenameEnd,
+ bool isAngled, const DirectoryLookup *FromDir,
+ const DirectoryLookup *&CurDir);
+
+ /// GetCurLookup - The DirectoryLookup structure used to find the current
+ /// FileEntry, if CurLexer is non-null and if applicable. This allows us to
+ /// implement #include_next and find directory-specific properties.
+ const DirectoryLookup *GetCurDirLookup() { return CurDirLookup; }
+
+ /// isInPrimaryFile - Return true if we're in the top-level file, not in a
+ /// #include.
+ bool isInPrimaryFile() const;
+
+ /// ConcatenateIncludeName - Handle cases where the #include name is expanded
+ /// from a macro as multiple tokens, which need to be glued together. This
+ /// occurs for code like:
+ /// #define FOO <a/b.h>
+ /// #include FOO
+ /// because in this case, "<a/b.h>" is returned as 7 tokens, not one.
+ ///
+ /// This code concatenates and consumes tokens up to the '>' token. It returns
+ /// false if the > was found, otherwise it returns true if it finds and consumes
+ /// the EOM marker.
+ bool ConcatenateIncludeName(llvm::SmallVector<char, 128> &FilenameBuffer);
+
private:
void PushIncludeMacroStack() {
@@ -646,10 +690,6 @@ private:
/// be reused for allocating new MacroInfo objects.
void ReleaseMacroInfo(MacroInfo* MI);
- /// isInPrimaryFile - Return true if we're in the top-level file, not in a
- /// #include.
- bool isInPrimaryFile() const;
-
/// ReadMacroName - Lex and validate a macro name, which occurs after a
/// #define or #undef. This emits a diagnostic, sets the token kind to eom,
/// and discards the rest of the macro line if the macro name is invalid.
@@ -722,24 +762,6 @@ private:
/// start getting tokens from it using the PTH cache.
void EnterSourceFileWithPTH(PTHLexer *PL, const DirectoryLookup *Dir);
- /// GetIncludeFilenameSpelling - Turn the specified lexer token into a fully
- /// checked and spelled filename, e.g. as an operand of #include. This returns
- /// true if the input filename was in <>'s or false if it were in ""'s. The
- /// caller is expected to provide a buffer that is large enough to hold the
- /// spelling of the filename, but is also expected to handle the case when
- /// this method decides to use a different buffer.
- bool GetIncludeFilenameSpelling(SourceLocation Loc,
- const char *&BufStart, const char *&BufEnd);
-
- /// LookupFile - Given a "foo" or <foo> reference, look up the indicated file,
- /// return null on failure. isAngled indicates whether the file reference is
- /// for system #include's or not (i.e. using <> instead of "").
- const FileEntry *LookupFile(const char *FilenameStart,const char *FilenameEnd,
- bool isAngled, const DirectoryLookup *FromDir,
- const DirectoryLookup *&CurDir);
-
-
-
/// IsFileLexer - Returns true if we are lexing from a file and not a
/// pragma or a macro.
static bool IsFileLexer(const Lexer* L, const PreprocessorLexer* P) {
diff --git a/include/clang/Lex/Token.h b/include/clang/Lex/Token.h
index 8acdb30cc705..8d910959b9fa 100644
--- a/include/clang/Lex/Token.h
+++ b/include/clang/Lex/Token.h
@@ -17,6 +17,7 @@
#include "clang/Basic/TemplateKinds.h"
#include "clang/Basic/TokenKinds.h"
#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/OperatorKinds.h"
#include <cstdlib>
namespace clang {
@@ -62,12 +63,12 @@ class Token {
/// Kind - The actual flavor of token this is.
///
- unsigned Kind : 8; // DON'T make Kind a 'tok::TokenKind';
+ unsigned char Kind; // DON'T make Kind a 'tok::TokenKind';
// MSVC will treat it as a signed char and
// TokenKinds > 127 won't be handled correctly.
/// Flags - Bits we track about this token, members of the TokenFlags enum.
- unsigned Flags : 8;
+ unsigned char Flags;
public:
// Various flags set per token:
@@ -261,6 +262,9 @@ struct TemplateIdAnnotation {
/// FIXME: Temporarily stores the name of a specialization
IdentifierInfo *Name;
+ /// FIXME: Temporarily stores the overloaded operator kind.
+ OverloadedOperatorKind Operator;
+
/// The declaration of the template corresponding to the
/// template-name. This is an Action::DeclTy*.
void *Template;
diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h
index 050b3f42e4cd..073365dcede3 100644
--- a/include/clang/Parse/Action.h
+++ b/include/clang/Parse/Action.h
@@ -161,6 +161,23 @@ public:
// Declaration Tracking Callbacks.
//===--------------------------------------------------------------------===//
+ typedef uintptr_t ParsingDeclStackState;
+
+ /// PushParsingDeclaration - Notes that the parser has begun
+ /// processing a declaration of some sort. Guaranteed to be matched
+ /// by a call to PopParsingDeclaration with the value returned by
+ /// this method.
+ virtual ParsingDeclStackState PushParsingDeclaration() {
+ return ParsingDeclStackState();
+ }
+
+ /// PopParsingDeclaration - Notes that the parser has completed
+ /// processing a declaration of some sort. The decl will be empty
+ /// if the declaration didn't correspond to a full declaration (or
+ /// if the actions module returned an empty decl for it).
+ virtual void PopParsingDeclaration(ParsingDeclStackState S, DeclPtrTy D) {
+ }
+
/// ConvertDeclToDeclGroup - If the parser has one decl in a context where it
/// needs a decl group, it calls this to convert between the two
/// representations.
@@ -236,30 +253,36 @@ public:
virtual bool isCurrentClassName(const IdentifierInfo &II, Scope *S,
const CXXScopeSpec *SS = 0) = 0;
- /// \brief Determine whether the given identifier refers to the name of a
+ /// \brief Determine whether the given name refers to a template.
+ ///
+ /// This callback is used by the parser after it has seen a '<' to determine
+ /// whether the given name refers to a template and, if so, what kind of
/// template.
///
- /// \param S the scope in which name lookup occurs
+ /// \param S the scope in which the name occurs.
///
- /// \param II the identifier that we are querying to determine whether it
- /// is a template.
+ /// \param SS the C++ nested-name-specifier that precedes the template name,
+ /// if any.
///
- /// \param IdLoc the source location of the identifier
+ /// \param Name the name that we are querying to determine whether it is
+ /// a template.
///
- /// \param SS the C++ scope specifier that precedes the template name, if
- /// any.
+ /// \param ObjectType if we are determining whether the given name is a
+ /// template name in the context of a member access expression (e.g.,
+ /// \c p->X<int>), this is the type of the object referred to by the
+ /// member access (e.g., \c p).
///
/// \param EnteringContext whether we are potentially entering the context
- /// referred to by the scope specifier \p SS
+ /// referred to by the nested-name-specifier \p SS, which allows semantic
+ /// analysis to look into uninstantiated templates.
///
/// \param Template if the name does refer to a template, the declaration
/// of the template that the name refers to.
///
/// \returns the kind of template that this name refers to.
virtual TemplateNameKind isTemplateName(Scope *S,
- const IdentifierInfo &II,
- SourceLocation IdLoc,
- const CXXScopeSpec *SS,
+ const CXXScopeSpec &SS,
+ UnqualifiedId &Name,
TypeTy *ObjectType,
bool EnteringContext,
TemplateTy &Template) = 0;
@@ -854,47 +877,33 @@ public:
virtual SourceRange getExprRange(ExprTy *E) const {
return SourceRange();
}
-
- /// ActOnIdentifierExpr - Parse an identifier in expression context.
- /// 'HasTrailingLParen' indicates whether or not the identifier has a '('
- /// token immediately after it.
- /// An optional CXXScopeSpec can be passed to indicate the C++ scope (class or
- /// namespace) that the identifier must be a member of.
- /// i.e. for "foo::bar", 'II' will be "bar" and 'SS' will be "foo::".
- virtual OwningExprResult ActOnIdentifierExpr(Scope *S, SourceLocation Loc,
- IdentifierInfo &II,
- bool HasTrailingLParen,
- const CXXScopeSpec *SS = 0,
- bool isAddressOfOperand = false){
- return ExprEmpty();
- }
-
- /// ActOnOperatorFunctionIdExpr - Parse a C++ overloaded operator
- /// name (e.g., @c operator+ ) as an expression. This is very
- /// similar to ActOnIdentifierExpr, except that instead of providing
- /// an identifier the parser provides the kind of overloaded
- /// operator that was parsed.
- virtual OwningExprResult ActOnCXXOperatorFunctionIdExpr(
- Scope *S, SourceLocation OperatorLoc,
- OverloadedOperatorKind Op,
- bool HasTrailingLParen, const CXXScopeSpec &SS,
- bool isAddressOfOperand = false) {
- return ExprEmpty();
- }
-
- /// ActOnCXXConversionFunctionExpr - Parse a C++ conversion function
- /// name (e.g., @c operator void const *) as an expression. This is
- /// very similar to ActOnIdentifierExpr, except that instead of
- /// providing an identifier the parser provides the type of the
- /// conversion function.
- virtual OwningExprResult ActOnCXXConversionFunctionExpr(
- Scope *S, SourceLocation OperatorLoc,
- TypeTy *Type, bool HasTrailingLParen,
- const CXXScopeSpec &SS,
- bool isAddressOfOperand = false) {
+
+ /// \brief Parsed an id-expression (C++) or identifier (C) in expression
+ /// context, e.g., the expression "x" that refers to a variable named "x".
+ ///
+ /// \param S the scope in which this id-expression or identifier occurs.
+ ///
+ /// \param SS the C++ nested-name-specifier that qualifies the name of the
+ /// value, e.g., "std::" in "std::sort".
+ ///
+ /// \param Name the name to which the id-expression refers. In C, this will
+ /// always be an identifier. In C++, it may also be an overloaded operator,
+ /// destructor name (if there is a nested-name-specifier), or template-id.
+ ///
+ /// \param HasTrailingLParen whether the next token following the
+ /// id-expression or identifier is a left parentheses ('(').
+ ///
+ /// \param IsAddressOfOperand whether the token that precedes this
+ /// id-expression or identifier was an ampersand ('&'), indicating that
+ /// we will be taking the address of this expression.
+ virtual OwningExprResult ActOnIdExpression(Scope *S,
+ const CXXScopeSpec &SS,
+ UnqualifiedId &Name,
+ bool HasTrailingLParen,
+ bool IsAddressOfOperand) {
return ExprEmpty();
}
-
+
virtual OwningExprResult ActOnPredefinedExpr(SourceLocation Loc,
tok::TokenKind Kind) {
return ExprEmpty();
@@ -936,16 +945,42 @@ public:
SourceLocation RLoc) {
return ExprEmpty();
}
- virtual OwningExprResult ActOnMemberReferenceExpr(Scope *S, ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- SourceLocation MemberLoc,
- IdentifierInfo &Member,
- DeclPtrTy ObjCImpDecl,
- const CXXScopeSpec *SS = 0) {
+
+ /// \brief Parsed a member access expresion (C99 6.5.2.3, C++ [expr.ref])
+ /// of the form \c x.m or \c p->m.
+ ///
+ /// \param S the scope in which the member access expression occurs.
+ ///
+ /// \param Base the class or pointer to class into which this member
+ /// access expression refers, e.g., \c x in \c x.m.
+ ///
+ /// \param OpLoc the location of the "." or "->" operator.
+ ///
+ /// \param OpKind the kind of member access operator, which will be either
+ /// tok::arrow ("->") or tok::period (".").
+ ///
+ /// \param SS in C++, the nested-name-specifier that precedes the member
+ /// name, if any.
+ ///
+ /// \param Member the name of the member that we are referring to. In C,
+ /// this will always store an identifier; in C++, we may also have operator
+ /// names, conversion function names, destructors, and template names.
+ ///
+ /// \param ObjCImpDecl the Objective-C implementation declaration.
+ /// FIXME: Do we really need this?
+ ///
+ /// \param HasTrailingLParen whether this member name is immediately followed
+ /// by a left parentheses ('(').
+ virtual OwningExprResult ActOnMemberAccessExpr(Scope *S, ExprArg Base,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ const CXXScopeSpec &SS,
+ UnqualifiedId &Member,
+ DeclPtrTy ObjCImpDecl,
+ bool HasTrailingLParen) {
return ExprEmpty();
}
-
+
/// ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
/// This provides the location of the left/right parens and a list of comma
/// locations. There are guaranteed to be one fewer commas than arguments,
@@ -1245,8 +1280,7 @@ public:
}
/// ActOnFriendTypeDecl - Parsed a friend type declaration.
- virtual DeclPtrTy ActOnFriendTypeDecl(Scope *S,
- const DeclSpec &DS,
+ virtual DeclPtrTy ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
MultiTemplateParamsArg TParams) {
return DeclPtrTy();
}
@@ -1376,123 +1410,6 @@ public:
return ExprEmpty();
}
- /// ActOnDestructorReferenceExpr - Parsed a destructor reference, for example:
- ///
- /// t->~T();
- virtual OwningExprResult
- ActOnDestructorReferenceExpr(Scope *S, ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- SourceLocation ClassNameLoc,
- IdentifierInfo *ClassName,
- const CXXScopeSpec &SS,
- bool HasTrailingLParen) {
- return ExprEmpty();
- }
-
- /// \brief Parsed a C++ destructor reference that refers to a type.
- ///
- /// This action is used when parsing a destructor reference that uses a
- /// template-id, e.g.,
- ///
- /// \code
- /// t->~Tmpl<T1, T2>
- /// \endcode
- ///
- /// \param S the scope in which the destructor reference occurs.
- /// \param Base the base object of the destructor reference expression.
- /// \param OpLoc the location of the operator ('.' or '->').
- /// \param OpKind the kind of the destructor reference operator ('.' or '->').
- /// \param TypeRange the source range that covers the destructor type.
- /// \param Type the type that is being destroyed.
- /// \param SS the scope specifier that precedes the destructor name.
- /// \param HasTrailingLParen whether the destructor name is followed by a '('.
- virtual OwningExprResult
- ActOnDestructorReferenceExpr(Scope *S, ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- SourceRange TypeRange,
- TypeTy *Type,
- const CXXScopeSpec &SS,
- bool HasTrailingLParen) {
- return ExprEmpty();
- }
-
- /// ActOnOverloadedOperatorReferenceExpr - Parsed an overloaded operator
- /// reference, for example:
- ///
- /// t.operator++();
- virtual OwningExprResult
- ActOnOverloadedOperatorReferenceExpr(Scope *S, ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- SourceLocation ClassNameLoc,
- OverloadedOperatorKind OverOpKind,
- const CXXScopeSpec *SS = 0) {
- return ExprEmpty();
- }
-
- /// ActOnConversionOperatorReferenceExpr - Parsed an overloaded conversion
- /// function reference, for example:
- ///
- /// t.operator int();
- virtual OwningExprResult
- ActOnConversionOperatorReferenceExpr(Scope *S, ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- SourceLocation ClassNameLoc,
- TypeTy *Ty,
- const CXXScopeSpec *SS = 0) {
- return ExprEmpty();
- }
-
- /// \brief Parsed a reference to a member template-id.
- ///
- /// This callback will occur instead of ActOnMemberReferenceExpr() when the
- /// member in question is a template for which the code provides an
- /// explicitly-specified template argument list, e.g.,
- ///
- /// \code
- /// x.f<int>()
- /// \endcode
- ///
- /// \param S the scope in which the member reference expression occurs
- ///
- /// \param Base the expression to the left of the "." or "->".
- ///
- /// \param OpLoc the location of the "." or "->".
- ///
- /// \param OpKind the kind of operator, which will be "." or "->".
- ///
- /// \param SS the scope specifier that precedes the template-id in, e.g.,
- /// \c x.Base::f<int>().
- ///
- /// \param Template the declaration of the template that is being referenced.
- ///
- /// \param TemplateNameLoc the location of the template name referred to by
- /// \p Template.
- ///
- /// \param LAngleLoc the location of the left angle bracket ('<')
- ///
- /// \param TemplateArgs the (possibly-empty) template argument list provided
- /// as part of the member reference.
- ///
- /// \param RAngleLoc the location of the right angle bracket ('>')
- virtual OwningExprResult
- ActOnMemberTemplateIdReferenceExpr(Scope *S, ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- const CXXScopeSpec &SS,
- // FIXME: "template" keyword?
- TemplateTy Template,
- SourceLocation TemplateNameLoc,
- SourceLocation LAngleLoc,
- ASTTemplateArgsPtr TemplateArgs,
- SourceLocation *TemplateArgLocs,
- SourceLocation RAngleLoc) {
- return ExprEmpty();
- }
-
/// ActOnFinishFullExpr - Called whenever a full expression has been parsed.
/// (C++ [intro.execution]p12).
virtual OwningExprResult ActOnFinishFullExpr(ExprArg Expr) {
@@ -1712,40 +1629,6 @@ public:
return TypeResult();
}
- /// \brief Form a reference to a template-id (that will refer to a function)
- /// from a template and a list of template arguments.
- ///
- /// This action forms an expression that references the given template-id,
- /// possibly checking well-formedness of the template arguments. It does not
- /// imply the declaration of any entity.
- ///
- /// \param SS The scope specifier that may precede the template name.
- ///
- /// \param Template A template whose specialization results in a
- /// function or a dependent template.
- ///
- /// \param TemplateNameLoc The location of the template name.
- ///
- /// \param LAngleLoc The location of the left angle bracket ('<') that starts
- /// the template argument list.
- ///
- /// \param TemplateArgs The template arguments in the template argument list,
- /// which may be empty.
- ///
- /// \param TemplateArgLocs The locations of the template arguments.
- ///
- /// \param RAngleLoc The location of the right angle bracket ('>') that
- /// closes the template argument list.
- virtual OwningExprResult ActOnTemplateIdExpr(const CXXScopeSpec &SS,
- TemplateTy Template,
- SourceLocation TemplateNameLoc,
- SourceLocation LAngleLoc,
- ASTTemplateArgsPtr TemplateArgs,
- SourceLocation *TemplateArgLocs,
- SourceLocation RAngleLoc) {
- return ExprError();
- }
-
/// \brief Form a dependent template name.
///
/// This action forms a dependent template name given the template
@@ -1756,22 +1639,19 @@ public:
///
/// \param TemplateKWLoc the location of the "template" keyword (if any).
///
- /// \param Name the name of the template (an identifier)
- ///
- /// \param NameLoc the location of the identifier
- ///
/// \param SS the nested-name-specifier that precedes the "template" keyword
- /// or the template name. FIXME: If the dependent template name occurs in
+ /// or the template name. If the dependent template name occurs in
/// a member access expression, e.g., "x.template f<T>", this
/// nested-name-specifier will be empty.
///
+ /// \param Name the name of the template.
+ ///
/// \param ObjectType if this dependent template name occurs in the
/// context of a member access expression, the type of the object being
/// accessed.
virtual TemplateTy ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
- const IdentifierInfo &Name,
- SourceLocation NameLoc,
const CXXScopeSpec &SS,
+ UnqualifiedId &Name,
TypeTy *ObjectType) {
return TemplateTy();
}
@@ -2473,13 +2353,12 @@ public:
const CXXScopeSpec *SS);
virtual TemplateNameKind isTemplateName(Scope *S,
- const IdentifierInfo &II,
- SourceLocation IdLoc,
- const CXXScopeSpec *SS,
+ const CXXScopeSpec &SS,
+ UnqualifiedId &Name,
TypeTy *ObjectType,
bool EnteringContext,
TemplateTy &Template);
-
+
/// ActOnDeclarator - If this is a typedef declarator, we modify the
/// IdentifierInfo::FETokenInfo field to keep track of this fact, until S is
/// popped.
diff --git a/include/clang/Parse/DeclSpec.h b/include/clang/Parse/DeclSpec.h
index 51970f1867d9..dccb8bcfeb9a 100644
--- a/include/clang/Parse/DeclSpec.h
+++ b/include/clang/Parse/DeclSpec.h
@@ -390,17 +390,20 @@ public:
};
- ObjCDeclSpec() : objcDeclQualifier(DQ_None), PropertyAttributes(DQ_PR_noattr),
- GetterName(0), SetterName(0) { }
+ ObjCDeclSpec()
+ : objcDeclQualifier(DQ_None), PropertyAttributes(DQ_PR_noattr),
+ GetterName(0), SetterName(0) { }
ObjCDeclQualifier getObjCDeclQualifier() const { return objcDeclQualifier; }
- void setObjCDeclQualifier(ObjCDeclQualifier DQVal)
- { objcDeclQualifier = (ObjCDeclQualifier) (objcDeclQualifier | DQVal); }
+ void setObjCDeclQualifier(ObjCDeclQualifier DQVal) {
+ objcDeclQualifier = (ObjCDeclQualifier) (objcDeclQualifier | DQVal);
+ }
- ObjCPropertyAttributeKind getPropertyAttributes() const
- { return ObjCPropertyAttributeKind(PropertyAttributes); }
+ ObjCPropertyAttributeKind getPropertyAttributes() const {
+ return ObjCPropertyAttributeKind(PropertyAttributes);
+ }
void setPropertyAttributes(ObjCPropertyAttributeKind PRVal) {
PropertyAttributes =
- (ObjCPropertyAttributeKind) (PropertyAttributes | PRVal);
+ (ObjCPropertyAttributeKind)(PropertyAttributes | PRVal);
}
const IdentifierInfo *getGetterName() const { return GetterName; }
@@ -456,6 +459,193 @@ public:
}
};
+/// \brief Represents a C++ unqualified-id that has been parsed.
+class UnqualifiedId {
+private:
+ const UnqualifiedId &operator=(const UnqualifiedId &); // DO NOT IMPLEMENT
+
+public:
+ /// \brief Describes the kind of unqualified-id parsed.
+ enum IdKind {
+ /// \brief An identifier.
+ IK_Identifier,
+ /// \brief An overloaded operator name, e.g., operator+.
+ IK_OperatorFunctionId,
+ /// \brief A conversion function name, e.g., operator int.
+ IK_ConversionFunctionId,
+ /// \brief A constructor name.
+ IK_ConstructorName,
+ /// \brief A destructor name.
+ IK_DestructorName,
+ /// \brief A template-id, e.g., f<int>.
+ IK_TemplateId
+ } Kind;
+
+ /// \brief Anonymous union that holds extra data associated with the
+ /// parsed unqualified-id.
+ union {
+ /// \brief When Kind == IK_Identifier, the parsed identifier.
+ IdentifierInfo *Identifier;
+
+ /// \brief When Kind == IK_OperatorFunctionId, the overloaded operator
+ /// that we parsed.
+ struct {
+ /// \brief The kind of overloaded operator.
+ OverloadedOperatorKind Operator;
+
+ /// \brief The source locations of the individual tokens that name
+ /// the operator, e.g., the "new", "[", and "]" tokens in
+ /// operator new [].
+ ///
+ /// Different operators have different numbers of tokens in their name,
+ /// up to three. Any remaining source locations in this array will be
+ /// set to an invalid value for operators with fewer than three tokens.
+ unsigned SymbolLocations[3];
+ } OperatorFunctionId;
+
+ /// \brief When Kind == IK_ConversionFunctionId, the type that the
+ /// conversion function names.
+ ActionBase::TypeTy *ConversionFunctionId;
+
+ /// \brief When Kind == IK_ConstructorName, the class-name of the type
+ /// whose constructor is being referenced.
+ ActionBase::TypeTy *ConstructorName;
+
+ /// \brief When Kind == IK_DestructorName, the type referred to by the
+ /// class-name.
+ ActionBase::TypeTy *DestructorName;
+
+ /// \brief When Kind == IK_TemplateId, the template-id annotation that
+ /// contains the template name and template arguments.
+ TemplateIdAnnotation *TemplateId;
+ };
+
+ /// \brief The location of the first token that describes this unqualified-id,
+ /// which will be the location of the identifier, "operator" keyword,
+ /// tilde (for a destructor), or the template name of a template-id.
+ SourceLocation StartLocation;
+
+ /// \brief The location of the last token that describes this unqualified-id.
+ SourceLocation EndLocation;
+
+ UnqualifiedId() : Kind(IK_Identifier), Identifier(0) { }
+
+ /// \brief Do not use this copy constructor. It is temporary, and only
+ /// exists because we are holding FieldDeclarators in a SmallVector when we
+ /// don't actually need them.
+ ///
+ /// FIXME: Kill this copy constructor.
+ UnqualifiedId(const UnqualifiedId &Other)
+ : Kind(IK_Identifier), Identifier(Other.Identifier),
+ StartLocation(Other.StartLocation), EndLocation(Other.EndLocation) {
+ assert(Other.Kind == IK_Identifier && "Cannot copy non-identifiers");
+ }
+
+ /// \brief Destroy this unqualified-id.
+ ~UnqualifiedId() { clear(); }
+
+ /// \brief Clear out this unqualified-id, setting it to default (invalid)
+ /// state.
+ void clear();
+
+ /// \brief Determine whether this unqualified-id refers to a valid name.
+ bool isValid() const { return StartLocation.isValid(); }
+
+ /// \brief Determine whether this unqualified-id refers to an invalid name.
+ bool isInvalid() const { return !isValid(); }
+
+ /// \brief Determine what kind of name we have.
+ IdKind getKind() const { return Kind; }
+
+ /// \brief Specify that this unqualified-id was parsed as an identifier.
+ ///
+ /// \param Id the parsed identifier.
+ /// \param IdLoc the location of the parsed identifier.
+ void setIdentifier(const IdentifierInfo *Id, SourceLocation IdLoc) {
+ Kind = IK_Identifier;
+ Identifier = const_cast<IdentifierInfo *>(Id);
+ StartLocation = EndLocation = IdLoc;
+ }
+
+ /// \brief Specify that this unqualified-id was parsed as an
+ /// operator-function-id.
+ ///
+ /// \param OperatorLoc the location of the 'operator' keyword.
+ ///
+ /// \param Op the overloaded operator.
+ ///
+ /// \param SymbolLocations the locations of the individual operator symbols
+ /// in the operator.
+ void setOperatorFunctionId(SourceLocation OperatorLoc,
+ OverloadedOperatorKind Op,
+ SourceLocation SymbolLocations[3]);
+
+ /// \brief Specify that this unqualified-id was parsed as a
+ /// conversion-function-id.
+ ///
+ /// \param OperatorLoc the location of the 'operator' keyword.
+ ///
+ /// \param Ty the type to which this conversion function is converting.
+ ///
+ /// \param EndLoc the location of the last token that makes up the type name.
+ void setConversionFunctionId(SourceLocation OperatorLoc,
+ ActionBase::TypeTy *Ty,
+ SourceLocation EndLoc) {
+ Kind = IK_ConversionFunctionId;
+ StartLocation = OperatorLoc;
+ EndLocation = EndLoc;
+ ConversionFunctionId = Ty;
+ }
+
+ /// \brief Specify that this unqualified-id was parsed as a constructor name.
+ ///
+ /// \param ClassType the class type referred to by the constructor name.
+ ///
+ /// \param ClassNameLoc the location of the class name.
+ ///
+ /// \param EndLoc the location of the last token that makes up the type name.
+ void setConstructorName(ActionBase::TypeTy *ClassType,
+ SourceLocation ClassNameLoc,
+ SourceLocation EndLoc) {
+ Kind = IK_ConstructorName;
+ StartLocation = ClassNameLoc;
+ EndLocation = EndLoc;
+ ConstructorName = ClassType;
+ }
+
+ /// \brief Specify that this unqualified-id was parsed as a destructor name.
+ ///
+ /// \param TildeLoc the location of the '~' that introduces the destructor
+ /// name.
+ ///
+ /// \param ClassType the name of the class referred to by the destructor name.
+ void setDestructorName(SourceLocation TildeLoc, ActionBase::TypeTy *ClassType,
+ SourceLocation EndLoc) {
+ Kind = IK_DestructorName;
+ StartLocation = TildeLoc;
+ EndLocation = EndLoc;
+ DestructorName = ClassType;
+ }
+
+ /// \brief Specify that this unqualified-id was parsed as a template-id.
+ ///
+ /// \param TemplateId the template-id annotation that describes the parsed
+ /// template-id. This UnqualifiedId instance will take ownership of the
+ /// \p TemplateId and will free it on destruction.
+ void setTemplateId(TemplateIdAnnotation *TemplateId) {
+ assert(TemplateId && "NULL template-id annotation?");
+ Kind = IK_TemplateId;
+ this->TemplateId = TemplateId;
+ StartLocation = TemplateId->TemplateNameLoc;
+ EndLocation = TemplateId->RAngleLoc;
+ }
+
+ /// \brief Return the source range that covers this unqualified-id.
+ SourceRange getSourceRange() const {
+ return SourceRange(StartLocation, EndLocation);
+ }
+};
+
/// CachedTokens - A set of tokens that has been cached for later
/// parsing.
typedef llvm::SmallVector<Token, 4> CachedTokens;
@@ -790,33 +980,16 @@ public:
BlockLiteralContext // Block literal declarator.
};
- /// DeclaratorKind - The kind of declarator this represents.
- enum DeclaratorKind {
- DK_Abstract, // An abstract declarator (has no identifier)
- DK_Normal, // A normal declarator (has an identifier).
- DK_Constructor, // A C++ constructor (identifier is the class name)
- DK_Destructor, // A C++ destructor (identifier is ~class name)
- DK_Operator, // A C++ overloaded operator name
- DK_Conversion, // A C++ conversion function (identifier is
- // "operator " then the type name)
- DK_TemplateId // A C++ template-id naming a function template
- // specialization.
- };
-
private:
const DeclSpec &DS;
CXXScopeSpec SS;
- IdentifierInfo *Identifier;
- SourceLocation IdentifierLoc;
+ UnqualifiedId Name;
SourceRange Range;
/// Context - Where we are parsing this declarator.
///
TheContext Context;
- /// Kind - What kind of declarator this is.
- DeclaratorKind Kind;
-
/// DeclTypeInfo - This holds each type that the declarator includes as it is
/// parsed. This is pushed from the identifier out, which means that element
/// #0 will be the most closely bound to the identifier, and
@@ -835,21 +1008,6 @@ private:
/// AsmLabel - The asm label, if specified.
ActionBase::ExprTy *AsmLabel;
- union {
- // When Kind is DK_Constructor, DK_Destructor, or DK_Conversion, the
- // type associated with the constructor, destructor, or conversion
- // operator.
- ActionBase::TypeTy *Type;
-
- /// When Kind is DK_Operator, this is the actual overloaded
- /// operator that this declarator names.
- OverloadedOperatorKind OperatorKind;
-
- /// When Kind is DK_TemplateId, this is the template-id annotation that
- /// contains the template and its template arguments.
- TemplateIdAnnotation *TemplateId;
- };
-
/// InlineParams - This is a local array used for the first function decl
/// chunk to avoid going to the heap for the common case when we have one
/// function chunk in the declarator.
@@ -863,10 +1021,9 @@ private:
public:
Declarator(const DeclSpec &ds, TheContext C)
- : DS(ds), Identifier(0), Range(ds.getSourceRange()), Context(C),
- Kind(DK_Abstract),
+ : DS(ds), Range(ds.getSourceRange()), Context(C),
InvalidType(DS.getTypeSpecType() == DeclSpec::TST_error),
- GroupingParens(false), AttrList(0), AsmLabel(0), Type(0),
+ GroupingParens(false), AttrList(0), AsmLabel(0),
InlineParamsUsed(false), Extension(false) {
}
@@ -890,8 +1047,10 @@ public:
const CXXScopeSpec &getCXXScopeSpec() const { return SS; }
CXXScopeSpec &getCXXScopeSpec() { return SS; }
+ /// \brief Retrieve the name specified by this declarator.
+ UnqualifiedId &getName() { return Name; }
+
TheContext getContext() const { return Context; }
- DeclaratorKind getKind() const { return Kind; }
/// getSourceRange - Get the source range that spans this declarator.
const SourceRange &getSourceRange() const { return Range; }
@@ -922,22 +1081,15 @@ public:
/// clear - Reset the contents of this Declarator.
void clear() {
SS.clear();
- Identifier = 0;
- IdentifierLoc = SourceLocation();
+ Name.clear();
Range = DS.getSourceRange();
- if (Kind == DK_TemplateId)
- TemplateId->Destroy();
-
- Kind = DK_Abstract;
-
for (unsigned i = 0, e = DeclTypeInfo.size(); i != e; ++i)
DeclTypeInfo[i].destroy();
DeclTypeInfo.clear();
delete AttrList;
AttrList = 0;
AsmLabel = 0;
- Type = 0;
InlineParamsUsed = false;
}
@@ -968,84 +1120,28 @@ public:
/// isPastIdentifier - Return true if we have parsed beyond the point where
/// the
- bool isPastIdentifier() const { return IdentifierLoc.isValid(); }
+ bool isPastIdentifier() const { return Name.isValid(); }
/// hasName - Whether this declarator has a name, which might be an
/// identifier (accessible via getIdentifier()) or some kind of
/// special C++ name (constructor, destructor, etc.).
- bool hasName() const { return getKind() != DK_Abstract; }
-
- IdentifierInfo *getIdentifier() const { return Identifier; }
- SourceLocation getIdentifierLoc() const { return IdentifierLoc; }
-
- void SetIdentifier(IdentifierInfo *ID, SourceLocation Loc) {
- Identifier = ID;
- IdentifierLoc = Loc;
- if (ID)
- Kind = DK_Normal;
- else
- Kind = DK_Abstract;
- SetRangeEnd(Loc);
- }
-
- /// setConstructor - Set this declarator to be a C++ constructor
- /// declarator. Also extends the range.
- void setConstructor(ActionBase::TypeTy *Ty, SourceLocation Loc) {
- IdentifierLoc = Loc;
- Kind = DK_Constructor;
- Type = Ty;
- SetRangeEnd(Loc);
- }
-
- /// setDestructor - Set this declarator to be a C++ destructor
- /// declarator. Also extends the range to End, which should be the identifier
- /// token.
- void setDestructor(ActionBase::TypeTy *Ty, SourceLocation Loc,
- SourceLocation EndLoc) {
- IdentifierLoc = Loc;
- Kind = DK_Destructor;
- Type = Ty;
- if (!EndLoc.isInvalid())
- SetRangeEnd(EndLoc);
- }
-
- /// setConversionFunction - Set this declarator to be a C++
- /// conversion function declarator (e.g., @c operator int const *).
- /// Also extends the range to EndLoc, which should be the last token of the
- /// type name.
- void setConversionFunction(ActionBase::TypeTy *Ty, SourceLocation Loc,
- SourceLocation EndLoc) {
- Identifier = 0;
- IdentifierLoc = Loc;
- Kind = DK_Conversion;
- Type = Ty;
- if (!EndLoc.isInvalid())
- SetRangeEnd(EndLoc);
+ bool hasName() const {
+ return Name.getKind() != UnqualifiedId::IK_Identifier || Name.Identifier;
}
- /// setOverloadedOperator - Set this declaration to be a C++
- /// overloaded operator declarator (e.g., @c operator+).
- /// Also extends the range to EndLoc, which should be the last token of the
- /// operator.
- void setOverloadedOperator(OverloadedOperatorKind Op, SourceLocation Loc,
- SourceLocation EndLoc) {
- IdentifierLoc = Loc;
- Kind = DK_Operator;
- OperatorKind = Op;
- if (!EndLoc.isInvalid())
- SetRangeEnd(EndLoc);
+ IdentifierInfo *getIdentifier() const {
+ if (Name.getKind() == UnqualifiedId::IK_Identifier)
+ return Name.Identifier;
+
+ return 0;
}
+ SourceLocation getIdentifierLoc() const { return Name.StartLocation; }
- /// \brief Set this declaration to be a C++ template-id, which includes the
- /// template (or set of function templates) along with template arguments.
- void setTemplateId(TemplateIdAnnotation *TemplateId) {
- assert(TemplateId && "NULL template-id provided to declarator?");
- IdentifierLoc = TemplateId->TemplateNameLoc;
- Kind = DK_TemplateId;
- SetRangeEnd(TemplateId->RAngleLoc);
- this->TemplateId = TemplateId;
+ /// \brief Set the name of this declarator to be the given identifier.
+ void SetIdentifier(IdentifierInfo *Id, SourceLocation IdLoc) {
+ Name.setIdentifier(Id, IdLoc);
}
-
+
/// AddTypeInfo - Add a chunk to this declarator. Also extend the range to
/// EndLoc, which should be the last token of the chunk.
void AddTypeInfo(const DeclaratorChunk &TI, SourceLocation EndLoc) {
@@ -1069,6 +1165,13 @@ public:
return DeclTypeInfo[i];
}
+ void DropFirstTypeObject()
+ {
+ assert(!DeclTypeInfo.empty() && "No type chunks to drop.");
+ DeclTypeInfo.front().destroy();
+ DeclTypeInfo.erase(DeclTypeInfo.begin());
+ }
+
/// isFunctionDeclarator - Once this declarator is fully parsed and formed,
/// this method returns true if the identifier is a function declarator.
bool isFunctionDeclarator() const {
@@ -1108,22 +1211,6 @@ public:
void setExtension(bool Val = true) { Extension = Val; }
bool getExtension() const { return Extension; }
- ActionBase::TypeTy *getDeclaratorIdType() const {
- assert((Kind == DK_Constructor || Kind == DK_Destructor ||
- Kind == DK_Conversion) && "Declarator kind does not have a type");
- return Type;
- }
-
- OverloadedOperatorKind getOverloadedOperator() const {
- assert(Kind == DK_Operator && "Declarator is not an overloaded operator");
- return OperatorKind;
- }
-
- TemplateIdAnnotation *getTemplateId() {
- assert(Kind == DK_TemplateId && "Declarator is not a template-id");
- return TemplateId;
- }
-
void setInvalidType(bool Val = true) { InvalidType = Val; }
bool isInvalidType() const {
return InvalidType || DS.getTypeSpecType() == DeclSpec::TST_error;
@@ -1142,7 +1229,7 @@ struct FieldDeclarator {
BitfieldSize = 0;
}
};
-
+
} // end namespace clang
#endif
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index 9cb4677f6637..f34d469d9823 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -571,6 +571,99 @@ private:
return *ClassStack.top();
}
+ /// \brief RAII object used to inform the actions that we're
+ /// currently parsing a declaration. This is active when parsing a
+ /// variable's initializer, but not when parsing the body of a
+ /// class or function definition.
+ class ParsingDeclRAIIObject {
+ Action &Actions;
+ Action::ParsingDeclStackState State;
+ bool Popped;
+
+ public:
+ ParsingDeclRAIIObject(Parser &P) : Actions(P.Actions) {
+ push();
+ }
+
+ ~ParsingDeclRAIIObject() {
+ abort();
+ }
+
+ /// Resets the RAII object for a new declaration.
+ void reset() {
+ abort();
+ push();
+ }
+
+ /// Signals that the context was completed without an appropriate
+ /// declaration being parsed.
+ void abort() {
+ pop(DeclPtrTy());
+ }
+
+ void complete(DeclPtrTy D) {
+ assert(!Popped && "ParsingDeclaration has already been popped!");
+ pop(D);
+ }
+
+ private:
+ void push() {
+ State = Actions.PushParsingDeclaration();
+ Popped = false;
+ }
+
+ void pop(DeclPtrTy D) {
+ if (!Popped) {
+ Actions.PopParsingDeclaration(State, D);
+ Popped = true;
+ }
+ }
+ };
+
+ /// A class for parsing a DeclSpec.
+ class ParsingDeclSpec : public DeclSpec {
+ ParsingDeclRAIIObject ParsingRAII;
+
+ public:
+ ParsingDeclSpec(Parser &P) : ParsingRAII(P) {
+ }
+
+ void complete(DeclPtrTy D) {
+ ParsingRAII.complete(D);
+ }
+
+ void abort() {
+ ParsingRAII.abort();
+ }
+ };
+
+ /// A class for parsing a declarator.
+ class ParsingDeclarator : public Declarator {
+ ParsingDeclRAIIObject ParsingRAII;
+
+ public:
+ ParsingDeclarator(Parser &P, const ParsingDeclSpec &DS, TheContext C)
+ : Declarator(DS, C), ParsingRAII(P) {
+ }
+
+ const ParsingDeclSpec &getDeclSpec() const {
+ return static_cast<const ParsingDeclSpec&>(Declarator::getDeclSpec());
+ }
+
+ ParsingDeclSpec &getMutableDeclSpec() const {
+ return const_cast<ParsingDeclSpec&>(getDeclSpec());
+ }
+
+ void clear() {
+ Declarator::clear();
+ ParsingRAII.reset();
+ }
+
+ void complete(DeclPtrTy D) {
+ ParsingRAII.complete(D);
+ }
+ };
+
/// \brief RAII object used to
class ParsingClassDefinition {
Parser &P;
@@ -603,14 +696,17 @@ private:
: Kind(NonTemplate), TemplateParams(0), TemplateLoc() { }
ParsedTemplateInfo(TemplateParameterLists *TemplateParams,
- bool isSpecialization)
+ bool isSpecialization,
+ bool lastParameterListWasEmpty = false)
: Kind(isSpecialization? ExplicitSpecialization : Template),
- TemplateParams(TemplateParams) { }
+ TemplateParams(TemplateParams),
+ LastParameterListWasEmpty(lastParameterListWasEmpty) { }
explicit ParsedTemplateInfo(SourceLocation ExternLoc,
SourceLocation TemplateLoc)
: Kind(ExplicitInstantiation), TemplateParams(0),
- ExternLoc(ExternLoc), TemplateLoc(TemplateLoc) { }
+ ExternLoc(ExternLoc), TemplateLoc(TemplateLoc),
+ LastParameterListWasEmpty(false){ }
/// \brief The kind of template we are parsing.
enum {
@@ -635,6 +731,9 @@ private:
/// \brief The location of the 'template' keyword, for an explicit
/// instantiation.
SourceLocation TemplateLoc;
+
+ /// \brief Whether the last template parameter list was empty.
+ bool LastParameterListWasEmpty;
};
void PushParsingClass(DeclPtrTy TagOrTemplate, bool TopLevelClass);
@@ -658,7 +757,7 @@ private:
DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(
AccessSpecifier AS = AS_none);
- DeclPtrTy ParseFunctionDefinition(Declarator &D,
+ DeclPtrTy ParseFunctionDefinition(ParsingDeclarator &D,
const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo());
void ParseKNRParamDeclarations(Declarator &D);
// EndLoc, if non-NULL, is filled with the location of the last token of
@@ -944,11 +1043,12 @@ private:
DeclGroupPtrTy ParseDeclaration(unsigned Context, SourceLocation &DeclEnd);
DeclGroupPtrTy ParseSimpleDeclaration(unsigned Context,
- SourceLocation &DeclEnd,
- bool RequireSemi = true);
+ SourceLocation &DeclEnd);
+ DeclGroupPtrTy ParseDeclGroup(ParsingDeclSpec &DS, unsigned Context,
+ bool AllowFunctionDefinitions,
+ SourceLocation *DeclEnd = 0);
DeclPtrTy ParseDeclarationAfterDeclarator(Declarator &D,
const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo());
- DeclGroupPtrTy ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D);
DeclPtrTy ParseFunctionStatementBody(DeclPtrTy Decl);
DeclPtrTy ParseFunctionTryBlock(DeclPtrTy Decl);
@@ -973,8 +1073,16 @@ private:
void ParseEnumBody(SourceLocation StartLoc, DeclPtrTy TagDecl);
void ParseStructUnionBody(SourceLocation StartLoc, unsigned TagType,
DeclPtrTy TagDecl);
- void ParseStructDeclaration(DeclSpec &DS,
- llvm::SmallVectorImpl<FieldDeclarator> &Fields);
+
+ struct FieldCallback {
+ virtual DeclPtrTy invoke(FieldDeclarator &Field) = 0;
+ virtual ~FieldCallback() {}
+
+ private:
+ virtual void _anchor();
+ };
+
+ void ParseStructDeclaration(DeclSpec &DS, FieldCallback &Callback);
bool isDeclarationSpecifier();
bool isTypeSpecifierQualifier();
@@ -1197,6 +1305,21 @@ private:
BaseResult ParseBaseSpecifier(DeclPtrTy ClassDecl);
AccessSpecifier getAccessSpecifierIfPresent() const;
+ bool ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
+ IdentifierInfo *Name,
+ SourceLocation NameLoc,
+ bool EnteringContext,
+ TypeTy *ObjectType,
+ UnqualifiedId &Id);
+ bool ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
+ TypeTy *ObjectType,
+ UnqualifiedId &Result);
+ bool ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
+ bool AllowDestructorName,
+ bool AllowConstructorName,
+ 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
@@ -1247,6 +1370,7 @@ private:
bool AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
const CXXScopeSpec *SS,
+ UnqualifiedId &TemplateName,
SourceLocation TemplateKWLoc = SourceLocation(),
bool AllowTypeAnnotation = true);
void AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS = 0);
diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h
index d2f509df7b2c..5b3522c9eb49 100644
--- a/include/clang/Sema/CodeCompleteConsumer.h
+++ b/include/clang/Sema/CodeCompleteConsumer.h
@@ -26,6 +26,7 @@ namespace clang {
class FunctionDecl;
class FunctionType;
class FunctionTemplateDecl;
+class IdentifierInfo;
class NamedDecl;
class NestedNameSpecifier;
class Sema;
@@ -150,7 +151,8 @@ public:
/// \brief Describes the kind of result generated.
enum ResultKind {
RK_Declaration = 0, //< Refers to a declaration
- RK_Keyword //< Refers to a keyword or symbol.
+ RK_Keyword, //< Refers to a keyword or symbol.
+ RK_Macro //< Refers to a macro
};
/// \brief The kind of result stored here.
@@ -164,6 +166,9 @@ public:
/// \brief When Kind == RK_Keyword, the string representing the keyword
/// or symbol's spelling.
const char *Keyword;
+
+ /// \brief When Kind == RK_Macro, the identifier that refers to a macro.
+ IdentifierInfo *Macro;
};
/// \brief Describes how good this result is, with zero being the best
@@ -199,6 +204,12 @@ public:
QualifierIsInformative(0), StartsNestedNameSpecifier(false),
Qualifier(0) { }
+ /// \brief Build a result that refers to a macro.
+ Result(IdentifierInfo *Macro, unsigned Rank)
+ : Kind(RK_Macro), Macro(Macro), Rank(Rank), Hidden(false),
+ QualifierIsInformative(0), StartsNestedNameSpecifier(false),
+ Qualifier(0) { }
+
/// \brief Retrieve the declaration stored in this result.
NamedDecl *getDeclaration() const {
assert(Kind == RK_Declaration && "Not a declaration result");