aboutsummaryrefslogtreecommitdiff
path: root/include/clang
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang')
-rw-r--r--include/clang/AST/ASTConsumer.h14
-rw-r--r--include/clang/AST/ASTContext.h81
-rw-r--r--include/clang/AST/ASTImporter.h2
-rw-r--r--include/clang/AST/Attr.h607
-rw-r--r--include/clang/AST/CMakeLists.txt6
-rw-r--r--include/clang/AST/CanonicalType.h9
-rw-r--r--include/clang/AST/Decl.h238
-rw-r--r--include/clang/AST/DeclBase.h181
-rw-r--r--include/clang/AST/DeclCXX.h279
-rw-r--r--include/clang/AST/DeclContextInternals.h160
-rw-r--r--include/clang/AST/DeclFriend.h16
-rw-r--r--include/clang/AST/DeclGroup.h1
-rw-r--r--include/clang/AST/DeclObjC.h150
-rw-r--r--include/clang/AST/DeclTemplate.h679
-rw-r--r--include/clang/AST/DeclarationName.h147
-rw-r--r--include/clang/AST/Expr.h748
-rw-r--r--include/clang/AST/ExprCXX.h405
-rw-r--r--include/clang/AST/ExternalASTSource.h93
-rw-r--r--include/clang/AST/FullExpr.h1
-rw-r--r--include/clang/AST/Makefile8
-rw-r--r--include/clang/AST/NestedNameSpecifier.h2
-rw-r--r--include/clang/AST/OperationKinds.h158
-rw-r--r--include/clang/AST/RecursiveASTVisitor.h318
-rw-r--r--include/clang/AST/Redeclarable.h3
-rw-r--r--include/clang/AST/Stmt.h37
-rw-r--r--include/clang/AST/StmtCXX.h38
-rw-r--r--include/clang/AST/StmtVisitor.h107
-rw-r--r--include/clang/AST/Type.h143
-rw-r--r--include/clang/AST/TypeLoc.h4
-rw-r--r--include/clang/AST/TypeOrdering.h21
-rw-r--r--include/clang/Analysis/Analyses/FormatString.h595
-rw-r--r--include/clang/Analysis/Analyses/LiveVariables.h5
-rw-r--r--include/clang/Analysis/Analyses/PrintfFormatString.h445
-rw-r--r--include/clang/Analysis/Analyses/PseudoConstantAnalysis.h45
-rw-r--r--include/clang/Analysis/AnalysisContext.h53
-rw-r--r--include/clang/Analysis/CFG.h19
-rw-r--r--include/clang/Analysis/CFGStmtMap.h52
-rw-r--r--include/clang/Analysis/FlowSensitive/DataflowSolver.h17
-rw-r--r--include/clang/Analysis/ProgramPoint.h39
-rw-r--r--include/clang/Analysis/Visitors/CFGStmtVisitor.h4
-rw-r--r--include/clang/Basic/Attr.td90
-rw-r--r--include/clang/Basic/Builtins.def149
-rw-r--r--include/clang/Basic/Builtins.h5
-rw-r--r--include/clang/Basic/BuiltinsARM.def14
-rw-r--r--include/clang/Basic/BuiltinsX86.def221
-rw-r--r--include/clang/Basic/DeclNodes.td5
-rw-r--r--include/clang/Basic/Diagnostic.h71
-rw-r--r--include/clang/Basic/DiagnosticCommonKinds.td3
-rw-r--r--include/clang/Basic/DiagnosticDriverKinds.td2
-rw-r--r--include/clang/Basic/DiagnosticFrontendKinds.td2
-rw-r--r--include/clang/Basic/DiagnosticGroups.td27
-rw-r--r--include/clang/Basic/DiagnosticLexKinds.td26
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td20
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td150
-rw-r--r--include/clang/Basic/IdentifierTable.h74
-rw-r--r--include/clang/Basic/LangOptions.h3
-rw-r--r--include/clang/Basic/Linkage.h11
-rw-r--r--include/clang/Basic/Makefile1
-rw-r--r--include/clang/Basic/OnDiskHashTable.h83
-rw-r--r--include/clang/Basic/SourceManager.h48
-rw-r--r--include/clang/Basic/Specifiers.h62
-rw-r--r--include/clang/Basic/StmtNodes.td1
-rw-r--r--include/clang/Basic/TargetInfo.h43
-rw-r--r--include/clang/Basic/TargetOptions.h8
-rw-r--r--include/clang/Basic/TokenKinds.def13
-rw-r--r--include/clang/Basic/arm_neon.td2
-rw-r--r--include/clang/CMakeLists.txt1
-rw-r--r--include/clang/Checker/BugReporter/BugReporter.h3
-rw-r--r--include/clang/Checker/PathSensitive/AnalysisManager.h52
-rw-r--r--include/clang/Checker/PathSensitive/Checker.h31
-rw-r--r--include/clang/Checker/PathSensitive/CheckerHelpers.h40
-rw-r--r--include/clang/Checker/PathSensitive/ConstraintManager.h3
-rw-r--r--include/clang/Checker/PathSensitive/Environment.h8
-rw-r--r--include/clang/Checker/PathSensitive/GRCoreEngine.h168
-rw-r--r--include/clang/Checker/PathSensitive/GRExprEngine.h196
-rw-r--r--include/clang/Checker/PathSensitive/GRState.h99
-rw-r--r--include/clang/Checker/PathSensitive/GRSubEngine.h33
-rw-r--r--include/clang/Checker/PathSensitive/GRTransferFuncs.h6
-rw-r--r--include/clang/Checker/PathSensitive/GRWorkList.h10
-rw-r--r--include/clang/Checker/PathSensitive/MemRegion.h127
-rw-r--r--include/clang/Checker/PathSensitive/SVals.h27
-rw-r--r--include/clang/Checker/PathSensitive/Store.h41
-rw-r--r--include/clang/Checker/PathSensitive/SymbolManager.h79
-rw-r--r--include/clang/Checker/PathSensitive/ValueManager.h3
-rw-r--r--include/clang/Driver/CC1Options.td45
-rw-r--r--include/clang/Driver/Compilation.h2
-rw-r--r--include/clang/Driver/Driver.h29
-rw-r--r--include/clang/Driver/HostInfo.h9
-rw-r--r--include/clang/Driver/Job.h34
-rw-r--r--include/clang/Driver/OptParser.td3
-rw-r--r--include/clang/Driver/OptTable.h11
-rw-r--r--include/clang/Driver/Option.h10
-rw-r--r--include/clang/Driver/Options.td13
-rw-r--r--include/clang/Driver/Tool.h4
-rw-r--r--include/clang/Driver/ToolChain.h18
-rw-r--r--include/clang/Frontend/ASTConsumers.h9
-rw-r--r--include/clang/Frontend/ASTUnit.h341
-rw-r--r--include/clang/Frontend/AnalyzerOptions.h3
-rw-r--r--include/clang/Frontend/CodeGenOptions.h15
-rw-r--r--include/clang/Frontend/CompilerInstance.h59
-rw-r--r--include/clang/Frontend/DeclXML.def20
-rw-r--r--include/clang/Frontend/DiagnosticOptions.h2
-rw-r--r--include/clang/Frontend/DocumentXML.h1
-rw-r--r--include/clang/Frontend/FrontendAction.h14
-rw-r--r--include/clang/Frontend/FrontendActions.h33
-rw-r--r--include/clang/Frontend/FrontendOptions.h16
-rw-r--r--include/clang/Frontend/HeaderSearchOptions.h20
-rw-r--r--include/clang/Frontend/PCHDeserializationListener.h36
-rw-r--r--include/clang/Frontend/PreprocessorOptions.h67
-rw-r--r--include/clang/Frontend/PreprocessorOutputOptions.h16
-rw-r--r--include/clang/Frontend/StmtXML.def99
-rw-r--r--include/clang/Frontend/TypeXML.def8
-rw-r--r--include/clang/Frontend/Utils.h7
-rw-r--r--include/clang/FrontendTool/Utils.h30
-rw-r--r--include/clang/Index/TranslationUnit.h2
-rw-r--r--include/clang/Index/Utils.h36
-rw-r--r--include/clang/Lex/CodeCompletionHandler.h67
-rw-r--r--include/clang/Lex/ExternalPreprocessorSource.h2
-rw-r--r--include/clang/Lex/HeaderSearch.h2
-rw-r--r--include/clang/Lex/Lexer.h29
-rw-r--r--include/clang/Lex/MacroInfo.h37
-rw-r--r--include/clang/Lex/PPCallbacks.h10
-rw-r--r--include/clang/Lex/PTHLexer.h2
-rw-r--r--include/clang/Lex/PreprocessingRecord.h3
-rw-r--r--include/clang/Lex/Preprocessor.h73
-rw-r--r--include/clang/Lex/Token.h1
-rw-r--r--include/clang/Makefile2
-rw-r--r--include/clang/Parse/Action.h3309
-rw-r--r--include/clang/Parse/Ownership.h845
-rw-r--r--include/clang/Parse/ParseAST.h (renamed from include/clang/Sema/ParseAST.h)8
-rw-r--r--include/clang/Parse/Parser.h509
-rw-r--r--include/clang/Rewrite/FixItRewriter.h11
-rw-r--r--include/clang/Rewrite/FrontendActions.h4
-rw-r--r--include/clang/Sema/AnalysisBasedWarnings.h64
-rw-r--r--include/clang/Sema/AttributeList.h (renamed from include/clang/Parse/AttributeList.h)30
-rw-r--r--include/clang/Sema/CXXFieldCollector.h79
-rw-r--r--include/clang/Sema/CodeCompleteConsumer.h495
-rw-r--r--include/clang/Sema/DeclSpec.h (renamed from include/clang/Parse/DeclSpec.h)127
-rw-r--r--include/clang/Sema/DelayedDiagnostic.h168
-rw-r--r--include/clang/Sema/Designator.h (renamed from include/clang/Parse/Designator.h)79
-rw-r--r--include/clang/Sema/ExternalSemaSource.h2
-rw-r--r--include/clang/Sema/IdentifierResolver.h198
-rw-r--r--include/clang/Sema/Initialization.h780
-rw-r--r--include/clang/Sema/Lookup.h679
-rw-r--r--include/clang/Sema/ObjCMethodList.h38
-rw-r--r--include/clang/Sema/Overload.h648
-rw-r--r--include/clang/Sema/Ownership.h462
-rw-r--r--include/clang/Sema/ParsedTemplate.h (renamed from include/clang/Parse/Template.h)43
-rw-r--r--include/clang/Sema/PrettyDeclStackTrace.h46
-rw-r--r--include/clang/Sema/Scope.h (renamed from include/clang/Parse/Scope.h)26
-rw-r--r--include/clang/Sema/ScopeInfo.h137
-rw-r--r--include/clang/Sema/Sema.h4457
-rw-r--r--include/clang/Sema/SemaInternal.h30
-rw-r--r--include/clang/Sema/Template.h244
-rw-r--r--include/clang/Sema/TemplateDeduction.h111
-rw-r--r--include/clang/Serialization/ASTBitCodes.h (renamed from include/clang/Frontend/PCHBitCodes.h)193
-rw-r--r--include/clang/Serialization/ASTDeserializationListener.h49
-rw-r--r--include/clang/Serialization/ASTReader.h (renamed from include/clang/Frontend/PCHReader.h)667
-rw-r--r--include/clang/Serialization/ASTWriter.h (renamed from include/clang/Frontend/PCHWriter.h)257
-rw-r--r--include/clang/Serialization/CMakeLists.txt12
-rw-r--r--include/clang/Serialization/Makefile19
161 files changed, 15576 insertions, 8481 deletions
diff --git a/include/clang/AST/ASTConsumer.h b/include/clang/AST/ASTConsumer.h
index 06113954fc48..84833c099f97 100644
--- a/include/clang/AST/ASTConsumer.h
+++ b/include/clang/AST/ASTConsumer.h
@@ -18,9 +18,10 @@ namespace clang {
class ASTContext;
class CXXRecordDecl;
class DeclGroupRef;
- class TagDecl;
class HandleTagDeclDefinition;
+ class ASTDeserializationListener; // layering violation because void* is ugly
class SemaConsumer; // layering violation required for safe SemaConsumer
+ class TagDecl;
class VarDecl;
/// ASTConsumer - This is an abstract interface that should be implemented by
@@ -48,6 +49,11 @@ public:
/// elements). Use Decl::getNextDeclarator() to walk the chain.
virtual void HandleTopLevelDecl(DeclGroupRef D);
+ /// HandleInterestingDecl - Handle the specified interesting declaration. This
+ /// is called by the AST reader when deserializing things that might interest
+ /// the consumer. The default implementation forwards to HandleTopLevelDecl.
+ virtual void HandleInterestingDecl(DeclGroupRef D);
+
/// HandleTranslationUnit - This method is called when the ASTs for entire
/// translation unit have been parsed.
virtual void HandleTranslationUnit(ASTContext &Ctx) {}
@@ -80,6 +86,12 @@ public:
/// it was actually used.
virtual void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) {}
+ /// \brief If the consumer is interested in entities being deserialized from
+ /// AST files, it should return a pointer to a ASTDeserializationListener here
+ ///
+ /// The return type is void* because ASTDS lives in Frontend.
+ virtual ASTDeserializationListener *GetASTDeserializationListener() { return 0; }
+
/// PrintStats - If desired, print any statistics.
virtual void PrintStats() {}
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 3799451360f4..ae4ee946fe27 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -18,7 +18,6 @@
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/PartialDiagnostic.h"
-#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/PrettyPrinter.h"
@@ -50,6 +49,7 @@ namespace clang {
class SelectorTable;
class SourceManager;
class TargetInfo;
+ class CXXABI;
// Decls
class DeclContext;
class CXXMethodDecl;
@@ -198,7 +198,7 @@ class ASTContext {
///
/// Since so few decls have attrs, we keep them in a hash map instead of
/// wasting space in the Decl class.
- llvm::DenseMap<const Decl*, Attr*> DeclAttrs;
+ llvm::DenseMap<const Decl*, AttrVec*> DeclAttrs;
/// \brief Keeps track of the static data member templates from which
/// static data members of class template specializations were instantiated.
@@ -275,13 +275,18 @@ class ASTContext {
/// this ASTContext object.
LangOptions LangOpts;
- /// MallocAlloc/BumpAlloc - The allocator objects used to create AST objects.
- bool FreeMemory;
- llvm::MallocAllocator MallocAlloc;
+ /// \brief The allocator used to create AST objects.
+ ///
+ /// AST objects are never destructed; rather, all memory associated with the
+ /// AST objects will be released when the ASTContext itself is destroyed.
llvm::BumpPtrAllocator BumpAlloc;
/// \brief Allocator for partial diagnostics.
PartialDiagnostic::StorageAllocator DiagAllocator;
+
+ /// \brief The current C++ ABI.
+ llvm::OwningPtr<CXXABI> ABI;
+ CXXABI *createCXXABI(const TargetInfo &T);
public:
const TargetInfo &Target;
@@ -301,13 +306,9 @@ public:
SourceManager& getSourceManager() { return SourceMgr; }
const SourceManager& getSourceManager() const { return SourceMgr; }
void *Allocate(unsigned Size, unsigned Align = 8) {
- return FreeMemory ? MallocAlloc.Allocate(Size, Align) :
- BumpAlloc.Allocate(Size, Align);
- }
- void Deallocate(void *Ptr) {
- if (FreeMemory)
- MallocAlloc.Deallocate(Ptr);
+ return BumpAlloc.Allocate(Size, Align);
}
+ void Deallocate(void *Ptr) { }
PartialDiagnostic::StorageAllocator &getDiagAllocator() {
return DiagAllocator;
@@ -320,10 +321,10 @@ public:
}
/// \brief Retrieve the attributes for the given declaration.
- Attr*& getDeclAttrs(const Decl *D) { return DeclAttrs[D]; }
+ AttrVec& getDeclAttrs(const Decl *D);
/// \brief Erase the attributes corresponding to the given declaration.
- void eraseDeclAttrs(const Decl *D) { DeclAttrs.erase(D); }
+ void eraseDeclAttrs(const Decl *D);
/// \brief If this variable is an instantiated static data member of a
/// class template specialization, returns the templated static data member
@@ -393,7 +394,7 @@ public:
ASTContext(const LangOptions& LOpts, SourceManager &SM, const TargetInfo &t,
IdentifierTable &idents, SelectorTable &sels,
Builtin::Context &builtins,
- bool FreeMemory = true, unsigned size_reserve=0);
+ unsigned size_reserve);
~ASTContext();
@@ -520,7 +521,7 @@ public:
llvm::SmallVectorImpl<const Expr *> &Layout);
/// This builds the struct used for __block variables.
- QualType BuildByRefType(const char *DeclName, QualType Ty);
+ QualType BuildByRefType(llvm::StringRef DeclName, QualType Ty);
/// Returns true iff we need copy/dispose helpers for the given type.
bool BlockRequiresCopying(QualType Ty);
@@ -873,7 +874,8 @@ public:
return getExtQualType(T, Qs);
}
- DeclarationName getNameForTemplate(TemplateName Name);
+ DeclarationNameInfo getNameForTemplate(TemplateName Name,
+ SourceLocation NameLoc);
TemplateName getOverloadedTemplateName(UnresolvedSetIterator Begin,
UnresolvedSetIterator End);
@@ -909,6 +911,11 @@ public:
///
Qualifiers::GC getObjCGCAttrKind(const QualType &Ty) const;
+ /// areCompatibleVectorTypes - Return true if the given vector types either
+ /// are of the same unqualified type or if one is GCC and other - equivalent
+ /// AltiVec vector type.
+ bool areCompatibleVectorTypes(QualType FirstVec, QualType SecondVec);
+
/// isObjCNSObjectType - Return true if this is an NSObject object with
/// its NSObject attribute set.
bool isObjCNSObjectType(QualType Ty) const;
@@ -1002,13 +1009,12 @@ public:
/// of class definition.
const CXXMethodDecl *getKeyFunction(const CXXRecordDecl *RD);
- void CollectObjCIvars(const ObjCInterfaceDecl *OI,
- llvm::SmallVectorImpl<FieldDecl*> &Fields);
-
void ShallowCollectObjCIvars(const ObjCInterfaceDecl *OI,
llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars);
- void CollectNonClassIvars(const ObjCInterfaceDecl *OI,
- llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars);
+
+ void DeepCollectObjCIvars(const ObjCInterfaceDecl *OI, bool leafClass,
+ llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars);
+
unsigned CountNonClassIvars(const ObjCInterfaceDecl *OI);
void CollectInheritedProtocols(const Decl *CDecl,
llvm::SmallPtrSet<ObjCProtocolDecl*, 8> &Protocols);
@@ -1067,8 +1073,6 @@ public:
bool UnwrapSimilarPointerTypes(QualType &T1, QualType &T2);
- /// \brief Retrieves the "canonical" declaration of
-
/// \brief Retrieves the "canonical" nested name specifier for a
/// given nested name specifier.
///
@@ -1218,7 +1222,8 @@ public:
//===--------------------------------------------------------------------===//
/// Compatibility predicates used to check assignment expressions.
- bool typesAreCompatible(QualType, QualType); // C99 6.2.7p1
+ bool typesAreCompatible(QualType T1, QualType T2,
+ bool CompareUnqualified = false); // C99 6.2.7p1
bool typesAreBlockPointerCompatible(QualType, QualType);
@@ -1235,6 +1240,8 @@ public:
bool ObjCQualifiedIdTypesAreCompatible(QualType LHS, QualType RHS,
bool ForCompare);
+ bool ObjCQualifiedClassTypesAreCompatible(QualType LHS, QualType RHS);
+
// Check the safety of assignment from LHS to RHS
bool canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT,
const ObjCObjectPointerType *RHSOPT);
@@ -1246,10 +1253,13 @@ public:
bool areComparableObjCPointerTypes(QualType LHS, QualType RHS);
QualType areCommonBaseCompatible(const ObjCObjectPointerType *LHSOPT,
const ObjCObjectPointerType *RHSOPT);
-
+ bool canBindObjCObjectType(QualType To, QualType From);
+
// Functions for calculating composite types
- QualType mergeTypes(QualType, QualType, bool OfBlockPointer=false);
- QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false);
+ QualType mergeTypes(QualType, QualType, bool OfBlockPointer=false,
+ bool Unqualified = false);
+ QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false,
+ bool Unqualified = false);
QualType mergeObjCGCQualifiers(QualType, QualType);
@@ -1257,6 +1267,10 @@ public:
/// that are common to binary operators (C99 6.3.1.8, C++ [expr]p9)
/// and returns the result type of that conversion.
QualType UsualArithmeticConversionsType(QualType lhs, QualType rhs);
+
+ void ResetObjCLayout(const ObjCContainerDecl *CD) {
+ ObjCLayouts[CD] = 0;
+ }
//===--------------------------------------------------------------------===//
// Integer Predicates
@@ -1337,6 +1351,17 @@ public:
/// when it is called.
void AddDeallocation(void (*Callback)(void*), void *Data);
+ GVALinkage GetGVALinkageForFunction(const FunctionDecl *FD);
+ GVALinkage GetGVALinkageForVariable(const VarDecl *VD);
+
+ /// \brief Determines if the decl can be CodeGen'ed or deserialized from PCH
+ /// lazily, only when used; this is only relevant for function or file scoped
+ /// var definitions.
+ ///
+ /// \returns true if the function/var must be CodeGen'ed/deserialized even if
+ /// it is not used.
+ bool DeclMustBeEmitted(const Decl *D);
+
//===--------------------------------------------------------------------===//
// Statistics
//===--------------------------------------------------------------------===//
@@ -1386,7 +1411,7 @@ private:
const ASTRecordLayout &getObjCLayout(const ObjCInterfaceDecl *D,
const ObjCImplementationDecl *Impl);
-
+
private:
/// \brief A set of deallocations that should be performed when the
/// ASTContext is destroyed.
diff --git a/include/clang/AST/ASTImporter.h b/include/clang/AST/ASTImporter.h
index 7975c4378876..9380058118c5 100644
--- a/include/clang/AST/ASTImporter.h
+++ b/include/clang/AST/ASTImporter.h
@@ -14,8 +14,8 @@
#ifndef LLVM_CLANG_AST_ASTIMPORTER_H
#define LLVM_CLANG_AST_ASTIMPORTER_H
-#include "clang/AST/Type.h"
#include "clang/AST/DeclarationName.h"
+#include "clang/AST/Type.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h
index 9faa62eef6f7..62ca49fbf3b1 100644
--- a/include/clang/AST/Attr.h
+++ b/include/clang/AST/Attr.h
@@ -15,8 +15,11 @@
#define LLVM_CLANG_AST_ATTR_H
#include "llvm/Support/Casting.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "clang/Basic/AttrKinds.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/SourceLocation.h"
#include <cassert>
#include <cstring>
#include <algorithm>
@@ -27,28 +30,39 @@ namespace clang {
class IdentifierInfo;
class ObjCInterfaceDecl;
class Expr;
+ class QualType;
+ class FunctionDecl;
+ class TypeSourceInfo;
}
// Defined in ASTContext.h
void *operator new(size_t Bytes, clang::ASTContext &C,
size_t Alignment = 16) throw ();
+// FIXME: Being forced to not have a default argument here due to redeclaration
+// rules on default arguments sucks
+void *operator new[](size_t Bytes, clang::ASTContext &C,
+ size_t Alignment) throw ();
// It is good practice to pair new/delete operators. Also, MSVC gives many
// warnings if a matching delete overload is not declared, even though the
// throw() spec guarantees it will not be implicitly called.
void operator delete(void *Ptr, clang::ASTContext &C, size_t)
throw ();
+void operator delete[](void *Ptr, clang::ASTContext &C, size_t)
+ throw ();
namespace clang {
/// Attr - This represents one attribute.
class Attr {
private:
- Attr *Next;
- attr::Kind AttrKind;
+ SourceLocation Loc;
+ unsigned AttrKind : 16;
bool Inherited : 1;
protected:
+ virtual ~Attr();
+
void* operator new(size_t bytes) throw() {
assert(0 && "Attrs cannot be allocated with regular 'new'.");
return 0;
@@ -57,41 +71,36 @@ protected:
assert(0 && "Attrs cannot be released with regular 'delete'.");
}
-protected:
- Attr(attr::Kind AK) : Next(0), AttrKind(AK), Inherited(false) {}
- virtual ~Attr() {
- assert(Next == 0 && "Destroy didn't work");
+public:
+ // Forward so that the regular new and delete do not hide global ones.
+ void* operator new(size_t Bytes, ASTContext &C,
+ size_t Alignment = 16) throw() {
+ return ::operator new(Bytes, C, Alignment);
}
+ void operator delete(void *Ptr, ASTContext &C,
+ size_t Alignment) throw() {
+ return ::operator delete(Ptr, C, Alignment);
+ }
+
+protected:
+ Attr(attr::Kind AK, SourceLocation L)
+ : Loc(L), AttrKind(AK), Inherited(false) {}
+
public:
- virtual void Destroy(ASTContext &C);
/// \brief Whether this attribute should be merged to new
/// declarations.
virtual bool isMerged() const { return true; }
- attr::Kind getKind() const { return AttrKind; }
-
- Attr *getNext() { return Next; }
- const Attr *getNext() const { return Next; }
- void setNext(Attr *next) { Next = next; }
-
- template<typename T> const T *getNext() const {
- for (const Attr *attr = getNext(); attr; attr = attr->getNext())
- if (const T *V = dyn_cast<T>(attr))
- return V;
- return 0;
+ attr::Kind getKind() const {
+ return static_cast<attr::Kind>(AttrKind);
}
- bool isInherited() const { return Inherited; }
- void setInherited(bool value) { Inherited = value; }
-
- void addAttr(Attr *attr) {
- assert((attr != 0) && "addAttr(): attr is null");
+ SourceLocation getLocation() const { return Loc; }
+ void setLocation(SourceLocation L) { Loc = L; }
- // FIXME: This doesn't preserve the order in any way.
- attr->Next = Next;
- Next = attr;
- }
+ bool isInherited() const { return Inherited; }
+ void setInherited(bool I) { Inherited = I; }
// Clone this attribute.
virtual Attr* clone(ASTContext &C) const = 0;
@@ -101,490 +110,112 @@ public:
};
#include "clang/AST/Attrs.inc"
-
-class AttrWithString : public Attr {
-private:
- const char *Str;
- unsigned StrLen;
-protected:
- AttrWithString(attr::Kind AK, ASTContext &C, llvm::StringRef s);
- llvm::StringRef getString() const { return llvm::StringRef(Str, StrLen); }
- void ReplaceString(ASTContext &C, llvm::StringRef newS);
-public:
- virtual void Destroy(ASTContext &C);
-};
-
-#define DEF_SIMPLE_ATTR(ATTR) \
-class ATTR##Attr : public Attr { \
-public: \
- ATTR##Attr() : Attr(attr::ATTR) {} \
- virtual Attr *clone(ASTContext &C) const; \
- static bool classof(const Attr *A) { return A->getKind() == attr::ATTR; } \
- static bool classof(const ATTR##Attr *A) { return true; } \
-}
-DEF_SIMPLE_ATTR(Packed);
-
-/// \brief Attribute for specifying a maximum field alignment; this is only
-/// valid on record decls.
-class MaxFieldAlignmentAttr : public Attr {
- unsigned Alignment;
-
-public:
- MaxFieldAlignmentAttr(unsigned alignment)
- : Attr(attr::MaxFieldAlignment), Alignment(alignment) {}
+/// AttrVec - A vector of Attr, which is how they are stored on the AST.
+typedef llvm::SmallVector<Attr*, 2> AttrVec;
+typedef llvm::SmallVector<const Attr*, 2> ConstAttrVec;
- /// getAlignment - The specified alignment in bits.
- unsigned getAlignment() const { return Alignment; }
-
- virtual Attr* clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) {
- return A->getKind() == attr::MaxFieldAlignment;
- }
- static bool classof(const MaxFieldAlignmentAttr *A) { return true; }
-};
-
-DEF_SIMPLE_ATTR(AlignMac68k);
-
-/// \brief Atribute for specifying the alignment of a variable or type.
-///
-/// This node will either contain the precise Alignment (in bits, not bytes!)
-/// or will contain the expression for the alignment attribute in the case of
-/// a dependent expression within a class or function template. At template
-/// instantiation time these are transformed into concrete attributes.
-class AlignedAttr : public Attr {
- unsigned Alignment;
- Expr *AlignmentExpr;
-public:
- AlignedAttr(unsigned alignment)
- : Attr(attr::Aligned), Alignment(alignment), AlignmentExpr(0) {}
- AlignedAttr(Expr *E)
- : Attr(attr::Aligned), Alignment(0), AlignmentExpr(E) {}
-
- /// getAlignmentExpr - Get a dependent alignment expression if one is present.
- Expr *getAlignmentExpr() const {
- return AlignmentExpr;
- }
-
- /// isDependent - Is the alignment a dependent expression
- bool isDependent() const {
- return getAlignmentExpr();
- }
+/// DestroyAttrs - Destroy the contents of an AttrVec.
+inline void DestroyAttrs (AttrVec& V, ASTContext &C) {
+}
- /// getAlignment - The specified alignment in bits. Requires !isDependent().
- unsigned getAlignment() const {
- assert(!isDependent() && "Cannot get a value dependent alignment");
- return Alignment;
- }
+/// specific_attr_iterator - Iterates over a subrange of an AttrVec, only
+/// providing attributes that are of a specifc type.
+template <typename SpecificAttr>
+class specific_attr_iterator {
+ /// Current - The current, underlying iterator.
+ /// In order to ensure we don't dereference an invalid iterator unless
+ /// specifically requested, we don't necessarily advance this all the
+ /// way. Instead, we advance it when an operation is requested; if the
+ /// operation is acting on what should be a past-the-end iterator,
+ /// then we offer no guarantees, but this way we do not dererence a
+ /// past-the-end iterator when we move to a past-the-end position.
+ mutable AttrVec::const_iterator Current;
- /// getMaxAlignment - Get the maximum alignment of attributes on this list.
- unsigned getMaxAlignment() const {
- const AlignedAttr *Next = getNext<AlignedAttr>();
- if (Next)
- return std::max(Next->getMaxAlignment(), getAlignment());
- else
- return getAlignment();
+ void AdvanceToNext() const {
+ while (!llvm::isa<SpecificAttr>(*Current))
+ ++Current;
}
- virtual Attr* clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) {
- return A->getKind() == attr::Aligned;
+ void AdvanceToNext(AttrVec::const_iterator I) const {
+ while (Current != I && !llvm::isa<SpecificAttr>(*Current))
+ ++Current;
}
- static bool classof(const AlignedAttr *A) { return true; }
-};
-class AnnotateAttr : public AttrWithString {
public:
- AnnotateAttr(ASTContext &C, llvm::StringRef ann)
- : AttrWithString(attr::Annotate, C, ann) {}
-
- llvm::StringRef getAnnotation() const { return getString(); }
+ typedef SpecificAttr* value_type;
+ typedef SpecificAttr* reference;
+ typedef SpecificAttr* pointer;
+ typedef std::forward_iterator_tag iterator_category;
+ typedef std::ptrdiff_t difference_type;
- virtual Attr* clone(ASTContext &C) const;
+ specific_attr_iterator() : Current() { }
+ explicit specific_attr_iterator(AttrVec::const_iterator i) : Current(i) { }
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) {
- return A->getKind() == attr::Annotate;
+ reference operator*() const {
+ AdvanceToNext();
+ return llvm::cast<SpecificAttr>(*Current);
}
- static bool classof(const AnnotateAttr *A) { return true; }
-};
-
-class AsmLabelAttr : public AttrWithString {
-public:
- AsmLabelAttr(ASTContext &C, llvm::StringRef L)
- : AttrWithString(attr::AsmLabel, C, L) {}
-
- llvm::StringRef getLabel() const { return getString(); }
-
- virtual Attr* clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) {
- return A->getKind() == attr::AsmLabel;
- }
- static bool classof(const AsmLabelAttr *A) { return true; }
-};
-
-DEF_SIMPLE_ATTR(AlwaysInline);
-
-class AliasAttr : public AttrWithString {
-public:
- AliasAttr(ASTContext &C, llvm::StringRef aliasee)
- : AttrWithString(attr::Alias, C, aliasee) {}
-
- llvm::StringRef getAliasee() const { return getString(); }
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) { return A->getKind() == attr::Alias; }
- static bool classof(const AliasAttr *A) { return true; }
-};
-
-class ConstructorAttr : public Attr {
- int priority;
-public:
- ConstructorAttr(int p) : Attr(attr::Constructor), priority(p) {}
-
- int getPriority() const { return priority; }
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A)
- { return A->getKind() == attr::Constructor; }
- static bool classof(const ConstructorAttr *A) { return true; }
-};
-
-class DestructorAttr : public Attr {
- int priority;
-public:
- DestructorAttr(int p) : Attr(attr::Destructor), priority(p) {}
-
- int getPriority() const { return priority; }
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A)
- { return A->getKind() == attr::Destructor; }
- static bool classof(const DestructorAttr *A) { return true; }
-};
-
-class IBOutletAttr : public Attr {
-public:
- IBOutletAttr() : Attr(attr::IBOutlet) {}
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) {
- return A->getKind() == attr::IBOutlet;
- }
- static bool classof(const IBOutletAttr *A) { return true; }
-};
-
-class IBOutletCollectionAttr : public Attr {
- const ObjCInterfaceDecl *D;
-public:
- IBOutletCollectionAttr(const ObjCInterfaceDecl *d = 0)
- : Attr(attr::IBOutletCollection), D(d) {}
-
- const ObjCInterfaceDecl *getClass() const { return D; }
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) {
- return A->getKind() == attr::IBOutletCollection;
+ pointer operator->() const {
+ AdvanceToNext();
+ return llvm::cast<SpecificAttr>(*Current);
}
- static bool classof(const IBOutletCollectionAttr *A) { return true; }
-};
-
-class IBActionAttr : public Attr {
-public:
- IBActionAttr() : Attr(attr::IBAction) {}
-
- virtual Attr *clone(ASTContext &C) const;
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) {
- return A->getKind() == attr::IBAction;
+ specific_attr_iterator& operator++() {
+ ++Current;
+ return *this;
}
- static bool classof(const IBActionAttr *A) { return true; }
-};
-
-DEF_SIMPLE_ATTR(AnalyzerNoReturn);
-DEF_SIMPLE_ATTR(Deprecated);
-DEF_SIMPLE_ATTR(GNUInline);
-DEF_SIMPLE_ATTR(Malloc);
-DEF_SIMPLE_ATTR(NoReturn);
-DEF_SIMPLE_ATTR(NoInstrumentFunction);
-
-class SectionAttr : public AttrWithString {
-public:
- SectionAttr(ASTContext &C, llvm::StringRef N)
- : AttrWithString(attr::Section, C, N) {}
-
- llvm::StringRef getName() const { return getString(); }
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) {
- return A->getKind() == attr::Section;
+ specific_attr_iterator operator++(int) {
+ specific_attr_iterator Tmp(*this);
+ ++(*this);
+ return Tmp;
}
- static bool classof(const SectionAttr *A) { return true; }
-};
-
-DEF_SIMPLE_ATTR(Unavailable);
-DEF_SIMPLE_ATTR(Unused);
-DEF_SIMPLE_ATTR(Used);
-DEF_SIMPLE_ATTR(Weak);
-DEF_SIMPLE_ATTR(WeakImport);
-DEF_SIMPLE_ATTR(WeakRef);
-DEF_SIMPLE_ATTR(NoThrow);
-DEF_SIMPLE_ATTR(Const);
-DEF_SIMPLE_ATTR(Pure);
-
-class NonNullAttr : public Attr {
- unsigned* ArgNums;
- unsigned Size;
-public:
- NonNullAttr(ASTContext &C, unsigned* arg_nums = 0, unsigned size = 0);
-
- virtual void Destroy(ASTContext &C);
-
- typedef const unsigned *iterator;
- iterator begin() const { return ArgNums; }
- iterator end() const { return ArgNums + Size; }
- unsigned size() const { return Size; }
- bool isNonNull(unsigned arg) const {
- return ArgNums ? std::binary_search(ArgNums, ArgNums+Size, arg) : true;
+ friend bool operator==(specific_attr_iterator Left,
+ specific_attr_iterator Right) {
+ if (Left.Current < Right.Current)
+ Left.AdvanceToNext(Right.Current);
+ else
+ Right.AdvanceToNext(Left.Current);
+ return Left.Current == Right.Current;
}
-
- virtual Attr *clone(ASTContext &C) const;
-
- static bool classof(const Attr *A) { return A->getKind() == attr::NonNull; }
- static bool classof(const NonNullAttr *A) { return true; }
-};
-
-class FormatAttr : public AttrWithString {
- int formatIdx, firstArg;
-public:
- FormatAttr(ASTContext &C, llvm::StringRef type, int idx, int first)
- : AttrWithString(attr::Format, C, type), formatIdx(idx), firstArg(first) {}
-
- llvm::StringRef getType() const { return getString(); }
- void setType(ASTContext &C, llvm::StringRef type);
- int getFormatIdx() const { return formatIdx; }
- int getFirstArg() const { return firstArg; }
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) { return A->getKind() == attr::Format; }
- static bool classof(const FormatAttr *A) { return true; }
-};
-
-class FormatArgAttr : public Attr {
- int formatIdx;
-public:
- FormatArgAttr(int idx) : Attr(attr::FormatArg), formatIdx(idx) {}
- int getFormatIdx() const { return formatIdx; }
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) { return A->getKind() == attr::FormatArg; }
- static bool classof(const FormatArgAttr *A) { return true; }
-};
-
-class SentinelAttr : public Attr {
- int sentinel, NullPos;
-public:
- SentinelAttr(int sentinel_val, int nullPos) : Attr(attr::Sentinel),
- sentinel(sentinel_val), NullPos(nullPos) {}
- int getSentinel() const { return sentinel; }
- int getNullPos() const { return NullPos; }
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) { return A->getKind() == attr::Sentinel; }
- static bool classof(const SentinelAttr *A) { return true; }
-};
-
-class VisibilityAttr : public Attr {
-public:
- /// @brief An enumeration for the kinds of visibility of symbols.
- enum VisibilityTypes {
- DefaultVisibility = 0,
- HiddenVisibility,
- ProtectedVisibility
- };
-private:
- VisibilityTypes VisibilityType;
-public:
- VisibilityAttr(VisibilityTypes v) : Attr(attr::Visibility),
- VisibilityType(v) {}
-
- VisibilityTypes getVisibility() const { return VisibilityType; }
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A)
- { return A->getKind() == attr::Visibility; }
- static bool classof(const VisibilityAttr *A) { return true; }
-};
-
-DEF_SIMPLE_ATTR(FastCall);
-DEF_SIMPLE_ATTR(StdCall);
-DEF_SIMPLE_ATTR(ThisCall);
-DEF_SIMPLE_ATTR(CDecl);
-DEF_SIMPLE_ATTR(TransparentUnion);
-DEF_SIMPLE_ATTR(ObjCNSObject);
-DEF_SIMPLE_ATTR(ObjCException);
-
-class OverloadableAttr : public Attr {
-public:
- OverloadableAttr() : Attr(attr::Overloadable) { }
-
- virtual bool isMerged() const { return false; }
-
- virtual Attr *clone(ASTContext &C) const;
-
- static bool classof(const Attr *A)
- { return A->getKind() == attr::Overloadable; }
- static bool classof(const OverloadableAttr *) { return true; }
-};
-
-class BlocksAttr : public Attr {
-public:
- enum BlocksAttrTypes {
- ByRef = 0
- };
-private:
- BlocksAttrTypes BlocksAttrType;
-public:
- BlocksAttr(BlocksAttrTypes t) : Attr(attr::Blocks), BlocksAttrType(t) {}
-
- BlocksAttrTypes getType() const { return BlocksAttrType; }
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) { return A->getKind() == attr::Blocks; }
- static bool classof(const BlocksAttr *A) { return true; }
-};
-
-class FunctionDecl;
-
-class CleanupAttr : public Attr {
- FunctionDecl *FD;
-
-public:
- CleanupAttr(FunctionDecl *fd) : Attr(attr::Cleanup), FD(fd) {}
-
- const FunctionDecl *getFunctionDecl() const { return FD; }
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) { return A->getKind() == attr::Cleanup; }
- static bool classof(const CleanupAttr *A) { return true; }
-};
-
-DEF_SIMPLE_ATTR(NoDebug);
-DEF_SIMPLE_ATTR(WarnUnusedResult);
-DEF_SIMPLE_ATTR(NoInline);
-
-class RegparmAttr : public Attr {
- unsigned NumParams;
-
-public:
- RegparmAttr(unsigned np) : Attr(attr::Regparm), NumParams(np) {}
-
- unsigned getNumParams() const { return NumParams; }
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) { return A->getKind() == attr::Regparm; }
- static bool classof(const RegparmAttr *A) { return true; }
-};
-
-class ReqdWorkGroupSizeAttr : public Attr {
- unsigned X, Y, Z;
-public:
- ReqdWorkGroupSizeAttr(unsigned X, unsigned Y, unsigned Z)
- : Attr(attr::ReqdWorkGroupSize), X(X), Y(Y), Z(Z) {}
-
- unsigned getXDim() const { return X; }
- unsigned getYDim() const { return Y; }
- unsigned getZDim() const { return Z; }
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) {
- return A->getKind() == attr::ReqdWorkGroupSize;
+ friend bool operator!=(specific_attr_iterator Left,
+ specific_attr_iterator Right) {
+ return !(Left == Right);
}
- static bool classof(const ReqdWorkGroupSizeAttr *A) { return true; }
};
-class InitPriorityAttr : public Attr {
- unsigned Priority;
-public:
- InitPriorityAttr(unsigned priority)
- : Attr(attr::InitPriority), Priority(priority) {}
-
- virtual void Destroy(ASTContext &C) { Attr::Destroy(C); }
-
- unsigned getPriority() const { return Priority; }
-
- virtual Attr *clone(ASTContext &C) const;
-
- static bool classof(const Attr *A)
- { return A->getKind() == attr::InitPriority; }
- static bool classof(const InitPriorityAttr *A) { return true; }
-};
-
-// Checker-specific attributes.
-DEF_SIMPLE_ATTR(CFReturnsNotRetained);
-DEF_SIMPLE_ATTR(CFReturnsRetained);
-DEF_SIMPLE_ATTR(NSReturnsNotRetained);
-DEF_SIMPLE_ATTR(NSReturnsRetained);
-
-// Target-specific attributes
-DEF_SIMPLE_ATTR(DLLImport);
-DEF_SIMPLE_ATTR(DLLExport);
-
-class MSP430InterruptAttr : public Attr {
- unsigned Number;
-
-public:
- MSP430InterruptAttr(unsigned n) : Attr(attr::MSP430Interrupt), Number(n) {}
-
- unsigned getNumber() const { return Number; }
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A)
- { return A->getKind() == attr::MSP430Interrupt; }
- static bool classof(const MSP430InterruptAttr *A) { return true; }
-};
+template <typename T>
+inline specific_attr_iterator<T> specific_attr_begin(const AttrVec& vec) {
+ return specific_attr_iterator<T>(vec.begin());
+}
+template <typename T>
+inline specific_attr_iterator<T> specific_attr_end(const AttrVec& vec) {
+ return specific_attr_iterator<T>(vec.end());
+}
-DEF_SIMPLE_ATTR(X86ForceAlignArgPointer);
+template <typename T>
+inline bool hasSpecificAttr(const AttrVec& vec) {
+ return specific_attr_begin<T>(vec) != specific_attr_end<T>(vec);
+}
+template <typename T>
+inline T *getSpecificAttr(const AttrVec& vec) {
+ specific_attr_iterator<T> i = specific_attr_begin<T>(vec);
+ if (i != specific_attr_end<T>(vec))
+ return *i;
+ else
+ return 0;
+}
-#undef DEF_SIMPLE_ATTR
+/// getMaxAlignment - Returns the highest alignment value found among
+/// AlignedAttrs in an AttrVec, or 0 if there are none.
+inline unsigned getMaxAttrAlignment(const AttrVec& V, ASTContext &Ctx) {
+ unsigned Align = 0;
+ specific_attr_iterator<AlignedAttr> i(V.begin()), e(V.end());
+ for(; i != e; ++i)
+ Align = std::max(Align, i->getAlignment(Ctx));
+ return Align;
+}
} // end namespace clang
diff --git a/include/clang/AST/CMakeLists.txt b/include/clang/AST/CMakeLists.txt
index 3b090715e083..800c58361b02 100644
--- a/include/clang/AST/CMakeLists.txt
+++ b/include/clang/AST/CMakeLists.txt
@@ -5,6 +5,12 @@ tablegen(Attrs.inc
add_custom_target(ClangAttrClasses
DEPENDS Attrs.inc)
+tablegen(AttrImpl.inc
+ -gen-clang-attr-impl
+ -I ${CMAKE_CURRENT_SOURCE_DIR}/../../)
+add_custom_target(ClangAttrImpl
+ DEPENDS AttrImpl.inc)
+
set(LLVM_TARGET_DEFINITIONS ../Basic/StmtNodes.td)
tablegen(StmtNodes.inc
-gen-clang-stmt-nodes)
diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h
index 9f97fd8a7aee..dad4dfc926e1 100644
--- a/include/clang/AST/CanonicalType.h
+++ b/include/clang/AST/CanonicalType.h
@@ -273,6 +273,9 @@ public:
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isArrayType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasPointerRepresentation)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasObjCPointerRepresentation)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasIntegerRepresentation)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasSignedIntegerRepresentation)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasUnsignedIntegerRepresentation)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasFloatingRepresentation)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isPromotableIntegerType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSignedIntegerType)
@@ -700,9 +703,9 @@ inline CanQual<Type> CanQual<T>::getNonReferenceType() const {
template<typename T>
CanQual<T> CanQual<T>::getFromOpaquePtr(void *Ptr) {
CanQual<T> Result;
- Result.Stored.setFromOpaqueValue(Ptr);
- assert((!Result || Result.Stored.isCanonical())
- && "Type is not canonical!");
+ Result.Stored = QualType::getFromOpaquePtr(Ptr);
+ assert((!Result || Result.Stored.getAsOpaquePtr() == (void*)-1 ||
+ Result.Stored.isCanonical()) && "Type is not canonical!");
return Result;
}
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index 39cd51f606b5..674925532210 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -118,16 +118,6 @@ public:
return getIdentifier() ? getIdentifier()->getName() : "";
}
- /// getNameAsCString - Get the name of identifier for this declaration as a
- /// C string (const char*). This requires that the declaration have a name
- /// and that it be a simple identifier.
- //
- // FIXME: Deprecated, move clients to getName().
- const char *getNameAsCString() const {
- assert(Name.isIdentifier() && "Name is not a simple identifier");
- return getIdentifier() ? getIdentifier()->getNameStart() : "";
- }
-
/// getNameAsString - Get a human-readable name for the declaration, even if
/// it is one of the special kinds of names (C++ constructor, Objective-C
/// selector, etc). Creating this name requires expensive string
@@ -229,6 +219,8 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
/// NamespaceDecl - Represent a C++ namespace.
class NamespaceDecl : public NamedDecl, public DeclContext {
+ bool IsInline : 1;
+
SourceLocation LBracLoc, RBracLoc;
// For extended namespace definitions:
@@ -239,7 +231,7 @@ class NamespaceDecl : public NamedDecl, public DeclContext {
// there will be one NamespaceDecl for each declaration.
// NextNamespace points to the next extended declaration.
// OrigNamespace points to the original namespace declaration.
- // OrigNamespace of the first namespace decl points to itself.
+ // OrigNamespace of the first namespace decl points to its anonymous namespace
NamespaceDecl *NextNamespace;
/// \brief A pointer to either the original namespace definition for
@@ -258,28 +250,36 @@ class NamespaceDecl : public NamedDecl, public DeclContext {
NamespaceDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id)
: NamedDecl(Namespace, DC, L, Id), DeclContext(Namespace),
- NextNamespace(0), OrigOrAnonNamespace(0, true) { }
+ IsInline(false), NextNamespace(0), OrigOrAnonNamespace(0, true) { }
public:
static NamespaceDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id);
- virtual void Destroy(ASTContext& C);
-
- // \brief Returns true if this is an anonymous namespace declaration.
- //
- // For example:
+ /// \brief Returns true if this is an anonymous namespace declaration.
+ ///
+ /// For example:
/// \code
- // namespace {
- // ...
- // };
- // \endcode
- // q.v. C++ [namespace.unnamed]
+ /// namespace {
+ /// ...
+ /// };
+ /// \endcode
+ /// q.v. C++ [namespace.unnamed]
bool isAnonymousNamespace() const {
return !getIdentifier();
}
- /// \brief Return the next extended namespace declaration or null if this
+ /// \brief Returns true if this is an inline namespace declaration.
+ bool isInline() const {
+ return IsInline;
+ }
+
+ /// \brief Set whether this is an inline namespace declaration.
+ void setInline(bool Inline) {
+ IsInline = Inline;
+ }
+
+ /// \brief Return the next extended namespace declaration or null if there
/// is none.
NamespaceDecl *getNextNamespace() { return NextNamespace; }
const NamespaceDecl *getNextNamespace() const { return NextNamespace; }
@@ -345,8 +345,8 @@ public:
return static_cast<NamespaceDecl *>(const_cast<DeclContext*>(DC));
}
- friend class PCHDeclReader;
- friend class PCHDeclWriter;
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
};
/// ValueDecl - Represent the declaration of a variable (in which case it is
@@ -392,8 +392,6 @@ struct QualifierInfo {
unsigned NumTPLists,
TemplateParameterList **TPLists);
- void Destroy(ASTContext &Context);
-
private:
// Copy constructor and copy assignment are disabled.
QualifierInfo(const QualifierInfo&);
@@ -421,9 +419,6 @@ protected:
: ValueDecl(DK, DC, L, N, T), DeclInfo(TInfo) {}
public:
- virtual ~DeclaratorDecl();
- virtual void Destroy(ASTContext &C);
-
TypeSourceInfo *getTypeSourceInfo() const {
return hasExtInfo()
? getExtInfo()->TInfo
@@ -507,36 +502,11 @@ struct EvaluatedStmt {
APValue Evaluated;
};
-// \brief Describes the kind of template specialization that a
-// particular template specialization declaration represents.
-enum TemplateSpecializationKind {
- /// This template specialization was formed from a template-id but
- /// has not yet been declared, defined, or instantiated.
- TSK_Undeclared = 0,
- /// This template specialization was implicitly instantiated from a
- /// template. (C++ [temp.inst]).
- TSK_ImplicitInstantiation,
- /// This template specialization was declared or defined by an
- /// explicit specialization (C++ [temp.expl.spec]) or partial
- /// specialization (C++ [temp.class.spec]).
- TSK_ExplicitSpecialization,
- /// This template specialization was instantiated from a template
- /// due to an explicit instantiation declaration request
- /// (C++0x [temp.explicit]).
- TSK_ExplicitInstantiationDeclaration,
- /// This template specialization was instantiated from a template
- /// due to an explicit instantiation definition request
- /// (C++ [temp.explicit]).
- TSK_ExplicitInstantiationDefinition
-};
-
/// VarDecl - An instance of this class is created to represent a variable
/// declaration or definition.
class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
public:
- enum StorageClass {
- None, Auto, Register, Extern, Static, PrivateExtern
- };
+ typedef clang::StorageClass StorageClass;
/// getStorageClassSpecifierString - Return the string used to
/// specify the storage class \arg SC.
@@ -568,10 +538,6 @@ private:
bool ThreadSpecified : 1;
bool HasCXXDirectInit : 1;
- /// DeclaredInCondition - Whether this variable was declared in a
- /// condition, e.g., if (int x = foo()) { ... }.
- bool DeclaredInCondition : 1;
-
/// \brief Whether this variable is the exception variable in a C++ catch
/// or an Objective-C @catch statement.
bool ExceptionVar : 1;
@@ -587,7 +553,7 @@ protected:
StorageClass SCAsWritten)
: DeclaratorDecl(DK, DC, L, Id, T, TInfo), Init(),
ThreadSpecified(false), HasCXXDirectInit(false),
- DeclaredInCondition(false), ExceptionVar(false), NRVOVariable(false) {
+ ExceptionVar(false), NRVOVariable(false) {
SClass = SC;
SClassAsWritten = SCAsWritten;
}
@@ -609,9 +575,6 @@ public:
QualType T, TypeSourceInfo *TInfo, StorageClass S,
StorageClass SCAsWritten);
- virtual void Destroy(ASTContext& C);
- virtual ~VarDecl();
-
virtual SourceLocation getInnerLocStart() const;
virtual SourceRange getSourceRange() const;
@@ -619,8 +582,14 @@ public:
StorageClass getStorageClassAsWritten() const {
return (StorageClass) SClassAsWritten;
}
- void setStorageClass(StorageClass SC) { SClass = SC; }
- void setStorageClassAsWritten(StorageClass SC) { SClassAsWritten = SC; }
+ void setStorageClass(StorageClass SC) {
+ assert(isLegalForVariable(SC));
+ SClass = SC;
+ }
+ void setStorageClassAsWritten(StorageClass SC) {
+ assert(isLegalForVariable(SC));
+ SClassAsWritten = SC;
+ }
void setThreadSpecified(bool T) { ThreadSpecified = T; }
bool isThreadSpecified() const {
@@ -630,25 +599,26 @@ public:
/// hasLocalStorage - Returns true if a variable with function scope
/// is a non-static local variable.
bool hasLocalStorage() const {
- if (getStorageClass() == None)
+ if (getStorageClass() == SC_None)
return !isFileVarDecl();
// Return true for: Auto, Register.
// Return false for: Extern, Static, PrivateExtern.
- return getStorageClass() <= Register;
+ return getStorageClass() >= SC_Auto;
}
/// isStaticLocal - Returns true if a variable with function scope is a
/// static local variable.
bool isStaticLocal() const {
- return getStorageClass() == Static && !isFileVarDecl();
+ return getStorageClass() == SC_Static && !isFileVarDecl();
}
/// hasExternStorage - Returns true if a variable has extern or
/// __private_extern__ storage.
bool hasExternalStorage() const {
- return getStorageClass() == Extern || getStorageClass() == PrivateExtern;
+ return getStorageClass() == SC_Extern ||
+ getStorageClass() == SC_PrivateExtern;
}
/// hasGlobalStorage - Returns true for all variables that do not
@@ -670,7 +640,7 @@ public:
if (getKind() != Decl::Var)
return false;
if (const DeclContext *DC = getDeclContext())
- return DC->getLookupContext()->isFunctionOrMethod();
+ return DC->getRedeclContext()->isFunctionOrMethod();
return false;
}
@@ -679,10 +649,8 @@ public:
bool isFunctionOrMethodVarDecl() const {
if (getKind() != Decl::Var)
return false;
- if (const DeclContext *DC = getDeclContext())
- return DC->getLookupContext()->isFunctionOrMethod() &&
- DC->getLookupContext()->getDeclKind() != Decl::Block;
- return false;
+ const DeclContext *DC = getDeclContext()->getRedeclContext();
+ return DC->isFunctionOrMethod() && DC->getDeclKind() != Decl::Block;
}
/// \brief Determines whether this is a static data member.
@@ -696,7 +664,7 @@ public:
/// \endcode
bool isStaticDataMember() const {
// If it wasn't static, it would be a FieldDecl.
- return getDeclContext()->isRecord();
+ return getKind() != Decl::ParmVar && getDeclContext()->isRecord();
}
virtual VarDecl *getCanonicalDecl();
@@ -743,11 +711,10 @@ public:
bool isFileVarDecl() const {
if (getKind() != Decl::Var)
return false;
- if (const DeclContext *Ctx = getDeclContext()) {
- Ctx = Ctx->getLookupContext();
- if (isa<TranslationUnitDecl>(Ctx) || isa<NamespaceDecl>(Ctx) )
- return true;
- }
+
+ if (getDeclContext()->getRedeclContext()->isFileContext())
+ return true;
+
if (isStaticDataMember())
return true;
@@ -912,18 +879,6 @@ public:
return HasCXXDirectInit;
}
- /// isDeclaredInCondition - Whether this variable was declared as
- /// part of a condition in an if/switch/while statement, e.g.,
- /// @code
- /// if (int x = foo()) { ... }
- /// @endcode
- bool isDeclaredInCondition() const {
- return DeclaredInCondition;
- }
- void setDeclaredInCondition(bool InCondition) {
- DeclaredInCondition = InCondition;
- }
-
/// \brief Determine whether this variable is the exception variable in a
/// C++ catch statememt or an Objective-C @catch statement.
bool isExceptionVariable() const {
@@ -973,7 +928,7 @@ class ImplicitParamDecl : public VarDecl {
protected:
ImplicitParamDecl(Kind DK, DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, QualType Tw)
- : VarDecl(DK, DC, L, Id, Tw, /*TInfo=*/0, VarDecl::None, VarDecl::None) {}
+ : VarDecl(DK, DC, L, Id, Tw, /*TInfo=*/0, SC_None, SC_None) {}
public:
static ImplicitParamDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
@@ -1117,9 +1072,7 @@ public:
class FunctionDecl : public DeclaratorDecl, public DeclContext,
public Redeclarable<FunctionDecl> {
public:
- enum StorageClass {
- None, Extern, Static, PrivateExtern
- };
+ typedef clang::StorageClass StorageClass;
/// \brief The kind of templated function a FunctionDecl can be.
enum TemplatedKind {
@@ -1179,11 +1132,15 @@ private:
DependentFunctionTemplateSpecializationInfo *>
TemplateOrSpecialization;
+ /// DNLoc - Provides source/type location info for the
+ /// declaration name embedded in the DeclaratorDecl base class.
+ DeclarationNameLoc DNLoc;
+
protected:
- FunctionDecl(Kind DK, DeclContext *DC, SourceLocation L,
- DeclarationName N, QualType T, TypeSourceInfo *TInfo,
+ FunctionDecl(Kind DK, DeclContext *DC, const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo *TInfo,
StorageClass S, StorageClass SCAsWritten, bool isInline)
- : DeclaratorDecl(DK, DC, L, N, T, TInfo),
+ : DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo),
DeclContext(DK),
ParamInfo(0), Body(),
SClass(S), SClassAsWritten(SCAsWritten), IsInline(isInline),
@@ -1191,10 +1148,9 @@ protected:
HasWrittenPrototype(true), IsDeleted(false), IsTrivial(false),
IsCopyAssignment(false),
HasImplicitReturnZero(false),
- EndRangeLoc(L), TemplateOrSpecialization() {}
-
- virtual ~FunctionDecl() {}
- virtual void Destroy(ASTContext& C);
+ EndRangeLoc(NameInfo.getEndLoc()),
+ TemplateOrSpecialization(),
+ DNLoc(NameInfo.getInfo()) {}
typedef Redeclarable<FunctionDecl> redeclarable_base;
virtual FunctionDecl *getNextRedeclaration() { return RedeclLink.getNext(); }
@@ -1211,11 +1167,27 @@ public:
static FunctionDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L,
DeclarationName N, QualType T,
TypeSourceInfo *TInfo,
- StorageClass S = None,
- StorageClass SCAsWritten = None,
+ StorageClass S = SC_None,
+ StorageClass SCAsWritten = SC_None,
+ bool isInline = false,
+ bool hasWrittenPrototype = true) {
+ DeclarationNameInfo NameInfo(N, L);
+ return FunctionDecl::Create(C, DC, NameInfo, T, TInfo, S, SCAsWritten,
+ isInline, hasWrittenPrototype);
+ }
+
+ static FunctionDecl *Create(ASTContext &C, DeclContext *DC,
+ const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo *TInfo,
+ StorageClass S = SC_None,
+ StorageClass SCAsWritten = SC_None,
bool isInline = false,
bool hasWrittenPrototype = true);
+ DeclarationNameInfo getNameInfo() const {
+ return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc);
+ }
+
virtual void getNameForDiagnostic(std::string &S,
const PrintingPolicy &Policy,
bool Qualified) const;
@@ -1245,7 +1217,7 @@ public:
/// set that function declaration to the actual declaration
/// containing the body (if there is one).
/// NOTE: For checking if there is a body, use hasBody() instead, to avoid
- /// unnecessary PCH de-serialization of the body.
+ /// unnecessary AST de-serialization of the body.
Stmt *getBody(const FunctionDecl *&Definition) const;
virtual Stmt *getBody() const {
@@ -1389,12 +1361,18 @@ public:
}
StorageClass getStorageClass() const { return StorageClass(SClass); }
- void setStorageClass(StorageClass SC) { SClass = SC; }
+ void setStorageClass(StorageClass SC) {
+ assert(isLegalForFunction(SC));
+ SClass = SC;
+ }
StorageClass getStorageClassAsWritten() const {
return StorageClass(SClassAsWritten);
}
- void setStorageClassAsWritten(StorageClass SC) { SClassAsWritten = SC; }
+ void setStorageClassAsWritten(StorageClass SC) {
+ assert(isLegalForFunction(SC));
+ SClassAsWritten = SC;
+ }
/// \brief Determine whether the "inline" keyword was specified for this
/// function.
@@ -1632,8 +1610,8 @@ public:
return static_cast<FunctionDecl *>(const_cast<DeclContext*>(DC));
}
- friend class PCHDeclReader;
- friend class PCHDeclWriter;
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
};
@@ -1705,7 +1683,6 @@ protected:
const llvm::APSInt &V)
: ValueDecl(EnumConstant, DC, L, Id, T), Init((Stmt*)E), Val(V) {}
- virtual ~EnumConstantDecl() {}
public:
static EnumConstantDecl *Create(ASTContext &C, EnumDecl *DC,
@@ -1713,8 +1690,6 @@ public:
QualType T, Expr *E,
const llvm::APSInt &V);
- virtual void Destroy(ASTContext& C);
-
const Expr *getInitExpr() const { return (const Expr*) Init; }
Expr *getInitExpr() { return (Expr*) Init; }
const llvm::APSInt &getInitVal() const { return Val; }
@@ -1722,6 +1697,8 @@ public:
void setInitExpr(Expr *E) { Init = (Stmt*) E; }
void setInitVal(const llvm::APSInt &V) { Val = V; }
+ SourceRange getSourceRange() const;
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const EnumConstantDecl *D) { return true; }
@@ -1770,8 +1747,6 @@ class TypedefDecl : public TypeDecl, public Redeclarable<TypedefDecl> {
IdentifierInfo *Id, TypeSourceInfo *TInfo)
: TypeDecl(Typedef, DC, L, Id), TInfo(TInfo) {}
- virtual ~TypedefDecl();
-
protected:
typedef Redeclarable<TypedefDecl> redeclarable_base;
virtual TypedefDecl *getNextRedeclaration() { return RedeclLink.getNext(); }
@@ -1832,6 +1807,9 @@ private:
/// it is a declaration ("struct foo;").
bool IsDefinition : 1;
+ /// IsBeingDefined - True if this is currently being defined.
+ bool IsBeingDefined : 1;
+
/// IsEmbeddedInDeclarator - True if this tag declaration is
/// "embedded" (i.e., defined or declared for the very first time)
/// in the syntax of a declarator.
@@ -1873,6 +1851,7 @@ protected:
"EnumDecl not matched with TTK_Enum");
TagDeclKind = TK;
IsDefinition = false;
+ IsBeingDefined = false;
IsEmbeddedInDeclarator = false;
setPreviousDeclaration(PrevDecl);
}
@@ -1881,8 +1860,6 @@ protected:
virtual TagDecl *getNextRedeclaration() { return RedeclLink.getNext(); }
public:
- void Destroy(ASTContext &C);
-
typedef redeclarable_base::redecl_iterator redecl_iterator;
redecl_iterator redecls_begin() const {
return redeclarable_base::redecls_begin();
@@ -1911,11 +1888,22 @@ public:
return const_cast<TagDecl*>(this)->getCanonicalDecl();
}
+ /// isThisDeclarationADefinition() - Return true if this declaration
+ /// defines the type. Provided for consistency.
+ bool isThisDeclarationADefinition() const {
+ return isDefinition();
+ }
+
/// isDefinition - Return true if this decl has its body specified.
bool isDefinition() const {
return IsDefinition;
}
+ /// isBeingDefined - Return true if this decl is currently being defined.
+ bool isBeingDefined() const {
+ return IsBeingDefined;
+ }
+
bool isEmbeddedInDeclarator() const {
return IsEmbeddedInDeclarator;
}
@@ -2003,8 +1991,8 @@ public:
return static_cast<TagDecl *>(const_cast<DeclContext*>(DC));
}
- friend class PCHDeclReader;
- friend class PCHDeclWriter;
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
};
/// EnumDecl - Represents an enum. As an extension, we allow forward-declared
@@ -2037,6 +2025,8 @@ class EnumDecl : public TagDecl {
IdentifierInfo *Id, EnumDecl *PrevDecl, SourceLocation TKL)
: TagDecl(Enum, TTK_Enum, DC, L, Id, PrevDecl, TKL), InstantiatedFrom(0) {
IntegerType = QualType();
+ NumNegativeBits = 0;
+ NumPositiveBits = 0;
}
public:
EnumDecl *getCanonicalDecl() {
@@ -2058,8 +2048,6 @@ public:
SourceLocation TKL, EnumDecl *PrevDecl);
static EnumDecl *Create(ASTContext &C, EmptyShell Empty);
- virtual void Destroy(ASTContext& C);
-
/// completeDefinition - When created, the EnumDecl corresponds to a
/// forward-declared enum. This method is used to mark the
/// declaration as being defined; it's enumerators have already been
@@ -2167,7 +2155,6 @@ protected:
RecordDecl(Kind DK, TagKind TK, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
RecordDecl *PrevDecl, SourceLocation TKL);
- virtual ~RecordDecl();
public:
static RecordDecl *Create(ASTContext &C, TagKind TK, DeclContext *DC,
@@ -2183,8 +2170,6 @@ public:
return cast_or_null<RecordDecl>(TagDecl::getPreviousDeclaration());
}
- virtual void Destroy(ASTContext& C);
-
bool hasFlexibleArrayMember() const { return HasFlexibleArrayMember; }
void setHasFlexibleArrayMember(bool V) { HasFlexibleArrayMember = V; }
@@ -2307,9 +2292,6 @@ protected:
IsVariadic(false), ParamInfo(0), NumParams(0), Body(0),
SignatureAsWritten(0) {}
- virtual ~BlockDecl();
- virtual void Destroy(ASTContext& C);
-
public:
static BlockDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L);
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index be30b8ed296b..1369c2b5955a 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -222,11 +222,13 @@ protected:
// NOTE: VC++ treats enums as signed, avoid using the AccessSpecifier enum
unsigned Access : 2;
friend class CXXClassMemberWrapper;
-
- // PCHLevel - the "level" of precompiled header/AST file from which this
- // declaration was built.
- unsigned PCHLevel : 3;
-
+
+ /// PCHLevel - the "level" of AST file from which this declaration was built.
+ unsigned PCHLevel : 2;
+
+ /// ChangedAfterLoad - if this declaration has changed since being loaded
+ bool ChangedAfterLoad : 1;
+
/// IdentifierNamespace - This specifies what IDNS_* namespace this lives in.
unsigned IdentifierNamespace : 15;
@@ -243,7 +245,7 @@ protected:
: NextDeclInContext(0), DeclCtx(DC),
Loc(L), DeclKind(DK), InvalidDecl(0),
HasAttrs(false), Implicit(false), Used(false),
- Access(AS_none), PCHLevel(0),
+ Access(AS_none), PCHLevel(0), ChangedAfterLoad(false),
IdentifierNamespace(getIdentifierNamespaceForKind(DK)) {
if (Decl::CollectingStats()) add(DK);
}
@@ -251,7 +253,7 @@ protected:
Decl(Kind DK, EmptyShell Empty)
: NextDeclInContext(0), DeclKind(DK), InvalidDecl(0),
HasAttrs(false), Implicit(false), Used(false),
- Access(AS_none), PCHLevel(0),
+ Access(AS_none), PCHLevel(0), ChangedAfterLoad(false),
IdentifierNamespace(getIdentifierNamespaceForKind(DK)) {
if (Decl::CollectingStats()) add(DK);
}
@@ -305,24 +307,52 @@ public:
}
bool hasAttrs() const { return HasAttrs; }
- void initAttrs(Attr *attrs);
- void addAttr(Attr *attr);
- const Attr *getAttrs() const {
- if (!HasAttrs) return 0; // common case, no attributes.
- return getAttrsImpl(); // Uncommon case, out of line hash lookup.
+ void setAttrs(const AttrVec& Attrs);
+ AttrVec& getAttrs() {
+ return const_cast<AttrVec&>(const_cast<const Decl*>(this)->getAttrs());
}
+ const AttrVec &getAttrs() const;
void swapAttrs(Decl *D);
- void invalidateAttrs();
+ void dropAttrs();
+
+ void addAttr(Attr *A) {
+ if (hasAttrs())
+ getAttrs().push_back(A);
+ else
+ setAttrs(AttrVec(1, A));
+ }
+
+ typedef AttrVec::const_iterator attr_iterator;
+
+ // FIXME: Do not rely on iterators having comparable singular values.
+ // Note that this should error out if they do not.
+ attr_iterator attr_begin() const {
+ return hasAttrs() ? getAttrs().begin() : 0;
+ }
+ attr_iterator attr_end() const {
+ return hasAttrs() ? getAttrs().end() : 0;
+ }
- template<typename T> const T *getAttr() const {
- for (const Attr *attr = getAttrs(); attr; attr = attr->getNext())
- if (const T *V = dyn_cast<T>(attr))
- return V;
- return 0;
+ template <typename T>
+ specific_attr_iterator<T> specific_attr_begin() const {
+ return specific_attr_iterator<T>(attr_begin());
+ }
+ template <typename T>
+ specific_attr_iterator<T> specific_attr_end() const {
+ return specific_attr_iterator<T>(attr_end());
}
+ template<typename T> T *getAttr() const {
+ return hasAttrs() ? getSpecificAttr<T>(getAttrs()) : 0;
+ }
template<typename T> bool hasAttr() const {
- return getAttr<T>() != 0;
+ return hasAttrs() && hasSpecificAttr<T>(getAttrs());
+ }
+
+ /// getMaxAlignment - return the maximum alignment specified by attributes
+ /// on this decl, 0 if there are none.
+ unsigned getMaxAlignment() const {
+ return hasAttrs() ? getMaxAttrAlignment(getAttrs(), getASTContext()) : 0;
}
/// setInvalidDecl - Indicates the Decl had a semantic error. This
@@ -343,22 +373,21 @@ public:
/// (in addition to the "used" bit set by \c setUsed()) when determining
/// whether the function is used.
bool isUsed(bool CheckUsedAttr = true) const;
-
+
void setUsed(bool U = true) { Used = U; }
/// \brief Retrieve the level of precompiled header from which this
/// declaration was generated.
///
/// The PCH level of a declaration describes where the declaration originated
- /// from. A PCH level of 0 indicates that the declaration was not from a
- /// precompiled header. A PCH level of 1 indicates that the declaration was
- /// from a top-level precompiled header; 2 indicates that the declaration
- /// comes from a precompiled header on which the top-level precompiled header
- /// depends, and so on.
+ /// from. A PCH level of 0 indicates that the declaration was parsed from
+ /// source. A PCH level of 1 indicates that the declaration was loaded from
+ /// a top-level AST file. A PCH level 2 indicates that the declaration was
+ /// loaded from a PCH file the AST file depends on, and so on.
unsigned getPCHLevel() const { return PCHLevel; }
/// \brief The maximum PCH level that any declaration may have.
- static const unsigned MaxPCHLevel = 7;
+ static const unsigned MaxPCHLevel = 3;
/// \brief Set the PCH level of this declaration.
void setPCHLevel(unsigned Level) {
@@ -366,6 +395,19 @@ public:
PCHLevel = Level;
}
+ /// \brief Query whether this declaration was changed in a significant way
+ /// since being loaded from an AST file.
+ ///
+ /// In an epic violation of layering, what is "significant" is entirely
+ /// up to the serialization system, but implemented in AST and Sema.
+ bool isChangedSinceDeserialization() const { return ChangedAfterLoad; }
+
+ /// \brief Mark this declaration as having changed since deserialization, or
+ /// reset the flag.
+ void setChangedSinceDeserialization(bool Changed) {
+ ChangedAfterLoad = Changed;
+ }
+
unsigned getIdentifierNamespace() const {
return IdentifierNamespace;
}
@@ -411,10 +453,10 @@ public:
void setLexicalDeclContext(DeclContext *DC);
- // isDefinedOutsideFunctionOrMethod - This predicate returns true if this
- // scoped decl is defined outside the current function or method. This is
- // roughly global variables and functions, but also handles enums (which could
- // be defined inside or outside a function etc).
+ /// isDefinedOutsideFunctionOrMethod - This predicate returns true if this
+ /// scoped decl is defined outside the current function or method. This is
+ /// roughly global variables and functions, but also handles enums (which
+ /// could be defined inside or outside a function etc).
bool isDefinedOutsideFunctionOrMethod() const;
/// \brief Retrieves the "canonical" declaration of the given declaration.
@@ -572,9 +614,6 @@ public:
static DeclContext *castToDeclContext(const Decl *);
static Decl *castFromDeclContext(const DeclContext *);
- /// Destroy - Call destructors and release memory.
- virtual void Destroy(ASTContext& C);
-
void print(llvm::raw_ostream &Out, unsigned Indentation = 0) const;
void print(llvm::raw_ostream &Out, const PrintingPolicy &Policy,
unsigned Indentation = 0) const;
@@ -603,6 +642,29 @@ public:
virtual void print(llvm::raw_ostream &OS) const;
};
+class DeclContextLookupResult
+ : public std::pair<NamedDecl**,NamedDecl**> {
+public:
+ DeclContextLookupResult(NamedDecl **I, NamedDecl **E)
+ : std::pair<NamedDecl**,NamedDecl**>(I, E) {}
+ DeclContextLookupResult()
+ : std::pair<NamedDecl**,NamedDecl**>() {}
+
+ using std::pair<NamedDecl**,NamedDecl**>::operator=;
+};
+
+class DeclContextLookupConstResult
+ : public std::pair<NamedDecl*const*, NamedDecl*const*> {
+public:
+ DeclContextLookupConstResult(std::pair<NamedDecl**,NamedDecl**> R)
+ : std::pair<NamedDecl*const*, NamedDecl*const*>(R) {}
+ DeclContextLookupConstResult(NamedDecl * const *I, NamedDecl * const *E)
+ : std::pair<NamedDecl*const*, NamedDecl*const*>(I, E) {}
+ DeclContextLookupConstResult()
+ : std::pair<NamedDecl*const*, NamedDecl*const*>() {}
+
+ using std::pair<NamedDecl*const*,NamedDecl*const*>::operator=;
+};
/// DeclContext - This is used only as base class of specific decl types that
/// can act as declaration contexts. These decls are (only the top classes
@@ -654,8 +716,6 @@ protected:
ExternalVisibleStorage(false), LookupPtr(0), FirstDecl(0),
LastDecl(0) { }
- void DestroyDecls(ASTContext &C);
-
public:
~DeclContext();
@@ -724,6 +784,8 @@ public:
return DeclKind == Decl::Namespace;
}
+ bool isInlineNamespace() const;
+
/// \brief Determines whether this context is dependent on a
/// template parameter.
bool isDependentContext() const;
@@ -742,19 +804,18 @@ public:
/// Here, E is a transparent context, so its enumerator (Val1) will
/// appear (semantically) that it is in the same context of E.
/// Examples of transparent contexts include: enumerations (except for
- /// C++0x scoped enums), C++ linkage specifications, and C++0x
- /// inline namespaces.
+ /// C++0x scoped enums), and C++ linkage specifications.
bool isTransparentContext() const;
/// \brief Determine whether this declaration context is equivalent
/// to the declaration context DC.
- bool Equals(DeclContext *DC) {
+ bool Equals(const DeclContext *DC) const {
return DC && this->getPrimaryContext() == DC->getPrimaryContext();
}
/// \brief Determine whether this declaration context encloses the
/// declaration context DC.
- bool Encloses(DeclContext *DC);
+ bool Encloses(const DeclContext *DC) const;
/// getPrimaryContext - There may be many different
/// declarations of the same entity (including forward declarations
@@ -767,13 +828,12 @@ public:
return const_cast<DeclContext*>(this)->getPrimaryContext();
}
- /// getLookupContext - Retrieve the innermost non-transparent
- /// context of this context, which corresponds to the innermost
- /// location from which name lookup can find the entities in this
- /// context.
- DeclContext *getLookupContext();
- const DeclContext *getLookupContext() const {
- return const_cast<DeclContext *>(this)->getLookupContext();
+ /// getRedeclContext - Retrieve the context in which an entity conflicts with
+ /// other entities of the same name, or where it is a redeclaration if the
+ /// two entities are compatible. This skips through transparent contexts.
+ DeclContext *getRedeclContext();
+ const DeclContext *getRedeclContext() const {
+ return const_cast<DeclContext *>(this)->getRedeclContext();
}
/// \brief Retrieve the nearest enclosing namespace context.
@@ -782,6 +842,14 @@ public:
return const_cast<DeclContext *>(this)->getEnclosingNamespaceContext();
}
+ /// \brief Test if this context is part of the enclosing namespace set of
+ /// the context NS, as defined in C++0x [namespace.def]p9. If either context
+ /// isn't a namespace, this is equivalent to Equals().
+ ///
+ /// The enclosing namespace set of a namespace is the namespace and, if it is
+ /// inline, its enclosing namespace, recursively.
+ bool InEnclosingNamespaceSetOf(const DeclContext *NS) const;
+
/// getNextContext - If this is a DeclContext that may have other
/// DeclContexts that are semantically connected but syntactically
/// different, such as C++ namespaces, this routine retrieves the
@@ -845,6 +913,12 @@ public:
decl_iterator decls_end() const;
bool decls_empty() const;
+ /// noload_decls_begin/end - Iterate over the declarations stored in this
+ /// context that are currently loaded; don't attempt to retrieve anything
+ /// from an external source.
+ decl_iterator noload_decls_begin() const;
+ decl_iterator noload_decls_end() const;
+
/// specific_decl_iterator - Iterates over a subrange of
/// declarations stored in a DeclContext, providing only those that
/// are of type SpecificDecl (or a class derived from it). This
@@ -1020,9 +1094,8 @@ public:
/// access to the results of lookup up a name within this context.
typedef NamedDecl * const * lookup_const_iterator;
- typedef std::pair<lookup_iterator, lookup_iterator> lookup_result;
- typedef std::pair<lookup_const_iterator, lookup_const_iterator>
- lookup_const_result;
+ typedef DeclContextLookupResult lookup_result;
+ typedef DeclContextLookupConstResult lookup_const_result;
/// lookup - Find the declarations (if any) with the given Name in
/// this context. Returns a range of iterators that contains all of
@@ -1052,6 +1125,14 @@ public:
/// the declaration chains.
void makeDeclVisibleInContext(NamedDecl *D, bool Recoverable = true);
+ /// \brief Deserialize all the visible declarations from external storage.
+ ///
+ /// Name lookup deserializes visible declarations lazily, thus a DeclContext
+ /// may not have a complete name lookup table. This function deserializes
+ /// the rest of visible declarations from the external storage and completes
+ /// the name lookup table.
+ void MaterializeVisibleDeclsFromExternalStorage();
+
/// udir_iterator - Iterates through the using-directives stored
/// within this context.
typedef UsingDirectiveDecl * const * udir_iterator;
@@ -1109,7 +1190,6 @@ public:
private:
void LoadLexicalDeclsFromExternalStorage() const;
- void LoadVisibleDeclsFromExternalStorage() const;
friend class DependentDiagnostic;
StoredDeclsMap *CreateStoredDeclsMap(ASTContext &C) const;
@@ -1123,7 +1203,6 @@ inline bool Decl::isTemplateParameter() const {
getKind() == TemplateTemplateParm;
}
-
// Specialization selected when ToTy is not a known subclass of DeclContext.
template <class ToTy,
bool IsKnownSubtype = ::llvm::is_base_of< DeclContext, ToTy>::value>
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index 41474ab21e32..a9802bfcaf4e 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/include/clang/AST/DeclCXX.h
@@ -17,6 +17,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/TypeLoc.h"
#include "clang/AST/UnresolvedSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/SmallPtrSet.h"
@@ -159,7 +160,6 @@ class CXXBaseSpecifier {
/// Range - The source code range that covers the full base
/// specifier, including the "virtual" (if present) and access
/// specifier (if present).
- // FIXME: Move over to a TypeLoc!
SourceRange Range;
/// Virtual - Whether this is a virtual base class or not.
@@ -177,15 +177,17 @@ class CXXBaseSpecifier {
/// VC++ bug.
unsigned Access : 2;
- /// BaseType - The type of the base class. This will be a class or
- /// struct (or a typedef of such).
- QualType BaseType;
+ /// BaseTypeInfo - The type of the base class. This will be a class or struct
+ /// (or a typedef of such). The source code range does not include the
+ /// "virtual" or access specifier.
+ TypeSourceInfo *BaseTypeInfo;
public:
CXXBaseSpecifier() { }
- CXXBaseSpecifier(SourceRange R, bool V, bool BC, AccessSpecifier A, QualType T)
- : Range(R), Virtual(V), BaseOfClass(BC), Access(A), BaseType(T) { }
+ CXXBaseSpecifier(SourceRange R, bool V, bool BC, AccessSpecifier A,
+ TypeSourceInfo *TInfo)
+ : Range(R), Virtual(V), BaseOfClass(BC), Access(A), BaseTypeInfo(TInfo) { }
/// getSourceRange - Retrieves the source range that contains the
/// entire base specifier.
@@ -195,7 +197,7 @@ public:
/// class (or not).
bool isVirtual() const { return Virtual; }
- /// \brief Determine whether this base class if a base of a class declared
+ /// \brief Determine whether this base class is a base of a class declared
/// with the 'class' keyword (vs. one declared with the 'struct' keyword).
bool isBaseOfClass() const { return BaseOfClass; }
@@ -221,7 +223,10 @@ public:
/// getType - Retrieves the type of the base class. This type will
/// always be an unqualified class type.
- QualType getType() const { return BaseType; }
+ QualType getType() const { return BaseTypeInfo->getType(); }
+
+ /// getTypeLoc - Retrieves the type and source location of the base class.
+ TypeSourceInfo *getTypeSourceInfo() const { return BaseTypeInfo; }
};
/// CXXRecordDecl - Represents a C++ struct/union/class.
@@ -400,8 +405,6 @@ protected:
CXXRecordDecl *PrevDecl,
SourceLocation TKL = SourceLocation());
- ~CXXRecordDecl();
-
public:
/// base_class_iterator - Iterator that traverses the base classes
/// of a class.
@@ -449,8 +452,6 @@ public:
bool DelayTypeCreation = false);
static CXXRecordDecl *Create(ASTContext &C, EmptyShell Empty);
- virtual void Destroy(ASTContext& C);
-
bool isDynamicClass() const {
return data().Polymorphic || data().NumVBases != 0;
}
@@ -1056,29 +1057,30 @@ public:
return true;
}
- friend class PCHDeclReader;
- friend class PCHDeclWriter;
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
};
/// CXXMethodDecl - Represents a static or instance method of a
/// struct/union/class.
class CXXMethodDecl : public FunctionDecl {
protected:
- CXXMethodDecl(Kind DK, CXXRecordDecl *RD, SourceLocation L,
- DeclarationName N, QualType T, TypeSourceInfo *TInfo,
+ CXXMethodDecl(Kind DK, CXXRecordDecl *RD,
+ const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo *TInfo,
bool isStatic, StorageClass SCAsWritten, bool isInline)
- : FunctionDecl(DK, RD, L, N, T, TInfo, (isStatic ? Static : None),
+ : FunctionDecl(DK, RD, NameInfo, T, TInfo, (isStatic ? SC_Static : SC_None),
SCAsWritten, isInline) {}
public:
static CXXMethodDecl *Create(ASTContext &C, CXXRecordDecl *RD,
- SourceLocation L, DeclarationName N,
- QualType T, TypeSourceInfo *TInfo,
- bool isStatic = false,
- StorageClass SCAsWritten = FunctionDecl::None,
- bool isInline = false);
+ const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo *TInfo,
+ bool isStatic = false,
+ StorageClass SCAsWritten = SC_None,
+ bool isInline = false);
- bool isStatic() const { return getStorageClass() == Static; }
+ bool isStatic() const { return getStorageClass() == SC_Static; }
bool isInstance() const { return !isStatic(); }
bool isVirtual() const {
@@ -1249,9 +1251,6 @@ public:
VarDecl **Indices,
unsigned NumIndices);
- /// \brief Destroy the base or member initializer.
- void Destroy(ASTContext &Context);
-
/// isBaseInitializer - Returns true when this initializer is
/// initializing a base class.
bool isBaseInitializer() const { return BaseOrMember.is<TypeSourceInfo*>(); }
@@ -1285,7 +1284,7 @@ public:
/// getMember - If this is a member initializer, returns the
/// declaration of the non-static data member being
/// initialized. Otherwise, returns NULL.
- FieldDecl *getMember() {
+ FieldDecl *getMember() const {
if (isMemberInitializer())
return BaseOrMember.get<FieldDecl*>();
else
@@ -1363,7 +1362,7 @@ public:
reinterpret_cast<VarDecl **>(this + 1)[I] = Index;
}
- Expr *getInit() { return static_cast<Expr *>(Init); }
+ Expr *getInit() const { return static_cast<Expr *>(Init); }
};
/// CXXConstructorDecl - Represents a C++ constructor within a
@@ -1394,22 +1393,21 @@ class CXXConstructorDecl : public CXXMethodDecl {
CXXBaseOrMemberInitializer **BaseOrMemberInitializers;
unsigned NumBaseOrMemberInitializers;
- CXXConstructorDecl(CXXRecordDecl *RD, SourceLocation L,
- DeclarationName N, QualType T, TypeSourceInfo *TInfo,
+ CXXConstructorDecl(CXXRecordDecl *RD, const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo *TInfo,
bool isExplicitSpecified, bool isInline,
bool isImplicitlyDeclared)
- : CXXMethodDecl(CXXConstructor, RD, L, N, T, TInfo, false,
- FunctionDecl::None, isInline),
+ : CXXMethodDecl(CXXConstructor, RD, NameInfo, T, TInfo, false,
+ SC_None, isInline),
IsExplicitSpecified(isExplicitSpecified), ImplicitlyDefined(false),
BaseOrMemberInitializers(0), NumBaseOrMemberInitializers(0) {
setImplicit(isImplicitlyDeclared);
}
- virtual void Destroy(ASTContext& C);
public:
static CXXConstructorDecl *Create(ASTContext &C, EmptyShell Empty);
static CXXConstructorDecl *Create(ASTContext &C, CXXRecordDecl *RD,
- SourceLocation L, DeclarationName N,
+ const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
bool isExplicit,
bool isInline, bool isImplicitlyDeclared);
@@ -1519,8 +1517,8 @@ public:
static bool classof(const CXXConstructorDecl *D) { return true; }
static bool classofKind(Kind K) { return K == CXXConstructor; }
- friend class PCHDeclReader;
- friend class PCHDeclWriter;
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
};
/// CXXDestructorDecl - Represents a C++ destructor within a
@@ -1543,11 +1541,10 @@ class CXXDestructorDecl : public CXXMethodDecl {
FunctionDecl *OperatorDelete;
- CXXDestructorDecl(CXXRecordDecl *RD, SourceLocation L,
- DeclarationName N, QualType T,
- bool isInline, bool isImplicitlyDeclared)
- : CXXMethodDecl(CXXDestructor, RD, L, N, T, /*TInfo=*/0, false,
- FunctionDecl::None, isInline),
+ CXXDestructorDecl(CXXRecordDecl *RD, const DeclarationNameInfo &NameInfo,
+ QualType T, bool isInline, bool isImplicitlyDeclared)
+ : CXXMethodDecl(CXXDestructor, RD, NameInfo, T, /*TInfo=*/0, false,
+ SC_None, isInline),
ImplicitlyDefined(false), OperatorDelete(0) {
setImplicit(isImplicitlyDeclared);
}
@@ -1555,7 +1552,7 @@ class CXXDestructorDecl : public CXXMethodDecl {
public:
static CXXDestructorDecl *Create(ASTContext& C, EmptyShell Empty);
static CXXDestructorDecl *Create(ASTContext &C, CXXRecordDecl *RD,
- SourceLocation L, DeclarationName N,
+ const DeclarationNameInfo &NameInfo,
QualType T, bool isInline,
bool isImplicitlyDeclared);
@@ -1585,8 +1582,8 @@ public:
static bool classof(const CXXDestructorDecl *D) { return true; }
static bool classofKind(Kind K) { return K == CXXDestructor; }
- friend class PCHDeclReader;
- friend class PCHDeclWriter;
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
};
/// CXXConversionDecl - Represents a C++ conversion function within a
@@ -1604,17 +1601,17 @@ class CXXConversionDecl : public CXXMethodDecl {
/// explicitly wrote a cast. This is a C++0x feature.
bool IsExplicitSpecified : 1;
- CXXConversionDecl(CXXRecordDecl *RD, SourceLocation L,
- DeclarationName N, QualType T, TypeSourceInfo *TInfo,
+ CXXConversionDecl(CXXRecordDecl *RD, const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo *TInfo,
bool isInline, bool isExplicitSpecified)
- : CXXMethodDecl(CXXConversion, RD, L, N, T, TInfo, false,
- FunctionDecl::None, isInline),
+ : CXXMethodDecl(CXXConversion, RD, NameInfo, T, TInfo, false,
+ SC_None, isInline),
IsExplicitSpecified(isExplicitSpecified) { }
public:
static CXXConversionDecl *Create(ASTContext &C, EmptyShell Empty);
static CXXConversionDecl *Create(ASTContext &C, CXXRecordDecl *RD,
- SourceLocation L, DeclarationName N,
+ const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
bool isInline, bool isExplicit);
@@ -1642,8 +1639,8 @@ public:
static bool classof(const CXXConversionDecl *D) { return true; }
static bool classofKind(Kind K) { return K == CXXConversion; }
- friend class PCHDeclReader;
- friend class PCHDeclWriter;
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
};
/// LinkageSpecDecl - This represents a linkage specification. For example:
@@ -1710,7 +1707,9 @@ public:
// artificial name, for all using-directives in order to store
// them in DeclContext effectively.
class UsingDirectiveDecl : public NamedDecl {
-
+ /// \brief The location of the "using" keyword.
+ SourceLocation UsingLoc;
+
/// SourceLocation - Location of 'namespace' token.
SourceLocation NamespaceLoc;
@@ -1722,10 +1721,6 @@ class UsingDirectiveDecl : public NamedDecl {
/// name, if any.
NestedNameSpecifier *Qualifier;
- /// IdentLoc - Location of nominated namespace-name identifier.
- // FIXME: We don't store location of scope specifier.
- SourceLocation IdentLoc;
-
/// NominatedNamespace - Namespace nominated by using-directive.
NamedDecl *NominatedNamespace;
@@ -1740,17 +1735,16 @@ class UsingDirectiveDecl : public NamedDecl {
return DeclarationName::getUsingDirectiveName();
}
- UsingDirectiveDecl(DeclContext *DC, SourceLocation L,
+ UsingDirectiveDecl(DeclContext *DC, SourceLocation UsingLoc,
SourceLocation NamespcLoc,
SourceRange QualifierRange,
NestedNameSpecifier *Qualifier,
SourceLocation IdentLoc,
NamedDecl *Nominated,
DeclContext *CommonAncestor)
- : NamedDecl(UsingDirective, DC, L, getName()),
+ : NamedDecl(UsingDirective, DC, IdentLoc, getName()), UsingLoc(UsingLoc),
NamespaceLoc(NamespcLoc), QualifierRange(QualifierRange),
- Qualifier(Qualifier), IdentLoc(IdentLoc),
- NominatedNamespace(Nominated),
+ Qualifier(Qualifier), NominatedNamespace(Nominated),
CommonAncestor(CommonAncestor) {
}
@@ -1759,18 +1753,10 @@ public:
/// that qualifies the namespace name.
SourceRange getQualifierRange() const { return QualifierRange; }
- /// \brief Set the source range of the nested-name-specifier that
- /// qualifies the namespace name.
- void setQualifierRange(SourceRange R) { QualifierRange = R; }
-
/// \brief Retrieve the nested-name-specifier that qualifies the
/// name of the namespace.
NestedNameSpecifier *getQualifier() const { return Qualifier; }
- /// \brief Set the nested-name-specifier that qualifes the name of the
- /// namespace.
- void setQualifier(NestedNameSpecifier *NNS) { Qualifier = NNS; }
-
NamedDecl *getNominatedNamespaceAsWritten() { return NominatedNamespace; }
const NamedDecl *getNominatedNamespaceAsWritten() const {
return NominatedNamespace;
@@ -1783,34 +1769,23 @@ public:
return const_cast<UsingDirectiveDecl*>(this)->getNominatedNamespace();
}
- /// setNominatedNamespace - Set the namespace nominataed by the
- /// using-directive.
- void setNominatedNamespace(NamedDecl* NS);
-
/// \brief Returns the common ancestor context of this using-directive and
/// its nominated namespace.
DeclContext *getCommonAncestor() { return CommonAncestor; }
const DeclContext *getCommonAncestor() const { return CommonAncestor; }
- /// \brief Set the common ancestor context of this using-directive and its
- /// nominated namespace.
- void setCommonAncestor(DeclContext* Cxt) { CommonAncestor = Cxt; }
-
+ /// \brief Return the location of the "using" keyword.
+ SourceLocation getUsingLoc() const { return UsingLoc; }
+
// FIXME: Could omit 'Key' in name.
/// getNamespaceKeyLocation - Returns location of namespace keyword.
SourceLocation getNamespaceKeyLocation() const { return NamespaceLoc; }
- /// setNamespaceKeyLocation - Set the the location of the namespacekeyword.
- void setNamespaceKeyLocation(SourceLocation L) { NamespaceLoc = L; }
-
/// getIdentLocation - Returns location of identifier.
- SourceLocation getIdentLocation() const { return IdentLoc; }
-
- /// setIdentLocation - set the location of the identifier.
- void setIdentLocation(SourceLocation L) { IdentLoc = L; }
+ SourceLocation getIdentLocation() const { return getLocation(); }
static UsingDirectiveDecl *Create(ASTContext &C, DeclContext *DC,
- SourceLocation L,
+ SourceLocation UsingLoc,
SourceLocation NamespaceLoc,
SourceRange QualifierRange,
NestedNameSpecifier *Qualifier,
@@ -1818,12 +1793,18 @@ public:
NamedDecl *Nominated,
DeclContext *CommonAncestor);
+ SourceRange getSourceRange() const {
+ return SourceRange(UsingLoc, getLocation());
+ }
+
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const UsingDirectiveDecl *D) { return true; }
static bool classofKind(Kind K) { return K == UsingDirective; }
// Friend for getUsingDirectiveName.
friend class DeclContext;
+
+ friend class ASTDeclReader;
};
/// NamespaceAliasDecl - Represents a C++ namespace alias. For example:
@@ -1832,7 +1813,8 @@ public:
/// namespace Foo = Bar;
/// @endcode
class NamespaceAliasDecl : public NamedDecl {
- SourceLocation AliasLoc;
+ /// \brief The location of the "namespace" keyword.
+ SourceLocation NamespaceLoc;
/// \brief The source range that covers the nested-name-specifier
/// preceding the namespace name.
@@ -1849,15 +1831,17 @@ class NamespaceAliasDecl : public NamedDecl {
/// NamespaceDecl or a NamespaceAliasDecl.
NamedDecl *Namespace;
- NamespaceAliasDecl(DeclContext *DC, SourceLocation L,
+ NamespaceAliasDecl(DeclContext *DC, SourceLocation NamespaceLoc,
SourceLocation AliasLoc, IdentifierInfo *Alias,
SourceRange QualifierRange,
NestedNameSpecifier *Qualifier,
SourceLocation IdentLoc, NamedDecl *Namespace)
- : NamedDecl(NamespaceAlias, DC, L, Alias), AliasLoc(AliasLoc),
- QualifierRange(QualifierRange), Qualifier(Qualifier),
- IdentLoc(IdentLoc), Namespace(Namespace) { }
+ : NamedDecl(NamespaceAlias, DC, AliasLoc, Alias),
+ NamespaceLoc(NamespaceLoc), QualifierRange(QualifierRange),
+ Qualifier(Qualifier), IdentLoc(IdentLoc), Namespace(Namespace) { }
+ friend class ASTDeclReader;
+
public:
/// \brief Retrieve the source range of the nested-name-specifier
/// that qualifiers the namespace name.
@@ -1889,41 +1873,31 @@ public:
/// Returns the location of the alias name, i.e. 'foo' in
/// "namespace foo = ns::bar;".
- SourceLocation getAliasLoc() const { return AliasLoc; }
-
- /// Set the location o;f the alias name, e.e., 'foo' in
- /// "namespace foo = ns::bar;".
- void setAliasLoc(SourceLocation L) { AliasLoc = L; }
+ SourceLocation getAliasLoc() const { return getLocation(); }
/// Returns the location of the 'namespace' keyword.
- SourceLocation getNamespaceLoc() const { return getLocation(); }
+ SourceLocation getNamespaceLoc() const { return NamespaceLoc; }
/// Returns the location of the identifier in the named namespace.
SourceLocation getTargetNameLoc() const { return IdentLoc; }
- /// Set the location of the identifier in the named namespace.
- void setTargetNameLoc(SourceLocation L) { IdentLoc = L; }
-
/// \brief Retrieve the namespace that this alias refers to, which
/// may either be a NamespaceDecl or a NamespaceAliasDecl.
NamedDecl *getAliasedNamespace() const { return Namespace; }
- /// \brief Set the namespace or namespace alias pointed to by this
- /// alias decl.
- void setAliasedNamespace(NamedDecl *ND) {
- assert((isa<NamespaceAliasDecl>(ND) || isa<NamespaceDecl>(ND)) &&
- "expecting namespace or namespace alias decl");
- Namespace = ND;
- }
-
static NamespaceAliasDecl *Create(ASTContext &C, DeclContext *DC,
- SourceLocation L, SourceLocation AliasLoc,
+ SourceLocation NamespaceLoc,
+ SourceLocation AliasLoc,
IdentifierInfo *Alias,
SourceRange QualifierRange,
NestedNameSpecifier *Qualifier,
SourceLocation IdentLoc,
NamedDecl *Namespace);
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(NamespaceLoc, IdentLoc);
+ }
+
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const NamespaceAliasDecl *D) { return true; }
static bool classofKind(Kind K) { return K == NamespaceAlias; }
@@ -2002,6 +1976,10 @@ class UsingDecl : public NamedDecl {
/// \brief Target nested name specifier.
NestedNameSpecifier* TargetNestedName;
+ /// DNLoc - Provides source/type location info for the
+ /// declaration name embedded in the ValueDecl base class.
+ DeclarationNameLoc DNLoc;
+
/// \brief The collection of shadow declarations associated with
/// this using declaration. This set can change as a class is
/// processed.
@@ -2010,34 +1988,31 @@ class UsingDecl : public NamedDecl {
// \brief Has 'typename' keyword.
bool IsTypeName;
- UsingDecl(DeclContext *DC, SourceLocation L, SourceRange NNR,
+ UsingDecl(DeclContext *DC, SourceRange NNR,
SourceLocation UL, NestedNameSpecifier* TargetNNS,
- DeclarationName Name, bool IsTypeNameArg)
- : NamedDecl(Using, DC, L, Name),
+ const DeclarationNameInfo &NameInfo, bool IsTypeNameArg)
+ : NamedDecl(Using, DC, NameInfo.getLoc(), NameInfo.getName()),
NestedNameRange(NNR), UsingLocation(UL), TargetNestedName(TargetNNS),
- IsTypeName(IsTypeNameArg) {
+ DNLoc(NameInfo.getInfo()), IsTypeName(IsTypeNameArg) {
}
public:
- // FIXME: Should be const?
/// \brief Returns the source range that covers the nested-name-specifier
/// preceding the namespace name.
- SourceRange getNestedNameRange() { return NestedNameRange; }
+ SourceRange getNestedNameRange() const { return NestedNameRange; }
/// \brief Set the source range of the nested-name-specifier.
void setNestedNameRange(SourceRange R) { NestedNameRange = R; }
- // FIXME; Should be const?
// FIXME: Naming is inconsistent with other get*Loc functions.
/// \brief Returns the source location of the "using" keyword.
- SourceLocation getUsingLocation() { return UsingLocation; }
+ SourceLocation getUsingLocation() const { return UsingLocation; }
/// \brief Set the source location of the 'using' keyword.
void setUsingLocation(SourceLocation L) { UsingLocation = L; }
-
/// \brief Get the target nested name declaration.
- NestedNameSpecifier* getTargetNestedNameDecl() {
+ NestedNameSpecifier* getTargetNestedNameDecl() const {
return TargetNestedName;
}
@@ -2046,6 +2021,10 @@ public:
TargetNestedName = NNS;
}
+ DeclarationNameInfo getNameInfo() const {
+ return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc);
+ }
+
/// \brief Return true if the using declaration has 'typename'.
bool isTypeName() const { return IsTypeName; }
@@ -2076,15 +2055,21 @@ public:
}
static UsingDecl *Create(ASTContext &C, DeclContext *DC,
- SourceLocation IdentL, SourceRange NNR, SourceLocation UsingL,
- NestedNameSpecifier* TargetNNS, DeclarationName Name, bool IsTypeNameArg);
+ SourceRange NNR, SourceLocation UsingL,
+ NestedNameSpecifier* TargetNNS,
+ const DeclarationNameInfo &NameInfo,
+ bool IsTypeNameArg);
+
+ SourceRange getSourceRange() const {
+ return SourceRange(UsingLocation, getNameInfo().getEndLoc());
+ }
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const UsingDecl *D) { return true; }
static bool classofKind(Kind K) { return K == Using; }
- friend class PCHDeclReader;
- friend class PCHDeclWriter;
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
};
/// UnresolvedUsingValueDecl - Represents a dependent using
@@ -2105,14 +2090,18 @@ class UnresolvedUsingValueDecl : public ValueDecl {
NestedNameSpecifier *TargetNestedNameSpecifier;
+ /// DNLoc - Provides source/type location info for the
+ /// declaration name embedded in the ValueDecl base class.
+ DeclarationNameLoc DNLoc;
+
UnresolvedUsingValueDecl(DeclContext *DC, QualType Ty,
SourceLocation UsingLoc, SourceRange TargetNNR,
NestedNameSpecifier *TargetNNS,
- SourceLocation TargetNameLoc,
- DeclarationName TargetName)
- : ValueDecl(UnresolvedUsingValue, DC, TargetNameLoc, TargetName, Ty),
- TargetNestedNameRange(TargetNNR), UsingLocation(UsingLoc),
- TargetNestedNameSpecifier(TargetNNS)
+ const DeclarationNameInfo &NameInfo)
+ : ValueDecl(UnresolvedUsingValue, DC,
+ NameInfo.getLoc(), NameInfo.getName(), Ty),
+ TargetNestedNameRange(TargetNNR), UsingLocation(UsingLoc),
+ TargetNestedNameSpecifier(TargetNNS), DNLoc(NameInfo.getInfo())
{ }
public:
@@ -2125,7 +2114,7 @@ public:
void setTargetNestedNameRange(SourceRange R) { TargetNestedNameRange = R; }
/// \brief Get target nested name declaration.
- NestedNameSpecifier* getTargetNestedNameSpecifier() {
+ NestedNameSpecifier* getTargetNestedNameSpecifier() const {
return TargetNestedNameSpecifier;
}
@@ -2140,10 +2129,18 @@ public:
/// \brief Set the source location of the 'using' keyword.
void setUsingLoc(SourceLocation L) { UsingLocation = L; }
+ DeclarationNameInfo getNameInfo() const {
+ return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc);
+ }
+
static UnresolvedUsingValueDecl *
Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc,
SourceRange TargetNNR, NestedNameSpecifier *TargetNNS,
- SourceLocation TargetNameLoc, DeclarationName TargetName);
+ const DeclarationNameInfo &NameInfo);
+
+ SourceRange getSourceRange() const {
+ return SourceRange(UsingLocation, getNameInfo().getEndLoc());
+ }
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const UnresolvedUsingValueDecl *D) { return true; }
@@ -2181,43 +2178,34 @@ class UnresolvedUsingTypenameDecl : public TypeDecl {
TypenameLocation(TypenameLoc), TargetNestedNameSpecifier(TargetNNS)
{ }
+ friend class ASTDeclReader;
+
public:
/// \brief Returns the source range that covers the nested-name-specifier
/// preceding the namespace name.
SourceRange getTargetNestedNameRange() const { return TargetNestedNameRange; }
- /// \brief Set the source range coverting the nested-name-specifier preceding
- /// the namespace name.
- void setTargetNestedNameRange(SourceRange R) { TargetNestedNameRange = R; }
-
/// \brief Get target nested name declaration.
NestedNameSpecifier* getTargetNestedNameSpecifier() {
return TargetNestedNameSpecifier;
}
- /// \brief Set the nested name declaration.
- void setTargetNestedNameSpecifier(NestedNameSpecifier* NNS) {
- TargetNestedNameSpecifier = NNS;
- }
-
/// \brief Returns the source location of the 'using' keyword.
SourceLocation getUsingLoc() const { return UsingLocation; }
- /// \brief Set the source location of the 'using' keyword.
- void setUsingLoc(SourceLocation L) { UsingLocation = L; }
-
/// \brief Returns the source location of the 'typename' keyword.
SourceLocation getTypenameLoc() const { return TypenameLocation; }
- /// \brief Set the source location of the 'typename' keyword.
- void setTypenameLoc(SourceLocation L) { TypenameLocation = L; }
-
static UnresolvedUsingTypenameDecl *
Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc,
SourceLocation TypenameLoc,
SourceRange TargetNNR, NestedNameSpecifier *TargetNNS,
SourceLocation TargetNameLoc, DeclarationName TargetName);
+ SourceRange getSourceRange() const {
+ return SourceRange(UsingLocation, getLocation());
+ }
+
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const UnresolvedUsingTypenameDecl *D) { return true; }
static bool classofKind(Kind K) { return K == UnresolvedUsingTypename; }
@@ -2243,12 +2231,11 @@ public:
StringLiteral *getMessage() { return Message; }
const StringLiteral *getMessage() const { return Message; }
- virtual ~StaticAssertDecl();
- virtual void Destroy(ASTContext& C);
-
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(StaticAssertDecl *D) { return true; }
static bool classofKind(Kind K) { return K == StaticAssert; }
+
+ friend class ASTDeclReader;
};
/// Insertion operator for diagnostics. This allows sending AccessSpecifier's
diff --git a/include/clang/AST/DeclContextInternals.h b/include/clang/AST/DeclContextInternals.h
index 9602b677fca5..97da6ca9a1ef 100644
--- a/include/clang/AST/DeclContextInternals.h
+++ b/include/clang/AST/DeclContextInternals.h
@@ -29,108 +29,54 @@ class DependentDiagnostic;
/// StoredDeclsList - This is an array of decls optimized a common case of only
/// containing one entry.
struct StoredDeclsList {
- /// The kind of data encoded in this list.
- enum DataKind {
- /// \brief The data is a NamedDecl*.
- DK_Decl = 0,
- /// \brief The data is a declaration ID (an unsigned value),
- /// shifted left by 2 bits.
- DK_DeclID = 1,
- /// \brief The data is a pointer to a vector (of type VectorTy)
- /// that contains declarations.
- DK_Decl_Vector = 2,
- /// \brief The data is a pointer to a vector (of type VectorTy)
- /// that contains declaration ID.
- DK_ID_Vector = 3
- };
-
- /// VectorTy - When in vector form, this is what the Data pointer points to.
- typedef llvm::SmallVector<uintptr_t, 4> VectorTy;
-
- /// \brief The stored data, which will be either a declaration ID, a
- /// pointer to a NamedDecl, or a pointer to a vector.
- uintptr_t Data;
+
+ /// DeclsTy - When in vector form, this is what the Data pointer points to.
+ typedef llvm::SmallVector<NamedDecl *, 4> DeclsTy;
+
+ /// \brief The stored data, which will be either a pointer to a NamedDecl,
+ /// or a pointer to a vector.
+ llvm::PointerUnion<NamedDecl *, DeclsTy *> Data;
public:
- StoredDeclsList() : Data(0) {}
+ StoredDeclsList() {}
StoredDeclsList(const StoredDeclsList &RHS) : Data(RHS.Data) {
- if (VectorTy *RHSVec = RHS.getAsVector()) {
- VectorTy *New = new VectorTy(*RHSVec);
- Data = reinterpret_cast<uintptr_t>(New) | (Data & 0x03);
- }
+ if (DeclsTy *RHSVec = RHS.getAsVector())
+ Data = new DeclsTy(*RHSVec);
}
~StoredDeclsList() {
// If this is a vector-form, free the vector.
- if (VectorTy *Vector = getAsVector())
+ if (DeclsTy *Vector = getAsVector())
delete Vector;
}
StoredDeclsList &operator=(const StoredDeclsList &RHS) {
- if (VectorTy *Vector = getAsVector())
+ if (DeclsTy *Vector = getAsVector())
delete Vector;
Data = RHS.Data;
- if (VectorTy *RHSVec = RHS.getAsVector()) {
- VectorTy *New = new VectorTy(*RHSVec);
- Data = reinterpret_cast<uintptr_t>(New) | (Data & 0x03);
- }
+ if (DeclsTy *RHSVec = RHS.getAsVector())
+ Data = new DeclsTy(*RHSVec);
return *this;
}
- bool isNull() const { return (Data & ~0x03) == 0; }
+ bool isNull() const { return Data.isNull(); }
NamedDecl *getAsDecl() const {
- if ((Data & 0x03) != DK_Decl)
- return 0;
-
- return reinterpret_cast<NamedDecl *>(Data & ~0x03);
+ return Data.dyn_cast<NamedDecl *>();
}
- VectorTy *getAsVector() const {
- if ((Data & 0x03) != DK_ID_Vector && (Data & 0x03) != DK_Decl_Vector)
- return 0;
-
- return reinterpret_cast<VectorTy *>(Data & ~0x03);
+ DeclsTy *getAsVector() const {
+ return Data.dyn_cast<DeclsTy *>();
}
void setOnlyValue(NamedDecl *ND) {
assert(!getAsVector() && "Not inline");
- Data = reinterpret_cast<uintptr_t>(ND);
- }
-
- void setFromDeclIDs(const llvm::SmallVectorImpl<unsigned> &Vec) {
- if (Vec.size() > 1) {
- VectorTy *Vector = getAsVector();
- if (!Vector) {
- Vector = new VectorTy;
- Data = reinterpret_cast<uintptr_t>(Vector) | DK_ID_Vector;
- }
-
- Vector->resize(Vec.size());
- std::copy(Vec.begin(), Vec.end(), Vector->begin());
- return;
- }
-
- if (VectorTy *Vector = getAsVector())
- delete Vector;
-
- if (Vec.empty())
- Data = 0;
- else
- Data = (Vec[0] << 2) | DK_DeclID;
- }
-
- /// \brief Force the stored declarations list to contain actual
- /// declarations.
- ///
- /// This routine will resolve any declaration IDs for declarations
- /// that may not yet have been loaded from external storage.
- void materializeDecls(ASTContext &Context);
-
- bool hasDeclarationIDs() const {
- DataKind DK = (DataKind)(Data & 0x03);
- return DK == DK_DeclID || DK == DK_ID_Vector;
+ Data = ND;
+ // Make sure that Data is a plain NamedDecl* so we can use its address
+ // at getLookupResult.
+ assert(*(NamedDecl **)&Data == ND &&
+ "PointerUnion mangles the NamedDecl pointer!");
}
void remove(NamedDecl *D) {
@@ -138,30 +84,26 @@ public:
if (NamedDecl *Singleton = getAsDecl()) {
assert(Singleton == D && "list is different singleton");
(void)Singleton;
- Data = 0;
+ Data = (NamedDecl *)0;
return;
}
- VectorTy &Vec = *getAsVector();
- VectorTy::iterator I = std::find(Vec.begin(), Vec.end(),
- reinterpret_cast<uintptr_t>(D));
+ DeclsTy &Vec = *getAsVector();
+ DeclsTy::iterator I = std::find(Vec.begin(), Vec.end(), D);
assert(I != Vec.end() && "list does not contain decl");
Vec.erase(I);
- assert(std::find(Vec.begin(), Vec.end(), reinterpret_cast<uintptr_t>(D))
+ assert(std::find(Vec.begin(), Vec.end(), D)
== Vec.end() && "list still contains decl");
}
/// getLookupResult - Return an array of all the decls that this list
/// represents.
- DeclContext::lookup_result getLookupResult(ASTContext &Context) {
+ DeclContext::lookup_result getLookupResult() {
if (isNull())
return DeclContext::lookup_result(DeclContext::lookup_iterator(0),
DeclContext::lookup_iterator(0));
- if (hasDeclarationIDs())
- materializeDecls(Context);
-
// If we have a single NamedDecl, return it.
if (getAsDecl()) {
assert(!isNull() && "Empty list isn't allowed");
@@ -172,19 +114,15 @@ public:
}
assert(getAsVector() && "Must have a vector at this point");
- VectorTy &Vector = *getAsVector();
+ DeclsTy &Vector = *getAsVector();
// Otherwise, we have a range result.
- return DeclContext::lookup_result((NamedDecl **)&Vector[0],
- (NamedDecl **)&Vector[0]+Vector.size());
+ return DeclContext::lookup_result(&Vector[0], &Vector[0]+Vector.size());
}
/// HandleRedeclaration - If this is a redeclaration of an existing decl,
/// replace the old one with D and return true. Otherwise return false.
- bool HandleRedeclaration(ASTContext &Context, NamedDecl *D) {
- if (hasDeclarationIDs())
- materializeDecls(Context);
-
+ bool HandleRedeclaration(NamedDecl *D) {
// Most decls only have one entry in their list, special case it.
if (NamedDecl *OldD = getAsDecl()) {
if (!D->declarationReplaces(OldD))
@@ -194,12 +132,12 @@ public:
}
// Determine if this declaration is actually a redeclaration.
- VectorTy &Vec = *getAsVector();
- for (VectorTy::iterator OD = Vec.begin(), ODEnd = Vec.end();
+ DeclsTy &Vec = *getAsVector();
+ for (DeclsTy::iterator OD = Vec.begin(), ODEnd = Vec.end();
OD != ODEnd; ++OD) {
- NamedDecl *OldD = reinterpret_cast<NamedDecl *>(*OD);
+ NamedDecl *OldD = *OD;
if (D->declarationReplaces(OldD)) {
- *OD = reinterpret_cast<uintptr_t>(D);
+ *OD = D;
return true;
}
}
@@ -211,17 +149,15 @@ public:
/// not a redeclaration to merge it into the appropriate place in our list.
///
void AddSubsequentDecl(NamedDecl *D) {
- assert(!hasDeclarationIDs() && "Must materialize before adding decls");
-
// If this is the second decl added to the list, convert this to vector
// form.
if (NamedDecl *OldD = getAsDecl()) {
- VectorTy *VT = new VectorTy();
- VT->push_back(reinterpret_cast<uintptr_t>(OldD));
- Data = reinterpret_cast<uintptr_t>(VT) | DK_Decl_Vector;
+ DeclsTy *VT = new DeclsTy();
+ VT->push_back(OldD);
+ Data = VT;
}
- VectorTy &Vec = *getAsVector();
+ DeclsTy &Vec = *getAsVector();
// Using directives end up in a special entry which contains only
// other using directives, so all this logic is wasted for them.
@@ -232,32 +168,30 @@ public:
// iterator which points at the first tag will start a span of
// decls that only contains tags.
if (D->hasTagIdentifierNamespace())
- Vec.push_back(reinterpret_cast<uintptr_t>(D));
+ Vec.push_back(D);
// Resolved using declarations go at the front of the list so that
// they won't show up in other lookup results. Unresolved using
// declarations (which are always in IDNS_Using | IDNS_Ordinary)
// follow that so that the using declarations will be contiguous.
else if (D->getIdentifierNamespace() & Decl::IDNS_Using) {
- VectorTy::iterator I = Vec.begin();
+ DeclsTy::iterator I = Vec.begin();
if (D->getIdentifierNamespace() != Decl::IDNS_Using) {
while (I != Vec.end() &&
- reinterpret_cast<NamedDecl *>(*I)
- ->getIdentifierNamespace() == Decl::IDNS_Using)
+ (*I)->getIdentifierNamespace() == Decl::IDNS_Using)
++I;
}
- Vec.insert(I, reinterpret_cast<uintptr_t>(D));
+ Vec.insert(I, D);
// All other declarations go at the end of the list, but before any
// tag declarations. But we can be clever about tag declarations
// because there can only ever be one in a scope.
- } else if (reinterpret_cast<NamedDecl *>(Vec.back())
- ->hasTagIdentifierNamespace()) {
- uintptr_t TagD = Vec.back();
- Vec.back() = reinterpret_cast<uintptr_t>(D);
+ } else if (Vec.back()->hasTagIdentifierNamespace()) {
+ NamedDecl *TagD = Vec.back();
+ Vec.back() = D;
Vec.push_back(TagD);
} else
- Vec.push_back(reinterpret_cast<uintptr_t>(D));
+ Vec.push_back(D);
}
};
diff --git a/include/clang/AST/DeclFriend.h b/include/clang/AST/DeclFriend.h
index 2807d16379ae..4b5e6fd48bb3 100644
--- a/include/clang/AST/DeclFriend.h
+++ b/include/clang/AST/DeclFriend.h
@@ -68,16 +68,16 @@ public:
SourceLocation FriendL);
static FriendDecl *Create(ASTContext &C, EmptyShell Empty);
- /// If this friend declaration names an (untemplated but
- /// possibly dependent) type, return the type; otherwise
- /// return null. This is used only for C++0x's unelaborated
- /// friend type declarations.
+ /// If this friend declaration names an (untemplated but possibly
+ /// dependent) type, return the type; otherwise return null. This
+ /// is used for elaborated-type-specifiers and, in C++0x, for
+ /// arbitrary friend type declarations.
TypeSourceInfo *getFriendType() const {
return Friend.dyn_cast<TypeSourceInfo*>();
}
- /// If this friend declaration doesn't name an unelaborated
- /// type, return the inner declaration.
+ /// If this friend declaration doesn't name a type, return the inner
+ /// declaration.
NamedDecl *getFriendDecl() const {
return Friend.dyn_cast<NamedDecl*>();
}
@@ -92,8 +92,8 @@ public:
static bool classof(const FriendDecl *D) { return true; }
static bool classofKind(Kind K) { return K == Decl::Friend; }
- friend class PCHDeclReader;
- friend class PCHDeclWriter;
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
};
/// An iterator over the friend declarations of a class.
diff --git a/include/clang/AST/DeclGroup.h b/include/clang/AST/DeclGroup.h
index e1fae8f2ae67..030291ea7345 100644
--- a/include/clang/AST/DeclGroup.h
+++ b/include/clang/AST/DeclGroup.h
@@ -34,7 +34,6 @@ private:
public:
static DeclGroup *Create(ASTContext &C, Decl **Decls, unsigned NumDecls);
- void Destroy(ASTContext& C);
unsigned size() const { return NumDecls; }
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h
index 30f63d895959..ad26748e1343 100644
--- a/include/clang/AST/DeclObjC.h
+++ b/include/clang/AST/DeclObjC.h
@@ -21,7 +21,6 @@ namespace clang {
class Expr;
class Stmt;
class FunctionDecl;
-class AttributeList;
class RecordDecl;
class ObjCIvarDecl;
class ObjCMethodDecl;
@@ -41,12 +40,6 @@ protected:
public:
ObjCListBase() : List(0), NumElts(0) {}
- ~ObjCListBase() {
- assert(List == 0 && "Destroy should have been called before dtor");
- }
-
- void Destroy(ASTContext &Ctx);
-
unsigned size() const { return NumElts; }
bool empty() const { return NumElts == 0; }
@@ -92,7 +85,6 @@ public:
void set(ObjCProtocolDecl* const* InList, unsigned Elts,
const SourceLocation *Locs, ASTContext &Ctx);
- void Destroy(ASTContext &Ctx);
};
@@ -128,6 +120,9 @@ private:
// Synthesized declaration method for a property setter/getter
bool IsSynthesized : 1;
+
+ // Method has a definition.
+ bool IsDefined : 1;
// NOTE: VC++ treats enums as signed, avoid using ImplementationControl enum
/// @required/@optional
@@ -171,29 +166,25 @@ private:
bool isInstance = true,
bool isVariadic = false,
bool isSynthesized = false,
+ bool isDefined = false,
ImplementationControl impControl = None,
unsigned numSelectorArgs = 0)
: NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo),
DeclContext(ObjCMethod),
IsInstance(isInstance), IsVariadic(isVariadic),
IsSynthesized(isSynthesized),
+ IsDefined(isDefined),
DeclImplementation(impControl), objcDeclQualifier(OBJC_TQ_None),
NumSelectorArgs(numSelectorArgs), MethodDeclType(T),
ResultTInfo(ResultTInfo),
EndLoc(endLoc), Body(0), SelfDecl(0), CmdDecl(0) {}
- virtual ~ObjCMethodDecl() {}
-
/// \brief A definition will return its interface declaration.
/// An interface declaration will return its definition.
/// Otherwise it will return itself.
virtual ObjCMethodDecl *getNextRedeclaration();
public:
-
- /// Destroy - Call destructors and release memory.
- virtual void Destroy(ASTContext& C);
-
static ObjCMethodDecl *Create(ASTContext &C,
SourceLocation beginLoc,
SourceLocation endLoc, Selector SelInfo,
@@ -203,6 +194,7 @@ public:
bool isInstance = true,
bool isVariadic = false,
bool isSynthesized = false,
+ bool isDefined = false,
ImplementationControl impControl = None,
unsigned numSelectorArgs = 0);
@@ -296,6 +288,9 @@ public:
bool isSynthesized() const { return IsSynthesized; }
void setSynthesized(bool isSynth) { IsSynthesized = isSynth; }
+
+ bool isDefined() const { return IsDefined; }
+ void setDefined(bool isDefined) { IsDefined = isDefined; }
// Related to protocols declared in @protocol
void setDeclImplementation(ImplementationControl ic) {
@@ -326,21 +321,6 @@ public:
}
};
-/// ObjCMethodList - a linked list of methods with different signatures.
-struct ObjCMethodList {
- ObjCMethodDecl *Method;
- ObjCMethodList *Next;
-
- ObjCMethodList() {
- Method = 0;
- Next = 0;
- }
- ObjCMethodList(ObjCMethodDecl *M, ObjCMethodList *C) {
- Method = M;
- Next = C;
- }
-};
-
/// ObjCContainerDecl - Represents a container for method declarations.
/// Current sub-classes are ObjCInterfaceDecl, ObjCCategoryDecl,
/// ObjCProtocolDecl, and ObjCImplDecl.
@@ -355,8 +335,6 @@ public:
IdentifierInfo *Id)
: NamedDecl(DK, DC, L, Id), DeclContext(DK) {}
- virtual ~ObjCContainerDecl() {}
-
// Iterator access to properties.
typedef specific_decl_iterator<ObjCPropertyDecl> prop_iterator;
prop_iterator prop_begin() const {
@@ -465,12 +443,19 @@ class ObjCInterfaceDecl : public ObjCContainerDecl {
/// Class's super class.
ObjCInterfaceDecl *SuperClass;
- /// Protocols referenced in interface header declaration
+ /// Protocols referenced in the @interface declaration
ObjCProtocolList ReferencedProtocols;
+
+ /// Protocols reference in both the @interface and class extensions.
+ ObjCList<ObjCProtocolDecl> AllReferencedProtocols;
/// List of categories defined for this class.
/// FIXME: Why is this a linked list??
ObjCCategoryDecl *CategoryList;
+
+ /// IvarList - List of all ivars defined by this class; including class
+ /// extensions and implementation. This list is built lazily.
+ ObjCIvarDecl *IvarList;
bool ForwardDecl:1; // declared with @class.
bool InternalInterface:1; // true - no @interface for @implementation
@@ -482,13 +467,7 @@ class ObjCInterfaceDecl : public ObjCContainerDecl {
ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id,
SourceLocation CLoc, bool FD, bool isInternal);
- virtual ~ObjCInterfaceDecl() {}
-
public:
-
- /// Destroy - Call destructors and release memory.
- virtual void Destroy(ASTContext& C);
-
static ObjCInterfaceDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation atLoc,
IdentifierInfo *Id,
@@ -513,25 +492,49 @@ public:
}
typedef ObjCProtocolList::iterator protocol_iterator;
- protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();}
- protocol_iterator protocol_end() const { return ReferencedProtocols.end(); }
+
+ protocol_iterator protocol_begin() const {
+ return ReferencedProtocols.begin();
+ }
+ protocol_iterator protocol_end() const {
+ return ReferencedProtocols.end();
+ }
+
typedef ObjCProtocolList::loc_iterator protocol_loc_iterator;
+
protocol_loc_iterator protocol_loc_begin() const {
return ReferencedProtocols.loc_begin();
}
+
protocol_loc_iterator protocol_loc_end() const {
return ReferencedProtocols.loc_end();
}
- unsigned protocol_size() const { return ReferencedProtocols.size(); }
+
+ typedef ObjCList<ObjCProtocolDecl>::iterator all_protocol_iterator;
+
+ all_protocol_iterator all_referenced_protocol_begin() const {
+ return AllReferencedProtocols.empty() ? protocol_begin()
+ : AllReferencedProtocols.begin();
+ }
+ all_protocol_iterator all_referenced_protocol_end() const {
+ return AllReferencedProtocols.empty() ? protocol_end()
+ : AllReferencedProtocols.end();
+ }
typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator;
+
ivar_iterator ivar_begin() const { return ivar_iterator(decls_begin()); }
ivar_iterator ivar_end() const { return ivar_iterator(decls_end()); }
+
unsigned ivar_size() const {
return std::distance(ivar_begin(), ivar_end());
}
+
bool ivar_empty() const { return ivar_begin() == ivar_end(); }
-
+
+ ObjCIvarDecl *all_declared_ivar_begin();
+ void setIvarList(ObjCIvarDecl *ivar) { IvarList = ivar; }
+
/// setProtocolList - Set the list of protocols that this interface
/// implements.
void setProtocolList(ObjCProtocolDecl *const* List, unsigned Num,
@@ -543,7 +546,6 @@ public:
/// into the protocol list for this class.
void mergeClassExtensionProtocolList(ObjCProtocolDecl *const* List,
unsigned Num,
- const SourceLocation *Locs,
ASTContext &C);
bool isForwardDecl() const { return ForwardDecl; }
@@ -625,6 +627,9 @@ public:
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const ObjCInterfaceDecl *D) { return true; }
static bool classofKind(Kind K) { return K == ObjCInterface; }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
};
/// ObjCIvarDecl - Represents an ObjC instance variable. In general, ObjC
@@ -650,21 +655,26 @@ public:
private:
ObjCIvarDecl(ObjCContainerDecl *DC, SourceLocation L, IdentifierInfo *Id,
- QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW)
+ QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW,
+ bool synthesized)
: FieldDecl(ObjCIvar, DC, L, Id, T, TInfo, BW, /*Mutable=*/false),
- DeclAccess(ac) {}
+ NextIvar(0), DeclAccess(ac), Synthesized(synthesized) {}
public:
static ObjCIvarDecl *Create(ASTContext &C, ObjCContainerDecl *DC,
SourceLocation L, IdentifierInfo *Id, QualType T,
TypeSourceInfo *TInfo,
- AccessControl ac, Expr *BW = NULL);
+ AccessControl ac, Expr *BW = NULL,
+ bool synthesized=false);
/// \brief Return the class interface that this ivar is logically contained
/// in; this is either the interface where the ivar was declared, or the
/// interface the ivar is conceptually a part of in the case of synthesized
/// ivars.
const ObjCInterfaceDecl *getContainingInterface() const;
+
+ ObjCIvarDecl *getNextIvar() { return NextIvar; }
+ void setNextIvar(ObjCIvarDecl *ivar) { NextIvar = ivar; }
void setAccessControl(AccessControl ac) { DeclAccess = ac; }
@@ -674,13 +684,21 @@ public:
return DeclAccess == None ? Protected : AccessControl(DeclAccess);
}
+ void setSynthesize(bool synth) { Synthesized = synth; }
+ bool getSynthesize() const { return Synthesized; }
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const ObjCIvarDecl *D) { return true; }
static bool classofKind(Kind K) { return K == ObjCIvar; }
private:
+ /// NextIvar - Next Ivar in the list of ivars declared in class; class's
+ /// extensions and class's implementation
+ ObjCIvarDecl *NextIvar;
+
// NOTE: VC++ treats enums as signed, avoid using the AccessControl enum
unsigned DeclAccess : 3;
+ unsigned Synthesized : 1;
};
@@ -700,8 +718,6 @@ public:
IdentifierInfo *Id, QualType T,
Expr *BW);
- virtual void Destroy(ASTContext& C);
-
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const ObjCAtDefsFieldDecl *D) { return true; }
@@ -745,15 +761,10 @@ class ObjCProtocolDecl : public ObjCContainerDecl {
isForwardProtoDecl(true) {
}
- virtual ~ObjCProtocolDecl() {}
-
public:
static ObjCProtocolDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id);
- /// Destroy - Call destructors and release memory.
- virtual void Destroy(ASTContext& C);
-
const ObjCProtocolList &getReferencedProtocols() const {
return ReferencedProtocols;
}
@@ -822,12 +833,7 @@ private:
ObjCClassDecl(DeclContext *DC, SourceLocation L,
ObjCInterfaceDecl *const *Elts, const SourceLocation *Locs,
unsigned nElts, ASTContext &C);
- virtual ~ObjCClassDecl() {}
public:
-
- /// Destroy - Call destructors and release memory.
- virtual void Destroy(ASTContext& C);
-
static ObjCClassDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L,
ObjCInterfaceDecl *const *Elts = 0,
const SourceLocation *Locs = 0,
@@ -860,7 +866,6 @@ class ObjCForwardProtocolDecl : public Decl {
ObjCForwardProtocolDecl(DeclContext *DC, SourceLocation L,
ObjCProtocolDecl *const *Elts, unsigned nElts,
const SourceLocation *Locs, ASTContext &C);
- virtual ~ObjCForwardProtocolDecl() {}
public:
static ObjCForwardProtocolDecl *Create(ASTContext &C, DeclContext *DC,
@@ -874,9 +879,6 @@ public:
return Create(C, DC, L, 0, 0, 0);
}
- /// Destroy - Call destructors and release memory.
- virtual void Destroy(ASTContext& C);
-
typedef ObjCProtocolList::iterator protocol_iterator;
protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();}
protocol_iterator protocol_end() const { return ReferencedProtocols.end(); }
@@ -928,6 +930,9 @@ class ObjCCategoryDecl : public ObjCContainerDecl {
/// FIXME: this should not be a singly-linked list. Move storage elsewhere.
ObjCCategoryDecl *NextClassCategory;
+ /// true of class extension has at least one bitfield ivar.
+ bool HasSynthBitfield : 1;
+
/// \brief The location of the '@' in '@interface'
SourceLocation AtLoc;
@@ -938,8 +943,8 @@ class ObjCCategoryDecl : public ObjCContainerDecl {
SourceLocation ClassNameLoc, SourceLocation CategoryNameLoc,
IdentifierInfo *Id)
: ObjCContainerDecl(ObjCCategory, DC, ClassNameLoc, Id),
- ClassInterface(0), NextClassCategory(0), AtLoc(AtLoc),
- CategoryNameLoc(CategoryNameLoc) {
+ ClassInterface(0), NextClassCategory(0), HasSynthBitfield(false),
+ AtLoc(AtLoc), CategoryNameLoc(CategoryNameLoc) {
}
public:
@@ -991,6 +996,9 @@ public:
bool IsClassExtension() const { return getIdentifier() == 0; }
const ObjCCategoryDecl *getNextClassExtension() const;
+ bool hasSynthBitfield() const { return HasSynthBitfield; }
+ void setHasSynthBitfield (bool val) { HasSynthBitfield = val; }
+
typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator;
ivar_iterator ivar_begin() const {
return ivar_iterator(decls_begin());
@@ -1032,8 +1040,6 @@ protected:
ClassInterface(classInterface) {}
public:
- virtual ~ObjCImplDecl() {}
-
const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; }
ObjCInterfaceDecl *getClassInterface() { return ClassInterface; }
void setClassInterface(ObjCInterfaceDecl *IFace);
@@ -1165,11 +1171,15 @@ class ObjCImplementationDecl : public ObjCImplDecl {
CXXBaseOrMemberInitializer **IvarInitializers;
unsigned NumIvarInitializers;
+ /// true of class extension has at least one bitfield ivar.
+ bool HasSynthBitfield : 1;
+
ObjCImplementationDecl(DeclContext *DC, SourceLocation L,
ObjCInterfaceDecl *classInterface,
ObjCInterfaceDecl *superDecl)
: ObjCImplDecl(ObjCImplementation, DC, L, classInterface),
- SuperClass(superDecl), IvarInitializers(0), NumIvarInitializers(0) {}
+ SuperClass(superDecl), IvarInitializers(0), NumIvarInitializers(0),
+ HasSynthBitfield(false) {}
public:
static ObjCImplementationDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
@@ -1207,6 +1217,9 @@ public:
void setIvarInitializers(ASTContext &C,
CXXBaseOrMemberInitializer ** initializers,
unsigned numInitializers);
+
+ bool hasSynthBitfield() const { return HasSynthBitfield; }
+ void setHasSynthBitfield (bool val) { HasSynthBitfield = val; }
/// getIdentifier - Get the identifier that names the class
/// interface associated with this implementation.
@@ -1262,6 +1275,9 @@ public:
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const ObjCImplementationDecl *D) { return true; }
static bool classofKind(Kind K) { return K == ObjCImplementation; }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
};
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h
index 135dd3ae78d3..b532668242fd 100644
--- a/include/clang/AST/DeclTemplate.h
+++ b/include/clang/AST/DeclTemplate.h
@@ -23,6 +23,7 @@ namespace clang {
class TemplateParameterList;
class TemplateDecl;
+class RedeclarableTemplateDecl;
class FunctionTemplateDecl;
class ClassTemplateDecl;
class ClassTemplatePartialSpecializationDecl;
@@ -193,13 +194,6 @@ public:
TemplateArgumentList() : NumFlatArguments(0), NumStructuredArguments(0) { }
- /// Used to release the memory associated with a TemplateArgumentList
- /// object. FIXME: This is currently not called anywhere, but the
- /// memory will still be freed when using a BumpPtrAllocator.
- void Destroy(ASTContext &C);
-
- ~TemplateArgumentList();
-
/// \brief Copies the template arguments into a locally new[]'d array.
void init(ASTContext &Context,
const TemplateArgument *Args, unsigned NumArgs);
@@ -255,8 +249,6 @@ protected:
: NamedDecl(DK, DC, L, Name), TemplatedDecl(Decl),
TemplateParams(Params) { }
public:
- ~TemplateDecl();
-
/// Get the list of template parameters
TemplateParameterList *getTemplateParameters() const {
return TemplateParams;
@@ -268,6 +260,7 @@ public:
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const TemplateDecl *D) { return true; }
+ static bool classof(const RedeclarableTemplateDecl *D) { return true; }
static bool classof(const FunctionTemplateDecl *D) { return true; }
static bool classof(const ClassTemplateDecl *D) { return true; }
static bool classof(const TemplateTemplateParmDecl *D) { return true; }
@@ -490,122 +483,179 @@ public:
}
};
-/// Declaration of a template function.
-class FunctionTemplateDecl : public TemplateDecl {
- static void DeallocateCommon(void *Ptr);
-
+/// Declaration of a redeclarable template.
+class RedeclarableTemplateDecl : public TemplateDecl {
+
+ RedeclarableTemplateDecl *getPreviousDeclarationImpl() {
+ return CommonOrPrev.dyn_cast<RedeclarableTemplateDecl*>();
+ }
+
+ RedeclarableTemplateDecl *getCanonicalDeclImpl();
+
+ void setPreviousDeclarationImpl(RedeclarableTemplateDecl *Prev);
+
+ RedeclarableTemplateDecl *getInstantiatedFromMemberTemplateImpl() {
+ return getCommonPtr()->InstantiatedFromMember.getPointer();
+ }
+
+ void setInstantiatedFromMemberTemplateImpl(RedeclarableTemplateDecl *TD) {
+ assert(!getCommonPtr()->InstantiatedFromMember.getPointer());
+ getCommonPtr()->InstantiatedFromMember.setPointer(TD);
+ }
+
protected:
- /// \brief Data that is common to all of the declarations of a given
- /// function template.
- struct Common {
- Common() : InstantiatedFromMember(0, false) { }
+ template <typename EntryType> struct SpecEntryTraits {
+ typedef EntryType DeclType;
- /// \brief The function template specializations for this function
- /// template, including explicit specializations and instantiations.
- llvm::FoldingSet<FunctionTemplateSpecializationInfo> Specializations;
+ static DeclType *getMostRecentDeclaration(EntryType *D) {
+ return D->getMostRecentDeclaration();
+ }
+ };
+
+ template <typename EntryType,
+ typename _SETraits = SpecEntryTraits<EntryType>,
+ typename _DeclType = typename _SETraits::DeclType>
+ class SpecIterator : public std::iterator<std::forward_iterator_tag,
+ _DeclType*, ptrdiff_t,
+ _DeclType*, _DeclType*> {
+ typedef _SETraits SETraits;
+ typedef _DeclType DeclType;
+
+ typedef typename llvm::FoldingSet<EntryType>::iterator SetIteratorType;
+
+ SetIteratorType SetIter;
+
+ public:
+ SpecIterator() : SetIter() {}
+ SpecIterator(SetIteratorType SetIter) : SetIter(SetIter) {}
+
+ DeclType *operator*() const {
+ return SETraits::getMostRecentDeclaration(&*SetIter);
+ }
+ DeclType *operator->() const { return **this; }
+
+ SpecIterator &operator++() { ++SetIter; return *this; }
+ SpecIterator operator++(int) {
+ SpecIterator tmp(*this);
+ ++(*this);
+ return tmp;
+ }
+
+ bool operator==(SpecIterator Other) const {
+ return SetIter == Other.SetIter;
+ }
+ bool operator!=(SpecIterator Other) const {
+ return SetIter != Other.SetIter;
+ }
+ };
+
+ template <typename EntryType>
+ SpecIterator<EntryType> makeSpecIterator(llvm::FoldingSet<EntryType> &Specs,
+ bool isEnd) {
+ return SpecIterator<EntryType>(isEnd ? Specs.end() : Specs.begin());
+ }
+
+ template <class EntryType> typename SpecEntryTraits<EntryType>::DeclType*
+ findSpecializationImpl(llvm::FoldingSet<EntryType> &Specs,
+ const TemplateArgument *Args, unsigned NumArgs,
+ void *&InsertPos);
+
+ struct CommonBase {
+ CommonBase() : InstantiatedFromMember(0, false) { }
- /// \brief The member function template from which this was most
+ /// \brief The template from which this was most
/// directly instantiated (or null).
///
- /// The boolean value indicates whether this member function template
+ /// The boolean value indicates whether this template
/// was explicitly specialized.
- llvm::PointerIntPair<FunctionTemplateDecl*, 1, bool> InstantiatedFromMember;
+ llvm::PointerIntPair<RedeclarableTemplateDecl*, 1, bool>
+ InstantiatedFromMember;
+
+ /// \brief The latest declaration of this template.
+ RedeclarableTemplateDecl *Latest;
};
/// \brief A pointer to the previous declaration (if this is a redeclaration)
- /// or to the data that is common to all declarations of this function
- /// template.
- llvm::PointerUnion<Common*, FunctionTemplateDecl*> CommonOrPrev;
+ /// or to the data that is common to all declarations of this template.
+ llvm::PointerUnion<CommonBase*, RedeclarableTemplateDecl*> CommonOrPrev;
- /// \brief Retrieves the "common" pointer shared by all
- /// (re-)declarations of the same function template. Calling this routine
- /// may implicitly allocate memory for the common pointer.
- Common *getCommonPtr();
+ /// \brief Retrieves the "common" pointer shared by all (re-)declarations of
+ /// the same template. Calling this routine may implicitly allocate memory
+ /// for the common pointer.
+ CommonBase *getCommonPtr();
- FunctionTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
- TemplateParameterList *Params, NamedDecl *Decl)
- : TemplateDecl(FunctionTemplate, DC, L, Name, Params, Decl),
- CommonOrPrev((Common*)0) { }
+ virtual CommonBase *newCommon() = 0;
-public:
- void Destroy(ASTContext &C);
+ // Construct a template decl with name, parameters, and templated element.
+ RedeclarableTemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
+ DeclarationName Name, TemplateParameterList *Params,
+ NamedDecl *Decl)
+ : TemplateDecl(DK, DC, L, Name, Params, Decl),
+ CommonOrPrev((CommonBase*)0) { }
- /// Get the underlying function declaration of the template.
- FunctionDecl *getTemplatedDecl() const {
- return static_cast<FunctionDecl*>(TemplatedDecl);
- }
+public:
+ template <class decl_type> friend class RedeclarableTemplate;
- /// \brief Retrieve the set of function template specializations of this
- /// function template.
- llvm::FoldingSet<FunctionTemplateSpecializationInfo> &getSpecializations() {
- return getCommonPtr()->Specializations;
+ RedeclarableTemplateDecl *getCanonicalDecl() {
+ return getCanonicalDeclImpl();
}
- /// \brief Retrieve the previous declaration of this function template, or
+ /// \brief Retrieve the previous declaration of this template, or
/// NULL if no such declaration exists.
- const FunctionTemplateDecl *getPreviousDeclaration() const {
- return CommonOrPrev.dyn_cast<FunctionTemplateDecl*>();
+ RedeclarableTemplateDecl *getPreviousDeclaration() {
+ return getPreviousDeclarationImpl();
}
- /// \brief Retrieve the previous declaration of this function template, or
+ /// \brief Retrieve the previous declaration of this template, or
/// NULL if no such declaration exists.
- FunctionTemplateDecl *getPreviousDeclaration() {
- return CommonOrPrev.dyn_cast<FunctionTemplateDecl*>();
+ const RedeclarableTemplateDecl *getPreviousDeclaration() const {
+ return
+ const_cast<RedeclarableTemplateDecl*>(this)->getPreviousDeclaration();
}
- /// \brief Set the previous declaration of this function template.
- void setPreviousDeclaration(FunctionTemplateDecl *Prev) {
- if (Prev)
- CommonOrPrev = Prev;
+ /// \brief Retrieve the first declaration of this template, or itself
+ /// if this the first one.
+ RedeclarableTemplateDecl *getFirstDeclaration() {
+ return getCanonicalDecl();
}
- virtual FunctionTemplateDecl *getCanonicalDecl();
+ /// \brief Retrieve the first declaration of this template, or itself
+ /// if this the first one.
+ const RedeclarableTemplateDecl *getFirstDeclaration() const {
+ return
+ const_cast<RedeclarableTemplateDecl*>(this)->getFirstDeclaration();
+ }
- /// \brief Retrieve the member function template that this function template
- /// was instantiated from.
- ///
- /// This routine will return non-NULL for member function templates of
- /// class templates. For example, given:
- ///
- /// \code
- /// template <typename T>
- /// struct X {
- /// template <typename U> void f();
- /// };
- /// \endcode
- ///
- /// X<int>::A<float> is a CXXMethodDecl (whose parent is X<int>, a
- /// ClassTemplateSpecializationDecl) for which getPrimaryTemplate() will
- /// return X<int>::f, a FunctionTemplateDecl (whose parent is again
- /// X<int>) for which getInstantiatedFromMemberTemplate() will return
- /// X<T>::f, a FunctionTemplateDecl (whose parent is X<T>, a
- /// ClassTemplateDecl).
- ///
- /// \returns NULL if this is not an instantiation of a member function
- /// template.
- FunctionTemplateDecl *getInstantiatedFromMemberTemplate() {
- return getCommonPtr()->InstantiatedFromMember.getPointer();
+ /// \brief Retrieve the most recent declaration of this template, or itself
+ /// if this the most recent one.
+ RedeclarableTemplateDecl *getMostRecentDeclaration() {
+ return getCommonPtr()->Latest;
}
- void setInstantiatedFromMemberTemplate(FunctionTemplateDecl *FTD) {
- assert(!getCommonPtr()->InstantiatedFromMember.getPointer());
- getCommonPtr()->InstantiatedFromMember.setPointer(FTD);
+ /// \brief Retrieve the most recent declaration of this template, or itself
+ /// if this the most recent one.
+ const RedeclarableTemplateDecl *getMostRecentDeclaration() const {
+ return
+ const_cast<RedeclarableTemplateDecl*>(this)->getMostRecentDeclaration();
}
/// \brief Determines whether this template was a specialization of a
/// member template.
///
- /// In the following example, the function template \c X<int>::f is a
- /// member specialization.
+ /// In the following example, the function template \c X<int>::f and the
+ /// member template \c X<int>::Inner are member specializations.
///
/// \code
/// template<typename T>
/// struct X {
/// template<typename U> void f(T, U);
+ /// template<typename U> struct Inner;
/// };
///
/// template<> template<typename T>
/// void X<int>::f(int, T);
+ /// template<> template<typename T>
+ /// struct X<int>::Inner { /* ... */ };
/// \endcode
bool isMemberSpecialization() {
return getCommonPtr()->InstantiatedFromMember.getInt();
@@ -618,6 +668,197 @@ public:
getCommonPtr()->InstantiatedFromMember.setInt(true);
}
+ /// \brief Retrieve the previous declaration of this template, or
+ /// NULL if no such declaration exists.
+ RedeclarableTemplateDecl *getInstantiatedFromMemberTemplate() {
+ return getInstantiatedFromMemberTemplateImpl();
+ }
+
+ virtual RedeclarableTemplateDecl *getNextRedeclaration();
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const RedeclarableTemplateDecl *D) { return true; }
+ static bool classof(const FunctionTemplateDecl *D) { return true; }
+ static bool classof(const ClassTemplateDecl *D) { return true; }
+ static bool classofKind(Kind K) {
+ return K >= firstRedeclarableTemplate && K <= lastRedeclarableTemplate;
+ }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+template <class decl_type>
+class RedeclarableTemplate {
+ RedeclarableTemplateDecl *thisDecl() {
+ return static_cast<decl_type*>(this);
+ }
+
+public:
+ /// \brief Retrieve the previous declaration of this function template, or
+ /// NULL if no such declaration exists.
+ decl_type *getPreviousDeclaration() {
+ return static_cast<decl_type*>(thisDecl()->getPreviousDeclarationImpl());
+ }
+
+ /// \brief Retrieve the previous declaration of this function template, or
+ /// NULL if no such declaration exists.
+ const decl_type *getPreviousDeclaration() const {
+ return const_cast<RedeclarableTemplate*>(this)->getPreviousDeclaration();
+ }
+
+ /// \brief Set the previous declaration of this function template.
+ void setPreviousDeclaration(decl_type *Prev) {
+ thisDecl()->setPreviousDeclarationImpl(Prev);
+ }
+
+ decl_type *getCanonicalDecl() {
+ return static_cast<decl_type*>(thisDecl()->getCanonicalDeclImpl());
+ }
+
+ const decl_type *getCanonicalDecl() const {
+ return const_cast<RedeclarableTemplate*>(this)->getCanonicalDecl();
+ }
+
+ /// \brief Retrieve the member template that this template was instantiated
+ /// from.
+ ///
+ /// This routine will return non-NULL for member templates of
+ /// class templates. For example, given:
+ ///
+ /// \code
+ /// template <typename T>
+ /// struct X {
+ /// template <typename U> void f();
+ /// template <typename U> struct A {};
+ /// };
+ /// \endcode
+ ///
+ /// X<int>::f<float> is a CXXMethodDecl (whose parent is X<int>, a
+ /// ClassTemplateSpecializationDecl) for which getPrimaryTemplate() will
+ /// return X<int>::f, a FunctionTemplateDecl (whose parent is again
+ /// X<int>) for which getInstantiatedFromMemberTemplate() will return
+ /// X<T>::f, a FunctionTemplateDecl (whose parent is X<T>, a
+ /// ClassTemplateDecl).
+ ///
+ /// X<int>::A<float> is a ClassTemplateSpecializationDecl (whose parent
+ /// is X<int>, also a CTSD) for which getSpecializedTemplate() will
+ /// return X<int>::A<U>, a ClassTemplateDecl (whose parent is again
+ /// X<int>) for which getInstantiatedFromMemberTemplate() will return
+ /// X<T>::A<U>, a ClassTemplateDecl (whose parent is X<T>, also a CTD).
+ ///
+ /// \returns NULL if this is not an instantiation of a member template.
+ decl_type *getInstantiatedFromMemberTemplate() {
+ return static_cast<decl_type*>(
+ thisDecl()->getInstantiatedFromMemberTemplateImpl());
+ }
+
+ void setInstantiatedFromMemberTemplate(decl_type *TD) {
+ thisDecl()->setInstantiatedFromMemberTemplateImpl(TD);
+ }
+};
+
+template <> struct RedeclarableTemplateDecl::
+SpecEntryTraits<FunctionTemplateSpecializationInfo> {
+ typedef FunctionDecl DeclType;
+
+ static DeclType *
+ getMostRecentDeclaration(FunctionTemplateSpecializationInfo *I) {
+ return I->Function->getMostRecentDeclaration();
+ }
+};
+
+/// Declaration of a template function.
+class FunctionTemplateDecl : public RedeclarableTemplateDecl,
+ public RedeclarableTemplate<FunctionTemplateDecl> {
+ static void DeallocateCommon(void *Ptr);
+
+protected:
+ typedef RedeclarableTemplate<FunctionTemplateDecl> redeclarable_base;
+
+ /// \brief Data that is common to all of the declarations of a given
+ /// function template.
+ struct Common : CommonBase {
+ /// \brief The function template specializations for this function
+ /// template, including explicit specializations and instantiations.
+ llvm::FoldingSet<FunctionTemplateSpecializationInfo> Specializations;
+ };
+
+ FunctionTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
+ TemplateParameterList *Params, NamedDecl *Decl)
+ : RedeclarableTemplateDecl(FunctionTemplate, DC, L, Name, Params, Decl) { }
+
+ CommonBase *newCommon();
+
+ Common *getCommonPtr() {
+ return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr());
+ }
+
+ friend void FunctionDecl::setFunctionTemplateSpecialization(
+ FunctionTemplateDecl *Template,
+ const TemplateArgumentList *TemplateArgs,
+ void *InsertPos,
+ TemplateSpecializationKind TSK,
+ const TemplateArgumentListInfo *TemplateArgsAsWritten,
+ SourceLocation PointOfInstantiation);
+
+ /// \brief Retrieve the set of function template specializations of this
+ /// function template.
+ llvm::FoldingSet<FunctionTemplateSpecializationInfo> &getSpecializations() {
+ return getCommonPtr()->Specializations;
+ }
+
+public:
+ /// Get the underlying function declaration of the template.
+ FunctionDecl *getTemplatedDecl() const {
+ return static_cast<FunctionDecl*>(TemplatedDecl);
+ }
+
+ /// Returns whether this template declaration defines the primary
+ /// pattern.
+ bool isThisDeclarationADefinition() const {
+ return getTemplatedDecl()->isThisDeclarationADefinition();
+ }
+
+ /// \brief Return the specialization with the provided arguments if it exists,
+ /// otherwise return the insertion point.
+ FunctionDecl *findSpecialization(const TemplateArgument *Args,
+ unsigned NumArgs, void *&InsertPos);
+
+ FunctionTemplateDecl *getCanonicalDecl() {
+ return redeclarable_base::getCanonicalDecl();
+ }
+ const FunctionTemplateDecl *getCanonicalDecl() const {
+ return redeclarable_base::getCanonicalDecl();
+ }
+
+ /// \brief Retrieve the previous declaration of this function template, or
+ /// NULL if no such declaration exists.
+ FunctionTemplateDecl *getPreviousDeclaration() {
+ return redeclarable_base::getPreviousDeclaration();
+ }
+
+ /// \brief Retrieve the previous declaration of this function template, or
+ /// NULL if no such declaration exists.
+ const FunctionTemplateDecl *getPreviousDeclaration() const {
+ return redeclarable_base::getPreviousDeclaration();
+ }
+
+ FunctionTemplateDecl *getInstantiatedFromMemberTemplate() {
+ return redeclarable_base::getInstantiatedFromMemberTemplate();
+ }
+
+ typedef SpecIterator<FunctionTemplateSpecializationInfo> spec_iterator;
+
+ spec_iterator spec_begin() {
+ return makeSpecIterator(getSpecializations(), false);
+ }
+
+ spec_iterator spec_end() {
+ return makeSpecIterator(getSpecializations(), true);
+ }
+
/// Create a template function node.
static FunctionTemplateDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
@@ -630,8 +871,8 @@ public:
static bool classof(const FunctionTemplateDecl *D) { return true; }
static bool classofKind(Kind K) { return K == FunctionTemplate; }
- friend class PCHDeclReader;
- friend class PCHDeclWriter;
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
};
//===----------------------------------------------------------------------===//
@@ -781,8 +1022,7 @@ class NonTypeTemplateParmDecl
NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D,
unsigned P, IdentifierInfo *Id, QualType T,
TypeSourceInfo *TInfo)
- : VarDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo, VarDecl::None,
- VarDecl::None),
+ : VarDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo, SC_None, SC_None),
TemplateParmPosition(D, P), DefaultArgumentAndInherited(0, false)
{ }
@@ -904,13 +1144,20 @@ public:
DefaultArgumentWasInherited = false;
}
+ SourceRange getSourceRange() const {
+ SourceLocation End = getLocation();
+ if (hasDefaultArgument() && !defaultArgumentWasInherited())
+ End = getDefaultArgument().getSourceRange().getEnd();
+ return SourceRange(getTemplateParameters()->getTemplateLoc(), End);
+ }
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const TemplateTemplateParmDecl *D) { return true; }
static bool classofKind(Kind K) { return K == TemplateTemplateParm; }
- friend class PCHDeclReader;
- friend class PCHDeclWriter;
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
};
/// \brief Represents a class template specialization, which refers to
@@ -991,12 +1238,21 @@ public:
static ClassTemplateSpecializationDecl *
Create(ASTContext &Context, EmptyShell Empty);
- virtual void Destroy(ASTContext& C);
-
virtual void getNameForDiagnostic(std::string &S,
const PrintingPolicy &Policy,
bool Qualified) const;
+ ClassTemplateSpecializationDecl *getMostRecentDeclaration() {
+ CXXRecordDecl *Recent
+ = cast<CXXRecordDecl>(CXXRecordDecl::getMostRecentDeclaration());
+ if (!isa<ClassTemplateSpecializationDecl>(Recent)) {
+ // FIXME: Does injected class name need to be in the redeclarations chain?
+ assert(Recent->isInjectedClassName() && Recent->getPreviousDeclaration());
+ Recent = Recent->getPreviousDeclaration();
+ }
+ return cast<ClassTemplateSpecializationDecl>(Recent);
+ }
+
/// \brief Retrieve the template that this specialization specializes.
ClassTemplateDecl *getSpecializedTemplate() const;
@@ -1044,7 +1300,8 @@ public:
if (getSpecializationKind() != TSK_ImplicitInstantiation &&
getSpecializationKind() != TSK_ExplicitInstantiationDefinition &&
getSpecializationKind() != TSK_ExplicitInstantiationDeclaration)
- return (ClassTemplateDecl*)0;
+ return llvm::PointerUnion<ClassTemplateDecl *,
+ ClassTemplatePartialSpecializationDecl *>();
if (SpecializedPartialSpecialization *PartialSpec
= SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
@@ -1123,7 +1380,8 @@ public:
/// \brief Sets the type of this specialization as it was written by
/// the user. This will be a class template specialization type.
void setTypeAsWritten(TypeSourceInfo *T) {
- if (!ExplicitInfo) ExplicitInfo = new ExplicitSpecializationInfo;
+ if (!ExplicitInfo)
+ ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
ExplicitInfo->TypeAsWritten = T;
}
/// \brief Gets the type of this specialization as it was written by
@@ -1138,13 +1396,15 @@ public:
}
/// \brief Sets the location of the extern keyword.
void setExternLoc(SourceLocation Loc) {
- if (!ExplicitInfo) ExplicitInfo = new ExplicitSpecializationInfo;
+ if (!ExplicitInfo)
+ ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
ExplicitInfo->ExternLoc = Loc;
}
/// \brief Sets the location of the template keyword.
void setTemplateKeywordLoc(SourceLocation Loc) {
- if (!ExplicitInfo) ExplicitInfo = new ExplicitSpecializationInfo;
+ if (!ExplicitInfo)
+ ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
ExplicitInfo->TemplateKeywordLoc = Loc;
}
/// \brief Gets the location of the template keyword, if present.
@@ -1242,6 +1502,11 @@ public:
static ClassTemplatePartialSpecializationDecl *
Create(ASTContext &Context, EmptyShell Empty);
+ ClassTemplatePartialSpecializationDecl *getMostRecentDeclaration() {
+ return cast<ClassTemplatePartialSpecializationDecl>(
+ ClassTemplateSpecializationDecl::getMostRecentDeclaration());
+ }
+
/// Get the list of template parameters
TemplateParameterList *getTemplateParameters() const {
return TemplateParams;
@@ -1355,15 +1620,16 @@ public:
};
/// Declaration of a class template.
-class ClassTemplateDecl : public TemplateDecl {
+class ClassTemplateDecl : public RedeclarableTemplateDecl,
+ public RedeclarableTemplate<ClassTemplateDecl> {
static void DeallocateCommon(void *Ptr);
protected:
+ typedef RedeclarableTemplate<ClassTemplateDecl> redeclarable_base;
+
/// \brief Data that is common to all of the declarations of a given
/// class template.
- struct Common {
- Common() : InstantiatedFromMember(0, 0) {}
-
+ struct Common : CommonBase {
/// \brief The class template specializations for this class
/// template, including explicit specializations and instantiations.
llvm::FoldingSet<ClassTemplateSpecializationDecl> Specializations;
@@ -1375,28 +1641,29 @@ protected:
/// \brief The injected-class-name type for this class template.
QualType InjectedClassNameType;
-
- /// \brief The templated member class from which this was most
- /// directly instantiated (or null).
- ///
- /// The boolean value indicates whether this member class template
- /// was explicitly specialized.
- llvm::PointerIntPair<ClassTemplateDecl *, 1, bool> InstantiatedFromMember;
};
- /// \brief A pointer to the previous declaration (if this is a redeclaration)
- /// or to the data that is common to all declarations of this class template.
- llvm::PointerUnion<Common*, ClassTemplateDecl*> CommonOrPrev;
+ /// \brief Retrieve the set of specializations of this class template.
+ llvm::FoldingSet<ClassTemplateSpecializationDecl> &getSpecializations() {
+ return getCommonPtr()->Specializations;
+ }
- /// \brief Retrieves the "common" pointer shared by all
- /// (re-)declarations of the same class template. Calling this routine
- /// may implicitly allocate memory for the common pointer.
- Common *getCommonPtr();
+ /// \brief Retrieve the set of partial specializations of this class
+ /// template.
+ llvm::FoldingSet<ClassTemplatePartialSpecializationDecl> &
+ getPartialSpecializations() {
+ return getCommonPtr()->PartialSpecializations;
+ }
ClassTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
TemplateParameterList *Params, NamedDecl *Decl)
- : TemplateDecl(ClassTemplate, DC, L, Name, Params, Decl),
- CommonOrPrev((Common*)0) { }
+ : RedeclarableTemplateDecl(ClassTemplate, DC, L, Name, Params, Decl) { }
+
+ CommonBase *newCommon();
+
+ Common *getCommonPtr() {
+ return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr());
+ }
public:
/// Get the underlying class declarations of the template.
@@ -1404,48 +1671,71 @@ public:
return static_cast<CXXRecordDecl *>(TemplatedDecl);
}
- /// \brief Retrieve the previous declaration of this class template, or
- /// NULL if no such declaration exists.
- const ClassTemplateDecl *getPreviousDeclaration() const {
- return CommonOrPrev.dyn_cast<ClassTemplateDecl*>();
+ /// Returns whether this template declaration defines the primary
+ /// class pattern.
+ bool isThisDeclarationADefinition() const {
+ return getTemplatedDecl()->isThisDeclarationADefinition();
}
- /// \brief Retrieve the previous declaration of this function template, or
+ /// Create a class template node.
+ static ClassTemplateDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L,
+ DeclarationName Name,
+ TemplateParameterList *Params,
+ NamedDecl *Decl,
+ ClassTemplateDecl *PrevDecl);
+
+ /// \brief Return the specialization with the provided arguments if it exists,
+ /// otherwise return the insertion point.
+ ClassTemplateSpecializationDecl *
+ findSpecialization(const TemplateArgument *Args, unsigned NumArgs,
+ void *&InsertPos);
+
+ /// \brief Insert the specified specialization knowing that it is not already
+ /// in. InsertPos must be obtained from findSpecialization.
+ void AddSpecialization(ClassTemplateSpecializationDecl *D, void *InsertPos) {
+ getSpecializations().InsertNode(D, InsertPos);
+ }
+
+ ClassTemplateDecl *getCanonicalDecl() {
+ return redeclarable_base::getCanonicalDecl();
+ }
+ const ClassTemplateDecl *getCanonicalDecl() const {
+ return redeclarable_base::getCanonicalDecl();
+ }
+
+ /// \brief Retrieve the previous declaration of this class template, or
/// NULL if no such declaration exists.
ClassTemplateDecl *getPreviousDeclaration() {
- return CommonOrPrev.dyn_cast<ClassTemplateDecl*>();
+ return redeclarable_base::getPreviousDeclaration();
}
- /// \brief Set the previous declaration of this class template.
- void setPreviousDeclaration(ClassTemplateDecl *Prev) {
- if (Prev)
- CommonOrPrev = Prev;
+ /// \brief Retrieve the previous declaration of this class template, or
+ /// NULL if no such declaration exists.
+ const ClassTemplateDecl *getPreviousDeclaration() const {
+ return redeclarable_base::getPreviousDeclaration();
}
- virtual ClassTemplateDecl *getCanonicalDecl();
-
- const ClassTemplateDecl *getCanonicalDecl() const {
- return const_cast<ClassTemplateDecl*>(this)->getCanonicalDecl();
+ ClassTemplateDecl *getInstantiatedFromMemberTemplate() {
+ return redeclarable_base::getInstantiatedFromMemberTemplate();
}
- /// Create a class template node.
- static ClassTemplateDecl *Create(ASTContext &C, DeclContext *DC,
- SourceLocation L,
- DeclarationName Name,
- TemplateParameterList *Params,
- NamedDecl *Decl,
- ClassTemplateDecl *PrevDecl);
+ /// \brief Return the partial specialization with the provided arguments if it
+ /// exists, otherwise return the insertion point.
+ ClassTemplatePartialSpecializationDecl *
+ findPartialSpecialization(const TemplateArgument *Args, unsigned NumArgs,
+ void *&InsertPos);
- /// \brief Retrieve the set of specializations of this class template.
- llvm::FoldingSet<ClassTemplateSpecializationDecl> &getSpecializations() {
- return getCommonPtr()->Specializations;
+ /// \brief Insert the specified partial specialization knowing that it is not
+ /// already in. InsertPos must be obtained from findPartialSpecialization.
+ void AddPartialSpecialization(ClassTemplatePartialSpecializationDecl *D,
+ void *InsertPos) {
+ getPartialSpecializations().InsertNode(D, InsertPos);
}
- /// \brief Retrieve the set of partial specializations of this class
- /// template.
- llvm::FoldingSet<ClassTemplatePartialSpecializationDecl> &
- getPartialSpecializations() {
- return getCommonPtr()->PartialSpecializations;
+ /// \brief Return the next partial specialization sequence number.
+ unsigned getNextPartialSpecSequenceNumber() {
+ return getPartialSpecializations().size();
}
/// \brief Retrieve the partial specializations as an ordered list.
@@ -1455,12 +1745,24 @@ public:
/// \brief Find a class template partial specialization with the given
/// type T.
///
- /// \brief A dependent type that names a specialization of this class
+ /// \param T a dependent type that names a specialization of this class
/// template.
///
/// \returns the class template partial specialization that exactly matches
/// the type \p T, or NULL if no such partial specialization exists.
ClassTemplatePartialSpecializationDecl *findPartialSpecialization(QualType T);
+
+ /// \brief Find a class template partial specialization which was instantiated
+ /// from the given member partial specialization.
+ ///
+ /// \param D a member class template partial specialization.
+ ///
+ /// \returns the class template partial specialization which was instantiated
+ /// from the given member partial specialization, or NULL if no such partial
+ /// specialization exists.
+ ClassTemplatePartialSpecializationDecl *
+ findPartialSpecInstantiatedFromMember(
+ ClassTemplatePartialSpecializationDecl *D);
/// \brief Retrieve the template specialization type of the
/// injected-class-name for this class template.
@@ -1478,78 +1780,45 @@ public:
/// \endcode
QualType getInjectedClassNameSpecialization();
- /// \brief Retrieve the member class template that this class template was
- /// derived from.
- ///
- /// This routine will return non-NULL for templated member classes of
- /// class templates. For example, given:
- ///
- /// \code
- /// template <typename T>
- /// struct X {
- /// template <typename U> struct A {};
- /// };
- /// \endcode
- ///
- /// X<int>::A<float> is a ClassTemplateSpecializationDecl (whose parent
- /// is X<int>, also a CTSD) for which getSpecializedTemplate() will
- /// return X<int>::A<U>, a TemplateClassDecl (whose parent is again
- /// X<int>) for which getInstantiatedFromMemberTemplate() will return
- /// X<T>::A<U>, a TemplateClassDecl (whose parent is X<T>, also a TCD).
- ///
- /// \returns null if this is not an instantiation of a member class template.
- ClassTemplateDecl *getInstantiatedFromMemberTemplate() {
- return getCommonPtr()->InstantiatedFromMember.getPointer();
+ typedef SpecIterator<ClassTemplateSpecializationDecl> spec_iterator;
+
+ spec_iterator spec_begin() {
+ return makeSpecIterator(getSpecializations(), false);
}
- void setInstantiatedFromMemberTemplate(ClassTemplateDecl *CTD) {
- assert(!getCommonPtr()->InstantiatedFromMember.getPointer());
- getCommonPtr()->InstantiatedFromMember.setPointer(CTD);
+ spec_iterator spec_end() {
+ return makeSpecIterator(getSpecializations(), true);
}
- /// \brief Determines whether this template was a specialization of a
- /// member template.
- ///
- /// In the following example, the member template \c X<int>::Inner is a
- /// member specialization.
- ///
- /// \code
- /// template<typename T>
- /// struct X {
- /// template<typename U> struct Inner;
- /// };
- ///
- /// template<> template<typename T>
- /// struct X<int>::Inner { /* ... */ };
- /// \endcode
- bool isMemberSpecialization() {
- return getCommonPtr()->InstantiatedFromMember.getInt();
+ typedef SpecIterator<ClassTemplatePartialSpecializationDecl>
+ partial_spec_iterator;
+
+ partial_spec_iterator partial_spec_begin() {
+ return makeSpecIterator(getPartialSpecializations(), false);
}
-
- /// \brief Note that this member template is a specialization.
- void setMemberSpecialization() {
- assert(getCommonPtr()->InstantiatedFromMember.getPointer() &&
- "Only member templates can be member template specializations");
- getCommonPtr()->InstantiatedFromMember.setInt(true);
+
+ partial_spec_iterator partial_spec_end() {
+ return makeSpecIterator(getPartialSpecializations(), true);
}
-
+
// Implement isa/cast/dyncast support
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const ClassTemplateDecl *D) { return true; }
static bool classofKind(Kind K) { return K == ClassTemplate; }
- virtual void Destroy(ASTContext& C);
-
- friend class PCHDeclReader;
- friend class PCHDeclWriter;
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
};
/// Declaration of a friend template. For example:
///
/// template <typename T> class A {
/// friend class MyVector<T>; // not a friend template
-/// template <typename U> friend class B; // friend template
+/// template <typename U> friend class B; // not a friend template
/// template <typename U> friend class Foo<T>::Nested; // friend template
+/// };
+/// NOTE: This class is not currently in use. All of the above
+/// will yield a FriendDecl, not a FriendTemplateDecl.
class FriendTemplateDecl : public Decl {
public:
typedef llvm::PointerUnion<NamedDecl*,TypeSourceInfo*> FriendUnion;
@@ -1580,6 +1849,12 @@ private:
FriendLoc(FriendLoc)
{}
+ FriendTemplateDecl(EmptyShell Empty)
+ : Decl(Decl::FriendTemplate, Empty),
+ NumParams(0),
+ Params(0)
+ {}
+
public:
static FriendTemplateDecl *Create(ASTContext &Context,
DeclContext *DC, SourceLocation Loc,
@@ -1588,6 +1863,8 @@ public:
FriendUnion Friend,
SourceLocation FriendLoc);
+ static FriendTemplateDecl *Create(ASTContext &Context, EmptyShell Empty);
+
/// If this friend declaration names a templated type (or
/// a dependent member type of a templated type), return that
/// type; otherwise return null.
@@ -1620,6 +1897,8 @@ public:
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == Decl::FriendTemplate; }
static bool classof(const FriendTemplateDecl *D) { return true; }
+
+ friend class ASTDeclReader;
};
/// Implementation of inline functions that require the template declarations
diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h
index 8a771d513c42..8bb627597520 100644
--- a/include/clang/AST/DeclarationName.h
+++ b/include/clang/AST/DeclarationName.h
@@ -30,6 +30,7 @@ namespace clang {
class IdentifierInfo;
class MultiKeywordSelector;
class UsingDirectiveDecl;
+ class TypeSourceInfo;
/// DeclarationName - The name of a declaration. In the common case,
/// this just stores an IdentifierInfo pointer to a normal
@@ -367,6 +368,146 @@ public:
DeclarationName getCXXLiteralOperatorName(IdentifierInfo *II);
};
+/// DeclarationNameLoc - Additional source/type location info
+/// for a declaration name. Needs a DeclarationName in order
+/// to be interpreted correctly.
+struct DeclarationNameLoc {
+ union {
+ // The source location for identifier stored elsewhere.
+ // struct {} Identifier;
+
+ // Type info for constructors, destructors and conversion functions.
+ // Locations (if any) for the tilde (destructor) or operator keyword
+ // (conversion) are stored elsewhere.
+ struct {
+ TypeSourceInfo* TInfo;
+ } NamedType;
+
+ // The location (if any) of the operator keyword is stored elsewhere.
+ struct {
+ unsigned BeginOpNameLoc;
+ unsigned EndOpNameLoc;
+ } CXXOperatorName;
+
+ // The location (if any) of the operator keyword is stored elsewhere.
+ struct {
+ unsigned OpNameLoc;
+ } CXXLiteralOperatorName;
+
+ // struct {} CXXUsingDirective;
+ // struct {} ObjCZeroArgSelector;
+ // struct {} ObjCOneArgSelector;
+ // struct {} ObjCMultiArgSelector;
+ };
+
+ DeclarationNameLoc(DeclarationName Name);
+ // FIXME: this should go away once all DNLocs are properly initialized.
+ DeclarationNameLoc() { NamedType.TInfo = 0; }
+}; // struct DeclarationNameLoc
+
+
+/// DeclarationNameInfo - A collector data type for bundling together
+/// a DeclarationName and the correspnding source/type location info.
+struct DeclarationNameInfo {
+private:
+ /// Name - The declaration name, also encoding name kind.
+ DeclarationName Name;
+ /// Loc - The main source location for the declaration name.
+ SourceLocation NameLoc;
+ /// Info - Further source/type location info for special kinds of names.
+ DeclarationNameLoc LocInfo;
+
+public:
+ // FIXME: remove it.
+ DeclarationNameInfo() {}
+
+ DeclarationNameInfo(DeclarationName Name, SourceLocation NameLoc)
+ : Name(Name), NameLoc(NameLoc), LocInfo(Name) {}
+
+ DeclarationNameInfo(DeclarationName Name, SourceLocation NameLoc,
+ DeclarationNameLoc LocInfo)
+ : Name(Name), NameLoc(NameLoc), LocInfo(LocInfo) {}
+
+ /// getName - Returns the embedded declaration name.
+ DeclarationName getName() const { return Name; }
+ /// setName - Sets the embedded declaration name.
+ void setName(DeclarationName N) { Name = N; }
+
+ /// getLoc - Returns the main location of the declaration name.
+ SourceLocation getLoc() const { return NameLoc; }
+ /// setLoc - Sets the main location of the declaration name.
+ void setLoc(SourceLocation L) { NameLoc = L; }
+
+ const DeclarationNameLoc &getInfo() const { return LocInfo; }
+ DeclarationNameLoc &getInfo() { return LocInfo; }
+ void setInfo(const DeclarationNameLoc &Info) { LocInfo = Info; }
+
+ /// getNamedTypeInfo - Returns the source type info associated to
+ /// the name. Assumes it is a constructor, destructor or conversion.
+ TypeSourceInfo *getNamedTypeInfo() const {
+ assert(Name.getNameKind() == DeclarationName::CXXConstructorName ||
+ Name.getNameKind() == DeclarationName::CXXDestructorName ||
+ Name.getNameKind() == DeclarationName::CXXConversionFunctionName);
+ return LocInfo.NamedType.TInfo;
+ }
+ /// setNamedTypeInfo - Sets the source type info associated to
+ /// the name. Assumes it is a constructor, destructor or conversion.
+ void setNamedTypeInfo(TypeSourceInfo *TInfo) {
+ assert(Name.getNameKind() == DeclarationName::CXXConstructorName ||
+ Name.getNameKind() == DeclarationName::CXXDestructorName ||
+ Name.getNameKind() == DeclarationName::CXXConversionFunctionName);
+ LocInfo.NamedType.TInfo = TInfo;
+ }
+
+ /// getCXXOperatorNameRange - Gets the range of the operator name
+ /// (without the operator keyword). Assumes it is a (non-literal) operator.
+ SourceRange getCXXOperatorNameRange() const {
+ assert(Name.getNameKind() == DeclarationName::CXXOperatorName);
+ return SourceRange(
+ SourceLocation::getFromRawEncoding(LocInfo.CXXOperatorName.BeginOpNameLoc),
+ SourceLocation::getFromRawEncoding(LocInfo.CXXOperatorName.EndOpNameLoc)
+ );
+ }
+ /// setCXXOperatorNameRange - Sets the range of the operator name
+ /// (without the operator keyword). Assumes it is a C++ operator.
+ void setCXXOperatorNameRange(SourceRange R) {
+ assert(Name.getNameKind() == DeclarationName::CXXOperatorName);
+ LocInfo.CXXOperatorName.BeginOpNameLoc = R.getBegin().getRawEncoding();
+ LocInfo.CXXOperatorName.EndOpNameLoc = R.getEnd().getRawEncoding();
+ }
+
+ /// getCXXLiteralOperatorNameLoc - Returns the location of the literal
+ /// operator name (not the operator keyword).
+ /// Assumes it is a literal operator.
+ SourceLocation getCXXLiteralOperatorNameLoc() const {
+ assert(Name.getNameKind() == DeclarationName::CXXLiteralOperatorName);
+ return SourceLocation::
+ getFromRawEncoding(LocInfo.CXXLiteralOperatorName.OpNameLoc);
+ }
+ /// setCXXLiteralOperatorNameLoc - Sets the location of the literal
+ /// operator name (not the operator keyword).
+ /// Assumes it is a literal operator.
+ void setCXXLiteralOperatorNameLoc(SourceLocation Loc) {
+ assert(Name.getNameKind() == DeclarationName::CXXLiteralOperatorName);
+ LocInfo.CXXLiteralOperatorName.OpNameLoc = Loc.getRawEncoding();
+ }
+
+ /// getAsString - Retrieve the human-readable string for this name.
+ std::string getAsString() const;
+
+ /// printName - Print the human-readable name to a stream.
+ void printName(llvm::raw_ostream &OS) const;
+
+ /// getBeginLoc - Retrieve the location of the first token.
+ SourceLocation getBeginLoc() const { return NameLoc; }
+ /// getEndLoc - Retrieve the location of the last token.
+ SourceLocation getEndLoc() const;
+ /// getSourceRange - The range of the declaration name.
+ SourceRange getSourceRange() const {
+ return SourceRange(getBeginLoc(), getEndLoc());
+ }
+};
+
/// Insertion operator for diagnostics. This allows sending DeclarationName's
/// into a diagnostic with <<.
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
@@ -385,6 +526,12 @@ inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
return PD;
}
+inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+ DeclarationNameInfo DNInfo) {
+ DNInfo.printName(OS);
+ return OS;
+}
+
} // end namespace clang
namespace llvm {
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index ade2b09c80c2..48130becf3b5 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -18,6 +18,7 @@
#include "clang/AST/Stmt.h"
#include "clang/AST/Type.h"
#include "clang/AST/DeclAccessPair.h"
+#include "clang/AST/OperationKinds.h"
#include "clang/AST/ASTVector.h"
#include "clang/AST/UsuallyTinyPtrVector.h"
#include "llvm/ADT/APSInt.h"
@@ -42,7 +43,7 @@ namespace clang {
class TemplateArgumentListInfo;
/// \brief A simple array of base specifiers.
-typedef UsuallyTinyPtrVector<const CXXBaseSpecifier> CXXBaseSpecifierArray;
+typedef llvm::SmallVector<CXXBaseSpecifier*, 4> CXXCastPath;
/// 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
@@ -61,8 +62,14 @@ protected:
/// (C++ [temp.dep.constexpr]).
bool ValueDependent : 1;
+ /// ValueKind - The value classification of this expression.
+ /// Only actually used by certain subclasses.
+ unsigned ValueKind : 2;
+
+ enum { BitsRemaining = 28 };
+
Expr(StmtClass SC, QualType T, bool TD, bool VD)
- : Stmt(SC), TypeDependent(TD), ValueDependent(VD) {
+ : Stmt(SC), TypeDependent(TD), ValueDependent(VD), ValueKind(0) {
setType(T);
}
@@ -258,7 +265,6 @@ public:
/// function returning an rvalue reference.
/// lvalues and xvalues are collectively referred to as glvalues, while
/// prvalues and xvalues together form rvalues.
- /// If a
Classification Classify(ASTContext &Ctx) const {
return ClassifyImpl(Ctx, 0);
}
@@ -310,7 +316,7 @@ public:
}
/// isConstantInitializer - Returns true if this expression is a constant
/// initializer, which can be emitted at compile-time.
- bool isConstantInitializer(ASTContext &Ctx) const;
+ bool isConstantInitializer(ASTContext &Ctx, bool ForRef) const;
/// EvalResult is a struct with detailed info about an evaluated expression.
struct EvalResult {
@@ -521,10 +527,14 @@ class DeclRefExpr : public Expr {
// (2) the declaration's name was followed by an explicit template
// argument list.
llvm::PointerIntPair<ValueDecl *, 2> DecoratedD;
-
+
// Loc - The location of the declaration name itself.
SourceLocation Loc;
+ /// DNLoc - Provides source/type location info for the
+ /// declaration name embedded in DecoratedD.
+ DeclarationNameLoc DNLoc;
+
/// \brief Retrieve the qualifier that preceded the declaration name, if any.
NameQualifier *getNameQualifier() {
if ((DecoratedD.getInt() & HasQualifierFlag) == 0)
@@ -537,31 +547,17 @@ class DeclRefExpr : public Expr {
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,
ValueDecl *D, SourceLocation NameLoc,
const TemplateArgumentListInfo *TemplateArgs,
QualType T);
+ DeclRefExpr(NestedNameSpecifier *Qualifier, SourceRange QualifierRange,
+ ValueDecl *D, const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *TemplateArgs,
+ QualType T);
+
/// \brief Construct an empty declaration reference expression.
explicit DeclRefExpr(EmptyShell Empty)
: Expr(DeclRefExprClass, Empty) { }
@@ -584,6 +580,14 @@ public:
QualType T,
const TemplateArgumentListInfo *TemplateArgs = 0);
+ static DeclRefExpr *Create(ASTContext &Context,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ ValueDecl *D,
+ const DeclarationNameInfo &NameInfo,
+ QualType T,
+ const TemplateArgumentListInfo *TemplateArgs = 0);
+
/// \brief Construct an empty declaration reference expression.
static DeclRefExpr *CreateEmpty(ASTContext &Context,
bool HasQualifier, unsigned NumTemplateArgs);
@@ -592,6 +596,10 @@ public:
const ValueDecl *getDecl() const { return DecoratedD.getPointer(); }
void setDecl(ValueDecl *NewD) { DecoratedD.setPointer(NewD); }
+ DeclarationNameInfo getNameInfo() const {
+ return DeclarationNameInfo(getDecl()->getDeclName(), Loc, DNLoc);
+ }
+
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
virtual SourceRange getSourceRange() const;
@@ -619,53 +627,77 @@ public:
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;
+ bool hasExplicitTemplateArgs() const {
+ return (DecoratedD.getInt() & HasExplicitTemplateArgumentListFlag);
+ }
+
+ /// \brief Retrieve the explicit template argument list that followed the
+ /// member template name.
+ ExplicitTemplateArgumentList &getExplicitTemplateArgs() {
+ assert(hasExplicitTemplateArgs());
+
+ 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.
+ const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const {
+ return const_cast<DeclRefExpr *>(this)->getExplicitTemplateArgs();
}
+ /// \brief Retrieves the optional explicit template arguments.
+ /// This points to the same data as getExplicitTemplateArgs(), but
+ /// returns null if there are no explicit template arguments.
+ const ExplicitTemplateArgumentList *getExplicitTemplateArgsOpt() const {
+ if (!hasExplicitTemplateArgs()) return 0;
+ return &getExplicitTemplateArgs();
+ }
+
/// \brief Copies the template arguments (if present) into the given
/// structure.
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
- if (hasExplicitTemplateArgumentList())
- getExplicitTemplateArgumentList()->copyInto(List);
+ if (hasExplicitTemplateArgs())
+ getExplicitTemplateArgs().copyInto(List);
}
/// \brief Retrieve the location of the left angle bracket following the
/// member name ('<'), if any.
SourceLocation getLAngleLoc() const {
- if (!hasExplicitTemplateArgumentList())
+ if (!hasExplicitTemplateArgs())
return SourceLocation();
- return getExplicitTemplateArgumentList()->LAngleLoc;
+ return getExplicitTemplateArgs().LAngleLoc;
}
/// \brief Retrieve the template arguments provided as part of this
/// template-id.
const TemplateArgumentLoc *getTemplateArgs() const {
- if (!hasExplicitTemplateArgumentList())
+ if (!hasExplicitTemplateArgs())
return 0;
- return getExplicitTemplateArgumentList()->getTemplateArgs();
+ return getExplicitTemplateArgs().getTemplateArgs();
}
/// \brief Retrieve the number of template arguments provided as part of this
/// template-id.
unsigned getNumTemplateArgs() const {
- if (!hasExplicitTemplateArgumentList())
+ if (!hasExplicitTemplateArgs())
return 0;
- return getExplicitTemplateArgumentList()->NumTemplateArgs;
+ return getExplicitTemplateArgs().NumTemplateArgs;
}
/// \brief Retrieve the location of the right angle bracket following the
/// template arguments ('>').
SourceLocation getRAngleLoc() const {
- if (!hasExplicitTemplateArgumentList())
+ if (!hasExplicitTemplateArgs())
return SourceLocation();
- return getExplicitTemplateArgumentList()->RAngleLoc;
+ return getExplicitTemplateArgs().RAngleLoc;
}
static bool classof(const Stmt *T) {
@@ -677,8 +709,8 @@ public:
virtual child_iterator child_begin();
virtual child_iterator child_end();
- friend class PCHStmtReader;
- friend class PCHStmtWriter;
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
};
/// PredefinedExpr - [C99 6.4.2.2] - A predefined identifier such as __func__.
@@ -725,28 +757,84 @@ public:
virtual child_iterator child_end();
};
+/// \brief Used by IntegerLiteral/FloatingLiteral to store the numeric without
+/// leaking memory.
+///
+/// For large floats/integers, APFloat/APInt will allocate memory from the heap
+/// to represent these numbers. Unfortunately, when we use a BumpPtrAllocator
+/// to allocate IntegerLiteral/FloatingLiteral nodes the memory associated with
+/// the APFloat/APInt values will never get freed. APNumericStorage uses
+/// ASTContext's allocator for memory allocation.
+class APNumericStorage {
+ unsigned BitWidth;
+ union {
+ uint64_t VAL; ///< Used to store the <= 64 bits integer value.
+ uint64_t *pVal; ///< Used to store the >64 bits integer value.
+ };
+
+ bool hasAllocation() const { return llvm::APInt::getNumWords(BitWidth) > 1; }
+
+ APNumericStorage(const APNumericStorage&); // do not implement
+ APNumericStorage& operator=(const APNumericStorage&); // do not implement
+
+protected:
+ APNumericStorage() : BitWidth(0), VAL(0) { }
+
+ llvm::APInt getIntValue() const {
+ unsigned NumWords = llvm::APInt::getNumWords(BitWidth);
+ if (NumWords > 1)
+ return llvm::APInt(BitWidth, NumWords, pVal);
+ else
+ return llvm::APInt(BitWidth, VAL);
+ }
+ void setIntValue(ASTContext &C, const llvm::APInt &Val);
+};
+
+class APIntStorage : public APNumericStorage {
+public:
+ llvm::APInt getValue() const { return getIntValue(); }
+ void setValue(ASTContext &C, const llvm::APInt &Val) { setIntValue(C, Val); }
+};
+
+class APFloatStorage : public APNumericStorage {
+public:
+ llvm::APFloat getValue() const { return llvm::APFloat(getIntValue()); }
+ void setValue(ASTContext &C, const llvm::APFloat &Val) {
+ setIntValue(C, Val.bitcastToAPInt());
+ }
+};
+
class IntegerLiteral : public Expr {
- llvm::APInt Value;
+ APIntStorage Num;
SourceLocation Loc;
+
+ /// \brief Construct an empty integer literal.
+ explicit IntegerLiteral(EmptyShell Empty)
+ : Expr(IntegerLiteralClass, Empty) { }
+
public:
// type should be IntTy, LongTy, LongLongTy, UnsignedIntTy, UnsignedLongTy,
// or UnsignedLongLongTy
- IntegerLiteral(const llvm::APInt &V, QualType type, SourceLocation l)
- : Expr(IntegerLiteralClass, type, false, false), Value(V), Loc(l) {
+ IntegerLiteral(ASTContext &C, const llvm::APInt &V,
+ QualType type, SourceLocation l)
+ : Expr(IntegerLiteralClass, type, false, false), Loc(l) {
assert(type->isIntegerType() && "Illegal type in IntegerLiteral");
+ setValue(C, V);
}
- /// \brief Construct an empty integer literal.
- explicit IntegerLiteral(EmptyShell Empty)
- : Expr(IntegerLiteralClass, Empty) { }
+ // type should be IntTy, LongTy, LongLongTy, UnsignedIntTy, UnsignedLongTy,
+ // or UnsignedLongLongTy
+ static IntegerLiteral *Create(ASTContext &C, const llvm::APInt &V,
+ QualType type, SourceLocation l);
+ static IntegerLiteral *Create(ASTContext &C, EmptyShell Empty);
- const llvm::APInt &getValue() const { return Value; }
+ llvm::APInt getValue() const { return Num.getValue(); }
virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
/// \brief Retrieve the location of the literal.
SourceLocation getLocation() const { return Loc; }
- void setValue(const llvm::APInt &Val) { Value = Val; }
+ void setValue(ASTContext &C, const llvm::APInt &Val) { Num.setValue(C, Val); }
void setLocation(SourceLocation Location) { Loc = Location; }
static bool classof(const Stmt *T) {
@@ -795,21 +883,30 @@ public:
};
class FloatingLiteral : public Expr {
- llvm::APFloat Value;
+ APFloatStorage Num;
bool IsExact : 1;
SourceLocation Loc;
-public:
- FloatingLiteral(const llvm::APFloat &V, bool isexact,
+
+ FloatingLiteral(ASTContext &C, const llvm::APFloat &V, bool isexact,
QualType Type, SourceLocation L)
- : Expr(FloatingLiteralClass, Type, false, false), Value(V),
- IsExact(isexact), Loc(L) {}
+ : Expr(FloatingLiteralClass, Type, false, false),
+ IsExact(isexact), Loc(L) {
+ setValue(C, V);
+ }
/// \brief Construct an empty floating-point literal.
explicit FloatingLiteral(EmptyShell Empty)
- : Expr(FloatingLiteralClass, Empty), Value(0.0) { }
+ : Expr(FloatingLiteralClass, Empty), IsExact(false) { }
- const llvm::APFloat &getValue() const { return Value; }
- void setValue(const llvm::APFloat &Val) { Value = Val; }
+public:
+ static FloatingLiteral *Create(ASTContext &C, const llvm::APFloat &V,
+ bool isexact, QualType Type, SourceLocation L);
+ static FloatingLiteral *Create(ASTContext &C, EmptyShell Empty);
+
+ llvm::APFloat getValue() const { return Num.getValue(); }
+ void setValue(ASTContext &C, const llvm::APFloat &Val) {
+ Num.setValue(C, Val);
+ }
bool isExact() const { return IsExact; }
void setExact(bool E) { IsExact = E; }
@@ -889,9 +986,6 @@ class StringLiteral : public Expr {
StringLiteral(QualType Ty) : Expr(StringLiteralClass, Ty, false, false) {}
-protected:
- virtual void DoDestroy(ASTContext &C);
-
public:
/// This is the "fully general" constructor that allows representation of
/// strings formed from multiple concatenated tokens.
@@ -912,8 +1006,7 @@ public:
llvm::StringRef getString() const {
return llvm::StringRef(StrData, ByteLength);
}
- // FIXME: These are deprecated, replace with StringRef.
- const char *getStrData() const { return StrData; }
+
unsigned getByteLength() const { return ByteLength; }
/// \brief Sets the string data to the given string data.
@@ -1009,40 +1102,27 @@ public:
/// applied to a non-complex value, the former returns its operand and the
/// later returns zero in the type of the operand.
///
-/// __builtin_offsetof(type, a.b[10]) is represented as a unary operator whose
-/// subexpression is a compound literal with the various MemberExpr and
-/// ArraySubscriptExpr's applied to it. (This is only used in C)
-///
class UnaryOperator : public Expr {
public:
- // Note that additions to this should also update the StmtVisitor class.
- enum Opcode {
- PostInc, PostDec, // [C99 6.5.2.4] Postfix increment and decrement operators
- PreInc, PreDec, // [C99 6.5.3.1] Prefix increment and decrement operators.
- AddrOf, Deref, // [C99 6.5.3.2] Address and indirection operators.
- Plus, Minus, // [C99 6.5.3.3] Unary arithmetic operators.
- Not, LNot, // [C99 6.5.3.3] Unary arithmetic operators.
- Real, Imag, // "__real expr"/"__imag expr" Extension.
- Extension, // __extension__ marker.
- OffsetOf // __builtin_offsetof
- };
+ typedef UnaryOperatorKind Opcode;
+
private:
- Stmt *Val;
- Opcode Opc;
+ unsigned Opc : 5;
SourceLocation Loc;
+ Stmt *Val;
public:
UnaryOperator(Expr *input, Opcode opc, QualType type, SourceLocation l)
: Expr(UnaryOperatorClass, type,
- input->isTypeDependent() && opc != OffsetOf,
+ input->isTypeDependent() || type->isDependentType(),
input->isValueDependent()),
- Val(input), Opc(opc), Loc(l) {}
+ Opc(opc), Loc(l), Val(input) {}
/// \brief Build an empty unary operator.
explicit UnaryOperator(EmptyShell Empty)
- : Expr(UnaryOperatorClass, Empty), Opc(AddrOf) { }
+ : Expr(UnaryOperatorClass, Empty), Opc(UO_AddrOf) { }
- Opcode getOpcode() const { return Opc; }
+ Opcode getOpcode() const { return static_cast<Opcode>(Opc); }
void setOpcode(Opcode O) { Opc = O; }
Expr *getSubExpr() const { return cast<Expr>(Val); }
@@ -1054,21 +1134,26 @@ public:
/// isPostfix - Return true if this is a postfix operation, like x++.
static bool isPostfix(Opcode Op) {
- return Op == PostInc || Op == PostDec;
+ return Op == UO_PostInc || Op == UO_PostDec;
}
/// isPostfix - Return true if this is a prefix operation, like --x.
static bool isPrefix(Opcode Op) {
- return Op == PreInc || Op == PreDec;
+ return Op == UO_PreInc || Op == UO_PreDec;
}
- bool isPrefix() const { return isPrefix(Opc); }
- bool isPostfix() const { return isPostfix(Opc); }
- bool isIncrementOp() const {return Opc==PreInc || Opc==PostInc; }
- bool isIncrementDecrementOp() const { return Opc>=PostInc && Opc<=PreDec; }
- bool isOffsetOfOp() const { return Opc == OffsetOf; }
- static bool isArithmeticOp(Opcode Op) { return Op >= Plus && Op <= LNot; }
- bool isArithmeticOp() const { return isArithmeticOp(Opc); }
+ bool isPrefix() const { return isPrefix(getOpcode()); }
+ bool isPostfix() const { return isPostfix(getOpcode()); }
+ bool isIncrementOp() const {
+ return Opc == UO_PreInc || Opc == UO_PostInc;
+ }
+ bool isIncrementDecrementOp() const {
+ return Opc <= UO_PreDec;
+ }
+ static bool isArithmeticOp(Opcode Op) {
+ return Op >= UO_Plus && Op <= UO_LNot;
+ }
+ bool isArithmeticOp() const { return isArithmeticOp(getOpcode()); }
/// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
/// corresponds to, e.g. "sizeof" or "[pre]++"
@@ -1310,9 +1395,6 @@ class SizeOfAlignOfExpr : public Expr {
} Argument;
SourceLocation OpLoc, RParenLoc;
-protected:
- virtual void DoDestroy(ASTContext& C);
-
public:
SizeOfAlignOfExpr(bool issizeof, TypeSourceInfo *TInfo,
QualType resultType, SourceLocation op,
@@ -1485,8 +1567,6 @@ protected:
CallExpr(ASTContext& C, StmtClass SC, Expr *fn, Expr **args, unsigned numargs,
QualType t, SourceLocation rparenloc);
- virtual void DoDestroy(ASTContext& C);
-
public:
CallExpr(ASTContext& C, Expr *fn, Expr **args, unsigned numargs, QualType t,
SourceLocation rparenloc);
@@ -1494,8 +1574,6 @@ public:
/// \brief Build an empty call expression.
CallExpr(ASTContext &C, StmtClass SC, EmptyShell Empty);
- ~CallExpr() {}
-
const Expr *getCallee() const { return cast<Expr>(SubExprs[FN]); }
Expr *getCallee() { return cast<Expr>(SubExprs[FN]); }
void setCallee(Expr *F) { SubExprs[FN] = F; }
@@ -1594,6 +1672,10 @@ class MemberExpr : public Expr {
/// MemberLoc - This is the location of the member name.
SourceLocation MemberLoc;
+ /// MemberDNLoc - Provides source/type location info for the
+ /// declaration name embedded in MemberDecl.
+ DeclarationNameLoc MemberDNLoc;
+
/// IsArrow - True if this is "X->F", false if this is "X.F".
bool IsArrow : 1;
@@ -1621,37 +1703,33 @@ class MemberExpr : public Expr {
return const_cast<MemberExpr *>(this)->getMemberQualifier();
}
- /// \brief Retrieve the explicit template argument list that followed the
- /// member template name, if any.
- ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() {
- if (!HasExplicitTemplateArgumentList)
- return 0;
-
- if (!HasQualifierOrFoundDecl)
- return reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1);
-
- return reinterpret_cast<ExplicitTemplateArgumentList *>(
- getMemberQualifier() + 1);
- }
-
- /// \brief Retrieve the explicit template argument list that followed the
- /// member template name, if any.
- const ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() const {
- return const_cast<MemberExpr *>(this)->getExplicitTemplateArgumentList();
+public:
+ MemberExpr(Expr *base, bool isarrow, ValueDecl *memberdecl,
+ const DeclarationNameInfo &NameInfo, QualType ty)
+ : Expr(MemberExprClass, ty,
+ base->isTypeDependent(), base->isValueDependent()),
+ Base(base), MemberDecl(memberdecl), MemberLoc(NameInfo.getLoc()),
+ MemberDNLoc(NameInfo.getInfo()), IsArrow(isarrow),
+ HasQualifierOrFoundDecl(false), HasExplicitTemplateArgumentList(false) {
+ assert(memberdecl->getDeclName() == NameInfo.getName());
}
-public:
+ // NOTE: this constructor should be used only when it is known that
+ // the member name can not provide additional syntactic info
+ // (i.e., source locations for C++ operator names or type source info
+ // for constructors, destructors and conversion oeprators).
MemberExpr(Expr *base, bool isarrow, ValueDecl *memberdecl,
SourceLocation l, QualType ty)
: Expr(MemberExprClass, ty,
base->isTypeDependent(), base->isValueDependent()),
- Base(base), MemberDecl(memberdecl), MemberLoc(l), IsArrow(isarrow),
+ Base(base), MemberDecl(memberdecl), MemberLoc(l), MemberDNLoc(),
+ IsArrow(isarrow),
HasQualifierOrFoundDecl(false), HasExplicitTemplateArgumentList(false) {}
static MemberExpr *Create(ASTContext &C, Expr *base, bool isarrow,
NestedNameSpecifier *qual, SourceRange qualrange,
ValueDecl *memberdecl, DeclAccessPair founddecl,
- SourceLocation l,
+ DeclarationNameInfo MemberNameInfo,
const TemplateArgumentListInfo *targs,
QualType ty);
@@ -1700,15 +1778,42 @@ public:
/// \brief Determines whether this member expression actually had a C++
/// template argument list explicitly specified, e.g., x.f<int>.
- bool hasExplicitTemplateArgumentList() const {
+ bool hasExplicitTemplateArgs() const {
return HasExplicitTemplateArgumentList;
}
/// \brief Copies the template arguments (if present) into the given
/// structure.
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
- if (hasExplicitTemplateArgumentList())
- getExplicitTemplateArgumentList()->copyInto(List);
+ if (hasExplicitTemplateArgs())
+ getExplicitTemplateArgs().copyInto(List);
+ }
+
+ /// \brief Retrieve the explicit template argument list that
+ /// follow the member template name. This must only be called on an
+ /// expression with explicit template arguments.
+ ExplicitTemplateArgumentList &getExplicitTemplateArgs() {
+ assert(HasExplicitTemplateArgumentList);
+ if (!HasQualifierOrFoundDecl)
+ return *reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1);
+
+ return *reinterpret_cast<ExplicitTemplateArgumentList *>(
+ getMemberQualifier() + 1);
+ }
+
+ /// \brief Retrieve the explicit template argument list that
+ /// followed the member template name. This must only be called on
+ /// an expression with explicit template arguments.
+ const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const {
+ return const_cast<MemberExpr *>(this)->getExplicitTemplateArgs();
+ }
+
+ /// \brief Retrieves the optional explicit template arguments.
+ /// This points to the same data as getExplicitTemplateArgs(), but
+ /// returns null if there are no explicit template arguments.
+ const ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() const {
+ if (!hasExplicitTemplateArgs()) return 0;
+ return &getExplicitTemplateArgs();
}
/// \brief Retrieve the location of the left angle bracket following the
@@ -1717,7 +1822,7 @@ public:
if (!HasExplicitTemplateArgumentList)
return SourceLocation();
- return getExplicitTemplateArgumentList()->LAngleLoc;
+ return getExplicitTemplateArgs().LAngleLoc;
}
/// \brief Retrieve the template arguments provided as part of this
@@ -1726,7 +1831,7 @@ public:
if (!HasExplicitTemplateArgumentList)
return 0;
- return getExplicitTemplateArgumentList()->getTemplateArgs();
+ return getExplicitTemplateArgs().getTemplateArgs();
}
/// \brief Retrieve the number of template arguments provided as part of this
@@ -1735,7 +1840,7 @@ public:
if (!HasExplicitTemplateArgumentList)
return 0;
- return getExplicitTemplateArgumentList()->NumTemplateArgs;
+ return getExplicitTemplateArgs().NumTemplateArgs;
}
/// \brief Retrieve the location of the right angle bracket following the
@@ -1744,7 +1849,13 @@ public:
if (!HasExplicitTemplateArgumentList)
return SourceLocation();
- return getExplicitTemplateArgumentList()->RAngleLoc;
+ return getExplicitTemplateArgs().RAngleLoc;
+ }
+
+ /// \brief Retrieve the member declaration name info.
+ DeclarationNameInfo getMemberNameInfo() const {
+ return DeclarationNameInfo(MemberDecl->getDeclName(),
+ MemberLoc, MemberDNLoc);
}
bool isArrow() const { return IsArrow; }
@@ -1758,9 +1869,8 @@ public:
virtual SourceRange getSourceRange() const {
// If we have an implicit base (like a C++ implicit this),
// make sure not to return its location
- SourceLocation EndLoc = MemberLoc;
- if (HasExplicitTemplateArgumentList)
- EndLoc = getRAngleLoc();
+ SourceLocation EndLoc = (HasExplicitTemplateArgumentList)
+ ? getRAngleLoc() : getMemberNameInfo().getEndLoc();
SourceLocation BaseLoc = getBase()->getLocStart();
if (BaseLoc.isInvalid())
@@ -1843,110 +1953,13 @@ public:
/// classes).
class CastExpr : public Expr {
public:
- /// CastKind - the kind of cast this represents.
- enum CastKind {
- /// CK_Unknown - Unknown cast kind.
- /// FIXME: The goal is to get rid of this and make all casts have a
- /// kind so that the AST client doesn't have to try to figure out what's
- /// going on.
- CK_Unknown,
-
- /// CK_BitCast - Used for reinterpret_cast.
- CK_BitCast,
-
- /// CK_LValueBitCast - Used for reinterpret_cast of expressions to
- /// a reference type.
- CK_LValueBitCast,
-
- /// CK_NoOp - Used for const_cast.
- CK_NoOp,
-
- /// CK_BaseToDerived - Base to derived class casts.
- CK_BaseToDerived,
-
- /// CK_DerivedToBase - Derived to base class casts.
- CK_DerivedToBase,
-
- /// CK_UncheckedDerivedToBase - Derived to base class casts that
- /// assume that the derived pointer is not null.
- CK_UncheckedDerivedToBase,
-
- /// CK_Dynamic - Dynamic cast.
- CK_Dynamic,
-
- /// CK_ToUnion - Cast to union (GCC extension).
- CK_ToUnion,
-
- /// CK_ArrayToPointerDecay - Array to pointer decay.
- CK_ArrayToPointerDecay,
-
- // CK_FunctionToPointerDecay - Function to pointer decay.
- CK_FunctionToPointerDecay,
-
- /// CK_NullToMemberPointer - Null pointer to member pointer.
- CK_NullToMemberPointer,
-
- /// CK_BaseToDerivedMemberPointer - Member pointer in base class to
- /// 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,
-
- /// CK_ConstructorConversion - Conversion by constructor
- CK_ConstructorConversion,
-
- /// CK_IntegralToPointer - Integral to pointer
- CK_IntegralToPointer,
-
- /// CK_PointerToIntegral - Pointer to integral
- CK_PointerToIntegral,
-
- /// CK_ToVoid - Cast to void.
- CK_ToVoid,
-
- /// CK_VectorSplat - Casting from an integer/floating type to an extended
- /// vector type with the same element type as the src type. Splats the
- /// src expression into the destination expression.
- CK_VectorSplat,
-
- /// CK_IntegralCast - Casting between integral types of different size.
- CK_IntegralCast,
-
- /// CK_IntegralToFloating - Integral to floating point.
- CK_IntegralToFloating,
-
- /// CK_FloatingToIntegral - Floating point to integral.
- CK_FloatingToIntegral,
-
- /// CK_FloatingCast - Casting between floating types of different size.
- CK_FloatingCast,
-
- /// CK_MemberPointerToBoolean - Member pointer to boolean
- CK_MemberPointerToBoolean,
-
- /// CK_AnyPointerToObjCPointerCast - Casting any pointer to objective-c
- /// pointer
- CK_AnyPointerToObjCPointerCast,
- /// CK_AnyPointerToBlockPointerCast - Casting any pointer to block
- /// pointer
- CK_AnyPointerToBlockPointerCast
-
- };
+ typedef clang::CastKind CastKind;
private:
- CastKind Kind;
+ unsigned Kind : 5;
+ unsigned BasePathSize : BitsRemaining - 5;
Stmt *Op;
- /// BasePath - For derived-to-base and base-to-derived casts, the base array
- /// contains the inheritance path.
- CXXBaseSpecifierArray BasePath;
-
void CheckBasePath() const {
#ifndef NDEBUG
switch (getCastKind()) {
@@ -1955,7 +1968,7 @@ private:
case CK_DerivedToBaseMemberPointer:
case CK_BaseToDerived:
case CK_BaseToDerivedMemberPointer:
- assert(!BasePath.empty() && "Cast kind should have a base path!");
+ assert(!path_empty() && "Cast kind should have a base path!");
break;
// These should not have an inheritance path.
@@ -1981,15 +1994,21 @@ private:
case CK_MemberPointerToBoolean:
case CK_AnyPointerToObjCPointerCast:
case CK_AnyPointerToBlockPointerCast:
- assert(BasePath.empty() && "Cast kind should not have a base path!");
+ case CK_ObjCObjectLValueCast:
+ assert(path_empty() && "Cast kind should not have a base path!");
break;
}
#endif
}
+ const CXXBaseSpecifier * const *path_buffer() const {
+ return const_cast<CastExpr*>(this)->path_buffer();
+ }
+ CXXBaseSpecifier **path_buffer();
+
protected:
CastExpr(StmtClass SC, QualType ty, const CastKind kind, Expr *op,
- CXXBaseSpecifierArray BasePath) :
+ unsigned BasePathSize) :
Expr(SC, ty,
// Cast expressions are type-dependent if the type is
// dependent (C++ [temp.dep.expr]p3).
@@ -1997,18 +2016,16 @@ protected:
// Cast expressions are value-dependent if the type is
// dependent or if the subexpression is value-dependent.
ty->isDependentType() || (op && op->isValueDependent())),
- Kind(kind), Op(op), BasePath(BasePath) {
- CheckBasePath();
- }
+ Kind(kind), BasePathSize(BasePathSize), Op(op) {
+ CheckBasePath();
+ }
/// \brief Construct an empty cast.
- CastExpr(StmtClass SC, EmptyShell Empty)
- : Expr(SC, Empty) { }
-
- virtual void DoDestroy(ASTContext &C);
+ CastExpr(StmtClass SC, EmptyShell Empty, unsigned BasePathSize)
+ : Expr(SC, Empty), BasePathSize(BasePathSize) { }
public:
- CastKind getCastKind() const { return Kind; }
+ CastKind getCastKind() const { return static_cast<CastKind>(Kind); }
void setCastKind(CastKind K) { Kind = K; }
const char *getCastKindName() const;
@@ -2024,8 +2041,16 @@ public:
return const_cast<CastExpr *>(this)->getSubExprAsWritten();
}
- const CXXBaseSpecifierArray& getBasePath() const { return BasePath; }
- CXXBaseSpecifierArray& getBasePath() { return BasePath; }
+ typedef CXXBaseSpecifier **path_iterator;
+ typedef const CXXBaseSpecifier * const *path_const_iterator;
+ bool path_empty() const { return BasePathSize == 0; }
+ unsigned path_size() const { return BasePathSize; }
+ path_iterator path_begin() { return path_buffer(); }
+ path_iterator path_end() { return path_buffer() + path_size(); }
+ path_const_iterator path_begin() const { return path_buffer(); }
+ path_const_iterator path_end() const { return path_buffer() + path_size(); }
+
+ void setCastPath(const CXXCastPath &Path);
static bool classof(const Stmt *T) {
return T->getStmtClass() >= firstCastExprConstant &&
@@ -2045,38 +2070,57 @@ public:
///
/// In C, implicit casts always produce rvalues. However, in C++, an
/// implicit cast whose result is being bound to a reference will be
-/// an lvalue. For example:
+/// an lvalue or xvalue. For example:
///
/// @code
/// class Base { };
/// class Derived : public Base { };
+/// Derived &&ref();
/// void f(Derived d) {
-/// Base& b = d; // initializer is an ImplicitCastExpr to an lvalue of type Base
+/// Base& b = d; // initializer is an ImplicitCastExpr
+/// // to an lvalue of type Base
+/// Base&& r = ref(); // initializer is an ImplicitCastExpr
+/// // to an xvalue of type Base
/// }
/// @endcode
class ImplicitCastExpr : public CastExpr {
- /// LvalueCast - Whether this cast produces an lvalue.
- bool LvalueCast;
+private:
+ ImplicitCastExpr(QualType ty, CastKind kind, Expr *op,
+ unsigned BasePathLength, ExprValueKind VK)
+ : CastExpr(ImplicitCastExprClass, ty, kind, op, BasePathLength) {
+ ValueKind = VK;
+ }
+
+ /// \brief Construct an empty implicit cast.
+ explicit ImplicitCastExpr(EmptyShell Shell, unsigned PathSize)
+ : CastExpr(ImplicitCastExprClass, Shell, PathSize) { }
public:
- ImplicitCastExpr(QualType ty, CastKind kind, Expr *op,
- CXXBaseSpecifierArray BasePath, bool Lvalue)
- : CastExpr(ImplicitCastExprClass, ty, kind, op, BasePath),
- LvalueCast(Lvalue) { }
+ enum OnStack_t { OnStack };
+ ImplicitCastExpr(OnStack_t _, QualType ty, CastKind kind, Expr *op,
+ ExprValueKind VK)
+ : CastExpr(ImplicitCastExprClass, ty, kind, op, 0) {
+ ValueKind = VK;
+ }
- /// \brief Construct an empty implicit cast.
- explicit ImplicitCastExpr(EmptyShell Shell)
- : CastExpr(ImplicitCastExprClass, Shell) { }
+ static ImplicitCastExpr *Create(ASTContext &Context, QualType T,
+ CastKind Kind, Expr *Operand,
+ const CXXCastPath *BasePath,
+ ExprValueKind Cat);
+
+ static ImplicitCastExpr *CreateEmpty(ASTContext &Context, unsigned PathSize);
virtual SourceRange getSourceRange() const {
return getSubExpr()->getSourceRange();
}
- /// isLvalueCast - Whether this cast produces an lvalue.
- bool isLvalueCast() const { return LvalueCast; }
+ /// getValueKind - The value kind that this cast produces.
+ ExprValueKind getValueKind() const {
+ return static_cast<ExprValueKind>(ValueKind);
+ }
- /// setLvalueCast - Set whether this cast produces an lvalue.
- void setLvalueCast(bool Lvalue) { LvalueCast = Lvalue; }
+ /// setValueKind - Set the value kind this cast produces.
+ void setValueKind(ExprValueKind Cat) { ValueKind = Cat; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == ImplicitCastExprClass;
@@ -2098,8 +2142,8 @@ public:
/// actual type of the expression as determined by semantic
/// analysis. These types may differ slightly. For example, in C++ one
/// can cast to a reference type, which indicates that the resulting
-/// expression will be an lvalue. The reference type, however, will
-/// not be used as the type of the expression.
+/// expression will be an lvalue or xvalue. The reference type, however,
+/// will not be used as the type of the expression.
class ExplicitCastExpr : public CastExpr {
/// TInfo - Source type info for the (written) type
/// this expression is casting to.
@@ -2107,13 +2151,12 @@ class ExplicitCastExpr : public CastExpr {
protected:
ExplicitCastExpr(StmtClass SC, QualType exprTy, CastKind kind,
- Expr *op, CXXBaseSpecifierArray BasePath,
- TypeSourceInfo *writtenTy)
- : CastExpr(SC, exprTy, kind, op, BasePath), TInfo(writtenTy) {}
+ Expr *op, unsigned PathSize, TypeSourceInfo *writtenTy)
+ : CastExpr(SC, exprTy, kind, op, PathSize), TInfo(writtenTy) {}
/// \brief Construct an empty explicit cast.
- ExplicitCastExpr(StmtClass SC, EmptyShell Shell)
- : CastExpr(SC, Shell) { }
+ ExplicitCastExpr(StmtClass SC, EmptyShell Shell, unsigned PathSize)
+ : CastExpr(SC, Shell, PathSize) { }
public:
/// getTypeInfoAsWritten - Returns the type source info for the type
@@ -2138,16 +2181,24 @@ public:
class CStyleCastExpr : public ExplicitCastExpr {
SourceLocation LPLoc; // the location of the left paren
SourceLocation RPLoc; // the location of the right paren
-public:
+
CStyleCastExpr(QualType exprTy, CastKind kind, Expr *op,
- CXXBaseSpecifierArray BasePath, TypeSourceInfo *writtenTy,
+ unsigned PathSize, TypeSourceInfo *writtenTy,
SourceLocation l, SourceLocation r)
- : ExplicitCastExpr(CStyleCastExprClass, exprTy, kind, op, BasePath,
+ : ExplicitCastExpr(CStyleCastExprClass, exprTy, kind, op, PathSize,
writtenTy), LPLoc(l), RPLoc(r) {}
/// \brief Construct an empty C-style explicit cast.
- explicit CStyleCastExpr(EmptyShell Shell)
- : ExplicitCastExpr(CStyleCastExprClass, Shell) { }
+ explicit CStyleCastExpr(EmptyShell Shell, unsigned PathSize)
+ : ExplicitCastExpr(CStyleCastExprClass, Shell, PathSize) { }
+
+public:
+ static CStyleCastExpr *Create(ASTContext &Context, QualType T, CastKind K,
+ Expr *Op, const CXXCastPath *BasePath,
+ TypeSourceInfo *WrittenTy, SourceLocation L,
+ SourceLocation R);
+
+ static CStyleCastExpr *CreateEmpty(ASTContext &Context, unsigned PathSize);
SourceLocation getLParenLoc() const { return LPLoc; }
void setLParenLoc(SourceLocation L) { LPLoc = L; }
@@ -2184,33 +2235,14 @@ public:
/// be used to express the computation.
class BinaryOperator : public Expr {
public:
- enum Opcode {
- // Operators listed in order of precedence.
- // Note that additions to this should also update the StmtVisitor class.
- PtrMemD, PtrMemI, // [C++ 5.5] Pointer-to-member operators.
- Mul, Div, Rem, // [C99 6.5.5] Multiplicative operators.
- Add, Sub, // [C99 6.5.6] Additive operators.
- Shl, Shr, // [C99 6.5.7] Bitwise shift operators.
- LT, GT, LE, GE, // [C99 6.5.8] Relational operators.
- EQ, NE, // [C99 6.5.9] Equality operators.
- And, // [C99 6.5.10] Bitwise AND operator.
- Xor, // [C99 6.5.11] Bitwise XOR operator.
- Or, // [C99 6.5.12] Bitwise OR operator.
- LAnd, // [C99 6.5.13] Logical AND operator.
- LOr, // [C99 6.5.14] Logical OR operator.
- Assign, MulAssign,// [C99 6.5.16] Assignment operators.
- DivAssign, RemAssign,
- AddAssign, SubAssign,
- ShlAssign, ShrAssign,
- AndAssign, XorAssign,
- OrAssign,
- Comma // [C99 6.5.17] Comma operator.
- };
+ typedef BinaryOperatorKind Opcode;
+
private:
+ unsigned Opc : 6;
+ SourceLocation OpLoc;
+
enum { LHS, RHS, END_EXPR };
Stmt* SubExprs[END_EXPR];
- Opcode Opc;
- SourceLocation OpLoc;
public:
BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy,
@@ -2227,12 +2259,12 @@ public:
/// \brief Construct an empty binary operator.
explicit BinaryOperator(EmptyShell Empty)
- : Expr(BinaryOperatorClass, Empty), Opc(Comma) { }
+ : Expr(BinaryOperatorClass, Empty), Opc(BO_Comma) { }
SourceLocation getOperatorLoc() const { return OpLoc; }
void setOperatorLoc(SourceLocation L) { OpLoc = L; }
- Opcode getOpcode() const { return Opc; }
+ Opcode getOpcode() const { return static_cast<Opcode>(Opc); }
void setOpcode(Opcode O) { Opc = O; }
Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); }
@@ -2248,6 +2280,8 @@ public:
/// corresponds to, e.g. "<<=".
static const char *getOpcodeStr(Opcode Op);
+ const char *getOpcodeStr() const { return getOpcodeStr(getOpcode()); }
+
/// \brief Retrieve the binary opcode that corresponds to the given
/// overloaded operator.
static Opcode getOverloadedOpcode(OverloadedOperatorKind OO);
@@ -2257,30 +2291,34 @@ public:
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc);
/// predicates to categorize the respective opcodes.
- bool isMultiplicativeOp() const { return Opc >= Mul && Opc <= Rem; }
- static bool isAdditiveOp(Opcode Opc) { return Opc == Add || Opc == Sub; }
- bool isAdditiveOp() const { return isAdditiveOp(Opc); }
- static bool isShiftOp(Opcode Opc) { return Opc == Shl || Opc == Shr; }
- bool isShiftOp() const { return isShiftOp(Opc); }
+ bool isMultiplicativeOp() const { return Opc >= BO_Mul && Opc <= BO_Rem; }
+ static bool isAdditiveOp(Opcode Opc) { return Opc == BO_Add || Opc==BO_Sub; }
+ bool isAdditiveOp() const { return isAdditiveOp(getOpcode()); }
+ static bool isShiftOp(Opcode Opc) { return Opc == BO_Shl || Opc == BO_Shr; }
+ bool isShiftOp() const { return isShiftOp(getOpcode()); }
- static bool isBitwiseOp(Opcode Opc) { return Opc >= And && Opc <= Or; }
- bool isBitwiseOp() const { return isBitwiseOp(Opc); }
+ static bool isBitwiseOp(Opcode Opc) { return Opc >= BO_And && Opc <= BO_Or; }
+ bool isBitwiseOp() const { return isBitwiseOp(getOpcode()); }
- static bool isRelationalOp(Opcode Opc) { return Opc >= LT && Opc <= GE; }
- bool isRelationalOp() const { return isRelationalOp(Opc); }
+ static bool isRelationalOp(Opcode Opc) { return Opc >= BO_LT && Opc<=BO_GE; }
+ bool isRelationalOp() const { return isRelationalOp(getOpcode()); }
- static bool isEqualityOp(Opcode Opc) { return Opc == EQ || Opc == NE; }
- bool isEqualityOp() const { return isEqualityOp(Opc); }
+ static bool isEqualityOp(Opcode Opc) { return Opc == BO_EQ || Opc == BO_NE; }
+ bool isEqualityOp() const { return isEqualityOp(getOpcode()); }
- static bool isComparisonOp(Opcode Opc) { return Opc >= LT && Opc <= NE; }
- bool isComparisonOp() const { return isComparisonOp(Opc); }
+ static bool isComparisonOp(Opcode Opc) { return Opc >= BO_LT && Opc<=BO_NE; }
+ bool isComparisonOp() const { return isComparisonOp(getOpcode()); }
- static bool isLogicalOp(Opcode Opc) { return Opc == LAnd || Opc == LOr; }
- bool isLogicalOp() const { return isLogicalOp(Opc); }
+ static bool isLogicalOp(Opcode Opc) { return Opc == BO_LAnd || Opc==BO_LOr; }
+ bool isLogicalOp() const { return isLogicalOp(getOpcode()); }
- bool isAssignmentOp() const { return Opc >= Assign && Opc <= OrAssign; }
- bool isCompoundAssignmentOp() const { return Opc > Assign && Opc <= OrAssign;}
- bool isShiftAssignOp() const { return Opc == ShlAssign || Opc == ShrAssign; }
+ bool isAssignmentOp() const { return Opc >= BO_Assign && Opc <= BO_OrAssign; }
+ bool isCompoundAssignmentOp() const {
+ return Opc > BO_Assign && Opc <= BO_OrAssign;
+ }
+ bool isShiftAssignOp() const {
+ return Opc == BO_ShlAssign || Opc == BO_ShrAssign;
+ }
static bool classof(const Stmt *S) {
return S->getStmtClass() >= firstBinaryOperatorConstant &&
@@ -2304,7 +2342,7 @@ protected:
}
BinaryOperator(StmtClass SC, EmptyShell Empty)
- : Expr(SC, Empty), Opc(MulAssign) { }
+ : Expr(SC, Empty), Opc(BO_MulAssign) { }
};
/// CompoundAssignOperator - For compound assignments (e.g. +=), we keep
@@ -2353,10 +2391,11 @@ public:
class ConditionalOperator : public Expr {
enum { COND, LHS, RHS, END_EXPR };
Stmt* SubExprs[END_EXPR]; // Left/Middle/Right hand sides.
+ Stmt* Save;
SourceLocation QuestionLoc, ColonLoc;
public:
ConditionalOperator(Expr *cond, SourceLocation QLoc, Expr *lhs,
- SourceLocation CLoc, Expr *rhs, QualType t)
+ SourceLocation CLoc, Expr *rhs, Expr *save, QualType t)
: Expr(ConditionalOperatorClass, t,
// FIXME: the type of the conditional operator doesn't
// depend on the type of the conditional, but the standard
@@ -2370,6 +2409,7 @@ public:
SubExprs[COND] = cond;
SubExprs[LHS] = lhs;
SubExprs[RHS] = rhs;
+ Save = save;
}
/// \brief Build an empty conditional operator.
@@ -2382,25 +2422,31 @@ public:
void setCond(Expr *E) { SubExprs[COND] = E; }
// getTrueExpr - Return the subexpression representing the value of the ?:
- // expression if the condition evaluates to true. In most cases this value
- // will be the same as getLHS() except a GCC extension allows the left
- // subexpression to be omitted, and instead of the condition be returned.
- // e.g: x ?: y is shorthand for x ? x : y, except that the expression "x"
- // is only evaluated once.
+ // expression if the condition evaluates to true.
Expr *getTrueExpr() const {
- return cast<Expr>(SubExprs[LHS] ? SubExprs[LHS] : SubExprs[COND]);
+ return cast<Expr>(!Save ? SubExprs[LHS] : SubExprs[COND]);
}
- // getTrueExpr - Return the subexpression representing the value of the ?:
+ // getFalseExpr - Return the subexpression representing the value of the ?:
// expression if the condition evaluates to false. This is the same as getRHS.
Expr *getFalseExpr() const { return cast<Expr>(SubExprs[RHS]); }
-
- Expr *getLHS() const { return cast_or_null<Expr>(SubExprs[LHS]); }
+
+ // getSaveExpr - In most cases this value will be null. Except a GCC extension
+ // allows the left subexpression to be omitted, and instead of that condition
+ // be returned. e.g: x ?: y is shorthand for x ? x : y, except that the
+ // expression "x" is only evaluated once. Under this senario, this function
+ // returns the original, non-converted condition expression for the ?:operator
+ Expr *getSaveExpr() const { return Save? cast<Expr>(Save) : (Expr*)0; }
+
+ Expr *getLHS() const { return Save ? 0 : cast<Expr>(SubExprs[LHS]); }
void setLHS(Expr *E) { SubExprs[LHS] = E; }
Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); }
void setRHS(Expr *E) { SubExprs[RHS] = E; }
+ Expr *getSAVE() const { return Save? cast<Expr>(Save) : (Expr*)0; }
+ void setSAVE(Expr *E) { Save = E; }
+
SourceLocation getQuestionLoc() const { return QuestionLoc; }
void setQuestionLoc(SourceLocation L) { QuestionLoc = L; }
@@ -2500,23 +2546,27 @@ public:
/// expressions) are compatible. The result of this built-in function can be
/// used in integer constant expressions.
class TypesCompatibleExpr : public Expr {
- QualType Type1;
- QualType Type2;
+ TypeSourceInfo *TInfo1;
+ TypeSourceInfo *TInfo2;
SourceLocation BuiltinLoc, RParenLoc;
public:
TypesCompatibleExpr(QualType ReturnType, SourceLocation BLoc,
- QualType t1, QualType t2, SourceLocation RP) :
+ TypeSourceInfo *tinfo1, TypeSourceInfo *tinfo2,
+ SourceLocation RP) :
Expr(TypesCompatibleExprClass, ReturnType, false, false),
- Type1(t1), Type2(t2), BuiltinLoc(BLoc), RParenLoc(RP) {}
+ TInfo1(tinfo1), TInfo2(tinfo2), BuiltinLoc(BLoc), RParenLoc(RP) {}
/// \brief Build an empty __builtin_type_compatible_p expression.
explicit TypesCompatibleExpr(EmptyShell Empty)
: Expr(TypesCompatibleExprClass, Empty) { }
- QualType getArgType1() const { return Type1; }
- void setArgType1(QualType T) { Type1 = T; }
- QualType getArgType2() const { return Type2; }
- void setArgType2(QualType T) { Type2 = T; }
+ TypeSourceInfo *getArgTInfo1() const { return TInfo1; }
+ void setArgTInfo1(TypeSourceInfo *TInfo) { TInfo1 = TInfo; }
+ TypeSourceInfo *getArgTInfo2() const { return TInfo2; }
+ void setArgTInfo2(TypeSourceInfo *TInfo) { TInfo2 = TInfo; }
+
+ QualType getArgType1() const { return TInfo1->getType(); }
+ QualType getArgType2() const { return TInfo2->getType(); }
SourceLocation getBuiltinLoc() const { return BuiltinLoc; }
void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; }
@@ -2553,9 +2603,6 @@ class ShuffleVectorExpr : public Expr {
Stmt **SubExprs;
unsigned NumExprs;
-protected:
- virtual void DoDestroy(ASTContext &C);
-
public:
// FIXME: Can a shufflevector be value-dependent? Does type-dependence need
// to be computed differently?
@@ -2588,8 +2635,6 @@ public:
}
static bool classof(const ShuffleVectorExpr *) { return true; }
- ~ShuffleVectorExpr() {}
-
/// getNumSubExprs - Return the size of the SubExprs array. This includes the
/// constant expression, the actual arguments passed in, and the function
/// pointers.
@@ -2716,11 +2761,13 @@ public:
/// VAArgExpr, used for the builtin function __builtin_va_arg.
class VAArgExpr : public Expr {
Stmt *Val;
+ TypeSourceInfo *TInfo;
SourceLocation BuiltinLoc, RParenLoc;
public:
- VAArgExpr(SourceLocation BLoc, Expr* e, QualType t, SourceLocation RPLoc)
+ VAArgExpr(SourceLocation BLoc, Expr* e, TypeSourceInfo *TInfo,
+ SourceLocation RPLoc, QualType t)
: Expr(VAArgExprClass, t, t->isDependentType(), false),
- Val(e),
+ Val(e), TInfo(TInfo),
BuiltinLoc(BLoc),
RParenLoc(RPLoc) { }
@@ -2731,6 +2778,9 @@ public:
Expr *getSubExpr() { return cast<Expr>(Val); }
void setSubExpr(Expr *E) { Val = E; }
+ TypeSourceInfo *getWrittenTypeInfo() const { return TInfo; }
+ void setWrittenTypeInfo(TypeSourceInfo *TI) { TInfo = TI; }
+
SourceLocation getBuiltinLoc() const { return BuiltinLoc; }
void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; }
@@ -2896,12 +2946,18 @@ public:
virtual child_iterator child_end();
typedef InitExprsTy::iterator iterator;
+ typedef InitExprsTy::const_iterator const_iterator;
typedef InitExprsTy::reverse_iterator reverse_iterator;
+ typedef InitExprsTy::const_reverse_iterator const_reverse_iterator;
iterator begin() { return InitExprs.begin(); }
+ const_iterator begin() const { return InitExprs.begin(); }
iterator end() { return InitExprs.end(); }
+ const_iterator end() const { return InitExprs.end(); }
reverse_iterator rbegin() { return InitExprs.rbegin(); }
+ const_reverse_iterator rbegin() const { return InitExprs.rbegin(); }
reverse_iterator rend() { return InitExprs.rend(); }
+ const_reverse_iterator rend() const { return InitExprs.rend(); }
};
/// @brief Represents a C99 designated initializer expression.
@@ -2961,11 +3017,6 @@ private:
: Expr(DesignatedInitExprClass, EmptyShell()),
NumDesignators(0), Designators(0), NumSubExprs(NumSubExprs) { }
-protected:
- virtual void DoDestroy(ASTContext &C);
-
- void DestroyDesignators(ASTContext &C);
-
public:
/// A field designator, e.g., ".x".
struct FieldDesignator {
@@ -3233,15 +3284,10 @@ class ParenListExpr : public Expr {
unsigned NumExprs;
SourceLocation LParenLoc, RParenLoc;
-protected:
- virtual void DoDestroy(ASTContext& C);
-
public:
ParenListExpr(ASTContext& C, SourceLocation lparenloc, Expr **exprs,
unsigned numexprs, SourceLocation rparenloc);
- ~ParenListExpr() {}
-
/// \brief Build an empty paren list.
explicit ParenListExpr(EmptyShell Empty) : Expr(ParenListExprClass, Empty) { }
@@ -3274,8 +3320,8 @@ public:
virtual child_iterator child_begin();
virtual child_iterator child_end();
- friend class PCHStmtReader;
- friend class PCHStmtWriter;
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
};
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
index b9553815d8eb..0a9435479d93 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/include/clang/AST/ExprCXX.h
@@ -121,12 +121,12 @@ private:
protected:
CXXNamedCastExpr(StmtClass SC, QualType ty, CastKind kind, Expr *op,
- CXXBaseSpecifierArray BasePath, TypeSourceInfo *writtenTy,
+ unsigned PathSize, TypeSourceInfo *writtenTy,
SourceLocation l)
- : ExplicitCastExpr(SC, ty, kind, op, BasePath, writtenTy), Loc(l) {}
+ : ExplicitCastExpr(SC, ty, kind, op, PathSize, writtenTy), Loc(l) {}
- explicit CXXNamedCastExpr(StmtClass SC, EmptyShell Shell)
- : ExplicitCastExpr(SC, Shell) { }
+ explicit CXXNamedCastExpr(StmtClass SC, EmptyShell Shell, unsigned PathSize)
+ : ExplicitCastExpr(SC, Shell, PathSize) { }
public:
const char *getCastName() const;
@@ -158,14 +158,22 @@ public:
/// This expression node represents a C++ static cast, e.g.,
/// @c static_cast<int>(1.0).
class CXXStaticCastExpr : public CXXNamedCastExpr {
-public:
CXXStaticCastExpr(QualType ty, CastKind kind, Expr *op,
- CXXBaseSpecifierArray BasePath, TypeSourceInfo *writtenTy,
+ unsigned pathSize, TypeSourceInfo *writtenTy,
SourceLocation l)
- : CXXNamedCastExpr(CXXStaticCastExprClass, ty, kind, op, BasePath, writtenTy, l) {}
+ : CXXNamedCastExpr(CXXStaticCastExprClass, ty, kind, op, pathSize,
+ writtenTy, l) {}
- explicit CXXStaticCastExpr(EmptyShell Empty)
- : CXXNamedCastExpr(CXXStaticCastExprClass, Empty) { }
+ explicit CXXStaticCastExpr(EmptyShell Empty, unsigned PathSize)
+ : CXXNamedCastExpr(CXXStaticCastExprClass, Empty, PathSize) { }
+
+public:
+ static CXXStaticCastExpr *Create(ASTContext &Context, QualType T,
+ CastKind K, Expr *Op,
+ const CXXCastPath *Path,
+ TypeSourceInfo *Written, SourceLocation L);
+ static CXXStaticCastExpr *CreateEmpty(ASTContext &Context,
+ unsigned PathSize);
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXStaticCastExprClass;
@@ -180,15 +188,23 @@ public:
/// This expression node represents a dynamic cast, e.g.,
/// @c dynamic_cast<Derived*>(BasePtr).
class CXXDynamicCastExpr : public CXXNamedCastExpr {
-public:
CXXDynamicCastExpr(QualType ty, CastKind kind, Expr *op,
- CXXBaseSpecifierArray BasePath, TypeSourceInfo *writtenTy,
+ unsigned pathSize, TypeSourceInfo *writtenTy,
SourceLocation l)
- : CXXNamedCastExpr(CXXDynamicCastExprClass, ty, kind, op, BasePath,
+ : CXXNamedCastExpr(CXXDynamicCastExprClass, ty, kind, op, pathSize,
writtenTy, l) {}
- explicit CXXDynamicCastExpr(EmptyShell Empty)
- : CXXNamedCastExpr(CXXDynamicCastExprClass, Empty) { }
+ explicit CXXDynamicCastExpr(EmptyShell Empty, unsigned pathSize)
+ : CXXNamedCastExpr(CXXDynamicCastExprClass, Empty, pathSize) { }
+
+public:
+ static CXXDynamicCastExpr *Create(ASTContext &Context, QualType T,
+ CastKind Kind, Expr *Op,
+ const CXXCastPath *Path,
+ TypeSourceInfo *Written, SourceLocation L);
+
+ static CXXDynamicCastExpr *CreateEmpty(ASTContext &Context,
+ unsigned pathSize);
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXDynamicCastExprClass;
@@ -203,15 +219,22 @@ public:
/// This expression node represents a reinterpret cast, e.g.,
/// @c reinterpret_cast<int>(VoidPtr).
class CXXReinterpretCastExpr : public CXXNamedCastExpr {
-public:
CXXReinterpretCastExpr(QualType ty, CastKind kind, Expr *op,
- CXXBaseSpecifierArray BasePath,
+ unsigned pathSize,
TypeSourceInfo *writtenTy, SourceLocation l)
- : CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, kind, op, BasePath,
+ : CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, kind, op, pathSize,
writtenTy, l) {}
- explicit CXXReinterpretCastExpr(EmptyShell Empty)
- : CXXNamedCastExpr(CXXReinterpretCastExprClass, Empty) { }
+ CXXReinterpretCastExpr(EmptyShell Empty, unsigned pathSize)
+ : CXXNamedCastExpr(CXXReinterpretCastExprClass, Empty, pathSize) { }
+
+public:
+ static CXXReinterpretCastExpr *Create(ASTContext &Context, QualType T,
+ CastKind Kind, Expr *Op,
+ const CXXCastPath *Path,
+ TypeSourceInfo *WrittenTy, SourceLocation L);
+ static CXXReinterpretCastExpr *CreateEmpty(ASTContext &Context,
+ unsigned pathSize);
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXReinterpretCastExprClass;
@@ -225,14 +248,18 @@ public:
/// This expression node represents a const cast, e.g.,
/// @c const_cast<char*>(PtrToConstChar).
class CXXConstCastExpr : public CXXNamedCastExpr {
-public:
CXXConstCastExpr(QualType ty, Expr *op, TypeSourceInfo *writtenTy,
SourceLocation l)
: CXXNamedCastExpr(CXXConstCastExprClass, ty, CK_NoOp, op,
- CXXBaseSpecifierArray(), writtenTy, l) {}
+ 0, writtenTy, l) {}
explicit CXXConstCastExpr(EmptyShell Empty)
- : CXXNamedCastExpr(CXXConstCastExprClass, Empty) { }
+ : CXXNamedCastExpr(CXXConstCastExprClass, Empty, 0) { }
+
+public:
+ static CXXConstCastExpr *Create(ASTContext &Context, QualType T, Expr *Op,
+ TypeSourceInfo *WrittenTy, SourceLocation L);
+ static CXXConstCastExpr *CreateEmpty(ASTContext &Context);
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXConstCastExprClass;
@@ -479,9 +506,6 @@ class CXXDefaultArgExpr : public Expr {
*reinterpret_cast<Expr **>(this + 1) = SubExpr;
}
-protected:
- virtual void DoDestroy(ASTContext &C);
-
public:
CXXDefaultArgExpr(EmptyShell Empty) : Expr(CXXDefaultArgExprClass, Empty) {}
@@ -535,8 +559,8 @@ public:
virtual child_iterator child_begin();
virtual child_iterator child_end();
- friend class PCHStmtReader;
- friend class PCHStmtWriter;
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
};
/// CXXTemporary - Represents a C++ temporary.
@@ -546,14 +570,11 @@ class CXXTemporary {
CXXTemporary(const CXXDestructorDecl *destructor)
: Destructor(destructor) { }
- ~CXXTemporary() { }
public:
static CXXTemporary *Create(ASTContext &C,
const CXXDestructorDecl *Destructor);
- void Destroy(ASTContext &Ctx);
-
const CXXDestructorDecl *getDestructor() const { return Destructor; }
};
@@ -579,10 +600,6 @@ class CXXBindTemporaryExpr : public Expr {
CXXBindTemporaryExpr(CXXTemporary *temp, Expr* subexpr)
: Expr(CXXBindTemporaryExprClass, subexpr->getType(), false, false),
Temp(temp), SubExpr(subexpr) { }
- ~CXXBindTemporaryExpr() { }
-
-protected:
- virtual void DoDestroy(ASTContext &C);
public:
CXXBindTemporaryExpr(EmptyShell Empty)
@@ -614,73 +631,6 @@ public:
virtual child_iterator child_end();
};
-/// CXXBindReferenceExpr - Represents binding an expression to a reference.
-/// In the example:
-///
-/// const int &i = 10;
-///
-/// a bind reference expression is inserted to indicate that 10 is bound to
-/// a reference, and that a temporary needs to be created to hold the
-/// value.
-class CXXBindReferenceExpr : public Expr {
- // SubExpr - The expression being bound.
- Stmt *SubExpr;
-
- // ExtendsLifetime - Whether binding this reference extends the lifetime of
- // the expression being bound. FIXME: Add C++ reference.
- bool ExtendsLifetime;
-
- /// RequiresTemporaryCopy - Whether binding the subexpression requires a
- /// temporary copy.
- bool RequiresTemporaryCopy;
-
- CXXBindReferenceExpr(Expr *subexpr, bool ExtendsLifetime,
- bool RequiresTemporaryCopy)
- : Expr(CXXBindReferenceExprClass, subexpr->getType(), false, false),
- SubExpr(subexpr), ExtendsLifetime(ExtendsLifetime),
- RequiresTemporaryCopy(RequiresTemporaryCopy) { }
- ~CXXBindReferenceExpr() { }
-
-protected:
- virtual void DoDestroy(ASTContext &C);
-
-public:
- static CXXBindReferenceExpr *Create(ASTContext &C, Expr *SubExpr,
- bool ExtendsLifetime,
- bool RequiresTemporaryCopy);
-
- explicit CXXBindReferenceExpr(EmptyShell Empty)
- : Expr(CXXBindReferenceExprClass, Empty) { }
-
- const Expr *getSubExpr() const { return cast<Expr>(SubExpr); }
- Expr *getSubExpr() { return cast<Expr>(SubExpr); }
- void setSubExpr(Expr *E) { SubExpr = E; }
-
- virtual SourceRange getSourceRange() const {
- return SubExpr->getSourceRange();
- }
-
- /// requiresTemporaryCopy - Whether binding the subexpression requires a
- /// temporary copy.
- bool requiresTemporaryCopy() const { return RequiresTemporaryCopy; }
-
- // extendsLifetime - Whether binding this reference extends the lifetime of
- // the expression being bound. FIXME: Add C++ reference.
- bool extendsLifetime() const { return ExtendsLifetime; }
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == CXXBindReferenceExprClass;
- }
- static bool classof(const CXXBindReferenceExpr *) { return true; }
-
- // Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
-
- friend class PCHStmtReader;
-};
-
/// CXXConstructExpr - Represents a call to a C++ constructor.
class CXXConstructExpr : public Expr {
public:
@@ -707,15 +657,12 @@ protected:
Expr **args, unsigned numargs,
bool ZeroInitialization = false,
ConstructionKind ConstructKind = CK_Complete);
- ~CXXConstructExpr() { }
/// \brief Construct an empty C++ construction expression.
CXXConstructExpr(StmtClass SC, EmptyShell Empty)
: Expr(SC, Empty), Constructor(0), Elidable(0), ZeroInitialization(0),
ConstructKind(0), Args(0), NumArgs(0) { }
- virtual void DoDestroy(ASTContext &C);
-
public:
/// \brief Construct an empty C++ construction expression.
explicit CXXConstructExpr(EmptyShell Empty)
@@ -796,7 +743,7 @@ public:
virtual child_iterator child_begin();
virtual child_iterator child_end();
- friend class PCHStmtReader;
+ friend class ASTStmtReader;
};
/// CXXFunctionalCastExpr - Represents an explicit C++ type conversion
@@ -805,17 +752,27 @@ public:
class CXXFunctionalCastExpr : public ExplicitCastExpr {
SourceLocation TyBeginLoc;
SourceLocation RParenLoc;
-public:
+
CXXFunctionalCastExpr(QualType ty, TypeSourceInfo *writtenTy,
SourceLocation tyBeginLoc, CastKind kind,
- Expr *castExpr, CXXBaseSpecifierArray BasePath,
+ Expr *castExpr, unsigned pathSize,
SourceLocation rParenLoc)
: ExplicitCastExpr(CXXFunctionalCastExprClass, ty, kind, castExpr,
- BasePath, writtenTy),
+ pathSize, writtenTy),
TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {}
- explicit CXXFunctionalCastExpr(EmptyShell Shell)
- : ExplicitCastExpr(CXXFunctionalCastExprClass, Shell) { }
+ explicit CXXFunctionalCastExpr(EmptyShell Shell, unsigned PathSize)
+ : ExplicitCastExpr(CXXFunctionalCastExprClass, Shell, PathSize) { }
+
+public:
+ static CXXFunctionalCastExpr *Create(ASTContext &Context, QualType T,
+ TypeSourceInfo *Written,
+ SourceLocation TyBeginLoc,
+ CastKind Kind, Expr *Op,
+ const CXXCastPath *Path,
+ SourceLocation RPLoc);
+ static CXXFunctionalCastExpr *CreateEmpty(ASTContext &Context,
+ unsigned PathSize);
SourceLocation getTypeBeginLoc() const { return TyBeginLoc; }
void setTypeBeginLoc(SourceLocation L) { TyBeginLoc = L; }
@@ -859,8 +816,6 @@ public:
explicit CXXTemporaryObjectExpr(EmptyShell Empty)
: CXXConstructExpr(CXXTemporaryObjectExprClass, Empty) { }
- ~CXXTemporaryObjectExpr() { }
-
SourceLocation getTypeBeginLoc() const { return TyBeginLoc; }
SourceLocation getRParenLoc() const { return RParenLoc; }
@@ -872,7 +827,7 @@ public:
}
static bool classof(const CXXTemporaryObjectExpr *) { return true; }
- friend class PCHStmtReader;
+ friend class ASTStmtReader;
};
/// CXXScalarValueInitExpr - [C++ 5.2.3p2]
@@ -952,7 +907,7 @@ class CXXNewExpr : public Expr {
SourceLocation StartLoc;
SourceLocation EndLoc;
- friend class PCHStmtReader;
+ friend class ASTStmtReader;
public:
CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew,
Expr **placementArgs, unsigned numPlaceArgs,
@@ -967,8 +922,6 @@ public:
void AllocateArgsArray(ASTContext &C, bool isArray, unsigned numPlaceArgs,
unsigned numConsArgs);
- virtual void DoDestroy(ASTContext &C);
-
QualType getAllocatedType() const {
assert(getType()->isPointerType());
return getType()->getAs<PointerType>()->getPointeeType();
@@ -1381,7 +1334,7 @@ public:
virtual child_iterator child_begin();
virtual child_iterator child_end();
- friend class PCHStmtReader;
+ friend class ASTStmtReader;
};
/// \brief A reference to an overloaded function set, either an
@@ -1395,7 +1348,7 @@ class OverloadExpr : public Expr {
unsigned NumResults;
/// The common name of these declarations.
- DeclarationName Name;
+ DeclarationNameInfo NameInfo;
/// The scope specifier, if any.
NestedNameSpecifier *Qualifier;
@@ -1403,16 +1356,13 @@ class OverloadExpr : public Expr {
/// The source range of the scope specifier.
SourceRange QualifierRange;
- /// The location of the name.
- SourceLocation NameLoc;
-
protected:
/// True if the name was a template-id.
bool HasExplicitTemplateArgs;
OverloadExpr(StmtClass K, ASTContext &C, QualType T, bool Dependent,
NestedNameSpecifier *Qualifier, SourceRange QRange,
- DeclarationName Name, SourceLocation NameLoc,
+ const DeclarationNameInfo &NameInfo,
bool HasTemplateArgs,
UnresolvedSetIterator Begin, UnresolvedSetIterator End);
@@ -1427,19 +1377,38 @@ public:
UnresolvedSetIterator End,
const TemplateArgumentListInfo *Args);
+ struct FindResult {
+ OverloadExpr *Expression;
+ bool IsAddressOfOperand;
+ bool HasFormOfMemberPointer;
+ };
+
/// Finds the overloaded expression in the given expression of
/// OverloadTy.
///
- /// \return the expression (which must be there) and true if it is
- /// within an address-of operator.
- static llvm::PointerIntPair<OverloadExpr*,1> find(Expr *E) {
+ /// \return the expression (which must be there) and true if it has
+ /// the particular form of a member pointer expression
+ static FindResult find(Expr *E) {
assert(E->getType()->isSpecificBuiltinType(BuiltinType::Overload));
- bool op = false;
+ FindResult Result;
+
E = E->IgnoreParens();
- if (isa<UnaryOperator>(E))
- op = true, E = cast<UnaryOperator>(E)->getSubExpr()->IgnoreParens();
- return llvm::PointerIntPair<OverloadExpr*,1>(cast<OverloadExpr>(E), op);
+ if (isa<UnaryOperator>(E)) {
+ assert(cast<UnaryOperator>(E)->getOpcode() == UO_AddrOf);
+ E = cast<UnaryOperator>(E)->getSubExpr();
+ OverloadExpr *Ovl = cast<OverloadExpr>(E->IgnoreParens());
+
+ Result.HasFormOfMemberPointer = (E == Ovl && Ovl->getQualifier());
+ Result.IsAddressOfOperand = true;
+ Result.Expression = Ovl;
+ } else {
+ Result.HasFormOfMemberPointer = false;
+ Result.IsAddressOfOperand = false;
+ Result.Expression = cast<OverloadExpr>(E);
+ }
+
+ return Result;
}
/// Gets the naming class of this lookup, if any.
@@ -1457,13 +1426,17 @@ public:
/// Gets the number of declarations in the unresolved set.
unsigned getNumDecls() const { return NumResults; }
+ /// Gets the full name info.
+ const DeclarationNameInfo &getNameInfo() const { return NameInfo; }
+ void setNameInfo(const DeclarationNameInfo &N) { NameInfo = N; }
+
/// Gets the name looked up.
- DeclarationName getName() const { return Name; }
- void setName(DeclarationName N) { Name = N; }
+ DeclarationName getName() const { return NameInfo.getName(); }
+ void setName(DeclarationName N) { NameInfo.setName(N); }
/// Gets the location of the name.
- SourceLocation getNameLoc() const { return NameLoc; }
- void setNameLoc(SourceLocation Loc) { NameLoc = Loc; }
+ SourceLocation getNameLoc() const { return NameInfo.getLoc(); }
+ void setNameLoc(SourceLocation Loc) { NameInfo.setLoc(Loc); }
/// Fetches the nested-name qualifier, if one was given.
NestedNameSpecifier *getQualifier() const { return Qualifier; }
@@ -1483,10 +1456,12 @@ public:
return const_cast<OverloadExpr*>(this)->getExplicitTemplateArgs();
}
- ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() {
- if (hasExplicitTemplateArgs())
- return &getExplicitTemplateArgs();
- return 0;
+ /// \brief Retrieves the optional explicit template arguments.
+ /// This points to the same data as getExplicitTemplateArgs(), but
+ /// returns null if there are no explicit template arguments.
+ const ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() {
+ if (!hasExplicitTemplateArgs()) return 0;
+ return &getExplicitTemplateArgs();
}
static bool classof(const Stmt *T) {
@@ -1526,11 +1501,11 @@ class UnresolvedLookupExpr : public OverloadExpr {
UnresolvedLookupExpr(ASTContext &C, QualType T, bool Dependent,
CXXRecordDecl *NamingClass,
NestedNameSpecifier *Qualifier, SourceRange QRange,
- DeclarationName Name, SourceLocation NameLoc,
+ const DeclarationNameInfo &NameInfo,
bool RequiresADL, bool Overloaded, bool HasTemplateArgs,
UnresolvedSetIterator Begin, UnresolvedSetIterator End)
: OverloadExpr(UnresolvedLookupExprClass, C, T, Dependent, Qualifier,
- QRange, Name, NameLoc, HasTemplateArgs, Begin, End),
+ QRange, NameInfo, HasTemplateArgs, Begin, End),
RequiresADL(RequiresADL), Overloaded(Overloaded), NamingClass(NamingClass)
{}
@@ -1545,16 +1520,15 @@ public:
CXXRecordDecl *NamingClass,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
- DeclarationName Name,
- SourceLocation NameLoc,
+ const DeclarationNameInfo &NameInfo,
bool ADL, bool Overloaded,
UnresolvedSetIterator Begin,
UnresolvedSetIterator End) {
return new(C) UnresolvedLookupExpr(C,
Dependent ? C.DependentTy : C.OverloadTy,
Dependent, NamingClass,
- Qualifier, QualifierRange,
- Name, NameLoc, ADL, Overloaded, false,
+ Qualifier, QualifierRange, NameInfo,
+ ADL, Overloaded, false,
Begin, End);
}
@@ -1563,8 +1537,7 @@ public:
CXXRecordDecl *NamingClass,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
- DeclarationName Name,
- SourceLocation NameLoc,
+ const DeclarationNameInfo &NameInfo,
bool ADL,
const TemplateArgumentListInfo &Args,
UnresolvedSetIterator Begin,
@@ -1603,6 +1576,14 @@ public:
return *reinterpret_cast<const ExplicitTemplateArgumentList*>(this + 1);
}
+ /// \brief Retrieves the optional explicit template arguments.
+ /// This points to the same data as getExplicitTemplateArgs(), but
+ /// returns null if there are no explicit template arguments.
+ const ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() {
+ if (!hasExplicitTemplateArgs()) return 0;
+ return &getExplicitTemplateArgs();
+ }
+
/// \brief Copies the template arguments (if present) into the given
/// structure.
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
@@ -1626,7 +1607,7 @@ public:
}
virtual SourceRange getSourceRange() const {
- SourceRange Range(getNameLoc());
+ SourceRange Range(getNameInfo().getSourceRange());
if (getQualifier()) Range.setBegin(getQualifierRange().getBegin());
if (hasExplicitTemplateArgs()) Range.setEnd(getRAngleLoc());
return Range;
@@ -1657,10 +1638,7 @@ public:
/// declaration can be found.
class DependentScopeDeclRefExpr : public Expr {
/// The name of the entity we will be referencing.
- DeclarationName Name;
-
- /// Location of the name of the declaration we're referencing.
- SourceLocation Loc;
+ DeclarationNameInfo NameInfo;
/// QualifierRange - The source range that covers the
/// nested-name-specifier.
@@ -1676,12 +1654,10 @@ class DependentScopeDeclRefExpr : public Expr {
DependentScopeDeclRefExpr(QualType T,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
- DeclarationName Name,
- SourceLocation NameLoc,
+ const DeclarationNameInfo &NameInfo,
bool HasExplicitTemplateArgs)
: Expr(DependentScopeDeclRefExprClass, T, true, true),
- Name(Name), Loc(NameLoc),
- QualifierRange(QualifierRange), Qualifier(Qualifier),
+ NameInfo(NameInfo), QualifierRange(QualifierRange), Qualifier(Qualifier),
HasExplicitTemplateArgs(HasExplicitTemplateArgs)
{}
@@ -1689,20 +1665,23 @@ public:
static DependentScopeDeclRefExpr *Create(ASTContext &C,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
- DeclarationName Name,
- SourceLocation NameLoc,
+ const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs = 0);
static DependentScopeDeclRefExpr *CreateEmpty(ASTContext &C,
unsigned NumTemplateArgs);
/// \brief Retrieve the name that this expression refers to.
- DeclarationName getDeclName() const { return Name; }
- void setDeclName(DeclarationName N) { Name = N; }
+ const DeclarationNameInfo &getNameInfo() const { return NameInfo; }
+ void setNameInfo(const DeclarationNameInfo &N) { NameInfo = N; }
+
+ /// \brief Retrieve the name that this expression refers to.
+ DeclarationName getDeclName() const { return NameInfo.getName(); }
+ void setDeclName(DeclarationName N) { NameInfo.setName(N); }
/// \brief Retrieve the location of the name within the expression.
- SourceLocation getLocation() const { return Loc; }
- void setLocation(SourceLocation L) { Loc = L; }
+ SourceLocation getLocation() const { return NameInfo.getLoc(); }
+ void setLocation(SourceLocation L) { NameInfo.setLoc(L); }
/// \brief Retrieve the source range of the nested-name-specifier.
SourceRange getQualifierRange() const { return QualifierRange; }
@@ -1731,6 +1710,14 @@ public:
return *reinterpret_cast<const ExplicitTemplateArgumentList*>(this + 1);
}
+ /// \brief Retrieves the optional explicit template arguments.
+ /// This points to the same data as getExplicitTemplateArgs(), but
+ /// returns null if there are no explicit template arguments.
+ const ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() {
+ if (!hasExplicitTemplateArgs()) return 0;
+ return &getExplicitTemplateArgs();
+ }
+
/// \brief Copies the template arguments (if present) into the given
/// structure.
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
@@ -1777,10 +1764,6 @@ class CXXExprWithTemporaries : public Expr {
CXXExprWithTemporaries(ASTContext &C, Expr *SubExpr, CXXTemporary **Temps,
unsigned NumTemps);
- ~CXXExprWithTemporaries();
-
-protected:
- virtual void DoDestroy(ASTContext &C);
public:
CXXExprWithTemporaries(EmptyShell Empty)
@@ -1991,10 +1974,7 @@ class CXXDependentScopeMemberExpr : public Expr {
/// \brief The member to which this member expression refers, which
/// can be name, overloaded operator, or destructor.
/// FIXME: could also be a template-id
- DeclarationName Member;
-
- /// \brief The location of the member name.
- SourceLocation MemberLoc;
+ DeclarationNameInfo MemberNameInfo;
CXXDependentScopeMemberExpr(ASTContext &C,
Expr *Base, QualType BaseType, bool IsArrow,
@@ -2002,8 +1982,7 @@ class CXXDependentScopeMemberExpr : public Expr {
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
NamedDecl *FirstQualifierFoundInScope,
- DeclarationName Member,
- SourceLocation MemberLoc,
+ DeclarationNameInfo MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs);
public:
@@ -2014,14 +1993,13 @@ public:
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
NamedDecl *FirstQualifierFoundInScope,
- DeclarationName Member,
- SourceLocation MemberLoc)
+ DeclarationNameInfo MemberNameInfo)
: Expr(CXXDependentScopeMemberExprClass, C.DependentTy, true, true),
Base(Base), BaseType(BaseType), IsArrow(IsArrow),
HasExplicitTemplateArgs(false), OperatorLoc(OperatorLoc),
Qualifier(Qualifier), QualifierRange(QualifierRange),
FirstQualifierFoundInScope(FirstQualifierFoundInScope),
- Member(Member), MemberLoc(MemberLoc) { }
+ MemberNameInfo(MemberNameInfo) { }
static CXXDependentScopeMemberExpr *
Create(ASTContext &C,
@@ -2030,8 +2008,7 @@ public:
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
NamedDecl *FirstQualifierFoundInScope,
- DeclarationName Member,
- SourceLocation MemberLoc,
+ DeclarationNameInfo MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs);
static CXXDependentScopeMemberExpr *
@@ -2092,13 +2069,20 @@ public:
/// \brief Retrieve the name of the member that this expression
/// refers to.
- DeclarationName getMember() const { return Member; }
- void setMember(DeclarationName N) { Member = N; }
+ const DeclarationNameInfo &getMemberNameInfo() const {
+ return MemberNameInfo;
+ }
+ void setMemberNameInfo(const DeclarationNameInfo &N) { MemberNameInfo = N; }
+
+ /// \brief Retrieve the name of the member that this expression
+ /// refers to.
+ DeclarationName getMember() const { return MemberNameInfo.getName(); }
+ void setMember(DeclarationName N) { MemberNameInfo.setName(N); }
// \brief Retrieve the location of the name of the member that this
// expression refers to.
- SourceLocation getMemberLoc() const { return MemberLoc; }
- void setMemberLoc(SourceLocation L) { MemberLoc = L; }
+ SourceLocation getMemberLoc() const { return MemberNameInfo.getLoc(); }
+ void setMemberLoc(SourceLocation L) { MemberNameInfo.setLoc(L); }
/// \brief Determines whether this member expression actually had a C++
/// template argument list explicitly specified, e.g., x.f<int>.
@@ -2108,57 +2092,59 @@ public:
/// \brief Retrieve the explicit template argument list that followed the
/// member template name, if any.
- ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() {
+ ExplicitTemplateArgumentList &getExplicitTemplateArgs() {
assert(HasExplicitTemplateArgs);
- return reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1);
+ return *reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1);
}
/// \brief Retrieve the explicit template argument list that followed the
/// member template name, if any.
- const ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() const {
+ const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const {
return const_cast<CXXDependentScopeMemberExpr *>(this)
- ->getExplicitTemplateArgumentList();
+ ->getExplicitTemplateArgs();
+ }
+
+ /// \brief Retrieves the optional explicit template arguments.
+ /// This points to the same data as getExplicitTemplateArgs(), but
+ /// returns null if there are no explicit template arguments.
+ const ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() {
+ if (!hasExplicitTemplateArgs()) return 0;
+ return &getExplicitTemplateArgs();
}
/// \brief Copies the template arguments (if present) into the given
/// structure.
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
- assert(HasExplicitTemplateArgs);
- getExplicitTemplateArgumentList()->copyInto(List);
+ getExplicitTemplateArgs().copyInto(List);
}
/// \brief Initializes the template arguments using the given structure.
void initializeTemplateArgumentsFrom(const TemplateArgumentListInfo &List) {
- assert(HasExplicitTemplateArgs);
- getExplicitTemplateArgumentList()->initializeFrom(List);
+ getExplicitTemplateArgs().initializeFrom(List);
}
/// \brief Retrieve the location of the left angle bracket following the
/// member name ('<'), if any.
SourceLocation getLAngleLoc() const {
- assert(HasExplicitTemplateArgs);
- return getExplicitTemplateArgumentList()->LAngleLoc;
+ return getExplicitTemplateArgs().LAngleLoc;
}
/// \brief Retrieve the template arguments provided as part of this
/// template-id.
const TemplateArgumentLoc *getTemplateArgs() const {
- assert(HasExplicitTemplateArgs);
- return getExplicitTemplateArgumentList()->getTemplateArgs();
+ return getExplicitTemplateArgs().getTemplateArgs();
}
/// \brief Retrieve the number of template arguments provided as part of this
/// template-id.
unsigned getNumTemplateArgs() const {
- assert(HasExplicitTemplateArgs);
- return getExplicitTemplateArgumentList()->NumTemplateArgs;
+ return getExplicitTemplateArgs().NumTemplateArgs;
}
/// \brief Retrieve the location of the right angle bracket following the
/// template arguments ('>').
SourceLocation getRAngleLoc() const {
- assert(HasExplicitTemplateArgs);
- return getExplicitTemplateArgumentList()->RAngleLoc;
+ return getExplicitTemplateArgs().RAngleLoc;
}
virtual SourceRange getSourceRange() const {
@@ -2168,12 +2154,12 @@ public:
else if (getQualifier())
Range.setBegin(getQualifierRange().getBegin());
else
- Range.setBegin(MemberLoc);
+ Range.setBegin(MemberNameInfo.getBeginLoc());
if (hasExplicitTemplateArgs())
Range.setEnd(getRAngleLoc());
else
- Range.setEnd(MemberLoc);
+ Range.setEnd(MemberNameInfo.getEndLoc());
return Range;
}
@@ -2226,8 +2212,7 @@ class UnresolvedMemberExpr : public OverloadExpr {
SourceLocation OperatorLoc,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
- DeclarationName Member,
- SourceLocation MemberLoc,
+ const DeclarationNameInfo &MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs,
UnresolvedSetIterator Begin, UnresolvedSetIterator End);
@@ -2242,8 +2227,7 @@ public:
SourceLocation OperatorLoc,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
- DeclarationName Member,
- SourceLocation MemberLoc,
+ const DeclarationNameInfo &MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs,
UnresolvedSetIterator Begin, UnresolvedSetIterator End);
@@ -2287,6 +2271,11 @@ public:
/// \brief Retrieves the naming class of this lookup.
CXXRecordDecl *getNamingClass() const;
+ /// \brief Retrieve the full name info for the member that this expression
+ /// refers to.
+ const DeclarationNameInfo &getMemberNameInfo() const { return getNameInfo(); }
+ void setMemberNameInfo(const DeclarationNameInfo &N) { setNameInfo(N); }
+
/// \brief Retrieve the name of the member that this expression
/// refers to.
DeclarationName getMemberName() const { return getName(); }
@@ -2311,6 +2300,14 @@ public:
return *reinterpret_cast<const ExplicitTemplateArgumentList *>(this + 1);
}
+ /// \brief Retrieves the optional explicit template arguments.
+ /// This points to the same data as getExplicitTemplateArgs(), but
+ /// returns null if there are no explicit template arguments.
+ const ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() {
+ if (!hasExplicitTemplateArgs()) return 0;
+ return &getExplicitTemplateArgs();
+ }
+
/// \brief Copies the template arguments into the given structure.
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
getExplicitTemplateArgs().copyInto(List);
@@ -2341,18 +2338,14 @@ public:
}
virtual SourceRange getSourceRange() const {
- SourceRange Range;
+ SourceRange Range = getMemberNameInfo().getSourceRange();
if (!isImplicitAccess())
Range.setBegin(Base->getSourceRange().getBegin());
else if (getQualifier())
Range.setBegin(getQualifierRange().getBegin());
- else
- Range.setBegin(getMemberLoc());
if (hasExplicitTemplateArgs())
Range.setEnd(getRAngleLoc());
- else
- Range.setEnd(getMemberLoc());
return Range;
}
diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h
index def9ced94c29..a8ef0053a442 100644
--- a/include/clang/AST/ExternalASTSource.h
+++ b/include/clang/AST/ExternalASTSource.h
@@ -14,31 +14,25 @@
#ifndef LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
#define LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
-#include "clang/AST/DeclarationName.h"
-#include "clang/AST/Type.h"
-#include "llvm/ADT/SmallVector.h"
#include <cassert>
#include <vector>
+
+namespace llvm {
+template <class T> class SmallVectorImpl;
+}
+
namespace clang {
class ASTConsumer;
class Decl;
class DeclContext;
+class DeclContextLookupResult;
+class DeclarationName;
class ExternalSemaSource; // layering violation required for downcasting
+class NamedDecl;
+class Selector;
class Stmt;
-/// \brief The deserialized representation of a set of declarations
-/// with the same name that are visible in a given context.
-struct VisibleDeclaration {
- /// \brief The name of the declarations.
- DeclarationName Name;
-
- /// \brief The ID numbers of all of the declarations with this name.
- ///
- /// These declarations have not necessarily been de-serialized.
- llvm::SmallVector<unsigned, 4> Declarations;
-};
-
/// \brief Abstract interface for external sources of AST nodes.
///
/// External AST sources provide AST nodes constructed from some
@@ -58,6 +52,20 @@ public:
virtual ~ExternalASTSource();
+ /// \brief RAII class for safely pairing a StartedDeserializing call
+ /// with FinishedDeserializing.
+ class Deserializing {
+ ExternalASTSource *Source;
+ public:
+ explicit Deserializing(ExternalASTSource *source) : Source(source) {
+ assert(Source);
+ Source->StartedDeserializing();
+ }
+ ~Deserializing() {
+ Source->FinishedDeserializing();
+ }
+ };
+
/// \brief Resolve a declaration ID into a declaration, potentially
/// building a new declaration.
///
@@ -89,10 +97,18 @@ public:
/// Generally the final step of this method is either to call
/// SetExternalVisibleDeclsForName or to recursively call lookup on
/// the DeclContext after calling SetExternalVisibleDecls.
- virtual DeclContext::lookup_result
+ virtual DeclContextLookupResult
FindExternalVisibleDeclsByName(const DeclContext *DC,
DeclarationName Name) = 0;
+ /// \brief Deserialize all the visible declarations from external storage.
+ ///
+ /// Name lookup deserializes visible declarations lazily, thus a DeclContext
+ /// may not have a complete name lookup table. This function deserializes
+ /// the rest of visible declarations from the external storage and completes
+ /// the name lookup table of the DeclContext.
+ virtual void MaterializeVisibleDecls(const DeclContext *DC) = 0;
+
/// \brief Finds all declarations lexically contained within the given
/// DeclContext.
///
@@ -100,6 +116,19 @@ public:
virtual bool FindExternalLexicalDecls(const DeclContext *DC,
llvm::SmallVectorImpl<Decl*> &Result) = 0;
+ /// \brief Notify ExternalASTSource that we started deserialization of
+ /// a decl or type so until FinishedDeserializing is called there may be
+ /// decls that are initializing. Must be paired with FinishedDeserializing.
+ ///
+ /// The default implementation of this method is a no-op.
+ virtual void StartedDeserializing() { }
+
+ /// \brief Notify ExternalASTSource that we finished the deserialization of
+ /// a decl or type. Must be paired with StartedDeserializing.
+ ///
+ /// The default implementation of this method is a no-op.
+ virtual void FinishedDeserializing() { }
+
/// \brief Function that will be invoked when we begin parsing a new
/// translation unit involving this external AST source.
///
@@ -113,30 +142,18 @@ public:
virtual void PrintStats();
protected:
- /// \brief Initialize the context's lookup map with the given decls.
- /// It is assumed that none of the declarations are redeclarations of
- /// each other.
- static void SetExternalVisibleDecls(const DeclContext *DC,
- const llvm::SmallVectorImpl<VisibleDeclaration> &Decls);
-
- /// \brief Initialize the context's lookup map with the given decls.
- /// It is assumed that none of the declarations are redeclarations of
- /// each other.
- static void SetExternalVisibleDecls(const DeclContext *DC,
- const llvm::SmallVectorImpl<NamedDecl*> &Decls);
-
- static DeclContext::lookup_result
- SetExternalVisibleDeclsForName(const DeclContext *DC,
- const VisibleDeclaration &VD);
-
- static DeclContext::lookup_result
+ static DeclContextLookupResult
SetExternalVisibleDeclsForName(const DeclContext *DC,
DeclarationName Name,
llvm::SmallVectorImpl<NamedDecl*> &Decls);
- static DeclContext::lookup_result
+ static DeclContextLookupResult
SetNoExternalVisibleDeclsForName(const DeclContext *DC,
DeclarationName Name);
+
+ void MaterializeVisibleDeclsForName(const DeclContext *DC,
+ DeclarationName Name,
+ llvm::SmallVectorImpl<NamedDecl*> &Decls);
};
/// \brief A lazy pointer to an AST node (of base type T) that resides
@@ -145,7 +162,7 @@ protected:
/// The AST node is identified within the external AST source by a
/// 63-bit offset, and can be retrieved via an operation on the
/// external AST source itself.
-template<typename T, T* (ExternalASTSource::*Get)(uint64_t Offset)>
+template<typename T, typename OffsT, T* (ExternalASTSource::*Get)(OffsT Offset)>
struct LazyOffsetPtr {
/// \brief Either a pointer to an AST node or the offset within the
/// external AST source where the AST node can be found.
@@ -203,9 +220,13 @@ public:
};
/// \brief A lazy pointer to a statement.
-typedef LazyOffsetPtr<Stmt, &ExternalASTSource::GetExternalDeclStmt>
+typedef LazyOffsetPtr<Stmt, uint64_t, &ExternalASTSource::GetExternalDeclStmt>
LazyDeclStmtPtr;
+/// \brief A lazy pointer to a declaration.
+typedef LazyOffsetPtr<Decl, uint32_t, &ExternalASTSource::GetExternalDecl>
+ LazyDeclPtr;
+
} // end namespace clang
#endif // LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
diff --git a/include/clang/AST/FullExpr.h b/include/clang/AST/FullExpr.h
index bb81bf0fe7c8..6ceefed8a63a 100644
--- a/include/clang/AST/FullExpr.h
+++ b/include/clang/AST/FullExpr.h
@@ -47,7 +47,6 @@ class FullExpr {
public:
static FullExpr Create(ASTContext &Context, Expr *SubExpr,
CXXTemporary **Temps, unsigned NumTemps);
- void Destroy(ASTContext &Context);
Expr *getExpr() {
if (Expr *E = SubExpr.dyn_cast<Expr *>())
diff --git a/include/clang/AST/Makefile b/include/clang/AST/Makefile
index 00a1e1bf7977..6ba6e897d186 100644
--- a/include/clang/AST/Makefile
+++ b/include/clang/AST/Makefile
@@ -1,6 +1,6 @@
CLANG_LEVEL := ../../..
TD_SRC_DIR = $(PROJ_SRC_DIR)/../Basic
-BUILT_SOURCES = Attrs.inc StmtNodes.inc DeclNodes.inc
+BUILT_SOURCES = Attrs.inc AttrImpl.inc StmtNodes.inc DeclNodes.inc
TABLEGEN_INC_FILES_COMMON = 1
@@ -12,6 +12,12 @@ $(ObjDir)/Attrs.inc.tmp : $(TD_SRC_DIR)/Attr.td $(TBLGEN) \
$(Verb) $(TableGen) -gen-clang-attr-classes -o $(call SYSPATH, $@) \
-I $(PROJ_SRC_DIR)/../../ $<
+$(ObjDir)/AttrImpl.inc.tmp : $(TD_SRC_DIR)/Attr.td $(TBLGEN) \
+ $(ObjDir)/.dir
+ $(Echo) "Building Clang attribute implementations with tblgen"
+ $(Verb) $(TableGen) -gen-clang-attr-impl -o $(call SYSPATH, $@) \
+ -I $(PROJ_SRC_DIR)/../../ $<
+
$(ObjDir)/StmtNodes.inc.tmp : $(TD_SRC_DIR)/StmtNodes.td $(TBLGEN) \
$(ObjDir)/.dir
$(Echo) "Building Clang statement node tables with tblgen"
diff --git a/include/clang/AST/NestedNameSpecifier.h b/include/clang/AST/NestedNameSpecifier.h
index 1594b090fea5..3b25f3bb403f 100644
--- a/include/clang/AST/NestedNameSpecifier.h
+++ b/include/clang/AST/NestedNameSpecifier.h
@@ -181,8 +181,6 @@ public:
ID.AddPointer(Specifier);
}
- void Destroy(ASTContext &Context);
-
/// \brief Dump the nested name specifier to standard output to aid
/// in debugging.
void dump(const LangOptions &LO);
diff --git a/include/clang/AST/OperationKinds.h b/include/clang/AST/OperationKinds.h
new file mode 100644
index 000000000000..804531192971
--- /dev/null
+++ b/include/clang/AST/OperationKinds.h
@@ -0,0 +1,158 @@
+//===- OperationKinds.h - Operation enums -----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file enumerates the different kinds of operations that can be
+// performed by various expressions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_OPERATION_KINDS_H
+#define LLVM_CLANG_AST_OPERATION_KINDS_H
+
+namespace clang {
+
+/// CastKind - the kind of cast this represents.
+enum CastKind {
+ /// CK_Unknown - Unknown cast kind.
+ /// FIXME: The goal is to get rid of this and make all casts have a
+ /// kind so that the AST client doesn't have to try to figure out what's
+ /// going on.
+ CK_Unknown,
+
+ /// CK_BitCast - Used for reinterpret_cast.
+ CK_BitCast,
+
+ /// CK_LValueBitCast - Used for reinterpret_cast of expressions to
+ /// a reference type.
+ CK_LValueBitCast,
+
+ /// CK_NoOp - Used for const_cast.
+ CK_NoOp,
+
+ /// CK_BaseToDerived - Base to derived class casts.
+ CK_BaseToDerived,
+
+ /// CK_DerivedToBase - Derived to base class casts.
+ CK_DerivedToBase,
+
+ /// CK_UncheckedDerivedToBase - Derived to base class casts that
+ /// assume that the derived pointer is not null.
+ CK_UncheckedDerivedToBase,
+
+ /// CK_Dynamic - Dynamic cast.
+ CK_Dynamic,
+
+ /// CK_ToUnion - Cast to union (GCC extension).
+ CK_ToUnion,
+
+ /// CK_ArrayToPointerDecay - Array to pointer decay.
+ CK_ArrayToPointerDecay,
+
+ // CK_FunctionToPointerDecay - Function to pointer decay.
+ CK_FunctionToPointerDecay,
+
+ /// CK_NullToMemberPointer - Null pointer to member pointer.
+ CK_NullToMemberPointer,
+
+ /// CK_BaseToDerivedMemberPointer - Member pointer in base class to
+ /// 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,
+
+ /// CK_ConstructorConversion - Conversion by constructor
+ CK_ConstructorConversion,
+
+ /// CK_IntegralToPointer - Integral to pointer
+ CK_IntegralToPointer,
+
+ /// CK_PointerToIntegral - Pointer to integral
+ CK_PointerToIntegral,
+
+ /// CK_ToVoid - Cast to void.
+ CK_ToVoid,
+
+ /// CK_VectorSplat - Casting from an integer/floating type to an extended
+ /// vector type with the same element type as the src type. Splats the
+ /// src expression into the destination expression.
+ CK_VectorSplat,
+
+ /// CK_IntegralCast - Casting between integral types of different size.
+ CK_IntegralCast,
+
+ /// CK_IntegralToFloating - Integral to floating point.
+ CK_IntegralToFloating,
+
+ /// CK_FloatingToIntegral - Floating point to integral.
+ CK_FloatingToIntegral,
+
+ /// CK_FloatingCast - Casting between floating types of different size.
+ CK_FloatingCast,
+
+ /// CK_MemberPointerToBoolean - Member pointer to boolean
+ CK_MemberPointerToBoolean,
+
+ /// CK_AnyPointerToObjCPointerCast - Casting any pointer to objective-c
+ /// pointer
+ CK_AnyPointerToObjCPointerCast,
+
+ /// CK_AnyPointerToBlockPointerCast - Casting any pointer to block
+ /// pointer
+ CK_AnyPointerToBlockPointerCast,
+
+ /// \brief Converting between two Objective-C object types, which
+ /// can occur when performing reference binding to an Objective-C
+ /// object.
+ CK_ObjCObjectLValueCast
+};
+
+
+enum BinaryOperatorKind {
+ // Operators listed in order of precedence.
+ // Note that additions to this should also update the StmtVisitor class.
+ BO_PtrMemD, BO_PtrMemI, // [C++ 5.5] Pointer-to-member operators.
+ BO_Mul, BO_Div, BO_Rem, // [C99 6.5.5] Multiplicative operators.
+ BO_Add, BO_Sub, // [C99 6.5.6] Additive operators.
+ BO_Shl, BO_Shr, // [C99 6.5.7] Bitwise shift operators.
+ BO_LT, BO_GT, BO_LE, BO_GE, // [C99 6.5.8] Relational operators.
+ BO_EQ, BO_NE, // [C99 6.5.9] Equality operators.
+ BO_And, // [C99 6.5.10] Bitwise AND operator.
+ BO_Xor, // [C99 6.5.11] Bitwise XOR operator.
+ BO_Or, // [C99 6.5.12] Bitwise OR operator.
+ BO_LAnd, // [C99 6.5.13] Logical AND operator.
+ BO_LOr, // [C99 6.5.14] Logical OR operator.
+ BO_Assign, BO_MulAssign, // [C99 6.5.16] Assignment operators.
+ BO_DivAssign, BO_RemAssign,
+ BO_AddAssign, BO_SubAssign,
+ BO_ShlAssign, BO_ShrAssign,
+ BO_AndAssign, BO_XorAssign,
+ BO_OrAssign,
+ BO_Comma // [C99 6.5.17] Comma operator.
+};
+
+enum UnaryOperatorKind {
+ // Note that additions to this should also update the StmtVisitor class.
+ UO_PostInc, UO_PostDec, // [C99 6.5.2.4] Postfix increment and decrement
+ UO_PreInc, UO_PreDec, // [C99 6.5.3.1] Prefix increment and decrement
+ UO_AddrOf, UO_Deref, // [C99 6.5.3.2] Address and indirection
+ UO_Plus, UO_Minus, // [C99 6.5.3.3] Unary arithmetic
+ UO_Not, UO_LNot, // [C99 6.5.3.3] Unary arithmetic
+ UO_Real, UO_Imag, // "__real expr"/"__imag expr" Extension.
+ UO_Extension // __extension__ marker.
+};
+
+}
+
+#endif
diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h
index 0853dddbe9e5..232e47b03ae5 100644
--- a/include/clang/AST/RecursiveASTVisitor.h
+++ b/include/clang/AST/RecursiveASTVisitor.h
@@ -42,7 +42,7 @@
OPERATOR(Plus) OPERATOR(Minus) \
OPERATOR(Not) OPERATOR(LNot) \
OPERATOR(Real) OPERATOR(Imag) \
- OPERATOR(Extension) OPERATOR(OffsetOf)
+ OPERATOR(Extension)
// All binary operators (excluding compound assign operators).
#define BINOP_LIST() \
@@ -123,12 +123,27 @@ namespace clang {
/// users may override Traverse* and WalkUpFrom* to implement custom
/// traversal strategies. Returning false from one of these overridden
/// functions will abort the entire traversal.
+///
+/// By default, this visitor tries to visit every part of the explicit
+/// source code exactly once. The default policy towards templates
+/// is to descend into the 'pattern' class or function body, not any
+/// explicit or implicit instantiations. Explicit specializations
+/// are still visited, and the patterns of partial specializations
+/// are visited separately. This behavior can be changed by
+/// overriding shouldVisitTemplateInstantiations() in the derived class
+/// to return true, in which case all known implicit and explicit
+/// instantiations will be visited at the same time as the pattern
+/// from which they were produced.
template<typename Derived>
class RecursiveASTVisitor {
public:
/// \brief Return a reference to the derived class.
Derived &getDerived() { return *static_cast<Derived*>(this); }
+ /// \brief Return whether this visitor should recurse into
+ /// template instantiations.
+ bool shouldVisitTemplateInstantiations() const { return false; }
+
/// \brief Recursively visit a statement or expression, by
/// dispatching to Traverse*() based on the argument's dynamic type.
///
@@ -351,8 +366,11 @@ public:
private:
// These are helper methods used by more than one Traverse* method.
bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL);
- bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL,
+ bool TraverseClassInstantiations(ClassTemplateDecl* D, Decl *Pattern);
+ bool TraverseFunctionInstantiations(FunctionTemplateDecl* D) ;
+ bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL,
unsigned Count);
+ bool TraverseArrayTypeLocHelper(ArrayTypeLoc TL);
bool TraverseRecordHelper(RecordDecl *D);
bool TraverseCXXRecordHelper(CXXRecordDecl *D);
bool TraverseDeclaratorHelper(DeclaratorDecl *D);
@@ -375,14 +393,14 @@ bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S) {
if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) {
switch (BinOp->getOpcode()) {
#define OPERATOR(NAME) \
- case BinaryOperator::NAME: DISPATCH(Bin##PtrMemD, BinaryOperator, S);
+ case BO_##NAME: DISPATCH(Bin##PtrMemD, BinaryOperator, S);
BINOP_LIST()
#undef OPERATOR
#undef BINOP_LIST
#define OPERATOR(NAME) \
- case BinaryOperator::NAME##Assign: \
+ case BO_##NAME##Assign: \
DISPATCH(Bin##NAME##Assign, CompoundAssignOperator, S);
CAO_LIST()
@@ -392,7 +410,7 @@ bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S) {
} else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) {
switch (UnOp->getOpcode()) {
#define OPERATOR(NAME) \
- case UnaryOperator::NAME: DISPATCH(Unary##NAME, UnaryOperator, S);
+ case UO_##NAME: DISPATCH(Unary##NAME, UnaryOperator, S);
UNARYOP_LIST()
#undef OPERATOR
@@ -540,8 +558,11 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc(
return true;
case TemplateArgument::Type: {
- TypeSourceInfo *TSI = ArgLoc.getTypeSourceInfo();
- return getDerived().TraverseTypeLoc(TSI->getTypeLoc());
+ // FIXME: how can TSI ever be NULL?
+ if (TypeSourceInfo *TSI = ArgLoc.getTypeSourceInfo())
+ return getDerived().TraverseTypeLoc(TSI->getTypeLoc());
+ else
+ return true;
}
case TemplateArgument::Template:
@@ -796,23 +817,31 @@ DEF_TRAVERSE_TYPELOC(MemberPointerType, {
TRY_TO(TraverseTypeLoc(TL.getPointeeLoc()));
})
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseArrayTypeLocHelper(ArrayTypeLoc TL) {
+ // This isn't available for ArrayType, but is for the ArrayTypeLoc.
+ TRY_TO(TraverseStmt(TL.getSizeExpr()));
+ return true;
+}
+
DEF_TRAVERSE_TYPELOC(ConstantArrayType, {
TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
+ return TraverseArrayTypeLocHelper(TL);
})
DEF_TRAVERSE_TYPELOC(IncompleteArrayType, {
TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
+ return TraverseArrayTypeLocHelper(TL);
})
DEF_TRAVERSE_TYPELOC(VariableArrayType, {
TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
- TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr()));
+ return TraverseArrayTypeLocHelper(TL);
})
DEF_TRAVERSE_TYPELOC(DependentSizedArrayType, {
TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
- if (TL.getTypePtr()->getSizeExpr())
- TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr()));
+ return TraverseArrayTypeLocHelper(TL);
})
// FIXME: order? why not size expr first?
@@ -1083,19 +1112,124 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper(
return true;
}
+// A helper method for traversing the implicit instantiations of a
+// class.
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseClassInstantiations(
+ ClassTemplateDecl* D, Decl *Pattern) {
+ assert(isa<ClassTemplateDecl>(Pattern) ||
+ isa<ClassTemplatePartialSpecializationDecl>(Pattern));
+
+ ClassTemplateDecl::spec_iterator end = D->spec_end();
+ for (ClassTemplateDecl::spec_iterator it = D->spec_begin(); it != end; ++it) {
+ ClassTemplateSpecializationDecl* SD = *it;
+
+ switch (SD->getSpecializationKind()) {
+ // Visit the implicit instantiations with the requested pattern.
+ case TSK_ImplicitInstantiation: {
+ llvm::PointerUnion<ClassTemplateDecl *,
+ ClassTemplatePartialSpecializationDecl *> U
+ = SD->getInstantiatedFrom();
+
+ bool ShouldVisit;
+ if (U.is<ClassTemplateDecl*>())
+ ShouldVisit = (U.get<ClassTemplateDecl*>() == Pattern);
+ else
+ ShouldVisit
+ = (U.get<ClassTemplatePartialSpecializationDecl*>() == Pattern);
+
+ if (ShouldVisit)
+ TRY_TO(TraverseClassTemplateSpecializationDecl(SD));
+ break;
+ }
+
+ // We don't need to do anything on an explicit instantiation
+ // or explicit specialization because there will be an explicit
+ // node for it elsewhere.
+ case TSK_ExplicitInstantiationDeclaration:
+ case TSK_ExplicitInstantiationDefinition:
+ case TSK_ExplicitSpecialization:
+ break;
+
+ // We don't need to do anything for an uninstantiated
+ // specialization.
+ case TSK_Undeclared:
+ break;
+ }
+ }
+
+ return true;
+}
+
DEF_TRAVERSE_DECL(ClassTemplateDecl, {
- TRY_TO(TraverseDecl(D->getTemplatedDecl()));
+ CXXRecordDecl* TempDecl = D->getTemplatedDecl();
+ TRY_TO(TraverseDecl(TempDecl));
TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
- // We should not traverse the specializations/partial
- // specializations. Those will show up in other contexts.
- // getInstantiatedFromMemberTemplate() is just a link from a
- // template instantiation back to the template from which it was
- // instantiated, and thus should not be traversed either.
+
+ // By default, we do not traverse the instantiations of
+ // class templates since they do not apprear in the user code. The
+ // following code optionally traverses them.
+ if (getDerived().shouldVisitTemplateInstantiations()) {
+ // If this is the definition of the primary template, visit
+ // instantiations which were formed from this pattern.
+ if (D->isThisDeclarationADefinition())
+ TRY_TO(TraverseClassInstantiations(D, D));
+ }
+
+ // Note that getInstantiatedFromMemberTemplate() is just a link
+ // from a template instantiation back to the template from which
+ // it was instantiated, and thus should not be traversed.
})
+// A helper method for traversing the instantiations of a
+// function while skipping its specializations.
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseFunctionInstantiations(
+ FunctionTemplateDecl* D) {
+ FunctionTemplateDecl::spec_iterator end = D->spec_end();
+ for (FunctionTemplateDecl::spec_iterator it = D->spec_begin(); it != end; ++it) {
+ FunctionDecl* FD = *it;
+ switch (FD->getTemplateSpecializationKind()) {
+ case TSK_ImplicitInstantiation:
+ // We don't know what kind of FunctionDecl this is.
+ TRY_TO(TraverseDecl(FD));
+ break;
+
+ // No need to visit explicit instantiations, we'll find the node
+ // eventually.
+ case TSK_ExplicitInstantiationDeclaration:
+ case TSK_ExplicitInstantiationDefinition:
+ break;
+
+ case TSK_Undeclared: // Declaration of the template definition.
+ case TSK_ExplicitSpecialization:
+ break;
+ default:
+ assert(false && "Unknown specialization kind.");
+ }
+ }
+
+ return true;
+}
+
DEF_TRAVERSE_DECL(FunctionTemplateDecl, {
TRY_TO(TraverseDecl(D->getTemplatedDecl()));
TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
+
+ // By default, we do not traverse the instantiations of
+ // function templates since they do not apprear in the user code. The
+ // following code optionally traverses them.
+ if (getDerived().shouldVisitTemplateInstantiations()) {
+ // Explicit function specializations will be traversed from the
+ // context of their declaration. There is therefore no need to
+ // traverse them for here.
+ //
+ // In addition, we only traverse the function instantiations when
+ // the function template is a function template definition.
+ if (D->isThisDeclarationADefinition()) {
+ TRY_TO(TraverseFunctionInstantiations(D));
+ }
+ }
})
DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, {
@@ -1110,10 +1244,10 @@ DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, {
DEF_TRAVERSE_DECL(TemplateTypeParmDecl, {
// D is the "T" in something like "template<typename T> class vector;"
- if (D->hasDefaultArgument())
- TRY_TO(TraverseTypeLoc(D->getDefaultArgumentInfo()->getTypeLoc()));
if (D->getTypeForDecl())
TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0)));
+ if (D->hasDefaultArgument())
+ TRY_TO(TraverseTypeLoc(D->getDefaultArgumentInfo()->getTypeLoc()));
})
DEF_TRAVERSE_DECL(TypedefDecl, {
@@ -1166,7 +1300,7 @@ bool RecursiveASTVisitor<Derived>::TraverseCXXRecordHelper(
for (CXXRecordDecl::base_class_iterator I = D->bases_begin(),
E = D->bases_end();
I != E; ++I) {
- TRY_TO(TraverseType(I->getType()));
+ TRY_TO(TraverseTypeLoc(I->getTypeSourceInfo()->getTypeLoc()));
}
// We don't traverse the friends or the conversions, as they are
// already in decls_begin()/decls_end().
@@ -1191,10 +1325,16 @@ DEF_TRAVERSE_DECL(ClassTemplateSpecializationDecl, {
// ("template set<int>;"), we do need a callback, since this
// is the only callback that's made for this instantiation.
// We use getTypeAsWritten() to distinguish.
- // FIXME: see how we want to handle template specializations.
if (TypeSourceInfo *TSI = D->getTypeAsWritten())
TRY_TO(TraverseTypeLoc(TSI->getTypeLoc()));
- return true;
+
+ if (!getDerived().shouldVisitTemplateInstantiations() &&
+ D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization)
+ // Returning from here skips traversing the
+ // declaration context of the ClassTemplateSpecializationDecl
+ // (embedded in the DEF_TRAVERSE_DECL() macro)
+ // which contains the instantiated members of the class.
+ return true;
})
template <typename Derived>
@@ -1222,6 +1362,12 @@ DEF_TRAVERSE_DECL(ClassTemplatePartialSpecializationDecl, {
// though that's our parent class -- we already visit all the
// template args here.
TRY_TO(TraverseCXXRecordHelper(D));
+
+ // If we're visiting instantiations, visit the instantiations of
+ // this template now.
+ if (getDerived().shouldVisitTemplateInstantiations() &&
+ D->isThisDeclarationADefinition())
+ TRY_TO(TraverseClassInstantiations(D->getSpecializedTemplate(), D));
})
DEF_TRAVERSE_DECL(EnumConstantDecl, {
@@ -1304,7 +1450,45 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) {
}
TRY_TO(TraverseType(D->getResultType()));
- TRY_TO(TraverseDeclContextHelper(D)); // Parameters.
+
+ // If we're an explicit template specialization, iterate over the
+ // template args that were explicitly specified.
+ if (const FunctionTemplateSpecializationInfo *FTSI =
+ D->getTemplateSpecializationInfo()) {
+ if (FTSI->getTemplateSpecializationKind() != TSK_Undeclared &&
+ FTSI->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) {
+ // A specialization might not have explicit template arguments if it has
+ // a templated return type and concrete arguments.
+ if (const TemplateArgumentListInfo *TALI =
+ FTSI->TemplateArgumentsAsWritten) {
+ TRY_TO(TraverseTemplateArgumentLocsHelper(TALI->getArgumentArray(),
+ TALI->size()));
+ }
+ }
+ }
+
+ for (FunctionDecl::param_iterator I = D->param_begin(), E = D->param_end();
+ I != E; ++I) {
+ TRY_TO(TraverseDecl(*I));
+ }
+
+ if (FunctionProtoType *FuncProto = dyn_cast<FunctionProtoType>(FuncType)) {
+ if (D->isThisDeclarationADefinition()) {
+ // This would be visited if we called TraverseType(D->getType())
+ // above, but we don't (at least, not in the
+ // declaration-is-a-definition case), in order to avoid duplicate
+ // visiting for parameters. (We need to check parameters here,
+ // rather than letting D->getType() do it, so we visit default
+ // parameter values). So we need to re-do some of the work the
+ // type would do.
+ for (FunctionProtoType::exception_iterator
+ E = FuncProto->exception_begin(),
+ EEnd = FuncProto->exception_end();
+ E != EEnd; ++E) {
+ TRY_TO(TraverseType(*E));
+ }
+ }
+ }
if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
// Constructor initializers.
@@ -1356,9 +1540,6 @@ DEF_TRAVERSE_DECL(CXXDestructorDecl, {
template<typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseVarHelper(VarDecl *D) {
TRY_TO(TraverseDeclaratorHelper(D));
- // FIXME: This often double-counts -- for instance, for all local
- // vars, though not for global vars -- because the initializer is
- // also captured when the var-decl is in a DeclStmt.
TRY_TO(TraverseStmt(D->getInit()));
return true;
}
@@ -1373,11 +1554,13 @@ DEF_TRAVERSE_DECL(ImplicitParamDecl, {
DEF_TRAVERSE_DECL(NonTypeTemplateParmDecl, {
// A non-type template parameter, e.g. "S" in template<int S> class Foo ...
- TRY_TO(TraverseStmt(D->getDefaultArgument()));
TRY_TO(TraverseVarHelper(D));
+ TRY_TO(TraverseStmt(D->getDefaultArgument()));
})
DEF_TRAVERSE_DECL(ParmVarDecl, {
+ TRY_TO(TraverseVarHelper(D));
+
if (D->hasDefaultArg() &&
D->hasUninstantiatedDefaultArg() &&
!D->hasUnparsedDefaultArg())
@@ -1387,8 +1570,6 @@ DEF_TRAVERSE_DECL(ParmVarDecl, {
!D->hasUninstantiatedDefaultArg() &&
!D->hasUnparsedDefaultArg())
TRY_TO(TraverseStmt(D->getDefaultArg()));
-
- TRY_TO(TraverseVarHelper(D));
})
#undef DEF_TRAVERSE_DECL
@@ -1431,35 +1612,36 @@ DEF_TRAVERSE_STMT(AsmStmt, {
})
DEF_TRAVERSE_STMT(CXXCatchStmt, {
- // We don't traverse S->getCaughtType(), as we are already
- // traversing the exception object, which has this type.
+ TRY_TO(TraverseDecl(S->getExceptionDecl()));
// child_begin()/end() iterates over the handler block.
})
-DEF_TRAVERSE_STMT(ForStmt, {
- TRY_TO(TraverseDecl(S->getConditionVariable()));
- // child_begin()/end() iterates over init, cond, inc, and body stmts.
- })
-
-DEF_TRAVERSE_STMT(IfStmt, {
- TRY_TO(TraverseDecl(S->getConditionVariable()));
- // child_begin()/end() iterates over cond, then, and else stmts.
+DEF_TRAVERSE_STMT(DeclStmt, {
+ for (DeclStmt::decl_iterator I = S->decl_begin(), E = S->decl_end();
+ I != E; ++I) {
+ TRY_TO(TraverseDecl(*I));
+ }
+ // Suppress the default iteration over child_begin/end by
+ // returning. Here's why: A DeclStmt looks like 'type var [=
+ // initializer]'. The decls above already traverse over the
+ // initializers, so we don't have to do it again (which
+ // child_begin/end would do).
+ return true;
})
-DEF_TRAVERSE_STMT(WhileStmt, {
- TRY_TO(TraverseDecl(S->getConditionVariable()));
- // child_begin()/end() iterates over cond, then, and else stmts.
- })
// These non-expr stmts (most of them), do not need any action except
// iterating over the children.
DEF_TRAVERSE_STMT(BreakStmt, { })
+DEF_TRAVERSE_STMT(CXXTryStmt, { })
+DEF_TRAVERSE_STMT(CaseStmt, { })
DEF_TRAVERSE_STMT(CompoundStmt, { })
DEF_TRAVERSE_STMT(ContinueStmt, { })
-DEF_TRAVERSE_STMT(CXXTryStmt, { })
-DEF_TRAVERSE_STMT(DeclStmt, { })
+DEF_TRAVERSE_STMT(DefaultStmt, { })
DEF_TRAVERSE_STMT(DoStmt, { })
+DEF_TRAVERSE_STMT(ForStmt, { })
DEF_TRAVERSE_STMT(GotoStmt, { })
+DEF_TRAVERSE_STMT(IfStmt, { })
DEF_TRAVERSE_STMT(IndirectGotoStmt, { })
DEF_TRAVERSE_STMT(LabelStmt, { })
DEF_TRAVERSE_STMT(NullStmt, { })
@@ -1470,10 +1652,10 @@ DEF_TRAVERSE_STMT(ObjCAtThrowStmt, { })
DEF_TRAVERSE_STMT(ObjCAtTryStmt, { })
DEF_TRAVERSE_STMT(ObjCForCollectionStmt, { })
DEF_TRAVERSE_STMT(ReturnStmt, { })
-DEF_TRAVERSE_STMT(SwitchStmt, { })
DEF_TRAVERSE_STMT(SwitchCase, { })
-DEF_TRAVERSE_STMT(CaseStmt, { })
-DEF_TRAVERSE_STMT(DefaultStmt, { })
+DEF_TRAVERSE_STMT(SwitchStmt, { })
+DEF_TRAVERSE_STMT(WhileStmt, { })
+
DEF_TRAVERSE_STMT(CXXDependentScopeMemberExpr, {
if (S->hasExplicitTemplateArgs()) {
@@ -1565,6 +1747,37 @@ DEF_TRAVERSE_STMT(CXXNewExpr, {
TRY_TO(TraverseType(S->getAllocatedType()));
})
+DEF_TRAVERSE_STMT(OffsetOfExpr, {
+ // The child-iterator will pick up the expression representing
+ // the field.
+ // FIMXE: for code like offsetof(Foo, a.b.c), should we get
+ // making a MemberExpr callbacks for Foo.a, Foo.a.b, and Foo.a.b.c?
+ TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(SizeOfAlignOfExpr, {
+ // The child-iterator will pick up the arg if it's an expression,
+ // but not if it's a type.
+ if (S->isArgumentType())
+ TRY_TO(TraverseTypeLoc(S->getArgumentTypeInfo()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(CXXTypeidExpr, {
+ // The child-iterator will pick up the arg if it's an expression,
+ // but not if it's a type.
+ if (S->isTypeOperand())
+ TRY_TO(TraverseTypeLoc(S->getTypeOperandSourceInfo()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(TypesCompatibleExpr, {
+ TRY_TO(TraverseTypeLoc(S->getArgTInfo1()->getTypeLoc()));
+ TRY_TO(TraverseTypeLoc(S->getArgTInfo2()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(UnaryTypeTraitExpr, {
+ TRY_TO(TraverseType(S->getQueriedType()));
+ })
+
// These exprs (most of them), do not need any action except iterating
// over the children.
DEF_TRAVERSE_STMT(AddrLabelExpr, { })
@@ -1573,7 +1786,6 @@ DEF_TRAVERSE_STMT(BlockDeclRefExpr, { })
DEF_TRAVERSE_STMT(BlockExpr, { })
DEF_TRAVERSE_STMT(ChooseExpr, { })
DEF_TRAVERSE_STMT(CompoundLiteralExpr, { })
-DEF_TRAVERSE_STMT(CXXBindReferenceExpr, { })
DEF_TRAVERSE_STMT(CXXBindTemporaryExpr, { })
DEF_TRAVERSE_STMT(CXXBoolLiteralExpr, { })
DEF_TRAVERSE_STMT(CXXDefaultArgExpr, { })
@@ -1583,7 +1795,6 @@ DEF_TRAVERSE_STMT(CXXNullPtrLiteralExpr, { })
DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, { })
DEF_TRAVERSE_STMT(CXXThisExpr, { })
DEF_TRAVERSE_STMT(CXXThrowExpr, { })
-DEF_TRAVERSE_STMT(CXXTypeidExpr, { })
DEF_TRAVERSE_STMT(CXXUnresolvedConstructExpr, { })
DEF_TRAVERSE_STMT(DesignatedInitExpr, { })
DEF_TRAVERSE_STMT(ExtVectorElementExpr, { })
@@ -1598,18 +1809,17 @@ DEF_TRAVERSE_STMT(ObjCPropertyRefExpr, { })
DEF_TRAVERSE_STMT(ObjCProtocolExpr, { })
DEF_TRAVERSE_STMT(ObjCSelectorExpr, { })
DEF_TRAVERSE_STMT(ObjCSuperExpr, { })
-DEF_TRAVERSE_STMT(OffsetOfExpr, { })
DEF_TRAVERSE_STMT(ParenExpr, { })
DEF_TRAVERSE_STMT(ParenListExpr, { })
DEF_TRAVERSE_STMT(PredefinedExpr, { })
DEF_TRAVERSE_STMT(ShuffleVectorExpr, { })
-DEF_TRAVERSE_STMT(SizeOfAlignOfExpr, { })
DEF_TRAVERSE_STMT(StmtExpr, { })
-DEF_TRAVERSE_STMT(TypesCompatibleExpr, { })
-DEF_TRAVERSE_STMT(UnaryTypeTraitExpr, { })
DEF_TRAVERSE_STMT(UnresolvedLookupExpr, { })
DEF_TRAVERSE_STMT(UnresolvedMemberExpr, { })
-DEF_TRAVERSE_STMT(VAArgExpr, { })
+DEF_TRAVERSE_STMT(VAArgExpr, {
+ // The child-iterator will pick up the expression argument.
+ TRY_TO(TraverseTypeLoc(S->getWrittenTypeInfo()->getTypeLoc()));
+ })
DEF_TRAVERSE_STMT(CXXConstructExpr, { })
DEF_TRAVERSE_STMT(CXXTemporaryObjectExpr, {
diff --git a/include/clang/AST/Redeclarable.h b/include/clang/AST/Redeclarable.h
index 55e1f8477992..ba778293ba2d 100644
--- a/include/clang/AST/Redeclarable.h
+++ b/include/clang/AST/Redeclarable.h
@@ -177,6 +177,9 @@ public:
static_cast<const decl_type*>(this)));
}
redecl_iterator redecls_end() const { return redecl_iterator(); }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
};
}
diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h
index a0c95b1fce8c..62a6b6463df5 100644
--- a/include/clang/AST/Stmt.h
+++ b/include/clang/AST/Stmt.h
@@ -151,22 +151,11 @@ public:
struct EmptyShell { };
protected:
- /// DestroyChildren - Invoked by destructors of subclasses of Stmt to
- /// recursively release child AST nodes.
- void DestroyChildren(ASTContext& Ctx);
-
/// \brief Construct an empty statement.
explicit Stmt(StmtClass SC, EmptyShell) : sClass(SC), RefCount(1) {
if (Stmt::CollectingStats()) Stmt::addStmtClass(SC);
}
- /// \brief Virtual method that performs the actual destruction of
- /// this statement.
- ///
- /// Subclasses should override this method (not Destroy()) to
- /// provide class-specific destruction.
- virtual void DoDestroy(ASTContext &Ctx);
-
public:
Stmt(StmtClass SC) : sClass(SC), RefCount(1) {
if (Stmt::CollectingStats()) Stmt::addStmtClass(SC);
@@ -181,13 +170,6 @@ public:
}
#endif
- /// \brief Destroy the current statement and its children.
- void Destroy(ASTContext &Ctx) {
- assert(RefCount >= 1);
- if (--RefCount == 0)
- DoDestroy(Ctx);
- }
-
/// \brief Increases the reference count for this statement.
///
/// Invoke the Retain() operation when this statement or expression
@@ -221,6 +203,7 @@ public:
/// This is useful in a debugger.
void dump() const;
void dump(SourceManager &SM) const;
+ void dump(llvm::raw_ostream &OS, SourceManager &SM) const;
/// dumpAll - This does a dump of the specified AST fragment and all subtrees.
void dumpAll() const;
@@ -295,9 +278,6 @@ class DeclStmt : public Stmt {
DeclGroupRef DG;
SourceLocation StartLoc, EndLoc;
-protected:
- virtual void DoDestroy(ASTContext &Ctx);
-
public:
DeclStmt(DeclGroupRef dg, SourceLocation startLoc,
SourceLocation endLoc) : Stmt(DeclStmtClass), DG(dg),
@@ -671,9 +651,6 @@ public:
// over the initialization expression referenced by the condition variable.
virtual child_iterator child_begin();
virtual child_iterator child_end();
-
-protected:
- virtual void DoDestroy(ASTContext &Ctx);
};
/// SwitchStmt - This represents a 'switch' stmt.
@@ -685,9 +662,6 @@ class SwitchStmt : public Stmt {
SwitchCase *FirstCase;
SourceLocation SwitchLoc;
-protected:
- virtual void DoDestroy(ASTContext &Ctx);
-
public:
SwitchStmt(ASTContext &C, VarDecl *Var, Expr *cond);
@@ -794,9 +768,6 @@ public:
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
-
-protected:
- virtual void DoDestroy(ASTContext &Ctx);
};
/// DoStmt - This represents a 'do/while' stmt.
@@ -910,9 +881,6 @@ public:
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
-
-protected:
- virtual void DoDestroy(ASTContext &Ctx);
};
/// GotoStmt - This represents a direct goto.
@@ -1113,9 +1081,6 @@ class AsmStmt : public Stmt {
StringLiteral **Constraints;
Stmt **Exprs;
StringLiteral **Clobbers;
-
-protected:
- virtual void DoDestroy(ASTContext &Ctx);
public:
AsmStmt(ASTContext &C, SourceLocation asmloc, bool issimple, bool isvolatile,
diff --git a/include/clang/AST/StmtCXX.h b/include/clang/AST/StmtCXX.h
index 4e87c2701c26..0508f35e48e8 100644
--- a/include/clang/AST/StmtCXX.h
+++ b/include/clang/AST/StmtCXX.h
@@ -29,14 +29,14 @@ class CXXCatchStmt : public Stmt {
/// The handler block.
Stmt *HandlerBlock;
-protected:
- virtual void DoDestroy(ASTContext& Ctx);
-
public:
CXXCatchStmt(SourceLocation catchLoc, VarDecl *exDecl, Stmt *handlerBlock)
: Stmt(CXXCatchStmtClass), CatchLoc(catchLoc), ExceptionDecl(exDecl),
HandlerBlock(handlerBlock) {}
+ CXXCatchStmt(EmptyShell Empty)
+ : Stmt(CXXCatchStmtClass), ExceptionDecl(0), HandlerBlock(0) {}
+
virtual SourceRange getSourceRange() const {
return SourceRange(CatchLoc, HandlerBlock->getLocEnd());
}
@@ -53,6 +53,8 @@ public:
virtual child_iterator child_begin();
virtual child_iterator child_end();
+
+ friend class ASTStmtReader;
};
/// CXXTryStmt - A C++ try block, including all handlers.
@@ -64,38 +66,46 @@ class CXXTryStmt : public Stmt {
CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, Stmt **handlers,
unsigned numHandlers);
+ CXXTryStmt(EmptyShell Empty, unsigned numHandlers)
+ : Stmt(CXXTryStmtClass), NumHandlers(numHandlers) { }
+
+ Stmt const * const *getStmts() const {
+ return reinterpret_cast<Stmt const * const*>(this + 1);
+ }
+ Stmt **getStmts() {
+ return reinterpret_cast<Stmt **>(this + 1);
+ }
+
public:
static CXXTryStmt *Create(ASTContext &C, SourceLocation tryLoc,
Stmt *tryBlock, Stmt **handlers,
unsigned numHandlers);
+ static CXXTryStmt *Create(ASTContext &C, EmptyShell Empty,
+ unsigned numHandlers);
+
virtual SourceRange getSourceRange() const {
return SourceRange(getTryLoc(), getEndLoc());
}
SourceLocation getTryLoc() const { return TryLoc; }
SourceLocation getEndLoc() const {
- Stmt const * const*Stmts = reinterpret_cast<Stmt const * const*>(this + 1);
- return Stmts[NumHandlers]->getLocEnd();
+ return getStmts()[NumHandlers]->getLocEnd();
}
CompoundStmt *getTryBlock() {
- Stmt **Stmts = reinterpret_cast<Stmt **>(this + 1);
- return llvm::cast<CompoundStmt>(Stmts[0]);
+ return llvm::cast<CompoundStmt>(getStmts()[0]);
}
const CompoundStmt *getTryBlock() const {
- Stmt const * const*Stmts = reinterpret_cast<Stmt const * const*>(this + 1);
- return llvm::cast<CompoundStmt>(Stmts[0]);
+ return llvm::cast<CompoundStmt>(getStmts()[0]);
}
unsigned getNumHandlers() const { return NumHandlers; }
CXXCatchStmt *getHandler(unsigned i) {
- Stmt **Stmts = reinterpret_cast<Stmt **>(this + 1);
- return llvm::cast<CXXCatchStmt>(Stmts[i + 1]);
+ return llvm::cast<CXXCatchStmt>(getStmts()[i + 1]);
}
const CXXCatchStmt *getHandler(unsigned i) const {
- Stmt const * const*Stmts = reinterpret_cast<Stmt const * const*>(this + 1);
- return llvm::cast<CXXCatchStmt>(Stmts[i + 1]);
+ return llvm::cast<CXXCatchStmt>(getStmts()[i + 1]);
}
static bool classof(const Stmt *T) {
@@ -105,6 +115,8 @@ public:
virtual child_iterator child_begin();
virtual child_iterator child_end();
+
+ friend class ASTStmtReader;
};
diff --git a/include/clang/AST/StmtVisitor.h b/include/clang/AST/StmtVisitor.h
index 8078451fa31f..b8c141d7ef8e 100644
--- a/include/clang/AST/StmtVisitor.h
+++ b/include/clang/AST/StmtVisitor.h
@@ -37,68 +37,57 @@ public:
if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) {
switch (BinOp->getOpcode()) {
default: assert(0 && "Unknown binary operator!");
- case BinaryOperator::PtrMemD: DISPATCH(BinPtrMemD, BinaryOperator);
- case BinaryOperator::PtrMemI: DISPATCH(BinPtrMemI, BinaryOperator);
- case BinaryOperator::Mul: DISPATCH(BinMul, BinaryOperator);
- case BinaryOperator::Div: DISPATCH(BinDiv, BinaryOperator);
- case BinaryOperator::Rem: DISPATCH(BinRem, BinaryOperator);
- case BinaryOperator::Add: DISPATCH(BinAdd, BinaryOperator);
- case BinaryOperator::Sub: DISPATCH(BinSub, BinaryOperator);
- case BinaryOperator::Shl: DISPATCH(BinShl, BinaryOperator);
- case BinaryOperator::Shr: DISPATCH(BinShr, BinaryOperator);
-
- case BinaryOperator::LT: DISPATCH(BinLT, BinaryOperator);
- case BinaryOperator::GT: DISPATCH(BinGT, BinaryOperator);
- case BinaryOperator::LE: DISPATCH(BinLE, BinaryOperator);
- case BinaryOperator::GE: DISPATCH(BinGE, BinaryOperator);
- case BinaryOperator::EQ: DISPATCH(BinEQ, BinaryOperator);
- case BinaryOperator::NE: DISPATCH(BinNE, BinaryOperator);
-
- case BinaryOperator::And: DISPATCH(BinAnd, BinaryOperator);
- case BinaryOperator::Xor: DISPATCH(BinXor, BinaryOperator);
- case BinaryOperator::Or : DISPATCH(BinOr, BinaryOperator);
- case BinaryOperator::LAnd: DISPATCH(BinLAnd, BinaryOperator);
- case BinaryOperator::LOr : DISPATCH(BinLOr, BinaryOperator);
- case BinaryOperator::Assign: DISPATCH(BinAssign, BinaryOperator);
- case BinaryOperator::MulAssign:
- DISPATCH(BinMulAssign, CompoundAssignOperator);
- case BinaryOperator::DivAssign:
- DISPATCH(BinDivAssign, CompoundAssignOperator);
- case BinaryOperator::RemAssign:
- DISPATCH(BinRemAssign, CompoundAssignOperator);
- case BinaryOperator::AddAssign:
- DISPATCH(BinAddAssign, CompoundAssignOperator);
- case BinaryOperator::SubAssign:
- DISPATCH(BinSubAssign, CompoundAssignOperator);
- case BinaryOperator::ShlAssign:
- DISPATCH(BinShlAssign, CompoundAssignOperator);
- case BinaryOperator::ShrAssign:
- DISPATCH(BinShrAssign, CompoundAssignOperator);
- case BinaryOperator::AndAssign:
- DISPATCH(BinAndAssign, CompoundAssignOperator);
- case BinaryOperator::OrAssign:
- DISPATCH(BinOrAssign, CompoundAssignOperator);
- case BinaryOperator::XorAssign:
- DISPATCH(BinXorAssign, CompoundAssignOperator);
- case BinaryOperator::Comma: DISPATCH(BinComma, BinaryOperator);
+ case BO_PtrMemD: DISPATCH(BinPtrMemD, BinaryOperator);
+ case BO_PtrMemI: DISPATCH(BinPtrMemI, BinaryOperator);
+ case BO_Mul: DISPATCH(BinMul, BinaryOperator);
+ case BO_Div: DISPATCH(BinDiv, BinaryOperator);
+ case BO_Rem: DISPATCH(BinRem, BinaryOperator);
+ case BO_Add: DISPATCH(BinAdd, BinaryOperator);
+ case BO_Sub: DISPATCH(BinSub, BinaryOperator);
+ case BO_Shl: DISPATCH(BinShl, BinaryOperator);
+ case BO_Shr: DISPATCH(BinShr, BinaryOperator);
+
+ case BO_LT: DISPATCH(BinLT, BinaryOperator);
+ case BO_GT: DISPATCH(BinGT, BinaryOperator);
+ case BO_LE: DISPATCH(BinLE, BinaryOperator);
+ case BO_GE: DISPATCH(BinGE, BinaryOperator);
+ case BO_EQ: DISPATCH(BinEQ, BinaryOperator);
+ case BO_NE: DISPATCH(BinNE, BinaryOperator);
+
+ case BO_And: DISPATCH(BinAnd, BinaryOperator);
+ case BO_Xor: DISPATCH(BinXor, BinaryOperator);
+ case BO_Or : DISPATCH(BinOr, BinaryOperator);
+ case BO_LAnd: DISPATCH(BinLAnd, BinaryOperator);
+ case BO_LOr : DISPATCH(BinLOr, BinaryOperator);
+ case BO_Assign: DISPATCH(BinAssign, BinaryOperator);
+ case BO_MulAssign: DISPATCH(BinMulAssign, CompoundAssignOperator);
+ case BO_DivAssign: DISPATCH(BinDivAssign, CompoundAssignOperator);
+ case BO_RemAssign: DISPATCH(BinRemAssign, CompoundAssignOperator);
+ case BO_AddAssign: DISPATCH(BinAddAssign, CompoundAssignOperator);
+ case BO_SubAssign: DISPATCH(BinSubAssign, CompoundAssignOperator);
+ case BO_ShlAssign: DISPATCH(BinShlAssign, CompoundAssignOperator);
+ case BO_ShrAssign: DISPATCH(BinShrAssign, CompoundAssignOperator);
+ case BO_AndAssign: DISPATCH(BinAndAssign, CompoundAssignOperator);
+ case BO_OrAssign: DISPATCH(BinOrAssign, CompoundAssignOperator);
+ case BO_XorAssign: DISPATCH(BinXorAssign, CompoundAssignOperator);
+ case BO_Comma: DISPATCH(BinComma, BinaryOperator);
}
} else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) {
switch (UnOp->getOpcode()) {
default: assert(0 && "Unknown unary operator!");
- case UnaryOperator::PostInc: DISPATCH(UnaryPostInc, UnaryOperator);
- case UnaryOperator::PostDec: DISPATCH(UnaryPostDec, UnaryOperator);
- case UnaryOperator::PreInc: DISPATCH(UnaryPreInc, UnaryOperator);
- case UnaryOperator::PreDec: DISPATCH(UnaryPreDec, UnaryOperator);
- case UnaryOperator::AddrOf: DISPATCH(UnaryAddrOf, UnaryOperator);
- case UnaryOperator::Deref: DISPATCH(UnaryDeref, UnaryOperator);
- case UnaryOperator::Plus: DISPATCH(UnaryPlus, UnaryOperator);
- case UnaryOperator::Minus: DISPATCH(UnaryMinus, UnaryOperator);
- case UnaryOperator::Not: DISPATCH(UnaryNot, UnaryOperator);
- case UnaryOperator::LNot: DISPATCH(UnaryLNot, UnaryOperator);
- case UnaryOperator::Real: DISPATCH(UnaryReal, UnaryOperator);
- case UnaryOperator::Imag: DISPATCH(UnaryImag, UnaryOperator);
- case UnaryOperator::Extension: DISPATCH(UnaryExtension, UnaryOperator);
- case UnaryOperator::OffsetOf: DISPATCH(UnaryOffsetOf, UnaryOperator);
+ case UO_PostInc: DISPATCH(UnaryPostInc, UnaryOperator);
+ case UO_PostDec: DISPATCH(UnaryPostDec, UnaryOperator);
+ case UO_PreInc: DISPATCH(UnaryPreInc, UnaryOperator);
+ case UO_PreDec: DISPATCH(UnaryPreDec, UnaryOperator);
+ case UO_AddrOf: DISPATCH(UnaryAddrOf, UnaryOperator);
+ case UO_Deref: DISPATCH(UnaryDeref, UnaryOperator);
+ case UO_Plus: DISPATCH(UnaryPlus, UnaryOperator);
+ case UO_Minus: DISPATCH(UnaryMinus, UnaryOperator);
+ case UO_Not: DISPATCH(UnaryNot, UnaryOperator);
+ case UO_LNot: DISPATCH(UnaryLNot, UnaryOperator);
+ case UO_Real: DISPATCH(UnaryReal, UnaryOperator);
+ case UO_Imag: DISPATCH(UnaryImag, UnaryOperator);
+ case UO_Extension: DISPATCH(UnaryExtension, UnaryOperator);
}
}
@@ -163,7 +152,7 @@ public:
UNARYOP_FALLBACK(Plus) UNARYOP_FALLBACK(Minus)
UNARYOP_FALLBACK(Not) UNARYOP_FALLBACK(LNot)
UNARYOP_FALLBACK(Real) UNARYOP_FALLBACK(Imag)
- UNARYOP_FALLBACK(Extension) UNARYOP_FALLBACK(OffsetOf)
+ UNARYOP_FALLBACK(Extension)
#undef UNARYOP_FALLBACK
// Base case, ignore it. :)
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 4c148e8fa221..92e62a58d42c 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -289,7 +289,18 @@ public:
L += R;
return L;
}
+
+ Qualifiers &operator-=(Qualifiers R) {
+ Mask = Mask & ~(R.Mask);
+ return *this;
+ }
+ /// \brief Compute the difference between two qualifier sets.
+ friend Qualifiers operator-(Qualifiers L, Qualifiers R) {
+ L -= R;
+ return L;
+ }
+
std::string getAsString() const;
std::string getAsString(const PrintingPolicy &Policy) const {
std::string Buffer;
@@ -399,7 +410,8 @@ enum CallingConv {
CC_C, // __attribute__((cdecl))
CC_X86StdCall, // __attribute__((stdcall))
CC_X86FastCall, // __attribute__((fastcall))
- CC_X86ThisCall // __attribute__((thiscall))
+ CC_X86ThisCall, // __attribute__((thiscall))
+ CC_X86Pascal // __attribute__((pascal))
};
@@ -787,12 +799,12 @@ private:
/// \brief Linkage of this type.
mutable unsigned CachedLinkage : 2;
- /// \brief FromPCH - Whether this type comes from a PCH file.
- mutable bool FromPCH : 1;
+ /// \brief FromAST - Whether this type comes from an AST file.
+ mutable bool FromAST : 1;
- /// \brief Set whether this type comes from a PCH file.
- void setFromPCH(bool V = true) const {
- FromPCH = V;
+ /// \brief Set whether this type comes from an AST file.
+ void setFromAST(bool V = true) const {
+ FromAST = V;
}
protected:
@@ -806,16 +818,15 @@ protected:
Type(TypeClass tc, QualType Canonical, bool dependent)
: CanonicalType(Canonical.isNull() ? QualType(this_(), 0) : Canonical),
TC(tc), Dependent(dependent), LinkageKnown(false),
- CachedLinkage(NoLinkage), FromPCH(false) {}
- virtual ~Type() {}
- virtual void Destroy(ASTContext& C);
+ CachedLinkage(NoLinkage), FromAST(false) {}
+ virtual ~Type();
friend class ASTContext;
public:
TypeClass getTypeClass() const { return static_cast<TypeClass>(TC); }
- /// \brief Whether this type comes from a PCH file.
- bool isFromPCH() const { return FromPCH; }
+ /// \brief Whether this type comes from an AST file.
+ bool isFromAST() const { return FromAST; }
bool isCanonicalUnqualified() const {
return CanonicalType.getTypePtr() == this;
@@ -824,14 +835,6 @@ public:
/// Types are partitioned into 3 broad categories (C99 6.2.5p1):
/// object types, function types, and incomplete types.
- /// \brief Determines whether the type describes an object in memory.
- ///
- /// Note that this definition of object type corresponds to the C++
- /// definition of object type, which includes incomplete types, as
- /// opposed to the C definition (which does not include incomplete
- /// types).
- bool isObjectType() const;
-
/// isIncompleteType - Return true if this is an incomplete type.
/// A type that can describe objects, but which lacks information needed to
/// determine its size (e.g. void, or a fwd declared struct). Clients of this
@@ -906,6 +909,7 @@ public:
bool isFunctionPointerType() const;
bool isMemberPointerType() const;
bool isMemberFunctionPointerType() const;
+ bool isMemberDataPointerType() const;
bool isArrayType() const;
bool isConstantArrayType() const;
bool isIncompleteArrayType() const;
@@ -926,6 +930,7 @@ public:
bool isObjCQualifiedInterfaceType() const; // NSString<foo>
bool isObjCQualifiedIdType() const; // id<foo>
bool isObjCQualifiedClassType() const; // Class<foo>
+ bool isObjCObjectOrInterfaceType() const;
bool isObjCIdType() const; // id
bool isObjCClassType() const; // Class
bool isObjCSelType() const; // Class
@@ -952,10 +957,22 @@ public:
/// an objective pointer type for the purpose of GC'ability
bool hasObjCPointerRepresentation() const;
+ /// \brief Determine whether this type has an integer representation
+ /// of some sort, e.g., it is an integer type or a vector.
+ bool hasIntegerRepresentation() const;
+
+ /// \brief Determine whether this type has an signed integer representation
+ /// of some sort, e.g., it is an signed integer type or a vector.
+ bool hasSignedIntegerRepresentation() const;
+
+ /// \brief Determine whether this type has an unsigned integer representation
+ /// of some sort, e.g., it is an unsigned integer type or a vector.
+ bool hasUnsignedIntegerRepresentation() const;
+
/// \brief Determine whether this type has a floating-point representation
/// of some sort, e.g., it is a floating-point type or a vector thereof.
bool hasFloatingRepresentation() const;
-
+
// Type Checking Functions: Check to see if this type is structurally the
// specified type, ignoring typedefs and qualifiers, and return a pointer to
// the best type we can.
@@ -975,7 +992,8 @@ public:
/// type of a class template or class template partial specialization.
CXXRecordDecl *getAsCXXRecordDecl() const;
- // Member-template getAs<specific type>'. This scheme will eventually
+ // Member-template getAs<specific type>'. Look through sugar for
+ // an instance of <specific type>. This scheme will eventually
// replace the specific getAsXXXX methods above.
//
// There are some specializations of this member template listed
@@ -1035,8 +1053,8 @@ public:
void dump() const;
static bool classof(const Type *) { return true; }
- friend class PCHReader;
- friend class PCHWriter;
+ friend class ASTReader;
+ friend class ASTWriter;
};
template <> inline const TypedefType *Type::getAs() const {
@@ -1353,9 +1371,20 @@ protected:
virtual Linkage getLinkageImpl() const;
public:
-
QualType getPointeeType() const { return PointeeType; }
+ /// Returns true if the member type (i.e. the pointee type) is a
+ /// function type rather than a data-member type.
+ bool isMemberFunctionPointer() const {
+ return PointeeType->isFunctionProtoType();
+ }
+
+ /// Returns true if the member type (i.e. the pointee type) is a
+ /// data type rather than a function type.
+ bool isMemberDataPointer() const {
+ return !PointeeType->isFunctionProtoType();
+ }
+
const Type *getClass() const { return Class; }
bool isSugared() const { return false; }
@@ -1454,6 +1483,17 @@ public:
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
+
+ /// \brief Determine the number of bits required to address a member of
+ // an array with the given element type and number of elements.
+ static unsigned getNumAddressingBits(ASTContext &Context,
+ QualType ElementType,
+ const llvm::APInt &NumElements);
+
+ /// \brief Determine the maximum number of active bits that an array's size
+ /// can require, which limits the maximum size of the array.
+ static unsigned getMaxSizeBits(ASTContext &Context);
+
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getElementType(), getSize(),
getSizeModifier(), getIndexTypeCVRQualifiers());
@@ -1533,7 +1573,6 @@ class VariableArrayType : public ArrayType {
: ArrayType(VariableArray, et, can, sm, tq),
SizeExpr((Stmt*) e), Brackets(brackets) {}
friend class ASTContext; // ASTContext creates these.
- virtual void Destroy(ASTContext& C);
public:
Expr *getSizeExpr() const {
@@ -1592,7 +1631,6 @@ class DependentSizedArrayType : public ArrayType {
: ArrayType(DependentSizedArray, et, can, sm, tq),
Context(Context), SizeExpr((Stmt*) e), Brackets(brackets) {}
friend class ASTContext; // ASTContext creates these.
- virtual void Destroy(ASTContext& C);
public:
Expr *getSizeExpr() const {
@@ -1646,7 +1684,6 @@ class DependentSizedExtVectorType : public Type, public llvm::FoldingSetNode {
Context(Context), SizeExpr(SizeExpr), ElementType(ElementType),
loc(loc) {}
friend class ASTContext;
- virtual void Destroy(ASTContext& C);
public:
Expr *getSizeExpr() const { return SizeExpr; }
@@ -1844,13 +1881,13 @@ class FunctionType : public Type {
// * FunctionNoProtoType::Profile
// * FunctionProtoType::Profile
// * TypePrinter::PrintFunctionProto
- // * PCH read and write
+ // * AST read and write
// * Codegen
class ExtInfo {
public:
// Constructor with no defaults. Use this when you know that you
- // have all the elements (when reading a PCH file for example).
+ // have all the elements (when reading an AST file for example).
ExtInfo(bool noReturn, unsigned regParm, CallingConv cc) :
NoReturn(noReturn), RegParm(regParm), CC(cc) {}
@@ -1892,7 +1929,7 @@ class FunctionType : public Type {
// The value passed to __attribute__((regparm(x)))
unsigned RegParm;
// The calling convention as specified via
- // __attribute__((cdecl|stdcall|fastcall|thiscall))
+ // __attribute__((cdecl|stdcall|fastcall|thiscall|pascal))
CallingConv CC;
};
@@ -2259,14 +2296,9 @@ public:
};
class TagType : public Type {
- /// Stores the TagDecl associated with this type. The decl will
- /// point to the TagDecl that actually defines the entity (or is a
- /// definition in progress), if there is such a definition. The
- /// single-bit value will be non-zero when this tag is in the
- /// process of being defined.
- mutable llvm::PointerIntPair<TagDecl *, 1> decl;
- friend class ASTContext;
- friend class TagDecl;
+ /// Stores the TagDecl associated with this type. The decl may point to any
+ /// TagDecl that declares the entity.
+ TagDecl * decl;
protected:
TagType(TypeClass TC, const TagDecl *D, QualType can);
@@ -2274,12 +2306,11 @@ protected:
virtual Linkage getLinkageImpl() const;
public:
- TagDecl *getDecl() const { return decl.getPointer(); }
+ TagDecl *getDecl() const;
/// @brief Determines whether this type is in the process of being
/// defined.
- bool isBeingDefined() const { return decl.getInt(); }
- void setBeingDefined(bool Def) const { decl.setInt(Def? 1 : 0); }
+ bool isBeingDefined() const;
static bool classof(const Type *T) {
return T->getTypeClass() >= TagFirst && T->getTypeClass() <= TagLast;
@@ -2468,8 +2499,6 @@ class TemplateSpecializationType
const TemplateArgument *Args,
unsigned NumArgs, QualType Canon);
- virtual void Destroy(ASTContext& C);
-
friend class ASTContext; // ASTContext creates these
public:
@@ -2574,9 +2603,8 @@ class InjectedClassNameType : public Type {
QualType InjectedType;
friend class ASTContext; // ASTContext creates these.
- friend class TagDecl; // TagDecl mutilates the Decl
- friend class PCHReader; // FIXME: ASTContext::getInjectedClassNameType is not
- // currently suitable for PCH reading, too much
+ friend class ASTReader; // FIXME: ASTContext::getInjectedClassNameType is not
+ // currently suitable for AST reading, too much
// interdependencies.
InjectedClassNameType(CXXRecordDecl *D, QualType TST)
: Type(InjectedClassName, QualType(), true),
@@ -2592,7 +2620,7 @@ public:
return cast<TemplateSpecializationType>(InjectedType.getTypePtr());
}
- CXXRecordDecl *getDecl() const { return Decl; }
+ CXXRecordDecl *getDecl() const;
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@@ -2836,8 +2864,6 @@ class DependentTemplateSpecializationType :
const TemplateArgument *Args,
QualType Canon);
- virtual void Destroy(ASTContext& C);
-
friend class ASTContext; // ASTContext creates these
public:
@@ -3014,8 +3040,6 @@ class ObjCObjectTypeImpl : public ObjCObjectType, public llvm::FoldingSetNode {
: ObjCObjectType(Canonical, Base, Protocols, NumProtocols) {}
public:
- void Destroy(ASTContext& C); // key function
-
void Profile(llvm::FoldingSetNodeID &ID);
static void Profile(llvm::FoldingSetNodeID &ID,
QualType Base,
@@ -3049,8 +3073,6 @@ class ObjCInterfaceType : public ObjCObjectType {
Decl(const_cast<ObjCInterfaceDecl*>(D)) {}
friend class ASTContext; // ASTContext creates these.
public:
- void Destroy(ASTContext& C); // key function
-
/// getDecl - Get the declaration of this interface.
ObjCInterfaceDecl *getDecl() const { return Decl; }
@@ -3103,8 +3125,6 @@ protected:
virtual Linkage getLinkageImpl() const;
public:
- void Destroy(ASTContext& C);
-
/// getPointeeType - Gets the type pointed to by this ObjC pointer.
/// The result will always be an ObjCObjectType or sugar thereof.
QualType getPointeeType() const { return PointeeType; }
@@ -3486,7 +3506,13 @@ inline bool Type::isMemberPointerType() const {
}
inline bool Type::isMemberFunctionPointerType() const {
if (const MemberPointerType* T = getAs<MemberPointerType>())
- return T->getPointeeType()->isFunctionType();
+ return T->isMemberFunctionPointer();
+ else
+ return false;
+}
+inline bool Type::isMemberDataPointerType() const {
+ if (const MemberPointerType* T = getAs<MemberPointerType>())
+ return T->isMemberDataPointer();
else
return false;
}
@@ -3523,6 +3549,11 @@ inline bool Type::isObjCObjectPointerType() const {
inline bool Type::isObjCObjectType() const {
return isa<ObjCObjectType>(CanonicalType);
}
+inline bool Type::isObjCObjectOrInterfaceType() const {
+ return isa<ObjCInterfaceType>(CanonicalType) ||
+ isa<ObjCObjectType>(CanonicalType);
+}
+
inline bool Type::isObjCQualifiedIdType() const {
if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>())
return OPT->isObjCQualifiedIdType();
diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h
index 842c06878453..f1c64bd95977 100644
--- a/include/clang/AST/TypeLoc.h
+++ b/include/clang/AST/TypeLoc.h
@@ -341,6 +341,10 @@ private:
template <class Base, class Derived, class TypeClass>
class InheritingConcreteTypeLoc : public Base {
public:
+ static bool classofType(const Type *Ty) {
+ return TypeClass::classof(Ty);
+ }
+
static bool classof(const TypeLoc *TL) {
return Derived::classofType(TL->getTypePtr());
}
diff --git a/include/clang/AST/TypeOrdering.h b/include/clang/AST/TypeOrdering.h
index 1a050d29c860..7cf0d5e999b6 100644
--- a/include/clang/AST/TypeOrdering.h
+++ b/include/clang/AST/TypeOrdering.h
@@ -17,6 +17,7 @@
#define LLVM_CLANG_TYPE_ORDERING_H
#include "clang/AST/Type.h"
+#include "clang/AST/CanonicalType.h"
#include <functional>
namespace clang {
@@ -51,6 +52,26 @@ namespace llvm {
return LHS == RHS;
}
};
+
+ template<> struct DenseMapInfo<clang::CanQualType> {
+ static inline clang::CanQualType getEmptyKey() {
+ return clang::CanQualType();
+ }
+
+ static inline clang::CanQualType getTombstoneKey() {
+ using clang::CanQualType;
+ return CanQualType::getFromOpaquePtr(reinterpret_cast<clang::Type *>(-1));
+ }
+
+ static unsigned getHashValue(clang::CanQualType Val) {
+ return (unsigned)((uintptr_t)Val.getAsOpaquePtr()) ^
+ ((unsigned)((uintptr_t)Val.getAsOpaquePtr() >> 9));
+ }
+
+ static bool isEqual(clang::CanQualType LHS, clang::CanQualType RHS) {
+ return LHS == RHS;
+ }
+ };
}
#endif
diff --git a/include/clang/Analysis/Analyses/FormatString.h b/include/clang/Analysis/Analyses/FormatString.h
new file mode 100644
index 000000000000..280b1260ac26
--- /dev/null
+++ b/include/clang/Analysis/Analyses/FormatString.h
@@ -0,0 +1,595 @@
+//= FormatString.h - Analysis of printf/fprintf format strings --*- 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 APIs for analyzing the format strings of printf, fscanf,
+// and friends.
+//
+// The structure of format strings for fprintf are described in C99 7.19.6.1.
+//
+// The structure of format strings for fscanf are described in C99 7.19.6.2.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FORMAT_H
+#define LLVM_CLANG_FORMAT_H
+
+#include "clang/AST/CanonicalType.h"
+
+namespace clang {
+
+//===----------------------------------------------------------------------===//
+/// Common components of both fprintf and fscanf format strings.
+namespace analyze_format_string {
+
+/// Class representing optional flags with location and representation
+/// information.
+class OptionalFlag {
+public:
+ OptionalFlag(const char *Representation)
+ : representation(Representation), flag(false) {}
+ bool isSet() { return flag; }
+ void set() { flag = true; }
+ void clear() { flag = false; }
+ void setPosition(const char *position) {
+ assert(position);
+ this->position = position;
+ }
+ const char *getPosition() const {
+ assert(position);
+ return position;
+ }
+ const char *toString() const { return representation; }
+
+ // Overloaded operators for bool like qualities
+ operator bool() const { return flag; }
+ OptionalFlag& operator=(const bool &rhs) {
+ flag = rhs;
+ return *this; // Return a reference to myself.
+ }
+private:
+ const char *representation;
+ const char *position;
+ bool flag;
+};
+
+/// Represents the length modifier in a format string in scanf/printf.
+class LengthModifier {
+public:
+ enum Kind {
+ None,
+ AsChar, // 'hh'
+ AsShort, // 'h'
+ AsLong, // 'l'
+ AsLongLong, // 'll', 'q' (BSD, deprecated)
+ AsIntMax, // 'j'
+ AsSizeT, // 'z'
+ AsPtrDiff, // 't'
+ AsLongDouble, // 'L'
+ AsWideChar = AsLong // for '%ls', only makes sense for printf
+ };
+
+ LengthModifier()
+ : Position(0), kind(None) {}
+ LengthModifier(const char *pos, Kind k)
+ : Position(pos), kind(k) {}
+
+ const char *getStart() const {
+ return Position;
+ }
+
+ unsigned getLength() const {
+ switch (kind) {
+ default:
+ return 1;
+ case AsLongLong:
+ case AsChar:
+ return 2;
+ case None:
+ return 0;
+ }
+ }
+
+ Kind getKind() const { return kind; }
+ void setKind(Kind k) { kind = k; }
+
+ const char *toString() const;
+
+private:
+ const char *Position;
+ Kind kind;
+};
+
+class ConversionSpecifier {
+public:
+ enum Kind {
+ InvalidSpecifier = 0,
+ // C99 conversion specifiers.
+ cArg,
+ dArg,
+ iArg,
+ IntArgBeg = cArg, IntArgEnd = iArg,
+
+ oArg,
+ uArg,
+ xArg,
+ XArg,
+ UIntArgBeg = oArg, UIntArgEnd = XArg,
+
+ fArg,
+ FArg,
+ eArg,
+ EArg,
+ gArg,
+ GArg,
+ aArg,
+ AArg,
+ DoubleArgBeg = fArg, DoubleArgEnd = AArg,
+
+ sArg,
+ pArg,
+ nArg,
+ PercentArg,
+ CArg,
+ SArg,
+
+ // ** Printf-specific **
+
+ // Objective-C specific specifiers.
+ ObjCObjArg, // '@'
+ ObjCBeg = ObjCObjArg, ObjCEnd = ObjCObjArg,
+
+ // GlibC specific specifiers.
+ PrintErrno, // 'm'
+
+ PrintfConvBeg = ObjCObjArg, PrintfConvEnd = PrintErrno,
+
+ // ** Scanf-specific **
+ ScanListArg, // '['
+ ScanfConvBeg = ScanListArg, ScanfConvEnd = ScanListArg
+ };
+
+ ConversionSpecifier(bool isPrintf)
+ : IsPrintf(isPrintf), Position(0), EndScanList(0), kind(InvalidSpecifier) {}
+
+ ConversionSpecifier(bool isPrintf, const char *pos, Kind k)
+ : IsPrintf(isPrintf), Position(pos), EndScanList(0), kind(k) {}
+
+ const char *getStart() const {
+ return Position;
+ }
+
+ llvm::StringRef getCharacters() const {
+ return llvm::StringRef(getStart(), getLength());
+ }
+
+ bool consumesDataArgument() const {
+ switch (kind) {
+ case PrintErrno:
+ assert(IsPrintf);
+ case PercentArg:
+ return false;
+ default:
+ return true;
+ }
+ }
+
+ Kind getKind() const { return kind; }
+ void setKind(Kind k) { kind = k; }
+ unsigned getLength() const {
+ return EndScanList ? EndScanList - Position : 1;
+ }
+
+ const char *toString() const;
+
+ bool isPrintfKind() const { return IsPrintf; }
+
+protected:
+ bool IsPrintf;
+ const char *Position;
+ const char *EndScanList;
+ Kind kind;
+};
+
+class ArgTypeResult {
+public:
+ enum Kind { UnknownTy, InvalidTy, SpecificTy, ObjCPointerTy, CPointerTy,
+ CStrTy, WCStrTy, WIntTy };
+private:
+ const Kind K;
+ QualType T;
+ ArgTypeResult(bool) : K(InvalidTy) {}
+public:
+ ArgTypeResult(Kind k = UnknownTy) : K(k) {}
+ ArgTypeResult(QualType t) : K(SpecificTy), T(t) {}
+ ArgTypeResult(CanQualType t) : K(SpecificTy), T(t) {}
+
+ static ArgTypeResult Invalid() { return ArgTypeResult(true); }
+
+ bool isValid() const { return K != InvalidTy; }
+
+ const QualType *getSpecificType() const {
+ return K == SpecificTy ? &T : 0;
+ }
+
+ bool matchesType(ASTContext &C, QualType argTy) const;
+
+ bool matchesAnyObjCObjectRef() const { return K == ObjCPointerTy; }
+
+ QualType getRepresentativeType(ASTContext &C) const;
+};
+
+class OptionalAmount {
+public:
+ enum HowSpecified { NotSpecified, Constant, Arg, Invalid };
+
+ OptionalAmount(HowSpecified howSpecified,
+ unsigned amount,
+ const char *amountStart,
+ unsigned amountLength,
+ bool usesPositionalArg)
+ : start(amountStart), length(amountLength), hs(howSpecified), amt(amount),
+ UsesPositionalArg(usesPositionalArg), UsesDotPrefix(0) {}
+
+ OptionalAmount(bool valid = true)
+ : start(0),length(0), hs(valid ? NotSpecified : Invalid), amt(0),
+ UsesPositionalArg(0), UsesDotPrefix(0) {}
+
+ bool isInvalid() const {
+ return hs == Invalid;
+ }
+
+ HowSpecified getHowSpecified() const { return hs; }
+ void setHowSpecified(HowSpecified h) { hs = h; }
+
+ bool hasDataArgument() const { return hs == Arg; }
+
+ unsigned getArgIndex() const {
+ assert(hasDataArgument());
+ return amt;
+ }
+
+ unsigned getConstantAmount() const {
+ assert(hs == Constant);
+ return amt;
+ }
+
+ const char *getStart() const {
+ // We include the . character if it is given.
+ return start - UsesDotPrefix;
+ }
+
+ unsigned getConstantLength() const {
+ assert(hs == Constant);
+ return length + UsesDotPrefix;
+ }
+
+ ArgTypeResult getArgType(ASTContext &Ctx) const;
+
+ void toString(llvm::raw_ostream &os) const;
+
+ bool usesPositionalArg() const { return (bool) UsesPositionalArg; }
+ unsigned getPositionalArgIndex() const {
+ assert(hasDataArgument());
+ return amt + 1;
+ }
+
+ bool usesDotPrefix() const { return UsesDotPrefix; }
+ void setUsesDotPrefix() { UsesDotPrefix = true; }
+
+private:
+ const char *start;
+ unsigned length;
+ HowSpecified hs;
+ unsigned amt;
+ bool UsesPositionalArg : 1;
+ bool UsesDotPrefix;
+};
+
+
+class FormatSpecifier {
+protected:
+ LengthModifier LM;
+ OptionalAmount FieldWidth;
+ ConversionSpecifier CS;
+ /// Positional arguments, an IEEE extension:
+ /// IEEE Std 1003.1, 2004 Edition
+ /// http://www.opengroup.org/onlinepubs/009695399/functions/printf.html
+ bool UsesPositionalArg;
+ unsigned argIndex;
+public:
+ FormatSpecifier(bool isPrintf)
+ : CS(isPrintf), UsesPositionalArg(false), argIndex(0) {}
+
+ void setLengthModifier(LengthModifier lm) {
+ LM = lm;
+ }
+
+ void setUsesPositionalArg() { UsesPositionalArg = true; }
+
+ void setArgIndex(unsigned i) {
+ argIndex = i;
+ }
+
+ unsigned getArgIndex() const {
+ return argIndex;
+ }
+
+ unsigned getPositionalArgIndex() const {
+ return argIndex + 1;
+ }
+
+ const LengthModifier &getLengthModifier() const {
+ return LM;
+ }
+
+ const OptionalAmount &getFieldWidth() const {
+ return FieldWidth;
+ }
+
+ void setFieldWidth(const OptionalAmount &Amt) {
+ FieldWidth = Amt;
+ }
+
+ bool usesPositionalArg() const { return UsesPositionalArg; }
+
+ bool hasValidLengthModifier() const;
+};
+
+} // end analyze_format_string namespace
+
+//===----------------------------------------------------------------------===//
+/// Pieces specific to fprintf format strings.
+
+namespace analyze_printf {
+
+class PrintfConversionSpecifier :
+ public analyze_format_string::ConversionSpecifier {
+public:
+ PrintfConversionSpecifier()
+ : ConversionSpecifier(true, 0, InvalidSpecifier) {}
+
+ PrintfConversionSpecifier(const char *pos, Kind k)
+ : ConversionSpecifier(true, pos, k) {}
+
+ bool isObjCArg() const { return kind >= ObjCBeg && kind <= ObjCEnd; }
+ bool isIntArg() const { return kind >= IntArgBeg && kind <= IntArgEnd; }
+ bool isUIntArg() const { return kind >= UIntArgBeg && kind <= UIntArgEnd; }
+ bool isDoubleArg() const { return kind >= DoubleArgBeg &&
+ kind <= DoubleArgBeg; }
+ unsigned getLength() const {
+ // Conversion specifiers currently only are represented by
+ // single characters, but we be flexible.
+ return 1;
+ }
+
+ static bool classof(const analyze_format_string::ConversionSpecifier *CS) {
+ return CS->isPrintfKind();
+ }
+};
+
+using analyze_format_string::ArgTypeResult;
+using analyze_format_string::LengthModifier;
+using analyze_format_string::OptionalAmount;
+using analyze_format_string::OptionalFlag;
+
+class PrintfSpecifier : public analyze_format_string::FormatSpecifier {
+ OptionalFlag IsLeftJustified; // '-'
+ OptionalFlag HasPlusPrefix; // '+'
+ OptionalFlag HasSpacePrefix; // ' '
+ OptionalFlag HasAlternativeForm; // '#'
+ OptionalFlag HasLeadingZeroes; // '0'
+ OptionalAmount Precision;
+public:
+ PrintfSpecifier() :
+ FormatSpecifier(/* isPrintf = */ true),
+ IsLeftJustified("-"), HasPlusPrefix("+"), HasSpacePrefix(" "),
+ HasAlternativeForm("#"), HasLeadingZeroes("0") {}
+
+ static PrintfSpecifier Parse(const char *beg, const char *end);
+
+ // Methods for incrementally constructing the PrintfSpecifier.
+ void setConversionSpecifier(const PrintfConversionSpecifier &cs) {
+ CS = cs;
+ }
+ void setIsLeftJustified(const char *position) {
+ IsLeftJustified = true;
+ IsLeftJustified.setPosition(position);
+ }
+ void setHasPlusPrefix(const char *position) {
+ HasPlusPrefix = true;
+ HasPlusPrefix.setPosition(position);
+ }
+ void setHasSpacePrefix(const char *position) {
+ HasSpacePrefix = true;
+ HasSpacePrefix.setPosition(position);
+ }
+ void setHasAlternativeForm(const char *position) {
+ HasAlternativeForm = true;
+ HasAlternativeForm.setPosition(position);
+ }
+ void setHasLeadingZeros(const char *position) {
+ HasLeadingZeroes = true;
+ HasLeadingZeroes.setPosition(position);
+ }
+ void setUsesPositionalArg() { UsesPositionalArg = true; }
+
+ // Methods for querying the format specifier.
+
+ const PrintfConversionSpecifier &getConversionSpecifier() const {
+ return cast<PrintfConversionSpecifier>(CS);
+ }
+
+ void setPrecision(const OptionalAmount &Amt) {
+ Precision = Amt;
+ Precision.setUsesDotPrefix();
+ }
+
+ const OptionalAmount &getPrecision() const {
+ return Precision;
+ }
+
+ bool consumesDataArgument() const {
+ return getConversionSpecifier().consumesDataArgument();
+ }
+
+ /// \brief Returns the builtin type that a data argument
+ /// paired with this format specifier should have. This method
+ /// will return null if the format specifier does not have
+ /// a matching data argument or the matching argument matches
+ /// more than one type.
+ ArgTypeResult getArgType(ASTContext &Ctx) const;
+
+ const OptionalFlag &isLeftJustified() const { return IsLeftJustified; }
+ const OptionalFlag &hasPlusPrefix() const { return HasPlusPrefix; }
+ const OptionalFlag &hasAlternativeForm() const { return HasAlternativeForm; }
+ const OptionalFlag &hasLeadingZeros() const { return HasLeadingZeroes; }
+ const OptionalFlag &hasSpacePrefix() const { return HasSpacePrefix; }
+ bool usesPositionalArg() const { return UsesPositionalArg; }
+
+ /// Changes the specifier and length according to a QualType, retaining any
+ /// flags or options. Returns true on success, or false when a conversion
+ /// was not successful.
+ bool fixType(QualType QT);
+
+ void toString(llvm::raw_ostream &os) const;
+
+ // Validation methods - to check if any element results in undefined behavior
+ bool hasValidPlusPrefix() const;
+ bool hasValidAlternativeForm() const;
+ bool hasValidLeadingZeros() const;
+ bool hasValidSpacePrefix() const;
+ bool hasValidLeftJustified() const;
+
+ bool hasValidPrecision() const;
+ bool hasValidFieldWidth() const;
+};
+} // end analyze_printf namespace
+
+//===----------------------------------------------------------------------===//
+/// Pieces specific to fscanf format strings.
+
+namespace analyze_scanf {
+
+class ScanfConversionSpecifier :
+ public analyze_format_string::ConversionSpecifier {
+public:
+ ScanfConversionSpecifier()
+ : ConversionSpecifier(false, 0, InvalidSpecifier) {}
+
+ ScanfConversionSpecifier(const char *pos, Kind k)
+ : ConversionSpecifier(false, pos, k) {}
+
+ void setEndScanList(const char *pos) { EndScanList = pos; }
+
+ static bool classof(const analyze_format_string::ConversionSpecifier *CS) {
+ return !CS->isPrintfKind();
+ }
+};
+
+using analyze_format_string::LengthModifier;
+using analyze_format_string::OptionalAmount;
+using analyze_format_string::OptionalFlag;
+
+class ScanfSpecifier : public analyze_format_string::FormatSpecifier {
+ OptionalFlag SuppressAssignment; // '*'
+public:
+ ScanfSpecifier() :
+ FormatSpecifier(/* isPrintf = */ false),
+ SuppressAssignment("*") {}
+
+ void setSuppressAssignment(const char *position) {
+ SuppressAssignment = true;
+ SuppressAssignment.setPosition(position);
+ }
+
+ const OptionalFlag &getSuppressAssignment() const {
+ return SuppressAssignment;
+ }
+
+ void setConversionSpecifier(const ScanfConversionSpecifier &cs) {
+ CS = cs;
+ }
+
+ const ScanfConversionSpecifier &getConversionSpecifier() const {
+ return cast<ScanfConversionSpecifier>(CS);
+ }
+
+ bool consumesDataArgument() const {
+ return CS.consumesDataArgument() && !SuppressAssignment;
+ }
+
+ static ScanfSpecifier Parse(const char *beg, const char *end);
+};
+
+} // end analyze_scanf namespace
+
+//===----------------------------------------------------------------------===//
+// Parsing and processing of format strings (both fprintf and fscanf).
+
+namespace analyze_format_string {
+
+enum PositionContext { FieldWidthPos = 0, PrecisionPos = 1 };
+
+class FormatStringHandler {
+public:
+ FormatStringHandler() {}
+ virtual ~FormatStringHandler();
+
+ virtual void HandleNullChar(const char *nullCharacter) {}
+
+ virtual void HandleInvalidPosition(const char *startPos, unsigned posLen,
+ PositionContext p) {}
+
+ virtual void HandleZeroPosition(const char *startPos, unsigned posLen) {}
+
+ virtual void HandleIncompleteSpecifier(const char *startSpecifier,
+ unsigned specifierLen) {}
+
+ // Printf-specific handlers.
+
+ virtual bool HandleInvalidPrintfConversionSpecifier(
+ const analyze_printf::PrintfSpecifier &FS,
+ const char *startSpecifier,
+ unsigned specifierLen) {
+ return true;
+ }
+
+ virtual bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS,
+ const char *startSpecifier,
+ unsigned specifierLen) {
+ return true;
+ }
+
+ // Scanf-specific handlers.
+
+ virtual bool HandleInvalidScanfConversionSpecifier(
+ const analyze_scanf::ScanfSpecifier &FS,
+ const char *startSpecifier,
+ unsigned specifierLen) {
+ return true;
+ }
+
+ virtual bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS,
+ const char *startSpecifier,
+ unsigned specifierLen) {
+ return true;
+ }
+
+ virtual void HandleIncompleteScanList(const char *start, const char *end) {}
+};
+
+bool ParsePrintfString(FormatStringHandler &H,
+ const char *beg, const char *end);
+
+bool ParseScanfString(FormatStringHandler &H,
+ const char *beg, const char *end);
+
+} // end analyze_format_string namespace
+} // end clang namespace
+#endif
diff --git a/include/clang/Analysis/Analyses/LiveVariables.h b/include/clang/Analysis/Analyses/LiveVariables.h
index 44ab080acbf3..237fe14aed4f 100644
--- a/include/clang/Analysis/Analyses/LiveVariables.h
+++ b/include/clang/Analysis/Analyses/LiveVariables.h
@@ -41,8 +41,9 @@ struct LiveVariables_ValueTypes {
ObserverTy* Observer;
ValTy AlwaysLive;
AnalysisContext *AC;
+ bool killAtAssign;
- AnalysisDataTy() : Observer(NULL), AC(NULL) {}
+ AnalysisDataTy() : Observer(NULL), AC(NULL), killAtAssign(true) {}
};
//===-----------------------------------------------------===//
@@ -68,7 +69,7 @@ class LiveVariables : public DataflowValues<LiveVariables_ValueTypes,
public:
typedef LiveVariables_ValueTypes::ObserverTy ObserverTy;
- LiveVariables(AnalysisContext &AC);
+ LiveVariables(AnalysisContext &AC, bool killAtAssign = true);
/// IsLive - Return true if a variable is live at the end of a
/// specified block.
diff --git a/include/clang/Analysis/Analyses/PrintfFormatString.h b/include/clang/Analysis/Analyses/PrintfFormatString.h
deleted file mode 100644
index d907637d39c5..000000000000
--- a/include/clang/Analysis/Analyses/PrintfFormatString.h
+++ /dev/null
@@ -1,445 +0,0 @@
-//==- PrintfFormatStrings.h - Analysis of printf format strings --*- C++ -*-==//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Handling of format string in printf and friends. The structure of format
-// strings for fprintf() are described in C99 7.19.6.1.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_FPRINTF_FORMAT_H
-#define LLVM_CLANG_FPRINTF_FORMAT_H
-
-#include "clang/AST/CanonicalType.h"
-
-namespace clang {
-
-class ASTContext;
-
-namespace analyze_printf {
-
-class ArgTypeResult {
-public:
- enum Kind { UnknownTy, InvalidTy, SpecificTy, ObjCPointerTy, CPointerTy,
- CStrTy, WCStrTy };
-private:
- const Kind K;
- QualType T;
- ArgTypeResult(bool) : K(InvalidTy) {}
-public:
- ArgTypeResult(Kind k = UnknownTy) : K(k) {}
- ArgTypeResult(QualType t) : K(SpecificTy), T(t) {}
- ArgTypeResult(CanQualType t) : K(SpecificTy), T(t) {}
-
- static ArgTypeResult Invalid() { return ArgTypeResult(true); }
-
- bool isValid() const { return K != InvalidTy; }
-
- const QualType *getSpecificType() const {
- return K == SpecificTy ? &T : 0;
- }
-
- bool matchesType(ASTContext &C, QualType argTy) const;
-
- bool matchesAnyObjCObjectRef() const { return K == ObjCPointerTy; }
-
- QualType getRepresentativeType(ASTContext &C) const;
-};
-
-class ConversionSpecifier {
-public:
- enum Kind {
- InvalidSpecifier = 0,
- // C99 conversion specifiers.
- dArg, // 'd'
- IntAsCharArg, // 'c'
- iArg, // 'i',
- oArg, // 'o',
- uArg, // 'u',
- xArg, // 'x',
- XArg, // 'X',
- fArg, // 'f',
- FArg, // 'F',
- eArg, // 'e',
- EArg, // 'E',
- gArg, // 'g',
- GArg, // 'G',
- aArg, // 'a',
- AArg, // 'A',
- CStrArg, // 's'
- VoidPtrArg, // 'p'
- OutIntPtrArg, // 'n'
- PercentArg, // '%'
- // MacOS X unicode extensions.
- CArg, // 'C'
- UnicodeStrArg, // 'S'
- // Objective-C specific specifiers.
- ObjCObjArg, // '@'
- // GlibC specific specifiers.
- PrintErrno, // 'm'
- // Specifier ranges.
- IntArgBeg = dArg,
- IntArgEnd = iArg,
- UIntArgBeg = oArg,
- UIntArgEnd = XArg,
- DoubleArgBeg = fArg,
- DoubleArgEnd = AArg,
- C99Beg = IntArgBeg,
- C99End = DoubleArgEnd,
- ObjCBeg = ObjCObjArg,
- ObjCEnd = ObjCObjArg
- };
-
- ConversionSpecifier()
- : Position(0), kind(InvalidSpecifier) {}
-
- ConversionSpecifier(const char *pos, Kind k)
- : Position(pos), kind(k) {}
-
- const char *getStart() const {
- return Position;
- }
-
- llvm::StringRef getCharacters() const {
- return llvm::StringRef(getStart(), getLength());
- }
-
- bool consumesDataArgument() const {
- switch (kind) {
- case PercentArg:
- case PrintErrno:
- return false;
- default:
- return true;
- }
- }
-
- bool isObjCArg() const { return kind >= ObjCBeg && kind <= ObjCEnd; }
- bool isIntArg() const { return kind >= dArg && kind <= iArg; }
- bool isUIntArg() const { return kind >= oArg && kind <= XArg; }
- bool isDoubleArg() const { return kind >= fArg && kind <= AArg; }
- Kind getKind() const { return kind; }
- void setKind(Kind k) { kind = k; }
- unsigned getLength() const {
- // Conversion specifiers currently only are represented by
- // single characters, but we be flexible.
- return 1;
- }
- const char *toString() const;
-
-private:
- const char *Position;
- Kind kind;
-};
-
-class LengthModifier {
-public:
- enum Kind {
- None,
- AsChar, // 'hh'
- AsShort, // 'h'
- AsLong, // 'l'
- AsLongLong, // 'll', 'q' (BSD, deprecated)
- AsIntMax, // 'j'
- AsSizeT, // 'z'
- AsPtrDiff, // 't'
- AsLongDouble, // 'L'
- AsWideChar = AsLong // for '%ls'
- };
-
- LengthModifier()
- : Position(0), kind(None) {}
- LengthModifier(const char *pos, Kind k)
- : Position(pos), kind(k) {}
-
- const char *getStart() const {
- return Position;
- }
-
- unsigned getLength() const {
- switch (kind) {
- default:
- return 1;
- case AsLongLong:
- case AsChar:
- return 2;
- case None:
- return 0;
- }
- }
-
- Kind getKind() const { return kind; }
- void setKind(Kind k) { kind = k; }
-
- const char *toString() const;
-
-private:
- const char *Position;
- Kind kind;
-};
-
-class OptionalAmount {
-public:
- enum HowSpecified { NotSpecified, Constant, Arg, Invalid };
-
- OptionalAmount(HowSpecified howSpecified,
- unsigned amount,
- const char *amountStart,
- unsigned amountLength,
- bool usesPositionalArg)
- : start(amountStart), length(amountLength), hs(howSpecified), amt(amount),
- UsesPositionalArg(usesPositionalArg), UsesDotPrefix(0) {}
-
- OptionalAmount(bool valid = true)
- : start(0),length(0), hs(valid ? NotSpecified : Invalid), amt(0),
- UsesPositionalArg(0), UsesDotPrefix(0) {}
-
- bool isInvalid() const {
- return hs == Invalid;
- }
-
- HowSpecified getHowSpecified() const { return hs; }
- void setHowSpecified(HowSpecified h) { hs = h; }
-
- bool hasDataArgument() const { return hs == Arg; }
-
- unsigned getArgIndex() const {
- assert(hasDataArgument());
- return amt;
- }
-
- unsigned getConstantAmount() const {
- assert(hs == Constant);
- return amt;
- }
-
- const char *getStart() const {
- // We include the . character if it is given.
- return start - UsesDotPrefix;
- }
-
- unsigned getConstantLength() const {
- assert(hs == Constant);
- return length + UsesDotPrefix;
- }
-
- ArgTypeResult getArgType(ASTContext &Ctx) const;
-
- void toString(llvm::raw_ostream &os) const;
-
- bool usesPositionalArg() const { return (bool) UsesPositionalArg; }
- unsigned getPositionalArgIndex() const {
- assert(hasDataArgument());
- return amt + 1;
- }
-
- bool usesDotPrefix() const { return UsesDotPrefix; }
- void setUsesDotPrefix() { UsesDotPrefix = true; }
-
-private:
- const char *start;
- unsigned length;
- HowSpecified hs;
- unsigned amt;
- bool UsesPositionalArg : 1;
- bool UsesDotPrefix;
-};
-
-// Class representing optional flags with location and representation
-// information.
-class OptionalFlag {
-public:
- OptionalFlag(const char *Representation)
- : representation(Representation), flag(false) {}
- bool isSet() { return flag; }
- void set() { flag = true; }
- void clear() { flag = false; }
- void setPosition(const char *position) {
- assert(position);
- this->position = position;
- }
- const char *getPosition() const {
- assert(position);
- return position;
- }
- const char *toString() const { return representation; }
-
- // Overloaded operators for bool like qualities
- operator bool() const { return flag; }
- OptionalFlag& operator=(const bool &rhs) {
- flag = rhs;
- return *this; // Return a reference to myself.
- }
-private:
- const char *representation;
- const char *position;
- bool flag;
-};
-
-class FormatSpecifier {
- LengthModifier LM;
- OptionalFlag IsLeftJustified; // '-'
- OptionalFlag HasPlusPrefix; // '+'
- OptionalFlag HasSpacePrefix; // ' '
- OptionalFlag HasAlternativeForm; // '#'
- OptionalFlag HasLeadingZeroes; // '0'
- /// Positional arguments, an IEEE extension:
- /// IEEE Std 1003.1, 2004 Edition
- /// http://www.opengroup.org/onlinepubs/009695399/functions/printf.html
- bool UsesPositionalArg;
- unsigned argIndex;
- ConversionSpecifier CS;
- OptionalAmount FieldWidth;
- OptionalAmount Precision;
-public:
- FormatSpecifier() :
- IsLeftJustified("-"), HasPlusPrefix("+"), HasSpacePrefix(" "),
- HasAlternativeForm("#"), HasLeadingZeroes("0"), UsesPositionalArg(false),
- argIndex(0) {}
-
- static FormatSpecifier Parse(const char *beg, const char *end);
-
- // Methods for incrementally constructing the FormatSpecifier.
- void setConversionSpecifier(const ConversionSpecifier &cs) {
- CS = cs;
- }
- void setLengthModifier(LengthModifier lm) {
- LM = lm;
- }
- void setIsLeftJustified(const char *position) {
- IsLeftJustified = true;
- IsLeftJustified.setPosition(position);
- }
- void setHasPlusPrefix(const char *position) {
- HasPlusPrefix = true;
- HasPlusPrefix.setPosition(position);
- }
- void setHasSpacePrefix(const char *position) {
- HasSpacePrefix = true;
- HasSpacePrefix.setPosition(position);
- }
- void setHasAlternativeForm(const char *position) {
- HasAlternativeForm = true;
- HasAlternativeForm.setPosition(position);
- }
- void setHasLeadingZeros(const char *position) {
- HasLeadingZeroes = true;
- HasLeadingZeroes.setPosition(position);
- }
- void setUsesPositionalArg() { UsesPositionalArg = true; }
-
- void setArgIndex(unsigned i) {
- assert(CS.consumesDataArgument());
- argIndex = i;
- }
-
- unsigned getArgIndex() const {
- assert(CS.consumesDataArgument());
- return argIndex;
- }
-
- unsigned getPositionalArgIndex() const {
- assert(CS.consumesDataArgument());
- return argIndex + 1;
- }
-
- // Methods for querying the format specifier.
-
- const ConversionSpecifier &getConversionSpecifier() const {
- return CS;
- }
-
- const LengthModifier &getLengthModifier() const {
- return LM;
- }
-
- const OptionalAmount &getFieldWidth() const {
- return FieldWidth;
- }
-
- void setFieldWidth(const OptionalAmount &Amt) {
- FieldWidth = Amt;
- }
-
- void setPrecision(const OptionalAmount &Amt) {
- Precision = Amt;
- Precision.setUsesDotPrefix();
- }
-
- const OptionalAmount &getPrecision() const {
- return Precision;
- }
-
- /// \brief Returns the builtin type that a data argument
- /// paired with this format specifier should have. This method
- /// will return null if the format specifier does not have
- /// a matching data argument or the matching argument matches
- /// more than one type.
- ArgTypeResult getArgType(ASTContext &Ctx) const;
-
- const OptionalFlag &isLeftJustified() const { return IsLeftJustified; }
- const OptionalFlag &hasPlusPrefix() const { return HasPlusPrefix; }
- const OptionalFlag &hasAlternativeForm() const { return HasAlternativeForm; }
- const OptionalFlag &hasLeadingZeros() const { return HasLeadingZeroes; }
- const OptionalFlag &hasSpacePrefix() const { return HasSpacePrefix; }
- bool usesPositionalArg() const { return UsesPositionalArg; }
-
- /// Changes the specifier and length according to a QualType, retaining any
- /// flags or options. Returns true on success, or false when a conversion
- /// was not successful.
- bool fixType(QualType QT);
-
- void toString(llvm::raw_ostream &os) const;
-
- // Validation methods - to check if any element results in undefined behavior
- bool hasValidPlusPrefix() const;
- bool hasValidAlternativeForm() const;
- bool hasValidLeadingZeros() const;
- bool hasValidSpacePrefix() const;
- bool hasValidLeftJustified() const;
-
- bool hasValidLengthModifier() const;
- bool hasValidPrecision() const;
- bool hasValidFieldWidth() const;
-};
-
-enum PositionContext { FieldWidthPos = 0, PrecisionPos = 1 };
-
-class FormatStringHandler {
-public:
- FormatStringHandler() {}
- virtual ~FormatStringHandler();
-
- virtual void HandleIncompleteFormatSpecifier(const char *startSpecifier,
- unsigned specifierLen) {}
-
- virtual void HandleNullChar(const char *nullCharacter) {}
-
- virtual void HandleInvalidPosition(const char *startPos, unsigned posLen,
- PositionContext p) {}
-
- virtual void HandleZeroPosition(const char *startPos, unsigned posLen) {}
-
- virtual bool
- HandleInvalidConversionSpecifier(const analyze_printf::FormatSpecifier &FS,
- const char *startSpecifier,
- unsigned specifierLen) { return true; }
-
- virtual bool HandleFormatSpecifier(const analyze_printf::FormatSpecifier &FS,
- const char *startSpecifier,
- unsigned specifierLen) {
- return true;
- }
-};
-
-bool ParseFormatString(FormatStringHandler &H,
- const char *beg, const char *end);
-
-} // end printf namespace
-} // end clang namespace
-#endif
diff --git a/include/clang/Analysis/Analyses/PseudoConstantAnalysis.h b/include/clang/Analysis/Analyses/PseudoConstantAnalysis.h
new file mode 100644
index 000000000000..cb73850b08c7
--- /dev/null
+++ b/include/clang/Analysis/Analyses/PseudoConstantAnalysis.h
@@ -0,0 +1,45 @@
+//== PseudoConstantAnalysis.h - Find Pseudo-constants in the AST -*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file tracks the usage of variables in a Decl body to see if they are
+// never written to, implying that they constant. This is useful in static
+// analysis to see if a developer might have intended a variable to be const.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_PSEUDOCONSTANTANALYSIS
+#define LLVM_CLANG_ANALYSIS_PSEUDOCONSTANTANALYSIS
+
+#include "clang/AST/Stmt.h"
+
+namespace clang {
+
+class PseudoConstantAnalysis {
+public:
+ PseudoConstantAnalysis(const Stmt *DeclBody);
+ ~PseudoConstantAnalysis();
+
+ bool isPseudoConstant(const VarDecl *VD);
+ bool wasReferenced(const VarDecl *VD);
+
+private:
+ void RunAnalysis();
+ inline static const Decl *getDecl(const Expr *E);
+
+ // for storing the result of analyzed ValueDecls
+ void *NonConstantsImpl;
+ void *UsedVarsImpl;
+
+ const Stmt *DeclBody;
+ bool Analyzed;
+};
+
+}
+
+#endif
diff --git a/include/clang/Analysis/AnalysisContext.h b/include/clang/Analysis/AnalysisContext.h
index 9ebd93b75b38..7d4d25f8b0d8 100644
--- a/include/clang/Analysis/AnalysisContext.h
+++ b/include/clang/Analysis/AnalysisContext.h
@@ -30,41 +30,67 @@ class CFG;
class CFGBlock;
class LiveVariables;
class ParentMap;
+class PseudoConstantAnalysis;
class ImplicitParamDecl;
class LocationContextManager;
class StackFrameContext;
+namespace idx { class TranslationUnit; }
+
/// AnalysisContext contains the context data for the function or method under
/// analysis.
class AnalysisContext {
const Decl *D;
+ // TranslationUnit is NULL if we don't have multiple translation units.
+ idx::TranslationUnit *TU;
+
// AnalysisContext owns the following data.
- CFG *cfg;
- bool builtCFG;
+ CFG *cfg, *completeCFG;
+ bool builtCFG, builtCompleteCFG;
LiveVariables *liveness;
+ LiveVariables *relaxedLiveness;
ParentMap *PM;
+ PseudoConstantAnalysis *PCA;
llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
llvm::BumpPtrAllocator A;
+ bool UseUnoptimizedCFG;
bool AddEHEdges;
public:
- AnalysisContext(const Decl *d, bool addehedges = false)
- : D(d), cfg(0), builtCFG(false), liveness(0), PM(0),
- ReferencedBlockVars(0), AddEHEdges(addehedges) {}
+ AnalysisContext(const Decl *d, idx::TranslationUnit *tu,
+ bool useUnoptimizedCFG = false,
+ bool addehedges = false)
+ : D(d), TU(tu), cfg(0), completeCFG(0),
+ builtCFG(false), builtCompleteCFG(false),
+ liveness(0), relaxedLiveness(0), PM(0), PCA(0),
+ ReferencedBlockVars(0), UseUnoptimizedCFG(useUnoptimizedCFG),
+ AddEHEdges(addehedges) {}
~AnalysisContext();
ASTContext &getASTContext() { return D->getASTContext(); }
- const Decl *getDecl() { return D; }
+ const Decl *getDecl() const { return D; }
+
+ idx::TranslationUnit *getTranslationUnit() const { return TU; }
+
/// getAddEHEdges - Return true iff we are adding exceptional edges from
/// callExprs. If this is false, then try/catch statements and blocks
/// reachable from them can appear to be dead in the CFG, analysis passes must
/// cope with that.
bool getAddEHEdges() const { return AddEHEdges; }
+
+ bool getUseUnoptimizedCFG() const { return UseUnoptimizedCFG; }
+
Stmt *getBody();
CFG *getCFG();
+
+ /// Return a version of the CFG without any edges pruned.
+ CFG *getUnoptimizedCFG();
+
ParentMap &getParentMap();
+ PseudoConstantAnalysis *getPseudoConstantAnalysis();
LiveVariables *getLiveVariables();
+ LiveVariables *getRelaxedLiveVariables();
typedef const VarDecl * const * referenced_decls_iterator;
@@ -79,10 +105,16 @@ public:
class AnalysisContextManager {
typedef llvm::DenseMap<const Decl*, AnalysisContext*> ContextMap;
ContextMap Contexts;
+ bool UseUnoptimizedCFG;
public:
+ AnalysisContextManager(bool useUnoptimizedCFG = false)
+ : UseUnoptimizedCFG(useUnoptimizedCFG) {}
+
~AnalysisContextManager();
- AnalysisContext *getContext(const Decl *D);
+ AnalysisContext *getContext(const Decl *D, idx::TranslationUnit *TU = 0);
+
+ bool getUseUnoptimizedCFG() const { return UseUnoptimizedCFG; }
// Discard all previously created AnalysisContexts.
void clear();
@@ -94,7 +126,10 @@ public:
private:
ContextKind Kind;
+
+ // AnalysisContext can't be const since some methods may modify its member.
AnalysisContext *Ctx;
+
const LocationContext *Parent;
protected:
@@ -109,6 +144,10 @@ public:
AnalysisContext *getAnalysisContext() const { return Ctx; }
+ idx::TranslationUnit *getTranslationUnit() const {
+ return Ctx->getTranslationUnit();
+ }
+
const LocationContext *getParent() const { return Parent; }
bool isParentOf(const LocationContext *LC) const;
diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h
index b7256c9dc3db..b7a8e1159693 100644
--- a/include/clang/Analysis/CFG.h
+++ b/include/clang/Analysis/CFG.h
@@ -35,22 +35,6 @@ namespace clang {
class LangOptions;
class ASTContext;
-namespace {
-// An element of the CFG for implicit descructor calls implied by the language
-// rules.
-class Dtor {
- // Statement that introduces the variable.
- Stmt *S;
- // A token which ends the scope, return, goto, throw, }.
- SourceLocation Loc;
-public:
- Dtor(Stmt *s, SourceLocation l) : S(s), Loc(l) {
- }
- SourceLocation getLoc() { return Loc; }
- Stmt *getStmt() { return S; }
-};
-}
-
/// CFGElement - Represents a top-level expression in a basic block.
class CFGElement {
llvm::PointerIntPair<Stmt *, 2> Data;
@@ -59,7 +43,6 @@ public:
explicit CFGElement() {}
CFGElement(Stmt *S, bool lvalue) : Data(S, lvalue ? 1 : 0) {}
CFGElement(Stmt *S, Type t) : Data(S, t == StartScope ? 2 : 3) {}
- // CFGElement(Dtor *S, Type t) : Data(reinterpret_cast<Stmt*>(S), 4) {}
Stmt *getStmt() const { return Data.getPointer(); }
bool asLValue() const { return Data.getInt() == 1; }
bool asStartScope() const { return Data.getInt() == 2; }
@@ -67,7 +50,6 @@ public:
bool asDtor() const { return Data.getInt() == 4; }
operator Stmt*() const { return getStmt(); }
operator bool() const { return getStmt() != 0; }
- operator Dtor*() const { return reinterpret_cast<Dtor*>(getStmt()); }
};
/// CFGBlock - Represents a single basic block in a source-level CFG.
@@ -285,6 +267,7 @@ public:
/// buildCFG - Builds a CFG from an AST. The responsibility to free the
/// constructed CFG belongs to the caller.
static CFG* buildCFG(const Decl *D, Stmt* AST, ASTContext *C,
+ bool pruneTriviallyFalseEdges = true,
bool AddEHEdges = false,
bool AddScopes = false /* NOT FULLY IMPLEMENTED.
NOT READY FOR GENERAL USE. */);
diff --git a/include/clang/Analysis/CFGStmtMap.h b/include/clang/Analysis/CFGStmtMap.h
new file mode 100644
index 000000000000..6e8e140afb23
--- /dev/null
+++ b/include/clang/Analysis/CFGStmtMap.h
@@ -0,0 +1,52 @@
+//===--- CFGStmtMap.h - Map from Stmt* to CFGBlock* -----------*- 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 the CFGStmtMap class, which defines a mapping from
+// Stmt* to CFGBlock*
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CFGSTMTMAP_H
+#define LLVM_CLANG_CFGSTMTMAP_H
+
+#include "clang/Analysis/CFG.h"
+
+namespace clang {
+
+class CFG;
+class CFGBlock;
+class ParentMap;
+class Stmt;
+
+class CFGStmtMap {
+ ParentMap *PM;
+ void *M;
+
+ CFGStmtMap(ParentMap *pm, void *m) : PM(pm), M(m) {}
+
+public:
+ ~CFGStmtMap();
+
+ /// Returns a new CFGMap for the given CFG. It is the caller's
+ /// responsibility to 'delete' this object when done using it.
+ static CFGStmtMap *Build(CFG* C, ParentMap *PM);
+
+ /// Returns the CFGBlock the specified Stmt* appears in. For Stmt* that
+ /// are terminators, the CFGBlock is the block they appear as a terminator,
+ /// and not the block they appear as a block-level expression (e.g, '&&').
+ /// CaseStmts and LabelStmts map to the CFGBlock they label.
+ CFGBlock *getBlock(Stmt * S);
+
+ const CFGBlock *getBlock(const Stmt * S) const {
+ return const_cast<CFGStmtMap*>(this)->getBlock(const_cast<Stmt*>(S));
+ }
+};
+
+} // end clang namespace
+#endif
diff --git a/include/clang/Analysis/FlowSensitive/DataflowSolver.h b/include/clang/Analysis/FlowSensitive/DataflowSolver.h
index 3c762011a657..9375db06be72 100644
--- a/include/clang/Analysis/FlowSensitive/DataflowSolver.h
+++ b/include/clang/Analysis/FlowSensitive/DataflowSolver.h
@@ -231,7 +231,7 @@ private:
EdgeDataMapTy& M = D.getEdgeDataMap();
bool firstMerge = true;
-
+ bool noEdges = true;
for (PrevBItr I=ItrTraits::PrevBegin(B),E=ItrTraits::PrevEnd(B); I!=E; ++I){
CFGBlock *PrevBlk = *I;
@@ -243,6 +243,7 @@ private:
M.find(ItrTraits::PrevEdge(B, PrevBlk));
if (EI != M.end()) {
+ noEdges = false;
if (firstMerge) {
firstMerge = false;
V.copyValues(EI->second);
@@ -252,8 +253,20 @@ private:
}
}
+ bool isInitialized = true;
+ typename BlockDataMapTy::iterator BI = D.getBlockDataMap().find(B);
+ if(BI == D.getBlockDataMap().end()) {
+ isInitialized = false;
+ BI = D.getBlockDataMap().insert( std::make_pair(B,ValTy()) ).first;
+ }
+ // If no edges have been found, it means this is the first time the solver
+ // has been called on block B, we copy the initialization values (if any)
+ // as current value for V (which will be used as edge data)
+ if(noEdges && isInitialized)
+ Merge(V, BI->second);
+
// Set the data for the block.
- D.getBlockDataMap()[B].copyValues(V);
+ BI->second.copyValues(V);
}
/// ProcessBlock - Process the transfer functions for a given block.
diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h
index 075838d45e5c..ba303de7a8da 100644
--- a/include/clang/Analysis/ProgramPoint.h
+++ b/include/clang/Analysis/ProgramPoint.h
@@ -15,6 +15,7 @@
#ifndef LLVM_CLANG_ANALYSIS_PROGRAM_POINT
#define LLVM_CLANG_ANALYSIS_PROGRAM_POINT
+#include "clang/Analysis/AnalysisContext.h"
#include "clang/Analysis/CFG.h"
#include "llvm/System/DataTypes.h"
#include "llvm/ADT/DenseMap.h"
@@ -26,6 +27,7 @@
namespace clang {
class LocationContext;
+class AnalysisContext;
class FunctionDecl;
class ProgramPoint {
@@ -45,7 +47,7 @@ public:
CallEnterKind,
CallExitKind,
MinPostStmtKind = PostStmtKind,
- MaxPostStmtKind = PostLValueKind };
+ MaxPostStmtKind = CallExitKind };
private:
std::pair<const void *, const void *> Data;
@@ -107,16 +109,16 @@ public:
const void *tag = 0)
: ProgramPoint(B, BlockEntranceKind, L, tag) {}
- CFGBlock* getBlock() const {
- return const_cast<CFGBlock*>(reinterpret_cast<const CFGBlock*>(getData1()));
+ const CFGBlock* getBlock() const {
+ return reinterpret_cast<const CFGBlock*>(getData1());
}
- CFGElement getFirstElement() const {
+ const CFGElement getFirstElement() const {
const CFGBlock* B = getBlock();
return B->empty() ? CFGElement() : B->front();
}
- Stmt *getFirstStmt() const {
+ const Stmt *getFirstStmt() const {
return getFirstElement().getStmt();
}
@@ -130,16 +132,16 @@ public:
BlockExit(const CFGBlock* B, const LocationContext *L)
: ProgramPoint(B, BlockExitKind, L) {}
- CFGBlock* getBlock() const {
- return const_cast<CFGBlock*>(reinterpret_cast<const CFGBlock*>(getData1()));
+ const CFGBlock* getBlock() const {
+ return reinterpret_cast<const CFGBlock*>(getData1());
}
- Stmt* getLastStmt() const {
+ const Stmt* getLastStmt() const {
const CFGBlock* B = getBlock();
return B->empty() ? CFGElement() : B->back();
}
- Stmt* getTerminator() const {
+ const Stmt* getTerminator() const {
return getBlock()->getTerminator();
}
@@ -298,12 +300,12 @@ public:
BlockEdge(const CFGBlock* B1, const CFGBlock* B2, const LocationContext *L)
: ProgramPoint(B1, B2, BlockEdgeKind, L) {}
- CFGBlock* getSrc() const {
- return const_cast<CFGBlock*>(static_cast<const CFGBlock*>(getData1()));
+ const CFGBlock* getSrc() const {
+ return static_cast<const CFGBlock*>(getData1());
}
- CFGBlock* getDst() const {
- return const_cast<CFGBlock*>(static_cast<const CFGBlock*>(getData2()));
+ const CFGBlock* getDst() const {
+ return static_cast<const CFGBlock*>(getData2());
}
static bool classof(const ProgramPoint* Location) {
@@ -313,16 +315,17 @@ public:
class CallEnter : public StmtPoint {
public:
- // CallEnter uses the caller's location context.
- CallEnter(const Stmt *S, const FunctionDecl *fd, const LocationContext *L)
- : StmtPoint(S, fd, CallEnterKind, L, 0) {}
+ // L is caller's location context. AC is callee's AnalysisContext.
+ CallEnter(const Stmt *S, const AnalysisContext *AC, const LocationContext *L)
+ : StmtPoint(S, AC, CallEnterKind, L, 0) {}
const Stmt *getCallExpr() const {
return static_cast<const Stmt *>(getData1());
}
- const FunctionDecl *getCallee() const {
- return static_cast<const FunctionDecl *>(getData2());
+ AnalysisContext *getCalleeContext() const {
+ return const_cast<AnalysisContext *>(
+ static_cast<const AnalysisContext *>(getData2()));
}
static bool classof(const ProgramPoint *Location) {
diff --git a/include/clang/Analysis/Visitors/CFGStmtVisitor.h b/include/clang/Analysis/Visitors/CFGStmtVisitor.h
index 8a85ec15cdce..6421f185ff7f 100644
--- a/include/clang/Analysis/Visitors/CFGStmtVisitor.h
+++ b/include/clang/Analysis/Visitors/CFGStmtVisitor.h
@@ -86,7 +86,7 @@ public:
BinaryOperator* B = cast<BinaryOperator>(S);
if (B->isLogicalOp())
return static_cast<ImplClass*>(this)->BlockStmt_VisitLogicalOp(B);
- else if (B->getOpcode() == BinaryOperator::Comma)
+ else if (B->getOpcode() == BO_Comma)
return static_cast<ImplClass*>(this)->BlockStmt_VisitComma(B);
// Fall through.
}
@@ -149,7 +149,7 @@ public:
case Stmt::BinaryOperatorClass: {
BinaryOperator* B = cast<BinaryOperator>(S);
- if (B->getOpcode() != BinaryOperator::Comma) break;
+ if (B->getOpcode() != BO_Comma) break;
static_cast<ImplClass*>(this)->Visit(B->getRHS());
return;
}
diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td
index 98871d26204f..2f2267f7f79f 100644
--- a/include/clang/Basic/Attr.td
+++ b/include/clang/Basic/Attr.td
@@ -33,8 +33,8 @@ class SubsetSubject<AttrSubject base, string description, code check>
// a possible subject.
def NormalVar : SubsetSubject<Var, "non-register, non-parameter variable",
[{S->getStorageClass() != VarDecl::Register &&
- S->getKind() != Decl::ImplicitParam
- S->getKind() != Decl::ParmVar
+ S->getKind() != Decl::ImplicitParam &&
+ S->getKind() != Decl::ParmVar &&
S->getKind() != Decl::NonTypeTemplateParm}]>;
def CXXVirtualMethod : SubsetSubject<CXXRecord, "virtual member function",
[{S->isVirtual()}]>;
@@ -51,18 +51,27 @@ class IntArgument<string name> : Argument<name>;
class StringArgument<string name> : Argument<name>;
class ExprArgument<string name> : Argument<name>;
class FunctionArgument<string name> : Argument<name>;
-class ObjCInterfaceArgument<string name> : Argument<name>;
-class UnsignedIntArgument<string name> : Argument<name>;
-class UnsignedIntOrTypeArgument<string name> : Argument<name>;
+class TypeArgument<string name> : Argument<name>;
+class UnsignedArgument<string name> : Argument<name>;
+class VariadicUnsignedArgument<string name> : Argument<name>;
+
+// This one's a doozy, so it gets its own special type
+// It can be an unsigned integer, or a type. Either can
+// be dependent.
+class AlignedArgument<string name> : Argument<name>;
// An integer argument with a default value
class DefaultIntArgument<string name, int default> : IntArgument<name> {
int Default = default;
}
-// Zero or more arguments of a type
-class VariadicArgument<Argument arg> : Argument<arg.Name> {
- Argument VariadicArg = arg;
+// This argument is more complex, it includes the enumerator type name,
+// a list of strings to accept, and a list of enumerators to map them to.
+class EnumArgument<string name, string type, list<string> values,
+ list<string> enums> : Argument<name> {
+ string Type = type;
+ list<string> Values = values;
+ list<string> Enums = enums;
}
class Attr {
@@ -76,9 +85,8 @@ class Attr {
// The attribute will not be permitted in C++0x attribute-specifiers if
// this is empty; the empty string can be used as a namespace.
list<string> Namespaces = [];
- // A temporary development bit to tell TableGen not to emit certain
- // information about the attribute.
- bit DoNotEmit = 1;
+ // Any additional text that should be included verbatim in the class.
+ code AdditionalMembers = [{}];
}
//
@@ -87,13 +95,13 @@ class Attr {
def Alias : Attr {
let Spellings = ["alias"];
- let Args = [StringArgument<"AliasName">];
+ let Args = [StringArgument<"Aliasee">];
}
def Aligned : Attr {
let Spellings = ["align", "aligned"];
let Subjects = [NonBitField, NormalVar, Tag];
- let Args = [UnsignedIntOrTypeArgument<"Alignment">];
+ let Args = [AlignedArgument<"Alignment">];
let Namespaces = ["", "std"];
}
@@ -123,19 +131,17 @@ def BaseCheck : Attr {
let Spellings = ["base_check"];
let Subjects = [CXXRecord];
let Namespaces = ["", "std"];
- let DoNotEmit = 0;
}
def Blocks : Attr {
let Spellings = ["blocks"];
- let Args = [IdentifierArgument<"Type">];
+ let Args = [EnumArgument<"Type", "BlockType", ["byref"], ["ByRef"]>];
}
def CarriesDependency : Attr {
let Spellings = ["carries_dependency"];
let Subjects = [ParmVar, Function];
let Namespaces = ["", "std"];
- let DoNotEmit = 0;
}
def CDecl : Attr {
@@ -189,7 +195,6 @@ def Final : Attr {
let Spellings = ["final"];
let Subjects = [CXXRecord, CXXVirtualMethod];
let Namespaces = ["", "std"];
- let DoNotEmit = 0;
}
def Format : Attr {
@@ -211,7 +216,6 @@ def Hiding : Attr {
let Spellings = ["hiding"];
let Subjects = [Field, CXXMethod];
let Namespaces = ["", "std"];
- let DoNotEmit = 0;
}
def IBAction : Attr {
@@ -224,7 +228,7 @@ def IBOutlet : Attr {
def IBOutletCollection : Attr {
let Spellings = ["iboutletcollection"];
- let Args = [ObjCInterfaceArgument<"Class">];
+ let Args = [TypeArgument<"Interface">];
}
def Malloc : Attr {
@@ -233,12 +237,12 @@ def Malloc : Attr {
def MaxFieldAlignment : Attr {
let Spellings = [];
- let Args = [UnsignedIntArgument<"Alignment">];
+ let Args = [UnsignedArgument<"Alignment">];
}
def MSP430Interrupt : Attr {
let Spellings = [];
- let Args = [UnsignedIntArgument<"Number">];
+ let Args = [UnsignedArgument<"Number">];
}
def NoDebug : Attr {
@@ -251,7 +255,15 @@ def NoInline : Attr {
def NonNull : Attr {
let Spellings = ["nonnull"];
- let Args = [VariadicArgument<UnsignedIntArgument<"Args">>];
+ let Args = [VariadicUnsignedArgument<"Args">];
+ let AdditionalMembers =
+[{bool isNonNull(unsigned idx) const {
+ for (args_iterator i = args_begin(), e = args_end();
+ i != e; ++i)
+ if (*i == idx)
+ return true;
+ return false;
+ } }];
}
def NoReturn : Attr {
@@ -290,13 +302,20 @@ def Override : Attr {
let Spellings = ["override"];
let Subjects = [CXXVirtualMethod];
let Namespaces = ["", "std"];
- let DoNotEmit = 0;
}
def Overloadable : Attr {
let Spellings = ["overloadable"];
}
+def Ownership : Attr {
+ let Spellings = ["ownership_holds", "ownership_returns", "ownership_takes"];
+ let Args = [EnumArgument<"OwnKind", "OwnershipKind",
+ ["ownership_holds", "ownership_returns", "ownership_takes"],
+ ["Holds", "Returns", "Takes"]>,
+ StringArgument<"Module">, VariadicUnsignedArgument<"Args">];
+}
+
def Packed : Attr {
let Spellings = ["packed"];
}
@@ -307,18 +326,18 @@ def Pure : Attr {
def Regparm : Attr {
let Spellings = ["regparm"];
- let Args = [UnsignedIntArgument<"NumParams">];
+ let Args = [UnsignedArgument<"NumParams">];
}
def ReqdWorkGroupSize : Attr {
let Spellings = ["reqd_work_group_size"];
- let Args = [UnsignedIntArgument<"XDim">, UnsignedIntArgument<"YDim">,
- UnsignedIntArgument<"ZDim">];
+ let Args = [UnsignedArgument<"XDim">, UnsignedArgument<"YDim">,
+ UnsignedArgument<"ZDim">];
}
def InitPriority : Attr {
let Spellings = ["init_priority"];
- let Args = [UnsignedIntArgument<"Priority">];
+ let Args = [UnsignedArgument<"Priority">];
}
def Section : Attr {
@@ -328,8 +347,8 @@ def Section : Attr {
def Sentinel : Attr {
let Spellings = ["sentinel"];
- let Args = [DefaultIntArgument<"NulPos", 0>,
- DefaultIntArgument<"Sentinel", 0>];
+ let Args = [DefaultIntArgument<"Sentinel", 0>,
+ DefaultIntArgument<"NullPos", 0>];
}
def StdCall : Attr {
@@ -340,6 +359,10 @@ def ThisCall : Attr {
let Spellings = ["thiscall", "__thiscall"];
}
+def Pascal : Attr {
+ let Spellings = ["pascal", "__pascal"];
+}
+
def TransparentUnion : Attr {
let Spellings = ["transparent_union"];
}
@@ -358,7 +381,14 @@ def Used : Attr {
def Visibility : Attr {
let Spellings = ["visibility"];
- let Args = [StringArgument<"Visibility">];
+ let Args = [EnumArgument<"Visibility", "VisibilityType",
+ ["default", "hidden", "internal", "protected"],
+ ["Default", "Hidden", "Hidden", "Protected"]>];
+}
+
+def VecReturn : Attr {
+ let Spellings = ["vecreturn"];
+ let Subjects = [CXXRecord];
}
def WarnUnusedResult : Attr {
diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def
index eff4f5e6727b..0da893899b0b 100644
--- a/include/clang/Basic/Builtins.def
+++ b/include/clang/Basic/Builtins.def
@@ -66,6 +66,11 @@
// P:N: -> similar to the p:N: attribute, but the function is like vprintf
// in that it accepts its arguments as a va_list rather than
// through an ellipsis
+// s:N: -> this is a scanf-like function whose Nth argument is the format
+// string.
+// S:N: -> similar to the s:N: attribute, but the function is like vscanf
+// in that it accepts its arguments as a va_list rather than
+// through an ellipsis
// e -> const, but only when -fmath-errno=0
// FIXME: gcc has nonnull
@@ -193,9 +198,9 @@ BUILTIN(__builtin_cexpl, "XLdXLd", "Fnc")
BUILTIN(__builtin_cimag, "dXd", "Fnc")
BUILTIN(__builtin_cimagf, "fXf", "Fnc")
BUILTIN(__builtin_cimagl, "LdXLd", "Fnc")
-BUILTIN(__builtin_conj, "dXd", "Fnc")
-BUILTIN(__builtin_conjf, "fXf", "Fnc")
-BUILTIN(__builtin_conjl, "LdXLd", "Fnc")
+BUILTIN(__builtin_conj, "XdXd", "Fnc")
+BUILTIN(__builtin_conjf, "XfXf", "Fnc")
+BUILTIN(__builtin_conjl, "XLdXLd", "Fnc")
BUILTIN(__builtin_clog, "XdXd", "Fnc")
BUILTIN(__builtin_clogf, "XfXf", "Fnc")
BUILTIN(__builtin_clogl, "XLdXLd", "Fnc")
@@ -281,12 +286,14 @@ BUILTIN(__builtin_stdarg_start, "vA.", "n")
BUILTIN(__builtin_bcmp, "iv*v*z", "n")
BUILTIN(__builtin_bcopy, "vv*v*z", "n")
BUILTIN(__builtin_bzero, "vv*z", "nF")
+BUILTIN(__builtin_fprintf, "iP*cC*.", "Fp:1:")
BUILTIN(__builtin_memchr, "v*vC*iz", "nF")
BUILTIN(__builtin_memcmp, "ivC*vC*z", "nF")
BUILTIN(__builtin_memcpy, "v*v*vC*z", "nF")
BUILTIN(__builtin_memmove, "v*v*vC*z", "nF")
BUILTIN(__builtin_mempcpy, "v*v*vC*z", "nF")
BUILTIN(__builtin_memset, "v*v*iz", "nF")
+BUILTIN(__builtin_printf, "icC*.", "Fp:0:")
BUILTIN(__builtin_stpcpy, "c*c*cC*", "nF")
BUILTIN(__builtin_stpncpy, "c*c*cC*z", "nF")
BUILTIN(__builtin_strcasecmp, "icC*cC*", "nF")
@@ -319,7 +326,7 @@ BUILTIN(__builtin_vsprintf, "ic*cC*a", "nFP:1:")
BUILTIN(__builtin_vsnprintf, "ic*zcC*a", "nFP:2:")
// GCC exception builtins
-BUILTIN(__builtin_eh_return, "vzv*", "") // FIXME: Takes intptr_t, not size_t!
+BUILTIN(__builtin_eh_return, "vzv*", "r") // FIXME: Takes intptr_t, not size_t!
BUILTIN(__builtin_frob_return_addr, "v*v*", "n")
BUILTIN(__builtin_dwarf_cfa, "v*", "n")
BUILTIN(__builtin_init_dwarf_reg_size_table, "vv*", "n")
@@ -363,75 +370,75 @@ BUILTIN(__builtin_alloca, "v*z" , "n")
// long long -> i64.
BUILTIN(__sync_fetch_and_add, "v.", "")
-BUILTIN(__sync_fetch_and_add_1, "cc*c.", "n")
-BUILTIN(__sync_fetch_and_add_2, "ss*s.", "n")
-BUILTIN(__sync_fetch_and_add_4, "ii*i.", "n")
-BUILTIN(__sync_fetch_and_add_8, "LLiLLi*LLi.", "n")
-BUILTIN(__sync_fetch_and_add_16, "LLLiLLLi*LLLi.", "n")
+BUILTIN(__sync_fetch_and_add_1, "ccD*c.", "n")
+BUILTIN(__sync_fetch_and_add_2, "ssD*s.", "n")
+BUILTIN(__sync_fetch_and_add_4, "iiD*i.", "n")
+BUILTIN(__sync_fetch_and_add_8, "LLiLLiD*LLi.", "n")
+BUILTIN(__sync_fetch_and_add_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_fetch_and_sub, "v.", "")
-BUILTIN(__sync_fetch_and_sub_1, "cc*c.", "n")
-BUILTIN(__sync_fetch_and_sub_2, "ss*s.", "n")
-BUILTIN(__sync_fetch_and_sub_4, "ii*i.", "n")
-BUILTIN(__sync_fetch_and_sub_8, "LLiLLi*LLi.", "n")
-BUILTIN(__sync_fetch_and_sub_16, "LLLiLLLi*LLLi.", "n")
+BUILTIN(__sync_fetch_and_sub_1, "ccD*c.", "n")
+BUILTIN(__sync_fetch_and_sub_2, "ssD*s.", "n")
+BUILTIN(__sync_fetch_and_sub_4, "iiD*i.", "n")
+BUILTIN(__sync_fetch_and_sub_8, "LLiLLiD*LLi.", "n")
+BUILTIN(__sync_fetch_and_sub_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_fetch_and_or, "v.", "")
-BUILTIN(__sync_fetch_and_or_1, "cc*c.", "n")
-BUILTIN(__sync_fetch_and_or_2, "ss*s.", "n")
-BUILTIN(__sync_fetch_and_or_4, "ii*i.", "n")
-BUILTIN(__sync_fetch_and_or_8, "LLiLLi*LLi.", "n")
-BUILTIN(__sync_fetch_and_or_16, "LLLiLLLi*LLLi.", "n")
+BUILTIN(__sync_fetch_and_or_1, "ccD*c.", "n")
+BUILTIN(__sync_fetch_and_or_2, "ssD*s.", "n")
+BUILTIN(__sync_fetch_and_or_4, "iiD*i.", "n")
+BUILTIN(__sync_fetch_and_or_8, "LLiLLiD*LLi.", "n")
+BUILTIN(__sync_fetch_and_or_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_fetch_and_and, "v.", "")
-BUILTIN(__sync_fetch_and_and_1, "cc*c.", "n")
-BUILTIN(__sync_fetch_and_and_2, "ss*s.", "n")
-BUILTIN(__sync_fetch_and_and_4, "ii*i.", "n")
-BUILTIN(__sync_fetch_and_and_8, "LLiLLi*LLi.", "n")
-BUILTIN(__sync_fetch_and_and_16, "LLLiLLLi*LLLi.", "n")
+BUILTIN(__sync_fetch_and_and_1, "ccD*c.", "n")
+BUILTIN(__sync_fetch_and_and_2, "ssD*s.", "n")
+BUILTIN(__sync_fetch_and_and_4, "iiD*i.", "n")
+BUILTIN(__sync_fetch_and_and_8, "LLiLLiD*LLi.", "n")
+BUILTIN(__sync_fetch_and_and_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_fetch_and_xor, "v.", "")
-BUILTIN(__sync_fetch_and_xor_1, "cc*c.", "n")
-BUILTIN(__sync_fetch_and_xor_2, "ss*s.", "n")
-BUILTIN(__sync_fetch_and_xor_4, "ii*i.", "n")
-BUILTIN(__sync_fetch_and_xor_8, "LLiLLi*LLi.", "n")
-BUILTIN(__sync_fetch_and_xor_16, "LLLiLLLi*LLLi.", "n")
+BUILTIN(__sync_fetch_and_xor_1, "ccD*c.", "n")
+BUILTIN(__sync_fetch_and_xor_2, "ssD*s.", "n")
+BUILTIN(__sync_fetch_and_xor_4, "iiD*i.", "n")
+BUILTIN(__sync_fetch_and_xor_8, "LLiLLiD*LLi.", "n")
+BUILTIN(__sync_fetch_and_xor_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_add_and_fetch, "v.", "")
-BUILTIN(__sync_add_and_fetch_1, "cc*c.", "n")
-BUILTIN(__sync_add_and_fetch_2, "ss*s.", "n")
-BUILTIN(__sync_add_and_fetch_4, "ii*i.", "n")
-BUILTIN(__sync_add_and_fetch_8, "LLiLLi*LLi.", "n")
-BUILTIN(__sync_add_and_fetch_16, "LLLiLLLi*LLLi.", "n")
+BUILTIN(__sync_add_and_fetch_1, "ccD*c.", "n")
+BUILTIN(__sync_add_and_fetch_2, "ssD*s.", "n")
+BUILTIN(__sync_add_and_fetch_4, "iiD*i.", "n")
+BUILTIN(__sync_add_and_fetch_8, "LLiLLiD*LLi.", "n")
+BUILTIN(__sync_add_and_fetch_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_sub_and_fetch, "v.", "")
-BUILTIN(__sync_sub_and_fetch_1, "cc*c.", "n")
-BUILTIN(__sync_sub_and_fetch_2, "ss*s.", "n")
-BUILTIN(__sync_sub_and_fetch_4, "ii*i.", "n")
-BUILTIN(__sync_sub_and_fetch_8, "LLiLLi*LLi.", "n")
-BUILTIN(__sync_sub_and_fetch_16, "LLLiLLLi*LLLi.", "n")
+BUILTIN(__sync_sub_and_fetch_1, "ccD*c.", "n")
+BUILTIN(__sync_sub_and_fetch_2, "ssD*s.", "n")
+BUILTIN(__sync_sub_and_fetch_4, "iiD*i.", "n")
+BUILTIN(__sync_sub_and_fetch_8, "LLiLLiD*LLi.", "n")
+BUILTIN(__sync_sub_and_fetch_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_or_and_fetch, "v.", "")
-BUILTIN(__sync_or_and_fetch_1, "cc*c.", "n")
-BUILTIN(__sync_or_and_fetch_2, "ss*s.", "n")
-BUILTIN(__sync_or_and_fetch_4, "ii*i.", "n")
-BUILTIN(__sync_or_and_fetch_8, "LLiLLi*LLi.", "n")
-BUILTIN(__sync_or_and_fetch_16, "LLLiLLLi*LLLi.", "n")
+BUILTIN(__sync_or_and_fetch_1, "ccD*c.", "n")
+BUILTIN(__sync_or_and_fetch_2, "ssD*s.", "n")
+BUILTIN(__sync_or_and_fetch_4, "iiD*i.", "n")
+BUILTIN(__sync_or_and_fetch_8, "LLiLLiD*LLi.", "n")
+BUILTIN(__sync_or_and_fetch_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_and_and_fetch, "v.", "")
-BUILTIN(__sync_and_and_fetch_1, "cc*c.", "n")
-BUILTIN(__sync_and_and_fetch_2, "ss*s.", "n")
-BUILTIN(__sync_and_and_fetch_4, "ii*i.", "n")
-BUILTIN(__sync_and_and_fetch_8, "LLiLLi*LLi.", "n")
-BUILTIN(__sync_and_and_fetch_16, "LLLiLLLi*LLLi.", "n")
+BUILTIN(__sync_and_and_fetch_1, "ccD*c.", "n")
+BUILTIN(__sync_and_and_fetch_2, "ssD*s.", "n")
+BUILTIN(__sync_and_and_fetch_4, "iiD*i.", "n")
+BUILTIN(__sync_and_and_fetch_8, "LLiLLiD*LLi.", "n")
+BUILTIN(__sync_and_and_fetch_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_xor_and_fetch, "v.", "")
-BUILTIN(__sync_xor_and_fetch_1, "cc*c.", "n")
-BUILTIN(__sync_xor_and_fetch_2, "ss*s.", "n")
-BUILTIN(__sync_xor_and_fetch_4, "ii*i.", "n")
-BUILTIN(__sync_xor_and_fetch_8, "LLiLLi*LLi.", "n")
-BUILTIN(__sync_xor_and_fetch_16, "LLLiLLLi*LLLi.", "n")
+BUILTIN(__sync_xor_and_fetch_1, "ccD*c.", "n")
+BUILTIN(__sync_xor_and_fetch_2, "ssD*s.", "n")
+BUILTIN(__sync_xor_and_fetch_4, "iiD*i.", "n")
+BUILTIN(__sync_xor_and_fetch_8, "LLiLLiD*LLi.", "n")
+BUILTIN(__sync_xor_and_fetch_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_bool_compare_and_swap, "v.", "")
BUILTIN(__sync_bool_compare_and_swap_1, "bcD*cc.", "n")
@@ -448,18 +455,18 @@ BUILTIN(__sync_val_compare_and_swap_8, "LLiLLiD*LLiLLi.", "n")
BUILTIN(__sync_val_compare_and_swap_16, "LLLiLLLiD*LLLiLLLi.", "n")
BUILTIN(__sync_lock_test_and_set, "v.", "")
-BUILTIN(__sync_lock_test_and_set_1, "cc*c.", "n")
-BUILTIN(__sync_lock_test_and_set_2, "ss*s.", "n")
-BUILTIN(__sync_lock_test_and_set_4, "ii*i.", "n")
-BUILTIN(__sync_lock_test_and_set_8, "LLiLLi*LLi.", "n")
-BUILTIN(__sync_lock_test_and_set_16, "LLLiLLLi*LLLi.", "n")
+BUILTIN(__sync_lock_test_and_set_1, "ccD*c.", "n")
+BUILTIN(__sync_lock_test_and_set_2, "ssD*s.", "n")
+BUILTIN(__sync_lock_test_and_set_4, "iiD*i.", "n")
+BUILTIN(__sync_lock_test_and_set_8, "LLiLLiD*LLi.", "n")
+BUILTIN(__sync_lock_test_and_set_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_lock_release, "v.", "")
-BUILTIN(__sync_lock_release_1, "vc*.", "n")
-BUILTIN(__sync_lock_release_2, "vs*.", "n")
-BUILTIN(__sync_lock_release_4, "vi*.", "n")
-BUILTIN(__sync_lock_release_8, "vLLi*.", "n")
-BUILTIN(__sync_lock_release_16, "vLLLi*.", "n")
+BUILTIN(__sync_lock_release_1, "vcD*.", "n")
+BUILTIN(__sync_lock_release_2, "vsD*.", "n")
+BUILTIN(__sync_lock_release_4, "viD*.", "n")
+BUILTIN(__sync_lock_release_8, "vLLiD*.", "n")
+BUILTIN(__sync_lock_release_16, "vLLLiD*.", "n")
@@ -468,10 +475,10 @@ BUILTIN(__sync_synchronize, "v.", "n")
// LLVM instruction builtin [Clang extension].
BUILTIN(__builtin_llvm_memory_barrier,"vbbbbb", "n")
// GCC does not support these, they are a Clang extension.
-BUILTIN(__sync_fetch_and_min, "ii*i", "n")
-BUILTIN(__sync_fetch_and_max, "ii*i", "n")
-BUILTIN(__sync_fetch_and_umin, "UiUi*Ui", "n")
-BUILTIN(__sync_fetch_and_umax, "UiUi*Ui", "n")
+BUILTIN(__sync_fetch_and_min, "iiD*i", "n")
+BUILTIN(__sync_fetch_and_max, "iiD*i", "n")
+BUILTIN(__sync_fetch_and_umin, "UiUiD*Ui", "n")
+BUILTIN(__sync_fetch_and_umax, "UiUiD*Ui", "n")
// Random libc builtins.
BUILTIN(__builtin_abort, "v", "Fnr")
@@ -516,6 +523,7 @@ LIBBUILTIN(vprintf, "icC*a", "fP:0:", "stdio.h")
LIBBUILTIN(vfprintf, "i.", "fP:1:", "stdio.h")
LIBBUILTIN(vsnprintf, "ic*zcC*a", "fP:2:", "stdio.h")
LIBBUILTIN(vsprintf, "ic*cC*a", "fP:1:", "stdio.h")
+LIBBUILTIN(scanf, "icC*.", "fs:0:", "stdio.h")
// C99
LIBBUILTIN(longjmp, "vJi", "fr", "setjmp.h")
@@ -560,5 +568,10 @@ LIBBUILTIN(cos, "dd", "fe", "math.h")
LIBBUILTIN(cosl, "LdLd", "fe", "math.h")
LIBBUILTIN(cosf, "ff", "fe", "math.h")
+// Blocks runtime Builtin math library functions
+LIBBUILTIN(_Block_object_assign, "vv*vC*iC", "f", "Blocks.h")
+LIBBUILTIN(_Block_object_dispose, "vvC*iC", "f", "Blocks.h")
+// FIXME: Also declare NSConcreteGlobalBlock and NSConcreteStackBlock.
+
#undef BUILTIN
#undef LIBBUILTIN
diff --git a/include/clang/Basic/Builtins.h b/include/clang/Basic/Builtins.h
index 07f091a58a4e..94d5e6955a24 100644
--- a/include/clang/Basic/Builtins.h
+++ b/include/clang/Basic/Builtins.h
@@ -119,6 +119,11 @@ public:
/// argument and whether this function as a va_list argument.
bool isPrintfLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg);
+ /// \brief Determine whether this builtin is like scanf in its
+ /// formatting rules and, if so, set the index to the format string
+ /// argument and whether this function as a va_list argument.
+ bool isScanfLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg);
+
/// hasVAListUse - Return true of the specified builtin uses __builtin_va_list
/// as an operand or return type.
bool hasVAListUse(unsigned ID) const {
diff --git a/include/clang/Basic/BuiltinsARM.def b/include/clang/Basic/BuiltinsARM.def
index 54e4c2b2083a..080d17fa1e32 100644
--- a/include/clang/Basic/BuiltinsARM.def
+++ b/include/clang/Basic/BuiltinsARM.def
@@ -15,9 +15,21 @@
// The format of this database matches clang/Basic/Builtins.def.
// In libgcc
-BUILTIN(__clear_cache, "vc*c*", "")
+BUILTIN(__clear_cache, "v.", "")
BUILTIN(__builtin_thread_pointer, "v*", "")
+// Saturating arithmetic
+BUILTIN(__builtin_arm_qadd, "iii", "nc")
+BUILTIN(__builtin_arm_qsub, "iii", "nc")
+BUILTIN(__builtin_arm_ssat, "iiUi", "nc")
+BUILTIN(__builtin_arm_usat, "UiUiUi", "nc")
+
+// VFP
+BUILTIN(__builtin_arm_get_fpscr, "Ui", "nc")
+BUILTIN(__builtin_arm_set_fpscr, "vUi", "nc")
+BUILTIN(__builtin_arm_vcvtr_f, "ffi", "nc")
+BUILTIN(__builtin_arm_vcvtr_d, "fdi", "nc")
+
// NEON
#define GET_NEON_BUILTINS
#include "clang/Basic/arm_neon.inc"
diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def
index a878dd1bd1a3..5ad64b9b49d1 100644
--- a/include/clang/Basic/BuiltinsX86.def
+++ b/include/clang/Basic/BuiltinsX86.def
@@ -22,10 +22,81 @@
// definition anyway, since code generation will lower to the
// intrinsic if one exists.
-BUILTIN(__builtin_ia32_emms , "v", "")
-
// FIXME: Are these nothrow/const?
+// MMX
+BUILTIN(__builtin_ia32_emms, "v", "")
+BUILTIN(__builtin_ia32_femms, "v", "")
+BUILTIN(__builtin_ia32_paddb, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_paddw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_paddd, "V2iV2iV2i", "")
+BUILTIN(__builtin_ia32_paddsb, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_paddsw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_paddusb, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_paddusw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_psubb, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_psubw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_psubd, "V2iV2iV2i", "")
+BUILTIN(__builtin_ia32_psubsb, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_psubsw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_psubusb, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_psubusw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_pmulhw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_pmullw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_pmulhuw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_pmuludq, "V1LLiV2iV2i", "")
+BUILTIN(__builtin_ia32_pmaddwd, "V2iV4sV4s", "")
+BUILTIN(__builtin_ia32_pand, "V1LLiV1LLiV1LLi", "")
+BUILTIN(__builtin_ia32_pandn, "V1LLiV1LLiV1LLi", "")
+BUILTIN(__builtin_ia32_por, "V1LLiV1LLiV1LLi", "")
+BUILTIN(__builtin_ia32_pxor, "V1LLiV1LLiV1LLi", "")
+BUILTIN(__builtin_ia32_pavgb, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_pavgw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_pmaxub, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_pmaxsw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_pminub, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_pminsw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_psadbw, "V4sV8cV8c", "")
+BUILTIN(__builtin_ia32_psllw, "V4sV4sV1LLi", "")
+BUILTIN(__builtin_ia32_pslld, "V2iV2iV1LLi", "")
+BUILTIN(__builtin_ia32_psllq, "V1LLiV1LLiV1LLi", "")
+BUILTIN(__builtin_ia32_psrlw, "V4sV4sV1LLi", "")
+BUILTIN(__builtin_ia32_psrld, "V2iV2iV1LLi", "")
+BUILTIN(__builtin_ia32_psrlq, "V1LLiV1LLiV1LLi", "")
+BUILTIN(__builtin_ia32_psraw, "V4sV4sV1LLi", "")
+BUILTIN(__builtin_ia32_psrad, "V2iV2iV1LLi", "")
+BUILTIN(__builtin_ia32_psllwi, "V4sV4si", "")
+BUILTIN(__builtin_ia32_pslldi, "V2iV2ii", "")
+BUILTIN(__builtin_ia32_psllqi, "V1LLiV1LLii", "")
+BUILTIN(__builtin_ia32_psrlwi, "V4sV4si", "")
+BUILTIN(__builtin_ia32_psrldi, "V2iV2ii", "")
+BUILTIN(__builtin_ia32_psrlqi, "V1LLiV1LLii", "")
+BUILTIN(__builtin_ia32_psrawi, "V4sV4si", "")
+BUILTIN(__builtin_ia32_psradi, "V2iV2ii", "")
+BUILTIN(__builtin_ia32_packsswb, "V8cV4sV4s", "")
+BUILTIN(__builtin_ia32_packssdw, "V4sV2iV2i", "")
+BUILTIN(__builtin_ia32_packuswb, "V8cV4sV4s", "")
+BUILTIN(__builtin_ia32_punpckhbw, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_punpckhwd, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_punpckhdq, "V2iV2iV2i", "")
+BUILTIN(__builtin_ia32_punpcklbw, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_punpcklwd, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_punpckldq, "V2iV2iV2i", "")
+BUILTIN(__builtin_ia32_pcmpeqb, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_pcmpeqw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_pcmpeqd, "V2iV2iV2i", "")
+BUILTIN(__builtin_ia32_pcmpgtb, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_pcmpgtw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_pcmpgtd, "V2iV2iV2i", "")
+BUILTIN(__builtin_ia32_maskmovq, "vV8cV8cc*", "")
+BUILTIN(__builtin_ia32_pmovmskb, "iV8c", "")
+BUILTIN(__builtin_ia32_movntq, "vV1LLi*V1LLi", "")
+BUILTIN(__builtin_ia32_palignr, "V8cV8cV8cc", "") // FIXME: Correct type?
+BUILTIN(__builtin_ia32_vec_init_v2si, "V2iii", "")
+BUILTIN(__builtin_ia32_vec_init_v4hi, "V4sssss", "")
+BUILTIN(__builtin_ia32_vec_init_v8qi, "V8ccccccccc", "")
+BUILTIN(__builtin_ia32_vec_ext_v2si, "iV2ii", "")
+
// SSE intrinsics.
BUILTIN(__builtin_ia32_comieq, "iV4fV4f", "")
BUILTIN(__builtin_ia32_comilt, "iV4fV4f", "")
@@ -57,29 +128,6 @@ BUILTIN(__builtin_ia32_minps, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_maxps, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_minss, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_maxss, "V4fV4fV4f", "")
-BUILTIN(__builtin_ia32_paddsb, "V8cV8cV8c", "")
-BUILTIN(__builtin_ia32_paddsw, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_psubsb, "V8cV8cV8c", "")
-BUILTIN(__builtin_ia32_psubsw, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_paddusb, "V8cV8cV8c", "")
-BUILTIN(__builtin_ia32_paddusw, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_psubusb, "V8cV8cV8c", "")
-BUILTIN(__builtin_ia32_psubusw, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_pmulhw, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_pmulhuw, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_pavgb, "V8cV8cV8c", "")
-BUILTIN(__builtin_ia32_pavgw, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_pcmpeqb, "V8cV8cV8c", "")
-BUILTIN(__builtin_ia32_pcmpeqw, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_pcmpeqd, "V2iV2iV2i", "")
-BUILTIN(__builtin_ia32_pcmpgtb, "V8cV8cV8c", "")
-BUILTIN(__builtin_ia32_pcmpgtw, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_pcmpgtd, "V2iV2iV2i", "")
-BUILTIN(__builtin_ia32_pmaxub, "V8cV8cV8c", "")
-BUILTIN(__builtin_ia32_pmaxsw, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_pminub, "V8cV8cV8c", "")
-BUILTIN(__builtin_ia32_pminsw, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_punpcklwd, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_cmppd, "V2dV2dV2dc", "")
BUILTIN(__builtin_ia32_cmpsd, "V2dV2dV2dc", "")
BUILTIN(__builtin_ia32_minpd, "V2dV2dV2d", "")
@@ -147,18 +195,6 @@ BUILTIN(__builtin_ia32_pabsw128, "V8sV8s", "")
BUILTIN(__builtin_ia32_pabsw, "V4sV4s", "")
BUILTIN(__builtin_ia32_pabsd128, "V4iV4i", "")
BUILTIN(__builtin_ia32_pabsd, "V2iV2i", "")
-BUILTIN(__builtin_ia32_psllw, "V4sV4sV1LLi", "")
-BUILTIN(__builtin_ia32_pslld, "V2iV2iV1LLi", "")
-BUILTIN(__builtin_ia32_psllq, "V1LLiV1LLiV1LLi", "")
-BUILTIN(__builtin_ia32_psrlw, "V4sV4sV1LLi", "")
-BUILTIN(__builtin_ia32_psrld, "V2iV2iV1LLi", "")
-BUILTIN(__builtin_ia32_psrlq, "V1LLiV1LLiV1LLi", "")
-BUILTIN(__builtin_ia32_psraw, "V4sV4sV1LLi", "")
-BUILTIN(__builtin_ia32_psrad, "V2iV2iV1LLi", "")
-BUILTIN(__builtin_ia32_pmaddwd, "V2iV4sV4s", "")
-BUILTIN(__builtin_ia32_packsswb, "V8cV4sV4s", "")
-BUILTIN(__builtin_ia32_packssdw, "V4sV2iV2i", "")
-BUILTIN(__builtin_ia32_packuswb, "V8cV4sV4s", "")
BUILTIN(__builtin_ia32_ldmxcsr, "vUi", "")
BUILTIN(__builtin_ia32_stmxcsr, "Ui", "")
BUILTIN(__builtin_ia32_cvtpi2ps, "V4fV4fV2i", "")
@@ -166,17 +202,13 @@ BUILTIN(__builtin_ia32_cvtps2pi, "V2iV4f", "")
BUILTIN(__builtin_ia32_cvtss2si, "iV4f", "")
BUILTIN(__builtin_ia32_cvtss2si64, "LLiV4f", "")
BUILTIN(__builtin_ia32_cvttps2pi, "V2iV4f", "")
-BUILTIN(__builtin_ia32_maskmovq, "vV8cV8cc*", "")
BUILTIN(__builtin_ia32_loadups, "V4ffC*", "")
BUILTIN(__builtin_ia32_storeups, "vf*V4f", "")
BUILTIN(__builtin_ia32_storehps, "vV2i*V4f", "")
BUILTIN(__builtin_ia32_storelps, "vV2i*V4f", "")
BUILTIN(__builtin_ia32_movmskps, "iV4f", "")
-BUILTIN(__builtin_ia32_pmovmskb, "iV8c", "")
BUILTIN(__builtin_ia32_movntps, "vf*V4f", "")
-BUILTIN(__builtin_ia32_movntq, "vV1LLi*V1LLi", "")
BUILTIN(__builtin_ia32_sfence, "v", "")
-BUILTIN(__builtin_ia32_psadbw, "V4sV8cV8c", "")
BUILTIN(__builtin_ia32_rcpps, "V4fV4f", "")
BUILTIN(__builtin_ia32_rcpss, "V4fV4f", "")
BUILTIN(__builtin_ia32_rsqrtps, "V4fV4f", "")
@@ -212,15 +244,6 @@ BUILTIN(__builtin_ia32_lfence, "v", "")
BUILTIN(__builtin_ia32_mfence, "v", "")
BUILTIN(__builtin_ia32_loaddqu, "V16ccC*", "")
BUILTIN(__builtin_ia32_storedqu, "vc*V16c", "")
-BUILTIN(__builtin_ia32_psllwi, "V4sV4si", "")
-BUILTIN(__builtin_ia32_pslldi, "V2iV2ii", "")
-BUILTIN(__builtin_ia32_psllqi, "V1LLiV1LLii", "")
-BUILTIN(__builtin_ia32_psrawi, "V4sV4si", "")
-BUILTIN(__builtin_ia32_psradi, "V2iV2ii", "")
-BUILTIN(__builtin_ia32_psrlwi, "V4sV4si", "")
-BUILTIN(__builtin_ia32_psrldi, "V2iV2ii", "")
-BUILTIN(__builtin_ia32_psrlqi, "V1LLiV1LLii", "")
-BUILTIN(__builtin_ia32_pmuludq, "V1LLiV2iV2i", "")
BUILTIN(__builtin_ia32_pmuludq128, "V2LLiV4iV4i", "")
BUILTIN(__builtin_ia32_psraw128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_psrad128, "V4iV4iV4i", "")
@@ -244,8 +267,7 @@ BUILTIN(__builtin_ia32_pmaddwd128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_monitor, "vv*UiUi", "")
BUILTIN(__builtin_ia32_mwait, "vUiUi", "")
BUILTIN(__builtin_ia32_lddqu, "V16ccC*", "")
-BUILTIN(__builtin_ia32_palignr128, "V16cV16cV16cc", "")
-BUILTIN(__builtin_ia32_palignr, "V8cV8cV8cc", "")
+BUILTIN(__builtin_ia32_palignr128, "V16cV16cV16cc", "") // FIXME: Correct type?
BUILTIN(__builtin_ia32_insertps128, "V4fV4fV4fi", "")
BUILTIN(__builtin_ia32_storelv4si, "vV2i*V2LLi", "")
@@ -324,5 +346,98 @@ BUILTIN(__builtin_ia32_aesenclast128, "V2LLiV2LLiV2LLi", "")
BUILTIN(__builtin_ia32_aesdec128, "V2LLiV2LLiV2LLi", "")
BUILTIN(__builtin_ia32_aesdeclast128, "V2LLiV2LLiV2LLi", "")
BUILTIN(__builtin_ia32_aesimc128, "V2LLiV2LLi", "")
-BUILTIN(__builtin_ia32_aeskeygenassist128, "V2LLiV2LLii", "")
+BUILTIN(__builtin_ia32_aeskeygenassist128, "V2LLiV2LLic", "")
+
+// AVX
+BUILTIN(__builtin_ia32_addsubpd256, "V4dV4dV4d", "")
+BUILTIN(__builtin_ia32_addsubps256, "V8fV8fV8f", "")
+BUILTIN(__builtin_ia32_haddpd256, "V4dV4dV4d", "")
+BUILTIN(__builtin_ia32_hsubps256, "V8fV8fV8f", "")
+BUILTIN(__builtin_ia32_hsubpd256, "V4dV4dV4d", "")
+BUILTIN(__builtin_ia32_haddps256, "V8fV8fV8f", "")
+BUILTIN(__builtin_ia32_maxpd256, "V4dV4dV4d", "")
+BUILTIN(__builtin_ia32_maxps256, "V8fV8fV8f", "")
+BUILTIN(__builtin_ia32_minpd256, "V4dV4dV4d", "")
+BUILTIN(__builtin_ia32_minps256, "V8fV8fV8f", "")
+BUILTIN(__builtin_ia32_vpermilvarpd, "V2dV2dV2LLi", "")
+BUILTIN(__builtin_ia32_vpermilvarps, "V4fV4fV4i", "")
+BUILTIN(__builtin_ia32_vpermilvarpd256, "V4dV4dV4LLi", "")
+BUILTIN(__builtin_ia32_vpermilvarps256, "V8fV8fV8i", "")
+BUILTIN(__builtin_ia32_blendpd256, "V4dV4dV4di", "")
+BUILTIN(__builtin_ia32_blendps256, "V8fV8fV8fi", "")
+BUILTIN(__builtin_ia32_blendvpd256, "V4dV4dV4dV4d", "")
+BUILTIN(__builtin_ia32_blendvps256, "V8fV8fV8fV8f", "")
+BUILTIN(__builtin_ia32_dpps256, "V8fV8fV8fi", "")
+BUILTIN(__builtin_ia32_cmppd256, "V4dV4dV4dc", "")
+BUILTIN(__builtin_ia32_cmpps256, "V8fV8fV8fc", "")
+BUILTIN(__builtin_ia32_vextractf128_pd256, "V2dV4dc", "")
+BUILTIN(__builtin_ia32_vextractf128_ps256, "V4fV8fc", "")
+BUILTIN(__builtin_ia32_vextractf128_si256, "V4iV8ic", "")
+BUILTIN(__builtin_ia32_cvtdq2pd256, "V4dV4i", "")
+BUILTIN(__builtin_ia32_cvtdq2ps256, "V8fV8i", "")
+BUILTIN(__builtin_ia32_cvtpd2ps256, "V4fV4d", "")
+BUILTIN(__builtin_ia32_cvtps2dq256, "V8iV8f", "")
+BUILTIN(__builtin_ia32_cvtps2pd256, "V4dV4f", "")
+BUILTIN(__builtin_ia32_cvttpd2dq256, "V4iV4d", "")
+BUILTIN(__builtin_ia32_cvtpd2dq256, "V4iV4d", "")
+BUILTIN(__builtin_ia32_cvttps2dq256, "V8iV8f", "")
+BUILTIN(__builtin_ia32_vperm2f128_pd256, "V4dV4dV4dc", "")
+BUILTIN(__builtin_ia32_vperm2f128_ps256, "V8fV8fV8fc", "")
+BUILTIN(__builtin_ia32_vperm2f128_si256, "V8iV8iV8ic", "")
+BUILTIN(__builtin_ia32_vpermilpd, "V2dV2dc", "")
+BUILTIN(__builtin_ia32_vpermilps, "V4fV4fc", "")
+BUILTIN(__builtin_ia32_vpermilpd256, "V4dV4dc", "")
+BUILTIN(__builtin_ia32_vpermilps256, "V8fV8fc", "")
+BUILTIN(__builtin_ia32_vinsertf128_pd256, "V4dV4dV2dc", "")
+BUILTIN(__builtin_ia32_vinsertf128_ps256, "V8fV8fV4fc", "")
+BUILTIN(__builtin_ia32_vinsertf128_si256, "V8iV8iV4ic", "")
+BUILTIN(__builtin_ia32_sqrtpd256, "V4dV4d", "")
+BUILTIN(__builtin_ia32_sqrtps256, "V8fV8f", "")
+BUILTIN(__builtin_ia32_rsqrtps256, "V8fV8f", "")
+BUILTIN(__builtin_ia32_rcpps256, "V8fV8f", "")
+BUILTIN(__builtin_ia32_roundpd256, "V4dV4di", "")
+BUILTIN(__builtin_ia32_roundps256, "V8fV8fi", "")
+BUILTIN(__builtin_ia32_vtestzpd, "iV2dV2d", "")
+BUILTIN(__builtin_ia32_vtestcpd, "iV2dV2d", "")
+BUILTIN(__builtin_ia32_vtestnzcpd, "iV2dV2d", "")
+BUILTIN(__builtin_ia32_vtestzps, "iV4fV4f", "")
+BUILTIN(__builtin_ia32_vtestcps, "iV4fV4f", "")
+BUILTIN(__builtin_ia32_vtestnzcps, "iV4fV4f", "")
+BUILTIN(__builtin_ia32_vtestzpd256, "iV4dV4d", "")
+BUILTIN(__builtin_ia32_vtestcpd256, "iV4dV4d", "")
+BUILTIN(__builtin_ia32_vtestnzcpd256, "iV4dV4d", "")
+BUILTIN(__builtin_ia32_vtestzps256, "iV8fV8f", "")
+BUILTIN(__builtin_ia32_vtestcps256, "iV8fV8f", "")
+BUILTIN(__builtin_ia32_vtestnzcps256, "iV8fV8f", "")
+BUILTIN(__builtin_ia32_ptestz256, "iV4LLiV4LLi", "")
+BUILTIN(__builtin_ia32_ptestc256, "iV4LLiV4LLi", "")
+BUILTIN(__builtin_ia32_ptestnzc256, "iV4LLiV4LLi", "")
+BUILTIN(__builtin_ia32_movmskpd256, "iV4d", "")
+BUILTIN(__builtin_ia32_movmskps256, "iV8f", "")
+BUILTIN(__builtin_ia32_vzeroall, "v", "")
+BUILTIN(__builtin_ia32_vzeroupper, "v", "")
+BUILTIN(__builtin_ia32_vbroadcastss, "V4ffC*", "")
+BUILTIN(__builtin_ia32_vbroadcastsd256, "V4ddC*", "")
+BUILTIN(__builtin_ia32_vbroadcastss256, "V8ffC*", "")
+BUILTIN(__builtin_ia32_vbroadcastf128_pd256, "V4dV2dC*", "")
+BUILTIN(__builtin_ia32_vbroadcastf128_ps256, "V8fV4fC*", "")
+BUILTIN(__builtin_ia32_loadupd256, "V4ddC*", "")
+BUILTIN(__builtin_ia32_loadups256, "V8ffC*", "")
+BUILTIN(__builtin_ia32_storeupd256, "vd*V4d", "")
+BUILTIN(__builtin_ia32_storeups256, "vf*V8f", "")
+BUILTIN(__builtin_ia32_loaddqu256, "V32ccC*", "")
+BUILTIN(__builtin_ia32_storedqu256, "vc*V32c", "")
+BUILTIN(__builtin_ia32_lddqu256, "V32ccC*", "")
+BUILTIN(__builtin_ia32_movntdq256, "vV4LLi*V4LLi", "")
+BUILTIN(__builtin_ia32_movntpd256, "vd*V4d", "")
+BUILTIN(__builtin_ia32_movntps256, "vf*V8f", "")
+BUILTIN(__builtin_ia32_maskloadpd, "V2dV2dC*V2d", "")
+BUILTIN(__builtin_ia32_maskloadps, "V4fV4fC*V4f", "")
+BUILTIN(__builtin_ia32_maskloadpd256, "V4dV4dC*V4d", "")
+BUILTIN(__builtin_ia32_maskloadps256, "V8fV8fC*V8f", "")
+BUILTIN(__builtin_ia32_maskstorepd, "vV2d*V2dV2d", "")
+BUILTIN(__builtin_ia32_maskstoreps, "vV4f*V4fV4f", "")
+BUILTIN(__builtin_ia32_maskstorepd256, "vV4d*V4dV4d", "")
+BUILTIN(__builtin_ia32_maskstoreps256, "vV8f*V8fV8f", "")
+
#undef BUILTIN
diff --git a/include/clang/Basic/DeclNodes.td b/include/clang/Basic/DeclNodes.td
index 203fb451e38b..e2f93e02c525 100644
--- a/include/clang/Basic/DeclNodes.td
+++ b/include/clang/Basic/DeclNodes.td
@@ -43,8 +43,9 @@ def Named : Decl<1>;
def ParmVar : DDecl<Var>;
def NonTypeTemplateParm : DDecl<Var>;
def Template : DDecl<Named, 1>;
- def FunctionTemplate : DDecl<Template>;
- def ClassTemplate : DDecl<Template>;
+ def RedeclarableTemplate : DDecl<Template, 1>;
+ def FunctionTemplate : DDecl<RedeclarableTemplate>;
+ def ClassTemplate : DDecl<RedeclarableTemplate>;
def TemplateTemplateParm : DDecl<Template>;
def Using : DDecl<Named>;
def UsingShadow : DDecl<Named>;
diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h
index 1fe0d8154cd4..37d26947c335 100644
--- a/include/clang/Basic/Diagnostic.h
+++ b/include/clang/Basic/Diagnostic.h
@@ -16,6 +16,7 @@
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/type_traits.h"
#include <string>
@@ -95,23 +96,20 @@ namespace clang {
/// compilation.
class FixItHint {
public:
- /// \brief Code that should be removed to correct the error.
+ /// \brief Code that should be replaced to correct the error. Empty for an
+ /// insertion hint.
CharSourceRange RemoveRange;
- /// \brief The location at which we should insert code to correct
- /// the error.
- SourceLocation InsertionLoc;
-
/// \brief The actual code to insert at the insertion location, as a
/// string.
std::string CodeToInsert;
/// \brief Empty code modification hint, indicating that no code
/// modification is known.
- FixItHint() : RemoveRange(), InsertionLoc() { }
+ FixItHint() : RemoveRange() { }
bool isNull() const {
- return !RemoveRange.isValid() && !InsertionLoc.isValid();
+ return !RemoveRange.isValid();
}
/// \brief Create a code modification hint that inserts the given
@@ -119,7 +117,8 @@ public:
static FixItHint CreateInsertion(SourceLocation InsertionLoc,
llvm::StringRef Code) {
FixItHint Hint;
- Hint.InsertionLoc = InsertionLoc;
+ Hint.RemoveRange =
+ CharSourceRange(SourceRange(InsertionLoc, InsertionLoc), false);
Hint.CodeToInsert = Code;
return Hint;
}
@@ -141,7 +140,6 @@ public:
llvm::StringRef Code) {
FixItHint Hint;
Hint.RemoveRange = RemoveRange;
- Hint.InsertionLoc = RemoveRange.getBegin();
Hint.CodeToInsert = Code;
return Hint;
}
@@ -205,16 +203,32 @@ private:
unsigned TemplateBacktraceLimit; // Cap on depth of template backtrace stack,
// 0 -> no limit.
ExtensionHandling ExtBehavior; // Map extensions onto warnings or errors?
- DiagnosticClient *Client;
-
+ llvm::OwningPtr<DiagnosticClient> Client;
+
/// DiagMappings - Mapping information for diagnostics. Mapping info is
/// packed into four bits per diagnostic. The low three bits are the mapping
/// (an instance of diag::Mapping), or zero if unset. The high bit is set
/// when the mapping was established as a user mapping. If the high bit is
/// clear, then the low bits are set to the default value, and should be
/// mapped with -pedantic, -Werror, etc.
+ class DiagMappings {
+ unsigned char Values[diag::DIAG_UPPER_LIMIT/2];
+
+ public:
+ DiagMappings() {
+ memset(Values, 0, diag::DIAG_UPPER_LIMIT/2);
+ }
+
+ void setMapping(diag::kind Diag, unsigned Map) {
+ size_t Shift = (Diag & 1)*4;
+ Values[Diag/2] = (Values[Diag/2] & ~(15 << Shift)) | (Map << Shift);
+ }
+
+ diag::Mapping getMapping(diag::kind Diag) const {
+ return (diag::Mapping)((Values[Diag/2] >> (Diag & 1)*4) & 15);
+ }
+ };
- typedef std::vector<unsigned char> DiagMappings;
mutable std::vector<DiagMappings> DiagMappingsStack;
/// ErrorOccurred / FatalErrorOccurred - This is set to true when an error or
@@ -272,8 +286,12 @@ public:
// Diagnostic characterization methods, used by a client to customize how
//
- DiagnosticClient *getClient() { return Client; }
- const DiagnosticClient *getClient() const { return Client; }
+ DiagnosticClient *getClient() { return Client.get(); }
+ const DiagnosticClient *getClient() const { return Client.get(); }
+
+ /// \brief Return the current diagnostic client along with ownership of that
+ /// client.
+ DiagnosticClient *takeClient() { return Client.take(); }
/// pushMappings - Copies the current DiagMappings and pushes the new copy
/// onto the top of the stack.
@@ -285,7 +303,10 @@ public:
/// stack.
bool popMappings();
- void setClient(DiagnosticClient* client) { Client = client; }
+ /// \brief Set the diagnostic client associated with this diagnostic object.
+ ///
+ /// The diagnostic object takes ownership of \c client.
+ void setClient(DiagnosticClient* client) { Client.reset(client); }
/// setErrorLimit - Specify a limit for the number of errors we should
/// emit before giving up. Zero disables the limit.
@@ -382,6 +403,10 @@ public:
unsigned getNumErrorsSuppressed() const { return NumErrorsSuppressed; }
unsigned getNumWarnings() const { return NumWarnings; }
+ void setNumWarnings(unsigned NumWarnings) {
+ this->NumWarnings = NumWarnings;
+ }
+
/// getCustomDiagID - Return an ID for a diagnostic with the specified message
/// and level. If this is the first request for this diagnosic, it is
/// registered and created, otherwise the existing ID is returned.
@@ -404,6 +429,10 @@ public:
ArgToStringCookie = Cookie;
}
+ /// \brief Reset the state of the diagnostic object to its initial
+ /// configuration.
+ void Reset();
+
//===--------------------------------------------------------------------===//
// Diagnostic classification and reporting interfaces.
//
@@ -535,17 +564,13 @@ private:
/// specified builtin diagnostic. This returns the high bit encoding, or zero
/// if the field is completely uninitialized.
diag::Mapping getDiagnosticMappingInfo(diag::kind Diag) const {
- const DiagMappings &currentMappings = DiagMappingsStack.back();
- return (diag::Mapping)((currentMappings[Diag/2] >> (Diag & 1)*4) & 15);
+ return DiagMappingsStack.back().getMapping(Diag);
}
void setDiagnosticMappingInternal(unsigned DiagId, unsigned Map,
bool isUser) const {
if (isUser) Map |= 8; // Set the high bit for user mappings.
- unsigned char &Slot = DiagMappingsStack.back()[DiagId/2];
- unsigned Shift = (DiagId & 1)*4;
- Slot &= ~(15 << Shift);
- Slot |= Map << Shift;
+ DiagMappingsStack.back().setMapping((diag::kind)DiagId, Map);
}
/// getDiagnosticLevel - This is an internal implementation helper used when
@@ -927,7 +952,9 @@ public:
Diagnostic::Level getLevel() const { return Level; }
const FullSourceLoc &getLocation() const { return Loc; }
llvm::StringRef getMessage() const { return Message; }
-
+
+ void setLocation(FullSourceLoc Loc) { this->Loc = Loc; }
+
typedef std::vector<CharSourceRange>::const_iterator range_iterator;
range_iterator range_begin() const { return Ranges.begin(); }
range_iterator range_end() const { return Ranges.end(); }
diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td
index 4b0bf57bef63..98ea9d4bd6d9 100644
--- a/include/clang/Basic/DiagnosticCommonKinds.td
+++ b/include/clang/Basic/DiagnosticCommonKinds.td
@@ -41,7 +41,8 @@ def err_expected_colon_after_setter_name : Error<
"must end with ':'">;
// Parse && Sema
-def ext_no_declarators : ExtWarn<"declaration does not declare anything">;
+def ext_no_declarators : ExtWarn<"declaration does not declare anything">,
+ InGroup<MissingDeclarations>;
def err_param_redefinition : Error<"redefinition of parameter %0">;
def err_invalid_storage_class_in_func_decl : Error<
"invalid storage class specifier in function declarator">;
diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td
index f4a31cc5766c..34cd6004edee 100644
--- a/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/include/clang/Basic/DiagnosticDriverKinds.td
@@ -68,6 +68,8 @@ def err_drv_invalid_gcc_output_type : Error<
"invalid output type '%0' for use with gcc tool">;
def err_drv_cc_print_options_failure : Error<
"unable to open CC_PRINT_OPTIONS file: %0">;
+def err_drv_preamble_format : Error<
+ "incorrect format for -preamble-bytes=N,END">;
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 989ec38d2950..7c74bf458e58 100644
--- a/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -99,7 +99,7 @@ def warn_fixit_no_changes : Note<
def err_fe_invoking : Error<"error invoking%0: %1">, DefaultFatal;
// PCH reader
-def err_relocatable_without_without_isysroot : Error<
+def err_relocatable_without_isysroot : Error<
"must specify system root with -isysroot when building a relocatable "
"PCH file">;
def warn_pch_target_triple : Error<
diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td
index 49077513c137..d4b7f1f55743 100644
--- a/include/clang/Basic/DiagnosticGroups.td
+++ b/include/clang/Basic/DiagnosticGroups.td
@@ -25,15 +25,19 @@ def AmbigMemberTemplate : DiagGroup<"ambiguous-member-template">;
def : DiagGroup<"attributes">;
def : DiagGroup<"bad-function-cast">;
def BoolConversions : DiagGroup<"bool-conversions">;
-def : DiagGroup<"c++-compat">;
-def : DiagGroup<"cast-align">;
+def CXXCompat: DiagGroup<"c++-compat">;
+def CastAlign : DiagGroup<"cast-align">;
def : DiagGroup<"cast-qual">;
def : DiagGroup<"char-align">;
def Comment : DiagGroup<"comment">;
def : DiagGroup<"ctor-dtor-privacy">;
def : DiagGroup<"declaration-after-statement">;
def GNUDesignator : DiagGroup<"gnu-designator">;
-def Deprecated : DiagGroup<"deprecated">;
+
+def DeprecatedDeclarations : DiagGroup<"deprecated-declarations">;
+def Deprecated : DiagGroup<"deprecated", [ DeprecatedDeclarations] >,
+ DiagCategory<"Deprecations">;
+
def : DiagGroup<"disabled-optimization">;
def : DiagGroup<"discard-qual">;
def : DiagGroup<"div-by-zero">;
@@ -46,7 +50,9 @@ def FormatZeroLength : DiagGroup<"format-zero-length">;
def CXXHexFloats : DiagGroup<"c++-hex-floats">;
def : DiagGroup<"c++0x-compat", [CXXHexFloats]>;
+def : DiagGroup<"effc++">;
def FourByteMultiChar : DiagGroup<"four-char-constants">;
+def GlobalConstructors : DiagGroup<"global-constructors">;
def : DiagGroup<"idiomatic-parentheses">;
def IgnoredQualifiers : DiagGroup<"ignored-qualifiers">;
def : DiagGroup<"import">;
@@ -55,9 +61,10 @@ def : DiagGroup<"inline">;
def : DiagGroup<"int-to-pointer-cast">;
def : DiagGroup<"invalid-pch">;
def LiteralRange : DiagGroup<"literal-range">;
+def LocalTypeTemplateArgs : DiagGroup<"local-type-template-args">;
def : DiagGroup<"main">;
def MissingBraces : DiagGroup<"missing-braces">;
-def : DiagGroup<"missing-declarations">;
+def MissingDeclarations: DiagGroup<"missing-declarations">;
def : DiagGroup<"missing-format-attribute">;
def : DiagGroup<"missing-include-dirs">;
def : DiagGroup<"missing-noreturn">;
@@ -71,8 +78,11 @@ def InitializerOverrides : DiagGroup<"initializer-overrides">;
def NonNull : DiagGroup<"nonnull">;
def : DiagGroup<"nonportable-cfstrings">;
def : DiagGroup<"non-virtual-dtor">;
+def : DiagGroup<"old-style-cast">;
def : DiagGroup<"old-style-definition">;
+def OutOfLineDeclaration : DiagGroup<"out-of-line-declaration">;
def : DiagGroup<"overflow">;
+def OverlengthStrings : DiagGroup<"overlength-strings">;
def : DiagGroup<"overloaded-virtual">;
def : DiagGroup<"packed">;
def PointerArith : DiagGroup<"pointer-arith">;
@@ -88,6 +98,8 @@ def Shadow : DiagGroup<"shadow">;
def : DiagGroup<"shorten-64-to-32">;
def : DiagGroup<"sign-promo">;
def SignCompare : DiagGroup<"sign-compare">;
+def : DiagGroup<"stack-protector">;
+def : DiagGroup<"switch-default">;
def : DiagGroup<"synth">;
// Preprocessor warnings.
@@ -110,7 +122,7 @@ def : DiagGroup<"strict-overflow">;
def InvalidOffsetof : DiagGroup<"invalid-offsetof">;
def : DiagGroup<"strict-prototypes">;
-def : DiagGroup<"strict-selector-match">;
+def StrictSelector : DiagGroup<"strict-selector-match">;
def SwitchEnum : DiagGroup<"switch-enum">;
def Switch : DiagGroup<"switch", [SwitchEnum]>;
def Trigraphs : DiagGroup<"trigraphs">;
@@ -119,9 +131,11 @@ def : DiagGroup<"type-limits">;
def Uninitialized : DiagGroup<"uninitialized">;
def UnknownPragmas : DiagGroup<"unknown-pragmas">;
def UnknownAttributes : DiagGroup<"unknown-attributes">;
+def UnnamedTypeTemplateArgs : DiagGroup<"unnamed-type-template-args">;
def UnusedArgument : DiagGroup<"unused-argument">;
def UnusedExceptionParameter : DiagGroup<"unused-exception-parameter">;
def UnusedFunction : DiagGroup<"unused-function">;
+def UnusedMemberFunction : DiagGroup<"unused-member-function">;
def UnusedLabel : DiagGroup<"unused-label">;
def UnusedParameter : DiagGroup<"unused-parameter">;
def UnusedValue : DiagGroup<"unused-value">;
@@ -129,6 +143,8 @@ def UnusedVariable : DiagGroup<"unused-variable">;
def ReadOnlySetterAttrs : DiagGroup<"readonly-setter-attrs">;
def Reorder : DiagGroup<"reorder">;
def UndeclaredSelector : DiagGroup<"undeclared-selector">;
+def Selector : DiagGroup<"selector">;
+def NonfragileAbi2 : DiagGroup<"nonfragile-abi2">;
def Protocol : DiagGroup<"protocol">;
def SuperSubClassMismatch : DiagGroup<"super-class-method-mismatch">;
def : DiagGroup<"variadic-macros">;
@@ -154,6 +170,7 @@ def Conversion : DiagGroup<"conversion",
def Unused : DiagGroup<"unused",
[UnusedArgument, UnusedFunction, UnusedLabel,
// UnusedParameter, (matches GCC's behavior)
+ // UnusedMemberFunction, (clean-up llvm before enabling)
UnusedValue, UnusedVariable]>,
DiagCategory<"Unused Entity Issue">;
diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td
index 21c93e7e8fa2..dcb05c8fcd45 100644
--- a/include/clang/Basic/DiagnosticLexKinds.td
+++ b/include/clang/Basic/DiagnosticLexKinds.td
@@ -51,6 +51,7 @@ def err_empty_character : Error<"empty character constant">;
def err_unterminated_block_comment : Error<"unterminated /* comment">;
def err_invalid_character_to_charify : Error<
"invalid argument to convert to character">;
+def err_unterminated___pragma : Error<"missing terminating ')' character">;
def err_conflict_marker : Error<"version control conflict marker in file">;
@@ -94,7 +95,10 @@ def ext_binary_literal : Extension<
def err_pascal_string_too_long : Error<"Pascal string is too long">;
def warn_octal_escape_too_large : ExtWarn<"octal escape sequence out of range">;
def warn_hex_escape_too_large : ExtWarn<"hex escape sequence out of range">;
-
+def ext_string_too_long : Extension<"string literal of length %0 exceeds "
+ "maximum length %1 that %select{C90|ISO C99|C++}2 compilers are required to "
+ "support">, InGroup<OverlengthStrings>;
+
//===----------------------------------------------------------------------===//
// PTH Diagnostics
//===----------------------------------------------------------------------===//
@@ -227,6 +231,10 @@ def err_pragma_comment_malformed : Error<
"pragma comment requires parenthesized identifier and optional string">;
def err_pragma_message_malformed : Error<
"pragma message requires parenthesized string">;
+def err_pragma_push_pop_macro_malformed : Error<
+ "pragma %0 requires a parenthesized string">;
+def warn_pragma_pop_macro_no_push : Warning<
+ "pragma pop_macro could not pop '%0', no matching push_macro">;
def warn_pragma_message : Warning<"%0">;
def warn_pragma_ignored : Warning<"unknown pragma ignored">,
InGroup<UnknownPragmas>, DefaultIgnore;
@@ -241,15 +249,11 @@ def ext_stdc_pragma_syntax_eom :
def warn_stdc_fenv_access_not_supported :
Warning<"pragma STDC FENV_ACCESS ON is not supported, ignoring pragma">,
InGroup<UnknownPragmas>;
-def warn_pragma_diagnostic_gcc_invalid :
- ExtWarn<"pragma diagnostic expected 'error', 'warning', 'ignored', or"
- " 'fatal'">,
- InGroup<UnknownPragmas>;
-def warn_pragma_diagnostic_clang_invalid :
- ExtWarn<"pragma diagnostic expected 'error', 'warning', 'ignored', 'fatal'"
+def warn_pragma_diagnostic_invalid :
+ ExtWarn<"pragma diagnostic expected 'error', 'warning', 'ignored', 'fatal',"
" 'push', or 'pop'">,
InGroup<UnknownPragmas>;
-def warn_pragma_diagnostic_clang_cannot_ppp :
+def warn_pragma_diagnostic_cannot_pop :
ExtWarn<"pragma diagnostic pop could not pop, no matching push">,
InGroup<UnknownPragmas>;
def warn_pragma_diagnostic_invalid_option :
@@ -261,6 +265,9 @@ def warn_pragma_diagnostic_invalid_token :
def warn_pragma_diagnostic_unknown_warning :
ExtWarn<"unknown warning group '%0', ignored">,
InGroup<UnknownPragmas>;
+// - #pragma __debug
+def warn_pragma_debug_unexpected_command : Warning<
+ "unexpected debug command '%0'">;
def err_pragma_comment_unknown_kind : Error<"unknown kind of pragma comment">;
def err_defined_macro_name : Error<"'defined' cannot be used as a macro name">;
@@ -277,6 +284,9 @@ def err_too_few_args_in_macro_invoc : Error<
"too few arguments provided to function-like macro invocation">;
def err_pp_bad_paste : Error<
"pasting formed '%0', an invalid preprocessing token">;
+def err_pp_bad_paste_ms : Warning<
+ "pasting formed '%0', an invalid preprocessing token">, DefaultError,
+ InGroup<DiagGroup<"invalid-token-paste">>;
def err_pp_operator_used_as_macro_name : Error<
"C++ operator '%0' cannot be used as a macro name">;
def err_pp_illegal_floating_literal : Error<
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index ca761f9bf5e9..646fd0d1bfb6 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -35,8 +35,9 @@ def ext_integer_complex : Extension<
"complex integer types are an extension">;
def ext_thread_before : Extension<"'__thread' before 'static'">;
-def ext_empty_struct_union_enum : Extension<"use of empty %0 extension">;
-
+def ext_empty_struct_union : Extension<"empty %select{struct|union}0 "
+ "(accepted as an extension) has size 0 in C, size 1 in C++">,
+ InGroup<CXXCompat>;
def error_empty_enum : Error<"use of empty enum">;
def err_invalid_sign_spec : Error<"'%0' cannot be signed or unsigned">;
def err_invalid_short_spec : Error<"'short %0' is invalid">;
@@ -102,6 +103,8 @@ def err_expected_member_name_or_semi : Error<
"expected member name or ';' after declaration specifiers">;
def err_function_declared_typedef : Error<
"function definition declared 'typedef'">;
+def err_iboutletcollection_builtintype : Error<
+ "type argument of iboutletcollection attribute cannot be a builtin type">;
def err_expected_fn_body : Error<
"expected function body after function declarator">;
def err_expected_method_body : Error<"expected method body">;
@@ -125,6 +128,7 @@ def err_expected_semi_after_namespace_name : Error<
"expected ';' after namespace name">;
def err_unexpected_namespace_attributes_alias : Error<
"attributes can not be specified on namespace alias">;
+def err_inline_namespace_alias : Error<"namespace alias cannot be inline">;
def err_namespace_nonnamespace_scope : Error<
"namespaces can only be defined in global or namespace scope">;
def err_expected_semi_after_attribute_list : Error<
@@ -150,6 +154,8 @@ def err_illegal_decl_reference_to_reference : Error<
"%0 declared as a reference to a reference">;
def err_rvalue_reference : Error<
"rvalue references are only allowed in C++0x">;
+def ext_inline_namespace : Extension<
+ "inline namespaces are a C++0x feature">;
def err_argument_required_after_attribute : Error<
"argument required after attribute">;
def err_missing_param : Error<"expected parameter declarator">;
@@ -270,6 +276,8 @@ def err_destructor_tilde_identifier : Error<
"expected a class name after '~' to name a destructor">;
def err_destructor_template_id : Error<
"destructor name %0 does not refer to a template">;
+def err_default_arg_unparsed : Error<
+ "unexpected end of default argument expression">;
// C++ derived classes
def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">;
@@ -373,10 +381,10 @@ def warn_pragma_extra_tokens_at_eol : Warning<
// - #pragma options
def warn_pragma_options_expected_align : Warning<
"expected 'align' following '#pragma options' - ignored">;
-def warn_pragma_options_expected_equal : Warning<
- "expected '=' following '#pragma options align' - ignored">;
-def warn_pragma_options_invalid_option : Warning<
- "invalid alignment option in '#pragma options align' - ignored">;
+def warn_pragma_align_expected_equal : Warning<
+ "expected '=' following '#pragma %select{align|options align}0' - ignored">;
+def warn_pragma_align_invalid_option : Warning<
+ "invalid alignment option in '#pragma %select{align|options align}0' - ignored">;
// - #pragma pack
def warn_pragma_pack_invalid_action : Warning<
"unknown action for '#pragma pack' - ignored">;
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 01a37fb6f2c6..a25b2a341fc5 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -104,6 +104,8 @@ def warn_decl_in_param_list : Warning<
"declaration of %0 will not be visible outside of this function">;
def warn_unused_function : Warning<"unused function %0">,
InGroup<UnusedFunction>, DefaultIgnore;
+def warn_unused_member_function : Warning<"unused member function %0">,
+ InGroup<UnusedMemberFunction>, DefaultIgnore;
def warn_implicit_function_decl : Warning<
"implicit declaration of function %0">,
@@ -168,6 +170,13 @@ def warn_access_decl_deprecated : Warning<
"access declarations are deprecated; use using declarations instead">,
InGroup<Deprecated>;
+def warn_global_constructor : Warning<
+ "declaration requires a global constructor">,
+ InGroup<GlobalConstructors>, DefaultIgnore;
+def warn_global_destructor : Warning<
+ "declaration requires a global destructor">,
+ InGroup<GlobalConstructors>, DefaultIgnore;
+
def err_invalid_thread : Error<
"'__thread' is only allowed on variable declarations">;
def err_thread_non_global : Error<
@@ -227,7 +236,8 @@ def err_main_arg_wrong : Error<"%select{first|second|third|fourth}0 "
"platform-specific data}0) must be of type %1">;
/// parser diagnostics
-def ext_typedef_without_a_name : ExtWarn<"typedef requires a name">;
+def ext_typedef_without_a_name : ExtWarn<"typedef requires a name">,
+ InGroup<MissingDeclarations>;
def err_typedef_not_identifier : Error<"typedef name must be an identifier">;
def err_statically_allocated_object : Error<
"interface type cannot be statically allocated">;
@@ -322,6 +332,8 @@ def warn_implements_nscopying : Warning<
"NSCopying protocol is not appropriate with -fobjc-gc[-only]">;
def warn_multiple_method_decl : Warning<"multiple methods named %0 found">;
+def warn_strict_multiple_method_decl : Warning<
+ "multiple methods named %0 found">, InGroup<StrictSelector>, DefaultIgnore;
def warn_accessor_property_type_mismatch : Warning<
"type of property %0 does not match type of accessor %1">;
def note_declared_at : Note<"declared here">;
@@ -399,6 +411,8 @@ def warn_objc_property_attr_mutually_exclusive : Warning<
InGroup<ReadOnlySetterAttrs>, DefaultIgnore;
def warn_undeclared_selector : Warning<
"undeclared selector %0">, InGroup<UndeclaredSelector>, DefaultIgnore;
+def warn_unimplemented_selector: Warning<
+ "unimplemented selector %0">, InGroup<Selector>, DefaultIgnore;
def warn_unimplemented_protocol_method : Warning<
"method in protocol not implemented">, InGroup<Protocol>;
@@ -407,6 +421,10 @@ def err_static_assert_expression_is_not_constant : Error<
"static_assert expression is not an integral constant expression">;
def err_static_assert_failed : Error<"static_assert failed \"%0\"">;
+def err_inline_namespace_mismatch : Error<
+ "%select{|non-}0inline namespace "
+ "cannot be reopened as %select{non-|}0inline">;
+
def err_unexpected_friend : Error<
"friends can only be classes or functions">;
def ext_enum_friend : ExtWarn<
@@ -549,6 +567,8 @@ def note_access_natural : Note<
def note_access_constrained_by_path : Note<
"constrained by %select{|implicitly }1%select{private|protected}0"
" inheritance here">;
+def note_access_protected_restricted : Note<
+ "object type %select{|%1 }0must derive from context type %2">;
// C++ name lookup
def err_incomplete_nested_name_spec : Error<
@@ -621,9 +641,9 @@ def err_missing_default_ctor : Error<
"%select{|implicit default }0constructor for %1 must explicitly initialize "
"the %select{base class|member}2 %3 which does not have a default "
"constructor">;
-def err_illegal_union_member : Error<
- "union member %0 has a non-trivial %select{constructor|"
- "copy constructor|copy assignment operator|destructor}1">;
+def err_illegal_union_or_anon_struct_member : Error<
+ "%select{anonymous struct|union}0 member %1 has a non-trivial "
+ "%select{constructor|copy constructor|copy assignment operator|destructor}2">;
def note_nontrivial_has_virtual : Note<
"because type %0 has a virtual %select{member function|base class}1">;
def note_nontrivial_has_nontrivial : Note<
@@ -814,6 +834,11 @@ def err_attributes_are_not_compatible : Error<
"%0 and %1 attributes are not compatible">;
def err_attribute_wrong_number_arguments : Error<
"attribute requires %0 argument(s)">;
+def err_iboutletcollection_type : Error<
+ "invalid type %0 as argument of iboutletcollection attribute">;
+def err_iboutletcollection_object_type : Error<
+ "%select{ivar|property}1 with iboutletcollection attribute must "
+ "have object type (invalid %0)">;
def err_attribute_missing_parameter_name : Error<
"attribute requires unquoted parameter">;
def err_attribute_invalid_vector_type : Error<"invalid vector element type %0">;
@@ -833,8 +858,10 @@ def err_attribute_argument_out_of_bounds : Error<
"'%0' attribute parameter %1 is out of bounds">;
def err_attribute_requires_objc_interface : Error<
"attribute may only be applied to an Objective-C interface">;
-def err_nonnull_pointers_only : Error<
+def warn_nonnull_pointers_only : Warning<
"nonnull attribute only applies to pointer arguments">;
+def err_ownership_type : Error<
+ "%0 attribute only applies to %1 arguments">;
def err_format_strftime_third_parameter : Error<
"strftime format attribute requires 3rd parameter to be 0">;
def err_format_attribute_requires_variadic : Error<
@@ -957,6 +984,10 @@ def warn_impcast_integer_64_32 : Warning<
"implicit conversion loses integer precision: %0 to %1">,
InGroup<DiagGroup<"shorten-64-to-32">>, DefaultIgnore;
+def warn_cast_align : Warning<
+ "cast from %0 to %1 increases required alignment from %2 to %3">,
+ InGroup<CastAlign>, DefaultIgnore;
+
def warn_attribute_ignored_for_field_of_type : Warning<
"%0 attribute ignored for field of type %1">;
def warn_transparent_union_attribute_field_size_align : Warning<
@@ -976,7 +1007,7 @@ def warn_transparent_union_attribute_zero_fields : Warning<
"transparent_union attribute ignored">;
def warn_attribute_type_not_supported : Warning<
"'%0' attribute argument not supported: %1">;
-def warn_attribute_unknown_visibility : Warning<"unknown visibility '%1'">;
+def warn_attribute_unknown_visibility : Warning<"unknown visibility '%0'">;
def err_unknown_machine_mode : Error<"unknown machine mode %0">;
def err_unsupported_machine_mode : Error<"unsupported machine mode %0">;
def err_mode_not_primitive : Error<
@@ -1139,6 +1170,9 @@ def note_ovl_candidate_explicit_arg_mismatch_unnamed : Note<
def note_ovl_candidate_instantiation_depth : Note<
"candidate template ignored: substitution exceeded maximum template "
"instantiation depth">;
+def note_ovl_candidate_underqualified : Note<
+ "candidate template ignored: can't deduce a type for %0 which would "
+ "make %2 equal %1">;
def note_ovl_candidate_substitution_failure : Note<
"candidate template ignored: substitution failure %0">;
@@ -1195,7 +1229,7 @@ def note_ovl_candidate_bad_cvr_this : Note<"candidate "
"%select{|function|||function||||"
"function (the implicit copy assignment operator)}0 not viable: "
"'this' argument has type %2, but method is not marked "
- "%select{const|volatile|const or volatile|restrict|const or restrict|"
+ "%select{const|restrict|const or restrict|volatile|const or volatile|"
"volatile or restrict|const, volatile, or restrict}3">;
def note_ovl_candidate_bad_cvr : Note<"candidate "
"%select{function|function|constructor|"
@@ -1204,7 +1238,7 @@ def note_ovl_candidate_bad_cvr : Note<"candidate "
"constructor (the implicit copy constructor)|"
"function (the implicit copy assignment operator)}0%1 not viable: "
"%ordinal4 argument (%2) would lose "
- "%select{const|volatile|const and volatile|restrict|const and restrict|"
+ "%select{const|restrict|const and restrict|volatile|const and volatile|"
"volatile and restrict|const, volatile, and restrict}3 qualifier"
"%select{||s||s|s|s}3">;
def note_ovl_candidate_bad_base_to_derived_conv : Note<"candidate "
@@ -1258,6 +1292,8 @@ def err_addr_ovl_ambiguous : Error<
"address of overloaded function %0 is ambiguous">;
def err_addr_ovl_not_func_ptrref : Error<
"address of overloaded function %0 cannot be converted to type %1">;
+def err_addr_ovl_no_qualifier : Error<
+ "can't form member pointer of type %0 without '&' and class name">;
// C++ Template Declarations
def err_template_param_shadow : Error<
@@ -1335,9 +1371,10 @@ def err_template_arg_nontype_ambig : Error<
"template argument for non-type template parameter is treated as type %0">;
def err_template_arg_must_be_template : Error<
"template argument for template template parameter must be a class template">;
-def err_template_arg_local_type : Error<"template argument uses local type %0">;
-def err_template_arg_unnamed_type : Error<
- "template argument uses unnamed type">;
+def ext_template_arg_local_type : ExtWarn<
+ "template argument uses local type %0">, InGroup<LocalTypeTemplateArgs>;
+def ext_template_arg_unnamed_type : ExtWarn<
+ "template argument uses unnamed type">, InGroup<UnnamedTypeTemplateArgs>;
def note_template_unnamed_type_here : Note<
"unnamed type used in template argument was declared here">;
def err_template_arg_overload_type : Error<
@@ -1683,9 +1720,8 @@ def note_dependent_var_use : Note<"must qualify identifier to find this "
"declaration in dependent base class">;
def err_undeclared_use : Error<"use of undeclared %0">;
def warn_deprecated : Warning<"%0 is deprecated">,
- InGroup<DiagGroup<"deprecated-declarations">>;
-def warn_unavailable : Warning<"%0 is unavailable">,
- InGroup<DiagGroup<"unavailable-declarations">>;
+ InGroup<DeprecatedDeclarations>;
+def err_unavailable : Error<"%0 is unavailable">;
def note_unavailable_here : Note<
"function has been explicitly marked %select{unavailable|deleted}0 here">;
def warn_not_enough_argument : Warning<
@@ -1706,6 +1742,8 @@ def warn_redefinition_of_typedef : Warning<
"redefinition of typedef %0 is invalid in C">,
InGroup<DiagGroup<"typedef-redefinition"> >, DefaultError;
+def err_inline_declaration_block_scope : Error<
+ "inline declaration of %0 not allowed in block scope">;
def err_static_non_static : Error<
"static declaration of %0 follows non-static declaration">;
def err_non_static_static : Error<
@@ -1768,6 +1806,8 @@ def err_typecheck_field_variable_size : Error<
"extension will never be supported">;
def err_vm_func_decl : Error<
"function declaration cannot have variably modified type">;
+def err_array_too_large : Error<
+ "array is too large (%0 elements)">;
def err_typecheck_negative_array_size : Error<"array size is negative">;
def warn_typecheck_function_qualifiers : Warning<
@@ -1809,7 +1849,7 @@ def warn_missing_field_initializers : Warning<
InGroup<MissingFieldInitializers>, DefaultIgnore;
def warn_braces_around_scalar_init : Warning<
"braces around scalar initializer">;
-def err_many_braces_around_scalar_init : Error<
+def warn_many_braces_around_scalar_init : ExtWarn<
"too many braces around scalar initializer">;
def err_empty_scalar_initializer : Error<"scalar initializer cannot be empty">;
def err_illegal_initializer : Error<
@@ -1844,9 +1884,9 @@ def warn_missing_braces : Warning<
def err_redefinition_of_label : Error<"redefinition of label '%0'">;
def err_undeclared_label_use : Error<"use of undeclared label '%0'">;
-def err_goto_into_protected_scope : Error<"illegal goto into protected scope">;
+def err_goto_into_protected_scope : Error<"goto into protected scope">;
def err_switch_into_protected_scope : Error<
- "illegal switch case into protected scope">;
+ "switch case is in protected scope">;
def err_indirect_goto_without_addrlabel : Error<
"indirect goto in function with no address-of-label expressions">;
def warn_indirect_goto_in_protected_scope : Warning<
@@ -1990,7 +2030,7 @@ def note_precedence_bitwise_silence : Note<
def warn_logical_instead_of_bitwise : Warning<
"use of logical %0 with constant operand; switch to bitwise %1 or "
- "remove constant">, InGroup<DiagGroup<"logical-bitwise-confusion">>;
+ "remove constant">, InGroup<DiagGroup<"constant-logical-operand">>;
def err_sizeof_nonfragile_interface : Error<
"invalid application of '%select{alignof|sizeof}1' to interface %0 in "
@@ -2048,8 +2088,9 @@ def err_qualified_typedef_declarator : Error<
"typedef declarator cannot be qualified">;
def err_qualified_param_declarator : Error<
"parameter declarator cannot be qualified">;
-def err_out_of_line_declaration : Error<
- "out-of-line declaration of a member must be a definition">;
+def ext_out_of_line_declaration : ExtWarn<
+ "out-of-line declaration of a member must be a definition">,
+ InGroup<OutOfLineDeclaration>, DefaultError;
def note_member_def_close_match : Note<"member declaration nearly matches">;
def err_typecheck_ivar_variable_size : Error<
"instance variables must have a constant size">;
@@ -2093,7 +2134,11 @@ def err_typecheck_address_of : Error<"address of %0 requested">;
def ext_typecheck_addrof_void : Extension<
"ISO C forbids taking the address of an expression of type 'void'">;
def err_unqualified_pointer_member_function : Error<
- "must explicitly qualify member function %0 when taking its address">;
+ "must explicitly qualify name of member function when taking its address">;
+def err_invalid_form_pointer_member_function : Error<
+ "cannot create a non-constant pointer to member function">;
+def err_parens_pointer_member_function : Error<
+ "cannot parenthesize the name of a method when forming a member pointer">;
def err_typecheck_invalid_lvalue_addrof : Error<
"address expression must be an lvalue or a function designator">;
def ext_typecheck_addrof_class_temporary : ExtWarn<
@@ -2110,8 +2155,8 @@ def warn_indirection_through_null : Warning<
def note_indirection_through_null : Note<
"consider using __builtin_trap() or qualifying pointer with 'volatile'">;
-def err_indirection_requires_nonfragile_object : Error<
- "indirection cannot be to an interface in non-fragile ABI (%0 invalid)">;
+def err_assignment_requires_nonfragile_object : Error<
+ "cannot assign to class object in non-fragile ABI (%0 invalid)">;
def err_direct_interface_unsupported : Error<
"indirection to an interface is not supported (%0 invalid)">;
def err_typecheck_invalid_operands : Error<
@@ -2183,10 +2228,10 @@ def err_builtin_direct_init_more_than_one_arg : Error<
"initializer of a builtin type can only take one argument">;
def err_value_init_for_array_type : Error<
"array types cannot be value-initialized">;
-def warn_printf_nonliteral_noargs : Warning<
+def warn_format_nonliteral_noargs : Warning<
"format string is not a string literal (potentially insecure)">,
InGroup<FormatSecurity>;
-def warn_printf_nonliteral : Warning<
+def warn_format_nonliteral : Warning<
"format string is not a string literal">,
InGroup<FormatNonLiteral>, DefaultIgnore;
@@ -2215,7 +2260,7 @@ def ext_integer_complement_complex : Extension<
def error_nosetter_property_assignment : Error<
"setter method is needed to assign to object using property" " assignment syntax">;
def error_no_subobject_property_setting : Error<
- "expression is not assignable using property assignment syntax">;
+ "expression is not assignable">;
def ext_freestanding_complex : Extension<
"complex numbers are an extension in a freestanding C99 implementation">;
@@ -2263,7 +2308,13 @@ def warn_register_objc_catch_parm : Warning<
"'register' storage specifier on @catch parameter will be ignored">;
def err_qualified_objc_catch_parm : Error<
"@catch parameter declarator cannot be qualified">;
-
+def err_objc_pointer_cxx_catch_gnu : Error<
+ "can't catch Objective C exceptions in C++ in the GNU runtime">;
+def err_objc_pointer_cxx_catch_fragile : Error<
+ "can't catch Objective C exceptions in C++ in the non-unified "
+ "exception model">;
+def err_objc_object_catch : Error<
+ "can't catch an Objective C object by value">;
def warn_setter_getter_impl_required : Warning<
"property %0 requires method %1 to be defined - "
@@ -2313,6 +2364,9 @@ def err_bad_static_cast_pointer_nonpointer : Error<
"cannot cast from type %1 to pointer type %2">;
def err_bad_static_cast_member_pointer_nonmp : Error<
"cannot cast from type %1 to member pointer type %2">;
+def err_bad_cxx_cast_member_pointer_size : Error<
+ "cannot %select{||reinterpret_cast||C-style cast|}0 from member pointer "
+ "type %1 to member pointer type %2 of different size">;
def err_bad_static_cast_incomplete : Error<"%0 is an incomplete type">;
// These messages don't adhere to the pattern.
@@ -2378,8 +2432,12 @@ def err_ambiguous_delete_operand : Error<"ambiguous conversion of delete "
"expression of type %0 to a pointer">;
def warn_delete_incomplete : Warning<
"deleting pointer to incomplete type %0 may cause undefined behaviour">;
+def err_delete_incomplete_class_type : Warning<
+ "deleting incomplete class type %0; no conversions to pointer type">;
def err_no_suitable_delete_member_function_found : Error<
"no suitable member %0 in %1">;
+def err_ambiguous_suitable_delete_member_function_found : Error<
+ "multiple suitable %0 functions in %1">;
def note_member_declared_here : Note<
"member %0 declared here">;
def err_decrement_bool : Error<"cannot decrement expression of type bool">;
@@ -2486,8 +2544,11 @@ def note_condition_assign_to_comparison : Note<
def note_condition_assign_silence : Note<
"place parentheses around the assignment to silence this warning">;
-def warn_value_always_zero : Warning<
- "%0 is always %select{zero|false|NULL}1 in this context">;
+def warn_ivar_variable_conflict : Warning<
+ "when default property synthesis is on, "
+ "%0 lookup will access property ivar instead of global variable">,
+ InGroup<NonfragileAbi2>;
+def note_global_declared_at : Note<"global variable declared here">;
// assignment related diagnostics (also for argument passing, returning, etc).
// In most of these diagnostics the %2 is a value from the
@@ -2648,6 +2709,8 @@ def err_typecheck_cond_expect_scalar : Error<
"used type %0 where arithmetic or pointer type is required">;
def ext_typecheck_cond_one_void : Extension<
"C99 forbids conditional expressions with only one void side">;
+def err_typecheck_cast_to_incomplete : Error<
+ "cast to incomplete type %0">;
def ext_typecheck_cast_nonscalar : Extension<
"C99 forbids casting nonscalar type %0 to the same type">;
def ext_typecheck_cast_to_union : Extension<"C99 forbids casts to union type">;
@@ -2885,7 +2948,7 @@ def err_operator_new_default_arg: Error<
def err_operator_delete_dependent_param_type : Error<
"%0 cannot take a dependent type as first parameter; use %1 instead">;
def err_operator_delete_param_type : Error<
- "%0 takes type %1 as first parameter">;
+ "first parameter of %0 must have type %1">;
// C++ literal operators
def err_literal_operator_outside_namespace : Error<
@@ -2932,33 +2995,36 @@ def warn_printf_insufficient_data_args : Warning<
"more '%%' conversions than data arguments">, InGroup<Format>;
def warn_printf_data_arg_not_used : Warning<
"data argument not used by format string">, InGroup<FormatExtraArgs>;
-def warn_printf_invalid_conversion : Warning<
+def warn_format_invalid_conversion : Warning<
"invalid conversion specifier '%0'">, InGroup<Format>;
def warn_printf_incomplete_specifier : Warning<
"incomplete format specifier">, InGroup<Format>;
-def warn_printf_missing_format_string : Warning<
+def warn_missing_format_string : Warning<
"format string missing">, InGroup<Format>;
+def warn_scanf_nonzero_width : Warning<
+ "zero field width in scanf format string is unused">,
+ InGroup<Format>;
def warn_printf_conversion_argument_type_mismatch : Warning<
"conversion specifies type %0 but the argument has type %1">,
InGroup<Format>;
def warn_printf_positional_arg_exceeds_data_args : Warning <
"data argument position '%0' exceeds the number of data arguments (%1)">,
InGroup<Format>;
-def warn_printf_zero_positional_specifier : Warning<
+def warn_format_zero_positional_specifier : Warning<
"position arguments in format strings start counting at 1 (not 0)">,
InGroup<Format>;
-def warn_printf_invalid_positional_specifier : Warning<
+def warn_format_invalid_positional_specifier : Warning<
"invalid position specified for %select{field width|field precision}0">,
InGroup<Format>;
-def warn_printf_mix_positional_nonpositional_args : Warning<
+def warn_format_mix_positional_nonpositional_args : Warning<
"cannot mix positional and non-positional arguments in format string">,
InGroup<Format>;
def warn_null_arg : Warning<
"null passed to a callee which requires a non-null argument">,
InGroup<NonNull>;
-def warn_printf_empty_format_string : Warning<
+def warn_empty_format_string : Warning<
"format string is empty">, InGroup<FormatZeroLength>;
-def warn_printf_format_string_is_wide_literal : Warning<
+def warn_format_string_is_wide_literal : Warning<
"format string should not be a wide string">, InGroup<Format>;
def warn_printf_format_string_contains_null_char : Warning<
"format string contains '\\0' within the string body">, InGroup<Format>;
@@ -2973,12 +3039,15 @@ def warn_printf_nonsensical_optional_amount: Warning<
def warn_printf_nonsensical_flag: Warning<
"flag '%0' results in undefined behavior with '%1' conversion specifier">,
InGroup<Format>;
-def warn_printf_nonsensical_length: Warning<
+def warn_format_nonsensical_length: Warning<
"length modifier '%0' results in undefined behavior or no effect with '%1' conversion specifier">,
InGroup<Format>;
def warn_printf_ignored_flag: Warning<
"flag '%0' is ignored when flag '%1' is present">,
InGroup<Format>;
+def warn_scanf_scanlist_incomplete : Warning<
+ "no closing ']' for '%%[' in scanf format string">,
+ InGroup<Format>;
// CHECK: returning address/reference of stack memory
def warn_ret_stack_addr : Warning<
@@ -2995,7 +3064,8 @@ def err_ret_local_block : Error<
// should result in a warning, since these always evaluate to a constant.
// Array comparisons have similar warnings
def warn_comparison_always : Warning<
- "%select{self-|array }0comparison always evaluates to %select{false|true|a constant}1">;
+ "%select{self-|array }0comparison always evaluates to %select{false|true|a constant}1">,
+ InGroup<DiagGroup<"tautological-compare">>;
def warn_stringcompare : Warning<
"result of comparison against %select{a string literal|@encode}0 is "
@@ -3127,6 +3197,8 @@ def err_selector_element_type : Error<
"selector element type %0 is not a valid object">;
def err_collection_expr_type : Error<
"collection expression type %0 is not a valid object">;
+def warn_collection_expr_type : Warning<
+ "collection expression type %0 may not respond to %1">;
def err_invalid_conversion_between_ext_vectors : Error<
"invalid conversion between ext-vector type %0 and %1">;
diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h
index 6b8bcdc52f6f..24fe086a79e9 100644
--- a/include/clang/Basic/IdentifierTable.h
+++ b/include/clang/Basic/IdentifierTable.h
@@ -59,7 +59,11 @@ class IdentifierInfo {
bool IsPoisoned : 1; // True if identifier is poisoned.
bool IsCPPOperatorKeyword : 1; // True if ident is a C++ operator keyword.
bool NeedsHandleIdentifier : 1; // See "RecomputeNeedsHandleIdentifier".
- // 9 bits left in 32-bit word.
+ bool IsFromAST : 1; // True if identfier first appeared in an AST
+ // file and wasn't modified since.
+ bool RevertedTokenID : 1; // True if RevertTokenIDToIdentifier was
+ // called.
+ // 7 bits left in 32-bit word.
void *FETokenInfo; // Managed by the language front-end.
llvm::StringMapEntry<IdentifierInfo*> *Entry;
@@ -125,13 +129,28 @@ public:
NeedsHandleIdentifier = 1;
else
RecomputeNeedsHandleIdentifier();
+ IsFromAST = false;
}
- /// get/setTokenID - If this is a source-language token (e.g. 'for'), this API
+ /// getTokenID - If this is a source-language token (e.g. 'for'), this API
/// can be used to cause the lexer to map identifiers to source-language
/// tokens.
tok::TokenKind getTokenID() const { return (tok::TokenKind)TokenID; }
- void setTokenID(tok::TokenKind ID) { TokenID = ID; }
+
+ /// \brief True if RevertTokenIDToIdentifier() was called.
+ bool hasRevertedTokenIDToIdentifier() const { return RevertedTokenID; }
+
+ /// \brief Revert TokenID to tok::identifier; used for GNU libstdc++ 4.2
+ /// compatibility.
+ ///
+ /// TokenID is normally read-only but there are 2 instances where we revert it
+ /// to tok::identifier for libstdc++ 4.2. Keep track of when this happens
+ /// using this method so we can inform serialization about it.
+ void RevertTokenIDToIdentifier() {
+ assert(TokenID != tok::identifier && "Already at tok::identifier");
+ TokenID = tok::identifier;
+ RevertedTokenID = true;
+ }
/// getPPKeywordID - Return the preprocessor keyword ID for this identifier.
/// For example, "define" will return tok::pp_define.
@@ -186,6 +205,7 @@ public:
NeedsHandleIdentifier = 1;
else
RecomputeNeedsHandleIdentifier();
+ IsFromAST = false;
}
/// isPoisoned - Return true if this token has been poisoned.
@@ -213,6 +233,12 @@ public:
/// know that HandleIdentifier will not affect the token.
bool isHandleIdentifierCase() const { return NeedsHandleIdentifier; }
+ /// isFromAST - Return true if the identifier in its current state was loaded
+ /// from an AST file.
+ bool isFromAST() const { return IsFromAST; }
+
+ void setIsFromAST(bool FromAST = true) { IsFromAST = FromAST; }
+
private:
/// RecomputeNeedsHandleIdentifier - The Preprocessor::HandleIdentifier does
/// several special (but rare) things to identifiers of various sorts. For
@@ -313,6 +339,12 @@ public:
return *II;
}
+ IdentifierInfo &get(llvm::StringRef Name, tok::TokenKind TokenCode) {
+ IdentifierInfo &II = get(Name);
+ II.TokenID = TokenCode;
+ return II;
+ }
+
IdentifierInfo &get(const char *NameStart, const char *NameEnd) {
return get(llvm::StringRef(NameStart, NameEnd-NameStart));
}
@@ -321,35 +353,33 @@ public:
return get(llvm::StringRef(Name, NameLen));
}
- /// \brief Creates a new IdentifierInfo from the given string.
+ /// \brief Gets an IdentifierInfo for the given name without consulting
+ /// external sources.
///
- /// This is a lower-level version of get() that requires that this
- /// identifier not be known previously and that does not consult an
- /// external source for identifiers. In particular, external
- /// identifier sources can use this routine to build IdentifierInfo
- /// nodes and then introduce additional information about those
- /// identifiers.
- IdentifierInfo &CreateIdentifierInfo(const char *NameStart,
- const char *NameEnd) {
+ /// This is a version of get() meant for external sources that want to
+ /// introduce or modify an identifier. If they called get(), they would
+ /// likely end up in a recursion.
+ IdentifierInfo &getOwn(const char *NameStart, const char *NameEnd) {
llvm::StringMapEntry<IdentifierInfo*> &Entry =
HashTable.GetOrCreateValue(NameStart, NameEnd);
IdentifierInfo *II = Entry.getValue();
- assert(!II && "IdentifierInfo already exists");
+ if (!II) {
- // Lookups failed, make a new IdentifierInfo.
- void *Mem = getAllocator().Allocate<IdentifierInfo>();
- II = new (Mem) IdentifierInfo();
- Entry.setValue(II);
+ // Lookups failed, make a new IdentifierInfo.
+ void *Mem = getAllocator().Allocate<IdentifierInfo>();
+ II = new (Mem) IdentifierInfo();
+ Entry.setValue(II);
- // Make sure getName() knows how to find the IdentifierInfo
- // contents.
- II->Entry = &Entry;
+ // Make sure getName() knows how to find the IdentifierInfo
+ // contents.
+ II->Entry = &Entry;
+ }
return *II;
}
- IdentifierInfo &CreateIdentifierInfo(llvm::StringRef Name) {
- return CreateIdentifierInfo(Name.begin(), Name.end());
+ IdentifierInfo &getOwn(llvm::StringRef Name) {
+ return getOwn(Name.begin(), Name.end());
}
typedef HashTableTy::const_iterator iterator;
diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h
index bbcceb70ac91..5bd0d04a4eea 100644
--- a/include/clang/Basic/LangOptions.h
+++ b/include/clang/Basic/LangOptions.h
@@ -34,6 +34,7 @@ public:
unsigned HexFloats : 1; // C99 Hexadecimal float constants.
unsigned C99 : 1; // C99 Support
unsigned Microsoft : 1; // Microsoft extensions.
+ unsigned Borland : 1; // Borland extensions.
unsigned CPlusPlus : 1; // C++ Support
unsigned CPlusPlus0x : 1; // C++0x Support
unsigned CXXOperatorNames : 1; // Treat C++ operator names as keywords.
@@ -140,7 +141,7 @@ public:
HexFloats = 0;
GC = ObjC1 = ObjC2 = ObjCNonFragileABI = ObjCNonFragileABI2 = 0;
NoConstantCFStrings = 0; InlineVisibilityHidden = 0;
- C99 = Microsoft = CPlusPlus = CPlusPlus0x = 0;
+ C99 = Microsoft = Borland = CPlusPlus = CPlusPlus0x = 0;
CXXOperatorNames = PascalStrings = WritableStrings = ConstStrings = 0;
Exceptions = SjLjExceptions = Freestanding = NoBuiltin = 0;
NeXTRuntime = 1;
diff --git a/include/clang/Basic/Linkage.h b/include/clang/Basic/Linkage.h
index de0de348d351..01b6c790428a 100644
--- a/include/clang/Basic/Linkage.h
+++ b/include/clang/Basic/Linkage.h
@@ -41,6 +41,17 @@ enum Linkage {
ExternalLinkage
};
+/// \brief A more specific kind of linkage. This is relevant to CodeGen and
+/// AST file reading.
+enum GVALinkage {
+ GVA_Internal,
+ GVA_C99Inline,
+ GVA_CXXInline,
+ GVA_StrongExternal,
+ GVA_TemplateInstantiation,
+ GVA_ExplicitTemplateInstantiation
+};
+
/// \brief Determine whether the given linkage is semantically
/// external.
inline bool isExternalLinkage(Linkage L) {
diff --git a/include/clang/Basic/Makefile b/include/clang/Basic/Makefile
index 7db3e2982af4..bc64f6aab555 100644
--- a/include/clang/Basic/Makefile
+++ b/include/clang/Basic/Makefile
@@ -16,6 +16,7 @@ INPUT_TDS = $(wildcard $(PROJ_SRC_DIR)/Diagnostic*.td)
# Compute the Clang version from the LLVM version, unless specified explicitly.
ifndef CLANG_VERSION
CLANG_VERSION := $(subst svn,,$(LLVMVersion))
+CLANG_VERSION := $(subst rc,,$(CLANG_VERSION))
endif
CLANG_VERSION_COMPONENTS := $(subst ., ,$(CLANG_VERSION))
diff --git a/include/clang/Basic/OnDiskHashTable.h b/include/clang/Basic/OnDiskHashTable.h
index 2019e27ce5de..8909e47146a7 100644
--- a/include/clang/Basic/OnDiskHashTable.h
+++ b/include/clang/Basic/OnDiskHashTable.h
@@ -124,8 +124,9 @@ class OnDiskChainedHashTableGenerator {
Item *next;
const uint32_t hash;
- Item(typename Info::key_type_ref k, typename Info::data_type_ref d)
- : key(k), data(d), next(0), hash(Info::ComputeHash(k)) {}
+ Item(typename Info::key_type_ref k, typename Info::data_type_ref d,
+ Info &InfoObj)
+ : key(k), data(d), next(0), hash(InfoObj.ComputeHash(k)) {}
};
class Bucket {
@@ -168,10 +169,17 @@ public:
void insert(typename Info::key_type_ref key,
typename Info::data_type_ref data) {
+ Info InfoObj;
+ insert(key, data, InfoObj);
+ }
+
+ void insert(typename Info::key_type_ref key,
+ typename Info::data_type_ref data, Info &InfoObj) {
++NumEntries;
if (4*NumEntries >= 3*NumBuckets) resize(NumBuckets*2);
- insert(Buckets, NumBuckets, new (BA.Allocate<Item>()) Item(key, data));
+ insert(Buckets, NumBuckets, new (BA.Allocate<Item>()) Item(key, data,
+ InfoObj));
}
io::Offset Emit(llvm::raw_ostream &out) {
@@ -278,8 +286,8 @@ public:
InfoPtr = &InfoObj;
using namespace io;
- const internal_key_type& iKey = Info::GetInternalKey(eKey);
- unsigned key_hash = Info::ComputeHash(iKey);
+ const internal_key_type& iKey = InfoObj.GetInternalKey(eKey);
+ unsigned key_hash = InfoObj.ComputeHash(iKey);
// Each bucket is just a 32-bit offset into the hash table file.
unsigned idx = key_hash & (NumBuckets - 1);
@@ -326,6 +334,71 @@ public:
iterator end() const { return iterator(); }
+ /// \brief Iterates over all the entries in the table, returning
+ /// a key/data pair.
+ class item_iterator {
+ const unsigned char* Ptr;
+ unsigned NumItemsInBucketLeft;
+ unsigned NumEntriesLeft;
+ Info *InfoObj;
+ public:
+ typedef std::pair<external_key_type, data_type> value_type;
+
+ item_iterator(const unsigned char* const Ptr, unsigned NumEntries,
+ Info *InfoObj)
+ : Ptr(Ptr), NumItemsInBucketLeft(0), NumEntriesLeft(NumEntries),
+ InfoObj(InfoObj) { }
+ item_iterator()
+ : Ptr(0), NumItemsInBucketLeft(0), NumEntriesLeft(0), InfoObj(0) { }
+
+ bool operator==(const item_iterator& X) const {
+ return X.NumEntriesLeft == NumEntriesLeft;
+ }
+ bool operator!=(const item_iterator& X) const {
+ return X.NumEntriesLeft != NumEntriesLeft;
+ }
+
+ item_iterator& operator++() { // Preincrement
+ if (!NumItemsInBucketLeft) {
+ // 'Items' starts with a 16-bit unsigned integer representing the
+ // number of items in this bucket.
+ NumItemsInBucketLeft = io::ReadUnalignedLE16(Ptr);
+ }
+ Ptr += 4; // Skip the hash.
+ // Determine the length of the key and the data.
+ const std::pair<unsigned, unsigned>& L = Info::ReadKeyDataLength(Ptr);
+ Ptr += L.first + L.second;
+ assert(NumItemsInBucketLeft);
+ --NumItemsInBucketLeft;
+ assert(NumEntriesLeft);
+ --NumEntriesLeft;
+ return *this;
+ }
+ item_iterator operator++(int) { // Postincrement
+ item_iterator tmp = *this; ++*this; return tmp;
+ }
+
+ value_type operator*() const {
+ const unsigned char* LocalPtr = Ptr;
+ if (!NumItemsInBucketLeft)
+ LocalPtr += 2; // number of items in bucket
+ LocalPtr += 4; // Skip the hash.
+
+ // Determine the length of the key and the data.
+ const std::pair<unsigned, unsigned>& L = Info::ReadKeyDataLength(LocalPtr);
+
+ // Read the key.
+ const internal_key_type& Key =
+ InfoObj->ReadKey(LocalPtr, L.first);
+ return std::make_pair(InfoObj->GetExternalKey(Key),
+ InfoObj->ReadData(Key, LocalPtr + L.first, L.second));
+ }
+ };
+
+ item_iterator item_begin() {
+ return item_iterator(Base + 4, getNumEntries(), &InfoObj);
+ }
+ item_iterator item_end() { return item_iterator(); }
static OnDiskChainedHashTable* Create(const unsigned char* buckets,
const unsigned char* const base,
diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h
index 6a4be4609433..7a66117f2076 100644
--- a/include/clang/Basic/SourceManager.h
+++ b/include/clang/Basic/SourceManager.h
@@ -50,13 +50,20 @@ namespace SrcMgr {
C_User, C_System, C_ExternCSystem
};
- /// ContentCache - Once instance of this struct is kept for every file
+ /// ContentCache - One instance of this struct is kept for every file
/// loaded or used. This object owns the MemoryBuffer object.
class ContentCache {
+ enum CCFlags {
+ /// \brief Whether the buffer is invalid.
+ InvalidFlag = 0x01,
+ /// \brief Whether the buffer should not be freed on destruction.
+ DoNotFreeFlag = 0x02
+ };
+
/// Buffer - The actual buffer containing the characters from the input
/// file. This is owned by the ContentCache object.
- /// The bit indicates whether the buffer is invalid.
- mutable llvm::PointerIntPair<const llvm::MemoryBuffer *, 1, bool> Buffer;
+ /// The bits indicate indicates whether the buffer is invalid.
+ mutable llvm::PointerIntPair<const llvm::MemoryBuffer *, 2> Buffer;
public:
/// Reference to the file entry. This reference does not own
@@ -103,11 +110,27 @@ namespace SrcMgr {
Buffer.setPointer(B);
Buffer.setInt(false);
}
+
+ /// \brief Get the underlying buffer, returning NULL if the buffer is not
+ /// yet available.
+ const llvm::MemoryBuffer *getRawBuffer() const {
+ return Buffer.getPointer();
+ }
/// \brief Replace the existing buffer (which will be deleted)
/// with the given buffer.
- void replaceBuffer(const llvm::MemoryBuffer *B);
+ void replaceBuffer(const llvm::MemoryBuffer *B, bool DoNotFree = false);
+ /// \brief Determine whether the buffer itself is invalid.
+ bool isBufferInvalid() const {
+ return Buffer.getInt() & InvalidFlag;
+ }
+
+ /// \brief Determine whether the buffer should be freed.
+ bool shouldFreeBuffer() const {
+ return (Buffer.getInt() & DoNotFreeFlag) == 0;
+ }
+
ContentCache(const FileEntry *Ent = 0)
: Buffer(0, false), Entry(Ent), SourceLineCache(0), NumLines(0) {}
@@ -421,10 +444,9 @@ public:
FileID getMainFileID() const { return MainFileID; }
/// createMainFileID - Create the FileID for the main source file.
- FileID createMainFileID(const FileEntry *SourceFile,
- SourceLocation IncludePos) {
+ FileID createMainFileID(const FileEntry *SourceFile) {
assert(MainFileID.isInvalid() && "MainFileID already set!");
- MainFileID = createFileID(SourceFile, IncludePos, SrcMgr::C_User);
+ MainFileID = createFileID(SourceFile, SourceLocation(), SrcMgr::C_User);
return MainFileID;
}
@@ -435,7 +457,7 @@ public:
/// createFileID - Create a new FileID that represents the specified file
/// being #included from the specified IncludePosition. This returns 0 on
/// error and translates NULL into standard input.
- /// PreallocateID should be non-zero to specify which a pre-allocated,
+ /// PreallocateID should be non-zero to specify which pre-allocated,
/// lazily computed source location is being filled in by this operation.
FileID createFileID(const FileEntry *SourceFile, SourceLocation IncludePos,
SrcMgr::CharacteristicKind FileCharacter,
@@ -485,14 +507,18 @@ public:
/// \brief Override the contents of the given source file by providing an
/// already-allocated buffer.
///
- /// \param SourceFile the source file whose contents will be override.
+ /// \param SourceFile the source file whose contents will be overriden.
///
/// \param Buffer the memory buffer whose contents will be used as the
/// data in the given source file.
///
+ /// \param DoNotFree If true, then the buffer will not be freed when the
+ /// source manager is destroyed.
+ ///
/// \returns true if an error occurred, false otherwise.
bool overrideFileContents(const FileEntry *SourceFile,
- const llvm::MemoryBuffer *Buffer);
+ const llvm::MemoryBuffer *Buffer,
+ bool DoNotFree = false);
//===--------------------------------------------------------------------===//
// FileID manipulation methods.
@@ -768,7 +794,7 @@ public:
unsigned sloc_entry_size() const { return SLocEntryTable.size(); }
// FIXME: Exposing this is a little gross; what we want is a good way
- // to iterate the entries that were not defined in a PCH file (or
+ // to iterate the entries that were not defined in an AST file (or
// any other external source).
unsigned sloc_loaded_entry_size() const { return SLocEntryLoaded.size(); }
diff --git a/include/clang/Basic/Specifiers.h b/include/clang/Basic/Specifiers.h
index 9e54762add7d..e757a2f4a185 100644
--- a/include/clang/Basic/Specifiers.h
+++ b/include/clang/Basic/Specifiers.h
@@ -78,6 +78,68 @@ namespace clang {
AS_none
};
+ /// ExprValueKind - The categorization of expression values,
+ /// currently following the C++0x scheme.
+ enum ExprValueKind {
+ /// An r-value expression (a gr-value in the C++0x taxonomy)
+ /// produces a temporary value.
+ VK_RValue,
+
+ /// An l-value expression is a reference to an object with
+ /// independent storage.
+ VK_LValue,
+
+ /// An x-value expression is a reference to an object with
+ /// independent storage but which can be "moved", i.e.
+ /// efficiently cannibalized for its resources.
+ VK_XValue
+ };
+
+ // \brief Describes the kind of template specialization that a
+ // particular template specialization declaration represents.
+ enum TemplateSpecializationKind {
+ /// This template specialization was formed from a template-id but
+ /// has not yet been declared, defined, or instantiated.
+ TSK_Undeclared = 0,
+ /// This template specialization was implicitly instantiated from a
+ /// template. (C++ [temp.inst]).
+ TSK_ImplicitInstantiation,
+ /// This template specialization was declared or defined by an
+ /// explicit specialization (C++ [temp.expl.spec]) or partial
+ /// specialization (C++ [temp.class.spec]).
+ TSK_ExplicitSpecialization,
+ /// This template specialization was instantiated from a template
+ /// due to an explicit instantiation declaration request
+ /// (C++0x [temp.explicit]).
+ TSK_ExplicitInstantiationDeclaration,
+ /// This template specialization was instantiated from a template
+ /// due to an explicit instantiation definition request
+ /// (C++ [temp.explicit]).
+ TSK_ExplicitInstantiationDefinition
+ };
+
+ /// \brief Storage classes.
+ enum StorageClass {
+ // These are legal on both functions and variables.
+ SC_None,
+ SC_Extern,
+ SC_Static,
+ SC_PrivateExtern,
+
+ // These are only legal on variables.
+ SC_Auto,
+ SC_Register
+ };
+
+ /// Checks whether the given storage class is legal for functions.
+ inline bool isLegalForFunction(StorageClass SC) {
+ return SC <= SC_PrivateExtern;
+ }
+
+ /// Checks whether the given storage class is legal for variables.
+ inline bool isLegalForVariable(StorageClass SC) {
+ return true;
+ }
} // end namespace clang
#endif // LLVM_CLANG_BASIC_SPECIFIERS_H
diff --git a/include/clang/Basic/StmtNodes.td b/include/clang/Basic/StmtNodes.td
index a2f69730a010..4aa055e695e9 100644
--- a/include/clang/Basic/StmtNodes.td
+++ b/include/clang/Basic/StmtNodes.td
@@ -103,7 +103,6 @@ def UnaryTypeTraitExpr : DStmt<Expr>;
def DependentScopeDeclRefExpr : DStmt<Expr>;
def CXXConstructExpr : DStmt<Expr>;
def CXXBindTemporaryExpr : DStmt<Expr>;
-def CXXBindReferenceExpr : DStmt<Expr>;
def CXXExprWithTemporaries : DStmt<Expr>;
def CXXTemporaryObjectExpr : DStmt<CXXConstructExpr>;
def CXXUnresolvedConstructExpr : DStmt<Expr>;
diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h
index 9f7debf9c500..40df9ba11da4 100644
--- a/include/clang/Basic/TargetInfo.h
+++ b/include/clang/Basic/TargetInfo.h
@@ -16,6 +16,7 @@
// FIXME: Daniel isn't smart enough to use a prototype for this.
#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"
#include "llvm/System/DataTypes.h"
#include <cassert>
@@ -37,6 +38,22 @@ class TargetOptions;
namespace Builtin { struct Info; }
+/// TargetCXXABI - The types of C++ ABIs for which we can generate code.
+enum TargetCXXABI {
+ /// The generic ("Itanium") C++ ABI, documented at:
+ /// http://www.codesourcery.com/public/cxx-abi/
+ CXXABI_Itanium,
+
+ /// The ARM C++ ABI, based largely on the Itanium ABI but with
+ /// significant differences.
+ /// http://infocenter.arm.com
+ /// /help/topic/com.arm.doc.ihi0041c/IHI0041C_cppabi.pdf
+ CXXABI_ARM,
+
+ /// The Visual Studio ABI. Only scattered official documentation exists.
+ CXXABI_Microsoft
+};
+
/// TargetInfo - This class exposes information about the current target.
///
class TargetInfo {
@@ -58,7 +75,7 @@ protected:
const char *UserLabelPrefix;
const llvm::fltSemantics *FloatFormat, *DoubleFormat, *LongDoubleFormat;
unsigned char RegParmMax, SSERegParmMax;
- std::string CXXABI;
+ TargetCXXABI CXXABI;
unsigned HasAlignMac68kSupport : 1;
unsigned RealTypeUsesObjCFPRet : 3;
@@ -412,7 +429,7 @@ public:
}
/// getCXXABI - Get the C++ ABI in use.
- virtual llvm::StringRef getCXXABI() const {
+ virtual TargetCXXABI getCXXABI() const {
return CXXABI;
}
@@ -434,11 +451,23 @@ public:
/// setCXXABI - Use this specific C++ ABI.
///
- /// \return - False on error (invalid ABI name).
- virtual bool setCXXABI(const std::string &Name) {
- if (Name != "itanium" && Name != "microsoft")
- return false;
- CXXABI = Name;
+ /// \return - False on error (invalid C++ ABI name).
+ bool setCXXABI(const std::string &Name) {
+ static const TargetCXXABI Unknown = static_cast<TargetCXXABI>(-1);
+ TargetCXXABI ABI = llvm::StringSwitch<TargetCXXABI>(Name)
+ .Case("arm", CXXABI_ARM)
+ .Case("itanium", CXXABI_Itanium)
+ .Case("microsoft", CXXABI_Microsoft)
+ .Default(Unknown);
+ if (ABI == Unknown) return false;
+ return setCXXABI(ABI);
+ }
+
+ /// setCXXABI - Set the C++ ABI to be used by this implementation.
+ ///
+ /// \return - False on error (ABI not valid on this target)
+ virtual bool setCXXABI(TargetCXXABI ABI) {
+ CXXABI = ABI;
return true;
}
diff --git a/include/clang/Basic/TargetOptions.h b/include/clang/Basic/TargetOptions.h
index 19b0cbbf5820..f3c206f2cc96 100644
--- a/include/clang/Basic/TargetOptions.h
+++ b/include/clang/Basic/TargetOptions.h
@@ -18,11 +18,6 @@ namespace clang {
/// TargetOptions - Options for controlling the target.
class TargetOptions {
public:
-
- TargetOptions() {
- CXXABI = "itanium";
- }
-
/// If given, the name of the target triple to compile for. If not given the
/// target will be selected to match the host.
std::string Triple;
@@ -37,6 +32,9 @@ public:
/// to "itanium".
std::string CXXABI;
+ /// If given, the version string of the linker in use.
+ std::string LinkerVersion;
+
/// The list of target specific features to enable or disable -- this should
/// be a list of strings starting with by '+' or '-'.
std::vector<std::string> Features;
diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def
index b16b82854b1c..dc360adf8f19 100644
--- a/include/clang/Basic/TokenKinds.def
+++ b/include/clang/Basic/TokenKinds.def
@@ -96,6 +96,7 @@ TOK(unknown) // Not a token.
TOK(eof) // End of file.
TOK(eom) // End of macro (end of line inside a macro).
TOK(code_completion) // Code completion marker
+TOK(cxx_defaultarg_end) // C++ default argument end marker
// C99 6.4.9: Comments.
TOK(comment) // Comment (only in -E -C[C] mode)
@@ -185,6 +186,7 @@ PUNCTUATOR(at, "@")
// KEYCXX0X - This is a C++ keyword introduced to C++ in C++0x
// KEYGNU - This is a keyword if GNU extensions are enabled
// KEYMS - This is a keyword if Microsoft extensions are enabled
+// KEYBORLAND - This is a keyword if Borland extensions are enabled
//
KEYWORD(auto , KEYALL)
KEYWORD(break , KEYALL)
@@ -272,16 +274,11 @@ CXX_KEYWORD_OPERATOR(xor_eq , caretequal)
// C++0x keywords
KEYWORD(alignof , KEYCXX0X)
-KEYWORD(axiom , KEYCXX0X)
KEYWORD(char16_t , KEYCXX0X)
KEYWORD(char32_t , KEYCXX0X)
-KEYWORD(concept , KEYCXX0X)
-KEYWORD(concept_map , KEYCXX0X)
KEYWORD(constexpr , KEYCXX0X)
KEYWORD(decltype , KEYCXX0X)
-KEYWORD(late_check , KEYCXX0X)
KEYWORD(nullptr , KEYCXX0X)
-KEYWORD(requires , KEYCXX0X)
KEYWORD(static_assert , KEYCXX0X)
KEYWORD(thread_local , KEYCXX0X)
@@ -339,6 +336,9 @@ KEYWORD(__fastcall , KEYALL)
KEYWORD(__thiscall , KEYALL)
KEYWORD(__forceinline , KEYALL)
+// Borland Extension.
+KEYWORD(__pascal , KEYALL)
+
// Altivec Extension.
KEYWORD(__vector , KEYALTIVEC)
KEYWORD(__pixel , KEYALTIVEC)
@@ -375,6 +375,9 @@ ALIAS("_fastcall" , __fastcall , KEYMS)
ALIAS("_stdcall" , __stdcall , KEYMS)
ALIAS("_thiscall" , __thiscall , KEYMS)
+// Borland Extensions which should be disabled in strict conformance mode.
+ALIAS("_pascal" , __pascal , KEYBORLAND)
+
//===----------------------------------------------------------------------===//
// Objective-C @-preceeded keywords.
//===----------------------------------------------------------------------===//
diff --git a/include/clang/Basic/arm_neon.td b/include/clang/Basic/arm_neon.td
index b42755ca72ae..fa6ebb756ca3 100644
--- a/include/clang/Basic/arm_neon.td
+++ b/include/clang/Basic/arm_neon.td
@@ -64,6 +64,7 @@ class WInst<string p, string t> : Inst<p, t, OP_NONE> {}
// u: unsigned integer (int/float args)
// f: float (int args)
// d: default
+// g: default, ignore 'Q' size modifier.
// w: double width elements, same num elts
// n: double width elements, half num elts
// h: half width elements, double num elts
@@ -239,6 +240,7 @@ def VCREATE: Inst<"dl", "csihfUcUsUiUlPcPsl", OP_CAST>;
// E.3.19 Set all lanes to same value
def VDUP_N : Inst<"ds", "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl", OP_DUP>;
def VMOV_N : Inst<"ds", "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl", OP_DUP>;
+def VDUP_LANE : WInst<"dgi", "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl">;
////////////////////////////////////////////////////////////////////////////////
// E.3.20 Combining vectors
diff --git a/include/clang/CMakeLists.txt b/include/clang/CMakeLists.txt
index c2880481a2e9..e82cf429eecc 100644
--- a/include/clang/CMakeLists.txt
+++ b/include/clang/CMakeLists.txt
@@ -1,3 +1,4 @@
add_subdirectory(AST)
add_subdirectory(Basic)
add_subdirectory(Driver)
+add_subdirectory(Serialization)
diff --git a/include/clang/Checker/BugReporter/BugReporter.h b/include/clang/Checker/BugReporter/BugReporter.h
index 3749b43d7e23..370d96552c45 100644
--- a/include/clang/Checker/BugReporter/BugReporter.h
+++ b/include/clang/Checker/BugReporter/BugReporter.h
@@ -471,6 +471,9 @@ void registerFindLastStore(BugReporterContext& BRC, const void *memregion,
void registerNilReceiverVisitor(BugReporterContext &BRC);
+void registerVarDeclsLastStore(BugReporterContext &BRC, const void *stmt,
+ const ExplodedNode *N);
+
} // end namespace clang::bugreporter
//===----------------------------------------------------------------------===//
diff --git a/include/clang/Checker/PathSensitive/AnalysisManager.h b/include/clang/Checker/PathSensitive/AnalysisManager.h
index 3c7cb68c0943..38550798b812 100644
--- a/include/clang/Checker/PathSensitive/AnalysisManager.h
+++ b/include/clang/Checker/PathSensitive/AnalysisManager.h
@@ -21,6 +21,11 @@
namespace clang {
+namespace idx {
+ class Indexer;
+ class TranslationUnit;
+}
+
class AnalysisManager : public BugReporterData {
AnalysisContextManager AnaCtxMgr;
LocationContextManager LocCtxMgr;
@@ -35,6 +40,11 @@ class AnalysisManager : public BugReporterData {
StoreManagerCreator CreateStoreMgr;
ConstraintManagerCreator CreateConstraintMgr;
+ /// \brief Provide function definitions in other translation units. This is
+ /// NULL if we don't have multiple translation units. AnalysisManager does
+ /// not own the Indexer.
+ idx::Indexer *Idxer;
+
enum AnalysisScope { ScopeTU, ScopeDecl } AScope;
// The maximum number of exploded nodes the analyzer will generate.
@@ -62,13 +72,15 @@ public:
AnalysisManager(ASTContext &ctx, Diagnostic &diags,
const LangOptions &lang, PathDiagnosticClient *pd,
StoreManagerCreator storemgr,
- ConstraintManagerCreator constraintmgr, unsigned maxnodes,
- unsigned maxloop,
+ ConstraintManagerCreator constraintmgr,
+ idx::Indexer *idxer,
+ unsigned maxnodes, unsigned maxloop,
bool vizdot, bool vizubi, bool purge, bool eager, bool trim,
- bool inlinecall)
+ bool inlinecall, bool useUnoptimizedCFG)
- : Ctx(ctx), Diags(diags), LangInfo(lang), PD(pd),
- CreateStoreMgr(storemgr), CreateConstraintMgr(constraintmgr),
+ : AnaCtxMgr(useUnoptimizedCFG), Ctx(ctx), Diags(diags), LangInfo(lang),
+ PD(pd),
+ CreateStoreMgr(storemgr), CreateConstraintMgr(constraintmgr),Idxer(idxer),
AScope(ScopeDecl), MaxNodes(maxnodes), MaxLoop(maxloop),
VisualizeEGDot(vizdot), VisualizeEGUbi(vizubi), PurgeDead(purge),
EagerlyAssume(eager), TrimGraph(trim), InlineCall(inlinecall) {}
@@ -79,6 +91,10 @@ public:
LocCtxMgr.clear();
AnaCtxMgr.clear();
}
+
+ AnalysisContextManager& getAnalysisContextManager() {
+ return AnaCtxMgr;
+ }
StoreManagerCreator getStoreManagerCreator() {
return CreateStoreMgr;
@@ -88,6 +104,8 @@ public:
return CreateConstraintMgr;
}
+ idx::Indexer *getIndexer() const { return Idxer; }
+
virtual ASTContext &getASTContext() {
return Ctx;
}
@@ -133,6 +151,10 @@ public:
bool shouldInlineCall() const { return InlineCall; }
+ bool hasIndexer() const { return Idxer != 0; }
+
+ const AnalysisContext *getAnalysisContextInAnotherTU(const Decl *D);
+
CFG *getCFG(Decl const *D) {
return AnaCtxMgr.getContext(D)->getCFG();
}
@@ -145,9 +167,25 @@ public:
return AnaCtxMgr.getContext(D)->getParentMap();
}
+ AnalysisContext *getAnalysisContext(const Decl *D) {
+ return AnaCtxMgr.getContext(D);
+ }
+
+ AnalysisContext *getAnalysisContext(const Decl *D, idx::TranslationUnit *TU) {
+ return AnaCtxMgr.getContext(D, TU);
+ }
+
+ const StackFrameContext *getStackFrame(AnalysisContext *Ctx,
+ LocationContext const *Parent,
+ Stmt const *S, const CFGBlock *Blk,
+ unsigned Idx) {
+ return LocCtxMgr.getStackFrame(Ctx, Parent, S, Blk, Idx);
+ }
+
// Get the top level stack frame.
- const StackFrameContext *getStackFrame(Decl const *D) {
- return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D), 0, 0, 0, 0);
+ const StackFrameContext *getStackFrame(Decl const *D,
+ idx::TranslationUnit *TU) {
+ return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D, TU), 0, 0, 0, 0);
}
// Get a stack frame with parent.
diff --git a/include/clang/Checker/PathSensitive/Checker.h b/include/clang/Checker/PathSensitive/Checker.h
index 49dc3fa7dc44..136a29da5f2a 100644
--- a/include/clang/Checker/PathSensitive/Checker.h
+++ b/include/clang/Checker/PathSensitive/Checker.h
@@ -36,7 +36,6 @@ class CheckerContext {
const GRState *ST;
const Stmt *statement;
const unsigned size;
- bool DoneEvaluating; // FIXME: This is not a permanent API change.
public:
bool *respondsToCallback;
public:
@@ -166,6 +165,10 @@ public:
Eng.getBugReporter().EmitReport(R);
}
+ AnalysisContext *getCurrentAnalysisContext() const {
+ return Pred->getLocationContext()->getAnalysisContext();
+ }
+
private:
ExplodedNode *GenerateNodeImpl(const Stmt* stmt, const GRState *state,
bool markAsSink) {
@@ -223,7 +226,6 @@ private:
// FIXME: Remove the 'tag' option.
void GR_VisitBind(ExplodedNodeSet &Dst,
GRStmtNodeBuilder &Builder, GRExprEngine &Eng,
- const Stmt *AssignE,
const Stmt *StoreE, ExplodedNode *Pred, void *tag,
SVal location, SVal val,
bool isPrevisit) {
@@ -231,7 +233,7 @@ private:
isPrevisit ? ProgramPoint::PreStmtKind :
ProgramPoint::PostStmtKind, 0, StoreE);
assert(isPrevisit && "Only previsit supported for now.");
- PreVisitBind(C, AssignE, StoreE, location, val);
+ PreVisitBind(C, StoreE, location, val);
}
// FIXME: Remove the 'tag' option.
@@ -261,15 +263,17 @@ public:
virtual void _PreVisit(CheckerContext &C, const Stmt *S) {}
virtual void _PostVisit(CheckerContext &C, const Stmt *S) {}
virtual void VisitLocation(CheckerContext &C, const Stmt *S, SVal location) {}
- virtual void PreVisitBind(CheckerContext &C, const Stmt *AssignE,
- const Stmt *StoreE, SVal location, SVal val) {}
+ virtual void PreVisitBind(CheckerContext &C, const Stmt *StoreE,
+ SVal location, SVal val) {}
virtual void EvalDeadSymbols(CheckerContext &C, SymbolReaper &SymReaper) {}
virtual void EvalEndPath(GREndPathNodeBuilder &B, void *tag,
GRExprEngine &Eng) {}
+ virtual void MarkLiveSymbols(const GRState *state, SymbolReaper &SymReaper) {}
+
virtual void VisitBranchCondition(GRBranchNodeBuilder &Builder,
GRExprEngine &Eng,
- Stmt *Condition, void *tag) {}
+ const Stmt *Condition, void *tag) {}
virtual bool EvalNilReceiver(CheckerContext &C, const ObjCMessageExpr *ME) {
return false;
@@ -280,12 +284,23 @@ public:
}
virtual const GRState *EvalAssume(const GRState *state, SVal Cond,
- bool Assumption) {
+ bool Assumption, bool *respondsToCallback) {
+ *respondsToCallback = false;
+ return state;
+ }
+
+ virtual bool WantsRegionChangeUpdate(const GRState *state) { return false; }
+
+ virtual const GRState *EvalRegionChanges(const GRState *state,
+ const MemRegion * const *Begin,
+ const MemRegion * const *End,
+ bool *respondsToCallback) {
+ *respondsToCallback = false;
return state;
}
virtual void VisitEndAnalysis(ExplodedGraph &G, BugReporter &B,
- bool hasWorkRemaining) {}
+ GRExprEngine &Eng) {}
};
} // end clang namespace
diff --git a/include/clang/Checker/PathSensitive/CheckerHelpers.h b/include/clang/Checker/PathSensitive/CheckerHelpers.h
new file mode 100644
index 000000000000..ea3c842ffc1f
--- /dev/null
+++ b/include/clang/Checker/PathSensitive/CheckerHelpers.h
@@ -0,0 +1,40 @@
+//== CheckerHelpers.h - Helper functions for checkers ------------*- 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 CheckerVisitor.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CHECKER_PATHSENSITIVE_CHECKERHELPERS
+#define LLVM_CLANG_CHECKER_PATHSENSITIVE_CHECKERHELPERS
+
+#include "clang/AST/Stmt.h"
+
+namespace clang {
+
+bool containsMacro(const Stmt *S);
+bool containsEnum(const Stmt *S);
+bool containsStaticLocal(const Stmt *S);
+bool containsBuiltinOffsetOf(const Stmt *S);
+template <class T> bool containsStmt(const Stmt *S) {
+ if (isa<T>(S))
+ return true;
+
+ for (Stmt::const_child_iterator I = S->child_begin(); I != S->child_end();
+ ++I)
+ if (const Stmt *child = *I)
+ if (containsStmt<T>(child))
+ return true;
+
+ return false;
+}
+
+}
+
+#endif
diff --git a/include/clang/Checker/PathSensitive/ConstraintManager.h b/include/clang/Checker/PathSensitive/ConstraintManager.h
index ce7d1b381714..97535f55bfb9 100644
--- a/include/clang/Checker/PathSensitive/ConstraintManager.h
+++ b/include/clang/Checker/PathSensitive/ConstraintManager.h
@@ -34,9 +34,6 @@ public:
virtual const GRState *Assume(const GRState *state, DefinedSVal Cond,
bool Assumption) = 0;
- virtual const GRState *AssumeInBound(const GRState *state, DefinedSVal Idx,
- DefinedSVal UpperBound, bool Assumption) = 0;
-
std::pair<const GRState*, const GRState*> AssumeDual(const GRState *state,
DefinedSVal Cond) {
return std::make_pair(Assume(state, Cond, true),
diff --git a/include/clang/Checker/PathSensitive/Environment.h b/include/clang/Checker/PathSensitive/Environment.h
index 2981731f863c..611f5079452a 100644
--- a/include/clang/Checker/PathSensitive/Environment.h
+++ b/include/clang/Checker/PathSensitive/Environment.h
@@ -83,8 +83,14 @@ public:
return Environment(F.GetEmptyMap());
}
- Environment BindExpr(Environment Env, const Stmt *S, SVal V,
+ /// Bind the value 'V' to the statement 'S'.
+ Environment bindExpr(Environment Env, const Stmt *S, SVal V,
bool Invalidate);
+
+ /// Bind the location 'location' and value 'V' to the statement 'S'. This
+ /// is used when simulating loads/stores.
+ Environment bindExprAndLocation(Environment Env, const Stmt *S, SVal location,
+ SVal V);
Environment RemoveDeadBindings(Environment Env,
SymbolReaper &SymReaper, const GRState *ST,
diff --git a/include/clang/Checker/PathSensitive/GRCoreEngine.h b/include/clang/Checker/PathSensitive/GRCoreEngine.h
index 7f101dca97e5..216ecac73653 100644
--- a/include/clang/Checker/PathSensitive/GRCoreEngine.h
+++ b/include/clang/Checker/PathSensitive/GRCoreEngine.h
@@ -43,6 +43,11 @@ class GRCoreEngine {
friend class GRCallEnterNodeBuilder;
friend class GRCallExitNodeBuilder;
+public:
+ typedef std::vector<std::pair<BlockEdge, const ExplodedNode*> >
+ BlocksAborted;
+private:
+
GRSubEngine& SubEngine;
/// G - The simulation graph. Each node is a (location,state) pair.
@@ -57,21 +62,21 @@ class GRCoreEngine {
/// These are used to record for key nodes in the ExplodedGraph the
/// number of times different CFGBlocks have been visited along a path.
GRBlockCounter::Factory BCounterFactory;
-
- /// A flag that indicates whether paths were halted because
- /// ProcessBlockEntrace returned false.
- bool BlockAborted;
+
+ /// The locations where we stopped doing work because we visited a location
+ /// too many times.
+ BlocksAborted blocksAborted;
void GenerateNode(const ProgramPoint& Loc, const GRState* State,
ExplodedNode* Pred);
void HandleBlockEdge(const BlockEdge& E, ExplodedNode* Pred);
void HandleBlockEntrance(const BlockEntrance& E, ExplodedNode* Pred);
- void HandleBlockExit(CFGBlock* B, ExplodedNode* Pred);
- void HandlePostStmt(const PostStmt& S, CFGBlock* B,
+ void HandleBlockExit(const CFGBlock* B, ExplodedNode* Pred);
+ void HandlePostStmt(const PostStmt& S, const CFGBlock* B,
unsigned StmtIdx, ExplodedNode *Pred);
- void HandleBranch(Stmt* Cond, Stmt* Term, CFGBlock* B,
+ void HandleBranch(const Stmt* Cond, const Stmt* Term, const CFGBlock* B,
ExplodedNode* Pred);
void HandleCallEnter(const CallEnter &L, const CFGBlock *Block,
unsigned Index, ExplodedNode *Pred);
@@ -82,25 +87,42 @@ class GRCoreEngine {
return SubEngine.getInitialState(InitLoc);
}
- void ProcessEndPath(GREndPathNodeBuilder& Builder);
+ void ProcessEndPath(GREndPathNodeBuilder& Builder) {
+ SubEngine.ProcessEndPath(Builder);
+ }
- void ProcessStmt(CFGElement E, GRStmtNodeBuilder& Builder);
+ void ProcessStmt(const CFGElement E, GRStmtNodeBuilder& Builder) {
+ SubEngine.ProcessStmt(E, Builder);
+ }
- bool ProcessBlockEntrance(CFGBlock* Blk, const ExplodedNode *Pred,
- GRBlockCounter BC);
+ bool ProcessBlockEntrance(const CFGBlock* Blk, const ExplodedNode *Pred,
+ GRBlockCounter BC) {
+ return SubEngine.ProcessBlockEntrance(Blk, Pred, BC);
+ }
- void ProcessBranch(Stmt* Condition, Stmt* Terminator,
- GRBranchNodeBuilder& Builder);
+ void ProcessBranch(const Stmt* Condition, const Stmt* Terminator,
+ GRBranchNodeBuilder& Builder) {
+ SubEngine.ProcessBranch(Condition, Terminator, Builder);
+ }
- void ProcessIndirectGoto(GRIndirectGotoNodeBuilder& Builder);
+ void ProcessIndirectGoto(GRIndirectGotoNodeBuilder& Builder) {
+ SubEngine.ProcessIndirectGoto(Builder);
+ }
- void ProcessSwitch(GRSwitchNodeBuilder& Builder);
+ void ProcessSwitch(GRSwitchNodeBuilder& Builder) {
+ SubEngine.ProcessSwitch(Builder);
+ }
- void ProcessCallEnter(GRCallEnterNodeBuilder &Builder);
- void ProcessCallExit(GRCallExitNodeBuilder &Builder);
+ void ProcessCallEnter(GRCallEnterNodeBuilder &Builder) {
+ SubEngine.ProcessCallEnter(Builder);
+ }
+
+ void ProcessCallExit(GRCallExitNodeBuilder &Builder) {
+ SubEngine.ProcessCallExit(Builder);
+ }
private:
GRCoreEngine(const GRCoreEngine&); // Do not implement.
@@ -112,16 +134,14 @@ public:
GRCoreEngine(GRSubEngine& subengine)
: SubEngine(subengine), G(new ExplodedGraph()),
WList(GRWorkList::MakeBFS()),
- BCounterFactory(G->getAllocator()),
- BlockAborted(false) {}
+ BCounterFactory(G->getAllocator()) {}
/// Construct a GRCoreEngine object to analyze the provided CFG and to
/// use the provided worklist object to execute the worklist algorithm.
/// The GRCoreEngine object assumes ownership of 'wlist'.
GRCoreEngine(GRWorkList* wlist, GRSubEngine& subengine)
: SubEngine(subengine), G(new ExplodedGraph()), WList(wlist),
- BCounterFactory(G->getAllocator()),
- BlockAborted(false) {}
+ BCounterFactory(G->getAllocator()) {}
~GRCoreEngine() {
delete WList;
@@ -136,12 +156,29 @@ public:
/// ExecuteWorkList - Run the worklist algorithm for a maximum number of
/// steps. Returns true if there is still simulation state on the worklist.
- bool ExecuteWorkList(const LocationContext *L, unsigned Steps);
+ bool ExecuteWorkList(const LocationContext *L, unsigned Steps,
+ const GRState *InitState);
+ void ExecuteWorkListWithInitialState(const LocationContext *L, unsigned Steps,
+ const GRState *InitState,
+ ExplodedNodeSet &Dst);
+
+ // Functions for external checking of whether we have unfinished work
+ bool wasBlockAborted() const { return !blocksAborted.empty(); }
+ bool hasWorkRemaining() const { return wasBlockAborted() || WList->hasWork(); }
+
+ GRWorkList *getWorkList() const { return WList; }
+
+ BlocksAborted::const_iterator blocks_aborted_begin() const {
+ return blocksAborted.begin();
+ }
+ BlocksAborted::const_iterator blocks_aborted_end() const {
+ return blocksAborted.end();
+ }
};
class GRStmtNodeBuilder {
GRCoreEngine& Eng;
- CFGBlock& B;
+ const CFGBlock& B;
const unsigned Idx;
ExplodedNode* Pred;
GRStateManager& Mgr;
@@ -163,7 +200,7 @@ public:
void GenerateAutoTransition(ExplodedNode* N);
public:
- GRStmtNodeBuilder(CFGBlock* b, unsigned idx, ExplodedNode* N,
+ GRStmtNodeBuilder(const CFGBlock* b, unsigned idx, ExplodedNode* N,
GRCoreEngine* e, GRStateManager &mgr);
~GRStmtNodeBuilder();
@@ -222,11 +259,11 @@ public:
/// getStmt - Return the current block-level expression associated with
/// this builder.
- Stmt* getStmt() const { return B[Idx]; }
+ const Stmt* getStmt() const { return B[Idx]; }
/// getBlock - Return the CFGBlock associated with the block-level expression
/// of this builder.
- CFGBlock* getBlock() const { return &B; }
+ const CFGBlock* getBlock() const { return &B; }
unsigned getIndex() const { return Idx; }
@@ -239,15 +276,15 @@ public:
return Pred->getState();
}
- ExplodedNode* MakeNode(ExplodedNodeSet& Dst, Stmt* S, ExplodedNode* Pred,
- const GRState* St) {
+ ExplodedNode* MakeNode(ExplodedNodeSet& Dst, const Stmt* S,
+ ExplodedNode* Pred, const GRState* St) {
return MakeNode(Dst, S, Pred, St, PointKind);
}
- ExplodedNode* MakeNode(ExplodedNodeSet& Dst, Stmt* S, ExplodedNode* Pred,
+ ExplodedNode* MakeNode(ExplodedNodeSet& Dst, const Stmt* S,ExplodedNode* Pred,
const GRState* St, ProgramPoint::Kind K);
- ExplodedNode* MakeSinkNode(ExplodedNodeSet& Dst, Stmt* S,
+ ExplodedNode* MakeSinkNode(ExplodedNodeSet& Dst, const Stmt* S,
ExplodedNode* Pred, const GRState* St) {
bool Tmp = BuildSinks;
BuildSinks = true;
@@ -259,9 +296,9 @@ public:
class GRBranchNodeBuilder {
GRCoreEngine& Eng;
- CFGBlock* Src;
- CFGBlock* DstT;
- CFGBlock* DstF;
+ const CFGBlock* Src;
+ const CFGBlock* DstT;
+ const CFGBlock* DstF;
ExplodedNode* Pred;
typedef llvm::SmallVector<ExplodedNode*,3> DeferredTy;
@@ -273,8 +310,8 @@ class GRBranchNodeBuilder {
bool InFeasibleFalse;
public:
- GRBranchNodeBuilder(CFGBlock* src, CFGBlock* dstT, CFGBlock* dstF,
- ExplodedNode* pred, GRCoreEngine* e)
+ GRBranchNodeBuilder(const CFGBlock* src, const CFGBlock* dstT,
+ const CFGBlock* dstF, ExplodedNode* pred, GRCoreEngine* e)
: Eng(*e), Src(src), DstT(dstT), DstF(dstF), Pred(pred),
GeneratedTrue(false), GeneratedFalse(false),
InFeasibleTrue(!DstT), InFeasibleFalse(!DstF) {}
@@ -289,7 +326,7 @@ public:
ExplodedNode* generateNode(const GRState* State, bool branch);
- CFGBlock* getTargetBlock(bool branch) const {
+ const CFGBlock* getTargetBlock(bool branch) const {
return branch ? DstT : DstF;
}
@@ -311,31 +348,31 @@ public:
class GRIndirectGotoNodeBuilder {
GRCoreEngine& Eng;
- CFGBlock* Src;
- CFGBlock& DispatchBlock;
- Expr* E;
+ const CFGBlock* Src;
+ const CFGBlock& DispatchBlock;
+ const Expr* E;
ExplodedNode* Pred;
public:
- GRIndirectGotoNodeBuilder(ExplodedNode* pred, CFGBlock* src, Expr* e,
- CFGBlock* dispatch, GRCoreEngine* eng)
- : Eng(*eng), Src(src), DispatchBlock(*dispatch), E(e), Pred(pred) {}
+ GRIndirectGotoNodeBuilder(ExplodedNode* pred, const CFGBlock* src,
+ const Expr* e, const CFGBlock* dispatch, GRCoreEngine* eng)
+ : Eng(*eng), Src(src), DispatchBlock(*dispatch), E(e), Pred(pred) {}
class iterator {
- CFGBlock::succ_iterator I;
+ CFGBlock::const_succ_iterator I;
friend class GRIndirectGotoNodeBuilder;
- iterator(CFGBlock::succ_iterator i) : I(i) {}
+ iterator(CFGBlock::const_succ_iterator i) : I(i) {}
public:
iterator& operator++() { ++I; return *this; }
bool operator!=(const iterator& X) const { return I != X.I; }
- LabelStmt* getLabel() const {
+ const LabelStmt* getLabel() const {
return llvm::cast<LabelStmt>((*I)->getLabel());
}
- CFGBlock* getBlock() const {
+ const CFGBlock* getBlock() const {
return *I;
}
};
@@ -346,37 +383,38 @@ public:
ExplodedNode* generateNode(const iterator& I, const GRState* State,
bool isSink = false);
- Expr* getTarget() const { return E; }
+ const Expr* getTarget() const { return E; }
const GRState* getState() const { return Pred->State; }
};
class GRSwitchNodeBuilder {
GRCoreEngine& Eng;
- CFGBlock* Src;
- Expr* Condition;
+ const CFGBlock* Src;
+ const Expr* Condition;
ExplodedNode* Pred;
public:
- GRSwitchNodeBuilder(ExplodedNode* pred, CFGBlock* src,
- Expr* condition, GRCoreEngine* eng)
+ GRSwitchNodeBuilder(ExplodedNode* pred, const CFGBlock* src,
+ const Expr* condition, GRCoreEngine* eng)
: Eng(*eng), Src(src), Condition(condition), Pred(pred) {}
class iterator {
- CFGBlock::succ_reverse_iterator I;
+ CFGBlock::const_succ_reverse_iterator I;
friend class GRSwitchNodeBuilder;
- iterator(CFGBlock::succ_reverse_iterator i) : I(i) {}
+ iterator(CFGBlock::const_succ_reverse_iterator i) : I(i) {}
public:
iterator& operator++() { ++I; return *this; }
- bool operator!=(const iterator& X) const { return I != X.I; }
+ bool operator!=(const iterator &X) const { return I != X.I; }
+ bool operator==(const iterator &X) const { return I == X.I; }
- CaseStmt* getCase() const {
+ const CaseStmt* getCase() const {
return llvm::cast<CaseStmt>((*I)->getLabel());
}
- CFGBlock* getBlock() const {
+ const CFGBlock* getBlock() const {
return *I;
}
};
@@ -389,21 +427,21 @@ public:
ExplodedNode* generateDefaultCaseNode(const GRState* State,
bool isSink = false);
- Expr* getCondition() const { return Condition; }
+ const Expr* getCondition() const { return Condition; }
const GRState* getState() const { return Pred->State; }
};
class GREndPathNodeBuilder {
GRCoreEngine &Eng;
- CFGBlock& B;
+ const CFGBlock& B;
ExplodedNode* Pred;
public:
bool HasGeneratedNode;
public:
- GREndPathNodeBuilder(CFGBlock* b, ExplodedNode* N, GRCoreEngine* e)
+ GREndPathNodeBuilder(const CFGBlock* b, ExplodedNode* N, GRCoreEngine* e)
: Eng(*e), B(*b), Pred(N), HasGeneratedNode(false) {}
~GREndPathNodeBuilder();
@@ -427,7 +465,7 @@ public:
void GenerateCallExitNode(const GRState *state);
- CFGBlock* getBlock() const { return &B; }
+ const CFGBlock* getBlock() const { return &B; }
const GRState* getState() const {
return getPredecessor()->getState();
@@ -442,8 +480,8 @@ class GRCallEnterNodeBuilder {
// The call site.
const Stmt *CE;
- // The definition of callee.
- const FunctionDecl *FD;
+ // The AnalysisContext of the callee.
+ AnalysisContext *CalleeCtx;
// The parent block of the CallExpr.
const CFGBlock *Block;
@@ -453,9 +491,9 @@ class GRCallEnterNodeBuilder {
public:
GRCallEnterNodeBuilder(GRCoreEngine &eng, const ExplodedNode *pred,
- const Stmt *s, const FunctionDecl *fd,
+ const Stmt *s, AnalysisContext *callee,
const CFGBlock *blk, unsigned idx)
- : Eng(eng), Pred(pred), CE(s), FD(fd), Block(blk), Index(idx) {}
+ : Eng(eng), Pred(pred), CE(s), CalleeCtx(callee), Block(blk), Index(idx) {}
const GRState *getState() const { return Pred->getState(); }
@@ -465,7 +503,7 @@ public:
const Stmt *getCallExpr() const { return CE; }
- const FunctionDecl *getCallee() const { return FD; }
+ AnalysisContext *getCalleeContext() const { return CalleeCtx; }
const CFGBlock *getBlock() const { return Block; }
diff --git a/include/clang/Checker/PathSensitive/GRExprEngine.h b/include/clang/Checker/PathSensitive/GRExprEngine.h
index 8eaf3f4a97d7..5ba0b36b315d 100644
--- a/include/clang/Checker/PathSensitive/GRExprEngine.h
+++ b/include/clang/Checker/PathSensitive/GRExprEngine.h
@@ -64,7 +64,7 @@ class GRExprEngine : public GRSubEngine {
const GRState* CleanedState;
/// CurrentStmt - The current block-level statement.
- Stmt* CurrentStmt;
+ const Stmt* CurrentStmt;
// Obj-C Class Identifiers.
IdentifierInfo* NSExceptionII;
@@ -75,10 +75,26 @@ class GRExprEngine : public GRSubEngine {
llvm::OwningPtr<GRSimpleAPICheck> BatchAuditor;
+ enum CallbackKind {
+ PreVisitStmtCallback,
+ PostVisitStmtCallback,
+ ProcessAssumeCallback,
+ EvalRegionChangesCallback
+ };
+
+ typedef uint32_t CallbackTag;
+
+ /// GetCallbackTag - Create a tag for a certain kind of callback. The 'Sub'
+ /// argument can be used to differentiate callbacks that depend on another
+ /// value from a small set of possibilities, such as statement classes.
+ static inline CallbackTag GetCallbackTag(CallbackKind K, uint32_t Sub = 0) {
+ assert(Sub == ((Sub << 8) >> 8) && "Tag sub-kind must fit into 24 bits");
+ return K | (Sub << 8);
+ }
+
typedef llvm::DenseMap<void *, unsigned> CheckerMap;
typedef std::vector<std::pair<void *, Checker*> > CheckersOrdered;
- typedef llvm::DenseMap<std::pair<unsigned, unsigned>, CheckersOrdered *>
- CheckersOrderedCache;
+ typedef llvm::DenseMap<CallbackTag, CheckersOrdered *> CheckersOrderedCache;
/// A registration map from checker tag to the index into the
/// ordered checkers vector.
@@ -89,7 +105,7 @@ class GRExprEngine : public GRSubEngine {
CheckersOrdered Checkers;
/// A map used for caching the checkers that respond to the callback for
- /// a particular statement and visitation order.
+ /// a particular callback tag.
CheckersOrderedCache COCache;
/// The BugReporter associated with this engine. It is important that
@@ -101,10 +117,10 @@ class GRExprEngine : public GRSubEngine {
class CallExprWLItem {
public:
- CallExpr::arg_iterator I;
+ CallExpr::const_arg_iterator I;
ExplodedNode *N;
- CallExprWLItem(const CallExpr::arg_iterator &i, ExplodedNode *n)
+ CallExprWLItem(const CallExpr::const_arg_iterator &i, ExplodedNode *n)
: I(i), N(n) {}
};
@@ -114,13 +130,22 @@ public:
~GRExprEngine();
void ExecuteWorkList(const LocationContext *L, unsigned Steps = 150000) {
- CoreEngine.ExecuteWorkList(L, Steps);
+ CoreEngine.ExecuteWorkList(L, Steps, 0);
+ }
+
+ /// Execute the work list with an initial state. Nodes that reaches the exit
+ /// of the function are added into the Dst set, which represent the exit
+ /// state of the function call.
+ void ExecuteWorkListWithInitialState(const LocationContext *L, unsigned Steps,
+ const GRState *InitState,
+ ExplodedNodeSet &Dst) {
+ CoreEngine.ExecuteWorkListWithInitialState(L, Steps, InitState, Dst);
}
/// getContext - Return the ASTContext associated with this analysis.
ASTContext& getContext() const { return AMgr.getASTContext(); }
- AnalysisManager &getAnalysisManager() const { return AMgr; }
+ virtual AnalysisManager &getAnalysisManager() { return AMgr; }
SValuator &getSValuator() { return SVator; }
@@ -166,17 +191,18 @@ public:
/// ProcessStmt - Called by GRCoreEngine. Used to generate new successor
/// nodes by processing the 'effects' of a block-level statement.
- void ProcessStmt(CFGElement E, GRStmtNodeBuilder& builder);
+ void ProcessStmt(const CFGElement E, GRStmtNodeBuilder& builder);
/// ProcessBlockEntrance - Called by GRCoreEngine when start processing
/// a CFGBlock. This method returns true if the analysis should continue
/// exploring the given path, and false otherwise.
- bool ProcessBlockEntrance(CFGBlock* B, const ExplodedNode *Pred,
+ bool ProcessBlockEntrance(const CFGBlock* B, const ExplodedNode *Pred,
GRBlockCounter BC);
/// ProcessBranch - Called by GRCoreEngine. Used to generate successor
/// nodes by processing the 'effects' of a branch condition.
- void ProcessBranch(Stmt* Condition, Stmt* Term, GRBranchNodeBuilder& builder);
+ void ProcessBranch(const Stmt* Condition, const Stmt* Term,
+ GRBranchNodeBuilder& builder);
/// ProcessIndirectGoto - Called by GRCoreEngine. Used to generate successor
/// nodes by processing the 'effects' of a computed goto jump.
@@ -201,10 +227,19 @@ public:
/// EvalAssume - Callback function invoked by the ConstraintManager when
/// making assumptions about state values.
- const GRState *ProcessAssume(const GRState *state, SVal cond, bool assumption);
+ const GRState *ProcessAssume(const GRState *state, SVal cond,bool assumption);
+
+ /// WantsRegionChangeUpdate - Called by GRStateManager to determine if a
+ /// region change should trigger a ProcessRegionChanges update.
+ bool WantsRegionChangeUpdate(const GRState* state);
- GRStateManager& getStateManager() { return StateMgr; }
- const GRStateManager& getStateManager() const { return StateMgr; }
+ /// ProcessRegionChanges - Called by GRStateManager whenever a change is made
+ /// to the store. Used to update checkers that track region values.
+ const GRState* ProcessRegionChanges(const GRState *state,
+ const MemRegion * const *Begin,
+ const MemRegion * const *End);
+
+ virtual GRStateManager& getStateManager() { return StateMgr; }
StoreManager& getStoreManager() { return StateMgr.getStoreManager(); }
@@ -227,21 +262,29 @@ public:
SymbolManager& getSymbolManager() { return SymMgr; }
const SymbolManager& getSymbolManager() const { return SymMgr; }
+ // Functions for external checking of whether we have unfinished work
+ bool wasBlockAborted() const { return CoreEngine.wasBlockAborted(); }
+ bool hasWorkRemaining() const {
+ return wasBlockAborted() || CoreEngine.getWorkList()->hasWork();
+ }
+
+ const GRCoreEngine &getCoreEngine() const { return CoreEngine; }
+
protected:
const GRState* GetState(ExplodedNode* N) {
return N == EntryNode ? CleanedState : N->getState();
}
public:
- ExplodedNode* MakeNode(ExplodedNodeSet& Dst, Stmt* S, ExplodedNode* Pred,
- const GRState* St,
+ ExplodedNode* MakeNode(ExplodedNodeSet& Dst, const Stmt* S,
+ ExplodedNode* Pred, const GRState* St,
ProgramPoint::Kind K = ProgramPoint::PostStmtKind,
const void *tag = 0);
/// CheckerVisit - Dispatcher for performing checker-specific logic
/// at specific statements.
- void CheckerVisit(Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
- bool isPrevisit);
+ void CheckerVisit(const Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
+ CallbackKind Kind);
bool CheckerEvalCall(const CallExpr *CE,
ExplodedNodeSet &Dst,
@@ -252,125 +295,130 @@ public:
const GRState *state,
ExplodedNode *Pred);
- void CheckerVisitBind(const Stmt *AssignE, const Stmt *StoreE,
- ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
- SVal location, SVal val, bool isPrevisit);
-
+ void CheckerVisitBind(const Stmt *StoreE, 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.
- void Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst);
+ void Visit(const Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst);
/// VisitLValue - Evaluate the lvalue of the expression. For example, if Ex is
/// a DeclRefExpr, it evaluates to the MemRegionVal which represents its
/// storage location. Note that not all kinds of expressions has lvalue.
- void VisitLValue(Expr* Ex, ExplodedNode* Pred, ExplodedNodeSet& Dst);
+ void VisitLValue(const Expr* Ex, ExplodedNode* Pred, ExplodedNodeSet& Dst);
/// VisitArraySubscriptExpr - Transfer function for array accesses.
- void VisitArraySubscriptExpr(ArraySubscriptExpr* Ex, ExplodedNode* Pred,
+ void VisitArraySubscriptExpr(const ArraySubscriptExpr* Ex, ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue);
/// VisitAsmStmt - Transfer function logic for inline asm.
- void VisitAsmStmt(AsmStmt* A, ExplodedNode* Pred, ExplodedNodeSet& Dst);
+ void VisitAsmStmt(const AsmStmt* A, ExplodedNode* Pred, ExplodedNodeSet& Dst);
- void VisitAsmStmtHelperOutputs(AsmStmt* A,
- AsmStmt::outputs_iterator I,
- AsmStmt::outputs_iterator E,
+ void VisitAsmStmtHelperOutputs(const AsmStmt* A,
+ AsmStmt::const_outputs_iterator I,
+ AsmStmt::const_outputs_iterator E,
ExplodedNode* Pred, ExplodedNodeSet& Dst);
- void VisitAsmStmtHelperInputs(AsmStmt* A,
- AsmStmt::inputs_iterator I,
- AsmStmt::inputs_iterator E,
+ void VisitAsmStmtHelperInputs(const AsmStmt* A,
+ AsmStmt::const_inputs_iterator I,
+ AsmStmt::const_inputs_iterator E,
ExplodedNode* Pred, ExplodedNodeSet& Dst);
/// VisitBlockExpr - Transfer function logic for BlockExprs.
- void VisitBlockExpr(BlockExpr *BE, ExplodedNode *Pred, ExplodedNodeSet &Dst);
+ void VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred,
+ ExplodedNodeSet &Dst);
/// VisitBinaryOperator - Transfer function logic for binary operators.
- void VisitBinaryOperator(BinaryOperator* B, ExplodedNode* Pred,
+ void VisitBinaryOperator(const BinaryOperator* B, ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue);
/// VisitCall - Transfer function for function calls.
- void VisitCall(CallExpr* CE, ExplodedNode* Pred,
- CallExpr::arg_iterator AI, CallExpr::arg_iterator AE,
+ void VisitCall(const CallExpr* CE, ExplodedNode* Pred,
+ CallExpr::const_arg_iterator AI,
+ CallExpr::const_arg_iterator AE,
ExplodedNodeSet& Dst, bool asLValue);
/// VisitCast - Transfer function logic for all casts (implicit and explicit).
- void VisitCast(CastExpr *CastE, Expr *Ex, ExplodedNode *Pred,
+ void VisitCast(const CastExpr *CastE, const Expr *Ex, ExplodedNode *Pred,
ExplodedNodeSet &Dst, bool asLValue);
/// VisitCompoundLiteralExpr - Transfer function logic for compound literals.
- void VisitCompoundLiteralExpr(CompoundLiteralExpr* CL, ExplodedNode* Pred,
- ExplodedNodeSet& Dst, bool asLValue);
+ void VisitCompoundLiteralExpr(const CompoundLiteralExpr* CL,
+ ExplodedNode* Pred, ExplodedNodeSet& Dst,
+ bool asLValue);
/// VisitDeclRefExpr - Transfer function logic for DeclRefExprs.
- void VisitDeclRefExpr(DeclRefExpr* DR, ExplodedNode* Pred,
+ void VisitDeclRefExpr(const DeclRefExpr* DR, ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue);
/// VisitBlockDeclRefExpr - Transfer function logic for BlockDeclRefExprs.
- void VisitBlockDeclRefExpr(BlockDeclRefExpr* DR, ExplodedNode* Pred,
+ void VisitBlockDeclRefExpr(const BlockDeclRefExpr* DR, ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue);
- void VisitCommonDeclRefExpr(Expr* DR, const NamedDecl *D,ExplodedNode* Pred,
- ExplodedNodeSet& Dst, bool asLValue);
+ void VisitCommonDeclRefExpr(const Expr* DR, const NamedDecl *D,
+ ExplodedNode* Pred, ExplodedNodeSet& Dst,
+ bool asLValue);
/// VisitDeclStmt - Transfer function logic for DeclStmts.
- void VisitDeclStmt(DeclStmt* DS, ExplodedNode* Pred, ExplodedNodeSet& Dst);
+ void VisitDeclStmt(const DeclStmt* DS, ExplodedNode* Pred,
+ ExplodedNodeSet& Dst);
/// VisitGuardedExpr - Transfer function logic for ?, __builtin_choose
- void VisitGuardedExpr(Expr* Ex, Expr* L, Expr* R, ExplodedNode* Pred,
- ExplodedNodeSet& Dst);
+ void VisitGuardedExpr(const Expr* Ex, const Expr* L, const Expr* R,
+ ExplodedNode* Pred, ExplodedNodeSet& Dst);
/// VisitCondInit - Transfer function for handling the initialization
/// of a condition variable in an IfStmt, SwitchStmt, etc.
- void VisitCondInit(VarDecl *VD, Stmt *S, ExplodedNode *Pred,
+ void VisitCondInit(const VarDecl *VD, const Stmt *S, ExplodedNode *Pred,
ExplodedNodeSet& Dst);
- void VisitInitListExpr(InitListExpr* E, ExplodedNode* Pred,
+ void VisitInitListExpr(const InitListExpr* E, ExplodedNode* Pred,
ExplodedNodeSet& Dst);
/// VisitLogicalExpr - Transfer function logic for '&&', '||'
- void VisitLogicalExpr(BinaryOperator* B, ExplodedNode* Pred,
+ void VisitLogicalExpr(const BinaryOperator* B, ExplodedNode* Pred,
ExplodedNodeSet& Dst);
/// VisitMemberExpr - Transfer function for member expressions.
- void VisitMemberExpr(MemberExpr* M, ExplodedNode* Pred, ExplodedNodeSet& Dst,
- bool asLValue);
+ void VisitMemberExpr(const MemberExpr* M, ExplodedNode* Pred,
+ ExplodedNodeSet& Dst, bool asLValue);
/// VisitObjCIvarRefExpr - Transfer function logic for ObjCIvarRefExprs.
- void VisitObjCIvarRefExpr(ObjCIvarRefExpr* DR, ExplodedNode* Pred,
+ void VisitObjCIvarRefExpr(const ObjCIvarRefExpr* DR, ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue);
/// VisitObjCForCollectionStmt - Transfer function logic for
/// ObjCForCollectionStmt.
- void VisitObjCForCollectionStmt(ObjCForCollectionStmt* S, ExplodedNode* Pred,
- ExplodedNodeSet& Dst);
+ void VisitObjCForCollectionStmt(const ObjCForCollectionStmt* S,
+ ExplodedNode* Pred, ExplodedNodeSet& Dst);
- void VisitObjCForCollectionStmtAux(ObjCForCollectionStmt* S,
+ void VisitObjCForCollectionStmtAux(const ObjCForCollectionStmt* S,
ExplodedNode* Pred,
ExplodedNodeSet& Dst, SVal ElementV);
/// VisitObjCMessageExpr - Transfer function for ObjC message expressions.
- void VisitObjCMessageExpr(ObjCMessageExpr* ME, ExplodedNode* Pred,
+ void VisitObjCMessageExpr(const ObjCMessageExpr* ME, ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue);
/// VisitReturnStmt - Transfer function logic for return statements.
- void VisitReturnStmt(ReturnStmt* R, ExplodedNode* Pred, ExplodedNodeSet& Dst);
+ void VisitReturnStmt(const ReturnStmt* R, ExplodedNode* Pred,
+ ExplodedNodeSet& Dst);
/// VisitOffsetOfExpr - Transfer function for offsetof.
- void VisitOffsetOfExpr(OffsetOfExpr* Ex, ExplodedNode* Pred,
+ void VisitOffsetOfExpr(const OffsetOfExpr* Ex, ExplodedNode* Pred,
ExplodedNodeSet& Dst);
/// VisitSizeOfAlignOfExpr - Transfer function for sizeof.
- void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr* Ex, ExplodedNode* Pred,
+ void VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr* Ex, ExplodedNode* Pred,
ExplodedNodeSet& Dst);
/// VisitUnaryOperator - Transfer function logic for unary operators.
- void VisitUnaryOperator(UnaryOperator* B, ExplodedNode* Pred,
+ void VisitUnaryOperator(const UnaryOperator* B, ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue);
- void VisitCXXThisExpr(CXXThisExpr *TE, ExplodedNode *Pred,
+ void VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
ExplodedNodeSet & Dst);
void VisitCXXConstructExpr(const CXXConstructExpr *E, SVal Dest,
@@ -380,17 +428,17 @@ public:
void VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE, ExplodedNode *Pred,
ExplodedNodeSet &Dst);
- void VisitCXXNewExpr(CXXNewExpr *CNE, ExplodedNode *Pred,
+ void VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
ExplodedNodeSet &Dst);
- void VisitCXXDeleteExpr(CXXDeleteExpr *CDE, ExplodedNode *Pred,
+ void VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, ExplodedNode *Pred,
ExplodedNodeSet &Dst);
void VisitAggExpr(const Expr *E, SVal Dest, ExplodedNode *Pred,
ExplodedNodeSet &Dst);
/// Create a C++ temporary object for an rvalue.
- void CreateCXXTemporaryObject(Expr *Ex, ExplodedNode *Pred,
+ void CreateCXXTemporaryObject(const Expr *Ex, ExplodedNode *Pred,
ExplodedNodeSet &Dst);
/// Synthesize CXXThisRegion.
@@ -398,14 +446,15 @@ public:
const StackFrameContext *SFC);
/// Evaluate arguments with a work list algorithm.
- void EvalArguments(ExprIterator AI, ExprIterator AE,
+ void EvalArguments(ConstExprIterator AI, ConstExprIterator AE,
const FunctionProtoType *FnType,
ExplodedNode *Pred, ExplodedNodeSet &Dst);
/// EvalEagerlyAssume - Given the nodes in 'Src', eagerly assume symbolic
/// expressions of the form 'x != 0' and generate new nodes (stored in Dst)
/// with those assumptions.
- void EvalEagerlyAssume(ExplodedNodeSet& Dst, ExplodedNodeSet& Src, Expr *Ex);
+ void EvalEagerlyAssume(ExplodedNodeSet& Dst, ExplodedNodeSet& Src,
+ const Expr *Ex);
SVal EvalMinus(SVal X) {
return X.isValid() ? SVator.EvalMinus(cast<NonLoc>(X)) : X;
@@ -433,42 +482,41 @@ public:
}
protected:
- void EvalObjCMessageExpr(ExplodedNodeSet& Dst, ObjCMessageExpr* ME,
+ void EvalObjCMessageExpr(ExplodedNodeSet& Dst, const ObjCMessageExpr* ME,
ExplodedNode* Pred, const GRState *state) {
assert (Builder && "GRStmtNodeBuilder must be defined.");
getTF().EvalObjCMessageExpr(Dst, *this, *Builder, ME, Pred, state);
}
- const GRState* MarkBranch(const GRState* St, Stmt* Terminator,
+ const GRState* MarkBranch(const GRState* St, const Stmt* Terminator,
bool branchTaken);
/// EvalBind - Handle the semantics of binding a value to a specific location.
/// This method is used by EvalStore, VisitDeclStmt, and others.
- void EvalBind(ExplodedNodeSet& Dst, Stmt *AssignE,
- Stmt* StoreE, ExplodedNode* Pred,
+ void EvalBind(ExplodedNodeSet& Dst, const Stmt* StoreE, ExplodedNode* Pred,
const GRState* St, SVal location, SVal Val,
bool atDeclInit = false);
public:
// FIXME: 'tag' should be removed, and a LocationContext should be used
// instead.
- void EvalLoad(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred,
+ void EvalLoad(ExplodedNodeSet& Dst, const Expr* Ex, ExplodedNode* Pred,
const GRState* St, SVal location, const void *tag = 0,
QualType LoadTy = QualType());
// FIXME: 'tag' should be removed, and a LocationContext should be used
// instead.
- void EvalStore(ExplodedNodeSet& Dst, Expr* AssignE, Expr* StoreE,
+ void EvalStore(ExplodedNodeSet& Dst, const Expr* AssignE, const Expr* StoreE,
ExplodedNode* Pred, const GRState* St, SVal TargetLV, SVal Val,
const void *tag = 0);
private:
- void EvalLoadCommon(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred,
+ void EvalLoadCommon(ExplodedNodeSet& Dst, const Expr* Ex, ExplodedNode* Pred,
const GRState* St, SVal location, const void *tag,
QualType LoadTy);
// FIXME: 'tag' should be removed, and a LocationContext should be used
// instead.
- void EvalLocation(ExplodedNodeSet &Dst, Stmt *S, ExplodedNode* Pred,
+ void EvalLocation(ExplodedNodeSet &Dst, const Stmt *S, ExplodedNode* Pred,
const GRState* St, SVal location,
const void *tag, bool isLoad);
diff --git a/include/clang/Checker/PathSensitive/GRState.h b/include/clang/Checker/PathSensitive/GRState.h
index 67a2caf06a13..d72d63ab3c98 100644
--- a/include/clang/Checker/PathSensitive/GRState.h
+++ b/include/clang/Checker/PathSensitive/GRState.h
@@ -77,6 +77,10 @@ private:
Store St;
GenericDataMap GDM;
+ /// makeWithStore - Return a GRState with the same values as the current
+ /// state with the exception of using the specified Store.
+ const GRState *makeWithStore(Store store) const;
+
public:
/// This ctor is used when creating the first GRState object.
@@ -134,10 +138,6 @@ public:
return Env.LookupExpr(E);
}
- /// makeWithStore - Return a GRState with the same values as the current
- /// state with the exception of using the specified Store.
- const GRState *makeWithStore(Store store) const;
-
BasicValueFactory &getBasicVals() const;
SymbolManager &getSymbolManager() const;
@@ -201,8 +201,15 @@ public:
const LocationContext *LC,
SVal V) const;
+ /// Create a new state by binding the value 'V' to the statement 'S' in the
+ /// state's environment.
const GRState *BindExpr(const Stmt *S, SVal V, bool Invalidate = true) const;
+ /// Create a new state by binding the value 'V' and location 'locaton' to the
+ /// statement 'S' in the state's environment.
+ const GRState *bindExprAndLocation(const Stmt *S, SVal location, SVal V)
+ const;
+
const GRState *bindDecl(const VarRegion *VR, SVal V) const;
const GRState *bindDeclWithNoInit(const VarRegion *VR) const;
@@ -215,6 +222,28 @@ public:
const GRState *unbindLoc(Loc LV) const;
+ /// InvalidateRegion - Returns the state with bindings for the given region
+ /// cleared from the store. See InvalidateRegions.
+ const GRState *InvalidateRegion(const MemRegion *R,
+ const Expr *E, unsigned BlockCount,
+ StoreManager::InvalidatedSymbols *IS = NULL)
+ const {
+ return InvalidateRegions(&R, &R+1, E, BlockCount, IS, false);
+ }
+
+ /// InvalidateRegions - Returns the state with bindings for the given regions
+ /// cleared from the store. The regions are provided as a continuous array
+ /// from Begin to End. Optionally invalidates global regions as well.
+ const GRState *InvalidateRegions(const MemRegion * const *Begin,
+ const MemRegion * const *End,
+ const Expr *E, unsigned BlockCount,
+ StoreManager::InvalidatedSymbols *IS,
+ bool invalidateGlobals) const;
+
+ /// EnterStackFrame - Returns the state for entry to the given stack frame,
+ /// preserving the current state.
+ const GRState *EnterStackFrame(const StackFrameContext *frame) const;
+
/// Get the lvalue for a variable reference.
Loc getLValue(const VarDecl *D, const LocationContext *LC) const;
@@ -235,11 +264,18 @@ public:
const llvm::APSInt *getSymVal(SymbolRef sym) const;
- SVal getSVal(const Stmt* Ex) const;
-
+ /// Returns the SVal bound to the statement 'S' in the state's environment.
+ SVal getSVal(const Stmt* S) const;
+
SVal getSValAsScalarOrLoc(const Stmt *Ex) const;
SVal getSVal(Loc LV, QualType T = QualType()) const;
+
+ /// Returns a "simplified" SVal bound to the location 'LV' in the state's
+ /// store. A simplified SVal will include optimizations such as
+ /// if the SVal is a symbol whose value is perfectly constrained then that
+ /// constant value is returned instead.
+ SVal getSimplifiedSVal(Loc LV, QualType T= QualType()) const;
SVal getSVal(const MemRegion* R) const;
@@ -375,6 +411,9 @@ class GRStateManager {
friend class GRState;
friend class GRExprEngine; // FIXME: Remove.
private:
+ /// Eng - The GRSubEngine that owns this state manager.
+ GRSubEngine &Eng;
+
EnvironmentManager EnvMgr;
llvm::OwningPtr<StoreManager> StoreMgr;
llvm::OwningPtr<ConstraintManager> ConstraintMgr;
@@ -404,7 +443,8 @@ public:
ConstraintManagerCreator CreateConstraintManager,
llvm::BumpPtrAllocator& alloc,
GRSubEngine &subeng)
- : EnvMgr(alloc),
+ : Eng(subeng),
+ EnvMgr(alloc),
GDMFactory(alloc),
ValueMgr(alloc, Ctx, *this),
Alloc(alloc) {
@@ -447,11 +487,16 @@ public:
StoreManager& getStoreManager() { return *StoreMgr; }
ConstraintManager& getConstraintManager() { return *ConstraintMgr; }
+ GRSubEngine& getOwningEngine() { return Eng; }
const GRState* RemoveDeadBindings(const GRState* St,
const StackFrameContext *LCtx,
SymbolReaper& SymReaper);
+ /// Marshal a new state for the callee in another translation unit.
+ /// 'state' is owned by the caller's engine.
+ const GRState *MarshalState(const GRState *state, const StackFrameContext *L);
+
public:
SVal ArrayToPointer(Loc Array) {
@@ -581,50 +626,10 @@ GRState::Assume(DefinedOrUnknownSVal Cond) const {
cast<DefinedSVal>(Cond));
}
-inline const GRState *GRState::AssumeInBound(DefinedOrUnknownSVal Idx,
- DefinedOrUnknownSVal UpperBound,
- bool Assumption) const {
- if (Idx.isUnknown() || UpperBound.isUnknown())
- return this;
-
- ConstraintManager &CM = *getStateManager().ConstraintMgr;
- return CM.AssumeInBound(this, cast<DefinedSVal>(Idx),
- cast<DefinedSVal>(UpperBound), Assumption);
-}
-
-inline const GRState *
-GRState::bindCompoundLiteral(const CompoundLiteralExpr* CL,
- const LocationContext *LC, SVal V) const {
- Store new_store =
- getStateManager().StoreMgr->BindCompoundLiteral(St, CL, LC, V);
- return makeWithStore(new_store);
-}
-
-inline const GRState *GRState::bindDecl(const VarRegion* VR, SVal IVal) const {
- Store new_store = getStateManager().StoreMgr->BindDecl(St, VR, IVal);
- return makeWithStore(new_store);
-}
-
-inline const GRState *GRState::bindDeclWithNoInit(const VarRegion* VR) const {
- Store new_store = getStateManager().StoreMgr->BindDeclWithNoInit(St, VR);
- return makeWithStore(new_store);
-}
-
-inline const GRState *GRState::bindLoc(Loc LV, SVal V) const {
- Store new_store = getStateManager().StoreMgr->Bind(St, LV, V);
- return makeWithStore(new_store);
-}
-
inline const GRState *GRState::bindLoc(SVal LV, SVal V) const {
return !isa<Loc>(LV) ? this : bindLoc(cast<Loc>(LV), V);
}
-inline const GRState *GRState::bindDefault(SVal loc, SVal V) const {
- const MemRegion *R = cast<loc::MemRegionVal>(loc).getRegion();
- Store new_store = getStateManager().StoreMgr->BindDefault(St, R, V);
- return makeWithStore(new_store);
-}
-
inline Loc GRState::getLValue(const VarDecl* VD,
const LocationContext *LC) const {
return getStateManager().StoreMgr->getLValueVar(VD, LC);
diff --git a/include/clang/Checker/PathSensitive/GRSubEngine.h b/include/clang/Checker/PathSensitive/GRSubEngine.h
index 90a41d7c093f..1904835fbc34 100644
--- a/include/clang/Checker/PathSensitive/GRSubEngine.h
+++ b/include/clang/Checker/PathSensitive/GRSubEngine.h
@@ -17,7 +17,7 @@
namespace clang {
-class Stmt;
+class AnalysisManager;
class CFGBlock;
class CFGElement;
class ExplodedNode;
@@ -32,6 +32,8 @@ class GREndPathNodeBuilder;
class GRCallEnterNodeBuilder;
class GRCallExitNodeBuilder;
class LocationContext;
+class MemRegion;
+class Stmt;
class GRSubEngine {
public:
@@ -39,21 +41,23 @@ public:
virtual const GRState* getInitialState(const LocationContext *InitLoc) = 0;
- virtual GRStateManager& getStateManager() = 0;
+ virtual AnalysisManager &getAnalysisManager() = 0;
+
+ virtual GRStateManager &getStateManager() = 0;
/// Called by GRCoreEngine. Used to generate new successor
/// nodes by processing the 'effects' of a block-level statement.
- virtual void ProcessStmt(CFGElement E, GRStmtNodeBuilder& builder) = 0;
+ virtual void ProcessStmt(const CFGElement E, GRStmtNodeBuilder& builder) = 0;
/// Called by GRCoreEngine when start processing
/// a CFGBlock. This method returns true if the analysis should continue
/// exploring the given path, and false otherwise.
- virtual bool ProcessBlockEntrance(CFGBlock* B, const ExplodedNode *Pred,
+ virtual bool ProcessBlockEntrance(const CFGBlock* B, const ExplodedNode *Pred,
GRBlockCounter BC) = 0;
/// Called by GRCoreEngine. Used to generate successor
/// nodes by processing the 'effects' of a branch condition.
- virtual void ProcessBranch(Stmt* Condition, Stmt* Term,
+ virtual void ProcessBranch(const Stmt* Condition, const Stmt* Term,
GRBranchNodeBuilder& builder) = 0;
/// Called by GRCoreEngine. Used to generate successor
@@ -73,12 +77,27 @@ public:
// Generate the first post callsite node.
virtual void ProcessCallExit(GRCallExitNodeBuilder &builder) = 0;
-
+
/// Called by ConstraintManager. Used to call checker-specific
/// logic for handling assumptions on symbolic values.
virtual const GRState* ProcessAssume(const GRState *state,
SVal cond, bool assumption) = 0;
-
+
+ /// WantsRegionChangeUpdate - Called by GRStateManager to determine if a
+ /// region change should trigger a ProcessRegionChanges update.
+ virtual bool WantsRegionChangeUpdate(const GRState* state) = 0;
+
+ /// ProcessRegionChanges - Called by GRStateManager whenever a change is made
+ /// to the store. Used to update checkers that track region values.
+ virtual const GRState* ProcessRegionChanges(const GRState* state,
+ const MemRegion* const *Begin,
+ const MemRegion* const *End) = 0;
+
+ inline const GRState* ProcessRegionChange(const GRState* state,
+ const MemRegion* MR) {
+ return ProcessRegionChanges(state, &MR, &MR+1);
+ }
+
/// Called by GRCoreEngine when the analysis worklist is either empty or the
// maximum number of analysis steps have been reached.
virtual void ProcessEndWorklist(bool hasWorkRemaining) = 0;
diff --git a/include/clang/Checker/PathSensitive/GRTransferFuncs.h b/include/clang/Checker/PathSensitive/GRTransferFuncs.h
index 374f99820bd0..320b7f7b8abd 100644
--- a/include/clang/Checker/PathSensitive/GRTransferFuncs.h
+++ b/include/clang/Checker/PathSensitive/GRTransferFuncs.h
@@ -42,13 +42,13 @@ public:
virtual void EvalCall(ExplodedNodeSet& Dst,
GRExprEngine& Engine,
GRStmtNodeBuilder& Builder,
- CallExpr* CE, SVal L,
+ const CallExpr* CE, SVal L,
ExplodedNode* Pred) {}
virtual void EvalObjCMessageExpr(ExplodedNodeSet& Dst,
GRExprEngine& Engine,
GRStmtNodeBuilder& Builder,
- ObjCMessageExpr* ME,
+ const ObjCMessageExpr* ME,
ExplodedNode* Pred,
const GRState *state) {}
@@ -73,7 +73,7 @@ public:
virtual void EvalReturn(ExplodedNodeSet& Dst,
GRExprEngine& Engine,
GRStmtNodeBuilder& Builder,
- ReturnStmt* S,
+ const ReturnStmt* S,
ExplodedNode* Pred) {}
// Assumptions.
diff --git a/include/clang/Checker/PathSensitive/GRWorkList.h b/include/clang/Checker/PathSensitive/GRWorkList.h
index b8f90fa1eea1..315b614043d4 100644
--- a/include/clang/Checker/PathSensitive/GRWorkList.h
+++ b/include/clang/Checker/PathSensitive/GRWorkList.h
@@ -27,12 +27,12 @@ class ExplodedNodeImpl;
class GRWorkListUnit {
ExplodedNode* Node;
GRBlockCounter Counter;
- CFGBlock* Block;
+ const CFGBlock* Block;
unsigned BlockIdx; // This is the index of the next statement.
public:
GRWorkListUnit(ExplodedNode* N, GRBlockCounter C,
- CFGBlock* B, unsigned idx)
+ const CFGBlock* B, unsigned idx)
: Node(N),
Counter(C),
Block(B),
@@ -46,7 +46,7 @@ public:
ExplodedNode* getNode() const { return Node; }
GRBlockCounter getBlockCounter() const { return Counter; }
- CFGBlock* getBlock() const { return Block; }
+ const CFGBlock* getBlock() const { return Block; }
unsigned getIndex() const { return BlockIdx; }
};
@@ -58,8 +58,8 @@ public:
virtual void Enqueue(const GRWorkListUnit& U) = 0;
- void Enqueue(ExplodedNode* N, CFGBlock& B, unsigned idx) {
- Enqueue(GRWorkListUnit(N, CurrentCounter, &B, idx));
+ void Enqueue(ExplodedNode* N, const CFGBlock* B, unsigned idx) {
+ Enqueue(GRWorkListUnit(N, CurrentCounter, B, idx));
}
void Enqueue(ExplodedNode* N) {
diff --git a/include/clang/Checker/PathSensitive/MemRegion.h b/include/clang/Checker/PathSensitive/MemRegion.h
index feb4b7218a7e..96f906af28e1 100644
--- a/include/clang/Checker/PathSensitive/MemRegion.h
+++ b/include/clang/Checker/PathSensitive/MemRegion.h
@@ -20,6 +20,7 @@
#include "clang/AST/DeclObjC.h"
#include "clang/Checker/PathSensitive/SVals.h"
#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/ADT/FoldingSet.h"
#include <string>
@@ -38,6 +39,22 @@ class ValueManager;
class VarRegion;
class CodeTextRegion;
+/// Represent a region's offset within the top level base region.
+class RegionOffset {
+ /// The base region.
+ const MemRegion *R;
+
+ /// The bit offset within the base region. It shouldn't be negative.
+ int64_t Offset;
+
+public:
+ RegionOffset(const MemRegion *r) : R(r), Offset(0) {}
+ RegionOffset(const MemRegion *r, int64_t off) : R(r), Offset(off) {}
+
+ const MemRegion *getRegion() const { return R; }
+ int64_t getOffset() const { return Offset; }
+};
+
//===----------------------------------------------------------------------===//
// Base region classes.
//===----------------------------------------------------------------------===//
@@ -111,6 +128,9 @@ public:
bool hasStackParametersStorage() const;
+ /// Compute the offset within the top level memory object.
+ RegionOffset getAsOffset() const;
+
virtual void dumpToStream(llvm::raw_ostream& os) const;
void dump() const;
@@ -261,6 +281,7 @@ public:
}
};
+
/// SubRegion - A region that subsets another larger region. Most regions
/// are subclasses of SubRegion.
class SubRegion : public MemRegion {
@@ -287,31 +308,6 @@ public:
};
//===----------------------------------------------------------------------===//
-// Auxillary data classes for use with MemRegions.
-//===----------------------------------------------------------------------===//
-
-class ElementRegion;
-
-class RegionRawOffset {
-private:
- friend class ElementRegion;
-
- const MemRegion *Region;
- int64_t Offset;
-
- RegionRawOffset(const MemRegion* reg, int64_t offset = 0)
- : Region(reg), Offset(offset) {}
-
-public:
- // FIXME: Eventually support symbolic offsets.
- int64_t getByteOffset() const { return Offset; }
- const MemRegion *getRegion() const { return Region; }
-
- void dumpToStream(llvm::raw_ostream& os) const;
- void dump() const;
-};
-
-//===----------------------------------------------------------------------===//
// MemRegion subclasses.
//===----------------------------------------------------------------------===//
@@ -353,25 +349,23 @@ protected:
TypedRegion(const MemRegion* sReg, Kind k) : SubRegion(sReg, k) {}
public:
- virtual QualType getValueType(ASTContext &C) const = 0;
+ virtual QualType getValueType() const = 0;
- virtual QualType getLocationType(ASTContext& C) const {
+ virtual QualType getLocationType() const {
// FIXME: We can possibly optimize this later to cache this value.
- return C.getPointerType(getValueType(C));
+ return getContext().getPointerType(getValueType());
}
- QualType getDesugaredValueType(ASTContext& C) const {
- QualType T = getValueType(C);
+ QualType getDesugaredValueType() const {
+ QualType T = getValueType();
return T.getTypePtr() ? T.getDesugaredType() : T;
}
- QualType getDesugaredLocationType(ASTContext& C) const {
- return getLocationType(C).getDesugaredType();
+ QualType getDesugaredLocationType() const {
+ return getLocationType().getDesugaredType();
}
- bool isBoundable() const {
- return !getValueType(getContext()).isNull();
- }
+ bool isBoundable() const { return true; }
static bool classof(const MemRegion* R) {
unsigned k = R->getKind();
@@ -384,9 +378,8 @@ class CodeTextRegion : public TypedRegion {
protected:
CodeTextRegion(const MemRegion *sreg, Kind k) : TypedRegion(sreg, k) {}
public:
- QualType getValueType(ASTContext &C) const {
- // Do not get the object type of a CodeTextRegion.
- assert(0);
+ QualType getValueType() const {
+ assert(0 && "Do not get the object type of a CodeTextRegion.");
return QualType();
}
@@ -405,8 +398,8 @@ public:
FunctionTextRegion(const FunctionDecl* fd, const MemRegion* sreg)
: CodeTextRegion(sreg, FunctionTextRegionKind), FD(fd) {}
- QualType getLocationType(ASTContext &C) const {
- return C.getPointerType(FD->getType());
+ QualType getLocationType() const {
+ return getContext().getPointerType(FD->getType());
}
const FunctionDecl *getDecl() const {
@@ -444,7 +437,7 @@ class BlockTextRegion : public CodeTextRegion {
: CodeTextRegion(sreg, BlockTextRegionKind), BD(bd), AC(ac), locTy(lTy) {}
public:
- QualType getLocationType(ASTContext &C) const {
+ QualType getLocationType() const {
return locTy;
}
@@ -581,7 +574,7 @@ public:
const StringLiteral* getStringLiteral() const { return Str; }
- QualType getValueType(ASTContext& C) const {
+ QualType getValueType() const {
return Str->getType();
}
@@ -615,8 +608,8 @@ private:
const CompoundLiteralExpr* CL,
const MemRegion* superRegion);
public:
- QualType getValueType(ASTContext& C) const {
- return C.getCanonicalType(CL->getType());
+ QualType getValueType() const {
+ return CL->getType();
}
bool isBoundable() const { return !CL->isFileScope(); }
@@ -673,9 +666,9 @@ public:
const StackFrameContext *getStackFrame() const;
- QualType getValueType(ASTContext& C) const {
+ QualType getValueType() const {
// FIXME: We can cache this if needed.
- return C.getCanonicalType(getDecl()->getType());
+ return getDecl()->getType();
}
void dumpToStream(llvm::raw_ostream& os) const;
@@ -701,10 +694,10 @@ class CXXThisRegion : public TypedRegion {
void Profile(llvm::FoldingSetNodeID &ID) const;
public:
- QualType getValueType(ASTContext &C) const {
+ QualType getValueType() const {
return QualType(ThisPointerTy, 0);
}
-
+
void dumpToStream(llvm::raw_ostream& os) const;
static bool classof(const MemRegion* R) {
@@ -727,9 +720,9 @@ public:
const FieldDecl* getDecl() const { return cast<FieldDecl>(D); }
- QualType getValueType(ASTContext& C) const {
+ QualType getValueType() const {
// FIXME: We can cache this if needed.
- return C.getCanonicalType(getDecl()->getType());
+ return getDecl()->getType();
}
DefinedOrUnknownSVal getExtent(ValueManager& ValMgr) const;
@@ -758,7 +751,7 @@ class ObjCIvarRegion : public DeclRegion {
public:
const ObjCIvarDecl* getDecl() const { return cast<ObjCIvarDecl>(D); }
- QualType getValueType(ASTContext&) const { return getDecl()->getType(); }
+ QualType getValueType() const { return getDecl()->getType(); }
void dumpToStream(llvm::raw_ostream& os) const;
@@ -766,6 +759,30 @@ public:
return R->getKind() == ObjCIvarRegionKind;
}
};
+//===----------------------------------------------------------------------===//
+// Auxillary data classes for use with MemRegions.
+//===----------------------------------------------------------------------===//
+
+class ElementRegion;
+
+class RegionRawOffset {
+private:
+ friend class ElementRegion;
+
+ const MemRegion *Region;
+ int64_t Offset;
+
+ RegionRawOffset(const MemRegion* reg, int64_t offset = 0)
+ : Region(reg), Offset(offset) {}
+
+public:
+ // FIXME: Eventually support symbolic offsets.
+ int64_t getByteOffset() const { return Offset; }
+ const MemRegion *getRegion() const { return Region; }
+
+ void dumpToStream(llvm::raw_ostream& os) const;
+ void dump() const;
+};
class ElementRegion : public TypedRegion {
friend class MemRegionManager;
@@ -788,15 +805,15 @@ public:
SVal getIndex() const { return Index; }
- QualType getValueType(ASTContext&) const {
+ QualType getValueType() const {
return ElementType;
}
QualType getElementType() const {
return ElementType;
}
-
- RegionRawOffset getAsRawOffset() const;
+ /// Compute the offset within the array. The array might also be a subobject.
+ RegionRawOffset getAsArrayOffset() const;
void dumpToStream(llvm::raw_ostream& os) const;
@@ -820,7 +837,7 @@ class CXXObjectRegion : public TypedRegion {
Expr const *E, const MemRegion *sReg);
public:
- QualType getValueType(ASTContext& C) const {
+ QualType getValueType() const {
return Ex->getType();
}
diff --git a/include/clang/Checker/PathSensitive/SVals.h b/include/clang/Checker/PathSensitive/SVals.h
index 55fd3ea5c929..cdb338a3f2cc 100644
--- a/include/clang/Checker/PathSensitive/SVals.h
+++ b/include/clang/Checker/PathSensitive/SVals.h
@@ -45,15 +45,14 @@ public:
enum { BaseBits = 2, BaseMask = 0x3 };
protected:
- void* Data;
+ const void* Data;
unsigned Kind;
protected:
SVal(const void* d, bool isLoc, unsigned ValKind)
- : Data(const_cast<void*>(d)),
- Kind((isLoc ? LocKind : NonLocKind) | (ValKind << BaseBits)) {}
+ : Data(d), Kind((isLoc ? LocKind : NonLocKind) | (ValKind << BaseBits)) {}
- explicit SVal(BaseKind k, void* D = NULL)
+ explicit SVal(BaseKind k, const void* D = NULL)
: Data(D), Kind(k) {}
public:
@@ -69,7 +68,7 @@ public:
inline void Profile(llvm::FoldingSetNodeID& ID) const {
ID.AddInteger((unsigned) getRawKind());
- ID.AddPointer(reinterpret_cast<void*>(Data));
+ ID.AddPointer(Data);
}
inline bool operator==(const SVal& R) const {
@@ -163,13 +162,13 @@ public:
class UndefinedVal : public SVal {
public:
UndefinedVal() : SVal(UndefinedKind) {}
- UndefinedVal(void* D) : SVal(UndefinedKind, D) {}
+ UndefinedVal(const void* D) : SVal(UndefinedKind, D) {}
static inline bool classof(const SVal* V) {
return V->getBaseKind() == UndefinedKind;
}
- void* getData() const { return Data; }
+ const void* getData() const { return Data; }
};
class DefinedOrUnknownSVal : public SVal {
@@ -287,7 +286,7 @@ public:
: NonLoc(SymExprValKind, reinterpret_cast<const void*>(SE)) {}
const SymExpr *getSymbolicExpression() const {
- return reinterpret_cast<SymExpr*>(Data);
+ return reinterpret_cast<const SymExpr*>(Data);
}
static inline bool classof(const SVal* V) {
@@ -305,7 +304,7 @@ public:
ConcreteInt(const llvm::APSInt& V) : NonLoc(ConcreteIntKind, &V) {}
const llvm::APSInt& getValue() const {
- return *static_cast<llvm::APSInt*>(Data);
+ return *static_cast<const llvm::APSInt*>(Data);
}
// Transfer functions for binary/unary operations on ConcreteInts.
@@ -368,7 +367,7 @@ class CompoundVal : public NonLoc {
public:
const CompoundValData* getValue() const {
- return static_cast<CompoundValData*>(Data);
+ return static_cast<const CompoundValData*>(Data);
}
typedef llvm::ImmutableList<SVal>::iterator iterator;
@@ -419,8 +418,8 @@ class GotoLabel : public Loc {
public:
GotoLabel(LabelStmt* Label) : Loc(GotoLabelKind, Label) {}
- LabelStmt* getLabel() const {
- return static_cast<LabelStmt*>(Data);
+ const LabelStmt* getLabel() const {
+ return static_cast<const LabelStmt*>(Data);
}
static inline bool classof(const SVal* V) {
@@ -439,7 +438,7 @@ public:
MemRegionVal(const MemRegion* r) : Loc(MemRegionKind, r) {}
const MemRegion* getRegion() const {
- return static_cast<MemRegion*>(Data);
+ return static_cast<const MemRegion*>(Data);
}
const MemRegion* StripCasts() const;
@@ -473,7 +472,7 @@ public:
ConcreteInt(const llvm::APSInt& V) : Loc(ConcreteIntKind, &V) {}
const llvm::APSInt& getValue() const {
- return *static_cast<llvm::APSInt*>(Data);
+ return *static_cast<const llvm::APSInt*>(Data);
}
// Transfer functions for binary/unary operations on ConcreteInts.
diff --git a/include/clang/Checker/PathSensitive/Store.h b/include/clang/Checker/PathSensitive/Store.h
index 7a60ebb0838e..a1a41847a206 100644
--- a/include/clang/Checker/PathSensitive/Store.h
+++ b/include/clang/Checker/PathSensitive/Store.h
@@ -149,9 +149,8 @@ public:
return UnknownVal();
}
- virtual const GRState *RemoveDeadBindings(GRState &state,
- const StackFrameContext *LCtx,
- SymbolReaper& SymReaper,
+ virtual Store RemoveDeadBindings(Store store, const StackFrameContext *LCtx,
+ SymbolReaper& SymReaper,
llvm::SmallVectorImpl<const MemRegion*>& RegionRoots) = 0;
virtual Store BindDecl(Store store, const VarRegion *VR, SVal initVal) = 0;
@@ -159,25 +158,39 @@ public:
virtual Store BindDeclWithNoInit(Store store, const VarRegion *VR) = 0;
typedef llvm::DenseSet<SymbolRef> InvalidatedSymbols;
-
- virtual Store InvalidateRegion(Store store,
- const MemRegion *R,
- const Expr *E, unsigned Count,
- InvalidatedSymbols *IS) = 0;
-
+ typedef llvm::SmallVector<const MemRegion *, 8> InvalidatedRegions;
+
+ /// InvalidateRegions - Clears out the specified regions from the store,
+ /// marking their values as unknown. Depending on the store, this may also
+ /// invalidate additional regions that may have changed based on accessing
+ /// the given regions. Optionally, invalidates non-static globals as well.
+ /// \param[in] store The initial store
+ /// \param[in] Begin A pointer to the first region to invalidate.
+ /// \param[in] End A pointer just past the last region to invalidate.
+ /// \param[in] E The current statement being evaluated. Used to conjure
+ /// symbols to mark the values of invalidated regions.
+ /// \param[in] Count The current block count. Used to conjure
+ /// symbols to mark the values of invalidated regions.
+ /// \param[in,out] IS A set to fill with any symbols that are no longer
+ /// accessible. Pass \c NULL if this information will not be used.
+ /// \param[in] invalidateGlobals If \c true, any non-static global regions
+ /// are invalidated as well.
+ /// \param[in,out] Regions A vector to fill with any regions being
+ /// invalidated. This should include any regions explicitly invalidated
+ /// even if they do not currently have bindings. Pass \c NULL if this
+ /// information will not be used.
virtual Store InvalidateRegions(Store store,
const MemRegion * const *Begin,
const MemRegion * const *End,
const Expr *E, unsigned Count,
InvalidatedSymbols *IS,
- bool invalidateGlobals) = 0;
+ bool invalidateGlobals,
+ InvalidatedRegions *Regions) = 0;
/// EnterStackFrame - Let the StoreManager to do something when execution
/// engine is about to execute into a callee.
- virtual const GRState *EnterStackFrame(const GRState *state,
- const StackFrameContext *frame) {
- return state;
- }
+ virtual Store EnterStackFrame(const GRState *state,
+ const StackFrameContext *frame);
virtual void print(Store store, llvm::raw_ostream& Out,
const char* nl, const char *sep) = 0;
diff --git a/include/clang/Checker/PathSensitive/SymbolManager.h b/include/clang/Checker/PathSensitive/SymbolManager.h
index ffbd2892499e..26ed0c1bc06f 100644
--- a/include/clang/Checker/PathSensitive/SymbolManager.h
+++ b/include/clang/Checker/PathSensitive/SymbolManager.h
@@ -40,6 +40,7 @@ class SymExpr : public llvm::FoldingSetNode {
public:
enum Kind { BEGIN_SYMBOLS,
RegionValueKind, ConjuredKind, DerivedKind, ExtentKind,
+ MetadataKind,
END_SYMBOLS,
SymIntKind, SymSymKind };
private:
@@ -190,6 +191,9 @@ public:
}
};
+/// SymbolExtent - Represents the extent (size in bytes) of a bounded region.
+/// Clients should not ask the SymbolManager for a region's extent. Always use
+/// SubRegion::getExtent instead -- the value returned may not be a symbol.
class SymbolExtent : public SymbolData {
const SubRegion *R;
@@ -218,6 +222,51 @@ public:
}
};
+/// SymbolMetadata - Represents path-dependent metadata about a specific region.
+/// Metadata symbols remain live as long as they are marked as in use before
+/// dead-symbol sweeping AND their associated regions are still alive.
+/// Intended for use by checkers.
+class SymbolMetadata : public SymbolData {
+ const MemRegion* R;
+ const Stmt* S;
+ QualType T;
+ unsigned Count;
+ const void* Tag;
+public:
+ SymbolMetadata(SymbolID sym, const MemRegion* r, const Stmt* s, QualType t,
+ unsigned count, const void* tag)
+ : SymbolData(MetadataKind, sym), R(r), S(s), T(t), Count(count), Tag(tag) {}
+
+ const MemRegion *getRegion() const { return R; }
+ const Stmt* getStmt() const { return S; }
+ unsigned getCount() const { return Count; }
+ const void* getTag() const { return Tag; }
+
+ QualType getType(ASTContext&) const;
+
+ void dumpToStream(llvm::raw_ostream &os) const;
+
+ static void Profile(llvm::FoldingSetNodeID& profile, const MemRegion *R,
+ const Stmt *S, QualType T, unsigned Count,
+ const void *Tag) {
+ profile.AddInteger((unsigned) MetadataKind);
+ profile.AddPointer(R);
+ profile.AddPointer(S);
+ profile.Add(T);
+ profile.AddInteger(Count);
+ profile.AddPointer(Tag);
+ }
+
+ virtual void Profile(llvm::FoldingSetNodeID& profile) {
+ Profile(profile, R, S, T, Count, Tag);
+ }
+
+ // Implement isa<T> support.
+ static inline bool classof(const SymExpr* SE) {
+ return SE->getKind() == MetadataKind;
+ }
+};
+
// SymIntExpr - Represents symbolic expression like 'x' + 3.
class SymIntExpr : public SymExpr {
const SymExpr *LHS;
@@ -336,6 +385,10 @@ public:
const SymbolExtent *getExtentSymbol(const SubRegion *R);
+ const SymbolMetadata* getMetadataSymbol(const MemRegion* R, const Stmt* S,
+ QualType T, unsigned VisitCount,
+ const void* SymbolTag = 0);
+
const SymIntExpr *getSymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op,
const llvm::APSInt& rhs, QualType t);
@@ -359,6 +412,7 @@ class SymbolReaper {
typedef llvm::DenseSet<SymbolRef> SetTy;
SetTy TheLiving;
+ SetTy MetadataInUse;
SetTy TheDead;
const LocationContext *LCtx;
const Stmt *Loc;
@@ -374,12 +428,24 @@ public:
const Stmt *getCurrentStatement() const { return Loc; }
bool isLive(SymbolRef sym);
-
bool isLive(const Stmt *ExprVal) const;
-
bool isLive(const VarRegion *VR) const;
-
+
+ // markLive - Unconditionally marks a symbol as live. This should never be
+ // used by checkers, only by the state infrastructure such as the store and
+ // environment. Checkers should instead use metadata symbols and markInUse.
void markLive(SymbolRef sym);
+
+ // markInUse - Marks a symbol as important to a checker. For metadata symbols,
+ // this will keep the symbol alive as long as its associated region is also
+ // live. For other symbols, this has no effect; checkers are not permitted
+ // to influence the life of other symbols. This should be used before any
+ // symbol marking has occurred, i.e. in the MarkLiveSymbols callback.
+ void markInUse(SymbolRef sym);
+
+ // maybeDead - If a symbol is known to be live, marks the symbol as live.
+ // Otherwise, if the symbol cannot be proven live, it is marked as dead.
+ // Returns true if the symbol is dead, false if live.
bool maybeDead(SymbolRef sym);
typedef SetTy::const_iterator dead_iterator;
@@ -389,6 +455,13 @@ public:
bool hasDeadSymbols() const {
return !TheDead.empty();
}
+
+ /// isDead - Returns whether or not a symbol has been confirmed dead. This
+ /// should only be called once all marking of dead symbols has completed.
+ /// (For checkers, this means only in the EvalDeadSymbols callback.)
+ bool isDead(SymbolRef sym) const {
+ return TheDead.count(sym);
+ }
};
class SymbolVisitor {
diff --git a/include/clang/Checker/PathSensitive/ValueManager.h b/include/clang/Checker/PathSensitive/ValueManager.h
index 5a9d54d337b0..b81e9c150234 100644
--- a/include/clang/Checker/PathSensitive/ValueManager.h
+++ b/include/clang/Checker/PathSensitive/ValueManager.h
@@ -106,6 +106,9 @@ public:
DefinedOrUnknownSVal getDerivedRegionValueSymbolVal(SymbolRef parentSymbol,
const TypedRegion *R);
+ DefinedSVal getMetadataSymbolVal(const void *SymbolTag, const MemRegion *MR,
+ const Expr *E, QualType T, unsigned Count);
+
DefinedSVal getFunctionPointer(const FunctionDecl *FD);
DefinedSVal getBlockPointer(const BlockDecl *BD, CanQualType locTy,
diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td
index 7076f30995d0..fd40aa0c5f4b 100644
--- a/include/clang/Driver/CC1Options.td
+++ b/include/clang/Driver/CC1Options.td
@@ -26,6 +26,8 @@ def target_cpu : Separate<"-target-cpu">,
HelpText<"Target a specific cpu type">;
def target_feature : Separate<"-target-feature">,
HelpText<"Target specific attributes">;
+def target_linker_version : Separate<"-target-linker-version">,
+ HelpText<"Target linker version">;
def triple : Separate<"-triple">,
HelpText<"Specify target triple (e.g. i686-apple-darwin9)">;
def triple_EQ : Joined<"-triple=">, Alias<triple>;
@@ -38,6 +40,8 @@ def analysis_CFGDump : Flag<"-cfg-dump">,
HelpText<"Display Control-Flow Graphs">;
def analysis_CFGView : Flag<"-cfg-view">,
HelpText<"View Control-Flow Graphs using GraphViz">;
+def analysis_UnoptimizedCFG : Flag<"-unoptimized-cfg">,
+ HelpText<"Generate unoptimized CFGs for all analyses">;
def analysis_DisplayLiveVariables : Flag<"-dump-live-variables">,
HelpText<"Print results of live variable analysis">;
def analysis_LLVMConventionChecker : Flag<"-analyzer-check-llvm-conventions">,
@@ -58,6 +62,8 @@ def analysis_ObjCMemChecker : Flag<"-analyzer-check-objc-mem">,
HelpText<"Run the [Core] Foundation reference count checker">;
def analysis_WarnSizeofPointer : Flag<"-warn-sizeof-pointer">,
HelpText<"Warn about unintended use of sizeof() on pointer expressions">;
+def analysis_WarnIdempotentOps : Flag<"-analyzer-check-idempotent-operations">,
+ HelpText<"Warn about idempotent operations">;
def analyzer_store : Separate<"-analyzer-store">,
HelpText<"Source Code Analysis - Abstract Memory Store Models">;
@@ -81,8 +87,6 @@ def analyzer_display_progress : Flag<"-analyzer-display-progress">,
HelpText<"Emit verbose output about the analyzer's progress">;
def analyzer_experimental_checks : Flag<"-analyzer-experimental-checks">,
HelpText<"Use experimental path-sensitive checks">;
-def analyzer_idempotent_operation : Flag<"-analyzer-idempotent-operation">,
- HelpText<"Use experimental path-sensitive idempotent operation checker">;
def analyzer_experimental_internal_checks :
Flag<"-analyzer-experimental-internal-checks">,
HelpText<"Use new default path-sensitive checks currently in testing">;
@@ -137,6 +141,8 @@ def ffunction_sections : Flag<"-ffunction-sections">,
HelpText<"Place each function in its own section (ELF Only)">;
def fdata_sections : Flag<"-fdata-sections">,
HelpText<"Place each data in its own section (ELF Only)">;
+def funroll_loops : Flag<"-funroll-loops">,
+ HelpText<"Turn on loop unroller">;
def masm_verbose : Flag<"-masm-verbose">,
HelpText<"Generate verbose assembly output">;
def mcode_model : Separate<"-mcode-model">,
@@ -209,6 +215,8 @@ def W : Joined<"-W">;
def fdiagnostics_print_source_range_info : Flag<"-fdiagnostics-print-source-range-info">,
HelpText<"Print source range spans in numeric form">;
+def fdiagnostics_parseable_fixits : Flag<"-fdiagnostics-parseable-fixits">,
+ HelpText<"Print fix-its in machine parseable form">;
def fdiagnostics_show_option : Flag<"-fdiagnostics-show-option">,
HelpText<"Print diagnostic name with mappable diagnostics">;
def fdiagnostics_show_category : Separate<"-fdiagnostics-show-category">,
@@ -229,7 +237,7 @@ def fcolor_diagnostics : Flag<"-fcolor-diagnostics">,
def Wno_rewrite_macros : Flag<"-Wno-rewrite-macros">,
HelpText<"Silence ObjC rewriting warnings">;
def Wwrite_strings : Flag<"-Wwrite-strings">,
- HelpText<"Add const qualifier to string literals">;
+ HelpText<"Remove const qualifier from string literals">;
def verify : Flag<"-verify">,
HelpText<"Verify emitted diagnostics and warnings">;
@@ -258,6 +266,8 @@ def code_completion_macros : Flag<"-code-completion-macros">,
HelpText<"Include macros in code-completion results">;
def code_completion_patterns : Flag<"-code-completion-patterns">,
HelpText<"Include code patterns in code-completion results">;
+def no_code_completion_globals : Flag<"-no-code-completion-globals">,
+ HelpText<"Do not include global declarations in code-completion results.">;
def disable_free : Flag<"-disable-free">,
HelpText<"Disable freeing of memory on exit">;
def help : Flag<"-help">,
@@ -296,16 +306,15 @@ def dump_tokens : Flag<"-dump-tokens">,
HelpText<"Run preprocessor, dump internal rep of tokens">;
def init_only : Flag<"-init-only">,
HelpText<"Only execute frontend initialization">;
-def parse_noop : Flag<"-parse-noop">,
- HelpText<"Run parser with noop callbacks (for timings)">;
def fsyntax_only : Flag<"-fsyntax-only">,
HelpText<"Run parser and perform semantic analysis">;
def fixit : Flag<"-fixit">,
HelpText<"Apply fix-it advice to the input source">;
def fixit_EQ : Joined<"-fixit=">,
HelpText<"Apply fix-it advice creating a file with the given suffix">;
-def parse_print_callbacks : Flag<"-parse-print-callbacks">,
- HelpText<"Run parser and print each callback invoked">;
+def print_preamble : Flag<"-print-preamble">,
+ HelpText<"Print the \"preamble\" of a file, which is a candidate for implicit"
+ " precompiled headers.">;
def emit_html : Flag<"-emit-html">,
HelpText<"Output input source as HTML">;
def ast_print : Flag<"-ast-print">,
@@ -343,8 +352,13 @@ def rewrite_objc : Flag<"-rewrite-objc">,
def rewrite_macros : Flag<"-rewrite-macros">,
HelpText<"Expand macros without full preprocessing">;
+def create_module : Flag<"-create-module">,
+ HelpText<"Create a module definition file">;
}
+def import_module : Separate<"-import-module">,
+ HelpText<"Import a module definition file">;
+
def relocatable_pch : Flag<"-relocatable-pch">,
HelpText<"Whether to build a relocatable precompiled header">;
def chained_pch : Flag<"-chained-pch">,
@@ -353,9 +367,10 @@ def print_stats : Flag<"-print-stats">,
HelpText<"Print performance metrics and statistics">;
def ftime_report : Flag<"-ftime-report">,
HelpText<"Print the amount of time each phase of compilation takes">;
-
def fdump_record_layouts : Flag<"-fdump-record-layouts">,
HelpText<"Dump record layout information">;
+def fix_what_you_can : Flag<"-fix-what-you-can">,
+ HelpText<"Apply fix-it advice even in the presence of unfixable errors">;
// Generic forwarding to LLVM options. This should only be used for debugging
// and experimental features.
@@ -395,12 +410,16 @@ def ffreestanding : Flag<"-ffreestanding">,
HelpText<"Assert that the compilation takes place in a freestanding environment">;
def fgnu_runtime : Flag<"-fgnu-runtime">,
HelpText<"Generate output compatible with the standard GNU Objective-C runtime">;
+def fhidden_weak_vtables : Flag<"-fhidden-weak-vtables">,
+ HelpText<"Generate weak vtables and RTTI with hidden visibility">;
def std_EQ : Joined<"-std=">,
HelpText<"Language standard to compile for">;
def fmath_errno : Flag<"-fmath-errno">,
HelpText<"Require math functions to indicate errors by setting errno">;
def fms_extensions : Flag<"-fms-extensions">,
HelpText<"Accept some non-standard constructs used in Microsoft header files ">;
+def fborland_extensions : Flag<"-fborland-extensions">,
+ HelpText<"Accept non-standard constructs supported by the Borland compiler">;
def main_file_name : Separate<"-main-file-name">,
HelpText<"Main file name to use for debug info">;
def fno_elide_constructors : Flag<"-fno-elide-constructors">,
@@ -444,6 +463,8 @@ def fpascal_strings : Flag<"-fpascal-strings">,
HelpText<"Recognize and construct Pascal-style string literals">;
def fno_rtti : Flag<"-fno-rtti">,
HelpText<"Disable generation of rtti information">;
+def fno_validate_pch : Flag<"-fno-validate-pch">,
+ HelpText<"Disable validation of precompiled headers">;
def fshort_wchar : Flag<"-fshort-wchar">,
HelpText<"Force wchar_t to be a short unsigned int">;
def static_define : Flag<"-static-define">,
@@ -483,6 +504,9 @@ def iquote : JoinedOrSeparate<"-iquote">, MetaVarName<"<directory>">,
HelpText<"Add directory to QUOTE include search path">;
def isystem : JoinedOrSeparate<"-isystem">, MetaVarName<"<directory>">,
HelpText<"Add directory to SYSTEM include search path">;
+def iwithsysroot : JoinedOrSeparate<"-iwithsysroot">,MetaVarName<"<directory>">,
+ HelpText<"Add directory to SYSTEM include search path, "
+ "absolute paths are relative to -isysroot">;
def iprefix : JoinedOrSeparate<"-iprefix">, MetaVarName<"<prefix>">,
HelpText<"Set the -iwithprefix/-iwithprefixbefore prefix">;
def iwithprefix : JoinedOrSeparate<"-iwithprefix">, MetaVarName<"<dir>">,
@@ -508,6 +532,9 @@ def include_pch : Separate<"-include-pch">, MetaVarName<"<file>">,
HelpText<"Include precompiled header file">;
def include_pth : Separate<"-include-pth">, MetaVarName<"<file>">,
HelpText<"Include file before parsing">;
+def preamble_bytes_EQ : Joined<"-preamble-bytes=">,
+ HelpText<"Assume that the precompiled header is a precompiled preamble "
+ "covering the first N bytes of the main file">;
def token_cache : Separate<"-token-cache">, MetaVarName<"<path>">,
HelpText<"Use specified token cache file">;
def U : JoinedOrSeparate<"-U">, MetaVarName<"<macro>">,
@@ -531,3 +558,5 @@ def dM : Flag<"-dM">,
HelpText<"Print macro definitions in -E mode instead of normal output">;
def dD : Flag<"-dD">,
HelpText<"Print macro definitions in -E mode in addition to normal output">;
+def H : Flag<"-H">,
+ HelpText<"Show header includes and nesting depth">;
diff --git a/include/clang/Driver/Compilation.h b/include/clang/Driver/Compilation.h
index 5f062a121c6d..22d6b4ec6c8f 100644
--- a/include/clang/Driver/Compilation.h
+++ b/include/clang/Driver/Compilation.h
@@ -80,6 +80,8 @@ public:
JobList &getJobs() { return Jobs; }
const JobList &getJobs() const { return Jobs; }
+ void addCommand(Command *C) { Jobs.addJob(C); }
+
const ArgStringList &getTempFiles() const { return TempFiles; }
const ArgStringList &getResultFiles() const { return ResultFiles; }
diff --git a/include/clang/Driver/Driver.h b/include/clang/Driver/Driver.h
index bb578b516ce3..28eff4f1d71d 100644
--- a/include/clang/Driver/Driver.h
+++ b/include/clang/Driver/Driver.h
@@ -37,7 +37,6 @@ namespace driver {
class InputInfo;
class JobAction;
class OptTable;
- class PipedJob;
class ToolChain;
/// Driver - Encapsulate logic for constructing compilation processes
@@ -65,6 +64,9 @@ public:
/// The original path to the clang executable.
std::string ClangExecutable;
+ /// The path to the installed clang directory, if any.
+ std::string InstalledDir;
+
/// The path to the compiler resource directory.
std::string ResourceDir;
@@ -145,7 +147,7 @@ private:
DerivedArgList *TranslateInputArgs(const InputArgList &Args) const;
public:
- Driver(llvm::StringRef _Name, llvm::StringRef _Dir,
+ Driver(llvm::StringRef _ClangExecutable,
llvm::StringRef _DefaultHostTriple,
llvm::StringRef _DefaultImageName,
bool IsProduction, bool CXXIsProduction,
@@ -167,8 +169,18 @@ public:
void setTitle(std::string Value) { DriverTitle = Value; }
/// \brief Get the path to the main clang executable.
- std::string getClangProgramPath() const {
- return ClangExecutable;
+ const char *getClangProgramPath() const {
+ return ClangExecutable.c_str();
+ }
+
+ /// \brief Get the path to where the clang executable was installed.
+ const char *getInstalledDir() const {
+ if (!InstalledDir.empty())
+ return InstalledDir.c_str();
+ return Dir.c_str();
+ }
+ void setInstalledDir(llvm::StringRef Value) {
+ InstalledDir = Value;
}
/// @}
@@ -194,16 +206,20 @@ public:
/// BuildActions - Construct the list of actions to perform for the
/// given arguments, which are only done for a single architecture.
///
+ /// \param TC - The default host tool chain.
/// \param Args - The input arguments.
/// \param Actions - The list to store the resulting actions onto.
- void BuildActions(const ArgList &Args, ActionList &Actions) const;
+ void BuildActions(const ToolChain &TC, const ArgList &Args,
+ ActionList &Actions) const;
/// BuildUniversalActions - Construct the list of actions to perform
/// for the given arguments, which may require a universal build.
///
+ /// \param TC - The default host tool chain.
/// \param Args - The input arguments.
/// \param Actions - The list to store the resulting actions onto.
- void BuildUniversalActions(const ArgList &Args, ActionList &Actions) const;
+ void BuildUniversalActions(const ToolChain &TC, const ArgList &Args,
+ ActionList &Actions) const;
/// BuildJobs - Bind actions to concrete tools and translate
/// arguments to form the list of jobs to run.
@@ -278,7 +294,6 @@ public:
const Action *A,
const ToolChain *TC,
const char *BoundArch,
- bool CanAcceptPipe,
bool AtTopLevel,
const char *LinkingOutput,
InputInfo &Result) const;
diff --git a/include/clang/Driver/HostInfo.h b/include/clang/Driver/HostInfo.h
index 1b99a4459d16..04e72992d684 100644
--- a/include/clang/Driver/HostInfo.h
+++ b/include/clang/Driver/HostInfo.h
@@ -10,7 +10,6 @@
#ifndef CLANG_DRIVER_HOSTINFO_H_
#define CLANG_DRIVER_HOSTINFO_H_
-#include "clang/Driver/Types.h"
#include "llvm/ADT/Triple.h"
#include <string>
@@ -48,10 +47,6 @@ public:
/// this host and support -arch, -Xarch, etc.
virtual bool useDriverDriver() const = 0;
- /// lookupTypeForExtension - Return the default language type to use for the
- /// given extension.
- virtual types::ID lookupTypeForExtension(const char *Ext) const = 0;
-
/// CreateToolChain - Construct the toolchain to use for this host (which the
/// host retains ownership of).
///
@@ -84,6 +79,10 @@ const HostInfo *createLinuxHostInfo(const Driver &D,
const llvm::Triple& Triple);
const HostInfo *createTCEHostInfo(const Driver &D,
const llvm::Triple& Triple);
+const HostInfo *createWindowsHostInfo(const Driver &D,
+ const llvm::Triple &Triple);
+const HostInfo *createMinGWHostInfo(const Driver &D,
+ const llvm::Triple &Triple);
const HostInfo *createUnknownHostInfo(const Driver &D,
const llvm::Triple& Triple);
diff --git a/include/clang/Driver/Job.h b/include/clang/Driver/Job.h
index 5a789fbb8f41..d2767d1b877b 100644
--- a/include/clang/Driver/Job.h
+++ b/include/clang/Driver/Job.h
@@ -29,7 +29,6 @@ class Job {
public:
enum JobClass {
CommandClass,
- PipedJobClass,
JobListClass
};
@@ -86,39 +85,6 @@ public:
static bool classof(const Command *) { return true; }
};
- /// PipedJob - A list of Commands which should be executed together
- /// with their standard inputs and outputs connected.
-class PipedJob : public Job {
-public:
- typedef llvm::SmallVector<Command*, 4> list_type;
- typedef list_type::size_type size_type;
- typedef list_type::iterator iterator;
- typedef list_type::const_iterator const_iterator;
-
-private:
- list_type Commands;
-
-public:
- PipedJob();
- virtual ~PipedJob();
-
- /// Add a command to the piped job (taking ownership).
- void addCommand(Command *C) { Commands.push_back(C); }
-
- const list_type &getCommands() const { return Commands; }
-
- size_type size() const { return Commands.size(); }
- iterator begin() { return Commands.begin(); }
- const_iterator begin() const { return Commands.begin(); }
- iterator end() { return Commands.end(); }
- const_iterator end() const { return Commands.end(); }
-
- static bool classof(const Job *J) {
- return J->getKind() == PipedJobClass;
- }
- static bool classof(const PipedJob *) { return true; }
-};
-
/// JobList - A sequence of jobs to perform.
class JobList : public Job {
public:
diff --git a/include/clang/Driver/OptParser.td b/include/clang/Driver/OptParser.td
index a9f4289fc86e..04efd00fb1d8 100644
--- a/include/clang/Driver/OptParser.td
+++ b/include/clang/Driver/OptParser.td
@@ -82,6 +82,9 @@ def Unsupported : OptionFlag;
// arguments to implement hidden help groups.
def HelpHidden : OptionFlag;
+// NoForward - The option should not be implicitly forwarded to other tools.
+def NoForward : OptionFlag;
+
// Define the option group class.
class OptionGroup<string name> {
diff --git a/include/clang/Driver/OptTable.h b/include/clang/Driver/OptTable.h
index e4a2eba578b8..08b483c90017 100644
--- a/include/clang/Driver/OptTable.h
+++ b/include/clang/Driver/OptTable.h
@@ -25,10 +25,11 @@ namespace options {
HelpHidden = (1 << 1),
LinkerInput = (1 << 2),
NoArgumentUnused = (1 << 3),
- RenderAsInput = (1 << 4),
- RenderJoined = (1 << 5),
- RenderSeparate = (1 << 6),
- Unsupported = (1 << 7)
+ NoForward = (1 << 4),
+ RenderAsInput = (1 << 5),
+ RenderJoined = (1 << 6),
+ RenderSeparate = (1 << 7),
+ Unsupported = (1 << 8)
};
}
@@ -52,7 +53,7 @@ namespace options {
const char *HelpText;
const char *MetaVar;
unsigned char Kind;
- unsigned char Flags;
+ unsigned short Flags;
unsigned char Param;
unsigned short GroupID;
unsigned short AliasID;
diff --git a/include/clang/Driver/Option.h b/include/clang/Driver/Option.h
index 0864382cb3a6..9625465f48f4 100644
--- a/include/clang/Driver/Option.h
+++ b/include/clang/Driver/Option.h
@@ -92,6 +92,9 @@ namespace driver {
/// This option should not report argument unused errors.
bool NoArgumentUnused : 1;
+ /// This option should not be implicitly forwarded.
+ bool NoForward : 1;
+
protected:
Option(OptionClass Kind, OptSpecifier ID, const char *Name,
const OptionGroup *Group, const Option *Alias);
@@ -124,7 +127,12 @@ namespace driver {
bool hasNoArgumentUnused() const { return NoArgumentUnused; }
void setNoArgumentUnused(bool Value) { NoArgumentUnused = Value; }
- bool hasForwardToGCC() const { return !DriverOption && !LinkerInput; }
+ bool hasNoForward() const { return NoForward; }
+ void setNoForward(bool Value) { NoForward = Value; }
+
+ bool hasForwardToGCC() const {
+ return !NoForward && !DriverOption && !LinkerInput;
+ }
/// getUnaliasedOption - Return the final option this option
/// aliases (itself, if the option has no alias).
diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td
index 73c8e6bda2e4..c51d12a48769 100644
--- a/include/clang/Driver/Options.td
+++ b/include/clang/Driver/Options.td
@@ -180,7 +180,8 @@ def Xarch__ : JoinedAndSeparate<"-Xarch_">, Flags<[DriverOption]>;
def Xassembler : Separate<"-Xassembler">,
HelpText<"Pass <arg> to the assembler">, MetaVarName<"<arg>">;
def Xclang : Separate<"-Xclang">,
- HelpText<"Pass <arg> to the clang compiler">, MetaVarName<"<arg>">;
+ HelpText<"Pass <arg> to the clang compiler">, MetaVarName<"<arg>">,
+ Flags<[NoForward]>;
def Xlinker : Separate<"-Xlinker">, Flags<[LinkerInput, RenderAsInput]>,
HelpText<"Pass <arg> to the linker">, MetaVarName<"<arg>">;
def Xpreprocessor : Separate<"-Xpreprocessor">,
@@ -242,6 +243,7 @@ def fast : Flag<"-fast">, Group<f_Group>;
def fasynchronous_unwind_tables : Flag<"-fasynchronous-unwind-tables">, Group<f_Group>;
def fblocks : Flag<"-fblocks">, Group<f_Group>;
def fbootclasspath_EQ : Joined<"-fbootclasspath=">, Group<f_Group>;
+def fborland_extensions : Flag<"-fborland-extensions">, Group<f_Group>;
def fbuiltin_strcat : Flag<"-fbuiltin-strcat">, Group<f_Group>;
def fbuiltin_strcpy : Flag<"-fbuiltin-strcpy">, Group<f_Group>;
def fbuiltin : Flag<"-fbuiltin">, Group<f_Group>;
@@ -260,6 +262,7 @@ def fdebug_pass_structure : Flag<"-fdebug-pass-structure">, Group<f_Group>;
def fdiagnostics_binary : Flag<"-fdiagnostics-binary">, Group<f_Group>, Flags<[HelpHidden]>;
def fdiagnostics_fixit_info : Flag<"-fdiagnostics-fixit-info">, Group<f_Group>;
def fdiagnostics_print_source_range_info : Flag<"-fdiagnostics-print-source-range-info">, Group<f_Group>;
+def fdiagnostics_parseable_fixits : Flag<"-fdiagnostics-parseable-fixits">, Group<f_Group>;
def fdiagnostics_show_option : Flag<"-fdiagnostics-show-option">, Group<f_Group>;
def fdiagnostics_show_category_EQ : Joined<"-fdiagnostics-show-category=">, Group<f_Group>;
def fdollars_in_identifiers : Flag<"-fdollars-in-identifiers">, Group<f_Group>;
@@ -300,6 +303,7 @@ def fno_asm : Flag<"-fno-asm">, Group<f_Group>;
def fno_asynchronous_unwind_tables : Flag<"-fno-asynchronous-unwind-tables">, Group<f_Group>;
def fno_assume_sane_operator_new : Flag<"-fno-assume-sane-operator-new">, Group<f_Group>;
def fno_blocks : Flag<"-fno-blocks">, Group<f_Group>;
+def fno_borland_extensions : Flag<"-fno-borland-extensions">, Group<f_Group>;
def fno_builtin_strcat : Flag<"-fno-builtin-strcat">, Group<f_Group>;
def fno_builtin_strcpy : Flag<"-fno-builtin-strcpy">, Group<f_Group>;
def fno_builtin : Flag<"-fno-builtin">, Group<f_Group>;
@@ -361,6 +365,7 @@ def fno_pie : Flag<"-fno-pie">, Group<f_Group>;
def fprofile_arcs : Flag<"-fprofile-arcs">, Group<f_Group>;
def fprofile_generate : Flag<"-fprofile-generate">, Group<f_Group>;
def framework : Separate<"-framework">, Flags<[LinkerInput]>;
+def frandom_seed_EQ : Joined<"-frandom-seed=">, Group<clang_ignored_f_Group>;
def frtti : Flag<"-frtti">, Group<f_Group>;
def fsched_interblock : Flag<"-fsched-interblock">, Group<clang_ignored_f_Group>;
def fshort_enums : Flag<"-fshort-enums">, Group<clang_ignored_f_Group>;
@@ -385,6 +390,7 @@ def fthreadsafe_statics : Flag<"-fthreadsafe-statics">, Group<f_Group>;
def ftime_report : Flag<"-ftime-report">, Group<f_Group>;
def ftrapv : Flag<"-ftrapv">, Group<f_Group>;
def funit_at_a_time : Flag<"-funit-at-a-time">, Group<f_Group>;
+def funroll_loops : Flag<"-funroll-loops">, Group<f_Group>;
def funsigned_bitfields : Flag<"-funsigned-bitfields">, Group<f_Group>;
def funsigned_char : Flag<"-funsigned-char">, Group<f_Group>;
def funwind_tables : Flag<"-funwind-tables">, Group<f_Group>;
@@ -420,7 +426,7 @@ def isysroot : JoinedOrSeparate<"-isysroot">, Group<clang_i_Group>;
def isystem : JoinedOrSeparate<"-isystem">, Group<clang_i_Group>;
def iwithprefixbefore : JoinedOrSeparate<"-iwithprefixbefore">, Group<clang_i_Group>;
def iwithprefix : JoinedOrSeparate<"-iwithprefix">, Group<clang_i_Group>;
-def iwithsysroot : JoinedOrSeparate<"-iwithsysroot">, Group<i_Group>;
+def iwithsysroot : JoinedOrSeparate<"-iwithsysroot">, Group<clang_i_Group>;
def i : Joined<"-i">, Group<i_Group>;
def keep__private__externs : Flag<"-keep_private_externs">;
def l : JoinedOrSeparate<"-l">, Flags<[LinkerInput, RenderJoined]>;
@@ -441,6 +447,7 @@ def mhard_float : Flag<"-mhard-float">, Group<m_Group>;
def miphoneos_version_min_EQ : Joined<"-miphoneos-version-min=">, Group<m_Group>;
def mios_version_min_EQ : Joined<"-mios-version-min=">, Alias<miphoneos_version_min_EQ>;
def mkernel : Flag<"-mkernel">, Group<m_Group>;
+def mlinker_version_EQ : Joined<"-mlinker-version=">, Flags<[NoForward]>;
def mllvm : Separate<"-mllvm">;
def mmacosx_version_min_EQ : Joined<"-mmacosx-version-min=">, Group<m_Group>;
def mmmx : Flag<"-mmmx">, Group<m_x86_Features_Group>;
@@ -461,6 +468,7 @@ def mno_sse4_2 : Flag<"-mno-sse4.2">, Group<m_x86_Features_Group>;
def mno_sse : Flag<"-mno-sse">, Group<m_x86_Features_Group>;
def mno_ssse3 : Flag<"-mno-ssse3">, Group<m_x86_Features_Group>;
def mno_aes : Flag<"-mno-aes">, Group<m_x86_Features_Group>;
+def mno_avx : Flag<"-mno-avx">, Group<m_x86_Features_Group>;
def mno_thumb : Flag<"-mno-thumb">, Group<m_Group>;
def marm : Flag<"-marm">, Alias<mno_thumb>;
@@ -481,6 +489,7 @@ def msse4_2 : Flag<"-msse4.2">, Group<m_x86_Features_Group>;
def msse : Flag<"-msse">, Group<m_x86_Features_Group>;
def mssse3 : Flag<"-mssse3">, Group<m_x86_Features_Group>;
def maes : Flag<"-maes">, Group<m_x86_Features_Group>;
+def mavx : Flag<"-mavx">, Group<m_x86_Features_Group>;
def mthumb : Flag<"-mthumb">, Group<m_Group>;
def mtune_EQ : Joined<"-mtune=">, Group<m_Group>;
def multi__module : Flag<"-multi_module">;
diff --git a/include/clang/Driver/Tool.h b/include/clang/Driver/Tool.h
index 4368a81e3a41..c30fa4c6e731 100644
--- a/include/clang/Driver/Tool.h
+++ b/include/clang/Driver/Tool.h
@@ -49,8 +49,6 @@ public:
const ToolChain &getToolChain() const { return TheToolChain; }
- virtual bool acceptsPipedInput() const = 0;
- virtual bool canPipeOutput() const = 0;
virtual bool hasIntegratedAssembler() const { return false; }
virtual bool hasIntegratedCPP() const = 0;
@@ -61,13 +59,11 @@ public:
/// ConstructJob - Construct jobs to perform the action \arg JA,
/// writing to \arg Output and with \arg Inputs.
///
- /// \param Dest - Where to put the resulting commands.
/// \param TCArgs - The argument list for this toolchain, with any
/// tool chain specific translations applied.
/// \param LinkingOutput - If this output will eventually feed the
/// linker, then this is the final output name of the linked image.
virtual void ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &TCArgs,
diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h
index 11a153c48ca3..55be4eee3d19 100644
--- a/include/clang/Driver/ToolChain.h
+++ b/include/clang/Driver/ToolChain.h
@@ -10,6 +10,7 @@
#ifndef CLANG_DRIVER_TOOLCHAIN_H_
#define CLANG_DRIVER_TOOLCHAIN_H_
+#include "clang/Driver/Types.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Triple.h"
#include "llvm/System/Path.h"
@@ -17,6 +18,7 @@
namespace clang {
namespace driver {
+ class ArgList;
class Compilation;
class DerivedArgList;
class Driver;
@@ -53,6 +55,7 @@ public:
const Driver &getDriver() const;
const llvm::Triple &getTriple() const { return Triple; }
+ llvm::Triple::ArchType getArch() const { return Triple.getArch(); }
llvm::StringRef getArchName() const { return Triple.getArchName(); }
llvm::StringRef getPlatform() const { return Triple.getVendorName(); }
llvm::StringRef getOS() const { return Triple.getOSName(); }
@@ -89,6 +92,10 @@ public:
// Platform defaults information
+ /// LookupTypeForExtension - Return the default language type to use for the
+ /// given extension.
+ virtual types::ID LookupTypeForExtension(const char *Ext) const;
+
/// IsBlocksDefault - Does this tool chain enable -fblocks by default.
virtual bool IsBlocksDefault() const { return false; }
@@ -135,6 +142,17 @@ public:
/// UseSjLjExceptions - Does this tool chain use SjLj exceptions.
virtual bool UseSjLjExceptions() const { return false; }
+
+ /// ComputeLLVMTriple - Return the LLVM target triple to use, after taking
+ /// command line arguments into account.
+ virtual std::string ComputeLLVMTriple(const ArgList &Args) const;
+
+ /// ComputeEffectiveClangTriple - Return the Clang triple to use for this
+ /// target, which may take into account the command line arguments. For
+ /// example, on Darwin the -mmacosx-version-min= command line argument (which
+ /// sets the deployment target) determines the version in the triple passed to
+ /// Clang.
+ virtual std::string ComputeEffectiveClangTriple(const ArgList &Args) const;
};
} // end namespace driver
diff --git a/include/clang/Frontend/ASTConsumers.h b/include/clang/Frontend/ASTConsumers.h
index 2d1df44cc968..cca243d6cd71 100644
--- a/include/clang/Frontend/ASTConsumers.h
+++ b/include/clang/Frontend/ASTConsumers.h
@@ -29,7 +29,6 @@ class CodeGenOptions;
class Diagnostic;
class FileManager;
class LangOptions;
-class PCHReader;
class Preprocessor;
class TargetOptions;
@@ -58,14 +57,6 @@ ASTConsumer *CreateASTViewer();
// to stderr; this is intended for debugging.
ASTConsumer *CreateDeclContextPrinter();
-// PCH generator: generates a precompiled header file; this file can be used
-// later with the PCHReader (clang -cc1 option -include-pch) to speed up compile
-// times.
-ASTConsumer *CreatePCHGenerator(const Preprocessor &PP,
- llvm::raw_ostream *OS,
- PCHReader *Chain,
- const char *isysroot = 0);
-
// Inheritance viewer: for C++ code, creates a graph of the inheritance
// tree for the given class and displays it with "dotty".
ASTConsumer *CreateInheritanceViewer(const std::string& clsname);
diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h
index 9252358f42a6..e3fd4b37edac 100644
--- a/include/clang/Frontend/ASTUnit.h
+++ b/include/clang/Frontend/ASTUnit.h
@@ -14,19 +14,26 @@
#ifndef LLVM_CLANG_FRONTEND_ASTUNIT_H
#define LLVM_CLANG_FRONTEND_ASTUNIT_H
+#include "clang/Index/ASTLocation.h"
+#include "clang/Serialization/ASTBitCodes.h"
+#include "clang/Sema/Sema.h"
+#include "clang/Sema/CodeCompleteConsumer.h"
#include "clang/Lex/PreprocessingRecord.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/FileManager.h"
+#include "clang-c/Index.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/OwningPtr.h"
-#include "clang/Basic/FileManager.h"
-#include "clang/Index/ASTLocation.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/System/Path.h"
+#include "llvm/Support/Timer.h"
#include <map>
#include <string>
#include <vector>
#include <cassert>
#include <utility>
+#include <sys/types.h>
namespace llvm {
class MemoryBuffer;
@@ -34,6 +41,7 @@ namespace llvm {
namespace clang {
class ASTContext;
+class CodeCompleteConsumer;
class CompilerInvocation;
class Decl;
class Diagnostic;
@@ -45,13 +53,14 @@ class SourceManager;
class TargetInfo;
using namespace idx;
-
-/// \brief Utility class for loading a ASTContext from a PCH file.
+
+/// \brief Utility class for loading a ASTContext from an AST file.
///
class ASTUnit {
public:
typedef std::map<FileID, std::vector<PreprocessedEntity *> >
PreprocessedEntitiesByFileMap;
+
private:
llvm::IntrusiveRefCntPtr<Diagnostic> Diagnostics;
llvm::OwningPtr<FileManager> FileMgr;
@@ -61,18 +70,32 @@ private:
llvm::OwningPtr<Preprocessor> PP;
llvm::OwningPtr<ASTContext> Ctx;
+ /// \brief The AST consumer that received information about the translation
+ /// unit as it was parsed or loaded.
+ llvm::OwningPtr<ASTConsumer> Consumer;
+
+ /// \brief The semantic analysis object used to type-check the translation
+ /// unit.
+ llvm::OwningPtr<Sema> TheSema;
+
/// Optional owned invocation, just used to make the invocation used in
/// LoadFromCommandLine available.
llvm::OwningPtr<CompilerInvocation> Invocation;
-
+
// OnlyLocalDecls - when true, walking this AST should only visit declarations
// that come from the AST itself, not from included precompiled headers.
// FIXME: This is temporary; eventually, CIndex will always do this.
bool OnlyLocalDecls;
- /// Track whether the main file was loaded from an AST or not.
+ /// \brief Whether to capture any diagnostics produced.
+ bool CaptureDiagnostics;
+
+ /// \brief Track whether the main file was loaded from an AST or not.
bool MainFileIsAST;
+ /// \brief Whether this AST represents a complete translation unit.
+ bool CompleteTranslationUnit;
+
/// Track the top-level decls which appeared in an ASTUnit which was loaded
/// from a source file.
//
@@ -114,12 +137,189 @@ private:
unsigned int ConcurrencyCheckValue;
static const unsigned int CheckLocked = 28573289;
static const unsigned int CheckUnlocked = 9803453;
+
+ /// \brief Counter that determines when we want to try building a
+ /// precompiled preamble.
+ ///
+ /// If zero, we will never build a precompiled preamble. Otherwise,
+ /// it's treated as a counter that decrements each time we reparse
+ /// without the benefit of a precompiled preamble. When it hits 1,
+ /// we'll attempt to rebuild the precompiled header. This way, if
+ /// building the precompiled preamble fails, we won't try again for
+ /// some number of calls.
+ unsigned PreambleRebuildCounter;
+
+ /// \brief The file in which the precompiled preamble is stored.
+ std::string PreambleFile;
+
+ /// \brief The contents of the preamble that has been precompiled to
+ /// \c PreambleFile.
+ std::vector<char> Preamble;
+
+ /// \brief Whether the preamble ends at the start of a new line.
+ ///
+ /// Used to inform the lexer as to whether it's starting at the beginning of
+ /// a line after skipping the preamble.
+ bool PreambleEndsAtStartOfLine;
+
+ /// \brief The size of the source buffer that we've reserved for the main
+ /// file within the precompiled preamble.
+ unsigned PreambleReservedSize;
+
+ /// \brief Keeps track of the files that were used when computing the
+ /// preamble, with both their buffer size and their modification time.
+ ///
+ /// If any of the files have changed from one compile to the next,
+ /// the preamble must be thrown away.
+ llvm::StringMap<std::pair<off_t, time_t> > FilesInPreamble;
+
+ /// \brief When non-NULL, this is the buffer used to store the contents of
+ /// the main file when it has been padded for use with the precompiled
+ /// preamble.
+ llvm::MemoryBuffer *SavedMainFileBuffer;
+
+ /// \brief When non-NULL, this is the buffer used to store the
+ /// contents of the preamble when it has been padded to build the
+ /// precompiled preamble.
+ llvm::MemoryBuffer *PreambleBuffer;
+
+ /// \brief The number of warnings that occurred while parsing the preamble.
+ ///
+ /// This value will be used to restore the state of the \c Diagnostic object
+ /// when re-using the precompiled preamble. Note that only the
+ /// number of warnings matters, since we will not save the preamble
+ /// when any errors are present.
+ unsigned NumWarningsInPreamble;
+
+ /// \brief The number of diagnostics that were stored when parsing
+ /// the precompiled preamble.
+ ///
+ /// This value is used to determine how many of the stored
+ /// diagnostics should be retained when reparsing in the presence of
+ /// a precompiled preamble.
+ unsigned NumStoredDiagnosticsInPreamble;
+
+ /// \brief The group of timers associated with this translation unit.
+ llvm::OwningPtr<llvm::TimerGroup> TimerGroup;
+
+ /// \brief A list of the serialization ID numbers for each of the top-level
+ /// declarations parsed within the precompiled preamble.
+ std::vector<serialization::DeclID> TopLevelDeclsInPreamble;
+
+ ///
+ /// \defgroup CodeCompleteCaching Code-completion caching
+ ///
+ /// \{
+ ///
+
+ /// \brief Whether we should be caching code-completion results.
+ bool ShouldCacheCodeCompletionResults;
+
+public:
+ /// \brief A cached code-completion result, which may be introduced in one of
+ /// many different contexts.
+ struct CachedCodeCompletionResult {
+ /// \brief The code-completion string corresponding to this completion
+ /// result.
+ CodeCompletionString *Completion;
+
+ /// \brief A bitmask that indicates which code-completion contexts should
+ /// contain this completion result.
+ ///
+ /// The bits in the bitmask correspond to the values of
+ /// CodeCompleteContext::Kind. To map from a completion context kind to a
+ /// bit, subtract one from the completion context kind and shift 1 by that
+ /// number of bits. Many completions can occur in several different
+ /// contexts.
+ unsigned ShowInContexts;
+
+ /// \brief The priority given to this code-completion result.
+ unsigned Priority;
+
+ /// \brief The libclang cursor kind corresponding to this code-completion
+ /// result.
+ CXCursorKind Kind;
+
+ /// \brief The availability of this code-completion result.
+ CXAvailabilityKind Availability;
+
+ /// \brief The simplified type class for a non-macro completion result.
+ SimplifiedTypeClass TypeClass;
+
+ /// \brief The type of a non-macro completion result, stored as a unique
+ /// integer used by the string map of cached completion types.
+ ///
+ /// This value will be zero if the type is not known, or a unique value
+ /// determined by the formatted type string. Se \c CachedCompletionTypes
+ /// for more information.
+ unsigned Type;
+ };
+
+ /// \brief Retrieve the mapping from formatted type names to unique type
+ /// identifiers.
+ llvm::StringMap<unsigned> &getCachedCompletionTypes() {
+ return CachedCompletionTypes;
+ }
+
+private:
+ /// \brief The set of cached code-completion results.
+ std::vector<CachedCodeCompletionResult> CachedCompletionResults;
+
+ /// \brief A mapping from the formatted type name to a unique number for that
+ /// type, which is used for type equality comparisons.
+ llvm::StringMap<unsigned> CachedCompletionTypes;
+
+ /// \brief The number of top-level declarations present the last time we
+ /// cached code-completion results.
+ ///
+ /// The value is used to help detect when we should repopulate the global
+ /// completion cache.
+ unsigned NumTopLevelDeclsAtLastCompletionCache;
+
+ /// \brief The number of reparses left until we'll consider updating the
+ /// code-completion cache.
+ ///
+ /// This is meant to avoid thrashing during reparsing, by not allowing the
+ /// code-completion cache to be updated on every reparse.
+ unsigned CacheCodeCompletionCoolDown;
+
+ /// \brief Bit used by CIndex to mark when a translation unit may be in an
+ /// inconsistent state, and is not safe to free.
+ unsigned UnsafeToFree : 1;
+
+ /// \brief Cache any "global" code-completion results, so that we can avoid
+ /// recomputing them with each completion.
+ void CacheCodeCompletionResults();
+
+ /// \brief Clear out and deallocate
+ void ClearCachedCompletionResults();
+
+ ///
+ /// \}
+ ///
+
+ /// \brief The timers we've created from the various parses, reparses, etc.
+ /// involved in this translation unit.
+ std::vector<llvm::Timer *> Timers;
ASTUnit(const ASTUnit&); // DO NOT IMPLEMENT
ASTUnit &operator=(const ASTUnit &); // DO NOT IMPLEMENT
explicit ASTUnit(bool MainFileIsAST);
+ void CleanTemporaryFiles();
+ bool Parse(llvm::MemoryBuffer *OverrideMainBuffer);
+
+ std::pair<llvm::MemoryBuffer *, std::pair<unsigned, bool> >
+ ComputePreamble(CompilerInvocation &Invocation,
+ unsigned MaxLines, bool &CreatedBuffer);
+
+ llvm::MemoryBuffer *getMainBufferWithPrecompiledPreamble(
+ CompilerInvocation PreambleInvocation,
+ bool AllowRebuild = true,
+ unsigned MaxLines = 0);
+ void RealizeTopLevelDeclsFromPreamble();
+
public:
class ConcurrencyCheck {
volatile ASTUnit &Self;
@@ -143,6 +343,9 @@ public:
bool isMainFileAST() const { return MainFileIsAST; }
+ bool isUnsafeToFree() const { return UnsafeToFree; }
+ void setUnsafeToFree(bool Value) { UnsafeToFree = Value; }
+
const Diagnostic &getDiagnostics() const { return *Diagnostics; }
Diagnostic &getDiagnostics() { return *Diagnostics; }
@@ -155,11 +358,17 @@ public:
const ASTContext &getASTContext() const { return *Ctx.get(); }
ASTContext &getASTContext() { return *Ctx.get(); }
+ bool hasSema() const { return TheSema; }
+ Sema &getSema() const {
+ assert(TheSema && "ASTUnit does not have a Sema object!");
+ return *TheSema;
+ }
+
const FileManager &getFileManager() const { return *FileMgr; }
FileManager &getFileManager() { return *FileMgr; }
const std::string &getOriginalSourceFileName();
- const std::string &getPCHFileName();
+ const std::string &getASTFileName();
/// \brief Add a temporary file that the ASTUnit depends on.
///
@@ -170,16 +379,48 @@ public:
bool getOnlyLocalDecls() const { return OnlyLocalDecls; }
+ /// \brief Retrieve the maximum PCH level of declarations that a
+ /// traversal of the translation unit should consider.
+ unsigned getMaxPCHLevel() const;
+
void setLastASTLocation(ASTLocation ALoc) { LastLoc = ALoc; }
ASTLocation getLastASTLocation() const { return LastLoc; }
- std::vector<Decl*> &getTopLevelDecls() {
+ typedef std::vector<Decl *>::iterator top_level_iterator;
+
+ top_level_iterator top_level_begin() {
+ assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!");
+ if (!TopLevelDeclsInPreamble.empty())
+ RealizeTopLevelDeclsFromPreamble();
+ return TopLevelDecls.begin();
+ }
+
+ top_level_iterator top_level_end() {
+ assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!");
+ if (!TopLevelDeclsInPreamble.empty())
+ RealizeTopLevelDeclsFromPreamble();
+ return TopLevelDecls.end();
+ }
+
+ std::size_t top_level_size() const {
assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!");
- return TopLevelDecls;
+ return TopLevelDeclsInPreamble.size() + TopLevelDecls.size();
}
- const std::vector<Decl*> &getTopLevelDecls() const {
+
+ bool top_level_empty() const {
assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!");
- return TopLevelDecls;
+ return TopLevelDeclsInPreamble.empty() && TopLevelDecls.empty();
+ }
+
+ /// \brief Add a new top-level declaration.
+ void addTopLevelDecl(Decl *D) {
+ TopLevelDecls.push_back(D);
+ }
+
+ /// \brief Add a new top-level declaration, identified by its ID in
+ /// the precompiled preamble.
+ void addTopLevelDeclFromPreamble(serialization::DeclID D) {
+ TopLevelDeclsInPreamble.push_back(D);
}
/// \brief Retrieve the mapping from File IDs to the preprocessed entities
@@ -202,19 +443,40 @@ public:
return StoredDiagnostics;
}
+ typedef std::vector<CachedCodeCompletionResult>::iterator
+ cached_completion_iterator;
+
+ cached_completion_iterator cached_completion_begin() {
+ return CachedCompletionResults.begin();
+ }
+
+ cached_completion_iterator cached_completion_end() {
+ return CachedCompletionResults.end();
+ }
+
+ unsigned cached_completion_size() const {
+ return CachedCompletionResults.size();
+ }
+
+ /// \brief Whether this AST represents a complete translation unit.
+ ///
+ /// If false, this AST is only a partial translation unit, e.g., one
+ /// that might still be used as a precompiled header or preamble.
+ bool isCompleteTranslationUnit() const { return CompleteTranslationUnit; }
+
/// \brief A mapping from a file name to the memory buffer that stores the
/// remapped contents of that file.
typedef std::pair<std::string, const llvm::MemoryBuffer *> RemappedFile;
- /// \brief Create a ASTUnit from a PCH file.
+ /// \brief Create a ASTUnit from an AST file.
///
- /// \param Filename - The PCH file to load.
+ /// \param Filename - The AST file to load.
///
/// \param Diags - The diagnostics engine to use for reporting errors; its
/// lifetime is expected to extend past that of the returned ASTUnit.
///
- /// \returns - The initialized ASTUnit or null if the PCH failed to load.
- static ASTUnit *LoadFromPCHFile(const std::string &Filename,
+ /// \returns - The initialized ASTUnit or null if the AST failed to load.
+ static ASTUnit *LoadFromASTFile(const std::string &Filename,
llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
bool OnlyLocalDecls = false,
RemappedFile *RemappedFiles = 0,
@@ -235,7 +497,10 @@ public:
static ASTUnit *LoadFromCompilerInvocation(CompilerInvocation *CI,
llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
bool OnlyLocalDecls = false,
- bool CaptureDiagnostics = false);
+ bool CaptureDiagnostics = false,
+ bool PrecompilePreamble = false,
+ bool CompleteTranslationUnit = true,
+ bool CacheCodeCompletionResults = false);
/// LoadFromCommandLine - Create an ASTUnit from a vector of command line
/// arguments, which must specify exactly one source file.
@@ -258,7 +523,49 @@ public:
bool OnlyLocalDecls = false,
RemappedFile *RemappedFiles = 0,
unsigned NumRemappedFiles = 0,
- bool CaptureDiagnostics = false);
+ bool CaptureDiagnostics = false,
+ bool PrecompilePreamble = false,
+ bool CompleteTranslationUnit = true,
+ bool CacheCodeCompletionResults = false);
+
+ /// \brief Reparse the source files using the same command-line options that
+ /// were originally used to produce this translation unit.
+ ///
+ /// \returns True if a failure occurred that causes the ASTUnit not to
+ /// contain any translation-unit information, false otherwise.
+ bool Reparse(RemappedFile *RemappedFiles = 0,
+ unsigned NumRemappedFiles = 0);
+
+ /// \brief Perform code completion at the given file, line, and
+ /// column within this translation unit.
+ ///
+ /// \param File The file in which code completion will occur.
+ ///
+ /// \param Line The line at which code completion will occur.
+ ///
+ /// \param Column The column at which code completion will occur.
+ ///
+ /// \param IncludeMacros Whether to include macros in the code-completion
+ /// results.
+ ///
+ /// \param IncludeCodePatterns Whether to include code patterns (such as a
+ /// for loop) in the code-completion results.
+ ///
+ /// FIXME: The Diag, LangOpts, SourceMgr, FileMgr, StoredDiagnostics, and
+ /// OwnedBuffers parameters are all disgusting hacks. They will go away.
+ void CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column,
+ RemappedFile *RemappedFiles, unsigned NumRemappedFiles,
+ bool IncludeMacros, bool IncludeCodePatterns,
+ CodeCompleteConsumer &Consumer,
+ Diagnostic &Diag, LangOptions &LangOpts,
+ SourceManager &SourceMgr, FileManager &FileMgr,
+ llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics,
+ llvm::SmallVectorImpl<const llvm::MemoryBuffer *> &OwnedBuffers);
+
+ /// \brief Save this translation unit to a file with the given name.
+ ///
+ /// \returns True if an error occurred, false otherwise.
+ bool Save(llvm::StringRef File);
};
} // namespace clang
diff --git a/include/clang/Frontend/AnalyzerOptions.h b/include/clang/Frontend/AnalyzerOptions.h
index ab4aed96d864..9ed15ba2f996 100644
--- a/include/clang/Frontend/AnalyzerOptions.h
+++ b/include/clang/Frontend/AnalyzerOptions.h
@@ -66,6 +66,7 @@ public:
unsigned AnalyzerDisplayProgress : 1;
unsigned AnalyzeNestedBlocks : 1;
unsigned EagerlyAssume : 1;
+ unsigned IdempotentOps : 1;
unsigned PurgeDead : 1;
unsigned TrimGraph : 1;
unsigned VisualizeEGDot : 1;
@@ -74,6 +75,7 @@ public:
unsigned EnableExperimentalInternalChecks : 1;
unsigned EnableIdempotentOperationChecker : 1;
unsigned InlineCall : 1;
+ unsigned UnoptimizedCFG : 1;
public:
AnalyzerOptions() {
@@ -90,6 +92,7 @@ public:
VisualizeEGUbi = 0;
EnableExperimentalChecks = 0;
EnableExperimentalInternalChecks = 0;
+ UnoptimizedCFG = 0;
}
};
diff --git a/include/clang/Frontend/CodeGenOptions.h b/include/clang/Frontend/CodeGenOptions.h
index 2918f4e9d3cb..b3f57094b4af 100644
--- a/include/clang/Frontend/CodeGenOptions.h
+++ b/include/clang/Frontend/CodeGenOptions.h
@@ -46,7 +46,14 @@ public:
/// internal state before optimizations are
/// done.
unsigned DisableRedZone : 1; /// Set when -mno-red-zone is enabled.
+ unsigned EmitDeclMetadata : 1; /// Emit special metadata indicating what Decl*
+ /// various IR entities came from. Only useful
+ /// when running CodeGen as a subroutine.
unsigned FunctionSections : 1; /// Set when -ffunction-sections is enabled
+ unsigned HiddenWeakTemplateVTables : 1; /// Emit weak vtables and RTTI for
+ /// template classes with hidden visibility
+ unsigned HiddenWeakVTables : 1; /// Emit weak vtables, RTTI, and thunks with
+ /// hidden visibility
unsigned InstrumentFunctions : 1; /// Set when -finstrument-functions is enabled
unsigned MergeAllConstants : 1; /// Merge identical constants.
unsigned NoCommon : 1; /// Set when -fno-common or C++ is enabled.
@@ -67,9 +74,6 @@ public:
unsigned UnwindTables : 1; /// Emit unwind tables.
unsigned VerifyModule : 1; /// Control whether the module should be run
/// through the LLVM Verifier.
- unsigned EmitDeclMetadata : 1; /// Emit special metadata indicating what Decl*
- /// various IR entities came from. Only useful
- /// when running CodeGen as a subroutine.
/// The code model to use (-mcmodel).
std::string CodeModel;
@@ -108,7 +112,11 @@ public:
DisableFPElim = 0;
DisableLLVMOpts = 0;
DisableRedZone = 0;
+ EmitDeclMetadata = 0;
FunctionSections = 0;
+ HiddenWeakTemplateVTables = 0;
+ HiddenWeakVTables = 0;
+ InstrumentFunctions = 0;
MergeAllConstants = 1;
NoCommon = 0;
NoImplicitFloat = 0;
@@ -125,7 +133,6 @@ public:
UnrollLoops = 0;
UnwindTables = 0;
VerifyModule = 1;
- EmitDeclMetadata = 0;
Inlining = NoInlining;
RelocationModel = "pic";
diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h
index 54ce8bfe3ba0..1b3c336fc0eb 100644
--- a/include/clang/Frontend/CompilerInstance.h
+++ b/include/clang/Frontend/CompilerInstance.h
@@ -34,8 +34,9 @@ class DiagnosticClient;
class ExternalASTSource;
class FileManager;
class FrontendAction;
-class PCHReader;
+class ASTReader;
class Preprocessor;
+class Sema;
class SourceManager;
class TargetInfo;
@@ -67,9 +68,6 @@ class CompilerInstance {
/// The diagnostics engine instance.
llvm::IntrusiveRefCntPtr<Diagnostic> Diagnostics;
- /// The diagnostics client instance.
- llvm::OwningPtr<DiagnosticClient> DiagClient;
-
/// The target being compiled for.
llvm::OwningPtr<TargetInfo> Target;
@@ -91,15 +89,15 @@ class CompilerInstance {
/// The code completion consumer.
llvm::OwningPtr<CodeCompleteConsumer> CompletionConsumer;
+ /// \brief The semantic analysis object.
+ llvm::OwningPtr<Sema> TheSema;
+
/// The frontend timer
llvm::OwningPtr<llvm::Timer> FrontendTimer;
/// The list of active output files.
std::list< std::pair<std::string, llvm::raw_ostream*> > OutputFiles;
- /// The PCH reader. Not owned; the ASTContext owns this.
- PCHReader *Reader;
-
void operator=(const CompilerInstance &); // DO NOT IMPLEMENT
CompilerInstance(const CompilerInstance&); // DO NOT IMPLEMENT
public:
@@ -265,18 +263,11 @@ public:
void setDiagnostics(Diagnostic *Value);
DiagnosticClient &getDiagnosticClient() const {
- assert(DiagClient && "Compiler instance has no diagnostic client!");
- return *DiagClient;
+ assert(Diagnostics && Diagnostics->getClient() &&
+ "Compiler instance has no diagnostic client!");
+ return *Diagnostics->getClient();
}
- /// takeDiagnosticClient - Remove the current diagnostics client and give
- /// ownership to the caller.
- DiagnosticClient *takeDiagnosticClient() { return DiagClient.take(); }
-
- /// setDiagnosticClient - Replace the current diagnostics client; the compiler
- /// instance takes ownership of \arg Value.
- void setDiagnosticClient(DiagnosticClient *Value);
-
/// }
/// @name Target Info
/// {
@@ -372,6 +363,10 @@ public:
/// takes ownership of \arg Value.
void setASTContext(ASTContext *Value);
+ /// \brief Replace the current Sema; the compiler instance takes ownership
+ /// of S.
+ void setSema(Sema *S);
+
/// }
/// @name ASTConsumer
/// {
@@ -392,6 +387,18 @@ public:
void setASTConsumer(ASTConsumer *Value);
/// }
+ /// @name Semantic analysis
+ /// {
+ bool hasSema() const { return TheSema != 0; }
+
+ Sema &getSema() const {
+ assert(TheSema && "Compiler instance has no Sema object!");
+ return *TheSema;
+ }
+
+ Sema *takeSema() { return TheSema.take(); }
+
+ /// }
/// @name Code Completion
/// {
@@ -502,17 +509,18 @@ public:
/// Create an external AST source to read a PCH file and attach it to the AST
/// context.
- void createPCHExternalASTSource(llvm::StringRef Path);
+ void createPCHExternalASTSource(llvm::StringRef Path,
+ bool DisablePCHValidation,
+ void *DeserializationListener);
/// Create an external AST source to read a PCH file.
///
/// \return - The new object on success, or null on failure.
static ExternalASTSource *
createPCHExternalASTSource(llvm::StringRef Path, const std::string &Sysroot,
- Preprocessor &PP, ASTContext &Context);
-
- /// Get the PCH reader, if any.
- PCHReader *getPCHReader() { return Reader; }
+ bool DisablePCHValidation,
+ Preprocessor &PP, ASTContext &Context,
+ void *DeserializationListener);
/// Create a code completion consumer using the invocation; note that this
/// will cause the source manager to truncate the input source file at the
@@ -526,8 +534,13 @@ public:
createCodeCompletionConsumer(Preprocessor &PP, const std::string &Filename,
unsigned Line, unsigned Column,
bool UseDebugPrinter, bool ShowMacros,
- bool ShowCodePatterns, llvm::raw_ostream &OS);
+ bool ShowCodePatterns, bool ShowGlobals,
+ llvm::raw_ostream &OS);
+ /// \brief Create the Sema object to be used for parsing.
+ void createSema(bool CompleteTranslationUnit,
+ CodeCompleteConsumer *CompletionConsumer);
+
/// Create the frontend timer and replace any existing one with it.
void createFrontendTimer();
diff --git a/include/clang/Frontend/DeclXML.def b/include/clang/Frontend/DeclXML.def
index 16551ee03e1f..18451189bc06 100644
--- a/include/clang/Frontend/DeclXML.def
+++ b/include/clang/Frontend/DeclXML.def
@@ -95,10 +95,10 @@ NODE_XML(FunctionDecl, "Function")
TYPE_ATTRIBUTE_XML(getType()->getAs<FunctionType>()->getResultType())
ATTRIBUTE_XML(getType()->getAs<FunctionType>(), "function_type")
ATTRIBUTE_ENUM_OPT_XML(getStorageClass(), "storage_class")
- ENUM_XML(FunctionDecl::None, "")
- ENUM_XML(FunctionDecl::Extern, "extern")
- ENUM_XML(FunctionDecl::Static, "static")
- ENUM_XML(FunctionDecl::PrivateExtern, "__private_extern__")
+ ENUM_XML(SC_None, "")
+ ENUM_XML(SC_Extern, "extern")
+ ENUM_XML(SC_Static, "static")
+ ENUM_XML(SC_PrivateExtern, "__private_extern__")
END_ENUM_XML
ATTRIBUTE_OPT_XML(isInlineSpecified(), "inline")
//ATTRIBUTE_OPT_XML(isVariadic(), "variadic") // in the type reference
@@ -289,12 +289,12 @@ NODE_XML(VarDecl, "Var")
ATTRIBUTE_XML(getNameAsString(), "name")
TYPE_ATTRIBUTE_XML(getType())
ATTRIBUTE_ENUM_OPT_XML(getStorageClass(), "storage_class")
- ENUM_XML(VarDecl::None, "")
- ENUM_XML(VarDecl::Auto, "auto")
- ENUM_XML(VarDecl::Register, "register")
- ENUM_XML(VarDecl::Extern, "extern")
- ENUM_XML(VarDecl::Static, "static")
- ENUM_XML(VarDecl::PrivateExtern, "__private_extern__")
+ ENUM_XML(SC_None, "")
+ ENUM_XML(SC_Auto, "auto")
+ ENUM_XML(SC_Register, "register")
+ ENUM_XML(SC_Extern, "extern")
+ ENUM_XML(SC_Static, "static")
+ ENUM_XML(SC_PrivateExtern, "__private_extern__")
END_ENUM_XML
SUB_NODE_OPT_XML(Expr) // init expr
END_NODE_XML
diff --git a/include/clang/Frontend/DiagnosticOptions.h b/include/clang/Frontend/DiagnosticOptions.h
index 516dc67b425d..c80bc037212b 100644
--- a/include/clang/Frontend/DiagnosticOptions.h
+++ b/include/clang/Frontend/DiagnosticOptions.h
@@ -30,6 +30,7 @@ public:
unsigned ShowCarets : 1; /// Show carets in diagnostics.
unsigned ShowFixits : 1; /// Show fixit information.
unsigned ShowSourceRanges : 1; /// Show source ranges in numeric form.
+ unsigned ShowParseableFixits : 1; /// Show machine parseable fix-its.
unsigned ShowOptionNames : 1; /// Show the diagnostic name for mappable
/// diagnostics.
unsigned ShowCategories : 2; /// Show categories: 0 -> none, 1 -> Number,
@@ -83,6 +84,7 @@ public:
ShowOptionNames = 0;
ShowCategories = 0;
ShowSourceRanges = 0;
+ ShowParseableFixits = 0;
VerifyDiagnostics = 0;
BinaryOutput = 0;
ErrorLimit = 0;
diff --git a/include/clang/Frontend/DocumentXML.h b/include/clang/Frontend/DocumentXML.h
index 73d892105f21..602d84655828 100644
--- a/include/clang/Frontend/DocumentXML.h
+++ b/include/clang/Frontend/DocumentXML.h
@@ -150,7 +150,6 @@ inline void DocumentXML::addAttribute(const char* pName, const T& value) {
{
llvm::raw_string_ostream buf(repr);
buf << value;
- buf.flush();
}
Out << ' ' << pName << "=\""
diff --git a/include/clang/Frontend/FrontendAction.h b/include/clang/Frontend/FrontendAction.h
index f6a68bf69e89..773543ac06a5 100644
--- a/include/clang/Frontend/FrontendAction.h
+++ b/include/clang/Frontend/FrontendAction.h
@@ -145,8 +145,8 @@ public:
/// @{
/// usesPreprocessorOnly - Does this action only use the preprocessor? If so
- /// no AST context will be created and this action will be invalid with PCH
- /// inputs.
+ /// no AST context will be created and this action will be invalid with AST
+ /// file inputs.
virtual bool usesPreprocessorOnly() const = 0;
/// usesCompleteTranslationUnit - For AST based actions, should the
@@ -225,8 +225,14 @@ protected:
llvm::StringRef InFile) = 0;
public:
- virtual bool ParseArgs(const std::vector<std::string>& arg) = 0;
- virtual void PrintHelp(llvm::raw_ostream&) = 0;
+ /// ParseArgs - Parse the given plugin command line arguments.
+ ///
+ /// \param CI - The compiler instance, for use in reporting diagnostics.
+ /// \return True if the parsing succeeded; otherwise the plugin will be
+ /// destroyed and no action run. The plugin is responsible for using the
+ /// CompilerInstance's Diagnostic object to report errors.
+ virtual bool ParseArgs(const CompilerInstance &CI,
+ const std::vector<std::string> &arg) = 0;
};
/// PreprocessorFrontendAction - Abstract base class to use for preprocessor
diff --git a/include/clang/Frontend/FrontendActions.h b/include/clang/Frontend/FrontendActions.h
index 26262cfa9522..7b8063ce549c 100644
--- a/include/clang/Frontend/FrontendActions.h
+++ b/include/clang/Frontend/FrontendActions.h
@@ -74,6 +74,17 @@ protected:
virtual bool usesCompleteTranslationUnit() { return false; }
virtual bool hasASTFileSupport() const { return false; }
+
+public:
+ /// \brief Compute the AST consumer arguments that will be used to
+ /// create the PCHGenerator instance returned by CreateASTConsumer.
+ ///
+ /// \returns true if an error occurred, false otherwise.
+ static bool ComputeASTConsumerArguments(CompilerInstance &CI,
+ llvm::StringRef InFile,
+ std::string &Sysroot,
+ llvm::raw_ostream *&OS,
+ bool &Chaining);
};
class InheritanceViewAction : public ASTFrontendAction {
@@ -134,6 +145,16 @@ public:
virtual bool hasCodeCompletionSupport() const;
};
+class PrintPreambleAction : public FrontendAction {
+protected:
+ void ExecuteAction();
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &, llvm::StringRef) {
+ return 0;
+ }
+
+ virtual bool usesPreprocessorOnly() const { return true; }
+};
+
//===----------------------------------------------------------------------===//
// Preprocessor Actions
//===----------------------------------------------------------------------===//
@@ -153,28 +174,18 @@ protected:
void ExecuteAction();
};
-class ParseOnlyAction : public PreprocessorFrontendAction {
-protected:
- void ExecuteAction();
-};
-
class PreprocessOnlyAction : public PreprocessorFrontendAction {
protected:
void ExecuteAction();
};
-class PrintParseAction : public PreprocessorFrontendAction {
-protected:
- void ExecuteAction();
-};
-
class PrintPreprocessedAction : public PreprocessorFrontendAction {
protected:
void ExecuteAction();
virtual bool hasPCHSupport() const { return true; }
};
-
+
} // end namespace clang
#endif
diff --git a/include/clang/Frontend/FrontendOptions.h b/include/clang/Frontend/FrontendOptions.h
index 4010ea6dd7dc..4c16d084fc0d 100644
--- a/include/clang/Frontend/FrontendOptions.h
+++ b/include/clang/Frontend/FrontendOptions.h
@@ -25,6 +25,7 @@ namespace frontend {
ASTPrintXML, ///< Parse ASTs and print them in XML.
ASTView, ///< Parse ASTs and view them in Graphviz.
BoostCon, ///< BoostCon mode.
+ CreateModule, ///< Create module definition
DumpRawTokens, ///< Dump out raw tokens.
DumpTokens, ///< Dump out preprocessed tokens.
EmitAssembly, ///< Emit a .s file.
@@ -39,11 +40,10 @@ namespace frontend {
GeneratePTH, ///< Generate pre-tokenized header.
InheritanceView, ///< View C++ inheritance for a specified class.
InitOnly, ///< Only execute frontend initialization.
- ParseNoop, ///< Parse with noop callbacks.
- ParsePrintCallbacks, ///< Parse and print each callback.
ParseSyntaxOnly, ///< Parse and perform semantic analysis.
PluginAction, ///< Run a plugin action, \see ActionName.
PrintDeclContext, ///< Print DeclContext and their Decls.
+ PrintPreamble, ///< Print the "preamble" of the input file
PrintPreprocessedInput, ///< -E mode.
RewriteMacros, ///< Expand macros but not #includes.
RewriteObjC, ///< ObjC->C Rewriter.
@@ -60,21 +60,25 @@ public:
/// completion results.
unsigned DisableFree : 1; ///< Disable memory freeing on exit.
unsigned RelocatablePCH : 1; ///< When generating PCH files,
- /// instruct the PCH writer to create
+ /// instruct the AST writer to create
/// relocatable PCH files.
unsigned ChainedPCH : 1; ///< When generating PCH files,
- /// instruct the PCH writer to create
+ /// instruct the AST writer to create
/// chained PCH files.
unsigned ShowHelp : 1; ///< Show the -help text.
unsigned ShowMacrosInCodeCompletion : 1; ///< Show macros in code completion
/// results.
unsigned ShowCodePatternsInCodeCompletion : 1; ///< Show code patterns in code
/// completion results.
+ unsigned ShowGlobalSymbolsInCodeCompletion : 1; ///< Show top-level decls in
+ /// code completion results.
unsigned ShowStats : 1; ///< Show frontend performance
/// metrics and statistics.
unsigned ShowTimers : 1; ///< Show timers for individual
/// actions.
unsigned ShowVersion : 1; ///< Show the -version text.
+ unsigned FixWhatYouCan : 1; ///< Apply fixes even if there are
+ /// unfixable errors.
/// The input files and their types.
std::vector<std::pair<InputKind, std::string> > Inputs;
@@ -106,6 +110,9 @@ public:
/// \brief The list of AST files to merge.
std::vector<std::string> ASTMergeFiles;
+ /// \brief The list of modules to import.
+ std::vector<std::string> Modules;
+
/// \brief A list of arguments to forward to LLVM's option processing; this
/// should only be used for debugging and experimental features.
std::vector<std::string> LLVMArgs;
@@ -121,6 +128,7 @@ public:
ShowHelp = 0;
ShowMacrosInCodeCompletion = 0;
ShowCodePatternsInCodeCompletion = 0;
+ ShowGlobalSymbolsInCodeCompletion = 1;
ShowStats = 0;
ShowTimers = 0;
ShowVersion = 0;
diff --git a/include/clang/Frontend/HeaderSearchOptions.h b/include/clang/Frontend/HeaderSearchOptions.h
index c6682451835a..588d32bf736e 100644
--- a/include/clang/Frontend/HeaderSearchOptions.h
+++ b/include/clang/Frontend/HeaderSearchOptions.h
@@ -35,11 +35,16 @@ public:
frontend::IncludeDirGroup Group;
unsigned IsUserSupplied : 1;
unsigned IsFramework : 1;
-
- Entry(llvm::StringRef _Path, frontend::IncludeDirGroup _Group,
- bool _IsUserSupplied, bool _IsFramework)
- : Path(_Path), Group(_Group), IsUserSupplied(_IsUserSupplied),
- IsFramework(_IsFramework) {}
+
+ /// IsSysRootRelative - This is true if an absolute path should be treated
+ /// relative to the sysroot, or false if it should always be the absolute
+ /// path.
+ unsigned IsSysRootRelative : 1;
+
+ Entry(llvm::StringRef path, frontend::IncludeDirGroup group,
+ bool isUserSupplied, bool isFramework, bool isSysRootRelative)
+ : Path(path), Group(group), IsUserSupplied(isUserSupplied),
+ IsFramework(isFramework), IsSysRootRelative(isSysRootRelative) {}
};
/// If non-empty, the directory to use as a "virtual system root" for include
@@ -85,8 +90,9 @@ public:
/// AddPath - Add the \arg Path path to the specified \arg Group list.
void AddPath(llvm::StringRef Path, frontend::IncludeDirGroup Group,
- bool IsUserSupplied, bool IsFramework) {
- UserEntries.push_back(Entry(Path, Group, IsUserSupplied, IsFramework));
+ bool IsUserSupplied, bool IsFramework, bool IsSysRootRelative) {
+ UserEntries.push_back(Entry(Path, Group, IsUserSupplied, IsFramework,
+ IsSysRootRelative));
}
};
diff --git a/include/clang/Frontend/PCHDeserializationListener.h b/include/clang/Frontend/PCHDeserializationListener.h
deleted file mode 100644
index c9b90e22c8cd..000000000000
--- a/include/clang/Frontend/PCHDeserializationListener.h
+++ /dev/null
@@ -1,36 +0,0 @@
-//===- PCHDeserializationListener.h - Decl/Type PCH Read Events -*- 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 the PCHDeserializationListener class, which is notified
-// by the PCHReader whenever a type or declaration is deserialized.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_FRONTEND_PCH_DESERIALIZATION_LISTENER_H
-#define LLVM_CLANG_FRONTEND_PCH_DESERIALIZATION_LISTENER_H
-
-#include "clang/Frontend/PCHBitCodes.h"
-
-namespace clang {
-
-class Decl;
-class QualType;
-
-class PCHDeserializationListener {
-protected:
- ~PCHDeserializationListener() {}
-
-public:
- virtual void TypeRead(pch::TypeID ID, QualType T) = 0;
- virtual void DeclRead(pch::DeclID ID, const Decl *D) = 0;
-};
-
-}
-
-#endif
diff --git a/include/clang/Frontend/PreprocessorOptions.h b/include/clang/Frontend/PreprocessorOptions.h
index 891359b74784..851c1f0108af 100644
--- a/include/clang/Frontend/PreprocessorOptions.h
+++ b/include/clang/Frontend/PreprocessorOptions.h
@@ -43,6 +43,17 @@ public:
/// The implicit PCH included at the start of the translation unit, or empty.
std::string ImplicitPCHInclude;
+ /// \brief When true, disables most of the normal validation performed on
+ /// precompiled headers.
+ bool DisablePCHValidation;
+
+ /// \brief If non-zero, the implicit PCH include is actually a precompiled
+ /// preamble that covers this number of bytes in the main source file.
+ ///
+ /// The boolean indicates whether the preamble ends at the start of a new
+ /// line.
+ std::pair<unsigned, bool> PrecompiledPreambleBytes;
+
/// The implicit PTH input included at the start of the translation unit, or
/// empty.
std::string ImplicitPTHInclude;
@@ -62,26 +73,53 @@ public:
std::vector<std::pair<std::string, const llvm::MemoryBuffer *> >
RemappedFileBuffers;
- typedef std::vector<std::pair<std::string, std::string> >::const_iterator
+ /// \brief Whether the compiler instance should retain (i.e., not free)
+ /// the buffers associated with remapped files.
+ ///
+ /// This flag defaults to false; it can be set true only through direct
+ /// manipulation of the compiler invocation object, in cases where the
+ /// compiler invocation and its buffers will be reused.
+ bool RetainRemappedFileBuffers;
+
+ typedef std::vector<std::pair<std::string, std::string> >::iterator
remapped_file_iterator;
- remapped_file_iterator remapped_file_begin() const {
+ typedef std::vector<std::pair<std::string, std::string> >::const_iterator
+ const_remapped_file_iterator;
+ remapped_file_iterator remapped_file_begin() {
return RemappedFiles.begin();
}
- remapped_file_iterator remapped_file_end() const {
+ const_remapped_file_iterator remapped_file_begin() const {
+ return RemappedFiles.begin();
+ }
+ remapped_file_iterator remapped_file_end() {
+ return RemappedFiles.end();
+ }
+ const_remapped_file_iterator remapped_file_end() const {
return RemappedFiles.end();
}
typedef std::vector<std::pair<std::string, const llvm::MemoryBuffer *> >::
- const_iterator remapped_file_buffer_iterator;
- remapped_file_buffer_iterator remapped_file_buffer_begin() const {
+ iterator remapped_file_buffer_iterator;
+ typedef std::vector<std::pair<std::string, const llvm::MemoryBuffer *> >::
+ const_iterator const_remapped_file_buffer_iterator;
+ remapped_file_buffer_iterator remapped_file_buffer_begin() {
return RemappedFileBuffers.begin();
}
- remapped_file_buffer_iterator remapped_file_buffer_end() const {
+ const_remapped_file_buffer_iterator remapped_file_buffer_begin() const {
+ return RemappedFileBuffers.begin();
+ }
+ remapped_file_buffer_iterator remapped_file_buffer_end() {
+ return RemappedFileBuffers.end();
+ }
+ const_remapped_file_buffer_iterator remapped_file_buffer_end() const {
return RemappedFileBuffers.end();
}
public:
- PreprocessorOptions() : UsePredefines(true), DetailedRecord(false) {}
+ PreprocessorOptions() : UsePredefines(true), DetailedRecord(false),
+ DisablePCHValidation(false),
+ PrecompiledPreambleBytes(0, true),
+ RetainRemappedFileBuffers(false) { }
void addMacroDef(llvm::StringRef Name) {
Macros.push_back(std::make_pair(Name, false));
@@ -92,9 +130,24 @@ public:
void addRemappedFile(llvm::StringRef From, llvm::StringRef To) {
RemappedFiles.push_back(std::make_pair(From, To));
}
+
+ remapped_file_iterator eraseRemappedFile(remapped_file_iterator Remapped) {
+ return RemappedFiles.erase(Remapped);
+ }
+
void addRemappedFile(llvm::StringRef From, const llvm::MemoryBuffer * To) {
RemappedFileBuffers.push_back(std::make_pair(From, To));
}
+
+ remapped_file_buffer_iterator
+ eraseRemappedFile(remapped_file_buffer_iterator Remapped) {
+ return RemappedFileBuffers.erase(Remapped);
+ }
+
+ void clearRemappedFiles() {
+ RemappedFiles.clear();
+ RemappedFileBuffers.clear();
+ }
};
} // end namespace clang
diff --git a/include/clang/Frontend/PreprocessorOutputOptions.h b/include/clang/Frontend/PreprocessorOutputOptions.h
index a712a3d1bb05..82517c51d1c1 100644
--- a/include/clang/Frontend/PreprocessorOutputOptions.h
+++ b/include/clang/Frontend/PreprocessorOutputOptions.h
@@ -16,19 +16,21 @@ namespace clang {
/// output (e.g., -E).
class PreprocessorOutputOptions {
public:
- unsigned ShowCPP : 1; ///< Print normal preprocessed output.
- unsigned ShowMacros : 1; ///< Print macro definitions.
- unsigned ShowLineMarkers : 1; ///< Show #line markers.
- unsigned ShowComments : 1; ///< Show comments.
- unsigned ShowMacroComments : 1; ///< Show comments, even in macros.
+ unsigned ShowCPP : 1; ///< Print normal preprocessed output.
+ unsigned ShowComments : 1; ///< Show comments.
+ unsigned ShowHeaderIncludes : 1; ///< Show header inclusions (-H).
+ unsigned ShowLineMarkers : 1; ///< Show #line markers.
+ unsigned ShowMacroComments : 1; ///< Show comments, even in macros.
+ unsigned ShowMacros : 1; ///< Print macro definitions.
public:
PreprocessorOutputOptions() {
ShowCPP = 1;
- ShowMacros = 0;
- ShowLineMarkers = 1;
ShowComments = 0;
+ ShowHeaderIncludes = 0;
+ ShowLineMarkers = 1;
ShowMacroComments = 0;
+ ShowMacros = 0;
}
};
diff --git a/include/clang/Frontend/StmtXML.def b/include/clang/Frontend/StmtXML.def
index f63761a908af..c03a5a883569 100644
--- a/include/clang/Frontend/StmtXML.def
+++ b/include/clang/Frontend/StmtXML.def
@@ -241,20 +241,19 @@ NODE_XML(UnaryOperator, "UnaryOperator") // op(expr) or (expr)op
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
ATTRIBUTE_ENUM_XML(getOpcode(), "kind")
- ENUM_XML(UnaryOperator::PostInc, "postinc")
- ENUM_XML(UnaryOperator::PostDec, "postdec")
- ENUM_XML(UnaryOperator::PreInc, "preinc")
- ENUM_XML(UnaryOperator::PreDec, "predec")
- ENUM_XML(UnaryOperator::AddrOf, "addrof")
- ENUM_XML(UnaryOperator::Deref, "deref")
- ENUM_XML(UnaryOperator::Plus, "plus")
- ENUM_XML(UnaryOperator::Minus, "minus")
- ENUM_XML(UnaryOperator::Not, "not") // bitwise not
- ENUM_XML(UnaryOperator::LNot, "lnot") // boolean not
- ENUM_XML(UnaryOperator::Real, "__real")
- ENUM_XML(UnaryOperator::Imag, "__imag")
- ENUM_XML(UnaryOperator::Extension, "__extension__")
- ENUM_XML(UnaryOperator::OffsetOf, "__builtin_offsetof")
+ ENUM_XML(UO_PostInc, "postinc")
+ ENUM_XML(UO_PostDec, "postdec")
+ ENUM_XML(UO_PreInc, "preinc")
+ ENUM_XML(UO_PreDec, "predec")
+ ENUM_XML(UO_AddrOf, "addrof")
+ ENUM_XML(UO_Deref, "deref")
+ ENUM_XML(UO_Plus, "plus")
+ ENUM_XML(UO_Minus, "minus")
+ ENUM_XML(UO_Not, "not") // bitwise not
+ ENUM_XML(UO_LNot, "lnot") // boolean not
+ ENUM_XML(UO_Real, "__real")
+ ENUM_XML(UO_Imag, "__imag")
+ ENUM_XML(UO_Extension, "__extension__")
END_ENUM_XML
SUB_NODE_XML(Expr) // expr
END_NODE_XML
@@ -263,38 +262,38 @@ NODE_XML(BinaryOperator, "BinaryOperator") // (expr1) op (expr2)
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
ATTRIBUTE_ENUM_XML(getOpcode(), "kind")
- ENUM_XML(BinaryOperator::PtrMemD , "ptrmemd")
- ENUM_XML(BinaryOperator::PtrMemI , "ptrmemi")
- ENUM_XML(BinaryOperator::Mul , "mul")
- ENUM_XML(BinaryOperator::Div , "div")
- ENUM_XML(BinaryOperator::Rem , "rem")
- ENUM_XML(BinaryOperator::Add , "add")
- ENUM_XML(BinaryOperator::Sub , "sub")
- ENUM_XML(BinaryOperator::Shl , "shl")
- ENUM_XML(BinaryOperator::Shr , "shr")
- ENUM_XML(BinaryOperator::LT , "lt")
- ENUM_XML(BinaryOperator::GT , "gt")
- ENUM_XML(BinaryOperator::LE , "le")
- ENUM_XML(BinaryOperator::GE , "ge")
- ENUM_XML(BinaryOperator::EQ , "eq")
- ENUM_XML(BinaryOperator::NE , "ne")
- ENUM_XML(BinaryOperator::And , "and") // bitwise and
- ENUM_XML(BinaryOperator::Xor , "xor")
- ENUM_XML(BinaryOperator::Or , "or") // bitwise or
- ENUM_XML(BinaryOperator::LAnd , "land") // boolean and
- ENUM_XML(BinaryOperator::LOr , "lor") // boolean or
- ENUM_XML(BinaryOperator::Assign , "assign")
- ENUM_XML(BinaryOperator::MulAssign, "mulassign")
- ENUM_XML(BinaryOperator::DivAssign, "divassign")
- ENUM_XML(BinaryOperator::RemAssign, "remassign")
- ENUM_XML(BinaryOperator::AddAssign, "addassign")
- ENUM_XML(BinaryOperator::SubAssign, "subassign")
- ENUM_XML(BinaryOperator::ShlAssign, "shlassign")
- ENUM_XML(BinaryOperator::ShrAssign, "shrassign")
- ENUM_XML(BinaryOperator::AndAssign, "andassign")
- ENUM_XML(BinaryOperator::XorAssign, "xorassign")
- ENUM_XML(BinaryOperator::OrAssign , "orassign")
- ENUM_XML(BinaryOperator::Comma , "comma")
+ ENUM_XML(BO_PtrMemD , "ptrmemd")
+ ENUM_XML(BO_PtrMemI , "ptrmemi")
+ ENUM_XML(BO_Mul , "mul")
+ ENUM_XML(BO_Div , "div")
+ ENUM_XML(BO_Rem , "rem")
+ ENUM_XML(BO_Add , "add")
+ ENUM_XML(BO_Sub , "sub")
+ ENUM_XML(BO_Shl , "shl")
+ ENUM_XML(BO_Shr , "shr")
+ ENUM_XML(BO_LT , "lt")
+ ENUM_XML(BO_GT , "gt")
+ ENUM_XML(BO_LE , "le")
+ ENUM_XML(BO_GE , "ge")
+ ENUM_XML(BO_EQ , "eq")
+ ENUM_XML(BO_NE , "ne")
+ ENUM_XML(BO_And , "and") // bitwise and
+ ENUM_XML(BO_Xor , "xor")
+ ENUM_XML(BO_Or , "or") // bitwise or
+ ENUM_XML(BO_LAnd , "land") // boolean and
+ ENUM_XML(BO_LOr , "lor") // boolean or
+ ENUM_XML(BO_Assign , "assign")
+ ENUM_XML(BO_MulAssign, "mulassign")
+ ENUM_XML(BO_DivAssign, "divassign")
+ ENUM_XML(BO_RemAssign, "remassign")
+ ENUM_XML(BO_AddAssign, "addassign")
+ ENUM_XML(BO_SubAssign, "subassign")
+ ENUM_XML(BO_ShlAssign, "shlassign")
+ ENUM_XML(BO_ShrAssign, "shrassign")
+ ENUM_XML(BO_AndAssign, "andassign")
+ ENUM_XML(BO_XorAssign, "xorassign")
+ ENUM_XML(BO_OrAssign , "orassign")
+ ENUM_XML(BO_Comma , "comma")
END_ENUM_XML
SUB_NODE_XML(Expr) // expr1
SUB_NODE_XML(Expr) // expr2
@@ -445,6 +444,14 @@ NODE_XML(CXXOperatorCallExpr, "CXXOperatorCallExpr") // fnexpr(arg1, arg2, ..
SUB_NODE_SEQUENCE_XML(Expr) // arg1..argN
END_NODE_XML
+NODE_XML(CXXConstructExpr, "CXXConstructExpr") // ctor(arg1, arg2, ...)
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_XML(getNumArgs(), "num_args") // unsigned
+ SUB_NODE_XML(Expr) // fnexpr
+ SUB_NODE_SEQUENCE_XML(Expr) // arg1..argN
+END_NODE_XML
+
NODE_XML(CXXNamedCastExpr, "CXXNamedCastExpr") // xxx_cast<type>(expr)
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
diff --git a/include/clang/Frontend/TypeXML.def b/include/clang/Frontend/TypeXML.def
index e8cb4a6de055..1536c924a82f 100644
--- a/include/clang/Frontend/TypeXML.def
+++ b/include/clang/Frontend/TypeXML.def
@@ -278,18 +278,10 @@ NODE_XML(UnresolvedUsingType, "UnresolvedUsing")
ID_ATTRIBUTE_XML
END_NODE_XML
-NODE_XML(DependentTypeOfExprType, "DependentTypeOfExpr")
- ID_ATTRIBUTE_XML
-END_NODE_XML
-
NODE_XML(DecltypeType, "Decltype")
ID_ATTRIBUTE_XML
END_NODE_XML
-NODE_XML(DependentDecltypeType, "DependentDecltype")
- ID_ATTRIBUTE_XML
-END_NODE_XML
-
//===----------------------------------------------------------------------===//
#undef NODE_XML
#undef ID_ATTRIBUTE_XML
diff --git a/include/clang/Frontend/Utils.h b/include/clang/Frontend/Utils.h
index f37cc01a2753..fe722db381d0 100644
--- a/include/clang/Frontend/Utils.h
+++ b/include/clang/Frontend/Utils.h
@@ -23,6 +23,7 @@ class Triple;
namespace clang {
class ASTConsumer;
+class CompilerInstance;
class Decl;
class DependencyOutputOptions;
class Diagnostic;
@@ -31,7 +32,6 @@ class HeaderSearch;
class HeaderSearchOptions;
class IdentifierTable;
class LangOptions;
-class MinimalAction;
class Preprocessor;
class PreprocessorOptions;
class PreprocessorOutputOptions;
@@ -65,11 +65,6 @@ void ProcessWarningOptions(Diagnostic &Diags, const DiagnosticOptions &Opts);
void DoPrintPreprocessedInput(Preprocessor &PP, llvm::raw_ostream* OS,
const PreprocessorOutputOptions &Opts);
-/// CreatePrintParserActionsAction - Return the actions implementation that
-/// implements the -parse-print-callbacks option.
-MinimalAction *CreatePrintParserActionsAction(Preprocessor &PP,
- llvm::raw_ostream* OS);
-
/// CheckDiagnostics - Gather the expected diagnostics and check them.
bool CheckDiagnostics(Preprocessor &PP);
diff --git a/include/clang/FrontendTool/Utils.h b/include/clang/FrontendTool/Utils.h
new file mode 100644
index 000000000000..031ee7df70ae
--- /dev/null
+++ b/include/clang/FrontendTool/Utils.h
@@ -0,0 +1,30 @@
+//===--- Utils.h - Misc utilities for the front-end -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This header contains miscellaneous utilities for various front-end actions
+// which were split from Frontend to minimise Frontend's dependencies.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTENDTOOL_UTILS_H
+#define LLVM_CLANG_FRONTENDTOOL_UTILS_H
+
+namespace clang {
+
+class CompilerInstance;
+
+/// ExecuteCompilerInvocation - Execute the given actions described by the
+/// compiler invocation object in the given compiler instance.
+///
+/// \return - True on success.
+bool ExecuteCompilerInvocation(CompilerInstance *Clang);
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Index/TranslationUnit.h b/include/clang/Index/TranslationUnit.h
index b86ba3ee8a58..0099d630f164 100644
--- a/include/clang/Index/TranslationUnit.h
+++ b/include/clang/Index/TranslationUnit.h
@@ -16,6 +16,7 @@
namespace clang {
class ASTContext;
+ class Diagnostic;
class Preprocessor;
namespace idx {
@@ -28,6 +29,7 @@ public:
virtual ~TranslationUnit();
virtual ASTContext &getASTContext() = 0;
virtual Preprocessor &getPreprocessor() = 0;
+ virtual Diagnostic &getDiagnostic() = 0;
virtual DeclReferenceMap &getDeclReferenceMap() = 0;
virtual SelectorMap &getSelectorMap() = 0;
};
diff --git a/include/clang/Index/Utils.h b/include/clang/Index/Utils.h
deleted file mode 100644
index f8e01f728648..000000000000
--- a/include/clang/Index/Utils.h
+++ /dev/null
@@ -1,36 +0,0 @@
-//===--- Utils.h - Misc utilities for indexing-----------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This header contains miscellaneous utilities for indexing related
-// functionality.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_INDEX_UTILS_H
-#define LLVM_CLANG_INDEX_UTILS_H
-
-namespace clang {
- class ASTContext;
- class SourceLocation;
-
-namespace idx {
- class ASTLocation;
-
-/// \brief Returns the ASTLocation that a source location points to.
-///
-/// \returns the resolved ASTLocation or an invalid ASTLocation if the source
-/// location could not be resolved.
-ASTLocation ResolveLocationInAST(ASTContext &Ctx, SourceLocation Loc,
- ASTLocation *LastLoc = 0);
-
-} // end namespace idx
-
-} // end namespace clang
-
-#endif
diff --git a/include/clang/Lex/CodeCompletionHandler.h b/include/clang/Lex/CodeCompletionHandler.h
new file mode 100644
index 000000000000..d28a3aa7d630
--- /dev/null
+++ b/include/clang/Lex/CodeCompletionHandler.h
@@ -0,0 +1,67 @@
+//===--- CodeCompletionHandler.h - Preprocessor code completion -*- 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 the CodeCompletionHandler interface, which provides
+// code-completion callbacks for the preprocessor.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_LEX_CODECOMPLETIONHANDLER_H
+#define LLVM_CLANG_LEX_CODECOMPLETIONHANDLER_H
+
+namespace clang {
+
+class IdentifierInfo;
+class MacroInfo;
+
+/// \brief Callback handler that receives notifications when performing code
+/// completion within the preprocessor.
+class CodeCompletionHandler {
+public:
+ virtual ~CodeCompletionHandler();
+
+ /// \brief Callback invoked when performing code completion for a preprocessor
+ /// directive.
+ ///
+ /// This callback will be invoked when the preprocessor processes a '#' at the
+ /// start of a line, followed by the code-completion token.
+ ///
+ /// \param InConditional Whether we're inside a preprocessor conditional
+ /// already.
+ virtual void CodeCompleteDirective(bool InConditional) { }
+
+ /// \brief Callback invoked when performing code completion within a block of
+ /// code that was excluded due to preprocessor conditionals.
+ virtual void CodeCompleteInConditionalExclusion() { }
+
+ /// \brief Callback invoked when performing code completion in a context
+ /// where the name of a macro is expected.
+ ///
+ /// \param IsDefinition Whether this is the definition of a macro, e.g.,
+ /// in a #define.
+ virtual void CodeCompleteMacroName(bool IsDefinition) { }
+
+ /// \brief Callback invoked when performing code completion in a preprocessor
+ /// expression, such as the condition of an #if or #elif directive.
+ virtual void CodeCompletePreprocessorExpression() { }
+
+ /// \brief Callback invoked when performing code completion inside a
+ /// function-like macro argument.
+ virtual void CodeCompleteMacroArgument(IdentifierInfo *Macro,
+ MacroInfo *MacroInfo,
+ unsigned ArgumentIndex) { }
+
+ /// \brief Callback invoked when performing code completion in a part of the
+ /// file where we expect natural language, e.g., a comment, string, or
+ /// #error directive.
+ virtual void CodeCompleteNaturalLanguage() { }
+};
+
+}
+
+#endif // LLVM_CLANG_LEX_CODECOMPLETIONHANDLER_H
diff --git a/include/clang/Lex/ExternalPreprocessorSource.h b/include/clang/Lex/ExternalPreprocessorSource.h
index af5c3898161e..791d3fe304ec 100644
--- a/include/clang/Lex/ExternalPreprocessorSource.h
+++ b/include/clang/Lex/ExternalPreprocessorSource.h
@@ -19,7 +19,7 @@ namespace clang {
/// \brief Abstract interface for external sources of preprocessor
/// information.
///
-/// This abstract class allows an external sources (such as the \c PCHReader)
+/// This abstract class allows an external sources (such as the \c ASTReader)
/// to provide additional macro definitions.
class ExternalPreprocessorSource {
public:
diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h
index 978585caf0e4..80b38dee06af 100644
--- a/include/clang/Lex/HeaderSearch.h
+++ b/include/clang/Lex/HeaderSearch.h
@@ -219,7 +219,7 @@ public:
header_file_iterator header_file_end() const { return FileInfo.end(); }
unsigned header_file_size() const { return FileInfo.size(); }
- // Used by PCHReader.
+ // Used by ASTReader.
void setHeaderFileInfoForUID(HeaderFileInfo HFI, unsigned UID);
void PrintStats();
diff --git a/include/clang/Lex/Lexer.h b/include/clang/Lex/Lexer.h
index 6a6e319463f0..9e0fb7ee70ea 100644
--- a/include/clang/Lex/Lexer.h
+++ b/include/clang/Lex/Lexer.h
@@ -219,6 +219,33 @@ public:
const SourceManager &SM,
const LangOptions &LangOpts);
+ /// \brief Given a location any where in a source buffer, find the location
+ /// that corresponds to the beginning of the token in which the original
+ /// source location lands.
+ ///
+ /// \param Loc
+ static SourceLocation GetBeginningOfToken(SourceLocation Loc,
+ const SourceManager &SM,
+ const LangOptions &LangOpts);
+
+ /// \brief Compute the preamble of the given file.
+ ///
+ /// The preamble of a file contains the initial comments, include directives,
+ /// and other preprocessor directives that occur before the code in this
+ /// particular file actually begins. The preamble of the main source file is
+ /// a potential prefix header.
+ ///
+ /// \param Buffer The memory buffer containing the file's contents.
+ ///
+ /// \param MaxLines If non-zero, restrict the length of the preamble
+ /// to fewer than this number of lines.
+ ///
+ /// \returns The offset into the file where the preamble ends and the rest
+ /// of the file begins along with a boolean value indicating whether
+ /// the preamble ends at the beginning of a new line.
+ static std::pair<unsigned, bool>
+ ComputePreamble(const llvm::MemoryBuffer *Buffer, unsigned MaxLines = 0);
+
//===--------------------------------------------------------------------===//
// Internal implementation interfaces.
private:
@@ -361,6 +388,8 @@ private:
//===--------------------------------------------------------------------===//
// Other lexer functions.
+ void SkipBytes(unsigned Bytes, bool StartOfLine);
+
// Helper functions to lex the remainder of a token of the specific type.
void LexIdentifier (Token &Result, const char *CurPtr);
void LexNumericConstant (Token &Result, const char *CurPtr);
diff --git a/include/clang/Lex/MacroInfo.h b/include/clang/Lex/MacroInfo.h
index 5887041c46b9..90f95b7acee3 100644
--- a/include/clang/Lex/MacroInfo.h
+++ b/include/clang/Lex/MacroInfo.h
@@ -62,6 +62,9 @@ class MacroInfo {
/// it has not yet been redefined or undefined.
bool IsBuiltinMacro : 1;
+ /// IsFromAST - True if this macro was loaded from an AST file.
+ bool IsFromAST : 1;
+
private:
//===--------------------------------------------------------------------===//
// State that changes as the macro is used.
@@ -76,24 +79,28 @@ private:
/// emit -Wunused-macros diagnostics.
bool IsUsed : 1;
- ~MacroInfo() {
+ /// AllowRedefinitionsWithoutWarning - True if this macro can be redefined
+ /// without emitting a warning.
+ bool IsAllowRedefinitionsWithoutWarning : 1;
+
+ ~MacroInfo() {
assert(ArgumentList == 0 && "Didn't call destroy before dtor!");
}
public:
MacroInfo(SourceLocation DefLoc);
-
+ MacroInfo(const MacroInfo &MI, llvm::BumpPtrAllocator &PPAllocator);
+
/// FreeArgumentList - Free the argument list of the macro, restoring it to a
/// state where it can be reused for other devious purposes.
- void FreeArgumentList(llvm::BumpPtrAllocator &PPAllocator) {
- PPAllocator.Deallocate(ArgumentList);
+ void FreeArgumentList() {
ArgumentList = 0;
NumArguments = 0;
}
/// Destroy - destroy this MacroInfo object.
- void Destroy(llvm::BumpPtrAllocator &PPAllocator) {
- FreeArgumentList(PPAllocator);
+ void Destroy() {
+ FreeArgumentList();
this->~MacroInfo();
}
@@ -125,6 +132,12 @@ public:
IsUsed = Val;
}
+ /// setIsAllowRedefinitionsWithoutWarning - Set the value of the
+ /// IsAllowRedefinitionsWithoutWarning flag.
+ void setIsAllowRedefinitionsWithoutWarning(bool Val) {
+ IsAllowRedefinitionsWithoutWarning = Val;
+ }
+
/// setArgumentList - Set the specified list of identifiers as the argument
/// list for this macro.
void setArgumentList(IdentifierInfo* const *List, unsigned NumArgs,
@@ -172,10 +185,22 @@ public:
/// __LINE__, which requires processing before expansion.
bool isBuiltinMacro() const { return IsBuiltinMacro; }
+ /// isFromAST - Return true if this macro was loaded from an AST file.
+ bool isFromAST() const { return IsFromAST; }
+
+ /// setIsFromAST - Set whether this macro was loaded from an AST file.
+ void setIsFromAST(bool FromAST = true) { IsFromAST = FromAST; }
+
/// isUsed - Return false if this macro is defined in the main file and has
/// not yet been used.
bool isUsed() const { return IsUsed; }
+ /// isAllowRedefinitionsWithoutWarning - Return true if this macro can be
+ /// redefined without warning.
+ bool isAllowRedefinitionsWithoutWarning() const {
+ return IsAllowRedefinitionsWithoutWarning;
+ }
+
/// getNumTokens - Return the number of tokens that this macro expands to.
///
unsigned getNumTokens() const {
diff --git a/include/clang/Lex/PPCallbacks.h b/include/clang/Lex/PPCallbacks.h
index 99fe29b22dc2..782f2d57a5c6 100644
--- a/include/clang/Lex/PPCallbacks.h
+++ b/include/clang/Lex/PPCallbacks.h
@@ -89,7 +89,8 @@ public:
/// MacroUndefined - This hook is called whenever a macro #undef is seen.
/// MI is released immediately following this callback.
- virtual void MacroUndefined(const IdentifierInfo *II, const MacroInfo *MI) {
+ virtual void MacroUndefined(SourceLocation Loc, const IdentifierInfo *II,
+ const MacroInfo *MI) {
}
};
@@ -149,9 +150,10 @@ public:
Second->MacroDefined(II, MI);
}
- virtual void MacroUndefined(const IdentifierInfo *II, const MacroInfo *MI) {
- First->MacroUndefined(II, MI);
- Second->MacroUndefined(II, MI);
+ virtual void MacroUndefined(SourceLocation Loc, const IdentifierInfo *II,
+ const MacroInfo *MI) {
+ First->MacroUndefined(Loc, II, MI);
+ Second->MacroUndefined(Loc, II, MI);
}
};
diff --git a/include/clang/Lex/PTHLexer.h b/include/clang/Lex/PTHLexer.h
index e96a8c514e6e..0b5a76ccfd6e 100644
--- a/include/clang/Lex/PTHLexer.h
+++ b/include/clang/Lex/PTHLexer.h
@@ -50,6 +50,8 @@ class PTHLexer : public PreprocessorLexer {
/// ReadToken - Used by PTHLexer to read tokens TokBuf.
void ReadToken(Token& T);
+
+ bool LexEndOfFile(Token &Result);
/// PTHMgr - The PTHManager object that created this PTHLexer.
PTHManager& PTHMgr;
diff --git a/include/clang/Lex/PreprocessingRecord.h b/include/clang/Lex/PreprocessingRecord.h
index ef28af9b7fe0..730f04f2fa09 100644
--- a/include/clang/Lex/PreprocessingRecord.h
+++ b/include/clang/Lex/PreprocessingRecord.h
@@ -257,7 +257,8 @@ namespace clang {
virtual void MacroExpands(const Token &Id, const MacroInfo* MI);
virtual void MacroDefined(const IdentifierInfo *II, const MacroInfo *MI);
- virtual void MacroUndefined(const IdentifierInfo *II, const MacroInfo *MI);
+ virtual void MacroUndefined(SourceLocation Loc, const IdentifierInfo *II,
+ const MacroInfo *MI);
};
} // end namespace clang
diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h
index 1ee4bb635179..6b9b89ea5eb9 100644
--- a/include/clang/Lex/Preprocessor.h
+++ b/include/clang/Lex/Preprocessor.h
@@ -42,6 +42,7 @@ class CommentHandler;
class ScratchBuffer;
class TargetInfo;
class PPCallbacks;
+class CodeCompletionHandler;
class DirectoryLookup;
class PreprocessingRecord;
@@ -77,7 +78,8 @@ class Preprocessor {
IdentifierInfo *Ident__BASE_FILE__; // __BASE_FILE__
IdentifierInfo *Ident__TIMESTAMP__; // __TIMESTAMP__
IdentifierInfo *Ident__COUNTER__; // __COUNTER__
- IdentifierInfo *Ident_Pragma, *Ident__VA_ARGS__; // _Pragma, __VA_ARGS__
+ IdentifierInfo *Ident_Pragma, *Ident__pragma; // _Pragma, __pragma
+ IdentifierInfo *Ident__VA_ARGS__; // __VA_ARGS__
IdentifierInfo *Ident__has_feature; // __has_feature
IdentifierInfo *Ident__has_builtin; // __has_builtin
IdentifierInfo *Ident__has_include; // __has_include
@@ -117,7 +119,7 @@ class Preprocessor {
/// conceptually similar the IdentifierTable. In addition, the current control
/// flow (in clang::ParseAST()), make it convenient to put here.
/// FIXME: Make sure the lifetime of Identifiers/Selectors *isn't* tied to
- /// the lifetime fo the preprocessor.
+ /// the lifetime of the preprocessor.
SelectorTable Selectors;
/// BuiltinInfo - Information about builtins.
@@ -131,9 +133,18 @@ class Preprocessor {
/// with this preprocessor.
std::vector<CommentHandler *> CommentHandlers;
+ /// \brief The code-completion handler.
+ CodeCompletionHandler *CodeComplete;
+
/// \brief The file that we're performing code-completion for, if any.
const FileEntry *CodeCompletionFile;
+ /// \brief The number of bytes that we will initially skip when entering the
+ /// main file, which is used when loading a precompiled preamble, along
+ /// with a flag that indicates whether skipping this number of bytes will
+ /// place the lexer at the start of a line.
+ std::pair<unsigned, bool> SkipMainFilePreamble;
+
/// CurLexer - This is the current top of the stack that we're lexing from if
/// not expanding a macro and we are lexing directly from source code.
/// Only one of CurLexer, CurPTHLexer, or CurTokenLexer will be non-null.
@@ -192,6 +203,11 @@ class Preprocessor {
/// reused for quick allocation.
MacroArgs *MacroArgCache;
friend class MacroArgs;
+
+ /// PragmaPushMacroInfo - For each IdentifierInfo used in a #pragma
+ /// push_macro directive, we keep a MacroInfo stack used to restore
+ /// previous macro value.
+ llvm::DenseMap<IdentifierInfo*, std::vector<MacroInfo*> > PragmaPushMacroInfo;
// Various statistics we track for performance analysis.
unsigned NumDirectives, NumIncluded, NumDefined, NumUndefined, NumPragma;
@@ -362,6 +378,25 @@ public:
/// It is an error to remove a handler that has not been registered.
void RemoveCommentHandler(CommentHandler *Handler);
+ /// \brief Set the code completion handler to the given object.
+ void setCodeCompletionHandler(CodeCompletionHandler &Handler) {
+ CodeComplete = &Handler;
+ }
+
+ /// \brief Retrieve the current code-completion handler.
+ CodeCompletionHandler *getCodeCompletionHandler() const {
+ return CodeComplete;
+ }
+
+ /// \brief Clear out the code completion handler.
+ void clearCodeCompletionHandler() {
+ CodeComplete = 0;
+ }
+
+ /// \brief Hook used by the lexer to invoke the "natural language" code
+ /// completion point.
+ void CodeCompleteNaturalLanguage();
+
/// \brief Retrieve the preprocessing record, or NULL if there is no
/// preprocessing record.
PreprocessingRecord *getPreprocessingRecord() const { return Record; }
@@ -556,6 +591,18 @@ public:
/// for which we are performing code completion.
bool isCodeCompletionFile(SourceLocation FileLoc) const;
+ /// \brief Instruct the preprocessor to skip part of the main
+ /// the main source file.
+ ///
+ /// \brief Bytes The number of bytes in the preamble to skip.
+ ///
+ /// \brief StartOfLine Whether skipping these bytes puts the lexer at the
+ /// start of a line.
+ void setSkipMainFilePreamble(unsigned Bytes, bool StartOfLine) {
+ SkipMainFilePreamble.first = Bytes;
+ SkipMainFilePreamble.second = StartOfLine;
+ }
+
/// Diag - Forwarding function for diagnostics. This emits a diagnostic at
/// the specified Token's location, translating the token's start
/// position in the current buffer into a SourcePosition object for rendering.
@@ -726,7 +773,10 @@ public:
/// AllocateMacroInfo - Allocate a new MacroInfo object with the provide
/// SourceLocation.
- MacroInfo* AllocateMacroInfo(SourceLocation L);
+ MacroInfo *AllocateMacroInfo(SourceLocation L);
+
+ /// CloneMacroInfo - Allocate a new MacroInfo object which is clone of MI.
+ MacroInfo *CloneMacroInfo(const MacroInfo &MI);
/// GetIncludeFilenameSpelling - Turn the specified lexer token into a fully
/// checked and spelled filename, e.g. as an operand of #include. This returns
@@ -784,6 +834,9 @@ private:
IncludeMacroStack.pop_back();
}
+ /// AllocateMacroInfo - Allocate a new MacroInfo object.
+ MacroInfo *AllocateMacroInfo();
+
/// ReleaseMacroInfo - Release the specified MacroInfo. This memory will
/// be reused for allocating new MacroInfo objects.
void ReleaseMacroInfo(MacroInfo* MI);
@@ -852,6 +905,13 @@ private:
/// been read into 'Tok'.
void Handle_Pragma(Token &Tok);
+ /// HandleMicrosoft__pragma - Like Handle_Pragma except the pragma text
+ /// is not enclosed within a string literal.
+ void HandleMicrosoft__pragma(Token &Tok);
+
+ void Handle_Pragma(const std::string &StrVal, SourceLocation PragmaLoc,
+ SourceLocation RParenLoc);
+
/// EnterSourceFileWithLexer - Add a lexer to the top of the include stack and
/// start lexing tokens from it instead of the current buffer.
void EnterSourceFileWithLexer(Lexer *TheLexer, const DirectoryLookup *Dir);
@@ -880,7 +940,8 @@ private:
bool InCachingLexMode() const {
// If the Lexer pointers are 0 and IncludeMacroStack is empty, it means
// that we are past EOF, not that we are in CachingLex mode.
- return CurPPLexer == 0 && CurTokenLexer == 0 && !IncludeMacroStack.empty();
+ return CurPPLexer == 0 && CurTokenLexer == 0 && CurPTHLexer == 0 &&
+ !IncludeMacroStack.empty();
}
void EnterCachingLexMode();
void ExitCachingLexMode() {
@@ -929,6 +990,10 @@ public:
void HandlePragmaDependency(Token &DependencyTok);
void HandlePragmaComment(Token &CommentTok);
void HandlePragmaMessage(Token &MessageTok);
+ void HandlePragmaPushMacro(Token &Tok);
+ void HandlePragmaPopMacro(Token &Tok);
+ IdentifierInfo *ParsePragmaPushOrPopMacro(Token &Tok);
+
// Return true and store the first token only if any CommentHandler
// has inserted some tokens and getCommentRetentionState() is false.
bool HandleComment(Token &Token, SourceRange Comment);
diff --git a/include/clang/Lex/Token.h b/include/clang/Lex/Token.h
index bd9b46869a35..954b36ec6d11 100644
--- a/include/clang/Lex/Token.h
+++ b/include/clang/Lex/Token.h
@@ -231,6 +231,7 @@ public:
/// newlines in it.
///
bool needsCleaning() const { return (Flags & NeedsCleaning) ? true : false; }
+
};
/// PPConditionalInfo - Information about the conditional stack (#if directives)
diff --git a/include/clang/Makefile b/include/clang/Makefile
index e366e4ec4458..030b0720fd81 100644
--- a/include/clang/Makefile
+++ b/include/clang/Makefile
@@ -1,5 +1,5 @@
CLANG_LEVEL := ../..
-DIRS := AST Basic Driver
+DIRS := AST Basic Driver Serialization
include $(CLANG_LEVEL)/Makefile
diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h
deleted file mode 100644
index 9cb47aa8da25..000000000000
--- a/include/clang/Parse/Action.h
+++ /dev/null
@@ -1,3309 +0,0 @@
-//===--- Action.h - Parser Action Interface ---------------------*- 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 the Action and EmptyAction interface.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_PARSE_ACTION_H
-#define LLVM_CLANG_PARSE_ACTION_H
-
-#include "clang/Basic/IdentifierTable.h"
-#include "clang/Basic/SourceLocation.h"
-#include "clang/Basic/Specifiers.h"
-#include "clang/Basic/TemplateKinds.h"
-#include "clang/Basic/TypeTraits.h"
-#include "clang/Parse/DeclSpec.h"
-#include "clang/Parse/Ownership.h"
-#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/ADT/PointerUnion.h"
-
-namespace clang {
- // Semantic.
- class DeclSpec;
- class ObjCDeclSpec;
- class CXXScopeSpec;
- class Declarator;
- class AttributeList;
- struct FieldDeclarator;
- // Parse.
- class Scope;
- class Action;
- class Selector;
- class Designation;
- class InitListDesignations;
- // Lex.
- class Preprocessor;
- class Token;
-
- // We can re-use the low bit of expression, statement, base, and
- // member-initializer pointers for the "invalid" flag of
- // ActionResult.
- template<> struct IsResultPtrLowBitFree<0> { static const bool value = true;};
- template<> struct IsResultPtrLowBitFree<1> { static const bool value = true;};
- template<> struct IsResultPtrLowBitFree<3> { static const bool value = true;};
- template<> struct IsResultPtrLowBitFree<4> { static const bool value = true;};
- template<> struct IsResultPtrLowBitFree<5> { static const bool value = true;};
-
-/// Action - As the parser reads the input file and recognizes the productions
-/// of the grammar, it invokes methods on this class to turn the parsed input
-/// into something useful: e.g. a parse tree.
-///
-/// The callback methods that this class provides are phrased as actions that
-/// the parser has just done or is about to do when the method is called. They
-/// are not requests that the actions module do the specified action.
-///
-/// All of the methods here are optional except getTypeName() and
-/// isCurrentClassName(), which must be specified in order for the
-/// parse to complete accurately. The MinimalAction class does this
-/// bare-minimum of tracking to implement this functionality.
-class Action : public ActionBase {
- /// \brief The parser's current scope.
- ///
- /// The parser maintains this state here so that is accessible to \c Action
- /// subclasses via \c getCurScope().
- Scope *CurScope;
-
-protected:
- friend class Parser;
-
- /// \brief Retrieve the parser's current scope.
- Scope *getCurScope() const { return CurScope; }
-
-public:
- Action() : CurScope(0) { }
-
- /// Out-of-line virtual destructor to provide home for this class.
- virtual ~Action();
-
- // Types - Though these don't actually enforce strong typing, they document
- // what types are required to be identical for the actions.
- typedef ActionBase::ExprTy ExprTy;
- typedef ActionBase::StmtTy StmtTy;
-
- /// Expr/Stmt/Type/BaseResult - Provide a unique type to wrap
- /// ExprTy/StmtTy/TypeTy/BaseTy, providing strong typing and
- /// allowing for failure.
- typedef ActionResult<0> ExprResult;
- typedef ActionResult<1> StmtResult;
- typedef ActionResult<2> TypeResult;
- typedef ActionResult<3> BaseResult;
- typedef ActionResult<4> MemInitResult;
- typedef ActionResult<5, DeclPtrTy> DeclResult;
-
- /// Same, but with ownership.
- typedef ASTOwningResult<&ActionBase::DeleteExpr> OwningExprResult;
- typedef ASTOwningResult<&ActionBase::DeleteStmt> OwningStmtResult;
- // Note that these will replace ExprResult and StmtResult when the transition
- // is complete.
-
- /// Single expressions or statements as arguments.
-#if !defined(DISABLE_SMART_POINTERS)
- typedef ASTOwningResult<&ActionBase::DeleteExpr> ExprArg;
- typedef ASTOwningResult<&ActionBase::DeleteStmt> StmtArg;
-#else
- typedef ASTOwningPtr<&ActionBase::DeleteExpr> ExprArg;
- typedef ASTOwningPtr<&ActionBase::DeleteStmt> StmtArg;
-#endif
-
- /// Multiple expressions or statements as arguments.
- typedef ASTMultiPtr<&ActionBase::DeleteExpr> MultiExprArg;
- typedef ASTMultiPtr<&ActionBase::DeleteStmt> MultiStmtArg;
- typedef ASTMultiPtr<&ActionBase::DeleteTemplateParams> MultiTemplateParamsArg;
-
- class FullExprArg {
- public:
- FullExprArg(ActionBase &actions) : Expr(actions) { }
-
- // FIXME: The const_cast here is ugly. RValue references would make this
- // much nicer (or we could duplicate a bunch of the move semantics
- // emulation code from Ownership.h).
- FullExprArg(const FullExprArg& Other)
- : Expr(move(const_cast<FullExprArg&>(Other).Expr)) {}
-
- FullExprArg &operator=(const FullExprArg& Other) {
- Expr.operator=(move(const_cast<FullExprArg&>(Other).Expr));
- return *this;
- }
-
- OwningExprResult release() {
- return move(Expr);
- }
-
- ExprArg* operator->() {
- return &Expr;
- }
-
- private:
- // FIXME: No need to make the entire Action class a friend when it's just
- // Action::FullExpr that needs access to the constructor below.
- friend class Action;
-
- explicit FullExprArg(ExprArg expr)
- : Expr(move(expr)) {}
-
- ExprArg Expr;
- };
-
- template<typename T>
- FullExprArg MakeFullExpr(T &Arg) {
- return FullExprArg(ActOnFinishFullExpr(move(Arg)));
- }
-
- // Utilities for Action implementations to return smart results.
-
- OwningExprResult ExprError() { return OwningExprResult(*this, true); }
- OwningStmtResult StmtError() { return OwningStmtResult(*this, true); }
-
- OwningExprResult ExprError(const DiagnosticBuilder&) { return ExprError(); }
- OwningStmtResult StmtError(const DiagnosticBuilder&) { return StmtError(); }
-
- OwningExprResult ExprEmpty() { return OwningExprResult(*this, false); }
- OwningStmtResult StmtEmpty() { return OwningStmtResult(*this, false); }
-
- /// Statistics.
- virtual void PrintStats() const {}
-
- /// getDeclName - Return a pretty name for the specified decl if possible, or
- /// an empty string if not. This is used for pretty crash reporting.
- virtual std::string getDeclName(DeclPtrTy D) { return ""; }
-
- //===--------------------------------------------------------------------===//
- // 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.
- virtual DeclGroupPtrTy ConvertDeclToDeclGroup(DeclPtrTy Ptr) {
- return DeclGroupPtrTy();
- }
-
- /// getTypeName - Return non-null if the specified identifier is a type name
- /// in the current scope.
- ///
- /// \param II the identifier for which we are performing name lookup
- ///
- /// \param NameLoc the location of the identifier
- ///
- /// \param S the scope in which this name lookup occurs
- ///
- /// \param SS if non-NULL, the C++ scope specifier that precedes the
- /// identifier
- ///
- /// \param isClassName whether this is a C++ class-name production, in
- /// which we can end up referring to a member of an unknown specialization
- /// that we know (from the grammar) is supposed to be a type. For example,
- /// this occurs when deriving from "std::vector<T>::allocator_type", where T
- /// is a template parameter.
- ///
- /// \param ObjectType if we're checking whether an identifier is a type
- /// within a C++ member access expression, this will be the type of the
- ///
- /// \returns the type referred to by this identifier, or NULL if the type
- /// does not name an identifier.
- virtual TypeTy *getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
- Scope *S, CXXScopeSpec *SS = 0,
- bool isClassName = false,
- TypeTy *ObjectType = 0) = 0;
-
- /// isTagName() - This method is called *for error recovery purposes only*
- /// to determine if the specified name is a valid tag name ("struct foo"). If
- /// so, this returns the TST for the tag corresponding to it (TST_enum,
- /// TST_union, TST_struct, TST_class). This is used to diagnose cases in C
- /// where the user forgot to specify the tag.
- virtual DeclSpec::TST isTagName(IdentifierInfo &II, Scope *S) {
- return DeclSpec::TST_unspecified;
- }
-
- /// \brief Action called as part of error recovery when the parser has
- /// determined that the given name must refer to a type, but
- /// \c getTypeName() did not return a result.
- ///
- /// This callback permits the action to give a detailed diagnostic when an
- /// unknown type name is encountered and, potentially, to try to recover
- /// by producing a new type in \p SuggestedType.
- ///
- /// \param II the name that should be a type.
- ///
- /// \param IILoc the location of the name in the source.
- ///
- /// \param S the scope in which name lookup was performed.
- ///
- /// \param SS if non-NULL, the C++ scope specifier that preceded the name.
- ///
- /// \param SuggestedType if the action sets this type to a non-NULL type,
- /// the parser will recovery by consuming the type name token and then
- /// pretending that the given type was the type it parsed.
- ///
- /// \returns true if a diagnostic was emitted, false otherwise. When false,
- /// the parser itself will emit a generic "unknown type name" diagnostic.
- virtual bool DiagnoseUnknownTypeName(const IdentifierInfo &II,
- SourceLocation IILoc,
- Scope *S,
- CXXScopeSpec *SS,
- TypeTy *&SuggestedType) {
- return false;
- }
-
- /// isCurrentClassName - Return true if the specified name is the
- /// name of the innermost C++ class type currently being defined.
- virtual bool isCurrentClassName(const IdentifierInfo &II, Scope *S,
- const CXXScopeSpec *SS = 0) = 0;
-
- /// \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 the name occurs.
- ///
- /// \param SS the C++ nested-name-specifier that precedes the template name,
- /// if any.
- ///
- /// \param Name the name that we are querying to determine whether it is
- /// a template.
- ///
- /// \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 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.
- ///
- /// \param MemberOfUnknownSpecialization Will be set true if the resulting
- /// member would be a member of an unknown specialization, in which case this
- /// lookup cannot possibly pass at this time.
- ///
- /// \returns the kind of template that this name refers to.
- virtual TemplateNameKind isTemplateName(Scope *S,
- CXXScopeSpec &SS,
- UnqualifiedId &Name,
- TypeTy *ObjectType,
- bool EnteringContext,
- TemplateTy &Template,
- bool &MemberOfUnknownSpecialization) = 0;
-
- /// \brief Action called as part of error recovery when the parser has
- /// determined that the given name must refer to a template, but
- /// \c isTemplateName() did not return a result.
- ///
- /// This callback permits the action to give a detailed diagnostic when an
- /// unknown template name is encountered and, potentially, to try to recover
- /// by producing a new template in \p SuggestedTemplate.
- ///
- /// \param II the name that should be a template.
- ///
- /// \param IILoc the location of the name in the source.
- ///
- /// \param S the scope in which name lookup was performed.
- ///
- /// \param SS the C++ scope specifier that preceded the name.
- ///
- /// \param SuggestedTemplate if the action sets this template to a non-NULL,
- /// template, the parser will recover by consuming the template name token
- /// and the template argument list that follows.
- ///
- /// \param SuggestedTemplateKind as input, the kind of template that we
- /// expect (e.g., \c TNK_Type_template or \c TNK_Function_template). If the
- /// action provides a suggested template, this should be set to the kind of
- /// template.
- ///
- /// \returns true if a diagnostic was emitted, false otherwise. When false,
- /// the parser itself will emit a generic "unknown template name" diagnostic.
- virtual bool DiagnoseUnknownTemplateName(const IdentifierInfo &II,
- SourceLocation IILoc,
- Scope *S,
- const CXXScopeSpec *SS,
- TemplateTy &SuggestedTemplate,
- TemplateNameKind &SuggestedKind) {
- return false;
- }
-
- /// \brief Determine whether the given name refers to a non-type nested name
- /// specifier, e.g., the name of a namespace or namespace alias.
- ///
- /// This actual is used in the parsing of pseudo-destructor names to
- /// distinguish a nested-name-specifier and a "type-name ::" when we
- /// see the token sequence "X :: ~".
- virtual bool isNonTypeNestedNameSpecifier(Scope *S, CXXScopeSpec &SS,
- SourceLocation IdLoc,
- IdentifierInfo &II,
- TypeTy *ObjectType) {
- return false;
- }
-
- /// ActOnCXXGlobalScopeSpecifier - Return the object that represents the
- /// global scope ('::').
- virtual CXXScopeTy *ActOnCXXGlobalScopeSpecifier(Scope *S,
- SourceLocation CCLoc) {
- return 0;
- }
-
- /// \brief Parsed an identifier followed by '::' in a C++
- /// nested-name-specifier.
- ///
- /// \param S the scope in which the nested-name-specifier was parsed.
- ///
- /// \param SS the nested-name-specifier that precedes the identifier. For
- /// example, if we are parsing "foo::bar::", \p SS will describe the "foo::"
- /// that has already been parsed.
- ///
- /// \param IdLoc the location of the identifier we have just parsed (e.g.,
- /// the "bar" in "foo::bar::".
- ///
- /// \param CCLoc the location of the '::' at the end of the
- /// nested-name-specifier.
- ///
- /// \param II the identifier that represents the scope that this
- /// nested-name-specifier refers to, e.g., the "bar" in "foo::bar::".
- ///
- /// \param ObjectType if this nested-name-specifier occurs as part of a
- /// C++ member access expression such as "x->Base::f", the type of the base
- /// object (e.g., *x in the example, if "x" were a pointer).
- ///
- /// \param EnteringContext if true, then we intend to immediately enter the
- /// context of this nested-name-specifier, e.g., for an out-of-line
- /// definition of a class member.
- ///
- /// \returns a CXXScopeTy* object representing the C++ scope.
- virtual CXXScopeTy *ActOnCXXNestedNameSpecifier(Scope *S,
- CXXScopeSpec &SS,
- SourceLocation IdLoc,
- SourceLocation CCLoc,
- IdentifierInfo &II,
- TypeTy *ObjectType,
- bool EnteringContext) {
- return 0;
- }
-
- /// IsInvalidUnlessNestedName - This method is used for error recovery
- /// purposes to determine whether the specified identifier is only valid as
- /// a nested name specifier, for example a namespace name. It is
- /// conservatively correct to always return false from this method.
- ///
- /// The arguments are the same as those passed to ActOnCXXNestedNameSpecifier.
- virtual bool IsInvalidUnlessNestedName(Scope *S,
- CXXScopeSpec &SS,
- IdentifierInfo &II,
- TypeTy *ObjectType,
- bool EnteringContext) {
- return false;
- }
-
- /// ActOnCXXNestedNameSpecifier - Called during parsing of a
- /// nested-name-specifier that involves a template-id, e.g.,
- /// "foo::bar<int, float>::", and now we need to build a scope
- /// specifier. \p SS is empty or the previously parsed nested-name
- /// part ("foo::"), \p Type is the already-parsed class template
- /// specialization (or other template-id that names a type), \p
- /// TypeRange is the source range where the type is located, and \p
- /// CCLoc is the location of the trailing '::'.
- virtual CXXScopeTy *ActOnCXXNestedNameSpecifier(Scope *S,
- const CXXScopeSpec &SS,
- TypeTy *Type,
- SourceRange TypeRange,
- SourceLocation CCLoc) {
- return 0;
- }
-
- /// ShouldEnterDeclaratorScope - Called when a C++ scope specifier
- /// is parsed as part of a declarator-id to determine whether a scope
- /// should be entered.
- ///
- /// \param S the current scope
- /// \param SS the scope being entered
- /// \param isFriendDeclaration whether this is a friend declaration
- virtual bool ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
- return false;
- }
-
- /// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global
- /// scope or nested-name-specifier) is parsed as part of a declarator-id.
- /// After this method is called, according to [C++ 3.4.3p3], names should be
- /// looked up in the declarator-id's scope, until the declarator is parsed and
- /// ActOnCXXExitDeclaratorScope is called.
- /// The 'SS' should be a non-empty valid CXXScopeSpec.
- /// \returns true if an error occurred, false otherwise.
- virtual bool ActOnCXXEnterDeclaratorScope(Scope *S, CXXScopeSpec &SS) {
- return false;
- }
-
- /// ActOnCXXExitDeclaratorScope - Called when a declarator that previously
- /// invoked ActOnCXXEnterDeclaratorScope(), is finished. 'SS' is the same
- /// CXXScopeSpec that was passed to ActOnCXXEnterDeclaratorScope as well.
- /// Used to indicate that names should revert to being looked up in the
- /// defining scope.
- virtual void ActOnCXXExitDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
- }
-
- /// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse an
- /// initializer for the declaration 'Dcl'.
- /// After this method is called, according to [C++ 3.4.1p13], if 'Dcl' is a
- /// static data member of class X, names should be looked up in the scope of
- /// class X.
- virtual void ActOnCXXEnterDeclInitializer(Scope *S, DeclPtrTy Dcl) {
- }
-
- /// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an
- /// initializer for the declaration 'Dcl'.
- virtual void ActOnCXXExitDeclInitializer(Scope *S, DeclPtrTy Dcl) {
- }
-
- /// ActOnDeclarator - This callback is invoked when a declarator is parsed and
- /// 'Init' specifies the initializer if any. This is for things like:
- /// "int X = 4" or "typedef int foo".
- ///
- virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D) {
- return DeclPtrTy();
- }
-
- /// ActOnParamDeclarator - This callback is invoked when a parameter
- /// declarator is parsed. This callback only occurs for functions
- /// with prototypes. S is the function prototype scope for the
- /// parameters (C++ [basic.scope.proto]).
- virtual DeclPtrTy ActOnParamDeclarator(Scope *S, Declarator &D) {
- return DeclPtrTy();
- }
-
- /// \brief Parsed an exception object declaration within an Objective-C
- /// @catch statement.
- virtual DeclPtrTy ActOnObjCExceptionDecl(Scope *S, Declarator &D) {
- return DeclPtrTy();
- }
-
- /// AddInitializerToDecl - This action is called immediately after
- /// ActOnDeclarator (when an initializer is present). The code is factored
- /// this way to make sure we are able to handle the following:
- /// void func() { int xx = xx; }
- /// This allows ActOnDeclarator to register "xx" prior to parsing the
- /// initializer. The declaration above should still result in a warning,
- /// since the reference to "xx" is uninitialized.
- virtual void AddInitializerToDecl(DeclPtrTy Dcl, ExprArg Init) {
- return;
- }
-
- /// SetDeclDeleted - This action is called immediately after ActOnDeclarator
- /// if =delete is parsed. C++0x [dcl.fct.def]p10
- /// Note that this can be called even for variable declarations. It's the
- /// action's job to reject it.
- virtual void SetDeclDeleted(DeclPtrTy Dcl, SourceLocation DelLoc) {
- return;
- }
-
- /// ActOnUninitializedDecl - This action is called immediately after
- /// ActOnDeclarator (when an initializer is *not* present).
- /// If TypeContainsUndeducedAuto is true, then the type of the declarator
- /// has an undeduced 'auto' type somewhere.
- virtual void ActOnUninitializedDecl(DeclPtrTy Dcl,
- bool TypeContainsUndeducedAuto) {
- return;
- }
-
- /// \brief Note that the given declaration had an initializer that could not
- /// be parsed.
- virtual void ActOnInitializerError(DeclPtrTy Dcl) {
- return;
- }
-
- /// FinalizeDeclaratorGroup - After a sequence of declarators are parsed, this
- /// gives the actions implementation a chance to process the group as a whole.
- virtual DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec& DS,
- DeclPtrTy *Group,
- unsigned NumDecls) {
- return DeclGroupPtrTy();
- }
-
-
- /// @brief Indicates that all K&R-style parameter declarations have
- /// been parsed prior to a function definition.
- /// @param S The function prototype scope.
- /// @param D The function declarator.
- virtual void ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
- SourceLocation LocAfterDecls) {
- }
-
- /// ActOnStartOfFunctionDef - This is called at the start of a function
- /// definition, instead of calling ActOnDeclarator. The Declarator includes
- /// information about formal arguments that are part of this function.
- virtual DeclPtrTy ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) {
- // Default to ActOnDeclarator.
- return ActOnStartOfFunctionDef(FnBodyScope,
- ActOnDeclarator(FnBodyScope, D));
- }
-
- /// ActOnStartOfFunctionDef - This is called at the start of a function
- /// definition, after the FunctionDecl has already been created.
- virtual DeclPtrTy ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) {
- return D;
- }
-
- virtual void ActOnStartOfObjCMethodDef(Scope *FnBodyScope, DeclPtrTy D) {
- return;
- }
-
- /// ActOnFinishFunctionBody - This is called when a function body has
- /// completed parsing. Decl is returned by ParseStartOfFunctionDef.
- virtual DeclPtrTy ActOnFinishFunctionBody(DeclPtrTy Decl, StmtArg Body) {
- return Decl;
- }
-
- virtual DeclPtrTy ActOnFileScopeAsmDecl(SourceLocation Loc,
- ExprArg AsmString) {
- return DeclPtrTy();
- }
-
- /// ActOnPopScope - This callback is called immediately before the specified
- /// scope is popped and deleted.
- virtual void ActOnPopScope(SourceLocation Loc, Scope *S) {}
-
- /// ActOnTranslationUnitScope - This callback is called once, immediately
- /// after creating the translation unit scope (in Parser::Initialize).
- virtual void ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {}
-
- /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
- /// no declarator (e.g. "struct foo;") is parsed.
- virtual DeclPtrTy ParsedFreeStandingDeclSpec(Scope *S,
- AccessSpecifier Access,
- DeclSpec &DS) {
- return DeclPtrTy();
- }
-
- /// ActOnStartLinkageSpecification - Parsed the beginning of a C++
- /// linkage specification, including the language and (if present)
- /// the '{'. ExternLoc is the location of the 'extern', LangLoc is
- /// the location of the language string literal, which is provided
- /// by Lang/StrSize. LBraceLoc, if valid, provides the location of
- /// the '{' brace. Otherwise, this linkage specification does not
- /// have any braces.
- virtual DeclPtrTy ActOnStartLinkageSpecification(Scope *S,
- SourceLocation ExternLoc,
- SourceLocation LangLoc,
- llvm::StringRef Lang,
- SourceLocation LBraceLoc) {
- return DeclPtrTy();
- }
-
- /// ActOnFinishLinkageSpecification - Completely the definition of
- /// the C++ linkage specification LinkageSpec. If RBraceLoc is
- /// valid, it's the position of the closing '}' brace in a linkage
- /// specification that uses braces.
- virtual DeclPtrTy ActOnFinishLinkageSpecification(Scope *S,
- DeclPtrTy LinkageSpec,
- SourceLocation RBraceLoc) {
- return LinkageSpec;
- }
-
- /// ActOnEndOfTranslationUnit - This is called at the very end of the
- /// translation unit when EOF is reached and all but the top-level scope is
- /// popped.
- virtual void ActOnEndOfTranslationUnit() {}
-
- //===--------------------------------------------------------------------===//
- // Type Parsing Callbacks.
- //===--------------------------------------------------------------------===//
-
- /// ActOnTypeName - A type-name (type-id in C++) was parsed.
- virtual TypeResult ActOnTypeName(Scope *S, Declarator &D) {
- return TypeResult();
- }
-
- enum TagUseKind {
- TUK_Reference, // Reference to a tag: 'struct foo *X;'
- TUK_Declaration, // Fwd decl of a tag: 'struct foo;'
- TUK_Definition, // Definition of a tag: 'struct foo { int X; } Y;'
- TUK_Friend // Friend declaration: 'friend struct foo;'
- };
-
- /// \brief The parser has encountered a tag (e.g., "class X") that should be
- /// turned into a declaration by the action module.
- ///
- /// \param S the scope in which this tag occurs.
- ///
- /// \param TagSpec an instance of DeclSpec::TST, indicating what kind of tag
- /// this is (struct/union/enum/class).
- ///
- /// \param TUK how the tag we have encountered is being used, which
- /// can be a reference to a (possibly pre-existing) tag, a
- /// declaration of that tag, or the beginning of a definition of
- /// that tag.
- ///
- /// \param KWLoc the location of the "struct", "class", "union", or "enum"
- /// keyword.
- ///
- /// \param SS C++ scope specifier that precedes the name of the tag, e.g.,
- /// the "std::" in "class std::type_info".
- ///
- /// \param Name the name of the tag, e.g., "X" in "struct X". This parameter
- /// may be NULL, to indicate an anonymous class/struct/union/enum type.
- ///
- /// \param NameLoc the location of the name of the tag.
- ///
- /// \param Attr the set of attributes that appertain to the tag.
- ///
- /// \param AS when this tag occurs within a C++ class, provides the
- /// current access specifier (AS_public, AS_private, AS_protected).
- /// Otherwise, it will be AS_none.
- ///
- /// \param TemplateParameterLists the set of C++ template parameter lists
- /// that apply to this tag, if the tag is a declaration or definition (see
- /// the \p TK parameter). The action module is responsible for determining,
- /// based on the template parameter lists and the scope specifier, whether
- /// the declared tag is a class template or not.
- ///
- /// \param OwnedDecl the callee should set this flag true when the returned
- /// declaration is "owned" by this reference. Ownership is handled entirely
- /// by the action module.
- ///
- /// \returns the declaration to which this tag refers.
- virtual DeclPtrTy ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
- SourceLocation KWLoc, CXXScopeSpec &SS,
- IdentifierInfo *Name, SourceLocation NameLoc,
- AttributeList *Attr, AccessSpecifier AS,
- MultiTemplateParamsArg TemplateParameterLists,
- bool &OwnedDecl, bool &IsDependent) {
- return DeclPtrTy();
- }
-
- /// Acts on a reference to a dependent tag name. This arises in
- /// cases like:
- ///
- /// template <class T> class A;
- /// template <class T> class B {
- /// friend class A<T>::M; // here
- /// };
- ///
- /// \param TagSpec an instance of DeclSpec::TST corresponding to the
- /// tag specifier.
- ///
- /// \param TUK the tag use kind (either TUK_Friend or TUK_Reference)
- ///
- /// \param SS the scope specifier (always defined)
- virtual TypeResult ActOnDependentTag(Scope *S,
- unsigned TagSpec,
- TagUseKind TUK,
- const CXXScopeSpec &SS,
- IdentifierInfo *Name,
- SourceLocation KWLoc,
- SourceLocation NameLoc) {
- return TypeResult();
- }
-
- /// Act on @defs() element found when parsing a structure. ClassName is the
- /// name of the referenced class.
- virtual void ActOnDefs(Scope *S, DeclPtrTy TagD, SourceLocation DeclStart,
- IdentifierInfo *ClassName,
- llvm::SmallVectorImpl<DeclPtrTy> &Decls) {}
- virtual DeclPtrTy ActOnField(Scope *S, DeclPtrTy TagD,
- SourceLocation DeclStart,
- Declarator &D, ExprTy *BitfieldWidth) {
- return DeclPtrTy();
- }
-
- virtual DeclPtrTy ActOnIvar(Scope *S, SourceLocation DeclStart,
- DeclPtrTy IntfDecl,
- Declarator &D, ExprTy *BitfieldWidth,
- tok::ObjCKeywordKind visibility) {
- return DeclPtrTy();
- }
-
- virtual void ActOnFields(Scope* S, SourceLocation RecLoc, DeclPtrTy TagDecl,
- DeclPtrTy *Fields, unsigned NumFields,
- SourceLocation LBrac, SourceLocation RBrac,
- AttributeList *AttrList) {}
-
- /// ActOnTagStartDefinition - Invoked when we have entered the
- /// scope of a tag's definition (e.g., for an enumeration, class,
- /// struct, or union).
- virtual void ActOnTagStartDefinition(Scope *S, DeclPtrTy TagDecl) { }
-
- /// ActOnStartCXXMemberDeclarations - Invoked when we have parsed a
- /// C++ record definition's base-specifiers clause and are starting its
- /// member declarations.
- virtual void ActOnStartCXXMemberDeclarations(Scope *S, DeclPtrTy TagDecl,
- SourceLocation LBraceLoc) { }
-
- /// ActOnTagFinishDefinition - Invoked once we have finished parsing
- /// the definition of a tag (enumeration, class, struct, or union).
- ///
- /// The scope is the scope of the tag definition.
- virtual void ActOnTagFinishDefinition(Scope *S, DeclPtrTy TagDecl,
- SourceLocation RBraceLoc) { }
-
- /// ActOnTagDefinitionError - Invoked if there's an unrecoverable
- /// error parsing the definition of a tag.
- ///
- /// The scope is the scope of the tag definition.
- virtual void ActOnTagDefinitionError(Scope *S, DeclPtrTy TagDecl) { }
-
- virtual DeclPtrTy ActOnEnumConstant(Scope *S, DeclPtrTy EnumDecl,
- DeclPtrTy LastEnumConstant,
- SourceLocation IdLoc, IdentifierInfo *Id,
- SourceLocation EqualLoc, ExprTy *Val) {
- return DeclPtrTy();
- }
- virtual void ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
- SourceLocation RBraceLoc, DeclPtrTy EnumDecl,
- DeclPtrTy *Elements, unsigned NumElements,
- Scope *S, AttributeList *AttrList) {}
-
- //===--------------------------------------------------------------------===//
- // Statement Parsing Callbacks.
- //===--------------------------------------------------------------------===//
-
- virtual OwningStmtResult ActOnNullStmt(SourceLocation SemiLoc) {
- return StmtEmpty();
- }
-
- virtual OwningStmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R,
- MultiStmtArg Elts,
- bool isStmtExpr) {
- return StmtEmpty();
- }
- virtual OwningStmtResult ActOnDeclStmt(DeclGroupPtrTy Decl,
- SourceLocation StartLoc,
- SourceLocation EndLoc) {
- return StmtEmpty();
- }
-
- virtual void ActOnForEachDeclStmt(DeclGroupPtrTy Decl) {
- }
-
- virtual OwningStmtResult ActOnExprStmt(FullExprArg Expr) {
- return OwningStmtResult(*this, Expr->release());
- }
-
- /// ActOnCaseStmt - Note that this handles the GNU 'case 1 ... 4' extension,
- /// which can specify an RHS value. The sub-statement of the case is
- /// specified in a separate action.
- virtual OwningStmtResult ActOnCaseStmt(SourceLocation CaseLoc, ExprArg LHSVal,
- SourceLocation DotDotDotLoc,
- ExprArg RHSVal,
- SourceLocation ColonLoc) {
- return StmtEmpty();
- }
-
- /// ActOnCaseStmtBody - This installs a statement as the body of a case.
- virtual void ActOnCaseStmtBody(StmtTy *CaseStmt, StmtArg SubStmt) {}
-
- virtual OwningStmtResult ActOnDefaultStmt(SourceLocation DefaultLoc,
- SourceLocation ColonLoc,
- StmtArg SubStmt, Scope *CurScope){
- return StmtEmpty();
- }
-
- virtual OwningStmtResult ActOnLabelStmt(SourceLocation IdentLoc,
- IdentifierInfo *II,
- SourceLocation ColonLoc,
- StmtArg SubStmt) {
- return StmtEmpty();
- }
-
- /// \brief Parsed an "if" statement.
- ///
- /// \param IfLoc the location of the "if" keyword.
- ///
- /// \param CondVal if the "if" condition was parsed as an expression,
- /// the expression itself.
- ///
- /// \param CondVar if the "if" condition was parsed as a condition variable,
- /// the condition variable itself.
- ///
- /// \param ThenVal the "then" statement.
- ///
- /// \param ElseLoc the location of the "else" keyword.
- ///
- /// \param ElseVal the "else" statement.
- virtual OwningStmtResult ActOnIfStmt(SourceLocation IfLoc,
- FullExprArg CondVal,
- DeclPtrTy CondVar,
- StmtArg ThenVal,
- SourceLocation ElseLoc,
- StmtArg ElseVal) {
- return StmtEmpty();
- }
-
- /// \brief Parsed the start of a "switch" statement.
- ///
- /// \param SwitchLoc The location of the "switch" keyword.
- ///
- /// \param Cond if the "switch" condition was parsed as an expression,
- /// the expression itself.
- ///
- /// \param CondVar if the "switch" condition was parsed as a condition
- /// variable, the condition variable itself.
- virtual OwningStmtResult ActOnStartOfSwitchStmt(SourceLocation SwitchLoc,
- ExprArg Cond,
- DeclPtrTy CondVar) {
- return StmtEmpty();
- }
-
- virtual OwningStmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc,
- StmtArg Switch, StmtArg Body) {
- return StmtEmpty();
- }
-
- /// \brief Parsed a "while" statement.
- ///
- /// \param Cond if the "while" condition was parsed as an expression,
- /// the expression itself.
- ///
- /// \param CondVar if the "while" condition was parsed as a condition
- /// variable, the condition variable itself.
- ///
- /// \param Body the body of the "while" loop.
- virtual OwningStmtResult ActOnWhileStmt(SourceLocation WhileLoc,
- FullExprArg Cond, DeclPtrTy CondVar,
- StmtArg Body) {
- return StmtEmpty();
- }
- virtual OwningStmtResult ActOnDoStmt(SourceLocation DoLoc, StmtArg Body,
- SourceLocation WhileLoc,
- SourceLocation CondLParen,
- ExprArg Cond,
- SourceLocation CondRParen) {
- return StmtEmpty();
- }
-
- /// \brief Parsed a "for" statement.
- ///
- /// \param ForLoc the location of the "for" keyword.
- ///
- /// \param LParenLoc the location of the left parentheses.
- ///
- /// \param First the statement used to initialize the for loop.
- ///
- /// \param Second the condition to be checked during each iteration, if
- /// that condition was parsed as an expression.
- ///
- /// \param SecondArg the condition variable to be checked during each
- /// iterator, if that condition was parsed as a variable declaration.
- ///
- /// \param Third the expression that will be evaluated to "increment" any
- /// values prior to the next iteration.
- ///
- /// \param RParenLoc the location of the right parentheses.
- ///
- /// \param Body the body of the "body" loop.
- virtual OwningStmtResult ActOnForStmt(SourceLocation ForLoc,
- SourceLocation LParenLoc,
- StmtArg First, FullExprArg Second,
- DeclPtrTy SecondVar, FullExprArg Third,
- SourceLocation RParenLoc,
- StmtArg Body) {
- return StmtEmpty();
- }
-
- virtual OwningStmtResult ActOnObjCForCollectionStmt(SourceLocation ForColLoc,
- SourceLocation LParenLoc,
- StmtArg First, ExprArg Second,
- SourceLocation RParenLoc, StmtArg Body) {
- return StmtEmpty();
- }
- virtual OwningStmtResult ActOnGotoStmt(SourceLocation GotoLoc,
- SourceLocation LabelLoc,
- IdentifierInfo *LabelII) {
- return StmtEmpty();
- }
- virtual OwningStmtResult ActOnIndirectGotoStmt(SourceLocation GotoLoc,
- SourceLocation StarLoc,
- ExprArg DestExp) {
- return StmtEmpty();
- }
- virtual OwningStmtResult ActOnContinueStmt(SourceLocation ContinueLoc,
- Scope *CurScope) {
- return StmtEmpty();
- }
- virtual OwningStmtResult ActOnBreakStmt(SourceLocation GotoLoc,
- Scope *CurScope) {
- return StmtEmpty();
- }
- virtual OwningStmtResult ActOnReturnStmt(SourceLocation ReturnLoc,
- ExprArg RetValExp) {
- return StmtEmpty();
- }
- virtual OwningStmtResult ActOnAsmStmt(SourceLocation AsmLoc,
- bool IsSimple,
- bool IsVolatile,
- unsigned NumOutputs,
- unsigned NumInputs,
- IdentifierInfo **Names,
- MultiExprArg Constraints,
- MultiExprArg Exprs,
- ExprArg AsmString,
- MultiExprArg Clobbers,
- SourceLocation RParenLoc,
- bool MSAsm = false) {
- return StmtEmpty();
- }
-
- // Objective-c statements
-
- /// \brief Parsed an Objective-C @catch statement.
- ///
- /// \param AtLoc The location of the '@' starting the '@catch'.
- ///
- /// \param RParen The location of the right parentheses ')' after the
- /// exception variable.
- ///
- /// \param Parm The variable that will catch the exception. Will be NULL if
- /// this is a @catch(...) block.
- ///
- /// \param Body The body of the @catch block.
- virtual OwningStmtResult ActOnObjCAtCatchStmt(SourceLocation AtLoc,
- SourceLocation RParen,
- DeclPtrTy Parm, StmtArg Body) {
- return StmtEmpty();
- }
-
- /// \brief Parsed an Objective-C @finally statement.
- ///
- /// \param AtLoc The location of the '@' starting the '@finally'.
- ///
- /// \param Body The body of the @finally block.
- virtual OwningStmtResult ActOnObjCAtFinallyStmt(SourceLocation AtLoc,
- StmtArg Body) {
- return StmtEmpty();
- }
-
- /// \brief Parsed an Objective-C @try-@catch-@finally statement.
- ///
- /// \param AtLoc The location of the '@' starting '@try'.
- ///
- /// \param Try The body of the '@try' statement.
- ///
- /// \param CatchStmts The @catch statements.
- ///
- /// \param Finally The @finally statement.
- virtual OwningStmtResult ActOnObjCAtTryStmt(SourceLocation AtLoc,
- StmtArg Try,
- MultiStmtArg CatchStmts,
- StmtArg Finally) {
- return StmtEmpty();
- }
-
- virtual OwningStmtResult ActOnObjCAtThrowStmt(SourceLocation AtLoc,
- ExprArg Throw,
- Scope *CurScope) {
- return StmtEmpty();
- }
-
- virtual OwningStmtResult ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc,
- ExprArg SynchExpr,
- StmtArg SynchBody) {
- return StmtEmpty();
- }
-
- // C++ Statements
- virtual DeclPtrTy ActOnExceptionDeclarator(Scope *S, Declarator &D) {
- return DeclPtrTy();
- }
-
- virtual OwningStmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc,
- DeclPtrTy ExceptionDecl,
- StmtArg HandlerBlock) {
- return StmtEmpty();
- }
-
- virtual OwningStmtResult ActOnCXXTryBlock(SourceLocation TryLoc,
- StmtArg TryBlock,
- MultiStmtArg Handlers) {
- return StmtEmpty();
- }
-
- //===--------------------------------------------------------------------===//
- // Expression Parsing Callbacks.
- //===--------------------------------------------------------------------===//
-
- /// \brief Describes how the expressions currently being parsed are
- /// evaluated at run-time, if at all.
- enum ExpressionEvaluationContext {
- /// \brief The current expression and its subexpressions occur within an
- /// unevaluated operand (C++0x [expr]p8), such as a constant expression
- /// or the subexpression of \c sizeof, where the type or the value of the
- /// expression may be significant but no code will be generated to evaluate
- /// the value of the expression at run time.
- Unevaluated,
-
- /// \brief The current expression is potentially evaluated at run time,
- /// which means that code may be generated to evaluate the value of the
- /// expression at run time.
- PotentiallyEvaluated,
-
- /// \brief The current expression may be potentially evaluated or it may
- /// be unevaluated, but it is impossible to tell from the lexical context.
- /// This evaluation context is used primary for the operand of the C++
- /// \c typeid expression, whose argument is potentially evaluated only when
- /// it is an lvalue of polymorphic class type (C++ [basic.def.odr]p2).
- PotentiallyPotentiallyEvaluated
- };
-
- /// \brief The parser is entering a new expression evaluation context.
- ///
- /// \param NewContext is the new expression evaluation context.
- virtual void
- PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext) { }
-
- /// \brief The parser is exiting an expression evaluation context.
- virtual void
- PopExpressionEvaluationContext() { }
-
- // Primary Expressions.
-
- /// \brief Retrieve the source range that corresponds to the given
- /// expression.
- virtual SourceRange getExprRange(ExprTy *E) const {
- return SourceRange();
- }
-
- /// \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,
- CXXScopeSpec &SS,
- UnqualifiedId &Name,
- bool HasTrailingLParen,
- bool IsAddressOfOperand) {
- return ExprEmpty();
- }
-
- virtual OwningExprResult ActOnPredefinedExpr(SourceLocation Loc,
- tok::TokenKind Kind) {
- return ExprEmpty();
- }
- virtual OwningExprResult ActOnCharacterConstant(const Token &) {
- return ExprEmpty();
- }
- virtual OwningExprResult ActOnNumericConstant(const Token &) {
- return ExprEmpty();
- }
-
- /// ActOnStringLiteral - The specified tokens were lexed as pasted string
- /// fragments (e.g. "foo" "bar" L"baz").
- virtual OwningExprResult ActOnStringLiteral(const Token *Toks,
- unsigned NumToks) {
- return ExprEmpty();
- }
-
- virtual OwningExprResult ActOnParenExpr(SourceLocation L, SourceLocation R,
- ExprArg Val) {
- return move(Val); // Default impl returns operand.
- }
-
- virtual OwningExprResult ActOnParenOrParenListExpr(SourceLocation L,
- SourceLocation R,
- MultiExprArg Val,
- TypeTy *TypeOfCast=0) {
- return ExprEmpty();
- }
-
- // Postfix Expressions.
- virtual OwningExprResult ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc,
- tok::TokenKind Kind,
- ExprArg Input) {
- return ExprEmpty();
- }
- virtual OwningExprResult ActOnArraySubscriptExpr(Scope *S, ExprArg Base,
- SourceLocation LLoc,
- ExprArg Idx,
- SourceLocation RLoc) {
- return ExprEmpty();
- }
-
- /// \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,
- 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,
- /// unless there are zero arguments.
- virtual OwningExprResult ActOnCallExpr(Scope *S, ExprArg Fn,
- SourceLocation LParenLoc,
- MultiExprArg Args,
- SourceLocation *CommaLocs,
- SourceLocation RParenLoc) {
- return ExprEmpty();
- }
-
- // Unary Operators. 'Tok' is the token for the operator.
- virtual OwningExprResult ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
- tok::TokenKind Op, ExprArg Input) {
- return ExprEmpty();
- }
- virtual OwningExprResult
- ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType,
- void *TyOrEx, const SourceRange &ArgRange) {
- return ExprEmpty();
- }
-
- virtual OwningExprResult ActOnCompoundLiteral(SourceLocation LParen,
- TypeTy *Ty,
- SourceLocation RParen,
- ExprArg Op) {
- return ExprEmpty();
- }
- virtual OwningExprResult ActOnInitList(SourceLocation LParenLoc,
- MultiExprArg InitList,
- SourceLocation RParenLoc) {
- return ExprEmpty();
- }
- /// @brief Parsed a C99 designated initializer.
- ///
- /// @param Desig Contains the designation with one or more designators.
- ///
- /// @param Loc The location of the '=' or ':' prior to the
- /// initialization expression.
- ///
- /// @param GNUSyntax If true, then this designated initializer used
- /// the deprecated GNU syntax @c fieldname:foo or @c [expr]foo rather
- /// than the C99 syntax @c .fieldname=foo or @c [expr]=foo.
- ///
- /// @param Init The value that the entity (or entities) described by
- /// the designation will be initialized with.
- virtual OwningExprResult ActOnDesignatedInitializer(Designation &Desig,
- SourceLocation Loc,
- bool GNUSyntax,
- OwningExprResult Init) {
- return ExprEmpty();
- }
-
- virtual OwningExprResult ActOnCastExpr(Scope *S, SourceLocation LParenLoc,
- TypeTy *Ty, SourceLocation RParenLoc,
- ExprArg Op) {
- return ExprEmpty();
- }
-
- virtual bool TypeIsVectorType(TypeTy *Ty) {
- return false;
- }
-
- virtual OwningExprResult ActOnBinOp(Scope *S, SourceLocation TokLoc,
- tok::TokenKind Kind,
- ExprArg LHS, ExprArg RHS) {
- return ExprEmpty();
- }
-
- /// ActOnConditionalOp - Parse a ?: operation. Note that 'LHS' may be null
- /// in the case of a the GNU conditional expr extension.
- virtual OwningExprResult ActOnConditionalOp(SourceLocation QuestionLoc,
- SourceLocation ColonLoc,
- ExprArg Cond, ExprArg LHS,
- ExprArg RHS) {
- return ExprEmpty();
- }
-
- //===---------------------- GNU Extension Expressions -------------------===//
-
- virtual OwningExprResult ActOnAddrLabel(SourceLocation OpLoc,
- SourceLocation LabLoc,
- IdentifierInfo *LabelII) { // "&&foo"
- return ExprEmpty();
- }
-
- virtual OwningExprResult ActOnStmtExpr(SourceLocation LPLoc, StmtArg SubStmt,
- SourceLocation RPLoc) { // "({..})"
- return ExprEmpty();
- }
-
- // __builtin_offsetof(type, identifier(.identifier|[expr])*)
- struct OffsetOfComponent {
- SourceLocation LocStart, LocEnd;
- bool isBrackets; // true if [expr], false if .ident
- union {
- IdentifierInfo *IdentInfo;
- ExprTy *E;
- } U;
- };
-
- virtual OwningExprResult ActOnBuiltinOffsetOf(Scope *S,
- SourceLocation BuiltinLoc,
- SourceLocation TypeLoc,
- TypeTy *Arg1,
- OffsetOfComponent *CompPtr,
- unsigned NumComponents,
- SourceLocation RParenLoc) {
- return ExprEmpty();
- }
-
- // __builtin_types_compatible_p(type1, type2)
- virtual OwningExprResult ActOnTypesCompatibleExpr(SourceLocation BuiltinLoc,
- TypeTy *arg1, TypeTy *arg2,
- SourceLocation RPLoc) {
- return ExprEmpty();
- }
- // __builtin_choose_expr(constExpr, expr1, expr2)
- virtual OwningExprResult ActOnChooseExpr(SourceLocation BuiltinLoc,
- ExprArg cond, ExprArg expr1,
- ExprArg expr2, SourceLocation RPLoc){
- return ExprEmpty();
- }
-
- // __builtin_va_arg(expr, type)
- virtual OwningExprResult ActOnVAArg(SourceLocation BuiltinLoc,
- ExprArg expr, TypeTy *type,
- SourceLocation RPLoc) {
- return ExprEmpty();
- }
-
- /// ActOnGNUNullExpr - Parsed the GNU __null expression, the token
- /// for which is at position TokenLoc.
- virtual OwningExprResult ActOnGNUNullExpr(SourceLocation TokenLoc) {
- return ExprEmpty();
- }
-
- //===------------------------- "Block" Extension ------------------------===//
-
- /// ActOnBlockStart - This callback is invoked when a block literal is
- /// started. The result pointer is passed into the block finalizers.
- virtual void ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope) {}
-
- /// ActOnBlockArguments - This callback allows processing of block arguments.
- /// If there are no arguments, this is still invoked.
- virtual void ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) {}
-
- /// ActOnBlockError - If there is an error parsing a block, this callback
- /// is invoked to pop the information about the block from the action impl.
- virtual void ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope) {}
-
- /// ActOnBlockStmtExpr - This is called when the body of a block statement
- /// literal was successfully completed. ^(int x){...}
- virtual OwningExprResult ActOnBlockStmtExpr(SourceLocation CaretLoc,
- StmtArg Body,
- Scope *CurScope) {
- return ExprEmpty();
- }
-
- //===------------------------- C++ Declarations -------------------------===//
-
- /// ActOnStartNamespaceDef - This is called at the start of a namespace
- /// definition.
- virtual DeclPtrTy ActOnStartNamespaceDef(Scope *S, SourceLocation IdentLoc,
- IdentifierInfo *Ident,
- SourceLocation LBrace,
- AttributeList *AttrList) {
- return DeclPtrTy();
- }
-
- /// ActOnFinishNamespaceDef - This callback is called after a namespace is
- /// exited. Decl is returned by ActOnStartNamespaceDef.
- virtual void ActOnFinishNamespaceDef(DeclPtrTy Dcl, SourceLocation RBrace) {
- return;
- }
-
- /// ActOnUsingDirective - This is called when using-directive is parsed.
- virtual DeclPtrTy ActOnUsingDirective(Scope *CurScope,
- SourceLocation UsingLoc,
- SourceLocation NamespcLoc,
- CXXScopeSpec &SS,
- SourceLocation IdentLoc,
- IdentifierInfo *NamespcName,
- AttributeList *AttrList);
-
- /// ActOnNamespaceAliasDef - This is called when a namespace alias definition
- /// is parsed.
- virtual DeclPtrTy ActOnNamespaceAliasDef(Scope *CurScope,
- SourceLocation NamespaceLoc,
- SourceLocation AliasLoc,
- IdentifierInfo *Alias,
- CXXScopeSpec &SS,
- SourceLocation IdentLoc,
- IdentifierInfo *Ident) {
- return DeclPtrTy();
- }
-
- /// \brief Parsed a C++ using-declaration.
- ///
- /// This callback will be invoked when the parser has parsed a C++
- /// using-declaration, e.g.,
- ///
- /// \code
- /// namespace std {
- /// template<typename T, typename Alloc> class vector;
- /// }
- ///
- /// using std::vector; // using-declaration here
- /// \endcode
- ///
- /// \param CurScope the scope in which this using declaration was parsed.
- ///
- /// \param AS the currently-active access specifier.
- ///
- /// \param HasUsingKeyword true if this was declared with an
- /// explicit 'using' keyword (i.e. if this is technically a using
- /// declaration, not an access declaration)
- ///
- /// \param UsingLoc the location of the 'using' keyword.
- ///
- /// \param SS the nested-name-specifier that precedes the name.
- ///
- /// \param Name the name to which the using declaration refers.
- ///
- /// \param AttrList attributes applied to this using declaration, if any.
- ///
- /// \param IsTypeName whether this using declaration started with the
- /// 'typename' keyword. FIXME: This will eventually be split into a
- /// separate action.
- ///
- /// \param TypenameLoc the location of the 'typename' keyword, if present
- ///
- /// \returns a representation of the using declaration.
- virtual DeclPtrTy ActOnUsingDeclaration(Scope *CurScope,
- AccessSpecifier AS,
- bool HasUsingKeyword,
- SourceLocation UsingLoc,
- CXXScopeSpec &SS,
- UnqualifiedId &Name,
- AttributeList *AttrList,
- bool IsTypeName,
- SourceLocation TypenameLoc);
-
- /// ActOnParamDefaultArgument - Parse default argument for function parameter
- virtual void ActOnParamDefaultArgument(DeclPtrTy param,
- SourceLocation EqualLoc,
- ExprArg defarg) {
- }
-
- /// ActOnParamUnparsedDefaultArgument - We've seen a default
- /// argument for a function parameter, but we can't parse it yet
- /// because we're inside a class definition. Note that this default
- /// argument will be parsed later.
- virtual void ActOnParamUnparsedDefaultArgument(DeclPtrTy param,
- SourceLocation EqualLoc,
- SourceLocation ArgLoc) { }
-
- /// ActOnParamDefaultArgumentError - Parsing or semantic analysis of
- /// the default argument for the parameter param failed.
- virtual void ActOnParamDefaultArgumentError(DeclPtrTy param) { }
-
- /// AddCXXDirectInitializerToDecl - This action is called immediately after
- /// ActOnDeclarator, when a C++ direct initializer is present.
- /// e.g: "int x(1);"
- virtual void AddCXXDirectInitializerToDecl(DeclPtrTy Dcl,
- SourceLocation LParenLoc,
- MultiExprArg Exprs,
- SourceLocation *CommaLocs,
- SourceLocation RParenLoc) {
- return;
- }
-
- /// \brief Called when we re-enter a template parameter scope.
- ///
- /// This action occurs when we are going to parse an member
- /// function's default arguments or inline definition after the
- /// outermost class definition has been completed, and when one or
- /// more of the class definitions enclosing the member function is a
- /// template. The "entity" in the given scope will be set as it was
- /// when we entered the scope of the template initially, and should
- /// be used to, e.g., reintroduce the names of template parameters
- /// into the current scope so that they can be found by name lookup.
- ///
- /// \param S The (new) template parameter scope.
- ///
- /// \param Template the class template declaration whose template
- /// parameters should be reintroduced into the current scope.
- virtual void ActOnReenterTemplateScope(Scope *S, DeclPtrTy Template) {
- }
-
- /// ActOnStartDelayedMemberDeclarations - We have completed parsing
- /// a C++ class, and we are about to start parsing any parts of
- /// member declarations that could not be parsed earlier. Enter
- /// the appropriate record scope.
- virtual void ActOnStartDelayedMemberDeclarations(Scope *S,
- DeclPtrTy Record) {
- }
-
- /// ActOnStartDelayedCXXMethodDeclaration - We have completed
- /// parsing a top-level (non-nested) C++ class, and we are now
- /// parsing those parts of the given Method declaration that could
- /// not be parsed earlier (C++ [class.mem]p2), such as default
- /// arguments. This action should enter the scope of the given
- /// Method declaration as if we had just parsed the qualified method
- /// name. However, it should not bring the parameters into scope;
- /// that will be performed by ActOnDelayedCXXMethodParameter.
- virtual void ActOnStartDelayedCXXMethodDeclaration(Scope *S,
- DeclPtrTy Method) {
- }
-
- /// ActOnDelayedCXXMethodParameter - We've already started a delayed
- /// C++ method declaration. We're (re-)introducing the given
- /// function parameter into scope for use in parsing later parts of
- /// the method declaration. For example, we could see an
- /// ActOnParamDefaultArgument event for this parameter.
- virtual void ActOnDelayedCXXMethodParameter(Scope *S, DeclPtrTy Param) {
- }
-
- /// ActOnFinishDelayedCXXMethodDeclaration - We have finished
- /// processing the delayed method declaration for Method. The method
- /// declaration is now considered finished. There may be a separate
- /// ActOnStartOfFunctionDef action later (not necessarily
- /// immediately!) for this method, if it was also defined inside the
- /// class body.
- virtual void ActOnFinishDelayedCXXMethodDeclaration(Scope *S,
- DeclPtrTy Method) {
- }
-
- /// ActOnFinishDelayedMemberDeclarations - We have finished parsing
- /// a C++ class, and we are about to start parsing any parts of
- /// member declarations that could not be parsed earlier. Enter the
- /// appropriate record scope.
- virtual void ActOnFinishDelayedMemberDeclarations(Scope *S,
- DeclPtrTy Record) {
- }
-
- /// ActOnStaticAssertDeclaration - Parse a C++0x static_assert declaration.
- virtual DeclPtrTy ActOnStaticAssertDeclaration(SourceLocation AssertLoc,
- ExprArg AssertExpr,
- ExprArg AssertMessageExpr) {
- return DeclPtrTy();
- }
-
- /// ActOnFriendFunctionDecl - Parsed a friend function declarator.
- /// The name is actually a slight misnomer, because the declarator
- /// is not necessarily a function declarator.
- virtual DeclPtrTy ActOnFriendFunctionDecl(Scope *S,
- Declarator &D,
- bool IsDefinition,
- MultiTemplateParamsArg TParams) {
- return DeclPtrTy();
- }
-
- /// ActOnFriendTypeDecl - Parsed a friend type declaration.
- virtual DeclPtrTy ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
- MultiTemplateParamsArg TParams) {
- return DeclPtrTy();
- }
-
- //===------------------------- C++ Expressions --------------------------===//
-
- /// \brief Parsed a destructor name or pseudo-destructor name.
- ///
- /// \returns the type being destructed.
- virtual TypeTy *getDestructorName(SourceLocation TildeLoc,
- IdentifierInfo &II, SourceLocation NameLoc,
- Scope *S, CXXScopeSpec &SS,
- TypeTy *ObjectType,
- bool EnteringContext) {
- return getTypeName(II, NameLoc, S, &SS, false, ObjectType);
- }
-
-
- /// ActOnCXXNamedCast - Parse {dynamic,static,reinterpret,const}_cast's.
- virtual OwningExprResult ActOnCXXNamedCast(SourceLocation OpLoc,
- tok::TokenKind Kind,
- SourceLocation LAngleBracketLoc,
- TypeTy *Ty,
- SourceLocation RAngleBracketLoc,
- SourceLocation LParenLoc,
- ExprArg Op,
- SourceLocation RParenLoc) {
- return ExprEmpty();
- }
-
- /// ActOnCXXTypeidOfType - Parse typeid( type-id ).
- virtual OwningExprResult ActOnCXXTypeid(SourceLocation OpLoc,
- SourceLocation LParenLoc, bool isType,
- void *TyOrExpr,
- SourceLocation RParenLoc) {
- return ExprEmpty();
- }
-
- /// ActOnCXXThis - Parse the C++ 'this' pointer.
- virtual OwningExprResult ActOnCXXThis(SourceLocation ThisLoc) {
- return ExprEmpty();
- }
-
- /// ActOnCXXBoolLiteral - Parse {true,false} literals.
- virtual OwningExprResult ActOnCXXBoolLiteral(SourceLocation OpLoc,
- tok::TokenKind Kind) {
- return ExprEmpty();
- }
-
- /// ActOnCXXNullPtrLiteral - Parse 'nullptr'.
- virtual OwningExprResult ActOnCXXNullPtrLiteral(SourceLocation Loc) {
- return ExprEmpty();
- }
-
- /// ActOnCXXThrow - Parse throw expressions.
- virtual OwningExprResult ActOnCXXThrow(SourceLocation OpLoc, ExprArg Op) {
- return ExprEmpty();
- }
-
- /// ActOnCXXTypeConstructExpr - Parse construction of a specified type.
- /// Can be interpreted either as function-style casting ("int(x)")
- /// or class type construction ("ClassType(x,y,z)")
- /// or creation of a value-initialized type ("int()").
- virtual OwningExprResult ActOnCXXTypeConstructExpr(SourceRange TypeRange,
- TypeTy *TypeRep,
- SourceLocation LParenLoc,
- MultiExprArg Exprs,
- SourceLocation *CommaLocs,
- SourceLocation RParenLoc) {
- return ExprEmpty();
- }
-
- /// \brief Parsed a condition declaration in a C++ if, switch, or while
- /// statement.
- ///
- /// This callback will be invoked after parsing the declaration of "x" in
- ///
- /// \code
- /// if (int x = f()) {
- /// // ...
- /// }
- /// \endcode
- ///
- /// \param S the scope of the if, switch, or while statement.
- ///
- /// \param D the declarator that that describes the variable being declared.
- virtual DeclResult ActOnCXXConditionDeclaration(Scope *S, Declarator &D) {
- return DeclResult();
- }
-
- /// \brief Parsed an expression that will be handled as the condition in
- /// an if/while/for statement.
- ///
- /// This routine handles the conversion of the expression to 'bool'.
- ///
- /// \param S The scope in which the expression occurs.
- ///
- /// \param Loc The location of the construct that requires the conversion to
- /// a boolean value.
- ///
- /// \param SubExpr The expression that is being converted to bool.
- virtual OwningExprResult ActOnBooleanCondition(Scope *S, SourceLocation Loc,
- ExprArg SubExpr) {
- return move(SubExpr);
- }
-
- /// \brief Parsed a C++ 'new' expression.
- ///
- /// \param StartLoc The start of the new expression, which is either the
- /// "new" keyword or the "::" preceding it, depending on \p UseGlobal.
- ///
- /// \param UseGlobal True if the "new" was qualified with "::".
- ///
- /// \param PlacementLParen The location of the opening parenthesis ('(') for
- /// the placement arguments, if any.
- ///
- /// \param PlacementArgs The placement arguments, if any.
- ///
- /// \param PlacementRParen The location of the closing parenthesis (')') for
- /// the placement arguments, if any.
- ///
- /// \param TypeIdParens If the type was expressed as a type-id in parentheses,
- /// the source range covering the parenthesized type-id.
- ///
- /// \param D The parsed declarator, which may include an array size (for
- /// array new) as the first declarator.
- ///
- /// \param ConstructorLParen The location of the opening parenthesis ('(') for
- /// the constructor arguments, if any.
- ///
- /// \param ConstructorArgs The constructor arguments, if any.
- ///
- /// \param ConstructorRParen The location of the closing parenthesis (')') for
- /// the constructor arguments, if any.
- virtual OwningExprResult ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
- SourceLocation PlacementLParen,
- MultiExprArg PlacementArgs,
- SourceLocation PlacementRParen,
- SourceRange TypeIdParens, Declarator &D,
- SourceLocation ConstructorLParen,
- MultiExprArg ConstructorArgs,
- SourceLocation ConstructorRParen) {
- return ExprEmpty();
- }
-
- /// ActOnCXXDelete - Parsed a C++ 'delete' expression. UseGlobal is true if
- /// the delete was qualified (::delete). ArrayForm is true if the array form
- /// was used (delete[]).
- virtual OwningExprResult ActOnCXXDelete(SourceLocation StartLoc,
- bool UseGlobal, bool ArrayForm,
- ExprArg Operand) {
- return ExprEmpty();
- }
-
- virtual OwningExprResult ActOnUnaryTypeTrait(UnaryTypeTrait OTT,
- SourceLocation KWLoc,
- SourceLocation LParen,
- TypeTy *Ty,
- SourceLocation RParen) {
- return ExprEmpty();
- }
-
- /// \brief Invoked when the parser is starting to parse a C++ member access
- /// expression such as x.f or x->f.
- ///
- /// \param S the scope in which the member access expression occurs.
- ///
- /// \param Base the expression in which a member is being accessed, e.g., the
- /// "x" in "x.f".
- ///
- /// \param OpLoc the location of the member access operator ("." or "->")
- ///
- /// \param OpKind the kind of member access operator ("." or "->")
- ///
- /// \param ObjectType originally NULL. The action should fill in this type
- /// with the type into which name lookup should look to find the member in
- /// the member access expression.
- ///
- /// \param MayBePseudoDestructor Originally false. The action should
- /// set this true if the expression may end up being a
- /// pseudo-destructor expression, indicating to the parser that it
- /// shoudl be parsed as a pseudo-destructor rather than as a member
- /// access expression. Note that this should apply both when the
- /// object type is a scalar and when the object type is dependent.
- ///
- /// \returns the (possibly modified) \p Base expression
- virtual OwningExprResult ActOnStartCXXMemberReference(Scope *S,
- ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- TypeTy *&ObjectType,
- bool &MayBePseudoDestructor) {
- return ExprEmpty();
- }
-
- /// \brief Parsed a C++ pseudo-destructor expression or a dependent
- /// member access expression that has the same syntactic form as a
- /// pseudo-destructor expression.
- ///
- /// \param S The scope in which the member access expression occurs.
- ///
- /// \param Base The expression in which a member is being accessed, e.g., the
- /// "x" in "x.f".
- ///
- /// \param OpLoc The location of the member access operator ("." or "->")
- ///
- /// \param OpKind The kind of member access operator ("." or "->")
- ///
- /// \param SS The nested-name-specifier that precedes the type names
- /// in the grammar. Note that this nested-name-specifier will not
- /// cover the last "type-name ::" in the grammar, because it isn't
- /// necessarily a nested-name-specifier.
- ///
- /// \param FirstTypeName The type name that follows the optional
- /// nested-name-specifier but precedes the '::', e.g., the first
- /// type-name in "type-name :: type-name". This type name may be
- /// empty. This will be either an identifier or a template-id.
- ///
- /// \param CCLoc The location of the '::' in "type-name ::
- /// typename". May be invalid, if there is no \p FirstTypeName.
- ///
- /// \param TildeLoc The location of the '~'.
- ///
- /// \param SecondTypeName The type-name following the '~', which is
- /// the name of the type being destroyed. This will be either an
- /// identifier or a template-id.
- ///
- /// \param HasTrailingLParen Whether the next token in the stream is
- /// a left parentheses.
- virtual OwningExprResult ActOnPseudoDestructorExpr(Scope *S, ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- CXXScopeSpec &SS,
- UnqualifiedId &FirstTypeName,
- SourceLocation CCLoc,
- SourceLocation TildeLoc,
- UnqualifiedId &SecondTypeName,
- bool HasTrailingLParen) {
- return ExprEmpty();
- }
-
- /// ActOnFinishFullExpr - Called whenever a full expression has been parsed.
- /// (C++ [intro.execution]p12).
- virtual OwningExprResult ActOnFinishFullExpr(ExprArg Expr) {
- return move(Expr);
- }
-
- //===---------------------------- C++ Classes ---------------------------===//
- /// ActOnBaseSpecifier - Parsed a base specifier
- virtual BaseResult ActOnBaseSpecifier(DeclPtrTy classdecl,
- SourceRange SpecifierRange,
- bool Virtual, AccessSpecifier Access,
- TypeTy *basetype,
- SourceLocation BaseLoc) {
- return BaseResult();
- }
-
- virtual void ActOnBaseSpecifiers(DeclPtrTy ClassDecl, BaseTy **Bases,
- unsigned NumBases) {
- }
-
- /// ActOnAccessSpecifier - This is invoked when an access specifier
- /// (and the colon following it) is found during the parsing of a
- /// C++ class member declarator.
- virtual DeclPtrTy ActOnAccessSpecifier(AccessSpecifier AS,
- SourceLocation ASLoc,
- SourceLocation ColonLoc) {
- return DeclPtrTy();
- }
-
- /// ActOnCXXMemberDeclarator - This is invoked when a C++ class member
- /// declarator is parsed. 'AS' is the access specifier, 'BitfieldWidth'
- /// specifies the bitfield width if there is one and 'Init' specifies the
- /// initializer if any. 'Deleted' is true if there's a =delete
- /// specifier on the function.
- virtual DeclPtrTy ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS,
- Declarator &D,
- MultiTemplateParamsArg TemplateParameterLists,
- ExprTy *BitfieldWidth,
- ExprTy *Init,
- bool IsDefinition,
- bool Deleted = false) {
- return DeclPtrTy();
- }
-
- virtual MemInitResult ActOnMemInitializer(DeclPtrTy ConstructorDecl,
- Scope *S,
- CXXScopeSpec &SS,
- IdentifierInfo *MemberOrBase,
- TypeTy *TemplateTypeTy,
- SourceLocation IdLoc,
- SourceLocation LParenLoc,
- ExprTy **Args, unsigned NumArgs,
- SourceLocation *CommaLocs,
- SourceLocation RParenLoc) {
- return true;
- }
-
- /// ActOnMemInitializers - This is invoked when all of the member
- /// initializers of a constructor have been parsed. ConstructorDecl
- /// is the function declaration (which will be a C++ constructor in
- /// a well-formed program), ColonLoc is the location of the ':' that
- /// starts the constructor initializer, and MemInit/NumMemInits
- /// contains the individual member (and base) initializers.
- /// AnyErrors will be true if there were any invalid member initializers
- /// that are not represented in the list.
- virtual void ActOnMemInitializers(DeclPtrTy ConstructorDecl,
- SourceLocation ColonLoc,
- MemInitTy **MemInits, unsigned NumMemInits,
- bool AnyErrors){
- }
-
- virtual void ActOnDefaultCtorInitializers(DeclPtrTy CDtorDecl) {}
-
- /// ActOnFinishCXXMemberSpecification - Invoked after all member declarators
- /// are parsed but *before* parsing of inline method definitions.
- virtual void ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
- DeclPtrTy TagDecl,
- SourceLocation LBrac,
- SourceLocation RBrac,
- AttributeList *AttrList) {
- }
-
- //===---------------------------C++ Templates----------------------------===//
-
- /// \brief Called when a C++ template type parameter(e.g., "typename T") has
- /// been parsed.
- ///
- /// Given
- ///
- /// \code
- /// template<typename T, typename U = T> struct pair;
- /// \endcode
- ///
- /// this callback will be invoked twice: once for the type parameter \c T
- /// with \p Depth=0 and \p Position=0, and once for the type parameter \c U
- /// with \p Depth=0 and \p Position=1.
- ///
- /// \param Typename Specifies whether the keyword "typename" was used to
- /// declare the type parameter (otherwise, "class" was used).
- ///
- /// \param Ellipsis Specifies whether this is a C++0x parameter pack.
- ///
- /// \param EllipsisLoc Specifies the start of the ellipsis.
- ///
- /// \param KeyLoc The location of the "class" or "typename" keyword.
- ///
- /// \param ParamName The name of the parameter, where NULL indicates an
- /// unnamed template parameter.
- ///
- /// \param ParamNameLoc The location of the parameter name (if any).
- ///
- /// \param Depth The depth of this template parameter, e.g., the number of
- /// template parameter lists that occurred outside the template parameter
- /// list in which this template type parameter occurs.
- ///
- /// \param Position The zero-based position of this template parameter within
- /// its template parameter list, which is also the number of template
- /// parameters that precede this parameter in the template parameter list.
- ///
- /// \param EqualLoc The location of the '=' sign for the default template
- /// argument, if any.
- ///
- /// \param DefaultArg The default argument, if provided.
- virtual DeclPtrTy ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis,
- SourceLocation EllipsisLoc,
- SourceLocation KeyLoc,
- IdentifierInfo *ParamName,
- SourceLocation ParamNameLoc,
- unsigned Depth, unsigned Position,
- SourceLocation EqualLoc,
- TypeTy *DefaultArg) {
- return DeclPtrTy();
- }
-
- /// \brief Called when a C++ non-type template parameter has been parsed.
- ///
- /// Given
- ///
- /// \code
- /// template<int Size> class Array;
- /// \endcode
- ///
- /// This callback will be invoked for the 'Size' non-type template parameter.
- ///
- /// \param S The current scope.
- ///
- /// \param D The parsed declarator.
- ///
- /// \param Depth The depth of this template parameter, e.g., the number of
- /// template parameter lists that occurred outside the template parameter
- /// list in which this template type parameter occurs.
- ///
- /// \param Position The zero-based position of this template parameter within
- /// its template parameter list, which is also the number of template
- /// parameters that precede this parameter in the template parameter list.
- ///
- /// \param EqualLoc The location of the '=' sign for the default template
- /// argument, if any.
- ///
- /// \param DefaultArg The default argument, if provided.
- virtual DeclPtrTy ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
- unsigned Depth,
- unsigned Position,
- SourceLocation EqualLoc,
- ExprArg DefaultArg) {
- return DeclPtrTy();
- }
-
- /// \brief Adds a default argument to the given non-type template
- /// parameter.
- virtual void ActOnNonTypeTemplateParameterDefault(DeclPtrTy TemplateParam,
- SourceLocation EqualLoc,
- ExprArg Default) {
- }
-
- /// \brief Called when a C++ template template parameter has been parsed.
- ///
- /// Given
- ///
- /// \code
- /// template<template <typename> class T> class X;
- /// \endcode
- ///
- /// this callback will be invoked for the template template parameter \c T.
- ///
- /// \param S The scope in which this template template parameter occurs.
- ///
- /// \param TmpLoc The location of the "template" keyword.
- ///
- /// \param TemplateParams The template parameters required by the template.
- ///
- /// \param ParamName The name of the parameter, or NULL if unnamed.
- ///
- /// \param ParamNameLoc The source location of the parameter name (if given).
- ///
- /// \param Depth The depth of this template parameter, e.g., the number of
- /// template parameter lists that occurred outside the template parameter
- /// list in which this template parameter occurs.
- ///
- /// \param Position The zero-based position of this template parameter within
- /// its template parameter list, which is also the number of template
- /// parameters that precede this parameter in the template parameter list.
- ///
- /// \param EqualLoc The location of the '=' sign for the default template
- /// argument, if any.
- ///
- /// \param DefaultArg The default argument, if provided.
- virtual DeclPtrTy ActOnTemplateTemplateParameter(Scope *S,
- SourceLocation TmpLoc,
- TemplateParamsTy *Params,
- IdentifierInfo *ParamName,
- SourceLocation ParamNameLoc,
- unsigned Depth,
- unsigned Position,
- SourceLocation EqualLoc,
- const ParsedTemplateArgument &DefaultArg) {
- return DeclPtrTy();
- }
-
- /// ActOnTemplateParameterList - Called when a complete template
- /// parameter list has been parsed, e.g.,
- ///
- /// @code
- /// export template<typename T, T Size>
- /// @endcode
- ///
- /// Depth is the number of enclosing template parameter lists. This
- /// value does not include templates from outer scopes. For example:
- ///
- /// @code
- /// template<typename T> // depth = 0
- /// class A {
- /// template<typename U> // depth = 0
- /// class B;
- /// };
- ///
- /// template<typename T> // depth = 0
- /// template<typename U> // depth = 1
- /// class A<T>::B { ... };
- /// @endcode
- ///
- /// ExportLoc, if valid, is the position of the "export"
- /// keyword. Otherwise, "export" was not specified.
- /// TemplateLoc is the position of the template keyword, LAngleLoc
- /// is the position of the left angle bracket, and RAngleLoc is the
- /// position of the corresponding right angle bracket.
- /// Params/NumParams provides the template parameters that were
- /// parsed as part of the template-parameter-list.
- virtual TemplateParamsTy *
- ActOnTemplateParameterList(unsigned Depth,
- SourceLocation ExportLoc,
- SourceLocation TemplateLoc,
- SourceLocation LAngleLoc,
- DeclPtrTy *Params, unsigned NumParams,
- SourceLocation RAngleLoc) {
- return 0;
- }
-
- /// \brief Form a type from a template and a list of template
- /// arguments.
- ///
- /// This action merely forms the type for the template-id, possibly
- /// checking well-formedness of the template arguments. It does not
- /// imply the declaration of any entity.
- ///
- /// \param Template A template whose specialization results in a
- /// type, e.g., a class template or template template parameter.
- virtual TypeResult ActOnTemplateIdType(TemplateTy Template,
- SourceLocation TemplateLoc,
- SourceLocation LAngleLoc,
- ASTTemplateArgsPtr TemplateArgs,
- SourceLocation RAngleLoc) {
- return TypeResult();
- }
-
- /// \brief Note that a template ID was used with a tag.
- ///
- /// \param Type The result of ActOnTemplateIdType.
- ///
- /// \param TUK Either TUK_Reference or TUK_Friend. Declarations and
- /// definitions are interpreted as explicit instantiations or
- /// specializations.
- ///
- /// \param TagSpec The tag keyword that was provided as part of the
- /// elaborated-type-specifier; either class, struct, union, or enum.
- ///
- /// \param TagLoc The location of the tag keyword.
- virtual TypeResult ActOnTagTemplateIdType(TypeResult Type,
- TagUseKind TUK,
- DeclSpec::TST TagSpec,
- SourceLocation TagLoc) {
- return TypeResult();
- }
-
- /// \brief Form a dependent template name.
- ///
- /// This action forms a dependent template name given the template
- /// name and its (presumably dependent) scope specifier. For
- /// example, given "MetaFun::template apply", the scope specifier \p
- /// SS will be "MetaFun::", \p TemplateKWLoc contains the location
- /// of the "template" keyword, and "apply" is the \p Name.
- ///
- /// \param S The scope in which the dependent template name was parsed.
- ///
- /// \param TemplateKWLoc the location of the "template" keyword (if any).
- ///
- /// \param SS the nested-name-specifier that precedes the "template" keyword
- /// 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.
- ///
- /// \param EnteringContext whether we are entering the context of this
- /// template.
- ///
- /// \param Template Will be set to the dependent template name, on success.
- ///
- /// \returns The kind of template name that was produced. Generally, this will
- /// be \c TNK_Dependent_template_name. However, if the nested-name-specifier
- /// is not dependent, or refers to the current instantiation, then we may
- /// be able to resolve the template kind more specifically.
- virtual TemplateNameKind ActOnDependentTemplateName(Scope *S,
- SourceLocation TemplateKWLoc,
- CXXScopeSpec &SS,
- UnqualifiedId &Name,
- TypeTy *ObjectType,
- bool EnteringContext,
- TemplateTy &Template) {
- return TNK_Non_template;
- }
-
- /// \brief Process the declaration or definition of an explicit
- /// class template specialization or a class template partial
- /// specialization.
- ///
- /// This routine is invoked when an explicit class template
- /// specialization or a class template partial specialization is
- /// declared or defined, to introduce the (partial) specialization
- /// and produce a declaration for it. In the following example,
- /// ActOnClassTemplateSpecialization will be invoked for the
- /// declarations at both A and B:
- ///
- /// \code
- /// template<typename T> class X;
- /// template<> class X<int> { }; // A: explicit specialization
- /// template<typename T> class X<T*> { }; // B: partial specialization
- /// \endcode
- ///
- /// Note that it is the job of semantic analysis to determine which
- /// of the two cases actually occurred in the source code, since
- /// they are parsed through the same path. The formulation of the
- /// template parameter lists describes which case we are in.
- ///
- /// \param S the current scope
- ///
- /// \param TagSpec whether this declares a class, struct, or union
- /// (template)
- ///
- /// \param TUK whether this is a declaration or a definition
- ///
- /// \param KWLoc the location of the 'class', 'struct', or 'union'
- /// keyword.
- ///
- /// \param SS the scope specifier preceding the template-id
- ///
- /// \param Template the declaration of the class template that we
- /// are specializing.
- ///
- /// \param Attr attributes on the specialization
- ///
- /// \param TemplateParameterLists the set of template parameter
- /// lists that apply to this declaration. In a well-formed program,
- /// the number of template parameter lists will be one more than the
- /// number of template-ids in the scope specifier. However, it is
- /// common for users to provide the wrong number of template
- /// parameter lists (such as a missing \c template<> prior to a
- /// specialization); the parser does not check this condition.
- virtual DeclResult
- ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagUseKind TUK,
- SourceLocation KWLoc,
- CXXScopeSpec &SS,
- TemplateTy Template,
- SourceLocation TemplateNameLoc,
- SourceLocation LAngleLoc,
- ASTTemplateArgsPtr TemplateArgs,
- SourceLocation RAngleLoc,
- AttributeList *Attr,
- MultiTemplateParamsArg TemplateParameterLists) {
- return DeclResult();
- }
-
- /// \brief Invoked when a declarator that has one or more template parameter
- /// lists has been parsed.
- ///
- /// This action is similar to ActOnDeclarator(), except that the declaration
- /// being created somehow involves a template, e.g., it is a template
- /// declaration or specialization.
- virtual DeclPtrTy ActOnTemplateDeclarator(Scope *S,
- MultiTemplateParamsArg TemplateParameterLists,
- Declarator &D) {
- return DeclPtrTy();
- }
-
- /// \brief Invoked when the parser is beginning to parse a function template
- /// or function template specialization definition.
- virtual DeclPtrTy ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope,
- MultiTemplateParamsArg TemplateParameterLists,
- Declarator &D) {
- return DeclPtrTy();
- }
-
- /// \brief Process the explicit instantiation of a class template
- /// specialization.
- ///
- /// This routine is invoked when an explicit instantiation of a
- /// class template specialization is encountered. In the following
- /// example, ActOnExplicitInstantiation will be invoked to force the
- /// instantiation of X<int>:
- ///
- /// \code
- /// template<typename T> class X { /* ... */ };
- /// template class X<int>; // explicit instantiation
- /// \endcode
- ///
- /// \param S the current scope
- ///
- /// \param ExternLoc the location of the 'extern' keyword that specifies that
- /// this is an extern template (if any).
- ///
- /// \param TemplateLoc the location of the 'template' keyword that
- /// specifies that this is an explicit instantiation.
- ///
- /// \param TagSpec whether this declares a class, struct, or union
- /// (template).
- ///
- /// \param KWLoc the location of the 'class', 'struct', or 'union'
- /// keyword.
- ///
- /// \param SS the scope specifier preceding the template-id.
- ///
- /// \param Template the declaration of the class template that we
- /// are instantiation.
- ///
- /// \param LAngleLoc the location of the '<' token in the template-id.
- ///
- /// \param TemplateArgs the template arguments used to form the
- /// template-id.
- ///
- /// \param TemplateArgLocs the locations of the template arguments.
- ///
- /// \param RAngleLoc the location of the '>' token in the template-id.
- ///
- /// \param Attr attributes that apply to this instantiation.
- virtual DeclResult
- ActOnExplicitInstantiation(Scope *S,
- SourceLocation ExternLoc,
- SourceLocation TemplateLoc,
- unsigned TagSpec,
- SourceLocation KWLoc,
- const CXXScopeSpec &SS,
- TemplateTy Template,
- SourceLocation TemplateNameLoc,
- SourceLocation LAngleLoc,
- ASTTemplateArgsPtr TemplateArgs,
- SourceLocation RAngleLoc,
- AttributeList *Attr) {
- return DeclResult();
- }
-
- /// \brief Process the explicit instantiation of a member class of a
- /// class template specialization.
- ///
- /// This routine is invoked when an explicit instantiation of a
- /// member class of a class template specialization is
- /// encountered. In the following example,
- /// ActOnExplicitInstantiation will be invoked to force the
- /// instantiation of X<int>::Inner:
- ///
- /// \code
- /// template<typename T> class X { class Inner { /* ... */}; };
- /// template class X<int>::Inner; // explicit instantiation
- /// \endcode
- ///
- /// \param S the current scope
- ///
- /// \param ExternLoc the location of the 'extern' keyword that specifies that
- /// this is an extern template (if any).
- ///
- /// \param TemplateLoc the location of the 'template' keyword that
- /// specifies that this is an explicit instantiation.
- ///
- /// \param TagSpec whether this declares a class, struct, or union
- /// (template).
- ///
- /// \param KWLoc the location of the 'class', 'struct', or 'union'
- /// keyword.
- ///
- /// \param SS the scope specifier preceding the template-id.
- ///
- /// \param Template the declaration of the class template that we
- /// are instantiation.
- ///
- /// \param LAngleLoc the location of the '<' token in the template-id.
- ///
- /// \param TemplateArgs the template arguments used to form the
- /// template-id.
- ///
- /// \param TemplateArgLocs the locations of the template arguments.
- ///
- /// \param RAngleLoc the location of the '>' token in the template-id.
- ///
- /// \param Attr attributes that apply to this instantiation.
- virtual DeclResult
- ActOnExplicitInstantiation(Scope *S,
- SourceLocation ExternLoc,
- SourceLocation TemplateLoc,
- unsigned TagSpec,
- SourceLocation KWLoc,
- CXXScopeSpec &SS,
- IdentifierInfo *Name,
- SourceLocation NameLoc,
- AttributeList *Attr) {
- return DeclResult();
- }
-
- /// \brief Process the explicit instantiation of a function template or a
- /// member of a class template.
- ///
- /// This routine is invoked when an explicit instantiation of a
- /// function template or member function of a class template specialization
- /// is encountered. In the following example,
- /// ActOnExplicitInstantiation will be invoked to force the
- /// instantiation of X<int>:
- ///
- /// \code
- /// template<typename T> void f(T);
- /// template void f(int); // explicit instantiation
- /// \endcode
- ///
- /// \param S the current scope
- ///
- /// \param ExternLoc the location of the 'extern' keyword that specifies that
- /// this is an extern template (if any).
- ///
- /// \param TemplateLoc the location of the 'template' keyword that
- /// specifies that this is an explicit instantiation.
- ///
- /// \param D the declarator describing the declaration to be implicitly
- /// instantiated.
- virtual DeclResult ActOnExplicitInstantiation(Scope *S,
- SourceLocation ExternLoc,
- SourceLocation TemplateLoc,
- Declarator &D) {
- return DeclResult();
- }
-
-
- /// \brief Called when the parser has parsed a C++ typename
- /// specifier that ends in an identifier, e.g., "typename T::type".
- ///
- /// \param TypenameLoc the location of the 'typename' keyword
- /// \param SS the nested-name-specifier following the typename (e.g., 'T::').
- /// \param II the identifier we're retrieving (e.g., 'type' in the example).
- /// \param IdLoc the location of the identifier.
- virtual TypeResult
- ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
- const CXXScopeSpec &SS, const IdentifierInfo &II,
- SourceLocation IdLoc) {
- return TypeResult();
- }
-
- /// \brief Called when the parser has parsed a C++ typename
- /// specifier that ends in a template-id, e.g.,
- /// "typename MetaFun::template apply<T1, T2>".
- ///
- /// \param TypenameLoc the location of the 'typename' keyword
- /// \param SS the nested-name-specifier following the typename (e.g., 'T::').
- /// \param TemplateLoc the location of the 'template' keyword, if any.
- /// \param Ty the type that the typename specifier refers to.
- virtual TypeResult
- ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
- const CXXScopeSpec &SS, SourceLocation TemplateLoc,
- TypeTy *Ty) {
- return TypeResult();
- }
-
- /// \brief Called when the parser begins parsing a construct which should not
- /// have access control applied to it.
- virtual void ActOnStartSuppressingAccessChecks() {
- }
-
- /// \brief Called when the parser finishes parsing a construct which should
- /// not have access control applied to it.
- virtual void ActOnStopSuppressingAccessChecks() {
- }
-
- //===----------------------- Obj-C Declarations -------------------------===//
-
- // ActOnStartClassInterface - this action is called immediately after parsing
- // the prologue for a class interface (before parsing the instance
- // variables). Instance variables are processed by ActOnFields().
- virtual DeclPtrTy ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
- IdentifierInfo *ClassName,
- SourceLocation ClassLoc,
- IdentifierInfo *SuperName,
- SourceLocation SuperLoc,
- const DeclPtrTy *ProtoRefs,
- unsigned NumProtoRefs,
- const SourceLocation *ProtoLocs,
- SourceLocation EndProtoLoc,
- AttributeList *AttrList) {
- return DeclPtrTy();
- }
-
- /// ActOnCompatiblityAlias - this action is called after complete parsing of
- /// @compaatibility_alias declaration. It sets up the alias relationships.
- virtual DeclPtrTy ActOnCompatiblityAlias(
- SourceLocation AtCompatibilityAliasLoc,
- IdentifierInfo *AliasName, SourceLocation AliasLocation,
- IdentifierInfo *ClassName, SourceLocation ClassLocation) {
- return DeclPtrTy();
- }
-
- // ActOnStartProtocolInterface - this action is called immdiately after
- // parsing the prologue for a protocol interface.
- virtual DeclPtrTy ActOnStartProtocolInterface(SourceLocation AtProtoLoc,
- IdentifierInfo *ProtocolName,
- SourceLocation ProtocolLoc,
- const DeclPtrTy *ProtoRefs,
- unsigned NumProtoRefs,
- const SourceLocation *ProtoLocs,
- SourceLocation EndProtoLoc,
- AttributeList *AttrList) {
- return DeclPtrTy();
- }
- // ActOnStartCategoryInterface - this action is called immdiately after
- // parsing the prologue for a category interface.
- virtual DeclPtrTy ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
- IdentifierInfo *ClassName,
- SourceLocation ClassLoc,
- IdentifierInfo *CategoryName,
- SourceLocation CategoryLoc,
- const DeclPtrTy *ProtoRefs,
- unsigned NumProtoRefs,
- const SourceLocation *ProtoLocs,
- SourceLocation EndProtoLoc) {
- return DeclPtrTy();
- }
- // ActOnStartClassImplementation - this action is called immdiately after
- // parsing the prologue for a class implementation. Instance variables are
- // processed by ActOnFields().
- virtual DeclPtrTy ActOnStartClassImplementation(
- SourceLocation AtClassImplLoc,
- IdentifierInfo *ClassName,
- SourceLocation ClassLoc,
- IdentifierInfo *SuperClassname,
- SourceLocation SuperClassLoc) {
- return DeclPtrTy();
- }
- // ActOnStartCategoryImplementation - this action is called immdiately after
- // parsing the prologue for a category implementation.
- virtual DeclPtrTy ActOnStartCategoryImplementation(
- SourceLocation AtCatImplLoc,
- IdentifierInfo *ClassName,
- SourceLocation ClassLoc,
- IdentifierInfo *CatName,
- SourceLocation CatLoc) {
- return DeclPtrTy();
- }
- // ActOnPropertyImplDecl - called for every property implementation
- virtual DeclPtrTy ActOnPropertyImplDecl(
- Scope *S,
- SourceLocation AtLoc, // location of the @synthesize/@dynamic
- SourceLocation PropertyNameLoc, // location for the property name
- bool ImplKind, // true for @synthesize, false for
- // @dynamic
- DeclPtrTy ClassImplDecl, // class or category implementation
- IdentifierInfo *propertyId, // name of property
- IdentifierInfo *propertyIvar) { // name of the ivar
- return DeclPtrTy();
- }
-
- struct ObjCArgInfo {
- IdentifierInfo *Name;
- SourceLocation NameLoc;
- // The Type is null if no type was specified, and the DeclSpec is invalid
- // in this case.
- TypeTy *Type;
- ObjCDeclSpec DeclSpec;
-
- /// ArgAttrs - Attribute list for this argument.
- AttributeList *ArgAttrs;
- };
-
- // ActOnMethodDeclaration - called for all method declarations.
- virtual DeclPtrTy ActOnMethodDeclaration(
- SourceLocation BeginLoc, // location of the + or -.
- SourceLocation EndLoc, // location of the ; or {.
- tok::TokenKind MethodType, // tok::minus for instance, tok::plus for class.
- DeclPtrTy ClassDecl, // class this methods belongs to.
- ObjCDeclSpec &ReturnQT, // for return type's in inout etc.
- TypeTy *ReturnType, // the method return type.
- Selector Sel, // a unique name for the method.
- ObjCArgInfo *ArgInfo, // ArgInfo: Has 'Sel.getNumArgs()' entries.
- DeclaratorChunk::ParamInfo *CParamInfo, unsigned CNumArgs, // c-style args
- AttributeList *MethodAttrList, // optional
- // tok::objc_not_keyword, tok::objc_optional, tok::objc_required
- tok::ObjCKeywordKind impKind,
- bool isVariadic = false) {
- return DeclPtrTy();
- }
- // ActOnAtEnd - called to mark the @end. For declarations (interfaces,
- // protocols, categories), the parser passes all methods/properties.
- // For class implementations, these values default to 0. For implementations,
- // methods are processed incrementally (by ActOnMethodDeclaration above).
- virtual void ActOnAtEnd(Scope *S, SourceRange AtEnd,
- DeclPtrTy classDecl,
- DeclPtrTy *allMethods = 0,
- unsigned allNum = 0,
- DeclPtrTy *allProperties = 0,
- unsigned pNum = 0,
- DeclGroupPtrTy *allTUVars = 0,
- unsigned tuvNum = 0) {
- }
- // ActOnProperty - called to build one property AST
- virtual DeclPtrTy ActOnProperty(Scope *S, SourceLocation AtLoc,
- FieldDeclarator &FD, ObjCDeclSpec &ODS,
- Selector GetterSel, Selector SetterSel,
- DeclPtrTy ClassCategory,
- bool *OverridingProperty,
- tok::ObjCKeywordKind MethodImplKind) {
- return DeclPtrTy();
- }
-
- virtual OwningExprResult
- ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
- IdentifierInfo &propertyName,
- SourceLocation receiverNameLoc,
- SourceLocation propertyNameLoc) {
- return ExprEmpty();
- }
-
- /// \brief Describes the kind of message expression indicated by a message
- /// send that starts with an identifier.
- enum ObjCMessageKind {
- /// \brief The message is sent to 'super'.
- ObjCSuperMessage,
- /// \brief The message is an instance message.
- ObjCInstanceMessage,
- /// \brief The message is a class message, and the identifier is a type
- /// name.
- ObjCClassMessage
- };
-
- /// \brief Determine the kind of Objective-C message send that we will be
- /// performing based on the identifier given.
- ///
- /// This action determines how a message send that starts with [
- /// identifier (followed by another identifier) will be parsed,
- /// e.g., as a class message, instance message, super message. The
- /// result depends on the meaning of the given identifier. If the
- /// identifier is unknown, the action should indicate that the
- /// message is an instance message.
- ///
- /// By default, this routine applies syntactic disambiguation and uses
- /// \c getTypeName() to determine whether the identifier refers to a type.
- /// However, \c Action subclasses may override this routine to improve
- /// error recovery.
- ///
- /// \param S The scope in which the message send occurs.
- ///
- /// \param Name The identifier following the '['.
- ///
- /// \param NameLoc The location of the identifier.
- ///
- /// \param IsSuper Whether the name is the pseudo-keyword "super".
- ///
- /// \param HasTrailingDot Whether the name is followed by a period.
- ///
- /// \param ReceiverType If this routine returns \c ObjCClassMessage,
- /// this argument will be set to the receiver type.
- ///
- /// \returns The kind of message send.
- virtual ObjCMessageKind getObjCMessageKind(Scope *S,
- IdentifierInfo *Name,
- SourceLocation NameLoc,
- bool IsSuper,
- bool HasTrailingDot,
- TypeTy *&ReceiverType);
-
- /// \brief Parsed a message send to 'super'.
- ///
- /// \param S The scope in which the message send occurs.
- /// \param SuperLoc The location of the 'super' keyword.
- /// \param Sel The selector to which the message is being sent.
- /// \param LBracLoc The location of the opening square bracket ']'.
- /// \param SelectorLoc The location of the first identifier in the selector.
- /// \param RBrac The location of the closing square bracket ']'.
- /// \param Args The message arguments.
- virtual OwningExprResult ActOnSuperMessage(Scope *S, SourceLocation SuperLoc,
- Selector Sel,
- SourceLocation LBracLoc,
- SourceLocation SelectorLoc,
- SourceLocation RBracLoc,
- MultiExprArg Args) {
- return OwningExprResult(*this);
- }
-
- /// \brief Parsed a message send to a class.
- ///
- /// \param S The scope in which the message send occurs.
- /// \param Receiver The type of the class receiving the message.
- /// \param Sel The selector to which the message is being sent.
- /// \param LBracLoc The location of the opening square bracket ']'.
- /// \param SelectorLoc The location of the first identifier in the selector.
- /// \param RBrac The location of the closing square bracket ']'.
- /// \param Args The message arguments.
- virtual OwningExprResult ActOnClassMessage(Scope *S,
- TypeTy *Receiver,
- Selector Sel,
- SourceLocation LBracLoc,
- SourceLocation SelectorLoc,
- SourceLocation RBracLoc,
- MultiExprArg Args) {
- return OwningExprResult(*this);
- }
-
- /// \brief Parsed a message send to an object instance.
- ///
- /// \param S The scope in which the message send occurs.
- /// \param Receiver The expression that computes the receiver object.
- /// \param Sel The selector to which the message is being sent.
- /// \param LBracLoc The location of the opening square bracket ']'.
- /// \param SelectorLoc The location of the first identifier in the selector.
- /// \param RBrac The location of the closing square bracket ']'.
- /// \param Args The message arguments.
- virtual OwningExprResult ActOnInstanceMessage(Scope *S,
- ExprArg Receiver,
- Selector Sel,
- SourceLocation LBracLoc,
- SourceLocation SelectorLoc,
- SourceLocation RBracLoc,
- MultiExprArg Args) {
- return OwningExprResult(*this);
- }
-
- virtual DeclPtrTy ActOnForwardClassDeclaration(
- SourceLocation AtClassLoc,
- IdentifierInfo **IdentList,
- SourceLocation *IdentLocs,
- unsigned NumElts) {
- return DeclPtrTy();
- }
- virtual DeclPtrTy ActOnForwardProtocolDeclaration(
- SourceLocation AtProtocolLoc,
- const IdentifierLocPair*IdentList,
- unsigned NumElts,
- AttributeList *AttrList) {
- return DeclPtrTy();
- }
-
- /// FindProtocolDeclaration - This routine looks up protocols and
- /// issues error if they are not declared. It returns list of valid
- /// protocols found.
- virtual void FindProtocolDeclaration(bool WarnOnDeclarations,
- const IdentifierLocPair *ProtocolId,
- unsigned NumProtocols,
- llvm::SmallVectorImpl<DeclPtrTy> &ResProtos) {
- }
-
- //===----------------------- Obj-C Expressions --------------------------===//
-
- virtual ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs,
- ExprTy **Strings,
- unsigned NumStrings) {
- return ExprResult();
- }
-
- virtual ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc,
- SourceLocation EncLoc,
- SourceLocation LParenLoc,
- TypeTy *Ty,
- SourceLocation RParenLoc) {
- return ExprResult();
- }
-
- virtual ExprResult ParseObjCSelectorExpression(Selector Sel,
- SourceLocation AtLoc,
- SourceLocation SelLoc,
- SourceLocation LParenLoc,
- SourceLocation RParenLoc) {
- return ExprResult();
- }
-
- virtual ExprResult ParseObjCProtocolExpression(IdentifierInfo *ProtocolId,
- SourceLocation AtLoc,
- SourceLocation ProtoLoc,
- SourceLocation LParenLoc,
- SourceLocation RParenLoc) {
- return ExprResult();
- }
-
- //===---------------------------- Pragmas -------------------------------===//
-
- enum PragmaOptionsAlignKind {
- POAK_Native, // #pragma options align=native
- POAK_Natural, // #pragma options align=natural
- POAK_Packed, // #pragma options align=packed
- POAK_Power, // #pragma options align=power
- POAK_Mac68k, // #pragma options align=mac68k
- POAK_Reset // #pragma options align=reset
- };
-
- /// ActOnPragmaOptionsAlign - Called on well formed #pragma options
- /// align={...}.
- virtual void ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
- SourceLocation PragmaLoc,
- SourceLocation KindLoc) {
- return;
- }
-
- enum PragmaPackKind {
- PPK_Default, // #pragma pack([n])
- PPK_Show, // #pragma pack(show), only supported by MSVC.
- PPK_Push, // #pragma pack(push, [identifier], [n])
- PPK_Pop // #pragma pack(pop, [identifier], [n])
- };
-
- /// ActOnPragmaPack - Called on well formed #pragma pack(...).
- virtual void ActOnPragmaPack(PragmaPackKind Kind,
- IdentifierInfo *Name,
- ExprTy *Alignment,
- SourceLocation PragmaLoc,
- SourceLocation LParenLoc,
- SourceLocation RParenLoc) {
- return;
- }
-
- /// ActOnPragmaUnused - Called on well formed #pragma unused(...).
- virtual void ActOnPragmaUnused(const Token *Identifiers,
- unsigned NumIdentifiers, Scope *CurScope,
- SourceLocation PragmaLoc,
- SourceLocation LParenLoc,
- SourceLocation RParenLoc) {
- return;
- }
-
- /// ActOnPragmaWeakID - Called on well formed #pragma weak ident.
- virtual void ActOnPragmaWeakID(IdentifierInfo* WeakName,
- SourceLocation PragmaLoc,
- SourceLocation WeakNameLoc) {
- return;
- }
-
- /// ActOnPragmaWeakAlias - Called on well formed #pragma weak ident = ident.
- virtual void ActOnPragmaWeakAlias(IdentifierInfo* WeakName,
- IdentifierInfo* AliasName,
- SourceLocation PragmaLoc,
- SourceLocation WeakNameLoc,
- SourceLocation AliasNameLoc) {
- return;
- }
-
- /// \name Code completion actions
- ///
- /// These actions are used to signal that a code-completion token has been
- /// found at a point in the grammar where the Action implementation is
- /// likely to be able to provide a list of possible completions, e.g.,
- /// after the "." or "->" of a member access expression.
- ///
- /// \todo Code completion for designated field initializers
- /// \todo Code completion for call arguments after a function template-id
- /// \todo Code completion within a call expression, object construction, etc.
- /// \todo Code completion within a template argument list.
- /// \todo Code completion for attributes.
- //@{
-
- /// \brief Describes the context in which code completion occurs.
- enum CodeCompletionContext {
- /// \brief Code completion occurs at top-level or namespace context.
- CCC_Namespace,
- /// \brief Code completion occurs within a class, struct, or union.
- CCC_Class,
- /// \brief Code completion occurs within an Objective-C interface, protocol,
- /// or category.
- CCC_ObjCInterface,
- /// \brief Code completion occurs within an Objective-C implementation or
- /// category implementation
- CCC_ObjCImplementation,
- /// \brief Code completion occurs within the list of instance variables
- /// in an Objective-C interface, protocol, category, or implementation.
- CCC_ObjCInstanceVariableList,
- /// \brief Code completion occurs following one or more template
- /// headers.
- CCC_Template,
- /// \brief Code completion occurs following one or more template
- /// headers within a class.
- CCC_MemberTemplate,
- /// \brief Code completion occurs within an expression.
- CCC_Expression,
- /// \brief Code completion occurs within a statement, which may
- /// also be an expression or a declaration.
- CCC_Statement,
- /// \brief Code completion occurs at the beginning of the
- /// initialization statement (or expression) in a for loop.
- CCC_ForInit,
- /// \brief Code completion occurs within the condition of an if,
- /// while, switch, or for statement.
- CCC_Condition,
- /// \brief Code completion occurs within the body of a function on a
- /// recovery path, where we do not have a specific handle on our position
- /// in the grammar.
- CCC_RecoveryInFunction
- };
-
- /// \brief Code completion for an ordinary name that occurs within the given
- /// scope.
- ///
- /// \param S the scope in which the name occurs.
- ///
- /// \param CompletionContext the context in which code completion
- /// occurs.
- virtual void CodeCompleteOrdinaryName(Scope *S,
- CodeCompletionContext CompletionContext) { }
-
- /// \brief Code completion for a member access expression.
- ///
- /// This code completion action is invoked when the code-completion token
- /// is found after the "." or "->" of a member access expression.
- ///
- /// \param S the scope in which the member access expression occurs.
- ///
- /// \param Base the base expression (e.g., the x in "x.foo") of the member
- /// access.
- ///
- /// \param OpLoc the location of the "." or "->" operator.
- ///
- /// \param IsArrow true when the operator is "->", false when it is ".".
- virtual void CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *Base,
- SourceLocation OpLoc,
- bool IsArrow) { }
-
- /// \brief Code completion for a reference to a tag.
- ///
- /// This code completion action is invoked when the code-completion
- /// token is found after a tag keyword (struct, union, enum, or class).
- ///
- /// \param S the scope in which the tag reference occurs.
- ///
- /// \param TagSpec an instance of DeclSpec::TST, indicating what kind of tag
- /// this is (struct/union/enum/class).
- virtual void CodeCompleteTag(Scope *S, unsigned TagSpec) { }
-
- /// \brief Code completion for a case statement.
- ///
- /// \brief S the scope in which the case statement occurs.
- virtual void CodeCompleteCase(Scope *S) { }
-
- /// \brief Code completion for a call.
- ///
- /// \brief S the scope in which the call occurs.
- ///
- /// \param Fn the expression describing the function being called.
- ///
- /// \param Args the arguments to the function call (so far).
- ///
- /// \param NumArgs the number of arguments in \p Args.
- virtual void CodeCompleteCall(Scope *S, ExprTy *Fn,
- ExprTy **Args, unsigned NumArgs) { }
-
- /// \brief Code completion for the initializer of a variable declaration.
- ///
- /// \param S The scope in which the initializer occurs.
- ///
- /// \param D The declaration being initialized.
- virtual void CodeCompleteInitializer(Scope *S, DeclPtrTy D) { }
-
- /// \brief Code completion after the "return" keyword within a function.
- ///
- /// \param S The scope in which the return statement occurs.
- virtual void CodeCompleteReturn(Scope *S) { }
-
- /// \brief Code completion for the right-hand side of an assignment or
- /// compound assignment operator.
- ///
- /// \param S The scope in which the assignment occurs.
- ///
- /// \param LHS The left-hand side of the assignment expression.
- virtual void CodeCompleteAssignmentRHS(Scope *S, ExprTy *LHS) { }
-
- /// \brief Code completion for a C++ nested-name-specifier that precedes a
- /// qualified-id of some form.
- ///
- /// This code completion action is invoked when the code-completion token
- /// is found after the "::" of a nested-name-specifier.
- ///
- /// \param S the scope in which the nested-name-specifier occurs.
- ///
- /// \param SS the scope specifier ending with "::".
- ///
- /// \parame EnteringContext whether we're entering the context of this
- /// scope specifier.
- virtual void CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
- bool EnteringContext) { }
-
- /// \brief Code completion for a C++ "using" declaration or directive.
- ///
- /// This code completion action is invoked when the code-completion token is
- /// found after the "using" keyword.
- ///
- /// \param S the scope in which the "using" occurs.
- virtual void CodeCompleteUsing(Scope *S) { }
-
- /// \brief Code completion for a C++ using directive.
- ///
- /// This code completion action is invoked when the code-completion token is
- /// found after "using namespace".
- ///
- /// \param S the scope in which the "using namespace" occurs.
- virtual void CodeCompleteUsingDirective(Scope *S) { }
-
- /// \brief Code completion for a C++ namespace declaration or namespace
- /// alias declaration.
- ///
- /// This code completion action is invoked when the code-completion token is
- /// found after "namespace".
- ///
- /// \param S the scope in which the "namespace" token occurs.
- virtual void CodeCompleteNamespaceDecl(Scope *S) { }
-
- /// \brief Code completion for a C++ namespace alias declaration.
- ///
- /// This code completion action is invoked when the code-completion token is
- /// found after "namespace identifier = ".
- ///
- /// \param S the scope in which the namespace alias declaration occurs.
- virtual void CodeCompleteNamespaceAliasDecl(Scope *S) { }
-
- /// \brief Code completion for an operator name.
- ///
- /// This code completion action is invoked when the code-completion token is
- /// found after the keyword "operator".
- ///
- /// \param S the scope in which the operator keyword occurs.
- virtual void CodeCompleteOperatorName(Scope *S) { }
-
- /// \brief Code completion after the '@' at the top level.
- ///
- /// \param S the scope in which the '@' occurs.
- ///
- /// \param ObjCImpDecl the Objective-C implementation or category
- /// implementation.
- ///
- /// \param InInterface whether we are in an Objective-C interface or
- /// protocol.
- virtual void CodeCompleteObjCAtDirective(Scope *S, DeclPtrTy ObjCImpDecl,
- bool InInterface) { }
-
- /// \brief Code completion after the '@' in the list of instance variables.
- virtual void CodeCompleteObjCAtVisibility(Scope *S) { }
-
- /// \brief Code completion after the '@' in a statement.
- virtual void CodeCompleteObjCAtStatement(Scope *S) { }
-
- /// \brief Code completion after the '@' in an expression.
- virtual void CodeCompleteObjCAtExpression(Scope *S) { }
-
- /// \brief Code completion for an ObjC property decl.
- ///
- /// This code completion action is invoked when the code-completion token is
- /// found after the left paren.
- ///
- /// \param S the scope in which the operator keyword occurs.
- virtual void CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) { }
-
- /// \brief Code completion for the getter of an Objective-C property
- /// declaration.
- ///
- /// This code completion action is invoked when the code-completion
- /// token is found after the "getter = " in a property declaration.
- ///
- /// \param S the scope in which the property is being declared.
- ///
- /// \param ClassDecl the Objective-C class or category in which the property
- /// is being defined.
- ///
- /// \param Methods the set of methods declared thus far within \p ClassDecl.
- ///
- /// \param NumMethods the number of methods in \p Methods
- virtual void CodeCompleteObjCPropertyGetter(Scope *S, DeclPtrTy ClassDecl,
- DeclPtrTy *Methods,
- unsigned NumMethods) {
- }
-
- /// \brief Code completion for the setter of an Objective-C property
- /// declaration.
- ///
- /// This code completion action is invoked when the code-completion
- /// token is found after the "setter = " in a property declaration.
- ///
- /// \param S the scope in which the property is being declared.
- ///
- /// \param ClassDecl the Objective-C class or category in which the property
- /// is being defined.
- ///
- /// \param Methods the set of methods declared thus far within \p ClassDecl.
- ///
- /// \param NumMethods the number of methods in \p Methods
- virtual void CodeCompleteObjCPropertySetter(Scope *S, DeclPtrTy ClassDecl,
- DeclPtrTy *Methods,
- unsigned NumMethods) {
- }
-
- /// \brief Code completion for the receiver in an Objective-C message send.
- ///
- /// This code completion action is invoked when we see a '[' that indicates
- /// the start of an Objective-C message send.
- ///
- /// \param S The scope in which the Objective-C message send occurs.
- virtual void CodeCompleteObjCMessageReceiver(Scope *S) { }
-
- /// \brief Code completion for an ObjC message expression that sends
- /// a message to the superclass.
- ///
- /// This code completion action is invoked when the code-completion token is
- /// found after the class name and after each argument.
- ///
- /// \param S The scope in which the message expression occurs.
- /// \param SuperLoc The location of the 'super' keyword.
- /// \param SelIdents The identifiers that describe the selector (thus far).
- /// \param NumSelIdents The number of identifiers in \p SelIdents.
- virtual void CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
- IdentifierInfo **SelIdents,
- unsigned NumSelIdents) { }
-
- /// \brief Code completion for an ObjC message expression that refers to
- /// a class method.
- ///
- /// This code completion action is invoked when the code-completion token is
- /// found after the class name and after each argument.
- ///
- /// \param S The scope in which the message expression occurs.
- /// \param Receiver The type of the class that is receiving a message.
- /// \param SelIdents The identifiers that describe the selector (thus far).
- /// \param NumSelIdents The number of identifiers in \p SelIdents.
- virtual void CodeCompleteObjCClassMessage(Scope *S, TypeTy *Receiver,
- IdentifierInfo **SelIdents,
- unsigned NumSelIdents) { }
-
- /// \brief Code completion for an ObjC message expression that refers to
- /// an instance method.
- ///
- /// This code completion action is invoked when the code-completion token is
- /// found after the receiver expression and after each argument.
- ///
- /// \param S the scope in which the operator keyword occurs.
- /// \param Receiver an expression for the receiver of the message.
- /// \param SelIdents the identifiers that describe the selector (thus far).
- /// \param NumSelIdents the number of identifiers in \p SelIdents.
- virtual void CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
- IdentifierInfo **SelIdents,
- unsigned NumSelIdents) { }
-
- /// \brief Code completion for a list of protocol references in Objective-C,
- /// such as P1 and P2 in \c id<P1,P2>.
- ///
- /// This code completion action is invoked prior to each identifier
- /// in the protocol list.
- ///
- /// \param Protocols the set of protocols that have already been parsed.
- ///
- /// \param NumProtocols the number of protocols that have already been
- /// parsed.
- virtual void CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
- unsigned NumProtocols) { }
-
- /// \brief Code completion for a protocol declaration or definition, after
- /// the @protocol but before any identifier.
- ///
- /// \param S the scope in which the protocol declaration occurs.
- virtual void CodeCompleteObjCProtocolDecl(Scope *S) { }
-
- /// \brief Code completion for an Objective-C interface, after the
- /// @interface but before any identifier.
- virtual void CodeCompleteObjCInterfaceDecl(Scope *S) { }
-
- /// \brief Code completion for the superclass of an Objective-C
- /// interface, after the ':'.
- ///
- /// \param S the scope in which the interface declaration occurs.
- ///
- /// \param ClassName the name of the class being defined.
- virtual void CodeCompleteObjCSuperclass(Scope *S,
- IdentifierInfo *ClassName,
- SourceLocation ClassNameLoc) {
- }
-
- /// \brief Code completion for an Objective-C implementation, after the
- /// @implementation but before any identifier.
- virtual void CodeCompleteObjCImplementationDecl(Scope *S) { }
-
- /// \brief Code completion for the category name in an Objective-C interface
- /// declaration.
- ///
- /// This code completion action is invoked after the '(' that indicates
- /// a category name within an Objective-C interface declaration.
- virtual void CodeCompleteObjCInterfaceCategory(Scope *S,
- IdentifierInfo *ClassName,
- SourceLocation ClassNameLoc) {
- }
-
- /// \brief Code completion for the category name in an Objective-C category
- /// implementation.
- ///
- /// This code completion action is invoked after the '(' that indicates
- /// the category name within an Objective-C category implementation.
- virtual void CodeCompleteObjCImplementationCategory(Scope *S,
- IdentifierInfo *ClassName,
- SourceLocation ClassNameLoc) {
- }
-
- /// \brief Code completion for the property names when defining an
- /// Objective-C property.
- ///
- /// This code completion action is invoked after @synthesize or @dynamic and
- /// after each "," within one of those definitions.
- virtual void CodeCompleteObjCPropertyDefinition(Scope *S,
- DeclPtrTy ObjCImpDecl) {
- }
-
- /// \brief Code completion for the instance variable name that should
- /// follow an '=' when synthesizing an Objective-C property.
- ///
- /// This code completion action is invoked after each '=' that occurs within
- /// an @synthesized definition.
- virtual void CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
- IdentifierInfo *PropertyName,
- DeclPtrTy ObjCImpDecl) {
- }
-
- /// \brief Code completion for an Objective-C method declaration or
- /// definition, which may occur within an interface, category,
- /// extension, protocol, or implementation thereof (where applicable).
- ///
- /// This code completion action is invoked after the "-" or "+" that
- /// starts a method declaration or definition, and after the return
- /// type such a declaration (e.g., "- (id)").
- ///
- /// \param S The scope in which the completion occurs.
- ///
- /// \param IsInstanceMethod Whether this is an instance method
- /// (introduced with '-'); otherwise, it's a class method
- /// (introduced with '+').
- ///
- /// \param ReturnType If non-NULL, the specified return type of the method
- /// being declared or defined.
- ///
- /// \param IDecl The interface, category, protocol, or
- /// implementation, or category implementation in which this method
- /// declaration or definition occurs.
- virtual void CodeCompleteObjCMethodDecl(Scope *S,
- bool IsInstanceMethod,
- TypeTy *ReturnType,
- DeclPtrTy IDecl) {
- }
-
- /// \brief Code completion for a selector identifier or argument name within
- /// an Objective-C method declaration.
- ///
- /// \param S The scope in which this code completion occurs.
- ///
- /// \param IsInstanceMethod Whether we are parsing an instance method (or,
- /// if false, a class method).
- ///
- /// \param AtParameterName Whether the actual code completion point is at the
- /// argument name.
- ///
- /// \param ReturnType If non-NULL, the specified return type of the method
- /// being declared or defined.
- ///
- /// \param SelIdents The identifiers that occurred in the selector for the
- /// method declaration prior to the code completion point.
- ///
- /// \param NumSelIdents The number of identifiers provided by SelIdents.
- virtual void CodeCompleteObjCMethodDeclSelector(Scope *S,
- bool IsInstanceMethod,
- bool AtParameterName,
- TypeTy *ReturnType,
- IdentifierInfo **SelIdents,
- unsigned NumSelIdents) { }
-
- //@}
-};
-
-/// MinimalAction - Minimal actions are used by light-weight clients of the
-/// parser that do not need name resolution or significant semantic analysis to
-/// be performed. The actions implemented here are in the form of unresolved
-/// identifiers. By using a simpler interface than the SemanticAction class,
-/// the parser doesn't have to build complex data structures and thus runs more
-/// quickly.
-class MinimalAction : public Action {
- /// Translation Unit Scope - useful to Objective-C actions that need
- /// to lookup file scope declarations in the "ordinary" C decl namespace.
- /// For example, user-defined classes, built-in "id" type, etc.
- Scope *TUScope;
- IdentifierTable &Idents;
- Preprocessor &PP;
- void *TypeNameInfoTablePtr;
-public:
- MinimalAction(Preprocessor &pp);
- ~MinimalAction();
-
- /// getTypeName - This looks at the IdentifierInfo::FETokenInfo field to
- /// determine whether the name is a typedef or not in this scope.
- ///
- /// \param II the identifier for which we are performing name lookup
- ///
- /// \param NameLoc the location of the identifier
- ///
- /// \param S the scope in which this name lookup occurs
- ///
- /// \param SS if non-NULL, the C++ scope specifier that precedes the
- /// identifier
- ///
- /// \param isClassName whether this is a C++ class-name production, in
- /// which we can end up referring to a member of an unknown specialization
- /// that we know (from the grammar) is supposed to be a type. For example,
- /// this occurs when deriving from "std::vector<T>::allocator_type", where T
- /// is a template parameter.
- ///
- /// \returns the type referred to by this identifier, or NULL if the type
- /// does not name an identifier.
- virtual TypeTy *getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
- Scope *S, CXXScopeSpec *SS,
- bool isClassName = false,
- TypeTy *ObjectType = 0);
-
- /// isCurrentClassName - Always returns false, because MinimalAction
- /// does not support C++ classes with constructors.
- virtual bool isCurrentClassName(const IdentifierInfo& II, Scope *S,
- const CXXScopeSpec *SS);
-
- virtual TemplateNameKind isTemplateName(Scope *S,
- CXXScopeSpec &SS,
- UnqualifiedId &Name,
- TypeTy *ObjectType,
- bool EnteringContext,
- TemplateTy &Template,
- bool &MemberOfUnknownSpecialization);
-
-
- /// ActOnDeclarator - If this is a typedef declarator, we modify the
- /// IdentifierInfo::FETokenInfo field to keep track of this fact, until S is
- /// popped.
- virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D);
-
- /// ActOnPopScope - When a scope is popped, if any typedefs are now
- /// out-of-scope, they are removed from the IdentifierInfo::FETokenInfo field.
- virtual void ActOnPopScope(SourceLocation Loc, Scope *S);
- virtual void ActOnTranslationUnitScope(SourceLocation Loc, Scope *S);
-
- virtual DeclPtrTy ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
- IdentifierInfo **IdentList,
- SourceLocation *SLocs,
- unsigned NumElts);
-
- virtual DeclPtrTy ActOnStartClassInterface(SourceLocation interLoc,
- IdentifierInfo *ClassName,
- SourceLocation ClassLoc,
- IdentifierInfo *SuperName,
- SourceLocation SuperLoc,
- const DeclPtrTy *ProtoRefs,
- unsigned NumProtoRefs,
- const SourceLocation *ProtoLocs,
- SourceLocation EndProtoLoc,
- AttributeList *AttrList);
-};
-
-/// PrettyStackTraceActionsDecl - If a crash occurs in the parser while parsing
-/// something related to a virtualized decl, include that virtualized decl in
-/// the stack trace.
-class PrettyStackTraceActionsDecl : public llvm::PrettyStackTraceEntry {
- Action::DeclPtrTy TheDecl;
- SourceLocation Loc;
- Action &Actions;
- SourceManager &SM;
- const char *Message;
-public:
- PrettyStackTraceActionsDecl(Action::DeclPtrTy Decl, SourceLocation L,
- Action &actions, SourceManager &sm,
- const char *Msg)
- : TheDecl(Decl), Loc(L), Actions(actions), SM(sm), Message(Msg) {}
-
- virtual void print(llvm::raw_ostream &OS) const;
-};
-
-/// \brief RAII object that enters a new expression evaluation context.
-class EnterExpressionEvaluationContext {
- /// \brief The action object.
- Action &Actions;
-
-public:
- EnterExpressionEvaluationContext(Action &Actions,
- Action::ExpressionEvaluationContext NewContext)
- : Actions(Actions) {
- Actions.PushExpressionEvaluationContext(NewContext);
- }
-
- ~EnterExpressionEvaluationContext() {
- Actions.PopExpressionEvaluationContext();
- }
-};
-
-} // end namespace clang
-
-#endif
diff --git a/include/clang/Parse/Ownership.h b/include/clang/Parse/Ownership.h
deleted file mode 100644
index e9a20b7872b5..000000000000
--- a/include/clang/Parse/Ownership.h
+++ /dev/null
@@ -1,845 +0,0 @@
-//===--- Ownership.h - Parser Ownership Helpers -----------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains classes for managing ownership of Stmt and Expr nodes.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_PARSE_OWNERSHIP_H
-#define LLVM_CLANG_PARSE_OWNERSHIP_H
-
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/PointerIntPair.h"
-
-//===----------------------------------------------------------------------===//
-// OpaquePtr
-//===----------------------------------------------------------------------===//
-
-namespace clang {
- class ActionBase;
-
- /// OpaquePtr - This is a very simple POD type that wraps a pointer that the
- /// Parser doesn't know about but that Sema or another client does. The UID
- /// template argument is used to make sure that "Decl" pointers are not
- /// compatible with "Type" pointers for example.
- template<int UID>
- class OpaquePtr {
- void *Ptr;
- public:
- OpaquePtr() : Ptr(0) {}
-
- template <typename T>
- T* getAs() const {
- return llvm::PointerLikeTypeTraits<T*>::getFromVoidPointer(Ptr);
- }
-
- template <typename T>
- T getAsVal() const {
- return llvm::PointerLikeTypeTraits<T>::getFromVoidPointer(Ptr);
- }
-
- void *get() const { return Ptr; }
-
- template<typename T>
- static OpaquePtr make(T P) {
- OpaquePtr R; R.set(P); return R;
- }
-
- template<typename T>
- void set(T P) {
- Ptr = llvm::PointerLikeTypeTraits<T>::getAsVoidPointer(P);
- }
-
- operator bool() const { return Ptr != 0; }
- };
-}
-
-namespace llvm {
- template <int UID>
- class PointerLikeTypeTraits<clang::OpaquePtr<UID> > {
- public:
- static inline void *getAsVoidPointer(clang::OpaquePtr<UID> P) {
- // FIXME: Doesn't work? return P.getAs< void >();
- return P.get();
- }
- static inline clang::OpaquePtr<UID> getFromVoidPointer(void *P) {
- return clang::OpaquePtr<UID>::make(P);
- }
- enum { NumLowBitsAvailable = 3 };
- };
-}
-
-
-
-// -------------------------- About Move Emulation -------------------------- //
-// The smart pointer classes in this file attempt to emulate move semantics
-// as they appear in C++0x with rvalue references. Since C++03 doesn't have
-// rvalue references, some tricks are needed to get similar results.
-// Move semantics in C++0x have the following properties:
-// 1) "Moving" means transferring the value of an object to another object,
-// similar to copying, but without caring what happens to the old object.
-// In particular, this means that the new object can steal the old object's
-// resources instead of creating a copy.
-// 2) Since moving can modify the source object, it must either be explicitly
-// requested by the user, or the modifications must be unnoticeable.
-// 3) As such, C++0x moving is only allowed in three contexts:
-// * By explicitly using std::move() to request it.
-// * From a temporary object, since that object cannot be accessed
-// afterwards anyway, thus making the state unobservable.
-// * On function return, since the object is not observable afterwards.
-//
-// To sum up: moving from a named object should only be possible with an
-// explicit std::move(), or on function return. Moving from a temporary should
-// be implicitly done. Moving from a const object is forbidden.
-//
-// The emulation is not perfect, and has the following shortcomings:
-// * move() is not in namespace std.
-// * move() is required on function return.
-// * There are difficulties with implicit conversions.
-// * Microsoft's compiler must be given the /Za switch to successfully compile.
-//
-// -------------------------- Implementation -------------------------------- //
-// The move emulation relies on the peculiar reference binding semantics of
-// C++03: as a rule, a non-const reference may not bind to a temporary object,
-// except for the implicit object parameter in a member function call, which
-// can refer to a temporary even when not being const.
-// The moveable object has five important functions to facilitate moving:
-// * A private, unimplemented constructor taking a non-const reference to its
-// own class. This constructor serves a two-fold purpose.
-// - It prevents the creation of a copy constructor that takes a const
-// reference. Temporaries would be able to bind to the argument of such a
-// constructor, and that would be bad.
-// - Named objects will bind to the non-const reference, but since it's
-// private, this will fail to compile. This prevents implicit moving from
-// named objects.
-// There's also a copy assignment operator for the same purpose.
-// * An implicit, non-const conversion operator to a special mover type. This
-// type represents the rvalue reference of C++0x. Being a non-const member,
-// its implicit this parameter can bind to temporaries.
-// * A constructor that takes an object of this mover type. This constructor
-// performs the actual move operation. There is an equivalent assignment
-// operator.
-// There is also a free move() function that takes a non-const reference to
-// an object and returns a temporary. Internally, this function uses explicit
-// constructor calls to move the value from the referenced object to the return
-// value.
-//
-// There are now three possible scenarios of use.
-// * Copying from a const object. Constructor overload resolution will find the
-// non-const copy constructor, and the move constructor. The first is not
-// viable because the const object cannot be bound to the non-const reference.
-// The second fails because the conversion to the mover object is non-const.
-// Moving from a const object fails as intended.
-// * Copying from a named object. Constructor overload resolution will select
-// the non-const copy constructor, but fail as intended, because this
-// constructor is private.
-// * Copying from a temporary. Constructor overload resolution cannot select
-// the non-const copy constructor, because the temporary cannot be bound to
-// the non-const reference. It thus selects the move constructor. The
-// temporary can be bound to the implicit this parameter of the conversion
-// operator, because of the special binding rule. Construction succeeds.
-// Note that the Microsoft compiler, as an extension, allows binding
-// temporaries against non-const references. The compiler thus selects the
-// non-const copy constructor and fails, because the constructor is private.
-// Passing /Za (disable extensions) disables this behaviour.
-// The free move() function is used to move from a named object.
-//
-// Note that when passing an object of a different type (the classes below
-// have OwningResult and OwningPtr, which should be mixable), you get a problem.
-// Argument passing and function return use copy initialization rules. The
-// effect of this is that, when the source object is not already of the target
-// type, the compiler will first seek a way to convert the source object to the
-// target type, and only then attempt to copy the resulting object. This means
-// that when passing an OwningResult where an OwningPtr is expected, the
-// compiler will first seek a conversion from OwningResult to OwningPtr, then
-// copy the OwningPtr. The resulting conversion sequence is:
-// OwningResult object -> ResultMover -> OwningResult argument to
-// OwningPtr(OwningResult) -> OwningPtr -> PtrMover -> final OwningPtr
-// This conversion sequence is too complex to be allowed. Thus the special
-// move_* functions, which help the compiler out with some explicit
-// conversions.
-
-// Flip this switch to measure performance impact of the smart pointers.
-// #define DISABLE_SMART_POINTERS
-
-namespace llvm {
- template<>
- class PointerLikeTypeTraits<clang::ActionBase*> {
- typedef clang::ActionBase* PT;
- public:
- static inline void *getAsVoidPointer(PT P) { return P; }
- static inline PT getFromVoidPointer(void *P) {
- return static_cast<PT>(P);
- }
- enum { NumLowBitsAvailable = 2 };
- };
-}
-
-namespace clang {
- // Basic
- class DiagnosticBuilder;
-
- // Determines whether the low bit of the result pointer for the
- // given UID is always zero. If so, ActionResult will use that bit
- // for it's "invalid" flag.
- template<unsigned UID>
- struct IsResultPtrLowBitFree {
- static const bool value = false;
- };
-
- /// ActionBase - A small part split from Action because of the horrible
- /// definition order dependencies between Action and the smart pointers.
- class ActionBase {
- public:
- /// Out-of-line virtual destructor to provide home for this class.
- virtual ~ActionBase();
-
- // Types - Though these don't actually enforce strong typing, they document
- // what types are required to be identical for the actions.
- typedef OpaquePtr<0> DeclPtrTy;
- typedef OpaquePtr<1> DeclGroupPtrTy;
- typedef OpaquePtr<2> TemplateTy;
- typedef void AttrTy;
- typedef void BaseTy;
- typedef void MemInitTy;
- typedef void ExprTy;
- typedef void StmtTy;
- typedef void TemplateParamsTy;
- typedef void CXXScopeTy;
- typedef void TypeTy; // FIXME: Change TypeTy to use OpaquePtr<N>.
-
- /// ActionResult - This structure is used while parsing/acting on
- /// expressions, stmts, etc. It encapsulates both the object returned by
- /// the action, plus a sense of whether or not it is valid.
- /// When CompressInvalid is true, the "invalid" flag will be
- /// stored in the low bit of the Val pointer.
- template<unsigned UID,
- typename PtrTy = void*,
- bool CompressInvalid = IsResultPtrLowBitFree<UID>::value>
- class ActionResult {
- PtrTy Val;
- bool Invalid;
-
- public:
- ActionResult(bool Invalid = false) : Val(PtrTy()), Invalid(Invalid) {}
- template<typename ActualExprTy>
- ActionResult(ActualExprTy val) : Val(val), Invalid(false) {}
- ActionResult(const DiagnosticBuilder &) : Val(PtrTy()), Invalid(true) {}
-
- PtrTy get() const { return Val; }
- void set(PtrTy V) { Val = V; }
- bool isInvalid() const { return Invalid; }
-
- const ActionResult &operator=(PtrTy RHS) {
- Val = RHS;
- Invalid = false;
- return *this;
- }
- };
-
- // This ActionResult partial specialization places the "invalid"
- // flag into the low bit of the pointer.
- template<unsigned UID, typename PtrTy>
- class ActionResult<UID, PtrTy, true> {
- // A pointer whose low bit is 1 if this result is invalid, 0
- // otherwise.
- uintptr_t PtrWithInvalid;
- typedef llvm::PointerLikeTypeTraits<PtrTy> PtrTraits;
- public:
- ActionResult(bool Invalid = false)
- : PtrWithInvalid(static_cast<uintptr_t>(Invalid)) { }
-
- template<typename ActualExprTy>
- ActionResult(ActualExprTy *val) {
- PtrTy V(val);
- void *VP = PtrTraits::getAsVoidPointer(V);
- PtrWithInvalid = reinterpret_cast<uintptr_t>(VP);
- assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer");
- }
-
- ActionResult(PtrTy V) {
- void *VP = PtrTraits::getAsVoidPointer(V);
- PtrWithInvalid = reinterpret_cast<uintptr_t>(VP);
- assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer");
- }
-
- ActionResult(const DiagnosticBuilder &) : PtrWithInvalid(0x01) { }
-
- PtrTy get() const {
- void *VP = reinterpret_cast<void *>(PtrWithInvalid & ~0x01);
- return PtrTraits::getFromVoidPointer(VP);
- }
-
- void set(PtrTy V) {
- void *VP = PtrTraits::getAsVoidPointer(V);
- PtrWithInvalid = reinterpret_cast<uintptr_t>(VP);
- assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer");
- }
-
- bool isInvalid() const { return PtrWithInvalid & 0x01; }
-
- const ActionResult &operator=(PtrTy RHS) {
- void *VP = PtrTraits::getAsVoidPointer(RHS);
- PtrWithInvalid = reinterpret_cast<uintptr_t>(VP);
- assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer");
- return *this;
- }
- };
-
- /// Deletion callbacks - Since the parser doesn't know the concrete types of
- /// the AST nodes being generated, it must do callbacks to delete objects
- /// when recovering from errors. These are in ActionBase because the smart
- /// pointers need access to them.
- virtual void DeleteExpr(ExprTy *E) {}
- virtual void DeleteStmt(StmtTy *S) {}
- virtual void DeleteTemplateParams(TemplateParamsTy *P) {}
- };
-
- /// ASTDestroyer - The type of an AST node destruction function pointer.
- typedef void (ActionBase::*ASTDestroyer)(void *);
-
- /// For the transition phase: translate from an ASTDestroyer to its
- /// ActionResult UID.
- template <ASTDestroyer Destroyer> struct DestroyerToUID;
- template <> struct DestroyerToUID<&ActionBase::DeleteExpr> {
- static const unsigned UID = 0;
- };
- template <> struct DestroyerToUID<&ActionBase::DeleteStmt> {
- static const unsigned UID = 1;
- };
- /// ASTOwningResult - A moveable smart pointer for AST nodes that also
- /// has an extra flag to indicate an additional success status.
- template <ASTDestroyer Destroyer> class ASTOwningResult;
-
- /// ASTMultiPtr - A moveable smart pointer to multiple AST nodes. Only owns
- /// the individual pointers, not the array holding them.
- template <ASTDestroyer Destroyer> class ASTMultiPtr;
-
-#if !defined(DISABLE_SMART_POINTERS)
- namespace moving {
- /// Move emulation helper for ASTOwningResult. NEVER EVER use this class
- /// directly if you don't know what you're doing.
- template <ASTDestroyer Destroyer>
- class ASTResultMover {
- ASTOwningResult<Destroyer> &Moved;
-
- public:
- ASTResultMover(ASTOwningResult<Destroyer> &moved) : Moved(moved) {}
-
- ASTOwningResult<Destroyer> * operator ->() { return &Moved; }
- };
-
- /// Move emulation helper for ASTMultiPtr. NEVER EVER use this class
- /// directly if you don't know what you're doing.
- template <ASTDestroyer Destroyer>
- class ASTMultiMover {
- ASTMultiPtr<Destroyer> &Moved;
-
- public:
- ASTMultiMover(ASTMultiPtr<Destroyer> &moved) : Moved(moved) {}
-
- ASTMultiPtr<Destroyer> * operator ->() { return &Moved; }
-
- /// Reset the moved object's internal structures.
- void release();
- };
- }
-#else
-
- /// Kept only as a type-safe wrapper for a void pointer, when smart pointers
- /// are disabled. When they are enabled, ASTOwningResult takes over.
- template <ASTDestroyer Destroyer>
- class ASTOwningPtr {
- void *Node;
-
- public:
- explicit ASTOwningPtr(ActionBase &) : Node(0) {}
- ASTOwningPtr(ActionBase &, void *node) : Node(node) {}
- // Normal copying operators are defined implicitly.
- ASTOwningPtr(const ASTOwningResult<Destroyer> &o);
-
- ASTOwningPtr & operator =(void *raw) {
- Node = raw;
- return *this;
- }
-
- /// Access to the raw pointer.
- void * get() const { return Node; }
-
- /// Release the raw pointer.
- void * take() {
- return Node;
- }
-
- /// Take outside ownership of the raw pointer and cast it down.
- template<typename T>
- T *takeAs() {
- return static_cast<T*>(Node);
- }
-
- /// Alias for interface familiarity with unique_ptr.
- void * release() {
- return take();
- }
- };
-#endif
-
- // Important: There are two different implementations of
- // ASTOwningResult below, depending on whether
- // DISABLE_SMART_POINTERS is defined. If you make changes that
- // affect the interface, be sure to compile and test both ways!
-
-#if !defined(DISABLE_SMART_POINTERS)
- template <ASTDestroyer Destroyer>
- class ASTOwningResult {
- llvm::PointerIntPair<ActionBase*, 1, bool> ActionInv;
- void *Ptr;
-
- friend class moving::ASTResultMover<Destroyer>;
-
-#if !(defined(_MSC_VER) && _MSC_VER >= 1600)
- ASTOwningResult(ASTOwningResult&); // DO NOT IMPLEMENT
- ASTOwningResult& operator =(ASTOwningResult&); // DO NOT IMPLEMENT
-#endif
-
- void destroy() {
- if (Ptr) {
- assert(ActionInv.getPointer() &&
- "Smart pointer has node but no action.");
- (ActionInv.getPointer()->*Destroyer)(Ptr);
- Ptr = 0;
- }
- }
-
- public:
- typedef ActionBase::ActionResult<DestroyerToUID<Destroyer>::UID> DumbResult;
-
- explicit ASTOwningResult(ActionBase &actions, bool invalid = false)
- : ActionInv(&actions, invalid), Ptr(0) {}
- ASTOwningResult(ActionBase &actions, void *node)
- : ActionInv(&actions, false), Ptr(node) {}
- ASTOwningResult(ActionBase &actions, const DumbResult &res)
- : ActionInv(&actions, res.isInvalid()), Ptr(res.get()) {}
- /// Move from another owning result
- ASTOwningResult(moving::ASTResultMover<Destroyer> mover)
- : ActionInv(mover->ActionInv),
- Ptr(mover->Ptr) {
- mover->Ptr = 0;
- }
-
- ~ASTOwningResult() {
- destroy();
- }
-
- /// Move assignment from another owning result
- ASTOwningResult &operator=(moving::ASTResultMover<Destroyer> mover) {
- destroy();
- ActionInv = mover->ActionInv;
- Ptr = mover->Ptr;
- mover->Ptr = 0;
- return *this;
- }
-
-#if defined(_MSC_VER) && _MSC_VER >= 1600
- // Emulated move semantics don't work with msvc.
- ASTOwningResult(ASTOwningResult &&mover)
- : ActionInv(mover.ActionInv),
- Ptr(mover.Ptr) {
- mover.Ptr = 0;
- }
- ASTOwningResult &operator=(ASTOwningResult &&mover) {
- *this = moving::ASTResultMover<Destroyer>(mover);
- return *this;
- }
-#endif
-
- /// Assignment from a raw pointer. Takes ownership - beware!
- ASTOwningResult &operator=(void *raw) {
- destroy();
- Ptr = raw;
- ActionInv.setInt(false);
- return *this;
- }
-
- /// Assignment from an ActionResult. Takes ownership - beware!
- ASTOwningResult &operator=(const DumbResult &res) {
- destroy();
- Ptr = res.get();
- ActionInv.setInt(res.isInvalid());
- return *this;
- }
-
- /// Access to the raw pointer.
- void *get() const { return Ptr; }
-
- bool isInvalid() const { return ActionInv.getInt(); }
-
- /// Does this point to a usable AST node? To be usable, the node must be
- /// valid and non-null.
- bool isUsable() const { return !isInvalid() && get(); }
-
- /// Take outside ownership of the raw pointer.
- void *take() {
- if (isInvalid())
- return 0;
- void *tmp = Ptr;
- Ptr = 0;
- return tmp;
- }
-
- /// Take outside ownership of the raw pointer and cast it down.
- template<typename T>
- T *takeAs() {
- return static_cast<T*>(take());
- }
-
- /// Alias for interface familiarity with unique_ptr.
- void *release() { return take(); }
-
- /// Pass ownership to a classical ActionResult.
- DumbResult result() {
- if (isInvalid())
- return true;
- return take();
- }
-
- /// Move hook
- operator moving::ASTResultMover<Destroyer>() {
- return moving::ASTResultMover<Destroyer>(*this);
- }
- };
-#else
- template <ASTDestroyer Destroyer>
- class ASTOwningResult {
- public:
- typedef ActionBase::ActionResult<DestroyerToUID<Destroyer>::UID> DumbResult;
-
- private:
- DumbResult Result;
-
- public:
- explicit ASTOwningResult(ActionBase &actions, bool invalid = false)
- : Result(invalid) { }
- ASTOwningResult(ActionBase &actions, void *node) : Result(node) { }
- ASTOwningResult(ActionBase &actions, const DumbResult &res) : Result(res) { }
- // Normal copying semantics are defined implicitly.
- ASTOwningResult(const ASTOwningPtr<Destroyer> &o) : Result(o.get()) { }
-
- /// Assignment from a raw pointer. Takes ownership - beware!
- ASTOwningResult & operator =(void *raw) {
- Result = raw;
- return *this;
- }
-
- /// Assignment from an ActionResult. Takes ownership - beware!
- ASTOwningResult & operator =(const DumbResult &res) {
- Result = res;
- return *this;
- }
-
- /// Access to the raw pointer.
- void * get() const { return Result.get(); }
-
- bool isInvalid() const { return Result.isInvalid(); }
-
- /// Does this point to a usable AST node? To be usable, the node must be
- /// valid and non-null.
- bool isUsable() const { return !Result.isInvalid() && get(); }
-
- /// Take outside ownership of the raw pointer.
- void * take() {
- return Result.get();
- }
-
- /// Take outside ownership of the raw pointer and cast it down.
- template<typename T>
- T *takeAs() {
- return static_cast<T*>(take());
- }
-
- /// Alias for interface familiarity with unique_ptr.
- void * release() { return take(); }
-
- /// Pass ownership to a classical ActionResult.
- DumbResult result() { return Result; }
- };
-#endif
-
- template <ASTDestroyer Destroyer>
- class ASTMultiPtr {
-#if !defined(DISABLE_SMART_POINTERS)
- ActionBase &Actions;
-#endif
- void **Nodes;
- unsigned Count;
-
-#if !defined(DISABLE_SMART_POINTERS)
- friend class moving::ASTMultiMover<Destroyer>;
-
-#if defined(_MSC_VER)
- // Last tested with Visual Studio 2008.
- // Visual C++ appears to have a bug where it does not recognise
- // the return value from ASTMultiMover<Destroyer>::opeator-> as
- // being a pointer to ASTMultiPtr. However, the diagnostics
- // suggest it has the right name, simply that the pointer type
- // is not convertible to itself.
- // Either way, a classic C-style hard cast resolves any issue.
- static ASTMultiPtr* hack(moving::ASTMultiMover<Destroyer> & source) {
- return (ASTMultiPtr*)source.operator->();
- }
-#endif
-
- ASTMultiPtr(ASTMultiPtr&); // DO NOT IMPLEMENT
- // Reference member prevents copy assignment.
-
- void destroy() {
- assert((Count == 0 || Nodes) && "No nodes when count is not zero.");
- for (unsigned i = 0; i < Count; ++i) {
- if (Nodes[i])
- (Actions.*Destroyer)(Nodes[i]);
- }
- }
-#endif
-
- public:
-#if !defined(DISABLE_SMART_POINTERS)
- explicit ASTMultiPtr(ActionBase &actions)
- : Actions(actions), Nodes(0), Count(0) {}
- ASTMultiPtr(ActionBase &actions, void **nodes, unsigned count)
- : Actions(actions), Nodes(nodes), Count(count) {}
- /// Move constructor
- ASTMultiPtr(moving::ASTMultiMover<Destroyer> mover)
-#if defined(_MSC_VER)
- // Apply the visual C++ hack supplied above.
- // Last tested with Visual Studio 2008.
- : Actions(hack(mover)->Actions), Nodes(hack(mover)->Nodes), Count(hack(mover)->Count) {
-#else
- : Actions(mover->Actions), Nodes(mover->Nodes), Count(mover->Count) {
-#endif
- mover.release();
- }
-#else
- // Normal copying implicitly defined
- explicit ASTMultiPtr(ActionBase &) : Nodes(0), Count(0) {}
- ASTMultiPtr(ActionBase &, void **nodes, unsigned count)
- : Nodes(nodes), Count(count) {}
- // Fake mover in Parse/AstGuard.h needs this:
- ASTMultiPtr(void **nodes, unsigned count) : Nodes(nodes), Count(count) {}
-#endif
-
-#if !defined(DISABLE_SMART_POINTERS)
- /// Move assignment
- ASTMultiPtr & operator =(moving::ASTMultiMover<Destroyer> mover) {
- destroy();
- Nodes = mover->Nodes;
- Count = mover->Count;
- mover.release();
- return *this;
- }
-#endif
-
- /// Access to the raw pointers.
- void ** get() const { return Nodes; }
-
- /// Access to the count.
- unsigned size() const { return Count; }
-
- void ** release() {
-#if !defined(DISABLE_SMART_POINTERS)
- void **tmp = Nodes;
- Nodes = 0;
- Count = 0;
- return tmp;
-#else
- return Nodes;
-#endif
- }
-
-#if !defined(DISABLE_SMART_POINTERS)
- /// Move hook
- operator moving::ASTMultiMover<Destroyer>() {
- return moving::ASTMultiMover<Destroyer>(*this);
- }
-#endif
- };
-
- class ParsedTemplateArgument;
-
- class ASTTemplateArgsPtr {
-#if !defined(DISABLE_SMART_POINTERS)
- ActionBase &Actions;
-#endif
- ParsedTemplateArgument *Args;
- mutable unsigned Count;
-
-#if !defined(DISABLE_SMART_POINTERS)
- void destroy();
-#endif
-
- public:
- ASTTemplateArgsPtr(ActionBase &actions, ParsedTemplateArgument *args,
- unsigned count) :
-#if !defined(DISABLE_SMART_POINTERS)
- Actions(actions),
-#endif
- Args(args), Count(count) { }
-
- // FIXME: Lame, not-fully-type-safe emulation of 'move semantics'.
- ASTTemplateArgsPtr(ASTTemplateArgsPtr &Other) :
-#if !defined(DISABLE_SMART_POINTERS)
- Actions(Other.Actions),
-#endif
- Args(Other.Args), Count(Other.Count) {
-#if !defined(DISABLE_SMART_POINTERS)
- Other.Count = 0;
-#endif
- }
-
- // FIXME: Lame, not-fully-type-safe emulation of 'move semantics'.
- ASTTemplateArgsPtr& operator=(ASTTemplateArgsPtr &Other) {
-#if !defined(DISABLE_SMART_POINTERS)
- Actions = Other.Actions;
-#endif
- Args = Other.Args;
- Count = Other.Count;
-#if !defined(DISABLE_SMART_POINTERS)
- Other.Count = 0;
-#endif
- return *this;
- }
-
-#if !defined(DISABLE_SMART_POINTERS)
- ~ASTTemplateArgsPtr() { destroy(); }
-#endif
-
- ParsedTemplateArgument *getArgs() const { return Args; }
- unsigned size() const { return Count; }
-
- void reset(ParsedTemplateArgument *args, unsigned count) {
-#if !defined(DISABLE_SMART_POINTERS)
- destroy();
-#endif
- Args = args;
- Count = count;
- }
-
- const ParsedTemplateArgument &operator[](unsigned Arg) const;
-
- ParsedTemplateArgument *release() const {
-#if !defined(DISABLE_SMART_POINTERS)
- Count = 0;
-#endif
- return Args;
- }
- };
-
- /// \brief A small vector that owns a set of AST nodes.
- template <ASTDestroyer Destroyer, unsigned N = 8>
- class ASTOwningVector : public llvm::SmallVector<void *, N> {
-#if !defined(DISABLE_SMART_POINTERS)
- ActionBase &Actions;
- bool Owned;
-#endif
-
- ASTOwningVector(ASTOwningVector &); // do not implement
- ASTOwningVector &operator=(ASTOwningVector &); // do not implement
-
- public:
- explicit ASTOwningVector(ActionBase &Actions)
-#if !defined(DISABLE_SMART_POINTERS)
- : Actions(Actions), Owned(true)
-#endif
- { }
-
-#if !defined(DISABLE_SMART_POINTERS)
- ~ASTOwningVector() {
- if (!Owned)
- return;
-
- for (unsigned I = 0, Last = this->size(); I != Last; ++I)
- (Actions.*Destroyer)((*this)[I]);
- }
-#endif
-
- void **take() {
-#if !defined(DISABLE_SMART_POINTERS)
- Owned = false;
-#endif
- return &this->front();
- }
-
- template<typename T> T **takeAs() { return (T**)take(); }
-
-#if !defined(DISABLE_SMART_POINTERS)
- ActionBase &getActions() const { return Actions; }
-#endif
- };
-
- /// A SmallVector of statements, with stack size 32 (as that is the only one
- /// used.)
- typedef ASTOwningVector<&ActionBase::DeleteStmt, 32> StmtVector;
- /// A SmallVector of expressions, with stack size 12 (the maximum used.)
- typedef ASTOwningVector<&ActionBase::DeleteExpr, 12> ExprVector;
-
- template <ASTDestroyer Destroyer, unsigned N> inline
- ASTMultiPtr<Destroyer> move_arg(ASTOwningVector<Destroyer, N> &vec) {
-#if !defined(DISABLE_SMART_POINTERS)
- return ASTMultiPtr<Destroyer>(vec.getActions(), vec.take(), vec.size());
-#else
- return ASTMultiPtr<Destroyer>(vec.take(), vec.size());
-#endif
- }
-
-#if !defined(DISABLE_SMART_POINTERS)
-
- // Out-of-line implementations due to definition dependencies
-
- template <ASTDestroyer Destroyer> inline
- void moving::ASTMultiMover<Destroyer>::release() {
- Moved.Nodes = 0;
- Moved.Count = 0;
- }
-
- // Move overloads.
-
- template <ASTDestroyer Destroyer> inline
- ASTOwningResult<Destroyer> move(ASTOwningResult<Destroyer> &ptr) {
- return ASTOwningResult<Destroyer>(moving::ASTResultMover<Destroyer>(ptr));
- }
-
- template <ASTDestroyer Destroyer> inline
- ASTMultiPtr<Destroyer> move(ASTMultiPtr<Destroyer> &ptr) {
- return ASTMultiPtr<Destroyer>(moving::ASTMultiMover<Destroyer>(ptr));
- }
-
-#else
-
- template <ASTDestroyer Destroyer> inline
- ASTOwningPtr<Destroyer>::ASTOwningPtr(const ASTOwningResult<Destroyer> &o)
- : Node(o.get()) { }
-
- // These versions are hopefully no-ops.
- template <ASTDestroyer Destroyer> inline
- ASTOwningResult<Destroyer>& move(ASTOwningResult<Destroyer> &ptr) {
- return ptr;
- }
-
- template <ASTDestroyer Destroyer> inline
- ASTOwningPtr<Destroyer>& move(ASTOwningPtr<Destroyer> &ptr) {
- return ptr;
- }
-
- template <ASTDestroyer Destroyer> inline
- ASTMultiPtr<Destroyer>& move(ASTMultiPtr<Destroyer> &ptr) {
- return ptr;
- }
-#endif
-}
-
-#endif
diff --git a/include/clang/Sema/ParseAST.h b/include/clang/Parse/ParseAST.h
index f6cff2a023e6..0d37e21becd3 100644
--- a/include/clang/Sema/ParseAST.h
+++ b/include/clang/Parse/ParseAST.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SEMA_PARSEAST_H
-#define LLVM_CLANG_SEMA_PARSEAST_H
+#ifndef LLVM_CLANG_PARSE_PARSEAST_H
+#define LLVM_CLANG_PARSE_PARSEAST_H
namespace clang {
class Preprocessor;
@@ -38,6 +38,10 @@ namespace clang {
bool CompleteTranslationUnit = true,
CodeCompleteConsumer *CompletionConsumer = 0);
+ /// \brief Parse the main file known to the preprocessor, producing an
+ /// abstract syntax tree.
+ void ParseAST(Sema &S, bool PrintStats = false);
+
} // end namespace clang
#endif
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index b8c294ada691..41a2fb615791 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -16,8 +16,10 @@
#include "clang/Basic/Specifiers.h"
#include "clang/Lex/Preprocessor.h"
-#include "clang/Parse/Action.h"
-#include "clang/Parse/DeclSpec.h"
+#include "clang/Lex/CodeCompletionHandler.h"
+#include "clang/Sema/Sema.h"
+#include "clang/Sema/DeclSpec.h"
+#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/ADT/OwningPtr.h"
#include <stack>
#include <list>
@@ -27,6 +29,7 @@ namespace clang {
struct CXX0XAttributeList;
class PragmaHandler;
class Scope;
+ class DeclGroupRef;
class DiagnosticBuilder;
class Parser;
class PragmaUnusedHandler;
@@ -69,7 +72,7 @@ namespace prec {
/// parsing units of the grammar, productions are invoked to handle whatever has
/// been read.
///
-class Parser {
+class Parser : public CodeCompletionHandler {
friend class PragmaUnusedHandler;
friend class ColonProtectionRAIIObject;
friend class ParenBraceBracketBalancer;
@@ -90,9 +93,8 @@ class Parser {
unsigned short ParenCount, BracketCount, BraceCount;
/// Actions - These are the callbacks we invoke as we parse various constructs
- /// in the file. This refers to the common base class between MinimalActions
- /// and SemaActions for those uses that don't matter.
- Action &Actions;
+ /// in the file.
+ Sema &Actions;
Diagnostic &Diags;
@@ -110,6 +112,8 @@ class Parser {
IdentifierInfo *Ident_vector;
IdentifierInfo *Ident_pixel;
+ llvm::OwningPtr<PragmaHandler> AlignHandler;
+ llvm::OwningPtr<PragmaHandler> GCCVisibilityHandler;
llvm::OwningPtr<PragmaHandler> OptionsHandler;
llvm::OwningPtr<PragmaHandler> PackHandler;
llvm::OwningPtr<PragmaHandler> UnusedHandler;
@@ -131,61 +135,56 @@ class Parser {
unsigned TemplateParameterDepth;
public:
- Parser(Preprocessor &PP, Action &Actions);
+ Parser(Preprocessor &PP, Sema &Actions);
~Parser();
const LangOptions &getLang() const { return PP.getLangOptions(); }
const TargetInfo &getTargetInfo() const { return PP.getTargetInfo(); }
Preprocessor &getPreprocessor() const { return PP; }
- Action &getActions() const { return Actions; }
+ Sema &getActions() const { return Actions; }
const Token &getCurToken() const { return Tok; }
Scope *getCurScope() const { return Actions.getCurScope(); }
// Type forwarding. All of these are statically 'void*', but they may all be
// different actual classes based on the actions in place.
- typedef Action::ExprTy ExprTy;
- typedef Action::StmtTy StmtTy;
- typedef Action::DeclPtrTy DeclPtrTy;
- typedef Action::DeclGroupPtrTy DeclGroupPtrTy;
- typedef Action::TypeTy TypeTy;
- typedef Action::BaseTy BaseTy;
- typedef Action::MemInitTy MemInitTy;
- typedef Action::CXXScopeTy CXXScopeTy;
- typedef Action::TemplateParamsTy TemplateParamsTy;
- typedef Action::TemplateTy TemplateTy;
-
- typedef llvm::SmallVector<TemplateParamsTy *, 4> TemplateParameterLists;
-
- typedef Action::ExprResult ExprResult;
- typedef Action::StmtResult StmtResult;
- typedef Action::BaseResult BaseResult;
- typedef Action::MemInitResult MemInitResult;
- typedef Action::TypeResult TypeResult;
-
- typedef Action::OwningExprResult OwningExprResult;
- typedef Action::OwningStmtResult OwningStmtResult;
-
- typedef Action::ExprArg ExprArg;
- typedef Action::MultiStmtArg MultiStmtArg;
- typedef Action::FullExprArg FullExprArg;
-
- /// Adorns a ExprResult with Actions to make it an OwningExprResult
- OwningExprResult Owned(ExprResult res) {
- return OwningExprResult(Actions, res);
+ typedef Expr ExprTy;
+ typedef Stmt StmtTy;
+ typedef OpaquePtr<DeclGroupRef> DeclGroupPtrTy;
+ typedef CXXBaseSpecifier BaseTy;
+ typedef CXXBaseOrMemberInitializer MemInitTy;
+ typedef NestedNameSpecifier CXXScopeTy;
+ typedef TemplateParameterList TemplateParamsTy;
+ typedef OpaquePtr<TemplateName> TemplateTy;
+
+ typedef llvm::SmallVector<TemplateParameterList *, 4> TemplateParameterLists;
+
+ typedef clang::ExprResult ExprResult;
+ typedef clang::StmtResult StmtResult;
+ typedef clang::BaseResult BaseResult;
+ typedef clang::MemInitResult MemInitResult;
+ typedef clang::TypeResult TypeResult;
+
+ typedef Expr *ExprArg;
+ typedef ASTMultiPtr<Stmt*> MultiStmtArg;
+ typedef Sema::FullExprArg FullExprArg;
+
+ /// Adorns a ExprResult with Actions to make it an ExprResult
+ ExprResult Owned(ExprResult res) {
+ return ExprResult(res);
}
- /// Adorns a StmtResult with Actions to make it an OwningStmtResult
- OwningStmtResult Owned(StmtResult res) {
- return OwningStmtResult(Actions, res);
+ /// Adorns a StmtResult with Actions to make it an StmtResult
+ StmtResult Owned(StmtResult res) {
+ return StmtResult(res);
}
- OwningExprResult ExprError() { return OwningExprResult(Actions, true); }
- OwningStmtResult StmtError() { return OwningStmtResult(Actions, true); }
+ ExprResult ExprError() { return ExprResult(true); }
+ StmtResult StmtError() { return StmtResult(true); }
- OwningExprResult ExprError(const DiagnosticBuilder &) { return ExprError(); }
- OwningStmtResult StmtError(const DiagnosticBuilder &) { return StmtError(); }
+ ExprResult ExprError(const DiagnosticBuilder &) { return ExprError(); }
+ StmtResult StmtError(const DiagnosticBuilder &) { return StmtError(); }
- OwningExprResult ExprEmpty() { return OwningExprResult(Actions, false); }
+ ExprResult ExprEmpty() { return ExprResult(false); }
// Parsing methods.
@@ -201,7 +200,7 @@ public:
/// the EOF was encountered.
bool ParseTopLevelDecl(DeclGroupPtrTy &Result);
- DeclGroupPtrTy RetrievePendingObjCImpDecl();
+ DeclGroupPtrTy FinishPendingObjCActions();
private:
//===--------------------------------------------------------------------===//
@@ -349,6 +348,15 @@ private:
return PP.LookAhead(0);
}
+ /// getTypeAnnotation - Read a parsed type out of an annotation token.
+ static ParsedType getTypeAnnotation(Token &Tok) {
+ return ParsedType::getFromOpaquePtr(Tok.getAnnotationValue());
+ }
+
+ static void setTypeAnnotation(Token &Tok, ParsedType T) {
+ Tok.setAnnotationValue(T.getAsOpaquePtr());
+ }
+
/// TryAnnotateTypeOrScopeToken - If the current token position is on a
/// typename (possibly qualified in C++) or a C++ scope specifier not followed
/// by a typename, TryAnnotateTypeOrScopeToken will replace one or more tokens
@@ -538,7 +546,7 @@ private:
// Lexing and parsing of C++ inline methods.
struct LexedMethod {
- Action::DeclPtrTy D;
+ Decl *D;
CachedTokens Toks;
/// \brief Whether this member function had an associated template
@@ -546,7 +554,7 @@ private:
/// othewise, it is a member function declaration.
bool TemplateScope;
- explicit LexedMethod(Action::DeclPtrTy MD) : D(MD), TemplateScope(false) {}
+ explicit LexedMethod(Decl *MD) : D(MD), TemplateScope(false) {}
};
/// LateParsedDefaultArgument - Keeps track of a parameter that may
@@ -554,12 +562,12 @@ private:
/// occurs within a member function declaration inside the class
/// (C++ [class.mem]p2).
struct LateParsedDefaultArgument {
- explicit LateParsedDefaultArgument(Action::DeclPtrTy P,
+ explicit LateParsedDefaultArgument(Decl *P,
CachedTokens *Toks = 0)
: Param(P), Toks(Toks) { }
/// Param - The parameter declaration for this parameter.
- Action::DeclPtrTy Param;
+ Decl *Param;
/// Toks - The sequence of tokens that comprises the default
/// argument expression, not including the '=' or the terminating
@@ -573,11 +581,11 @@ private:
/// until the class itself is completely-defined, such as a default
/// argument (C++ [class.mem]p2).
struct LateParsedMethodDeclaration {
- explicit LateParsedMethodDeclaration(Action::DeclPtrTy M)
+ explicit LateParsedMethodDeclaration(Decl *M)
: Method(M), TemplateScope(false) { }
/// Method - The method declaration.
- Action::DeclPtrTy Method;
+ Decl *Method;
/// \brief Whether this member function had an associated template
/// scope. When true, D is a template declaration.
@@ -608,7 +616,7 @@ private:
/// any member function declarations or definitions that need to be
/// parsed after the corresponding top-level class is complete.
struct ParsingClass {
- ParsingClass(DeclPtrTy TagOrTemplate, bool TopLevelClass)
+ ParsingClass(Decl *TagOrTemplate, bool TopLevelClass)
: TopLevelClass(TopLevelClass), TemplateScope(false),
TagOrTemplate(TagOrTemplate) { }
@@ -622,7 +630,7 @@ private:
bool TemplateScope : 1;
/// \brief The class or class template whose definition we are parsing.
- DeclPtrTy TagOrTemplate;
+ Decl *TagOrTemplate;
/// MethodDecls - Method declarations that contain pieces whose
/// parsing will be delayed until the class is fully defined.
@@ -651,15 +659,28 @@ private:
/// variable's initializer, but not when parsing the body of a
/// class or function definition.
class ParsingDeclRAIIObject {
- Action &Actions;
- Action::ParsingDeclStackState State;
+ Sema &Actions;
+ Sema::ParsingDeclStackState State;
bool Popped;
-
+
public:
ParsingDeclRAIIObject(Parser &P) : Actions(P.Actions) {
push();
}
+ ParsingDeclRAIIObject(Parser &P, ParsingDeclRAIIObject *Other)
+ : Actions(P.Actions) {
+ if (Other) steal(*Other);
+ else push();
+ }
+
+ /// Creates a RAII object which steals the state from a different
+ /// object instead of pushing.
+ ParsingDeclRAIIObject(ParsingDeclRAIIObject &Other)
+ : Actions(Other.Actions) {
+ steal(Other);
+ }
+
~ParsingDeclRAIIObject() {
abort();
}
@@ -673,21 +694,27 @@ private:
/// Signals that the context was completed without an appropriate
/// declaration being parsed.
void abort() {
- pop(DeclPtrTy());
+ pop(0);
}
- void complete(DeclPtrTy D) {
+ void complete(Decl *D) {
assert(!Popped && "ParsingDeclaration has already been popped!");
pop(D);
}
private:
+ void steal(ParsingDeclRAIIObject &Other) {
+ State = Other.State;
+ Popped = Other.Popped;
+ Other.Popped = true;
+ }
+
void push() {
State = Actions.PushParsingDeclaration();
Popped = false;
}
- void pop(DeclPtrTy D) {
+ void pop(Decl *D) {
if (!Popped) {
Actions.PopParsingDeclaration(State, D);
Popped = true;
@@ -700,10 +727,12 @@ private:
ParsingDeclRAIIObject ParsingRAII;
public:
- ParsingDeclSpec(Parser &P) : ParsingRAII(P) {
- }
+ ParsingDeclSpec(Parser &P) : ParsingRAII(P) {}
+ ParsingDeclSpec(ParsingDeclRAIIObject &RAII) : ParsingRAII(RAII) {}
+ ParsingDeclSpec(Parser &P, ParsingDeclRAIIObject *RAII)
+ : ParsingRAII(P, RAII) {}
- void complete(DeclPtrTy D) {
+ void complete(Decl *D) {
ParsingRAII.complete(D);
}
@@ -734,7 +763,7 @@ private:
ParsingRAII.reset();
}
- void complete(DeclPtrTy D) {
+ void complete(Decl *D) {
ParsingRAII.complete(D);
}
};
@@ -745,7 +774,7 @@ private:
bool Popped;
public:
- ParsingClassDefinition(Parser &P, DeclPtrTy TagOrTemplate, bool TopLevelClass)
+ ParsingClassDefinition(Parser &P, Decl *TagOrTemplate, bool TopLevelClass)
: P(P), Popped(false) {
P.PushParsingClass(TagOrTemplate, TopLevelClass);
}
@@ -811,12 +840,12 @@ private:
bool LastParameterListWasEmpty;
};
- void PushParsingClass(DeclPtrTy TagOrTemplate, bool TopLevelClass);
+ void PushParsingClass(Decl *TagOrTemplate, bool TopLevelClass);
void DeallocateParsedClasses(ParsingClass *Class);
void PopParsingClass();
- DeclPtrTy ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D,
- const ParsedTemplateInfo &TemplateInfo);
+ Decl *ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D,
+ const ParsedTemplateInfo &TemplateInfo);
void ParseLexedMethodDeclarations(ParsingClass &Class);
void ParseLexedMethodDefs(ParsingClass &Class);
bool ConsumeAndStoreUntil(tok::TokenKind T1,
@@ -832,7 +861,8 @@ private:
//===--------------------------------------------------------------------===//
// C99 6.9: External Definitions.
- DeclGroupPtrTy ParseExternalDeclaration(CXX0XAttributeList Attr);
+ DeclGroupPtrTy ParseExternalDeclaration(CXX0XAttributeList Attr,
+ ParsingDeclSpec *DS = 0);
bool isDeclarationAfterDeclarator() const;
bool isStartOfFunctionDefinition(const ParsingDeclarator &Declarator);
DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(AttributeList *Attr,
@@ -841,40 +871,40 @@ private:
AttributeList *Attr,
AccessSpecifier AS = AS_none);
- DeclPtrTy ParseFunctionDefinition(ParsingDeclarator &D,
+ Decl *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
// the simple-asm.
- OwningExprResult ParseSimpleAsm(SourceLocation *EndLoc = 0);
- OwningExprResult ParseAsmStringLiteral();
+ ExprResult ParseSimpleAsm(SourceLocation *EndLoc = 0);
+ ExprResult ParseAsmStringLiteral();
// Objective-C External Declarations
- DeclPtrTy ParseObjCAtDirectives();
- DeclPtrTy ParseObjCAtClassDeclaration(SourceLocation atLoc);
- DeclPtrTy ParseObjCAtInterfaceDeclaration(SourceLocation atLoc,
+ Decl *ParseObjCAtDirectives();
+ Decl *ParseObjCAtClassDeclaration(SourceLocation atLoc);
+ Decl *ParseObjCAtInterfaceDeclaration(SourceLocation atLoc,
AttributeList *prefixAttrs = 0);
- void ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl,
+ void ParseObjCClassInstanceVariables(Decl *interfaceDecl,
tok::ObjCKeywordKind visibility,
SourceLocation atLoc);
- bool ParseObjCProtocolReferences(llvm::SmallVectorImpl<Action::DeclPtrTy> &P,
+ bool ParseObjCProtocolReferences(llvm::SmallVectorImpl<Decl *> &P,
llvm::SmallVectorImpl<SourceLocation> &PLocs,
bool WarnOnDeclarations,
SourceLocation &LAngleLoc,
SourceLocation &EndProtoLoc);
- void ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl,
+ void ParseObjCInterfaceDeclList(Decl *interfaceDecl,
tok::ObjCKeywordKind contextKey);
- DeclPtrTy ParseObjCAtProtocolDeclaration(SourceLocation atLoc,
+ Decl *ParseObjCAtProtocolDeclaration(SourceLocation atLoc,
AttributeList *prefixAttrs = 0);
- DeclPtrTy ObjCImpDecl;
- llvm::SmallVector<DeclPtrTy, 4> PendingObjCImpDecl;
+ Decl *ObjCImpDecl;
+ llvm::SmallVector<Decl *, 4> PendingObjCImpDecl;
- DeclPtrTy ParseObjCAtImplementationDeclaration(SourceLocation atLoc);
- DeclPtrTy ParseObjCAtEndDeclaration(SourceRange atEnd);
- DeclPtrTy ParseObjCAtAliasDeclaration(SourceLocation atLoc);
- DeclPtrTy ParseObjCPropertySynthesize(SourceLocation atLoc);
- DeclPtrTy ParseObjCPropertyDynamic(SourceLocation atLoc);
+ Decl *ParseObjCAtImplementationDeclaration(SourceLocation atLoc);
+ Decl *ParseObjCAtEndDeclaration(SourceRange atEnd);
+ Decl *ParseObjCAtAliasDeclaration(SourceLocation atLoc);
+ Decl *ParseObjCPropertySynthesize(SourceLocation atLoc);
+ Decl *ParseObjCPropertyDynamic(SourceLocation atLoc);
IdentifierInfo *ParseObjCSelectorPiece(SourceLocation &MethodLocation);
// Definitions for Objective-c context sensitive keywords recognition.
@@ -886,58 +916,69 @@ private:
bool isTokIdentifier_in() const;
- TypeTy *ParseObjCTypeName(ObjCDeclSpec &DS);
+ ParsedType ParseObjCTypeName(ObjCDeclSpec &DS, bool IsParameter);
void ParseObjCMethodRequirement();
- DeclPtrTy ParseObjCMethodPrototype(DeclPtrTy classOrCat,
+ Decl *ParseObjCMethodPrototype(Decl *classOrCat,
tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword);
- DeclPtrTy ParseObjCMethodDecl(SourceLocation mLoc, tok::TokenKind mType,
- DeclPtrTy classDecl,
+ Decl *ParseObjCMethodDecl(SourceLocation mLoc, tok::TokenKind mType,
+ Decl *classDecl,
tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword);
- void ParseObjCPropertyAttribute(ObjCDeclSpec &DS, DeclPtrTy ClassDecl,
- DeclPtrTy *Methods, unsigned NumMethods);
+ void ParseObjCPropertyAttribute(ObjCDeclSpec &DS, Decl *ClassDecl,
+ Decl **Methods, unsigned NumMethods);
- DeclPtrTy ParseObjCMethodDefinition();
+ Decl *ParseObjCMethodDefinition();
//===--------------------------------------------------------------------===//
// C99 6.5: Expressions.
- OwningExprResult ParseExpression();
- OwningExprResult ParseConstantExpression();
+ ExprResult ParseExpression();
+ ExprResult ParseConstantExpression();
// Expr that doesn't include commas.
- OwningExprResult ParseAssignmentExpression();
+ ExprResult ParseAssignmentExpression();
- OwningExprResult ParseExpressionWithLeadingAt(SourceLocation AtLoc);
+ ExprResult ParseExpressionWithLeadingAt(SourceLocation AtLoc);
- OwningExprResult ParseExpressionWithLeadingExtension(SourceLocation ExtLoc);
+ ExprResult ParseExpressionWithLeadingExtension(SourceLocation ExtLoc);
- OwningExprResult ParseRHSOfBinaryExpression(OwningExprResult LHS,
+ ExprResult ParseRHSOfBinaryExpression(ExprResult LHS,
prec::Level MinPrec);
- OwningExprResult ParseCastExpression(bool isUnaryExpression,
+ ExprResult ParseCastExpression(bool isUnaryExpression,
bool isAddressOfOperand,
bool &NotCastExpr,
- TypeTy *TypeOfCast);
- OwningExprResult ParseCastExpression(bool isUnaryExpression,
+ ParsedType TypeOfCast);
+ ExprResult ParseCastExpression(bool isUnaryExpression,
bool isAddressOfOperand = false,
- TypeTy *TypeOfCast = 0);
- OwningExprResult ParsePostfixExpressionSuffix(OwningExprResult LHS);
- OwningExprResult ParseSizeofAlignofExpression();
- OwningExprResult ParseBuiltinPrimaryExpression();
+ ParsedType TypeOfCast = ParsedType());
+
+ /// Returns true if the next token would start a postfix-expression
+ /// suffix.
+ bool isPostfixExpressionSuffixStart() {
+ tok::TokenKind K = Tok.getKind();
+ return (K == tok::l_square || K == tok::l_paren ||
+ K == tok::period || K == tok::arrow ||
+ K == tok::plusplus || K == tok::minusminus);
+ }
- OwningExprResult ParseExprAfterTypeofSizeofAlignof(const Token &OpTok,
+ ExprResult ParsePostfixExpressionSuffix(ExprResult LHS);
+ ExprResult ParseSizeofAlignofExpression();
+ ExprResult ParseBuiltinPrimaryExpression();
+
+ ExprResult ParseExprAfterTypeofSizeofAlignof(const Token &OpTok,
bool &isCastExpr,
- TypeTy *&CastTy,
+ ParsedType &CastTy,
SourceRange &CastRange);
- static const unsigned ExprListSize = 12;
- typedef llvm::SmallVector<ExprTy*, ExprListSize> ExprListTy;
- typedef llvm::SmallVector<SourceLocation, ExprListSize> CommaLocsTy;
+ typedef llvm::SmallVector<Expr*, 20> ExprListTy;
+ typedef llvm::SmallVector<SourceLocation, 20> CommaLocsTy;
/// ParseExpressionList - Used for C/C++ (argument-)expression-list.
- bool ParseExpressionList(ExprListTy &Exprs, CommaLocsTy &CommaLocs,
- void (Action::*Completer)(Scope *S, void *Data,
- ExprTy **Args,
- unsigned NumArgs) = 0,
- void *Data = 0);
+ bool ParseExpressionList(llvm::SmallVectorImpl<Expr*> &Exprs,
+ llvm::SmallVectorImpl<SourceLocation> &CommaLocs,
+ void (Sema::*Completer)(Scope *S,
+ Expr *Data,
+ Expr **Args,
+ unsigned NumArgs) = 0,
+ Expr *Data = 0);
/// ParenParseOption - Control what ParseParenExpression will parse.
enum ParenParseOption {
@@ -946,67 +987,67 @@ private:
CompoundLiteral, // Also allow '(' type-name ')' '{' ... '}'
CastExpr // Also allow '(' type-name ')' <anything>
};
- OwningExprResult ParseParenExpression(ParenParseOption &ExprType,
+ ExprResult ParseParenExpression(ParenParseOption &ExprType,
bool stopIfCastExpr,
- TypeTy *TypeOfCast,
- TypeTy *&CastTy,
+ ParsedType TypeOfCast,
+ ParsedType &CastTy,
SourceLocation &RParenLoc);
- OwningExprResult ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
- TypeTy *&CastTy,
+ ExprResult ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
+ ParsedType &CastTy,
SourceLocation LParenLoc,
SourceLocation &RParenLoc);
- OwningExprResult ParseCompoundLiteralExpression(TypeTy *Ty,
+ ExprResult ParseCompoundLiteralExpression(ParsedType Ty,
SourceLocation LParenLoc,
SourceLocation RParenLoc);
- OwningExprResult ParseStringLiteralExpression();
+ ExprResult ParseStringLiteralExpression();
//===--------------------------------------------------------------------===//
// C++ Expressions
- OwningExprResult ParseCXXIdExpression(bool isAddressOfOperand = false);
+ ExprResult ParseCXXIdExpression(bool isAddressOfOperand = false);
bool ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
- TypeTy *ObjectType,
+ ParsedType ObjectType,
bool EnteringContext,
bool *MayBePseudoDestructor = 0);
//===--------------------------------------------------------------------===//
// C++ 5.2p1: C++ Casts
- OwningExprResult ParseCXXCasts();
+ ExprResult ParseCXXCasts();
//===--------------------------------------------------------------------===//
// C++ 5.2p1: C++ Type Identification
- OwningExprResult ParseCXXTypeid();
+ ExprResult ParseCXXTypeid();
//===--------------------------------------------------------------------===//
// C++ 5.2.4: C++ Pseudo-Destructor Expressions
- OwningExprResult ParseCXXPseudoDestructor(ExprArg Base, SourceLocation OpLoc,
+ ExprResult ParseCXXPseudoDestructor(ExprArg Base, SourceLocation OpLoc,
tok::TokenKind OpKind,
CXXScopeSpec &SS,
- Action::TypeTy *ObjectType);
+ ParsedType ObjectType);
//===--------------------------------------------------------------------===//
// C++ 9.3.2: C++ 'this' pointer
- OwningExprResult ParseCXXThis();
+ ExprResult ParseCXXThis();
//===--------------------------------------------------------------------===//
// C++ 15: C++ Throw Expression
- OwningExprResult ParseThrowExpression();
+ ExprResult ParseThrowExpression();
// EndLoc is filled with the location of the last token of the specification.
bool ParseExceptionSpecification(SourceLocation &EndLoc,
- llvm::SmallVector<TypeTy*, 2> &Exceptions,
- llvm::SmallVector<SourceRange, 2> &Ranges,
+ llvm::SmallVectorImpl<ParsedType> &Exns,
+ llvm::SmallVectorImpl<SourceRange> &Ranges,
bool &hasAnyExceptionSpec);
//===--------------------------------------------------------------------===//
// C++ 2.13.5: C++ Boolean Literals
- OwningExprResult ParseCXXBoolLiteral();
+ ExprResult ParseCXXBoolLiteral();
//===--------------------------------------------------------------------===//
// C++ 5.2.3: Explicit type conversion (functional notation)
- OwningExprResult ParseCXXTypeConstructExpression(const DeclSpec &DS);
+ ExprResult ParseCXXTypeConstructExpression(const DeclSpec &DS);
bool isCXXSimpleTypeSpecifier() const;
@@ -1019,15 +1060,16 @@ private:
//===--------------------------------------------------------------------===//
// C++ 5.3.4 and 5.3.5: C++ new and delete
- bool ParseExpressionListOrTypeId(ExprListTy &Exprs, Declarator &D);
+ bool ParseExpressionListOrTypeId(llvm::SmallVectorImpl<Expr*> &Exprs,
+ Declarator &D);
void ParseDirectNewDeclarator(Declarator &D);
- OwningExprResult ParseCXXNewExpression(bool UseGlobal, SourceLocation Start);
- OwningExprResult ParseCXXDeleteExpression(bool UseGlobal,
+ ExprResult ParseCXXNewExpression(bool UseGlobal, SourceLocation Start);
+ ExprResult ParseCXXDeleteExpression(bool UseGlobal,
SourceLocation Start);
//===--------------------------------------------------------------------===//
// C++ if/switch/while condition expression.
- bool ParseCXXCondition(OwningExprResult &ExprResult, DeclPtrTy &DeclResult,
+ bool ParseCXXCondition(ExprResult &ExprResult, Decl *&DeclResult,
SourceLocation Loc, bool ConvertToBoolean);
//===--------------------------------------------------------------------===//
@@ -1040,65 +1082,65 @@ private:
/// initializer: [C99 6.7.8]
/// assignment-expression
/// '{' ...
- OwningExprResult ParseInitializer() {
+ ExprResult ParseInitializer() {
if (Tok.isNot(tok::l_brace))
return ParseAssignmentExpression();
return ParseBraceInitializer();
}
- OwningExprResult ParseBraceInitializer();
- OwningExprResult ParseInitializerWithPotentialDesignator();
+ ExprResult ParseBraceInitializer();
+ ExprResult ParseInitializerWithPotentialDesignator();
//===--------------------------------------------------------------------===//
// clang Expressions
- OwningExprResult ParseBlockLiteralExpression(); // ^{...}
+ ExprResult ParseBlockLiteralExpression(); // ^{...}
//===--------------------------------------------------------------------===//
// Objective-C Expressions
- OwningExprResult ParseObjCAtExpression(SourceLocation AtLocation);
- OwningExprResult ParseObjCStringLiteral(SourceLocation AtLoc);
- OwningExprResult ParseObjCEncodeExpression(SourceLocation AtLoc);
- OwningExprResult ParseObjCSelectorExpression(SourceLocation AtLoc);
- OwningExprResult ParseObjCProtocolExpression(SourceLocation AtLoc);
+ ExprResult ParseObjCAtExpression(SourceLocation AtLocation);
+ ExprResult ParseObjCStringLiteral(SourceLocation AtLoc);
+ ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc);
+ ExprResult ParseObjCSelectorExpression(SourceLocation AtLoc);
+ ExprResult ParseObjCProtocolExpression(SourceLocation AtLoc);
bool isSimpleObjCMessageExpression();
- OwningExprResult ParseObjCMessageExpression();
- OwningExprResult ParseObjCMessageExpressionBody(SourceLocation LBracloc,
+ ExprResult ParseObjCMessageExpression();
+ ExprResult ParseObjCMessageExpressionBody(SourceLocation LBracloc,
SourceLocation SuperLoc,
- TypeTy *ReceiverType,
+ ParsedType ReceiverType,
ExprArg ReceiverExpr);
- OwningExprResult ParseAssignmentExprWithObjCMessageExprStart(
+ ExprResult ParseAssignmentExprWithObjCMessageExprStart(
SourceLocation LBracloc, SourceLocation SuperLoc,
- TypeTy *ReceiverType, ExprArg ReceiverExpr);
+ ParsedType ReceiverType, ExprArg ReceiverExpr);
bool ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr);
//===--------------------------------------------------------------------===//
// C99 6.8: Statements and Blocks.
- OwningStmtResult ParseStatement() {
+ StmtResult ParseStatement() {
return ParseStatementOrDeclaration(true);
}
- OwningStmtResult ParseStatementOrDeclaration(bool OnlyStatement = false);
- OwningStmtResult ParseLabeledStatement(AttributeList *Attr);
- OwningStmtResult ParseCaseStatement(AttributeList *Attr);
- OwningStmtResult ParseDefaultStatement(AttributeList *Attr);
- OwningStmtResult ParseCompoundStatement(AttributeList *Attr,
+ StmtResult ParseStatementOrDeclaration(bool OnlyStatement = false);
+ StmtResult ParseLabeledStatement(AttributeList *Attr);
+ StmtResult ParseCaseStatement(AttributeList *Attr);
+ StmtResult ParseDefaultStatement(AttributeList *Attr);
+ StmtResult ParseCompoundStatement(AttributeList *Attr,
bool isStmtExpr = false);
- OwningStmtResult ParseCompoundStatementBody(bool isStmtExpr = false);
- bool ParseParenExprOrCondition(OwningExprResult &ExprResult,
- DeclPtrTy &DeclResult,
+ StmtResult ParseCompoundStatementBody(bool isStmtExpr = false);
+ bool ParseParenExprOrCondition(ExprResult &ExprResult,
+ Decl *&DeclResult,
SourceLocation Loc,
bool ConvertToBoolean);
- OwningStmtResult ParseIfStatement(AttributeList *Attr);
- OwningStmtResult ParseSwitchStatement(AttributeList *Attr);
- OwningStmtResult ParseWhileStatement(AttributeList *Attr);
- OwningStmtResult ParseDoStatement(AttributeList *Attr);
- OwningStmtResult ParseForStatement(AttributeList *Attr);
- OwningStmtResult ParseGotoStatement(AttributeList *Attr);
- OwningStmtResult ParseContinueStatement(AttributeList *Attr);
- OwningStmtResult ParseBreakStatement(AttributeList *Attr);
- OwningStmtResult ParseReturnStatement(AttributeList *Attr);
- OwningStmtResult ParseAsmStatement(bool &msAsm);
- OwningStmtResult FuzzyParseMicrosoftAsmStatement();
+ StmtResult ParseIfStatement(AttributeList *Attr);
+ StmtResult ParseSwitchStatement(AttributeList *Attr);
+ StmtResult ParseWhileStatement(AttributeList *Attr);
+ StmtResult ParseDoStatement(AttributeList *Attr);
+ StmtResult ParseForStatement(AttributeList *Attr);
+ StmtResult ParseGotoStatement(AttributeList *Attr);
+ StmtResult ParseContinueStatement(AttributeList *Attr);
+ StmtResult ParseBreakStatement(AttributeList *Attr);
+ StmtResult ParseReturnStatement(AttributeList *Attr);
+ StmtResult ParseAsmStatement(bool &msAsm);
+ StmtResult FuzzyParseMicrosoftAsmStatement();
bool ParseAsmOperandsOpt(llvm::SmallVectorImpl<IdentifierInfo *> &Names,
llvm::SmallVectorImpl<ExprTy *> &Constraints,
llvm::SmallVectorImpl<ExprTy *> &Exprs);
@@ -1106,17 +1148,17 @@ private:
//===--------------------------------------------------------------------===//
// C++ 6: Statements and Blocks
- OwningStmtResult ParseCXXTryBlock(AttributeList *Attr);
- OwningStmtResult ParseCXXTryBlockCommon(SourceLocation TryLoc);
- OwningStmtResult ParseCXXCatchBlock();
+ StmtResult ParseCXXTryBlock(AttributeList *Attr);
+ StmtResult ParseCXXTryBlockCommon(SourceLocation TryLoc);
+ StmtResult ParseCXXCatchBlock();
//===--------------------------------------------------------------------===//
// Objective-C Statements
- OwningStmtResult ParseObjCAtStatement(SourceLocation atLoc);
- OwningStmtResult ParseObjCTryStmt(SourceLocation atLoc);
- OwningStmtResult ParseObjCThrowStmt(SourceLocation atLoc);
- OwningStmtResult ParseObjCSynchronizedStmt(SourceLocation atLoc);
+ StmtResult ParseObjCAtStatement(SourceLocation atLoc);
+ StmtResult ParseObjCTryStmt(SourceLocation atLoc);
+ StmtResult ParseObjCThrowStmt(SourceLocation atLoc);
+ StmtResult ParseObjCSynchronizedStmt(SourceLocation atLoc);
//===--------------------------------------------------------------------===//
@@ -1140,10 +1182,10 @@ private:
DeclGroupPtrTy ParseDeclGroup(ParsingDeclSpec &DS, unsigned Context,
bool AllowFunctionDefinitions,
SourceLocation *DeclEnd = 0);
- DeclPtrTy ParseDeclarationAfterDeclarator(Declarator &D,
+ Decl *ParseDeclarationAfterDeclarator(Declarator &D,
const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo());
- DeclPtrTy ParseFunctionStatementBody(DeclPtrTy Decl);
- DeclPtrTy ParseFunctionTryBlock(DeclPtrTy Decl);
+ Decl *ParseFunctionStatementBody(Decl *Decl);
+ Decl *ParseFunctionTryBlock(Decl *Decl);
bool ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
const ParsedTemplateInfo &TemplateInfo,
@@ -1161,16 +1203,16 @@ private:
void ParseSpecifierQualifierList(DeclSpec &DS);
- void ParseObjCTypeQualifierList(ObjCDeclSpec &DS);
+ void ParseObjCTypeQualifierList(ObjCDeclSpec &DS, bool IsParameter);
void ParseEnumSpecifier(SourceLocation TagLoc, DeclSpec &DS,
const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), AccessSpecifier AS = AS_none);
- void ParseEnumBody(SourceLocation StartLoc, DeclPtrTy TagDecl);
+ void ParseEnumBody(SourceLocation StartLoc, Decl *TagDecl);
void ParseStructUnionBody(SourceLocation StartLoc, unsigned TagType,
- DeclPtrTy TagDecl);
+ Decl *TagDecl);
struct FieldCallback {
- virtual DeclPtrTy invoke(FieldDeclarator &Field) = 0;
+ virtual Decl *invoke(FieldDeclarator &Field) = 0;
virtual ~FieldCallback() {}
private:
@@ -1323,10 +1365,11 @@ private:
AttributeList *ParseGNUAttributes(SourceLocation *EndLoc = 0);
AttributeList *ParseMicrosoftDeclSpec(AttributeList* CurrAttr = 0);
AttributeList *ParseMicrosoftTypeAttributes(AttributeList* CurrAttr = 0);
+ AttributeList *ParseBorlandTypeAttributes(AttributeList* CurrAttr = 0);
void ParseTypeofSpecifier(DeclSpec &DS);
void ParseDecltypeSpecifier(DeclSpec &DS);
- OwningExprResult ParseCXX0XAlignArgument(SourceLocation Start);
+ ExprResult ParseCXX0XAlignArgument(SourceLocation Start);
/// DeclaratorScopeObj - RAII object used in Parser::ParseDirectDeclarator to
/// enter a new C++ declarator scope and exit it when the function is
@@ -1386,21 +1429,21 @@ private:
bool isCXX0XAttributeSpecifier(bool FullLookahead = false,
tok::TokenKind *After = 0);
- DeclPtrTy ParseNamespace(unsigned Context, SourceLocation &DeclEnd);
- DeclPtrTy ParseLinkage(ParsingDeclSpec &DS, unsigned Context);
- DeclPtrTy ParseUsingDirectiveOrDeclaration(unsigned Context,
- SourceLocation &DeclEnd,
- CXX0XAttributeList Attrs);
- DeclPtrTy ParseUsingDirective(unsigned Context, SourceLocation UsingLoc,
- SourceLocation &DeclEnd,
- AttributeList *Attr);
- DeclPtrTy ParseUsingDeclaration(unsigned Context, SourceLocation UsingLoc,
- SourceLocation &DeclEnd,
- AccessSpecifier AS = AS_none);
- DeclPtrTy ParseStaticAssertDeclaration(SourceLocation &DeclEnd);
- DeclPtrTy ParseNamespaceAlias(SourceLocation NamespaceLoc,
- SourceLocation AliasLoc, IdentifierInfo *Alias,
- SourceLocation &DeclEnd);
+ Decl *ParseNamespace(unsigned Context, SourceLocation &DeclEnd,
+ SourceLocation InlineLoc = SourceLocation());
+ Decl *ParseLinkage(ParsingDeclSpec &DS, unsigned Context);
+ Decl *ParseUsingDirectiveOrDeclaration(unsigned Context,
+ SourceLocation &DeclEnd,
+ CXX0XAttributeList Attrs);
+ Decl *ParseUsingDirective(unsigned Context, SourceLocation UsingLoc,
+ SourceLocation &DeclEnd, AttributeList *Attr);
+ Decl *ParseUsingDeclaration(unsigned Context, SourceLocation UsingLoc,
+ SourceLocation &DeclEnd,
+ AccessSpecifier AS = AS_none);
+ Decl *ParseStaticAssertDeclaration(SourceLocation &DeclEnd);
+ Decl *ParseNamespaceAlias(SourceLocation NamespaceLoc,
+ SourceLocation AliasLoc, IdentifierInfo *Alias,
+ SourceLocation &DeclEnd);
//===--------------------------------------------------------------------===//
// C++ 9: classes [class] and C structs/unions.
@@ -1412,64 +1455,65 @@ private:
AccessSpecifier AS = AS_none,
bool SuppressDeclarations = false);
void ParseCXXMemberSpecification(SourceLocation StartLoc, unsigned TagType,
- DeclPtrTy TagDecl);
+ Decl *TagDecl);
void ParseCXXClassMemberDeclaration(AccessSpecifier AS,
- const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo());
- void ParseConstructorInitializer(DeclPtrTy ConstructorDecl);
- MemInitResult ParseMemInitializer(DeclPtrTy ConstructorDecl);
+ const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
+ ParsingDeclRAIIObject *DiagsFromTParams = 0);
+ void ParseConstructorInitializer(Decl *ConstructorDecl);
+ MemInitResult ParseMemInitializer(Decl *ConstructorDecl);
void HandleMemberFunctionDefaultArgs(Declarator& DeclaratorInfo,
- DeclPtrTy ThisDecl);
+ Decl *ThisDecl);
//===--------------------------------------------------------------------===//
// C++ 10: Derived classes [class.derived]
- void ParseBaseClause(DeclPtrTy ClassDecl);
- BaseResult ParseBaseSpecifier(DeclPtrTy ClassDecl);
+ void ParseBaseClause(Decl *ClassDecl);
+ BaseResult ParseBaseSpecifier(Decl *ClassDecl);
AccessSpecifier getAccessSpecifierIfPresent() const;
bool ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
IdentifierInfo *Name,
SourceLocation NameLoc,
bool EnteringContext,
- TypeTy *ObjectType,
+ ParsedType ObjectType,
UnqualifiedId &Id,
bool AssumeTemplateId,
SourceLocation TemplateKWLoc);
bool ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
- TypeTy *ObjectType,
+ ParsedType ObjectType,
UnqualifiedId &Result);
bool ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
bool AllowDestructorName,
bool AllowConstructorName,
- TypeTy *ObjectType,
+ ParsedType ObjectType,
UnqualifiedId &Result);
//===--------------------------------------------------------------------===//
// C++ 14: Templates [temp]
- typedef llvm::SmallVector<DeclPtrTy, 4> TemplateParameterList;
// C++ 14.1: Template Parameters [temp.param]
- DeclPtrTy ParseDeclarationStartingWithTemplate(unsigned Context,
+ Decl *ParseDeclarationStartingWithTemplate(unsigned Context,
SourceLocation &DeclEnd,
AccessSpecifier AS = AS_none);
- DeclPtrTy ParseTemplateDeclarationOrSpecialization(unsigned Context,
+ Decl *ParseTemplateDeclarationOrSpecialization(unsigned Context,
SourceLocation &DeclEnd,
AccessSpecifier AS);
- DeclPtrTy ParseSingleDeclarationAfterTemplate(
+ Decl *ParseSingleDeclarationAfterTemplate(
unsigned Context,
const ParsedTemplateInfo &TemplateInfo,
+ ParsingDeclRAIIObject &DiagsFromParams,
SourceLocation &DeclEnd,
AccessSpecifier AS=AS_none);
bool ParseTemplateParameters(unsigned Depth,
- TemplateParameterList &TemplateParams,
+ llvm::SmallVectorImpl<Decl*> &TemplateParams,
SourceLocation &LAngleLoc,
SourceLocation &RAngleLoc);
bool ParseTemplateParameterList(unsigned Depth,
- TemplateParameterList &TemplateParams);
+ llvm::SmallVectorImpl<Decl*> &TemplateParams);
bool isStartOfTemplateTypeParameter();
- DeclPtrTy ParseTemplateParameter(unsigned Depth, unsigned Position);
- DeclPtrTy ParseTypeParameter(unsigned Depth, unsigned Position);
- DeclPtrTy ParseTemplateTemplateParameter(unsigned Depth, unsigned Position);
- DeclPtrTy ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position);
+ Decl *ParseTemplateParameter(unsigned Depth, unsigned Position);
+ Decl *ParseTypeParameter(unsigned Depth, unsigned Position);
+ Decl *ParseTemplateTemplateParameter(unsigned Depth, unsigned Position);
+ Decl *ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position);
// C++ 14.3: Template arguments [temp.arg]
typedef llvm::SmallVector<ParsedTemplateArgument, 16> TemplateArgList;
@@ -1491,13 +1535,24 @@ private:
bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs);
ParsedTemplateArgument ParseTemplateTemplateArgument();
ParsedTemplateArgument ParseTemplateArgument();
- DeclPtrTy ParseExplicitInstantiation(SourceLocation ExternLoc,
- SourceLocation TemplateLoc,
- SourceLocation &DeclEnd);
+ Decl *ParseExplicitInstantiation(SourceLocation ExternLoc,
+ SourceLocation TemplateLoc,
+ SourceLocation &DeclEnd);
//===--------------------------------------------------------------------===//
// GNU G++: Type Traits [Type-Traits.html in the GCC manual]
- OwningExprResult ParseUnaryTypeTrait();
+ ExprResult ParseUnaryTypeTrait();
+
+ //===--------------------------------------------------------------------===//
+ // Preprocessor code-completion pass-through
+ virtual void CodeCompleteDirective(bool InConditional);
+ virtual void CodeCompleteInConditionalExclusion();
+ virtual void CodeCompleteMacroName(bool IsDefinition);
+ virtual void CodeCompletePreprocessorExpression();
+ virtual void CodeCompleteMacroArgument(IdentifierInfo *Macro,
+ MacroInfo *MacroInfo,
+ unsigned ArgumentIndex);
+ virtual void CodeCompleteNaturalLanguage();
};
} // end namespace clang
diff --git a/include/clang/Rewrite/FixItRewriter.h b/include/clang/Rewrite/FixItRewriter.h
index 4ebcef0fff61..9b2e0160c5d6 100644
--- a/include/clang/Rewrite/FixItRewriter.h
+++ b/include/clang/Rewrite/FixItRewriter.h
@@ -27,13 +27,16 @@ namespace clang {
class SourceManager;
class FileEntry;
-class FixItPathRewriter {
+class FixItOptions {
public:
- virtual ~FixItPathRewriter();
+ virtual ~FixItOptions();
/// \brief This file is about to be rewritten. Return the name of the file
/// that is okay to write to.
virtual std::string RewriteFilename(const std::string &Filename) = 0;
+
+ /// \brief Whether to abort fixing a file when not all errors could be fixed.
+ bool FixWhatYouCan;
};
class FixItRewriter : public DiagnosticClient {
@@ -50,7 +53,7 @@ class FixItRewriter : public DiagnosticClient {
/// \brief Turn an input path into an output path. NULL implies overwriting
/// the original.
- FixItPathRewriter *PathRewriter;
+ FixItOptions *FixItOpts;
/// \brief The number of rewriter failures.
unsigned NumFailures;
@@ -60,7 +63,7 @@ public:
/// \brief Initialize a new fix-it rewriter.
FixItRewriter(Diagnostic &Diags, SourceManager &SourceMgr,
- const LangOptions &LangOpts, FixItPathRewriter *PathRewriter);
+ const LangOptions &LangOpts, FixItOptions *FixItOpts);
/// \brief Destroy the fix-it rewriter.
~FixItRewriter();
diff --git a/include/clang/Rewrite/FrontendActions.h b/include/clang/Rewrite/FrontendActions.h
index 2ff8d0a5b60a..2b5f88ccee9d 100644
--- a/include/clang/Rewrite/FrontendActions.h
+++ b/include/clang/Rewrite/FrontendActions.h
@@ -16,7 +16,7 @@
namespace clang {
class FixItRewriter;
-class FixItPathRewriter;
+class FixItOptions;
//===----------------------------------------------------------------------===//
// AST Consumer Actions
@@ -31,7 +31,7 @@ protected:
class FixItAction : public ASTFrontendAction {
protected:
llvm::OwningPtr<FixItRewriter> Rewriter;
- llvm::OwningPtr<FixItPathRewriter> PathRewriter;
+ llvm::OwningPtr<FixItOptions> FixItOpts;
virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
llvm::StringRef InFile);
diff --git a/include/clang/Sema/AnalysisBasedWarnings.h b/include/clang/Sema/AnalysisBasedWarnings.h
new file mode 100644
index 000000000000..0a6656e97e1b
--- /dev/null
+++ b/include/clang/Sema/AnalysisBasedWarnings.h
@@ -0,0 +1,64 @@
+//=- AnalysisBasedWarnings.h - Sema warnings based on libAnalysis -*- 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 AnalysisBasedWarnings, a worker object used by Sema
+// that issues warnings based on dataflow-analysis.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_ANALYSIS_WARNINGS_H
+#define LLVM_CLANG_SEMA_ANALYSIS_WARNINGS_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/DenseMap.h"
+
+namespace clang {
+
+class BlockExpr;
+class Decl;
+class FunctionDecl;
+class ObjCMethodDecl;
+class QualType;
+class Sema;
+
+namespace sema {
+
+class AnalysisBasedWarnings {
+public:
+ class Policy {
+ friend class AnalysisBasedWarnings;
+ // The warnings to run.
+ unsigned enableCheckFallThrough : 1;
+ unsigned enableCheckUnreachable : 1;
+ public:
+ Policy();
+ void disableCheckFallThrough() { enableCheckFallThrough = 0; }
+ };
+
+private:
+ Sema &S;
+ Policy DefaultPolicy;
+
+ enum VisitFlag { NotVisited = 0, Visited = 1, Pending = 2 };
+ llvm::DenseMap<const FunctionDecl*, VisitFlag> VisitedFD;
+
+ void IssueWarnings(Policy P, const Decl *D, QualType BlockTy);
+
+public:
+ AnalysisBasedWarnings(Sema &s);
+
+ Policy getDefaultPolicy() { return DefaultPolicy; }
+
+ void IssueWarnings(Policy P, const BlockExpr *E);
+ void IssueWarnings(Policy P, const FunctionDecl *D);
+ void IssueWarnings(Policy P, const ObjCMethodDecl *D);
+};
+
+}} // end namespace clang::sema
+
+#endif
diff --git a/include/clang/Parse/AttributeList.h b/include/clang/Sema/AttributeList.h
index b60a94025e09..53316477e1c5 100644
--- a/include/clang/Parse/AttributeList.h
+++ b/include/clang/Sema/AttributeList.h
@@ -1,4 +1,4 @@
-//===--- AttributeList.h ----------------------------------------*- C++ -*-===//
+//===--- AttributeList.h - Parsed attribute sets ----------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,20 +7,21 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines the AttributeList class interface.
+// This file defines the AttributeList class, which is used to collect
+// parsed attributes.
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_ATTRLIST_H
-#define LLVM_CLANG_ATTRLIST_H
+#ifndef LLVM_CLANG_SEMA_ATTRLIST_H
+#define LLVM_CLANG_SEMA_ATTRLIST_H
-#include "clang/Parse/Ownership.h"
+#include "clang/Sema/Ownership.h"
#include "clang/Basic/SourceLocation.h"
#include <cassert>
namespace clang {
class IdentifierInfo;
- class Action;
+ class Expr;
/// AttributeList - Represents GCC's __attribute__ declaration. There are
/// 4 forms of this construct...they are:
@@ -37,7 +38,7 @@ class AttributeList {
SourceLocation ScopeLoc;
IdentifierInfo *ParmName;
SourceLocation ParmLoc;
- ActionBase::ExprTy **Args;
+ Expr **Args;
unsigned NumArgs;
AttributeList *Next;
bool DeclspecAttribute, CXX0XAttribute;
@@ -48,7 +49,7 @@ public:
AttributeList(IdentifierInfo *AttrName, SourceLocation AttrLoc,
IdentifierInfo *ScopeName, SourceLocation ScopeLoc,
IdentifierInfo *ParmName, SourceLocation ParmLoc,
- ActionBase::ExprTy **args, unsigned numargs,
+ Expr **args, unsigned numargs,
AttributeList *Next, bool declspec = false, bool cxx0x = false);
~AttributeList();
@@ -97,7 +98,11 @@ public:
AT_ns_returns_retained, // Clang-specific.
AT_objc_gc,
AT_overloadable, // Clang-specific.
+ AT_ownership_holds, // Clang-specific.
+ AT_ownership_returns, // Clang-specific.
+ AT_ownership_takes, // Clang-specific.
AT_packed,
+ AT_pascal,
AT_pure,
AT_regparm,
AT_section,
@@ -108,6 +113,7 @@ public:
AT_unavailable,
AT_unused,
AT_used,
+ AT_vecreturn, // PS3 PPU-specific.
AT_vector_size,
AT_visibility,
AT_warn_unused_result,
@@ -145,16 +151,16 @@ public:
unsigned getNumArgs() const { return NumArgs; }
/// getArg - Return the specified argument.
- ActionBase::ExprTy *getArg(unsigned Arg) const {
+ Expr *getArg(unsigned Arg) const {
assert(Arg < NumArgs && "Arg access out of range!");
return Args[Arg];
}
class arg_iterator {
- ActionBase::ExprTy** X;
+ Expr** X;
unsigned Idx;
public:
- arg_iterator(ActionBase::ExprTy** x, unsigned idx) : X(x), Idx(idx) {}
+ arg_iterator(Expr** x, unsigned idx) : X(x), Idx(idx) {}
arg_iterator& operator++() {
++Idx;
@@ -171,7 +177,7 @@ public:
return !operator==(I);
}
- ActionBase::ExprTy* operator*() const {
+ Expr* operator*() const {
return X[Idx];
}
diff --git a/include/clang/Sema/CXXFieldCollector.h b/include/clang/Sema/CXXFieldCollector.h
new file mode 100644
index 000000000000..63c6ee3f74ba
--- /dev/null
+++ b/include/clang/Sema/CXXFieldCollector.h
@@ -0,0 +1,79 @@
+//===- CXXFieldCollector.h - Utility class for C++ class semantic analysis ===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides CXXFieldCollector that is used during parsing & semantic
+// analysis of C++ classes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_CXXFIELDCOLLECTOR_H
+#define LLVM_CLANG_SEMA_CXXFIELDCOLLECTOR_H
+
+#include "llvm/ADT/SmallVector.h"
+
+namespace clang {
+ class FieldDecl;
+
+/// CXXFieldCollector - Used to keep track of CXXFieldDecls during parsing of
+/// C++ classes.
+class CXXFieldCollector {
+ /// Fields - Contains all FieldDecls collected during parsing of a C++
+ /// class. When a nested class is entered, its fields are appended to the
+ /// fields of its parent class, when it is exited its fields are removed.
+ llvm::SmallVector<FieldDecl*, 32> Fields;
+
+ /// FieldCount - Each entry represents the number of fields collected during
+ /// the parsing of a C++ class. When a nested class is entered, a new field
+ /// count is pushed, when it is exited, the field count is popped.
+ llvm::SmallVector<size_t, 4> FieldCount;
+
+ // Example:
+ //
+ // class C {
+ // int x,y;
+ // class NC {
+ // int q;
+ // // At this point, Fields contains [x,y,q] decls and FieldCount contains
+ // // [2,1].
+ // };
+ // int z;
+ // // At this point, Fields contains [x,y,z] decls and FieldCount contains
+ // // [3].
+ // };
+
+public:
+ /// StartClass - Called by Sema::ActOnStartCXXClassDef.
+ void StartClass() { FieldCount.push_back(0); }
+
+ /// Add - Called by Sema::ActOnCXXMemberDeclarator.
+ void Add(FieldDecl *D) {
+ Fields.push_back(D);
+ ++FieldCount.back();
+ }
+
+ /// getCurNumField - The number of fields added to the currently parsed class.
+ size_t getCurNumFields() const {
+ assert(!FieldCount.empty() && "no currently-parsed class");
+ return FieldCount.back();
+ }
+
+ /// getCurFields - Pointer to array of fields added to the currently parsed
+ /// class.
+ FieldDecl **getCurFields() { return &*(Fields.end() - getCurNumFields()); }
+
+ /// FinishClass - Called by Sema::ActOnFinishCXXClassDef.
+ void FinishClass() {
+ Fields.resize(Fields.size() - getCurNumFields());
+ FieldCount.pop_back();
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h
index 1d9d25073177..6c1ecbf2cc29 100644
--- a/include/clang/Sema/CodeCompleteConsumer.h
+++ b/include/clang/Sema/CodeCompleteConsumer.h
@@ -13,20 +13,30 @@
#ifndef LLVM_CLANG_SEMA_CODECOMPLETECONSUMER_H
#define LLVM_CLANG_SEMA_CODECOMPLETECONSUMER_H
+#include "clang/AST/Type.h"
+#include "clang/AST/CanonicalType.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
+#include "clang-c/Index.h"
#include <memory>
#include <string>
namespace llvm {
-class raw_ostream;
+ class raw_ostream;
}
namespace clang {
+class Decl;
+
/// \brief Default priority values for code-completion results based
/// on their kind.
enum {
+ /// \brief Priority for the next initialization in a constructor initializer
+ /// list.
+ CCP_NextInitializer = 7,
+ /// \brief Priority for a send-to-super completion.
+ CCP_SuperCompletion = 8,
/// \brief Priority for a declaration that is in the local scope.
CCP_LocalDeclaration = 8,
/// \brief Priority for a member declaration found from the current
@@ -37,12 +47,12 @@ enum {
CCP_Keyword = 30,
/// \brief Priority for a code pattern.
CCP_CodePattern = 30,
- /// \brief Priority for a type.
- CCP_Type = 40,
/// \brief Priority for a non-type declaration.
CCP_Declaration = 50,
/// \brief Priority for a constant value (e.g., enumerator).
CCP_Constant = 60,
+ /// \brief Priority for a type.
+ CCP_Type = 65,
/// \brief Priority for a preprocessor macro.
CCP_Macro = 70,
/// \brief Priority for a nested-name-specifier.
@@ -52,11 +62,23 @@ enum {
CCP_Unlikely = 80
};
-/// \brief Priority value deltas that are applied to code-completion results
+/// \brief Priority value deltas that are added to code-completion results
/// based on the context of the result.
enum {
/// \brief The result is in a base class.
- CCD_InBaseClass = 2
+ CCD_InBaseClass = 2,
+ /// \brief The result is a type match against void.
+ ///
+ /// Since everything converts to "void", we don't give as drastic an
+ /// adjustment for matching void.
+ CCD_VoidMatch = -5,
+ /// \brief The result is a C++ non-static member function whose qualifiers
+ /// exactly match the object type on which the member function can be called.
+ CCD_ObjectQualifierMatch = -1,
+ /// \brief The selector of the given message exactly matches the selector
+ /// of the current method, which might imply that some kind of delegation
+ /// is occurring.
+ CCD_SelectorMatch = -3
};
/// \brief Priority value factors by which we will divide or multiply the
@@ -70,6 +92,41 @@ enum {
/// Objective-C object pointer types).
CCF_SimilarTypeMatch = 2
};
+
+/// \brief A simplified classification of types used when determining
+/// "similar" types for code completion.
+enum SimplifiedTypeClass {
+ STC_Arithmetic,
+ STC_Array,
+ STC_Block,
+ STC_Function,
+ STC_ObjectiveC,
+ STC_Other,
+ STC_Pointer,
+ STC_Record,
+ STC_Void
+};
+
+/// \brief Determine the simplified type class of the given canonical type.
+SimplifiedTypeClass getSimplifiedTypeClass(CanQualType T);
+
+/// \brief Determine the type that this declaration will have if it is used
+/// as a type or in an expression.
+QualType getDeclUsageType(ASTContext &C, NamedDecl *ND);
+
+/// \brief Determine the priority to be given to a macro code completion result
+/// with the given name.
+///
+/// \param MacroName The name of the macro.
+///
+/// \param PreferredTypeIsPointer Whether the preferred type for the context
+/// of this macro is a pointer type.
+unsigned getMacroUsagePriority(llvm::StringRef MacroName,
+ bool PreferredTypeIsPointer = false);
+
+/// \brief Determine the libclang cursor kind associated with the given
+/// declaration.
+CXCursorKind getCursorKindForDecl(Decl *D);
class FunctionDecl;
class FunctionType;
@@ -79,6 +136,121 @@ class NamedDecl;
class NestedNameSpecifier;
class Sema;
+/// \brief The context in which code completion occurred, so that the
+/// code-completion consumer can process the results accordingly.
+class CodeCompletionContext {
+public:
+ enum Kind {
+ /// \brief An unspecified code-completion context.
+ CCC_Other,
+ /// \brief Code completion occurred within a "top-level" completion context,
+ /// e.g., at namespace or global scope.
+ CCC_TopLevel,
+ /// \brief Code completion occurred within an Objective-C interface,
+ /// protocol, or category interface.
+ CCC_ObjCInterface,
+ /// \brief Code completion occurred within an Objective-C implementation
+ /// or category implementation.
+ CCC_ObjCImplementation,
+ /// \brief Code completion occurred within the instance variable list of
+ /// an Objective-C interface, implementation, or category implementation.
+ CCC_ObjCIvarList,
+ /// \brief Code completion occurred within a class, struct, or union.
+ CCC_ClassStructUnion,
+ /// \brief Code completion occurred where a statement (or declaration) is
+ /// expected in a function, method, or block.
+ CCC_Statement,
+ /// \brief Code completion occurred where an expression is expected.
+ CCC_Expression,
+ /// \brief Code completion occurred where an Objective-C message receiver
+ /// is expected.
+ CCC_ObjCMessageReceiver,
+ /// \brief Code completion occurred on the right-hand side of a member
+ /// access expression.
+ ///
+ /// The results of this completion are the members of the type being
+ /// accessed. The type itself is available via
+ /// \c CodeCompletionContext::getType().
+ CCC_MemberAccess,
+ /// \brief Code completion occurred after the "enum" keyword, to indicate
+ /// an enumeration name.
+ CCC_EnumTag,
+ /// \brief Code completion occurred after the "union" keyword, to indicate
+ /// a union name.
+ CCC_UnionTag,
+ /// \brief Code completion occurred after the "struct" or "class" keyword,
+ /// to indicate a struct or class name.
+ CCC_ClassOrStructTag,
+ /// \brief Code completion occurred where a protocol name is expected.
+ CCC_ObjCProtocolName,
+ /// \brief Code completion occurred where a namespace or namespace alias
+ /// is expected.
+ CCC_Namespace,
+ /// \brief Code completion occurred where a type name is expected.
+ CCC_Type,
+ /// \brief Code completion occurred where a new name is expected.
+ CCC_Name,
+ /// \brief Code completion occurred where a new name is expected and a
+ /// qualified name is permissible.
+ CCC_PotentiallyQualifiedName,
+ /// \brief Code completion occurred where an macro is being defined.
+ CCC_MacroName,
+ /// \brief Code completion occurred where a macro name is expected
+ /// (without any arguments, in the case of a function-like macro).
+ CCC_MacroNameUse,
+ /// \brief Code completion occurred within a preprocessor expression.
+ CCC_PreprocessorExpression,
+ /// \brief Code completion occurred where a preprocessor directive is
+ /// expected.
+ CCC_PreprocessorDirective,
+ /// \brief Code completion occurred in a context where natural language is
+ /// expected, e.g., a comment or string literal.
+ ///
+ /// This context usually implies that no completions should be added,
+ /// unless they come from an appropriate natural-language dictionary.
+ CCC_NaturalLanguage,
+ /// \brief Code completion for a selector, as in an @selector expression.
+ CCC_SelectorName,
+ /// \brief Code completion within a type-qualifier list.
+ CCC_TypeQualifiers
+ };
+
+private:
+ enum Kind Kind;
+
+ /// \brief The type that would prefer to see at this point (e.g., the type
+ /// of an initializer or function parameter).
+ QualType PreferredType;
+
+ /// \brief The type of the base object in a member access expression.
+ QualType BaseType;
+
+public:
+ /// \brief Construct a new code-completion context of the given kind.
+ CodeCompletionContext(enum Kind Kind) : Kind(Kind) { }
+
+ /// \brief Construct a new code-completion context of the given kind.
+ CodeCompletionContext(enum Kind Kind, QualType T) : Kind(Kind) {
+ if (Kind == CCC_MemberAccess)
+ BaseType = T;
+ else
+ PreferredType = T;
+ }
+
+ /// \brief Retrieve the kind of code-completion context.
+ enum Kind getKind() const { return Kind; }
+
+ /// \brief Retrieve the type that this expression would prefer to have, e.g.,
+ /// if the expression is a variable initializer or a function argument, the
+ /// type of the corresponding variable or function parameter.
+ QualType getPreferredType() const { return PreferredType; }
+
+ /// \brief Retrieve the type of the base object in a member-access
+ /// expression.
+ QualType getBaseType() const { return BaseType; }
+};
+
+
/// \brief A "string" used to describe how code completion can
/// be performed for an entity.
///
@@ -274,7 +446,10 @@ public:
std::string getAsString() const;
/// \brief Clone this code-completion string.
- CodeCompletionString *Clone() const;
+ ///
+ /// \param Result If non-NULL, points to an empty code-completion
+ /// result that will be given a cloned copy of
+ CodeCompletionString *Clone(CodeCompletionString *Result = 0) const;
/// \brief Serialize this code-completion string to the given stream.
void Serialize(llvm::raw_ostream &OS) const;
@@ -284,140 +459,193 @@ public:
/// \returns true if successful, false otherwise.
bool Deserialize(const char *&Str, const char *StrEnd);
};
-
-llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
- const CodeCompletionString &CCS);
-/// \brief Abstract interface for a consumer of code-completion
-/// information.
-class CodeCompleteConsumer {
-protected:
- /// \brief Whether to include macros in the code-completion results.
- bool IncludeMacros;
-
- /// \brief Whether to include code patterns (such as for loops) within
- /// the completion results.
- bool IncludeCodePatterns;
-
- /// \brief Whether the output format for the code-completion consumer is
- /// binary.
- bool OutputIsBinary;
-
+/// \brief Captures a result of code completion.
+class CodeCompletionResult {
public:
- /// \brief Captures a result of code completion.
- struct Result {
- /// \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_Macro, //< Refers to a macro
- RK_Pattern //< Refers to a precomputed pattern.
- };
+ /// \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_Macro, //< Refers to a macro
+ RK_Pattern //< Refers to a precomputed pattern.
+ };
- /// \brief The kind of result stored here.
- ResultKind Kind;
+ /// \brief The kind of result stored here.
+ ResultKind Kind;
- union {
- /// \brief When Kind == RK_Declaration, the declaration we are referring
- /// to.
- NamedDecl *Declaration;
+ union {
+ /// \brief When Kind == RK_Declaration, the declaration we are referring
+ /// to.
+ NamedDecl *Declaration;
- /// \brief When Kind == RK_Keyword, the string representing the keyword
- /// or symbol's spelling.
- const char *Keyword;
+ /// \brief When Kind == RK_Keyword, the string representing the keyword
+ /// or symbol's spelling.
+ const char *Keyword;
- /// \brief When Kind == RK_Pattern, the code-completion string that
- /// describes the completion text to insert.
- CodeCompletionString *Pattern;
+ /// \brief When Kind == RK_Pattern, the code-completion string that
+ /// describes the completion text to insert.
+ CodeCompletionString *Pattern;
- /// \brief When Kind == RK_Macro, the identifier that refers to a macro.
- IdentifierInfo *Macro;
- };
+ /// \brief When Kind == RK_Macro, the identifier that refers to a macro.
+ IdentifierInfo *Macro;
+ };
- /// \brief The priority of this particular code-completion result.
- unsigned Priority;
+ /// \brief The priority of this particular code-completion result.
+ unsigned Priority;
- /// \brief Specifies which parameter (of a function, Objective-C method,
- /// macro, etc.) we should start with when formatting the result.
- unsigned StartParameter;
+ /// \brief The cursor kind that describes this result.
+ CXCursorKind CursorKind;
+
+ /// \brief The availability of this result.
+ CXAvailabilityKind Availability;
- /// \brief Whether this result is hidden by another name.
- bool Hidden : 1;
+ /// \brief Specifies which parameter (of a function, Objective-C method,
+ /// macro, etc.) we should start with when formatting the result.
+ unsigned StartParameter;
- /// \brief Whether this result was found via lookup into a base class.
- bool QualifierIsInformative : 1;
+ /// \brief Whether this result is hidden by another name.
+ bool Hidden : 1;
- /// \brief Whether this declaration is the beginning of a
- /// nested-name-specifier and, therefore, should be followed by '::'.
- bool StartsNestedNameSpecifier : 1;
+ /// \brief Whether this result was found via lookup into a base class.
+ bool QualifierIsInformative : 1;
+
+ /// \brief Whether this declaration is the beginning of a
+ /// nested-name-specifier and, therefore, should be followed by '::'.
+ bool StartsNestedNameSpecifier : 1;
- /// \brief Whether all parameters (of a function, Objective-C
- /// method, etc.) should be considered "informative".
- bool AllParametersAreInformative : 1;
+ /// \brief Whether all parameters (of a function, Objective-C
+ /// method, etc.) should be considered "informative".
+ bool AllParametersAreInformative : 1;
- /// \brief Whether we're completing a declaration of the given entity,
- /// rather than a use of that entity.
- bool DeclaringEntity : 1;
+ /// \brief Whether we're completing a declaration of the given entity,
+ /// rather than a use of that entity.
+ bool DeclaringEntity : 1;
- /// \brief If the result should have a nested-name-specifier, this is it.
- /// When \c QualifierIsInformative, the nested-name-specifier is
- /// informative rather than required.
- NestedNameSpecifier *Qualifier;
+ /// \brief If the result should have a nested-name-specifier, this is it.
+ /// When \c QualifierIsInformative, the nested-name-specifier is
+ /// informative rather than required.
+ NestedNameSpecifier *Qualifier;
- /// \brief Build a result that refers to a declaration.
- Result(NamedDecl *Declaration,
- NestedNameSpecifier *Qualifier = 0,
- bool QualifierIsInformative = false)
- : Kind(RK_Declaration), Declaration(Declaration),
- Priority(getPriorityFromDecl(Declaration)), StartParameter(0),
- Hidden(false), QualifierIsInformative(QualifierIsInformative),
- StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
- DeclaringEntity(false), Qualifier(Qualifier) {
- }
+ /// \brief Build a result that refers to a declaration.
+ CodeCompletionResult(NamedDecl *Declaration,
+ NestedNameSpecifier *Qualifier = 0,
+ bool QualifierIsInformative = false)
+ : Kind(RK_Declaration), Declaration(Declaration),
+ Priority(getPriorityFromDecl(Declaration)),
+ Availability(CXAvailability_Available), StartParameter(0),
+ Hidden(false), QualifierIsInformative(QualifierIsInformative),
+ StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
+ DeclaringEntity(false), Qualifier(Qualifier) {
+ computeCursorKindAndAvailability();
+ }
- /// \brief Build a result that refers to a keyword or symbol.
- Result(const char *Keyword, unsigned Priority = CCP_Keyword)
- : Kind(RK_Keyword), Keyword(Keyword), Priority(Priority),
- StartParameter(0), Hidden(false), QualifierIsInformative(0),
- StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
- DeclaringEntity(false), Qualifier(0) { }
+ /// \brief Build a result that refers to a keyword or symbol.
+ CodeCompletionResult(const char *Keyword, unsigned Priority = CCP_Keyword)
+ : Kind(RK_Keyword), Keyword(Keyword), Priority(Priority),
+ Availability(CXAvailability_Available),
+ StartParameter(0), Hidden(false), QualifierIsInformative(0),
+ StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
+ DeclaringEntity(false), Qualifier(0) {
+ computeCursorKindAndAvailability();
+ }
- /// \brief Build a result that refers to a macro.
- Result(IdentifierInfo *Macro, unsigned Priority = CCP_Macro)
- : Kind(RK_Macro), Macro(Macro), Priority(Priority), StartParameter(0),
- Hidden(false), QualifierIsInformative(0),
- StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
- DeclaringEntity(false), Qualifier(0) { }
-
- /// \brief Build a result that refers to a pattern.
- Result(CodeCompletionString *Pattern, unsigned Priority = CCP_CodePattern)
- : Kind(RK_Pattern), Pattern(Pattern), Priority(Priority),
- StartParameter(0), Hidden(false), QualifierIsInformative(0),
- StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
- DeclaringEntity(false), Qualifier(0) { }
+ /// \brief Build a result that refers to a macro.
+ CodeCompletionResult(IdentifierInfo *Macro, unsigned Priority = CCP_Macro)
+ : Kind(RK_Macro), Macro(Macro), Priority(Priority),
+ Availability(CXAvailability_Available), StartParameter(0),
+ Hidden(false), QualifierIsInformative(0),
+ StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
+ DeclaringEntity(false), Qualifier(0) {
+ computeCursorKindAndAvailability();
+ }
+
+ /// \brief Build a result that refers to a pattern.
+ CodeCompletionResult(CodeCompletionString *Pattern,
+ unsigned Priority = CCP_CodePattern,
+ CXCursorKind CursorKind = CXCursor_NotImplemented,
+ CXAvailabilityKind Availability = CXAvailability_Available)
+ : Kind(RK_Pattern), Pattern(Pattern), Priority(Priority),
+ CursorKind(CursorKind), Availability(Availability), StartParameter(0),
+ Hidden(false), QualifierIsInformative(0),
+ StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
+ DeclaringEntity(false), Qualifier(0)
+ {
+ }
- /// \brief Retrieve the declaration stored in this result.
- NamedDecl *getDeclaration() const {
- assert(Kind == RK_Declaration && "Not a declaration result");
- return Declaration;
- }
+ /// \brief Retrieve the declaration stored in this result.
+ NamedDecl *getDeclaration() const {
+ assert(Kind == RK_Declaration && "Not a declaration result");
+ return Declaration;
+ }
- /// \brief Retrieve the keyword stored in this result.
- const char *getKeyword() const {
- assert(Kind == RK_Keyword && "Not a keyword result");
- return Keyword;
- }
+ /// \brief Retrieve the keyword stored in this result.
+ const char *getKeyword() const {
+ assert(Kind == RK_Keyword && "Not a keyword result");
+ return Keyword;
+ }
- /// \brief Create a new code-completion string that describes how to insert
- /// this result into a program.
- CodeCompletionString *CreateCodeCompletionString(Sema &S);
+ /// \brief Create a new code-completion string that describes how to insert
+ /// this result into a program.
+ ///
+ /// \param S The semantic analysis that created the result.
+ ///
+ /// \param Result If non-NULL, the already-allocated, empty
+ /// code-completion string that will be populated with the
+ /// appropriate code completion string for this result.
+ CodeCompletionString *CreateCodeCompletionString(Sema &S,
+ CodeCompletionString *Result = 0);
- void Destroy();
+ void Destroy();
- /// brief Determine a base priority for the given declaration.
- static unsigned getPriorityFromDecl(NamedDecl *ND);
- };
+ /// brief Determine a base priority for the given declaration.
+ static unsigned getPriorityFromDecl(NamedDecl *ND);
+private:
+ void computeCursorKindAndAvailability();
+};
+
+bool operator<(const CodeCompletionResult &X, const CodeCompletionResult &Y);
+
+inline bool operator>(const CodeCompletionResult &X,
+ const CodeCompletionResult &Y) {
+ return Y < X;
+}
+
+inline bool operator<=(const CodeCompletionResult &X,
+ const CodeCompletionResult &Y) {
+ return !(Y < X);
+}
+
+inline bool operator>=(const CodeCompletionResult &X,
+ const CodeCompletionResult &Y) {
+ return !(X < Y);
+}
+
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+ const CodeCompletionString &CCS);
+
+/// \brief Abstract interface for a consumer of code-completion
+/// information.
+class CodeCompleteConsumer {
+protected:
+ /// \brief Whether to include macros in the code-completion results.
+ bool IncludeMacros;
+
+ /// \brief Whether to include code patterns (such as for loops) within
+ /// the completion results.
+ bool IncludeCodePatterns;
+
+ /// \brief Whether to include global (top-level) declarations and names in
+ /// the completion results.
+ bool IncludeGlobals;
+
+ /// \brief Whether the output format for the code-completion consumer is
+ /// binary.
+ bool OutputIsBinary;
+
+public:
class OverloadCandidate {
public:
/// \brief Describes the type of overload candidate.
@@ -482,12 +710,13 @@ public:
Sema &S) const;
};
- CodeCompleteConsumer() : IncludeMacros(false), OutputIsBinary(false) { }
+ CodeCompleteConsumer() : IncludeMacros(false), IncludeCodePatterns(false),
+ IncludeGlobals(true), OutputIsBinary(false) { }
CodeCompleteConsumer(bool IncludeMacros, bool IncludeCodePatterns,
- bool OutputIsBinary)
+ bool IncludeGlobals, bool OutputIsBinary)
: IncludeMacros(IncludeMacros), IncludeCodePatterns(IncludeCodePatterns),
- OutputIsBinary(OutputIsBinary) { }
+ IncludeGlobals(IncludeGlobals), OutputIsBinary(OutputIsBinary) { }
/// \brief Whether the code-completion consumer wants to see macros.
bool includeMacros() const { return IncludeMacros; }
@@ -495,6 +724,9 @@ public:
/// \brief Whether the code-completion consumer wants to see code patterns.
bool includeCodePatterns() const { return IncludeCodePatterns; }
+ /// \brief Whether to include global (top-level) declaration results.
+ bool includeGlobals() const { return IncludeGlobals; }
+
/// \brief Determine whether the output of this consumer is binary.
bool isOutputBinary() const { return OutputIsBinary; }
@@ -504,7 +736,9 @@ public:
/// \name Code-completion callbacks
//@{
/// \brief Process the finalized code-completion results.
- virtual void ProcessCodeCompleteResults(Sema &S, Result *Results,
+ virtual void ProcessCodeCompleteResults(Sema &S,
+ CodeCompletionContext Context,
+ CodeCompletionResult *Results,
unsigned NumResults) { }
/// \param S the semantic-analyzer object for which code-completion is being
@@ -520,7 +754,7 @@ public:
unsigned NumCandidates) { }
//@}
};
-
+
/// \brief A simple code-completion consumer that prints the results it
/// receives in a simple format.
class PrintingCodeCompleteConsumer : public CodeCompleteConsumer {
@@ -531,11 +765,15 @@ public:
/// \brief Create a new printing code-completion consumer that prints its
/// results to the given raw output stream.
PrintingCodeCompleteConsumer(bool IncludeMacros, bool IncludeCodePatterns,
+ bool IncludeGlobals,
llvm::raw_ostream &OS)
- : CodeCompleteConsumer(IncludeMacros, IncludeCodePatterns, false), OS(OS) {}
+ : CodeCompleteConsumer(IncludeMacros, IncludeCodePatterns, IncludeGlobals,
+ false), OS(OS) {}
/// \brief Prints the finalized code-completion results.
- virtual void ProcessCodeCompleteResults(Sema &S, Result *Results,
+ virtual void ProcessCodeCompleteResults(Sema &S,
+ CodeCompletionContext Context,
+ CodeCompletionResult *Results,
unsigned NumResults);
virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
@@ -554,18 +792,21 @@ public:
/// results to the given raw output stream in a format readable to the CIndex
/// library.
CIndexCodeCompleteConsumer(bool IncludeMacros, bool IncludeCodePatterns,
- llvm::raw_ostream &OS)
- : CodeCompleteConsumer(IncludeMacros, IncludeCodePatterns, true), OS(OS) {}
+ bool IncludeGlobals, llvm::raw_ostream &OS)
+ : CodeCompleteConsumer(IncludeMacros, IncludeCodePatterns, IncludeGlobals,
+ true), OS(OS) {}
/// \brief Prints the finalized code-completion results.
- virtual void ProcessCodeCompleteResults(Sema &S, Result *Results,
+ virtual void ProcessCodeCompleteResults(Sema &S,
+ CodeCompletionContext Context,
+ CodeCompletionResult *Results,
unsigned NumResults);
virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
OverloadCandidate *Candidates,
unsigned NumCandidates);
};
-
+
} // end namespace clang
#endif // LLVM_CLANG_SEMA_CODECOMPLETECONSUMER_H
diff --git a/include/clang/Parse/DeclSpec.h b/include/clang/Sema/DeclSpec.h
index 0e6dbecb36d6..0893ae7e4958 100644
--- a/include/clang/Parse/DeclSpec.h
+++ b/include/clang/Sema/DeclSpec.h
@@ -1,4 +1,4 @@
-//===--- SemaDeclSpec.h - Declaration Specifier Semantic Analys -*- C++ -*-===//
+//===--- DeclSpec.h - Parsed declaration specifiers -------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,14 +7,21 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines interfaces used for Declaration Specifiers and Declarators.
+// This file defines the classes used to store parsed information about
+// declaration-specifiers and declarators.
+//
+// static const int volatile x, *y, *(*(*z)[10])(const void *x);
+// ------------------------- - -- ---------------------------
+// declaration-specifiers \ | /
+// declarators
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_PARSE_DECLSPEC_H
-#define LLVM_CLANG_PARSE_DECLSPEC_H
+#ifndef LLVM_CLANG_SEMA_DECLSPEC_H
+#define LLVM_CLANG_SEMA_DECLSPEC_H
-#include "clang/Parse/AttributeList.h"
+#include "clang/Sema/AttributeList.h"
+#include "clang/Sema/Ownership.h"
#include "clang/Lex/Token.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/Specifiers.h"
@@ -24,6 +31,7 @@ namespace clang {
class LangOptions;
class Diagnostic;
class IdentifierInfo;
+ class NestedNameSpecifier;
class Preprocessor;
class Declarator;
struct TemplateIdAnnotation;
@@ -41,7 +49,7 @@ namespace clang {
/// The actual scope is described by getScopeRep().
class CXXScopeSpec {
SourceRange Range;
- void *ScopeRep;
+ NestedNameSpecifier *ScopeRep;
public:
CXXScopeSpec() : Range(), ScopeRep() { }
@@ -53,8 +61,8 @@ public:
SourceLocation getBeginLoc() const { return Range.getBegin(); }
SourceLocation getEndLoc() const { return Range.getEnd(); }
- ActionBase::CXXScopeTy *getScopeRep() const { return ScopeRep; }
- void setScopeRep(ActionBase::CXXScopeTy *S) { ScopeRep = S; }
+ NestedNameSpecifier *getScopeRep() const { return ScopeRep; }
+ void setScopeRep(NestedNameSpecifier *S) { ScopeRep = S; }
/// No scope specifier.
bool isEmpty() const { return !Range.isValid(); }
@@ -162,6 +170,7 @@ private:
// storage-class-specifier
/*SCS*/unsigned StorageClassSpec : 3;
bool SCS_thread_specified : 1;
+ bool SCS_extern_in_linkage_spec : 1;
// type-specifier
/*TSW*/unsigned TypeSpecWidth : 2;
@@ -189,10 +198,11 @@ private:
/*SCS*/unsigned StorageClassSpecAsWritten : 3;
- /// TypeRep - This contains action-specific information about a specific TST.
- /// For example, for a typedef or struct, it might contain the declaration for
- /// these.
- void *TypeRep;
+ union {
+ UnionParsedType TypeRep;
+ Decl *DeclRep;
+ Expr *ExprRep;
+ };
// attributes.
AttributeList *AttrList;
@@ -203,7 +213,7 @@ private:
// List of protocol qualifiers for objective-c classes. Used for
// protocol-qualified interfaces "NString<foo>" and protocol-qualified id
// "id<foo>".
- const ActionBase::DeclPtrTy *ProtocolQualifiers;
+ Decl * const *ProtocolQualifiers;
unsigned NumProtocolQualifiers;
SourceLocation ProtocolLAngleLoc;
SourceLocation *ProtocolLocs;
@@ -221,8 +231,17 @@ private:
WrittenBuiltinSpecs writtenBS;
void SaveWrittenBuiltinSpecs();
- void SaveStorageSpecifierAsWritten() {
- StorageClassSpecAsWritten = StorageClassSpec;
+ void SaveStorageSpecifierAsWritten();
+
+ static bool isTypeRep(TST T) {
+ return (T == TST_typename || T == TST_typeofType);
+ }
+ static bool isExprRep(TST T) {
+ return (T == TST_typeofExpr || T == TST_decltype);
+ }
+ static bool isDeclRep(TST T) {
+ return (T == TST_enum || T == TST_struct ||
+ T == TST_union || T == TST_class);
}
DeclSpec(const DeclSpec&); // DO NOT IMPLEMENT
@@ -232,6 +251,7 @@ public:
DeclSpec()
: StorageClassSpec(SCS_unspecified),
SCS_thread_specified(false),
+ SCS_extern_in_linkage_spec(false),
TypeSpecWidth(TSW_unspecified),
TypeSpecComplex(TSC_unspecified),
TypeSpecSign(TSS_unspecified),
@@ -247,7 +267,6 @@ public:
Friend_specified(false),
Constexpr_specified(false),
StorageClassSpecAsWritten(SCS_unspecified),
- TypeRep(0),
AttrList(0),
ProtocolQualifiers(0),
NumProtocolQualifiers(0),
@@ -262,6 +281,10 @@ public:
// storage-class-specifier
SCS getStorageClassSpec() const { return (SCS)StorageClassSpec; }
bool isThreadSpecified() const { return SCS_thread_specified; }
+ bool isExternInLinkageSpec() const { return SCS_extern_in_linkage_spec; }
+ void setExternInLinkageSpec(bool Value) {
+ SCS_extern_in_linkage_spec = Value;
+ }
SourceLocation getStorageClassSpecLoc() const { return StorageClassSpecLoc; }
SourceLocation getThreadSpecLoc() const { return SCS_threadLoc; }
@@ -269,6 +292,7 @@ public:
void ClearStorageClassSpecs() {
StorageClassSpec = DeclSpec::SCS_unspecified;
SCS_thread_specified = false;
+ SCS_extern_in_linkage_spec = false;
StorageClassSpecLoc = SourceLocation();
SCS_threadLoc = SourceLocation();
}
@@ -282,7 +306,18 @@ public:
bool isTypeAltiVecPixel() const { return TypeAltiVecPixel; }
bool isTypeAltiVecBool() const { return TypeAltiVecBool; }
bool isTypeSpecOwned() const { return TypeSpecOwned; }
- void *getTypeRep() const { return TypeRep; }
+ ParsedType getRepAsType() const {
+ assert(isTypeRep((TST) TypeSpecType) && "DeclSpec does not store a type");
+ return TypeRep;
+ }
+ Decl *getRepAsDecl() const {
+ assert(isDeclRep((TST) TypeSpecType) && "DeclSpec does not store a decl");
+ return DeclRep;
+ }
+ Expr *getRepAsExpr() const {
+ assert(isExprRep((TST) TypeSpecType) && "DeclSpec does not store an expr");
+ return ExprRep;
+ }
CXXScopeSpec &getTypeSpecScope() { return TypeScope; }
const CXXScopeSpec &getTypeSpecScope() const { return TypeScope; }
@@ -379,13 +414,30 @@ public:
bool SetTypeSpecSign(TSS S, SourceLocation Loc, const char *&PrevSpec,
unsigned &DiagID);
bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec,
- unsigned &DiagID, void *Rep = 0, bool Owned = false);
+ unsigned &DiagID);
+ bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID, ParsedType Rep);
+ bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID, Decl *Rep, bool Owned);
+ bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID, Expr *Rep);
bool SetTypeAltiVecVector(bool isAltiVecVector, SourceLocation Loc,
const char *&PrevSpec, unsigned &DiagID);
bool SetTypeAltiVecPixel(bool isAltiVecPixel, SourceLocation Loc,
const char *&PrevSpec, unsigned &DiagID);
bool SetTypeSpecError();
- void UpdateTypeRep(void *Rep) { TypeRep = Rep; }
+ void UpdateDeclRep(Decl *Rep) {
+ assert(isDeclRep((TST) TypeSpecType));
+ DeclRep = Rep;
+ }
+ void UpdateTypeRep(ParsedType Rep) {
+ assert(isTypeRep((TST) TypeSpecType));
+ TypeRep = Rep;
+ }
+ void UpdateExprRep(Expr *Rep) {
+ assert(isExprRep((TST) TypeSpecType));
+ ExprRep = Rep;
+ }
bool SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec,
unsigned &DiagID, const LangOptions &Lang);
@@ -436,7 +488,7 @@ public:
return AL;
}
- typedef const ActionBase::DeclPtrTy *ProtocolQualifierListTy;
+ typedef Decl * const *ProtocolQualifierListTy;
ProtocolQualifierListTy getProtocolQualifiers() const {
return ProtocolQualifiers;
}
@@ -445,7 +497,7 @@ public:
return NumProtocolQualifiers;
}
SourceLocation getProtocolLAngleLoc() const { return ProtocolLAngleLoc; }
- void setProtocolQualifiers(const ActionBase::DeclPtrTy *Protos, unsigned NP,
+ void setProtocolQualifiers(Decl * const *Protos, unsigned NP,
SourceLocation *ProtoLocs,
SourceLocation LAngleLoc);
@@ -577,15 +629,15 @@ public:
/// \brief When Kind == IK_ConversionFunctionId, the type that the
/// conversion function names.
- ActionBase::TypeTy *ConversionFunctionId;
+ UnionParsedType ConversionFunctionId;
/// \brief When Kind == IK_ConstructorName, the class-name of the type
/// whose constructor is being referenced.
- ActionBase::TypeTy *ConstructorName;
+ UnionParsedType ConstructorName;
/// \brief When Kind == IK_DestructorName, the type referred to by the
/// class-name.
- ActionBase::TypeTy *DestructorName;
+ UnionParsedType DestructorName;
/// \brief When Kind == IK_TemplateId or IK_ConstructorTemplateId,
/// the template-id annotation that contains the template name and
@@ -662,7 +714,7 @@ public:
///
/// \param EndLoc the location of the last token that makes up the type name.
void setConversionFunctionId(SourceLocation OperatorLoc,
- ActionBase::TypeTy *Ty,
+ ParsedType Ty,
SourceLocation EndLoc) {
Kind = IK_ConversionFunctionId;
StartLocation = OperatorLoc;
@@ -693,7 +745,7 @@ public:
/// \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,
+ void setConstructorName(ParsedType ClassType,
SourceLocation ClassNameLoc,
SourceLocation EndLoc) {
Kind = IK_ConstructorName;
@@ -716,7 +768,8 @@ public:
/// name.
///
/// \param ClassType the name of the class referred to by the destructor name.
- void setDestructorName(SourceLocation TildeLoc, ActionBase::TypeTy *ClassType,
+ void setDestructorName(SourceLocation TildeLoc,
+ ParsedType ClassType,
SourceLocation EndLoc) {
Kind = IK_DestructorName;
StartLocation = TildeLoc;
@@ -788,7 +841,7 @@ struct DeclaratorChunk {
/// This is the size of the array, or null if [] or [*] was specified.
/// Since the parser is multi-purpose, and we don't want to impose a root
/// expression class on all clients, NumElts is untyped.
- ActionBase::ExprTy *NumElts;
+ Expr *NumElts;
void destroy() {}
};
@@ -801,7 +854,7 @@ struct DeclaratorChunk {
struct ParamInfo {
IdentifierInfo *Ident;
SourceLocation IdentLoc;
- ActionBase::DeclPtrTy Param;
+ Decl *Param;
/// DefaultArgTokens - When the parameter's default argument
/// cannot be parsed immediately (because it occurs within the
@@ -812,14 +865,14 @@ struct DeclaratorChunk {
ParamInfo() {}
ParamInfo(IdentifierInfo *ident, SourceLocation iloc,
- ActionBase::DeclPtrTy param,
+ Decl *param,
CachedTokens *DefArgTokens = 0)
: Ident(ident), IdentLoc(iloc), Param(param),
DefaultArgTokens(DefArgTokens) {}
};
struct TypeAndRange {
- ActionBase::TypeTy *Ty;
+ ParsedType Ty;
SourceRange Range;
};
@@ -999,7 +1052,7 @@ struct DeclaratorChunk {
/// getArray - Return a DeclaratorChunk for an array.
///
static DeclaratorChunk getArray(unsigned TypeQuals, bool isStatic,
- bool isStar, void *NumElts,
+ bool isStar, Expr *NumElts,
SourceLocation LBLoc, SourceLocation RBLoc) {
DeclaratorChunk I;
I.Kind = Array;
@@ -1020,7 +1073,7 @@ struct DeclaratorChunk {
unsigned TypeQuals, bool hasExceptionSpec,
SourceLocation ThrowLoc,
bool hasAnyExceptionSpec,
- ActionBase::TypeTy **Exceptions,
+ ParsedType *Exceptions,
SourceRange *ExceptionRanges,
unsigned NumExceptions,
SourceLocation LPLoc, SourceLocation RPLoc,
@@ -1104,7 +1157,7 @@ private:
AttributeList *AttrList;
/// AsmLabel - The asm label, if specified.
- ActionBase::ExprTy *AsmLabel;
+ Expr *AsmLabel;
/// 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
@@ -1303,8 +1356,8 @@ public:
return false;
}
- void setAsmLabel(ActionBase::ExprTy *E) { AsmLabel = E; }
- ActionBase::ExprTy *getAsmLabel() const { return AsmLabel; }
+ void setAsmLabel(Expr *E) { AsmLabel = E; }
+ Expr *getAsmLabel() const { return AsmLabel; }
void setExtension(bool Val = true) { Extension = Val; }
bool getExtension() const { return Extension; }
@@ -1322,7 +1375,7 @@ public:
/// structure field declarators, which is basically just a bitfield size.
struct FieldDeclarator {
Declarator D;
- ActionBase::ExprTy *BitfieldSize;
+ Expr *BitfieldSize;
explicit FieldDeclarator(DeclSpec &DS) : D(DS, Declarator::MemberContext) {
BitfieldSize = 0;
}
diff --git a/include/clang/Sema/DelayedDiagnostic.h b/include/clang/Sema/DelayedDiagnostic.h
new file mode 100644
index 000000000000..6a9a1bf5b608
--- /dev/null
+++ b/include/clang/Sema/DelayedDiagnostic.h
@@ -0,0 +1,168 @@
+//===--- DelayedDiagnostic.h - Delayed declarator diagnostics ---*- 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 the DelayedDiagnostic class, which is used to
+// record diagnostics that are being conditionally produced during
+// declarator parsing. Certain kinds of diagnostics --- notably
+// deprecation and access control --- are suppressed based on
+// semantic properties of the parsed declaration that aren't known
+// until it is fully parsed.
+//
+// This file also defines AccessedEntity.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_DELAYED_DIAGNOSTIC_H
+#define LLVM_CLANG_SEMA_DELAYED_DIAGNOSTIC_H
+
+#include "clang/AST/DeclCXX.h"
+
+namespace clang {
+namespace sema {
+
+/// A declaration being accessed, together with information about how
+/// it was accessed.
+class AccessedEntity {
+public:
+ /// A member declaration found through lookup. The target is the
+ /// member.
+ enum MemberNonce { Member };
+
+ /// A hierarchy (base-to-derived or derived-to-base) conversion.
+ /// The target is the base class.
+ enum BaseNonce { Base };
+
+ bool isMemberAccess() const { return IsMember; }
+
+ AccessedEntity(ASTContext &Context,
+ MemberNonce _,
+ CXXRecordDecl *NamingClass,
+ DeclAccessPair FoundDecl,
+ QualType BaseObjectType)
+ : Access(FoundDecl.getAccess()), IsMember(true),
+ Target(FoundDecl.getDecl()), NamingClass(NamingClass),
+ BaseObjectType(BaseObjectType), Diag(0, Context.getDiagAllocator()) {
+ }
+
+ AccessedEntity(ASTContext &Context,
+ BaseNonce _,
+ CXXRecordDecl *BaseClass,
+ CXXRecordDecl *DerivedClass,
+ AccessSpecifier Access)
+ : Access(Access), IsMember(false),
+ Target(BaseClass),
+ NamingClass(DerivedClass),
+ Diag(0, Context.getDiagAllocator()) {
+ }
+
+ bool isQuiet() const { return Diag.getDiagID() == 0; }
+
+ AccessSpecifier getAccess() const { return AccessSpecifier(Access); }
+
+ // These apply to member decls...
+ NamedDecl *getTargetDecl() const { return Target; }
+ CXXRecordDecl *getNamingClass() const { return NamingClass; }
+
+ // ...and these apply to hierarchy conversions.
+ CXXRecordDecl *getBaseClass() const {
+ assert(!IsMember); return cast<CXXRecordDecl>(Target);
+ }
+ CXXRecordDecl *getDerivedClass() const { return NamingClass; }
+
+ /// Retrieves the base object type, important when accessing
+ /// an instance member.
+ QualType getBaseObjectType() const { return BaseObjectType; }
+
+ /// Sets a diagnostic to be performed. The diagnostic is given
+ /// four (additional) arguments:
+ /// %0 - 0 if the entity was private, 1 if protected
+ /// %1 - the DeclarationName of the entity
+ /// %2 - the TypeDecl type of the naming class
+ /// %3 - the TypeDecl type of the declaring class
+ void setDiag(const PartialDiagnostic &PDiag) {
+ assert(isQuiet() && "partial diagnostic already defined");
+ Diag = PDiag;
+ }
+ PartialDiagnostic &setDiag(unsigned DiagID) {
+ assert(isQuiet() && "partial diagnostic already defined");
+ assert(DiagID && "creating null diagnostic");
+ Diag.Reset(DiagID);
+ return Diag;
+ }
+ const PartialDiagnostic &getDiag() const {
+ return Diag;
+ }
+
+private:
+ unsigned Access : 2;
+ bool IsMember;
+ NamedDecl *Target;
+ CXXRecordDecl *NamingClass;
+ QualType BaseObjectType;
+ PartialDiagnostic Diag;
+};
+
+/// A diagnostic message which has been conditionally emitted pending
+/// the complete parsing of the current declaration.
+class DelayedDiagnostic {
+public:
+ enum DDKind { Deprecation, Access };
+
+ unsigned char Kind; // actually a DDKind
+ bool Triggered;
+
+ SourceLocation Loc;
+
+ union {
+ /// Deprecation.
+ struct { NamedDecl *Decl; } DeprecationData;
+
+ /// Access control.
+ char AccessData[sizeof(AccessedEntity)];
+ };
+
+ void destroy() {
+ switch (Kind) {
+ case Access: getAccessData().~AccessedEntity(); break;
+ case Deprecation: break;
+ }
+ }
+
+ static DelayedDiagnostic makeDeprecation(SourceLocation Loc,
+ NamedDecl *D) {
+ DelayedDiagnostic DD;
+ DD.Kind = Deprecation;
+ DD.Triggered = false;
+ DD.Loc = Loc;
+ DD.DeprecationData.Decl = D;
+ return DD;
+ }
+
+ static DelayedDiagnostic makeAccess(SourceLocation Loc,
+ const AccessedEntity &Entity) {
+ DelayedDiagnostic DD;
+ DD.Kind = Access;
+ DD.Triggered = false;
+ DD.Loc = Loc;
+ new (&DD.getAccessData()) AccessedEntity(Entity);
+ return DD;
+ }
+
+ AccessedEntity &getAccessData() {
+ return *reinterpret_cast<AccessedEntity*>(AccessData);
+ }
+ const AccessedEntity &getAccessData() const {
+ return *reinterpret_cast<const AccessedEntity*>(AccessData);
+ }
+};
+
+}
+}
+
+#endif
diff --git a/include/clang/Parse/Designator.h b/include/clang/Sema/Designator.h
index 255af5901819..6fe7ab24f0a2 100644
--- a/include/clang/Parse/Designator.h
+++ b/include/clang/Sema/Designator.h
@@ -7,19 +7,26 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines interfaces used to represent Designators in the parser and
-// is the input to Actions module.
+// This file defines interfaces used to represent designators (a la
+// C99 designated initializers) during parsing.
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_PARSE_DESIGNATOR_H
-#define LLVM_CLANG_PARSE_DESIGNATOR_H
+#ifndef LLVM_CLANG_SEMA_DESIGNATOR_H
+#define LLVM_CLANG_SEMA_DESIGNATOR_H
-#include "clang/Parse/Action.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/SmallVector.h"
namespace clang {
-/// Designator - This class is a discriminated union which holds the various
+class Expr;
+class IdentifierInfo;
+class Sema;
+
+/// Designator - A designator in a C99 designated initializer.
+///
+/// This class is a discriminated union which holds the various
/// different sorts of designators possible. A Designation is an array of
/// these. An example of a designator are things like this:
/// [8] .field [47] // C99 designation: 3 designators
@@ -41,12 +48,12 @@ private:
unsigned NameLoc;
};
struct ArrayDesignatorInfo {
- ActionBase::ExprTy *Index;
+ Expr *Index;
unsigned LBracketLoc;
mutable unsigned RBracketLoc;
};
struct ArrayRangeDesignatorInfo {
- ActionBase::ExprTy *Start, *End;
+ Expr *Start, *End;
unsigned LBracketLoc, EllipsisLoc;
mutable unsigned RBracketLoc;
};
@@ -79,16 +86,16 @@ public:
return SourceLocation::getFromRawEncoding(FieldInfo.NameLoc);
}
- ActionBase::ExprTy *getArrayIndex() const {
+ Expr *getArrayIndex() const {
assert(isArrayDesignator() && "Invalid accessor");
return ArrayInfo.Index;
}
- ActionBase::ExprTy *getArrayRangeStart() const {
+ Expr *getArrayRangeStart() const {
assert(isArrayRangeDesignator() && "Invalid accessor");
return ArrayRangeInfo.Start;
}
- ActionBase::ExprTy *getArrayRangeEnd() const {
+ Expr *getArrayRangeEnd() const {
assert(isArrayRangeDesignator() && "Invalid accessor");
return ArrayRangeInfo.End;
}
@@ -126,7 +133,7 @@ public:
return D;
}
- static Designator getArray(ActionBase::ExprTy *Index,
+ static Designator getArray(Expr *Index,
SourceLocation LBracketLoc) {
Designator D;
D.Kind = ArrayDesignator;
@@ -136,8 +143,8 @@ public:
return D;
}
- static Designator getArrayRange(ActionBase::ExprTy *Start,
- ActionBase::ExprTy *End,
+ static Designator getArrayRange(Expr *Start,
+ Expr *End,
SourceLocation LBracketLoc,
SourceLocation EllipsisLoc) {
Designator D;
@@ -159,35 +166,13 @@ public:
ArrayRangeInfo.RBracketLoc = RBracketLoc.getRawEncoding();
}
- /// ClearExprs - Null out any expression references, which prevents them from
- /// being 'delete'd later.
- void ClearExprs(Action &Actions) {
- switch (Kind) {
- case FieldDesignator: return;
- case ArrayDesignator:
- ArrayInfo.Index = 0;
- return;
- case ArrayRangeDesignator:
- ArrayRangeInfo.Start = 0;
- ArrayRangeInfo.End = 0;
- return;
- }
- }
+ /// ClearExprs - Null out any expression references, which prevents
+ /// them from being 'delete'd later.
+ void ClearExprs(Sema &Actions) {}
- /// FreeExprs - Release any unclaimed memory for the expressions in this
- /// designator.
- void FreeExprs(Action &Actions) {
- switch (Kind) {
- case FieldDesignator: return; // nothing to free.
- case ArrayDesignator:
- Actions.DeleteExpr(getArrayIndex());
- return;
- case ArrayRangeDesignator:
- Actions.DeleteExpr(getArrayRangeStart());
- Actions.DeleteExpr(getArrayRangeEnd());
- return;
- }
- }
+ /// FreeExprs - Release any unclaimed memory for the expressions in
+ /// this designator.
+ void FreeExprs(Sema &Actions) {}
};
@@ -221,17 +206,11 @@ public:
/// ClearExprs - Null out any expression references, which prevents them from
/// being 'delete'd later.
- void ClearExprs(Action &Actions) {
- for (unsigned i = 0, e = Designators.size(); i != e; ++i)
- Designators[i].ClearExprs(Actions);
- }
+ void ClearExprs(Sema &Actions) {}
/// FreeExprs - Release any unclaimed memory for the expressions in this
/// designation.
- void FreeExprs(Action &Actions) {
- for (unsigned i = 0, e = Designators.size(); i != e; ++i)
- Designators[i].FreeExprs(Actions);
- }
+ void FreeExprs(Sema &Actions) {}
};
} // end namespace clang
diff --git a/include/clang/Sema/ExternalSemaSource.h b/include/clang/Sema/ExternalSemaSource.h
index ad42a847fa48..7be003390b10 100644
--- a/include/clang/Sema/ExternalSemaSource.h
+++ b/include/clang/Sema/ExternalSemaSource.h
@@ -13,8 +13,8 @@
#ifndef LLVM_CLANG_SEMA_EXTERNAL_SEMA_SOURCE_H
#define LLVM_CLANG_SEMA_EXTERNAL_SEMA_SOURCE_H
-#include "clang/AST/DeclObjC.h"
#include "clang/AST/ExternalASTSource.h"
+#include "clang/Sema/ObjCMethodList.h"
namespace clang {
diff --git a/include/clang/Sema/IdentifierResolver.h b/include/clang/Sema/IdentifierResolver.h
new file mode 100644
index 000000000000..7e9d338293ee
--- /dev/null
+++ b/include/clang/Sema/IdentifierResolver.h
@@ -0,0 +1,198 @@
+//===- IdentifierResolver.h - Lexical Scope Name lookup ---------*- 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 the IdentifierResolver class, which is used for lexical
+// scoped lookup, based on declaration names.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_SEMA_IDENTIFIERRESOLVER_H
+#define LLVM_CLANG_AST_SEMA_IDENTIFIERRESOLVER_H
+
+#include "clang/Basic/IdentifierTable.h"
+
+namespace clang {
+
+class ASTContext;
+class Decl;
+class DeclContext;
+class DeclarationName;
+class NamedDecl;
+class Scope;
+
+/// IdentifierResolver - Keeps track of shadowed decls on enclosing
+/// scopes. It manages the shadowing chains of declaration names and
+/// implements efficent decl lookup based on a declaration name.
+class IdentifierResolver {
+
+ /// IdDeclInfo - Keeps track of information about decls associated
+ /// to a particular declaration name. IdDeclInfos are lazily
+ /// constructed and assigned to a declaration name the first time a
+ /// decl with that declaration name is shadowed in some scope.
+ class IdDeclInfo {
+ public:
+ typedef llvm::SmallVector<NamedDecl*, 2> DeclsTy;
+
+ inline DeclsTy::iterator decls_begin() { return Decls.begin(); }
+ inline DeclsTy::iterator decls_end() { return Decls.end(); }
+
+ void AddDecl(NamedDecl *D) { Decls.push_back(D); }
+
+ /// RemoveDecl - Remove the decl from the scope chain.
+ /// The decl must already be part of the decl chain.
+ void RemoveDecl(NamedDecl *D);
+
+ /// Replaces the Old declaration with the New declaration. If the
+ /// replacement is successful, returns true. If the old
+ /// declaration was not found, returns false.
+ bool ReplaceDecl(NamedDecl *Old, NamedDecl *New);
+
+ private:
+ DeclsTy Decls;
+ };
+
+public:
+
+ /// iterator - Iterate over the decls of a specified declaration name.
+ /// It will walk or not the parent declaration contexts depending on how
+ /// it was instantiated.
+ class iterator {
+ public:
+ typedef NamedDecl * value_type;
+ typedef NamedDecl * reference;
+ typedef NamedDecl * pointer;
+ typedef std::input_iterator_tag iterator_category;
+ typedef std::ptrdiff_t difference_type;
+
+ /// Ptr - There are 3 forms that 'Ptr' represents:
+ /// 1) A single NamedDecl. (Ptr & 0x1 == 0)
+ /// 2) A IdDeclInfo::DeclsTy::iterator that traverses only the decls of the
+ /// same declaration context. (Ptr & 0x3 == 0x1)
+ /// 3) A IdDeclInfo::DeclsTy::iterator that traverses the decls of parent
+ /// declaration contexts too. (Ptr & 0x3 == 0x3)
+ uintptr_t Ptr;
+ typedef IdDeclInfo::DeclsTy::iterator BaseIter;
+
+ /// A single NamedDecl. (Ptr & 0x1 == 0)
+ iterator(NamedDecl *D) {
+ Ptr = reinterpret_cast<uintptr_t>(D);
+ assert((Ptr & 0x1) == 0 && "Invalid Ptr!");
+ }
+ /// A IdDeclInfo::DeclsTy::iterator that walks or not the parent declaration
+ /// contexts depending on 'LookInParentCtx'.
+ iterator(BaseIter I) {
+ Ptr = reinterpret_cast<uintptr_t>(I) | 0x1;
+ }
+
+ bool isIterator() const { return (Ptr & 0x1); }
+
+ BaseIter getIterator() const {
+ assert(isIterator() && "Ptr not an iterator!");
+ return reinterpret_cast<BaseIter>(Ptr & ~0x3);
+ }
+
+ friend class IdentifierResolver;
+
+ void incrementSlowCase();
+ public:
+ iterator() : Ptr(0) {}
+
+ NamedDecl *operator*() const {
+ if (isIterator())
+ return *getIterator();
+ else
+ return reinterpret_cast<NamedDecl*>(Ptr);
+ }
+
+ bool operator==(const iterator &RHS) const {
+ return Ptr == RHS.Ptr;
+ }
+ bool operator!=(const iterator &RHS) const {
+ return Ptr != RHS.Ptr;
+ }
+
+ // Preincrement.
+ iterator& operator++() {
+ if (!isIterator()) // common case.
+ Ptr = 0;
+ else
+ incrementSlowCase();
+ return *this;
+ }
+
+ uintptr_t getAsOpaqueValue() const { return Ptr; }
+
+ static iterator getFromOpaqueValue(uintptr_t P) {
+ iterator Result;
+ Result.Ptr = P;
+ return Result;
+ }
+ };
+
+ /// begin - Returns an iterator for decls with the name 'Name'.
+ static iterator begin(DeclarationName Name);
+
+ /// end - Returns an iterator that has 'finished'.
+ static iterator end() {
+ return iterator();
+ }
+
+ /// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true
+ /// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns
+ /// true if 'D' belongs to the given declaration context.
+ bool isDeclInScope(Decl *D, DeclContext *Ctx, ASTContext &Context,
+ Scope *S = 0) const;
+
+ /// AddDecl - Link the decl to its shadowed decl chain.
+ void AddDecl(NamedDecl *D);
+
+ /// RemoveDecl - Unlink the decl from its shadowed decl chain.
+ /// The decl must already be part of the decl chain.
+ void RemoveDecl(NamedDecl *D);
+
+ /// Replace the decl Old with the new declaration New on its
+ /// identifier chain. Returns true if the old declaration was found
+ /// (and, therefore, replaced).
+ bool ReplaceDecl(NamedDecl *Old, NamedDecl *New);
+
+ /// \brief Link the declaration into the chain of declarations for
+ /// the given identifier.
+ ///
+ /// This is a lower-level routine used by the AST reader to link a
+ /// declaration into a specific IdentifierInfo before the
+ /// declaration actually has a name.
+ void AddDeclToIdentifierChain(IdentifierInfo *II, NamedDecl *D);
+
+ explicit IdentifierResolver(const LangOptions &LangOpt);
+ ~IdentifierResolver();
+
+private:
+ const LangOptions &LangOpt;
+
+ class IdDeclInfoMap;
+ IdDeclInfoMap *IdDeclInfos;
+
+ /// FETokenInfo contains a Decl pointer if lower bit == 0.
+ static inline bool isDeclPtr(void *Ptr) {
+ return (reinterpret_cast<uintptr_t>(Ptr) & 0x1) == 0;
+ }
+
+ /// FETokenInfo contains a IdDeclInfo pointer if lower bit == 1.
+ static inline IdDeclInfo *toIdDeclInfo(void *Ptr) {
+ assert((reinterpret_cast<uintptr_t>(Ptr) & 0x1) == 1
+ && "Ptr not a IdDeclInfo* !");
+ return reinterpret_cast<IdDeclInfo*>(
+ reinterpret_cast<uintptr_t>(Ptr) & ~0x1
+ );
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Sema/Initialization.h b/include/clang/Sema/Initialization.h
new file mode 100644
index 000000000000..0062b3a29adc
--- /dev/null
+++ b/include/clang/Sema/Initialization.h
@@ -0,0 +1,780 @@
+//===--- SemaInit.h - Semantic Analysis for Initializers --------*- 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 supporting data types for initialization of objects.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_SEMA_INITIALIZATION_H
+#define LLVM_CLANG_SEMA_INITIALIZATION_H
+
+#include "clang/Sema/Ownership.h"
+#include "clang/Sema/Overload.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/UnresolvedSet.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/SmallVector.h"
+#include <cassert>
+
+namespace llvm {
+ class raw_ostream;
+}
+
+namespace clang {
+
+class CXXBaseSpecifier;
+class DeclaratorDecl;
+class DeclaratorInfo;
+class FieldDecl;
+class FunctionDecl;
+class ParmVarDecl;
+class Sema;
+class TypeLoc;
+class VarDecl;
+
+/// \brief Describes an entity that is being initialized.
+class InitializedEntity {
+public:
+ /// \brief Specifies the kind of entity being initialized.
+ enum EntityKind {
+ /// \brief The entity being initialized is a variable.
+ EK_Variable,
+ /// \brief The entity being initialized is a function parameter.
+ EK_Parameter,
+ /// \brief The entity being initialized is the result of a function call.
+ EK_Result,
+ /// \brief The entity being initialized is an exception object that
+ /// is being thrown.
+ EK_Exception,
+ /// \brief The entity being initialized is a non-static data member
+ /// subobject.
+ EK_Member,
+ /// \brief The entity being initialized is an element of an array.
+ EK_ArrayElement,
+ /// \brief The entity being initialized is an object (or array of
+ /// objects) allocated via new.
+ EK_New,
+ /// \brief The entity being initialized is a temporary object.
+ EK_Temporary,
+ /// \brief The entity being initialized is a base member subobject.
+ EK_Base,
+ /// \brief The entity being initialized is an element of a vector.
+ /// or vector.
+ EK_VectorElement,
+ /// \brief The entity being initialized is a field of block descriptor for
+ /// the copied-in c++ object.
+ EK_BlockElement
+ };
+
+private:
+ /// \brief The kind of entity being initialized.
+ EntityKind Kind;
+
+ /// \brief If non-NULL, the parent entity in which this
+ /// initialization occurs.
+ const InitializedEntity *Parent;
+
+ /// \brief The type of the object or reference being initialized.
+ QualType Type;
+
+ union {
+ /// \brief When Kind == EK_Variable, EK_Parameter, or EK_Member,
+ /// the VarDecl, ParmVarDecl, or FieldDecl, respectively.
+ DeclaratorDecl *VariableOrMember;
+
+ struct {
+ /// \brief When Kind == EK_Result, EK_Exception, or EK_New, the
+ /// location of the 'return', 'throw', or 'new' keyword,
+ /// respectively. When Kind == EK_Temporary, the location where
+ /// the temporary is being created.
+ unsigned Location;
+
+ /// \brief Whether the
+ bool NRVO;
+ } LocAndNRVO;
+
+ /// \brief When Kind == EK_Base, the base specifier that provides the
+ /// base class. The lower bit specifies whether the base is an inherited
+ /// virtual base.
+ uintptr_t Base;
+
+ /// \brief When Kind == EK_ArrayElement or EK_VectorElement, the
+ /// index of the array or vector element being initialized.
+ unsigned Index;
+ };
+
+ InitializedEntity() { }
+
+ /// \brief Create the initialization entity for a variable.
+ InitializedEntity(VarDecl *Var)
+ : Kind(EK_Variable), Parent(0), Type(Var->getType()),
+ VariableOrMember(reinterpret_cast<DeclaratorDecl*>(Var)) { }
+
+ /// \brief Create the initialization entity for a parameter.
+ InitializedEntity(ParmVarDecl *Parm)
+ : Kind(EK_Parameter), Parent(0), Type(Parm->getType().getUnqualifiedType()),
+ VariableOrMember(reinterpret_cast<DeclaratorDecl*>(Parm)) { }
+
+ /// \brief Create the initialization entity for the result of a
+ /// function, throwing an object, performing an explicit cast, or
+ /// initializing a parameter for which there is no declaration.
+ InitializedEntity(EntityKind Kind, SourceLocation Loc, QualType Type,
+ bool NRVO = false)
+ : Kind(Kind), Parent(0), Type(Type)
+ {
+ LocAndNRVO.Location = Loc.getRawEncoding();
+ LocAndNRVO.NRVO = NRVO;
+ }
+
+ /// \brief Create the initialization entity for a member subobject.
+ InitializedEntity(FieldDecl *Member, const InitializedEntity *Parent)
+ : Kind(EK_Member), Parent(Parent), Type(Member->getType()),
+ VariableOrMember(reinterpret_cast<DeclaratorDecl*>(Member)) { }
+
+ /// \brief Create the initialization entity for an array element.
+ InitializedEntity(ASTContext &Context, unsigned Index,
+ const InitializedEntity &Parent);
+
+public:
+ /// \brief Create the initialization entity for a variable.
+ static InitializedEntity InitializeVariable(VarDecl *Var) {
+ return InitializedEntity(Var);
+ }
+
+ /// \brief Create the initialization entity for a parameter.
+ static InitializedEntity InitializeParameter(ParmVarDecl *Parm) {
+ return InitializedEntity(Parm);
+ }
+
+ /// \brief Create the initialization entity for a parameter that is
+ /// only known by its type.
+ static InitializedEntity InitializeParameter(QualType Type) {
+ InitializedEntity Entity;
+ Entity.Kind = EK_Parameter;
+ Entity.Type = Type;
+ Entity.Parent = 0;
+ Entity.VariableOrMember = 0;
+ return Entity;
+ }
+
+ /// \brief Create the initialization entity for the result of a function.
+ static InitializedEntity InitializeResult(SourceLocation ReturnLoc,
+ QualType Type, bool NRVO) {
+ return InitializedEntity(EK_Result, ReturnLoc, Type, NRVO);
+ }
+
+ static InitializedEntity InitializeBlock(SourceLocation BlockVarLoc,
+ QualType Type, bool NRVO) {
+ return InitializedEntity(EK_BlockElement, BlockVarLoc, Type, NRVO);
+ }
+
+ /// \brief Create the initialization entity for an exception object.
+ static InitializedEntity InitializeException(SourceLocation ThrowLoc,
+ QualType Type, bool NRVO) {
+ return InitializedEntity(EK_Exception, ThrowLoc, Type, NRVO);
+ }
+
+ /// \brief Create the initialization entity for an object allocated via new.
+ static InitializedEntity InitializeNew(SourceLocation NewLoc, QualType Type) {
+ return InitializedEntity(EK_New, NewLoc, Type);
+ }
+
+ /// \brief Create the initialization entity for a temporary.
+ static InitializedEntity InitializeTemporary(QualType Type) {
+ return InitializedEntity(EK_Temporary, SourceLocation(), Type);
+ }
+
+ /// \brief Create the initialization entity for a base class subobject.
+ static InitializedEntity InitializeBase(ASTContext &Context,
+ CXXBaseSpecifier *Base,
+ bool IsInheritedVirtualBase);
+
+ /// \brief Create the initialization entity for a member subobject.
+ static InitializedEntity InitializeMember(FieldDecl *Member,
+ const InitializedEntity *Parent = 0) {
+ return InitializedEntity(Member, Parent);
+ }
+
+ /// \brief Create the initialization entity for an array element.
+ static InitializedEntity InitializeElement(ASTContext &Context,
+ unsigned Index,
+ const InitializedEntity &Parent) {
+ return InitializedEntity(Context, Index, Parent);
+ }
+
+ /// \brief Determine the kind of initialization.
+ EntityKind getKind() const { return Kind; }
+
+ /// \brief Retrieve the parent of the entity being initialized, when
+ /// the initialization itself is occuring within the context of a
+ /// larger initialization.
+ const InitializedEntity *getParent() const { return Parent; }
+
+ /// \brief Retrieve type being initialized.
+ QualType getType() const { return Type; }
+
+ /// \brief Retrieve the name of the entity being initialized.
+ DeclarationName getName() const;
+
+ /// \brief Retrieve the variable, parameter, or field being
+ /// initialized.
+ DeclaratorDecl *getDecl() const;
+
+ /// \brief Determine whether this initialization allows the named return
+ /// value optimization, which also applies to thrown objects.
+ bool allowsNRVO() const;
+
+ /// \brief Retrieve the base specifier.
+ CXXBaseSpecifier *getBaseSpecifier() const {
+ assert(getKind() == EK_Base && "Not a base specifier");
+ return reinterpret_cast<CXXBaseSpecifier *>(Base & ~0x1);
+ }
+
+ /// \brief Return whether the base is an inherited virtual base.
+ bool isInheritedVirtualBase() const {
+ assert(getKind() == EK_Base && "Not a base specifier");
+ return Base & 0x1;
+ }
+
+ /// \brief Determine the location of the 'return' keyword when initializing
+ /// the result of a function call.
+ SourceLocation getReturnLoc() const {
+ assert(getKind() == EK_Result && "No 'return' location!");
+ return SourceLocation::getFromRawEncoding(LocAndNRVO.Location);
+ }
+
+ /// \brief Determine the location of the 'throw' keyword when initializing
+ /// an exception object.
+ SourceLocation getThrowLoc() const {
+ assert(getKind() == EK_Exception && "No 'throw' location!");
+ return SourceLocation::getFromRawEncoding(LocAndNRVO.Location);
+ }
+
+ /// \brief If this is already the initializer for an array or vector
+ /// element, sets the element index.
+ void setElementIndex(unsigned Index) {
+ assert(getKind() == EK_ArrayElement || getKind() == EK_VectorElement);
+ this->Index = Index;
+ }
+};
+
+/// \brief Describes the kind of initialization being performed, along with
+/// location information for tokens related to the initialization (equal sign,
+/// parentheses).
+class InitializationKind {
+public:
+ /// \brief The kind of initialization being performed.
+ enum InitKind {
+ IK_Direct, ///< Direct initialization
+ IK_Copy, ///< Copy initialization
+ IK_Default, ///< Default initialization
+ IK_Value ///< Value initialization
+ };
+
+private:
+ /// \brief The kind of initialization that we're storing.
+ enum StoredInitKind {
+ SIK_Direct = IK_Direct, ///< Direct initialization
+ SIK_Copy = IK_Copy, ///< Copy initialization
+ SIK_Default = IK_Default, ///< Default initialization
+ SIK_Value = IK_Value, ///< Value initialization
+ SIK_ImplicitValue, ///< Implicit value initialization
+ SIK_DirectCast, ///< Direct initialization due to a cast
+ /// \brief Direct initialization due to a C-style or functional cast.
+ SIK_DirectCStyleOrFunctionalCast
+ };
+
+ /// \brief The kind of initialization being performed.
+ StoredInitKind Kind;
+
+ /// \brief The source locations involved in the initialization.
+ SourceLocation Locations[3];
+
+ InitializationKind(StoredInitKind Kind, SourceLocation Loc1,
+ SourceLocation Loc2, SourceLocation Loc3)
+ : Kind(Kind)
+ {
+ Locations[0] = Loc1;
+ Locations[1] = Loc2;
+ Locations[2] = Loc3;
+ }
+
+public:
+ /// \brief Create a direct initialization.
+ static InitializationKind CreateDirect(SourceLocation InitLoc,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc) {
+ return InitializationKind(SIK_Direct, InitLoc, LParenLoc, RParenLoc);
+ }
+
+ /// \brief Create a direct initialization due to a cast.
+ static InitializationKind CreateCast(SourceRange TypeRange,
+ bool IsCStyleCast) {
+ return InitializationKind(IsCStyleCast? SIK_DirectCStyleOrFunctionalCast
+ : SIK_DirectCast,
+ TypeRange.getBegin(), TypeRange.getBegin(),
+ TypeRange.getEnd());
+ }
+
+ /// \brief Create a copy initialization.
+ static InitializationKind CreateCopy(SourceLocation InitLoc,
+ SourceLocation EqualLoc) {
+ return InitializationKind(SIK_Copy, InitLoc, EqualLoc, EqualLoc);
+ }
+
+ /// \brief Create a default initialization.
+ static InitializationKind CreateDefault(SourceLocation InitLoc) {
+ return InitializationKind(SIK_Default, InitLoc, InitLoc, InitLoc);
+ }
+
+ /// \brief Create a value initialization.
+ static InitializationKind CreateValue(SourceLocation InitLoc,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc,
+ bool isImplicit = false) {
+ return InitializationKind(isImplicit? SIK_ImplicitValue : SIK_Value,
+ InitLoc, LParenLoc, RParenLoc);
+ }
+
+ /// \brief Determine the initialization kind.
+ InitKind getKind() const {
+ if (Kind > SIK_ImplicitValue)
+ return IK_Direct;
+ if (Kind == SIK_ImplicitValue)
+ return IK_Value;
+
+ return (InitKind)Kind;
+ }
+
+ /// \brief Determine whether this initialization is an explicit cast.
+ bool isExplicitCast() const {
+ return Kind == SIK_DirectCast || Kind == SIK_DirectCStyleOrFunctionalCast;
+ }
+
+ /// \brief Determine whether this initialization is a C-style cast.
+ bool isCStyleOrFunctionalCast() const {
+ return Kind == SIK_DirectCStyleOrFunctionalCast;
+ }
+
+ /// \brief Determine whether this initialization is an implicit
+ /// value-initialization, e.g., as occurs during aggregate
+ /// initialization.
+ bool isImplicitValueInit() const { return Kind == SIK_ImplicitValue; }
+
+ /// \brief Retrieve the location at which initialization is occurring.
+ SourceLocation getLocation() const { return Locations[0]; }
+
+ /// \brief Retrieve the source range that covers the initialization.
+ SourceRange getRange() const {
+ return SourceRange(Locations[0], Locations[2]);
+ }
+
+ /// \brief Retrieve the location of the equal sign for copy initialization
+ /// (if present).
+ SourceLocation getEqualLoc() const {
+ assert(Kind == SIK_Copy && "Only copy initialization has an '='");
+ return Locations[1];
+ }
+
+ bool isCopyInit() const { return Kind == SIK_Copy; }
+
+ /// \brief Retrieve the source range containing the locations of the open
+ /// and closing parentheses for value and direct initializations.
+ SourceRange getParenRange() const {
+ assert((getKind() == IK_Direct || Kind == SIK_Value) &&
+ "Only direct- and value-initialization have parentheses");
+ return SourceRange(Locations[1], Locations[2]);
+ }
+};
+
+/// \brief Describes the sequence of initializations required to initialize
+/// a given object or reference with a set of arguments.
+class InitializationSequence {
+public:
+ /// \brief Describes the kind of initialization sequence computed.
+ ///
+ /// FIXME: Much of this information is in the initialization steps... why is
+ /// it duplicated here?
+ enum SequenceKind {
+ /// \brief A failed initialization sequence. The failure kind tells what
+ /// happened.
+ FailedSequence = 0,
+
+ /// \brief A dependent initialization, which could not be
+ /// type-checked due to the presence of dependent types or
+ /// dependently-type expressions.
+ DependentSequence,
+
+ /// \brief A user-defined conversion sequence.
+ UserDefinedConversion,
+
+ /// \brief A constructor call.
+ ConstructorInitialization,
+
+ /// \brief A reference binding.
+ ReferenceBinding,
+
+ /// \brief List initialization
+ ListInitialization,
+
+ /// \brief Zero-initialization.
+ ZeroInitialization,
+
+ /// \brief No initialization required.
+ NoInitialization,
+
+ /// \brief Standard conversion sequence.
+ StandardConversion,
+
+ /// \brief C conversion sequence.
+ CAssignment,
+
+ /// \brief String initialization
+ StringInit
+ };
+
+ /// \brief Describes the kind of a particular step in an initialization
+ /// sequence.
+ enum StepKind {
+ /// \brief Resolve the address of an overloaded function to a specific
+ /// function declaration.
+ SK_ResolveAddressOfOverloadedFunction,
+ /// \brief Perform a derived-to-base cast, producing an rvalue.
+ SK_CastDerivedToBaseRValue,
+ /// \brief Perform a derived-to-base cast, producing an xvalue.
+ SK_CastDerivedToBaseXValue,
+ /// \brief Perform a derived-to-base cast, producing an lvalue.
+ SK_CastDerivedToBaseLValue,
+ /// \brief Reference binding to an lvalue.
+ SK_BindReference,
+ /// \brief Reference binding to a temporary.
+ SK_BindReferenceToTemporary,
+ /// \brief An optional copy of a temporary object to another
+ /// temporary object, which is permitted (but not required) by
+ /// C++98/03 but not C++0x.
+ SK_ExtraneousCopyToTemporary,
+ /// \brief Perform a user-defined conversion, either via a conversion
+ /// function or via a constructor.
+ SK_UserConversion,
+ /// \brief Perform a qualification conversion, producing an rvalue.
+ SK_QualificationConversionRValue,
+ /// \brief Perform a qualification conversion, producing an xvalue.
+ SK_QualificationConversionXValue,
+ /// \brief Perform a qualification conversion, producing an lvalue.
+ SK_QualificationConversionLValue,
+ /// \brief Perform an implicit conversion sequence.
+ SK_ConversionSequence,
+ /// \brief Perform list-initialization
+ SK_ListInitialization,
+ /// \brief Perform initialization via a constructor.
+ SK_ConstructorInitialization,
+ /// \brief Zero-initialize the object
+ SK_ZeroInitialization,
+ /// \brief C assignment
+ SK_CAssignment,
+ /// \brief Initialization by string
+ SK_StringInit,
+ /// \brief An initialization that "converts" an Objective-C object
+ /// (not a point to an object) to another Objective-C object type.
+ SK_ObjCObjectConversion
+ };
+
+ /// \brief A single step in the initialization sequence.
+ class Step {
+ public:
+ /// \brief The kind of conversion or initialization step we are taking.
+ StepKind Kind;
+
+ // \brief The type that results from this initialization.
+ QualType Type;
+
+ union {
+ /// \brief When Kind == SK_ResolvedOverloadedFunction or Kind ==
+ /// SK_UserConversion, the function that the expression should be
+ /// resolved to or the conversion function to call, respectively.
+ ///
+ /// Always a FunctionDecl.
+ /// For conversion decls, the naming class is the source type.
+ /// For construct decls, the naming class is the target type.
+ struct {
+ FunctionDecl *Function;
+ DeclAccessPair FoundDecl;
+ } Function;
+
+ /// \brief When Kind = SK_ConversionSequence, the implicit conversion
+ /// sequence
+ ImplicitConversionSequence *ICS;
+ };
+
+ void Destroy();
+ };
+
+private:
+ /// \brief The kind of initialization sequence computed.
+ enum SequenceKind SequenceKind;
+
+ /// \brief Steps taken by this initialization.
+ llvm::SmallVector<Step, 4> Steps;
+
+public:
+ /// \brief Describes why initialization failed.
+ enum FailureKind {
+ /// \brief Too many initializers provided for a reference.
+ FK_TooManyInitsForReference,
+ /// \brief Array must be initialized with an initializer list.
+ FK_ArrayNeedsInitList,
+ /// \brief Array must be initialized with an initializer list or a
+ /// string literal.
+ FK_ArrayNeedsInitListOrStringLiteral,
+ /// \brief Cannot resolve the address of an overloaded function.
+ FK_AddressOfOverloadFailed,
+ /// \brief Overloading due to reference initialization failed.
+ FK_ReferenceInitOverloadFailed,
+ /// \brief Non-const lvalue reference binding to a temporary.
+ FK_NonConstLValueReferenceBindingToTemporary,
+ /// \brief Non-const lvalue reference binding to an lvalue of unrelated
+ /// type.
+ FK_NonConstLValueReferenceBindingToUnrelated,
+ /// \brief Rvalue reference binding to an lvalue.
+ FK_RValueReferenceBindingToLValue,
+ /// \brief Reference binding drops qualifiers.
+ FK_ReferenceInitDropsQualifiers,
+ /// \brief Reference binding failed.
+ FK_ReferenceInitFailed,
+ /// \brief Implicit conversion failed.
+ FK_ConversionFailed,
+ /// \brief Too many initializers for scalar
+ FK_TooManyInitsForScalar,
+ /// \brief Reference initialization from an initializer list
+ FK_ReferenceBindingToInitList,
+ /// \brief Initialization of some unused destination type with an
+ /// initializer list.
+ FK_InitListBadDestinationType,
+ /// \brief Overloading for a user-defined conversion failed.
+ FK_UserConversionOverloadFailed,
+ /// \brief Overloaded for initialization by constructor failed.
+ FK_ConstructorOverloadFailed,
+ /// \brief Default-initialization of a 'const' object.
+ FK_DefaultInitOfConst,
+ /// \brief Initialization of an incomplete type.
+ FK_Incomplete
+ };
+
+private:
+ /// \brief The reason why initialization failued.
+ FailureKind Failure;
+
+ /// \brief The failed result of overload resolution.
+ OverloadingResult FailedOverloadResult;
+
+ /// \brief The candidate set created when initialization failed.
+ OverloadCandidateSet FailedCandidateSet;
+
+ /// \brief Prints a follow-up note that highlights the location of
+ /// the initialized entity, if it's remote.
+ void PrintInitLocationNote(Sema &S, const InitializedEntity &Entity);
+
+public:
+ /// \brief Try to perform initialization of the given entity, creating a
+ /// record of the steps required to perform the initialization.
+ ///
+ /// The generated initialization sequence will either contain enough
+ /// information to diagnose
+ ///
+ /// \param S the semantic analysis object.
+ ///
+ /// \param Entity the entity being initialized.
+ ///
+ /// \param Kind the kind of initialization being performed.
+ ///
+ /// \param Args the argument(s) provided for initialization.
+ ///
+ /// \param NumArgs the number of arguments provided for initialization.
+ InitializationSequence(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ Expr **Args,
+ unsigned NumArgs);
+
+ ~InitializationSequence();
+
+ /// \brief Perform the actual initialization of the given entity based on
+ /// the computed initialization sequence.
+ ///
+ /// \param S the semantic analysis object.
+ ///
+ /// \param Entity the entity being initialized.
+ ///
+ /// \param Kind the kind of initialization being performed.
+ ///
+ /// \param Args the argument(s) provided for initialization, ownership of
+ /// which is transfered into the routine.
+ ///
+ /// \param ResultType if non-NULL, will be set to the type of the
+ /// initialized object, which is the type of the declaration in most
+ /// cases. However, when the initialized object is a variable of
+ /// incomplete array type and the initializer is an initializer
+ /// list, this type will be set to the completed array type.
+ ///
+ /// \returns an expression that performs the actual object initialization, if
+ /// the initialization is well-formed. Otherwise, emits diagnostics
+ /// and returns an invalid expression.
+ ExprResult Perform(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ MultiExprArg Args,
+ QualType *ResultType = 0);
+
+ /// \brief Diagnose an potentially-invalid initialization sequence.
+ ///
+ /// \returns true if the initialization sequence was ill-formed,
+ /// false otherwise.
+ bool Diagnose(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ Expr **Args, unsigned NumArgs);
+
+ /// \brief Determine the kind of initialization sequence computed.
+ enum SequenceKind getKind() const { return SequenceKind; }
+
+ /// \brief Set the kind of sequence computed.
+ void setSequenceKind(enum SequenceKind SK) { SequenceKind = SK; }
+
+ /// \brief Determine whether the initialization sequence is valid.
+ operator bool() const { return SequenceKind != FailedSequence; }
+
+ typedef llvm::SmallVector<Step, 4>::const_iterator step_iterator;
+ step_iterator step_begin() const { return Steps.begin(); }
+ step_iterator step_end() const { return Steps.end(); }
+
+ /// \brief Determine whether this initialization is a direct reference
+ /// binding (C++ [dcl.init.ref]).
+ bool isDirectReferenceBinding() const;
+
+ /// \brief Determine whether this initialization failed due to an ambiguity.
+ bool isAmbiguous() const;
+
+ /// \brief Determine whether this initialization is direct call to a
+ /// constructor.
+ bool isConstructorInitialization() const;
+
+ /// \brief Add a new step in the initialization that resolves the address
+ /// of an overloaded function to a specific function declaration.
+ ///
+ /// \param Function the function to which the overloaded function reference
+ /// resolves.
+ void AddAddressOverloadResolutionStep(FunctionDecl *Function,
+ DeclAccessPair Found);
+
+ /// \brief Add a new step in the initialization that performs a derived-to-
+ /// base cast.
+ ///
+ /// \param BaseType the base type to which we will be casting.
+ ///
+ /// \param IsLValue true if the result of this cast will be treated as
+ /// an lvalue.
+ void AddDerivedToBaseCastStep(QualType BaseType,
+ ExprValueKind Category);
+
+ /// \brief Add a new step binding a reference to an object.
+ ///
+ /// \param BindingTemporary True if we are binding a reference to a temporary
+ /// object (thereby extending its lifetime); false if we are binding to an
+ /// lvalue or an lvalue treated as an rvalue.
+ ///
+ /// \param UnnecessaryCopy True if we should check for a copy
+ /// constructor for a completely unnecessary but
+ void AddReferenceBindingStep(QualType T, bool BindingTemporary);
+
+ /// \brief Add a new step that makes an extraneous copy of the input
+ /// to a temporary of the same class type.
+ ///
+ /// This extraneous copy only occurs during reference binding in
+ /// C++98/03, where we are permitted (but not required) to introduce
+ /// an extra copy. At a bare minimum, we must check that we could
+ /// call the copy constructor, and produce a diagnostic if the copy
+ /// constructor is inaccessible or no copy constructor matches.
+ //
+ /// \param T The type of the temporary being created.
+ void AddExtraneousCopyToTemporary(QualType T);
+
+ /// \brief Add a new step invoking a conversion function, which is either
+ /// a constructor or a conversion function.
+ void AddUserConversionStep(FunctionDecl *Function,
+ DeclAccessPair FoundDecl,
+ QualType T);
+
+ /// \brief Add a new step that performs a qualification conversion to the
+ /// given type.
+ void AddQualificationConversionStep(QualType Ty,
+ ExprValueKind Category);
+
+ /// \brief Add a new step that applies an implicit conversion sequence.
+ void AddConversionSequenceStep(const ImplicitConversionSequence &ICS,
+ QualType T);
+
+ /// \brief Add a list-initialiation step
+ void AddListInitializationStep(QualType T);
+
+ /// \brief Add a constructor-initialization step.
+ void AddConstructorInitializationStep(CXXConstructorDecl *Constructor,
+ AccessSpecifier Access,
+ QualType T);
+
+ /// \brief Add a zero-initialization step.
+ void AddZeroInitializationStep(QualType T);
+
+ /// \brief Add a C assignment step.
+ //
+ // FIXME: It isn't clear whether this should ever be needed;
+ // ideally, we would handle everything needed in C in the common
+ // path. However, that isn't the case yet.
+ void AddCAssignmentStep(QualType T);
+
+ /// \brief Add a string init step.
+ void AddStringInitStep(QualType T);
+
+ /// \brief Add an Objective-C object conversion step, which is
+ /// always a no-op.
+ void AddObjCObjectConversionStep(QualType T);
+
+ /// \brief Note that this initialization sequence failed.
+ void SetFailed(FailureKind Failure) {
+ SequenceKind = FailedSequence;
+ this->Failure = Failure;
+ }
+
+ /// \brief Note that this initialization sequence failed due to failed
+ /// overload resolution.
+ void SetOverloadFailure(FailureKind Failure, OverloadingResult Result);
+
+ /// \brief Retrieve a reference to the candidate set when overload
+ /// resolution fails.
+ OverloadCandidateSet &getFailedCandidateSet() {
+ return FailedCandidateSet;
+ }
+
+ /// \brief Determine why initialization failed.
+ FailureKind getFailureKind() const {
+ assert(getKind() == FailedSequence && "Not an initialization failure!");
+ return Failure;
+ }
+
+ /// \brief Dump a representation of this initialization sequence to
+ /// the given stream, for debugging purposes.
+ void dump(llvm::raw_ostream &OS) const;
+
+ /// \brief Dump a representation of this initialization sequence to
+ /// standard error, for debugging purposes.
+ void dump() const;
+};
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_SEMA_INITIALIZATION_H
diff --git a/include/clang/Sema/Lookup.h b/include/clang/Sema/Lookup.h
new file mode 100644
index 000000000000..1c7720abb1e1
--- /dev/null
+++ b/include/clang/Sema/Lookup.h
@@ -0,0 +1,679 @@
+//===--- Lookup.h - Classes for name lookup ---------------------*- 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 the LookupResult class, which is integral to
+// Sema's name-lookup subsystem.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_LOOKUP_H
+#define LLVM_CLANG_SEMA_LOOKUP_H
+
+#include "clang/Sema/Sema.h"
+#include "clang/AST/DeclCXX.h"
+
+namespace clang {
+
+/// @brief Represents the results of name lookup.
+///
+/// An instance of the LookupResult class captures the results of a
+/// single name lookup, which can return no result (nothing found),
+/// a single declaration, a set of overloaded functions, or an
+/// ambiguity. Use the getKind() method to determine which of these
+/// results occurred for a given lookup.
+class LookupResult {
+public:
+ enum LookupResultKind {
+ /// @brief No entity found met the criteria.
+ NotFound = 0,
+
+ /// @brief No entity found met the criteria within the current
+ /// instantiation,, but there were dependent base classes of the
+ /// current instantiation that could not be searched.
+ NotFoundInCurrentInstantiation,
+
+ /// @brief Name lookup found a single declaration that met the
+ /// criteria. getFoundDecl() will return this declaration.
+ Found,
+
+ /// @brief Name lookup found a set of overloaded functions that
+ /// met the criteria.
+ FoundOverloaded,
+
+ /// @brief Name lookup found an unresolvable value declaration
+ /// and cannot yet complete. This only happens in C++ dependent
+ /// contexts with dependent using declarations.
+ FoundUnresolvedValue,
+
+ /// @brief Name lookup results in an ambiguity; use
+ /// getAmbiguityKind to figure out what kind of ambiguity
+ /// we have.
+ Ambiguous
+ };
+
+ enum AmbiguityKind {
+ /// Name lookup results in an ambiguity because multiple
+ /// entities that meet the lookup criteria were found in
+ /// subobjects of different types. For example:
+ /// @code
+ /// struct A { void f(int); }
+ /// struct B { void f(double); }
+ /// struct C : A, B { };
+ /// void test(C c) {
+ /// c.f(0); // error: A::f and B::f come from subobjects of different
+ /// // types. overload resolution is not performed.
+ /// }
+ /// @endcode
+ AmbiguousBaseSubobjectTypes,
+
+ /// Name lookup results in an ambiguity because multiple
+ /// nonstatic entities that meet the lookup criteria were found
+ /// in different subobjects of the same type. For example:
+ /// @code
+ /// struct A { int x; };
+ /// struct B : A { };
+ /// struct C : A { };
+ /// struct D : B, C { };
+ /// int test(D d) {
+ /// return d.x; // error: 'x' is found in two A subobjects (of B and C)
+ /// }
+ /// @endcode
+ AmbiguousBaseSubobjects,
+
+ /// Name lookup results in an ambiguity because multiple definitions
+ /// of entity that meet the lookup criteria were found in different
+ /// declaration contexts.
+ /// @code
+ /// namespace A {
+ /// int i;
+ /// namespace B { int i; }
+ /// int test() {
+ /// using namespace B;
+ /// return i; // error 'i' is found in namespace A and A::B
+ /// }
+ /// }
+ /// @endcode
+ AmbiguousReference,
+
+ /// Name lookup results in an ambiguity because an entity with a
+ /// tag name was hidden by an entity with an ordinary name from
+ /// a different context.
+ /// @code
+ /// namespace A { struct Foo {}; }
+ /// namespace B { void Foo(); }
+ /// namespace C {
+ /// using namespace A;
+ /// using namespace B;
+ /// }
+ /// void test() {
+ /// C::Foo(); // error: tag 'A::Foo' is hidden by an object in a
+ /// // different namespace
+ /// }
+ /// @endcode
+ AmbiguousTagHiding
+ };
+
+ /// A little identifier for flagging temporary lookup results.
+ enum TemporaryToken {
+ Temporary
+ };
+
+ typedef UnresolvedSetImpl::iterator iterator;
+
+ LookupResult(Sema &SemaRef, const DeclarationNameInfo &NameInfo,
+ Sema::LookupNameKind LookupKind,
+ Sema::RedeclarationKind Redecl = Sema::NotForRedeclaration)
+ : ResultKind(NotFound),
+ Paths(0),
+ NamingClass(0),
+ SemaRef(SemaRef),
+ NameInfo(NameInfo),
+ LookupKind(LookupKind),
+ IDNS(0),
+ Redecl(Redecl != Sema::NotForRedeclaration),
+ HideTags(true),
+ Diagnose(Redecl == Sema::NotForRedeclaration)
+ {
+ configure();
+ }
+
+ // TODO: consider whether this constructor should be restricted to take
+ // as input a const IndentifierInfo* (instead of Name),
+ // forcing other cases towards the constructor taking a DNInfo.
+ LookupResult(Sema &SemaRef, DeclarationName Name,
+ SourceLocation NameLoc, Sema::LookupNameKind LookupKind,
+ Sema::RedeclarationKind Redecl = Sema::NotForRedeclaration)
+ : ResultKind(NotFound),
+ Paths(0),
+ NamingClass(0),
+ SemaRef(SemaRef),
+ NameInfo(Name, NameLoc),
+ LookupKind(LookupKind),
+ IDNS(0),
+ Redecl(Redecl != Sema::NotForRedeclaration),
+ HideTags(true),
+ Diagnose(Redecl == Sema::NotForRedeclaration)
+ {
+ configure();
+ }
+
+ /// Creates a temporary lookup result, initializing its core data
+ /// using the information from another result. Diagnostics are always
+ /// disabled.
+ LookupResult(TemporaryToken _, const LookupResult &Other)
+ : ResultKind(NotFound),
+ Paths(0),
+ NamingClass(0),
+ SemaRef(Other.SemaRef),
+ NameInfo(Other.NameInfo),
+ LookupKind(Other.LookupKind),
+ IDNS(Other.IDNS),
+ Redecl(Other.Redecl),
+ HideTags(Other.HideTags),
+ Diagnose(false)
+ {}
+
+ ~LookupResult() {
+ if (Diagnose) diagnose();
+ if (Paths) deletePaths(Paths);
+ }
+
+ /// Gets the name info to look up.
+ const DeclarationNameInfo &getLookupNameInfo() const {
+ return NameInfo;
+ }
+
+ /// \brief Sets the name info to look up.
+ void setLookupNameInfo(const DeclarationNameInfo &NameInfo) {
+ this->NameInfo = NameInfo;
+ }
+
+ /// Gets the name to look up.
+ DeclarationName getLookupName() const {
+ return NameInfo.getName();
+ }
+
+ /// \brief Sets the name to look up.
+ void setLookupName(DeclarationName Name) {
+ NameInfo.setName(Name);
+ }
+
+ /// Gets the kind of lookup to perform.
+ Sema::LookupNameKind getLookupKind() const {
+ return LookupKind;
+ }
+
+ /// True if this lookup is just looking for an existing declaration.
+ bool isForRedeclaration() const {
+ return Redecl;
+ }
+
+ /// Sets whether tag declarations should be hidden by non-tag
+ /// declarations during resolution. The default is true.
+ void setHideTags(bool Hide) {
+ HideTags = Hide;
+ }
+
+ bool isAmbiguous() const {
+ return getResultKind() == Ambiguous;
+ }
+
+ /// Determines if this names a single result which is not an
+ /// unresolved value using decl. If so, it is safe to call
+ /// getFoundDecl().
+ bool isSingleResult() const {
+ return getResultKind() == Found;
+ }
+
+ /// Determines if the results are overloaded.
+ bool isOverloadedResult() const {
+ return getResultKind() == FoundOverloaded;
+ }
+
+ bool isUnresolvableResult() const {
+ return getResultKind() == FoundUnresolvedValue;
+ }
+
+ LookupResultKind getResultKind() const {
+ sanity();
+ return ResultKind;
+ }
+
+ AmbiguityKind getAmbiguityKind() const {
+ assert(isAmbiguous());
+ return Ambiguity;
+ }
+
+ const UnresolvedSetImpl &asUnresolvedSet() const {
+ return Decls;
+ }
+
+ iterator begin() const { return iterator(Decls.begin()); }
+ iterator end() const { return iterator(Decls.end()); }
+
+ /// \brief Return true if no decls were found
+ bool empty() const { return Decls.empty(); }
+
+ /// \brief Return the base paths structure that's associated with
+ /// these results, or null if none is.
+ CXXBasePaths *getBasePaths() const {
+ return Paths;
+ }
+
+ /// \brief Tests whether the given declaration is acceptable.
+ bool isAcceptableDecl(NamedDecl *D) const {
+ return D->isInIdentifierNamespace(IDNS);
+ }
+
+ /// \brief Returns the identifier namespace mask for this lookup.
+ unsigned getIdentifierNamespace() const {
+ return IDNS;
+ }
+
+ /// \brief Returns whether these results arose from performing a
+ /// lookup into a class.
+ bool isClassLookup() const {
+ return NamingClass != 0;
+ }
+
+ /// \brief Returns the 'naming class' for this lookup, i.e. the
+ /// class which was looked into to find these results.
+ ///
+ /// C++0x [class.access.base]p5:
+ /// The access to a member is affected by the class in which the
+ /// member is named. This naming class is the class in which the
+ /// member name was looked up and found. [Note: this class can be
+ /// explicit, e.g., when a qualified-id is used, or implicit,
+ /// e.g., when a class member access operator (5.2.5) is used
+ /// (including cases where an implicit "this->" is added). If both
+ /// a class member access operator and a qualified-id are used to
+ /// name the member (as in p->T::m), the class naming the member
+ /// is the class named by the nested-name-specifier of the
+ /// qualified-id (that is, T). -- end note ]
+ ///
+ /// This is set by the lookup routines when they find results in a class.
+ CXXRecordDecl *getNamingClass() const {
+ return NamingClass;
+ }
+
+ /// \brief Sets the 'naming class' for this lookup.
+ void setNamingClass(CXXRecordDecl *Record) {
+ NamingClass = Record;
+ }
+
+ /// \brief Returns the base object type associated with this lookup;
+ /// important for [class.protected]. Most lookups do not have an
+ /// associated base object.
+ QualType getBaseObjectType() const {
+ return BaseObjectType;
+ }
+
+ /// \brief Sets the base object type for this lookup.
+ void setBaseObjectType(QualType T) {
+ BaseObjectType = T;
+ }
+
+ /// \brief Add a declaration to these results with its natural access.
+ /// Does not test the acceptance criteria.
+ void addDecl(NamedDecl *D) {
+ addDecl(D, D->getAccess());
+ }
+
+ /// \brief Add a declaration to these results with the given access.
+ /// Does not test the acceptance criteria.
+ void addDecl(NamedDecl *D, AccessSpecifier AS) {
+ Decls.addDecl(D, AS);
+ ResultKind = Found;
+ }
+
+ /// \brief Add all the declarations from another set of lookup
+ /// results.
+ void addAllDecls(const LookupResult &Other) {
+ Decls.append(Other.Decls.begin(), Other.Decls.end());
+ ResultKind = Found;
+ }
+
+ /// \brief Determine whether no result was found because we could not
+ /// search into dependent base classes of the current instantiation.
+ bool wasNotFoundInCurrentInstantiation() const {
+ return ResultKind == NotFoundInCurrentInstantiation;
+ }
+
+ /// \brief Note that while no result was found in the current instantiation,
+ /// there were dependent base classes that could not be searched.
+ void setNotFoundInCurrentInstantiation() {
+ assert(ResultKind == NotFound && Decls.empty());
+ ResultKind = NotFoundInCurrentInstantiation;
+ }
+
+ /// \brief Resolves the result kind of the lookup, possibly hiding
+ /// decls.
+ ///
+ /// This should be called in any environment where lookup might
+ /// generate multiple lookup results.
+ void resolveKind();
+
+ /// \brief Re-resolves the result kind of the lookup after a set of
+ /// removals has been performed.
+ void resolveKindAfterFilter() {
+ if (Decls.empty()) {
+ if (ResultKind != NotFoundInCurrentInstantiation)
+ ResultKind = NotFound;
+ } else {
+ AmbiguityKind SavedAK = Ambiguity;
+ ResultKind = Found;
+ resolveKind();
+
+ // If we didn't make the lookup unambiguous, restore the old
+ // ambiguity kind.
+ if (ResultKind == Ambiguous) {
+ Ambiguity = SavedAK;
+ } else if (Paths) {
+ deletePaths(Paths);
+ Paths = 0;
+ }
+ }
+ }
+
+ template <class DeclClass>
+ DeclClass *getAsSingle() const {
+ if (getResultKind() != Found) return 0;
+ return dyn_cast<DeclClass>(getFoundDecl());
+ }
+
+ /// \brief Fetch the unique decl found by this lookup. Asserts
+ /// that one was found.
+ ///
+ /// This is intended for users who have examined the result kind
+ /// and are certain that there is only one result.
+ NamedDecl *getFoundDecl() const {
+ assert(getResultKind() == Found
+ && "getFoundDecl called on non-unique result");
+ return (*begin())->getUnderlyingDecl();
+ }
+
+ /// Fetches a representative decl. Useful for lazy diagnostics.
+ NamedDecl *getRepresentativeDecl() const {
+ assert(!Decls.empty() && "cannot get representative of empty set");
+ return *begin();
+ }
+
+ /// \brief Asks if the result is a single tag decl.
+ bool isSingleTagDecl() const {
+ return getResultKind() == Found && isa<TagDecl>(getFoundDecl());
+ }
+
+ /// \brief Make these results show that the name was found in
+ /// base classes of different types.
+ ///
+ /// The given paths object is copied and invalidated.
+ void setAmbiguousBaseSubobjectTypes(CXXBasePaths &P);
+
+ /// \brief Make these results show that the name was found in
+ /// distinct base classes of the same type.
+ ///
+ /// The given paths object is copied and invalidated.
+ void setAmbiguousBaseSubobjects(CXXBasePaths &P);
+
+ /// \brief Make these results show that the name was found in
+ /// different contexts and a tag decl was hidden by an ordinary
+ /// decl in a different context.
+ void setAmbiguousQualifiedTagHiding() {
+ setAmbiguous(AmbiguousTagHiding);
+ }
+
+ /// \brief Clears out any current state.
+ void clear() {
+ ResultKind = NotFound;
+ Decls.clear();
+ if (Paths) deletePaths(Paths);
+ Paths = NULL;
+ }
+
+ /// \brief Clears out any current state and re-initializes for a
+ /// different kind of lookup.
+ void clear(Sema::LookupNameKind Kind) {
+ clear();
+ LookupKind = Kind;
+ configure();
+ }
+
+ /// \brief Change this lookup's redeclaration kind.
+ void setRedeclarationKind(Sema::RedeclarationKind RK) {
+ Redecl = RK;
+ configure();
+ }
+
+ void print(llvm::raw_ostream &);
+
+ /// Suppress the diagnostics that would normally fire because of this
+ /// lookup. This happens during (e.g.) redeclaration lookups.
+ void suppressDiagnostics() {
+ Diagnose = false;
+ }
+
+ /// Determines whether this lookup is suppressing diagnostics.
+ bool isSuppressingDiagnostics() const {
+ return !Diagnose;
+ }
+
+ /// Sets a 'context' source range.
+ void setContextRange(SourceRange SR) {
+ NameContextRange = SR;
+ }
+
+ /// Gets the source range of the context of this name; for C++
+ /// qualified lookups, this is the source range of the scope
+ /// specifier.
+ SourceRange getContextRange() const {
+ return NameContextRange;
+ }
+
+ /// Gets the location of the identifier. This isn't always defined:
+ /// sometimes we're doing lookups on synthesized names.
+ SourceLocation getNameLoc() const {
+ return NameInfo.getLoc();
+ }
+
+ /// \brief Get the Sema object that this lookup result is searching
+ /// with.
+ Sema &getSema() const { return SemaRef; }
+
+ /// A class for iterating through a result set and possibly
+ /// filtering out results. The results returned are possibly
+ /// sugared.
+ class Filter {
+ LookupResult &Results;
+ LookupResult::iterator I;
+ bool Changed;
+#ifndef NDEBUG
+ bool CalledDone;
+#endif
+
+ friend class LookupResult;
+ Filter(LookupResult &Results)
+ : Results(Results), I(Results.begin()), Changed(false)
+#ifndef NDEBUG
+ , CalledDone(false)
+#endif
+ {}
+
+ public:
+#ifndef NDEBUG
+ ~Filter() {
+ assert(CalledDone &&
+ "LookupResult::Filter destroyed without done() call");
+ }
+#endif
+
+ bool hasNext() const {
+ return I != Results.end();
+ }
+
+ NamedDecl *next() {
+ assert(I != Results.end() && "next() called on empty filter");
+ return *I++;
+ }
+
+ /// Erase the last element returned from this iterator.
+ void erase() {
+ Results.Decls.erase(--I);
+ Changed = true;
+ }
+
+ /// Replaces the current entry with the given one, preserving the
+ /// access bits.
+ void replace(NamedDecl *D) {
+ Results.Decls.replace(I-1, D);
+ Changed = true;
+ }
+
+ /// Replaces the current entry with the given one.
+ void replace(NamedDecl *D, AccessSpecifier AS) {
+ Results.Decls.replace(I-1, D, AS);
+ Changed = true;
+ }
+
+ void done() {
+#ifndef NDEBUG
+ assert(!CalledDone && "done() called twice");
+ CalledDone = true;
+#endif
+
+ if (Changed)
+ Results.resolveKindAfterFilter();
+ }
+ };
+
+ /// Create a filter for this result set.
+ Filter makeFilter() {
+ return Filter(*this);
+ }
+
+private:
+ void diagnose() {
+ if (isAmbiguous())
+ SemaRef.DiagnoseAmbiguousLookup(*this);
+ else if (isClassLookup() && SemaRef.getLangOptions().AccessControl)
+ SemaRef.CheckLookupAccess(*this);
+ }
+
+ void setAmbiguous(AmbiguityKind AK) {
+ ResultKind = Ambiguous;
+ Ambiguity = AK;
+ }
+
+ void addDeclsFromBasePaths(const CXXBasePaths &P);
+ void configure();
+
+ // Sanity checks.
+#ifndef NDEBUG
+ void sanity() const;
+#else
+ void sanity() const {}
+#endif
+
+ bool sanityCheckUnresolved() const {
+ for (iterator I = begin(), E = end(); I != E; ++I)
+ if (isa<UnresolvedUsingValueDecl>(*I))
+ return true;
+ return false;
+ }
+
+ static void deletePaths(CXXBasePaths *);
+
+ // Results.
+ LookupResultKind ResultKind;
+ AmbiguityKind Ambiguity; // ill-defined unless ambiguous
+ UnresolvedSet<8> Decls;
+ CXXBasePaths *Paths;
+ CXXRecordDecl *NamingClass;
+ QualType BaseObjectType;
+
+ // Parameters.
+ Sema &SemaRef;
+ DeclarationNameInfo NameInfo;
+ SourceRange NameContextRange;
+ Sema::LookupNameKind LookupKind;
+ unsigned IDNS; // set by configure()
+
+ bool Redecl;
+
+ /// \brief True if tag declarations should be hidden if non-tags
+ /// are present
+ bool HideTags;
+
+ bool Diagnose;
+};
+
+ /// \brief Consumes visible declarations found when searching for
+ /// all visible names within a given scope or context.
+ ///
+ /// This abstract class is meant to be subclassed by clients of \c
+ /// Sema::LookupVisibleDecls(), each of which should override the \c
+ /// FoundDecl() function to process declarations as they are found.
+ class VisibleDeclConsumer {
+ public:
+ /// \brief Destroys the visible declaration consumer.
+ virtual ~VisibleDeclConsumer();
+
+ /// \brief Invoked each time \p Sema::LookupVisibleDecls() finds a
+ /// declaration visible from the current scope or context.
+ ///
+ /// \param ND the declaration found.
+ ///
+ /// \param Hiding a declaration that hides the declaration \p ND,
+ /// or NULL if no such declaration exists.
+ ///
+ /// \param InBaseClass whether this declaration was found in base
+ /// class of the context we searched.
+ virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding,
+ bool InBaseClass) = 0;
+ };
+
+/// \brief A class for storing results from argument-dependent lookup.
+class ADLResult {
+private:
+ /// A map from canonical decls to the 'most recent' decl.
+ llvm::DenseMap<NamedDecl*, NamedDecl*> Decls;
+
+public:
+ /// Adds a new ADL candidate to this map.
+ void insert(NamedDecl *D);
+
+ /// Removes any data associated with a given decl.
+ void erase(NamedDecl *D) {
+ Decls.erase(cast<NamedDecl>(D->getCanonicalDecl()));
+ }
+
+ class iterator {
+ typedef llvm::DenseMap<NamedDecl*,NamedDecl*>::iterator inner_iterator;
+ inner_iterator iter;
+
+ friend class ADLResult;
+ iterator(const inner_iterator &iter) : iter(iter) {}
+ public:
+ iterator() {}
+
+ iterator &operator++() { ++iter; return *this; }
+ iterator operator++(int) { return iterator(iter++); }
+
+ NamedDecl *operator*() const { return iter->second; }
+
+ bool operator==(const iterator &other) const { return iter == other.iter; }
+ bool operator!=(const iterator &other) const { return iter != other.iter; }
+ };
+
+ iterator begin() { return iterator(Decls.begin()); }
+ iterator end() { return iterator(Decls.end()); }
+};
+
+}
+
+#endif
diff --git a/include/clang/Sema/ObjCMethodList.h b/include/clang/Sema/ObjCMethodList.h
new file mode 100644
index 000000000000..225c13776c59
--- /dev/null
+++ b/include/clang/Sema/ObjCMethodList.h
@@ -0,0 +1,38 @@
+//===--- ObjCMethodList.h - A singly linked list of methods -----*- 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 ObjCMethodList, a singly-linked list of methods.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_OBJC_METHOD_LIST_H
+#define LLVM_CLANG_SEMA_OBJC_METHOD_LIST_H
+
+namespace clang {
+
+class ObjCMethodDecl;
+
+/// ObjCMethodList - a linked list of methods with different signatures.
+struct ObjCMethodList {
+ ObjCMethodDecl *Method;
+ ObjCMethodList *Next;
+
+ ObjCMethodList() {
+ Method = 0;
+ Next = 0;
+ }
+ ObjCMethodList(ObjCMethodDecl *M, ObjCMethodList *C) {
+ Method = M;
+ Next = C;
+ }
+};
+
+}
+
+#endif
diff --git a/include/clang/Sema/Overload.h b/include/clang/Sema/Overload.h
new file mode 100644
index 000000000000..851d68ac4d79
--- /dev/null
+++ b/include/clang/Sema/Overload.h
@@ -0,0 +1,648 @@
+//===--- Overload.h - C++ Overloading ---------------------------*- 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 the data structures and types used in C++
+// overload resolution.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_OVERLOAD_H
+#define LLVM_CLANG_SEMA_OVERLOAD_H
+
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/TemplateBase.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/UnresolvedSet.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace clang {
+ class ASTContext;
+ class CXXConstructorDecl;
+ class CXXConversionDecl;
+ class FunctionDecl;
+ class Sema;
+
+ /// OverloadingResult - Capture the result of performing overload
+ /// resolution.
+ enum OverloadingResult {
+ OR_Success, ///< Overload resolution succeeded.
+ OR_No_Viable_Function, ///< No viable function found.
+ OR_Ambiguous, ///< Ambiguous candidates found.
+ OR_Deleted ///< Succeeded, but refers to a deleted function.
+ };
+
+ enum OverloadCandidateDisplayKind {
+ /// Requests that all candidates be shown. Viable candidates will
+ /// be printed first.
+ OCD_AllCandidates,
+
+ /// Requests that only viable candidates be shown.
+ OCD_ViableCandidates
+ };
+
+ /// ImplicitConversionKind - The kind of implicit conversion used to
+ /// convert an argument to a parameter's type. The enumerator values
+ /// match with Table 9 of (C++ 13.3.3.1.1) and are listed such that
+ /// better conversion kinds have smaller values.
+ enum ImplicitConversionKind {
+ ICK_Identity = 0, ///< Identity conversion (no conversion)
+ ICK_Lvalue_To_Rvalue, ///< Lvalue-to-rvalue conversion (C++ 4.1)
+ ICK_Array_To_Pointer, ///< Array-to-pointer conversion (C++ 4.2)
+ ICK_Function_To_Pointer, ///< Function-to-pointer (C++ 4.3)
+ ICK_NoReturn_Adjustment, ///< Removal of noreturn from a type (Clang)
+ ICK_Qualification, ///< Qualification conversions (C++ 4.4)
+ ICK_Integral_Promotion, ///< Integral promotions (C++ 4.5)
+ ICK_Floating_Promotion, ///< Floating point promotions (C++ 4.6)
+ ICK_Complex_Promotion, ///< Complex promotions (Clang extension)
+ ICK_Integral_Conversion, ///< Integral conversions (C++ 4.7)
+ ICK_Floating_Conversion, ///< Floating point conversions (C++ 4.8)
+ ICK_Complex_Conversion, ///< Complex conversions (C99 6.3.1.6)
+ ICK_Floating_Integral, ///< Floating-integral conversions (C++ 4.9)
+ ICK_Pointer_Conversion, ///< Pointer conversions (C++ 4.10)
+ ICK_Pointer_Member, ///< Pointer-to-member conversions (C++ 4.11)
+ ICK_Boolean_Conversion, ///< Boolean conversions (C++ 4.12)
+ ICK_Compatible_Conversion, ///< Conversions between compatible types in C99
+ ICK_Derived_To_Base, ///< Derived-to-base (C++ [over.best.ics])
+ ICK_Vector_Conversion, ///< Vector conversions
+ ICK_Vector_Splat, ///< A vector splat from an arithmetic type
+ ICK_Complex_Real, ///< Complex-real conversions (C99 6.3.1.7)
+ ICK_Num_Conversion_Kinds ///< The number of conversion kinds
+ };
+
+ /// ImplicitConversionCategory - The category of an implicit
+ /// conversion kind. The enumerator values match with Table 9 of
+ /// (C++ 13.3.3.1.1) and are listed such that better conversion
+ /// categories have smaller values.
+ enum ImplicitConversionCategory {
+ ICC_Identity = 0, ///< Identity
+ ICC_Lvalue_Transformation, ///< Lvalue transformation
+ ICC_Qualification_Adjustment, ///< Qualification adjustment
+ ICC_Promotion, ///< Promotion
+ ICC_Conversion ///< Conversion
+ };
+
+ ImplicitConversionCategory
+ GetConversionCategory(ImplicitConversionKind Kind);
+
+ /// ImplicitConversionRank - The rank of an implicit conversion
+ /// kind. The enumerator values match with Table 9 of (C++
+ /// 13.3.3.1.1) and are listed such that better conversion ranks
+ /// have smaller values.
+ enum ImplicitConversionRank {
+ ICR_Exact_Match = 0, ///< Exact Match
+ ICR_Promotion, ///< Promotion
+ ICR_Conversion, ///< Conversion
+ ICR_Complex_Real_Conversion ///< Complex <-> Real conversion
+ };
+
+ ImplicitConversionRank GetConversionRank(ImplicitConversionKind Kind);
+
+ /// StandardConversionSequence - represents a standard conversion
+ /// sequence (C++ 13.3.3.1.1). A standard conversion sequence
+ /// contains between zero and three conversions. If a particular
+ /// conversion is not needed, it will be set to the identity conversion
+ /// (ICK_Identity). Note that the three conversions are
+ /// specified as separate members (rather than in an array) so that
+ /// we can keep the size of a standard conversion sequence to a
+ /// single word.
+ class StandardConversionSequence {
+ public:
+ /// First -- The first conversion can be an lvalue-to-rvalue
+ /// conversion, array-to-pointer conversion, or
+ /// function-to-pointer conversion.
+ ImplicitConversionKind First : 8;
+
+ /// Second - The second conversion can be an integral promotion,
+ /// floating point promotion, integral conversion, floating point
+ /// conversion, floating-integral conversion, pointer conversion,
+ /// pointer-to-member conversion, or boolean conversion.
+ ImplicitConversionKind Second : 8;
+
+ /// Third - The third conversion can be a qualification conversion.
+ ImplicitConversionKind Third : 8;
+
+ /// Deprecated - Whether this the deprecated conversion of a
+ /// string literal to a pointer to non-const character data
+ /// (C++ 4.2p2).
+ bool DeprecatedStringLiteralToCharPtr : 1;
+
+ /// IncompatibleObjC - Whether this is an Objective-C conversion
+ /// that we should warn about (if we actually use it).
+ bool IncompatibleObjC : 1;
+
+ /// ReferenceBinding - True when this is a reference binding
+ /// (C++ [over.ics.ref]).
+ bool ReferenceBinding : 1;
+
+ /// DirectBinding - True when this is a reference binding that is a
+ /// direct binding (C++ [dcl.init.ref]).
+ bool DirectBinding : 1;
+
+ /// RRefBinding - True when this is a reference binding of an rvalue
+ /// reference to an rvalue (C++0x [over.ics.rank]p3b4).
+ bool RRefBinding : 1;
+
+ /// FromType - The type that this conversion is converting
+ /// from. This is an opaque pointer that can be translated into a
+ /// QualType.
+ void *FromTypePtr;
+
+ /// ToType - The types that this conversion is converting to in
+ /// each step. This is an opaque pointer that can be translated
+ /// into a QualType.
+ void *ToTypePtrs[3];
+
+ /// CopyConstructor - The copy constructor that is used to perform
+ /// this conversion, when the conversion is actually just the
+ /// initialization of an object via copy constructor. Such
+ /// conversions are either identity conversions or derived-to-base
+ /// conversions.
+ CXXConstructorDecl *CopyConstructor;
+
+ void setFromType(QualType T) { FromTypePtr = T.getAsOpaquePtr(); }
+ void setToType(unsigned Idx, QualType T) {
+ assert(Idx < 3 && "To type index is out of range");
+ ToTypePtrs[Idx] = T.getAsOpaquePtr();
+ }
+ void setAllToTypes(QualType T) {
+ ToTypePtrs[0] = T.getAsOpaquePtr();
+ ToTypePtrs[1] = ToTypePtrs[0];
+ ToTypePtrs[2] = ToTypePtrs[0];
+ }
+
+ QualType getFromType() const {
+ return QualType::getFromOpaquePtr(FromTypePtr);
+ }
+ QualType getToType(unsigned Idx) const {
+ assert(Idx < 3 && "To type index is out of range");
+ return QualType::getFromOpaquePtr(ToTypePtrs[Idx]);
+ }
+
+ void setAsIdentityConversion();
+
+ bool isIdentityConversion() const {
+ return First == ICK_Identity && Second == ICK_Identity &&
+ Third == ICK_Identity;
+ }
+
+ ImplicitConversionRank getRank() const;
+ bool isPointerConversionToBool() const;
+ bool isPointerConversionToVoidPointer(ASTContext& Context) const;
+ void DebugPrint() const;
+ };
+
+ /// UserDefinedConversionSequence - Represents a user-defined
+ /// conversion sequence (C++ 13.3.3.1.2).
+ struct UserDefinedConversionSequence {
+ /// Before - Represents the standard conversion that occurs before
+ /// the actual user-defined conversion. (C++ 13.3.3.1.2p1):
+ ///
+ /// If the user-defined conversion is specified by a constructor
+ /// (12.3.1), the initial standard conversion sequence converts
+ /// the source type to the type required by the argument of the
+ /// constructor. If the user-defined conversion is specified by
+ /// a conversion function (12.3.2), the initial standard
+ /// conversion sequence converts the source type to the implicit
+ /// object parameter of the conversion function.
+ StandardConversionSequence Before;
+
+ /// EllipsisConversion - When this is true, it means user-defined
+ /// conversion sequence starts with a ... (elipsis) conversion, instead of
+ /// a standard conversion. In this case, 'Before' field must be ignored.
+ // FIXME. I much rather put this as the first field. But there seems to be
+ // a gcc code gen. bug which causes a crash in a test. Putting it here seems
+ // to work around the crash.
+ bool EllipsisConversion : 1;
+
+ /// After - Represents the standard conversion that occurs after
+ /// the actual user-defined conversion.
+ StandardConversionSequence After;
+
+ /// ConversionFunction - The function that will perform the
+ /// user-defined conversion.
+ FunctionDecl* ConversionFunction;
+
+ void DebugPrint() const;
+ };
+
+ /// Represents an ambiguous user-defined conversion sequence.
+ struct AmbiguousConversionSequence {
+ typedef llvm::SmallVector<FunctionDecl*, 4> ConversionSet;
+
+ void *FromTypePtr;
+ void *ToTypePtr;
+ char Buffer[sizeof(ConversionSet)];
+
+ QualType getFromType() const {
+ return QualType::getFromOpaquePtr(FromTypePtr);
+ }
+ QualType getToType() const {
+ return QualType::getFromOpaquePtr(ToTypePtr);
+ }
+ void setFromType(QualType T) { FromTypePtr = T.getAsOpaquePtr(); }
+ void setToType(QualType T) { ToTypePtr = T.getAsOpaquePtr(); }
+
+ ConversionSet &conversions() {
+ return *reinterpret_cast<ConversionSet*>(Buffer);
+ }
+
+ const ConversionSet &conversions() const {
+ return *reinterpret_cast<const ConversionSet*>(Buffer);
+ }
+
+ void addConversion(FunctionDecl *D) {
+ conversions().push_back(D);
+ }
+
+ typedef ConversionSet::iterator iterator;
+ iterator begin() { return conversions().begin(); }
+ iterator end() { return conversions().end(); }
+
+ typedef ConversionSet::const_iterator const_iterator;
+ const_iterator begin() const { return conversions().begin(); }
+ const_iterator end() const { return conversions().end(); }
+
+ void construct();
+ void destruct();
+ void copyFrom(const AmbiguousConversionSequence &);
+ };
+
+ /// BadConversionSequence - Records information about an invalid
+ /// conversion sequence.
+ struct BadConversionSequence {
+ enum FailureKind {
+ no_conversion,
+ unrelated_class,
+ suppressed_user,
+ bad_qualifiers
+ };
+
+ // This can be null, e.g. for implicit object arguments.
+ Expr *FromExpr;
+
+ FailureKind Kind;
+
+ private:
+ // The type we're converting from (an opaque QualType).
+ void *FromTy;
+
+ // The type we're converting to (an opaque QualType).
+ void *ToTy;
+
+ public:
+ void init(FailureKind K, Expr *From, QualType To) {
+ init(K, From->getType(), To);
+ FromExpr = From;
+ }
+ void init(FailureKind K, QualType From, QualType To) {
+ Kind = K;
+ FromExpr = 0;
+ setFromType(From);
+ setToType(To);
+ }
+
+ QualType getFromType() const { return QualType::getFromOpaquePtr(FromTy); }
+ QualType getToType() const { return QualType::getFromOpaquePtr(ToTy); }
+
+ void setFromExpr(Expr *E) {
+ FromExpr = E;
+ setFromType(E->getType());
+ }
+ void setFromType(QualType T) { FromTy = T.getAsOpaquePtr(); }
+ void setToType(QualType T) { ToTy = T.getAsOpaquePtr(); }
+ };
+
+ /// ImplicitConversionSequence - Represents an implicit conversion
+ /// sequence, which may be a standard conversion sequence
+ /// (C++ 13.3.3.1.1), user-defined conversion sequence (C++ 13.3.3.1.2),
+ /// or an ellipsis conversion sequence (C++ 13.3.3.1.3).
+ class ImplicitConversionSequence {
+ public:
+ /// Kind - The kind of implicit conversion sequence. BadConversion
+ /// specifies that there is no conversion from the source type to
+ /// the target type. AmbiguousConversion represents the unique
+ /// ambiguous conversion (C++0x [over.best.ics]p10).
+ enum Kind {
+ StandardConversion = 0,
+ UserDefinedConversion,
+ AmbiguousConversion,
+ EllipsisConversion,
+ BadConversion
+ };
+
+ private:
+ enum {
+ Uninitialized = BadConversion + 1
+ };
+
+ /// ConversionKind - The kind of implicit conversion sequence.
+ unsigned ConversionKind;
+
+ void setKind(Kind K) {
+ destruct();
+ ConversionKind = K;
+ }
+
+ void destruct() {
+ if (ConversionKind == AmbiguousConversion) Ambiguous.destruct();
+ }
+
+ public:
+ union {
+ /// When ConversionKind == StandardConversion, provides the
+ /// details of the standard conversion sequence.
+ StandardConversionSequence Standard;
+
+ /// When ConversionKind == UserDefinedConversion, provides the
+ /// details of the user-defined conversion sequence.
+ UserDefinedConversionSequence UserDefined;
+
+ /// When ConversionKind == AmbiguousConversion, provides the
+ /// details of the ambiguous conversion.
+ AmbiguousConversionSequence Ambiguous;
+
+ /// When ConversionKind == BadConversion, provides the details
+ /// of the bad conversion.
+ BadConversionSequence Bad;
+ };
+
+ ImplicitConversionSequence() : ConversionKind(Uninitialized) {}
+ ~ImplicitConversionSequence() {
+ destruct();
+ }
+ ImplicitConversionSequence(const ImplicitConversionSequence &Other)
+ : ConversionKind(Other.ConversionKind)
+ {
+ switch (ConversionKind) {
+ case Uninitialized: break;
+ case StandardConversion: Standard = Other.Standard; break;
+ case UserDefinedConversion: UserDefined = Other.UserDefined; break;
+ case AmbiguousConversion: Ambiguous.copyFrom(Other.Ambiguous); break;
+ case EllipsisConversion: break;
+ case BadConversion: Bad = Other.Bad; break;
+ }
+ }
+
+ ImplicitConversionSequence &
+ operator=(const ImplicitConversionSequence &Other) {
+ destruct();
+ new (this) ImplicitConversionSequence(Other);
+ return *this;
+ }
+
+ Kind getKind() const {
+ assert(isInitialized() && "querying uninitialized conversion");
+ return Kind(ConversionKind);
+ }
+
+ /// \brief Return a ranking of the implicit conversion sequence
+ /// kind, where smaller ranks represent better conversion
+ /// sequences.
+ ///
+ /// In particular, this routine gives user-defined conversion
+ /// sequences and ambiguous conversion sequences the same rank,
+ /// per C++ [over.best.ics]p10.
+ unsigned getKindRank() const {
+ switch (getKind()) {
+ case StandardConversion:
+ return 0;
+
+ case UserDefinedConversion:
+ case AmbiguousConversion:
+ return 1;
+
+ case EllipsisConversion:
+ return 2;
+
+ case BadConversion:
+ return 3;
+ }
+
+ return 3;
+ }
+
+ bool isBad() const { return getKind() == BadConversion; }
+ bool isStandard() const { return getKind() == StandardConversion; }
+ bool isEllipsis() const { return getKind() == EllipsisConversion; }
+ bool isAmbiguous() const { return getKind() == AmbiguousConversion; }
+ bool isUserDefined() const { return getKind() == UserDefinedConversion; }
+
+ /// Determines whether this conversion sequence has been
+ /// initialized. Most operations should never need to query
+ /// uninitialized conversions and should assert as above.
+ bool isInitialized() const { return ConversionKind != Uninitialized; }
+
+ /// Sets this sequence as a bad conversion for an explicit argument.
+ void setBad(BadConversionSequence::FailureKind Failure,
+ Expr *FromExpr, QualType ToType) {
+ setKind(BadConversion);
+ Bad.init(Failure, FromExpr, ToType);
+ }
+
+ /// Sets this sequence as a bad conversion for an implicit argument.
+ void setBad(BadConversionSequence::FailureKind Failure,
+ QualType FromType, QualType ToType) {
+ setKind(BadConversion);
+ Bad.init(Failure, FromType, ToType);
+ }
+
+ void setStandard() { setKind(StandardConversion); }
+ void setEllipsis() { setKind(EllipsisConversion); }
+ void setUserDefined() { setKind(UserDefinedConversion); }
+ void setAmbiguous() {
+ if (ConversionKind == AmbiguousConversion) return;
+ ConversionKind = AmbiguousConversion;
+ Ambiguous.construct();
+ }
+
+ // The result of a comparison between implicit conversion
+ // sequences. Use Sema::CompareImplicitConversionSequences to
+ // actually perform the comparison.
+ enum CompareKind {
+ Better = -1,
+ Indistinguishable = 0,
+ Worse = 1
+ };
+
+ void DiagnoseAmbiguousConversion(Sema &S,
+ SourceLocation CaretLoc,
+ const PartialDiagnostic &PDiag) const;
+
+ void DebugPrint() const;
+ };
+
+ enum OverloadFailureKind {
+ ovl_fail_too_many_arguments,
+ ovl_fail_too_few_arguments,
+ ovl_fail_bad_conversion,
+ ovl_fail_bad_deduction,
+
+ /// This conversion candidate was not considered because it
+ /// duplicates the work of a trivial or derived-to-base
+ /// conversion.
+ ovl_fail_trivial_conversion,
+
+ /// This conversion candidate is not viable because its result
+ /// type is not implicitly convertible to the desired type.
+ ovl_fail_bad_final_conversion,
+
+ /// This conversion function template specialization candidate is not
+ /// viable because the final conversion was not an exact match.
+ ovl_fail_final_conversion_not_exact
+ };
+
+ /// OverloadCandidate - A single candidate in an overload set (C++ 13.3).
+ struct OverloadCandidate {
+ /// Function - The actual function that this candidate
+ /// represents. When NULL, this is a built-in candidate
+ /// (C++ [over.oper]) or a surrogate for a conversion to a
+ /// function pointer or reference (C++ [over.call.object]).
+ FunctionDecl *Function;
+
+ /// FoundDecl - The original declaration that was looked up /
+ /// invented / otherwise found, together with its access.
+ /// Might be a UsingShadowDecl or a FunctionTemplateDecl.
+ DeclAccessPair FoundDecl;
+
+ // BuiltinTypes - Provides the return and parameter types of a
+ // built-in overload candidate. Only valid when Function is NULL.
+ struct {
+ QualType ResultTy;
+ QualType ParamTypes[3];
+ } BuiltinTypes;
+
+ /// Surrogate - The conversion function for which this candidate
+ /// is a surrogate, but only if IsSurrogate is true.
+ CXXConversionDecl *Surrogate;
+
+ /// Conversions - The conversion sequences used to convert the
+ /// function arguments to the function parameters.
+ llvm::SmallVector<ImplicitConversionSequence, 4> Conversions;
+
+ /// Viable - True to indicate that this overload candidate is viable.
+ bool Viable;
+
+ /// IsSurrogate - True to indicate that this candidate is a
+ /// surrogate for a conversion to a function pointer or reference
+ /// (C++ [over.call.object]).
+ bool IsSurrogate;
+
+ /// IgnoreObjectArgument - True to indicate that the first
+ /// argument's conversion, which for this function represents the
+ /// implicit object argument, should be ignored. This will be true
+ /// when the candidate is a static member function (where the
+ /// implicit object argument is just a placeholder) or a
+ /// non-static member function when the call doesn't have an
+ /// object argument.
+ bool IgnoreObjectArgument;
+
+ /// FailureKind - The reason why this candidate is not viable.
+ /// Actually an OverloadFailureKind.
+ unsigned char FailureKind;
+
+ /// A structure used to record information about a failed
+ /// template argument deduction.
+ struct DeductionFailureInfo {
+ // A Sema::TemplateDeductionResult.
+ unsigned Result;
+
+ /// \brief Opaque pointer containing additional data about
+ /// this deduction failure.
+ void *Data;
+
+ /// \brief Retrieve the template parameter this deduction failure
+ /// refers to, if any.
+ TemplateParameter getTemplateParameter();
+
+ /// \brief Retrieve the template argument list associated with this
+ /// deduction failure, if any.
+ TemplateArgumentList *getTemplateArgumentList();
+
+ /// \brief Return the first template argument this deduction failure
+ /// refers to, if any.
+ const TemplateArgument *getFirstArg();
+
+ /// \brief Return the second template argument this deduction failure
+ /// refers to, if any.
+ const TemplateArgument *getSecondArg();
+
+ /// \brief Free any memory associated with this deduction failure.
+ void Destroy();
+ };
+
+ union {
+ DeductionFailureInfo DeductionFailure;
+
+ /// FinalConversion - For a conversion function (where Function is
+ /// a CXXConversionDecl), the standard conversion that occurs
+ /// after the call to the overload candidate to convert the result
+ /// of calling the conversion function to the required type.
+ StandardConversionSequence FinalConversion;
+ };
+
+ /// hasAmbiguousConversion - Returns whether this overload
+ /// candidate requires an ambiguous conversion or not.
+ bool hasAmbiguousConversion() const {
+ for (llvm::SmallVectorImpl<ImplicitConversionSequence>::const_iterator
+ I = Conversions.begin(), E = Conversions.end(); I != E; ++I) {
+ if (!I->isInitialized()) return false;
+ if (I->isAmbiguous()) return true;
+ }
+ return false;
+ }
+ };
+
+ /// OverloadCandidateSet - A set of overload candidates, used in C++
+ /// overload resolution (C++ 13.3).
+ class OverloadCandidateSet : public llvm::SmallVector<OverloadCandidate, 16> {
+ typedef llvm::SmallVector<OverloadCandidate, 16> inherited;
+ llvm::SmallPtrSet<Decl *, 16> Functions;
+
+ SourceLocation Loc;
+
+ OverloadCandidateSet(const OverloadCandidateSet &);
+ OverloadCandidateSet &operator=(const OverloadCandidateSet &);
+
+ public:
+ OverloadCandidateSet(SourceLocation Loc) : Loc(Loc) {}
+
+ SourceLocation getLocation() const { return Loc; }
+
+ /// \brief Determine when this overload candidate will be new to the
+ /// overload set.
+ bool isNewCandidate(Decl *F) {
+ return Functions.insert(F->getCanonicalDecl());
+ }
+
+ /// \brief Clear out all of the candidates.
+ void clear();
+
+ ~OverloadCandidateSet() { clear(); }
+
+ /// Find the best viable function on this overload set, if it exists.
+ OverloadingResult BestViableFunction(Sema &S, SourceLocation Loc,
+ OverloadCandidateSet::iterator& Best);
+
+ void NoteCandidates(Sema &S,
+ OverloadCandidateDisplayKind OCD,
+ Expr **Args, unsigned NumArgs,
+ const char *Opc = 0,
+ SourceLocation Loc = SourceLocation());
+ };
+
+ bool isBetterOverloadCandidate(Sema &S,
+ const OverloadCandidate& Cand1,
+ const OverloadCandidate& Cand2,
+ SourceLocation Loc);
+} // end namespace clang
+
+#endif // LLVM_CLANG_SEMA_OVERLOAD_H
diff --git a/include/clang/Sema/Ownership.h b/include/clang/Sema/Ownership.h
new file mode 100644
index 000000000000..7739f3a5d229
--- /dev/null
+++ b/include/clang/Sema/Ownership.h
@@ -0,0 +1,462 @@
+//===--- Ownership.h - Parser ownership helpers -----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains classes for managing ownership of Stmt and Expr nodes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_OWNERSHIP_H
+#define LLVM_CLANG_SEMA_OWNERSHIP_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/PointerIntPair.h"
+
+//===----------------------------------------------------------------------===//
+// OpaquePtr
+//===----------------------------------------------------------------------===//
+
+namespace clang {
+ class Attr;
+ class CXXBaseOrMemberInitializer;
+ class CXXBaseSpecifier;
+ class Decl;
+ class DeclGroupRef;
+ class Expr;
+ class NestedNameSpecifier;
+ class QualType;
+ class Sema;
+ class Stmt;
+ class TemplateName;
+ class TemplateParameterList;
+
+ /// OpaquePtr - This is a very simple POD type that wraps a pointer that the
+ /// Parser doesn't know about but that Sema or another client does. The UID
+ /// template argument is used to make sure that "Decl" pointers are not
+ /// compatible with "Type" pointers for example.
+ template <class PtrTy>
+ class OpaquePtr {
+ void *Ptr;
+ explicit OpaquePtr(void *Ptr) : Ptr(Ptr) {}
+
+ typedef llvm::PointerLikeTypeTraits<PtrTy> Traits;
+
+ public:
+ OpaquePtr() : Ptr(0) {}
+
+ static OpaquePtr make(PtrTy P) { OpaquePtr OP; OP.set(P); return OP; }
+
+ template <typename T> T* getAs() const {
+ return get();
+ }
+
+ template <typename T> T getAsVal() const {
+ return get();
+ }
+
+ PtrTy get() const {
+ return Traits::getFromVoidPointer(Ptr);
+ }
+
+ void set(PtrTy P) {
+ Ptr = Traits::getAsVoidPointer(P);
+ }
+
+ operator bool() const { return Ptr != 0; }
+
+ void *getAsOpaquePtr() const { return Ptr; }
+ static OpaquePtr getFromOpaquePtr(void *P) { return OpaquePtr(P); }
+ };
+
+ /// UnionOpaquePtr - A version of OpaquePtr suitable for membership
+ /// in a union.
+ template <class T> struct UnionOpaquePtr {
+ void *Ptr;
+
+ static UnionOpaquePtr make(OpaquePtr<T> P) {
+ UnionOpaquePtr OP = { P.getAsOpaquePtr() };
+ return OP;
+ }
+
+ OpaquePtr<T> get() const { return OpaquePtr<T>::getFromOpaquePtr(Ptr); }
+ operator OpaquePtr<T>() const { return get(); }
+
+ UnionOpaquePtr &operator=(OpaquePtr<T> P) {
+ Ptr = P.getAsOpaquePtr();
+ return *this;
+ }
+ };
+}
+
+namespace llvm {
+ template <class T>
+ class PointerLikeTypeTraits<clang::OpaquePtr<T> > {
+ public:
+ static inline void *getAsVoidPointer(clang::OpaquePtr<T> P) {
+ // FIXME: Doesn't work? return P.getAs< void >();
+ return P.getAsOpaquePtr();
+ }
+ static inline clang::OpaquePtr<T> getFromVoidPointer(void *P) {
+ return clang::OpaquePtr<T>::getFromOpaquePtr(P);
+ }
+ enum { NumLowBitsAvailable = 0 };
+ };
+}
+
+
+
+// -------------------------- About Move Emulation -------------------------- //
+// The smart pointer classes in this file attempt to emulate move semantics
+// as they appear in C++0x with rvalue references. Since C++03 doesn't have
+// rvalue references, some tricks are needed to get similar results.
+// Move semantics in C++0x have the following properties:
+// 1) "Moving" means transferring the value of an object to another object,
+// similar to copying, but without caring what happens to the old object.
+// In particular, this means that the new object can steal the old object's
+// resources instead of creating a copy.
+// 2) Since moving can modify the source object, it must either be explicitly
+// requested by the user, or the modifications must be unnoticeable.
+// 3) As such, C++0x moving is only allowed in three contexts:
+// * By explicitly using std::move() to request it.
+// * From a temporary object, since that object cannot be accessed
+// afterwards anyway, thus making the state unobservable.
+// * On function return, since the object is not observable afterwards.
+//
+// To sum up: moving from a named object should only be possible with an
+// explicit std::move(), or on function return. Moving from a temporary should
+// be implicitly done. Moving from a const object is forbidden.
+//
+// The emulation is not perfect, and has the following shortcomings:
+// * move() is not in namespace std.
+// * move() is required on function return.
+// * There are difficulties with implicit conversions.
+// * Microsoft's compiler must be given the /Za switch to successfully compile.
+//
+// -------------------------- Implementation -------------------------------- //
+// The move emulation relies on the peculiar reference binding semantics of
+// C++03: as a rule, a non-const reference may not bind to a temporary object,
+// except for the implicit object parameter in a member function call, which
+// can refer to a temporary even when not being const.
+// The moveable object has five important functions to facilitate moving:
+// * A private, unimplemented constructor taking a non-const reference to its
+// own class. This constructor serves a two-fold purpose.
+// - It prevents the creation of a copy constructor that takes a const
+// reference. Temporaries would be able to bind to the argument of such a
+// constructor, and that would be bad.
+// - Named objects will bind to the non-const reference, but since it's
+// private, this will fail to compile. This prevents implicit moving from
+// named objects.
+// There's also a copy assignment operator for the same purpose.
+// * An implicit, non-const conversion operator to a special mover type. This
+// type represents the rvalue reference of C++0x. Being a non-const member,
+// its implicit this parameter can bind to temporaries.
+// * A constructor that takes an object of this mover type. This constructor
+// performs the actual move operation. There is an equivalent assignment
+// operator.
+// There is also a free move() function that takes a non-const reference to
+// an object and returns a temporary. Internally, this function uses explicit
+// constructor calls to move the value from the referenced object to the return
+// value.
+//
+// There are now three possible scenarios of use.
+// * Copying from a const object. Constructor overload resolution will find the
+// non-const copy constructor, and the move constructor. The first is not
+// viable because the const object cannot be bound to the non-const reference.
+// The second fails because the conversion to the mover object is non-const.
+// Moving from a const object fails as intended.
+// * Copying from a named object. Constructor overload resolution will select
+// the non-const copy constructor, but fail as intended, because this
+// constructor is private.
+// * Copying from a temporary. Constructor overload resolution cannot select
+// the non-const copy constructor, because the temporary cannot be bound to
+// the non-const reference. It thus selects the move constructor. The
+// temporary can be bound to the implicit this parameter of the conversion
+// operator, because of the special binding rule. Construction succeeds.
+// Note that the Microsoft compiler, as an extension, allows binding
+// temporaries against non-const references. The compiler thus selects the
+// non-const copy constructor and fails, because the constructor is private.
+// Passing /Za (disable extensions) disables this behaviour.
+// The free move() function is used to move from a named object.
+//
+// Note that when passing an object of a different type (the classes below
+// have OwningResult and OwningPtr, which should be mixable), you get a problem.
+// Argument passing and function return use copy initialization rules. The
+// effect of this is that, when the source object is not already of the target
+// type, the compiler will first seek a way to convert the source object to the
+// target type, and only then attempt to copy the resulting object. This means
+// that when passing an OwningResult where an OwningPtr is expected, the
+// compiler will first seek a conversion from OwningResult to OwningPtr, then
+// copy the OwningPtr. The resulting conversion sequence is:
+// OwningResult object -> ResultMover -> OwningResult argument to
+// OwningPtr(OwningResult) -> OwningPtr -> PtrMover -> final OwningPtr
+// This conversion sequence is too complex to be allowed. Thus the special
+// move_* functions, which help the compiler out with some explicit
+// conversions.
+
+namespace clang {
+ // Basic
+ class DiagnosticBuilder;
+
+ // Determines whether the low bit of the result pointer for the
+ // given UID is always zero. If so, ActionResult will use that bit
+ // for it's "invalid" flag.
+ template<class Ptr>
+ struct IsResultPtrLowBitFree {
+ static const bool value = false;
+ };
+
+ /// ActionResult - This structure is used while parsing/acting on
+ /// expressions, stmts, etc. It encapsulates both the object returned by
+ /// the action, plus a sense of whether or not it is valid.
+ /// When CompressInvalid is true, the "invalid" flag will be
+ /// stored in the low bit of the Val pointer.
+ template<class PtrTy,
+ bool CompressInvalid = IsResultPtrLowBitFree<PtrTy>::value>
+ class ActionResult {
+ PtrTy Val;
+ bool Invalid;
+
+ public:
+ ActionResult(bool Invalid = false)
+ : Val(PtrTy()), Invalid(Invalid) {}
+ ActionResult(PtrTy val) : Val(val), Invalid(false) {}
+ ActionResult(const DiagnosticBuilder &) : Val(PtrTy()), Invalid(true) {}
+
+ // These two overloads prevent void* -> bool conversions.
+ ActionResult(const void *);
+ ActionResult(volatile void *);
+
+ bool isInvalid() const { return Invalid; }
+ bool isUsable() const { return !Invalid && Val; }
+
+ PtrTy get() const { return Val; }
+ PtrTy release() const { return Val; }
+ PtrTy take() const { return Val; }
+ template <typename T> T *takeAs() { return static_cast<T*>(get()); }
+
+ void set(PtrTy V) { Val = V; }
+
+ const ActionResult &operator=(PtrTy RHS) {
+ Val = RHS;
+ Invalid = false;
+ return *this;
+ }
+ };
+
+ // This ActionResult partial specialization places the "invalid"
+ // flag into the low bit of the pointer.
+ template<typename PtrTy>
+ class ActionResult<PtrTy, true> {
+ // A pointer whose low bit is 1 if this result is invalid, 0
+ // otherwise.
+ uintptr_t PtrWithInvalid;
+ typedef llvm::PointerLikeTypeTraits<PtrTy> PtrTraits;
+ public:
+ ActionResult(bool Invalid = false)
+ : PtrWithInvalid(static_cast<uintptr_t>(Invalid)) { }
+
+ ActionResult(PtrTy V) {
+ void *VP = PtrTraits::getAsVoidPointer(V);
+ PtrWithInvalid = reinterpret_cast<uintptr_t>(VP);
+ assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer");
+ }
+ ActionResult(const DiagnosticBuilder &) : PtrWithInvalid(0x01) { }
+
+ // These two overloads prevent void* -> bool conversions.
+ ActionResult(const void *);
+ ActionResult(volatile void *);
+
+ bool isInvalid() const { return PtrWithInvalid & 0x01; }
+ bool isUsable() const { return PtrWithInvalid > 0x01; }
+
+ PtrTy get() const {
+ void *VP = reinterpret_cast<void *>(PtrWithInvalid & ~0x01);
+ return PtrTraits::getFromVoidPointer(VP);
+ }
+ PtrTy take() const { return get(); }
+ PtrTy release() const { return get(); }
+ template <typename T> T *takeAs() { return static_cast<T*>(get()); }
+
+ void set(PtrTy V) {
+ void *VP = PtrTraits::getAsVoidPointer(V);
+ PtrWithInvalid = reinterpret_cast<uintptr_t>(VP);
+ assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer");
+ }
+
+ const ActionResult &operator=(PtrTy RHS) {
+ void *VP = PtrTraits::getAsVoidPointer(RHS);
+ PtrWithInvalid = reinterpret_cast<uintptr_t>(VP);
+ assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer");
+ return *this;
+ }
+ };
+
+ /// ASTMultiPtr - A moveable smart pointer to multiple AST nodes. Only owns
+ /// the individual pointers, not the array holding them.
+ template <typename PtrTy> class ASTMultiPtr;
+
+ template <class PtrTy>
+ class ASTMultiPtr {
+ PtrTy *Nodes;
+ unsigned Count;
+
+ public:
+ // Normal copying implicitly defined
+ ASTMultiPtr() : Nodes(0), Count(0) {}
+ explicit ASTMultiPtr(Sema &) : Nodes(0), Count(0) {}
+ ASTMultiPtr(Sema &, PtrTy *nodes, unsigned count)
+ : Nodes(nodes), Count(count) {}
+ // Fake mover in Parse/AstGuard.h needs this:
+ ASTMultiPtr(PtrTy *nodes, unsigned count) : Nodes(nodes), Count(count) {}
+
+ /// Access to the raw pointers.
+ PtrTy *get() const { return Nodes; }
+
+ /// Access to the count.
+ unsigned size() const { return Count; }
+
+ PtrTy *release() {
+ return Nodes;
+ }
+ };
+
+ class ParsedTemplateArgument;
+
+ class ASTTemplateArgsPtr {
+ ParsedTemplateArgument *Args;
+ mutable unsigned Count;
+
+ public:
+ ASTTemplateArgsPtr(Sema &actions, ParsedTemplateArgument *args,
+ unsigned count) :
+ Args(args), Count(count) { }
+
+ // FIXME: Lame, not-fully-type-safe emulation of 'move semantics'.
+ ASTTemplateArgsPtr(ASTTemplateArgsPtr &Other) :
+ Args(Other.Args), Count(Other.Count) {
+ }
+
+ // FIXME: Lame, not-fully-type-safe emulation of 'move semantics'.
+ ASTTemplateArgsPtr& operator=(ASTTemplateArgsPtr &Other) {
+ Args = Other.Args;
+ Count = Other.Count;
+ return *this;
+ }
+
+ ParsedTemplateArgument *getArgs() const { return Args; }
+ unsigned size() const { return Count; }
+
+ void reset(ParsedTemplateArgument *args, unsigned count) {
+ Args = args;
+ Count = count;
+ }
+
+ const ParsedTemplateArgument &operator[](unsigned Arg) const;
+
+ ParsedTemplateArgument *release() const {
+ return Args;
+ }
+ };
+
+ /// \brief A small vector that owns a set of AST nodes.
+ template <class PtrTy, unsigned N = 8>
+ class ASTOwningVector : public llvm::SmallVector<PtrTy, N> {
+ ASTOwningVector(ASTOwningVector &); // do not implement
+ ASTOwningVector &operator=(ASTOwningVector &); // do not implement
+
+ public:
+ explicit ASTOwningVector(Sema &Actions)
+ { }
+
+ PtrTy *take() {
+ return &this->front();
+ }
+
+ template<typename T> T **takeAs() { return reinterpret_cast<T**>(take()); }
+ };
+
+ /// A SmallVector of statements, with stack size 32 (as that is the only one
+ /// used.)
+ typedef ASTOwningVector<Stmt*, 32> StmtVector;
+ /// A SmallVector of expressions, with stack size 12 (the maximum used.)
+ typedef ASTOwningVector<Expr*, 12> ExprVector;
+
+ template <class T, unsigned N> inline
+ ASTMultiPtr<T> move_arg(ASTOwningVector<T, N> &vec) {
+ return ASTMultiPtr<T>(vec.take(), vec.size());
+ }
+
+ // These versions are hopefully no-ops.
+ template <class T, bool C>
+ inline ActionResult<T,C> move(ActionResult<T,C> &ptr) {
+ return ptr;
+ }
+
+ template <class T> inline
+ ASTMultiPtr<T>& move(ASTMultiPtr<T> &ptr) {
+ return ptr;
+ }
+
+ // We can re-use the low bit of expression, statement, base, and
+ // member-initializer pointers for the "invalid" flag of
+ // ActionResult.
+ template<> struct IsResultPtrLowBitFree<Expr*> {
+ static const bool value = true;
+ };
+ template<> struct IsResultPtrLowBitFree<Stmt*> {
+ static const bool value = true;
+ };
+ template<> struct IsResultPtrLowBitFree<CXXBaseSpecifier*> {
+ static const bool value = true;
+ };
+ template<> struct IsResultPtrLowBitFree<CXXBaseOrMemberInitializer*> {
+ static const bool value = true;
+ };
+
+ /// An opaque type for threading parsed type information through the
+ /// parser.
+ typedef OpaquePtr<QualType> ParsedType;
+ typedef UnionOpaquePtr<QualType> UnionParsedType;
+
+ typedef ActionResult<Expr*> ExprResult;
+ typedef ActionResult<Stmt*> StmtResult;
+ typedef ActionResult<ParsedType> TypeResult;
+ typedef ActionResult<CXXBaseSpecifier*> BaseResult;
+ typedef ActionResult<CXXBaseOrMemberInitializer*> MemInitResult;
+
+ typedef ActionResult<Decl*> DeclResult;
+ typedef OpaquePtr<TemplateName> ParsedTemplateTy;
+
+ inline Expr *move(Expr *E) { return E; }
+ inline Stmt *move(Stmt *S) { return S; }
+
+ typedef ASTMultiPtr<Expr*> MultiExprArg;
+ typedef ASTMultiPtr<Stmt*> MultiStmtArg;
+ typedef ASTMultiPtr<TemplateParameterList*> MultiTemplateParamsArg;
+
+ inline ExprResult ExprError() { return ExprResult(true); }
+ inline StmtResult StmtError() { return StmtResult(true); }
+
+ inline ExprResult ExprError(const DiagnosticBuilder&) { return ExprError(); }
+ inline StmtResult StmtError(const DiagnosticBuilder&) { return StmtError(); }
+
+ inline ExprResult ExprEmpty() { return ExprResult(false); }
+ inline StmtResult StmtEmpty() { return StmtResult(false); }
+
+ inline Expr *AssertSuccess(ExprResult R) {
+ assert(!R.isInvalid() && "operation was asserted to never fail!");
+ return R.get();
+ }
+
+ inline Stmt *AssertSuccess(StmtResult R) {
+ assert(!R.isInvalid() && "operation was asserted to never fail!");
+ return R.get();
+ }
+}
+
+#endif
diff --git a/include/clang/Parse/Template.h b/include/clang/Sema/ParsedTemplate.h
index 84f4ed96b4c3..da68a494bf7b 100644
--- a/include/clang/Parse/Template.h
+++ b/include/clang/Sema/ParsedTemplate.h
@@ -1,4 +1,4 @@
-//===--- Template.h - Template Parsing Data Types -------------------------===//
+//===--- ParsedTemplate.h - Template Parsing Data Types -------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,11 +11,11 @@
// templates.
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_PARSE_TEMPLATE_H
-#define LLVM_CLANG_PARSE_TEMPLATE_H
+#ifndef LLVM_CLANG_SEMA_PARSEDTEMPLATE_H
+#define LLVM_CLANG_SEMA_PARSEDTEMPLATE_H
-#include "clang/Parse/DeclSpec.h"
-#include "clang/Parse/Ownership.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Ownership.h"
#include <cassert>
namespace clang {
@@ -52,9 +52,10 @@ namespace clang {
///
/// \param TemplateLoc the location of the template name.
ParsedTemplateArgument(const CXXScopeSpec &SS,
- ActionBase::TemplateTy Template,
+ ParsedTemplateTy Template,
SourceLocation TemplateLoc)
- : Kind(ParsedTemplateArgument::Template), Arg(Template.get()),
+ : Kind(ParsedTemplateArgument::Template),
+ Arg(Template.getAsOpaquePtr()),
Loc(TemplateLoc), SS(SS) { }
/// \brief Determine whether the given template argument is invalid.
@@ -64,21 +65,21 @@ namespace clang {
KindType getKind() const { return Kind; }
/// \brief Retrieve the template type argument's type.
- ActionBase::TypeTy *getAsType() const {
+ ParsedType getAsType() const {
assert(Kind == Type && "Not a template type argument");
- return Arg;
+ return ParsedType::getFromOpaquePtr(Arg);
}
/// \brief Retrieve the non-type template argument's expression.
- ActionBase::ExprTy *getAsExpr() const {
+ Expr *getAsExpr() const {
assert(Kind == NonType && "Not a non-type template argument");
- return Arg;
+ return static_cast<Expr*>(Arg);
}
/// \brief Retrieve the template template argument's template name.
- ActionBase::TemplateTy getAsTemplate() const {
+ ParsedTemplateTy getAsTemplate() const {
assert(Kind == Template && "Not a template template argument");
- return ActionBase::TemplateTy::make(Arg);
+ return ParsedTemplateTy::getFromOpaquePtr(Arg);
}
/// \brief Retrieve the location of the template argument.
@@ -128,8 +129,8 @@ namespace clang {
OverloadedOperatorKind Operator;
/// The declaration of the template corresponding to the
- /// template-name. This is an Action::TemplateTy.
- void *Template;
+ /// template-name.
+ ParsedTemplateTy Template;
/// The kind of template that Template refers to.
TemplateNameKind Kind;
@@ -161,18 +162,6 @@ namespace clang {
void Destroy() { free(this); }
};
-#if !defined(DISABLE_SMART_POINTERS)
- inline void ASTTemplateArgsPtr::destroy() {
- if (!Count)
- return;
-
- for (unsigned I = 0; I != Count; ++I)
- if (Args[I].getKind() == ParsedTemplateArgument::NonType)
- Actions.DeleteExpr(Args[I].getAsExpr());
-
- Count = 0;
- }
-#endif
inline const ParsedTemplateArgument &
ASTTemplateArgsPtr::operator[](unsigned Arg) const {
diff --git a/include/clang/Sema/PrettyDeclStackTrace.h b/include/clang/Sema/PrettyDeclStackTrace.h
new file mode 100644
index 000000000000..b78a1c01e5e3
--- /dev/null
+++ b/include/clang/Sema/PrettyDeclStackTrace.h
@@ -0,0 +1,46 @@
+//===- PrettyDeclStackTrace.h - Stack trace for decl processing -*- 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 an llvm::PrettyStackTraceEntry object for showing
+// that a particular declaration was being processed when a crash
+// occurred.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_PRETTY_DECL_STACK_TRACE_H
+#define LLVM_CLANG_SEMA_PRETTY_DECL_STACK_TRACE_H
+
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/Support/PrettyStackTrace.h"
+
+namespace clang {
+
+class Decl;
+class Sema;
+class SourceManager;
+
+/// PrettyDeclStackTraceEntry - If a crash occurs in the parser while
+/// parsing something related to a declaration, include that
+/// declaration in the stack trace.
+class PrettyDeclStackTraceEntry : public llvm::PrettyStackTraceEntry {
+ Sema &S;
+ Decl *TheDecl;
+ SourceLocation Loc;
+ const char *Message;
+
+public:
+ PrettyDeclStackTraceEntry(Sema &S, Decl *D, SourceLocation Loc, const char *Msg)
+ : S(S), TheDecl(D), Loc(Loc), Message(Msg) {}
+
+ virtual void print(llvm::raw_ostream &OS) const;
+};
+
+}
+
+#endif
diff --git a/include/clang/Parse/Scope.h b/include/clang/Sema/Scope.h
index 023f40d3957c..4229c6c62748 100644
--- a/include/clang/Parse/Scope.h
+++ b/include/clang/Sema/Scope.h
@@ -11,14 +11,16 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_PARSE_SCOPE_H
-#define LLVM_CLANG_PARSE_SCOPE_H
+#ifndef LLVM_CLANG_SEMA_SCOPE_H
+#define LLVM_CLANG_SEMA_SCOPE_H
-#include "clang/Parse/Action.h"
#include "llvm/ADT/SmallPtrSet.h"
namespace clang {
+class Decl;
+class UsingDirectiveDecl;
+
/// Scope - A scope is a transient data structure that is used while parsing the
/// program. It assists with resolving identifiers to the appropriate
/// declaration.
@@ -72,11 +74,7 @@ public:
/// ObjCMethodScope - This scope corresponds to an Objective-C method body.
/// It always has FnScope and DeclScope set as well.
- ObjCMethodScope = 0x400,
-
- /// ElseScope - This scope corresponds to an 'else' scope of an if/then/else
- /// statement.
- ElseScope = 0x800
+ ObjCMethodScope = 0x400
};
private:
/// The parent scope for this scope. This is null for the translation-unit
@@ -121,7 +119,7 @@ private:
/// popped, these declarations are removed from the IdentifierTable's notion
/// of current declaration. It is up to the current Action implementation to
/// implement these semantics.
- typedef llvm::SmallPtrSet<Action::DeclPtrTy, 32> DeclSetTy;
+ typedef llvm::SmallPtrSet<Decl *, 32> DeclSetTy;
DeclSetTy DeclsInScope;
/// Entity - The entity with which this scope is associated. For
@@ -130,7 +128,7 @@ private:
/// maintained by the Action implementation.
void *Entity;
- typedef llvm::SmallVector<Action::DeclPtrTy, 2> UsingDirectivesTy;
+ typedef llvm::SmallVector<UsingDirectiveDecl *, 2> UsingDirectivesTy;
UsingDirectivesTy UsingDirectives;
/// \brief The number of errors at the start of the given scope.
@@ -199,17 +197,17 @@ public:
decl_iterator decl_end() const { return DeclsInScope.end(); }
bool decl_empty() const { return DeclsInScope.empty(); }
- void AddDecl(Action::DeclPtrTy D) {
+ void AddDecl(Decl *D) {
DeclsInScope.insert(D);
}
- void RemoveDecl(Action::DeclPtrTy D) {
+ void RemoveDecl(Decl *D) {
DeclsInScope.erase(D);
}
/// isDeclScope - Return true if this is the scope that the specified decl is
/// declared in.
- bool isDeclScope(Action::DeclPtrTy D) {
+ bool isDeclScope(Decl *D) {
return DeclsInScope.count(D) != 0;
}
@@ -270,7 +268,7 @@ public:
typedef UsingDirectivesTy::iterator udir_iterator;
typedef UsingDirectivesTy::const_iterator const_udir_iterator;
- void PushUsingDirective(Action::DeclPtrTy UDir) {
+ void PushUsingDirective(UsingDirectiveDecl *UDir) {
UsingDirectives.push_back(UDir);
}
diff --git a/include/clang/Sema/ScopeInfo.h b/include/clang/Sema/ScopeInfo.h
new file mode 100644
index 000000000000..50cfa9bb5672
--- /dev/null
+++ b/include/clang/Sema/ScopeInfo.h
@@ -0,0 +1,137 @@
+//===--- ScopeInfo.h - Information about a semantic context -----*- 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 FunctionScopeInfo and BlockScopeInfo.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_SCOPE_INFO_H
+#define LLVM_CLANG_SEMA_SCOPE_INFO_H
+
+#include "clang/AST/Type.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace clang {
+
+class BlockDecl;
+class IdentifierInfo;
+class LabelStmt;
+class ReturnStmt;
+class Scope;
+class SwitchStmt;
+
+namespace sema {
+
+/// \brief Retains information about a function, method, or block that is
+/// currently being parsed.
+class FunctionScopeInfo {
+public:
+
+ /// \brief Whether this scope information structure defined information for
+ /// a block.
+ bool IsBlockInfo;
+
+ /// \brief Whether this function contains a VLA, @try, try, C++
+ /// initializer, or anything else that can't be jumped past.
+ bool HasBranchProtectedScope;
+
+ /// \brief Whether this function contains any switches or direct gotos.
+ bool HasBranchIntoScope;
+
+ /// \brief Whether this function contains any indirect gotos.
+ bool HasIndirectGoto;
+
+ /// \brief The number of errors that had occurred before starting this
+ /// function or block.
+ unsigned NumErrorsAtStartOfFunction;
+
+ /// LabelMap - This is a mapping from label identifiers to the LabelStmt for
+ /// it (which acts like the label decl in some ways). Forward referenced
+ /// labels have a LabelStmt created for them with a null location & SubStmt.
+ llvm::DenseMap<IdentifierInfo*, LabelStmt*> LabelMap;
+
+ /// SwitchStack - This is the current set of active switch statements in the
+ /// block.
+ llvm::SmallVector<SwitchStmt*, 8> SwitchStack;
+
+ /// \brief The list of return statements that occur within the function or
+ /// block, if there is any chance of applying the named return value
+ /// optimization.
+ llvm::SmallVector<ReturnStmt *, 4> Returns;
+
+ void setHasBranchIntoScope() {
+ HasBranchIntoScope = true;
+ }
+
+ void setHasBranchProtectedScope() {
+ HasBranchProtectedScope = true;
+ }
+
+ void setHasIndirectGoto() {
+ HasIndirectGoto = true;
+ }
+
+ bool NeedsScopeChecking() const {
+ return HasIndirectGoto ||
+ (HasBranchProtectedScope && HasBranchIntoScope);
+ }
+
+ FunctionScopeInfo(unsigned NumErrors)
+ : IsBlockInfo(false),
+ HasBranchProtectedScope(false),
+ HasBranchIntoScope(false),
+ HasIndirectGoto(false),
+ NumErrorsAtStartOfFunction(NumErrors) { }
+
+ virtual ~FunctionScopeInfo();
+
+ /// \brief Clear out the information in this function scope, making it
+ /// suitable for reuse.
+ void Clear(unsigned NumErrors);
+
+ static bool classof(const FunctionScopeInfo *FSI) { return true; }
+};
+
+/// \brief Retains information about a block that is currently being parsed.
+class BlockScopeInfo : public FunctionScopeInfo {
+public:
+ bool hasBlockDeclRefExprs;
+
+ BlockDecl *TheDecl;
+
+ /// TheScope - This is the scope for the block itself, which contains
+ /// arguments etc.
+ Scope *TheScope;
+
+ /// ReturnType - The return type of the block, or null if the block
+ /// signature didn't provide an explicit return type.
+ QualType ReturnType;
+
+ /// BlockType - The function type of the block, if one was given.
+ /// Its return type may be BuiltinType::Dependent.
+ QualType FunctionType;
+
+ BlockScopeInfo(unsigned NumErrors, Scope *BlockScope, BlockDecl *Block)
+ : FunctionScopeInfo(NumErrors), hasBlockDeclRefExprs(false),
+ TheDecl(Block), TheScope(BlockScope)
+ {
+ IsBlockInfo = true;
+ }
+
+ virtual ~BlockScopeInfo();
+
+ static bool classof(const FunctionScopeInfo *FSI) { return FSI->IsBlockInfo; }
+ static bool classof(const BlockScopeInfo *BSI) { return true; }
+};
+
+}
+}
+
+#endif
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
new file mode 100644
index 000000000000..4741028cb0c9
--- /dev/null
+++ b/include/clang/Sema/Sema.h
@@ -0,0 +1,4457 @@
+//===--- Sema.h - Semantic Analysis & AST Building --------------*- 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 the Sema class, which performs semantic analysis and
+// builds ASTs.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_SEMA_H
+#define LLVM_CLANG_SEMA_SEMA_H
+
+#include "clang/Sema/Ownership.h"
+#include "clang/Sema/AnalysisBasedWarnings.h"
+#include "clang/Sema/IdentifierResolver.h"
+#include "clang/Sema/ObjCMethodList.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/AST/OperationKinds.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/ExternalASTSource.h"
+#include "clang/Basic/Specifiers.h"
+#include "clang/Basic/TemplateKinds.h"
+#include "clang/Basic/TypeTraits.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include <deque>
+#include <string>
+
+namespace llvm {
+ class APSInt;
+ template <typename ValueT> struct DenseMapInfo;
+ template <typename ValueT, typename ValueInfoT> class DenseSet;
+}
+
+namespace clang {
+ class ADLResult;
+ class ASTConsumer;
+ class ASTContext;
+ class ArrayType;
+ class AttributeList;
+ class BlockDecl;
+ class CXXBasePath;
+ class CXXBasePaths;
+ typedef llvm::SmallVector<CXXBaseSpecifier*, 4> CXXCastPath;
+ class CXXConstructorDecl;
+ class CXXConversionDecl;
+ class CXXDestructorDecl;
+ class CXXFieldCollector;
+ class CXXMemberCallExpr;
+ class CXXMethodDecl;
+ class CXXScopeSpec;
+ class CXXTemporary;
+ class CXXTryStmt;
+ class CallExpr;
+ class ClassTemplateDecl;
+ class ClassTemplatePartialSpecializationDecl;
+ class ClassTemplateSpecializationDecl;
+ class CodeCompleteConsumer;
+ class CodeCompletionResult;
+ class Decl;
+ class DeclAccessPair;
+ class DeclContext;
+ class DeclRefExpr;
+ class DeclaratorDecl;
+ class DeducedTemplateArgument;
+ class DependentDiagnostic;
+ class DesignatedInitExpr;
+ class Designation;
+ class EnumConstantDecl;
+ class Expr;
+ class ExtVectorType;
+ class ExternalSemaSource;
+ class FormatAttr;
+ class FriendDecl;
+ class FullExpr;
+ class FunctionDecl;
+ class FunctionProtoType;
+ class FunctionTemplateDecl;
+ class ImplicitConversionSequence;
+ class InitListExpr;
+ class InitializationKind;
+ class InitializationSequence;
+ class InitializedEntity;
+ class IntegerLiteral;
+ class LabelStmt;
+ class LangOptions;
+ class LocalInstantiationScope;
+ class LookupResult;
+ class MacroInfo;
+ class MultiLevelTemplateArgumentList;
+ class NamedDecl;
+ class NonNullAttr;
+ class ObjCCategoryDecl;
+ class ObjCCategoryImplDecl;
+ class ObjCCompatibleAliasDecl;
+ class ObjCContainerDecl;
+ class ObjCImplDecl;
+ class ObjCImplementationDecl;
+ class ObjCInterfaceDecl;
+ class ObjCIvarDecl;
+ template <class T> class ObjCList;
+ class ObjCMethodDecl;
+ class ObjCPropertyDecl;
+ class ObjCProtocolDecl;
+ class OverloadCandidateSet;
+ class ParenListExpr;
+ class ParmVarDecl;
+ class Preprocessor;
+ class PseudoDestructorTypeStorage;
+ class QualType;
+ class StandardConversionSequence;
+ class Stmt;
+ class StringLiteral;
+ class SwitchStmt;
+ class TargetAttributesSema;
+ class TemplateArgument;
+ class TemplateArgumentList;
+ class TemplateArgumentListBuilder;
+ class TemplateArgumentLoc;
+ class TemplateDecl;
+ class TemplateParameterList;
+ class TemplatePartialOrderingContext;
+ class TemplateTemplateParmDecl;
+ class Token;
+ class TypedefDecl;
+ class UnqualifiedId;
+ class UnresolvedLookupExpr;
+ class UnresolvedMemberExpr;
+ class UnresolvedSetImpl;
+ class UnresolvedSetIterator;
+ class UsingDecl;
+ class UsingShadowDecl;
+ class ValueDecl;
+ class VarDecl;
+ class VisibilityAttr;
+ class VisibleDeclConsumer;
+
+namespace sema {
+ class AccessedEntity;
+ class BlockScopeInfo;
+ class DelayedDiagnostic;
+ class FunctionScopeInfo;
+ class TemplateDeductionInfo;
+}
+
+/// \brief Holds a QualType and a TypeSourceInfo* that came out of a declarator
+/// parsing.
+///
+/// LocInfoType is a "transient" type, only needed for passing to/from Parser
+/// and Sema, when we want to preserve type source info for a parsed type.
+/// It will not participate in the type system semantics in any way.
+class LocInfoType : public Type {
+ enum {
+ // The last number that can fit in Type's TC.
+ // Avoids conflict with an existing Type class.
+ LocInfo = Type::TypeLast + 1
+ };
+
+ TypeSourceInfo *DeclInfo;
+
+ LocInfoType(QualType ty, TypeSourceInfo *TInfo)
+ : Type((TypeClass)LocInfo, ty, ty->isDependentType()), DeclInfo(TInfo) {
+ assert(getTypeClass() == (TypeClass)LocInfo && "LocInfo didn't fit in TC?");
+ }
+ friend class Sema;
+
+public:
+ QualType getType() const { return getCanonicalTypeInternal(); }
+ TypeSourceInfo *getTypeSourceInfo() const { return DeclInfo; }
+
+ void getAsStringInternal(std::string &Str,
+ const PrintingPolicy &Policy) const;
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == (TypeClass)LocInfo;
+ }
+ static bool classof(const LocInfoType *) { return true; }
+};
+
+/// Sema - This implements semantic analysis and AST building for C.
+class Sema {
+ Sema(const Sema&); // DO NOT IMPLEMENT
+ void operator=(const Sema&); // DO NOT IMPLEMENT
+ mutable const TargetAttributesSema* TheTargetAttributesSema;
+public:
+ typedef OpaquePtr<DeclGroupRef> DeclGroupPtrTy;
+ typedef OpaquePtr<TemplateName> TemplateTy;
+ typedef OpaquePtr<QualType> TypeTy;
+ typedef Attr AttrTy;
+ typedef CXXBaseSpecifier BaseTy;
+ typedef CXXBaseOrMemberInitializer MemInitTy;
+ typedef Expr ExprTy;
+ typedef Stmt StmtTy;
+ typedef TemplateParameterList TemplateParamsTy;
+ typedef NestedNameSpecifier CXXScopeTy;
+
+ const LangOptions &LangOpts;
+ Preprocessor &PP;
+ ASTContext &Context;
+ ASTConsumer &Consumer;
+ Diagnostic &Diags;
+ SourceManager &SourceMgr;
+
+ /// \brief Source of additional semantic information.
+ ExternalSemaSource *ExternalSource;
+
+ /// \brief Code-completion consumer.
+ CodeCompleteConsumer *CodeCompleter;
+
+ /// CurContext - This is the current declaration context of parsing.
+ DeclContext *CurContext;
+
+ /// VAListTagName - The declaration name corresponding to __va_list_tag.
+ /// This is used as part of a hack to omit that class from ADL results.
+ DeclarationName VAListTagName;
+
+ /// A RAII object to temporarily push a declaration context.
+ class ContextRAII {
+ private:
+ Sema &S;
+ DeclContext *SavedContext;
+
+ public:
+ ContextRAII(Sema &S, DeclContext *ContextToPush)
+ : S(S), SavedContext(S.CurContext) {
+ assert(ContextToPush && "pushing null context");
+ S.CurContext = ContextToPush;
+ }
+
+ void pop() {
+ if (!SavedContext) return;
+ S.CurContext = SavedContext;
+ SavedContext = 0;
+ }
+
+ ~ContextRAII() {
+ pop();
+ }
+ };
+
+ /// PackContext - Manages the stack for #pragma pack. An alignment
+ /// of 0 indicates default alignment.
+ void *PackContext; // Really a "PragmaPackStack*"
+
+ /// VisContext - Manages the stack for #pragma GCC visibility.
+ void *VisContext; // Really a "PragmaVisStack*"
+
+ /// \brief Stack containing information about each of the nested
+ /// function, block, and method scopes that are currently active.
+ ///
+ /// This array is never empty. Clients should ignore the first
+ /// element, which is used to cache a single FunctionScopeInfo
+ /// that's used to parse every top-level function.
+ llvm::SmallVector<sema::FunctionScopeInfo *, 4> FunctionScopes;
+
+ /// ExprTemporaries - This is the stack of temporaries that are created by
+ /// the current full expression.
+ llvm::SmallVector<CXXTemporary*, 8> ExprTemporaries;
+
+ /// ExtVectorDecls - This is a list all the extended vector types. This allows
+ /// us to associate a raw vector type with one of the ext_vector type names.
+ /// This is only necessary for issuing pretty diagnostics.
+ llvm::SmallVector<TypedefDecl*, 24> ExtVectorDecls;
+
+ /// FieldCollector - Collects CXXFieldDecls during parsing of C++ classes.
+ llvm::OwningPtr<CXXFieldCollector> FieldCollector;
+
+ typedef llvm::SmallPtrSet<const CXXRecordDecl*, 8> RecordDeclSetTy;
+
+ /// PureVirtualClassDiagSet - a set of class declarations which we have
+ /// emitted a list of pure virtual functions. Used to prevent emitting the
+ /// same list more than once.
+ llvm::OwningPtr<RecordDeclSetTy> PureVirtualClassDiagSet;
+
+ /// \brief A mapping from external names to the most recent
+ /// locally-scoped external declaration with that name.
+ ///
+ /// This map contains external declarations introduced in local
+ /// scoped, e.g.,
+ ///
+ /// \code
+ /// void f() {
+ /// void foo(int, int);
+ /// }
+ /// \endcode
+ ///
+ /// Here, the name "foo" will be associated with the declaration on
+ /// "foo" within f. This name is not visible outside of
+ /// "f". However, we still find it in two cases:
+ ///
+ /// - If we are declaring another external with the name "foo", we
+ /// can find "foo" as a previous declaration, so that the types
+ /// of this external declaration can be checked for
+ /// compatibility.
+ ///
+ /// - If we would implicitly declare "foo" (e.g., due to a call to
+ /// "foo" in C when no prototype or definition is visible), then
+ /// we find this declaration of "foo" and complain that it is
+ /// not visible.
+ llvm::DenseMap<DeclarationName, NamedDecl *> LocallyScopedExternalDecls;
+
+ /// \brief All the tentative definitions encountered in the TU.
+ llvm::SmallVector<VarDecl *, 2> TentativeDefinitions;
+
+ /// \brief The set of file scoped decls seen so far that have not been used
+ /// and must warn if not used. Only contains the first declaration.
+ llvm::SmallVector<const DeclaratorDecl*, 4> UnusedFileScopedDecls;
+
+ /// \brief The stack of diagnostics that were delayed due to being
+ /// produced during the parsing of a declaration.
+ llvm::SmallVector<sema::DelayedDiagnostic, 0> DelayedDiagnostics;
+
+ /// \brief The depth of the current ParsingDeclaration stack.
+ /// If nonzero, we are currently parsing a declaration (and
+ /// hence should delay deprecation warnings).
+ unsigned ParsingDeclDepth;
+
+ /// WeakUndeclaredIdentifiers - Identifiers contained in
+ /// #pragma weak before declared. rare. may alias another
+ /// identifier, declared or undeclared
+ class WeakInfo {
+ IdentifierInfo *alias; // alias (optional)
+ SourceLocation loc; // for diagnostics
+ bool used; // identifier later declared?
+ public:
+ WeakInfo()
+ : alias(0), loc(SourceLocation()), used(false) {}
+ WeakInfo(IdentifierInfo *Alias, SourceLocation Loc)
+ : alias(Alias), loc(Loc), used(false) {}
+ inline IdentifierInfo * getAlias() const { return alias; }
+ inline SourceLocation getLocation() const { return loc; }
+ void setUsed(bool Used=true) { used = Used; }
+ inline bool getUsed() { return used; }
+ bool operator==(WeakInfo RHS) const {
+ return alias == RHS.getAlias() && loc == RHS.getLocation();
+ }
+ bool operator!=(WeakInfo RHS) const { return !(*this == RHS); }
+ };
+ llvm::DenseMap<IdentifierInfo*,WeakInfo> WeakUndeclaredIdentifiers;
+
+ /// WeakTopLevelDecl - Translation-unit scoped declarations generated by
+ /// #pragma weak during processing of other Decls.
+ /// I couldn't figure out a clean way to generate these in-line, so
+ /// we store them here and handle separately -- which is a hack.
+ /// It would be best to refactor this.
+ llvm::SmallVector<Decl*,2> WeakTopLevelDecl;
+
+ IdentifierResolver IdResolver;
+
+ /// Translation Unit Scope - useful to Objective-C actions that need
+ /// to lookup file scope declarations in the "ordinary" C decl namespace.
+ /// For example, user-defined classes, built-in "id" type, etc.
+ Scope *TUScope;
+
+ /// \brief The C++ "std" namespace, where the standard library resides.
+ LazyDeclPtr StdNamespace;
+
+ /// \brief The C++ "std::bad_alloc" class, which is defined by the C++
+ /// standard library.
+ LazyDeclPtr StdBadAlloc;
+
+ /// A flag to remember whether the implicit forms of operator new and delete
+ /// have been declared.
+ bool GlobalNewDeleteDeclared;
+
+ /// \brief The set of declarations that have been referenced within
+ /// a potentially evaluated expression.
+ typedef llvm::SmallVector<std::pair<SourceLocation, Decl *>, 10>
+ PotentiallyReferencedDecls;
+
+ /// \brief A set of diagnostics that may be emitted.
+ typedef llvm::SmallVector<std::pair<SourceLocation, PartialDiagnostic>, 10>
+ PotentiallyEmittedDiagnostics;
+
+ /// \brief Describes how the expressions currently being parsed are
+ /// evaluated at run-time, if at all.
+ enum ExpressionEvaluationContext {
+ /// \brief The current expression and its subexpressions occur within an
+ /// unevaluated operand (C++0x [expr]p8), such as a constant expression
+ /// or the subexpression of \c sizeof, where the type or the value of the
+ /// expression may be significant but no code will be generated to evaluate
+ /// the value of the expression at run time.
+ Unevaluated,
+
+ /// \brief The current expression is potentially evaluated at run time,
+ /// which means that code may be generated to evaluate the value of the
+ /// expression at run time.
+ PotentiallyEvaluated,
+
+ /// \brief The current expression may be potentially evaluated or it may
+ /// be unevaluated, but it is impossible to tell from the lexical context.
+ /// This evaluation context is used primary for the operand of the C++
+ /// \c typeid expression, whose argument is potentially evaluated only when
+ /// it is an lvalue of polymorphic class type (C++ [basic.def.odr]p2).
+ PotentiallyPotentiallyEvaluated
+ };
+
+ /// \brief Data structure used to record current or nested
+ /// expression evaluation contexts.
+ struct ExpressionEvaluationContextRecord {
+ /// \brief The expression evaluation context.
+ ExpressionEvaluationContext Context;
+
+ /// \brief The number of temporaries that were active when we
+ /// entered this expression evaluation context.
+ unsigned NumTemporaries;
+
+ /// \brief The set of declarations referenced within a
+ /// potentially potentially-evaluated context.
+ ///
+ /// When leaving a potentially potentially-evaluated context, each
+ /// of these elements will be as referenced if the corresponding
+ /// potentially potentially evaluated expression is potentially
+ /// evaluated.
+ PotentiallyReferencedDecls *PotentiallyReferenced;
+
+ /// \brief The set of diagnostics to emit should this potentially
+ /// potentially-evaluated context become evaluated.
+ PotentiallyEmittedDiagnostics *PotentiallyDiagnosed;
+
+ ExpressionEvaluationContextRecord(ExpressionEvaluationContext Context,
+ unsigned NumTemporaries)
+ : Context(Context), NumTemporaries(NumTemporaries),
+ PotentiallyReferenced(0), PotentiallyDiagnosed(0) { }
+
+ void addReferencedDecl(SourceLocation Loc, Decl *Decl) {
+ if (!PotentiallyReferenced)
+ PotentiallyReferenced = new PotentiallyReferencedDecls;
+ PotentiallyReferenced->push_back(std::make_pair(Loc, Decl));
+ }
+
+ void addDiagnostic(SourceLocation Loc, const PartialDiagnostic &PD) {
+ if (!PotentiallyDiagnosed)
+ PotentiallyDiagnosed = new PotentiallyEmittedDiagnostics;
+ PotentiallyDiagnosed->push_back(std::make_pair(Loc, PD));
+ }
+
+ void Destroy() {
+ delete PotentiallyReferenced;
+ delete PotentiallyDiagnosed;
+ PotentiallyReferenced = 0;
+ PotentiallyDiagnosed = 0;
+ }
+ };
+
+ /// A stack of expression evaluation contexts.
+ llvm::SmallVector<ExpressionEvaluationContextRecord, 8> ExprEvalContexts;
+
+ /// \brief Whether the code handled by Sema should be considered a
+ /// complete translation unit or not.
+ ///
+ /// When true (which is generally the case), Sema will perform
+ /// end-of-translation-unit semantic tasks (such as creating
+ /// initializers for tentative definitions in C) once parsing has
+ /// completed. This flag will be false when building PCH files,
+ /// since a PCH file is by definition not a complete translation
+ /// unit.
+ bool CompleteTranslationUnit;
+
+ llvm::BumpPtrAllocator BumpAlloc;
+
+ /// \brief The number of SFINAE diagnostics that have been trapped.
+ unsigned NumSFINAEErrors;
+
+ typedef std::pair<ObjCMethodList, ObjCMethodList> GlobalMethods;
+ typedef llvm::DenseMap<Selector, GlobalMethods> GlobalMethodPool;
+
+ /// Method Pool - allows efficient lookup when typechecking messages to "id".
+ /// We need to maintain a list, since selectors can have differing signatures
+ /// across classes. In Cocoa, this happens to be extremely uncommon (only 1%
+ /// of selectors are "overloaded").
+ GlobalMethodPool MethodPool;
+
+ /// Method selectors used in a @selector expression. Used for implementation
+ /// of -Wselector.
+ llvm::DenseMap<Selector, SourceLocation> ReferencedSelectors;
+
+
+ GlobalMethodPool::iterator ReadMethodPool(Selector Sel);
+
+ /// Private Helper predicate to check for 'self'.
+ bool isSelfExpr(Expr *RExpr);
+public:
+ Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
+ bool CompleteTranslationUnit = true,
+ CodeCompleteConsumer *CompletionConsumer = 0);
+ ~Sema();
+
+ /// \brief Perform initialization that occurs after the parser has been
+ /// initialized but before it parses anything.
+ void Initialize();
+
+ const LangOptions &getLangOptions() const { return LangOpts; }
+ Diagnostic &getDiagnostics() const { return Diags; }
+ SourceManager &getSourceManager() const { return SourceMgr; }
+ const TargetAttributesSema &getTargetAttributesSema() const;
+ Preprocessor &getPreprocessor() const { return PP; }
+ ASTContext &getASTContext() const { return Context; }
+ ASTConsumer &getASTConsumer() const { return Consumer; }
+
+ /// \brief Helper class that creates diagnostics with optional
+ /// template instantiation stacks.
+ ///
+ /// This class provides a wrapper around the basic DiagnosticBuilder
+ /// class that emits diagnostics. SemaDiagnosticBuilder is
+ /// responsible for emitting the diagnostic (as DiagnosticBuilder
+ /// does) and, if the diagnostic comes from inside a template
+ /// instantiation, printing the template instantiation stack as
+ /// well.
+ class SemaDiagnosticBuilder : public DiagnosticBuilder {
+ Sema &SemaRef;
+ unsigned DiagID;
+
+ public:
+ SemaDiagnosticBuilder(DiagnosticBuilder &DB, Sema &SemaRef, unsigned DiagID)
+ : DiagnosticBuilder(DB), SemaRef(SemaRef), DiagID(DiagID) { }
+
+ explicit SemaDiagnosticBuilder(Sema &SemaRef)
+ : DiagnosticBuilder(DiagnosticBuilder::Suppress), SemaRef(SemaRef) { }
+
+ ~SemaDiagnosticBuilder();
+ };
+
+ /// \brief Emit a diagnostic.
+ SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID);
+
+ /// \brief Emit a partial diagnostic.
+ SemaDiagnosticBuilder Diag(SourceLocation Loc, const PartialDiagnostic& PD);
+
+ /// \brief Build a partial diagnostic.
+ PartialDiagnostic PDiag(unsigned DiagID = 0); // in SemaInternal.h
+
+ ExprResult Owned(Expr* E) { return E; }
+ ExprResult Owned(ExprResult R) { return R; }
+ StmtResult Owned(Stmt* S) { return S; }
+
+ void ActOnEndOfTranslationUnit();
+
+ Scope *getScopeForContext(DeclContext *Ctx);
+
+ void PushFunctionScope();
+ void PushBlockScope(Scope *BlockScope, BlockDecl *Block);
+ void PopFunctionOrBlockScope();
+
+ sema::FunctionScopeInfo *getCurFunction() const {
+ return FunctionScopes.back();
+ }
+
+ bool hasAnyErrorsInThisFunction() const;
+
+ /// \brief Retrieve the current block, if any.
+ sema::BlockScopeInfo *getCurBlock();
+
+ /// WeakTopLevelDeclDecls - access to #pragma weak-generated Decls
+ llvm::SmallVector<Decl*,2> &WeakTopLevelDecls() { return WeakTopLevelDecl; }
+
+ //===--------------------------------------------------------------------===//
+ // Type Analysis / Processing: SemaType.cpp.
+ //
+
+ QualType adjustParameterType(QualType T);
+ QualType BuildQualifiedType(QualType T, SourceLocation Loc, Qualifiers Qs);
+ QualType BuildQualifiedType(QualType T, SourceLocation Loc, unsigned CVR) {
+ return BuildQualifiedType(T, Loc, Qualifiers::fromCVRMask(CVR));
+ }
+ QualType BuildPointerType(QualType T,
+ SourceLocation Loc, DeclarationName Entity);
+ QualType BuildReferenceType(QualType T, bool LValueRef,
+ SourceLocation Loc, DeclarationName Entity);
+ QualType BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
+ Expr *ArraySize, unsigned Quals,
+ SourceRange Brackets, DeclarationName Entity);
+ QualType BuildExtVectorType(QualType T, Expr *ArraySize,
+ SourceLocation AttrLoc);
+ QualType BuildFunctionType(QualType T,
+ QualType *ParamTypes, unsigned NumParamTypes,
+ bool Variadic, unsigned Quals,
+ SourceLocation Loc, DeclarationName Entity,
+ const FunctionType::ExtInfo &Info);
+ QualType BuildMemberPointerType(QualType T, QualType Class,
+ SourceLocation Loc,
+ DeclarationName Entity);
+ QualType BuildBlockPointerType(QualType T,
+ SourceLocation Loc, DeclarationName Entity);
+ TypeSourceInfo *GetTypeForDeclarator(Declarator &D, Scope *S,
+ TagDecl **OwnedDecl = 0);
+ TypeSourceInfo *GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
+ TypeSourceInfo *ReturnTypeInfo);
+ /// \brief Package the given type and TSI into a ParsedType.
+ ParsedType CreateParsedType(QualType T, TypeSourceInfo *TInfo);
+ DeclarationNameInfo GetNameForDeclarator(Declarator &D);
+ DeclarationNameInfo GetNameFromUnqualifiedId(const UnqualifiedId &Name);
+ static QualType GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo = 0);
+ bool CheckSpecifiedExceptionType(QualType T, const SourceRange &Range);
+ bool CheckDistantExceptionSpec(QualType T);
+ bool CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New);
+ bool CheckEquivalentExceptionSpec(
+ const FunctionProtoType *Old, SourceLocation OldLoc,
+ const FunctionProtoType *New, SourceLocation NewLoc);
+ bool CheckEquivalentExceptionSpec(
+ const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID,
+ const FunctionProtoType *Old, SourceLocation OldLoc,
+ const FunctionProtoType *New, SourceLocation NewLoc,
+ bool *MissingExceptionSpecification = 0,
+ bool *MissingEmptyExceptionSpecification = 0);
+ bool CheckExceptionSpecSubset(
+ const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID,
+ const FunctionProtoType *Superset, SourceLocation SuperLoc,
+ const FunctionProtoType *Subset, SourceLocation SubLoc);
+ bool CheckParamExceptionSpec(const PartialDiagnostic & NoteID,
+ const FunctionProtoType *Target, SourceLocation TargetLoc,
+ const FunctionProtoType *Source, SourceLocation SourceLoc);
+
+ TypeResult ActOnTypeName(Scope *S, Declarator &D);
+
+ bool RequireCompleteType(SourceLocation Loc, QualType T,
+ const PartialDiagnostic &PD,
+ std::pair<SourceLocation, PartialDiagnostic> Note);
+ bool RequireCompleteType(SourceLocation Loc, QualType T,
+ const PartialDiagnostic &PD);
+ bool RequireCompleteType(SourceLocation Loc, QualType T,
+ unsigned DiagID);
+
+ QualType getElaboratedType(ElaboratedTypeKeyword Keyword,
+ const CXXScopeSpec &SS, QualType T);
+
+ QualType BuildTypeofExprType(Expr *E);
+ QualType BuildDecltypeType(Expr *E);
+
+ //===--------------------------------------------------------------------===//
+ // Symbol table / Decl tracking callbacks: SemaDecl.cpp.
+ //
+
+ DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr);
+
+ void DiagnoseUseOfUnimplementedSelectors();
+
+ ParsedType getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
+ Scope *S, CXXScopeSpec *SS = 0,
+ bool isClassName = false,
+ ParsedType ObjectType = ParsedType());
+ TypeSpecifierType isTagName(IdentifierInfo &II, Scope *S);
+ bool DiagnoseUnknownTypeName(const IdentifierInfo &II,
+ SourceLocation IILoc,
+ Scope *S,
+ CXXScopeSpec *SS,
+ ParsedType &SuggestedType);
+
+ Decl *ActOnDeclarator(Scope *S, Declarator &D);
+
+ Decl *HandleDeclarator(Scope *S, Declarator &D,
+ MultiTemplateParamsArg TemplateParameterLists,
+ bool IsFunctionDefinition);
+ void RegisterLocallyScopedExternCDecl(NamedDecl *ND,
+ const LookupResult &Previous,
+ Scope *S);
+ void DiagnoseFunctionSpecifiers(Declarator& D);
+ void CheckShadow(Scope *S, VarDecl *D, const LookupResult& R);
+ void CheckShadow(Scope *S, VarDecl *D);
+ void CheckCastAlign(Expr *Op, QualType T, SourceRange TRange);
+ NamedDecl* ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
+ QualType R, TypeSourceInfo *TInfo,
+ LookupResult &Previous, bool &Redeclaration);
+ NamedDecl* ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
+ QualType R, TypeSourceInfo *TInfo,
+ LookupResult &Previous,
+ MultiTemplateParamsArg TemplateParamLists,
+ bool &Redeclaration);
+ void CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous,
+ bool &Redeclaration);
+ NamedDecl* ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
+ QualType R, TypeSourceInfo *TInfo,
+ LookupResult &Previous,
+ MultiTemplateParamsArg TemplateParamLists,
+ bool IsFunctionDefinition,
+ bool &Redeclaration);
+ void AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD);
+ void CheckFunctionDeclaration(Scope *S,
+ FunctionDecl *NewFD, LookupResult &Previous,
+ bool IsExplicitSpecialization,
+ bool &Redeclaration,
+ bool &OverloadableAttrRequired);
+ void CheckMain(FunctionDecl *FD);
+ Decl *ActOnParamDeclarator(Scope *S, Declarator &D);
+ ParmVarDecl *BuildParmVarDeclForTypedef(DeclContext *DC,
+ SourceLocation Loc,
+ QualType T);
+ ParmVarDecl *CheckParameter(DeclContext *DC,
+ TypeSourceInfo *TSInfo, QualType T,
+ IdentifierInfo *Name,
+ SourceLocation NameLoc,
+ StorageClass SC,
+ StorageClass SCAsWritten);
+ void ActOnParamDefaultArgument(Decl *param,
+ SourceLocation EqualLoc,
+ Expr *defarg);
+ void ActOnParamUnparsedDefaultArgument(Decl *param,
+ SourceLocation EqualLoc,
+ SourceLocation ArgLoc);
+ void ActOnParamDefaultArgumentError(Decl *param);
+ bool SetParamDefaultArgument(ParmVarDecl *Param, Expr *DefaultArg,
+ SourceLocation EqualLoc);
+
+
+ // Contains the locations of the beginning of unparsed default
+ // argument locations.
+ llvm::DenseMap<ParmVarDecl *,SourceLocation> UnparsedDefaultArgLocs;
+
+ void AddInitializerToDecl(Decl *dcl, Expr *init);
+ void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit);
+ void ActOnUninitializedDecl(Decl *dcl, bool TypeContainsUndeducedAuto);
+ void ActOnInitializerError(Decl *Dcl);
+ void SetDeclDeleted(Decl *dcl, SourceLocation DelLoc);
+ DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
+ Decl **Group,
+ unsigned NumDecls);
+ void ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
+ SourceLocation LocAfterDecls);
+ Decl *ActOnStartOfFunctionDef(Scope *S, Declarator &D);
+ Decl *ActOnStartOfFunctionDef(Scope *S, Decl *D);
+ void ActOnStartOfObjCMethodDef(Scope *S, Decl *D);
+
+ Decl *ActOnFinishFunctionBody(Decl *Decl, Stmt *Body);
+ Decl *ActOnFinishFunctionBody(Decl *Decl, Stmt *Body, bool IsInstantiation);
+
+ /// \brief Diagnose any unused parameters in the given sequence of
+ /// ParmVarDecl pointers.
+ void DiagnoseUnusedParameters(ParmVarDecl * const *Begin,
+ ParmVarDecl * const *End);
+
+ void DiagnoseInvalidJumps(Stmt *Body);
+ Decl *ActOnFileScopeAsmDecl(SourceLocation Loc, Expr *expr);
+
+ /// Scope actions.
+ void ActOnPopScope(SourceLocation Loc, Scope *S);
+ void ActOnTranslationUnitScope(Scope *S);
+
+ /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
+ /// no declarator (e.g. "struct foo;") is parsed.
+ Decl *ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
+ DeclSpec &DS);
+
+ Decl *BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
+ AccessSpecifier AS,
+ RecordDecl *Record);
+
+ bool isAcceptableTagRedeclaration(const TagDecl *Previous,
+ TagTypeKind NewTag,
+ SourceLocation NewTagLoc,
+ const IdentifierInfo &Name);
+
+ enum TagUseKind {
+ TUK_Reference, // Reference to a tag: 'struct foo *X;'
+ TUK_Declaration, // Fwd decl of a tag: 'struct foo;'
+ TUK_Definition, // Definition of a tag: 'struct foo { int X; } Y;'
+ TUK_Friend // Friend declaration: 'friend struct foo;'
+ };
+
+ Decl *ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
+ SourceLocation KWLoc, CXXScopeSpec &SS,
+ IdentifierInfo *Name, SourceLocation NameLoc,
+ AttributeList *Attr, AccessSpecifier AS,
+ MultiTemplateParamsArg TemplateParameterLists,
+ bool &OwnedDecl, bool &IsDependent);
+
+ TypeResult ActOnDependentTag(Scope *S,
+ unsigned TagSpec,
+ TagUseKind TUK,
+ const CXXScopeSpec &SS,
+ IdentifierInfo *Name,
+ SourceLocation TagLoc,
+ SourceLocation NameLoc);
+
+ void ActOnDefs(Scope *S, Decl *TagD, SourceLocation DeclStart,
+ IdentifierInfo *ClassName,
+ llvm::SmallVectorImpl<Decl *> &Decls);
+ Decl *ActOnField(Scope *S, Decl *TagD, SourceLocation DeclStart,
+ Declarator &D, Expr *BitfieldWidth);
+
+ FieldDecl *HandleField(Scope *S, RecordDecl *TagD, SourceLocation DeclStart,
+ Declarator &D, Expr *BitfieldWidth,
+ AccessSpecifier AS);
+
+ FieldDecl *CheckFieldDecl(DeclarationName Name, QualType T,
+ TypeSourceInfo *TInfo,
+ RecordDecl *Record, SourceLocation Loc,
+ bool Mutable, Expr *BitfieldWidth,
+ SourceLocation TSSL,
+ AccessSpecifier AS, NamedDecl *PrevDecl,
+ Declarator *D = 0);
+
+ enum CXXSpecialMember {
+ CXXInvalid = -1,
+ CXXConstructor = 0,
+ CXXCopyConstructor = 1,
+ CXXCopyAssignment = 2,
+ CXXDestructor = 3
+ };
+ bool CheckNontrivialField(FieldDecl *FD);
+ void DiagnoseNontrivial(const RecordType* Record, CXXSpecialMember mem);
+ CXXSpecialMember getSpecialMember(const CXXMethodDecl *MD);
+ void ActOnLastBitfield(SourceLocation DeclStart, Decl *IntfDecl,
+ llvm::SmallVectorImpl<Decl *> &AllIvarDecls);
+ Decl *ActOnIvar(Scope *S, SourceLocation DeclStart, Decl *IntfDecl,
+ Declarator &D, Expr *BitfieldWidth,
+ tok::ObjCKeywordKind visibility);
+
+ // This is used for both record definitions and ObjC interface declarations.
+ void ActOnFields(Scope* S, SourceLocation RecLoc, Decl *TagDecl,
+ Decl **Fields, unsigned NumFields,
+ SourceLocation LBrac, SourceLocation RBrac,
+ AttributeList *AttrList);
+
+ /// ActOnTagStartDefinition - Invoked when we have entered the
+ /// scope of a tag's definition (e.g., for an enumeration, class,
+ /// struct, or union).
+ void ActOnTagStartDefinition(Scope *S, Decl *TagDecl);
+
+ /// ActOnStartCXXMemberDeclarations - Invoked when we have parsed a
+ /// C++ record definition's base-specifiers clause and are starting its
+ /// member declarations.
+ void ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagDecl,
+ SourceLocation LBraceLoc);
+
+ /// ActOnTagFinishDefinition - Invoked once we have finished parsing
+ /// the definition of a tag (enumeration, class, struct, or union).
+ void ActOnTagFinishDefinition(Scope *S, Decl *TagDecl,
+ SourceLocation RBraceLoc);
+
+ /// ActOnTagDefinitionError - Invoked when there was an unrecoverable
+ /// error parsing the definition of a tag.
+ void ActOnTagDefinitionError(Scope *S, Decl *TagDecl);
+
+ EnumConstantDecl *CheckEnumConstant(EnumDecl *Enum,
+ EnumConstantDecl *LastEnumConst,
+ SourceLocation IdLoc,
+ IdentifierInfo *Id,
+ Expr *val);
+
+ Decl *ActOnEnumConstant(Scope *S, Decl *EnumDecl, Decl *LastEnumConstant,
+ SourceLocation IdLoc, IdentifierInfo *Id,
+ SourceLocation EqualLoc, Expr *Val);
+ void ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
+ SourceLocation RBraceLoc, Decl *EnumDecl,
+ Decl **Elements, unsigned NumElements,
+ Scope *S, AttributeList *Attr);
+
+ DeclContext *getContainingDC(DeclContext *DC);
+
+ /// Set the current declaration context until it gets popped.
+ void PushDeclContext(Scope *S, DeclContext *DC);
+ void PopDeclContext();
+
+ /// EnterDeclaratorContext - Used when we must lookup names in the context
+ /// of a declarator's nested name specifier.
+ void EnterDeclaratorContext(Scope *S, DeclContext *DC);
+ void ExitDeclaratorContext(Scope *S);
+
+ DeclContext *getFunctionLevelDeclContext();
+
+ /// getCurFunctionDecl - If inside of a function body, this returns a pointer
+ /// to the function decl for the function being parsed. If we're currently
+ /// in a 'block', this returns the containing context.
+ FunctionDecl *getCurFunctionDecl();
+
+ /// getCurMethodDecl - If inside of a method body, this returns a pointer to
+ /// the method decl for the method being parsed. If we're currently
+ /// in a 'block', this returns the containing context.
+ ObjCMethodDecl *getCurMethodDecl();
+
+ /// getCurFunctionOrMethodDecl - Return the Decl for the current ObjC method
+ /// or C function we're in, otherwise return null. If we're currently
+ /// in a 'block', this returns the containing context.
+ NamedDecl *getCurFunctionOrMethodDecl();
+
+ /// Add this decl to the scope shadowed decl chains.
+ void PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext = true);
+
+ /// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true
+ /// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns
+ /// true if 'D' belongs to the given declaration context.
+ bool isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S = 0);
+
+ /// Finds the scope corresponding to the given decl context, if it
+ /// happens to be an enclosing scope. Otherwise return NULL.
+ static Scope *getScopeForDeclContext(Scope *S, DeclContext *DC);
+
+ /// Subroutines of ActOnDeclarator().
+ TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D, QualType T,
+ TypeSourceInfo *TInfo);
+ void MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls);
+ bool MergeFunctionDecl(FunctionDecl *New, Decl *Old);
+ bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old);
+ void MergeVarDecl(VarDecl *New, LookupResult &OldDecls);
+ bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old);
+
+ // AssignmentAction - This is used by all the assignment diagnostic functions
+ // to represent what is actually causing the operation
+ enum AssignmentAction {
+ AA_Assigning,
+ AA_Passing,
+ AA_Returning,
+ AA_Converting,
+ AA_Initializing,
+ AA_Sending,
+ AA_Casting
+ };
+
+ /// C++ Overloading.
+ enum OverloadKind {
+ /// This is a legitimate overload: the existing declarations are
+ /// functions or function templates with different signatures.
+ Ovl_Overload,
+
+ /// This is not an overload because the signature exactly matches
+ /// an existing declaration.
+ Ovl_Match,
+
+ /// This is not an overload because the lookup results contain a
+ /// non-function.
+ Ovl_NonFunction
+ };
+ OverloadKind CheckOverload(Scope *S,
+ FunctionDecl *New,
+ const LookupResult &OldDecls,
+ NamedDecl *&OldDecl,
+ bool IsForUsingDecl);
+ bool IsOverload(FunctionDecl *New, FunctionDecl *Old, bool IsForUsingDecl);
+
+ bool TryImplicitConversion(InitializationSequence &Sequence,
+ const InitializedEntity &Entity,
+ Expr *From,
+ bool SuppressUserConversions,
+ bool AllowExplicit,
+ bool InOverloadResolution);
+
+ bool IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType);
+ bool IsFloatingPointPromotion(QualType FromType, QualType ToType);
+ bool IsComplexPromotion(QualType FromType, QualType ToType);
+ bool IsPointerConversion(Expr *From, QualType FromType, QualType ToType,
+ bool InOverloadResolution,
+ QualType& ConvertedType, bool &IncompatibleObjC);
+ bool isObjCPointerConversion(QualType FromType, QualType ToType,
+ QualType& ConvertedType, bool &IncompatibleObjC);
+ bool FunctionArgTypesAreEqual (FunctionProtoType* OldType,
+ FunctionProtoType* NewType);
+
+ bool CheckPointerConversion(Expr *From, QualType ToType,
+ CastKind &Kind,
+ CXXCastPath& BasePath,
+ bool IgnoreBaseAccess);
+ bool IsMemberPointerConversion(Expr *From, QualType FromType, QualType ToType,
+ bool InOverloadResolution,
+ QualType &ConvertedType);
+ bool CheckMemberPointerConversion(Expr *From, QualType ToType,
+ CastKind &Kind,
+ CXXCastPath &BasePath,
+ bool IgnoreBaseAccess);
+ bool IsQualificationConversion(QualType FromType, QualType ToType);
+ bool DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType);
+
+
+ ExprResult PerformCopyInitialization(const InitializedEntity &Entity,
+ SourceLocation EqualLoc,
+ ExprResult Init);
+ bool PerformObjectArgumentInitialization(Expr *&From,
+ NestedNameSpecifier *Qualifier,
+ NamedDecl *FoundDecl,
+ CXXMethodDecl *Method);
+
+ bool PerformContextuallyConvertToBool(Expr *&From);
+ bool PerformContextuallyConvertToObjCId(Expr *&From);
+
+ ExprResult
+ ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *FromE,
+ const PartialDiagnostic &NotIntDiag,
+ const PartialDiagnostic &IncompleteDiag,
+ const PartialDiagnostic &ExplicitConvDiag,
+ const PartialDiagnostic &ExplicitConvNote,
+ const PartialDiagnostic &AmbigDiag,
+ const PartialDiagnostic &AmbigNote,
+ const PartialDiagnostic &ConvDiag);
+
+ bool PerformObjectMemberConversion(Expr *&From,
+ NestedNameSpecifier *Qualifier,
+ NamedDecl *FoundDecl,
+ NamedDecl *Member);
+
+ // Members have to be NamespaceDecl* or TranslationUnitDecl*.
+ // TODO: make this is a typesafe union.
+ typedef llvm::SmallPtrSet<DeclContext *, 16> AssociatedNamespaceSet;
+ typedef llvm::SmallPtrSet<CXXRecordDecl *, 16> AssociatedClassSet;
+
+ void AddOverloadCandidate(NamedDecl *Function,
+ DeclAccessPair FoundDecl,
+ Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet &CandidateSet);
+
+ void AddOverloadCandidate(FunctionDecl *Function,
+ DeclAccessPair FoundDecl,
+ Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet& CandidateSet,
+ bool SuppressUserConversions = false,
+ bool PartialOverloading = false);
+ void AddFunctionCandidates(const UnresolvedSetImpl &Functions,
+ Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet& CandidateSet,
+ bool SuppressUserConversions = false);
+ void AddMethodCandidate(DeclAccessPair FoundDecl,
+ QualType ObjectType,
+ Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet& CandidateSet,
+ bool SuppressUserConversion = false);
+ void AddMethodCandidate(CXXMethodDecl *Method,
+ DeclAccessPair FoundDecl,
+ CXXRecordDecl *ActingContext, QualType ObjectType,
+ Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet& CandidateSet,
+ bool SuppressUserConversions = false);
+ void AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
+ DeclAccessPair FoundDecl,
+ CXXRecordDecl *ActingContext,
+ const TemplateArgumentListInfo *ExplicitTemplateArgs,
+ QualType ObjectType,
+ Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet& CandidateSet,
+ bool SuppressUserConversions = false);
+ void AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
+ DeclAccessPair FoundDecl,
+ const TemplateArgumentListInfo *ExplicitTemplateArgs,
+ Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet& CandidateSet,
+ bool SuppressUserConversions = false);
+ void AddConversionCandidate(CXXConversionDecl *Conversion,
+ DeclAccessPair FoundDecl,
+ CXXRecordDecl *ActingContext,
+ Expr *From, QualType ToType,
+ OverloadCandidateSet& CandidateSet);
+ void AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate,
+ DeclAccessPair FoundDecl,
+ CXXRecordDecl *ActingContext,
+ Expr *From, QualType ToType,
+ OverloadCandidateSet &CandidateSet);
+ void AddSurrogateCandidate(CXXConversionDecl *Conversion,
+ DeclAccessPair FoundDecl,
+ CXXRecordDecl *ActingContext,
+ const FunctionProtoType *Proto,
+ QualType ObjectTy, Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet& CandidateSet);
+ void AddMemberOperatorCandidates(OverloadedOperatorKind Op,
+ SourceLocation OpLoc,
+ Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet& CandidateSet,
+ SourceRange OpRange = SourceRange());
+ void AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys,
+ Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet& CandidateSet,
+ bool IsAssignmentOperator = false,
+ unsigned NumContextualBoolArguments = 0);
+ void AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
+ SourceLocation OpLoc,
+ Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet& CandidateSet);
+ void AddArgumentDependentLookupCandidates(DeclarationName Name,
+ bool Operator,
+ Expr **Args, unsigned NumArgs,
+ const TemplateArgumentListInfo *ExplicitTemplateArgs,
+ OverloadCandidateSet& CandidateSet,
+ bool PartialOverloading = false);
+
+ void NoteOverloadCandidate(FunctionDecl *Fn);
+
+ FunctionDecl *ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
+ bool Complain,
+ DeclAccessPair &Found);
+ FunctionDecl *ResolveSingleFunctionTemplateSpecialization(Expr *From);
+
+ Expr *FixOverloadedFunctionReference(Expr *E,
+ DeclAccessPair FoundDecl,
+ FunctionDecl *Fn);
+ ExprResult FixOverloadedFunctionReference(ExprResult,
+ DeclAccessPair FoundDecl,
+ FunctionDecl *Fn);
+
+ void AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE,
+ Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet &CandidateSet,
+ bool PartialOverloading = false);
+
+ ExprResult BuildOverloadedCallExpr(Scope *S, Expr *Fn,
+ UnresolvedLookupExpr *ULE,
+ SourceLocation LParenLoc,
+ Expr **Args, unsigned NumArgs,
+ SourceLocation *CommaLocs,
+ SourceLocation RParenLoc);
+
+ ExprResult CreateOverloadedUnaryOp(SourceLocation OpLoc,
+ unsigned Opc,
+ const UnresolvedSetImpl &Fns,
+ Expr *input);
+
+ ExprResult CreateOverloadedBinOp(SourceLocation OpLoc,
+ unsigned Opc,
+ const UnresolvedSetImpl &Fns,
+ Expr *LHS, Expr *RHS);
+
+ ExprResult CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
+ SourceLocation RLoc,
+ Expr *Base,Expr *Idx);
+
+ ExprResult
+ BuildCallToMemberFunction(Scope *S, Expr *MemExpr,
+ SourceLocation LParenLoc, Expr **Args,
+ unsigned NumArgs, SourceLocation *CommaLocs,
+ SourceLocation RParenLoc);
+ ExprResult
+ BuildCallToObjectOfClassType(Scope *S, Expr *Object, SourceLocation LParenLoc,
+ Expr **Args, unsigned NumArgs,
+ SourceLocation *CommaLocs,
+ SourceLocation RParenLoc);
+
+ ExprResult BuildOverloadedArrowExpr(Scope *S, Expr *Base,
+ SourceLocation OpLoc);
+
+ /// CheckCallReturnType - Checks that a call expression's return type is
+ /// complete. Returns true on failure. The location passed in is the location
+ /// that best represents the call.
+ bool CheckCallReturnType(QualType ReturnType, SourceLocation Loc,
+ CallExpr *CE, FunctionDecl *FD);
+
+ /// Helpers for dealing with blocks and functions.
+ bool CheckParmsForFunctionDef(FunctionDecl *FD);
+ void CheckCXXDefaultArguments(FunctionDecl *FD);
+ void CheckExtraCXXDefaultArguments(Declarator &D);
+ Scope *getNonFieldDeclScope(Scope *S);
+
+ /// \name Name lookup
+ ///
+ /// These routines provide name lookup that is used during semantic
+ /// analysis to resolve the various kinds of names (identifiers,
+ /// overloaded operator names, constructor names, etc.) into zero or
+ /// more declarations within a particular scope. The major entry
+ /// points are LookupName, which performs unqualified name lookup,
+ /// and LookupQualifiedName, which performs qualified name lookup.
+ ///
+ /// All name lookup is performed based on some specific criteria,
+ /// which specify what names will be visible to name lookup and how
+ /// far name lookup should work. These criteria are important both
+ /// for capturing language semantics (certain lookups will ignore
+ /// certain names, for example) and for performance, since name
+ /// lookup is often a bottleneck in the compilation of C++. Name
+ /// lookup criteria is specified via the LookupCriteria enumeration.
+ ///
+ /// The results of name lookup can vary based on the kind of name
+ /// lookup performed, the current language, and the translation
+ /// unit. In C, for example, name lookup will either return nothing
+ /// (no entity found) or a single declaration. In C++, name lookup
+ /// can additionally refer to a set of overloaded functions or
+ /// result in an ambiguity. All of the possible results of name
+ /// lookup are captured by the LookupResult class, which provides
+ /// the ability to distinguish among them.
+ //@{
+
+ /// @brief Describes the kind of name lookup to perform.
+ enum LookupNameKind {
+ /// Ordinary name lookup, which finds ordinary names (functions,
+ /// variables, typedefs, etc.) in C and most kinds of names
+ /// (functions, variables, members, types, etc.) in C++.
+ LookupOrdinaryName = 0,
+ /// Tag name lookup, which finds the names of enums, classes,
+ /// structs, and unions.
+ LookupTagName,
+ /// Member name lookup, which finds the names of
+ /// class/struct/union members.
+ LookupMemberName,
+ // Look up of an operator name (e.g., operator+) for use with
+ // operator overloading. This lookup is similar to ordinary name
+ // lookup, but will ignore any declarations that are class
+ // members.
+ LookupOperatorName,
+ /// Look up of a name that precedes the '::' scope resolution
+ /// operator in C++. This lookup completely ignores operator, object,
+ /// function, and enumerator names (C++ [basic.lookup.qual]p1).
+ LookupNestedNameSpecifierName,
+ /// Look up a namespace name within a C++ using directive or
+ /// namespace alias definition, ignoring non-namespace names (C++
+ /// [basic.lookup.udir]p1).
+ LookupNamespaceName,
+ /// Look up all declarations in a scope with the given name,
+ /// including resolved using declarations. This is appropriate
+ /// for checking redeclarations for a using declaration.
+ LookupUsingDeclName,
+ /// Look up an ordinary name that is going to be redeclared as a
+ /// name with linkage. This lookup ignores any declarations that
+ /// are outside of the current scope unless they have linkage. See
+ /// C99 6.2.2p4-5 and C++ [basic.link]p6.
+ LookupRedeclarationWithLinkage,
+ /// Look up the name of an Objective-C protocol.
+ LookupObjCProtocolName,
+ /// \brief Look up any declaration with any name.
+ LookupAnyName
+ };
+
+ /// \brief Specifies whether (or how) name lookup is being performed for a
+ /// redeclaration (vs. a reference).
+ enum RedeclarationKind {
+ /// \brief The lookup is a reference to this name that is not for the
+ /// purpose of redeclaring the name.
+ NotForRedeclaration = 0,
+ /// \brief The lookup results will be used for redeclaration of a name,
+ /// if an entity by that name already exists.
+ ForRedeclaration
+ };
+
+private:
+ bool CppLookupName(LookupResult &R, Scope *S);
+
+public:
+ /// \brief Look up a name, looking for a single declaration. Return
+ /// null if the results were absent, ambiguous, or overloaded.
+ ///
+ /// It is preferable to use the elaborated form and explicitly handle
+ /// ambiguity and overloaded.
+ NamedDecl *LookupSingleName(Scope *S, DeclarationName Name,
+ SourceLocation Loc,
+ LookupNameKind NameKind,
+ RedeclarationKind Redecl
+ = NotForRedeclaration);
+ bool LookupName(LookupResult &R, Scope *S,
+ bool AllowBuiltinCreation = false);
+ bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
+ bool InUnqualifiedLookup = false);
+ bool LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS,
+ bool AllowBuiltinCreation = false,
+ bool EnteringContext = false);
+ ObjCProtocolDecl *LookupProtocol(IdentifierInfo *II, SourceLocation IdLoc);
+
+ void LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,
+ QualType T1, QualType T2,
+ UnresolvedSetImpl &Functions);
+
+ DeclContextLookupResult LookupConstructors(CXXRecordDecl *Class);
+ CXXDestructorDecl *LookupDestructor(CXXRecordDecl *Class);
+
+ void ArgumentDependentLookup(DeclarationName Name, bool Operator,
+ Expr **Args, unsigned NumArgs,
+ ADLResult &Functions);
+
+ void LookupVisibleDecls(Scope *S, LookupNameKind Kind,
+ VisibleDeclConsumer &Consumer,
+ bool IncludeGlobalScope = true);
+ void LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind,
+ VisibleDeclConsumer &Consumer,
+ bool IncludeGlobalScope = true);
+
+ /// \brief The context in which typo-correction occurs.
+ ///
+ /// The typo-correction context affects which keywords (if any) are
+ /// considered when trying to correct for typos.
+ enum CorrectTypoContext {
+ /// \brief An unknown context, where any keyword might be valid.
+ CTC_Unknown,
+ /// \brief A context where no keywords are used (e.g. we expect an actual
+ /// name).
+ CTC_NoKeywords,
+ /// \brief A context where we're correcting a type name.
+ CTC_Type,
+ /// \brief An expression context.
+ CTC_Expression,
+ /// \brief A type cast, or anything else that can be followed by a '<'.
+ CTC_CXXCasts,
+ /// \brief A member lookup context.
+ CTC_MemberLookup,
+ /// \brief The receiver of an Objective-C message send within an
+ /// Objective-C method where 'super' is a valid keyword.
+ CTC_ObjCMessageReceiver
+ };
+
+ DeclarationName CorrectTypo(LookupResult &R, Scope *S, CXXScopeSpec *SS,
+ DeclContext *MemberContext = 0,
+ bool EnteringContext = false,
+ CorrectTypoContext CTC = CTC_Unknown,
+ const ObjCObjectPointerType *OPT = 0);
+
+ void FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs,
+ AssociatedNamespaceSet &AssociatedNamespaces,
+ AssociatedClassSet &AssociatedClasses);
+
+ bool DiagnoseAmbiguousLookup(LookupResult &Result);
+ //@}
+
+ ObjCInterfaceDecl *getObjCInterfaceDecl(IdentifierInfo *&Id,
+ SourceLocation IdLoc,
+ bool TypoCorrection = false);
+ NamedDecl *LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID,
+ Scope *S, bool ForRedeclaration,
+ SourceLocation Loc);
+ NamedDecl *ImplicitlyDefineFunction(SourceLocation Loc, IdentifierInfo &II,
+ Scope *S);
+ void AddKnownFunctionAttributes(FunctionDecl *FD);
+
+ // More parsing and symbol table subroutines.
+
+ // Decl attributes - this routine is the top level dispatcher.
+ void ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD);
+ void ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *AL);
+
+ void WarnUndefinedMethod(SourceLocation ImpLoc, ObjCMethodDecl *method,
+ bool &IncompleteImpl, unsigned DiagID);
+ void WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethod,
+ ObjCMethodDecl *IntfMethod);
+
+ bool isPropertyReadonly(ObjCPropertyDecl *PropertyDecl,
+ ObjCInterfaceDecl *IDecl);
+
+ typedef llvm::DenseSet<Selector, llvm::DenseMapInfo<Selector> > SelectorSet;
+
+ /// CheckProtocolMethodDefs - This routine checks unimplemented
+ /// methods declared in protocol, and those referenced by it.
+ /// \param IDecl - Used for checking for methods which may have been
+ /// inherited.
+ void CheckProtocolMethodDefs(SourceLocation ImpLoc,
+ ObjCProtocolDecl *PDecl,
+ bool& IncompleteImpl,
+ const SelectorSet &InsMap,
+ const SelectorSet &ClsMap,
+ ObjCContainerDecl *CDecl);
+
+ /// CheckImplementationIvars - This routine checks if the instance variables
+ /// listed in the implelementation match those listed in the interface.
+ void CheckImplementationIvars(ObjCImplementationDecl *ImpDecl,
+ ObjCIvarDecl **Fields, unsigned nIvars,
+ SourceLocation Loc);
+
+ /// ImplMethodsVsClassMethods - This is main routine to warn if any method
+ /// remains unimplemented in the class or category @implementation.
+ void ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl,
+ ObjCContainerDecl* IDecl,
+ bool IncompleteImpl = false);
+
+ /// DiagnoseUnimplementedProperties - This routine warns on those properties
+ /// which must be implemented by this implementation.
+ void DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl,
+ ObjCContainerDecl *CDecl,
+ const SelectorSet &InsMap);
+
+ /// DefaultSynthesizeProperties - This routine default synthesizes all
+ /// properties which must be synthesized in class's @implementation.
+ void DefaultSynthesizeProperties (Scope *S, ObjCImplDecl* IMPDecl,
+ ObjCInterfaceDecl *IDecl);
+
+ /// CollectImmediateProperties - This routine collects all properties in
+ /// the class and its conforming protocols; but not those it its super class.
+ void CollectImmediateProperties(ObjCContainerDecl *CDecl,
+ llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap,
+ llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& SuperPropMap);
+
+
+ /// LookupPropertyDecl - Looks up a property in the current class and all
+ /// its protocols.
+ ObjCPropertyDecl *LookupPropertyDecl(const ObjCContainerDecl *CDecl,
+ IdentifierInfo *II);
+
+ /// Called by ActOnProperty to handle @property declarations in
+ //// class extensions.
+ Decl *HandlePropertyInClassExtension(Scope *S,
+ ObjCCategoryDecl *CDecl,
+ SourceLocation AtLoc,
+ FieldDeclarator &FD,
+ Selector GetterSel,
+ Selector SetterSel,
+ const bool isAssign,
+ const bool isReadWrite,
+ const unsigned Attributes,
+ bool *isOverridingProperty,
+ TypeSourceInfo *T,
+ tok::ObjCKeywordKind MethodImplKind);
+
+ /// Called by ActOnProperty and HandlePropertyInClassExtension to
+ /// handle creating the ObjcPropertyDecl for a category or @interface.
+ ObjCPropertyDecl *CreatePropertyDecl(Scope *S,
+ ObjCContainerDecl *CDecl,
+ SourceLocation AtLoc,
+ FieldDeclarator &FD,
+ Selector GetterSel,
+ Selector SetterSel,
+ const bool isAssign,
+ const bool isReadWrite,
+ const unsigned Attributes,
+ TypeSourceInfo *T,
+ tok::ObjCKeywordKind MethodImplKind,
+ DeclContext *lexicalDC = 0);
+
+ /// AtomicPropertySetterGetterRules - This routine enforces the rule (via
+ /// warning) when atomic property has one but not the other user-declared
+ /// setter or getter.
+ void AtomicPropertySetterGetterRules(ObjCImplDecl* IMPDecl,
+ ObjCContainerDecl* IDecl);
+
+ void DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID, ObjCInterfaceDecl *SID);
+
+ /// MatchTwoMethodDeclarations - Checks if two methods' type match and returns
+ /// true, or false, accordingly.
+ bool MatchTwoMethodDeclarations(const ObjCMethodDecl *Method,
+ const ObjCMethodDecl *PrevMethod,
+ bool matchBasedOnSizeAndAlignment = false,
+ bool matchBasedOnStrictEqulity = false);
+
+ /// MatchAllMethodDeclarations - Check methods declaraed in interface or
+ /// or protocol against those declared in their implementations.
+ void MatchAllMethodDeclarations(const SelectorSet &InsMap,
+ const SelectorSet &ClsMap,
+ SelectorSet &InsMapSeen,
+ SelectorSet &ClsMapSeen,
+ ObjCImplDecl* IMPDecl,
+ ObjCContainerDecl* IDecl,
+ bool &IncompleteImpl,
+ bool ImmediateClass);
+
+private:
+ /// AddMethodToGlobalPool - Add an instance or factory method to the global
+ /// pool. See descriptoin of AddInstanceMethodToGlobalPool.
+ void AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl, bool instance);
+
+ /// LookupMethodInGlobalPool - Returns the instance or factory method and
+ /// optionally warns if there are multiple signatures.
+ ObjCMethodDecl *LookupMethodInGlobalPool(Selector Sel, SourceRange R,
+ bool receiverIdOrClass,
+ bool warn, bool instance);
+
+public:
+ /// AddInstanceMethodToGlobalPool - All instance methods in a translation
+ /// unit are added to a global pool. This allows us to efficiently associate
+ /// a selector with a method declaraation for purposes of typechecking
+ /// messages sent to "id" (where the class of the object is unknown).
+ void AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method, bool impl=false) {
+ AddMethodToGlobalPool(Method, impl, /*instance*/true);
+ }
+
+ /// AddFactoryMethodToGlobalPool - Same as above, but for factory methods.
+ void AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method, bool impl=false) {
+ AddMethodToGlobalPool(Method, impl, /*instance*/false);
+ }
+
+ /// LookupInstanceMethodInGlobalPool - Returns the method and warns if
+ /// there are multiple signatures.
+ ObjCMethodDecl *LookupInstanceMethodInGlobalPool(Selector Sel, SourceRange R,
+ bool receiverIdOrClass=false,
+ bool warn=true) {
+ return LookupMethodInGlobalPool(Sel, R, receiverIdOrClass,
+ warn, /*instance*/true);
+ }
+
+ /// LookupFactoryMethodInGlobalPool - Returns the method and warns if
+ /// there are multiple signatures.
+ ObjCMethodDecl *LookupFactoryMethodInGlobalPool(Selector Sel, SourceRange R,
+ bool receiverIdOrClass=false,
+ bool warn=true) {
+ return LookupMethodInGlobalPool(Sel, R, receiverIdOrClass,
+ warn, /*instance*/false);
+ }
+
+ /// LookupImplementedMethodInGlobalPool - Returns the method which has an
+ /// implementation.
+ ObjCMethodDecl *LookupImplementedMethodInGlobalPool(Selector Sel);
+
+ /// CollectIvarsToConstructOrDestruct - Collect those ivars which require
+ /// initialization.
+ void CollectIvarsToConstructOrDestruct(ObjCInterfaceDecl *OI,
+ llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars);
+ //===--------------------------------------------------------------------===//
+ // Statement Parsing Callbacks: SemaStmt.cpp.
+public:
+ class FullExprArg {
+ public:
+ FullExprArg(Sema &actions) : E(0) { }
+
+ // FIXME: The const_cast here is ugly. RValue references would make this
+ // much nicer (or we could duplicate a bunch of the move semantics
+ // emulation code from Ownership.h).
+ FullExprArg(const FullExprArg& Other): E(Other.E) {}
+
+ ExprResult release() {
+ return move(E);
+ }
+
+ Expr *get() const { return E; }
+
+ Expr *operator->() {
+ return E;
+ }
+
+ private:
+ // FIXME: No need to make the entire Sema class a friend when it's just
+ // Sema::FullExpr that needs access to the constructor below.
+ friend class Sema;
+
+ explicit FullExprArg(Expr *expr) : E(expr) {}
+
+ Expr *E;
+ };
+
+ FullExprArg MakeFullExpr(Expr *Arg) {
+ return FullExprArg(ActOnFinishFullExpr(Arg).release());
+ }
+
+ StmtResult ActOnExprStmt(FullExprArg Expr);
+
+ StmtResult ActOnNullStmt(SourceLocation SemiLoc);
+ StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R,
+ MultiStmtArg Elts,
+ bool isStmtExpr);
+ StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ void ActOnForEachDeclStmt(DeclGroupPtrTy Decl);
+ StmtResult ActOnCaseStmt(SourceLocation CaseLoc, Expr *LHSVal,
+ SourceLocation DotDotDotLoc, Expr *RHSVal,
+ SourceLocation ColonLoc);
+ void ActOnCaseStmtBody(Stmt *CaseStmt, Stmt *SubStmt);
+
+ StmtResult ActOnDefaultStmt(SourceLocation DefaultLoc,
+ SourceLocation ColonLoc,
+ Stmt *SubStmt, Scope *CurScope);
+ StmtResult ActOnLabelStmt(SourceLocation IdentLoc,
+ IdentifierInfo *II,
+ SourceLocation ColonLoc,
+ Stmt *SubStmt);
+ StmtResult ActOnIfStmt(SourceLocation IfLoc,
+ FullExprArg CondVal, Decl *CondVar,
+ Stmt *ThenVal,
+ SourceLocation ElseLoc, Stmt *ElseVal);
+ StmtResult ActOnStartOfSwitchStmt(SourceLocation SwitchLoc,
+ Expr *Cond,
+ Decl *CondVar);
+ StmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc,
+ Stmt *Switch, Stmt *Body);
+ StmtResult ActOnWhileStmt(SourceLocation WhileLoc,
+ FullExprArg Cond,
+ Decl *CondVar, Stmt *Body);
+ StmtResult ActOnDoStmt(SourceLocation DoLoc, Stmt *Body,
+ SourceLocation WhileLoc,
+ SourceLocation CondLParen, Expr *Cond,
+ SourceLocation CondRParen);
+
+ StmtResult ActOnForStmt(SourceLocation ForLoc,
+ SourceLocation LParenLoc,
+ Stmt *First, FullExprArg Second,
+ Decl *SecondVar,
+ FullExprArg Third,
+ SourceLocation RParenLoc,
+ Stmt *Body);
+ StmtResult ActOnObjCForCollectionStmt(SourceLocation ForColLoc,
+ SourceLocation LParenLoc,
+ Stmt *First, Expr *Second,
+ SourceLocation RParenLoc, Stmt *Body);
+
+ StmtResult ActOnGotoStmt(SourceLocation GotoLoc,
+ SourceLocation LabelLoc,
+ IdentifierInfo *LabelII);
+ StmtResult ActOnIndirectGotoStmt(SourceLocation GotoLoc,
+ SourceLocation StarLoc,
+ Expr *DestExp);
+ StmtResult ActOnContinueStmt(SourceLocation ContinueLoc, Scope *CurScope);
+ StmtResult ActOnBreakStmt(SourceLocation GotoLoc, Scope *CurScope);
+
+ StmtResult ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp);
+ StmtResult ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp);
+
+ StmtResult ActOnAsmStmt(SourceLocation AsmLoc,
+ bool IsSimple, bool IsVolatile,
+ unsigned NumOutputs, unsigned NumInputs,
+ IdentifierInfo **Names,
+ MultiExprArg Constraints,
+ MultiExprArg Exprs,
+ Expr *AsmString,
+ MultiExprArg Clobbers,
+ SourceLocation RParenLoc,
+ bool MSAsm = false);
+
+
+ VarDecl *BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType ExceptionType,
+ IdentifierInfo *Name, SourceLocation NameLoc,
+ bool Invalid = false);
+
+ Decl *ActOnObjCExceptionDecl(Scope *S, Declarator &D);
+
+ StmtResult ActOnObjCAtCatchStmt(SourceLocation AtLoc, SourceLocation RParen,
+ Decl *Parm, Stmt *Body);
+
+ StmtResult ActOnObjCAtFinallyStmt(SourceLocation AtLoc, Stmt *Body);
+
+ StmtResult ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try,
+ MultiStmtArg Catch, Stmt *Finally);
+
+ StmtResult BuildObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw);
+ StmtResult ActOnObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw,
+ Scope *CurScope);
+ StmtResult ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc,
+ Expr *SynchExpr,
+ Stmt *SynchBody);
+
+ VarDecl *BuildExceptionDeclaration(Scope *S, QualType ExDeclType,
+ TypeSourceInfo *TInfo,
+ IdentifierInfo *Name,
+ SourceLocation Loc,
+ SourceRange Range);
+ Decl *ActOnExceptionDeclarator(Scope *S, Declarator &D);
+
+ StmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc,
+ Decl *ExDecl, Stmt *HandlerBlock);
+ StmtResult ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
+ MultiStmtArg Handlers);
+ void DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock);
+
+ bool ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const;
+
+ /// \brief If it's a file scoped decl that must warn if not used, keep track
+ /// of it.
+ void MarkUnusedFileScopedDecl(const DeclaratorDecl *D);
+
+ /// DiagnoseUnusedExprResult - If the statement passed in is an expression
+ /// whose result is unused, warn.
+ void DiagnoseUnusedExprResult(const Stmt *S);
+ void DiagnoseUnusedDecl(const NamedDecl *ND);
+
+ typedef uintptr_t ParsingDeclStackState;
+
+ ParsingDeclStackState PushParsingDeclaration();
+ void PopParsingDeclaration(ParsingDeclStackState S, Decl *D);
+ void EmitDeprecationWarning(NamedDecl *D, SourceLocation Loc);
+
+ void HandleDelayedDeprecationCheck(sema::DelayedDiagnostic &DD, Decl *Ctx);
+
+ //===--------------------------------------------------------------------===//
+ // Expression Parsing Callbacks: SemaExpr.cpp.
+
+ bool DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc);
+ bool DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *PD,
+ ObjCMethodDecl *Getter,
+ SourceLocation Loc);
+ void DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc,
+ Expr **Args, unsigned NumArgs);
+
+ void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext);
+
+ void PopExpressionEvaluationContext();
+
+ void MarkDeclarationReferenced(SourceLocation Loc, Decl *D);
+ void MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T);
+ bool DiagRuntimeBehavior(SourceLocation Loc, const PartialDiagnostic &PD);
+
+ // Primary Expressions.
+ SourceRange getExprRange(Expr *E) const;
+
+ ExprResult ActOnIdExpression(Scope *S, CXXScopeSpec &SS, UnqualifiedId &Name,
+ bool HasTrailingLParen, bool IsAddressOfOperand);
+
+ bool DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
+ CorrectTypoContext CTC = CTC_Unknown);
+
+ ExprResult LookupInObjCMethod(LookupResult &R, Scope *S, IdentifierInfo *II,
+ bool AllowBuiltinCreation=false);
+
+ ExprResult ActOnDependentIdExpression(const CXXScopeSpec &SS,
+ const DeclarationNameInfo &NameInfo,
+ bool isAddressOfOperand,
+ const TemplateArgumentListInfo *TemplateArgs);
+
+ ExprResult BuildDeclRefExpr(ValueDecl *D, QualType Ty,
+ SourceLocation Loc,
+ const CXXScopeSpec *SS = 0);
+ ExprResult BuildDeclRefExpr(ValueDecl *D, QualType Ty,
+ const DeclarationNameInfo &NameInfo,
+ const CXXScopeSpec *SS = 0);
+ VarDecl *BuildAnonymousStructUnionMemberPath(FieldDecl *Field,
+ llvm::SmallVectorImpl<FieldDecl *> &Path);
+ ExprResult
+ BuildAnonymousStructUnionMemberReference(SourceLocation Loc,
+ FieldDecl *Field,
+ Expr *BaseObjectExpr = 0,
+ SourceLocation OpLoc = SourceLocation());
+ ExprResult BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS,
+ LookupResult &R,
+ const TemplateArgumentListInfo *TemplateArgs);
+ ExprResult BuildImplicitMemberExpr(const CXXScopeSpec &SS,
+ LookupResult &R,
+ const TemplateArgumentListInfo *TemplateArgs,
+ bool IsDefiniteInstance);
+ bool UseArgumentDependentLookup(const CXXScopeSpec &SS,
+ const LookupResult &R,
+ bool HasTrailingLParen);
+
+ ExprResult BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS,
+ const DeclarationNameInfo &NameInfo);
+ ExprResult BuildDependentDeclRefExpr(const CXXScopeSpec &SS,
+ const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *TemplateArgs);
+
+ ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS,
+ LookupResult &R,
+ bool ADL);
+ ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS,
+ const DeclarationNameInfo &NameInfo,
+ NamedDecl *D);
+
+ ExprResult ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind);
+ ExprResult ActOnNumericConstant(const Token &);
+ ExprResult ActOnCharacterConstant(const Token &);
+ ExprResult ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *Val);
+ ExprResult ActOnParenOrParenListExpr(SourceLocation L,
+ SourceLocation R,
+ MultiExprArg Val,
+ ParsedType TypeOfCast = ParsedType());
+
+ /// ActOnStringLiteral - The specified tokens were lexed as pasted string
+ /// fragments (e.g. "foo" "bar" L"baz").
+ ExprResult ActOnStringLiteral(const Token *Toks, unsigned NumToks);
+
+ // Binary/Unary Operators. 'Tok' is the token for the operator.
+ ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
+ Expr *InputArg);
+ ExprResult BuildUnaryOp(Scope *S, SourceLocation OpLoc,
+ UnaryOperatorKind Opc, Expr *input);
+ ExprResult ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
+ tok::TokenKind Op, Expr *Input);
+
+ ExprResult CreateSizeOfAlignOfExpr(TypeSourceInfo *T,
+ SourceLocation OpLoc,
+ bool isSizeOf, SourceRange R);
+ ExprResult CreateSizeOfAlignOfExpr(Expr *E, SourceLocation OpLoc,
+ bool isSizeOf, SourceRange R);
+ ExprResult
+ ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType,
+ void *TyOrEx, const SourceRange &ArgRange);
+
+ bool CheckAlignOfExpr(Expr *E, SourceLocation OpLoc, const SourceRange &R);
+ bool CheckSizeOfAlignOfOperand(QualType type, SourceLocation OpLoc,
+ const SourceRange &R, bool isSizeof);
+
+ ExprResult ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc,
+ tok::TokenKind Kind, Expr *Input);
+
+ ExprResult ActOnArraySubscriptExpr(Scope *S, Expr *Base, SourceLocation LLoc,
+ Expr *Idx, SourceLocation RLoc);
+ ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
+ Expr *Idx, SourceLocation RLoc);
+
+ ExprResult BuildMemberReferenceExpr(Expr *Base, QualType BaseType,
+ SourceLocation OpLoc, bool IsArrow,
+ CXXScopeSpec &SS,
+ NamedDecl *FirstQualifierInScope,
+ const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *TemplateArgs);
+
+ ExprResult BuildMemberReferenceExpr(Expr *Base, QualType BaseType,
+ SourceLocation OpLoc, bool IsArrow,
+ const CXXScopeSpec &SS,
+ NamedDecl *FirstQualifierInScope,
+ LookupResult &R,
+ const TemplateArgumentListInfo *TemplateArgs,
+ bool SuppressQualifierCheck = false);
+
+ ExprResult LookupMemberExpr(LookupResult &R, Expr *&Base,
+ bool &IsArrow, SourceLocation OpLoc,
+ CXXScopeSpec &SS,
+ Decl *ObjCImpDecl,
+ bool HasTemplateArgs);
+
+ bool CheckQualifiedMemberReference(Expr *BaseExpr, QualType BaseType,
+ const CXXScopeSpec &SS,
+ const LookupResult &R);
+
+ ExprResult ActOnDependentMemberExpr(Expr *Base, QualType BaseType,
+ bool IsArrow, SourceLocation OpLoc,
+ const CXXScopeSpec &SS,
+ NamedDecl *FirstQualifierInScope,
+ const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *TemplateArgs);
+
+ ExprResult ActOnMemberAccessExpr(Scope *S, Expr *Base,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ CXXScopeSpec &SS,
+ UnqualifiedId &Member,
+ Decl *ObjCImpDecl,
+ bool HasTrailingLParen);
+
+ void ActOnDefaultCtorInitializers(Decl *CDtorDecl);
+ bool ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
+ FunctionDecl *FDecl,
+ const FunctionProtoType *Proto,
+ Expr **Args, unsigned NumArgs,
+ SourceLocation RParenLoc);
+
+ /// 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.
+ ExprResult ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
+ MultiExprArg Args, SourceLocation *CommaLocs,
+ SourceLocation RParenLoc);
+ ExprResult BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
+ SourceLocation LParenLoc,
+ Expr **Args, unsigned NumArgs,
+ SourceLocation RParenLoc);
+
+ ExprResult ActOnCastExpr(Scope *S, SourceLocation LParenLoc,
+ ParsedType Ty, SourceLocation RParenLoc,
+ Expr *Op);
+ ExprResult BuildCStyleCastExpr(SourceLocation LParenLoc,
+ TypeSourceInfo *Ty,
+ SourceLocation RParenLoc,
+ Expr *Op);
+
+ bool TypeIsVectorType(ParsedType Ty) {
+ return GetTypeFromParser(Ty)->isVectorType();
+ }
+
+ ExprResult MaybeConvertParenListExprToParenExpr(Scope *S, Expr *ME);
+ ExprResult ActOnCastOfParenListExpr(Scope *S, SourceLocation LParenLoc,
+ SourceLocation RParenLoc, Expr *E,
+ TypeSourceInfo *TInfo);
+
+ ExprResult ActOnCompoundLiteral(SourceLocation LParenLoc,
+ ParsedType Ty,
+ SourceLocation RParenLoc,
+ Expr *Op);
+
+ ExprResult BuildCompoundLiteralExpr(SourceLocation LParenLoc,
+ TypeSourceInfo *TInfo,
+ SourceLocation RParenLoc,
+ Expr *InitExpr);
+
+ ExprResult ActOnInitList(SourceLocation LParenLoc,
+ MultiExprArg InitList,
+ SourceLocation RParenLoc);
+
+ ExprResult ActOnDesignatedInitializer(Designation &Desig,
+ SourceLocation Loc,
+ bool GNUSyntax,
+ ExprResult Init);
+
+ ExprResult ActOnBinOp(Scope *S, SourceLocation TokLoc,
+ tok::TokenKind Kind, Expr *LHS, Expr *RHS);
+ ExprResult BuildBinOp(Scope *S, SourceLocation OpLoc,
+ BinaryOperatorKind Opc, Expr *lhs, Expr *rhs);
+ ExprResult CreateBuiltinBinOp(SourceLocation TokLoc,
+ unsigned Opc, Expr *lhs, Expr *rhs);
+
+ /// ActOnConditionalOp - Parse a ?: operation. Note that 'LHS' may be null
+ /// in the case of a the GNU conditional expr extension.
+ ExprResult ActOnConditionalOp(SourceLocation QuestionLoc,
+ SourceLocation ColonLoc,
+ Expr *Cond, Expr *LHS, Expr *RHS);
+
+ /// ActOnAddrLabel - Parse the GNU address of label extension: "&&foo".
+ ExprResult ActOnAddrLabel(SourceLocation OpLoc,
+ SourceLocation LabLoc,
+ IdentifierInfo *LabelII);
+
+ ExprResult ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt,
+ SourceLocation RPLoc); // "({..})"
+
+ // __builtin_offsetof(type, identifier(.identifier|[expr])*)
+ struct OffsetOfComponent {
+ SourceLocation LocStart, LocEnd;
+ bool isBrackets; // true if [expr], false if .ident
+ union {
+ IdentifierInfo *IdentInfo;
+ ExprTy *E;
+ } U;
+ };
+
+ /// __builtin_offsetof(type, a.b[123][456].c)
+ ExprResult BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
+ TypeSourceInfo *TInfo,
+ OffsetOfComponent *CompPtr,
+ unsigned NumComponents,
+ SourceLocation RParenLoc);
+ ExprResult ActOnBuiltinOffsetOf(Scope *S,
+ SourceLocation BuiltinLoc,
+ SourceLocation TypeLoc,
+ ParsedType Arg1,
+ OffsetOfComponent *CompPtr,
+ unsigned NumComponents,
+ SourceLocation RParenLoc);
+
+ // __builtin_types_compatible_p(type1, type2)
+ ExprResult ActOnTypesCompatibleExpr(SourceLocation BuiltinLoc,
+ ParsedType arg1,
+ ParsedType arg2,
+ SourceLocation RPLoc);
+ ExprResult BuildTypesCompatibleExpr(SourceLocation BuiltinLoc,
+ TypeSourceInfo *argTInfo1,
+ TypeSourceInfo *argTInfo2,
+ SourceLocation RPLoc);
+
+ // __builtin_choose_expr(constExpr, expr1, expr2)
+ ExprResult ActOnChooseExpr(SourceLocation BuiltinLoc,
+ Expr *cond, Expr *expr1,
+ Expr *expr2, SourceLocation RPLoc);
+
+ // __builtin_va_arg(expr, type)
+ ExprResult ActOnVAArg(SourceLocation BuiltinLoc,
+ Expr *expr, ParsedType type,
+ SourceLocation RPLoc);
+ ExprResult BuildVAArgExpr(SourceLocation BuiltinLoc,
+ Expr *expr, TypeSourceInfo *TInfo,
+ SourceLocation RPLoc);
+
+ // __null
+ ExprResult ActOnGNUNullExpr(SourceLocation TokenLoc);
+
+ //===------------------------- "Block" Extension ------------------------===//
+
+ /// ActOnBlockStart - This callback is invoked when a block literal is
+ /// started.
+ void ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope);
+
+ /// ActOnBlockArguments - This callback allows processing of block arguments.
+ /// If there are no arguments, this is still invoked.
+ void ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope);
+
+ /// ActOnBlockError - If there is an error parsing a block, this callback
+ /// is invoked to pop the information about the block from the action impl.
+ void ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope);
+
+ /// ActOnBlockStmtExpr - This is called when the body of a block statement
+ /// literal was successfully completed. ^(int x){...}
+ ExprResult ActOnBlockStmtExpr(SourceLocation CaretLoc,
+ Stmt *Body, Scope *CurScope);
+
+ //===---------------------------- C++ Features --------------------------===//
+
+ // Act on C++ namespaces
+ Decl *ActOnStartNamespaceDef(Scope *S, SourceLocation InlineLoc,
+ SourceLocation IdentLoc,
+ IdentifierInfo *Ident,
+ SourceLocation LBrace,
+ AttributeList *AttrList);
+ void ActOnFinishNamespaceDef(Decl *Dcl, SourceLocation RBrace);
+
+ NamespaceDecl *getStdNamespace() const;
+ NamespaceDecl *getOrCreateStdNamespace();
+
+ CXXRecordDecl *getStdBadAlloc() const;
+
+ Decl *ActOnUsingDirective(Scope *CurScope,
+ SourceLocation UsingLoc,
+ SourceLocation NamespcLoc,
+ CXXScopeSpec &SS,
+ SourceLocation IdentLoc,
+ IdentifierInfo *NamespcName,
+ AttributeList *AttrList);
+
+ void PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir);
+
+ Decl *ActOnNamespaceAliasDef(Scope *CurScope,
+ SourceLocation NamespaceLoc,
+ SourceLocation AliasLoc,
+ IdentifierInfo *Alias,
+ CXXScopeSpec &SS,
+ SourceLocation IdentLoc,
+ IdentifierInfo *Ident);
+
+ void HideUsingShadowDecl(Scope *S, UsingShadowDecl *Shadow);
+ bool CheckUsingShadowDecl(UsingDecl *UD, NamedDecl *Target,
+ const LookupResult &PreviousDecls);
+ UsingShadowDecl *BuildUsingShadowDecl(Scope *S, UsingDecl *UD,
+ NamedDecl *Target);
+
+ bool CheckUsingDeclRedeclaration(SourceLocation UsingLoc,
+ bool isTypeName,
+ const CXXScopeSpec &SS,
+ SourceLocation NameLoc,
+ const LookupResult &Previous);
+ bool CheckUsingDeclQualifier(SourceLocation UsingLoc,
+ const CXXScopeSpec &SS,
+ SourceLocation NameLoc);
+
+ NamedDecl *BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
+ SourceLocation UsingLoc,
+ CXXScopeSpec &SS,
+ const DeclarationNameInfo &NameInfo,
+ AttributeList *AttrList,
+ bool IsInstantiation,
+ bool IsTypeName,
+ SourceLocation TypenameLoc);
+
+ Decl *ActOnUsingDeclaration(Scope *CurScope,
+ AccessSpecifier AS,
+ bool HasUsingKeyword,
+ SourceLocation UsingLoc,
+ CXXScopeSpec &SS,
+ UnqualifiedId &Name,
+ AttributeList *AttrList,
+ bool IsTypeName,
+ SourceLocation TypenameLoc);
+
+ /// AddCXXDirectInitializerToDecl - This action is called immediately after
+ /// ActOnDeclarator, when a C++ direct initializer is present.
+ /// e.g: "int x(1);"
+ void AddCXXDirectInitializerToDecl(Decl *Dcl,
+ SourceLocation LParenLoc,
+ MultiExprArg Exprs,
+ SourceLocation *CommaLocs,
+ SourceLocation RParenLoc);
+
+ /// InitializeVarWithConstructor - Creates an CXXConstructExpr
+ /// and sets it as the initializer for the the passed in VarDecl.
+ bool InitializeVarWithConstructor(VarDecl *VD,
+ CXXConstructorDecl *Constructor,
+ MultiExprArg Exprs);
+
+ /// BuildCXXConstructExpr - Creates a complete call to a constructor,
+ /// including handling of its default argument expressions.
+ ///
+ /// \param ConstructKind - a CXXConstructExpr::ConstructionKind
+ ExprResult
+ BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
+ CXXConstructorDecl *Constructor, MultiExprArg Exprs,
+ bool RequiresZeroInit, unsigned ConstructKind);
+
+ // FIXME: Can re remove this and have the above BuildCXXConstructExpr check if
+ // the constructor can be elidable?
+ ExprResult
+ BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
+ CXXConstructorDecl *Constructor, bool Elidable,
+ MultiExprArg Exprs, bool RequiresZeroInit,
+ unsigned ConstructKind);
+
+ /// BuildCXXDefaultArgExpr - Creates a CXXDefaultArgExpr, instantiating
+ /// the default expr if needed.
+ ExprResult BuildCXXDefaultArgExpr(SourceLocation CallLoc,
+ FunctionDecl *FD,
+ ParmVarDecl *Param);
+
+ /// FinalizeVarWithDestructor - Prepare for calling destructor on the
+ /// constructed variable.
+ void FinalizeVarWithDestructor(VarDecl *VD, const RecordType *DeclInitType);
+
+ /// \brief Declare the implicit default constructor for the given class.
+ ///
+ /// \param ClassDecl The class declaration into which the implicit
+ /// default constructor will be added.
+ ///
+ /// \returns The implicitly-declared default constructor.
+ CXXConstructorDecl *DeclareImplicitDefaultConstructor(
+ CXXRecordDecl *ClassDecl);
+
+ /// DefineImplicitDefaultConstructor - Checks for feasibility of
+ /// defining this constructor as the default constructor.
+ void DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
+ CXXConstructorDecl *Constructor);
+
+ /// \brief Declare the implicit destructor for the given class.
+ ///
+ /// \param ClassDecl The class declaration into which the implicit
+ /// destructor will be added.
+ ///
+ /// \returns The implicitly-declared destructor.
+ CXXDestructorDecl *DeclareImplicitDestructor(CXXRecordDecl *ClassDecl);
+
+ /// DefineImplicitDestructor - Checks for feasibility of
+ /// defining this destructor as the default destructor.
+ void DefineImplicitDestructor(SourceLocation CurrentLocation,
+ CXXDestructorDecl *Destructor);
+
+ /// \brief Declare the implicit copy constructor for the given class.
+ ///
+ /// \param S The scope of the class, which may be NULL if this is a
+ /// template instantiation.
+ ///
+ /// \param ClassDecl The class declaration into which the implicit
+ /// copy constructor will be added.
+ ///
+ /// \returns The implicitly-declared copy constructor.
+ CXXConstructorDecl *DeclareImplicitCopyConstructor(CXXRecordDecl *ClassDecl);
+
+ /// DefineImplicitCopyConstructor - Checks for feasibility of
+ /// defining this constructor as the copy constructor.
+ void DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
+ CXXConstructorDecl *Constructor,
+ unsigned TypeQuals);
+
+ /// \brief Declare the implicit copy assignment operator for the given class.
+ ///
+ /// \param S The scope of the class, which may be NULL if this is a
+ /// template instantiation.
+ ///
+ /// \param ClassDecl The class declaration into which the implicit
+ /// copy-assignment operator will be added.
+ ///
+ /// \returns The implicitly-declared copy assignment operator.
+ CXXMethodDecl *DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl);
+
+ /// \brief Defined an implicitly-declared copy assignment operator.
+ void DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
+ CXXMethodDecl *MethodDecl);
+
+ /// \brief Force the declaration of any implicitly-declared members of this
+ /// class.
+ void ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class);
+
+ /// MaybeBindToTemporary - If the passed in expression has a record type with
+ /// a non-trivial destructor, this will return CXXBindTemporaryExpr. Otherwise
+ /// it simply returns the passed in expression.
+ ExprResult MaybeBindToTemporary(Expr *E);
+
+ bool CompleteConstructorCall(CXXConstructorDecl *Constructor,
+ MultiExprArg ArgsPtr,
+ SourceLocation Loc,
+ ASTOwningVector<Expr*> &ConvertedArgs);
+
+ ParsedType getDestructorName(SourceLocation TildeLoc,
+ IdentifierInfo &II, SourceLocation NameLoc,
+ Scope *S, CXXScopeSpec &SS,
+ ParsedType ObjectType,
+ bool EnteringContext);
+
+ /// ActOnCXXNamedCast - Parse {dynamic,static,reinterpret,const}_cast's.
+ ExprResult ActOnCXXNamedCast(SourceLocation OpLoc,
+ tok::TokenKind Kind,
+ SourceLocation LAngleBracketLoc,
+ ParsedType Ty,
+ SourceLocation RAngleBracketLoc,
+ SourceLocation LParenLoc,
+ Expr *E,
+ SourceLocation RParenLoc);
+
+ ExprResult BuildCXXNamedCast(SourceLocation OpLoc,
+ tok::TokenKind Kind,
+ TypeSourceInfo *Ty,
+ Expr *E,
+ SourceRange AngleBrackets,
+ SourceRange Parens);
+
+ ExprResult BuildCXXTypeId(QualType TypeInfoType,
+ SourceLocation TypeidLoc,
+ TypeSourceInfo *Operand,
+ SourceLocation RParenLoc);
+ ExprResult BuildCXXTypeId(QualType TypeInfoType,
+ SourceLocation TypeidLoc,
+ Expr *Operand,
+ SourceLocation RParenLoc);
+
+ /// ActOnCXXTypeid - Parse typeid( something ).
+ ExprResult ActOnCXXTypeid(SourceLocation OpLoc,
+ SourceLocation LParenLoc, bool isType,
+ void *TyOrExpr,
+ SourceLocation RParenLoc);
+
+ //// ActOnCXXThis - Parse 'this' pointer.
+ ExprResult ActOnCXXThis(SourceLocation ThisLoc);
+
+ /// ActOnCXXBoolLiteral - Parse {true,false} literals.
+ ExprResult ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind);
+
+ /// ActOnCXXNullPtrLiteral - Parse 'nullptr'.
+ ExprResult ActOnCXXNullPtrLiteral(SourceLocation Loc);
+
+ //// ActOnCXXThrow - Parse throw expressions.
+ ExprResult ActOnCXXThrow(SourceLocation OpLoc, Expr *expr);
+ bool CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *&E);
+
+ /// ActOnCXXTypeConstructExpr - Parse construction of a specified type.
+ /// Can be interpreted either as function-style casting ("int(x)")
+ /// or class type construction ("ClassType(x,y,z)")
+ /// or creation of a value-initialized type ("int()").
+ ExprResult ActOnCXXTypeConstructExpr(SourceRange TypeRange,
+ ParsedType TypeRep,
+ SourceLocation LParenLoc,
+ MultiExprArg Exprs,
+ SourceLocation *CommaLocs,
+ SourceLocation RParenLoc);
+
+ /// ActOnCXXNew - Parsed a C++ 'new' expression.
+ ExprResult ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
+ SourceLocation PlacementLParen,
+ MultiExprArg PlacementArgs,
+ SourceLocation PlacementRParen,
+ SourceRange TypeIdParens, Declarator &D,
+ SourceLocation ConstructorLParen,
+ MultiExprArg ConstructorArgs,
+ SourceLocation ConstructorRParen);
+ ExprResult BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
+ SourceLocation PlacementLParen,
+ MultiExprArg PlacementArgs,
+ SourceLocation PlacementRParen,
+ SourceRange TypeIdParens,
+ QualType AllocType,
+ SourceLocation TypeLoc,
+ SourceRange TypeRange,
+ Expr *ArraySize,
+ SourceLocation ConstructorLParen,
+ MultiExprArg ConstructorArgs,
+ SourceLocation ConstructorRParen);
+
+ bool CheckAllocatedType(QualType AllocType, SourceLocation Loc,
+ SourceRange R);
+ bool FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
+ bool UseGlobal, QualType AllocType, bool IsArray,
+ Expr **PlaceArgs, unsigned NumPlaceArgs,
+ FunctionDecl *&OperatorNew,
+ FunctionDecl *&OperatorDelete);
+ bool FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
+ DeclarationName Name, Expr** Args,
+ unsigned NumArgs, DeclContext *Ctx,
+ bool AllowMissing, FunctionDecl *&Operator);
+ void DeclareGlobalNewDelete();
+ void DeclareGlobalAllocationFunction(DeclarationName Name, QualType Return,
+ QualType Argument,
+ bool addMallocAttr = false);
+
+ bool FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
+ DeclarationName Name, FunctionDecl* &Operator);
+
+ /// ActOnCXXDelete - Parsed a C++ 'delete' expression
+ ExprResult ActOnCXXDelete(SourceLocation StartLoc,
+ bool UseGlobal, bool ArrayForm,
+ Expr *Operand);
+
+ DeclResult ActOnCXXConditionDeclaration(Scope *S, Declarator &D);
+ ExprResult CheckConditionVariable(VarDecl *ConditionVar,
+ SourceLocation StmtLoc,
+ bool ConvertToBoolean);
+
+ /// ActOnUnaryTypeTrait - Parsed one of the unary type trait support
+ /// pseudo-functions.
+ ExprResult ActOnUnaryTypeTrait(UnaryTypeTrait OTT,
+ SourceLocation KWLoc,
+ SourceLocation LParen,
+ ParsedType Ty,
+ SourceLocation RParen);
+
+ ExprResult ActOnStartCXXMemberReference(Scope *S,
+ Expr *Base,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ ParsedType &ObjectType,
+ bool &MayBePseudoDestructor);
+
+ ExprResult DiagnoseDtorReference(SourceLocation NameLoc, Expr *MemExpr);
+
+ ExprResult BuildPseudoDestructorExpr(Expr *Base,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ const CXXScopeSpec &SS,
+ TypeSourceInfo *ScopeType,
+ SourceLocation CCLoc,
+ SourceLocation TildeLoc,
+ PseudoDestructorTypeStorage DestroyedType,
+ bool HasTrailingLParen);
+
+ ExprResult ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ CXXScopeSpec &SS,
+ UnqualifiedId &FirstTypeName,
+ SourceLocation CCLoc,
+ SourceLocation TildeLoc,
+ UnqualifiedId &SecondTypeName,
+ bool HasTrailingLParen);
+
+ /// MaybeCreateCXXExprWithTemporaries - If the list of temporaries is
+ /// non-empty, will create a new CXXExprWithTemporaries expression.
+ /// Otherwise, just returs the passed in expression.
+ Expr *MaybeCreateCXXExprWithTemporaries(Expr *SubExpr);
+ ExprResult MaybeCreateCXXExprWithTemporaries(ExprResult SubExpr);
+ FullExpr CreateFullExpr(Expr *SubExpr);
+
+ ExprResult ActOnFinishFullExpr(Expr *Expr);
+
+ // Marks SS invalid if it represents an incomplete type.
+ bool RequireCompleteDeclContext(CXXScopeSpec &SS, DeclContext *DC);
+
+ DeclContext *computeDeclContext(QualType T);
+ DeclContext *computeDeclContext(const CXXScopeSpec &SS,
+ bool EnteringContext = false);
+ bool isDependentScopeSpecifier(const CXXScopeSpec &SS);
+ CXXRecordDecl *getCurrentInstantiationOf(NestedNameSpecifier *NNS);
+ bool isUnknownSpecialization(const CXXScopeSpec &SS);
+
+ /// ActOnCXXGlobalScopeSpecifier - Return the object that represents the
+ /// global scope ('::').
+ NestedNameSpecifier *
+ ActOnCXXGlobalScopeSpecifier(Scope *S, SourceLocation CCLoc);
+
+ bool isAcceptableNestedNameSpecifier(NamedDecl *SD);
+ NamedDecl *FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS);
+
+ bool isNonTypeNestedNameSpecifier(Scope *S, CXXScopeSpec &SS,
+ SourceLocation IdLoc,
+ IdentifierInfo &II,
+ ParsedType ObjectType);
+
+ NestedNameSpecifier *BuildCXXNestedNameSpecifier(Scope *S,
+ CXXScopeSpec &SS,
+ SourceLocation IdLoc,
+ SourceLocation CCLoc,
+ IdentifierInfo &II,
+ QualType ObjectType,
+ NamedDecl *ScopeLookupResult,
+ bool EnteringContext,
+ bool ErrorRecoveryLookup);
+
+ NestedNameSpecifier *ActOnCXXNestedNameSpecifier(Scope *S,
+ CXXScopeSpec &SS,
+ SourceLocation IdLoc,
+ SourceLocation CCLoc,
+ IdentifierInfo &II,
+ ParsedType ObjectType,
+ bool EnteringContext);
+
+ bool IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS,
+ IdentifierInfo &II,
+ ParsedType ObjectType,
+ bool EnteringContext);
+
+ /// ActOnCXXNestedNameSpecifier - Called during parsing of a
+ /// nested-name-specifier that involves a template-id, e.g.,
+ /// "foo::bar<int, float>::", and now we need to build a scope
+ /// specifier. \p SS is empty or the previously parsed nested-name
+ /// part ("foo::"), \p Type is the already-parsed class template
+ /// specialization (or other template-id that names a type), \p
+ /// TypeRange is the source range where the type is located, and \p
+ /// CCLoc is the location of the trailing '::'.
+ CXXScopeTy *ActOnCXXNestedNameSpecifier(Scope *S,
+ const CXXScopeSpec &SS,
+ ParsedType Type,
+ SourceRange TypeRange,
+ SourceLocation CCLoc);
+
+ bool ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS);
+
+ /// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global
+ /// scope or nested-name-specifier) is parsed, part of a declarator-id.
+ /// After this method is called, according to [C++ 3.4.3p3], names should be
+ /// looked up in the declarator-id's scope, until the declarator is parsed and
+ /// ActOnCXXExitDeclaratorScope is called.
+ /// The 'SS' should be a non-empty valid CXXScopeSpec.
+ bool ActOnCXXEnterDeclaratorScope(Scope *S, CXXScopeSpec &SS);
+
+ /// ActOnCXXExitDeclaratorScope - Called when a declarator that previously
+ /// invoked ActOnCXXEnterDeclaratorScope(), is finished. 'SS' is the same
+ /// CXXScopeSpec that was passed to ActOnCXXEnterDeclaratorScope as well.
+ /// Used to indicate that names should revert to being looked up in the
+ /// defining scope.
+ void ActOnCXXExitDeclaratorScope(Scope *S, const CXXScopeSpec &SS);
+
+ /// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse an
+ /// initializer for the declaration 'Dcl'.
+ /// After this method is called, according to [C++ 3.4.1p13], if 'Dcl' is a
+ /// static data member of class X, names should be looked up in the scope of
+ /// class X.
+ void ActOnCXXEnterDeclInitializer(Scope *S, Decl *Dcl);
+
+ /// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an
+ /// initializer for the declaration 'Dcl'.
+ void ActOnCXXExitDeclInitializer(Scope *S, Decl *Dcl);
+
+ // ParseObjCStringLiteral - Parse Objective-C string literals.
+ ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs,
+ Expr **Strings,
+ unsigned NumStrings);
+
+ Expr *BuildObjCEncodeExpression(SourceLocation AtLoc,
+ TypeSourceInfo *EncodedTypeInfo,
+ SourceLocation RParenLoc);
+ CXXMemberCallExpr *BuildCXXMemberCallExpr(Expr *Exp,
+ NamedDecl *FoundDecl,
+ CXXMethodDecl *Method);
+
+ ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc,
+ SourceLocation EncodeLoc,
+ SourceLocation LParenLoc,
+ ParsedType Ty,
+ SourceLocation RParenLoc);
+
+ // ParseObjCSelectorExpression - Build selector expression for @selector
+ ExprResult ParseObjCSelectorExpression(Selector Sel,
+ SourceLocation AtLoc,
+ SourceLocation SelLoc,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc);
+
+ // ParseObjCProtocolExpression - Build protocol expression for @protocol
+ ExprResult ParseObjCProtocolExpression(IdentifierInfo * ProtocolName,
+ SourceLocation AtLoc,
+ SourceLocation ProtoLoc,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc);
+
+ //===--------------------------------------------------------------------===//
+ // C++ Declarations
+ //
+ Decl *ActOnStartLinkageSpecification(Scope *S,
+ SourceLocation ExternLoc,
+ SourceLocation LangLoc,
+ llvm::StringRef Lang,
+ SourceLocation LBraceLoc);
+ Decl *ActOnFinishLinkageSpecification(Scope *S,
+ Decl *LinkageSpec,
+ SourceLocation RBraceLoc);
+
+
+ //===--------------------------------------------------------------------===//
+ // C++ Classes
+ //
+ bool isCurrentClassName(const IdentifierInfo &II, Scope *S,
+ const CXXScopeSpec *SS = 0);
+
+ Decl *ActOnAccessSpecifier(AccessSpecifier Access,
+ SourceLocation ASLoc,
+ SourceLocation ColonLoc);
+
+ Decl *ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS,
+ Declarator &D,
+ MultiTemplateParamsArg TemplateParameterLists,
+ Expr *BitfieldWidth,
+ Expr *Init, bool IsDefinition,
+ bool Deleted = false);
+
+ MemInitResult ActOnMemInitializer(Decl *ConstructorD,
+ Scope *S,
+ CXXScopeSpec &SS,
+ IdentifierInfo *MemberOrBase,
+ ParsedType TemplateTypeTy,
+ SourceLocation IdLoc,
+ SourceLocation LParenLoc,
+ Expr **Args, unsigned NumArgs,
+ SourceLocation *CommaLocs,
+ SourceLocation RParenLoc);
+
+ MemInitResult BuildMemberInitializer(FieldDecl *Member, Expr **Args,
+ unsigned NumArgs, SourceLocation IdLoc,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc);
+
+ MemInitResult BuildBaseInitializer(QualType BaseType,
+ TypeSourceInfo *BaseTInfo,
+ Expr **Args, unsigned NumArgs,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc,
+ CXXRecordDecl *ClassDecl);
+
+ bool SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
+ CXXBaseOrMemberInitializer **Initializers,
+ unsigned NumInitializers, bool AnyErrors);
+
+ void SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation);
+
+
+ /// MarkBaseAndMemberDestructorsReferenced - Given a record decl,
+ /// mark all the non-trivial destructors of its members and bases as
+ /// referenced.
+ void MarkBaseAndMemberDestructorsReferenced(SourceLocation Loc,
+ CXXRecordDecl *Record);
+
+ /// \brief The list of classes whose vtables have been used within
+ /// this translation unit, and the source locations at which the
+ /// first use occurred.
+ llvm::SmallVector<std::pair<CXXRecordDecl *, SourceLocation>, 16>
+ VTableUses;
+
+ /// \brief The set of classes whose vtables have been used within
+ /// this translation unit, and a bit that will be true if the vtable is
+ /// required to be emitted (otherwise, it should be emitted only if needed
+ /// by code generation).
+ llvm::DenseMap<CXXRecordDecl *, bool> VTablesUsed;
+
+ /// \brief A list of all of the dynamic classes in this translation
+ /// unit.
+ llvm::SmallVector<CXXRecordDecl *, 16> DynamicClasses;
+
+ /// \brief Note that the vtable for the given class was used at the
+ /// given location.
+ void MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class,
+ bool DefinitionRequired = false);
+
+ /// MarkVirtualMembersReferenced - Will mark all members of the given
+ /// CXXRecordDecl referenced.
+ void MarkVirtualMembersReferenced(SourceLocation Loc,
+ const CXXRecordDecl *RD);
+
+ /// \brief Define all of the vtables that have been used in this
+ /// translation unit and reference any virtual members used by those
+ /// vtables.
+ ///
+ /// \returns true if any work was done, false otherwise.
+ bool DefineUsedVTables();
+
+ void AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl);
+
+ void ActOnMemInitializers(Decl *ConstructorDecl,
+ SourceLocation ColonLoc,
+ MemInitTy **MemInits, unsigned NumMemInits,
+ bool AnyErrors);
+
+ void CheckCompletedCXXClass(CXXRecordDecl *Record);
+ void ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
+ Decl *TagDecl,
+ SourceLocation LBrac,
+ SourceLocation RBrac,
+ AttributeList *AttrList);
+
+ void ActOnReenterTemplateScope(Scope *S, Decl *Template);
+ void ActOnStartDelayedMemberDeclarations(Scope *S, Decl *Record);
+ void ActOnStartDelayedCXXMethodDeclaration(Scope *S, Decl *Method);
+ void ActOnDelayedCXXMethodParameter(Scope *S, Decl *Param);
+ void ActOnFinishDelayedCXXMethodDeclaration(Scope *S, Decl *Method);
+ void ActOnFinishDelayedMemberDeclarations(Scope *S, Decl *Record);
+
+ Decl *ActOnStaticAssertDeclaration(SourceLocation AssertLoc,
+ Expr *AssertExpr,
+ Expr *AssertMessageExpr);
+
+ FriendDecl *CheckFriendTypeDecl(SourceLocation FriendLoc,
+ TypeSourceInfo *TSInfo);
+ Decl *ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
+ MultiTemplateParamsArg TemplateParams);
+ Decl *ActOnFriendFunctionDecl(Scope *S, Declarator &D, bool IsDefinition,
+ MultiTemplateParamsArg TemplateParams);
+
+ QualType CheckConstructorDeclarator(Declarator &D, QualType R,
+ StorageClass& SC);
+ void CheckConstructor(CXXConstructorDecl *Constructor);
+ QualType CheckDestructorDeclarator(Declarator &D, QualType R,
+ StorageClass& SC);
+ bool CheckDestructor(CXXDestructorDecl *Destructor);
+ void CheckConversionDeclarator(Declarator &D, QualType &R,
+ StorageClass& SC);
+ Decl *ActOnConversionDeclarator(CXXConversionDecl *Conversion);
+
+ //===--------------------------------------------------------------------===//
+ // C++ Derived Classes
+ //
+
+ /// ActOnBaseSpecifier - Parsed a base specifier
+ CXXBaseSpecifier *CheckBaseSpecifier(CXXRecordDecl *Class,
+ SourceRange SpecifierRange,
+ bool Virtual, AccessSpecifier Access,
+ TypeSourceInfo *TInfo);
+
+ /// SetClassDeclAttributesFromBase - Copies class decl traits
+ /// (such as whether the class has a trivial constructor,
+ /// trivial destructor etc) from the given base class.
+ void SetClassDeclAttributesFromBase(CXXRecordDecl *Class,
+ const CXXRecordDecl *BaseClass,
+ bool BaseIsVirtual);
+
+ BaseResult ActOnBaseSpecifier(Decl *classdecl,
+ SourceRange SpecifierRange,
+ bool Virtual, AccessSpecifier Access,
+ ParsedType basetype, SourceLocation
+ BaseLoc);
+
+ bool AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases,
+ unsigned NumBases);
+ void ActOnBaseSpecifiers(Decl *ClassDecl, BaseTy **Bases, unsigned NumBases);
+
+ bool IsDerivedFrom(QualType Derived, QualType Base);
+ bool IsDerivedFrom(QualType Derived, QualType Base, CXXBasePaths &Paths);
+
+ // FIXME: I don't like this name.
+ void BuildBasePathArray(const CXXBasePaths &Paths, CXXCastPath &BasePath);
+
+ bool BasePathInvolvesVirtualBase(const CXXCastPath &BasePath);
+
+ bool CheckDerivedToBaseConversion(QualType Derived, QualType Base,
+ SourceLocation Loc, SourceRange Range,
+ CXXCastPath *BasePath = 0,
+ bool IgnoreAccess = false);
+ bool CheckDerivedToBaseConversion(QualType Derived, QualType Base,
+ unsigned InaccessibleBaseID,
+ unsigned AmbigiousBaseConvID,
+ SourceLocation Loc, SourceRange Range,
+ DeclarationName Name,
+ CXXCastPath *BasePath);
+
+ std::string getAmbiguousPathsDisplayString(CXXBasePaths &Paths);
+
+ /// CheckOverridingFunctionReturnType - Checks whether the return types are
+ /// covariant, according to C++ [class.virtual]p5.
+ bool CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
+ const CXXMethodDecl *Old);
+
+ /// CheckOverridingFunctionExceptionSpec - Checks whether the exception
+ /// spec is a subset of base spec.
+ bool CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,
+ const CXXMethodDecl *Old);
+
+ /// CheckOverridingFunctionAttributes - Checks whether attributes are
+ /// incompatible or prevent overriding.
+ bool CheckOverridingFunctionAttributes(const CXXMethodDecl *New,
+ const CXXMethodDecl *Old);
+
+ bool CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange);
+
+ //===--------------------------------------------------------------------===//
+ // C++ Access Control
+ //
+
+ enum AccessResult {
+ AR_accessible,
+ AR_inaccessible,
+ AR_dependent,
+ AR_delayed
+ };
+
+ bool SetMemberAccessSpecifier(NamedDecl *MemberDecl,
+ NamedDecl *PrevMemberDecl,
+ AccessSpecifier LexicalAS);
+
+ AccessResult CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E,
+ DeclAccessPair FoundDecl);
+ AccessResult CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E,
+ DeclAccessPair FoundDecl);
+ AccessResult CheckAllocationAccess(SourceLocation OperatorLoc,
+ SourceRange PlacementRange,
+ CXXRecordDecl *NamingClass,
+ DeclAccessPair FoundDecl);
+ AccessResult CheckConstructorAccess(SourceLocation Loc,
+ CXXConstructorDecl *D,
+ const InitializedEntity &Entity,
+ AccessSpecifier Access,
+ bool IsCopyBindingRefToTemp = false);
+ AccessResult CheckDestructorAccess(SourceLocation Loc,
+ CXXDestructorDecl *Dtor,
+ const PartialDiagnostic &PDiag);
+ AccessResult CheckDirectMemberAccess(SourceLocation Loc,
+ NamedDecl *D,
+ const PartialDiagnostic &PDiag);
+ AccessResult CheckMemberOperatorAccess(SourceLocation Loc,
+ Expr *ObjectExpr,
+ Expr *ArgExpr,
+ DeclAccessPair FoundDecl);
+ AccessResult CheckAddressOfMemberAccess(Expr *OvlExpr,
+ DeclAccessPair FoundDecl);
+ AccessResult CheckBaseClassAccess(SourceLocation AccessLoc,
+ QualType Base, QualType Derived,
+ const CXXBasePath &Path,
+ unsigned DiagID,
+ bool ForceCheck = false,
+ bool ForceUnprivileged = false);
+ void CheckLookupAccess(const LookupResult &R);
+
+ void HandleDependentAccessCheck(const DependentDiagnostic &DD,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+ void PerformDependentDiagnostics(const DeclContext *Pattern,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+
+ void HandleDelayedAccessCheck(sema::DelayedDiagnostic &DD, Decl *Ctx);
+
+ /// A flag to suppress access checking.
+ bool SuppressAccessChecking;
+
+ void ActOnStartSuppressingAccessChecks();
+ void ActOnStopSuppressingAccessChecks();
+
+ enum AbstractDiagSelID {
+ AbstractNone = -1,
+ AbstractReturnType,
+ AbstractParamType,
+ AbstractVariableType,
+ AbstractFieldType,
+ AbstractArrayType
+ };
+
+ bool RequireNonAbstractType(SourceLocation Loc, QualType T,
+ const PartialDiagnostic &PD);
+ void DiagnoseAbstractType(const CXXRecordDecl *RD);
+
+ bool RequireNonAbstractType(SourceLocation Loc, QualType T, unsigned DiagID,
+ AbstractDiagSelID SelID = AbstractNone);
+
+ //===--------------------------------------------------------------------===//
+ // C++ Overloaded Operators [C++ 13.5]
+ //
+
+ bool CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl);
+
+ bool CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl);
+
+ //===--------------------------------------------------------------------===//
+ // C++ Templates [C++ 14]
+ //
+ void LookupTemplateName(LookupResult &R, Scope *S, CXXScopeSpec &SS,
+ QualType ObjectType, bool EnteringContext,
+ bool &MemberOfUnknownSpecialization);
+
+ TemplateNameKind isTemplateName(Scope *S,
+ CXXScopeSpec &SS,
+ bool hasTemplateKeyword,
+ UnqualifiedId &Name,
+ ParsedType ObjectType,
+ bool EnteringContext,
+ TemplateTy &Template,
+ bool &MemberOfUnknownSpecialization);
+
+ bool DiagnoseUnknownTemplateName(const IdentifierInfo &II,
+ SourceLocation IILoc,
+ Scope *S,
+ const CXXScopeSpec *SS,
+ TemplateTy &SuggestedTemplate,
+ TemplateNameKind &SuggestedKind);
+
+ bool DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl);
+ TemplateDecl *AdjustDeclIfTemplate(Decl *&Decl);
+
+ Decl *ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis,
+ SourceLocation EllipsisLoc,
+ SourceLocation KeyLoc,
+ IdentifierInfo *ParamName,
+ SourceLocation ParamNameLoc,
+ unsigned Depth, unsigned Position,
+ SourceLocation EqualLoc,
+ ParsedType DefaultArg);
+
+ QualType CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc);
+ Decl *ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
+ unsigned Depth,
+ unsigned Position,
+ SourceLocation EqualLoc,
+ Expr *DefaultArg);
+ Decl *ActOnTemplateTemplateParameter(Scope *S,
+ SourceLocation TmpLoc,
+ TemplateParamsTy *Params,
+ IdentifierInfo *ParamName,
+ SourceLocation ParamNameLoc,
+ unsigned Depth,
+ unsigned Position,
+ SourceLocation EqualLoc,
+ const ParsedTemplateArgument &DefaultArg);
+
+ TemplateParamsTy *
+ ActOnTemplateParameterList(unsigned Depth,
+ SourceLocation ExportLoc,
+ SourceLocation TemplateLoc,
+ SourceLocation LAngleLoc,
+ Decl **Params, unsigned NumParams,
+ SourceLocation RAngleLoc);
+
+ /// \brief The context in which we are checking a template parameter
+ /// list.
+ enum TemplateParamListContext {
+ TPC_ClassTemplate,
+ TPC_FunctionTemplate,
+ TPC_ClassTemplateMember,
+ TPC_FriendFunctionTemplate
+ };
+
+ bool CheckTemplateParameterList(TemplateParameterList *NewParams,
+ TemplateParameterList *OldParams,
+ TemplateParamListContext TPC);
+ TemplateParameterList *
+ MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc,
+ const CXXScopeSpec &SS,
+ TemplateParameterList **ParamLists,
+ unsigned NumParamLists,
+ bool IsFriend,
+ bool &IsExplicitSpecialization,
+ bool &Invalid);
+
+ DeclResult CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
+ SourceLocation KWLoc, CXXScopeSpec &SS,
+ IdentifierInfo *Name, SourceLocation NameLoc,
+ AttributeList *Attr,
+ TemplateParameterList *TemplateParams,
+ AccessSpecifier AS);
+
+ void translateTemplateArguments(const ASTTemplateArgsPtr &In,
+ TemplateArgumentListInfo &Out);
+
+ QualType CheckTemplateIdType(TemplateName Template,
+ SourceLocation TemplateLoc,
+ const TemplateArgumentListInfo &TemplateArgs);
+
+ TypeResult
+ ActOnTemplateIdType(TemplateTy Template, SourceLocation TemplateLoc,
+ SourceLocation LAngleLoc,
+ ASTTemplateArgsPtr TemplateArgs,
+ SourceLocation RAngleLoc);
+
+ TypeResult ActOnTagTemplateIdType(TypeResult Type,
+ TagUseKind TUK,
+ TypeSpecifierType TagSpec,
+ SourceLocation TagLoc);
+
+ ExprResult BuildTemplateIdExpr(const CXXScopeSpec &SS,
+ LookupResult &R,
+ bool RequiresADL,
+ const TemplateArgumentListInfo &TemplateArgs);
+ ExprResult BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS,
+ const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo &TemplateArgs);
+
+ TemplateNameKind ActOnDependentTemplateName(Scope *S,
+ SourceLocation TemplateKWLoc,
+ CXXScopeSpec &SS,
+ UnqualifiedId &Name,
+ ParsedType ObjectType,
+ bool EnteringContext,
+ TemplateTy &Template);
+
+ bool CheckClassTemplatePartialSpecializationArgs(
+ TemplateParameterList *TemplateParams,
+ const TemplateArgumentListBuilder &TemplateArgs,
+ bool &MirrorsPrimaryTemplate);
+
+ DeclResult
+ ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagUseKind TUK,
+ SourceLocation KWLoc,
+ CXXScopeSpec &SS,
+ TemplateTy Template,
+ SourceLocation TemplateNameLoc,
+ SourceLocation LAngleLoc,
+ ASTTemplateArgsPtr TemplateArgs,
+ SourceLocation RAngleLoc,
+ AttributeList *Attr,
+ MultiTemplateParamsArg TemplateParameterLists);
+
+ Decl *ActOnTemplateDeclarator(Scope *S,
+ MultiTemplateParamsArg TemplateParameterLists,
+ Declarator &D);
+
+ Decl *ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope,
+ MultiTemplateParamsArg TemplateParameterLists,
+ Declarator &D);
+
+ bool
+ CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
+ TemplateSpecializationKind NewTSK,
+ NamedDecl *PrevDecl,
+ TemplateSpecializationKind PrevTSK,
+ SourceLocation PrevPtOfInstantiation,
+ bool &SuppressNew);
+
+ bool CheckDependentFunctionTemplateSpecialization(FunctionDecl *FD,
+ const TemplateArgumentListInfo &ExplicitTemplateArgs,
+ LookupResult &Previous);
+
+ bool CheckFunctionTemplateSpecialization(FunctionDecl *FD,
+ const TemplateArgumentListInfo *ExplicitTemplateArgs,
+ LookupResult &Previous);
+ bool CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous);
+
+ DeclResult
+ ActOnExplicitInstantiation(Scope *S,
+ SourceLocation ExternLoc,
+ SourceLocation TemplateLoc,
+ unsigned TagSpec,
+ SourceLocation KWLoc,
+ const CXXScopeSpec &SS,
+ TemplateTy Template,
+ SourceLocation TemplateNameLoc,
+ SourceLocation LAngleLoc,
+ ASTTemplateArgsPtr TemplateArgs,
+ SourceLocation RAngleLoc,
+ AttributeList *Attr);
+
+ DeclResult
+ ActOnExplicitInstantiation(Scope *S,
+ SourceLocation ExternLoc,
+ SourceLocation TemplateLoc,
+ unsigned TagSpec,
+ SourceLocation KWLoc,
+ CXXScopeSpec &SS,
+ IdentifierInfo *Name,
+ SourceLocation NameLoc,
+ AttributeList *Attr);
+
+ DeclResult ActOnExplicitInstantiation(Scope *S,
+ SourceLocation ExternLoc,
+ SourceLocation TemplateLoc,
+ Declarator &D);
+
+ TemplateArgumentLoc
+ SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template,
+ SourceLocation TemplateLoc,
+ SourceLocation RAngleLoc,
+ Decl *Param,
+ TemplateArgumentListBuilder &Converted);
+
+ /// \brief Specifies the context in which a particular template
+ /// argument is being checked.
+ enum CheckTemplateArgumentKind {
+ /// \brief The template argument was specified in the code or was
+ /// instantiated with some deduced template arguments.
+ CTAK_Specified,
+
+ /// \brief The template argument was deduced via template argument
+ /// deduction.
+ CTAK_Deduced,
+
+ /// \brief The template argument was deduced from an array bound
+ /// via template argument deduction.
+ CTAK_DeducedFromArrayBound
+ };
+
+ bool CheckTemplateArgument(NamedDecl *Param,
+ const TemplateArgumentLoc &Arg,
+ TemplateDecl *Template,
+ SourceLocation TemplateLoc,
+ SourceLocation RAngleLoc,
+ TemplateArgumentListBuilder &Converted,
+ CheckTemplateArgumentKind CTAK = CTAK_Specified);
+
+ bool CheckTemplateArgumentList(TemplateDecl *Template,
+ SourceLocation TemplateLoc,
+ const TemplateArgumentListInfo &TemplateArgs,
+ bool PartialTemplateArgs,
+ TemplateArgumentListBuilder &Converted);
+
+ bool CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
+ const TemplateArgumentLoc &Arg,
+ TemplateArgumentListBuilder &Converted);
+
+ bool CheckTemplateArgument(TemplateTypeParmDecl *Param,
+ TypeSourceInfo *Arg);
+ bool CheckTemplateArgumentPointerToMember(Expr *Arg,
+ TemplateArgument &Converted);
+ bool CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
+ QualType InstantiatedParamType, Expr *&Arg,
+ TemplateArgument &Converted,
+ CheckTemplateArgumentKind CTAK = CTAK_Specified);
+ bool CheckTemplateArgument(TemplateTemplateParmDecl *Param,
+ const TemplateArgumentLoc &Arg);
+
+ ExprResult
+ BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
+ QualType ParamType,
+ SourceLocation Loc);
+ ExprResult
+ BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,
+ SourceLocation Loc);
+
+ /// \brief Enumeration describing how template parameter lists are compared
+ /// for equality.
+ enum TemplateParameterListEqualKind {
+ /// \brief We are matching the template parameter lists of two templates
+ /// that might be redeclarations.
+ ///
+ /// \code
+ /// template<typename T> struct X;
+ /// template<typename T> struct X;
+ /// \endcode
+ TPL_TemplateMatch,
+
+ /// \brief We are matching the template parameter lists of two template
+ /// template parameters as part of matching the template parameter lists
+ /// of two templates that might be redeclarations.
+ ///
+ /// \code
+ /// template<template<int I> class TT> struct X;
+ /// template<template<int Value> class Other> struct X;
+ /// \endcode
+ TPL_TemplateTemplateParmMatch,
+
+ /// \brief We are matching the template parameter lists of a template
+ /// template argument against the template parameter lists of a template
+ /// template parameter.
+ ///
+ /// \code
+ /// template<template<int Value> class Metafun> struct X;
+ /// template<int Value> struct integer_c;
+ /// X<integer_c> xic;
+ /// \endcode
+ TPL_TemplateTemplateArgumentMatch
+ };
+
+ bool TemplateParameterListsAreEqual(TemplateParameterList *New,
+ TemplateParameterList *Old,
+ bool Complain,
+ TemplateParameterListEqualKind Kind,
+ SourceLocation TemplateArgLoc
+ = SourceLocation());
+
+ bool CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams);
+
+ /// \brief Called when the parser has parsed a C++ typename
+ /// specifier, e.g., "typename T::type".
+ ///
+ /// \param S The scope in which this typename type occurs.
+ /// \param TypenameLoc the location of the 'typename' keyword
+ /// \param SS the nested-name-specifier following the typename (e.g., 'T::').
+ /// \param II the identifier we're retrieving (e.g., 'type' in the example).
+ /// \param IdLoc the location of the identifier.
+ TypeResult
+ ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
+ const CXXScopeSpec &SS, const IdentifierInfo &II,
+ SourceLocation IdLoc);
+
+ /// \brief Called when the parser has parsed a C++ typename
+ /// specifier that ends in a template-id, e.g.,
+ /// "typename MetaFun::template apply<T1, T2>".
+ ///
+ /// \param S The scope in which this typename type occurs.
+ /// \param TypenameLoc the location of the 'typename' keyword
+ /// \param SS the nested-name-specifier following the typename (e.g., 'T::').
+ /// \param TemplateLoc the location of the 'template' keyword, if any.
+ /// \param Ty the type that the typename specifier refers to.
+ TypeResult
+ ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
+ const CXXScopeSpec &SS, SourceLocation TemplateLoc,
+ ParsedType Ty);
+
+ QualType CheckTypenameType(ElaboratedTypeKeyword Keyword,
+ NestedNameSpecifier *NNS,
+ const IdentifierInfo &II,
+ SourceLocation KeywordLoc,
+ SourceRange NNSRange,
+ SourceLocation IILoc);
+
+ TypeSourceInfo *RebuildTypeInCurrentInstantiation(TypeSourceInfo *T,
+ SourceLocation Loc,
+ DeclarationName Name);
+ bool RebuildNestedNameSpecifierInCurrentInstantiation(CXXScopeSpec &SS);
+
+ ExprResult RebuildExprInCurrentInstantiation(Expr *E);
+
+ std::string
+ getTemplateArgumentBindingsText(const TemplateParameterList *Params,
+ const TemplateArgumentList &Args);
+
+ std::string
+ getTemplateArgumentBindingsText(const TemplateParameterList *Params,
+ const TemplateArgument *Args,
+ unsigned NumArgs);
+
+ /// \brief Describes the result of template argument deduction.
+ ///
+ /// The TemplateDeductionResult enumeration describes the result of
+ /// template argument deduction, as returned from
+ /// DeduceTemplateArguments(). The separate TemplateDeductionInfo
+ /// structure provides additional information about the results of
+ /// template argument deduction, e.g., the deduced template argument
+ /// list (if successful) or the specific template parameters or
+ /// deduced arguments that were involved in the failure.
+ enum TemplateDeductionResult {
+ /// \brief Template argument deduction was successful.
+ TDK_Success = 0,
+ /// \brief Template argument deduction exceeded the maximum template
+ /// instantiation depth (which has already been diagnosed).
+ TDK_InstantiationDepth,
+ /// \brief Template argument deduction did not deduce a value
+ /// for every template parameter.
+ TDK_Incomplete,
+ /// \brief Template argument deduction produced inconsistent
+ /// deduced values for the given template parameter.
+ TDK_Inconsistent,
+ /// \brief Template argument deduction failed due to inconsistent
+ /// cv-qualifiers on a template parameter type that would
+ /// otherwise be deduced, e.g., we tried to deduce T in "const T"
+ /// but were given a non-const "X".
+ TDK_Underqualified,
+ /// \brief Substitution of the deduced template argument values
+ /// resulted in an error.
+ TDK_SubstitutionFailure,
+ /// \brief Substitution of the deduced template argument values
+ /// into a non-deduced context produced a type or value that
+ /// produces a type that does not match the original template
+ /// arguments provided.
+ TDK_NonDeducedMismatch,
+ /// \brief When performing template argument deduction for a function
+ /// template, there were too many call arguments.
+ TDK_TooManyArguments,
+ /// \brief When performing template argument deduction for a function
+ /// template, there were too few call arguments.
+ TDK_TooFewArguments,
+ /// \brief The explicitly-specified template arguments were not valid
+ /// template arguments for the given template.
+ TDK_InvalidExplicitArguments,
+ /// \brief The arguments included an overloaded function name that could
+ /// not be resolved to a suitable function.
+ TDK_FailedOverloadResolution
+ };
+
+ TemplateDeductionResult
+ DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
+ const TemplateArgumentList &TemplateArgs,
+ sema::TemplateDeductionInfo &Info);
+
+ TemplateDeductionResult
+ SubstituteExplicitTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+ const TemplateArgumentListInfo &ExplicitTemplateArgs,
+ llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ llvm::SmallVectorImpl<QualType> &ParamTypes,
+ QualType *FunctionType,
+ sema::TemplateDeductionInfo &Info);
+
+ TemplateDeductionResult
+ FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
+ llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ unsigned NumExplicitlySpecified,
+ FunctionDecl *&Specialization,
+ sema::TemplateDeductionInfo &Info);
+
+ TemplateDeductionResult
+ DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+ const TemplateArgumentListInfo *ExplicitTemplateArgs,
+ Expr **Args, unsigned NumArgs,
+ FunctionDecl *&Specialization,
+ sema::TemplateDeductionInfo &Info);
+
+ TemplateDeductionResult
+ DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+ const TemplateArgumentListInfo *ExplicitTemplateArgs,
+ QualType ArgFunctionType,
+ FunctionDecl *&Specialization,
+ sema::TemplateDeductionInfo &Info);
+
+ TemplateDeductionResult
+ DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+ QualType ToType,
+ CXXConversionDecl *&Specialization,
+ sema::TemplateDeductionInfo &Info);
+
+ TemplateDeductionResult
+ DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+ const TemplateArgumentListInfo *ExplicitTemplateArgs,
+ FunctionDecl *&Specialization,
+ sema::TemplateDeductionInfo &Info);
+
+ FunctionTemplateDecl *getMoreSpecializedTemplate(FunctionTemplateDecl *FT1,
+ FunctionTemplateDecl *FT2,
+ SourceLocation Loc,
+ TemplatePartialOrderingContext TPOC);
+ UnresolvedSetIterator getMostSpecialized(UnresolvedSetIterator SBegin,
+ UnresolvedSetIterator SEnd,
+ TemplatePartialOrderingContext TPOC,
+ SourceLocation Loc,
+ const PartialDiagnostic &NoneDiag,
+ const PartialDiagnostic &AmbigDiag,
+ const PartialDiagnostic &CandidateDiag);
+
+ ClassTemplatePartialSpecializationDecl *
+ getMoreSpecializedPartialSpecialization(
+ ClassTemplatePartialSpecializationDecl *PS1,
+ ClassTemplatePartialSpecializationDecl *PS2,
+ SourceLocation Loc);
+
+ void MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs,
+ bool OnlyDeduced,
+ unsigned Depth,
+ llvm::SmallVectorImpl<bool> &Used);
+ void MarkDeducedTemplateParameters(FunctionTemplateDecl *FunctionTemplate,
+ llvm::SmallVectorImpl<bool> &Deduced);
+
+ //===--------------------------------------------------------------------===//
+ // C++ Template Instantiation
+ //
+
+ MultiLevelTemplateArgumentList getTemplateInstantiationArgs(NamedDecl *D,
+ const TemplateArgumentList *Innermost = 0,
+ bool RelativeToPrimary = false,
+ const FunctionDecl *Pattern = 0);
+
+ /// \brief A template instantiation that is currently in progress.
+ struct ActiveTemplateInstantiation {
+ /// \brief The kind of template instantiation we are performing
+ enum InstantiationKind {
+ /// We are instantiating a template declaration. The entity is
+ /// the declaration we're instantiating (e.g., a CXXRecordDecl).
+ TemplateInstantiation,
+
+ /// We are instantiating a default argument for a template
+ /// parameter. The Entity is the template, and
+ /// TemplateArgs/NumTemplateArguments provides the template
+ /// arguments as specified.
+ /// FIXME: Use a TemplateArgumentList
+ DefaultTemplateArgumentInstantiation,
+
+ /// We are instantiating a default argument for a function.
+ /// The Entity is the ParmVarDecl, and TemplateArgs/NumTemplateArgs
+ /// provides the template arguments as specified.
+ DefaultFunctionArgumentInstantiation,
+
+ /// We are substituting explicit template arguments provided for
+ /// a function template. The entity is a FunctionTemplateDecl.
+ ExplicitTemplateArgumentSubstitution,
+
+ /// We are substituting template argument determined as part of
+ /// template argument deduction for either a class template
+ /// partial specialization or a function template. The
+ /// Entity is either a ClassTemplatePartialSpecializationDecl or
+ /// a FunctionTemplateDecl.
+ DeducedTemplateArgumentSubstitution,
+
+ /// We are substituting prior template arguments into a new
+ /// template parameter. The template parameter itself is either a
+ /// NonTypeTemplateParmDecl or a TemplateTemplateParmDecl.
+ PriorTemplateArgumentSubstitution,
+
+ /// We are checking the validity of a default template argument that
+ /// has been used when naming a template-id.
+ DefaultTemplateArgumentChecking
+ } Kind;
+
+ /// \brief The point of instantiation within the source code.
+ SourceLocation PointOfInstantiation;
+
+ /// \brief The template in which we are performing the instantiation,
+ /// for substitutions of prior template arguments.
+ TemplateDecl *Template;
+
+ /// \brief The entity that is being instantiated.
+ uintptr_t Entity;
+
+ /// \brief The list of template arguments we are substituting, if they
+ /// are not part of the entity.
+ const TemplateArgument *TemplateArgs;
+
+ /// \brief The number of template arguments in TemplateArgs.
+ unsigned NumTemplateArgs;
+
+ /// \brief The source range that covers the construct that cause
+ /// the instantiation, e.g., the template-id that causes a class
+ /// template instantiation.
+ SourceRange InstantiationRange;
+
+ ActiveTemplateInstantiation()
+ : Kind(TemplateInstantiation), Template(0), Entity(0), TemplateArgs(0),
+ NumTemplateArgs(0) {}
+
+ /// \brief Determines whether this template is an actual instantiation
+ /// that should be counted toward the maximum instantiation depth.
+ bool isInstantiationRecord() const;
+
+ friend bool operator==(const ActiveTemplateInstantiation &X,
+ const ActiveTemplateInstantiation &Y) {
+ if (X.Kind != Y.Kind)
+ return false;
+
+ if (X.Entity != Y.Entity)
+ return false;
+
+ switch (X.Kind) {
+ case TemplateInstantiation:
+ return true;
+
+ case PriorTemplateArgumentSubstitution:
+ case DefaultTemplateArgumentChecking:
+ if (X.Template != Y.Template)
+ return false;
+
+ // Fall through
+
+ case DefaultTemplateArgumentInstantiation:
+ case ExplicitTemplateArgumentSubstitution:
+ case DeducedTemplateArgumentSubstitution:
+ case DefaultFunctionArgumentInstantiation:
+ return X.TemplateArgs == Y.TemplateArgs;
+
+ }
+
+ return true;
+ }
+
+ friend bool operator!=(const ActiveTemplateInstantiation &X,
+ const ActiveTemplateInstantiation &Y) {
+ return !(X == Y);
+ }
+ };
+
+ /// \brief List of active template instantiations.
+ ///
+ /// This vector is treated as a stack. As one template instantiation
+ /// requires another template instantiation, additional
+ /// instantiations are pushed onto the stack up to a
+ /// user-configurable limit LangOptions::InstantiationDepth.
+ llvm::SmallVector<ActiveTemplateInstantiation, 16>
+ ActiveTemplateInstantiations;
+
+ /// \brief The number of ActiveTemplateInstantiation entries in
+ /// \c ActiveTemplateInstantiations that are not actual instantiations and,
+ /// therefore, should not be counted as part of the instantiation depth.
+ unsigned NonInstantiationEntries;
+
+ /// \brief The last template from which a template instantiation
+ /// error or warning was produced.
+ ///
+ /// This value is used to suppress printing of redundant template
+ /// instantiation backtraces when there are multiple errors in the
+ /// same instantiation. FIXME: Does this belong in Sema? It's tough
+ /// to implement it anywhere else.
+ ActiveTemplateInstantiation LastTemplateInstantiationErrorContext;
+
+ /// \brief The stack of calls expression undergoing template instantiation.
+ ///
+ /// The top of this stack is used by a fixit instantiating unresolved
+ /// function calls to fix the AST to match the textual change it prints.
+ llvm::SmallVector<CallExpr *, 8> CallsUndergoingInstantiation;
+
+ /// \brief A stack object to be created when performing template
+ /// instantiation.
+ ///
+ /// Construction of an object of type \c InstantiatingTemplate
+ /// pushes the current instantiation onto the stack of active
+ /// instantiations. If the size of this stack exceeds the maximum
+ /// number of recursive template instantiations, construction
+ /// produces an error and evaluates true.
+ ///
+ /// Destruction of this object will pop the named instantiation off
+ /// the stack.
+ struct InstantiatingTemplate {
+ /// \brief Note that we are instantiating a class template,
+ /// function template, or a member thereof.
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ Decl *Entity,
+ SourceRange InstantiationRange = SourceRange());
+
+ /// \brief Note that we are instantiating a default argument in a
+ /// template-id.
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ TemplateDecl *Template,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceRange InstantiationRange = SourceRange());
+
+ /// \brief Note that we are instantiating a default argument in a
+ /// template-id.
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ FunctionTemplateDecl *FunctionTemplate,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ ActiveTemplateInstantiation::InstantiationKind Kind,
+ SourceRange InstantiationRange = SourceRange());
+
+ /// \brief Note that we are instantiating as part of template
+ /// argument deduction for a class template partial
+ /// specialization.
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ ClassTemplatePartialSpecializationDecl *PartialSpec,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceRange InstantiationRange = SourceRange());
+
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ ParmVarDecl *Param,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceRange InstantiationRange = SourceRange());
+
+ /// \brief Note that we are substituting prior template arguments into a
+ /// non-type or template template parameter.
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ TemplateDecl *Template,
+ NonTypeTemplateParmDecl *Param,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceRange InstantiationRange);
+
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ TemplateDecl *Template,
+ TemplateTemplateParmDecl *Param,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceRange InstantiationRange);
+
+ /// \brief Note that we are checking the default template argument
+ /// against the template parameter for a given template-id.
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ TemplateDecl *Template,
+ NamedDecl *Param,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceRange InstantiationRange);
+
+
+ /// \brief Note that we have finished instantiating this template.
+ void Clear();
+
+ ~InstantiatingTemplate() { Clear(); }
+
+ /// \brief Determines whether we have exceeded the maximum
+ /// recursive template instantiations.
+ operator bool() const { return Invalid; }
+
+ private:
+ Sema &SemaRef;
+ bool Invalid;
+
+ bool CheckInstantiationDepth(SourceLocation PointOfInstantiation,
+ SourceRange InstantiationRange);
+
+ InstantiatingTemplate(const InstantiatingTemplate&); // not implemented
+
+ InstantiatingTemplate&
+ operator=(const InstantiatingTemplate&); // not implemented
+ };
+
+ void PrintInstantiationStack();
+
+ /// \brief Determines whether we are currently in a context where
+ /// template argument substitution failures are not considered
+ /// errors.
+ ///
+ /// When this routine returns true, the emission of most diagnostics
+ /// will be suppressed and there will be no local error recovery.
+ bool isSFINAEContext() const;
+
+ /// \brief RAII class used to determine whether SFINAE has
+ /// trapped any errors that occur during template argument
+ /// deduction.
+ class SFINAETrap {
+ Sema &SemaRef;
+ unsigned PrevSFINAEErrors;
+ public:
+ explicit SFINAETrap(Sema &SemaRef)
+ : SemaRef(SemaRef), PrevSFINAEErrors(SemaRef.NumSFINAEErrors) { }
+
+ ~SFINAETrap() { SemaRef.NumSFINAEErrors = PrevSFINAEErrors; }
+
+ /// \brief Determine whether any SFINAE errors have been trapped.
+ bool hasErrorOccurred() const {
+ return SemaRef.NumSFINAEErrors > PrevSFINAEErrors;
+ }
+ };
+
+ /// \brief RAII class that determines when any errors have occurred
+ /// between the time the instance was created and the time it was
+ /// queried.
+ class ErrorTrap {
+ Sema &SemaRef;
+ unsigned PrevErrors;
+
+ public:
+ explicit ErrorTrap(Sema &SemaRef)
+ : SemaRef(SemaRef), PrevErrors(SemaRef.getDiagnostics().getNumErrors()) {}
+
+ /// \brief Determine whether any errors have occurred since this
+ /// object instance was created.
+ bool hasErrorOccurred() const {
+ return SemaRef.getDiagnostics().getNumErrors() > PrevErrors;
+ }
+ };
+
+ /// \brief The current instantiation scope used to store local
+ /// variables.
+ LocalInstantiationScope *CurrentInstantiationScope;
+
+ /// \brief The number of typos corrected by CorrectTypo.
+ unsigned TyposCorrected;
+
+ /// \brief Worker object for performing CFG-based warnings.
+ sema::AnalysisBasedWarnings AnalysisWarnings;
+
+ /// \brief An entity for which implicit template instantiation is required.
+ ///
+ /// The source location associated with the declaration is the first place in
+ /// the source code where the declaration was "used". It is not necessarily
+ /// the point of instantiation (which will be either before or after the
+ /// namespace-scope declaration that triggered this implicit instantiation),
+ /// However, it is the location that diagnostics should generally refer to,
+ /// because users will need to know what code triggered the instantiation.
+ typedef std::pair<ValueDecl *, SourceLocation> PendingImplicitInstantiation;
+
+ /// \brief The queue of implicit template instantiations that are required
+ /// but have not yet been performed.
+ std::deque<PendingImplicitInstantiation> PendingInstantiations;
+
+ /// \brief The queue of implicit template instantiations that are required
+ /// and must be performed within the current local scope.
+ ///
+ /// This queue is only used for member functions of local classes in
+ /// templates, which must be instantiated in the same scope as their
+ /// enclosing function, so that they can reference function-local
+ /// types, static variables, enumerators, etc.
+ std::deque<PendingImplicitInstantiation> PendingLocalImplicitInstantiations;
+
+ void PerformPendingInstantiations(bool LocalOnly = false);
+
+ TypeSourceInfo *SubstType(TypeSourceInfo *T,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ SourceLocation Loc, DeclarationName Entity);
+
+ QualType SubstType(QualType T,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ SourceLocation Loc, DeclarationName Entity);
+
+ TypeSourceInfo *SubstFunctionDeclType(TypeSourceInfo *T,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ SourceLocation Loc,
+ DeclarationName Entity);
+ ParmVarDecl *SubstParmVarDecl(ParmVarDecl *D,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+ ExprResult SubstExpr(Expr *E,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+
+ StmtResult SubstStmt(Stmt *S,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+
+ Decl *SubstDecl(Decl *D, DeclContext *Owner,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+
+ bool
+ SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
+ CXXRecordDecl *Pattern,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+
+ bool
+ InstantiateClass(SourceLocation PointOfInstantiation,
+ CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ TemplateSpecializationKind TSK,
+ bool Complain = true);
+
+ void InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
+ Decl *Pattern, Decl *Inst);
+
+ bool
+ InstantiateClassTemplateSpecialization(SourceLocation PointOfInstantiation,
+ ClassTemplateSpecializationDecl *ClassTemplateSpec,
+ TemplateSpecializationKind TSK,
+ bool Complain = true);
+
+ void InstantiateClassMembers(SourceLocation PointOfInstantiation,
+ CXXRecordDecl *Instantiation,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ TemplateSpecializationKind TSK);
+
+ void InstantiateClassTemplateSpecializationMembers(
+ SourceLocation PointOfInstantiation,
+ ClassTemplateSpecializationDecl *ClassTemplateSpec,
+ TemplateSpecializationKind TSK);
+
+ NestedNameSpecifier *
+ SubstNestedNameSpecifier(NestedNameSpecifier *NNS,
+ SourceRange Range,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+ DeclarationNameInfo
+ SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+ TemplateName
+ SubstTemplateName(TemplateName Name, SourceLocation Loc,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+ bool Subst(const TemplateArgumentLoc &Arg, TemplateArgumentLoc &Result,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+
+ void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
+ FunctionDecl *Function,
+ bool Recursive = false,
+ bool DefinitionRequired = false);
+ void InstantiateStaticDataMemberDefinition(
+ SourceLocation PointOfInstantiation,
+ VarDecl *Var,
+ bool Recursive = false,
+ bool DefinitionRequired = false);
+
+ void InstantiateMemInitializers(CXXConstructorDecl *New,
+ const CXXConstructorDecl *Tmpl,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+
+ NamedDecl *FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+ DeclContext *FindInstantiatedContext(SourceLocation Loc, DeclContext *DC,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+
+ // Objective-C declarations.
+ Decl *ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
+ IdentifierInfo *ClassName,
+ SourceLocation ClassLoc,
+ IdentifierInfo *SuperName,
+ SourceLocation SuperLoc,
+ Decl * const *ProtoRefs,
+ unsigned NumProtoRefs,
+ const SourceLocation *ProtoLocs,
+ SourceLocation EndProtoLoc,
+ AttributeList *AttrList);
+
+ Decl *ActOnCompatiblityAlias(
+ SourceLocation AtCompatibilityAliasLoc,
+ IdentifierInfo *AliasName, SourceLocation AliasLocation,
+ IdentifierInfo *ClassName, SourceLocation ClassLocation);
+
+ void CheckForwardProtocolDeclarationForCircularDependency(
+ IdentifierInfo *PName,
+ SourceLocation &PLoc, SourceLocation PrevLoc,
+ const ObjCList<ObjCProtocolDecl> &PList);
+
+ Decl *ActOnStartProtocolInterface(
+ SourceLocation AtProtoInterfaceLoc,
+ IdentifierInfo *ProtocolName, SourceLocation ProtocolLoc,
+ Decl * const *ProtoRefNames, unsigned NumProtoRefs,
+ const SourceLocation *ProtoLocs,
+ SourceLocation EndProtoLoc,
+ AttributeList *AttrList);
+
+ Decl *ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
+ IdentifierInfo *ClassName,
+ SourceLocation ClassLoc,
+ IdentifierInfo *CategoryName,
+ SourceLocation CategoryLoc,
+ Decl * const *ProtoRefs,
+ unsigned NumProtoRefs,
+ const SourceLocation *ProtoLocs,
+ SourceLocation EndProtoLoc);
+
+ Decl *ActOnStartClassImplementation(
+ SourceLocation AtClassImplLoc,
+ IdentifierInfo *ClassName, SourceLocation ClassLoc,
+ IdentifierInfo *SuperClassname,
+ SourceLocation SuperClassLoc);
+
+ Decl *ActOnStartCategoryImplementation(SourceLocation AtCatImplLoc,
+ IdentifierInfo *ClassName,
+ SourceLocation ClassLoc,
+ IdentifierInfo *CatName,
+ SourceLocation CatLoc);
+
+ Decl *ActOnForwardClassDeclaration(SourceLocation Loc,
+ IdentifierInfo **IdentList,
+ SourceLocation *IdentLocs,
+ unsigned NumElts);
+
+ Decl *ActOnForwardProtocolDeclaration(SourceLocation AtProtoclLoc,
+ const IdentifierLocPair *IdentList,
+ unsigned NumElts,
+ AttributeList *attrList);
+
+ void FindProtocolDeclaration(bool WarnOnDeclarations,
+ const IdentifierLocPair *ProtocolId,
+ unsigned NumProtocols,
+ llvm::SmallVectorImpl<Decl *> &Protocols);
+
+ /// Ensure attributes are consistent with type.
+ /// \param [in, out] Attributes The attributes to check; they will
+ /// be modified to be consistent with \arg PropertyTy.
+ void CheckObjCPropertyAttributes(Decl *PropertyPtrTy,
+ SourceLocation Loc,
+ unsigned &Attributes);
+ void ProcessPropertyDecl(ObjCPropertyDecl *property, ObjCContainerDecl *DC);
+ void DiagnosePropertyMismatch(ObjCPropertyDecl *Property,
+ ObjCPropertyDecl *SuperProperty,
+ const IdentifierInfo *Name);
+ void ComparePropertiesInBaseAndSuper(ObjCInterfaceDecl *IDecl);
+
+ void CompareMethodParamsInBaseAndSuper(Decl *IDecl,
+ ObjCMethodDecl *MethodDecl,
+ bool IsInstance);
+
+ void CompareProperties(Decl *CDecl, Decl *MergeProtocols);
+
+ void DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT,
+ ObjCInterfaceDecl *ID);
+
+ void MatchOneProtocolPropertiesInClass(Decl *CDecl,
+ ObjCProtocolDecl *PDecl);
+
+ void ActOnAtEnd(Scope *S, SourceRange AtEnd, Decl *classDecl,
+ Decl **allMethods = 0, unsigned allNum = 0,
+ Decl **allProperties = 0, unsigned pNum = 0,
+ DeclGroupPtrTy *allTUVars = 0, unsigned tuvNum = 0);
+
+ Decl *ActOnProperty(Scope *S, SourceLocation AtLoc,
+ FieldDeclarator &FD, ObjCDeclSpec &ODS,
+ Selector GetterSel, Selector SetterSel,
+ Decl *ClassCategory,
+ bool *OverridingProperty,
+ tok::ObjCKeywordKind MethodImplKind);
+
+ Decl *ActOnPropertyImplDecl(Scope *S,
+ SourceLocation AtLoc,
+ SourceLocation PropertyLoc,
+ bool ImplKind,Decl *ClassImplDecl,
+ IdentifierInfo *PropertyId,
+ IdentifierInfo *PropertyIvar);
+
+ struct ObjCArgInfo {
+ IdentifierInfo *Name;
+ SourceLocation NameLoc;
+ // The Type is null if no type was specified, and the DeclSpec is invalid
+ // in this case.
+ ParsedType Type;
+ ObjCDeclSpec DeclSpec;
+
+ /// ArgAttrs - Attribute list for this argument.
+ AttributeList *ArgAttrs;
+ };
+
+ Decl *ActOnMethodDeclaration(
+ SourceLocation BeginLoc, // location of the + or -.
+ SourceLocation EndLoc, // location of the ; or {.
+ tok::TokenKind MethodType,
+ Decl *ClassDecl, ObjCDeclSpec &ReturnQT, ParsedType ReturnType,
+ Selector Sel,
+ // optional arguments. The number of types/arguments is obtained
+ // from the Sel.getNumArgs().
+ ObjCArgInfo *ArgInfo,
+ DeclaratorChunk::ParamInfo *CParamInfo, unsigned CNumArgs, // c-style args
+ AttributeList *AttrList, tok::ObjCKeywordKind MethodImplKind,
+ bool isVariadic = false);
+
+ // Helper method for ActOnClassMethod/ActOnInstanceMethod.
+ // Will search "local" class/category implementations for a method decl.
+ // Will also search in class's root looking for instance method.
+ // Returns 0 if no method is found.
+ ObjCMethodDecl *LookupPrivateClassMethod(Selector Sel,
+ ObjCInterfaceDecl *CDecl);
+ ObjCMethodDecl *LookupPrivateInstanceMethod(Selector Sel,
+ ObjCInterfaceDecl *ClassDecl);
+
+ ExprResult
+ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
+ Expr *BaseExpr,
+ DeclarationName MemberName,
+ SourceLocation MemberLoc);
+
+ ExprResult
+ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
+ IdentifierInfo &propertyName,
+ SourceLocation receiverNameLoc,
+ SourceLocation propertyNameLoc);
+
+ /// \brief Describes the kind of message expression indicated by a message
+ /// send that starts with an identifier.
+ enum ObjCMessageKind {
+ /// \brief The message is sent to 'super'.
+ ObjCSuperMessage,
+ /// \brief The message is an instance message.
+ ObjCInstanceMessage,
+ /// \brief The message is a class message, and the identifier is a type
+ /// name.
+ ObjCClassMessage
+ };
+
+ ObjCMessageKind getObjCMessageKind(Scope *S,
+ IdentifierInfo *Name,
+ SourceLocation NameLoc,
+ bool IsSuper,
+ bool HasTrailingDot,
+ ParsedType &ReceiverType);
+
+ ExprResult ActOnSuperMessage(Scope *S, SourceLocation SuperLoc,
+ Selector Sel,
+ SourceLocation LBracLoc,
+ SourceLocation SelectorLoc,
+ SourceLocation RBracLoc,
+ MultiExprArg Args);
+
+ ExprResult BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
+ QualType ReceiverType,
+ SourceLocation SuperLoc,
+ Selector Sel,
+ ObjCMethodDecl *Method,
+ SourceLocation LBracLoc,
+ SourceLocation RBracLoc,
+ MultiExprArg Args);
+
+ ExprResult ActOnClassMessage(Scope *S,
+ ParsedType Receiver,
+ Selector Sel,
+ SourceLocation LBracLoc,
+ SourceLocation SelectorLoc,
+ SourceLocation RBracLoc,
+ MultiExprArg Args);
+
+ ExprResult BuildInstanceMessage(Expr *Receiver,
+ QualType ReceiverType,
+ SourceLocation SuperLoc,
+ Selector Sel,
+ ObjCMethodDecl *Method,
+ SourceLocation LBracLoc,
+ SourceLocation RBracLoc,
+ MultiExprArg Args);
+
+ ExprResult ActOnInstanceMessage(Scope *S,
+ Expr *Receiver,
+ Selector Sel,
+ SourceLocation LBracLoc,
+ SourceLocation SelectorLoc,
+ SourceLocation RBracLoc,
+ MultiExprArg Args);
+
+
+ enum PragmaOptionsAlignKind {
+ POAK_Native, // #pragma options align=native
+ POAK_Natural, // #pragma options align=natural
+ POAK_Packed, // #pragma options align=packed
+ POAK_Power, // #pragma options align=power
+ POAK_Mac68k, // #pragma options align=mac68k
+ POAK_Reset // #pragma options align=reset
+ };
+
+ /// ActOnPragmaOptionsAlign - Called on well formed #pragma options align.
+ void ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
+ SourceLocation PragmaLoc,
+ SourceLocation KindLoc);
+
+ enum PragmaPackKind {
+ PPK_Default, // #pragma pack([n])
+ PPK_Show, // #pragma pack(show), only supported by MSVC.
+ PPK_Push, // #pragma pack(push, [identifier], [n])
+ PPK_Pop // #pragma pack(pop, [identifier], [n])
+ };
+
+ /// ActOnPragmaPack - Called on well formed #pragma pack(...).
+ void ActOnPragmaPack(PragmaPackKind Kind,
+ IdentifierInfo *Name,
+ Expr *Alignment,
+ SourceLocation PragmaLoc,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc);
+
+ /// ActOnPragmaUnused - Called on well-formed '#pragma unused'.
+ void ActOnPragmaUnused(const Token *Identifiers,
+ unsigned NumIdentifiers, Scope *curScope,
+ SourceLocation PragmaLoc,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc);
+
+ /// ActOnPragmaVisibility - Called on well formed #pragma GCC visibility... .
+ void ActOnPragmaVisibility(bool IsPush, const IdentifierInfo* VisType,
+ SourceLocation PragmaLoc);
+
+ NamedDecl *DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II);
+ void DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W);
+
+ /// ActOnPragmaWeakID - Called on well formed #pragma weak ident.
+ void ActOnPragmaWeakID(IdentifierInfo* WeakName,
+ SourceLocation PragmaLoc,
+ SourceLocation WeakNameLoc);
+
+ /// ActOnPragmaWeakAlias - Called on well formed #pragma weak ident = ident.
+ void ActOnPragmaWeakAlias(IdentifierInfo* WeakName,
+ IdentifierInfo* AliasName,
+ SourceLocation PragmaLoc,
+ SourceLocation WeakNameLoc,
+ SourceLocation AliasNameLoc);
+
+ /// AddAlignmentAttributesForRecord - Adds any needed alignment attributes to
+ /// a the record decl, to handle '#pragma pack' and '#pragma options align'.
+ void AddAlignmentAttributesForRecord(RecordDecl *RD);
+
+ /// FreePackedContext - Deallocate and null out PackContext.
+ void FreePackedContext();
+
+ /// PushVisibilityAttr - Note that we've entered a context with a
+ /// visibility attribute.
+ void PushVisibilityAttr(const VisibilityAttr *Attr);
+
+ /// AddPushedVisibilityAttribute - If '#pragma GCC visibility' was used,
+ /// add an appropriate visibility attribute.
+ void AddPushedVisibilityAttribute(Decl *RD);
+
+ /// PopPragmaVisibility - Pop the top element of the visibility stack; used
+ /// for '#pragma GCC visibility' and visibility attributes on namespaces.
+ void PopPragmaVisibility();
+
+ /// FreeVisContext - Deallocate and null out VisContext.
+ void FreeVisContext();
+
+ /// AddAlignedAttr - Adds an aligned attribute to a particular declaration.
+ void AddAlignedAttr(SourceLocation AttrLoc, Decl *D, Expr *E);
+ void AddAlignedAttr(SourceLocation AttrLoc, Decl *D, TypeSourceInfo *T);
+
+ /// CastCategory - Get the correct forwarded implicit cast result category
+ /// from the inner expression.
+ ExprValueKind CastCategory(Expr *E);
+
+ /// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit
+ /// cast. If there is already an implicit cast, merge into the existing one.
+ /// If isLvalue, the result of the cast is an lvalue.
+ void ImpCastExprToType(Expr *&Expr, QualType Type, CastKind CK,
+ ExprValueKind VK = VK_RValue,
+ const CXXCastPath *BasePath = 0);
+
+ // UsualUnaryConversions - promotes integers (C99 6.3.1.1p2) and converts
+ // functions and arrays to their respective pointers (C99 6.3.2.1).
+ Expr *UsualUnaryConversions(Expr *&expr);
+
+ // DefaultFunctionArrayConversion - converts functions and arrays
+ // to their respective pointers (C99 6.3.2.1).
+ void DefaultFunctionArrayConversion(Expr *&expr);
+
+ // DefaultFunctionArrayLvalueConversion - converts functions and
+ // arrays to their respective pointers and performs the
+ // lvalue-to-rvalue conversion.
+ void DefaultFunctionArrayLvalueConversion(Expr *&expr);
+
+ // DefaultArgumentPromotion (C99 6.5.2.2p6). Used for function calls that
+ // do not have a prototype. Integer promotions are performed on each
+ // argument, and arguments that have type float are promoted to double.
+ void DefaultArgumentPromotion(Expr *&Expr);
+
+ // Used for emitting the right warning by DefaultVariadicArgumentPromotion
+ enum VariadicCallType {
+ VariadicFunction,
+ VariadicBlock,
+ VariadicMethod,
+ VariadicConstructor,
+ VariadicDoesNotApply
+ };
+
+ /// GatherArgumentsForCall - Collector argument expressions for various
+ /// form of call prototypes.
+ bool GatherArgumentsForCall(SourceLocation CallLoc,
+ FunctionDecl *FDecl,
+ const FunctionProtoType *Proto,
+ unsigned FirstProtoArg,
+ Expr **Args, unsigned NumArgs,
+ llvm::SmallVector<Expr *, 8> &AllArgs,
+ VariadicCallType CallType = VariadicDoesNotApply);
+
+ // DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but
+ // will warn if the resulting type is not a POD type.
+ bool DefaultVariadicArgumentPromotion(Expr *&Expr, VariadicCallType CT,
+ FunctionDecl *FDecl);
+
+ // UsualArithmeticConversions - performs the UsualUnaryConversions on it's
+ // operands and then handles various conversions that are common to binary
+ // operators (C99 6.3.1.8). If both operands aren't arithmetic, this
+ // routine returns the first non-arithmetic type found. The client is
+ // responsible for emitting appropriate error diagnostics.
+ QualType UsualArithmeticConversions(Expr *&lExpr, Expr *&rExpr,
+ bool isCompAssign = false);
+
+ /// AssignConvertType - All of the 'assignment' semantic checks return this
+ /// enum to indicate whether the assignment was allowed. These checks are
+ /// done for simple assignments, as well as initialization, return from
+ /// function, argument passing, etc. The query is phrased in terms of a
+ /// source and destination type.
+ enum AssignConvertType {
+ /// Compatible - the types are compatible according to the standard.
+ Compatible,
+
+ /// PointerToInt - The assignment converts a pointer to an int, which we
+ /// accept as an extension.
+ PointerToInt,
+
+ /// IntToPointer - The assignment converts an int to a pointer, which we
+ /// accept as an extension.
+ IntToPointer,
+
+ /// FunctionVoidPointer - The assignment is between a function pointer and
+ /// void*, which the standard doesn't allow, but we accept as an extension.
+ FunctionVoidPointer,
+
+ /// IncompatiblePointer - The assignment is between two pointers types that
+ /// are not compatible, but we accept them as an extension.
+ IncompatiblePointer,
+
+ /// IncompatiblePointer - The assignment is between two pointers types which
+ /// point to integers which have a different sign, but are otherwise identical.
+ /// This is a subset of the above, but broken out because it's by far the most
+ /// common case of incompatible pointers.
+ IncompatiblePointerSign,
+
+ /// CompatiblePointerDiscardsQualifiers - The assignment discards
+ /// c/v/r qualifiers, which we accept as an extension.
+ CompatiblePointerDiscardsQualifiers,
+
+ /// IncompatibleNestedPointerQualifiers - The assignment is between two
+ /// nested pointer types, and the qualifiers other than the first two
+ /// levels differ e.g. char ** -> const char **, but we accept them as an
+ /// extension.
+ IncompatibleNestedPointerQualifiers,
+
+ /// IncompatibleVectors - The assignment is between two vector types that
+ /// have the same size, which we accept as an extension.
+ IncompatibleVectors,
+
+ /// IntToBlockPointer - The assignment converts an int to a block
+ /// pointer. We disallow this.
+ IntToBlockPointer,
+
+ /// IncompatibleBlockPointer - The assignment is between two block
+ /// pointers types that are not compatible.
+ IncompatibleBlockPointer,
+
+ /// IncompatibleObjCQualifiedId - The assignment is between a qualified
+ /// id type and something else (that is incompatible with it). For example,
+ /// "id <XXX>" = "Foo *", where "Foo *" doesn't implement the XXX protocol.
+ IncompatibleObjCQualifiedId,
+
+ /// Incompatible - We reject this conversion outright, it is invalid to
+ /// represent it in the AST.
+ Incompatible
+ };
+
+ /// DiagnoseAssignmentResult - Emit a diagnostic, if required, for the
+ /// assignment conversion type specified by ConvTy. This returns true if the
+ /// conversion was invalid or false if the conversion was accepted.
+ bool DiagnoseAssignmentResult(AssignConvertType ConvTy,
+ SourceLocation Loc,
+ QualType DstType, QualType SrcType,
+ Expr *SrcExpr, AssignmentAction Action,
+ bool *Complained = 0);
+
+ /// CheckAssignmentConstraints - Perform type checking for assignment,
+ /// argument passing, variable initialization, and function return values.
+ /// This routine is only used by the following two methods. C99 6.5.16.
+ AssignConvertType CheckAssignmentConstraints(QualType lhs, QualType rhs);
+
+ // CheckSingleAssignmentConstraints - Currently used by
+ // CheckAssignmentOperands, and ActOnReturnStmt. Prior to type checking,
+ // this routine performs the default function/array converions.
+ AssignConvertType CheckSingleAssignmentConstraints(QualType lhs,
+ Expr *&rExpr);
+
+ // \brief If the lhs type is a transparent union, check whether we
+ // can initialize the transparent union with the given expression.
+ AssignConvertType CheckTransparentUnionArgumentConstraints(QualType lhs,
+ Expr *&rExpr);
+
+ // Helper function for CheckAssignmentConstraints (C99 6.5.16.1p1)
+ AssignConvertType CheckPointerTypesForAssignment(QualType lhsType,
+ QualType rhsType);
+
+ AssignConvertType CheckObjCPointerTypesForAssignment(QualType lhsType,
+ QualType rhsType);
+
+ // Helper function for CheckAssignmentConstraints involving two
+ // block pointer types.
+ AssignConvertType CheckBlockPointerTypesForAssignment(QualType lhsType,
+ QualType rhsType);
+
+ bool IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType);
+
+ bool CheckExceptionSpecCompatibility(Expr *From, QualType ToType);
+
+ bool PerformImplicitConversion(Expr *&From, QualType ToType,
+ AssignmentAction Action,
+ bool AllowExplicit = false);
+ bool PerformImplicitConversion(Expr *&From, QualType ToType,
+ AssignmentAction Action,
+ bool AllowExplicit,
+ ImplicitConversionSequence& ICS);
+ bool PerformImplicitConversion(Expr *&From, QualType ToType,
+ const ImplicitConversionSequence& ICS,
+ AssignmentAction Action,
+ bool IgnoreBaseAccess = false);
+ bool PerformImplicitConversion(Expr *&From, QualType ToType,
+ const StandardConversionSequence& SCS,
+ AssignmentAction Action,bool IgnoreBaseAccess);
+
+ /// the following "Check" methods will return a valid/converted QualType
+ /// or a null QualType (indicating an error diagnostic was issued).
+
+ /// type checking binary operators (subroutines of CreateBuiltinBinOp).
+ QualType InvalidOperands(SourceLocation l, Expr *&lex, Expr *&rex);
+ QualType CheckPointerToMemberOperands( // C++ 5.5
+ Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isIndirect);
+ QualType CheckMultiplyDivideOperands( // C99 6.5.5
+ Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign,
+ bool isDivide);
+ QualType CheckRemainderOperands( // C99 6.5.5
+ Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false);
+ QualType CheckAdditionOperands( // C99 6.5.6
+ Expr *&lex, Expr *&rex, SourceLocation OpLoc, QualType* CompLHSTy = 0);
+ QualType CheckSubtractionOperands( // C99 6.5.6
+ Expr *&lex, Expr *&rex, SourceLocation OpLoc, QualType* CompLHSTy = 0);
+ QualType CheckShiftOperands( // C99 6.5.7
+ Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false);
+ QualType CheckCompareOperands( // C99 6.5.8/9
+ Expr *&lex, Expr *&rex, SourceLocation OpLoc, unsigned Opc,
+ bool isRelational);
+ QualType CheckBitwiseOperands( // C99 6.5.[10...12]
+ Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false);
+ QualType CheckLogicalOperands( // C99 6.5.[13,14]
+ Expr *&lex, Expr *&rex, SourceLocation OpLoc, unsigned Opc);
+ // CheckAssignmentOperands is used for both simple and compound assignment.
+ // For simple assignment, pass both expressions and a null converted type.
+ // For compound assignment, pass both expressions and the converted type.
+ QualType CheckAssignmentOperands( // C99 6.5.16.[1,2]
+ Expr *lex, Expr *&rex, SourceLocation OpLoc, QualType convertedType);
+ QualType CheckCommaOperands( // C99 6.5.17
+ Expr *lex, Expr *&rex, SourceLocation OpLoc);
+ QualType CheckConditionalOperands( // C99 6.5.15
+ Expr *&cond, Expr *&lhs, Expr *&rhs, SourceLocation questionLoc);
+ QualType CXXCheckConditionalOperands( // C++ 5.16
+ Expr *&cond, Expr *&lhs, Expr *&rhs, SourceLocation questionLoc);
+ QualType FindCompositePointerType(SourceLocation Loc, Expr *&E1, Expr *&E2,
+ bool *NonStandardCompositeType = 0);
+
+ QualType FindCompositeObjCPointerType(Expr *&LHS, Expr *&RHS,
+ SourceLocation questionLoc);
+
+ /// type checking for vector binary operators.
+ QualType CheckVectorOperands(SourceLocation l, Expr *&lex, Expr *&rex);
+ QualType CheckVectorCompareOperands(Expr *&lex, Expr *&rx,
+ SourceLocation l, bool isRel);
+
+ /// type checking unary operators (subroutines of ActOnUnaryOp).
+ /// C99 6.5.3.1, 6.5.3.2, 6.5.3.4
+ QualType CheckIncrementDecrementOperand(Expr *op, SourceLocation OpLoc,
+ bool isInc, bool isPrefix);
+ QualType CheckAddressOfOperand(Expr *op, SourceLocation OpLoc);
+ QualType CheckIndirectionOperand(Expr *op, SourceLocation OpLoc);
+ QualType CheckRealImagOperand(Expr *&Op, SourceLocation OpLoc, bool isReal);
+
+ /// type checking primary expressions.
+ QualType CheckExtVectorComponent(QualType baseType, SourceLocation OpLoc,
+ const IdentifierInfo *Comp,
+ SourceLocation CmpLoc);
+
+ /// type checking declaration initializers (C99 6.7.8)
+ bool CheckInitList(const InitializedEntity &Entity,
+ InitListExpr *&InitList, QualType &DeclType);
+ bool CheckForConstantInitializer(Expr *e, QualType t);
+
+ // type checking C++ declaration initializers (C++ [dcl.init]).
+
+ /// ReferenceCompareResult - Expresses the result of comparing two
+ /// types (cv1 T1 and cv2 T2) to determine their compatibility for the
+ /// purposes of initialization by reference (C++ [dcl.init.ref]p4).
+ enum ReferenceCompareResult {
+ /// Ref_Incompatible - The two types are incompatible, so direct
+ /// reference binding is not possible.
+ Ref_Incompatible = 0,
+ /// Ref_Related - The two types are reference-related, which means
+ /// that their unqualified forms (T1 and T2) are either the same
+ /// or T1 is a base class of T2.
+ Ref_Related,
+ /// Ref_Compatible_With_Added_Qualification - The two types are
+ /// reference-compatible with added qualification, meaning that
+ /// they are reference-compatible and the qualifiers on T1 (cv1)
+ /// are greater than the qualifiers on T2 (cv2).
+ Ref_Compatible_With_Added_Qualification,
+ /// Ref_Compatible - The two types are reference-compatible and
+ /// have equivalent qualifiers (cv1 == cv2).
+ Ref_Compatible
+ };
+
+ ReferenceCompareResult CompareReferenceRelationship(SourceLocation Loc,
+ QualType T1, QualType T2,
+ bool &DerivedToBase,
+ bool &ObjCConversion);
+
+ /// CheckCastTypes - Check type constraints for casting between types under
+ /// C semantics, or forward to CXXCheckCStyleCast in C++.
+ bool CheckCastTypes(SourceRange TyRange, QualType CastTy, Expr *&CastExpr,
+ CastKind &Kind, CXXCastPath &BasePath,
+ bool FunctionalStyle = false);
+
+ // CheckVectorCast - check type constraints for vectors.
+ // Since vectors are an extension, there are no C standard reference for this.
+ // We allow casting between vectors and integer datatypes of the same size.
+ // returns true if the cast is invalid
+ bool CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty,
+ CastKind &Kind);
+
+ // CheckExtVectorCast - check type constraints for extended vectors.
+ // Since vectors are an extension, there are no C standard reference for this.
+ // We allow casting between vectors and integer datatypes of the same size,
+ // or vectors and the element type of that vector.
+ // returns true if the cast is invalid
+ bool CheckExtVectorCast(SourceRange R, QualType VectorTy, Expr *&CastExpr,
+ CastKind &Kind);
+
+ /// CXXCheckCStyleCast - Check constraints of a C-style or function-style
+ /// cast under C++ semantics.
+ bool CXXCheckCStyleCast(SourceRange R, QualType CastTy, Expr *&CastExpr,
+ CastKind &Kind, CXXCastPath &BasePath,
+ bool FunctionalStyle);
+
+ /// CheckMessageArgumentTypes - Check types in an Obj-C message send.
+ /// \param Method - May be null.
+ /// \param [out] ReturnType - The return type of the send.
+ /// \return true iff there were any incompatible types.
+ bool CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, Selector Sel,
+ ObjCMethodDecl *Method, bool isClassMessage,
+ SourceLocation lbrac, SourceLocation rbrac,
+ QualType &ReturnType);
+
+ /// CheckBooleanCondition - Diagnose problems involving the use of
+ /// the given expression as a boolean condition (e.g. in an if
+ /// statement). Also performs the standard function and array
+ /// decays, possibly changing the input variable.
+ ///
+ /// \param Loc - A location associated with the condition, e.g. the
+ /// 'if' keyword.
+ /// \return true iff there were any errors
+ bool CheckBooleanCondition(Expr *&CondExpr, SourceLocation Loc);
+
+ ExprResult ActOnBooleanCondition(Scope *S, SourceLocation Loc,
+ Expr *SubExpr);
+
+ /// DiagnoseAssignmentAsCondition - Given that an expression is
+ /// being used as a boolean condition, warn if it's an assignment.
+ void DiagnoseAssignmentAsCondition(Expr *E);
+
+ /// CheckCXXBooleanCondition - Returns true if conversion to bool is invalid.
+ bool CheckCXXBooleanCondition(Expr *&CondExpr);
+
+ /// ConvertIntegerToTypeWarnOnOverflow - Convert the specified APInt to have
+ /// the specified width and sign. If an overflow occurs, detect it and emit
+ /// the specified diagnostic.
+ void ConvertIntegerToTypeWarnOnOverflow(llvm::APSInt &OldVal,
+ unsigned NewWidth, bool NewSign,
+ SourceLocation Loc, unsigned DiagID);
+
+ /// Checks that the Objective-C declaration is declared in the global scope.
+ /// Emits an error and marks the declaration as invalid if it's not declared
+ /// in the global scope.
+ bool CheckObjCDeclScope(Decl *D);
+
+ void InitBuiltinVaListType();
+
+ /// VerifyIntegerConstantExpression - verifies that an expression is an ICE,
+ /// and reports the appropriate diagnostics. Returns false on success.
+ /// Can optionally return the value of the expression.
+ bool VerifyIntegerConstantExpression(const Expr *E, llvm::APSInt *Result = 0);
+
+ /// VerifyBitField - verifies that a bit field expression is an ICE and has
+ /// the correct width, and that the field type is valid.
+ /// Returns false on success.
+ /// Can optionally return whether the bit-field is of width 0
+ bool VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName,
+ QualType FieldTy, const Expr *BitWidth,
+ bool *ZeroWidth = 0);
+
+ /// \name Code completion
+ //@{
+ /// \brief Describes the context in which code completion occurs.
+ enum ParserCompletionContext {
+ /// \brief Code completion occurs at top-level or namespace context.
+ PCC_Namespace,
+ /// \brief Code completion occurs within a class, struct, or union.
+ PCC_Class,
+ /// \brief Code completion occurs within an Objective-C interface, protocol,
+ /// or category.
+ PCC_ObjCInterface,
+ /// \brief Code completion occurs within an Objective-C implementation or
+ /// category implementation
+ PCC_ObjCImplementation,
+ /// \brief Code completion occurs within the list of instance variables
+ /// in an Objective-C interface, protocol, category, or implementation.
+ PCC_ObjCInstanceVariableList,
+ /// \brief Code completion occurs following one or more template
+ /// headers.
+ PCC_Template,
+ /// \brief Code completion occurs following one or more template
+ /// headers within a class.
+ PCC_MemberTemplate,
+ /// \brief Code completion occurs within an expression.
+ PCC_Expression,
+ /// \brief Code completion occurs within a statement, which may
+ /// also be an expression or a declaration.
+ PCC_Statement,
+ /// \brief Code completion occurs at the beginning of the
+ /// initialization statement (or expression) in a for loop.
+ PCC_ForInit,
+ /// \brief Code completion occurs within the condition of an if,
+ /// while, switch, or for statement.
+ PCC_Condition,
+ /// \brief Code completion occurs within the body of a function on a
+ /// recovery path, where we do not have a specific handle on our position
+ /// in the grammar.
+ PCC_RecoveryInFunction,
+ /// \brief Code completion occurs where only a type is permitted.
+ PCC_Type
+ };
+
+ void CodeCompleteOrdinaryName(Scope *S,
+ ParserCompletionContext CompletionContext);
+ void CodeCompleteDeclarator(Scope *S,
+ bool AllowNonIdentifiers,
+ bool AllowNestedNameSpecifiers);
+
+ struct CodeCompleteExpressionData;
+ void CodeCompleteExpression(Scope *S,
+ const CodeCompleteExpressionData &Data);
+ void CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
+ SourceLocation OpLoc,
+ bool IsArrow);
+ void CodeCompleteTag(Scope *S, unsigned TagSpec);
+ void CodeCompleteTypeQualifiers(DeclSpec &DS);
+ void CodeCompleteCase(Scope *S);
+ void CodeCompleteCall(Scope *S, Expr *Fn, Expr **Args, unsigned NumArgs);
+ void CodeCompleteInitializer(Scope *S, Decl *D);
+ void CodeCompleteReturn(Scope *S);
+ void CodeCompleteAssignmentRHS(Scope *S, Expr *LHS);
+
+ void CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
+ bool EnteringContext);
+ void CodeCompleteUsing(Scope *S);
+ void CodeCompleteUsingDirective(Scope *S);
+ void CodeCompleteNamespaceDecl(Scope *S);
+ void CodeCompleteNamespaceAliasDecl(Scope *S);
+ void CodeCompleteOperatorName(Scope *S);
+ void CodeCompleteConstructorInitializer(Decl *Constructor,
+ CXXBaseOrMemberInitializer** Initializers,
+ unsigned NumInitializers);
+
+ void CodeCompleteObjCAtDirective(Scope *S, Decl *ObjCImpDecl,
+ bool InInterface);
+ void CodeCompleteObjCAtVisibility(Scope *S);
+ void CodeCompleteObjCAtStatement(Scope *S);
+ void CodeCompleteObjCAtExpression(Scope *S);
+ void CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS);
+ void CodeCompleteObjCPropertyGetter(Scope *S, Decl *ClassDecl,
+ Decl **Methods,
+ unsigned NumMethods);
+ void CodeCompleteObjCPropertySetter(Scope *S, Decl *ClassDecl,
+ Decl **Methods,
+ unsigned NumMethods);
+ void CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS);
+ void CodeCompleteObjCMessageReceiver(Scope *S);
+ void CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
+ IdentifierInfo **SelIdents,
+ unsigned NumSelIdents);
+ void CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
+ IdentifierInfo **SelIdents,
+ unsigned NumSelIdents);
+ void CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
+ IdentifierInfo **SelIdents,
+ unsigned NumSelIdents,
+ bool IsSuper);
+ void CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
+ IdentifierInfo **SelIdents,
+ unsigned NumSelIdents);
+ void CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
+ IdentifierInfo **SelIdents,
+ unsigned NumSelIdents,
+ bool IsSuper);
+ void CodeCompleteObjCForCollection(Scope *S,
+ DeclGroupPtrTy IterationVar);
+ void CodeCompleteObjCSelector(Scope *S,
+ IdentifierInfo **SelIdents,
+ unsigned NumSelIdents);
+ void CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
+ unsigned NumProtocols);
+ void CodeCompleteObjCProtocolDecl(Scope *S);
+ void CodeCompleteObjCInterfaceDecl(Scope *S);
+ void CodeCompleteObjCSuperclass(Scope *S,
+ IdentifierInfo *ClassName,
+ SourceLocation ClassNameLoc);
+ void CodeCompleteObjCImplementationDecl(Scope *S);
+ void CodeCompleteObjCInterfaceCategory(Scope *S,
+ IdentifierInfo *ClassName,
+ SourceLocation ClassNameLoc);
+ void CodeCompleteObjCImplementationCategory(Scope *S,
+ IdentifierInfo *ClassName,
+ SourceLocation ClassNameLoc);
+ void CodeCompleteObjCPropertyDefinition(Scope *S, Decl *ObjCImpDecl);
+ void CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
+ IdentifierInfo *PropertyName,
+ Decl *ObjCImpDecl);
+ void CodeCompleteObjCMethodDecl(Scope *S,
+ bool IsInstanceMethod,
+ ParsedType ReturnType,
+ Decl *IDecl);
+ void CodeCompleteObjCMethodDeclSelector(Scope *S,
+ bool IsInstanceMethod,
+ bool AtParameterName,
+ ParsedType ReturnType,
+ IdentifierInfo **SelIdents,
+ unsigned NumSelIdents);
+ void CodeCompletePreprocessorDirective(bool InConditional);
+ void CodeCompleteInPreprocessorConditionalExclusion(Scope *S);
+ void CodeCompletePreprocessorMacroName(bool IsDefinition);
+ void CodeCompletePreprocessorExpression();
+ void CodeCompletePreprocessorMacroArgument(Scope *S,
+ IdentifierInfo *Macro,
+ MacroInfo *MacroInfo,
+ unsigned Argument);
+ void CodeCompleteNaturalLanguage();
+ void GatherGlobalCodeCompletions(
+ llvm::SmallVectorImpl<CodeCompletionResult> &Results);
+ //@}
+
+ void PrintStats() const {}
+
+ //===--------------------------------------------------------------------===//
+ // Extra semantic analysis beyond the C type system
+
+public:
+ SourceLocation getLocationOfStringLiteralByte(const StringLiteral *SL,
+ unsigned ByteNo) const;
+
+private:
+ bool CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall);
+ bool CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall);
+
+ bool CheckablePrintfAttr(const FormatAttr *Format, CallExpr *TheCall);
+ bool CheckObjCString(Expr *Arg);
+
+ ExprResult CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
+ bool CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
+ bool CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
+
+ bool SemaBuiltinVAStart(CallExpr *TheCall);
+ bool SemaBuiltinUnorderedCompare(CallExpr *TheCall);
+ bool SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs);
+
+public:
+ // Used by C++ template instantiation.
+ ExprResult SemaBuiltinShuffleVector(CallExpr *TheCall);
+
+private:
+ bool SemaBuiltinPrefetch(CallExpr *TheCall);
+ bool SemaBuiltinObjectSize(CallExpr *TheCall);
+ bool SemaBuiltinLongjmp(CallExpr *TheCall);
+ ExprResult SemaBuiltinAtomicOverloaded(ExprResult TheCallResult);
+ bool SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum,
+ llvm::APSInt &Result);
+
+ bool SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall,
+ bool HasVAListArg, unsigned format_idx,
+ unsigned firstDataArg, bool isPrintf);
+
+ void CheckFormatString(const StringLiteral *FExpr, const Expr *OrigFormatExpr,
+ const CallExpr *TheCall, bool HasVAListArg,
+ unsigned format_idx, unsigned firstDataArg,
+ bool isPrintf);
+
+ void CheckNonNullArguments(const NonNullAttr *NonNull,
+ const CallExpr *TheCall);
+
+ void CheckPrintfScanfArguments(const CallExpr *TheCall, bool HasVAListArg,
+ unsigned format_idx, unsigned firstDataArg,
+ bool isPrintf);
+
+ void CheckReturnStackAddr(Expr *RetValExp, QualType lhsType,
+ SourceLocation ReturnLoc);
+ void CheckFloatComparison(SourceLocation loc, Expr* lex, Expr* rex);
+ void CheckImplicitConversions(Expr *E);
+
+ /// \brief The parser's current scope.
+ ///
+ /// The parser maintains this state here.
+ Scope *CurScope;
+
+protected:
+ friend class Parser;
+
+ /// \brief Retrieve the parser's current scope.
+ Scope *getCurScope() const { return CurScope; }
+};
+
+/// \brief RAII object that enters a new expression evaluation context.
+class EnterExpressionEvaluationContext {
+ Sema &Actions;
+
+public:
+ EnterExpressionEvaluationContext(Sema &Actions,
+ Sema::ExpressionEvaluationContext NewContext)
+ : Actions(Actions) {
+ Actions.PushExpressionEvaluationContext(NewContext);
+ }
+
+ ~EnterExpressionEvaluationContext() {
+ Actions.PopExpressionEvaluationContext();
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Sema/SemaInternal.h b/include/clang/Sema/SemaInternal.h
new file mode 100644
index 000000000000..64b83e3bf612
--- /dev/null
+++ b/include/clang/Sema/SemaInternal.h
@@ -0,0 +1,30 @@
+//===--- SemaInternal.h - Internal Sema Interfaces --------------*- 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 common API and #includes for the internal
+// implementation of Sema.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_SEMA_INTERNAL_H
+#define LLVM_CLANG_SEMA_SEMA_INTERNAL_H
+
+#include "clang/Sema/Sema.h"
+#include "clang/Sema/SemaDiagnostic.h"
+#include "clang/AST/ASTContext.h"
+
+namespace clang {
+
+inline PartialDiagnostic Sema::PDiag(unsigned DiagID) {
+ return PartialDiagnostic(DiagID, Context.getDiagAllocator());
+}
+
+}
+
+#endif
diff --git a/include/clang/Sema/Template.h b/include/clang/Sema/Template.h
new file mode 100644
index 000000000000..a7b3b8461854
--- /dev/null
+++ b/include/clang/Sema/Template.h
@@ -0,0 +1,244 @@
+//===------- SemaTemplate.h - 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 types used in the semantic analysis of C++ templates.
+//
+//===----------------------------------------------------------------------===/
+#ifndef LLVM_CLANG_SEMA_TEMPLATE_H
+#define LLVM_CLANG_SEMA_TEMPLATE_H
+
+#include "clang/AST/DeclTemplate.h"
+#include "llvm/ADT/SmallVector.h"
+#include <cassert>
+
+namespace clang {
+ /// \brief Data structure that captures multiple levels of template argument
+ /// lists for use in template instantiation.
+ ///
+ /// Multiple levels of template arguments occur when instantiating the
+ /// definitions of member templates. For example:
+ ///
+ /// \code
+ /// template<typename T>
+ /// struct X {
+ /// template<T Value>
+ /// struct Y {
+ /// void f();
+ /// };
+ /// };
+ /// \endcode
+ ///
+ /// When instantiating X<int>::Y<17>::f, the multi-level template argument
+ /// list will contain a template argument list (int) at depth 0 and a
+ /// template argument list (17) at depth 1.
+ class MultiLevelTemplateArgumentList {
+ public:
+ typedef std::pair<const TemplateArgument *, unsigned> ArgList;
+
+ private:
+ /// \brief The template argument lists, stored from the innermost template
+ /// argument list (first) to the outermost template argument list (last).
+ llvm::SmallVector<ArgList, 4> TemplateArgumentLists;
+
+ public:
+ /// \brief Construct an empty set of template argument lists.
+ MultiLevelTemplateArgumentList() { }
+
+ /// \brief Construct a single-level template argument list.
+ explicit
+ MultiLevelTemplateArgumentList(const TemplateArgumentList &TemplateArgs) {
+ addOuterTemplateArguments(&TemplateArgs);
+ }
+
+ /// \brief Determine the number of levels in this template argument
+ /// list.
+ unsigned getNumLevels() const { return TemplateArgumentLists.size(); }
+
+ /// \brief Retrieve the template argument at a given depth and index.
+ const TemplateArgument &operator()(unsigned Depth, unsigned Index) const {
+ assert(Depth < TemplateArgumentLists.size());
+ assert(Index < TemplateArgumentLists[getNumLevels() - Depth - 1].second);
+ return TemplateArgumentLists[getNumLevels() - Depth - 1].first[Index];
+ }
+
+ /// \brief Determine whether there is a non-NULL template argument at the
+ /// given depth and index.
+ ///
+ /// There must exist a template argument list at the given depth.
+ bool hasTemplateArgument(unsigned Depth, unsigned Index) const {
+ assert(Depth < TemplateArgumentLists.size());
+
+ if (Index >= TemplateArgumentLists[getNumLevels() - Depth - 1].second)
+ return false;
+
+ return !(*this)(Depth, Index).isNull();
+ }
+
+ /// \brief Add a new outermost level to the multi-level template argument
+ /// list.
+ void addOuterTemplateArguments(const TemplateArgumentList *TemplateArgs) {
+ TemplateArgumentLists.push_back(
+ ArgList(TemplateArgs->getFlatArgumentList(),
+ TemplateArgs->flat_size()));
+ }
+
+ /// \brief Add a new outmost level to the multi-level template argument
+ /// list.
+ void addOuterTemplateArguments(const TemplateArgument *Args,
+ unsigned NumArgs) {
+ TemplateArgumentLists.push_back(ArgList(Args, NumArgs));
+ }
+
+ /// \brief Retrieve the innermost template argument list.
+ const ArgList &getInnermost() const {
+ return TemplateArgumentLists.front();
+ }
+ };
+
+ /// \brief The context in which partial ordering of function templates occurs.
+ enum TPOC {
+ /// \brief Partial ordering of function templates for a function call.
+ TPOC_Call,
+ /// \brief Partial ordering of function templates for a call to a
+ /// conversion function.
+ TPOC_Conversion,
+ /// \brief Partial ordering of function templates in other contexts, e.g.,
+ /// taking the address of a function template or matching a function
+ /// template specialization to a function template.
+ TPOC_Other
+ };
+
+ // This is lame but unavoidable in a world without forward
+ // declarations of enums. The alternatives are to either pollute
+ // Sema.h (by including this file) or sacrifice type safety (by
+ // making Sema.h declare things as enums).
+ class TemplatePartialOrderingContext {
+ TPOC Value;
+ public:
+ TemplatePartialOrderingContext(TPOC Value) : Value(Value) {}
+ operator TPOC() const { return Value; }
+ };
+
+ /// \brief Captures a template argument whose value has been deduced
+ /// via c++ template argument deduction.
+ class DeducedTemplateArgument : public TemplateArgument {
+ /// \brief For a non-type template argument, whether the value was
+ /// deduced from an array bound.
+ bool DeducedFromArrayBound;
+
+ public:
+ DeducedTemplateArgument()
+ : TemplateArgument(), DeducedFromArrayBound(false) { }
+
+ DeducedTemplateArgument(const TemplateArgument &Arg,
+ bool DeducedFromArrayBound = false)
+ : TemplateArgument(Arg), DeducedFromArrayBound(DeducedFromArrayBound) { }
+
+ /// \brief Construct an integral non-type template argument that
+ /// has been deduced, possible from an array bound.
+ DeducedTemplateArgument(const llvm::APSInt &Value,
+ QualType ValueType,
+ bool DeducedFromArrayBound)
+ : TemplateArgument(Value, ValueType),
+ DeducedFromArrayBound(DeducedFromArrayBound) { }
+
+ /// \brief For a non-type template argument, determine whether the
+ /// template argument was deduced from an array bound.
+ bool wasDeducedFromArrayBound() const { return DeducedFromArrayBound; }
+
+ /// \brief Specify whether the given non-type template argument
+ /// was deduced from an array bound.
+ void setDeducedFromArrayBound(bool Deduced) {
+ DeducedFromArrayBound = Deduced;
+ }
+ };
+
+ /// \brief A stack-allocated class that identifies which local
+ /// variable declaration instantiations are present in this scope.
+ ///
+ /// A new instance of this class type will be created whenever we
+ /// instantiate a new function declaration, which will have its own
+ /// set of parameter declarations.
+ class LocalInstantiationScope {
+ /// \brief Reference to the semantic analysis that is performing
+ /// this template instantiation.
+ Sema &SemaRef;
+
+ /// \brief A mapping from local declarations that occur
+ /// within a template to their instantiations.
+ ///
+ /// This mapping is used during instantiation to keep track of,
+ /// e.g., function parameter and variable declarations. For example,
+ /// given:
+ ///
+ /// \code
+ /// template<typename T> T add(T x, T y) { return x + y; }
+ /// \endcode
+ ///
+ /// when we instantiate add<int>, we will introduce a mapping from
+ /// the ParmVarDecl for 'x' that occurs in the template to the
+ /// instantiated ParmVarDecl for 'x'.
+ llvm::DenseMap<const Decl *, Decl *> LocalDecls;
+
+ /// \brief The outer scope, which contains local variable
+ /// definitions from some other instantiation (that may not be
+ /// relevant to this particular scope).
+ LocalInstantiationScope *Outer;
+
+ /// \brief Whether we have already exited this scope.
+ bool Exited;
+
+ /// \brief Whether to combine this scope with the outer scope, such that
+ /// lookup will search our outer scope.
+ bool CombineWithOuterScope;
+
+ // This class is non-copyable
+ LocalInstantiationScope(const LocalInstantiationScope &);
+ LocalInstantiationScope &operator=(const LocalInstantiationScope &);
+
+ public:
+ LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope = false)
+ : SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope),
+ Exited(false), CombineWithOuterScope(CombineWithOuterScope)
+ {
+ SemaRef.CurrentInstantiationScope = this;
+ }
+
+ ~LocalInstantiationScope() {
+ Exit();
+ }
+
+ /// \brief Exit this local instantiation scope early.
+ void Exit() {
+ if (Exited)
+ return;
+
+ SemaRef.CurrentInstantiationScope = Outer;
+ Exited = true;
+ }
+
+ Decl *getInstantiationOf(const Decl *D);
+
+ VarDecl *getInstantiationOf(const VarDecl *Var) {
+ return cast<VarDecl>(getInstantiationOf(cast<Decl>(Var)));
+ }
+
+ ParmVarDecl *getInstantiationOf(const ParmVarDecl *Var) {
+ return cast<ParmVarDecl>(getInstantiationOf(cast<Decl>(Var)));
+ }
+
+ NonTypeTemplateParmDecl *getInstantiationOf(
+ const NonTypeTemplateParmDecl *Var) {
+ return cast<NonTypeTemplateParmDecl>(getInstantiationOf(cast<Decl>(Var)));
+ }
+
+ void InstantiatedLocal(const Decl *D, Decl *Inst);
+ };
+}
+
+#endif // LLVM_CLANG_SEMA_TEMPLATE_H
diff --git a/include/clang/Sema/TemplateDeduction.h b/include/clang/Sema/TemplateDeduction.h
new file mode 100644
index 000000000000..ac32e9c24f6d
--- /dev/null
+++ b/include/clang/Sema/TemplateDeduction.h
@@ -0,0 +1,111 @@
+//===- TemplateDeduction.h - C++ template argument deduction ----*- 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 types used with Sema's template argument deduction
+// routines.
+//
+//===----------------------------------------------------------------------===/
+#ifndef LLVM_CLANG_SEMA_TEMPLATE_DEDUCTION_H
+#define LLVM_CLANG_SEMA_TEMPLATE_DEDUCTION_H
+
+#include "clang/AST/DeclTemplate.h"
+
+namespace clang {
+
+class ASTContext;
+class TemplateArgumentList;
+
+namespace sema {
+
+/// \brief Provides information about an attempted template argument
+/// deduction, whose success or failure was described by a
+/// TemplateDeductionResult value.
+class TemplateDeductionInfo {
+ /// \brief The context in which the template arguments are stored.
+ ASTContext &Context;
+
+ /// \brief The deduced template argument list.
+ ///
+ TemplateArgumentList *Deduced;
+
+ /// \brief The source location at which template argument
+ /// deduction is occurring.
+ SourceLocation Loc;
+
+ // do not implement these
+ TemplateDeductionInfo(const TemplateDeductionInfo&);
+ TemplateDeductionInfo &operator=(const TemplateDeductionInfo&);
+
+public:
+ TemplateDeductionInfo(ASTContext &Context, SourceLocation Loc)
+ : Context(Context), Deduced(0), Loc(Loc) { }
+
+ ~TemplateDeductionInfo() {
+ // FIXME: if (Deduced) Deduced->Destroy(Context);
+ }
+
+ /// \brief Returns the location at which template argument is
+ /// occuring.
+ SourceLocation getLocation() const {
+ return Loc;
+ }
+
+ /// \brief Take ownership of the deduced template argument list.
+ TemplateArgumentList *take() {
+ TemplateArgumentList *Result = Deduced;
+ Deduced = 0;
+ return Result;
+ }
+
+ /// \brief Provide a new template argument list that contains the
+ /// results of template argument deduction.
+ void reset(TemplateArgumentList *NewDeduced) {
+ // FIXME: if (Deduced) Deduced->Destroy(Context);
+ Deduced = NewDeduced;
+ }
+
+ /// \brief The template parameter to which a template argument
+ /// deduction failure refers.
+ ///
+ /// Depending on the result of template argument deduction, this
+ /// template parameter may have different meanings:
+ ///
+ /// TDK_Incomplete: this is the first template parameter whose
+ /// corresponding template argument was not deduced.
+ ///
+ /// TDK_Inconsistent: this is the template parameter for which
+ /// two different template argument values were deduced.
+ TemplateParameter Param;
+
+ /// \brief The first template argument to which the template
+ /// argument deduction failure refers.
+ ///
+ /// Depending on the result of the template argument deduction,
+ /// this template argument may have different meanings:
+ ///
+ /// TDK_Inconsistent: this argument is the first value deduced
+ /// for the corresponding template parameter.
+ ///
+ /// TDK_SubstitutionFailure: this argument is the template
+ /// argument we were instantiating when we encountered an error.
+ ///
+ /// TDK_NonDeducedMismatch: this is the template argument
+ /// provided in the source code.
+ TemplateArgument FirstArg;
+
+ /// \brief The second template argument to which the template
+ /// argument deduction failure refers.
+ ///
+ /// FIXME: Finish documenting this.
+ TemplateArgument SecondArg;
+};
+
+}
+}
+
+#endif
diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Serialization/ASTBitCodes.h
index 27a2b7d0b951..0fa446dd34de 100644
--- a/include/clang/Frontend/PCHBitCodes.h
+++ b/include/clang/Serialization/ASTBitCodes.h
@@ -1,4 +1,4 @@
-//===- PCHBitCodes.h - Enum values for the PCH bitcode format ---*- C++ -*-===//
+//===- ASTBitCodes.h - Enum values for the PCH bitcode format ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// This header defines Bitcode enum values for Clang precompiled header files.
+// This header defines Bitcode enum values for Clang serialized AST files.
//
// The enum values defined in this file should be considered permanent. If
// new features are added, they should have values added at the end of the
@@ -17,42 +17,44 @@
#ifndef LLVM_CLANG_FRONTEND_PCHBITCODES_H
#define LLVM_CLANG_FRONTEND_PCHBITCODES_H
+#include "clang/AST/Type.h"
#include "llvm/Bitcode/BitCodes.h"
#include "llvm/System/DataTypes.h"
+#include "llvm/ADT/DenseMap.h"
namespace clang {
- namespace pch {
- /// \brief PCH major version number supported by this version of
+ namespace serialization {
+ /// \brief AST file major version number supported by this version of
/// Clang.
///
- /// Whenever the PCH format changes in a way that makes it
+ /// Whenever the AST file format changes in a way that makes it
/// incompatible with previous versions (such that a reader
/// designed for the previous version could not support reading
/// the new version), this number should be increased.
///
- /// Version 4 of PCH files also requires that the version control branch and
+ /// Version 4 of AST files also requires that the version control branch and
/// revision match exactly, since there is no backward compatibility of
- /// PCH files at this time.
+ /// AST files at this time.
const unsigned VERSION_MAJOR = 4;
- /// \brief PCH minor version number supported by this version of
+ /// \brief AST file minor version number supported by this version of
/// Clang.
///
- /// Whenever the PCH format changes in a way that is still
+ /// Whenever the AST format changes in a way that is still
/// compatible with previous versions (such that a reader designed
/// for the previous version could still support reading the new
/// version by ignoring new kinds of subblocks), this number
/// should be increased.
const unsigned VERSION_MINOR = 0;
- /// \brief An ID number that refers to a declaration in a PCH file.
+ /// \brief An ID number that refers to a declaration in an AST file.
///
/// The ID numbers of declarations are consecutive (in order of
/// discovery) and start at 2. 0 is reserved for NULL, and 1 is
/// reserved for the translation unit declaration.
typedef uint32_t DeclID;
- /// \brief An ID number that refers to a type in a PCH file.
+ /// \brief An ID number that refers to a type in an AST file.
///
/// The ID of a type is partitioned into two parts: the lower
/// three bits are used to store the const/volatile/restrict
@@ -64,18 +66,64 @@ namespace clang {
/// other types that have serialized representations.
typedef uint32_t TypeID;
- /// \brief An ID number that refers to an identifier in a PCH
+ /// \brief A type index; the type ID with the qualifier bits removed.
+ class TypeIdx {
+ uint32_t Idx;
+ public:
+ TypeIdx() : Idx(0) { }
+ explicit TypeIdx(uint32_t index) : Idx(index) { }
+
+ uint32_t getIndex() const { return Idx; }
+ TypeID asTypeID(unsigned FastQuals) const {
+ return (Idx << Qualifiers::FastWidth) | FastQuals;
+ }
+ static TypeIdx fromTypeID(TypeID ID) {
+ return TypeIdx(ID >> Qualifiers::FastWidth);
+ }
+ };
+
+ /// A structure for putting "fast"-unqualified QualTypes into a
+ /// DenseMap. This uses the standard pointer hash function.
+ struct UnsafeQualTypeDenseMapInfo {
+ static inline bool isEqual(QualType A, QualType B) { return A == B; }
+ static inline QualType getEmptyKey() {
+ return QualType::getFromOpaquePtr((void*) 1);
+ }
+ static inline QualType getTombstoneKey() {
+ return QualType::getFromOpaquePtr((void*) 2);
+ }
+ static inline unsigned getHashValue(QualType T) {
+ assert(!T.getLocalFastQualifiers() &&
+ "hash invalid for types with fast quals");
+ uintptr_t v = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
+ return (unsigned(v) >> 4) ^ (unsigned(v) >> 9);
+ }
+ };
+
+ /// \brief Map that provides the ID numbers of each type within the
+ /// output stream, plus those deserialized from a chained PCH.
+ ///
+ /// The ID numbers of types are consecutive (in order of discovery)
+ /// and start at 1. 0 is reserved for NULL. When types are actually
+ /// stored in the stream, the ID number is shifted by 2 bits to
+ /// allow for the const/volatile qualifiers.
+ ///
+ /// Keys in the map never have const/volatile qualifiers.
+ typedef llvm::DenseMap<QualType, TypeIdx, UnsafeQualTypeDenseMapInfo>
+ TypeIdxMap;
+
+ /// \brief An ID number that refers to an identifier in an AST
/// file.
typedef uint32_t IdentID;
typedef uint32_t SelectorID;
/// \brief Describes the various kinds of blocks that occur within
- /// a PCH file.
+ /// an AST file.
enum BlockIDs {
- /// \brief The PCH block, which acts as a container around the
- /// full PCH block.
- PCH_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID,
+ /// \brief The AST block, which acts as a container around the
+ /// full AST block.
+ AST_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID,
/// \brief The block containing information about the source
/// manager.
@@ -86,16 +134,16 @@ namespace clang {
PREPROCESSOR_BLOCK_ID,
/// \brief The block containing the definitions of all of the
- /// types and decls used within the PCH file.
+ /// types and decls used within the AST file.
DECLTYPES_BLOCK_ID
};
- /// \brief Record types that occur within the PCH block itself.
- enum PCHRecordTypes {
+ /// \brief Record types that occur within the AST block itself.
+ enum ASTRecordTypes {
/// \brief Record code for the offsets of each type.
///
/// The TYPE_OFFSET constant describes the record that occurs
- /// within the PCH block. The record itself is an array of offsets that
+ /// within the AST block. The record itself is an array of offsets that
/// point into the declarations and types block (identified by
/// DECLTYPES_BLOCK_ID). The index into the array is based on the ID
/// of a type. For a given type ID @c T, the lower three bits of
@@ -110,7 +158,7 @@ namespace clang {
///
/// The DECL_OFFSET constant describes the record that occurs
/// within the block identified by DECL_OFFSETS_BLOCK_ID within
- /// the PCH block. The record itself is an array of offsets that
+ /// the AST block. The record itself is an array of offsets that
/// point into the declarations and types block (identified by
/// DECLTYPES_BLOCK_ID). The declaration ID is an index into this
/// record, after subtracting one to account for the use of
@@ -126,8 +174,8 @@ namespace clang {
/// actually important to check.
LANGUAGE_OPTIONS = 3,
- /// \brief PCH metadata, including the PCH file version number
- /// and the target triple used to build the PCH file.
+ /// \brief AST file metadata, including the AST file version number
+ /// and the target triple used to build the AST file.
METADATA = 4,
/// \brief Record code for the table of offsets of each
@@ -142,7 +190,7 @@ namespace clang {
///
/// The identifier table is a simple blob that contains
/// NULL-terminated strings for all of the identifiers
- /// referenced by the PCH file. The IDENTIFIER_OFFSET table
+ /// referenced by the AST file. The IDENTIFIER_OFFSET table
/// contains the mapping from identifier IDs to the characters
/// in this blob. Note that the starting offsets of all of the
/// identifiers are odd, so that, when the identifier offset
@@ -154,10 +202,10 @@ namespace clang {
/// \brief Record code for the array of external definitions.
///
- /// The PCH file contains a list of all of the unnamed external
+ /// The AST file contains a list of all of the unnamed external
/// definitions present within the parsed headers, stored as an
/// array of declaration IDs. These external definitions will be
- /// reported to the AST consumer after the PCH file has been
+ /// reported to the AST consumer after the AST file has been
/// read, since their presence can affect the semantics of the
/// program (e.g., for code generation).
EXTERNAL_DEFINITIONS = 7,
@@ -172,7 +220,7 @@ namespace clang {
SPECIAL_TYPES = 8,
/// \brief Record code for the extra statistics we gather while
- /// generating a PCH file.
+ /// generating an AST file.
STATISTICS = 9,
/// \brief Record code for the array of tentative definitions.
@@ -198,7 +246,7 @@ namespace clang {
SOURCE_LOCATION_OFFSETS = 15,
/// \brief Record code for the set of source location entries
- /// that need to be preloaded by the PCH reader.
+ /// that need to be preloaded by the AST reader.
///
/// This set contains the source location entry for the
/// predefines buffer and for any file entries that need to be
@@ -212,17 +260,17 @@ namespace clang {
EXT_VECTOR_DECLS = 18,
/// \brief Record code for the original file that was used to
- /// generate the precompiled header.
+ /// generate the AST file.
ORIGINAL_FILE_NAME = 19,
/// Record #20 intentionally left blank.
/// \brief Record code for the version control branch and revision
- /// information of the compiler used to build this PCH file.
+ /// information of the compiler used to build this AST file.
VERSION_CONTROL_BRANCH_REVISION = 21,
- /// \brief Record code for the array of unused static functions.
- UNUSED_STATIC_FUNCS = 22,
+ /// \brief Record code for the array of unused file scoped decls.
+ UNUSED_FILESCOPED_DECLS = 22,
/// \brief Record code for the table of offsets to macro definition
/// entries in the preprocessing record.
@@ -234,10 +282,45 @@ namespace clang {
/// \brief Record code for the array of dynamic classes.
DYNAMIC_CLASSES = 25,
- /// \brief Record code for the chained PCH metadata, including the
- /// PCH version and the name of the PCH this is chained to.
- CHAINED_METADATA = 26
+ /// \brief Record code for the chained AST metadata, including the
+ /// AST file version and the name of the PCH this depends on.
+ CHAINED_METADATA = 26,
+
+ /// \brief Record code for referenced selector pool.
+ REFERENCED_SELECTOR_POOL = 27,
+
+ /// \brief Record code for an update to the TU's lexically contained
+ /// declarations.
+ TU_UPDATE_LEXICAL = 28,
+ /// \brief Record code for an update to first decls pointing to the
+ /// latest redeclarations.
+ REDECLS_UPDATE_LATEST = 29,
+
+ /// \brief Record code for declarations that Sema keeps references of.
+ SEMA_DECL_REFS = 30,
+
+ /// \brief Record code for weak undeclared identifiers.
+ WEAK_UNDECLARED_IDENTIFIERS = 31,
+
+ /// \brief Record code for pending implicit instantiations.
+ PENDING_IMPLICIT_INSTANTIATIONS = 32,
+
+ /// \brief Record code for a decl replacement block.
+ ///
+ /// If a declaration is modified after having been deserialized, and then
+ /// written to a dependent AST file, its ID and offset must be added to
+ /// the replacement block.
+ DECL_REPLACEMENTS = 33,
+
+ /// \brief Record code for an update to a decl context's lookup table.
+ ///
+ /// In practice, this should only be used for the TU and namespaces.
+ UPDATE_VISIBLE = 34,
+
+ /// \brief Record code for template specializations introduced after
+ /// serializations of the original template decl.
+ ADDITIONAL_TEMPLATE_SPECIALIZATIONS = 35
};
/// \brief Record types used within a source manager block.
@@ -286,10 +369,10 @@ namespace clang {
PP_MACRO_DEFINITION = 5
};
- /// \defgroup PCHAST Precompiled header AST constants
+ /// \defgroup ASTAST AST file AST constants
///
/// The constants in this group describe various components of the
- /// abstract syntax tree within a precompiled header.
+ /// abstract syntax tree within an AST file.
///
/// @{
@@ -371,7 +454,7 @@ namespace clang {
/// \brief Record codes for each kind of type.
///
/// These constants describe the type records that can occur within a
- /// block identified by DECLTYPES_BLOCK_ID in the PCH file. Each
+ /// block identified by DECLTYPES_BLOCK_ID in the AST file. Each
/// constant describes a record for a specific type class in the
/// AST.
enum TypeCode {
@@ -545,8 +628,8 @@ namespace clang {
/// \brief A record that stores the set of declarations that are
/// lexically stored within a given DeclContext.
///
- /// The record itself is an array of declaration IDs, in the
- /// order in which those declarations were added to the
+ /// The record itself is a blob that is an array of declaration IDs,
+ /// in the order in which those declarations were added to the
/// declaration context. This data is used when iterating over
/// the contents of a DeclContext, e.g., via
/// DeclContext::decls_begin()/DeclContext::decls_end().
@@ -588,17 +671,25 @@ namespace clang {
/// \brief An AccessSpecDecl record.
DECL_ACCESS_SPEC,
- // FIXME: Implement serialization for these decl types. This just
- // allocates the order in which
+ /// \brief A FriendDecl record.
DECL_FRIEND,
+ /// \brief A FriendTemplateDecl record.
DECL_FRIEND_TEMPLATE,
+ /// \brief A ClassTemplateDecl record.
DECL_CLASS_TEMPLATE,
+ /// \brief A ClassTemplateSpecializationDecl record.
DECL_CLASS_TEMPLATE_SPECIALIZATION,
+ /// \brief A ClassTemplatePartialSpecializationDecl record.
DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION,
+ /// \brief A FunctionTemplateDecl record.
DECL_FUNCTION_TEMPLATE,
+ /// \brief A TemplateTypeParmDecl record.
DECL_TEMPLATE_TYPE_PARM,
+ /// \brief A NonTypeTemplateParmDecl record.
DECL_NON_TYPE_TEMPLATE_PARM,
+ /// \brief A TemplateTemplateParmDecl record.
DECL_TEMPLATE_TEMPLATE_PARM,
+ /// \brief A StaticAssertDecl record.
DECL_STATIC_ASSERT
};
@@ -755,6 +846,11 @@ namespace clang {
STMT_OBJC_AT_THROW,
// C++
+
+ /// \brief A CXXCatchStmt record.
+ STMT_CXX_CATCH,
+ /// \brief A CXXTryStmt record.
+ STMT_CXX_TRY,
/// \brief A CXXOperatorCallExpr record.
EXPR_CXX_OPERATOR_CALL,
@@ -764,17 +860,17 @@ namespace clang {
EXPR_CXX_CONSTRUCT,
/// \brief A CXXTemporaryObjectExpr record.
EXPR_CXX_TEMPORARY_OBJECT,
- // \brief A CXXStaticCastExpr record.
+ /// \brief A CXXStaticCastExpr record.
EXPR_CXX_STATIC_CAST,
- // \brief A CXXDynamicCastExpr record.
+ /// \brief A CXXDynamicCastExpr record.
EXPR_CXX_DYNAMIC_CAST,
- // \brief A CXXReinterpretCastExpr record.
+ /// \brief A CXXReinterpretCastExpr record.
EXPR_CXX_REINTERPRET_CAST,
- // \brief A CXXConstCastExpr record.
+ /// \brief A CXXConstCastExpr record.
EXPR_CXX_CONST_CAST,
- // \brief A CXXFunctionalCastExpr record.
+ /// \brief A CXXFunctionalCastExpr record.
EXPR_CXX_FUNCTIONAL_CAST,
- // \brief A CXXBoolLiteralExpr record.
+ /// \brief A CXXBoolLiteralExpr record.
EXPR_CXX_BOOL_LITERAL,
EXPR_CXX_NULL_PTR_LITERAL, // CXXNullPtrLiteralExpr
EXPR_CXX_TYPEID_EXPR, // CXXTypeidExpr (of expr).
@@ -783,7 +879,6 @@ namespace clang {
EXPR_CXX_THROW, // CXXThrowExpr
EXPR_CXX_DEFAULT_ARG, // CXXDefaultArgExpr
EXPR_CXX_BIND_TEMPORARY, // CXXBindTemporaryExpr
- EXPR_CXX_BIND_REFERENCE, // CXXBindReferenceExpr
EXPR_CXX_SCALAR_VALUE_INIT, // CXXScalarValueInitExpr
EXPR_CXX_NEW, // CXXNewExpr
diff --git a/include/clang/Serialization/ASTDeserializationListener.h b/include/clang/Serialization/ASTDeserializationListener.h
new file mode 100644
index 000000000000..f8114de5f15a
--- /dev/null
+++ b/include/clang/Serialization/ASTDeserializationListener.h
@@ -0,0 +1,49 @@
+//===- ASTDeserializationListener.h - Decl/Type PCH Read Events -*- 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 the ASTDeserializationListener class, which is notified
+// by the ASTReader whenever a type or declaration is deserialized.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_AST_DESERIALIZATION_LISTENER_H
+#define LLVM_CLANG_FRONTEND_AST_DESERIALIZATION_LISTENER_H
+
+#include "clang/Serialization/ASTBitCodes.h"
+
+namespace clang {
+
+class Decl;
+class ASTReader;
+class QualType;
+
+class ASTDeserializationListener {
+protected:
+ virtual ~ASTDeserializationListener() {}
+
+public:
+ /// \brief Tell the listener about the reader.
+ virtual void SetReader(ASTReader *Reader) = 0;
+
+ /// \brief An identifier was deserialized from the AST file.
+ virtual void IdentifierRead(serialization::IdentID ID,
+ IdentifierInfo *II) = 0;
+ /// \brief A type was deserialized from the AST file. The ID here has the
+ /// qualifier bits already removed, and T is guaranteed to be locally
+ /// unqualified.
+ virtual void TypeRead(serialization::TypeIdx Idx, QualType T) = 0;
+ /// \brief A decl was deserialized from the AST file.
+ virtual void DeclRead(serialization::DeclID ID, const Decl *D) = 0;
+ /// \brief A selector was read from the AST file.
+ virtual void SelectorRead(serialization::SelectorID iD, Selector Sel) = 0;
+};
+
+}
+
+#endif
diff --git a/include/clang/Frontend/PCHReader.h b/include/clang/Serialization/ASTReader.h
index 47e871f50aeb..d31be88a3e3d 100644
--- a/include/clang/Frontend/PCHReader.h
+++ b/include/clang/Serialization/ASTReader.h
@@ -1,4 +1,4 @@
-//===--- PCHReader.h - Precompiled Headers Reader ---------------*- C++ -*-===//
+//===--- ASTReader.h - AST File Reader --------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,18 +7,17 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines the PCHReader class, which reads a precompiled header.
+// This file defines the ASTReader class, which reads AST files.
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_FRONTEND_PCH_READER_H
-#define LLVM_CLANG_FRONTEND_PCH_READER_H
+#ifndef LLVM_CLANG_FRONTEND_AST_READER_H
+#define LLVM_CLANG_FRONTEND_AST_READER_H
-#include "clang/Frontend/PCHBitCodes.h"
-#include "clang/AST/DeclarationName.h"
+#include "clang/Serialization/ASTBitCodes.h"
#include "clang/Sema/ExternalSemaSource.h"
+#include "clang/AST/DeclarationName.h"
#include "clang/AST/DeclObjC.h"
-#include "clang/AST/Type.h"
#include "clang/AST/TemplateBase.h"
#include "clang/Lex/ExternalPreprocessorSource.h"
#include "clang/Lex/PreprocessingRecord.h"
@@ -28,7 +27,6 @@
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/APSInt.h"
-#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
@@ -59,11 +57,12 @@ class GotoStmt;
class LabelStmt;
class MacroDefinition;
class NamedDecl;
-class PCHDeserializationListener;
+class ASTDeserializationListener;
class Preprocessor;
class Sema;
class SwitchCase;
-class PCHReader;
+class ASTReader;
+class ASTDeclReader;
struct HeaderFileInfo;
struct PCHPredefinesBlock {
@@ -75,15 +74,15 @@ struct PCHPredefinesBlock {
};
typedef llvm::SmallVector<PCHPredefinesBlock, 2> PCHPredefinesBlocks;
-/// \brief Abstract interface for callback invocations by the PCHReader.
+/// \brief Abstract interface for callback invocations by the ASTReader.
///
-/// While reading a PCH file, the PCHReader will call the methods of the
+/// While reading an AST file, the ASTReader will call the methods of the
/// listener to pass on specific information. Some of the listener methods can
-/// return true to indicate to the PCHReader that the information (and
-/// consequently the PCH file) is invalid.
-class PCHReaderListener {
+/// return true to indicate to the ASTReader that the information (and
+/// consequently the AST file) is invalid.
+class ASTReaderListener {
public:
- virtual ~PCHReaderListener();
+ virtual ~ASTReaderListener();
/// \brief Receives the language options.
///
@@ -103,8 +102,8 @@ public:
///
/// \param Buffers Information about the predefines buffers.
///
- /// \param OriginalFileName The original file name for the PCH, which will
- /// appear as an entry in the predefines buffer.
+ /// \param OriginalFileName The original file name for the AST file, which
+ /// will appear as an entry in the predefines buffer.
///
/// \param SuggestedPredefines If necessary, additional definitions are added
/// here.
@@ -123,16 +122,16 @@ public:
virtual void ReadCounter(unsigned Value) {}
};
-/// \brief PCHReaderListener implementation to validate the information of
+/// \brief ASTReaderListener implementation to validate the information of
/// the PCH file against an initialized Preprocessor.
-class PCHValidator : public PCHReaderListener {
+class PCHValidator : public ASTReaderListener {
Preprocessor &PP;
- PCHReader &Reader;
+ ASTReader &Reader;
unsigned NumHeaderInfos;
public:
- PCHValidator(Preprocessor &PP, PCHReader &Reader)
+ PCHValidator(Preprocessor &PP, ASTReader &Reader)
: PP(PP), Reader(Reader), NumHeaderInfos(0) {}
virtual bool ReadLanguageOptions(const LangOptions &LangOpts);
@@ -147,19 +146,19 @@ private:
void Error(const char *Msg);
};
-/// \brief Reads a precompiled head containing the contents of a
-/// translation unit.
+/// \brief Reads an AST files chain containing the contents of a translation
+/// unit.
///
-/// The PCHReader class reads a bitstream (produced by the PCHWriter
+/// The ASTReader class reads bitstreams (produced by the ASTWriter
/// class) containing the serialized representation of a given
/// abstract syntax tree and its supporting data structures. An
-/// instance of the PCHReader can be attached to an ASTContext object,
-/// which will provide access to the contents of the PCH file.
+/// instance of the ASTReader can be attached to an ASTContext object,
+/// which will provide access to the contents of the AST files.
///
-/// The PCH reader provides lazy de-serialization of declarations, as
+/// The AST reader provides lazy de-serialization of declarations, as
/// required when traversing the AST. Only those AST nodes that are
/// actually required will be de-serialized.
-class PCHReader
+class ASTReader
: public ExternalPreprocessorSource,
public ExternalPreprocessingRecordSource,
public ExternalSemaSource,
@@ -167,110 +166,226 @@ class PCHReader
public ExternalIdentifierLookup,
public ExternalSLocEntrySource {
public:
- enum PCHReadResult { Success, Failure, IgnorePCH };
+ enum ASTReadResult { Success, Failure, IgnorePCH };
friend class PCHValidator;
+ friend class ASTDeclReader;
private:
- /// \brief The receiver of some callbacks invoked by PCHReader.
- llvm::OwningPtr<PCHReaderListener> Listener;
+ /// \brief The receiver of some callbacks invoked by ASTReader.
+ llvm::OwningPtr<ASTReaderListener> Listener;
/// \brief The receiver of deserialization events.
- PCHDeserializationListener *DeserializationListener;
+ ASTDeserializationListener *DeserializationListener;
SourceManager &SourceMgr;
FileManager &FileMgr;
Diagnostic &Diags;
/// \brief The semantic analysis object that will be processing the
- /// PCH file and the translation unit that uses it.
+ /// AST files and the translation unit that uses it.
Sema *SemaObj;
/// \brief The preprocessor that will be loading the source file.
Preprocessor *PP;
- /// \brief The AST context into which we'll read the PCH file.
+ /// \brief The AST context into which we'll read the AST files.
ASTContext *Context;
-
- /// \brief The PCH stat cache installed by this PCHReader, if any.
- ///
- /// The dynamic type of this stat cache is always PCHStatCache
- void *StatCache;
/// \brief The AST consumer.
ASTConsumer *Consumer;
- /// \brief The bitstream reader from which we'll read the PCH file.
- llvm::BitstreamReader StreamFile;
- llvm::BitstreamCursor Stream;
+ /// \brief Information that is needed for every file in the chain.
+ struct PerFileData {
+ PerFileData();
+ ~PerFileData();
+
+ /// \brief The AST stat cache installed for this file, if any.
+ ///
+ /// The dynamic type of this stat cache is always ASTStatCache
+ void *StatCache;
+
+ /// \brief The bitstream reader from which we'll read the AST file.
+ llvm::BitstreamReader StreamFile;
+ llvm::BitstreamCursor Stream;
+
+ /// \brief The size of this file, in bits.
+ uint64_t SizeInBits;
- /// \brief The cursor to the start of the preprocessor block, which stores
- /// all of the macro definitions.
- llvm::BitstreamCursor MacroCursor;
+ /// \brief The cursor to the start of the preprocessor block, which stores
+ /// all of the macro definitions.
+ llvm::BitstreamCursor MacroCursor;
- /// DeclsCursor - This is a cursor to the start of the DECLS_BLOCK block. It
- /// has read all the abbreviations at the start of the block and is ready to
- /// jump around with these in context.
- llvm::BitstreamCursor DeclsCursor;
+ /// DeclsCursor - This is a cursor to the start of the DECLS_BLOCK block. It
+ /// has read all the abbreviations at the start of the block and is ready to
+ /// jump around with these in context.
+ llvm::BitstreamCursor DeclsCursor;
- /// \brief The file name of the PCH file.
- std::string FileName;
+ /// \brief The file name of the AST file.
+ std::string FileName;
- /// \brief The memory buffer that stores the data associated with
- /// this PCH file.
- llvm::OwningPtr<llvm::MemoryBuffer> Buffer;
+ /// \brief The memory buffer that stores the data associated with
+ /// this AST file.
+ llvm::OwningPtr<llvm::MemoryBuffer> Buffer;
- /// \brief Offset type for all of the source location entries in the
- /// PCH file.
- const uint32_t *SLocOffsets;
+ /// \brief Cursor used to read source location entries.
+ llvm::BitstreamCursor SLocEntryCursor;
- /// \brief The number of source location entries in the PCH file.
- unsigned TotalNumSLocEntries;
+ /// \brief The number of source location entries in this AST file.
+ unsigned LocalNumSLocEntries;
+
+ /// \brief Offsets for all of the source location entries in the
+ /// AST file.
+ const uint32_t *SLocOffsets;
+
+ /// \brief The number of types in this AST file.
+ unsigned LocalNumTypes;
+
+ /// \brief Offset of each type within the bitstream, indexed by the
+ /// type ID, or the representation of a Type*.
+ const uint32_t *TypeOffsets;
+
+ /// \brief The number of declarations in this AST file.
+ unsigned LocalNumDecls;
+
+ /// \brief Offset of each declaration within the bitstream, indexed
+ /// by the declaration ID (-1).
+ const uint32_t *DeclOffsets;
+
+ /// \brief The number of identifiers in this AST file.
+ unsigned LocalNumIdentifiers;
- /// \brief Cursor used to read source location entries.
- llvm::BitstreamCursor SLocEntryCursor;
+ /// \brief Offsets into the identifier table data.
+ ///
+ /// This array is indexed by the identifier ID (-1), and provides
+ /// the offset into IdentifierTableData where the string data is
+ /// stored.
+ const uint32_t *IdentifierOffsets;
- /// \brief Offset of each type within the bitstream, indexed by the
- /// type ID, or the representation of a Type*.
- const uint32_t *TypeOffsets;
+ /// \brief Actual data for the on-disk hash table.
+ ///
+ // This pointer points into a memory buffer, where the on-disk hash
+ // table for identifiers actually lives.
+ const char *IdentifierTableData;
- /// \brief Types that have already been loaded from the PCH file.
+ /// \brief A pointer to an on-disk hash table of opaque type
+ /// IdentifierHashTable.
+ void *IdentifierLookupTable;
+
+ /// \brief The number of macro definitions in this file.
+ unsigned LocalNumMacroDefinitions;
+
+ /// \brief Offsets of all of the macro definitions in the preprocessing
+ /// record in the AST file.
+ const uint32_t *MacroDefinitionOffsets;
+
+ /// \brief The number of preallocated preprocessing entities in the
+ /// preprocessing record.
+ unsigned NumPreallocatedPreprocessingEntities;
+
+ /// \brief A pointer to an on-disk hash table of opaque type
+ /// ASTSelectorLookupTable.
+ ///
+ /// This hash table provides the IDs of all selectors, and the associated
+ /// instance and factory methods.
+ void *SelectorLookupTable;
+
+ /// \brief A pointer to the character data that comprises the selector table
+ ///
+ /// The SelectorOffsets table refers into this memory.
+ const unsigned char *SelectorLookupTableData;
+
+ /// \brief Offsets into the method pool lookup table's data array
+ /// where each selector resides.
+ const uint32_t *SelectorOffsets;
+
+ /// \brief The number of selectors new to this file.
+ ///
+ /// This is the number of entries in SelectorOffsets.
+ unsigned LocalNumSelectors;
+ };
+
+ /// \brief The chain of AST files. The first entry is the one named by the
+ /// user, the last one is the one that doesn't depend on anything further.
+ /// That is, the entry I was created with -include-pch I+1.
+ llvm::SmallVector<PerFileData*, 2> Chain;
+
+ /// \brief Types that have already been loaded from the chain.
///
/// When the pointer at index I is non-NULL, the type with
- /// ID = (I + 1) << 3 has already been loaded from the PCH file.
+ /// ID = (I + 1) << FastQual::Width has already been loaded
std::vector<QualType> TypesLoaded;
- /// \brief Offset of each declaration within the bitstream, indexed
- /// by the declaration ID (-1).
- const uint32_t *DeclOffsets;
+ /// \brief Map that provides the ID numbers of each type within the
+ /// output stream, plus those deserialized from a chained PCH.
+ ///
+ /// The ID numbers of types are consecutive (in order of discovery)
+ /// and start at 1. 0 is reserved for NULL. When types are actually
+ /// stored in the stream, the ID number is shifted by 2 bits to
+ /// allow for the const/volatile qualifiers.
+ ///
+ /// Keys in the map never have const/volatile qualifiers.
+ serialization::TypeIdxMap TypeIdxs;
- /// \brief Declarations that have already been loaded from the PCH file.
+ /// \brief Declarations that have already been loaded from the chain.
///
/// When the pointer at index I is non-NULL, the declaration with ID
/// = I + 1 has already been loaded.
std::vector<Decl *> DeclsLoaded;
- typedef llvm::DenseMap<const DeclContext *, std::pair<uint64_t, uint64_t> >
- DeclContextOffsetsMap;
+ typedef llvm::DenseMap<serialization::DeclID,
+ std::pair<PerFileData *, uint64_t> >
+ DeclReplacementMap;
+ /// \brief Declarations that have been replaced in a later file in the chain.
+ DeclReplacementMap ReplacedDecls;
+
+ /// \brief Information about the contents of a DeclContext.
+ struct DeclContextInfo {
+ void *NameLookupTableData; // a ASTDeclContextNameLookupTable.
+ const serialization::DeclID *LexicalDecls;
+ unsigned NumLexicalDecls;
+ };
+ // In a full chain, there could be multiple updates to every decl context,
+ // so this is a vector. However, typically a chain is only two elements long,
+ // with only one file containing updates, so there will be only one update
+ // per decl context.
+ typedef llvm::SmallVector<DeclContextInfo, 1> DeclContextInfos;
+ typedef llvm::DenseMap<const DeclContext *, DeclContextInfos>
+ DeclContextOffsetsMap;
+ // Updates for visible decls can occur for other contexts than just the
+ // TU, and when we read those update records, the actual context will not
+ // be available yet (unless it's the TU), so have this pending map using the
+ // ID as a key. It will be realized when the context is actually loaded.
+ typedef llvm::SmallVector<void *, 1> DeclContextVisibleUpdates;
+ typedef llvm::DenseMap<serialization::DeclID, DeclContextVisibleUpdates>
+ DeclContextVisibleUpdatesPending;
/// \brief Offsets of the lexical and visible declarations for each
/// DeclContext.
DeclContextOffsetsMap DeclContextOffsets;
- /// \brief Actual data for the on-disk hash table.
- ///
- // This pointer points into a memory buffer, where the on-disk hash
- // table for identifiers actually lives.
- const char *IdentifierTableData;
+ /// \brief Updates to the visible declarations of declaration contexts that
+ /// haven't been loaded yet.
+ DeclContextVisibleUpdatesPending PendingVisibleUpdates;
- /// \brief A pointer to an on-disk hash table of opaque type
- /// IdentifierHashTable.
- void *IdentifierLookupTable;
+ typedef llvm::DenseMap<serialization::DeclID, serialization::DeclID>
+ FirstLatestDeclIDMap;
+ /// \brief Map of first declarations from a chained PCH that point to the
+ /// most recent declarations in another AST file.
+ FirstLatestDeclIDMap FirstLatestDeclIDs;
- /// \brief Offsets into the identifier table data.
- ///
- /// This array is indexed by the identifier ID (-1), and provides
- /// the offset into IdentifierTableData where the string data is
- /// stored.
- const uint32_t *IdentifierOffsets;
+ typedef llvm::SmallVector<serialization::DeclID, 4>
+ AdditionalTemplateSpecializations;
+ typedef llvm::DenseMap<serialization::DeclID,
+ AdditionalTemplateSpecializations>
+ AdditionalTemplateSpecializationsMap;
+
+ /// \brief Additional specializations (including partial) of templates that
+ /// were introduced after the template was serialized.
+ AdditionalTemplateSpecializationsMap AdditionalTemplateSpecializationsPending;
+
+ /// \brief Read the records that describe the contents of declcontexts.
+ bool ReadDeclContextStorage(llvm::BitstreamCursor &Cursor,
+ const std::pair<uint64_t, uint64_t> &Offsets,
+ DeclContextInfo &Info);
/// \brief A vector containing identifiers that have already been
/// loaded.
@@ -280,29 +395,6 @@ private:
/// been loaded.
std::vector<IdentifierInfo *> IdentifiersLoaded;
- /// \brief A pointer to an on-disk hash table of opaque type
- /// PCHMethodPoolLookupTable.
- ///
- /// This hash table provides the instance and factory methods
- /// associated with every selector known in the PCH file.
- void *MethodPoolLookupTable;
-
- /// \brief A pointer to the character data that comprises the method
- /// pool.
- ///
- /// The SelectorOffsets table refers into this memory.
- const unsigned char *MethodPoolLookupTableData;
-
- /// \brief The number of selectors stored in the method pool itself.
- unsigned TotalSelectorsInMethodPool;
-
- /// \brief Offsets into the method pool lookup table's data array
- /// where each selector resides.
- const uint32_t *SelectorOffsets;
-
- /// \brief The total number of selectors stored in the PCH file.
- unsigned TotalNumSelectors;
-
/// \brief A vector containing selectors that have already been loaded.
///
/// This vector is indexed by the Selector ID (-1). NULL selector
@@ -310,52 +402,102 @@ private:
/// been loaded.
llvm::SmallVector<Selector, 16> SelectorsLoaded;
- /// \brief Offsets of all of the macro definitions in the preprocessing
- /// record in the PCH file.
- const uint32_t *MacroDefinitionOffsets;
-
/// \brief The macro definitions we have already loaded.
llvm::SmallVector<MacroDefinition *, 16> MacroDefinitionsLoaded;
-
- /// \brief The number of preallocated preprocessing entities in the
- /// preprocessing record.
- unsigned NumPreallocatedPreprocessingEntities;
-
- /// \brief The set of external definitions stored in the the PCH
- /// file.
+
+ /// \name CodeGen-relevant special data
+ /// \brief Fields containing data that is relevant to CodeGen.
+ //@{
+
+ /// \brief The IDs of all declarations that fulfill the criteria of
+ /// "interesting" decls.
+ ///
+ /// This contains the data loaded from all EXTERNAL_DEFINITIONS blocks in the
+ /// chain. The referenced declarations are deserialized and passed to the
+ /// consumer eagerly.
llvm::SmallVector<uint64_t, 16> ExternalDefinitions;
- /// \brief The set of tentative definitions stored in the the PCH
- /// file.
+ /// \brief The IDs of all tentative definitions stored in the the chain.
+ ///
+ /// Sema keeps track of all tentative definitions in a TU because it has to
+ /// complete them and pass them on to CodeGen. Thus, tentative definitions in
+ /// the PCH chain must be eagerly deserialized.
llvm::SmallVector<uint64_t, 16> TentativeDefinitions;
-
- /// \brief The set of unused static functions stored in the the PCH
- /// file.
- llvm::SmallVector<uint64_t, 16> UnusedStaticFuncs;
- /// \brief The set of locally-scoped external declarations stored in
- /// the the PCH file.
- llvm::SmallVector<uint64_t, 16> LocallyScopedExternalDecls;
+ /// \brief The IDs of all CXXRecordDecls stored in the chain whose VTables are
+ /// used.
+ ///
+ /// CodeGen has to emit VTables for these records, so they have to be eagerly
+ /// deserialized.
+ llvm::SmallVector<uint64_t, 64> VTableUses;
+
+ //@}
+
+ /// \name Diagnostic-relevant special data
+ /// \brief Fields containing data that is used for generating diagnostics
+ //@{
- /// \brief The set of ext_vector type declarations stored in the the
- /// PCH file.
+ /// \brief Method selectors used in a @selector expression. Used for
+ /// implementation of -Wselector.
+ llvm::SmallVector<uint64_t, 64> ReferencedSelectorsData;
+
+ /// \brief A snapshot of Sema's unused file-scoped variable tracking, for
+ /// generating warnings.
+ llvm::SmallVector<uint64_t, 16> UnusedFileScopedDecls;
+
+ /// \brief A snapshot of Sema's weak undeclared identifier tracking, for
+ /// generating warnings.
+ llvm::SmallVector<uint64_t, 64> WeakUndeclaredIdentifiers;
+
+ /// \brief The IDs of type aliases for ext_vectors that exist in the chain.
+ ///
+ /// Used by Sema for finding sugared names for ext_vectors in diagnostics.
llvm::SmallVector<uint64_t, 4> ExtVectorDecls;
- /// \brief The set of VTable uses of CXXRecordDecls stored in the PCH file.
- llvm::SmallVector<uint64_t, 64> VTableUses;
+ //@}
+
+ /// \name Sema-relevant special data
+ /// \brief Fields containing data that is used for semantic analysis
+ //@{
- /// \brief The set of dynamic CXXRecord declarations stored in the PCH file.
+ /// \brief The IDs of all locally scoped external decls in the chain.
+ ///
+ /// Sema tracks these to validate that the types are consistent across all
+ /// local external declarations.
+ llvm::SmallVector<uint64_t, 16> LocallyScopedExternalDecls;
+
+ /// \brief A snapshot of the pwnsinf instantiations in the chain.
+ ///
+ /// This record tracks the instantiations that Sema has to perform at the end
+ /// of the TU. It consists of a pair of values for every pending instantiation
+ /// where the first value is the ID of the decl and the second is the
+ /// instantiation location.
+ llvm::SmallVector<uint64_t, 64> PendingInstantiations;
+
+ /// \brief The IDs of all dynamic class declarations in the chain.
+ ///
+ /// Sema tracks these because it checks for the key functions being defined
+ /// at the end of the TU, in which case it directs CodeGen to emit the VTable.
llvm::SmallVector<uint64_t, 16> DynamicClasses;
- /// \brief The set of Objective-C category definitions stored in the
- /// the PCH file.
- llvm::SmallVector<uint64_t, 4> ObjCCategoryImpls;
+ /// \brief The IDs of the declarations Sema stores directly.
+ ///
+ /// Sema tracks a few important decls, such as namespace std, directly.
+ llvm::SmallVector<uint64_t, 4> SemaDeclRefs;
+
+ /// \brief The IDs of the types ASTContext stores directly.
+ ///
+ /// The AST context tracks a few important types, such as va_list, directly.
+ llvm::SmallVector<uint64_t, 16> SpecialTypes;
- /// \brief The original file name that was used to build the PCH file, which
- /// may have been modified for relocatable-pch support.
+ //@}
+
+ /// \brief The original file name that was used to build the primary AST file,
+ /// which may have been modified for relocatable-pch support.
std::string OriginalFileName;
- /// \brief The actual original file name that was used to build the PCH file.
+ /// \brief The actual original file name that was used to build the primary
+ /// AST file.
std::string ActualOriginalFileName;
/// \brief Whether this precompiled header is a relocatable PCH file.
@@ -365,12 +507,20 @@ private:
/// precompiled header.
const char *isysroot;
- /// \brief Mapping from switch-case IDs in the PCH file to
- /// switch-case statements.
+ /// \brief Whether to disable the normal validation performed on precompiled
+ /// headers when they are loaded.
+ bool DisableValidation;
+
+ /// \brief Mapping from switch-case IDs in the chain to switch-case statements
+ ///
+ /// Statements usually don't have IDs, but switch cases need them, so that the
+ /// switch statement can refer to them.
std::map<unsigned, SwitchCase *> SwitchCaseStmts;
- /// \brief Mapping from label statement IDs in the PCH file to label
- /// statements.
+ /// \brief Mapping from label statement IDs in the chain to label statements.
+ ///
+ /// Statements usually don't have IDs, but labeled statements need them, so
+ /// that goto statements and address-of-label expressions can refer to them.
std::map<unsigned, LabelStmt *> LabelStmts;
/// \brief Mapping from label IDs to the set of "goto" statements
@@ -391,52 +541,44 @@ private:
/// the PCH file.
unsigned NumSLocEntriesRead;
+ /// \brief The number of source location entries in the chain.
+ unsigned TotalNumSLocEntries;
+
/// \brief The number of statements (and expressions) de-serialized
- /// from the PCH file.
+ /// from the chain.
unsigned NumStatementsRead;
/// \brief The total number of statements (and expressions) stored
- /// in the PCH file.
+ /// in the chain.
unsigned TotalNumStatements;
- /// \brief The number of macros de-serialized from the PCH file.
+ /// \brief The number of macros de-serialized from the chain.
unsigned NumMacrosRead;
+ /// \brief The total number of macros stored in the chain.
+ unsigned TotalNumMacros;
+
+ /// \brief The number of selectors that have been read.
+ unsigned NumSelectorsRead;
+
/// \brief The number of method pool entries that have been read.
- unsigned NumMethodPoolSelectorsRead;
+ unsigned NumMethodPoolEntriesRead;
- /// \brief The number of times we have looked into the global method
- /// pool and not found anything.
+ /// \brief The number of times we have looked up a selector in the method
+ /// pool and not found anything interesting.
unsigned NumMethodPoolMisses;
- /// \brief The total number of macros stored in the PCH file.
- unsigned TotalNumMacros;
+ /// \brief The total number of method pool entries in the selector table.
+ unsigned TotalNumMethodPoolEntries;
/// Number of lexical decl contexts read/total.
unsigned NumLexicalDeclContextsRead, TotalLexicalDeclContexts;
/// Number of visible decl contexts read/total.
unsigned NumVisibleDeclContextsRead, TotalVisibleDeclContexts;
-
- /// \brief When a type or declaration is being loaded from the PCH file, an
- /// instantance of this RAII object will be available on the stack to
- /// indicate when we are in a recursive-loading situation.
- class LoadingTypeOrDecl {
- PCHReader &Reader;
- LoadingTypeOrDecl *Parent;
-
- LoadingTypeOrDecl(const LoadingTypeOrDecl&); // do not implement
- LoadingTypeOrDecl &operator=(const LoadingTypeOrDecl&); // do not implement
-
- public:
- explicit LoadingTypeOrDecl(PCHReader &Reader);
- ~LoadingTypeOrDecl();
- };
- friend class LoadingTypeOrDecl;
-
- /// \brief If we are currently loading a type or declaration, points to the
- /// most recent LoadingTypeOrDecl object on the stack.
- LoadingTypeOrDecl *CurrentlyLoadingTypeOrDecl;
+
+ /// \brief Number of Decl/types that are currently deserializing.
+ unsigned NumCurrentElementsDeserializing;
/// \brief An IdentifierInfo that has been loaded but whose top-level
/// declarations of the same name have not (yet) been loaded.
@@ -445,16 +587,13 @@ private:
llvm::SmallVector<uint32_t, 4> DeclIDs;
};
- /// \brief The set of identifiers that were read while the PCH reader was
+ /// \brief The set of identifiers that were read while the AST reader was
/// (recursively) loading declarations.
///
/// The declarations on the identifier chain for these identifiers will be
/// loaded once the recursive loading has completed.
std::deque<PendingIdentifierInfo> PendingIdentifierInfos;
- /// \brief FIXME: document!
- llvm::SmallVector<uint64_t, 16> SpecialTypes;
-
/// \brief Contains declarations and definitions that will be
/// "interesting" to the ASTConsumer, when we get that AST consumer.
///
@@ -476,14 +615,14 @@ private:
/// \brief RAII object to change the reading kind.
class ReadingKindTracker {
- PCHReader &Reader;
+ ASTReader &Reader;
enum ReadingKind PrevKind;
ReadingKindTracker(const ReadingKindTracker&); // do not implement
ReadingKindTracker &operator=(const ReadingKindTracker&);// do not implement
public:
- ReadingKindTracker(enum ReadingKind newKind, PCHReader &reader)
+ ReadingKindTracker(enum ReadingKind newKind, ASTReader &reader)
: Reader(reader), PrevKind(Reader.ReadingKind) {
Reader.ReadingKind = newKind;
}
@@ -491,7 +630,7 @@ private:
~ReadingKindTracker() { Reader.ReadingKind = PrevKind; }
};
- /// \brief All predefines buffers in all PCH files, to be treated as if
+ /// \brief All predefines buffers in the chain, to be treated as if
/// concatenated.
PCHPredefinesBlocks PCHPredefinesBuffers;
@@ -510,31 +649,37 @@ private:
void MaybeAddSystemRootToFilename(std::string &Filename);
- PCHReadResult ReadPCHBlock();
+ ASTReadResult ReadASTCore(llvm::StringRef FileName);
+ ASTReadResult ReadASTBlock(PerFileData &F);
bool CheckPredefinesBuffers();
bool ParseLineTable(llvm::SmallVectorImpl<uint64_t> &Record);
- PCHReadResult ReadSourceManagerBlock();
- PCHReadResult ReadSLocEntryRecord(unsigned ID);
-
+ ASTReadResult ReadSourceManagerBlock(PerFileData &F);
+ ASTReadResult ReadSLocEntryRecord(unsigned ID);
+ llvm::BitstreamCursor &SLocCursorForID(unsigned ID);
bool ParseLanguageOptions(const llvm::SmallVectorImpl<uint64_t> &Record);
- QualType ReadTypeRecord(uint64_t Offset);
+
+ typedef std::pair<llvm::BitstreamCursor *, uint64_t> RecordLocation;
+
+ QualType ReadTypeRecord(unsigned Index);
+ RecordLocation TypeCursorForIndex(unsigned Index);
void LoadedDecl(unsigned Index, Decl *D);
- Decl *ReadDeclRecord(uint64_t Offset, unsigned Index);
+ Decl *ReadDeclRecord(unsigned Index, serialization::DeclID ID);
+ RecordLocation DeclCursorForIndex(unsigned Index, serialization::DeclID ID);
void PassInterestingDeclsToConsumer();
/// \brief Produce an error diagnostic and return true.
///
/// This routine should only be used for fatal errors that have to
- /// do with non-routine failures (e.g., corrupted PCH file).
+ /// do with non-routine failures (e.g., corrupted AST file).
void Error(const char *Msg);
- PCHReader(const PCHReader&); // do not implement
- PCHReader &operator=(const PCHReader &); // do not implement
+ ASTReader(const ASTReader&); // do not implement
+ ASTReader &operator=(const ASTReader &); // do not implement
public:
typedef llvm::SmallVector<uint64_t, 64> RecordData;
- /// \brief Load the PCH file and validate its contents against the given
+ /// \brief Load the AST file and validate its contents against the given
/// Preprocessor.
///
/// \param PP the preprocessor associated with the context in which this
@@ -546,41 +691,48 @@ public:
/// \param isysroot If non-NULL, the system include path specified by the
/// user. This is only used with relocatable PCH files. If non-NULL,
/// a relocatable PCH file will use the default path "/".
- PCHReader(Preprocessor &PP, ASTContext *Context, const char *isysroot = 0);
+ ///
+ /// \param DisableValidation If true, the AST reader will suppress most
+ /// of its regular consistency checking, allowing the use of precompiled
+ /// headers that cannot be determined to be compatible.
+ ASTReader(Preprocessor &PP, ASTContext *Context, const char *isysroot = 0,
+ bool DisableValidation = false);
- /// \brief Load the PCH file without using any pre-initialized Preprocessor.
+ /// \brief Load the AST file without using any pre-initialized Preprocessor.
///
/// The necessary information to initialize a Preprocessor later can be
- /// obtained by setting a PCHReaderListener.
+ /// obtained by setting a ASTReaderListener.
///
- /// \param SourceMgr the source manager into which the precompiled header
- /// will be loaded.
+ /// \param SourceMgr the source manager into which the AST file will be loaded
///
- /// \param FileMgr the file manager into which the precompiled header will
- /// be loaded.
+ /// \param FileMgr the file manager into which the AST file will be loaded.
///
/// \param Diags the diagnostics system to use for reporting errors and
- /// warnings relevant to loading the precompiled header.
+ /// warnings relevant to loading the AST file.
///
/// \param isysroot If non-NULL, the system include path specified by the
/// user. This is only used with relocatable PCH files. If non-NULL,
/// a relocatable PCH file will use the default path "/".
- PCHReader(SourceManager &SourceMgr, FileManager &FileMgr,
- Diagnostic &Diags, const char *isysroot = 0);
- ~PCHReader();
+ ///
+ /// \param DisableValidation If true, the AST reader will suppress most
+ /// of its regular consistency checking, allowing the use of precompiled
+ /// headers that cannot be determined to be compatible.
+ ASTReader(SourceManager &SourceMgr, FileManager &FileMgr,
+ Diagnostic &Diags, const char *isysroot = 0,
+ bool DisableValidation = false);
+ ~ASTReader();
/// \brief Load the precompiled header designated by the given file
/// name.
- PCHReadResult ReadPCH(const std::string &FileName);
+ ASTReadResult ReadAST(const std::string &FileName);
- /// \brief Set the PCH callbacks listener.
- void setListener(PCHReaderListener *listener) {
+ /// \brief Set the AST callbacks listener.
+ void setListener(ASTReaderListener *listener) {
Listener.reset(listener);
}
- void setDeserializationListener(PCHDeserializationListener *Listener) {
- DeserializationListener = Listener;
- }
+ /// \brief Set the AST deserialization listener.
+ void setDeserializationListener(ASTDeserializationListener *Listener);
/// \brief Set the Preprocessor to use.
void setPreprocessor(Preprocessor &pp);
@@ -588,16 +740,15 @@ public:
/// \brief Sets and initializes the given Context.
void InitializeContext(ASTContext &Context);
- /// \brief Retrieve the name of the PCH file
- const std::string &getFileName() const { return FileName; }
+ /// \brief Retrieve the name of the named (primary) AST file
+ const std::string &getFileName() const { return Chain[0]->FileName; }
/// \brief Retrieve the name of the original source file name
const std::string &getOriginalSourceFile() { return OriginalFileName; }
- /// \brief Retrieve the name of the original source file name
- /// directly from the PCH file, without actually loading the PCH
- /// file.
- static std::string getOriginalSourceFile(const std::string &PCHFileName,
+ /// \brief Retrieve the name of the original source file name directly from
+ /// the AST file, without actually loading the AST file.
+ static std::string getOriginalSourceFile(const std::string &ASTFileName,
Diagnostic &Diags);
/// \brief Returns the suggested contents of the predefines buffer,
@@ -608,40 +759,67 @@ public:
/// \brief Read preprocessed entities into the
virtual void ReadPreprocessedEntities();
- /// \brief Returns the number of types found in this file.
+ /// \brief Returns the number of source locations found in the chain.
+ unsigned getTotalNumSLocs() const {
+ return TotalNumSLocEntries;
+ }
+
+ /// \brief Returns the number of identifiers found in the chain.
+ unsigned getTotalNumIdentifiers() const {
+ return static_cast<unsigned>(IdentifiersLoaded.size());
+ }
+
+ /// \brief Returns the number of types found in the chain.
unsigned getTotalNumTypes() const {
return static_cast<unsigned>(TypesLoaded.size());
}
- /// \brief Returns the number of declarations found in this file.
+ /// \brief Returns the number of declarations found in the chain.
unsigned getTotalNumDecls() const {
return static_cast<unsigned>(DeclsLoaded.size());
}
+ /// \brief Returns the number of selectors found in the chain.
+ unsigned getTotalNumSelectors() const {
+ return static_cast<unsigned>(SelectorsLoaded.size());
+ }
+
/// \brief Reads a TemplateArgumentLocInfo appropriate for the
/// given TemplateArgument kind.
TemplateArgumentLocInfo
GetTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind,
+ llvm::BitstreamCursor &DeclsCursor,
const RecordData &Record, unsigned &Idx);
/// \brief Reads a TemplateArgumentLoc.
- TemplateArgumentLoc ReadTemplateArgumentLoc(const RecordData &Record,
- unsigned &Idx);
+ TemplateArgumentLoc
+ ReadTemplateArgumentLoc(llvm::BitstreamCursor &DeclsCursor,
+ const RecordData &Record, unsigned &Idx);
/// \brief Reads a declarator info from the given record.
- TypeSourceInfo *GetTypeSourceInfo(const RecordData &Record,
- unsigned &Idx);
+ TypeSourceInfo *GetTypeSourceInfo(llvm::BitstreamCursor &DeclsCursor,
+ const RecordData &Record, unsigned &Idx);
/// \brief Resolve and return the translation unit declaration.
TranslationUnitDecl *GetTranslationUnitDecl();
/// \brief Resolve a type ID into a type, potentially building a new
/// type.
- QualType GetType(pch::TypeID ID);
+ QualType GetType(serialization::TypeID ID);
+
+ /// \brief Returns the type ID associated with the given type.
+ /// If the type didn't come from the AST file the ID that is returned is
+ /// marked as "doesn't exist in AST".
+ serialization::TypeID GetTypeID(QualType T) const;
+
+ /// \brief Returns the type index associated with the given type.
+ /// If the type didn't come from the AST file the index that is returned is
+ /// marked as "doesn't exist in AST".
+ serialization::TypeIdx GetTypeIdx(QualType T) const;
/// \brief Resolve a declaration ID into a declaration, potentially
/// building a new declaration.
- Decl *GetDecl(pch::DeclID ID);
+ Decl *GetDecl(serialization::DeclID ID);
virtual Decl *GetExternalDecl(uint32_t ID);
/// \brief Resolve the offset of a statement into a statement.
@@ -663,6 +841,8 @@ public:
FindExternalVisibleDeclsByName(const DeclContext *DC,
DeclarationName Name);
+ virtual void MaterializeVisibleDecls(const DeclContext *DC);
+
/// \brief Read all of the declarations lexically stored in a
/// declaration context.
///
@@ -679,6 +859,15 @@ public:
virtual bool FindExternalLexicalDecls(const DeclContext *DC,
llvm::SmallVectorImpl<Decl*> &Decls);
+ /// \brief Notify ASTReader that we started deserialization of
+ /// a decl or type so until FinishedDeserializing is called there may be
+ /// decls that are initializing. Must be paired with FinishedDeserializing.
+ virtual void StartedDeserializing() { ++NumCurrentElementsDeserializing; }
+
+ /// \brief Notify ASTReader that we finished the deserialization of
+ /// a decl or type. Must be paired with StartedDeserializing.
+ virtual void FinishedDeserializing();
+
/// \brief Function that will be invoked when we begin parsing a new
/// translation unit involving this external AST source.
///
@@ -686,7 +875,7 @@ public:
/// the ASTConsumer.
virtual void StartTranslationUnit(ASTConsumer *Consumer);
- /// \brief Print some statistics about PCH usage.
+ /// \brief Print some statistics about AST usage.
virtual void PrintStats();
/// \brief Initialize the semantic source with the Sema instance
@@ -716,6 +905,9 @@ public:
virtual std::pair<ObjCMethodList, ObjCMethodList>
ReadMethodPool(Selector Sel);
+ /// \brief Load a selector from disk, registering its ID if it exists.
+ void LoadSelector(Selector Sel);
+
void SetIdentifierInfo(unsigned ID, IdentifierInfo *II);
void SetGloballyVisibleDecls(IdentifierInfo *II,
const llvm::SmallVectorImpl<uint32_t> &DeclIDs,
@@ -759,7 +951,8 @@ public:
TemplateName ReadTemplateName(const RecordData &Record, unsigned &Idx);
/// \brief Read a template argument.
- TemplateArgument ReadTemplateArgument(const RecordData &Record,unsigned &Idx);
+ TemplateArgument ReadTemplateArgument(llvm::BitstreamCursor &DeclsCursor,
+ const RecordData &Record,unsigned &Idx);
/// \brief Read a template parameter list.
TemplateParameterList *ReadTemplateParameterList(const RecordData &Record,
@@ -768,6 +961,7 @@ public:
/// \brief Read a template argument array.
void
ReadTemplateArgumentList(llvm::SmallVector<TemplateArgument, 8> &TemplArgs,
+ llvm::BitstreamCursor &DeclsCursor,
const RecordData &Record, unsigned &Idx);
/// \brief Read a UnresolvedSet structure.
@@ -775,7 +969,13 @@ public:
const RecordData &Record, unsigned &Idx);
/// \brief Read a C++ base specifier.
- CXXBaseSpecifier ReadCXXBaseSpecifier(const RecordData &Record,unsigned &Idx);
+ CXXBaseSpecifier ReadCXXBaseSpecifier(llvm::BitstreamCursor &DeclsCursor,
+ const RecordData &Record,unsigned &Idx);
+
+ /// \brief Read a CXXBaseOrMemberInitializer array.
+ std::pair<CXXBaseOrMemberInitializer **, unsigned>
+ ReadCXXBaseOrMemberInitializers(llvm::BitstreamCursor &DeclsCursor,
+ const RecordData &Record, unsigned &Idx);
/// \brief Read a source location.
SourceLocation ReadSourceLocation(const RecordData &Record, unsigned& Idx) {
@@ -800,13 +1000,13 @@ public:
CXXTemporary *ReadCXXTemporary(const RecordData &Record, unsigned &Idx);
/// \brief Reads attributes from the current stream position.
- Attr *ReadAttributes();
+ void ReadAttributes(llvm::BitstreamCursor &DeclsCursor, AttrVec &Attrs);
/// \brief Reads a statement.
- Stmt *ReadStmt();
+ Stmt *ReadStmt(llvm::BitstreamCursor &Cursor);
/// \brief Reads an expression.
- Expr *ReadExpr();
+ Expr *ReadExpr(llvm::BitstreamCursor &Cursor);
/// \brief Reads a sub-statement operand during statement reading.
Stmt *ReadSubStmt() {
@@ -822,16 +1022,15 @@ public:
Expr *ReadSubExpr();
/// \brief Reads the macro record located at the given offset.
- void ReadMacroRecord(uint64_t Offset);
+ void ReadMacroRecord(llvm::BitstreamCursor &Stream, uint64_t Offset);
/// \brief Read the set of macros defined by this external macro source.
virtual void ReadDefinedMacros();
/// \brief Retrieve the macro definition with the given ID.
- MacroDefinition *getMacroDefinition(pch::IdentID ID);
-
- /// \brief Retrieve the AST context that this PCH reader
- /// supplements.
+ MacroDefinition *getMacroDefinition(serialization::IdentID ID);
+
+ /// \brief Retrieve the AST context that this AST reader supplements.
ASTContext *getContext() { return Context; }
// \brief Contains declarations that were loaded before we have
@@ -843,10 +1042,6 @@ public:
/// imported.
Sema *getSema() { return SemaObj; }
- /// \brief Retrieve the stream that this PCH reader is reading from.
- llvm::BitstreamCursor &getStream() { return Stream; }
- llvm::BitstreamCursor &getDeclsCursor() { return DeclsCursor; }
-
/// \brief Retrieve the identifier table associated with the
/// preprocessor.
IdentifierTable &getIdentifierTable();
diff --git a/include/clang/Frontend/PCHWriter.h b/include/clang/Serialization/ASTWriter.h
index 70ad1d7c7e78..426fc4780148 100644
--- a/include/clang/Frontend/PCHWriter.h
+++ b/include/clang/Serialization/ASTWriter.h
@@ -1,4 +1,4 @@
-//===--- PCHWriter.h - Precompiled Headers Writer ---------------*- C++ -*-===//
+//===--- ASTWriter.h - AST File Writer --------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,23 +7,25 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines the PCHWriter class, which writes a precompiled
-// header containing a serialized representation of a translation
-// unit.
+// This file defines the ASTWriter class, which writes an AST file
+// containing a serialized representation of a translation unit.
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_FRONTEND_PCH_WRITER_H
-#define LLVM_CLANG_FRONTEND_PCH_WRITER_H
+#ifndef LLVM_CLANG_FRONTEND_AST_WRITER_H
+#define LLVM_CLANG_FRONTEND_AST_WRITER_H
#include "clang/AST/Decl.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/TemplateBase.h"
-#include "clang/Frontend/PCHBitCodes.h"
-#include "clang/Frontend/PCHDeserializationListener.h"
-#include "llvm/ADT/DenseMap.h"
+#include "clang/Serialization/ASTBitCodes.h"
+#include "clang/Serialization/ASTDeserializationListener.h"
+#include "clang/Sema/SemaConsumer.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/Bitcode/BitstreamWriter.h"
#include <map>
#include <queue>
+#include <vector>
namespace llvm {
class APFloat;
@@ -40,50 +42,32 @@ class CXXBaseOrMemberInitializer;
class LabelStmt;
class MacroDefinition;
class MemorizeStatCalls;
-class PCHReader;
+class ASTReader;
class Preprocessor;
class Sema;
class SourceManager;
class SwitchCase;
class TargetInfo;
-/// A structure for putting "fast"-unqualified QualTypes into a
-/// DenseMap. This uses the standard pointer hash function.
-struct UnsafeQualTypeDenseMapInfo {
- static inline bool isEqual(QualType A, QualType B) { return A == B; }
- static inline QualType getEmptyKey() {
- return QualType::getFromOpaquePtr((void*) 1);
- }
- static inline QualType getTombstoneKey() {
- return QualType::getFromOpaquePtr((void*) 2);
- }
- static inline unsigned getHashValue(QualType T) {
- assert(!T.getLocalFastQualifiers() &&
- "hash invalid for types with fast quals");
- uintptr_t v = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
- return (unsigned(v) >> 4) ^ (unsigned(v) >> 9);
- }
-};
-
-/// \brief Writes a precompiled header containing the contents of a
-/// translation unit.
+/// \brief Writes an AST file containing the contents of a translation unit.
///
-/// The PCHWriter class produces a bitstream containing the serialized
+/// The ASTWriter class produces a bitstream containing the serialized
/// representation of a given abstract syntax tree and its supporting
/// data structures. This bitstream can be de-serialized via an
-/// instance of the PCHReader class.
-class PCHWriter : public PCHDeserializationListener {
+/// instance of the ASTReader class.
+class ASTWriter : public ASTDeserializationListener {
public:
typedef llvm::SmallVector<uint64_t, 64> RecordData;
+ friend class ASTDeclWriter;
private:
/// \brief The bitstream writer used to emit this precompiled header.
llvm::BitstreamWriter &Stream;
- /// \brief The reader of existing PCH files, if we're chaining.
- PCHReader *Chain;
+ /// \brief The reader of existing AST files, if we're chaining.
+ ASTReader *Chain;
- /// \brief Stores a declaration or a type to be written to the PCH file.
+ /// \brief Stores a declaration or a type to be written to the AST file.
class DeclOrType {
public:
DeclOrType(Decl *D) : Stored(D), IsType(false) { }
@@ -106,24 +90,36 @@ private:
void *Stored;
bool IsType;
};
-
+
/// \brief The declarations and types to emit.
std::queue<DeclOrType> DeclTypesToEmit;
-
+
+ /// \brief The first ID number we can use for our own declarations.
+ serialization::DeclID FirstDeclID;
+
+ /// \brief The decl ID that will be assigned to the next new decl.
+ serialization::DeclID NextDeclID;
+
/// \brief Map that provides the ID numbers of each declaration within
- /// the output stream.
+ /// the output stream, as well as those deserialized from a chained PCH.
///
/// The ID numbers of declarations are consecutive (in order of
/// discovery) and start at 2. 1 is reserved for the translation
/// unit, while 0 is reserved for NULL.
- llvm::DenseMap<const Decl *, pch::DeclID> DeclIDs;
+ llvm::DenseMap<const Decl *, serialization::DeclID> DeclIDs;
/// \brief Offset of each declaration in the bitstream, indexed by
/// the declaration's ID.
std::vector<uint32_t> DeclOffsets;
+ /// \brief The first ID number we can use for our own types.
+ serialization::TypeID FirstTypeID;
+
+ /// \brief The type ID that will be assigned to the next new type.
+ serialization::TypeID NextTypeID;
+
/// \brief Map that provides the ID numbers of each type within the
- /// output stream.
+ /// output stream, plus those deserialized from a chained PCH.
///
/// The ID numbers of types are consecutive (in order of discovery)
/// and start at 1. 0 is reserved for NULL. When types are actually
@@ -131,14 +127,17 @@ private:
/// allow for the const/volatile qualifiers.
///
/// Keys in the map never have const/volatile qualifiers.
- llvm::DenseMap<QualType, pch::TypeID, UnsafeQualTypeDenseMapInfo> TypeIDs;
+ serialization::TypeIdxMap TypeIdxs;
/// \brief Offset of each type in the bitstream, indexed by
/// the type's ID.
std::vector<uint32_t> TypeOffsets;
- /// \brief The type ID that will be assigned to the next new type.
- pch::TypeID NextTypeID;
+ /// \brief The first ID number we can use for our own identifiers.
+ serialization::IdentID FirstIdentID;
+
+ /// \brief The identifier ID that will be assigned to the next new identifier.
+ serialization::IdentID NextIdentID;
/// \brief Map that provides the ID numbers of each identifier in
/// the output stream.
@@ -146,22 +145,25 @@ private:
/// The ID numbers for identifiers are consecutive (in order of
/// discovery), starting at 1. An ID of zero refers to a NULL
/// IdentifierInfo.
- llvm::DenseMap<const IdentifierInfo *, pch::IdentID> IdentifierIDs;
+ llvm::DenseMap<const IdentifierInfo *, serialization::IdentID> IdentifierIDs;
/// \brief Offsets of each of the identifier IDs into the identifier
/// table.
std::vector<uint32_t> IdentifierOffsets;
+ /// \brief The first ID number we can use for our own selectors.
+ serialization::SelectorID FirstSelectorID;
+
+ /// \brief The selector ID that will be assigned to the next new identifier.
+ serialization::SelectorID NextSelectorID;
+
/// \brief Map that provides the ID numbers of each Selector.
- llvm::DenseMap<Selector, pch::SelectorID> SelectorIDs;
+ llvm::DenseMap<Selector, serialization::SelectorID> SelectorIDs;
/// \brief Offset of each selector within the method pool/selector
/// table, indexed by the Selector ID (-1).
std::vector<uint32_t> SelectorOffsets;
- /// \brief A vector of all Selectors (ordered by ID).
- std::vector<Selector> SelVector;
-
/// \brief Offsets of each of the macro identifiers into the
/// bitstream.
///
@@ -172,19 +174,25 @@ private:
/// \brief Mapping from macro definitions (as they occur in the preprocessing
/// record) to the index into the macro definitions table.
- llvm::DenseMap<const MacroDefinition *, pch::IdentID> MacroDefinitions;
+ llvm::DenseMap<const MacroDefinition *, serialization::IdentID>
+ MacroDefinitions;
/// \brief Mapping from the macro definition indices in \c MacroDefinitions
/// to the corresponding offsets within the preprocessor block.
std::vector<uint32_t> MacroDefinitionOffsets;
+
+ typedef llvm::DenseMap<Decl *, Decl *> FirstLatestDeclMap;
+ /// \brief Map of first declarations from a chained PCH that point to the
+ /// most recent declarations in another PCH.
+ FirstLatestDeclMap FirstLatestDecls;
/// \brief Declarations encountered that might be external
/// definitions.
///
/// We keep track of external definitions (as well as tentative
- /// definitions) as we are emitting declarations to the PCH
- /// file. The PCH file contains a separate record for these external
- /// definitions, which are provided to the AST consumer by the PCH
+ /// definitions) as we are emitting declarations to the AST
+ /// file. The AST file contains a separate record for these external
+ /// definitions, which are provided to the AST consumer by the AST
/// reader. This is behavior is required to properly cope with,
/// e.g., tentative variable definitions that occur within
/// headers. The declarations themselves are stored as declaration
@@ -192,11 +200,38 @@ private:
/// record.
llvm::SmallVector<uint64_t, 16> ExternalDefinitions;
+ /// \brief Namespaces that have received extensions since their serialized
+ /// form.
+ ///
+ /// Basically, when we're chaining and encountering a namespace, we check if
+ /// its primary namespace comes from the chain. If it does, we add the primary
+ /// to this set, so that we can write out lexical content updates for it.
+ llvm::SmallPtrSet<const NamespaceDecl *, 16> UpdatedNamespaces;
+
+ /// \brief Decls that have been replaced in the current dependent AST file.
+ ///
+ /// When a decl changes fundamentally after being deserialized (this shouldn't
+ /// happen, but the ObjC AST nodes are designed this way), it will be
+ /// serialized again. In this case, it is registered here, so that the reader
+ /// knows to read the updated version.
+ llvm::SmallVector<std::pair<serialization::DeclID, uint64_t>, 16>
+ ReplacedDecls;
+
+ typedef llvm::SmallVector<serialization::DeclID, 4>
+ AdditionalTemplateSpecializationsList;
+ typedef llvm::DenseMap<serialization::DeclID,
+ AdditionalTemplateSpecializationsList>
+ AdditionalTemplateSpecializationsMap;
+
+ /// \brief Additional specializations (including partial) of templates that
+ /// were introduced after the template was serialized.
+ AdditionalTemplateSpecializationsMap AdditionalTemplateSpecializations;
+
/// \brief Statements that we've encountered while serializing a
/// declaration or type.
llvm::SmallVector<Stmt *, 16> StmtsToEmit;
-
- /// \brief Statements collection to use for PCHWriter::AddStmt().
+
+ /// \brief Statements collection to use for ASTWriter::AddStmt().
/// It will point to StmtsToEmit unless it is overriden.
llvm::SmallVector<Stmt *, 16> *CollectedStmts;
@@ -206,17 +241,17 @@ private:
/// \brief Mapping from LabelStmt statements to IDs.
std::map<LabelStmt *, unsigned> LabelIDs;
- /// \brief The number of statements written to the PCH file.
+ /// \brief The number of statements written to the AST file.
unsigned NumStatements;
- /// \brief The number of macros written to the PCH file.
+ /// \brief The number of macros written to the AST file.
unsigned NumMacros;
- /// \brief The number of lexical declcontexts written to the PCH
+ /// \brief The number of lexical declcontexts written to the AST
/// file.
unsigned NumLexicalDeclContexts;
- /// \brief The number of visible declcontexts written to the PCH
+ /// \brief The number of visible declcontexts written to the AST
/// file.
unsigned NumVisibleDeclContexts;
@@ -234,24 +269,31 @@ private:
void WriteType(QualType T);
uint64_t WriteDeclContextLexicalBlock(ASTContext &Context, DeclContext *DC);
uint64_t WriteDeclContextVisibleBlock(ASTContext &Context, DeclContext *DC);
-
- void WriteMethodPool(Sema &SemaRef);
+ void WriteTypeDeclOffsets();
+ void WriteSelectors(Sema &SemaRef);
+ void WriteReferencedSelectorsPool(Sema &SemaRef);
void WriteIdentifierTable(Preprocessor &PP);
- void WriteAttributeRecord(const Attr *Attr);
+ void WriteAttributeRecord(const AttrVec &Attrs);
+ void WriteDeclUpdateBlock();
+ void WriteDeclContextVisibleUpdate(const DeclContext *DC);
+ void WriteAdditionalTemplateSpecializations();
unsigned ParmVarDeclAbbrev;
+ unsigned DeclContextLexicalAbbrev;
+ unsigned DeclContextVisibleLookupAbbrev;
+ unsigned UpdateVisibleAbbrev;
void WriteDeclsBlockAbbrevs();
void WriteDecl(ASTContext &Context, Decl *D);
- void WritePCHCore(Sema &SemaRef, MemorizeStatCalls *StatCalls,
+ void WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls,
const char* isysroot);
- void WritePCHChain(Sema &SemaRef, MemorizeStatCalls *StatCalls,
+ void WriteASTChain(Sema &SemaRef, MemorizeStatCalls *StatCalls,
const char* isysroot);
public:
/// \brief Create a new precompiled header writer that outputs to
/// the given bitstream.
- PCHWriter(llvm::BitstreamWriter &Stream, PCHReader *Chain);
+ ASTWriter(llvm::BitstreamWriter &Stream);
/// \brief Write a precompiled header for the given semantic analysis.
///
@@ -266,7 +308,7 @@ public:
///
/// \param PPRec Record of the preprocessing actions that occurred while
/// preprocessing this file, e.g., macro instantiations
- void WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls,
+ void WriteAST(Sema &SemaRef, MemorizeStatCalls *StatCalls,
const char* isysroot);
/// \brief Emit a source location.
@@ -292,10 +334,12 @@ public:
/// \brief Emit a CXXTemporary.
void AddCXXTemporary(const CXXTemporary *Temp, RecordData &Record);
+
+ /// \brief Get the unique number used to refer to the given selector.
+ serialization::SelectorID getSelectorRef(Selector Sel);
- /// \brief Get the unique number used to refer to the given
- /// identifier.
- pch::IdentID getIdentifierRef(const IdentifierInfo *II);
+ /// \brief Get the unique number used to refer to the given identifier.
+ serialization::IdentID getIdentifierRef(const IdentifierInfo *II);
/// \brief Retrieve the offset of the macro definition for the given
/// identifier.
@@ -309,11 +353,23 @@ public:
/// \brief Retrieve the ID number corresponding to the given macro
/// definition.
- pch::IdentID getMacroDefinitionID(MacroDefinition *MD);
+ serialization::IdentID getMacroDefinitionID(MacroDefinition *MD);
/// \brief Emit a reference to a type.
void AddTypeRef(QualType T, RecordData &Record);
+ /// \brief Force a type to be emitted and get its ID.
+ serialization::TypeID GetOrCreateTypeID(QualType T);
+
+ /// \brief Determine the type ID of an already-emitted type.
+ serialization::TypeID getTypeID(QualType T) const;
+
+ /// \brief Force a type to be emitted and get its index.
+ serialization::TypeIdx GetOrCreateTypeIdx(QualType T);
+
+ /// \brief Determine the type index of an already-emitted type.
+ serialization::TypeIdx getTypeIdx(QualType T) const;
+
/// \brief Emits a reference to a declarator info.
void AddTypeSourceInfo(TypeSourceInfo *TInfo, RecordData &Record);
@@ -329,9 +385,12 @@ public:
/// \brief Emit a reference to a declaration.
void AddDeclRef(const Decl *D, RecordData &Record);
+ /// \brief Force a declaration to be emitted and get its ID.
+ serialization::DeclID GetDeclRef(const Decl *D);
+
/// \brief Determine the declaration ID of an already-emitted
/// declaration.
- pch::DeclID getDeclID(const Decl *D);
+ serialization::DeclID getDeclID(const Decl *D);
/// \brief Emit a declaration name.
void AddDeclarationName(DeclarationName Name, RecordData &Record);
@@ -356,11 +415,28 @@ public:
/// \brief Emit a UnresolvedSet structure.
void AddUnresolvedSet(const UnresolvedSetImpl &Set, RecordData &Record);
- /// brief Emit a C++ base specifier.
+ /// \brief Emit a C++ base specifier.
void AddCXXBaseSpecifier(const CXXBaseSpecifier &Base, RecordData &Record);
+ /// \brief Emit a CXXBaseOrMemberInitializer array.
+ void AddCXXBaseOrMemberInitializers(
+ const CXXBaseOrMemberInitializer * const *BaseOrMembers,
+ unsigned NumBaseOrMembers, RecordData &Record);
+
/// \brief Add a string to the given record.
- void AddString(const std::string &Str, RecordData &Record);
+ void AddString(llvm::StringRef Str, RecordData &Record);
+
+ /// \brief Mark a namespace as needing an update.
+ void AddUpdatedNamespace(const NamespaceDecl *NS) {
+ UpdatedNamespaces.insert(NS);
+ }
+
+ /// \brief Record a template specialization or partial specialization of
+ /// a template from a previous PCH file.
+ void AddAdditionalTemplateSpecialization(serialization::DeclID Templ,
+ serialization::DeclID Spec) {
+ AdditionalTemplateSpecializations[Templ].push_back(Spec);
+ }
/// \brief Note that the identifier II occurs at the given offset
/// within the identifier table.
@@ -398,9 +474,38 @@ public:
unsigned getParmVarDeclAbbrev() const { return ParmVarDeclAbbrev; }
- // PCHDeserializationListener implementation
- void TypeRead(pch::TypeID ID, QualType T);
- void DeclRead(pch::DeclID ID, const Decl *D);
+ bool hasChain() const { return Chain; }
+
+ // ASTDeserializationListener implementation
+ void SetReader(ASTReader *Reader);
+ void IdentifierRead(serialization::IdentID ID, IdentifierInfo *II);
+ void TypeRead(serialization::TypeIdx Idx, QualType T);
+ void DeclRead(serialization::DeclID ID, const Decl *D);
+ void SelectorRead(serialization::SelectorID iD, Selector Sel);
+};
+
+/// \brief AST and semantic-analysis consumer that generates a
+/// precompiled header from the parsed source code.
+class PCHGenerator : public SemaConsumer {
+ const Preprocessor &PP;
+ const char *isysroot;
+ llvm::raw_ostream *Out;
+ Sema *SemaPtr;
+ MemorizeStatCalls *StatCalls; // owned by the FileManager
+ std::vector<unsigned char> Buffer;
+ llvm::BitstreamWriter Stream;
+ ASTWriter Writer;
+
+protected:
+ ASTWriter &getWriter() { return Writer; }
+ const ASTWriter &getWriter() const { return Writer; }
+
+public:
+ PCHGenerator(const Preprocessor &PP, bool Chaining,
+ const char *isysroot, llvm::raw_ostream *Out);
+ virtual void InitializeSema(Sema &S) { SemaPtr = &S; }
+ virtual void HandleTranslationUnit(ASTContext &Ctx);
+ virtual ASTDeserializationListener *GetASTDeserializationListener();
};
} // end namespace clang
diff --git a/include/clang/Serialization/CMakeLists.txt b/include/clang/Serialization/CMakeLists.txt
new file mode 100644
index 000000000000..3712009bf37d
--- /dev/null
+++ b/include/clang/Serialization/CMakeLists.txt
@@ -0,0 +1,12 @@
+set(LLVM_TARGET_DEFINITIONS ../Basic/Attr.td)
+tablegen(AttrPCHRead.inc
+ -gen-clang-attr-pch-read
+ -I ${CMAKE_CURRENT_SOURCE_DIR}/../../)
+add_custom_target(ClangAttrPCHRead
+ DEPENDS AttrPCHRead.inc)
+
+tablegen(AttrPCHWrite.inc
+ -gen-clang-attr-pch-write
+ -I ${CMAKE_CURRENT_SOURCE_DIR}/../../)
+add_custom_target(ClangAttrPCHWrite
+ DEPENDS AttrPCHWrite.inc)
diff --git a/include/clang/Serialization/Makefile b/include/clang/Serialization/Makefile
new file mode 100644
index 000000000000..79486b11bc68
--- /dev/null
+++ b/include/clang/Serialization/Makefile
@@ -0,0 +1,19 @@
+CLANG_LEVEL := ../../..
+TD_SRC_DIR = $(PROJ_SRC_DIR)/../Basic
+BUILT_SOURCES = AttrPCHRead.inc AttrPCHWrite.inc
+
+TABLEGEN_INC_FILES_COMMON = 1
+
+include $(CLANG_LEVEL)/Makefile
+
+$(ObjDir)/AttrPCHRead.inc.tmp : $(TD_SRC_DIR)/Attr.td $(TBLGEN) \
+ $(ObjDir)/.dir
+ $(Echo) "Building Clang PCH reader with tblgen"
+ $(Verb) $(TableGen) -gen-clang-attr-pch-read -o $(call SYSPATH, $@) \
+ -I $(PROJ_SRC_DIR)/../../ $<
+
+$(ObjDir)/AttrPCHWrite.inc.tmp : $(TD_SRC_DIR)/Attr.td $(TBLGEN) \
+ $(ObjDir)/.dir
+ $(Echo) "Building Clang PCH writer with tblgen"
+ $(Verb) $(TableGen) -gen-clang-attr-pch-write -o $(call SYSPATH, $@) \
+ -I $(PROJ_SRC_DIR)/../../ $<