From 3d1dcd9bfdb15c49ee34d576a065079ac5c4d29f Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Fri, 17 Sep 2010 15:54:40 +0000 Subject: Vendor import of clang r114020 (from the release_28 branch): http://llvm.org/svn/llvm-project/cfe/branches/release_28@114020 Approved by: rpaulo (mentor) --- lib/Sema/AnalysisBasedWarnings.cpp | 39 +- lib/Sema/AnalysisBasedWarnings.h | 55 - lib/Sema/AttributeList.cpp | 136 + lib/Sema/CMakeLists.txt | 3 +- lib/Sema/CXXFieldCollector.h | 79 - lib/Sema/CodeCompleteConsumer.cpp | 233 +- lib/Sema/DeclSpec.cpp | 667 +++++ lib/Sema/IdentifierResolver.cpp | 35 +- lib/Sema/IdentifierResolver.h | 203 -- lib/Sema/JumpDiagnostics.cpp | 29 +- lib/Sema/Lookup.h | 654 ----- lib/Sema/Makefile | 1 - lib/Sema/ParseAST.cpp | 125 - lib/Sema/Sema.cpp | 261 +- lib/Sema/Sema.h | 4655 ------------------------------ lib/Sema/SemaAccess.cpp | 218 +- lib/Sema/SemaAttr.cpp | 135 +- lib/Sema/SemaCXXCast.cpp | 183 +- lib/Sema/SemaCXXScopeSpec.cpp | 42 +- lib/Sema/SemaChecking.cpp | 870 +++--- lib/Sema/SemaCodeComplete.cpp | 2077 ++++++++++--- lib/Sema/SemaDecl.cpp | 1400 +++++---- lib/Sema/SemaDeclAttr.cpp | 453 ++- lib/Sema/SemaDeclCXX.cpp | 1068 ++++--- lib/Sema/SemaDeclObjC.cpp | 442 ++- lib/Sema/SemaExceptionSpec.cpp | 10 +- lib/Sema/SemaExpr.cpp | 1704 +++++------ lib/Sema/SemaExprCXX.cpp | 604 ++-- lib/Sema/SemaExprObjC.cpp | 136 +- lib/Sema/SemaInit.cpp | 383 ++- lib/Sema/SemaInit.h | 765 ----- lib/Sema/SemaLookup.cpp | 168 +- lib/Sema/SemaObjCProperty.cpp | 175 +- lib/Sema/SemaOverload.cpp | 1374 +++++---- lib/Sema/SemaOverload.h | 617 ---- lib/Sema/SemaStmt.cpp | 382 ++- lib/Sema/SemaTemplate.cpp | 550 ++-- lib/Sema/SemaTemplate.h | 151 - lib/Sema/SemaTemplateDeduction.cpp | 191 +- lib/Sema/SemaTemplateInstantiate.cpp | 87 +- lib/Sema/SemaTemplateInstantiateDecl.cpp | 397 +-- lib/Sema/SemaType.cpp | 154 +- lib/Sema/TargetAttributesSema.cpp | 17 +- lib/Sema/TargetAttributesSema.h | 2 +- lib/Sema/TreeTransform.h | 2028 +++++++------ 45 files changed, 10189 insertions(+), 13769 deletions(-) delete mode 100644 lib/Sema/AnalysisBasedWarnings.h create mode 100644 lib/Sema/AttributeList.cpp delete mode 100644 lib/Sema/CXXFieldCollector.h create mode 100644 lib/Sema/DeclSpec.cpp delete mode 100644 lib/Sema/IdentifierResolver.h delete mode 100644 lib/Sema/Lookup.h delete mode 100644 lib/Sema/ParseAST.cpp delete mode 100644 lib/Sema/Sema.h delete mode 100644 lib/Sema/SemaInit.h delete mode 100644 lib/Sema/SemaOverload.h delete mode 100644 lib/Sema/SemaTemplate.h (limited to 'lib/Sema') diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp index 448d16116a39..cfebed6a05b2 100644 --- a/lib/Sema/AnalysisBasedWarnings.cpp +++ b/lib/Sema/AnalysisBasedWarnings.cpp @@ -13,9 +13,11 @@ // //===----------------------------------------------------------------------===// -#include "Sema.h" -#include "AnalysisBasedWarnings.h" +#include "clang/Sema/AnalysisBasedWarnings.h" +#include "clang/Sema/SemaInternal.h" #include "clang/Basic/SourceManager.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/StmtObjC.h" @@ -197,6 +199,8 @@ static ControlFlowKind CheckFallThrough(AnalysisContext &AC) { return AlwaysFallThrough; } +namespace { + struct CheckFallThroughDiagnostics { unsigned diag_MaybeFallThrough_HasNoReturn; unsigned diag_MaybeFallThrough_ReturnsNonVoid; @@ -266,6 +270,8 @@ struct CheckFallThroughDiagnostics { } }; +} + /// CheckFallThroughForFunctionDef - Check that we don't fall off the end of a /// function that should return a value. Check that we don't fall off the end /// of a noreturn function. We assume that functions and blocks not marked @@ -375,19 +381,16 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, S.SourceMgr.isInSystemHeader(D->getLocation())) return; - if (const FunctionDecl *FD = dyn_cast(D)) { - // For function templates, class templates and member function templates - // we'll do the analysis at instantiation time. - if (FD->isDependentContext()) - return; - } + // For code in dependent contexts, we'll do this at instantiation time. + if (cast(D)->isDependentContext()) + return; const Stmt *Body = D->getBody(); assert(Body); // Don't generate EH edges for CallExprs as we'd like to avoid the n^2 // explosion for destrutors that can result and the compile time hit. - AnalysisContext AC(D, false); + AnalysisContext AC(D, 0, false); // Warning: check missing 'return' if (P.enableCheckFallThrough) { @@ -401,3 +404,21 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, if (P.enableCheckUnreachable) CheckUnreachable(S, AC); } + +void clang::sema:: +AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, + const BlockExpr *E) { + return IssueWarnings(P, E->getBlockDecl(), E->getType()); +} + +void clang::sema:: +AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, + const ObjCMethodDecl *D) { + return IssueWarnings(P, D, QualType()); +} + +void clang::sema:: +AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, + const FunctionDecl *D) { + return IssueWarnings(P, D, QualType()); +} diff --git a/lib/Sema/AnalysisBasedWarnings.h b/lib/Sema/AnalysisBasedWarnings.h deleted file mode 100644 index dea19ba28ccf..000000000000 --- a/lib/Sema/AnalysisBasedWarnings.h +++ /dev/null @@ -1,55 +0,0 @@ -//=- 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 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 VisitedFD; - -public: - AnalysisBasedWarnings(Sema &s); - - Policy getDefaultPolicy() { return DefaultPolicy; } - - void IssueWarnings(Policy P, const Decl *D, QualType BlockTy = QualType()); -}; - -}} // end namespace clang::sema - -#endif diff --git a/lib/Sema/AttributeList.cpp b/lib/Sema/AttributeList.cpp new file mode 100644 index 000000000000..8ccb2ca586eb --- /dev/null +++ b/lib/Sema/AttributeList.cpp @@ -0,0 +1,136 @@ +//===--- AttributeList.cpp --------------------------------------*- 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 AttributeList class implementation +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/AttributeList.h" +#include "clang/Basic/IdentifierTable.h" +#include "llvm/ADT/StringSwitch.h" +using namespace clang; + +AttributeList::AttributeList(IdentifierInfo *aName, SourceLocation aLoc, + IdentifierInfo *sName, SourceLocation sLoc, + IdentifierInfo *pName, SourceLocation pLoc, + Expr **ExprList, unsigned numArgs, + AttributeList *n, bool declspec, bool cxx0x) + : AttrName(aName), AttrLoc(aLoc), ScopeName(sName), ScopeLoc(sLoc), + ParmName(pName), ParmLoc(pLoc), NumArgs(numArgs), Next(n), + DeclspecAttribute(declspec), CXX0XAttribute(cxx0x), Invalid(false) { + + if (numArgs == 0) + Args = 0; + else { + Args = new Expr*[numArgs]; + memcpy(Args, ExprList, numArgs*sizeof(Args[0])); + } +} + +AttributeList::~AttributeList() { + if (Args) { + // FIXME: before we delete the vector, we need to make sure the Expr's + // have been deleted. Since ActionBase::ExprTy is "void", we are dependent + // on the actions module for actually freeing the memory. The specific + // hooks are ActOnDeclarator, ActOnTypeName, ActOnParamDeclaratorType, + // ParseField, ParseTag. Once these routines have freed the expression, + // they should zero out the Args slot (to indicate the memory has been + // freed). If any element of the vector is non-null, we should assert. + delete [] Args; + } + delete Next; +} + +AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) { + llvm::StringRef AttrName = Name->getName(); + + // Normalize the attribute name, __foo__ becomes foo. + if (AttrName.startswith("__") && AttrName.endswith("__")) + AttrName = AttrName.substr(2, AttrName.size() - 4); + + return llvm::StringSwitch(AttrName) + .Case("weak", AT_weak) + .Case("weakref", AT_weakref) + .Case("pure", AT_pure) + .Case("mode", AT_mode) + .Case("used", AT_used) + .Case("alias", AT_alias) + .Case("align", AT_aligned) + .Case("final", AT_final) + .Case("cdecl", AT_cdecl) + .Case("const", AT_const) + .Case("blocks", AT_blocks) + .Case("format", AT_format) + .Case("hiding", AT_hiding) + .Case("malloc", AT_malloc) + .Case("packed", AT_packed) + .Case("unused", AT_unused) + .Case("aligned", AT_aligned) + .Case("cleanup", AT_cleanup) + .Case("nodebug", AT_nodebug) + .Case("nonnull", AT_nonnull) + .Case("nothrow", AT_nothrow) + .Case("objc_gc", AT_objc_gc) + .Case("regparm", AT_regparm) + .Case("section", AT_section) + .Case("stdcall", AT_stdcall) + .Case("annotate", AT_annotate) + .Case("fastcall", AT_fastcall) + .Case("ibaction", AT_IBAction) + .Case("iboutlet", AT_IBOutlet) + .Case("iboutletcollection", AT_IBOutletCollection) + .Case("noreturn", AT_noreturn) + .Case("noinline", AT_noinline) + .Case("override", AT_override) + .Case("sentinel", AT_sentinel) + .Case("NSObject", AT_nsobject) + .Case("dllimport", AT_dllimport) + .Case("dllexport", AT_dllexport) + .Case("may_alias", IgnoredAttribute) // FIXME: TBAA + .Case("base_check", AT_base_check) + .Case("deprecated", AT_deprecated) + .Case("visibility", AT_visibility) + .Case("destructor", AT_destructor) + .Case("format_arg", AT_format_arg) + .Case("gnu_inline", AT_gnu_inline) + .Case("weak_import", AT_weak_import) + .Case("vecreturn", AT_vecreturn) + .Case("vector_size", AT_vector_size) + .Case("constructor", AT_constructor) + .Case("unavailable", AT_unavailable) + .Case("overloadable", AT_overloadable) + .Case("address_space", AT_address_space) + .Case("always_inline", AT_always_inline) + .Case("returns_twice", IgnoredAttribute) + .Case("vec_type_hint", IgnoredAttribute) + .Case("objc_exception", AT_objc_exception) + .Case("ext_vector_type", AT_ext_vector_type) + .Case("transparent_union", AT_transparent_union) + .Case("analyzer_noreturn", AT_analyzer_noreturn) + .Case("warn_unused_result", AT_warn_unused_result) + .Case("carries_dependency", AT_carries_dependency) + .Case("ns_returns_not_retained", AT_ns_returns_not_retained) + .Case("ns_returns_retained", AT_ns_returns_retained) + .Case("cf_returns_not_retained", AT_cf_returns_not_retained) + .Case("cf_returns_retained", AT_cf_returns_retained) + .Case("ownership_returns", AT_ownership_returns) + .Case("ownership_holds", AT_ownership_holds) + .Case("ownership_takes", AT_ownership_takes) + .Case("reqd_work_group_size", AT_reqd_wg_size) + .Case("init_priority", AT_init_priority) + .Case("no_instrument_function", AT_no_instrument_function) + .Case("thiscall", AT_thiscall) + .Case("pascal", AT_pascal) + .Case("__cdecl", AT_cdecl) + .Case("__stdcall", AT_stdcall) + .Case("__fastcall", AT_fastcall) + .Case("__thiscall", AT_thiscall) + .Case("__pascal", AT_pascal) + .Default(UnknownAttribute); +} diff --git a/lib/Sema/CMakeLists.txt b/lib/Sema/CMakeLists.txt index 70b4792f3ba5..e65bb227f159 100644 --- a/lib/Sema/CMakeLists.txt +++ b/lib/Sema/CMakeLists.txt @@ -2,10 +2,11 @@ set(LLVM_NO_RTTI 1) add_clang_library(clangSema AnalysisBasedWarnings.cpp + AttributeList.cpp CodeCompleteConsumer.cpp + DeclSpec.cpp IdentifierResolver.cpp JumpDiagnostics.cpp - ParseAST.cpp Sema.cpp SemaAccess.cpp SemaAttr.cpp diff --git a/lib/Sema/CXXFieldCollector.h b/lib/Sema/CXXFieldCollector.h deleted file mode 100644 index 63c6ee3f74ba..000000000000 --- a/lib/Sema/CXXFieldCollector.h +++ /dev/null @@ -1,79 +0,0 @@ -//===- 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 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 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/lib/Sema/CodeCompleteConsumer.cpp b/lib/Sema/CodeCompleteConsumer.cpp index 6cefc61f6640..58a1627b478a 100644 --- a/lib/Sema/CodeCompleteConsumer.cpp +++ b/lib/Sema/CodeCompleteConsumer.cpp @@ -11,11 +11,13 @@ // //===----------------------------------------------------------------------===// #include "clang/Sema/CodeCompleteConsumer.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/Sema.h" #include "clang/AST/DeclCXX.h" -#include "clang/Parse/Scope.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" #include "clang/Lex/Preprocessor.h" #include "clang-c/Index.h" -#include "Sema.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/raw_ostream.h" #include @@ -234,8 +236,7 @@ std::string CodeCompletionString::getAsString() const { default: OS << C->Text; break; } } - OS.flush(); - return Result; + return OS.str(); } const char *CodeCompletionString::getTypedText() const { @@ -246,8 +247,10 @@ const char *CodeCompletionString::getTypedText() const { return 0; } -CodeCompletionString *CodeCompletionString::Clone() const { - CodeCompletionString *Result = new CodeCompletionString; +CodeCompletionString * +CodeCompletionString::Clone(CodeCompletionString *Result) const { + if (!Result) + Result = new CodeCompletionString; for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) Result->AddChunk(C->Clone()); return Result; @@ -373,19 +376,19 @@ bool CodeCompletionString::Deserialize(const char *&Str, const char *StrEnd) { return true; } -void CodeCompleteConsumer::Result::Destroy() { +void CodeCompletionResult::Destroy() { if (Kind == RK_Pattern) { delete Pattern; Pattern = 0; } } -unsigned CodeCompleteConsumer::Result::getPriorityFromDecl(NamedDecl *ND) { +unsigned CodeCompletionResult::getPriorityFromDecl(NamedDecl *ND) { if (!ND) return CCP_Unlikely; // Context-based decisions. - DeclContext *DC = ND->getDeclContext()->getLookupContext(); + DeclContext *DC = ND->getDeclContext()->getRedeclContext(); if (DC->isFunctionOrMethod() || isa(DC)) return CCP_LocalDeclaration; if (DC->isRecord() || isa(DC)) @@ -437,13 +440,16 @@ CodeCompleteConsumer::~CodeCompleteConsumer() { } void PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef, - Result *Results, + CodeCompletionContext Context, + CodeCompletionResult *Results, unsigned NumResults) { + std::stable_sort(Results, Results + NumResults); + // Print the results. for (unsigned I = 0; I != NumResults; ++I) { OS << "COMPLETION: "; switch (Results[I].Kind) { - case Result::RK_Declaration: + case CodeCompletionResult::RK_Declaration: OS << Results[I].Declaration; if (Results[I].Hidden) OS << " (Hidden)"; @@ -456,11 +462,11 @@ PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef, OS << '\n'; break; - case Result::RK_Keyword: + case CodeCompletionResult::RK_Keyword: OS << Results[I].Keyword << '\n'; break; - case Result::RK_Macro: { + case CodeCompletionResult::RK_Macro: { OS << Results[I].Macro->getName(); if (CodeCompletionString *CCS = Results[I].CreateCodeCompletionString(SemaRef)) { @@ -471,7 +477,7 @@ PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef, break; } - case Result::RK_Pattern: { + case CodeCompletionResult::RK_Pattern: { OS << "Pattern : " << Results[I].Pattern->getAsString() << '\n'; break; @@ -494,116 +500,104 @@ PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef, } } +void CodeCompletionResult::computeCursorKindAndAvailability() { + switch (Kind) { + case RK_Declaration: + // Set the availability based on attributes. + Availability = CXAvailability_Available; + if (Declaration->getAttr()) + Availability = CXAvailability_NotAvailable; + else if (Declaration->getAttr()) + Availability = CXAvailability_Deprecated; + + if (FunctionDecl *Function = dyn_cast(Declaration)) + if (Function->isDeleted()) + Availability = CXAvailability_NotAvailable; + + CursorKind = getCursorKindForDecl(Declaration); + if (CursorKind == CXCursor_UnexposedDecl) + CursorKind = CXCursor_NotImplemented; + break; + + case RK_Macro: + Availability = CXAvailability_Available; + CursorKind = CXCursor_MacroDefinition; + break; + + case RK_Keyword: + Availability = CXAvailability_Available; + CursorKind = CXCursor_NotImplemented; + break; + + case RK_Pattern: + // Do nothing: Patterns can come with cursor kinds! + break; + } +} + +/// \brief Retrieve the name that should be used to order a result. +/// +/// If the name needs to be constructed as a string, that string will be +/// saved into Saved and the returned StringRef will refer to it. +static llvm::StringRef getOrderedName(const CodeCompletionResult &R, + std::string &Saved) { + switch (R.Kind) { + case CodeCompletionResult::RK_Keyword: + return R.Keyword; + + case CodeCompletionResult::RK_Pattern: + return R.Pattern->getTypedText(); + + case CodeCompletionResult::RK_Macro: + return R.Macro->getName(); + + case CodeCompletionResult::RK_Declaration: + // Handle declarations below. + break; + } + + DeclarationName Name = R.Declaration->getDeclName(); + + // If the name is a simple identifier (by far the common case), or a + // zero-argument selector, just return a reference to that identifier. + if (IdentifierInfo *Id = Name.getAsIdentifierInfo()) + return Id->getName(); + if (Name.isObjCZeroArgSelector()) + if (IdentifierInfo *Id + = Name.getObjCSelector().getIdentifierInfoForSlot(0)) + return Id->getName(); + + Saved = Name.getAsString(); + return Saved; +} + +bool clang::operator<(const CodeCompletionResult &X, + const CodeCompletionResult &Y) { + std::string XSaved, YSaved; + llvm::StringRef XStr = getOrderedName(X, XSaved); + llvm::StringRef YStr = getOrderedName(Y, YSaved); + int cmp = XStr.compare_lower(YStr); + if (cmp) + return cmp < 0; + + // If case-insensitive comparison fails, try case-sensitive comparison. + cmp = XStr.compare(YStr); + if (cmp) + return cmp < 0; + + return false; +} + void CIndexCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef, - Result *Results, + CodeCompletionContext Context, + CodeCompletionResult *Results, unsigned NumResults) { // Print the results. for (unsigned I = 0; I != NumResults; ++I) { - CXCursorKind Kind = CXCursor_NotImplemented; - - switch (Results[I].Kind) { - case Result::RK_Declaration: - switch (Results[I].Declaration->getKind()) { - case Decl::Record: - case Decl::CXXRecord: - case Decl::ClassTemplateSpecialization: { - RecordDecl *Record = cast(Results[I].Declaration); - if (Record->isStruct()) - Kind = CXCursor_StructDecl; - else if (Record->isUnion()) - Kind = CXCursor_UnionDecl; - else - Kind = CXCursor_ClassDecl; - break; - } - - case Decl::ObjCMethod: { - ObjCMethodDecl *Method = cast(Results[I].Declaration); - if (Method->isInstanceMethod()) - Kind = CXCursor_ObjCInstanceMethodDecl; - else - Kind = CXCursor_ObjCClassMethodDecl; - break; - } - - case Decl::Typedef: - Kind = CXCursor_TypedefDecl; - break; - - case Decl::Enum: - Kind = CXCursor_EnumDecl; - break; - - case Decl::Field: - Kind = CXCursor_FieldDecl; - break; - - case Decl::EnumConstant: - Kind = CXCursor_EnumConstantDecl; - break; - - case Decl::Function: - case Decl::CXXMethod: - case Decl::CXXConstructor: - case Decl::CXXDestructor: - case Decl::CXXConversion: - Kind = CXCursor_FunctionDecl; - break; - - case Decl::Var: - Kind = CXCursor_VarDecl; - break; - - case Decl::ParmVar: - Kind = CXCursor_ParmDecl; - break; - - case Decl::ObjCInterface: - Kind = CXCursor_ObjCInterfaceDecl; - break; - - case Decl::ObjCCategory: - Kind = CXCursor_ObjCCategoryDecl; - break; - - case Decl::ObjCProtocol: - Kind = CXCursor_ObjCProtocolDecl; - break; - - case Decl::ObjCProperty: - Kind = CXCursor_ObjCPropertyDecl; - break; - - case Decl::ObjCIvar: - Kind = CXCursor_ObjCIvarDecl; - break; - - case Decl::ObjCImplementation: - Kind = CXCursor_ObjCImplementationDecl; - break; - - case Decl::ObjCCategoryImpl: - Kind = CXCursor_ObjCCategoryImplDecl; - break; - - default: - break; - } - break; - - case Result::RK_Macro: - Kind = CXCursor_MacroDefinition; - break; - - case Result::RK_Keyword: - case Result::RK_Pattern: - Kind = CXCursor_NotImplemented; - break; - } - - WriteUnsigned(OS, Kind); + WriteUnsigned(OS, Results[I].CursorKind); WriteUnsigned(OS, Results[I].Priority); + WriteUnsigned(OS, Results[I].Availability); CodeCompletionString *CCS = Results[I].CreateCodeCompletionString(SemaRef); assert(CCS && "No code-completion string?"); CCS->Serialize(OS); @@ -618,7 +612,8 @@ CIndexCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef, unsigned NumCandidates) { for (unsigned I = 0; I != NumCandidates; ++I) { WriteUnsigned(OS, CXCursor_NotImplemented); - WriteUnsigned(OS, /*Priority=*/0); + WriteUnsigned(OS, /*Priority=*/I); + WriteUnsigned(OS, /*Availability=*/CXAvailability_Available); CodeCompletionString *CCS = Candidates[I].CreateSignatureString(CurrentArg, SemaRef); assert(CCS && "No code-completion string?"); diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp new file mode 100644 index 000000000000..b46e8af9db86 --- /dev/null +++ b/lib/Sema/DeclSpec.cpp @@ -0,0 +1,667 @@ +//===--- SemaDeclSpec.cpp - Declaration Specifier 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 implements semantic analysis for declaration specifiers. +// +//===----------------------------------------------------------------------===// + +#include "clang/Parse/ParseDiagnostic.h" // FIXME: remove this back-dependency! +#include "clang/Sema/DeclSpec.h" +#include "clang/Sema/ParsedTemplate.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Basic/LangOptions.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/ErrorHandling.h" +#include +using namespace clang; + + +static DiagnosticBuilder Diag(Diagnostic &D, SourceLocation Loc, + SourceManager &SrcMgr, unsigned DiagID) { + return D.Report(FullSourceLoc(Loc, SrcMgr), DiagID); +} + + +void UnqualifiedId::setTemplateId(TemplateIdAnnotation *TemplateId) { + assert(TemplateId && "NULL template-id annotation?"); + Kind = IK_TemplateId; + this->TemplateId = TemplateId; + StartLocation = TemplateId->TemplateNameLoc; + EndLocation = TemplateId->RAngleLoc; +} + +void UnqualifiedId::setConstructorTemplateId(TemplateIdAnnotation *TemplateId) { + assert(TemplateId && "NULL template-id annotation?"); + Kind = IK_ConstructorTemplateId; + this->TemplateId = TemplateId; + StartLocation = TemplateId->TemplateNameLoc; + EndLocation = TemplateId->RAngleLoc; +} + +/// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function. +/// "TheDeclarator" is the declarator that this will be added to. +DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic, + SourceLocation EllipsisLoc, + ParamInfo *ArgInfo, + unsigned NumArgs, + unsigned TypeQuals, + bool hasExceptionSpec, + SourceLocation ThrowLoc, + bool hasAnyExceptionSpec, + ParsedType *Exceptions, + SourceRange *ExceptionRanges, + unsigned NumExceptions, + SourceLocation LPLoc, + SourceLocation RPLoc, + Declarator &TheDeclarator) { + DeclaratorChunk I; + I.Kind = Function; + I.Loc = LPLoc; + I.EndLoc = RPLoc; + I.Fun.hasPrototype = hasProto; + I.Fun.isVariadic = isVariadic; + I.Fun.EllipsisLoc = EllipsisLoc.getRawEncoding(); + I.Fun.DeleteArgInfo = false; + I.Fun.TypeQuals = TypeQuals; + I.Fun.NumArgs = NumArgs; + I.Fun.ArgInfo = 0; + I.Fun.hasExceptionSpec = hasExceptionSpec; + I.Fun.ThrowLoc = ThrowLoc.getRawEncoding(); + I.Fun.hasAnyExceptionSpec = hasAnyExceptionSpec; + I.Fun.NumExceptions = NumExceptions; + I.Fun.Exceptions = 0; + + // new[] an argument array if needed. + if (NumArgs) { + // If the 'InlineParams' in Declarator is unused and big enough, put our + // parameter list there (in an effort to avoid new/delete traffic). If it + // is already used (consider a function returning a function pointer) or too + // small (function taking too many arguments), go to the heap. + if (!TheDeclarator.InlineParamsUsed && + NumArgs <= llvm::array_lengthof(TheDeclarator.InlineParams)) { + I.Fun.ArgInfo = TheDeclarator.InlineParams; + I.Fun.DeleteArgInfo = false; + TheDeclarator.InlineParamsUsed = true; + } else { + I.Fun.ArgInfo = new DeclaratorChunk::ParamInfo[NumArgs]; + I.Fun.DeleteArgInfo = true; + } + memcpy(I.Fun.ArgInfo, ArgInfo, sizeof(ArgInfo[0])*NumArgs); + } + // new[] an exception array if needed + if (NumExceptions) { + I.Fun.Exceptions = new DeclaratorChunk::TypeAndRange[NumExceptions]; + for (unsigned i = 0; i != NumExceptions; ++i) { + I.Fun.Exceptions[i].Ty = Exceptions[i]; + I.Fun.Exceptions[i].Range = ExceptionRanges[i]; + } + } + return I; +} + +/// getParsedSpecifiers - Return a bitmask of which flavors of specifiers this +/// declaration specifier includes. +/// +unsigned DeclSpec::getParsedSpecifiers() const { + unsigned Res = 0; + if (StorageClassSpec != SCS_unspecified || + SCS_thread_specified) + Res |= PQ_StorageClassSpecifier; + + if (TypeQualifiers != TQ_unspecified) + Res |= PQ_TypeQualifier; + + if (hasTypeSpecifier()) + Res |= PQ_TypeSpecifier; + + if (FS_inline_specified || FS_virtual_specified || FS_explicit_specified) + Res |= PQ_FunctionSpecifier; + return Res; +} + +template static bool BadSpecifier(T TNew, T TPrev, + const char *&PrevSpec, + unsigned &DiagID) { + PrevSpec = DeclSpec::getSpecifierName(TPrev); + DiagID = (TNew == TPrev ? diag::ext_duplicate_declspec + : diag::err_invalid_decl_spec_combination); + return true; +} + +const char *DeclSpec::getSpecifierName(DeclSpec::SCS S) { + switch (S) { + case DeclSpec::SCS_unspecified: return "unspecified"; + case DeclSpec::SCS_typedef: return "typedef"; + case DeclSpec::SCS_extern: return "extern"; + case DeclSpec::SCS_static: return "static"; + case DeclSpec::SCS_auto: return "auto"; + case DeclSpec::SCS_register: return "register"; + case DeclSpec::SCS_private_extern: return "__private_extern__"; + case DeclSpec::SCS_mutable: return "mutable"; + } + llvm_unreachable("Unknown typespec!"); +} + +const char *DeclSpec::getSpecifierName(TSW W) { + switch (W) { + case TSW_unspecified: return "unspecified"; + case TSW_short: return "short"; + case TSW_long: return "long"; + case TSW_longlong: return "long long"; + } + llvm_unreachable("Unknown typespec!"); +} + +const char *DeclSpec::getSpecifierName(TSC C) { + switch (C) { + case TSC_unspecified: return "unspecified"; + case TSC_imaginary: return "imaginary"; + case TSC_complex: return "complex"; + } + llvm_unreachable("Unknown typespec!"); +} + + +const char *DeclSpec::getSpecifierName(TSS S) { + switch (S) { + case TSS_unspecified: return "unspecified"; + case TSS_signed: return "signed"; + case TSS_unsigned: return "unsigned"; + } + llvm_unreachable("Unknown typespec!"); +} + +const char *DeclSpec::getSpecifierName(DeclSpec::TST T) { + switch (T) { + case DeclSpec::TST_unspecified: return "unspecified"; + case DeclSpec::TST_void: return "void"; + case DeclSpec::TST_char: return "char"; + case DeclSpec::TST_wchar: return "wchar_t"; + case DeclSpec::TST_char16: return "char16_t"; + case DeclSpec::TST_char32: return "char32_t"; + case DeclSpec::TST_int: return "int"; + case DeclSpec::TST_float: return "float"; + case DeclSpec::TST_double: return "double"; + case DeclSpec::TST_bool: return "_Bool"; + case DeclSpec::TST_decimal32: return "_Decimal32"; + case DeclSpec::TST_decimal64: return "_Decimal64"; + case DeclSpec::TST_decimal128: return "_Decimal128"; + case DeclSpec::TST_enum: return "enum"; + case DeclSpec::TST_class: return "class"; + case DeclSpec::TST_union: return "union"; + case DeclSpec::TST_struct: return "struct"; + case DeclSpec::TST_typename: return "type-name"; + case DeclSpec::TST_typeofType: + case DeclSpec::TST_typeofExpr: return "typeof"; + case DeclSpec::TST_auto: return "auto"; + case DeclSpec::TST_decltype: return "(decltype)"; + case DeclSpec::TST_error: return "(error)"; + } + llvm_unreachable("Unknown typespec!"); +} + +const char *DeclSpec::getSpecifierName(TQ T) { + switch (T) { + case DeclSpec::TQ_unspecified: return "unspecified"; + case DeclSpec::TQ_const: return "const"; + case DeclSpec::TQ_restrict: return "restrict"; + case DeclSpec::TQ_volatile: return "volatile"; + } + llvm_unreachable("Unknown typespec!"); +} + +bool DeclSpec::SetStorageClassSpec(SCS S, SourceLocation Loc, + const char *&PrevSpec, + unsigned &DiagID) { + if (StorageClassSpec != SCS_unspecified) { + // Changing storage class is allowed only if the previous one + // was the 'extern' that is part of a linkage specification and + // the new storage class is 'typedef'. + if (!(SCS_extern_in_linkage_spec && + StorageClassSpec == SCS_extern && + S == SCS_typedef)) + return BadSpecifier(S, (SCS)StorageClassSpec, PrevSpec, DiagID); + } + StorageClassSpec = S; + StorageClassSpecLoc = Loc; + assert((unsigned)S == StorageClassSpec && "SCS constants overflow bitfield"); + return false; +} + +bool DeclSpec::SetStorageClassSpecThread(SourceLocation Loc, + const char *&PrevSpec, + unsigned &DiagID) { + if (SCS_thread_specified) { + PrevSpec = "__thread"; + DiagID = diag::ext_duplicate_declspec; + return true; + } + SCS_thread_specified = true; + SCS_threadLoc = Loc; + return false; +} + +/// These methods set the specified attribute of the DeclSpec, but return true +/// and ignore the request if invalid (e.g. "extern" then "auto" is +/// specified). +bool DeclSpec::SetTypeSpecWidth(TSW W, SourceLocation Loc, + const char *&PrevSpec, + unsigned &DiagID) { + if (TypeSpecWidth != TSW_unspecified && + // Allow turning long -> long long. + (W != TSW_longlong || TypeSpecWidth != TSW_long)) + return BadSpecifier(W, (TSW)TypeSpecWidth, PrevSpec, DiagID); + TypeSpecWidth = W; + TSWLoc = Loc; + if (TypeAltiVecVector && !TypeAltiVecBool && + ((TypeSpecWidth == TSW_long) || (TypeSpecWidth == TSW_longlong))) { + PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType); + DiagID = diag::warn_vector_long_decl_spec_combination; + return true; + } + return false; +} + +bool DeclSpec::SetTypeSpecComplex(TSC C, SourceLocation Loc, + const char *&PrevSpec, + unsigned &DiagID) { + if (TypeSpecComplex != TSC_unspecified) + return BadSpecifier(C, (TSC)TypeSpecComplex, PrevSpec, DiagID); + TypeSpecComplex = C; + TSCLoc = Loc; + return false; +} + +bool DeclSpec::SetTypeSpecSign(TSS S, SourceLocation Loc, + const char *&PrevSpec, + unsigned &DiagID) { + if (TypeSpecSign != TSS_unspecified) + return BadSpecifier(S, (TSS)TypeSpecSign, PrevSpec, DiagID); + TypeSpecSign = S; + TSSLoc = Loc; + return false; +} + +bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc, + const char *&PrevSpec, + unsigned &DiagID, + ParsedType Rep) { + assert(isTypeRep(T) && "T does not store a type"); + assert(Rep && "no type provided!"); + if (TypeSpecType != TST_unspecified) { + PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType); + DiagID = diag::err_invalid_decl_spec_combination; + return true; + } + TypeSpecType = T; + TypeRep = Rep; + TSTLoc = Loc; + TypeSpecOwned = false; + return false; +} + +bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc, + const char *&PrevSpec, + unsigned &DiagID, + Expr *Rep) { + assert(isExprRep(T) && "T does not store an expr"); + assert(Rep && "no expression provided!"); + if (TypeSpecType != TST_unspecified) { + PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType); + DiagID = diag::err_invalid_decl_spec_combination; + return true; + } + TypeSpecType = T; + ExprRep = Rep; + TSTLoc = Loc; + TypeSpecOwned = false; + return false; +} + +bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc, + const char *&PrevSpec, + unsigned &DiagID, + Decl *Rep, bool Owned) { + assert(isDeclRep(T) && "T does not store a decl"); + // Unlike the other cases, we don't assert that we actually get a decl. + + if (TypeSpecType != TST_unspecified) { + PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType); + DiagID = diag::err_invalid_decl_spec_combination; + return true; + } + TypeSpecType = T; + DeclRep = Rep; + TSTLoc = Loc; + TypeSpecOwned = Owned; + return false; +} + +bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc, + const char *&PrevSpec, + unsigned &DiagID) { + assert(!isDeclRep(T) && !isTypeRep(T) && !isExprRep(T) && + "rep required for these type-spec kinds!"); + if (TypeSpecType != TST_unspecified) { + PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType); + DiagID = diag::err_invalid_decl_spec_combination; + return true; + } + if (TypeAltiVecVector && (T == TST_bool) && !TypeAltiVecBool) { + TypeAltiVecBool = true; + TSTLoc = Loc; + return false; + } + TypeSpecType = T; + TSTLoc = Loc; + TypeSpecOwned = false; + if (TypeAltiVecVector && !TypeAltiVecBool && (TypeSpecType == TST_double)) { + PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType); + DiagID = diag::err_invalid_vector_decl_spec; + return true; + } + return false; +} + +bool DeclSpec::SetTypeAltiVecVector(bool isAltiVecVector, SourceLocation Loc, + const char *&PrevSpec, unsigned &DiagID) { + if (TypeSpecType != TST_unspecified) { + PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType); + DiagID = diag::err_invalid_vector_decl_spec_combination; + return true; + } + TypeAltiVecVector = isAltiVecVector; + AltiVecLoc = Loc; + return false; +} + +bool DeclSpec::SetTypeAltiVecPixel(bool isAltiVecPixel, SourceLocation Loc, + const char *&PrevSpec, unsigned &DiagID) { + if (!TypeAltiVecVector || TypeAltiVecPixel || + (TypeSpecType != TST_unspecified)) { + PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType); + DiagID = diag::err_invalid_pixel_decl_spec_combination; + return true; + } + TypeAltiVecPixel = isAltiVecPixel; + TSTLoc = Loc; + return false; +} + +bool DeclSpec::SetTypeSpecError() { + TypeSpecType = TST_error; + TypeSpecOwned = false; + TSTLoc = SourceLocation(); + return false; +} + +bool DeclSpec::SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID, const LangOptions &Lang) { + // Duplicates turn into warnings pre-C99. + if ((TypeQualifiers & T) && !Lang.C99) + return BadSpecifier(T, T, PrevSpec, DiagID); + TypeQualifiers |= T; + + switch (T) { + default: assert(0 && "Unknown type qualifier!"); + case TQ_const: TQ_constLoc = Loc; break; + case TQ_restrict: TQ_restrictLoc = Loc; break; + case TQ_volatile: TQ_volatileLoc = Loc; break; + } + return false; +} + +bool DeclSpec::SetFunctionSpecInline(SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID) { + // 'inline inline' is ok. + FS_inline_specified = true; + FS_inlineLoc = Loc; + return false; +} + +bool DeclSpec::SetFunctionSpecVirtual(SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID) { + // 'virtual virtual' is ok. + FS_virtual_specified = true; + FS_virtualLoc = Loc; + return false; +} + +bool DeclSpec::SetFunctionSpecExplicit(SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID) { + // 'explicit explicit' is ok. + FS_explicit_specified = true; + FS_explicitLoc = Loc; + return false; +} + +bool DeclSpec::SetFriendSpec(SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID) { + if (Friend_specified) { + PrevSpec = "friend"; + DiagID = diag::ext_duplicate_declspec; + return true; + } + + Friend_specified = true; + FriendLoc = Loc; + return false; +} + +bool DeclSpec::SetConstexprSpec(SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID) { + // 'constexpr constexpr' is ok. + Constexpr_specified = true; + ConstexprLoc = Loc; + return false; +} + +void DeclSpec::setProtocolQualifiers(Decl * const *Protos, + unsigned NP, + SourceLocation *ProtoLocs, + SourceLocation LAngleLoc) { + if (NP == 0) return; + ProtocolQualifiers = new Decl*[NP]; + ProtocolLocs = new SourceLocation[NP]; + memcpy((void*)ProtocolQualifiers, Protos, sizeof(Decl*)*NP); + memcpy(ProtocolLocs, ProtoLocs, sizeof(SourceLocation)*NP); + NumProtocolQualifiers = NP; + ProtocolLAngleLoc = LAngleLoc; +} + +void DeclSpec::SaveWrittenBuiltinSpecs() { + writtenBS.Sign = getTypeSpecSign(); + writtenBS.Width = getTypeSpecWidth(); + writtenBS.Type = getTypeSpecType(); + // Search the list of attributes for the presence of a mode attribute. + writtenBS.ModeAttr = false; + AttributeList* attrs = getAttributes(); + while (attrs) { + if (attrs->getKind() == AttributeList::AT_mode) { + writtenBS.ModeAttr = true; + break; + } + attrs = attrs->getNext(); + } +} + +void DeclSpec::SaveStorageSpecifierAsWritten() { + if (SCS_extern_in_linkage_spec && StorageClassSpec == SCS_extern) + // If 'extern' is part of a linkage specification, + // then it is not a storage class "as written". + StorageClassSpecAsWritten = SCS_unspecified; + else + StorageClassSpecAsWritten = StorageClassSpec; +} + +/// Finish - This does final analysis of the declspec, rejecting things like +/// "_Imaginary" (lacking an FP type). This returns a diagnostic to issue or +/// diag::NUM_DIAGNOSTICS if there is no error. After calling this method, +/// DeclSpec is guaranteed self-consistent, even if an error occurred. +void DeclSpec::Finish(Diagnostic &D, Preprocessor &PP) { + // Before possibly changing their values, save specs as written. + SaveWrittenBuiltinSpecs(); + SaveStorageSpecifierAsWritten(); + + // Check the type specifier components first. + SourceManager &SrcMgr = PP.getSourceManager(); + + // Validate and finalize AltiVec vector declspec. + if (TypeAltiVecVector) { + if (TypeAltiVecBool) { + // Sign specifiers are not allowed with vector bool. (PIM 2.1) + if (TypeSpecSign != TSS_unspecified) { + Diag(D, TSSLoc, SrcMgr, diag::err_invalid_vector_bool_decl_spec) + << getSpecifierName((TSS)TypeSpecSign); + } + + // Only char/int are valid with vector bool. (PIM 2.1) + if (((TypeSpecType != TST_unspecified) && (TypeSpecType != TST_char) && + (TypeSpecType != TST_int)) || TypeAltiVecPixel) { + Diag(D, TSTLoc, SrcMgr, diag::err_invalid_vector_bool_decl_spec) + << (TypeAltiVecPixel ? "__pixel" : + getSpecifierName((TST)TypeSpecType)); + } + + // Only 'short' is valid with vector bool. (PIM 2.1) + if ((TypeSpecWidth != TSW_unspecified) && (TypeSpecWidth != TSW_short)) + Diag(D, TSWLoc, SrcMgr, diag::err_invalid_vector_bool_decl_spec) + << getSpecifierName((TSW)TypeSpecWidth); + + // Elements of vector bool are interpreted as unsigned. (PIM 2.1) + if ((TypeSpecType == TST_char) || (TypeSpecType == TST_int) || + (TypeSpecWidth != TSW_unspecified)) + TypeSpecSign = TSS_unsigned; + } + + if (TypeAltiVecPixel) { + //TODO: perform validation + TypeSpecType = TST_int; + TypeSpecSign = TSS_unsigned; + TypeSpecWidth = TSW_short; + TypeSpecOwned = false; + } + } + + // signed/unsigned are only valid with int/char/wchar_t. + if (TypeSpecSign != TSS_unspecified) { + if (TypeSpecType == TST_unspecified) + TypeSpecType = TST_int; // unsigned -> unsigned int, signed -> signed int. + else if (TypeSpecType != TST_int && + TypeSpecType != TST_char && TypeSpecType != TST_wchar) { + Diag(D, TSSLoc, SrcMgr, diag::err_invalid_sign_spec) + << getSpecifierName((TST)TypeSpecType); + // signed double -> double. + TypeSpecSign = TSS_unspecified; + } + } + + // Validate the width of the type. + switch (TypeSpecWidth) { + case TSW_unspecified: break; + case TSW_short: // short int + case TSW_longlong: // long long int + if (TypeSpecType == TST_unspecified) + TypeSpecType = TST_int; // short -> short int, long long -> long long int. + else if (TypeSpecType != TST_int) { + Diag(D, TSWLoc, SrcMgr, + TypeSpecWidth == TSW_short ? diag::err_invalid_short_spec + : diag::err_invalid_longlong_spec) + << getSpecifierName((TST)TypeSpecType); + TypeSpecType = TST_int; + TypeSpecOwned = false; + } + break; + case TSW_long: // long double, long int + if (TypeSpecType == TST_unspecified) + TypeSpecType = TST_int; // long -> long int. + else if (TypeSpecType != TST_int && TypeSpecType != TST_double) { + Diag(D, TSWLoc, SrcMgr, diag::err_invalid_long_spec) + << getSpecifierName((TST)TypeSpecType); + TypeSpecType = TST_int; + TypeSpecOwned = false; + } + break; + } + + // TODO: if the implementation does not implement _Complex or _Imaginary, + // disallow their use. Need information about the backend. + if (TypeSpecComplex != TSC_unspecified) { + if (TypeSpecType == TST_unspecified) { + Diag(D, TSCLoc, SrcMgr, diag::ext_plain_complex) + << FixItHint::CreateInsertion( + PP.getLocForEndOfToken(getTypeSpecComplexLoc()), + " double"); + TypeSpecType = TST_double; // _Complex -> _Complex double. + } else if (TypeSpecType == TST_int || TypeSpecType == TST_char) { + // Note that this intentionally doesn't include _Complex _Bool. + Diag(D, TSTLoc, SrcMgr, diag::ext_integer_complex); + } else if (TypeSpecType != TST_float && TypeSpecType != TST_double) { + Diag(D, TSCLoc, SrcMgr, diag::err_invalid_complex_spec) + << getSpecifierName((TST)TypeSpecType); + TypeSpecComplex = TSC_unspecified; + } + } + + // C++ [class.friend]p6: + // No storage-class-specifier shall appear in the decl-specifier-seq + // of a friend declaration. + if (isFriendSpecified() && getStorageClassSpec()) { + DeclSpec::SCS SC = getStorageClassSpec(); + const char *SpecName = getSpecifierName(SC); + + SourceLocation SCLoc = getStorageClassSpecLoc(); + SourceLocation SCEndLoc = SCLoc.getFileLocWithOffset(strlen(SpecName)); + + Diag(D, SCLoc, SrcMgr, diag::err_friend_storage_spec) + << SpecName + << FixItHint::CreateRemoval(SourceRange(SCLoc, SCEndLoc)); + + ClearStorageClassSpecs(); + } + + assert(!TypeSpecOwned || isDeclRep((TST) TypeSpecType)); + + // Okay, now we can infer the real type. + + // TODO: return "auto function" and other bad things based on the real type. + + // 'data definition has no type or storage class'? +} + +bool DeclSpec::isMissingDeclaratorOk() { + TST tst = getTypeSpecType(); + return isDeclRep(tst) && getRepAsDecl() != 0 && + StorageClassSpec != DeclSpec::SCS_typedef; +} + +void UnqualifiedId::clear() { + if (Kind == IK_TemplateId) + TemplateId->Destroy(); + + Kind = IK_Identifier; + Identifier = 0; + StartLocation = SourceLocation(); + EndLocation = SourceLocation(); +} + +void UnqualifiedId::setOperatorFunctionId(SourceLocation OperatorLoc, + OverloadedOperatorKind Op, + SourceLocation SymbolLocations[3]) { + Kind = IK_OperatorFunctionId; + StartLocation = OperatorLoc; + EndLocation = OperatorLoc; + OperatorFunctionId.Operator = Op; + for (unsigned I = 0; I != 3; ++I) { + OperatorFunctionId.SymbolLocations[I] = SymbolLocations[I].getRawEncoding(); + + if (SymbolLocations[I].isValid()) + EndLocation = SymbolLocations[I]; + } +} diff --git a/lib/Sema/IdentifierResolver.cpp b/lib/Sema/IdentifierResolver.cpp index b09526e097b6..3f16ed772352 100644 --- a/lib/Sema/IdentifierResolver.cpp +++ b/lib/Sema/IdentifierResolver.cpp @@ -12,7 +12,9 @@ // //===----------------------------------------------------------------------===// -#include "IdentifierResolver.h" +#include "clang/Sema/IdentifierResolver.h" +#include "clang/Sema/Scope.h" +#include "clang/AST/Decl.h" #include "clang/Basic/LangOptions.h" using namespace clang; @@ -103,7 +105,7 @@ IdentifierResolver::~IdentifierResolver() { /// true if 'D' belongs to the given declaration context. bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx, ASTContext &Context, Scope *S) const { - Ctx = Ctx->getLookupContext(); + Ctx = Ctx->getRedeclContext(); if (Ctx->isFunctionOrMethod()) { // Ignore the scopes associated within transparent declaration contexts. @@ -111,7 +113,7 @@ bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx, ((DeclContext *)S->getEntity())->isTransparentContext()) S = S->getParent(); - if (S->isDeclScope(Action::DeclPtrTy::make(D))) + if (S->isDeclScope(D)) return true; if (LangOpt.CPlusPlus) { // C++ 3.3.2p3: @@ -128,17 +130,20 @@ bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx, // assert(S->getParent() && "No TUScope?"); if (S->getParent()->getFlags() & Scope::ControlScope) - return S->getParent()->isDeclScope(Action::DeclPtrTy::make(D)); + return S->getParent()->isDeclScope(D); } return false; } - return D->getDeclContext()->getLookupContext()->Equals(Ctx); + return D->getDeclContext()->getRedeclContext()->Equals(Ctx); } /// AddDecl - Link the decl to its shadowed decl chain. void IdentifierResolver::AddDecl(NamedDecl *D) { DeclarationName Name = D->getDeclName(); + if (IdentifierInfo *II = Name.getAsIdentifierInfo()) + II->setIsFromAST(false); + void *Ptr = Name.getFETokenInfo(); if (!Ptr) { @@ -164,6 +169,9 @@ void IdentifierResolver::AddDecl(NamedDecl *D) { void IdentifierResolver::RemoveDecl(NamedDecl *D) { assert(D && "null param passed"); DeclarationName Name = D->getDeclName(); + if (IdentifierInfo *II = Name.getAsIdentifierInfo()) + II->setIsFromAST(false); + void *Ptr = Name.getFETokenInfo(); assert(Ptr && "Didn't find this decl on its identifier's chain!"); @@ -182,6 +190,9 @@ bool IdentifierResolver::ReplaceDecl(NamedDecl *Old, NamedDecl *New) { "Cannot replace a decl with another decl of a different name"); DeclarationName Name = Old->getDeclName(); + if (IdentifierInfo *II = Name.getAsIdentifierInfo()) + II->setIsFromAST(false); + void *Ptr = Name.getFETokenInfo(); if (!Ptr) @@ -218,6 +229,7 @@ IdentifierResolver::begin(DeclarationName Name) { void IdentifierResolver::AddDeclToIdentifierChain(IdentifierInfo *II, NamedDecl *D) { + II->setIsFromAST(false); void *Ptr = II->getFETokenInfo(); if (!Ptr) { @@ -261,3 +273,16 @@ IdentifierResolver::IdDeclInfoMap::operator[](DeclarationName Name) { ++CurIndex; return *IDI; } + +void IdentifierResolver::iterator::incrementSlowCase() { + NamedDecl *D = **this; + void *InfoPtr = D->getDeclName().getFETokenInfo(); + assert(!isDeclPtr(InfoPtr) && "Decl with wrong id ?"); + IdDeclInfo *Info = toIdDeclInfo(InfoPtr); + + BaseIter I = getIterator(); + if (I != Info->decls_begin()) + *this = iterator(I-1); + else // No more decls. + *this = iterator(); +} diff --git a/lib/Sema/IdentifierResolver.h b/lib/Sema/IdentifierResolver.h deleted file mode 100644 index 59bd834073f3..000000000000 --- a/lib/Sema/IdentifierResolver.h +++ /dev/null @@ -1,203 +0,0 @@ -//===- 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" -#include "clang/Parse/Scope.h" -#include "clang/AST/Decl.h" -#include "clang/AST/DeclarationName.h" -#include "clang/AST/DeclCXX.h" - -namespace clang { - -/// 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 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(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(I) | 0x1; - } - - bool isIterator() const { return (Ptr & 0x1); } - - BaseIter getIterator() const { - assert(isIterator() && "Ptr not an iterator!"); - return reinterpret_cast(Ptr & ~0x3); - } - - friend class IdentifierResolver; - public: - iterator() : Ptr(0) {} - - NamedDecl *operator*() const { - if (isIterator()) - return *getIterator(); - else - return reinterpret_cast(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 { - NamedDecl *D = **this; - void *InfoPtr = D->getDeclName().getFETokenInfo(); - assert(!isDeclPtr(InfoPtr) && "Decl with wrong id ?"); - IdDeclInfo *Info = toIdDeclInfo(InfoPtr); - - BaseIter I = getIterator(); - if (I != Info->decls_begin()) - *this = iterator(I-1); - else // No more decls. - *this = iterator(); - } - 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 PCH 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(Ptr) & 0x1) == 0; - } - - /// FETokenInfo contains a IdDeclInfo pointer if lower bit == 1. - static inline IdDeclInfo *toIdDeclInfo(void *Ptr) { - assert((reinterpret_cast(Ptr) & 0x1) == 1 - && "Ptr not a IdDeclInfo* !"); - return reinterpret_cast( - reinterpret_cast(Ptr) & ~0x1 - ); - } -}; - -} // end namespace clang - -#endif diff --git a/lib/Sema/JumpDiagnostics.cpp b/lib/Sema/JumpDiagnostics.cpp index 3431ac611886..b23f615af7b7 100644 --- a/lib/Sema/JumpDiagnostics.cpp +++ b/lib/Sema/JumpDiagnostics.cpp @@ -12,11 +12,12 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/BitVector.h" -#include "Sema.h" +#include "clang/Sema/SemaInternal.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/Expr.h" #include "clang/AST/StmtObjC.h" #include "clang/AST/StmtCXX.h" +#include "llvm/ADT/BitVector.h" using namespace clang; namespace { @@ -180,12 +181,6 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned ParentScope) { // If we found a label, remember that it is in ParentScope scope. switch (S->getStmtClass()) { - case Stmt::LabelStmtClass: - case Stmt::DefaultStmtClass: - case Stmt::CaseStmtClass: - LabelAndGotoScopes[S] = ParentScope; - break; - case Stmt::AddrLabelExprClass: IndirectJumpTargets.push_back(cast(S)->getLabel()); break; @@ -225,6 +220,24 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned ParentScope) { Stmt *SubStmt = *CI; if (SubStmt == 0) continue; + // Cases, labels, and defaults aren't "scope parents". It's also + // important to handle these iteratively instead of recursively in + // order to avoid blowing out the stack. + while (true) { + Stmt *Next; + if (isa(SubStmt)) + Next = cast(SubStmt)->getSubStmt(); + else if (isa(SubStmt)) + Next = cast(SubStmt)->getSubStmt(); + else if (isa(SubStmt)) + Next = cast(SubStmt)->getSubStmt(); + else + break; + + LabelAndGotoScopes[SubStmt] = ParentScope; + SubStmt = Next; + } + // If this is a declstmt with a VLA definition, it defines a scope from here // to the end of the containing context. if (DeclStmt *DS = dyn_cast(SubStmt)) { diff --git a/lib/Sema/Lookup.h b/lib/Sema/Lookup.h deleted file mode 100644 index 271bb5bcd4a7..000000000000 --- a/lib/Sema/Lookup.h +++ /dev/null @@ -1,654 +0,0 @@ -//===--- 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 "Sema.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, DeclarationName Name, SourceLocation NameLoc, - Sema::LookupNameKind LookupKind, - Sema::RedeclarationKind Redecl = Sema::NotForRedeclaration) - : ResultKind(NotFound), - Paths(0), - NamingClass(0), - SemaRef(SemaRef), - Name(Name), - NameLoc(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), - Name(Other.Name), - NameLoc(Other.NameLoc), - 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 to look up. - DeclarationName getLookupName() const { - return Name; - } - - /// \brief Sets the name to look up. - void setLookupName(DeclarationName Name) { - this->Name = 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 { - ResultKind = Found; - resolveKind(); - - if (Paths && (ResultKind != Ambiguous)) { - deletePaths(Paths); - Paths = 0; - } - } - } - - template - DeclClass *getAsSingle() const { - if (getResultKind() != Found) return 0; - return dyn_cast(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(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 NameLoc; - } - - /// \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. - void sanity() const { - assert(ResultKind != NotFound || Decls.size() == 0); - assert(ResultKind != Found || Decls.size() == 1); - assert(ResultKind != FoundOverloaded || Decls.size() > 1 || - (Decls.size() == 1 && - isa((*begin())->getUnderlyingDecl()))); - assert(ResultKind != FoundUnresolvedValue || sanityCheckUnresolved()); - assert(ResultKind != Ambiguous || Decls.size() > 1 || - (Decls.size() == 1 && Ambiguity == AmbiguousBaseSubobjects)); - assert((Paths != NULL) == (ResultKind == Ambiguous && - (Ambiguity == AmbiguousBaseSubobjectTypes || - Ambiguity == AmbiguousBaseSubobjects))); - } - - bool sanityCheckUnresolved() const { - for (iterator I = begin(), E = end(); I != E; ++I) - if (isa(*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; - DeclarationName Name; - SourceLocation NameLoc; - 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 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(D->getCanonicalDecl())); - } - - class iterator { - typedef llvm::DenseMap::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/lib/Sema/Makefile b/lib/Sema/Makefile index 90f2dffa0f1b..2c02739d268f 100644 --- a/lib/Sema/Makefile +++ b/lib/Sema/Makefile @@ -14,7 +14,6 @@ CLANG_LEVEL := ../.. LIBRARYNAME := clangSema -BUILD_ARCHIVE = 1 include $(CLANG_LEVEL)/Makefile diff --git a/lib/Sema/ParseAST.cpp b/lib/Sema/ParseAST.cpp deleted file mode 100644 index bb0bd9e1cb5e..000000000000 --- a/lib/Sema/ParseAST.cpp +++ /dev/null @@ -1,125 +0,0 @@ -//===--- ParseAST.cpp - Provide the clang::ParseAST method ----------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the clang::ParseAST method. -// -//===----------------------------------------------------------------------===// - -#include "clang/Sema/ParseAST.h" -#include "Sema.h" -#include "clang/Sema/CodeCompleteConsumer.h" -#include "clang/Sema/SemaConsumer.h" -#include "clang/Sema/ExternalSemaSource.h" -#include "clang/AST/ASTConsumer.h" -#include "clang/AST/ExternalASTSource.h" -#include "clang/AST/Stmt.h" -#include "clang/Parse/Parser.h" -#include - -using namespace clang; - -static void DumpRecordLayouts(ASTContext &C) { - for (ASTContext::type_iterator I = C.types_begin(), E = C.types_end(); - I != E; ++I) { - const RecordType *RT = dyn_cast(*I); - if (!RT) - continue; - - const CXXRecordDecl *RD = dyn_cast(RT->getDecl()); - if (!RD || RD->isImplicit() || RD->isDependentType() || - RD->isInvalidDecl() || !RD->getDefinition()) - continue; - - // FIXME: Do we really need to hard code this? - if (RD->getQualifiedNameAsString() == "__va_list_tag") - continue; - - C.DumpRecordLayout(RD, llvm::errs()); - } -} - -//===----------------------------------------------------------------------===// -// Public interface to the file -//===----------------------------------------------------------------------===// - -/// ParseAST - Parse the entire file specified, notifying the ASTConsumer as -/// the file is parsed. This inserts the parsed decls into the translation unit -/// held by Ctx. -/// -void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer, - ASTContext &Ctx, bool PrintStats, - bool CompleteTranslationUnit, - CodeCompleteConsumer *CompletionConsumer) { - // Collect global stats on Decls/Stmts (until we have a module streamer). - if (PrintStats) { - Decl::CollectingStats(true); - Stmt::CollectingStats(true); - } - - Sema S(PP, Ctx, *Consumer, CompleteTranslationUnit, CompletionConsumer); - Parser P(PP, S); - PP.EnterMainSourceFile(); - - // Initialize the parser. - P.Initialize(); - - Consumer->Initialize(Ctx); - - if (SemaConsumer *SC = dyn_cast(Consumer)) - SC->InitializeSema(S); - - if (ExternalASTSource *External = Ctx.getExternalSource()) { - if (ExternalSemaSource *ExternalSema = - dyn_cast(External)) - ExternalSema->InitializeSema(S); - - External->StartTranslationUnit(Consumer); - } - - Parser::DeclGroupPtrTy ADecl; - - while (!P.ParseTopLevelDecl(ADecl)) { // Not end of file. - // If we got a null return and something *was* parsed, ignore it. This - // is due to a top-level semicolon, an action override, or a parse error - // skipping something. - if (ADecl) - Consumer->HandleTopLevelDecl(ADecl.getAsVal()); - }; - // Check for any pending objective-c implementation decl. - while ((ADecl = P.RetrievePendingObjCImpDecl())) - Consumer->HandleTopLevelDecl(ADecl.getAsVal()); - - // Process any TopLevelDecls generated by #pragma weak. - for (llvm::SmallVector::iterator - I = S.WeakTopLevelDecls().begin(), - E = S.WeakTopLevelDecls().end(); I != E; ++I) - Consumer->HandleTopLevelDecl(DeclGroupRef(*I)); - - // Dump record layouts, if requested. - if (PP.getLangOptions().DumpRecordLayouts) - DumpRecordLayouts(Ctx); - - Consumer->HandleTranslationUnit(Ctx); - - if (ExternalSemaSource *ESS = - dyn_cast_or_null(Ctx.getExternalSource())) - ESS->ForgetSema(); - - if (SemaConsumer *SC = dyn_cast(Consumer)) - SC->ForgetSema(); - - if (PrintStats) { - fprintf(stderr, "\nSTATISTICS:\n"); - P.getActions().PrintStats(); - Ctx.PrintStats(); - Decl::PrintStats(); - Stmt::PrintStats(); - Consumer->PrintStats(); - } -} diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index cddc84eeedff..17817d41691b 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -12,26 +12,36 @@ // //===----------------------------------------------------------------------===// -#include "Sema.h" +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/DelayedDiagnostic.h" #include "TargetAttributesSema.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/APFloat.h" +#include "clang/Sema/CXXFieldCollector.h" #include "clang/Sema/ExternalSemaSource.h" -#include "clang/AST/ASTConsumer.h" +#include "clang/Sema/PrettyDeclStackTrace.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/SemaConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTDiagnostic.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/Expr.h" #include "clang/Lex/Preprocessor.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/TargetInfo.h" using namespace clang; +using namespace sema; FunctionScopeInfo::~FunctionScopeInfo() { } void FunctionScopeInfo::Clear(unsigned NumErrors) { - NeedsScopeChecking = false; + HasBranchProtectedScope = false; + HasBranchIntoScope = false; + HasIndirectGoto = false; + LabelMap.clear(); SwitchStack.clear(); Returns.clear(); @@ -40,13 +50,13 @@ void FunctionScopeInfo::Clear(unsigned NumErrors) { BlockScopeInfo::~BlockScopeInfo() { } -void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) { +void Sema::ActOnTranslationUnitScope(Scope *S) { TUScope = S; PushDeclContext(S, Context.getTranslationUnitDecl()); VAListTagName = PP.getIdentifierInfo("__va_list_tag"); - if (!Context.isInt128Installed() && // May be set by PCHReader. + if (!Context.isInt128Installed() && // May be set by ASTReader. PP.getTargetInfo().getPointerWidth(0) >= 64) { TypeSourceInfo *TInfo; @@ -68,7 +78,7 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) { if (!PP.getLangOptions().ObjC1) return; - // Built-in ObjC types may already be set by PCHReader (hence isNull checks). + // Built-in ObjC types may already be set by ASTReader (hence isNull checks). if (Context.getObjCSelType().isNull()) { // Create the built-in typedef for 'SEL'. QualType SelT = Context.getPointerType(Context.ObjCBuiltinSelTy); @@ -113,7 +123,7 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) { PushOnScopeChains(ClassTypedef, TUScope); Context.setObjCClassType(Context.getTypeDeclType(ClassTypedef)); Context.ObjCClassRedefinitionType = Context.getObjCClassType(); - } + } } Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, @@ -123,9 +133,8 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, LangOpts(pp.getLangOptions()), PP(pp), Context(ctxt), Consumer(consumer), Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()), ExternalSource(0), CodeCompleter(CodeCompleter), CurContext(0), - PackContext(0), TopFunctionScope(0), ParsingDeclDepth(0), - IdResolver(pp.getLangOptions()), StdNamespace(0), StdBadAlloc(0), - GlobalNewDeleteDeclared(false), + PackContext(0), VisContext(0), ParsingDeclDepth(0), + IdResolver(pp.getLangOptions()), GlobalNewDeleteDeclared(false), CompleteTranslationUnit(CompleteTranslationUnit), NumSFINAEErrors(0), SuppressAccessChecking(false), NonInstantiationEntries(0), CurrentInstantiationScope(0), TyposCorrected(0), @@ -140,22 +149,52 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, &Context); ExprEvalContexts.push_back( - ExpressionEvaluationContextRecord(PotentiallyEvaluated, 0)); + ExpressionEvaluationContextRecord(PotentiallyEvaluated, 0)); + + FunctionScopes.push_back(new FunctionScopeInfo(Diags.getNumErrors())); +} + +void Sema::Initialize() { + // Tell the AST consumer about this Sema object. + Consumer.Initialize(Context); + + // FIXME: Isn't this redundant with the initialization above? + if (SemaConsumer *SC = dyn_cast(&Consumer)) + SC->InitializeSema(*this); + + // Tell the external Sema source about this Sema object. + if (ExternalSemaSource *ExternalSema + = dyn_cast_or_null(Context.getExternalSource())) + ExternalSema->InitializeSema(*this); } Sema::~Sema() { if (PackContext) FreePackedContext(); + if (VisContext) FreeVisContext(); delete TheTargetAttributesSema; - while (!FunctionScopes.empty()) - PopFunctionOrBlockScope(); + + // Kill all the active scopes. + for (unsigned I = 1, E = FunctionScopes.size(); I != E; ++I) + delete FunctionScopes[I]; + if (FunctionScopes.size() == 1) + delete FunctionScopes[0]; + + // Tell the SemaConsumer to forget about us; we're going out of scope. + if (SemaConsumer *SC = dyn_cast(&Consumer)) + SC->ForgetSema(); + + // Detach from the external Sema source. + if (ExternalSemaSource *ExternalSema + = dyn_cast_or_null(Context.getExternalSource())) + ExternalSema->ForgetSema(); } /// 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. +/// The result is of the given category. void Sema::ImpCastExprToType(Expr *&Expr, QualType Ty, - CastExpr::CastKind Kind, - bool isLvalue, CXXBaseSpecifierArray BasePath) { + CastKind Kind, ExprValueKind VK, + const CXXCastPath *BasePath) { QualType ExprTy = Context.getCanonicalType(Expr->getType()); QualType TypeTy = Context.getCanonicalType(Ty); @@ -173,8 +212,8 @@ void Sema::ImpCastExprToType(Expr *&Expr, QualType Ty, // If this is a derived-to-base cast to a through a virtual base, we // need a vtable. - if (Kind == CastExpr::CK_DerivedToBase && - BasePathInvolvesVirtualBase(BasePath)) { + if (Kind == CK_DerivedToBase && + BasePathInvolvesVirtualBase(*BasePath)) { QualType T = Expr->getType(); if (const PointerType *Pointer = T->getAs()) T = Pointer->getPointeeType(); @@ -184,53 +223,96 @@ void Sema::ImpCastExprToType(Expr *&Expr, QualType Ty, } if (ImplicitCastExpr *ImpCast = dyn_cast(Expr)) { - if (ImpCast->getCastKind() == Kind && BasePath.empty()) { + if (ImpCast->getCastKind() == Kind && (!BasePath || BasePath->empty())) { ImpCast->setType(Ty); - ImpCast->setLvalueCast(isLvalue); + ImpCast->setValueKind(VK); return; } } - Expr = new (Context) ImplicitCastExpr(Ty, Kind, Expr, BasePath, isLvalue); + Expr = ImplicitCastExpr::Create(Context, Ty, Kind, Expr, BasePath, VK); } -void Sema::DeleteExpr(ExprTy *E) { - if (E) static_cast(E)->Destroy(Context); +ExprValueKind Sema::CastCategory(Expr *E) { + Expr::Classification Classification = E->Classify(Context); + return Classification.isRValue() ? VK_RValue : + (Classification.isLValue() ? VK_LValue : VK_XValue); } -void Sema::DeleteStmt(StmtTy *S) { - if (S) static_cast(S)->Destroy(Context); + +/// \brief Used to prune the decls of Sema's UnusedFileScopedDecls vector. +static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) { + if (D->isUsed()) + return true; + + if (const FunctionDecl *FD = dyn_cast(D)) { + // UnusedFileScopedDecls stores the first declaration. + // The declaration may have become definition so check again. + const FunctionDecl *DeclToCheck; + if (FD->hasBody(DeclToCheck)) + return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck); + + // Later redecls may add new information resulting in not having to warn, + // so check again. + DeclToCheck = FD->getMostRecentDeclaration(); + if (DeclToCheck != FD) + return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck); + } + + if (const VarDecl *VD = dyn_cast(D)) { + // UnusedFileScopedDecls stores the first declaration. + // The declaration may have become definition so check again. + const VarDecl *DeclToCheck = VD->getDefinition(); + if (DeclToCheck) + return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck); + + // Later redecls may add new information resulting in not having to warn, + // so check again. + DeclToCheck = VD->getMostRecentDeclaration(); + if (DeclToCheck != VD) + return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck); + } + + return false; } /// 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. -void Sema::ActOnEndOfTranslationUnit() { - while (1) { - // C++: Perform implicit template instantiations. - // - // FIXME: When we perform these implicit instantiations, we do not carefully - // keep track of the point of instantiation (C++ [temp.point]). This means - // that name lookup that occurs within the template instantiation will - // always happen at the end of the translation unit, so it will find - // some names that should not be found. Although this is common behavior - // for C++ compilers, it is technically wrong. In the future, we either need - // to be able to filter the results of name lookup or we need to perform - // template instantiations earlier. - PerformPendingImplicitInstantiations(); - - /// If DefinedUsedVTables ends up marking any virtual member - /// functions it might lead to more pending template - /// instantiations, which is why we need to loop here. - if (!DefineUsedVTables()) - break; - } +void Sema::ActOnEndOfTranslationUnit() { + // At PCH writing, implicit instantiations and VTable handling info are + // stored and performed when the PCH is included. + if (CompleteTranslationUnit) + while (1) { + // C++: Perform implicit template instantiations. + // + // FIXME: When we perform these implicit instantiations, we do not + // carefully keep track of the point of instantiation (C++ [temp.point]). + // This means that name lookup that occurs within the template + // instantiation will always happen at the end of the translation unit, + // so it will find some names that should not be found. Although this is + // common behavior for C++ compilers, it is technically wrong. In the + // future, we either need to be able to filter the results of name lookup + // or we need to perform template instantiations earlier. + PerformPendingInstantiations(); + + /// If DefinedUsedVTables ends up marking any virtual member + /// functions it might lead to more pending template + /// instantiations, which is why we need to loop here. + if (!DefineUsedVTables()) + break; + } - // Remove functions that turned out to be used. - UnusedStaticFuncs.erase(std::remove_if(UnusedStaticFuncs.begin(), - UnusedStaticFuncs.end(), - std::bind2nd(std::mem_fun(&FunctionDecl::isUsed), - true)), - UnusedStaticFuncs.end()); + // Remove file scoped decls that turned out to be used. + UnusedFileScopedDecls.erase(std::remove_if(UnusedFileScopedDecls.begin(), + UnusedFileScopedDecls.end(), + std::bind1st(std::ptr_fun(ShouldRemoveFromUnused), + this)), + UnusedFileScopedDecls.end()); + + if (!CompleteTranslationUnit) { + TUScope = 0; + return; + } // Check for #pragma weak identifiers that were never declared // FIXME: This will cause diagnostics to be emitted in a non-determinstic @@ -244,9 +326,6 @@ void Sema::ActOnEndOfTranslationUnit() { << I->first; } - if (!CompleteTranslationUnit) - return; - // C99 6.9.2p2: // A declaration of an identifier for an object that has file // scope without an initializer, and without a storage-class @@ -293,14 +372,28 @@ void Sema::ActOnEndOfTranslationUnit() { } - // Output warning for unused functions. - for (std::vector::iterator - F = UnusedStaticFuncs.begin(), - FEnd = UnusedStaticFuncs.end(); - F != FEnd; - ++F) - Diag((*F)->getLocation(), diag::warn_unused_function) << (*F)->getDeclName(); - + // Output warning for unused file scoped decls. + for (llvm::SmallVectorImpl::iterator + I = UnusedFileScopedDecls.begin(), + E = UnusedFileScopedDecls.end(); I != E; ++I) { + if (const FunctionDecl *FD = dyn_cast(*I)) { + const FunctionDecl *DiagD; + if (!FD->hasBody(DiagD)) + DiagD = FD; + Diag(DiagD->getLocation(), + isa(DiagD) ? diag::warn_unused_member_function + : diag::warn_unused_function) + << DiagD->getDeclName(); + } else { + const VarDecl *DiagD = cast(*I)->getDefinition(); + if (!DiagD) + DiagD = cast(*I); + Diag(DiagD->getLocation(), diag::warn_unused_variable) + << DiagD->getDeclName(); + } + } + + TUScope = 0; } @@ -418,11 +511,11 @@ Scope *Sema::getScopeForContext(DeclContext *Ctx) { /// \brief Enter a new function scope void Sema::PushFunctionScope() { - if (FunctionScopes.empty()) { - // Use the "top" function scope rather than having to allocate memory for - // a new scope. - TopFunctionScope.Clear(getDiagnostics().getNumErrors()); - FunctionScopes.push_back(&TopFunctionScope); + if (FunctionScopes.size() == 1) { + // Use the "top" function scope rather than having to allocate + // memory for a new scope. + FunctionScopes.back()->Clear(getDiagnostics().getNumErrors()); + FunctionScopes.push_back(FunctionScopes.back()); return; } @@ -436,21 +529,17 @@ void Sema::PushBlockScope(Scope *BlockScope, BlockDecl *Block) { } void Sema::PopFunctionOrBlockScope() { - if (FunctionScopes.back() != &TopFunctionScope) - delete FunctionScopes.back(); - else - TopFunctionScope.Clear(getDiagnostics().getNumErrors()); - - FunctionScopes.pop_back(); + FunctionScopeInfo *Scope = FunctionScopes.pop_back_val(); + assert(!FunctionScopes.empty() && "mismatched push/pop!"); + if (FunctionScopes.back() != Scope) + delete Scope; } /// \brief Determine whether any errors occurred within this function/method/ /// block. bool Sema::hasAnyErrorsInThisFunction() const { - unsigned NumErrors = TopFunctionScope.NumErrorsAtStartOfFunction; - if (!FunctionScopes.empty()) - NumErrors = FunctionScopes.back()->NumErrorsAtStartOfFunction; - return NumErrors != getDiagnostics().getNumErrors(); + return getCurFunction()->NumErrorsAtStartOfFunction + != getDiagnostics().getNumErrors(); } BlockScopeInfo *Sema::getCurBlock() { @@ -462,3 +551,21 @@ BlockScopeInfo *Sema::getCurBlock() { // Pin this vtable to this file. ExternalSemaSource::~ExternalSemaSource() {} + +void PrettyDeclStackTraceEntry::print(llvm::raw_ostream &OS) const { + SourceLocation Loc = this->Loc; + if (!Loc.isValid() && TheDecl) Loc = TheDecl->getLocation(); + if (Loc.isValid()) { + Loc.print(OS, S.getSourceManager()); + OS << ": "; + } + OS << Message; + + if (TheDecl && isa(TheDecl)) { + std::string Name = cast(TheDecl)->getNameAsString(); + if (!Name.empty()) + OS << " '" << Name << '\''; + } + + OS << '\n'; +} diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h deleted file mode 100644 index 8336918c134e..000000000000 --- a/lib/Sema/Sema.h +++ /dev/null @@ -1,4655 +0,0 @@ -//===--- 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_AST_SEMA_H -#define LLVM_CLANG_AST_SEMA_H - -#include "IdentifierResolver.h" -#include "CXXFieldCollector.h" -#include "SemaOverload.h" -#include "SemaTemplate.h" -#include "AnalysisBasedWarnings.h" -#include "clang/AST/Attr.h" -#include "clang/AST/DeclBase.h" -#include "clang/AST/Decl.h" -#include "clang/AST/DeclObjC.h" -#include "clang/AST/DeclTemplate.h" -#include "clang/AST/ExprCXX.h" -#include "clang/AST/FullExpr.h" -#include "clang/Parse/Action.h" -#include "clang/Sema/SemaDiagnostic.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/OwningPtr.h" -#include -#include -#include -#include -#include - -namespace llvm { - class APSInt; -} - -namespace clang { - class ASTContext; - class ASTConsumer; - class CodeCompleteConsumer; - class Preprocessor; - class Decl; - class DeclContext; - class DeclSpec; - class ExternalSemaSource; - class NamedDecl; - class Stmt; - class Expr; - class InitListExpr; - class ParenListExpr; - class DesignatedInitExpr; - class CallExpr; - class DeclRefExpr; - class UnresolvedLookupExpr; - class UnresolvedMemberExpr; - class VarDecl; - class ParmVarDecl; - class TypedefDecl; - class FunctionDecl; - class QualType; - class LangOptions; - class Token; - class IntegerLiteral; - class StringLiteral; - class ArrayType; - class LabelStmt; - class SwitchStmt; - class CXXTryStmt; - class ExtVectorType; - class TypedefDecl; - class TemplateDecl; - class TemplateArgument; - class TemplateArgumentLoc; - class TemplateArgumentList; - class TemplateParameterList; - class TemplateTemplateParmDecl; - class ClassTemplatePartialSpecializationDecl; - class ClassTemplateDecl; - class ObjCInterfaceDecl; - class ObjCCompatibleAliasDecl; - class ObjCProtocolDecl; - class ObjCImplDecl; - class ObjCImplementationDecl; - class ObjCCategoryImplDecl; - class ObjCCategoryDecl; - class ObjCIvarDecl; - class ObjCMethodDecl; - class ObjCPropertyDecl; - class ObjCContainerDecl; - class PseudoDestructorTypeStorage; - class FunctionProtoType; - class CXXBasePath; - class CXXBasePaths; - class CXXTemporary; - class LookupResult; - class InitializedEntity; - class InitializationKind; - class InitializationSequence; - class VisibleDeclConsumer; - class TargetAttributesSema; - class ADLResult; - -/// \brief Retains information about a function, method, or block that is -/// currently being parsed. -struct FunctionScopeInfo { - /// \brief Whether this scope information structure defined information for - /// a block. - bool IsBlockInfo; - - /// \brief Set true when a function, method contains a VLA or ObjC try block, - /// which introduce scopes that need to be checked for goto conditions. If a - /// function does not contain this, then it need not have the jump checker run - /// on it. - bool NeedsScopeChecking; - - /// \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 LabelMap; - - /// SwitchStack - This is the current set of active switch statements in the - /// block. - llvm::SmallVector 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 Returns; - - FunctionScopeInfo(unsigned NumErrors) - : IsBlockInfo(false), NeedsScopeChecking(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. -struct BlockScopeInfo : FunctionScopeInfo { - 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; } -}; - -/// \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; } - - virtual 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 : public Action { - Sema(const Sema&); // DO NOT IMPLEMENT - void operator=(const Sema&); // DO NOT IMPLEMENT - mutable const TargetAttributesSema* TheTargetAttributesSema; -public: - 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*" - - /// \brief Stack containing information about each of the nested function, - /// block, and method scopes that are currently active. - llvm::SmallVector FunctionScopes; - - /// \brief Cached function scope object used for the top function scope - /// and when there is no function scope (in error cases). - /// - /// This should never be accessed directly; rather, it's address will be - /// pushed into \c FunctionScopes when we want to re-use it. - FunctionScopeInfo TopFunctionScope; - - /// ExprTemporaries - This is the stack of temporaries that are created by - /// the current full expression. - llvm::SmallVector 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 ExtVectorDecls; - - /// FieldCollector - Collects CXXFieldDecls during parsing of C++ classes. - llvm::OwningPtr FieldCollector; - - typedef llvm::SmallPtrSet 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 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 LocallyScopedExternalDecls; - - /// \brief All the tentative definitions encountered in the TU. - std::vector TentativeDefinitions; - - /// \brief The set of static functions seen so far that have not been used. - std::vector UnusedStaticFuncs; - - 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 { return cast(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; - }; - - struct DelayedDiagnostic { - 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(AccessData); - } - const AccessedEntity &getAccessData() const { - return *reinterpret_cast(AccessData); - } - }; - - /// \brief The stack of diagnostics that were delayed due to being - /// produced during the parsing of a declaration. - llvm::SmallVector 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 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 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. - NamespaceDecl *StdNamespace; - - /// \brief The C++ "std::bad_alloc" class, which is defined by the C++ - /// standard library. - CXXRecordDecl *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 std::vector > - PotentiallyReferencedDecls; - - /// \brief A set of diagnostics that may be emitted. - typedef std::vector > - PotentiallyEmittedDiagnostics; - - /// \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 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 llvm::DenseMap MethodPool; - - /// Instance/Factory Method Pools - 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"). - MethodPool InstanceMethodPool; - MethodPool FactoryMethodPool; - - MethodPool::iterator ReadMethodPool(Selector Sel, bool isInstance); - - /// 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(); - - const LangOptions &getLangOptions() const { return LangOpts; } - Diagnostic &getDiagnostics() const { return Diags; } - SourceManager &getSourceManager() const { return SourceMgr; } - const TargetAttributesSema &getTargetAttributesSema() const; - - /// \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) { - return PartialDiagnostic(DiagID, Context.getDiagAllocator()); - } - - virtual void DeleteExpr(ExprTy *E); - virtual void DeleteStmt(StmtTy *S); - - OwningExprResult Owned(Expr* E) { - assert(!E || E->isRetained()); - return OwningExprResult(*this, E); - } - OwningExprResult Owned(ExprResult R) { - if (R.isInvalid()) - return ExprError(); - assert(!R.get() || ((Expr*) R.get())->isRetained()); - return OwningExprResult(*this, R.get()); - } - OwningStmtResult Owned(Stmt* S) { - assert(!S || S->isRetained()); - return OwningStmtResult(*this, S); - } - - virtual void ActOnEndOfTranslationUnit(); - - Scope *getScopeForContext(DeclContext *Ctx); - - void PushFunctionScope(); - void PushBlockScope(Scope *BlockScope, BlockDecl *Block); - void PopFunctionOrBlockScope(); - - /// getLabelMap() - Return the current label map. If we're in a block, we - /// return it. - llvm::DenseMap &getLabelMap() { - if (FunctionScopes.empty()) - return TopFunctionScope.LabelMap; - - return FunctionScopes.back()->LabelMap; - } - - /// getSwitchStack - This is returns the switch stack for the current block or - /// function. - llvm::SmallVector &getSwitchStack() { - if (FunctionScopes.empty()) - return TopFunctionScope.SwitchStack; - - return FunctionScopes.back()->SwitchStack; - } - - /// \brief Determine whether the current function or block needs scope - /// checking. - bool &FunctionNeedsScopeChecking() { - if (FunctionScopes.empty()) - return TopFunctionScope.NeedsScopeChecking; - - return FunctionScopes.back()->NeedsScopeChecking; - } - - bool hasAnyErrorsInThisFunction() const; - - /// \brief Retrieve the current block, if any. - BlockScopeInfo *getCurBlock(); - - /// WeakTopLevelDeclDecls - access to #pragma weak-generated Decls - llvm::SmallVector &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, ExprArg ArraySize, - SourceLocation AttrLoc); - QualType BuildFunctionType(QualType T, - QualType *ParamTypes, unsigned NumParamTypes, - bool Variadic, unsigned Quals, - SourceLocation Loc, DeclarationName Entity); - 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 Create a LocInfoType to hold the given QualType and TypeSourceInfo. - QualType CreateLocInfoType(QualType T, TypeSourceInfo *TInfo); - DeclarationName GetNameForDeclarator(Declarator &D); - DeclarationName GetNameFromUnqualifiedId(const UnqualifiedId &Name); - static QualType GetTypeFromParser(TypeTy *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); - - virtual TypeResult ActOnTypeName(Scope *S, Declarator &D); - - bool RequireCompleteType(SourceLocation Loc, QualType T, - const PartialDiagnostic &PD, - std::pair 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. - // - - /// 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); - - DeclGroupPtrTy ConvertDeclToDeclGroup(DeclPtrTy Ptr); - - virtual TypeTy *getTypeName(IdentifierInfo &II, SourceLocation NameLoc, - Scope *S, CXXScopeSpec *SS, - bool isClassName = false, - TypeTy *ObjectType = 0); - virtual DeclSpec::TST isTagName(IdentifierInfo &II, Scope *S); - virtual bool DiagnoseUnknownTypeName(const IdentifierInfo &II, - SourceLocation IILoc, - Scope *S, - CXXScopeSpec *SS, - TypeTy *&SuggestedType); - - virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D) { - return HandleDeclarator(S, D, MultiTemplateParamsArg(*this), false); - } - - DeclPtrTy 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); - 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); - virtual DeclPtrTy 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, - VarDecl::StorageClass StorageClass, - VarDecl::StorageClass StorageClassAsWritten); - virtual void ActOnParamDefaultArgument(DeclPtrTy param, - SourceLocation EqualLoc, - ExprArg defarg); - virtual void ActOnParamUnparsedDefaultArgument(DeclPtrTy param, - SourceLocation EqualLoc, - SourceLocation ArgLoc); - virtual void ActOnParamDefaultArgumentError(DeclPtrTy param); - bool SetParamDefaultArgument(ParmVarDecl *Param, ExprArg DefaultArg, - SourceLocation EqualLoc); - - - // Contains the locations of the beginning of unparsed default - // argument locations. - llvm::DenseMap UnparsedDefaultArgLocs; - - virtual void AddInitializerToDecl(DeclPtrTy dcl, ExprArg init); - void AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit); - void ActOnUninitializedDecl(DeclPtrTy dcl, bool TypeContainsUndeducedAuto); - virtual void ActOnInitializerError(DeclPtrTy Dcl); - virtual void SetDeclDeleted(DeclPtrTy dcl, SourceLocation DelLoc); - virtual DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, - DeclPtrTy *Group, - unsigned NumDecls); - virtual void ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D, - SourceLocation LocAfterDecls); - virtual DeclPtrTy ActOnStartOfFunctionDef(Scope *S, Declarator &D); - virtual DeclPtrTy ActOnStartOfFunctionDef(Scope *S, DeclPtrTy D); - virtual void ActOnStartOfObjCMethodDef(Scope *S, DeclPtrTy D); - - virtual DeclPtrTy ActOnFinishFunctionBody(DeclPtrTy Decl, StmtArg Body); - DeclPtrTy ActOnFinishFunctionBody(DeclPtrTy Decl, StmtArg Body, - bool IsInstantiation); - - /// \brief Diagnose any unused parameters in the given sequence of - /// ParmVarDecl pointers. - template - void DiagnoseUnusedParameters(InputIterator Param, InputIterator ParamEnd) { - if (Diags.getDiagnosticLevel(diag::warn_unused_parameter) == - Diagnostic::Ignored) - return; - - // Don't diagnose unused-parameter errors in template instantiations; we - // will already have done so in the template itself. - if (!ActiveTemplateInstantiations.empty()) - return; - - for (; Param != ParamEnd; ++Param) { - if (!(*Param)->isUsed() && (*Param)->getDeclName() && - !(*Param)->template hasAttr()) { - Diag((*Param)->getLocation(), diag::warn_unused_parameter) - << (*Param)->getDeclName(); - } - } - } - - void DiagnoseInvalidJumps(Stmt *Body); - virtual DeclPtrTy ActOnFileScopeAsmDecl(SourceLocation Loc, ExprArg expr); - - /// Scope actions. - virtual void ActOnPopScope(SourceLocation Loc, Scope *S); - 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 AS, - DeclSpec &DS); - - virtual DeclPtrTy BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, - AccessSpecifier AS, - RecordDecl *Record); - - bool isAcceptableTagRedeclaration(const TagDecl *Previous, - TagDecl::TagKind NewTag, - SourceLocation NewTagLoc, - const IdentifierInfo &Name); - - 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); - - virtual TypeResult ActOnDependentTag(Scope *S, - unsigned TagSpec, - TagUseKind TUK, - const CXXScopeSpec &SS, - IdentifierInfo *Name, - SourceLocation TagLoc, - SourceLocation NameLoc); - - virtual void ActOnDefs(Scope *S, DeclPtrTy TagD, SourceLocation DeclStart, - IdentifierInfo *ClassName, - llvm::SmallVectorImpl &Decls); - virtual DeclPtrTy ActOnField(Scope *S, DeclPtrTy TagD, - SourceLocation DeclStart, - Declarator &D, ExprTy *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 - }; - void DiagnoseNontrivial(const RecordType* Record, CXXSpecialMember mem); - CXXSpecialMember getSpecialMember(const CXXMethodDecl *MD); - - virtual DeclPtrTy ActOnIvar(Scope *S, SourceLocation DeclStart, - DeclPtrTy IntfDecl, - Declarator &D, ExprTy *BitfieldWidth, - tok::ObjCKeywordKind visibility); - - // This is used for both record definitions and ObjC interface declarations. - 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). - virtual void ActOnTagFinishDefinition(Scope *S, DeclPtrTy TagDecl, - SourceLocation RBraceLoc); - - /// ActOnTagDefinitionError - Invoked when there was an unrecoverable - /// error parsing the definition of a tag. - virtual void ActOnTagDefinitionError(Scope *S, DeclPtrTy TagDecl); - - EnumConstantDecl *CheckEnumConstant(EnumDecl *Enum, - EnumConstantDecl *LastEnumConst, - SourceLocation IdLoc, - IdentifierInfo *Id, - ExprArg val); - - virtual DeclPtrTy ActOnEnumConstant(Scope *S, DeclPtrTy EnumDecl, - DeclPtrTy LastEnumConstant, - SourceLocation IdLoc, IdentifierInfo *Id, - SourceLocation EqualLoc, ExprTy *Val); - virtual void ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, - SourceLocation RBraceLoc, DeclPtrTy EnumDecl, - DeclPtrTy *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. - Scope *getScopeForDeclContext(Scope *S, DeclContext *DC) { - DeclContext *TargetDC = DC->getPrimaryContext(); - do { - if (DeclContext *ScopeDC = (DeclContext*) S->getEntity()) - if (ScopeDC->getPrimaryContext() == TargetDC) - return S; - } while ((S = S->getParent())); - - return NULL; - } - - /// 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); - - ImplicitConversionSequence - TryImplicitConversion(Expr* From, QualType ToType, - bool SuppressUserConversions, - bool AllowExplicit, - bool InOverloadResolution); - bool IsStandardConversion(Expr *From, QualType ToType, - bool InOverloadResolution, - StandardConversionSequence& SCS); - 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, - CastExpr::CastKind &Kind, - CXXBaseSpecifierArray& BasePath, - bool IgnoreBaseAccess); - bool IsMemberPointerConversion(Expr *From, QualType FromType, QualType ToType, - bool InOverloadResolution, - QualType &ConvertedType); - bool CheckMemberPointerConversion(Expr *From, QualType ToType, - CastExpr::CastKind &Kind, - CXXBaseSpecifierArray &BasePath, - bool IgnoreBaseAccess); - bool IsQualificationConversion(QualType FromType, QualType ToType); - OverloadingResult IsUserDefinedConversion(Expr *From, QualType ToType, - UserDefinedConversionSequence& User, - OverloadCandidateSet& Conversions, - bool AllowExplicit); - bool DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType); - - - ImplicitConversionSequence::CompareKind - CompareImplicitConversionSequences(const ImplicitConversionSequence& ICS1, - const ImplicitConversionSequence& ICS2); - - ImplicitConversionSequence::CompareKind - CompareStandardConversionSequences(const StandardConversionSequence& SCS1, - const StandardConversionSequence& SCS2); - - ImplicitConversionSequence::CompareKind - CompareQualificationConversions(const StandardConversionSequence& SCS1, - const StandardConversionSequence& SCS2); - - ImplicitConversionSequence::CompareKind - CompareDerivedToBaseConversions(const StandardConversionSequence& SCS1, - const StandardConversionSequence& SCS2); - - OwningExprResult PerformCopyInitialization(const InitializedEntity &Entity, - SourceLocation EqualLoc, - OwningExprResult Init); - ImplicitConversionSequence - TryObjectArgumentInitialization(QualType FromType, CXXMethodDecl *Method, - CXXRecordDecl *ActingContext); - bool PerformObjectArgumentInitialization(Expr *&From, - NestedNameSpecifier *Qualifier, - NamedDecl *FoundDecl, - CXXMethodDecl *Method); - - ImplicitConversionSequence TryContextuallyConvertToBool(Expr *From); - bool PerformContextuallyConvertToBool(Expr *&From); - - ImplicitConversionSequence TryContextuallyConvertToObjCId(Expr *From); - bool PerformContextuallyConvertToObjCId(Expr *&From); - - OwningExprResult - ConvertToIntegralOrEnumerationType(SourceLocation Loc, ExprArg 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 AssociatedNamespaceSet; - typedef llvm::SmallPtrSet 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); - bool isBetterOverloadCandidate(const OverloadCandidate& Cand1, - const OverloadCandidate& Cand2, - SourceLocation Loc); - OverloadingResult BestViableFunction(OverloadCandidateSet& CandidateSet, - SourceLocation Loc, - OverloadCandidateSet::iterator& Best); - - 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 - }; - void PrintOverloadCandidates(OverloadCandidateSet& CandidateSet, - OverloadCandidateDisplayKind OCD, - Expr **Args, unsigned NumArgs, - const char *Opc = 0, - SourceLocation Loc = SourceLocation()); - - void NoteOverloadCandidate(FunctionDecl *Fn); - void DiagnoseAmbiguousConversion(const ImplicitConversionSequence &ICS, - SourceLocation CaretLoc, - const PartialDiagnostic &PDiag); - - FunctionDecl *ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, - bool Complain, - DeclAccessPair &Found); - FunctionDecl *ResolveSingleFunctionTemplateSpecialization(Expr *From); - - Expr *FixOverloadedFunctionReference(Expr *E, - DeclAccessPair FoundDecl, - FunctionDecl *Fn); - OwningExprResult FixOverloadedFunctionReference(OwningExprResult, - DeclAccessPair FoundDecl, - FunctionDecl *Fn); - - void AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE, - Expr **Args, unsigned NumArgs, - OverloadCandidateSet &CandidateSet, - bool PartialOverloading = false); - - OwningExprResult BuildOverloadedCallExpr(Scope *S, Expr *Fn, - UnresolvedLookupExpr *ULE, - SourceLocation LParenLoc, - Expr **Args, unsigned NumArgs, - SourceLocation *CommaLocs, - SourceLocation RParenLoc); - - OwningExprResult CreateOverloadedUnaryOp(SourceLocation OpLoc, - unsigned Opc, - const UnresolvedSetImpl &Fns, - ExprArg input); - - OwningExprResult CreateOverloadedBinOp(SourceLocation OpLoc, - unsigned Opc, - const UnresolvedSetImpl &Fns, - Expr *LHS, Expr *RHS); - - OwningExprResult CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, - SourceLocation RLoc, - ExprArg Base,ExprArg Idx); - - OwningExprResult - 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); - - OwningExprResult BuildOverloadedArrowExpr(Scope *S, ExprArg 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 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); - DeclContext::lookup_result 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); - void LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind, - VisibleDeclConsumer &Consumer); - - /// \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); - - /// 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 llvm::DenseSet &InsMap, - const llvm::DenseSet &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 llvm::DenseSet& 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& PropMap, - llvm::DenseMap& 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. - DeclPtrTy 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); - - /// MatchAllMethodDeclarations - Check methods declaraed in interface or - /// or protocol against those declared in their implementations. - void MatchAllMethodDeclarations(const llvm::DenseSet &InsMap, - const llvm::DenseSet &ClsMap, - llvm::DenseSet &InsMapSeen, - llvm::DenseSet &ClsMapSeen, - ObjCImplDecl* IMPDecl, - ObjCContainerDecl* IDecl, - bool &IncompleteImpl, - bool ImmediateClass); - - /// 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); - - /// LookupInstanceMethodInGlobalPool - Returns the method and warns if - /// there are multiple signatures. - ObjCMethodDecl *LookupInstanceMethodInGlobalPool(Selector Sel, SourceRange R, - bool warn=true); - - /// LookupFactoryMethodInGlobalPool - Returns the method and warns if - /// there are multiple signatures. - ObjCMethodDecl *LookupFactoryMethodInGlobalPool(Selector Sel, SourceRange R); - - /// AddFactoryMethodToGlobalPool - Same as above, but for factory methods. - void AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method); - - /// CollectIvarsToConstructOrDestruct - Collect those ivars which require - /// initialization. - void CollectIvarsToConstructOrDestruct(const ObjCInterfaceDecl *OI, - llvm::SmallVectorImpl &Ivars); - //===--------------------------------------------------------------------===// - // Statement Parsing Callbacks: SemaStmt.cpp. -public: - virtual OwningStmtResult ActOnExprStmt(FullExprArg Expr); - - virtual OwningStmtResult ActOnNullStmt(SourceLocation SemiLoc); - virtual OwningStmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R, - MultiStmtArg Elts, - bool isStmtExpr); - virtual OwningStmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, - SourceLocation StartLoc, - SourceLocation EndLoc); - virtual void ActOnForEachDeclStmt(DeclGroupPtrTy Decl); - virtual OwningStmtResult ActOnCaseStmt(SourceLocation CaseLoc, ExprArg LHSVal, - SourceLocation DotDotDotLoc, ExprArg RHSVal, - SourceLocation ColonLoc); - virtual void ActOnCaseStmtBody(StmtTy *CaseStmt, StmtArg SubStmt); - - virtual OwningStmtResult ActOnDefaultStmt(SourceLocation DefaultLoc, - SourceLocation ColonLoc, - StmtArg SubStmt, Scope *CurScope); - virtual OwningStmtResult ActOnLabelStmt(SourceLocation IdentLoc, - IdentifierInfo *II, - SourceLocation ColonLoc, - StmtArg SubStmt); - virtual OwningStmtResult ActOnIfStmt(SourceLocation IfLoc, - FullExprArg CondVal, DeclPtrTy CondVar, - StmtArg ThenVal, - SourceLocation ElseLoc, StmtArg ElseVal); - virtual OwningStmtResult ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, - ExprArg Cond, - DeclPtrTy CondVar); - virtual OwningStmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc, - StmtArg Switch, StmtArg Body); - virtual OwningStmtResult ActOnWhileStmt(SourceLocation WhileLoc, - FullExprArg Cond, - DeclPtrTy CondVar, StmtArg Body); - virtual OwningStmtResult ActOnDoStmt(SourceLocation DoLoc, StmtArg Body, - SourceLocation WhileLoc, - SourceLocation CondLParen, ExprArg Cond, - SourceLocation CondRParen); - - virtual OwningStmtResult ActOnForStmt(SourceLocation ForLoc, - SourceLocation LParenLoc, - StmtArg First, FullExprArg Second, - DeclPtrTy SecondVar, - FullExprArg Third, - SourceLocation RParenLoc, - StmtArg Body); - virtual OwningStmtResult ActOnObjCForCollectionStmt(SourceLocation ForColLoc, - SourceLocation LParenLoc, - StmtArg First, ExprArg Second, - SourceLocation RParenLoc, StmtArg Body); - - virtual OwningStmtResult ActOnGotoStmt(SourceLocation GotoLoc, - SourceLocation LabelLoc, - IdentifierInfo *LabelII); - virtual OwningStmtResult ActOnIndirectGotoStmt(SourceLocation GotoLoc, - SourceLocation StarLoc, - ExprArg DestExp); - virtual OwningStmtResult ActOnContinueStmt(SourceLocation ContinueLoc, - Scope *CurScope); - virtual OwningStmtResult ActOnBreakStmt(SourceLocation GotoLoc, - Scope *CurScope); - - virtual OwningStmtResult ActOnReturnStmt(SourceLocation ReturnLoc, - ExprArg RetValExp); - OwningStmtResult ActOnBlockReturnStmt(SourceLocation ReturnLoc, - Expr *RetValExp); - - 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); - - - VarDecl *BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType ExceptionType, - IdentifierInfo *Name, SourceLocation NameLoc, - bool Invalid = false); - - virtual DeclPtrTy ActOnObjCExceptionDecl(Scope *S, Declarator &D); - - virtual OwningStmtResult ActOnObjCAtCatchStmt(SourceLocation AtLoc, - SourceLocation RParen, - DeclPtrTy Parm, StmtArg Body); - - virtual OwningStmtResult ActOnObjCAtFinallyStmt(SourceLocation AtLoc, - StmtArg Body); - - virtual OwningStmtResult ActOnObjCAtTryStmt(SourceLocation AtLoc, - StmtArg Try, - MultiStmtArg Catch, - StmtArg Finally); - - virtual OwningStmtResult BuildObjCAtThrowStmt(SourceLocation AtLoc, - ExprArg Throw); - virtual OwningStmtResult ActOnObjCAtThrowStmt(SourceLocation AtLoc, - ExprArg Throw, - Scope *CurScope); - virtual OwningStmtResult ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, - ExprArg SynchExpr, - StmtArg SynchBody); - - VarDecl *BuildExceptionDeclaration(Scope *S, QualType ExDeclType, - TypeSourceInfo *TInfo, - IdentifierInfo *Name, - SourceLocation Loc, - SourceRange Range); - virtual DeclPtrTy ActOnExceptionDeclarator(Scope *S, Declarator &D); - - virtual OwningStmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc, - DeclPtrTy ExDecl, - StmtArg HandlerBlock); - virtual OwningStmtResult ActOnCXXTryBlock(SourceLocation TryLoc, - StmtArg TryBlock, - MultiStmtArg Handlers); - void DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock); - - /// DiagnoseUnusedExprResult - If the statement passed in is an expression - /// whose result is unused, warn. - void DiagnoseUnusedExprResult(const Stmt *S); - void DiagnoseUnusedDecl(const NamedDecl *ND); - - ParsingDeclStackState PushParsingDeclaration(); - void PopParsingDeclaration(ParsingDeclStackState S, DeclPtrTy D); - void EmitDeprecationWarning(NamedDecl *D, SourceLocation Loc); - - void HandleDelayedDeprecationCheck(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); - - virtual void - PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext); - - virtual void PopExpressionEvaluationContext(); - - void MarkDeclarationReferenced(SourceLocation Loc, Decl *D); - void MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T); - bool DiagRuntimeBehavior(SourceLocation Loc, const PartialDiagnostic &PD); - - // Primary Expressions. - virtual SourceRange getExprRange(ExprTy *E) const; - - virtual OwningExprResult ActOnIdExpression(Scope *S, - CXXScopeSpec &SS, - UnqualifiedId &Name, - bool HasTrailingLParen, - bool IsAddressOfOperand); - - bool DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, - CorrectTypoContext CTC = CTC_Unknown); - - OwningExprResult LookupInObjCMethod(LookupResult &R, - Scope *S, - IdentifierInfo *II, - bool AllowBuiltinCreation=false); - - OwningExprResult ActOnDependentIdExpression(const CXXScopeSpec &SS, - DeclarationName Name, - SourceLocation NameLoc, - bool isAddressOfOperand, - const TemplateArgumentListInfo *TemplateArgs); - - OwningExprResult BuildDeclRefExpr(ValueDecl *D, QualType Ty, - SourceLocation Loc, - const CXXScopeSpec *SS = 0); - VarDecl *BuildAnonymousStructUnionMemberPath(FieldDecl *Field, - llvm::SmallVectorImpl &Path); - OwningExprResult - BuildAnonymousStructUnionMemberReference(SourceLocation Loc, - FieldDecl *Field, - Expr *BaseObjectExpr = 0, - SourceLocation OpLoc = SourceLocation()); - OwningExprResult BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS, - LookupResult &R, - const TemplateArgumentListInfo *TemplateArgs); - OwningExprResult BuildImplicitMemberExpr(const CXXScopeSpec &SS, - LookupResult &R, - const TemplateArgumentListInfo *TemplateArgs, - bool IsDefiniteInstance); - bool UseArgumentDependentLookup(const CXXScopeSpec &SS, - const LookupResult &R, - bool HasTrailingLParen); - - OwningExprResult BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS, - DeclarationName Name, - SourceLocation NameLoc); - OwningExprResult BuildDependentDeclRefExpr(const CXXScopeSpec &SS, - DeclarationName Name, - SourceLocation NameLoc, - const TemplateArgumentListInfo *TemplateArgs); - - OwningExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS, - LookupResult &R, - bool ADL); - OwningExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS, - SourceLocation Loc, - NamedDecl *D); - - virtual OwningExprResult ActOnPredefinedExpr(SourceLocation Loc, - tok::TokenKind Kind); - virtual OwningExprResult ActOnNumericConstant(const Token &); - virtual OwningExprResult ActOnCharacterConstant(const Token &); - virtual OwningExprResult ActOnParenExpr(SourceLocation L, SourceLocation R, - ExprArg Val); - virtual OwningExprResult ActOnParenOrParenListExpr(SourceLocation L, - SourceLocation R, - MultiExprArg Val, - TypeTy *TypeOfCast=0); - - /// ActOnStringLiteral - The specified tokens were lexed as pasted string - /// fragments (e.g. "foo" "bar" L"baz"). - virtual OwningExprResult ActOnStringLiteral(const Token *Toks, - unsigned NumToks); - - // Binary/Unary Operators. 'Tok' is the token for the operator. - OwningExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, - unsigned OpcIn, - ExprArg InputArg); - OwningExprResult BuildUnaryOp(Scope *S, SourceLocation OpLoc, - UnaryOperator::Opcode Opc, ExprArg input); - virtual OwningExprResult ActOnUnaryOp(Scope *S, SourceLocation OpLoc, - tok::TokenKind Op, ExprArg Input); - - OwningExprResult CreateSizeOfAlignOfExpr(TypeSourceInfo *T, - SourceLocation OpLoc, - bool isSizeOf, SourceRange R); - OwningExprResult CreateSizeOfAlignOfExpr(Expr *E, SourceLocation OpLoc, - bool isSizeOf, SourceRange R); - virtual OwningExprResult - 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); - - virtual OwningExprResult ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc, - tok::TokenKind Kind, - ExprArg Input); - - virtual OwningExprResult ActOnArraySubscriptExpr(Scope *S, ExprArg Base, - SourceLocation LLoc, - ExprArg Idx, - SourceLocation RLoc); - OwningExprResult CreateBuiltinArraySubscriptExpr(ExprArg Base, - SourceLocation LLoc, - ExprArg Idx, - SourceLocation RLoc); - - OwningExprResult BuildMemberReferenceExpr(ExprArg Base, - QualType BaseType, - SourceLocation OpLoc, - bool IsArrow, - CXXScopeSpec &SS, - NamedDecl *FirstQualifierInScope, - DeclarationName Name, - SourceLocation NameLoc, - const TemplateArgumentListInfo *TemplateArgs); - - OwningExprResult BuildMemberReferenceExpr(ExprArg Base, - QualType BaseType, - SourceLocation OpLoc, bool IsArrow, - const CXXScopeSpec &SS, - NamedDecl *FirstQualifierInScope, - LookupResult &R, - const TemplateArgumentListInfo *TemplateArgs, - bool SuppressQualifierCheck = false); - - OwningExprResult LookupMemberExpr(LookupResult &R, Expr *&Base, - bool &IsArrow, SourceLocation OpLoc, - CXXScopeSpec &SS, - DeclPtrTy ObjCImpDecl, - bool HasTemplateArgs); - - bool CheckQualifiedMemberReference(Expr *BaseExpr, QualType BaseType, - const CXXScopeSpec &SS, - const LookupResult &R); - - OwningExprResult ActOnDependentMemberExpr(ExprArg Base, - QualType BaseType, - bool IsArrow, - SourceLocation OpLoc, - const CXXScopeSpec &SS, - NamedDecl *FirstQualifierInScope, - DeclarationName Name, - SourceLocation NameLoc, - const TemplateArgumentListInfo *TemplateArgs); - - virtual OwningExprResult ActOnMemberAccessExpr(Scope *S, ExprArg Base, - SourceLocation OpLoc, - tok::TokenKind OpKind, - CXXScopeSpec &SS, - UnqualifiedId &Member, - DeclPtrTy ObjCImpDecl, - bool HasTrailingLParen); - - virtual void ActOnDefaultCtorInitializers(DeclPtrTy 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. - virtual OwningExprResult ActOnCallExpr(Scope *S, ExprArg Fn, - SourceLocation LParenLoc, - MultiExprArg Args, - SourceLocation *CommaLocs, - SourceLocation RParenLoc); - OwningExprResult BuildResolvedCallExpr(Expr *Fn, - NamedDecl *NDecl, - SourceLocation LParenLoc, - Expr **Args, unsigned NumArgs, - SourceLocation RParenLoc); - - virtual OwningExprResult ActOnCastExpr(Scope *S, SourceLocation LParenLoc, - TypeTy *Ty, SourceLocation RParenLoc, - ExprArg Op); - OwningExprResult BuildCStyleCastExpr(SourceLocation LParenLoc, - TypeSourceInfo *Ty, - SourceLocation RParenLoc, - ExprArg Op); - - virtual bool TypeIsVectorType(TypeTy *Ty) { - return GetTypeFromParser(Ty)->isVectorType(); - } - - OwningExprResult MaybeConvertParenListExprToParenExpr(Scope *S, ExprArg ME); - OwningExprResult ActOnCastOfParenListExpr(Scope *S, SourceLocation LParenLoc, - SourceLocation RParenLoc, ExprArg E, - TypeSourceInfo *TInfo); - - virtual OwningExprResult ActOnCompoundLiteral(SourceLocation LParenLoc, - TypeTy *Ty, - SourceLocation RParenLoc, - ExprArg Op); - - OwningExprResult BuildCompoundLiteralExpr(SourceLocation LParenLoc, - TypeSourceInfo *TInfo, - SourceLocation RParenLoc, - ExprArg InitExpr); - - virtual OwningExprResult ActOnInitList(SourceLocation LParenLoc, - MultiExprArg InitList, - SourceLocation RParenLoc); - - virtual OwningExprResult ActOnDesignatedInitializer(Designation &Desig, - SourceLocation Loc, - bool GNUSyntax, - OwningExprResult Init); - - virtual OwningExprResult ActOnBinOp(Scope *S, SourceLocation TokLoc, - tok::TokenKind Kind, - ExprArg LHS, ExprArg RHS); - OwningExprResult BuildBinOp(Scope *S, SourceLocation OpLoc, - BinaryOperator::Opcode Opc, - Expr *lhs, Expr *rhs); - OwningExprResult CreateBuiltinBinOp(SourceLocation TokLoc, - unsigned Opc, Expr *lhs, Expr *rhs); - - /// 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); - - /// ActOnAddrLabel - Parse the GNU address of label extension: "&&foo". - virtual OwningExprResult ActOnAddrLabel(SourceLocation OpLoc, - SourceLocation LabLoc, - IdentifierInfo *LabelII); - - virtual OwningExprResult ActOnStmtExpr(SourceLocation LPLoc, StmtArg SubStmt, - SourceLocation RPLoc); // "({..})" - - /// __builtin_offsetof(type, a.b[123][456].c) - OwningExprResult BuildBuiltinOffsetOf(SourceLocation BuiltinLoc, - TypeSourceInfo *TInfo, - OffsetOfComponent *CompPtr, - unsigned NumComponents, - SourceLocation RParenLoc); - virtual OwningExprResult ActOnBuiltinOffsetOf(Scope *S, - SourceLocation BuiltinLoc, - SourceLocation TypeLoc, - TypeTy *Arg1, - OffsetOfComponent *CompPtr, - unsigned NumComponents, - SourceLocation RParenLoc); - - // __builtin_types_compatible_p(type1, type2) - virtual OwningExprResult ActOnTypesCompatibleExpr(SourceLocation BuiltinLoc, - TypeTy *arg1, TypeTy *arg2, - SourceLocation RPLoc); - - // __builtin_choose_expr(constExpr, expr1, expr2) - virtual OwningExprResult ActOnChooseExpr(SourceLocation BuiltinLoc, - ExprArg cond, ExprArg expr1, - ExprArg expr2, SourceLocation RPLoc); - - // __builtin_va_arg(expr, type) - virtual OwningExprResult ActOnVAArg(SourceLocation BuiltinLoc, - ExprArg expr, TypeTy *type, - SourceLocation RPLoc); - - // __null - virtual OwningExprResult ActOnGNUNullExpr(SourceLocation TokenLoc); - - //===------------------------- "Block" Extension ------------------------===// - - /// ActOnBlockStart - This callback is invoked when a block literal is - /// started. - 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); - - //===---------------------------- C++ Features --------------------------===// - - // Act on C++ namespaces - virtual DeclPtrTy ActOnStartNamespaceDef(Scope *S, SourceLocation IdentLoc, - IdentifierInfo *Ident, - SourceLocation LBrace, - AttributeList *AttrList); - virtual void ActOnFinishNamespaceDef(DeclPtrTy Dcl, SourceLocation RBrace); - - NamespaceDecl *getStdNamespace(); - virtual DeclPtrTy ActOnUsingDirective(Scope *CurScope, - SourceLocation UsingLoc, - SourceLocation NamespcLoc, - CXXScopeSpec &SS, - SourceLocation IdentLoc, - IdentifierInfo *NamespcName, - AttributeList *AttrList); - - void PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir); - - virtual DeclPtrTy 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, - SourceLocation IdentLoc, - DeclarationName Name, - AttributeList *AttrList, - bool IsInstantiation, - bool IsTypeName, - SourceLocation TypenameLoc); - - virtual DeclPtrTy 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);" - virtual void AddCXXDirectInitializerToDecl(DeclPtrTy 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. - OwningExprResult - BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, - CXXConstructorDecl *Constructor, MultiExprArg Exprs, - bool RequiresZeroInit = false, - CXXConstructExpr::ConstructionKind ConstructKind = - CXXConstructExpr::CK_Complete); - - // FIXME: Can re remove this and have the above BuildCXXConstructExpr check if - // the constructor can be elidable? - OwningExprResult - BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, - CXXConstructorDecl *Constructor, bool Elidable, - MultiExprArg Exprs, bool RequiresZeroInit = false, - CXXConstructExpr::ConstructionKind ConstructKind = - CXXConstructExpr::CK_Complete); - - /// BuildCXXDefaultArgExpr - Creates a CXXDefaultArgExpr, instantiating - /// the default expr if needed. - OwningExprResult 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. - OwningExprResult MaybeBindToTemporary(Expr *E); - - bool CompleteConstructorCall(CXXConstructorDecl *Constructor, - MultiExprArg ArgsPtr, - SourceLocation Loc, - ASTOwningVector<&ActionBase::DeleteExpr> &ConvertedArgs); - - virtual TypeTy *getDestructorName(SourceLocation TildeLoc, - IdentifierInfo &II, SourceLocation NameLoc, - Scope *S, CXXScopeSpec &SS, - TypeTy *ObjectType, - bool EnteringContext); - - /// 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 E, - SourceLocation RParenLoc); - - OwningExprResult BuildCXXNamedCast(SourceLocation OpLoc, - tok::TokenKind Kind, - TypeSourceInfo *Ty, - ExprArg E, - SourceRange AngleBrackets, - SourceRange Parens); - - OwningExprResult BuildCXXTypeId(QualType TypeInfoType, - SourceLocation TypeidLoc, - TypeSourceInfo *Operand, - SourceLocation RParenLoc); - OwningExprResult BuildCXXTypeId(QualType TypeInfoType, - SourceLocation TypeidLoc, - ExprArg Operand, - SourceLocation RParenLoc); - - /// ActOnCXXTypeid - Parse typeid( something ). - virtual OwningExprResult ActOnCXXTypeid(SourceLocation OpLoc, - SourceLocation LParenLoc, bool isType, - void *TyOrExpr, - SourceLocation RParenLoc); - - //// ActOnCXXThis - Parse 'this' pointer. - virtual OwningExprResult ActOnCXXThis(SourceLocation ThisLoc); - - /// ActOnCXXBoolLiteral - Parse {true,false} literals. - virtual OwningExprResult ActOnCXXBoolLiteral(SourceLocation OpLoc, - tok::TokenKind Kind); - - /// ActOnCXXNullPtrLiteral - Parse 'nullptr'. - virtual OwningExprResult ActOnCXXNullPtrLiteral(SourceLocation Loc); - - //// ActOnCXXThrow - Parse throw expressions. - virtual OwningExprResult ActOnCXXThrow(SourceLocation OpLoc, - ExprArg 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()"). - virtual OwningExprResult ActOnCXXTypeConstructExpr(SourceRange TypeRange, - TypeTy *TypeRep, - SourceLocation LParenLoc, - MultiExprArg Exprs, - SourceLocation *CommaLocs, - SourceLocation RParenLoc); - - /// ActOnCXXNew - Parsed a C++ 'new' expression. - virtual OwningExprResult ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, - SourceLocation PlacementLParen, - MultiExprArg PlacementArgs, - SourceLocation PlacementRParen, - SourceRange TypeIdParens, Declarator &D, - SourceLocation ConstructorLParen, - MultiExprArg ConstructorArgs, - SourceLocation ConstructorRParen); - OwningExprResult BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, - SourceLocation PlacementLParen, - MultiExprArg PlacementArgs, - SourceLocation PlacementRParen, - SourceRange TypeIdParens, - QualType AllocType, - SourceLocation TypeLoc, - SourceRange TypeRange, - ExprArg 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 - virtual OwningExprResult ActOnCXXDelete(SourceLocation StartLoc, - bool UseGlobal, bool ArrayForm, - ExprArg Operand); - - virtual DeclResult ActOnCXXConditionDeclaration(Scope *S, - Declarator &D); - OwningExprResult CheckConditionVariable(VarDecl *ConditionVar, - SourceLocation StmtLoc, - bool ConvertToBoolean); - - /// ActOnUnaryTypeTrait - Parsed one of the unary type trait support - /// pseudo-functions. - virtual OwningExprResult ActOnUnaryTypeTrait(UnaryTypeTrait OTT, - SourceLocation KWLoc, - SourceLocation LParen, - TypeTy *Ty, - SourceLocation RParen); - - virtual OwningExprResult ActOnStartCXXMemberReference(Scope *S, - ExprArg Base, - SourceLocation OpLoc, - tok::TokenKind OpKind, - TypeTy *&ObjectType, - bool &MayBePseudoDestructor); - - OwningExprResult DiagnoseDtorReference(SourceLocation NameLoc, - ExprArg MemExpr); - - OwningExprResult BuildPseudoDestructorExpr(ExprArg Base, - SourceLocation OpLoc, - tok::TokenKind OpKind, - const CXXScopeSpec &SS, - TypeSourceInfo *ScopeType, - SourceLocation CCLoc, - SourceLocation TildeLoc, - PseudoDestructorTypeStorage DestroyedType, - bool HasTrailingLParen); - - virtual OwningExprResult ActOnPseudoDestructorExpr(Scope *S, ExprArg 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); - OwningExprResult MaybeCreateCXXExprWithTemporaries(OwningExprResult SubExpr); - FullExpr CreateFullExpr(Expr *SubExpr); - - virtual OwningExprResult ActOnFinishFullExpr(ExprArg 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 ('::'). - virtual CXXScopeTy *ActOnCXXGlobalScopeSpecifier(Scope *S, - SourceLocation CCLoc); - - bool isAcceptableNestedNameSpecifier(NamedDecl *SD); - NamedDecl *FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS); - - virtual bool isNonTypeNestedNameSpecifier(Scope *S, CXXScopeSpec &SS, - SourceLocation IdLoc, - IdentifierInfo &II, - TypeTy *ObjectType); - - CXXScopeTy *BuildCXXNestedNameSpecifier(Scope *S, - CXXScopeSpec &SS, - SourceLocation IdLoc, - SourceLocation CCLoc, - IdentifierInfo &II, - QualType ObjectType, - NamedDecl *ScopeLookupResult, - bool EnteringContext, - bool ErrorRecoveryLookup); - - virtual CXXScopeTy *ActOnCXXNestedNameSpecifier(Scope *S, - CXXScopeSpec &SS, - SourceLocation IdLoc, - SourceLocation CCLoc, - IdentifierInfo &II, - TypeTy *ObjectType, - bool EnteringContext); - - virtual bool IsInvalidUnlessNestedName(Scope *S, - CXXScopeSpec &SS, - IdentifierInfo &II, - TypeTy *ObjectType, - bool EnteringContext); - - /// ActOnCXXNestedNameSpecifier - Called during parsing of a - /// nested-name-specifier that involves a template-id, e.g., - /// "foo::bar::", 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); - - virtual 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. - virtual 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. - 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); - - // ParseObjCStringLiteral - Parse Objective-C string literals. - virtual ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs, - ExprTy **Strings, - unsigned NumStrings); - - Expr *BuildObjCEncodeExpression(SourceLocation AtLoc, - TypeSourceInfo *EncodedTypeInfo, - SourceLocation RParenLoc); - CXXMemberCallExpr *BuildCXXMemberCallExpr(Expr *Exp, - NamedDecl *FoundDecl, - CXXMethodDecl *Method); - - virtual ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc, - SourceLocation EncodeLoc, - SourceLocation LParenLoc, - TypeTy *Ty, - SourceLocation RParenLoc); - - // ParseObjCSelectorExpression - Build selector expression for @selector - virtual ExprResult ParseObjCSelectorExpression(Selector Sel, - SourceLocation AtLoc, - SourceLocation SelLoc, - SourceLocation LParenLoc, - SourceLocation RParenLoc); - - // ParseObjCProtocolExpression - Build protocol expression for @protocol - virtual ExprResult ParseObjCProtocolExpression(IdentifierInfo * ProtocolName, - SourceLocation AtLoc, - SourceLocation ProtoLoc, - SourceLocation LParenLoc, - SourceLocation RParenLoc); - - //===--------------------------------------------------------------------===// - // C++ Declarations - // - virtual DeclPtrTy ActOnStartLinkageSpecification(Scope *S, - SourceLocation ExternLoc, - SourceLocation LangLoc, - llvm::StringRef Lang, - SourceLocation LBraceLoc); - virtual DeclPtrTy ActOnFinishLinkageSpecification(Scope *S, - DeclPtrTy LinkageSpec, - SourceLocation RBraceLoc); - - - //===--------------------------------------------------------------------===// - // C++ Classes - // - virtual bool isCurrentClassName(const IdentifierInfo &II, Scope *S, - const CXXScopeSpec *SS); - - virtual DeclPtrTy ActOnAccessSpecifier(AccessSpecifier Access, - SourceLocation ASLoc, - SourceLocation ColonLoc); - - virtual DeclPtrTy ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, - Declarator &D, - MultiTemplateParamsArg TemplateParameterLists, - ExprTy *BitfieldWidth, - ExprTy *Init, bool IsDefinition, - bool Deleted = false); - - virtual MemInitResult ActOnMemInitializer(DeclPtrTy ConstructorD, - Scope *S, - CXXScopeSpec &SS, - IdentifierInfo *MemberOrBase, - TypeTy *TemplateTypeTy, - SourceLocation IdLoc, - SourceLocation LParenLoc, - ExprTy **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, 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 VTablesUsed; - - /// \brief A list of all of the dynamic classes in this translation - /// unit. - llvm::SmallVector 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 virtual 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); - - virtual void ActOnMemInitializers(DeclPtrTy ConstructorDecl, - SourceLocation ColonLoc, - MemInitTy **MemInits, unsigned NumMemInits, - bool AnyErrors); - - void CheckCompletedCXXClass(CXXRecordDecl *Record); - virtual void ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, - DeclPtrTy TagDecl, - SourceLocation LBrac, - SourceLocation RBrac, - AttributeList *AttrList); - - virtual void ActOnReenterTemplateScope(Scope *S, DeclPtrTy Template); - virtual void ActOnStartDelayedMemberDeclarations(Scope *S, - DeclPtrTy Record); - virtual void ActOnStartDelayedCXXMethodDeclaration(Scope *S, - DeclPtrTy Method); - virtual void ActOnDelayedCXXMethodParameter(Scope *S, DeclPtrTy Param); - virtual void ActOnFinishDelayedCXXMethodDeclaration(Scope *S, - DeclPtrTy Method); - virtual void ActOnFinishDelayedMemberDeclarations(Scope *S, - DeclPtrTy Record); - - virtual DeclPtrTy ActOnStaticAssertDeclaration(SourceLocation AssertLoc, - ExprArg AssertExpr, - ExprArg AssertMessageExpr); - - FriendDecl *CheckFriendTypeDecl(SourceLocation FriendLoc, - TypeSourceInfo *TSInfo); - DeclPtrTy ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, - MultiTemplateParamsArg TemplateParams); - DeclPtrTy ActOnFriendFunctionDecl(Scope *S, Declarator &D, bool IsDefinition, - MultiTemplateParamsArg TemplateParams); - - QualType CheckConstructorDeclarator(Declarator &D, QualType R, - FunctionDecl::StorageClass& SC); - void CheckConstructor(CXXConstructorDecl *Constructor); - QualType CheckDestructorDeclarator(Declarator &D, QualType R, - FunctionDecl::StorageClass& SC); - bool CheckDestructor(CXXDestructorDecl *Destructor); - void CheckConversionDeclarator(Declarator &D, QualType &R, - FunctionDecl::StorageClass& SC); - DeclPtrTy ActOnConversionDeclarator(CXXConversionDecl *Conversion); - - //===--------------------------------------------------------------------===// - // C++ Derived Classes - // - - /// ActOnBaseSpecifier - Parsed a base specifier - CXXBaseSpecifier *CheckBaseSpecifier(CXXRecordDecl *Class, - SourceRange SpecifierRange, - bool Virtual, AccessSpecifier Access, - QualType BaseType, - SourceLocation BaseLoc); - - /// 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); - - virtual BaseResult ActOnBaseSpecifier(DeclPtrTy classdecl, - SourceRange SpecifierRange, - bool Virtual, AccessSpecifier Access, - TypeTy *basetype, SourceLocation - BaseLoc); - - bool AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases, - unsigned NumBases); - virtual void ActOnBaseSpecifiers(DeclPtrTy 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, - CXXBaseSpecifierArray &BasePath); - - bool BasePathInvolvesVirtualBase(const CXXBaseSpecifierArray &BasePath); - - bool CheckDerivedToBaseConversion(QualType Derived, QualType Base, - SourceLocation Loc, SourceRange Range, - CXXBaseSpecifierArray *BasePath = 0, - bool IgnoreAccess = false); - bool CheckDerivedToBaseConversion(QualType Derived, QualType Base, - unsigned InaccessibleBaseID, - unsigned AmbigiousBaseConvID, - SourceLocation Loc, SourceRange Range, - DeclarationName Name, - CXXBaseSpecifierArray *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(DelayedDiagnostic &DD, Decl *Ctx); - - /// A flag to suppress access checking. - bool SuppressAccessChecking; - - void ActOnStartSuppressingAccessChecks(); - void ActOnStopSuppressingAccessChecks(); - - enum AbstractDiagSelID { - AbstractNone = -1, - AbstractReturnType, - AbstractParamType, - AbstractVariableType, - AbstractFieldType - }; - - bool RequireNonAbstractType(SourceLocation Loc, QualType T, - const PartialDiagnostic &PD, - const CXXRecordDecl *CurrentRD = 0); - - bool RequireNonAbstractType(SourceLocation Loc, QualType T, unsigned DiagID, - AbstractDiagSelID SelID = AbstractNone, - const CXXRecordDecl *CurrentRD = 0); - - //===--------------------------------------------------------------------===// - // 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); - - virtual TemplateNameKind isTemplateName(Scope *S, - CXXScopeSpec &SS, - UnqualifiedId &Name, - TypeTy *ObjectType, - bool EnteringContext, - TemplateTy &Template, - bool &MemberOfUnknownSpecialization); - - virtual bool DiagnoseUnknownTemplateName(const IdentifierInfo &II, - SourceLocation IILoc, - Scope *S, - const CXXScopeSpec *SS, - TemplateTy &SuggestedTemplate, - TemplateNameKind &SuggestedKind); - - bool DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl); - TemplateDecl *AdjustDeclIfTemplate(DeclPtrTy &Decl); - - 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); - - QualType CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc); - virtual DeclPtrTy ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, - unsigned Depth, - unsigned Position, - SourceLocation EqualLoc, - ExprArg DefaultArg); - virtual DeclPtrTy ActOnTemplateTemplateParameter(Scope *S, - SourceLocation TmpLoc, - TemplateParamsTy *Params, - IdentifierInfo *ParamName, - SourceLocation ParamNameLoc, - unsigned Depth, - unsigned Position, - SourceLocation EqualLoc, - const ParsedTemplateArgument &DefaultArg); - - virtual TemplateParamsTy * - ActOnTemplateParameterList(unsigned Depth, - SourceLocation ExportLoc, - SourceLocation TemplateLoc, - SourceLocation LAngleLoc, - DeclPtrTy *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); - - virtual TypeResult - ActOnTemplateIdType(TemplateTy Template, SourceLocation TemplateLoc, - SourceLocation LAngleLoc, - ASTTemplateArgsPtr TemplateArgs, - SourceLocation RAngleLoc); - - virtual TypeResult ActOnTagTemplateIdType(TypeResult Type, - TagUseKind TUK, - DeclSpec::TST TagSpec, - SourceLocation TagLoc); - - OwningExprResult BuildTemplateIdExpr(const CXXScopeSpec &SS, - LookupResult &R, - bool RequiresADL, - const TemplateArgumentListInfo &TemplateArgs); - OwningExprResult BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS, - DeclarationName Name, - SourceLocation NameLoc, - const TemplateArgumentListInfo &TemplateArgs); - - virtual TemplateNameKind ActOnDependentTemplateName(Scope *S, - SourceLocation TemplateKWLoc, - CXXScopeSpec &SS, - UnqualifiedId &Name, - TypeTy *ObjectType, - bool EnteringContext, - TemplateTy &Template); - - bool CheckClassTemplatePartialSpecializationArgs( - TemplateParameterList *TemplateParams, - const TemplateArgumentListBuilder &TemplateArgs, - bool &MirrorsPrimaryTemplate); - - 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); - - virtual DeclPtrTy ActOnTemplateDeclarator(Scope *S, - MultiTemplateParamsArg TemplateParameterLists, - Declarator &D); - - virtual DeclPtrTy 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); - - 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); - - virtual DeclResult - ActOnExplicitInstantiation(Scope *S, - SourceLocation ExternLoc, - SourceLocation TemplateLoc, - unsigned TagSpec, - SourceLocation KWLoc, - CXXScopeSpec &SS, - IdentifierInfo *Name, - SourceLocation NameLoc, - AttributeList *Attr); - - virtual 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); - - OwningExprResult - BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg, - QualType ParamType, - SourceLocation Loc); - OwningExprResult - 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 struct X; - /// template 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 class TT> struct X; - /// template 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 class Metafun> struct X; - /// template struct integer_c; - /// X 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. - virtual 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". - /// - /// \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. - virtual TypeResult - ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, - const CXXScopeSpec &SS, SourceLocation TemplateLoc, - TypeTy *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); - - 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_InconsistentQuals, - /// \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 - }; - - /// \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; - }; - - TemplateDeductionResult - DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, - const TemplateArgumentList &TemplateArgs, - TemplateDeductionInfo &Info); - - TemplateDeductionResult - SubstituteExplicitTemplateArguments(FunctionTemplateDecl *FunctionTemplate, - const TemplateArgumentListInfo &ExplicitTemplateArgs, - llvm::SmallVectorImpl &Deduced, - llvm::SmallVectorImpl &ParamTypes, - QualType *FunctionType, - TemplateDeductionInfo &Info); - - TemplateDeductionResult - FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, - llvm::SmallVectorImpl &Deduced, - unsigned NumExplicitlySpecified, - FunctionDecl *&Specialization, - TemplateDeductionInfo &Info); - - TemplateDeductionResult - DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, - const TemplateArgumentListInfo *ExplicitTemplateArgs, - Expr **Args, unsigned NumArgs, - FunctionDecl *&Specialization, - TemplateDeductionInfo &Info); - - TemplateDeductionResult - DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, - const TemplateArgumentListInfo *ExplicitTemplateArgs, - QualType ArgFunctionType, - FunctionDecl *&Specialization, - TemplateDeductionInfo &Info); - - TemplateDeductionResult - DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, - QualType ToType, - CXXConversionDecl *&Specialization, - TemplateDeductionInfo &Info); - - TemplateDeductionResult - DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, - const TemplateArgumentListInfo *ExplicitTemplateArgs, - FunctionDecl *&Specialization, - 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 &Used); - void MarkDeducedTemplateParameters(FunctionTemplateDecl *FunctionTemplate, - llvm::SmallVectorImpl &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 - 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 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 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 T add(T x, T y) { return x + y; } - /// \endcode - /// - /// when we instantiate add, we will introduce a mapping from - /// the ParmVarDecl for 'x' that occurs in the template to the - /// instantiated ParmVarDecl for 'x'. - llvm::DenseMap 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(getInstantiationOf(cast(Var))); - } - - ParmVarDecl *getInstantiationOf(const ParmVarDecl *Var) { - return cast(getInstantiationOf(cast(Var))); - } - - NonTypeTemplateParmDecl *getInstantiationOf( - const NonTypeTemplateParmDecl *Var) { - return cast(getInstantiationOf(cast(Var))); - } - - void InstantiatedLocal(const Decl *D, Decl *Inst); - }; - - /// \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 PendingImplicitInstantiation; - - /// \brief The queue of implicit template instantiations that are required - /// but have not yet been performed. - std::deque PendingImplicitInstantiations; - - /// \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 PendingLocalImplicitInstantiations; - - void PerformPendingImplicitInstantiations(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); - OwningExprResult SubstExpr(Expr *E, - const MultiLevelTemplateArgumentList &TemplateArgs); - - OwningStmtResult 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); - - 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); - - 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. - 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); - - virtual DeclPtrTy ActOnCompatiblityAlias( - SourceLocation AtCompatibilityAliasLoc, - IdentifierInfo *AliasName, SourceLocation AliasLocation, - IdentifierInfo *ClassName, SourceLocation ClassLocation); - - void CheckForwardProtocolDeclarationForCircularDependency( - IdentifierInfo *PName, - SourceLocation &PLoc, SourceLocation PrevLoc, - const ObjCList &PList); - - virtual DeclPtrTy ActOnStartProtocolInterface( - SourceLocation AtProtoInterfaceLoc, - IdentifierInfo *ProtocolName, SourceLocation ProtocolLoc, - const DeclPtrTy *ProtoRefNames, unsigned NumProtoRefs, - const SourceLocation *ProtoLocs, - SourceLocation EndProtoLoc, - AttributeList *AttrList); - - virtual DeclPtrTy ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc, - IdentifierInfo *ClassName, - SourceLocation ClassLoc, - IdentifierInfo *CategoryName, - SourceLocation CategoryLoc, - const DeclPtrTy *ProtoRefs, - unsigned NumProtoRefs, - const SourceLocation *ProtoLocs, - SourceLocation EndProtoLoc); - - virtual DeclPtrTy ActOnStartClassImplementation( - SourceLocation AtClassImplLoc, - IdentifierInfo *ClassName, SourceLocation ClassLoc, - IdentifierInfo *SuperClassname, - SourceLocation SuperClassLoc); - - virtual DeclPtrTy ActOnStartCategoryImplementation( - SourceLocation AtCatImplLoc, - IdentifierInfo *ClassName, - SourceLocation ClassLoc, - IdentifierInfo *CatName, - SourceLocation CatLoc); - - virtual DeclPtrTy ActOnForwardClassDeclaration(SourceLocation Loc, - IdentifierInfo **IdentList, - SourceLocation *IdentLocs, - unsigned NumElts); - - virtual DeclPtrTy ActOnForwardProtocolDeclaration(SourceLocation AtProtoclLoc, - const IdentifierLocPair *IdentList, - unsigned NumElts, - AttributeList *attrList); - - virtual void FindProtocolDeclaration(bool WarnOnDeclarations, - const IdentifierLocPair *ProtocolId, - unsigned NumProtocols, - llvm::SmallVectorImpl &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(DeclPtrTy 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, DeclPtrTy MergeProtocols); - - void DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT, - ObjCInterfaceDecl *ID); - - void MatchOneProtocolPropertiesInClass(Decl *CDecl, - ObjCProtocolDecl *PDecl); - - 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); - - virtual DeclPtrTy ActOnProperty(Scope *S, SourceLocation AtLoc, - FieldDeclarator &FD, ObjCDeclSpec &ODS, - Selector GetterSel, Selector SetterSel, - DeclPtrTy ClassCategory, - bool *OverridingProperty, - tok::ObjCKeywordKind MethodImplKind); - - virtual DeclPtrTy ActOnPropertyImplDecl(Scope *S, - SourceLocation AtLoc, - SourceLocation PropertyLoc, - bool ImplKind,DeclPtrTy ClassImplDecl, - IdentifierInfo *PropertyId, - IdentifierInfo *PropertyIvar); - - virtual DeclPtrTy ActOnMethodDeclaration( - SourceLocation BeginLoc, // location of the + or -. - SourceLocation EndLoc, // location of the ; or {. - tok::TokenKind MethodType, - DeclPtrTy ClassDecl, ObjCDeclSpec &ReturnQT, TypeTy *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); - - OwningExprResult - HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, - Expr *BaseExpr, - DeclarationName MemberName, - SourceLocation MemberLoc); - - virtual OwningExprResult - ActOnClassPropertyRefExpr(IdentifierInfo &receiverName, - IdentifierInfo &propertyName, - SourceLocation receiverNameLoc, - SourceLocation propertyNameLoc); - - virtual ObjCMessageKind getObjCMessageKind(Scope *S, - IdentifierInfo *Name, - SourceLocation NameLoc, - bool IsSuper, - bool HasTrailingDot, - TypeTy *&ReceiverType); - - virtual OwningExprResult ActOnSuperMessage(Scope *S, SourceLocation SuperLoc, - Selector Sel, - SourceLocation LBracLoc, - SourceLocation SelectorLoc, - SourceLocation RBracLoc, - MultiExprArg Args); - - OwningExprResult BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, - QualType ReceiverType, - SourceLocation SuperLoc, - Selector Sel, - ObjCMethodDecl *Method, - SourceLocation LBracLoc, - SourceLocation RBracLoc, - MultiExprArg Args); - - virtual OwningExprResult ActOnClassMessage(Scope *S, - TypeTy *Receiver, - Selector Sel, - SourceLocation LBracLoc, - SourceLocation SelectorLoc, - SourceLocation RBracLoc, - MultiExprArg Args); - - OwningExprResult BuildInstanceMessage(ExprArg Receiver, - QualType ReceiverType, - SourceLocation SuperLoc, - Selector Sel, - ObjCMethodDecl *Method, - SourceLocation LBracLoc, - SourceLocation RBracLoc, - MultiExprArg Args); - - virtual OwningExprResult ActOnInstanceMessage(Scope *S, - ExprArg Receiver, - Selector Sel, - SourceLocation LBracLoc, - SourceLocation SelectorLoc, - SourceLocation RBracLoc, - MultiExprArg Args); - - - /// ActOnPragmaOptionsAlign - Called on well formed #pragma options align. - virtual void ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind, - SourceLocation PragmaLoc, - SourceLocation KindLoc); - - /// ActOnPragmaPack - Called on well formed #pragma pack(...). - virtual void ActOnPragmaPack(PragmaPackKind Kind, - IdentifierInfo *Name, - ExprTy *Alignment, - SourceLocation PragmaLoc, - SourceLocation LParenLoc, - SourceLocation RParenLoc); - - /// ActOnPragmaUnused - Called on well-formed '#pragma unused'. - virtual void ActOnPragmaUnused(const Token *Identifiers, - unsigned NumIdentifiers, Scope *curScope, - SourceLocation PragmaLoc, - SourceLocation LParenLoc, - SourceLocation RParenLoc); - - NamedDecl *DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II); - void DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W); - - /// ActOnPragmaWeakID - Called on well formed #pragma weak ident. - virtual void ActOnPragmaWeakID(IdentifierInfo* WeakName, - SourceLocation PragmaLoc, - SourceLocation WeakNameLoc); - - /// ActOnPragmaWeakAlias - Called on well formed #pragma weak ident = ident. - virtual 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(); - - /// AddAlignedAttr - Adds an aligned attribute to a particular declaration. - void AddAlignedAttr(SourceLocation AttrLoc, Decl *D, 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, CastExpr::CastKind Kind, - bool isLvalue = false, - CXXBaseSpecifierArray BasePath = - CXXBaseSpecifierArray()); - - // 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 &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 " = "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); - - /// 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, - CastExpr::CastKind &Kind, CXXBaseSpecifierArray &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, - CastExpr::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, - 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, - CastExpr::CastKind &Kind, - CXXBaseSpecifierArray &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); - - virtual OwningExprResult ActOnBooleanCondition(Scope *S, SourceLocation Loc, - ExprArg 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 - //@{ - virtual void CodeCompleteOrdinaryName(Scope *S, - CodeCompletionContext CompletionContext); - virtual void CodeCompleteExpression(Scope *S, QualType T); - virtual void CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *Base, - SourceLocation OpLoc, - bool IsArrow); - virtual void CodeCompleteTag(Scope *S, unsigned TagSpec); - virtual void CodeCompleteCase(Scope *S); - virtual void CodeCompleteCall(Scope *S, ExprTy *Fn, - ExprTy **Args, unsigned NumArgs); - virtual void CodeCompleteInitializer(Scope *S, DeclPtrTy D); - virtual void CodeCompleteReturn(Scope *S); - virtual void CodeCompleteAssignmentRHS(Scope *S, ExprTy *LHS); - - virtual void CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, - bool EnteringContext); - virtual void CodeCompleteUsing(Scope *S); - virtual void CodeCompleteUsingDirective(Scope *S); - virtual void CodeCompleteNamespaceDecl(Scope *S); - virtual void CodeCompleteNamespaceAliasDecl(Scope *S); - virtual void CodeCompleteOperatorName(Scope *S); - - virtual void CodeCompleteObjCAtDirective(Scope *S, DeclPtrTy ObjCImpDecl, - bool InInterface); - virtual void CodeCompleteObjCAtVisibility(Scope *S); - virtual void CodeCompleteObjCAtStatement(Scope *S); - virtual void CodeCompleteObjCAtExpression(Scope *S); - virtual void CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS); - virtual void CodeCompleteObjCPropertyGetter(Scope *S, DeclPtrTy ClassDecl, - DeclPtrTy *Methods, - unsigned NumMethods); - virtual void CodeCompleteObjCPropertySetter(Scope *S, DeclPtrTy ClassDecl, - DeclPtrTy *Methods, - unsigned NumMethods); - virtual void CodeCompleteObjCMessageReceiver(Scope *S); - virtual void CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, - IdentifierInfo **SelIdents, - unsigned NumSelIdents); - virtual void CodeCompleteObjCClassMessage(Scope *S, TypeTy *Receiver, - IdentifierInfo **SelIdents, - unsigned NumSelIdents); - virtual void CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver, - IdentifierInfo **SelIdents, - unsigned NumSelIdents); - virtual void CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols, - unsigned NumProtocols); - virtual void CodeCompleteObjCProtocolDecl(Scope *S); - virtual void CodeCompleteObjCInterfaceDecl(Scope *S); - virtual void CodeCompleteObjCSuperclass(Scope *S, - IdentifierInfo *ClassName, - SourceLocation ClassNameLoc); - virtual void CodeCompleteObjCImplementationDecl(Scope *S); - virtual void CodeCompleteObjCInterfaceCategory(Scope *S, - IdentifierInfo *ClassName, - SourceLocation ClassNameLoc); - virtual void CodeCompleteObjCImplementationCategory(Scope *S, - IdentifierInfo *ClassName, - SourceLocation ClassNameLoc); - virtual void CodeCompleteObjCPropertyDefinition(Scope *S, - DeclPtrTy ObjCImpDecl); - virtual void CodeCompleteObjCPropertySynthesizeIvar(Scope *S, - IdentifierInfo *PropertyName, - DeclPtrTy ObjCImpDecl); - virtual void CodeCompleteObjCMethodDecl(Scope *S, - bool IsInstanceMethod, - TypeTy *ReturnType, - DeclPtrTy IDecl); - virtual void CodeCompleteObjCMethodDeclSelector(Scope *S, - bool IsInstanceMethod, - bool AtParameterName, - TypeTy *ReturnType, - IdentifierInfo **SelIdents, - unsigned NumSelIdents); - - //@} - - //===--------------------------------------------------------------------===// - // 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); - - Action::OwningExprResult 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. - Action::OwningExprResult SemaBuiltinShuffleVector(CallExpr *TheCall); - -private: - bool SemaBuiltinPrefetch(CallExpr *TheCall); - bool SemaBuiltinObjectSize(CallExpr *TheCall); - bool SemaBuiltinLongjmp(CallExpr *TheCall); - OwningExprResult SemaBuiltinAtomicOverloaded(OwningExprResult 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); - void CheckPrintfString(const StringLiteral *FExpr, const Expr *OrigFormatExpr, - const CallExpr *TheCall, bool HasVAListArg, - unsigned format_idx, unsigned firstDataArg); - void CheckNonNullArguments(const NonNullAttr *NonNull, - const CallExpr *TheCall); - void CheckPrintfArguments(const CallExpr *TheCall, bool HasVAListArg, - unsigned format_idx, unsigned firstDataArg); - void CheckReturnStackAddr(Expr *RetValExp, QualType lhsType, - SourceLocation ReturnLoc); - void CheckFloatComparison(SourceLocation loc, Expr* lex, Expr* rex); - void CheckImplicitConversions(Expr *E); -}; - -//===--------------------------------------------------------------------===// -// Typed version of Parser::ExprArg (smart pointer for wrapping Expr pointers). -template -class ExprOwningPtr : public Action::ExprArg { -public: - ExprOwningPtr(Sema *S, T *expr) : Action::ExprArg(*S, expr) {} - - void reset(T* p) { Action::ExprArg::operator=(p); } - T* get() const { return static_cast(Action::ExprArg::get()); } - T* take() { return static_cast(Action::ExprArg::take()); } - T* release() { return take(); } - - T& operator*() const { return *get(); } - T* operator->() const { return get(); } -}; - -} // end namespace clang - -#endif diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp index e110e3dfa471..e629f0fd35bf 100644 --- a/lib/Sema/SemaAccess.cpp +++ b/lib/Sema/SemaAccess.cpp @@ -11,9 +11,10 @@ // //===----------------------------------------------------------------------===// -#include "Sema.h" -#include "SemaInit.h" -#include "Lookup.h" +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/DelayedDiagnostic.h" +#include "clang/Sema/Initialization.h" +#include "clang/Sema/Lookup.h" #include "clang/AST/ASTContext.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclCXX.h" @@ -22,6 +23,7 @@ #include "clang/AST/ExprCXX.h" using namespace clang; +using namespace sema; /// A copy of Sema's enum without AR_delayed. enum AccessResult { @@ -132,10 +134,10 @@ struct EffectiveContext { bool Dependent; }; -/// Like Sema's AccessedEntity, but kindly lets us scribble all over +/// Like sema:;AccessedEntity, but kindly lets us scribble all over /// it. -struct AccessTarget : public Sema::AccessedEntity { - AccessTarget(const Sema::AccessedEntity &Entity) +struct AccessTarget : public AccessedEntity { + AccessTarget(const AccessedEntity &Entity) : AccessedEntity(Entity) { initialize(); } @@ -562,6 +564,130 @@ static AccessResult GetFriendKind(Sema &S, return OnFailure; } +namespace { + +/// A helper class for checking for a friend which will grant access +/// to a protected instance member. +struct ProtectedFriendContext { + Sema &S; + const EffectiveContext &EC; + const CXXRecordDecl *NamingClass; + bool CheckDependent; + bool EverDependent; + + /// The path down to the current base class. + llvm::SmallVector CurPath; + + ProtectedFriendContext(Sema &S, const EffectiveContext &EC, + const CXXRecordDecl *InstanceContext, + const CXXRecordDecl *NamingClass) + : S(S), EC(EC), NamingClass(NamingClass), + CheckDependent(InstanceContext->isDependentContext() || + NamingClass->isDependentContext()), + EverDependent(false) {} + + /// Check classes in the current path for friendship, starting at + /// the given index. + bool checkFriendshipAlongPath(unsigned I) { + assert(I < CurPath.size()); + for (unsigned E = CurPath.size(); I != E; ++I) { + switch (GetFriendKind(S, EC, CurPath[I])) { + case AR_accessible: return true; + case AR_inaccessible: continue; + case AR_dependent: EverDependent = true; continue; + } + } + return false; + } + + /// Perform a search starting at the given class. + /// + /// PrivateDepth is the index of the last (least derived) class + /// along the current path such that a notional public member of + /// the final class in the path would have access in that class. + bool findFriendship(const CXXRecordDecl *Cur, unsigned PrivateDepth) { + // If we ever reach the naming class, check the current path for + // friendship. We can also stop recursing because we obviously + // won't find the naming class there again. + if (Cur == NamingClass) + return checkFriendshipAlongPath(PrivateDepth); + + if (CheckDependent && MightInstantiateTo(Cur, NamingClass)) + EverDependent = true; + + // Recurse into the base classes. + for (CXXRecordDecl::base_class_const_iterator + I = Cur->bases_begin(), E = Cur->bases_end(); I != E; ++I) { + + // If this is private inheritance, then a public member of the + // base will not have any access in classes derived from Cur. + unsigned BasePrivateDepth = PrivateDepth; + if (I->getAccessSpecifier() == AS_private) + BasePrivateDepth = CurPath.size() - 1; + + const CXXRecordDecl *RD; + + QualType T = I->getType(); + if (const RecordType *RT = T->getAs()) { + RD = cast(RT->getDecl()); + } else if (const InjectedClassNameType *IT + = T->getAs()) { + RD = IT->getDecl(); + } else { + assert(T->isDependentType() && "non-dependent base wasn't a record?"); + EverDependent = true; + continue; + } + + // Recurse. We don't need to clean up if this returns true. + CurPath.push_back(RD); + if (findFriendship(RD->getCanonicalDecl(), BasePrivateDepth)) + return true; + CurPath.pop_back(); + } + + return false; + } + + bool findFriendship(const CXXRecordDecl *Cur) { + assert(CurPath.empty()); + CurPath.push_back(Cur); + return findFriendship(Cur, 0); + } +}; +} + +/// Search for a class P that EC is a friend of, under the constraint +/// InstanceContext <= P <= NamingClass +/// and with the additional restriction that a protected member of +/// NamingClass would have some natural access in P. +/// +/// That second condition isn't actually quite right: the condition in +/// the standard is whether the target would have some natural access +/// in P. The difference is that the target might be more accessible +/// along some path not passing through NamingClass. Allowing that +/// introduces two problems: +/// - It breaks encapsulation because you can suddenly access a +/// forbidden base class's members by subclassing it elsewhere. +/// - It makes access substantially harder to compute because it +/// breaks the hill-climbing algorithm: knowing that the target is +/// accessible in some base class would no longer let you change +/// the question solely to whether the base class is accessible, +/// because the original target might have been more accessible +/// because of crazy subclassing. +/// So we don't implement that. +static AccessResult GetProtectedFriendKind(Sema &S, const EffectiveContext &EC, + const CXXRecordDecl *InstanceContext, + const CXXRecordDecl *NamingClass) { + assert(InstanceContext->getCanonicalDecl() == InstanceContext); + assert(NamingClass->getCanonicalDecl() == NamingClass); + + ProtectedFriendContext PRC(S, EC, InstanceContext, NamingClass); + if (PRC.findFriendship(InstanceContext)) return AR_accessible; + if (PRC.EverDependent) return AR_dependent; + return AR_inaccessible; +} + static AccessResult HasAccess(Sema &S, const EffectiveContext &EC, const CXXRecordDecl *NamingClass, @@ -629,20 +755,25 @@ static AccessResult HasAccess(Sema &S, } } - if (!NamingClass->hasFriends()) - return OnFailure; - - // Don't consider friends if we're under the [class.protected] - // restriction, above. + // [M3] and [B3] say that, if the target is protected in N, we grant + // access if the access occurs in a friend or member of some class P + // that's a subclass of N and where the target has some natural + // access in P. The 'member' aspect is easy to handle because P + // would necessarily be one of the effective-context records, and we + // address that above. The 'friend' aspect is completely ridiculous + // to implement because there are no restrictions at all on P + // *unless* the [class.protected] restriction applies. If it does, + // however, we should ignore whether the naming class is a friend, + // and instead rely on whether any potential P is a friend. if (Access == AS_protected && Target.hasInstanceContext()) { const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S); if (!InstanceContext) return AR_dependent; - - switch (IsDerivedFromInclusive(InstanceContext, NamingClass)) { - case AR_accessible: break; + switch (GetProtectedFriendKind(S, EC, InstanceContext, NamingClass)) { + case AR_accessible: return AR_accessible; case AR_inaccessible: return OnFailure; case AR_dependent: return AR_dependent; } + llvm_unreachable("impossible friendship kind"); } switch (GetFriendKind(S, EC, NamingClass)) { @@ -799,6 +930,57 @@ static CXXBasePath *FindBestPath(Sema &S, return BestPath; } +/// Given that an entity has protected natural access, check whether +/// access might be denied because of the protected member access +/// restriction. +/// +/// \return true if a note was emitted +static bool TryDiagnoseProtectedAccess(Sema &S, const EffectiveContext &EC, + AccessTarget &Target) { + // Only applies to instance accesses. + if (!Target.hasInstanceContext()) + return false; + assert(Target.isMemberAccess()); + NamedDecl *D = Target.getTargetDecl(); + + const CXXRecordDecl *DeclaringClass = Target.getDeclaringClass(); + DeclaringClass = DeclaringClass->getCanonicalDecl(); + + for (EffectiveContext::record_iterator + I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { + const CXXRecordDecl *ECRecord = *I; + switch (IsDerivedFromInclusive(ECRecord, DeclaringClass)) { + case AR_accessible: break; + case AR_inaccessible: continue; + case AR_dependent: continue; + } + + // The effective context is a subclass of the declaring class. + // If that class isn't a superclass of the instance context, + // then the [class.protected] restriction applies. + + // To get this exactly right, this might need to be checked more + // holistically; it's not necessarily the case that gaining + // access here would grant us access overall. + + const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S); + assert(InstanceContext && "diagnosing dependent access"); + + switch (IsDerivedFromInclusive(InstanceContext, ECRecord)) { + case AR_accessible: continue; + case AR_dependent: continue; + case AR_inaccessible: + S.Diag(D->getLocation(), diag::note_access_protected_restricted) + << (InstanceContext != Target.getNamingClass()->getCanonicalDecl()) + << S.Context.getTypeDeclType(InstanceContext) + << S.Context.getTypeDeclType(ECRecord); + return true; + } + } + + return false; +} + /// Diagnose the path which caused the given declaration or base class /// to become inaccessible. static void DiagnoseAccessPath(Sema &S, @@ -817,6 +999,10 @@ static void DiagnoseAccessPath(Sema &S, if (D && (Access == D->getAccess() || D->getAccess() == AS_private)) { switch (HasAccess(S, EC, DeclaringClass, D->getAccess(), Entity)) { case AR_inaccessible: { + if (Access == AS_protected && + TryDiagnoseProtectedAccess(S, EC, Entity)) + return; + S.Diag(D->getLocation(), diag::note_access_natural) << (unsigned) (Access == AS_protected) << /*FIXME: not implicitly*/ 0; @@ -1033,7 +1219,7 @@ static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc, // access control. if (S.CurContext->isFileContext() && S.ParsingDeclDepth) { S.DelayedDiagnostics.push_back( - Sema::DelayedDiagnostic::makeAccess(Loc, Entity)); + DelayedDiagnostic::makeAccess(Loc, Entity)); return Sema::AR_delayed; } @@ -1266,7 +1452,7 @@ Sema::AccessResult Sema::CheckAddressOfMemberAccess(Expr *OvlExpr, Found.getAccess() == AS_public) return AR_accessible; - OverloadExpr *Ovl = OverloadExpr::find(OvlExpr).getPointer(); + OverloadExpr *Ovl = OverloadExpr::find(OvlExpr).Expression; CXXRecordDecl *NamingClass = Ovl->getNamingClass(); AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found, diff --git a/lib/Sema/SemaAttr.cpp b/lib/Sema/SemaAttr.cpp index 69f27b0ada7d..0921156b932f 100644 --- a/lib/Sema/SemaAttr.cpp +++ b/lib/Sema/SemaAttr.cpp @@ -12,8 +12,9 @@ // //===----------------------------------------------------------------------===// -#include "Sema.h" -#include "Lookup.h" +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/Lookup.h" +#include "clang/AST/Attr.h" #include "clang/AST/Expr.h" #include "clang/Basic/TargetInfo.h" #include "clang/Lex/Preprocessor.h" @@ -62,18 +63,30 @@ namespace { /// alignment to the previous value. If \arg Name is non-zero then /// the first such named record is popped, otherwise the top record /// is popped. Returns true if the pop succeeded. - bool pop(IdentifierInfo *Name); + bool pop(IdentifierInfo *Name, bool IsReset); }; } // end anonymous namespace. -bool PragmaPackStack::pop(IdentifierInfo *Name) { - if (Stack.empty()) - return false; - +bool PragmaPackStack::pop(IdentifierInfo *Name, bool IsReset) { // If name is empty just pop top. if (!Name) { - Alignment = Stack.back().Alignment; - Stack.pop_back(); + // An empty stack is a special case... + if (Stack.empty()) { + // If this isn't a reset, it is always an error. + if (!IsReset) + return false; + + // Otherwise, it is an error only if some alignment has been set. + if (!Alignment) + return false; + + // Otherwise, reset to the default alignment. + Alignment = 0; + } else { + Alignment = Stack.back().Alignment; + Stack.pop_back(); + } + return true; } @@ -108,9 +121,11 @@ void Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) { // Otherwise, check to see if we need a max field alignment attribute. if (unsigned Alignment = Stack->getAlignment()) { if (Alignment == PackStackEntry::kMac68kAlignmentSentinel) - RD->addAttr(::new (Context) AlignMac68kAttr()); + RD->addAttr(::new (Context) AlignMac68kAttr(SourceLocation(), Context)); else - RD->addAttr(::new (Context) MaxFieldAlignmentAttr(Alignment * 8)); + RD->addAttr(::new (Context) MaxFieldAlignmentAttr(SourceLocation(), + Context, + Alignment * 8)); } } @@ -122,13 +137,10 @@ void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind, PragmaPackStack *Context = static_cast(PackContext); - // Reset just pops the top of the stack. - if (Kind == Action::POAK_Reset) { - // Do the pop. - if (!Context->pop(0)) { - // If a name was specified then failure indicates the name - // wasn't found. Otherwise failure indicates the stack was - // empty. + // Reset just pops the top of the stack, or resets the current alignment to + // default. + if (Kind == Sema::POAK_Reset) { + if (!Context->pop(0, /*IsReset=*/true)) { Diag(PragmaLoc, diag::warn_pragma_options_align_reset_failed) << "stack empty"; } @@ -188,7 +200,6 @@ void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name, !(Val == 0 || Val.isPowerOf2()) || Val.getZExtValue() > 16) { Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment); - Alignment->Destroy(Context); return; // Ignore } @@ -201,11 +212,11 @@ void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name, PragmaPackStack *Context = static_cast(PackContext); switch (Kind) { - case Action::PPK_Default: // pack([n]) + case Sema::PPK_Default: // pack([n]) Context->setAlignment(AlignmentVal); break; - case Action::PPK_Show: // pack(show) + case Sema::PPK_Show: // pack(show) // Show the current alignment, making sure to show the right value // for the default. AlignmentVal = Context->getAlignment(); @@ -218,21 +229,21 @@ void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name, Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal; break; - case Action::PPK_Push: // pack(push [, id] [, [n]) + case Sema::PPK_Push: // pack(push [, id] [, [n]) Context->push(Name); // Set the new alignment if specified. if (Alignment) Context->setAlignment(AlignmentVal); break; - case Action::PPK_Pop: // pack(pop [, id] [, n]) + case Sema::PPK_Pop: // pack(pop [, id] [, n]) // MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack: // "#pragma pack(pop, identifier, n) is undefined" if (Alignment && Name) Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment); // Do the pop. - if (!Context->pop(Name)) { + if (!Context->pop(Name, /*IsReset=*/false)) { // If a name was specified then failure indicates the name // wasn't found. Otherwise failure indicates the stack was // empty. @@ -277,6 +288,80 @@ void Sema::ActOnPragmaUnused(const Token *Identifiers, unsigned NumIdentifiers, continue; } - VD->addAttr(::new (Context) UnusedAttr()); + VD->addAttr(::new (Context) UnusedAttr(Tok.getLocation(), Context)); + } +} + +typedef std::vector > VisStack; + +void Sema::AddPushedVisibilityAttribute(Decl *D) { + if (!VisContext) + return; + + if (D->hasAttr()) + return; + + VisStack *Stack = static_cast(VisContext); + VisibilityAttr::VisibilityType type = Stack->back().first; + SourceLocation loc = Stack->back().second; + + D->addAttr(::new (Context) VisibilityAttr(loc, Context, type)); +} + +/// FreeVisContext - Deallocate and null out VisContext. +void Sema::FreeVisContext() { + delete static_cast(VisContext); + VisContext = 0; +} + +static void PushPragmaVisibility(Sema &S, VisibilityAttr::VisibilityType type, + SourceLocation loc) { + // Put visibility on stack. + if (!S.VisContext) + S.VisContext = new VisStack; + + VisStack *Stack = static_cast(S.VisContext); + Stack->push_back(std::make_pair(type, loc)); +} + +void Sema::ActOnPragmaVisibility(bool IsPush, const IdentifierInfo* VisType, + SourceLocation PragmaLoc) { + if (IsPush) { + // Compute visibility to use. + VisibilityAttr::VisibilityType type; + if (VisType->isStr("default")) + type = VisibilityAttr::Default; + else if (VisType->isStr("hidden")) + type = VisibilityAttr::Hidden; + else if (VisType->isStr("internal")) + type = VisibilityAttr::Hidden; // FIXME + else if (VisType->isStr("protected")) + type = VisibilityAttr::Protected; + else { + Diag(PragmaLoc, diag::warn_attribute_unknown_visibility) << + VisType->getName(); + return; + } + PushPragmaVisibility(*this, type, PragmaLoc); + } else { + PopPragmaVisibility(); + } +} + +void Sema::PushVisibilityAttr(const VisibilityAttr *Attr) { + PushPragmaVisibility(*this, Attr->getVisibility(), Attr->getLocation()); +} + +void Sema::PopPragmaVisibility() { + // Pop visibility from stack, if there is one on the stack. + if (VisContext) { + VisStack *Stack = static_cast(VisContext); + + Stack->pop_back(); + // To simplify the implementation, never keep around an empty stack. + if (Stack->empty()) + FreeVisContext(); } + // FIXME: Add diag for pop without push. } diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp index b8e27e7b7285..21b1a73aa3bc 100644 --- a/lib/Sema/SemaCXXCast.cpp +++ b/lib/Sema/SemaCXXCast.cpp @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#include "Sema.h" -#include "SemaInit.h" +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/Initialization.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ASTContext.h" #include "clang/AST/CXXInheritance.h" @@ -43,16 +43,16 @@ static void CheckConstCast(Sema &Self, Expr *&SrcExpr, QualType DestType, static void CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType, const SourceRange &OpRange, const SourceRange &DestRange, - CastExpr::CastKind &Kind); + CastKind &Kind); static void CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType, const SourceRange &OpRange, - CastExpr::CastKind &Kind, - CXXBaseSpecifierArray &BasePath); + CastKind &Kind, + CXXCastPath &BasePath); static void CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType, const SourceRange &OpRange, const SourceRange &DestRange, - CastExpr::CastKind &Kind, - CXXBaseSpecifierArray &BasePath); + CastKind &Kind, + CXXCastPath &BasePath); static bool CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType); @@ -73,54 +73,54 @@ static TryCastResult TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr, QualType DestType, bool CStyle, const SourceRange &OpRange, unsigned &msg, - CastExpr::CastKind &Kind, - CXXBaseSpecifierArray &BasePath); + CastKind &Kind, + CXXCastPath &BasePath); static TryCastResult TryStaticPointerDowncast(Sema &Self, QualType SrcType, QualType DestType, bool CStyle, const SourceRange &OpRange, unsigned &msg, - CastExpr::CastKind &Kind, - CXXBaseSpecifierArray &BasePath); + CastKind &Kind, + CXXCastPath &BasePath); static TryCastResult TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType, bool CStyle, const SourceRange &OpRange, QualType OrigSrcType, QualType OrigDestType, unsigned &msg, - CastExpr::CastKind &Kind, - CXXBaseSpecifierArray &BasePath); + CastKind &Kind, + CXXCastPath &BasePath); static TryCastResult TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr, QualType SrcType, QualType DestType,bool CStyle, const SourceRange &OpRange, unsigned &msg, - CastExpr::CastKind &Kind, - CXXBaseSpecifierArray &BasePath); + CastKind &Kind, + CXXCastPath &BasePath); static TryCastResult TryStaticImplicitCast(Sema &Self, Expr *&SrcExpr, QualType DestType, bool CStyle, const SourceRange &OpRange, unsigned &msg, - CastExpr::CastKind &Kind); + CastKind &Kind); static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType, bool CStyle, const SourceRange &OpRange, unsigned &msg, - CastExpr::CastKind &Kind, - CXXBaseSpecifierArray &BasePath); + CastKind &Kind, + CXXCastPath &BasePath); static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType, bool CStyle, unsigned &msg); static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr, QualType DestType, bool CStyle, const SourceRange &OpRange, unsigned &msg, - CastExpr::CastKind &Kind); + CastKind &Kind); /// ActOnCXXNamedCast - Parse {dynamic,static,reinterpret,const}_cast's. -Action::OwningExprResult +ExprResult Sema::ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, - SourceLocation LAngleBracketLoc, TypeTy *Ty, + SourceLocation LAngleBracketLoc, ParsedType Ty, SourceLocation RAngleBracketLoc, - SourceLocation LParenLoc, ExprArg E, + SourceLocation LParenLoc, Expr *E, SourceLocation RParenLoc) { TypeSourceInfo *DestTInfo; @@ -133,11 +133,10 @@ Sema::ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, SourceRange(LParenLoc, RParenLoc)); } -Action::OwningExprResult +ExprResult Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, - TypeSourceInfo *DestTInfo, ExprArg E, + TypeSourceInfo *DestTInfo, Expr *Ex, SourceRange AngleBrackets, SourceRange Parens) { - Expr *Ex = E.takeAs(); QualType DestType = DestTInfo->getType(); SourceRange OpRange(OpLoc, Parens.getEnd()); @@ -153,39 +152,39 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, case tok::kw_const_cast: if (!TypeDependent) CheckConstCast(*this, Ex, DestType, OpRange, DestRange); - return Owned(new (Context) CXXConstCastExpr( + return Owned(CXXConstCastExpr::Create(Context, DestType.getNonLValueExprType(Context), - Ex, DestTInfo, OpLoc)); + Ex, DestTInfo, OpLoc)); case tok::kw_dynamic_cast: { - CastExpr::CastKind Kind = CastExpr::CK_Unknown; - CXXBaseSpecifierArray BasePath; + CastKind Kind = CK_Unknown; + CXXCastPath BasePath; if (!TypeDependent) CheckDynamicCast(*this, Ex, DestType, OpRange, DestRange, Kind, BasePath); - return Owned(new (Context)CXXDynamicCastExpr( + return Owned(CXXDynamicCastExpr::Create(Context, DestType.getNonLValueExprType(Context), - Kind, Ex, BasePath, DestTInfo, - OpLoc)); + Kind, Ex, &BasePath, DestTInfo, + OpLoc)); } case tok::kw_reinterpret_cast: { - CastExpr::CastKind Kind = CastExpr::CK_Unknown; + CastKind Kind = CK_Unknown; if (!TypeDependent) CheckReinterpretCast(*this, Ex, DestType, OpRange, DestRange, Kind); - return Owned(new (Context) CXXReinterpretCastExpr( + return Owned(CXXReinterpretCastExpr::Create(Context, DestType.getNonLValueExprType(Context), - Kind, Ex, CXXBaseSpecifierArray(), + Kind, Ex, 0, DestTInfo, OpLoc)); } case tok::kw_static_cast: { - CastExpr::CastKind Kind = CastExpr::CK_Unknown; - CXXBaseSpecifierArray BasePath; + CastKind Kind = CK_Unknown; + CXXCastPath BasePath; if (!TypeDependent) CheckStaticCast(*this, Ex, DestType, OpRange, Kind, BasePath); - return Owned(new (Context) CXXStaticCastExpr( + return Owned(CXXStaticCastExpr::Create(Context, DestType.getNonLValueExprType(Context), - Kind, Ex, BasePath, - DestTInfo, OpLoc)); + Kind, Ex, &BasePath, + DestTInfo, OpLoc)); } } @@ -197,7 +196,7 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, /// the same kind of pointer (plain or to-member). Unlike the Sema function, /// this one doesn't care if the two pointers-to-member don't point into the /// same class. This is because CastsAwayConstness doesn't care. -bool UnwrapDissimilarPointerTypes(QualType& T1, QualType& T2) { +static bool UnwrapDissimilarPointerTypes(QualType& T1, QualType& T2) { const PointerType *T1PtrType = T1->getAs(), *T2PtrType = T2->getAs(); if (T1PtrType && T2PtrType) { @@ -307,8 +306,8 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType) { static void CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType, const SourceRange &OpRange, - const SourceRange &DestRange, CastExpr::CastKind &Kind, - CXXBaseSpecifierArray &BasePath) { + const SourceRange &DestRange, CastKind &Kind, + CXXCastPath &BasePath) { QualType OrigDestType = DestType, OrigSrcType = SrcExpr->getType(); DestType = Self.Context.getCanonicalType(DestType); @@ -396,6 +395,7 @@ CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType, // C++ 5.2.7p3: If the type of v is the same as the required result type, // [except for cv]. if (DestRecord == SrcRecord) { + Kind = CK_NoOp; return; } @@ -407,7 +407,7 @@ CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType, &BasePath)) return; - Kind = CastExpr::CK_DerivedToBase; + Kind = CK_DerivedToBase; // If we are casting to or through a virtual base class, we need a // vtable. @@ -428,7 +428,7 @@ CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType, cast(SrcRecord->getDecl())); // Done. Everything else is run-time checks. - Kind = CastExpr::CK_Dynamic; + Kind = CK_Dynamic; } /// CheckConstCast - Check that a const_cast\(SrcExpr) is valid. @@ -457,7 +457,7 @@ CheckConstCast(Sema &Self, Expr *&SrcExpr, QualType DestType, void CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType, const SourceRange &OpRange, const SourceRange &DestRange, - CastExpr::CastKind &Kind) { + CastKind &Kind) { if (!DestType->isLValueReferenceType()) Self.DefaultFunctionArrayLvalueConversion(SrcExpr); @@ -475,13 +475,13 @@ CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType, /// implicit conversions explicit and getting rid of data loss warnings. void CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType, - const SourceRange &OpRange, CastExpr::CastKind &Kind, - CXXBaseSpecifierArray &BasePath) { + const SourceRange &OpRange, CastKind &Kind, + CXXCastPath &BasePath) { // This test is outside everything else because it's the only case where // a non-lvalue-reference target type does not lead to decay. // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void". if (DestType->isVoidType()) { - Kind = CastExpr::CK_ToVoid; + Kind = CK_ToVoid; return; } @@ -493,6 +493,8 @@ CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType, Kind, BasePath) != TC_Success && msg != 0) Self.Diag(OpRange.getBegin(), msg) << CT_Static << SrcExpr->getType() << DestType << OpRange; + else if (Kind == CK_Unknown || Kind == CK_BitCast) + Self.CheckCastAlign(SrcExpr, DestType, OpRange); } /// TryStaticCast - Check if a static cast can be performed, and do so if @@ -501,8 +503,8 @@ CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType, static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType, bool CStyle, const SourceRange &OpRange, unsigned &msg, - CastExpr::CastKind &Kind, - CXXBaseSpecifierArray &BasePath) { + CastKind &Kind, + CXXCastPath &BasePath) { // The order the tests is not entirely arbitrary. There is one conversion // that can be handled in two different ways. Given: // struct A {}; @@ -532,7 +534,7 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr, // reference to cv2 T2" if "cv2 T2" is reference-compatible with "cv1 T1". tcr = TryLValueToRValueCast(Self, SrcExpr, DestType, msg); if (tcr != TC_NotApplicable) { - Kind = CastExpr::CK_NoOp; + Kind = CK_NoOp; return tcr; } @@ -567,7 +569,7 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr, if (SrcType->isComplexType() || SrcType->isVectorType()) { // Fall through - these cannot be converted. } else if (SrcType->isArithmeticType() || SrcType->isEnumeralType()) { - Kind = CastExpr::CK_IntegralCast; + Kind = CK_IntegralCast; return TC_Success; } } @@ -602,19 +604,19 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr, msg = diag::err_bad_cxx_cast_const_away; return TC_Failed; } - Kind = CastExpr::CK_BitCast; + Kind = CK_BitCast; return TC_Success; } } else if (DestType->isObjCObjectPointerType()) { // allow both c-style cast and static_cast of objective-c pointers as // they are pervasive. - Kind = CastExpr::CK_AnyPointerToObjCPointerCast; + Kind = CK_AnyPointerToObjCPointerCast; return TC_Success; } else if (CStyle && DestType->isBlockPointerType()) { // allow c-style cast of void * to block pointers. - Kind = CastExpr::CK_AnyPointerToBlockPointerCast; + Kind = CK_AnyPointerToBlockPointerCast; return TC_Success; } } @@ -645,9 +647,10 @@ TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, QualType DestType, // this is the only cast possibility, so we issue an error if we fail now. // FIXME: Should allow casting away constness if CStyle. bool DerivedToBase; + bool ObjCConversion; if (Self.CompareReferenceRelationship(SrcExpr->getLocStart(), SrcExpr->getType(), R->getPointeeType(), - DerivedToBase) < + DerivedToBase, ObjCConversion) < Sema::Ref_Compatible_With_Added_Qualification) { msg = diag::err_bad_lvalue_to_rvalue_cast; return TC_Failed; @@ -662,8 +665,8 @@ TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, QualType DestType, TryCastResult TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr, QualType DestType, bool CStyle, const SourceRange &OpRange, - unsigned &msg, CastExpr::CastKind &Kind, - CXXBaseSpecifierArray &BasePath) { + unsigned &msg, CastKind &Kind, + CXXCastPath &BasePath) { // C++ 5.2.9p5: An lvalue of type "cv1 B", where B is a class type, can be // cast to type "reference to cv2 D", where D is a class derived from B, // if a valid standard conversion from "pointer to D" to "pointer to B" @@ -697,8 +700,8 @@ TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr, QualType DestType, TryCastResult TryStaticPointerDowncast(Sema &Self, QualType SrcType, QualType DestType, bool CStyle, const SourceRange &OpRange, - unsigned &msg, CastExpr::CastKind &Kind, - CXXBaseSpecifierArray &BasePath) { + unsigned &msg, CastKind &Kind, + CXXCastPath &BasePath) { // C++ 5.2.9p8: An rvalue of type "pointer to cv1 B", where B is a class // type, can be converted to an rvalue of type "pointer to cv2 D", where D // is a class derived from B, if a valid standard conversion from "pointer @@ -732,7 +735,7 @@ TryCastResult TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType, bool CStyle, const SourceRange &OpRange, QualType OrigSrcType, QualType OrigDestType, unsigned &msg, - CastExpr::CastKind &Kind, CXXBaseSpecifierArray &BasePath) { + CastKind &Kind, CXXCastPath &BasePath) { // We can only work with complete types. But don't complain if it doesn't work if (Self.RequireCompleteType(OpRange.getBegin(), SrcType, Self.PDiag(0)) || Self.RequireCompleteType(OpRange.getBegin(), DestType, Self.PDiag(0))) @@ -824,7 +827,7 @@ TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType, } Self.BuildBasePathArray(Paths, BasePath); - Kind = CastExpr::CK_BaseToDerived; + Kind = CK_BaseToDerived; return TC_Success; } @@ -839,8 +842,8 @@ TryCastResult TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr, QualType SrcType, QualType DestType, bool CStyle, const SourceRange &OpRange, - unsigned &msg, CastExpr::CastKind &Kind, - CXXBaseSpecifierArray &BasePath) { + unsigned &msg, CastKind &Kind, + CXXCastPath &BasePath) { const MemberPointerType *DestMemPtr = DestType->getAs(); if (!DestMemPtr) return TC_NotApplicable; @@ -900,7 +903,7 @@ TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr, QualType SrcType, } if (!CStyle && Self.CheckBaseClassAccess(OpRange.getBegin(), - DestType, SrcType, + DestClass, SrcClass, Paths.front(), diag::err_upcast_to_inaccessible_base)) { msg = 0; @@ -927,7 +930,7 @@ TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr, QualType SrcType, } Self.BuildBasePathArray(Paths, BasePath); - Kind = CastExpr::CK_DerivedToBaseMemberPointer; + Kind = CK_DerivedToBaseMemberPointer; return TC_Success; } @@ -939,7 +942,7 @@ TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr, QualType SrcType, TryCastResult TryStaticImplicitCast(Sema &Self, Expr *&SrcExpr, QualType DestType, bool CStyle, const SourceRange &OpRange, unsigned &msg, - CastExpr::CastKind &Kind) { + CastKind &Kind) { if (DestType->isRecordType()) { if (Self.RequireCompleteType(OpRange.getBegin(), DestType, diag::err_bad_dynamic_cast_incomplete)) { @@ -961,18 +964,17 @@ TryStaticImplicitCast(Sema &Self, Expr *&SrcExpr, QualType DestType, (CStyle || !DestType->isReferenceType())) return TC_NotApplicable; - Sema::OwningExprResult Result - = InitSeq.Perform(Self, Entity, InitKind, - Action::MultiExprArg(Self, (void**)&SrcExpr, 1)); + ExprResult Result + = InitSeq.Perform(Self, Entity, InitKind, MultiExprArg(Self, &SrcExpr, 1)); if (Result.isInvalid()) { msg = 0; return TC_Failed; } if (InitSeq.isConstructorInitialization()) - Kind = CastExpr::CK_ConstructorConversion; + Kind = CK_ConstructorConversion; else - Kind = CastExpr::CK_NoOp; + Kind = CK_NoOp; SrcExpr = Result.takeAs(); return TC_Success; @@ -1051,7 +1053,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr, QualType DestType, bool CStyle, const SourceRange &OpRange, unsigned &msg, - CastExpr::CastKind &Kind) { + CastKind &Kind) { bool IsLValueCast = false; DestType = Self.Context.getCanonicalType(DestType); @@ -1097,8 +1099,15 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr, return TC_Failed; } + // Don't allow casting between member pointers of different sizes. + if (Self.Context.getTypeSize(DestMemPtr) != + Self.Context.getTypeSize(SrcMemPtr)) { + msg = diag::err_bad_cxx_cast_member_pointer_size; + return TC_Failed; + } + // A valid member pointer cast. - Kind = IsLValueCast? CastExpr::CK_LValueBitCast : CastExpr::CK_BitCast; + Kind = IsLValueCast? CK_LValueBitCast : CK_BitCast; return TC_Success; } @@ -1113,7 +1122,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr, msg = diag::err_bad_reinterpret_cast_small_int; return TC_Failed; } - Kind = CastExpr::CK_PointerToIntegral; + Kind = CK_PointerToIntegral; return TC_Success; } @@ -1132,7 +1141,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr, // If both types have the same size, we can successfully cast. if (Self.Context.getTypeSize(SrcType) == Self.Context.getTypeSize(DestType)) { - Kind = CastExpr::CK_BitCast; + Kind = CK_BitCast; return TC_Success; } @@ -1163,7 +1172,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr, // to the same type. However, the behavior of compilers is pretty consistent // on this point: allow same-type conversion if the involved types are // pointers, disallow otherwise. - Kind = CastExpr::CK_NoOp; + Kind = CK_NoOp; return TC_Success; } @@ -1176,7 +1185,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr, msg = diag::err_bad_reinterpret_cast_small_int; return TC_Failed; } - Kind = CastExpr::CK_PointerToIntegral; + Kind = CK_PointerToIntegral; return TC_Success; } @@ -1184,7 +1193,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr, assert(destIsPtr && "One type must be a pointer"); // C++ 5.2.10p5: A value of integral or enumeration type can be explicitly // converted to a pointer. - Kind = CastExpr::CK_IntegralToPointer; + Kind = CK_IntegralToPointer; return TC_Success; } @@ -1209,13 +1218,13 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr, // Any pointer can be cast to an Objective-C pointer type with a C-style // cast. if (CStyle && DestType->isObjCObjectPointerType()) { - Kind = CastExpr::CK_AnyPointerToObjCPointerCast; + Kind = CK_AnyPointerToObjCPointerCast; return TC_Success; } // Not casting away constness, so the only remaining check is for compatible // pointer categories. - Kind = IsLValueCast? CastExpr::CK_LValueBitCast : CastExpr::CK_BitCast; + Kind = IsLValueCast? CK_LValueBitCast : CK_BitCast; if (SrcType->isFunctionPointerType()) { if (DestType->isFunctionPointerType()) { @@ -1252,14 +1261,14 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr, bool Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, Expr *&CastExpr, - CastExpr::CastKind &Kind, - CXXBaseSpecifierArray &BasePath, + CastKind &Kind, + CXXCastPath &BasePath, bool FunctionalStyle) { // This test is outside everything else because it's the only case where // a non-lvalue-reference target type does not lead to decay. // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void". if (CastTy->isVoidType()) { - Kind = CastExpr::CK_ToVoid; + Kind = CK_ToVoid; return false; } @@ -1285,7 +1294,7 @@ Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, Expr *&CastExpr, TryCastResult tcr = TryConstCast(*this, CastExpr, CastTy, /*CStyle*/true, msg); if (tcr == TC_Success) - Kind = CastExpr::CK_NoOp; + Kind = CK_NoOp; if (tcr == TC_NotApplicable) { // ... or if that is not possible, a static_cast, ignoring const, ... @@ -1301,6 +1310,8 @@ Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, Expr *&CastExpr, if (tcr != TC_Success && msg != 0) Diag(R.getBegin(), msg) << (FunctionalStyle ? CT_Functional : CT_CStyle) << CastExpr->getType() << CastTy << R; + else if (Kind == CK_Unknown || Kind == CK_BitCast) + CheckCastAlign(CastExpr, CastTy, R); return tcr != TC_Success; } diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp index f56573a8de26..631308eebb04 100644 --- a/lib/Sema/SemaCXXScopeSpec.cpp +++ b/lib/Sema/SemaCXXScopeSpec.cpp @@ -11,14 +11,14 @@ // //===----------------------------------------------------------------------===// -#include "Sema.h" -#include "Lookup.h" +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/Lookup.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/Basic/PartialDiagnostic.h" -#include "clang/Parse/DeclSpec.h" +#include "clang/Sema/DeclSpec.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/raw_ostream.h" using namespace clang; @@ -283,7 +283,7 @@ NamedDecl *Sema::FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS) { bool Sema::isNonTypeNestedNameSpecifier(Scope *S, CXXScopeSpec &SS, SourceLocation IdLoc, IdentifierInfo &II, - TypeTy *ObjectTypePtr) { + ParsedType ObjectTypePtr) { QualType ObjectType = GetTypeFromParser(ObjectTypePtr); LookupResult Found(*this, &II, IdLoc, LookupNestedNameSpecifierName); @@ -416,7 +416,17 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S, ObjectTypeSearchedInScope = true; } - } else if (isDependent) { + } else if (!isDependent) { + // Perform unqualified name lookup in the current scope. + LookupName(Found, S); + } + + // If we performed lookup into a dependent context and did not find anything, + // that's fine: just build a dependent nested-name-specifier. + if (Found.empty() && isDependent && + !(LookupCtx && LookupCtx->isRecord() && + (!cast(LookupCtx)->hasDefinition() || + !cast(LookupCtx)->hasAnyDependentBases()))) { // Don't speculate if we're just trying to improve error recovery. if (ErrorRecoveryLookup) return 0; @@ -429,11 +439,8 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S, return NestedNameSpecifier::Create(Context, &II); return NestedNameSpecifier::Create(Context, Prefix, &II); - } else { - // Perform unqualified name lookup in the current scope. - LookupName(Found, S); - } - + } + // FIXME: Deal with ambiguities cleanly. if (Found.empty() && !ErrorRecoveryLookup) { @@ -560,10 +567,10 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S, SourceLocation IdLoc, SourceLocation CCLoc, IdentifierInfo &II, - TypeTy *ObjectTypePtr, + ParsedType ObjectTypePtr, bool EnteringContext) { return BuildCXXNestedNameSpecifier(S, SS, IdLoc, CCLoc, II, - QualType::getFromOpaquePtr(ObjectTypePtr), + GetTypeFromParser(ObjectTypePtr), /*ScopeLookupResult=*/0, EnteringContext, false); } @@ -575,21 +582,20 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S, /// /// The arguments are the same as those passed to ActOnCXXNestedNameSpecifier. bool Sema::IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS, - IdentifierInfo &II, TypeTy *ObjectType, + IdentifierInfo &II, ParsedType ObjectType, bool EnteringContext) { return BuildCXXNestedNameSpecifier(S, SS, SourceLocation(), SourceLocation(), - II, QualType::getFromOpaquePtr(ObjectType), + II, GetTypeFromParser(ObjectType), /*ScopeLookupResult=*/0, EnteringContext, true); } Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S, const CXXScopeSpec &SS, - TypeTy *Ty, + ParsedType Ty, SourceRange TypeRange, SourceLocation CCLoc) { - NestedNameSpecifier *Prefix - = static_cast(SS.getScopeRep()); + NestedNameSpecifier *Prefix = SS.getScopeRep(); QualType T = GetTypeFromParser(Ty); return NestedNameSpecifier::Create(Context, Prefix, /*FIXME:*/false, T.getTypePtr()); @@ -620,7 +626,7 @@ bool Sema::ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) { case NestedNameSpecifier::Namespace: // These are always namespace scopes. We never want to enter a // namespace scope from anything but a file context. - return CurContext->getLookupContext()->isFileContext(); + return CurContext->getRedeclContext()->isFileContext(); case NestedNameSpecifier::Identifier: case NestedNameSpecifier::TypeSpec: diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 7a39f058c5ec..a0b4b988dbeb 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -12,10 +12,13 @@ // //===----------------------------------------------------------------------===// -#include "Sema.h" -#include "clang/Analysis/Analyses/PrintfFormatString.h" +#include "clang/Sema/Sema.h" +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/ScopeInfo.h" +#include "clang/Analysis/Analyses/FormatString.h" #include "clang/AST/ASTContext.h" #include "clang/AST/CharUnits.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" @@ -26,12 +29,12 @@ #include "clang/Lex/Preprocessor.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/StringExtras.h" #include "llvm/Support/raw_ostream.h" #include "clang/Basic/TargetBuiltins.h" #include "clang/Basic/TargetInfo.h" #include using namespace clang; +using namespace sema; /// getLocationOfStringLiteralByte - Return a source location that points to the /// specified byte of the specified string literal. @@ -122,9 +125,9 @@ bool Sema::CheckablePrintfAttr(const FormatAttr *Format, CallExpr *TheCall) { return false; } -Action::OwningExprResult +ExprResult Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { - OwningExprResult TheCallResult(Owned(TheCall)); + ExprResult TheCallResult(Owned(TheCall)); switch (BuiltinID) { case Builtin::BI__builtin___CFStringMakeConstantString: @@ -298,6 +301,10 @@ bool Sema::CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { unsigned i = 0, l = 0, u = 0; switch (BuiltinID) { default: return false; + case ARM::BI__builtin_arm_ssat: i = 1; l = 1; u = 31; break; + case ARM::BI__builtin_arm_usat: i = 1; u = 31; break; + case ARM::BI__builtin_arm_vcvtr_f: + case ARM::BI__builtin_arm_vcvtr_d: i = 1; u = 1; break; #define GET_NEON_IMMEDIATE_CHECK #include "clang/Basic/arm_neon.inc" #undef GET_NEON_IMMEDIATE_CHECK @@ -311,9 +318,9 @@ bool Sema::CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { unsigned Val = Result.getZExtValue(); if (Val < l || Val > (u + l)) return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range) - << llvm::utostr(l) << llvm::utostr(u+l) - << TheCall->getArg(i)->getSourceRange(); + << l << u+l << TheCall->getArg(i)->getSourceRange(); + // FIXME: VFP Intrinsics should error if VFP not present. return false; } @@ -334,16 +341,22 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) { // Printf checking. if (const FormatAttr *Format = FDecl->getAttr()) { - if (CheckablePrintfAttr(Format, TheCall)) { + const bool b = Format->getType() == "scanf"; + if (b || CheckablePrintfAttr(Format, TheCall)) { bool HasVAListArg = Format->getFirstArg() == 0; - CheckPrintfArguments(TheCall, HasVAListArg, Format->getFormatIdx() - 1, - HasVAListArg ? 0 : Format->getFirstArg() - 1); + CheckPrintfScanfArguments(TheCall, HasVAListArg, + Format->getFormatIdx() - 1, + HasVAListArg ? 0 : Format->getFirstArg() - 1, + !b); } } - for (const NonNullAttr *NonNull = FDecl->getAttr(); NonNull; - NonNull = NonNull->getNext()) - CheckNonNullArguments(NonNull, TheCall); + specific_attr_iterator + i = FDecl->specific_attr_begin(), + e = FDecl->specific_attr_end(); + + for (; i != e; ++i) + CheckNonNullArguments(*i, TheCall); return false; } @@ -362,12 +375,13 @@ bool Sema::CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall) { if (!Ty->isBlockPointerType()) return false; - if (!CheckablePrintfAttr(Format, TheCall)) + const bool b = Format->getType() == "scanf"; + if (!b && !CheckablePrintfAttr(Format, TheCall)) return false; bool HasVAListArg = Format->getFirstArg() == 0; - CheckPrintfArguments(TheCall, HasVAListArg, Format->getFormatIdx() - 1, - HasVAListArg ? 0 : Format->getFirstArg() - 1); + CheckPrintfScanfArguments(TheCall, HasVAListArg, Format->getFormatIdx() - 1, + HasVAListArg ? 0 : Format->getFirstArg() - 1, !b); return false; } @@ -380,8 +394,8 @@ bool Sema::CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall) { /// /// This function goes through and does final semantic checking for these /// builtins, -Sema::OwningExprResult -Sema::SemaBuiltinAtomicOverloaded(OwningExprResult TheCallResult) { +ExprResult +Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) { CallExpr *TheCall = (CallExpr *)TheCallResult.get(); DeclRefExpr *DRE =cast(TheCall->getCallee()->IgnoreParenCasts()); FunctionDecl *FDecl = cast(DRE->getDecl()); @@ -415,6 +429,10 @@ Sema::SemaBuiltinAtomicOverloaded(OwningExprResult TheCallResult) { return ExprError(); } + // The majority of builtins return a value, but a few have special return + // types, so allow them to override appropriately below. + QualType ResultType = ValType; + // We need to figure out which concrete builtin this maps onto. For example, // __sync_fetch_and_add with a 2 byte object turns into // __sync_fetch_and_add_2. @@ -483,11 +501,13 @@ Sema::SemaBuiltinAtomicOverloaded(OwningExprResult TheCallResult) { case Builtin::BI__sync_bool_compare_and_swap: BuiltinIndex = 11; NumFixed = 2; + ResultType = Context.BoolTy; break; case Builtin::BI__sync_lock_test_and_set: BuiltinIndex = 12; break; case Builtin::BI__sync_lock_release: BuiltinIndex = 13; NumFixed = 0; + ResultType = Context.VoidTy; break; } @@ -508,19 +528,10 @@ Sema::SemaBuiltinAtomicOverloaded(OwningExprResult TheCallResult) { FunctionDecl *NewBuiltinDecl = cast(LazilyCreateBuiltin(NewBuiltinII, NewBuiltinID, TUScope, false, DRE->getLocStart())); - const FunctionProtoType *BuiltinFT = - NewBuiltinDecl->getType()->getAs(); - - QualType OrigValType = ValType; - ValType = BuiltinFT->getArgType(0)->getAs()->getPointeeType(); - - // If the first type needs to be converted (e.g. void** -> int*), do it now. - if (BuiltinFT->getArgType(0) != FirstArg->getType()) { - ImpCastExprToType(FirstArg, BuiltinFT->getArgType(0), CastExpr::CK_BitCast); - TheCall->setArg(0, FirstArg); - } - // Next, walk the valid ones promoting to the right type. + // The first argument --- the pointer --- has a fixed type; we + // deduce the types of the rest of the arguments accordingly. Walk + // the remaining arguments, converting them to the deduced value type. for (unsigned i = 0; i != NumFixed; ++i) { Expr *Arg = TheCall->getArg(i+1); @@ -529,14 +540,13 @@ Sema::SemaBuiltinAtomicOverloaded(OwningExprResult TheCallResult) { if (ImplicitCastExpr *ICE = dyn_cast(Arg)) { Arg = ICE->getSubExpr(); ICE->setSubExpr(0); - ICE->Destroy(Context); TheCall->setArg(i+1, Arg); } // GCC does an implicit conversion to the pointer or integer ValType. This // can fail in some cases (1i -> int**), check for this error case now. - CastExpr::CastKind Kind = CastExpr::CK_Unknown; - CXXBaseSpecifierArray BasePath; + CastKind Kind = CK_Unknown; + CXXCastPath BasePath; if (CheckCastTypes(Arg->getSourceRange(), ValType, Arg, Kind, BasePath)) return ExprError(); @@ -546,7 +556,7 @@ Sema::SemaBuiltinAtomicOverloaded(OwningExprResult TheCallResult) { // pass in 42. The 42 gets converted to char. This is even more strange // for things like 45.123 -> char, etc. // FIXME: Do this check. - ImpCastExprToType(Arg, ValType, Kind); + ImpCastExprToType(Arg, ValType, Kind, VK_RValue, &BasePath); TheCall->setArg(i+1, Arg); } @@ -560,28 +570,10 @@ Sema::SemaBuiltinAtomicOverloaded(OwningExprResult TheCallResult) { UsualUnaryConversions(PromotedCall); TheCall->setCallee(PromotedCall); - // Change the result type of the call to match the result type of the decl. - TheCall->setType(NewBuiltinDecl->getCallResultType()); - - // If the value type was converted to an integer when processing the - // arguments (e.g. void* -> int), we need to convert the result back. - if (!Context.hasSameUnqualifiedType(ValType, OrigValType)) { - Expr *E = TheCallResult.takeAs(); - - assert(ValType->isIntegerType() && - "We always convert atomic operation values to integers."); - // FIXME: Handle floating point value type here too. - CastExpr::CastKind Kind; - if (OrigValType->isIntegerType()) - Kind = CastExpr::CK_IntegralCast; - else if (OrigValType->hasPointerRepresentation()) - Kind = CastExpr::CK_IntegralToPointer; - else - llvm_unreachable("Unhandled original value type!"); - - ImpCastExprToType(E, OrigValType, Kind); - return Owned(E); - } + // Change the result type of the call to match the original value type. This + // is arbitrary, but the codegen for these builtins ins design to handle it + // gracefully. + TheCall->setType(ResultType); return move(TheCallResult); } @@ -604,16 +596,11 @@ bool Sema::CheckObjCString(Expr *Arg) { return true; } - const char *Data = Literal->getStrData(); - unsigned Length = Literal->getByteLength(); - - for (unsigned i = 0; i < Length; ++i) { - if (!Data[i]) { - Diag(getLocationOfStringLiteralByte(Literal, i), - diag::warn_cfstring_literal_contains_nul_character) - << Arg->getSourceRange(); - break; - } + size_t NulPos = Literal->getString().find('\0'); + if (NulPos != llvm::StringRef::npos) { + Diag(getLocationOfStringLiteralByte(Literal, NulPos), + diag::warn_cfstring_literal_contains_nul_character) + << Arg->getSourceRange(); } return false; @@ -753,7 +740,6 @@ bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs) { assert(Cast->getType()->isSpecificBuiltinType(BuiltinType::Double) && "promotion from float to double is the only expected cast here"); Cast->setSubExpr(0); - Cast->Destroy(Context); TheCall->setArg(NumArgs-1, CastArg); OrigArg = CastArg; } @@ -764,7 +750,7 @@ bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs) { /// SemaBuiltinShuffleVector - Handle __builtin_shufflevector. // This is declared to take (...), so we have to check everything. -Action::OwningExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) { +ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) { if (TheCall->getNumArgs() < 2) return ExprError(Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args_at_least) @@ -797,7 +783,7 @@ Action::OwningExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) { // with mask. If so, verify that RHS is an integer vector type with the // same number of elts as lhs. if (TheCall->getNumArgs() == 2) { - if (!RHSType->isIntegerType() || + if (!RHSType->hasIntegerRepresentation() || RHSType->getAs()->getNumElements() != numElements) Diag(TheCall->getLocStart(), diag::err_shufflevector_incompatible_vector) << SourceRange(TheCall->getArg(1)->getLocStart(), @@ -941,29 +927,31 @@ bool Sema::SemaBuiltinLongjmp(CallExpr *TheCall) { // Handle i > 1 ? "x" : "y", recursivelly bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall, bool HasVAListArg, - unsigned format_idx, unsigned firstDataArg) { + unsigned format_idx, unsigned firstDataArg, + bool isPrintf) { + if (E->isTypeDependent() || E->isValueDependent()) return false; switch (E->getStmtClass()) { case Stmt::ConditionalOperatorClass: { const ConditionalOperator *C = cast(E); - return SemaCheckStringLiteral(C->getTrueExpr(), TheCall, - HasVAListArg, format_idx, firstDataArg) - && SemaCheckStringLiteral(C->getRHS(), TheCall, - HasVAListArg, format_idx, firstDataArg); + return SemaCheckStringLiteral(C->getTrueExpr(), TheCall, HasVAListArg, + format_idx, firstDataArg, isPrintf) + && SemaCheckStringLiteral(C->getRHS(), TheCall, HasVAListArg, + format_idx, firstDataArg, isPrintf); } case Stmt::ImplicitCastExprClass: { const ImplicitCastExpr *Expr = cast(E); return SemaCheckStringLiteral(Expr->getSubExpr(), TheCall, HasVAListArg, - format_idx, firstDataArg); + format_idx, firstDataArg, isPrintf); } case Stmt::ParenExprClass: { const ParenExpr *Expr = cast(E); return SemaCheckStringLiteral(Expr->getSubExpr(), TheCall, HasVAListArg, - format_idx, firstDataArg); + format_idx, firstDataArg, isPrintf); } case Stmt::DeclRefExprClass: { @@ -985,7 +973,8 @@ bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall, if (isConstant) { if (const Expr *Init = VD->getAnyInitializer()) return SemaCheckStringLiteral(Init, TheCall, - HasVAListArg, format_idx, firstDataArg); + HasVAListArg, format_idx, firstDataArg, + isPrintf); } // For vprintf* functions (i.e., HasVAListArg==true), we add a @@ -1025,7 +1014,7 @@ bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall, const Expr *Arg = CE->getArg(ArgIndex - 1); return SemaCheckStringLiteral(Arg, TheCall, HasVAListArg, - format_idx, firstDataArg); + format_idx, firstDataArg, isPrintf); } } } @@ -1043,8 +1032,8 @@ bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall, StrE = cast(E); if (StrE) { - CheckPrintfString(StrE, E, TheCall, HasVAListArg, format_idx, - firstDataArg); + CheckFormatString(StrE, E, TheCall, HasVAListArg, format_idx, + firstDataArg, isPrintf); return true; } @@ -1059,7 +1048,8 @@ bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall, void Sema::CheckNonNullArguments(const NonNullAttr *NonNull, const CallExpr *TheCall) { - for (NonNullAttr::iterator i = NonNull->begin(), e = NonNull->end(); + for (NonNullAttr::args_iterator i = NonNull->args_begin(), + e = NonNull->args_end(); i != e; ++i) { const Expr *ArgExpr = TheCall->getArg(*i); if (ArgExpr->isNullPointerConstant(Context, @@ -1069,55 +1059,13 @@ Sema::CheckNonNullArguments(const NonNullAttr *NonNull, } } -/// CheckPrintfArguments - Check calls to printf (and similar functions) for -/// correct use of format strings. -/// -/// HasVAListArg - A predicate indicating whether the printf-like -/// function is passed an explicit va_arg argument (e.g., vprintf) -/// -/// format_idx - The index into Args for the format string. -/// -/// Improper format strings to functions in the printf family can be -/// the source of bizarre bugs and very serious security holes. A -/// good source of information is available in the following paper -/// (which includes additional references): -/// -/// FormatGuard: Automatic Protection From printf Format String -/// Vulnerabilities, Proceedings of the 10th USENIX Security Symposium, 2001. -/// -/// TODO: -/// Functionality implemented: -/// -/// We can statically check the following properties for string -/// literal format strings for non v.*printf functions (where the -/// arguments are passed directly): -// -/// (1) Are the number of format conversions equal to the number of -/// data arguments? -/// -/// (2) Does each format conversion correctly match the type of the -/// corresponding data argument? -/// -/// Moreover, for all printf functions we can: -/// -/// (3) Check for a missing format string (when not caught by type checking). -/// -/// (4) Check for no-operation flags; e.g. using "#" with format -/// conversion 'c' (TODO) -/// -/// (5) Check the use of '%n', a major source of security holes. -/// -/// (6) Check for malformed format conversions that don't specify anything. -/// -/// (7) Check for empty format strings. e.g: printf(""); -/// -/// (8) Check that the format string is a wide literal. -/// -/// All of these checks can be done by parsing the format string. -/// +/// CheckPrintfScanfArguments - Check calls to printf and scanf (and similar +/// functions) for correct use of format strings. void -Sema::CheckPrintfArguments(const CallExpr *TheCall, bool HasVAListArg, - unsigned format_idx, unsigned firstDataArg) { +Sema::CheckPrintfScanfArguments(const CallExpr *TheCall, bool HasVAListArg, + unsigned format_idx, unsigned firstDataArg, + bool isPrintf) { + const Expr *Fn = TheCall->getCallee(); // The way the format attribute works in GCC, the implicit this argument @@ -1132,9 +1080,9 @@ Sema::CheckPrintfArguments(const CallExpr *TheCall, bool HasVAListArg, --firstDataArg; } - // CHECK: printf-like function is called with no format string. + // CHECK: printf/scanf-like function is called with no format string. if (format_idx >= TheCall->getNumArgs()) { - Diag(TheCall->getRParenLoc(), diag::warn_printf_missing_format_string) + Diag(TheCall->getRParenLoc(), diag::warn_missing_format_string) << Fn->getSourceRange(); return; } @@ -1154,23 +1102,24 @@ Sema::CheckPrintfArguments(const CallExpr *TheCall, bool HasVAListArg, // ObjC string uses the same format specifiers as C string, so we can use // the same format string checking logic for both ObjC and C strings. if (SemaCheckStringLiteral(OrigFormatExpr, TheCall, HasVAListArg, format_idx, - firstDataArg)) + firstDataArg, isPrintf)) return; // Literal format string found, check done! // If there are no arguments specified, warn with -Wformat-security, otherwise // warn only with -Wformat-nonliteral. if (TheCall->getNumArgs() == format_idx+1) Diag(TheCall->getArg(format_idx)->getLocStart(), - diag::warn_printf_nonliteral_noargs) + diag::warn_format_nonliteral_noargs) << OrigFormatExpr->getSourceRange(); else Diag(TheCall->getArg(format_idx)->getLocStart(), - diag::warn_printf_nonliteral) + diag::warn_format_nonliteral) << OrigFormatExpr->getSourceRange(); } namespace { -class CheckPrintfHandler : public analyze_printf::FormatStringHandler { +class CheckFormatHandler : public analyze_format_string::FormatStringHandler { +protected: Sema &S; const StringLiteral *FExpr; const Expr *OrigFormatExpr; @@ -1185,7 +1134,7 @@ class CheckPrintfHandler : public analyze_printf::FormatStringHandler { bool usesPositionalArgs; bool atFirstArg; public: - CheckPrintfHandler(Sema &s, const StringLiteral *fexpr, + CheckFormatHandler(Sema &s, const StringLiteral *fexpr, const Expr *origFormatExpr, unsigned firstDataArg, unsigned numDataArgs, bool isObjCLiteral, const char *beg, bool hasVAListArg, @@ -1203,55 +1152,43 @@ public: void DoneProcessing(); - void HandleIncompleteFormatSpecifier(const char *startSpecifier, - unsigned specifierLen); - - bool - HandleInvalidConversionSpecifier(const analyze_printf::FormatSpecifier &FS, - const char *startSpecifier, - unsigned specifierLen); - + void HandleIncompleteSpecifier(const char *startSpecifier, + unsigned specifierLen); + virtual void HandleInvalidPosition(const char *startSpecifier, unsigned specifierLen, - analyze_printf::PositionContext p); + analyze_format_string::PositionContext p); virtual void HandleZeroPosition(const char *startPos, unsigned posLen); void HandleNullChar(const char *nullCharacter); - bool HandleFormatSpecifier(const analyze_printf::FormatSpecifier &FS, - const char *startSpecifier, - unsigned specifierLen); -private: +protected: + bool HandleInvalidConversionSpecifier(unsigned argIndex, SourceLocation Loc, + const char *startSpec, + unsigned specifierLen, + const char *csStart, unsigned csLen); + SourceRange getFormatStringRange(); - CharSourceRange getFormatSpecifierRange(const char *startSpecifier, - unsigned specifierLen); + CharSourceRange getSpecifierRange(const char *startSpecifier, + unsigned specifierLen); SourceLocation getLocationOfByte(const char *x); - bool HandleAmount(const analyze_printf::OptionalAmount &Amt, unsigned k, - const char *startSpecifier, unsigned specifierLen); - void HandleInvalidAmount(const analyze_printf::FormatSpecifier &FS, - const analyze_printf::OptionalAmount &Amt, - unsigned type, - const char *startSpecifier, unsigned specifierLen); - void HandleFlag(const analyze_printf::FormatSpecifier &FS, - const analyze_printf::OptionalFlag &flag, - const char *startSpecifier, unsigned specifierLen); - void HandleIgnoredFlag(const analyze_printf::FormatSpecifier &FS, - const analyze_printf::OptionalFlag &ignoredFlag, - const analyze_printf::OptionalFlag &flag, - const char *startSpecifier, unsigned specifierLen); - const Expr *getDataArg(unsigned i) const; + + bool CheckNumArgs(const analyze_format_string::FormatSpecifier &FS, + const analyze_format_string::ConversionSpecifier &CS, + const char *startSpecifier, unsigned specifierLen, + unsigned argIndex); }; } -SourceRange CheckPrintfHandler::getFormatStringRange() { +SourceRange CheckFormatHandler::getFormatStringRange() { return OrigFormatExpr->getSourceRange(); } -CharSourceRange CheckPrintfHandler:: -getFormatSpecifierRange(const char *startSpecifier, unsigned specifierLen) { +CharSourceRange CheckFormatHandler:: +getSpecifierRange(const char *startSpecifier, unsigned specifierLen) { SourceLocation Start = getLocationOfByte(startSpecifier); SourceLocation End = getLocationOfByte(startSpecifier + specifierLen - 1); @@ -1261,39 +1198,67 @@ getFormatSpecifierRange(const char *startSpecifier, unsigned specifierLen) { return CharSourceRange::getCharRange(Start, End); } -SourceLocation CheckPrintfHandler::getLocationOfByte(const char *x) { +SourceLocation CheckFormatHandler::getLocationOfByte(const char *x) { return S.getLocationOfStringLiteralByte(FExpr, x - Beg); } -void CheckPrintfHandler:: -HandleIncompleteFormatSpecifier(const char *startSpecifier, - unsigned specifierLen) { +void CheckFormatHandler::HandleIncompleteSpecifier(const char *startSpecifier, + unsigned specifierLen){ SourceLocation Loc = getLocationOfByte(startSpecifier); S.Diag(Loc, diag::warn_printf_incomplete_specifier) - << getFormatSpecifierRange(startSpecifier, specifierLen); + << getSpecifierRange(startSpecifier, specifierLen); } void -CheckPrintfHandler::HandleInvalidPosition(const char *startPos, unsigned posLen, - analyze_printf::PositionContext p) { +CheckFormatHandler::HandleInvalidPosition(const char *startPos, unsigned posLen, + analyze_format_string::PositionContext p) { SourceLocation Loc = getLocationOfByte(startPos); - S.Diag(Loc, diag::warn_printf_invalid_positional_specifier) - << (unsigned) p << getFormatSpecifierRange(startPos, posLen); + S.Diag(Loc, diag::warn_format_invalid_positional_specifier) + << (unsigned) p << getSpecifierRange(startPos, posLen); } -void CheckPrintfHandler::HandleZeroPosition(const char *startPos, +void CheckFormatHandler::HandleZeroPosition(const char *startPos, unsigned posLen) { SourceLocation Loc = getLocationOfByte(startPos); - S.Diag(Loc, diag::warn_printf_zero_positional_specifier) - << getFormatSpecifierRange(startPos, posLen); + S.Diag(Loc, diag::warn_format_zero_positional_specifier) + << getSpecifierRange(startPos, posLen); +} + +void CheckFormatHandler::HandleNullChar(const char *nullCharacter) { + // The presence of a null character is likely an error. + S.Diag(getLocationOfByte(nullCharacter), + diag::warn_printf_format_string_contains_null_char) + << getFormatStringRange(); } -bool CheckPrintfHandler:: -HandleInvalidConversionSpecifier(const analyze_printf::FormatSpecifier &FS, - const char *startSpecifier, - unsigned specifierLen) { +const Expr *CheckFormatHandler::getDataArg(unsigned i) const { + return TheCall->getArg(FirstDataArg + i); +} - unsigned argIndex = FS.getArgIndex(); +void CheckFormatHandler::DoneProcessing() { + // Does the number of data arguments exceed the number of + // format conversions in the format string? + if (!HasVAListArg) { + // Find any arguments that weren't covered. + CoveredArgs.flip(); + signed notCoveredArg = CoveredArgs.find_first(); + if (notCoveredArg >= 0) { + assert((unsigned)notCoveredArg < NumDataArgs); + S.Diag(getDataArg((unsigned) notCoveredArg)->getLocStart(), + diag::warn_printf_data_arg_not_used) + << getFormatStringRange(); + } + } +} + +bool +CheckFormatHandler::HandleInvalidConversionSpecifier(unsigned argIndex, + SourceLocation Loc, + const char *startSpec, + unsigned specifierLen, + const char *csStart, + unsigned csLen) { + bool keepGoing = true; if (argIndex < NumDataArgs) { // Consider the argument coverered, even though the specifier doesn't @@ -1308,32 +1273,95 @@ HandleInvalidConversionSpecifier(const analyze_printf::FormatSpecifier &FS, // gibberish when trying to match arguments. keepGoing = false; } + + S.Diag(Loc, diag::warn_format_invalid_conversion) + << llvm::StringRef(csStart, csLen) + << getSpecifierRange(startSpec, specifierLen); + + return keepGoing; +} - const analyze_printf::ConversionSpecifier &CS = - FS.getConversionSpecifier(); - SourceLocation Loc = getLocationOfByte(CS.getStart()); - S.Diag(Loc, diag::warn_printf_invalid_conversion) - << llvm::StringRef(CS.getStart(), CS.getLength()) - << getFormatSpecifierRange(startSpecifier, specifierLen); +bool +CheckFormatHandler::CheckNumArgs( + const analyze_format_string::FormatSpecifier &FS, + const analyze_format_string::ConversionSpecifier &CS, + const char *startSpecifier, unsigned specifierLen, unsigned argIndex) { - return keepGoing; + if (argIndex >= NumDataArgs) { + if (FS.usesPositionalArg()) { + S.Diag(getLocationOfByte(CS.getStart()), + diag::warn_printf_positional_arg_exceeds_data_args) + << (argIndex+1) << NumDataArgs + << getSpecifierRange(startSpecifier, specifierLen); + } + else { + S.Diag(getLocationOfByte(CS.getStart()), + diag::warn_printf_insufficient_data_args) + << getSpecifierRange(startSpecifier, specifierLen); + } + + return false; + } + return true; } -void CheckPrintfHandler::HandleNullChar(const char *nullCharacter) { - // The presence of a null character is likely an error. - S.Diag(getLocationOfByte(nullCharacter), - diag::warn_printf_format_string_contains_null_char) - << getFormatStringRange(); +//===--- CHECK: Printf format string checking ------------------------------===// + +namespace { +class CheckPrintfHandler : public CheckFormatHandler { +public: + CheckPrintfHandler(Sema &s, const StringLiteral *fexpr, + const Expr *origFormatExpr, unsigned firstDataArg, + unsigned numDataArgs, bool isObjCLiteral, + const char *beg, bool hasVAListArg, + const CallExpr *theCall, unsigned formatIdx) + : CheckFormatHandler(s, fexpr, origFormatExpr, firstDataArg, + numDataArgs, isObjCLiteral, beg, hasVAListArg, + theCall, formatIdx) {} + + + bool HandleInvalidPrintfConversionSpecifier( + const analyze_printf::PrintfSpecifier &FS, + const char *startSpecifier, + unsigned specifierLen); + + bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS, + const char *startSpecifier, + unsigned specifierLen); + + bool HandleAmount(const analyze_format_string::OptionalAmount &Amt, unsigned k, + const char *startSpecifier, unsigned specifierLen); + void HandleInvalidAmount(const analyze_printf::PrintfSpecifier &FS, + const analyze_printf::OptionalAmount &Amt, + unsigned type, + const char *startSpecifier, unsigned specifierLen); + void HandleFlag(const analyze_printf::PrintfSpecifier &FS, + const analyze_printf::OptionalFlag &flag, + const char *startSpecifier, unsigned specifierLen); + void HandleIgnoredFlag(const analyze_printf::PrintfSpecifier &FS, + const analyze_printf::OptionalFlag &ignoredFlag, + const analyze_printf::OptionalFlag &flag, + const char *startSpecifier, unsigned specifierLen); +}; } -const Expr *CheckPrintfHandler::getDataArg(unsigned i) const { - return TheCall->getArg(FirstDataArg + i); +bool CheckPrintfHandler::HandleInvalidPrintfConversionSpecifier( + const analyze_printf::PrintfSpecifier &FS, + const char *startSpecifier, + unsigned specifierLen) { + const analyze_printf::PrintfConversionSpecifier &CS = + FS.getConversionSpecifier(); + + return HandleInvalidConversionSpecifier(FS.getArgIndex(), + getLocationOfByte(CS.getStart()), + startSpecifier, specifierLen, + CS.getStart(), CS.getLength()); } -bool -CheckPrintfHandler::HandleAmount(const analyze_printf::OptionalAmount &Amt, - unsigned k, const char *startSpecifier, - unsigned specifierLen) { +bool CheckPrintfHandler::HandleAmount( + const analyze_format_string::OptionalAmount &Amt, + unsigned k, const char *startSpecifier, + unsigned specifierLen) { if (Amt.hasDataArgument()) { if (!HasVAListArg) { @@ -1341,7 +1369,7 @@ CheckPrintfHandler::HandleAmount(const analyze_printf::OptionalAmount &Amt, if (argIndex >= NumDataArgs) { S.Diag(getLocationOfByte(Amt.getStart()), diag::warn_printf_asterisk_missing_arg) - << k << getFormatSpecifierRange(startSpecifier, specifierLen); + << k << getSpecifierRange(startSpecifier, specifierLen); // Don't do any more checking. We will just emit // spurious errors. return false; @@ -1363,7 +1391,7 @@ CheckPrintfHandler::HandleAmount(const analyze_printf::OptionalAmount &Amt, diag::warn_printf_asterisk_wrong_type) << k << ATR.getRepresentativeType(S.Context) << T - << getFormatSpecifierRange(startSpecifier, specifierLen) + << getSpecifierRange(startSpecifier, specifierLen) << Arg->getSourceRange(); // Don't do any more checking. We will just emit // spurious errors. @@ -1375,20 +1403,21 @@ CheckPrintfHandler::HandleAmount(const analyze_printf::OptionalAmount &Amt, } void CheckPrintfHandler::HandleInvalidAmount( - const analyze_printf::FormatSpecifier &FS, + const analyze_printf::PrintfSpecifier &FS, const analyze_printf::OptionalAmount &Amt, unsigned type, const char *startSpecifier, unsigned specifierLen) { - const analyze_printf::ConversionSpecifier &CS = FS.getConversionSpecifier(); + const analyze_printf::PrintfConversionSpecifier &CS = + FS.getConversionSpecifier(); switch (Amt.getHowSpecified()) { case analyze_printf::OptionalAmount::Constant: S.Diag(getLocationOfByte(Amt.getStart()), diag::warn_printf_nonsensical_optional_amount) << type << CS.toString() - << getFormatSpecifierRange(startSpecifier, specifierLen) - << FixItHint::CreateRemoval(getFormatSpecifierRange(Amt.getStart(), + << getSpecifierRange(startSpecifier, specifierLen) + << FixItHint::CreateRemoval(getSpecifierRange(Amt.getStart(), Amt.getConstantLength())); break; @@ -1397,26 +1426,27 @@ void CheckPrintfHandler::HandleInvalidAmount( diag::warn_printf_nonsensical_optional_amount) << type << CS.toString() - << getFormatSpecifierRange(startSpecifier, specifierLen); + << getSpecifierRange(startSpecifier, specifierLen); break; } } -void CheckPrintfHandler::HandleFlag(const analyze_printf::FormatSpecifier &FS, +void CheckPrintfHandler::HandleFlag(const analyze_printf::PrintfSpecifier &FS, const analyze_printf::OptionalFlag &flag, const char *startSpecifier, unsigned specifierLen) { // Warn about pointless flag with a fixit removal. - const analyze_printf::ConversionSpecifier &CS = FS.getConversionSpecifier(); + const analyze_printf::PrintfConversionSpecifier &CS = + FS.getConversionSpecifier(); S.Diag(getLocationOfByte(flag.getPosition()), diag::warn_printf_nonsensical_flag) << flag.toString() << CS.toString() - << getFormatSpecifierRange(startSpecifier, specifierLen) - << FixItHint::CreateRemoval(getFormatSpecifierRange(flag.getPosition(), 1)); + << getSpecifierRange(startSpecifier, specifierLen) + << FixItHint::CreateRemoval(getSpecifierRange(flag.getPosition(), 1)); } void CheckPrintfHandler::HandleIgnoredFlag( - const analyze_printf::FormatSpecifier &FS, + const analyze_printf::PrintfSpecifier &FS, const analyze_printf::OptionalFlag &ignoredFlag, const analyze_printf::OptionalFlag &flag, const char *startSpecifier, @@ -1425,30 +1455,33 @@ void CheckPrintfHandler::HandleIgnoredFlag( S.Diag(getLocationOfByte(ignoredFlag.getPosition()), diag::warn_printf_ignored_flag) << ignoredFlag.toString() << flag.toString() - << getFormatSpecifierRange(startSpecifier, specifierLen) - << FixItHint::CreateRemoval(getFormatSpecifierRange( + << getSpecifierRange(startSpecifier, specifierLen) + << FixItHint::CreateRemoval(getSpecifierRange( ignoredFlag.getPosition(), 1)); } bool -CheckPrintfHandler::HandleFormatSpecifier(const analyze_printf::FormatSpecifier +CheckPrintfHandler::HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS, const char *startSpecifier, unsigned specifierLen) { + using namespace analyze_format_string; using namespace analyze_printf; - const ConversionSpecifier &CS = FS.getConversionSpecifier(); + const PrintfConversionSpecifier &CS = FS.getConversionSpecifier(); - if (atFirstArg) { - atFirstArg = false; - usesPositionalArgs = FS.usesPositionalArg(); - } - else if (usesPositionalArgs != FS.usesPositionalArg()) { - // Cannot mix-and-match positional and non-positional arguments. - S.Diag(getLocationOfByte(CS.getStart()), - diag::warn_printf_mix_positional_nonpositional_args) - << getFormatSpecifierRange(startSpecifier, specifierLen); - return false; + if (FS.consumesDataArgument()) { + if (atFirstArg) { + atFirstArg = false; + usesPositionalArgs = FS.usesPositionalArg(); + } + else if (usesPositionalArgs != FS.usesPositionalArg()) { + // Cannot mix-and-match positional and non-positional arguments. + S.Diag(getLocationOfByte(CS.getStart()), + diag::warn_format_mix_positional_nonpositional_args) + << getSpecifierRange(startSpecifier, specifierLen); + return false; + } } // First check if the field width, precision, and conversion specifier @@ -1481,7 +1514,8 @@ CheckPrintfHandler::HandleFormatSpecifier(const analyze_printf::FormatSpecifier // Check for using an Objective-C specific conversion specifier // in a non-ObjC literal. if (!IsObjCLiteral && CS.isObjCArg()) { - return HandleInvalidConversionSpecifier(FS, startSpecifier, specifierLen); + return HandleInvalidPrintfConversionSpecifier(FS, startSpecifier, + specifierLen); } // Check for invalid use of field width @@ -1520,17 +1554,17 @@ CheckPrintfHandler::HandleFormatSpecifier(const analyze_printf::FormatSpecifier const LengthModifier &LM = FS.getLengthModifier(); if (!FS.hasValidLengthModifier()) S.Diag(getLocationOfByte(LM.getStart()), - diag::warn_printf_nonsensical_length) + diag::warn_format_nonsensical_length) << LM.toString() << CS.toString() - << getFormatSpecifierRange(startSpecifier, specifierLen) - << FixItHint::CreateRemoval(getFormatSpecifierRange(LM.getStart(), + << getSpecifierRange(startSpecifier, specifierLen) + << FixItHint::CreateRemoval(getSpecifierRange(LM.getStart(), LM.getLength())); // Are we using '%n'? - if (CS.getKind() == ConversionSpecifier::OutIntPtrArg) { + if (CS.getKind() == ConversionSpecifier::nArg) { // Issue a warning about this being a possible security issue. S.Diag(getLocationOfByte(CS.getStart()), diag::warn_printf_write_back) - << getFormatSpecifierRange(startSpecifier, specifierLen); + << getSpecifierRange(startSpecifier, specifierLen); // Continue checking the other format specifiers. return true; } @@ -1539,22 +1573,8 @@ CheckPrintfHandler::HandleFormatSpecifier(const analyze_printf::FormatSpecifier if (HasVAListArg) return true; - if (argIndex >= NumDataArgs) { - if (FS.usesPositionalArg()) { - S.Diag(getLocationOfByte(CS.getStart()), - diag::warn_printf_positional_arg_exceeds_data_args) - << (argIndex+1) << NumDataArgs - << getFormatSpecifierRange(startSpecifier, specifierLen); - } - else { - S.Diag(getLocationOfByte(CS.getStart()), - diag::warn_printf_insufficient_data_args) - << getFormatSpecifierRange(startSpecifier, specifierLen); - } - - // Don't do any more checking. + if (!CheckNumArgs(FS, CS, startSpecifier, specifierLen, argIndex)) return false; - } // Now type check the data expression that matches the // format specifier. @@ -1570,7 +1590,7 @@ CheckPrintfHandler::HandleFormatSpecifier(const analyze_printf::FormatSpecifier return true; // We may be able to offer a FixItHint if it is a supported type. - FormatSpecifier fixedFS = FS; + PrintfSpecifier fixedFS = FS; bool success = fixedFS.fixType(Ex->getType()); if (success) { @@ -1579,20 +1599,23 @@ CheckPrintfHandler::HandleFormatSpecifier(const analyze_printf::FormatSpecifier llvm::raw_svector_ostream os(buf); fixedFS.toString(os); + // FIXME: getRepresentativeType() perhaps should return a string + // instead of a QualType to better handle when the representative + // type is 'wint_t' (which is defined in the system headers). S.Diag(getLocationOfByte(CS.getStart()), diag::warn_printf_conversion_argument_type_mismatch) << ATR.getRepresentativeType(S.Context) << Ex->getType() - << getFormatSpecifierRange(startSpecifier, specifierLen) + << getSpecifierRange(startSpecifier, specifierLen) << Ex->getSourceRange() << FixItHint::CreateReplacement( - getFormatSpecifierRange(startSpecifier, specifierLen), + getSpecifierRange(startSpecifier, specifierLen), os.str()); } else { S.Diag(getLocationOfByte(CS.getStart()), diag::warn_printf_conversion_argument_type_mismatch) << ATR.getRepresentativeType(S.Context) << Ex->getType() - << getFormatSpecifierRange(startSpecifier, specifierLen) + << getSpecifierRange(startSpecifier, specifierLen) << Ex->getSourceRange(); } } @@ -1600,54 +1623,173 @@ CheckPrintfHandler::HandleFormatSpecifier(const analyze_printf::FormatSpecifier return true; } -void CheckPrintfHandler::DoneProcessing() { - // Does the number of data arguments exceed the number of - // format conversions in the format string? - if (!HasVAListArg) { - // Find any arguments that weren't covered. - CoveredArgs.flip(); - signed notCoveredArg = CoveredArgs.find_first(); - if (notCoveredArg >= 0) { - assert((unsigned)notCoveredArg < NumDataArgs); - S.Diag(getDataArg((unsigned) notCoveredArg)->getLocStart(), - diag::warn_printf_data_arg_not_used) - << getFormatStringRange(); +//===--- CHECK: Scanf format string checking ------------------------------===// + +namespace { +class CheckScanfHandler : public CheckFormatHandler { +public: + CheckScanfHandler(Sema &s, const StringLiteral *fexpr, + const Expr *origFormatExpr, unsigned firstDataArg, + unsigned numDataArgs, bool isObjCLiteral, + const char *beg, bool hasVAListArg, + const CallExpr *theCall, unsigned formatIdx) + : CheckFormatHandler(s, fexpr, origFormatExpr, firstDataArg, + numDataArgs, isObjCLiteral, beg, hasVAListArg, + theCall, formatIdx) {} + + bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS, + const char *startSpecifier, + unsigned specifierLen); + + bool HandleInvalidScanfConversionSpecifier( + const analyze_scanf::ScanfSpecifier &FS, + const char *startSpecifier, + unsigned specifierLen); + + void HandleIncompleteScanList(const char *start, const char *end); +}; +} + +void CheckScanfHandler::HandleIncompleteScanList(const char *start, + const char *end) { + S.Diag(getLocationOfByte(end), diag::warn_scanf_scanlist_incomplete) + << getSpecifierRange(start, end - start); +} + +bool CheckScanfHandler::HandleInvalidScanfConversionSpecifier( + const analyze_scanf::ScanfSpecifier &FS, + const char *startSpecifier, + unsigned specifierLen) { + + const analyze_scanf::ScanfConversionSpecifier &CS = + FS.getConversionSpecifier(); + + return HandleInvalidConversionSpecifier(FS.getArgIndex(), + getLocationOfByte(CS.getStart()), + startSpecifier, specifierLen, + CS.getStart(), CS.getLength()); +} + +bool CheckScanfHandler::HandleScanfSpecifier( + const analyze_scanf::ScanfSpecifier &FS, + const char *startSpecifier, + unsigned specifierLen) { + + using namespace analyze_scanf; + using namespace analyze_format_string; + + const ScanfConversionSpecifier &CS = FS.getConversionSpecifier(); + + // Handle case where '%' and '*' don't consume an argument. These shouldn't + // be used to decide if we are using positional arguments consistently. + if (FS.consumesDataArgument()) { + if (atFirstArg) { + atFirstArg = false; + usesPositionalArgs = FS.usesPositionalArg(); + } + else if (usesPositionalArgs != FS.usesPositionalArg()) { + // Cannot mix-and-match positional and non-positional arguments. + S.Diag(getLocationOfByte(CS.getStart()), + diag::warn_format_mix_positional_nonpositional_args) + << getSpecifierRange(startSpecifier, specifierLen); + return false; + } + } + + // Check if the field with is non-zero. + const OptionalAmount &Amt = FS.getFieldWidth(); + if (Amt.getHowSpecified() == OptionalAmount::Constant) { + if (Amt.getConstantAmount() == 0) { + const CharSourceRange &R = getSpecifierRange(Amt.getStart(), + Amt.getConstantLength()); + S.Diag(getLocationOfByte(Amt.getStart()), + diag::warn_scanf_nonzero_width) + << R << FixItHint::CreateRemoval(R); } } + + if (!FS.consumesDataArgument()) { + // FIXME: Technically specifying a precision or field width here + // makes no sense. Worth issuing a warning at some point. + return true; + } + + // Consume the argument. + unsigned argIndex = FS.getArgIndex(); + if (argIndex < NumDataArgs) { + // The check to see if the argIndex is valid will come later. + // We set the bit here because we may exit early from this + // function if we encounter some other error. + CoveredArgs.set(argIndex); + } + + // Check the length modifier is valid with the given conversion specifier. + const LengthModifier &LM = FS.getLengthModifier(); + if (!FS.hasValidLengthModifier()) { + S.Diag(getLocationOfByte(LM.getStart()), + diag::warn_format_nonsensical_length) + << LM.toString() << CS.toString() + << getSpecifierRange(startSpecifier, specifierLen) + << FixItHint::CreateRemoval(getSpecifierRange(LM.getStart(), + LM.getLength())); + } + + // The remaining checks depend on the data arguments. + if (HasVAListArg) + return true; + + if (!CheckNumArgs(FS, CS, startSpecifier, specifierLen, argIndex)) + return false; + + // FIXME: Check that the argument type matches the format specifier. + + return true; } -void Sema::CheckPrintfString(const StringLiteral *FExpr, +void Sema::CheckFormatString(const StringLiteral *FExpr, const Expr *OrigFormatExpr, const CallExpr *TheCall, bool HasVAListArg, - unsigned format_idx, unsigned firstDataArg) { - + unsigned format_idx, unsigned firstDataArg, + bool isPrintf) { + // CHECK: is the format string a wide literal? if (FExpr->isWide()) { Diag(FExpr->getLocStart(), - diag::warn_printf_format_string_is_wide_literal) + diag::warn_format_string_is_wide_literal) << OrigFormatExpr->getSourceRange(); return; } - + // Str - The format string. NOTE: this is NOT null-terminated! - const char *Str = FExpr->getStrData(); - + llvm::StringRef StrRef = FExpr->getString(); + const char *Str = StrRef.data(); + unsigned StrLen = StrRef.size(); + // CHECK: empty format string? - unsigned StrLen = FExpr->getByteLength(); - if (StrLen == 0) { - Diag(FExpr->getLocStart(), diag::warn_printf_empty_format_string) + Diag(FExpr->getLocStart(), diag::warn_empty_format_string) << OrigFormatExpr->getSourceRange(); return; } - - CheckPrintfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg, - TheCall->getNumArgs() - firstDataArg, - isa(OrigFormatExpr), Str, - HasVAListArg, TheCall, format_idx); - - if (!analyze_printf::ParseFormatString(H, Str, Str + StrLen)) - H.DoneProcessing(); + + if (isPrintf) { + CheckPrintfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg, + TheCall->getNumArgs() - firstDataArg, + isa(OrigFormatExpr), Str, + HasVAListArg, TheCall, format_idx); + + if (!analyze_format_string::ParsePrintfString(H, Str, Str + StrLen)) + H.DoneProcessing(); + } + else { + CheckScanfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg, + TheCall->getNumArgs() - firstDataArg, + isa(OrigFormatExpr), Str, + HasVAListArg, TheCall, format_idx); + + if (!analyze_format_string::ParseScanfString(H, Str, Str + StrLen)) + H.DoneProcessing(); + } } //===--- CHECK: Return Address of Stack Variable --------------------------===// @@ -1729,7 +1871,7 @@ static DeclRefExpr* EvalAddr(Expr *E) { // is AddrOf. All others don't make sense as pointers. UnaryOperator *U = cast(E); - if (U->getOpcode() == UnaryOperator::AddrOf) + if (U->getOpcode() == UO_AddrOf) return EvalVal(U->getSubExpr()); else return NULL; @@ -1739,9 +1881,9 @@ static DeclRefExpr* EvalAddr(Expr *E) { // Handle pointer arithmetic. All other binary operators are not valid // in this context. BinaryOperator *B = cast(E); - BinaryOperator::Opcode op = B->getOpcode(); + BinaryOperatorKind op = B->getOpcode(); - if (op != BinaryOperator::Add && op != BinaryOperator::Sub) + if (op != BO_Add && op != BO_Sub) return NULL; Expr *Base = B->getLHS(); @@ -1814,7 +1956,7 @@ static DeclRefExpr* EvalAddr(Expr *E) { /// EvalVal - This function is complements EvalAddr in the mutual recursion. /// See the comments for EvalAddr for more details. static DeclRefExpr* EvalVal(Expr *E) { - +do { // We should only be called for evaluating non-pointer expressions, or // expressions with a pointer type that are not used as references but instead // are l-values (e.g., DeclRefExpr with a pointer type). @@ -1823,6 +1965,15 @@ static DeclRefExpr* EvalVal(Expr *E) { // viewed AST node. We then recursively traverse the AST by calling // EvalAddr and EvalVal appropriately. switch (E->getStmtClass()) { + case Stmt::ImplicitCastExprClass: { + ImplicitCastExpr *IE = cast(E); + if (IE->getValueKind() == VK_LValue) { + E = IE->getSubExpr(); + continue; + } + return NULL; + } + case Stmt::DeclRefExprClass: { // DeclRefExpr: the base case. When we hit a DeclRefExpr we are looking // at code that refers to a variable's name. We check if it has local @@ -1835,9 +1986,11 @@ static DeclRefExpr* EvalVal(Expr *E) { return NULL; } - case Stmt::ParenExprClass: + case Stmt::ParenExprClass: { // Ignore parentheses. - return EvalVal(cast(E)->getSubExpr()); + E = cast(E)->getSubExpr(); + continue; + } case Stmt::UnaryOperatorClass: { // The only unary operator that make sense to handle here @@ -1845,7 +1998,7 @@ static DeclRefExpr* EvalVal(Expr *E) { // handling all sorts of rvalues passed to a unary operator. UnaryOperator *U = cast(E); - if (U->getOpcode() == UnaryOperator::Deref) + if (U->getOpcode() == UO_Deref) return EvalAddr(U->getSubExpr()); return NULL; @@ -1876,16 +2029,22 @@ static DeclRefExpr* EvalVal(Expr *E) { MemberExpr *M = cast(E); // Check for indirect access. We only want direct field accesses. - if (!M->isArrow()) - return EvalVal(M->getBase()); - else + if (M->isArrow()) return NULL; + + // Check whether the member type is itself a reference, in which case + // we're not going to refer to the member, but to what the member refers to. + if (M->getMemberDecl()->getType()->isReferenceType()) + return NULL; + + return EvalVal(M->getBase()); } // Everything else: we simply don't reason about them. default: return NULL; } +} while (true); } //===--- CHECK: Floating-Point comparisons (-Wfloat-equal) ---------------===// @@ -1954,7 +2113,6 @@ struct IntRange { /// True if the int is known not to have negative values. bool NonNegative; - IntRange() {} IntRange(unsigned Width, bool NonNegative) : Width(Width), NonNegative(NonNegative) {} @@ -2063,13 +2221,13 @@ IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) { // user has an explicit widening cast, we should treat the value as // being of the new, wider type. if (ImplicitCastExpr *CE = dyn_cast(E)) { - if (CE->getCastKind() == CastExpr::CK_NoOp) + if (CE->getCastKind() == CK_NoOp) return GetExprRange(C, CE->getSubExpr(), MaxWidth); IntRange OutputTypeRange = IntRange::forType(C, CE->getType()); - bool isIntegerCast = (CE->getCastKind() == CastExpr::CK_IntegralCast); - if (!isIntegerCast && CE->getCastKind() == CastExpr::CK_Unknown) + bool isIntegerCast = (CE->getCastKind() == CK_IntegralCast); + if (!isIntegerCast && CE->getCastKind() == CK_Unknown) isIntegerCast = CE->getSubExpr()->getType()->isIntegerType(); // Assume that non-integer casts can span the full range of the type. @@ -2108,38 +2266,38 @@ IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) { switch (BO->getOpcode()) { // Boolean-valued operations are single-bit and positive. - case BinaryOperator::LAnd: - case BinaryOperator::LOr: - case BinaryOperator::LT: - case BinaryOperator::GT: - case BinaryOperator::LE: - case BinaryOperator::GE: - case BinaryOperator::EQ: - case BinaryOperator::NE: + case BO_LAnd: + case BO_LOr: + case BO_LT: + case BO_GT: + case BO_LE: + case BO_GE: + case BO_EQ: + case BO_NE: return IntRange::forBoolType(); // The type of these compound assignments is the type of the LHS, // so the RHS is not necessarily an integer. - case BinaryOperator::MulAssign: - case BinaryOperator::DivAssign: - case BinaryOperator::RemAssign: - case BinaryOperator::AddAssign: - case BinaryOperator::SubAssign: + case BO_MulAssign: + case BO_DivAssign: + case BO_RemAssign: + case BO_AddAssign: + case BO_SubAssign: return IntRange::forType(C, E->getType()); // Operations with opaque sources are black-listed. - case BinaryOperator::PtrMemD: - case BinaryOperator::PtrMemI: + case BO_PtrMemD: + case BO_PtrMemI: return IntRange::forType(C, E->getType()); // Bitwise-and uses the *infinum* of the two source ranges. - case BinaryOperator::And: - case BinaryOperator::AndAssign: + case BO_And: + case BO_AndAssign: return IntRange::meet(GetExprRange(C, BO->getLHS(), MaxWidth), GetExprRange(C, BO->getRHS(), MaxWidth)); // Left shift gets black-listed based on a judgement call. - case BinaryOperator::Shl: + case BO_Shl: // ...except that we want to treat '1 << (blah)' as logically // positive. It's an important idiom. if (IntegerLiteral *I @@ -2151,12 +2309,12 @@ IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) { } // fallthrough - case BinaryOperator::ShlAssign: + case BO_ShlAssign: return IntRange::forType(C, E->getType()); // Right shift by a constant can narrow its left argument. - case BinaryOperator::Shr: - case BinaryOperator::ShrAssign: { + case BO_Shr: + case BO_ShrAssign: { IntRange L = GetExprRange(C, BO->getLHS(), MaxWidth); // If the shift amount is a positive constant, drop the width by @@ -2175,11 +2333,11 @@ IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) { } // Comma acts as its right operand. - case BinaryOperator::Comma: + case BO_Comma: return GetExprRange(C, BO->getRHS(), MaxWidth); // Black-list pointer subtractions. - case BinaryOperator::Sub: + case BO_Sub: if (BO->getLHS()->getType()->isPointerType()) return IntRange::forType(C, E->getType()); // fallthrough @@ -2198,13 +2356,12 @@ IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) { if (UnaryOperator *UO = dyn_cast(E)) { switch (UO->getOpcode()) { // Boolean-valued operations are white-listed. - case UnaryOperator::LNot: + case UO_LNot: return IntRange::forBoolType(); // Operations with opaque sources are black-listed. - case UnaryOperator::Deref: - case UnaryOperator::AddrOf: // should be impossible - case UnaryOperator::OffsetOf: + case UO_Deref: + case UO_AddrOf: // should be impossible return IntRange::forType(C, E->getType()); default: @@ -2277,20 +2434,20 @@ bool IsZero(Sema &S, Expr *E) { } void CheckTrivialUnsignedComparison(Sema &S, BinaryOperator *E) { - BinaryOperator::Opcode op = E->getOpcode(); - if (op == BinaryOperator::LT && IsZero(S, E->getRHS())) { + BinaryOperatorKind op = E->getOpcode(); + if (op == BO_LT && IsZero(S, E->getRHS())) { S.Diag(E->getOperatorLoc(), diag::warn_lunsigned_always_true_comparison) << "< 0" << "false" << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange(); - } else if (op == BinaryOperator::GE && IsZero(S, E->getRHS())) { + } else if (op == BO_GE && IsZero(S, E->getRHS())) { S.Diag(E->getOperatorLoc(), diag::warn_lunsigned_always_true_comparison) << ">= 0" << "true" << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange(); - } else if (op == BinaryOperator::GT && IsZero(S, E->getLHS())) { + } else if (op == BO_GT && IsZero(S, E->getLHS())) { S.Diag(E->getOperatorLoc(), diag::warn_runsigned_always_true_comparison) << "0 >" << "false" << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange(); - } else if (op == BinaryOperator::LE && IsZero(S, E->getLHS())) { + } else if (op == BO_LE && IsZero(S, E->getLHS())) { S.Diag(E->getOperatorLoc(), diag::warn_runsigned_always_true_comparison) << "0 <=" << "true" << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange(); @@ -2319,7 +2476,7 @@ void AnalyzeComparison(Sema &S, BinaryOperator *E) { // We don't do anything special if this isn't an unsigned integral // comparison: we're only interested in integral comparisons, and // signed comparisons only happen in cases we don't care to warn about. - if (!T->isUnsignedIntegerType()) + if (!T->hasUnsignedIntegerRepresentation()) return AnalyzeImpConvsInComparison(S, E); Expr *lex = E->getLHS()->IgnoreParenImpCasts(); @@ -2328,12 +2485,12 @@ void AnalyzeComparison(Sema &S, BinaryOperator *E) { // Check to see if one of the (unmodified) operands is of different // signedness. Expr *signedOperand, *unsignedOperand; - if (lex->getType()->isSignedIntegerType()) { - assert(!rex->getType()->isSignedIntegerType() && + if (lex->getType()->hasSignedIntegerRepresentation()) { + assert(!rex->getType()->hasSignedIntegerRepresentation() && "unsigned comparison between two signed integer expressions?"); signedOperand = lex; unsignedOperand = rex; - } else if (rex->getType()->isSignedIntegerType()) { + } else if (rex->getType()->hasSignedIntegerRepresentation()) { signedOperand = rex; unsignedOperand = lex; } else { @@ -2648,3 +2805,48 @@ bool Sema::CheckParmsForFunctionDef(FunctionDecl *FD) { return HasInvalidParm; } + +/// CheckCastAlign - Implements -Wcast-align, which warns when a +/// pointer cast increases the alignment requirements. +void Sema::CheckCastAlign(Expr *Op, QualType T, SourceRange TRange) { + // This is actually a lot of work to potentially be doing on every + // cast; don't do it if we're ignoring -Wcast_align (as is the default). + if (getDiagnostics().getDiagnosticLevel(diag::warn_cast_align) + == Diagnostic::Ignored) + return; + + // Ignore dependent types. + if (T->isDependentType() || Op->getType()->isDependentType()) + return; + + // Require that the destination be a pointer type. + const PointerType *DestPtr = T->getAs(); + if (!DestPtr) return; + + // If the destination has alignment 1, we're done. + QualType DestPointee = DestPtr->getPointeeType(); + if (DestPointee->isIncompleteType()) return; + CharUnits DestAlign = Context.getTypeAlignInChars(DestPointee); + if (DestAlign.isOne()) return; + + // Require that the source be a pointer type. + const PointerType *SrcPtr = Op->getType()->getAs(); + if (!SrcPtr) return; + QualType SrcPointee = SrcPtr->getPointeeType(); + + // Whitelist casts from cv void*. We already implicitly + // whitelisted casts to cv void*, since they have alignment 1. + // Also whitelist casts involving incomplete types, which implicitly + // includes 'void'. + if (SrcPointee->isIncompleteType()) return; + + CharUnits SrcAlign = Context.getTypeAlignInChars(SrcPointee); + if (SrcAlign >= DestAlign) return; + + Diag(TRange.getBegin(), diag::warn_cast_align) + << Op->getType() << T + << static_cast(SrcAlign.getQuantity()) + << static_cast(DestAlign.getQuantity()) + << TRange << Op->getSourceRange(); +} + diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 55288750fd5f..f00d1cd20f1e 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -10,10 +10,14 @@ // This file defines the code-completion semantic actions. // //===----------------------------------------------------------------------===// -#include "Sema.h" -#include "Lookup.h" +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/Overload.h" #include "clang/Sema/CodeCompleteConsumer.h" #include "clang/Sema/ExternalSemaSource.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/ScopeInfo.h" +#include "clang/AST/DeclObjC.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/Lex/MacroInfo.h" @@ -21,11 +25,13 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/Twine.h" #include #include #include using namespace clang; +using namespace sema; namespace { /// \brief A container of code-completion results. @@ -37,7 +43,7 @@ namespace { /// filtered out (returns false). typedef bool (ResultBuilder::*LookupFilter)(NamedDecl *) const; - typedef CodeCompleteConsumer::Result Result; + typedef CodeCompletionResult Result; private: /// \brief The actual results we have found. @@ -130,17 +136,28 @@ namespace { /// different levels of, e.g., the inheritance hierarchy. std::list ShadowMaps; + /// \brief If we're potentially referring to a C++ member function, the set + /// of qualifiers applied to the object type. + Qualifiers ObjectTypeQualifiers; + + /// \brief Whether the \p ObjectTypeQualifiers field is active. + bool HasObjectTypeQualifiers; + + /// \brief The selector that we prefer. + Selector PreferredSelector; + void AdjustResultPriorityForPreferredType(Result &R); public: explicit ResultBuilder(Sema &SemaRef, LookupFilter Filter = 0) - : SemaRef(SemaRef), Filter(Filter), AllowNestedNameSpecifiers(false) { } + : SemaRef(SemaRef), Filter(Filter), AllowNestedNameSpecifiers(false), + HasObjectTypeQualifiers(false) { } /// \brief Whether we should include code patterns in the completion /// results. bool includeCodePatterns() const { return SemaRef.CodeCompleter && - SemaRef.CodeCompleter->includeCodePatterns(); + SemaRef.CodeCompleter->includeCodePatterns(); } /// \brief Set the filter used for code-completion results. @@ -161,6 +178,27 @@ namespace { PreferredType = SemaRef.Context.getCanonicalType(T); } + /// \brief Set the cv-qualifiers on the object type, for us in filtering + /// calls to member functions. + /// + /// When there are qualifiers in this set, they will be used to filter + /// out member functions that aren't available (because there will be a + /// cv-qualifier mismatch) or prefer functions with an exact qualifier + /// match. + void setObjectTypeQualifiers(Qualifiers Quals) { + ObjectTypeQualifiers = Quals; + HasObjectTypeQualifiers = true; + } + + /// \brief Set the preferred selector. + /// + /// When an Objective-C method declaration result is added, and that + /// method's selector matches this preferred selector, we give that method + /// a slight priority boost. + void setPreferredSelector(Selector Sel) { + PreferredSelector = Sel; + } + /// \brief Specify whether nested-name-specifiers are allowed. void allowNestedNameSpecifiers(bool Allow = true) { AllowNestedNameSpecifiers = Allow; @@ -227,6 +265,7 @@ namespace { //@{ bool IsOrdinaryName(NamedDecl *ND) const; bool IsOrdinaryNonTypeName(NamedDecl *ND) const; + bool IsIntegralConstantValue(NamedDecl *ND) const; bool IsOrdinaryNonValueName(NamedDecl *ND) const; bool IsNestedNameSpecifier(NamedDecl *ND) const; bool IsEnum(NamedDecl *ND) const; @@ -238,6 +277,7 @@ namespace { bool IsMember(NamedDecl *ND) const; bool IsObjCIvar(NamedDecl *ND) const; bool IsObjCMessageReceiver(NamedDecl *ND) const; + bool IsObjCCollection(NamedDecl *ND) const; //@} }; } @@ -365,8 +405,12 @@ getRequiredQualification(ASTContext &Context, DeclContext *Parent = TargetParents.back(); TargetParents.pop_back(); - if (NamespaceDecl *Namespace = dyn_cast(Parent)) + if (NamespaceDecl *Namespace = dyn_cast(Parent)) { + if (!Namespace->getIdentifier()) + continue; + Result = NestedNameSpecifier::Create(Context, Result, Namespace); + } else if (TagDecl *TD = dyn_cast(Parent)) Result = NestedNameSpecifier::Create(Context, Result, false, @@ -425,6 +469,12 @@ bool ResultBuilder::isInterestingDecl(NamedDecl *ND, if (isa(ND)) return false; + if (Filter == &ResultBuilder::IsNestedNameSpecifier || + ((isa(ND) || isa(ND)) && + Filter != &ResultBuilder::IsNamespace && + Filter != &ResultBuilder::IsNamespaceOrAlias)) + AsNestedNameSpecifier = true; + // Filter out any unwanted results. if (Filter && !(this->*Filter)(ND)) { // Check whether it is interesting as a nested-name-specifier. @@ -438,11 +488,7 @@ bool ResultBuilder::isInterestingDecl(NamedDecl *ND, } return false; - } - - if (Filter == &ResultBuilder::IsNestedNameSpecifier) - AsNestedNameSpecifier = true; - + } // ... then it must be interesting! return true; } @@ -455,13 +501,13 @@ bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext, if (!SemaRef.getLangOptions().CPlusPlus) return true; - DeclContext *HiddenCtx = R.Declaration->getDeclContext()->getLookupContext(); + DeclContext *HiddenCtx = R.Declaration->getDeclContext()->getRedeclContext(); // There is no way to qualify a name declared in a function or method. if (HiddenCtx->isFunctionOrMethod()) return true; - if (HiddenCtx == Hiding->getDeclContext()->getLookupContext()) + if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext()) return true; // We can refer to the result with the appropriate qualification. Do it. @@ -475,21 +521,9 @@ bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext, return false; } -enum SimplifiedTypeClass { - STC_Arithmetic, - STC_Array, - STC_Block, - STC_Function, - STC_ObjectiveC, - STC_Other, - STC_Pointer, - STC_Record, - STC_Void -}; - /// \brief A simplified classification of types used to determine whether two /// types are "similar enough" when adjusting priorities. -static SimplifiedTypeClass getSimplifiedTypeClass(CanQualType T) { +SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) { switch (T->getTypeClass()) { case Type::Builtin: switch (cast(T)->getKind()) { @@ -560,7 +594,7 @@ static SimplifiedTypeClass getSimplifiedTypeClass(CanQualType T) { /// \brief Get the type that a given expression will have if this declaration /// is used as an expression in its "typical" code-completion form. -static QualType getDeclUsageType(ASTContext &C, NamedDecl *ND) { +QualType clang::getDeclUsageType(ASTContext &C, NamedDecl *ND) { ND = cast(ND->getUnderlyingDecl()); if (TypeDecl *Type = dyn_cast(ND)) @@ -594,9 +628,12 @@ void ResultBuilder::AdjustResultPriorityForPreferredType(Result &R) { CanQualType TC = SemaRef.Context.getCanonicalType(T); // Check for exactly-matching types (modulo qualifiers). - if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC)) - R.Priority /= CCF_ExactTypeMatch; - // Check for nearly-matching types, based on classification of each. + if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC)) { + if (PreferredType->isVoidType()) + R.Priority += CCD_VoidMatch; + else + R.Priority /= CCF_ExactTypeMatch; + } // Check for nearly-matching types, based on classification of each. else if ((getSimplifiedTypeClass(PreferredType) == getSimplifiedTypeClass(TC)) && !(PreferredType->isEnumeralType() && TC->isEnumeralType())) @@ -681,7 +718,14 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) { // Make sure that any given declaration only shows up in the result set once. if (!AllDeclsFound.insert(CanonDecl)) return; - + + // If this is an Objective-C method declaration whose selector matches our + // preferred selector, give it a priority boost. + if (!PreferredSelector.isNull()) + if (ObjCMethodDecl *Method = dyn_cast(R.Declaration)) + if (PreferredSelector == Method->getSelector()) + R.Priority += CCD_SelectorMatch; + // If the filter is for nested-name-specifiers, then this result starts a // nested-name-specifier. if (AsNestedNameSpecifier) { @@ -689,7 +733,7 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) { R.Priority = CCP_NestedNameSpecifier; } else if (!PreferredType.isNull()) AdjustResultPriorityForPreferredType(R); - + // If this result is supposed to have an informative qualifier, add one. if (R.QualifierIsInformative && !R.Qualifier && !R.StartsNestedNameSpecifier) { @@ -742,7 +786,7 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext, } else if (Filter == &ResultBuilder::IsMember && !R.Qualifier && InBaseClass && isa(R.Declaration->getDeclContext() - ->getLookupContext())) + ->getRedeclContext())) R.QualifierIsInformative = true; // If this result is supposed to have an informative qualifier, add one. @@ -762,9 +806,30 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext, if (InBaseClass) R.Priority += CCD_InBaseClass; + // If this is an Objective-C method declaration whose selector matches our + // preferred selector, give it a priority boost. + if (!PreferredSelector.isNull()) + if (ObjCMethodDecl *Method = dyn_cast(R.Declaration)) + if (PreferredSelector == Method->getSelector()) + R.Priority += CCD_SelectorMatch; + if (!PreferredType.isNull()) AdjustResultPriorityForPreferredType(R); + if (HasObjectTypeQualifiers) + if (CXXMethodDecl *Method = dyn_cast(R.Declaration)) + if (Method->isInstance()) { + Qualifiers MethodQuals + = Qualifiers::fromCVRMask(Method->getTypeQualifiers()); + if (ObjectTypeQualifiers == MethodQuals) + R.Priority += CCD_ObjectQualifierMatch; + else if (ObjectTypeQualifiers - MethodQuals) { + // The method cannot be invoked, because doing so would drop + // qualifiers. + return; + } + } + // Insert this result into the set of results. Results.push_back(R); } @@ -821,6 +886,17 @@ bool ResultBuilder::IsOrdinaryNonTypeName(NamedDecl *ND) const { return ND->getIdentifierNamespace() & IDNS; } +bool ResultBuilder::IsIntegralConstantValue(NamedDecl *ND) const { + if (!IsOrdinaryNonTypeName(ND)) + return 0; + + if (ValueDecl *VD = dyn_cast(ND->getUnderlyingDecl())) + if (VD->getType()->isIntegralOrEnumerationType()) + return true; + + return false; +} + /// \brief Determines whether this given declaration will be found by /// ordinary name lookup. bool ResultBuilder::IsOrdinaryNonValueName(NamedDecl *ND) const { @@ -888,7 +964,10 @@ bool ResultBuilder::IsNamespaceOrAlias(NamedDecl *ND) const { /// \brief Determines whether the given declaration is a type. bool ResultBuilder::IsType(NamedDecl *ND) const { - return isa(ND); + if (UsingShadowDecl *Using = dyn_cast(ND)) + ND = Using->getTargetDecl(); + + return isa(ND) || isa(ND); } /// \brief Determines which members of a class should be visible via @@ -944,6 +1023,20 @@ bool ResultBuilder::IsObjCMessageReceiver(NamedDecl *ND) const { return isObjCReceiverType(SemaRef.Context, T); } +bool ResultBuilder::IsObjCCollection(NamedDecl *ND) const { + if ((SemaRef.getLangOptions().CPlusPlus && !IsOrdinaryName(ND)) || + (!SemaRef.getLangOptions().CPlusPlus && !IsOrdinaryNonTypeName(ND))) + return false; + + QualType T = getDeclUsageType(SemaRef.Context, ND); + if (T.isNull()) + return false; + + T = SemaRef.Context.getBaseElementType(T); + return T->isObjCObjectType() || T->isObjCObjectPointerType() || + T->isObjCIdType() || + (SemaRef.getLangOptions().CPlusPlus && T->isRecordType()); +} /// \rief Determines whether the given declaration is an Objective-C /// instance variable. @@ -971,7 +1064,7 @@ namespace { /// \brief Add type specifiers for the current language as keyword results. static void AddTypeSpecifierResults(const LangOptions &LangOpts, ResultBuilder &Results) { - typedef CodeCompleteConsumer::Result Result; + typedef CodeCompletionResult Result; Results.AddResult(Result("short", CCP_Type)); Results.AddResult(Result("long", CCP_Type)); Results.AddResult(Result("signed", CCP_Type)); @@ -1046,10 +1139,10 @@ static void AddTypeSpecifierResults(const LangOptions &LangOpts, } } -static void AddStorageSpecifiers(Action::CodeCompletionContext CCC, +static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC, const LangOptions &LangOpts, ResultBuilder &Results) { - typedef CodeCompleteConsumer::Result Result; + typedef CodeCompletionResult Result; // Note: we don't suggest either "auto" or "register", because both // are pointless as storage specifiers. Elsewhere, we suggest "auto" // in C++0x as a type specifier. @@ -1057,13 +1150,13 @@ static void AddStorageSpecifiers(Action::CodeCompletionContext CCC, Results.AddResult(Result("static")); } -static void AddFunctionSpecifiers(Action::CodeCompletionContext CCC, +static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC, const LangOptions &LangOpts, ResultBuilder &Results) { - typedef CodeCompleteConsumer::Result Result; + typedef CodeCompletionResult Result; switch (CCC) { - case Action::CCC_Class: - case Action::CCC_MemberTemplate: + case Sema::PCC_Class: + case Sema::PCC_MemberTemplate: if (LangOpts.CPlusPlus) { Results.AddResult(Result("explicit")); Results.AddResult(Result("friend")); @@ -1072,20 +1165,21 @@ static void AddFunctionSpecifiers(Action::CodeCompletionContext CCC, } // Fall through - case Action::CCC_ObjCInterface: - case Action::CCC_ObjCImplementation: - case Action::CCC_Namespace: - case Action::CCC_Template: + case Sema::PCC_ObjCInterface: + case Sema::PCC_ObjCImplementation: + case Sema::PCC_Namespace: + case Sema::PCC_Template: if (LangOpts.CPlusPlus || LangOpts.C99) Results.AddResult(Result("inline")); break; - case Action::CCC_ObjCInstanceVariableList: - case Action::CCC_Expression: - case Action::CCC_Statement: - case Action::CCC_ForInit: - case Action::CCC_Condition: - case Action::CCC_RecoveryInFunction: + case Sema::PCC_ObjCInstanceVariableList: + case Sema::PCC_Expression: + case Sema::PCC_Statement: + case Sema::PCC_ForInit: + case Sema::PCC_Condition: + case Sema::PCC_RecoveryInFunction: + case Sema::PCC_Type: break; } } @@ -1110,31 +1204,32 @@ static void AddTypedefResult(ResultBuilder &Results) { Pattern->AddPlaceholderChunk("type"); Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); Pattern->AddPlaceholderChunk("name"); - Results.AddResult(CodeCompleteConsumer::Result(Pattern)); + Results.AddResult(CodeCompletionResult(Pattern)); } -static bool WantTypesInContext(Action::CodeCompletionContext CCC, +static bool WantTypesInContext(Sema::ParserCompletionContext CCC, const LangOptions &LangOpts) { if (LangOpts.CPlusPlus) return true; switch (CCC) { - case Action::CCC_Namespace: - case Action::CCC_Class: - case Action::CCC_ObjCInstanceVariableList: - case Action::CCC_Template: - case Action::CCC_MemberTemplate: - case Action::CCC_Statement: - case Action::CCC_RecoveryInFunction: + case Sema::PCC_Namespace: + case Sema::PCC_Class: + case Sema::PCC_ObjCInstanceVariableList: + case Sema::PCC_Template: + case Sema::PCC_MemberTemplate: + case Sema::PCC_Statement: + case Sema::PCC_RecoveryInFunction: + case Sema::PCC_Type: return true; - case Action::CCC_ObjCInterface: - case Action::CCC_ObjCImplementation: - case Action::CCC_Expression: - case Action::CCC_Condition: + case Sema::PCC_ObjCInterface: + case Sema::PCC_ObjCImplementation: + case Sema::PCC_Expression: + case Sema::PCC_Condition: return false; - case Action::CCC_ForInit: + case Sema::PCC_ForInit: return LangOpts.ObjC1 || LangOpts.C99; } @@ -1142,13 +1237,13 @@ static bool WantTypesInContext(Action::CodeCompletionContext CCC, } /// \brief Add language constructs that show up for "ordinary" names. -static void AddOrdinaryNameResults(Action::CodeCompletionContext CCC, +static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Scope *S, Sema &SemaRef, ResultBuilder &Results) { - typedef CodeCompleteConsumer::Result Result; + typedef CodeCompletionResult Result; switch (CCC) { - case Action::CCC_Namespace: + case Sema::PCC_Namespace: if (SemaRef.getLangOptions().CPlusPlus) { CodeCompletionString *Pattern = 0; @@ -1207,7 +1302,7 @@ static void AddOrdinaryNameResults(Action::CodeCompletionContext CCC, AddTypedefResult(Results); // Fall through - case Action::CCC_Class: + case Sema::PCC_Class: if (SemaRef.getLangOptions().CPlusPlus) { // Using declaration CodeCompletionString *Pattern = new CodeCompletionString; @@ -1231,7 +1326,7 @@ static void AddOrdinaryNameResults(Action::CodeCompletionContext CCC, Results.AddResult(Result(Pattern)); } - if (CCC == Action::CCC_Class) { + if (CCC == Sema::PCC_Class) { AddTypedefResult(Results); // public: @@ -1255,8 +1350,8 @@ static void AddOrdinaryNameResults(Action::CodeCompletionContext CCC, } // Fall through - case Action::CCC_Template: - case Action::CCC_MemberTemplate: + case Sema::PCC_Template: + case Sema::PCC_MemberTemplate: if (SemaRef.getLangOptions().CPlusPlus && Results.includeCodePatterns()) { // template < parameters > CodeCompletionString *Pattern = new CodeCompletionString; @@ -1271,24 +1366,24 @@ static void AddOrdinaryNameResults(Action::CodeCompletionContext CCC, AddFunctionSpecifiers(CCC, SemaRef.getLangOptions(), Results); break; - case Action::CCC_ObjCInterface: + case Sema::PCC_ObjCInterface: AddObjCInterfaceResults(SemaRef.getLangOptions(), Results, true); AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results); AddFunctionSpecifiers(CCC, SemaRef.getLangOptions(), Results); break; - case Action::CCC_ObjCImplementation: + case Sema::PCC_ObjCImplementation: AddObjCImplementationResults(SemaRef.getLangOptions(), Results, true); AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results); AddFunctionSpecifiers(CCC, SemaRef.getLangOptions(), Results); break; - case Action::CCC_ObjCInstanceVariableList: + case Sema::PCC_ObjCInstanceVariableList: AddObjCVisibilityResults(SemaRef.getLangOptions(), Results, true); break; - case Action::CCC_RecoveryInFunction: - case Action::CCC_Statement: { + case Sema::PCC_RecoveryInFunction: + case Sema::PCC_Statement: { AddTypedefResult(Results); CodeCompletionString *Pattern = 0; @@ -1344,7 +1439,7 @@ static void AddOrdinaryNameResults(Action::CodeCompletionContext CCC, } // Switch-specific statements. - if (!SemaRef.getSwitchStack().empty()) { + if (!SemaRef.getCurFunction()->SwitchStack.empty()) { // case expression: Pattern = new CodeCompletionString; Pattern->AddTypedTextChunk("case"); @@ -1460,12 +1555,12 @@ static void AddOrdinaryNameResults(Action::CodeCompletionContext CCC, } // Fall through (for statement expressions). - case Action::CCC_ForInit: - case Action::CCC_Condition: + case Sema::PCC_ForInit: + case Sema::PCC_Condition: AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results); // Fall through: conditions and statements can have expressions. - case Action::CCC_Expression: { + case Sema::PCC_Expression: { CodeCompletionString *Pattern = 0; if (SemaRef.getLangOptions().CPlusPlus) { // 'this', if we're in a non-static member function. @@ -1600,12 +1695,15 @@ static void AddOrdinaryNameResults(Action::CodeCompletionContext CCC, Results.AddResult(Result(Pattern)); break; } + + case Sema::PCC_Type: + break; } if (WantTypesInContext(CCC, SemaRef.getLangOptions())) AddTypeSpecifierResults(SemaRef.getLangOptions(), Results); - if (SemaRef.getLangOptions().CPlusPlus) + if (SemaRef.getLangOptions().CPlusPlus && CCC != Sema::PCC_Type) Results.AddResult(Result("operator")); } @@ -1645,6 +1743,117 @@ static void AddResultTypeChunk(ASTContext &Context, Result->AddResultTypeChunk(TypeStr); } +static void MaybeAddSentinel(ASTContext &Context, NamedDecl *FunctionOrMethod, + CodeCompletionString *Result) { + if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr()) + if (Sentinel->getSentinel() == 0) { + if (Context.getLangOptions().ObjC1 && + Context.Idents.get("nil").hasMacroDefinition()) + Result->AddTextChunk(", nil"); + else if (Context.Idents.get("NULL").hasMacroDefinition()) + Result->AddTextChunk(", NULL"); + else + Result->AddTextChunk(", (void*)0"); + } +} + +static std::string FormatFunctionParameter(ASTContext &Context, + ParmVarDecl *Param, + bool SuppressName = false) { + bool ObjCMethodParam = isa(Param->getDeclContext()); + if (Param->getType()->isDependentType() || + !Param->getType()->isBlockPointerType()) { + // The argument for a dependent or non-block parameter is a placeholder + // containing that parameter's type. + std::string Result; + + if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName) + Result = Param->getIdentifier()->getName(); + + Param->getType().getAsStringInternal(Result, + Context.PrintingPolicy); + + if (ObjCMethodParam) { + Result = "(" + Result; + Result += ")"; + if (Param->getIdentifier() && !SuppressName) + Result += Param->getIdentifier()->getName(); + } + return Result; + } + + // The argument for a block pointer parameter is a block literal with + // the appropriate type. + FunctionProtoTypeLoc *Block = 0; + TypeLoc TL; + if (TypeSourceInfo *TSInfo = Param->getTypeSourceInfo()) { + TL = TSInfo->getTypeLoc().getUnqualifiedLoc(); + while (true) { + // Look through typedefs. + if (TypedefTypeLoc *TypedefTL = dyn_cast(&TL)) { + if (TypeSourceInfo *InnerTSInfo + = TypedefTL->getTypedefDecl()->getTypeSourceInfo()) { + TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc(); + continue; + } + } + + // Look through qualified types + if (QualifiedTypeLoc *QualifiedTL = dyn_cast(&TL)) { + TL = QualifiedTL->getUnqualifiedLoc(); + continue; + } + + // Try to get the function prototype behind the block pointer type, + // then we're done. + if (BlockPointerTypeLoc *BlockPtr + = dyn_cast(&TL)) { + TL = BlockPtr->getPointeeLoc(); + Block = dyn_cast(&TL); + } + break; + } + } + + if (!Block) { + // We were unable to find a FunctionProtoTypeLoc with parameter names + // for the block; just use the parameter type as a placeholder. + std::string Result; + Param->getType().getUnqualifiedType(). + getAsStringInternal(Result, Context.PrintingPolicy); + + if (ObjCMethodParam) { + Result = "(" + Result; + Result += ")"; + if (Param->getIdentifier()) + Result += Param->getIdentifier()->getName(); + } + + return Result; + } + + // We have the function prototype behind the block pointer type, as it was + // written in the source. + std::string Result = "(^)("; + for (unsigned I = 0, N = Block->getNumArgs(); I != N; ++I) { + if (I) + Result += ", "; + Result += FormatFunctionParameter(Context, Block->getArg(I)); + + if (I == N - 1 && Block->getTypePtr()->isVariadic()) + Result += ", ..."; + } + if (Block->getTypePtr()->isVariadic() && Block->getNumArgs() == 0) + Result += "..."; + else if (Block->getNumArgs() == 0 && !Context.getLangOptions().CPlusPlus) + Result += "void"; + + Result += ")"; + Block->getTypePtr()->getResultType().getAsStringInternal(Result, + Context.PrintingPolicy); + return Result; +} + /// \brief Add function parameter chunks to the given code completion string. static void AddFunctionParameterChunks(ASTContext &Context, FunctionDecl *Function, @@ -1668,21 +1877,23 @@ static void AddFunctionParameterChunks(ASTContext &Context, CCStr->AddChunk(Chunk(CodeCompletionString::CK_Comma)); // Format the placeholder string. - std::string PlaceholderStr; - if (Param->getIdentifier()) - PlaceholderStr = Param->getIdentifier()->getName(); - - Param->getType().getAsStringInternal(PlaceholderStr, - Context.PrintingPolicy); - + std::string PlaceholderStr = FormatFunctionParameter(Context, Param); + + if (Function->isVariadic() && P == N - 1) + PlaceholderStr += ", ..."; + // Add the placeholder string. CCStr->AddPlaceholderChunk(PlaceholderStr); } if (const FunctionProtoType *Proto = Function->getType()->getAs()) - if (Proto->isVariadic()) - CCStr->AddPlaceholderChunk(", ..."); + if (Proto->isVariadic()) { + if (Proto->getNumArgs() == 0) + CCStr->AddPlaceholderChunk("..."); + + MaybeAddSentinel(Context, Function, CCStr); + } } /// \brief Add template parameter chunks to the given code completion string. @@ -1799,13 +2010,15 @@ static void AddFunctionTypeQualsToCompletionString(CodeCompletionString *Result, /// how to use this result, or NULL to indicate that the string or name of the /// result is all that is needed. CodeCompletionString * -CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) { +CodeCompletionResult::CreateCodeCompletionString(Sema &S, + CodeCompletionString *Result) { typedef CodeCompletionString::Chunk Chunk; if (Kind == RK_Pattern) - return Pattern->Clone(); + return Pattern->Clone(Result); - CodeCompletionString *Result = new CodeCompletionString; + if (!Result) + Result = new CodeCompletionString; if (Kind == RK_Keyword) { Result->AddTypedTextChunk(Keyword); @@ -1978,10 +2191,20 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) { continue; std::string Arg; - (*P)->getType().getAsStringInternal(Arg, S.Context.PrintingPolicy); - Arg = "(" + Arg + ")"; - if (IdentifierInfo *II = (*P)->getIdentifier()) - Arg += II->getName().str(); + + if ((*P)->getType()->isBlockPointerType() && !DeclaringEntity) + Arg = FormatFunctionParameter(S.Context, *P, true); + else { + (*P)->getType().getAsStringInternal(Arg, S.Context.PrintingPolicy); + Arg = "(" + Arg + ")"; + if (IdentifierInfo *II = (*P)->getIdentifier()) + if (DeclaringEntity || AllParametersAreInformative) + Arg += II->getName().str(); + } + + if (Method->isVariadic() && (P + 1) == PEnd) + Arg += ", ..."; + if (DeclaringEntity) Result->AddTextChunk(Arg); else if (AllParametersAreInformative) @@ -1991,12 +2214,16 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) { } if (Method->isVariadic()) { - if (DeclaringEntity) - Result->AddTextChunk(", ..."); - else if (AllParametersAreInformative) - Result->AddInformativeChunk(", ..."); - else - Result->AddPlaceholderChunk(", ..."); + if (Method->param_size() == 0) { + if (DeclaringEntity) + Result->AddTextChunk(", ..."); + else if (AllParametersAreInformative) + Result->AddInformativeChunk(", ..."); + else + Result->AddPlaceholderChunk(", ..."); + } + + MaybeAddSentinel(S.Context, Method, Result); } return Result; @@ -2076,226 +2303,421 @@ CodeCompleteConsumer::OverloadCandidate::CreateSignatureString( return Result; } -namespace { - struct SortCodeCompleteResult { - typedef CodeCompleteConsumer::Result Result; - - bool isEarlierDeclarationName(DeclarationName X, DeclarationName Y) const { - Selector XSel = X.getObjCSelector(); - Selector YSel = Y.getObjCSelector(); - if (!XSel.isNull() && !YSel.isNull()) { - // We are comparing two selectors. - unsigned N = std::min(XSel.getNumArgs(), YSel.getNumArgs()); - if (N == 0) - ++N; - for (unsigned I = 0; I != N; ++I) { - IdentifierInfo *XId = XSel.getIdentifierInfoForSlot(I); - IdentifierInfo *YId = YSel.getIdentifierInfoForSlot(I); - if (!XId || !YId) - return XId && !YId; - - switch (XId->getName().compare_lower(YId->getName())) { - case -1: return true; - case 1: return false; - default: break; - } - } - - return XSel.getNumArgs() < YSel.getNumArgs(); - } +unsigned clang::getMacroUsagePriority(llvm::StringRef MacroName, + bool PreferredTypeIsPointer) { + unsigned Priority = CCP_Macro; + + // Treat the "nil" and "NULL" macros as null pointer constants. + if (MacroName.equals("nil") || MacroName.equals("NULL")) { + Priority = CCP_Constant; + if (PreferredTypeIsPointer) + Priority = Priority / CCF_SimilarTypeMatch; + } + + return Priority; +} - // For non-selectors, order by kind. - if (X.getNameKind() != Y.getNameKind()) - return X.getNameKind() < Y.getNameKind(); - - // Order identifiers by comparison of their lowercased names. - if (IdentifierInfo *XId = X.getAsIdentifierInfo()) - return XId->getName().compare_lower( - Y.getAsIdentifierInfo()->getName()) < 0; - - // Order overloaded operators by the order in which they appear - // in our list of operators. - if (OverloadedOperatorKind XOp = X.getCXXOverloadedOperator()) - return XOp < Y.getCXXOverloadedOperator(); - - // Order C++0x user-defined literal operators lexically by their - // lowercased suffixes. - if (IdentifierInfo *XLit = X.getCXXLiteralIdentifier()) - return XLit->getName().compare_lower( - Y.getCXXLiteralIdentifier()->getName()) < 0; - - // The only stable ordering we have is to turn the name into a - // string and then compare the lower-case strings. This is - // inefficient, but thankfully does not happen too often. - return llvm::StringRef(X.getAsString()).compare_lower( - Y.getAsString()) < 0; - } - - /// \brief Retrieve the name that should be used to order a result. - /// - /// If the name needs to be constructed as a string, that string will be - /// saved into Saved and the returned StringRef will refer to it. - static llvm::StringRef getOrderedName(const Result &R, - std::string &Saved) { - switch (R.Kind) { - case Result::RK_Keyword: - return R.Keyword; - - case Result::RK_Pattern: - return R.Pattern->getTypedText(); - - case Result::RK_Macro: - return R.Macro->getName(); - - case Result::RK_Declaration: - // Handle declarations below. - break; - } - - DeclarationName Name = R.Declaration->getDeclName(); - - // If the name is a simple identifier (by far the common case), or a - // zero-argument selector, just return a reference to that identifier. - if (IdentifierInfo *Id = Name.getAsIdentifierInfo()) - return Id->getName(); - if (Name.isObjCZeroArgSelector()) - if (IdentifierInfo *Id - = Name.getObjCSelector().getIdentifierInfoForSlot(0)) - return Id->getName(); - - Saved = Name.getAsString(); - return Saved; - } - - bool operator()(const Result &X, const Result &Y) const { - std::string XSaved, YSaved; - llvm::StringRef XStr = getOrderedName(X, XSaved); - llvm::StringRef YStr = getOrderedName(Y, YSaved); - int cmp = XStr.compare_lower(YStr); - if (cmp) - return cmp < 0; - - // Non-hidden names precede hidden names. - if (X.Hidden != Y.Hidden) - return !X.Hidden; +CXCursorKind clang::getCursorKindForDecl(Decl *D) { + if (!D) + return CXCursor_UnexposedDecl; + + switch (D->getKind()) { + case Decl::Enum: return CXCursor_EnumDecl; + case Decl::EnumConstant: return CXCursor_EnumConstantDecl; + case Decl::Field: return CXCursor_FieldDecl; + case Decl::Function: + return CXCursor_FunctionDecl; + case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl; + case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl; + case Decl::ObjCClass: + // FIXME + return CXCursor_UnexposedDecl; + case Decl::ObjCForwardProtocol: + // FIXME + return CXCursor_UnexposedDecl; + case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl; + case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl; + case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl; + case Decl::ObjCMethod: + return cast(D)->isInstanceMethod() + ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl; + case Decl::CXXMethod: return CXCursor_CXXMethod; + case Decl::CXXConstructor: return CXCursor_Constructor; + case Decl::CXXDestructor: return CXCursor_Destructor; + case Decl::CXXConversion: return CXCursor_ConversionFunction; + case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl; + case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl; + case Decl::ParmVar: return CXCursor_ParmDecl; + case Decl::Typedef: return CXCursor_TypedefDecl; + case Decl::Var: return CXCursor_VarDecl; + case Decl::Namespace: return CXCursor_Namespace; + case Decl::NamespaceAlias: return CXCursor_NamespaceAlias; + case Decl::TemplateTypeParm: return CXCursor_TemplateTypeParameter; + case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter; + case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter; + case Decl::FunctionTemplate: return CXCursor_FunctionTemplate; + case Decl::ClassTemplate: return CXCursor_ClassTemplate; + case Decl::ClassTemplatePartialSpecialization: + return CXCursor_ClassTemplatePartialSpecialization; + case Decl::UsingDirective: return CXCursor_UsingDirective; - // Non-nested-name-specifiers precede nested-name-specifiers. - if (X.StartsNestedNameSpecifier != Y.StartsNestedNameSpecifier) - return !X.StartsNestedNameSpecifier; + case Decl::Using: + case Decl::UnresolvedUsingValue: + case Decl::UnresolvedUsingTypename: + return CXCursor_UsingDeclaration; - return false; - } - }; + default: + if (TagDecl *TD = dyn_cast(D)) { + switch (TD->getTagKind()) { + case TTK_Struct: return CXCursor_StructDecl; + case TTK_Class: return CXCursor_ClassDecl; + case TTK_Union: return CXCursor_UnionDecl; + case TTK_Enum: return CXCursor_EnumDecl; + } + } + } + + return CXCursor_UnexposedDecl; } static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results, bool TargetTypeIsPointer = false) { - typedef CodeCompleteConsumer::Result Result; + typedef CodeCompletionResult Result; Results.EnterNewScope(); for (Preprocessor::macro_iterator M = PP.macro_begin(), MEnd = PP.macro_end(); M != MEnd; ++M) { - unsigned Priority = CCP_Macro; - - // Treat the "nil" and "NULL" macros as null pointer constants. - if (M->first->isStr("nil") || M->first->isStr("NULL")) { - Priority = CCP_Constant; - if (TargetTypeIsPointer) - Priority = Priority / CCF_SimilarTypeMatch; - } - - Results.AddResult(Result(M->first, Priority)); + Results.AddResult(Result(M->first, + getMacroUsagePriority(M->first->getName(), + TargetTypeIsPointer))); } Results.ExitScope(); } +static void AddPrettyFunctionResults(const LangOptions &LangOpts, + ResultBuilder &Results) { + typedef CodeCompletionResult Result; + + Results.EnterNewScope(); + Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant)); + Results.AddResult(Result("__FUNCTION__", CCP_Constant)); + if (LangOpts.C99 || LangOpts.CPlusPlus0x) + Results.AddResult(Result("__func__", CCP_Constant)); + Results.ExitScope(); +} + static void HandleCodeCompleteResults(Sema *S, CodeCompleteConsumer *CodeCompleter, - CodeCompleteConsumer::Result *Results, - unsigned NumResults) { - std::stable_sort(Results, Results + NumResults, SortCodeCompleteResult()); - + CodeCompletionContext Context, + CodeCompletionResult *Results, + unsigned NumResults) { if (CodeCompleter) - CodeCompleter->ProcessCodeCompleteResults(*S, Results, NumResults); + CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults); for (unsigned I = 0; I != NumResults; ++I) Results[I].Destroy(); } +static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S, + Sema::ParserCompletionContext PCC) { + switch (PCC) { + case Sema::PCC_Namespace: + return CodeCompletionContext::CCC_TopLevel; + + case Sema::PCC_Class: + return CodeCompletionContext::CCC_ClassStructUnion; + + case Sema::PCC_ObjCInterface: + return CodeCompletionContext::CCC_ObjCInterface; + + case Sema::PCC_ObjCImplementation: + return CodeCompletionContext::CCC_ObjCImplementation; + + case Sema::PCC_ObjCInstanceVariableList: + return CodeCompletionContext::CCC_ObjCIvarList; + + case Sema::PCC_Template: + case Sema::PCC_MemberTemplate: + case Sema::PCC_RecoveryInFunction: + return CodeCompletionContext::CCC_Other; + + case Sema::PCC_Expression: + case Sema::PCC_ForInit: + case Sema::PCC_Condition: + return CodeCompletionContext::CCC_Expression; + + case Sema::PCC_Statement: + return CodeCompletionContext::CCC_Statement; + + case Sema::PCC_Type: + return CodeCompletionContext::CCC_Type; + } + + return CodeCompletionContext::CCC_Other; +} + +/// \brief If we're in a C++ virtual member function, add completion results +/// that invoke the functions we override, since it's common to invoke the +/// overridden function as well as adding new functionality. +/// +/// \param S The semantic analysis object for which we are generating results. +/// +/// \param InContext This context in which the nested-name-specifier preceding +/// the code-completion point +static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext, + ResultBuilder &Results) { + // Look through blocks. + DeclContext *CurContext = S.CurContext; + while (isa(CurContext)) + CurContext = CurContext->getParent(); + + + CXXMethodDecl *Method = dyn_cast(CurContext); + if (!Method || !Method->isVirtual()) + return; + + // We need to have names for all of the parameters, if we're going to + // generate a forwarding call. + for (CXXMethodDecl::param_iterator P = Method->param_begin(), + PEnd = Method->param_end(); + P != PEnd; + ++P) { + if (!(*P)->getDeclName()) + return; + } + + for (CXXMethodDecl::method_iterator M = Method->begin_overridden_methods(), + MEnd = Method->end_overridden_methods(); + M != MEnd; ++M) { + CodeCompletionString *Pattern = new CodeCompletionString; + CXXMethodDecl *Overridden = const_cast(*M); + if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl()) + continue; + + // If we need a nested-name-specifier, add one now. + if (!InContext) { + NestedNameSpecifier *NNS + = getRequiredQualification(S.Context, CurContext, + Overridden->getDeclContext()); + if (NNS) { + std::string Str; + llvm::raw_string_ostream OS(Str); + NNS->print(OS, S.Context.PrintingPolicy); + Pattern->AddTextChunk(OS.str()); + } + } else if (!InContext->Equals(Overridden->getDeclContext())) + continue; + + Pattern->AddTypedTextChunk(Overridden->getNameAsString()); + Pattern->AddChunk(CodeCompletionString::CK_LeftParen); + bool FirstParam = true; + for (CXXMethodDecl::param_iterator P = Method->param_begin(), + PEnd = Method->param_end(); + P != PEnd; ++P) { + if (FirstParam) + FirstParam = false; + else + Pattern->AddChunk(CodeCompletionString::CK_Comma); + + Pattern->AddPlaceholderChunk((*P)->getIdentifier()->getName()); + } + Pattern->AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(CodeCompletionResult(Pattern, + CCP_SuperCompletion, + CXCursor_CXXMethod)); + Results.Ignore(Overridden); + } +} + void Sema::CodeCompleteOrdinaryName(Scope *S, - CodeCompletionContext CompletionContext) { - typedef CodeCompleteConsumer::Result Result; - ResultBuilder Results(*this); + ParserCompletionContext CompletionContext) { + typedef CodeCompletionResult Result; + ResultBuilder Results(*this); + Results.EnterNewScope(); // Determine how to filter results, e.g., so that the names of // values (functions, enumerators, function templates, etc.) are // only allowed where we can have an expression. switch (CompletionContext) { - case CCC_Namespace: - case CCC_Class: - case CCC_ObjCInterface: - case CCC_ObjCImplementation: - case CCC_ObjCInstanceVariableList: - case CCC_Template: - case CCC_MemberTemplate: + case PCC_Namespace: + case PCC_Class: + case PCC_ObjCInterface: + case PCC_ObjCImplementation: + case PCC_ObjCInstanceVariableList: + case PCC_Template: + case PCC_MemberTemplate: + case PCC_Type: Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName); break; - case CCC_Expression: - case CCC_Statement: - case CCC_ForInit: - case CCC_Condition: + case PCC_Statement: + // For statements that are expressions, we prefer to call 'void' functions + // rather than functions that return a result, since then the result would + // be ignored. + Results.setPreferredType(Context.VoidTy); + // Fall through + + case PCC_Expression: + case PCC_ForInit: + case PCC_Condition: if (WantTypesInContext(CompletionContext, getLangOptions())) Results.setFilter(&ResultBuilder::IsOrdinaryName); else Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName); + + if (getLangOptions().CPlusPlus) + MaybeAddOverrideCalls(*this, /*InContext=*/0, Results); break; - case CCC_RecoveryInFunction: + case PCC_RecoveryInFunction: // Unfiltered break; } + // If we are in a C++ non-static member function, check the qualifiers on + // the member function to filter/prioritize the results list. + if (CXXMethodDecl *CurMethod = dyn_cast(CurContext)) + if (CurMethod->isInstance()) + Results.setObjectTypeQualifiers( + Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers())); + CodeCompletionDeclConsumer Consumer(Results, CurContext); - LookupVisibleDecls(S, LookupOrdinaryName, Consumer); + LookupVisibleDecls(S, LookupOrdinaryName, Consumer, + CodeCompleter->includeGlobals()); - Results.EnterNewScope(); AddOrdinaryNameResults(CompletionContext, S, *this, Results); Results.ExitScope(); + switch (CompletionContext) { + case PCC_Expression: + case PCC_Statement: + case PCC_RecoveryInFunction: + if (S->getFnParent()) + AddPrettyFunctionResults(PP.getLangOptions(), Results); + break; + + case PCC_Namespace: + case PCC_Class: + case PCC_ObjCInterface: + case PCC_ObjCImplementation: + case PCC_ObjCInstanceVariableList: + case PCC_Template: + case PCC_MemberTemplate: + case PCC_ForInit: + case PCC_Condition: + case PCC_Type: + break; + } + if (CodeCompleter->includeMacros()) AddMacroResults(PP, Results); - HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); + + HandleCodeCompleteResults(this, CodeCompleter, + mapCodeCompletionContext(*this, CompletionContext), + Results.data(),Results.size()); +} + +void Sema::CodeCompleteDeclarator(Scope *S, + bool AllowNonIdentifiers, + bool AllowNestedNameSpecifiers) { + typedef CodeCompletionResult Result; + ResultBuilder Results(*this); + Results.EnterNewScope(); + + // Type qualifiers can come after names. + Results.AddResult(Result("const")); + Results.AddResult(Result("volatile")); + if (getLangOptions().C99) + Results.AddResult(Result("restrict")); + + if (getLangOptions().CPlusPlus) { + if (AllowNonIdentifiers) { + Results.AddResult(Result("operator")); + } + + // Add nested-name-specifiers. + if (AllowNestedNameSpecifiers) { + Results.allowNestedNameSpecifiers(); + CodeCompletionDeclConsumer Consumer(Results, CurContext); + LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer, + CodeCompleter->includeGlobals()); + } + } + Results.ExitScope(); + + // Note that we intentionally suppress macro results here, since we do not + // encourage using macros to produce the names of entities. + + HandleCodeCompleteResults(this, CodeCompleter, + AllowNestedNameSpecifiers + ? CodeCompletionContext::CCC_PotentiallyQualifiedName + : CodeCompletionContext::CCC_Name, + Results.data(), Results.size()); } +struct Sema::CodeCompleteExpressionData { + CodeCompleteExpressionData(QualType PreferredType = QualType()) + : PreferredType(PreferredType), IntegralConstantExpression(false), + ObjCCollection(false) { } + + QualType PreferredType; + bool IntegralConstantExpression; + bool ObjCCollection; + llvm::SmallVector IgnoreDecls; +}; + /// \brief Perform code-completion in an expression context when we know what /// type we're looking for. -void Sema::CodeCompleteExpression(Scope *S, QualType T) { - typedef CodeCompleteConsumer::Result Result; +/// +/// \param IntegralConstantExpression Only permit integral constant +/// expressions. +void Sema::CodeCompleteExpression(Scope *S, + const CodeCompleteExpressionData &Data) { + typedef CodeCompletionResult Result; ResultBuilder Results(*this); - if (WantTypesInContext(CCC_Expression, getLangOptions())) + if (Data.ObjCCollection) + Results.setFilter(&ResultBuilder::IsObjCCollection); + else if (Data.IntegralConstantExpression) + Results.setFilter(&ResultBuilder::IsIntegralConstantValue); + else if (WantTypesInContext(PCC_Expression, getLangOptions())) Results.setFilter(&ResultBuilder::IsOrdinaryName); else Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName); - Results.setPreferredType(T.getNonReferenceType()); + + if (!Data.PreferredType.isNull()) + Results.setPreferredType(Data.PreferredType.getNonReferenceType()); + + // Ignore any declarations that we were told that we don't care about. + for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I) + Results.Ignore(Data.IgnoreDecls[I]); CodeCompletionDeclConsumer Consumer(Results, CurContext); - LookupVisibleDecls(S, LookupOrdinaryName, Consumer); + LookupVisibleDecls(S, LookupOrdinaryName, Consumer, + CodeCompleter->includeGlobals()); Results.EnterNewScope(); - AddOrdinaryNameResults(CCC_Expression, S, *this, Results); + AddOrdinaryNameResults(PCC_Expression, S, *this, Results); Results.ExitScope(); bool PreferredTypeIsPointer = false; - if (!T.isNull()) - PreferredTypeIsPointer = T->isAnyPointerType() || - T->isMemberPointerType() || T->isBlockPointerType(); + if (!Data.PreferredType.isNull()) + PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType() + || Data.PreferredType->isMemberPointerType() + || Data.PreferredType->isBlockPointerType(); + if (S->getFnParent() && + !Data.ObjCCollection && + !Data.IntegralConstantExpression) + AddPrettyFunctionResults(PP.getLangOptions(), Results); + if (CodeCompleter->includeMacros()) AddMacroResults(PP, Results, PreferredTypeIsPointer); - HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext(CodeCompletionContext::CCC_Expression, + Data.PreferredType), + Results.data(),Results.size()); } @@ -2303,7 +2725,7 @@ static void AddObjCProperties(ObjCContainerDecl *Container, bool AllowCategories, DeclContext *CurContext, ResultBuilder &Results) { - typedef CodeCompleteConsumer::Result Result; + typedef CodeCompletionResult Result; // Add properties in this container. for (ObjCContainerDecl::prop_iterator P = Container->prop_begin(), @@ -2327,9 +2749,9 @@ static void AddObjCProperties(ObjCContainerDecl *Container, } // Look through protocols. - for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(), - E = IFace->protocol_end(); - I != E; ++I) + for (ObjCInterfaceDecl::all_protocol_iterator + I = IFace->all_referenced_protocol_begin(), + E = IFace->all_referenced_protocol_end(); I != E; ++I) AddObjCProperties(*I, AllowCategories, CurContext, Results); // Look in the superclass. @@ -2339,8 +2761,8 @@ static void AddObjCProperties(ObjCContainerDecl *Container, } else if (const ObjCCategoryDecl *Category = dyn_cast(Container)) { // Look through protocols. - for (ObjCInterfaceDecl::protocol_iterator P = Category->protocol_begin(), - PEnd = Category->protocol_end(); + for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(), + PEnd = Category->protocol_end(); P != PEnd; ++P) AddObjCProperties(*P, AllowCategories, CurContext, Results); } @@ -2352,7 +2774,7 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE, if (!BaseE || !CodeCompleter) return; - typedef CodeCompleteConsumer::Result Result; + typedef CodeCompletionResult Result; Expr *Base = static_cast(BaseE); QualType BaseType = Base->getType(); @@ -2361,7 +2783,7 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE, if (const PointerType *Ptr = BaseType->getAs()) BaseType = Ptr->getPointeeType(); else if (BaseType->isObjCObjectPointerType()) - /*Do nothing*/ ; + /*Do nothing*/ ; else return; } @@ -2369,10 +2791,15 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE, ResultBuilder Results(*this, &ResultBuilder::IsMember); Results.EnterNewScope(); if (const RecordType *Record = BaseType->getAs()) { + // Indicate that we are performing a member access, and the cv-qualifiers + // for the base object type. + Results.setObjectTypeQualifiers(BaseType.getQualifiers()); + // Access to a C/C++ class, struct, or union. Results.allowNestedNameSpecifiers(); CodeCompletionDeclConsumer Consumer(Results, CurContext); - LookupVisibleDecls(Record->getDecl(), LookupMemberName, Consumer); + LookupVisibleDecls(Record->getDecl(), LookupMemberName, Consumer, + CodeCompleter->includeGlobals()); if (getLangOptions().CPlusPlus) { if (!Results.empty()) { @@ -2420,7 +2847,8 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE, if (Class) { CodeCompletionDeclConsumer Consumer(Results, CurContext); Results.setFilter(&ResultBuilder::IsObjCIvar); - LookupVisibleDecls(Class, LookupMemberName, Consumer); + LookupVisibleDecls(Class, LookupMemberName, Consumer, + CodeCompleter->includeGlobals()); } } @@ -2429,27 +2857,35 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE, Results.ExitScope(); // Hand off the results found for code completion. - HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext(CodeCompletionContext::CCC_MemberAccess, + BaseType), + Results.data(),Results.size()); } void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) { if (!CodeCompleter) return; - typedef CodeCompleteConsumer::Result Result; + typedef CodeCompletionResult Result; ResultBuilder::LookupFilter Filter = 0; + enum CodeCompletionContext::Kind ContextKind + = CodeCompletionContext::CCC_Other; switch ((DeclSpec::TST)TagSpec) { case DeclSpec::TST_enum: Filter = &ResultBuilder::IsEnum; + ContextKind = CodeCompletionContext::CCC_EnumTag; break; case DeclSpec::TST_union: Filter = &ResultBuilder::IsUnion; + ContextKind = CodeCompletionContext::CCC_UnionTag; break; case DeclSpec::TST_struct: case DeclSpec::TST_class: Filter = &ResultBuilder::IsClassOrStruct; + ContextKind = CodeCompletionContext::CCC_ClassOrStructTag; break; default: @@ -2462,22 +2898,46 @@ void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) { // First pass: look for tags. Results.setFilter(Filter); - LookupVisibleDecls(S, LookupTagName, Consumer); + LookupVisibleDecls(S, LookupTagName, Consumer, + CodeCompleter->includeGlobals()); - // Second pass: look for nested name specifiers. - Results.setFilter(&ResultBuilder::IsNestedNameSpecifier); - LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer); + if (CodeCompleter->includeGlobals()) { + // Second pass: look for nested name specifiers. + Results.setFilter(&ResultBuilder::IsNestedNameSpecifier); + LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer); + } - HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, ContextKind, + Results.data(),Results.size()); +} + +void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) { + ResultBuilder Results(*this); + Results.EnterNewScope(); + if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const)) + Results.AddResult("const"); + if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile)) + Results.AddResult("volatile"); + if (getLangOptions().C99 && + !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict)) + Results.AddResult("restrict"); + Results.ExitScope(); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_TypeQualifiers, + Results.data(), Results.size()); } void Sema::CodeCompleteCase(Scope *S) { - if (getSwitchStack().empty() || !CodeCompleter) + if (getCurFunction()->SwitchStack.empty() || !CodeCompleter) return; - SwitchStmt *Switch = getSwitchStack().back(); - if (!Switch->getCond()->getType()->isEnumeralType()) + SwitchStmt *Switch = getCurFunction()->SwitchStack.back(); + if (!Switch->getCond()->getType()->isEnumeralType()) { + CodeCompleteExpressionData Data(Switch->getCond()->getType()); + Data.IntegralConstantExpression = true; + CodeCompleteExpression(S, Data); return; + } // Code-complete the cases of a switch statement over an enumeration type // by providing the list of @@ -2541,14 +3001,16 @@ void Sema::CodeCompleteCase(Scope *S) { if (EnumeratorsSeen.count(*E)) continue; - Results.AddResult(CodeCompleteConsumer::Result(*E, Qualifier), + Results.AddResult(CodeCompletionResult(*E, Qualifier), CurContext, 0, false); } Results.ExitScope(); if (CodeCompleter->includeMacros()) AddMacroResults(PP, Results); - HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Expression, + Results.data(),Results.size()); } namespace { @@ -2562,7 +3024,7 @@ namespace { bool operator()(const OverloadCandidate &X, const OverloadCandidate &Y) const { - return S.isBetterOverloadCandidate(X, Y, Loc); + return isBetterOverloadCandidate(S, X, Y, Loc); } }; } @@ -2594,7 +3056,7 @@ void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn, // Ignore type-dependent call expressions entirely. if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args, NumArgs) || Expr::hasAnyTypeDependentArguments(Args, NumArgs)) { - CodeCompleteOrdinaryName(S, CCC_Expression); + CodeCompleteOrdinaryName(S, PCC_Expression); return; } @@ -2678,7 +3140,7 @@ void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn, } if (ParamType.isNull()) - CodeCompleteOrdinaryName(S, CCC_Expression); + CodeCompleteOrdinaryName(S, PCC_Expression); else CodeCompleteExpression(S, ParamType); @@ -2687,10 +3149,10 @@ void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn, Results.size()); } -void Sema::CodeCompleteInitializer(Scope *S, DeclPtrTy D) { - ValueDecl *VD = dyn_cast_or_null(D.getAs()); +void Sema::CodeCompleteInitializer(Scope *S, Decl *D) { + ValueDecl *VD = dyn_cast_or_null(D); if (!VD) { - CodeCompleteOrdinaryName(S, CCC_Expression); + CodeCompleteOrdinaryName(S, PCC_Expression); return; } @@ -2708,7 +3170,7 @@ void Sema::CodeCompleteReturn(Scope *S) { ResultType = Method->getResultType(); if (ResultType.isNull()) - CodeCompleteOrdinaryName(S, CCC_Expression); + CodeCompleteOrdinaryName(S, PCC_Expression); else CodeCompleteExpression(S, ResultType); } @@ -2717,7 +3179,7 @@ void Sema::CodeCompleteAssignmentRHS(Scope *S, ExprTy *LHS) { if (LHS) CodeCompleteExpression(S, static_cast(LHS)->getType()); else - CodeCompleteOrdinaryName(S, CCC_Expression); + CodeCompleteOrdinaryName(S, PCC_Expression); } void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, @@ -2735,16 +3197,29 @@ void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, return; ResultBuilder Results(*this); - CodeCompletionDeclConsumer Consumer(Results, CurContext); - LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer); + Results.EnterNewScope(); // The "template" keyword can follow "::" in the grammar, but only // put it into the grammar if the nested-name-specifier is dependent. NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep(); if (!Results.empty() && NNS->isDependent()) Results.AddResult("template"); + + // Add calls to overridden virtual functions, if there are any. + // + // FIXME: This isn't wonderful, because we don't know whether we're actually + // in a context that permits expressions. This is a general issue with + // qualified-id completions. + if (!EnteringContext) + MaybeAddOverrideCalls(*this, Ctx, Results); + Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); + CodeCompletionDeclConsumer Consumer(Results, CurContext); + LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer); + + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Name, + Results.data(),Results.size()); } void Sema::CodeCompleteUsing(Scope *S) { @@ -2756,15 +3231,18 @@ void Sema::CodeCompleteUsing(Scope *S) { // If we aren't in class scope, we could see the "namespace" keyword. if (!S->isClassScope()) - Results.AddResult(CodeCompleteConsumer::Result("namespace")); + Results.AddResult(CodeCompletionResult("namespace")); // After "using", we can see anything that would start a // nested-name-specifier. CodeCompletionDeclConsumer Consumer(Results, CurContext); - LookupVisibleDecls(S, LookupOrdinaryName, Consumer); + LookupVisibleDecls(S, LookupOrdinaryName, Consumer, + CodeCompleter->includeGlobals()); Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); } void Sema::CodeCompleteUsingDirective(Scope *S) { @@ -2776,9 +3254,12 @@ void Sema::CodeCompleteUsingDirective(Scope *S) { ResultBuilder Results(*this, &ResultBuilder::IsNamespaceOrAlias); Results.EnterNewScope(); CodeCompletionDeclConsumer Consumer(Results, CurContext); - LookupVisibleDecls(S, LookupOrdinaryName, Consumer); + LookupVisibleDecls(S, LookupOrdinaryName, Consumer, + CodeCompleter->includeGlobals()); Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Namespace, + Results.data(),Results.size()); } void Sema::CodeCompleteNamespaceDecl(Scope *S) { @@ -2807,12 +3288,14 @@ void Sema::CodeCompleteNamespaceDecl(Scope *S) { for (std::map::iterator NS = OrigToLatest.begin(), NSEnd = OrigToLatest.end(); NS != NSEnd; ++NS) - Results.AddResult(CodeCompleteConsumer::Result(NS->second, 0), + Results.AddResult(CodeCompletionResult(NS->second, 0), CurContext, 0, false); Results.ExitScope(); } - HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); } void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) { @@ -2822,15 +3305,18 @@ void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) { // After "namespace", we expect to see a namespace or alias. ResultBuilder Results(*this, &ResultBuilder::IsNamespaceOrAlias); CodeCompletionDeclConsumer Consumer(Results, CurContext); - LookupVisibleDecls(S, LookupOrdinaryName, Consumer); - HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); + LookupVisibleDecls(S, LookupOrdinaryName, Consumer, + CodeCompleter->includeGlobals()); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Namespace, + Results.data(),Results.size()); } void Sema::CodeCompleteOperatorName(Scope *S) { if (!CodeCompleter) return; - typedef CodeCompleteConsumer::Result Result; + typedef CodeCompletionResult Result; ResultBuilder Results(*this, &ResultBuilder::IsType); Results.EnterNewScope(); @@ -2843,13 +3329,122 @@ void Sema::CodeCompleteOperatorName(Scope *S) { // Add any type names visible from the current scope Results.allowNestedNameSpecifiers(); CodeCompletionDeclConsumer Consumer(Results, CurContext); - LookupVisibleDecls(S, LookupOrdinaryName, Consumer); + LookupVisibleDecls(S, LookupOrdinaryName, Consumer, + CodeCompleter->includeGlobals()); // Add any type specifiers AddTypeSpecifierResults(getLangOptions(), Results); Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Type, + Results.data(),Results.size()); +} + +void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD, + CXXBaseOrMemberInitializer** Initializers, + unsigned NumInitializers) { + CXXConstructorDecl *Constructor + = static_cast(ConstructorD); + if (!Constructor) + return; + + ResultBuilder Results(*this); + Results.EnterNewScope(); + + // Fill in any already-initialized fields or base classes. + llvm::SmallPtrSet InitializedFields; + llvm::SmallPtrSet InitializedBases; + for (unsigned I = 0; I != NumInitializers; ++I) { + if (Initializers[I]->isBaseInitializer()) + InitializedBases.insert( + Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0))); + else + InitializedFields.insert(cast(Initializers[I]->getMember())); + } + + // Add completions for base classes. + bool SawLastInitializer = (NumInitializers == 0); + CXXRecordDecl *ClassDecl = Constructor->getParent(); + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), + BaseEnd = ClassDecl->bases_end(); + Base != BaseEnd; ++Base) { + if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) { + SawLastInitializer + = NumInitializers > 0 && + Initializers[NumInitializers - 1]->isBaseInitializer() && + Context.hasSameUnqualifiedType(Base->getType(), + QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0)); + continue; + } + + CodeCompletionString *Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk( + Base->getType().getAsString(Context.PrintingPolicy)); + Pattern->AddChunk(CodeCompletionString::CK_LeftParen); + Pattern->AddPlaceholderChunk("args"); + Pattern->AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(CodeCompletionResult(Pattern, + SawLastInitializer? CCP_NextInitializer + : CCP_MemberDeclaration)); + SawLastInitializer = false; + } + + // Add completions for virtual base classes. + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(), + BaseEnd = ClassDecl->vbases_end(); + Base != BaseEnd; ++Base) { + if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) { + SawLastInitializer + = NumInitializers > 0 && + Initializers[NumInitializers - 1]->isBaseInitializer() && + Context.hasSameUnqualifiedType(Base->getType(), + QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0)); + continue; + } + + CodeCompletionString *Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk( + Base->getType().getAsString(Context.PrintingPolicy)); + Pattern->AddChunk(CodeCompletionString::CK_LeftParen); + Pattern->AddPlaceholderChunk("args"); + Pattern->AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(CodeCompletionResult(Pattern, + SawLastInitializer? CCP_NextInitializer + : CCP_MemberDeclaration)); + SawLastInitializer = false; + } + + // Add completions for members. + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), + FieldEnd = ClassDecl->field_end(); + Field != FieldEnd; ++Field) { + if (!InitializedFields.insert(cast(Field->getCanonicalDecl()))) { + SawLastInitializer + = NumInitializers > 0 && + Initializers[NumInitializers - 1]->isMemberInitializer() && + Initializers[NumInitializers - 1]->getMember() == *Field; + continue; + } + + if (!Field->getDeclName()) + continue; + + CodeCompletionString *Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk(Field->getIdentifier()->getName()); + Pattern->AddChunk(CodeCompletionString::CK_LeftParen); + Pattern->AddPlaceholderChunk("args"); + Pattern->AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(CodeCompletionResult(Pattern, + SawLastInitializer? CCP_NextInitializer + : CCP_MemberDeclaration)); + SawLastInitializer = false; + } + Results.ExitScope(); + + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Name, + Results.data(), Results.size()); } // Macro that expands to @Keyword or Keyword, depending on whether NeedAt is @@ -2858,7 +3453,7 @@ void Sema::CodeCompleteOperatorName(Scope *S) { static void AddObjCImplementationResults(const LangOptions &LangOpts, ResultBuilder &Results, bool NeedAt) { - typedef CodeCompleteConsumer::Result Result; + typedef CodeCompletionResult Result; // Since we have an implementation, we can end it. Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end))); @@ -2883,7 +3478,7 @@ static void AddObjCImplementationResults(const LangOptions &LangOpts, static void AddObjCInterfaceResults(const LangOptions &LangOpts, ResultBuilder &Results, bool NeedAt) { - typedef CodeCompleteConsumer::Result Result; + typedef CodeCompletionResult Result; // Since we have an interface or protocol, we can end it. Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end))); @@ -2901,7 +3496,7 @@ static void AddObjCInterfaceResults(const LangOptions &LangOpts, } static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) { - typedef CodeCompleteConsumer::Result Result; + typedef CodeCompletionResult Result; CodeCompletionString *Pattern = 0; // @class name ; @@ -2946,9 +3541,9 @@ static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) { Results.AddResult(Result(Pattern)); } -void Sema::CodeCompleteObjCAtDirective(Scope *S, DeclPtrTy ObjCImpDecl, +void Sema::CodeCompleteObjCAtDirective(Scope *S, Decl *ObjCImpDecl, bool InInterface) { - typedef CodeCompleteConsumer::Result Result; + typedef CodeCompletionResult Result; ResultBuilder Results(*this); Results.EnterNewScope(); if (ObjCImpDecl) @@ -2958,11 +3553,13 @@ void Sema::CodeCompleteObjCAtDirective(Scope *S, DeclPtrTy ObjCImpDecl, else AddObjCTopLevelResults(Results, false); Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); } static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) { - typedef CodeCompleteConsumer::Result Result; + typedef CodeCompletionResult Result; CodeCompletionString *Pattern = 0; // @encode ( type-name ) @@ -2991,7 +3588,7 @@ static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) { } static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) { - typedef CodeCompleteConsumer::Result Result; + typedef CodeCompletionResult Result; CodeCompletionString *Pattern = 0; if (Results.includeCodePatterns()) { @@ -3041,7 +3638,7 @@ static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) { static void AddObjCVisibilityResults(const LangOptions &LangOpts, ResultBuilder &Results, bool NeedAt) { - typedef CodeCompleteConsumer::Result Result; + typedef CodeCompletionResult Result; Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,private))); Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,protected))); Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,public))); @@ -3054,7 +3651,9 @@ void Sema::CodeCompleteObjCAtVisibility(Scope *S) { Results.EnterNewScope(); AddObjCVisibilityResults(getLangOptions(), Results, false); Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); } void Sema::CodeCompleteObjCAtStatement(Scope *S) { @@ -3063,7 +3662,9 @@ void Sema::CodeCompleteObjCAtStatement(Scope *S) { AddObjCStatementResults(Results, false); AddObjCExpressionResults(Results, false); Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); } void Sema::CodeCompleteObjCAtExpression(Scope *S) { @@ -3071,7 +3672,9 @@ void Sema::CodeCompleteObjCAtExpression(Scope *S) { Results.EnterNewScope(); AddObjCExpressionResults(Results, false); Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); } /// \brief Determine whether the addition of the given flag to an Objective-C @@ -3110,37 +3713,39 @@ void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) { unsigned Attributes = ODS.getPropertyAttributes(); - typedef CodeCompleteConsumer::Result Result; + typedef CodeCompletionResult Result; ResultBuilder Results(*this); Results.EnterNewScope(); if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly)) - Results.AddResult(CodeCompleteConsumer::Result("readonly")); + Results.AddResult(CodeCompletionResult("readonly")); if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign)) - Results.AddResult(CodeCompleteConsumer::Result("assign")); + Results.AddResult(CodeCompletionResult("assign")); if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite)) - Results.AddResult(CodeCompleteConsumer::Result("readwrite")); + Results.AddResult(CodeCompletionResult("readwrite")); if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain)) - Results.AddResult(CodeCompleteConsumer::Result("retain")); + Results.AddResult(CodeCompletionResult("retain")); if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy)) - Results.AddResult(CodeCompleteConsumer::Result("copy")); + Results.AddResult(CodeCompletionResult("copy")); if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic)) - Results.AddResult(CodeCompleteConsumer::Result("nonatomic")); + Results.AddResult(CodeCompletionResult("nonatomic")); if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) { CodeCompletionString *Setter = new CodeCompletionString; Setter->AddTypedTextChunk("setter"); Setter->AddTextChunk(" = "); Setter->AddPlaceholderChunk("method"); - Results.AddResult(CodeCompleteConsumer::Result(Setter)); + Results.AddResult(CodeCompletionResult(Setter)); } if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) { CodeCompletionString *Getter = new CodeCompletionString; Getter->AddTypedTextChunk("getter"); Getter->AddTextChunk(" = "); Getter->AddPlaceholderChunk("method"); - Results.AddResult(CodeCompleteConsumer::Result(Getter)); + Results.AddResult(CodeCompletionResult(Getter)); } Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); } /// \brief Descripts the kind of Objective-C method that we want to find @@ -3151,26 +3756,33 @@ enum ObjCMethodKind { MK_OneArgSelector //< One-argument selector. }; -static bool isAcceptableObjCMethod(ObjCMethodDecl *Method, - ObjCMethodKind WantKind, - IdentifierInfo **SelIdents, - unsigned NumSelIdents) { - Selector Sel = Method->getSelector(); +static bool isAcceptableObjCSelector(Selector Sel, + ObjCMethodKind WantKind, + IdentifierInfo **SelIdents, + unsigned NumSelIdents) { if (NumSelIdents > Sel.getNumArgs()) return false; - + switch (WantKind) { - case MK_Any: break; - case MK_ZeroArgSelector: return Sel.isUnarySelector(); - case MK_OneArgSelector: return Sel.getNumArgs() == 1; + case MK_Any: break; + case MK_ZeroArgSelector: return Sel.isUnarySelector(); + case MK_OneArgSelector: return Sel.getNumArgs() == 1; } - + for (unsigned I = 0; I != NumSelIdents; ++I) if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I)) return false; - + return true; } + +static bool isAcceptableObjCMethod(ObjCMethodDecl *Method, + ObjCMethodKind WantKind, + IdentifierInfo **SelIdents, + unsigned NumSelIdents) { + return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents, + NumSelIdents); +} /// \brief Add all of the Objective-C methods in the given Objective-C /// container to the set of results. @@ -3195,8 +3807,9 @@ static void AddObjCMethods(ObjCContainerDecl *Container, IdentifierInfo **SelIdents, unsigned NumSelIdents, DeclContext *CurContext, - ResultBuilder &Results) { - typedef CodeCompleteConsumer::Result Result; + ResultBuilder &Results, + bool InOriginalClass = true) { + typedef CodeCompletionResult Result; for (ObjCContainerDecl::method_iterator M = Container->meth_begin(), MEnd = Container->meth_end(); M != MEnd; ++M) { @@ -3209,6 +3822,8 @@ static void AddObjCMethods(ObjCContainerDecl *Container, Result R = Result(*M, 0); R.StartParameter = NumSelIdents; R.AllParametersAreInformative = (WantKind != MK_Any); + if (!InOriginalClass) + R.Priority += CCD_InBaseClass; Results.MaybeAddResult(R, CurContext); } } @@ -3223,13 +3838,13 @@ static void AddObjCMethods(ObjCContainerDecl *Container, E = Protocols.end(); I != E; ++I) AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents, - CurContext, Results); + CurContext, Results, false); // Add methods in categories. for (ObjCCategoryDecl *CatDecl = IFace->getCategoryList(); CatDecl; CatDecl = CatDecl->getNextClassCategory()) { AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents, - NumSelIdents, CurContext, Results); + NumSelIdents, CurContext, Results, InOriginalClass); // Add a categories protocol methods. const ObjCList &Protocols @@ -3238,37 +3853,36 @@ static void AddObjCMethods(ObjCContainerDecl *Container, E = Protocols.end(); I != E; ++I) AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, - NumSelIdents, CurContext, Results); + NumSelIdents, CurContext, Results, false); // Add methods in category implementations. if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation()) AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, - NumSelIdents, CurContext, Results); + NumSelIdents, CurContext, Results, InOriginalClass); } // Add methods in superclass. if (IFace->getSuperClass()) AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind, - SelIdents, NumSelIdents, CurContext, Results); + SelIdents, NumSelIdents, CurContext, Results, false); // Add methods in our implementation, if any. if (ObjCImplementationDecl *Impl = IFace->getImplementation()) AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, - NumSelIdents, CurContext, Results); + NumSelIdents, CurContext, Results, InOriginalClass); } -void Sema::CodeCompleteObjCPropertyGetter(Scope *S, DeclPtrTy ClassDecl, - DeclPtrTy *Methods, +void Sema::CodeCompleteObjCPropertyGetter(Scope *S, Decl *ClassDecl, + Decl **Methods, unsigned NumMethods) { - typedef CodeCompleteConsumer::Result Result; + typedef CodeCompletionResult Result; // Try to find the interface where getters might live. - ObjCInterfaceDecl *Class - = dyn_cast_or_null(ClassDecl.getAs()); + ObjCInterfaceDecl *Class = dyn_cast_or_null(ClassDecl); if (!Class) { if (ObjCCategoryDecl *Category - = dyn_cast_or_null(ClassDecl.getAs())) + = dyn_cast_or_null(ClassDecl)) Class = Category->getClassInterface(); if (!Class) @@ -3283,7 +3897,7 @@ void Sema::CodeCompleteObjCPropertyGetter(Scope *S, DeclPtrTy ClassDecl, // pushed into DeclContexts early enough. Argh! for (unsigned I = 0; I != NumMethods; ++I) { if (ObjCMethodDecl *Method - = dyn_cast_or_null(Methods[I].getAs())) + = dyn_cast_or_null(Methods[I])) if (Method->isInstanceMethod() && isAcceptableObjCMethod(Method, MK_ZeroArgSelector, 0, 0)) { Result R = Result(Method, 0); @@ -3294,20 +3908,22 @@ void Sema::CodeCompleteObjCPropertyGetter(Scope *S, DeclPtrTy ClassDecl, AddObjCMethods(Class, true, MK_ZeroArgSelector, 0, 0, CurContext, Results); Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter,Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); } -void Sema::CodeCompleteObjCPropertySetter(Scope *S, DeclPtrTy ObjCImplDecl, - DeclPtrTy *Methods, +void Sema::CodeCompleteObjCPropertySetter(Scope *S, Decl *ObjCImplDecl, + Decl **Methods, unsigned NumMethods) { - typedef CodeCompleteConsumer::Result Result; + typedef CodeCompletionResult Result; // Try to find the interface where setters might live. ObjCInterfaceDecl *Class - = dyn_cast_or_null(ObjCImplDecl.getAs()); + = dyn_cast_or_null(ObjCImplDecl); if (!Class) { if (ObjCCategoryDecl *Category - = dyn_cast_or_null(ObjCImplDecl.getAs())) + = dyn_cast_or_null(ObjCImplDecl)) Class = Category->getClassInterface(); if (!Class) @@ -3322,7 +3938,7 @@ void Sema::CodeCompleteObjCPropertySetter(Scope *S, DeclPtrTy ObjCImplDecl, // pushed into DeclContexts early enough. Argh! for (unsigned I = 0; I != NumMethods; ++I) { if (ObjCMethodDecl *Method - = dyn_cast_or_null(Methods[I].getAs())) + = dyn_cast_or_null(Methods[I])) if (Method->isInstanceMethod() && isAcceptableObjCMethod(Method, MK_OneArgSelector, 0, 0)) { Result R = Result(Method, 0); @@ -3334,7 +3950,54 @@ void Sema::CodeCompleteObjCPropertySetter(Scope *S, DeclPtrTy ObjCImplDecl, AddObjCMethods(Class, true, MK_OneArgSelector, 0, 0, CurContext, Results); Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter,Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); +} + +void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS) { + typedef CodeCompletionResult Result; + ResultBuilder Results(*this); + Results.EnterNewScope(); + + // Add context-sensitive, Objective-C parameter-passing keywords. + bool AddedInOut = false; + if ((DS.getObjCDeclQualifier() & + (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) { + Results.AddResult("in"); + Results.AddResult("inout"); + AddedInOut = true; + } + if ((DS.getObjCDeclQualifier() & + (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) { + Results.AddResult("out"); + if (!AddedInOut) + Results.AddResult("inout"); + } + if ((DS.getObjCDeclQualifier() & + (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref | + ObjCDeclSpec::DQ_Oneway)) == 0) { + Results.AddResult("bycopy"); + Results.AddResult("byref"); + Results.AddResult("oneway"); + } + + // Add various builtin type names and specifiers. + AddOrdinaryNameResults(PCC_Type, S, *this, Results); + Results.ExitScope(); + + // Add the various type names + Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName); + CodeCompletionDeclConsumer Consumer(Results, CurContext); + LookupVisibleDecls(S, LookupOrdinaryName, Consumer, + CodeCompleter->includeGlobals()); + + if (CodeCompleter->includeMacros()) + AddMacroResults(PP, Results); + + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Type, + Results.data(), Results.size()); } /// \brief When we have an expression with type "id", we may assume @@ -3407,28 +4070,138 @@ static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) { .Default(0); } +// Add a special completion for a message send to "super", which fills in the +// most likely case of forwarding all of our arguments to the superclass +// function. +/// +/// \param S The semantic analysis object. +/// +/// \param S NeedSuperKeyword Whether we need to prefix this completion with +/// the "super" keyword. Otherwise, we just need to provide the arguments. +/// +/// \param SelIdents The identifiers in the selector that have already been +/// provided as arguments for a send to "super". +/// +/// \param NumSelIdents The number of identifiers in \p SelIdents. +/// +/// \param Results The set of results to augment. +/// +/// \returns the Objective-C method declaration that would be invoked by +/// this "super" completion. If NULL, no completion was added. +static ObjCMethodDecl *AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword, + IdentifierInfo **SelIdents, + unsigned NumSelIdents, + ResultBuilder &Results) { + ObjCMethodDecl *CurMethod = S.getCurMethodDecl(); + if (!CurMethod) + return 0; + + ObjCInterfaceDecl *Class = CurMethod->getClassInterface(); + if (!Class) + return 0; + + // Try to find a superclass method with the same selector. + ObjCMethodDecl *SuperMethod = 0; + while ((Class = Class->getSuperClass()) && !SuperMethod) + SuperMethod = Class->getMethod(CurMethod->getSelector(), + CurMethod->isInstanceMethod()); + + if (!SuperMethod) + return 0; + + // Check whether the superclass method has the same signature. + if (CurMethod->param_size() != SuperMethod->param_size() || + CurMethod->isVariadic() != SuperMethod->isVariadic()) + return 0; + + for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(), + CurPEnd = CurMethod->param_end(), + SuperP = SuperMethod->param_begin(); + CurP != CurPEnd; ++CurP, ++SuperP) { + // Make sure the parameter types are compatible. + if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(), + (*SuperP)->getType())) + return 0; + + // Make sure we have a parameter name to forward! + if (!(*CurP)->getIdentifier()) + return 0; + } + + // We have a superclass method. Now, form the send-to-super completion. + CodeCompletionString *Pattern = new CodeCompletionString; + + // Give this completion a return type. + AddResultTypeChunk(S.Context, SuperMethod, Pattern); + + // If we need the "super" keyword, add it (plus some spacing). + if (NeedSuperKeyword) { + Pattern->AddTypedTextChunk("super"); + Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); + } + + Selector Sel = CurMethod->getSelector(); + if (Sel.isUnarySelector()) { + if (NeedSuperKeyword) + Pattern->AddTextChunk(Sel.getIdentifierInfoForSlot(0)->getName()); + else + Pattern->AddTypedTextChunk(Sel.getIdentifierInfoForSlot(0)->getName()); + } else { + ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(); + for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) { + if (I > NumSelIdents) + Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); + + if (I < NumSelIdents) + Pattern->AddInformativeChunk( + Sel.getIdentifierInfoForSlot(I)->getName().str() + ":"); + else if (NeedSuperKeyword || I > NumSelIdents) { + Pattern->AddTextChunk( + Sel.getIdentifierInfoForSlot(I)->getName().str() + ":"); + Pattern->AddPlaceholderChunk((*CurP)->getIdentifier()->getName()); + } else { + Pattern->AddTypedTextChunk( + Sel.getIdentifierInfoForSlot(I)->getName().str() + ":"); + Pattern->AddPlaceholderChunk((*CurP)->getIdentifier()->getName()); + } + } + } + + Results.AddResult(CodeCompletionResult(Pattern, CCP_SuperCompletion, + SuperMethod->isInstanceMethod() + ? CXCursor_ObjCInstanceMethodDecl + : CXCursor_ObjCClassMethodDecl)); + return SuperMethod; +} + void Sema::CodeCompleteObjCMessageReceiver(Scope *S) { - typedef CodeCompleteConsumer::Result Result; + typedef CodeCompletionResult Result; ResultBuilder Results(*this); // Find anything that looks like it could be a message receiver. Results.setFilter(&ResultBuilder::IsObjCMessageReceiver); CodeCompletionDeclConsumer Consumer(Results, CurContext); Results.EnterNewScope(); - LookupVisibleDecls(S, LookupOrdinaryName, Consumer); + LookupVisibleDecls(S, LookupOrdinaryName, Consumer, + CodeCompleter->includeGlobals()); // If we are in an Objective-C method inside a class that has a superclass, // add "super" as an option. if (ObjCMethodDecl *Method = getCurMethodDecl()) if (ObjCInterfaceDecl *Iface = Method->getClassInterface()) - if (Iface->getSuperClass()) + if (Iface->getSuperClass()) { Results.AddResult(Result("super")); + + AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, 0, 0, Results); + } Results.ExitScope(); if (CodeCompleter->includeMacros()) AddMacroResults(PP, Results); - HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_ObjCMessageReceiver, + Results.data(), Results.size()); } @@ -3454,10 +4227,11 @@ void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, // an instance method. QualType SuperTy = Context.getObjCInterfaceType(CDecl); SuperTy = Context.getObjCObjectPointerType(SuperTy); - OwningExprResult Super + ExprResult Super = Owned(new (Context) ObjCSuperExpr(SuperLoc, SuperTy)); return CodeCompleteObjCInstanceMessage(S, (Expr *)Super.get(), - SelIdents, NumSelIdents); + SelIdents, NumSelIdents, + /*IsSuper=*/true); } // Fall through to send to the superclass in CDecl. @@ -3480,7 +4254,7 @@ void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, CXXScopeSpec SS; UnqualifiedId id; id.setIdentifier(Super, SuperLoc); - OwningExprResult SuperExpr = ActOnIdExpression(S, SS, id, false, false); + ExprResult SuperExpr = ActOnIdExpression(S, SS, id, false, false); return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(), SelIdents, NumSelIdents); } @@ -3488,17 +4262,24 @@ void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, // Fall through } - TypeTy *Receiver = 0; + ParsedType Receiver; if (CDecl) - Receiver = Context.getObjCInterfaceType(CDecl).getAsOpaquePtr(); + Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl)); return CodeCompleteObjCClassMessage(S, Receiver, SelIdents, - NumSelIdents); + NumSelIdents, /*IsSuper=*/true); } -void Sema::CodeCompleteObjCClassMessage(Scope *S, TypeTy *Receiver, +void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver, IdentifierInfo **SelIdents, unsigned NumSelIdents) { - typedef CodeCompleteConsumer::Result Result; + CodeCompleteObjCClassMessage(S, Receiver, SelIdents, NumSelIdents, false); +} + +void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver, + IdentifierInfo **SelIdents, + unsigned NumSelIdents, + bool IsSuper) { + typedef CodeCompletionResult Result; ObjCInterfaceDecl *CDecl = 0; // If the given name refers to an interface type, retrieve the @@ -3515,6 +4296,20 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, TypeTy *Receiver, ResultBuilder Results(*this); Results.EnterNewScope(); + // If this is a send-to-super, try to add the special "super" send + // completion. + if (IsSuper) { + if (ObjCMethodDecl *SuperMethod + = AddSuperSendCompletion(*this, false, SelIdents, NumSelIdents, + Results)) + Results.Ignore(SuperMethod); + } + + // If we're inside an Objective-C method definition, prefer its selector to + // others. + if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) + Results.setPreferredSelector(CurMethod->getSelector()); + if (CDecl) AddObjCMethods(CDecl, false, MK_Any, SelIdents, NumSelIdents, CurContext, Results); @@ -3522,25 +4317,23 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, TypeTy *Receiver, // We're messaging "id" as a type; provide all class/factory methods. // If we have an external source, load the entire class method - // pool from the PCH file. + // pool from the AST file. if (ExternalSource) { for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); I != N; ++I) { Selector Sel = ExternalSource->GetExternalSelector(I); - if (Sel.isNull() || FactoryMethodPool.count(Sel) || - InstanceMethodPool.count(Sel)) + if (Sel.isNull() || MethodPool.count(Sel)) continue; - ReadMethodPool(Sel, /*isInstance=*/false); + ReadMethodPool(Sel); } } - for (llvm::DenseMap::iterator - M = FactoryMethodPool.begin(), - MEnd = FactoryMethodPool.end(); - M != MEnd; - ++M) { - for (ObjCMethodList *MethList = &M->second; MethList && MethList->Method; + for (GlobalMethodPool::iterator M = MethodPool.begin(), + MEnd = MethodPool.end(); + M != MEnd; ++M) { + for (ObjCMethodList *MethList = &M->second.second; + MethList && MethList->Method; MethList = MethList->Next) { if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents, NumSelIdents)) @@ -3555,13 +4348,22 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, TypeTy *Receiver, } Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(), Results.size()); } void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver, IdentifierInfo **SelIdents, unsigned NumSelIdents) { - typedef CodeCompleteConsumer::Result Result; + CodeCompleteObjCInstanceMessage(S, Receiver, SelIdents, NumSelIdents, false); +} + +void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver, + IdentifierInfo **SelIdents, + unsigned NumSelIdents, + bool IsSuper) { + typedef CodeCompletionResult Result; Expr *RecExpr = static_cast(Receiver); @@ -3574,6 +4376,20 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver, ResultBuilder Results(*this); Results.EnterNewScope(); + // If this is a send-to-super, try to add the special "super" send + // completion. + if (IsSuper) { + if (ObjCMethodDecl *SuperMethod + = AddSuperSendCompletion(*this, false, SelIdents, NumSelIdents, + Results)) + Results.Ignore(SuperMethod); + } + + // If we're inside an Objective-C method definition, prefer its selector to + // others. + if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) + Results.setPreferredSelector(CurMethod->getSelector()); + // If we're messaging an expression with type "id" or "Class", check // whether we know something special about the receiver that allows // us to assume a more-specific receiver type. @@ -3623,25 +4439,23 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver, // about as code-completion results. // If we have an external source, load the entire class method - // pool from the PCH file. + // pool from the AST file. if (ExternalSource) { for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); I != N; ++I) { Selector Sel = ExternalSource->GetExternalSelector(I); - if (Sel.isNull() || InstanceMethodPool.count(Sel) || - FactoryMethodPool.count(Sel)) + if (Sel.isNull() || MethodPool.count(Sel)) continue; - ReadMethodPool(Sel, /*isInstance=*/true); + ReadMethodPool(Sel); } } - for (llvm::DenseMap::iterator - M = InstanceMethodPool.begin(), - MEnd = InstanceMethodPool.end(); - M != MEnd; - ++M) { - for (ObjCMethodList *MethList = &M->second; MethList && MethList->Method; + for (GlobalMethodPool::iterator M = MethodPool.begin(), + MEnd = MethodPool.end(); + M != MEnd; ++M) { + for (ObjCMethodList *MethList = &M->second.first; + MethList && MethList->Method; MethList = MethList->Next) { if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents, NumSelIdents)) @@ -3656,7 +4470,79 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver, } Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); +} + +void Sema::CodeCompleteObjCForCollection(Scope *S, + DeclGroupPtrTy IterationVar) { + CodeCompleteExpressionData Data; + Data.ObjCCollection = true; + + if (IterationVar.getAsOpaquePtr()) { + DeclGroupRef DG = IterationVar.getAsVal(); + for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) { + if (*I) + Data.IgnoreDecls.push_back(*I); + } + } + + CodeCompleteExpression(S, Data); +} + +void Sema::CodeCompleteObjCSelector(Scope *S, IdentifierInfo **SelIdents, + unsigned NumSelIdents) { + // If we have an external source, load the entire class method + // pool from the AST file. + if (ExternalSource) { + for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); + I != N; ++I) { + Selector Sel = ExternalSource->GetExternalSelector(I); + if (Sel.isNull() || MethodPool.count(Sel)) + continue; + + ReadMethodPool(Sel); + } + } + + ResultBuilder Results(*this); + Results.EnterNewScope(); + for (GlobalMethodPool::iterator M = MethodPool.begin(), + MEnd = MethodPool.end(); + M != MEnd; ++M) { + + Selector Sel = M->first; + if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents, NumSelIdents)) + continue; + + CodeCompletionString *Pattern = new CodeCompletionString; + if (Sel.isUnarySelector()) { + Pattern->AddTypedTextChunk(Sel.getIdentifierInfoForSlot(0)->getName()); + Results.AddResult(Pattern); + continue; + } + + std::string Accumulator; + for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) { + if (I == NumSelIdents) { + if (!Accumulator.empty()) { + Pattern->AddInformativeChunk(Accumulator); + Accumulator.clear(); + } + } + + Accumulator += Sel.getIdentifierInfoForSlot(I)->getName().str(); + Accumulator += ':'; + } + Pattern->AddTypedTextChunk(Accumulator); + Results.AddResult(Pattern); + } + Results.ExitScope(); + + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_SelectorName, + Results.data(), Results.size()); } /// \brief Add all of the protocol declarations that we find in the given @@ -3664,7 +4550,7 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver, static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext, bool OnlyForwardDeclarations, ResultBuilder &Results) { - typedef CodeCompleteConsumer::Result Result; + typedef CodeCompletionResult Result; for (DeclContext::decl_iterator D = Ctx->decls_begin(), DEnd = Ctx->decls_end(); @@ -3704,7 +4590,9 @@ void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols, Results); Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_ObjCProtocolName, + Results.data(),Results.size()); } void Sema::CodeCompleteObjCProtocolDecl(Scope *) { @@ -3716,7 +4604,9 @@ void Sema::CodeCompleteObjCProtocolDecl(Scope *) { Results); Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_ObjCProtocolName, + Results.data(),Results.size()); } /// \brief Add all of the Objective-C interface declarations that we find in @@ -3725,7 +4615,7 @@ static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext, bool OnlyForwardDeclarations, bool OnlyUnimplemented, ResultBuilder &Results) { - typedef CodeCompleteConsumer::Result Result; + typedef CodeCompletionResult Result; for (DeclContext::decl_iterator D = Ctx->decls_begin(), DEnd = Ctx->decls_end(); @@ -3757,7 +4647,9 @@ void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) { false, Results); Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); } void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName, @@ -3776,7 +4668,9 @@ void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName, false, Results); Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); } void Sema::CodeCompleteObjCImplementationDecl(Scope *S) { @@ -3788,13 +4682,15 @@ void Sema::CodeCompleteObjCImplementationDecl(Scope *S) { true, Results); Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); } void Sema::CodeCompleteObjCInterfaceCategory(Scope *S, IdentifierInfo *ClassName, SourceLocation ClassNameLoc) { - typedef CodeCompleteConsumer::Result Result; + typedef CodeCompletionResult Result; ResultBuilder Results(*this); @@ -3819,13 +4715,15 @@ void Sema::CodeCompleteObjCInterfaceCategory(Scope *S, Results.AddResult(Result(Category, 0), CurContext, 0, false); Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); } void Sema::CodeCompleteObjCImplementationCategory(Scope *S, IdentifierInfo *ClassName, SourceLocation ClassNameLoc) { - typedef CodeCompleteConsumer::Result Result; + typedef CodeCompletionResult Result; // Find the corresponding interface. If we couldn't find the interface, the // program itself is ill-formed. However, we'll try to be helpful still by @@ -3856,16 +4754,18 @@ void Sema::CodeCompleteObjCImplementationCategory(Scope *S, } Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); } -void Sema::CodeCompleteObjCPropertyDefinition(Scope *S, DeclPtrTy ObjCImpDecl) { - typedef CodeCompleteConsumer::Result Result; +void Sema::CodeCompleteObjCPropertyDefinition(Scope *S, Decl *ObjCImpDecl) { + typedef CodeCompletionResult Result; ResultBuilder Results(*this); // Figure out where this @synthesize lives. ObjCContainerDecl *Container - = dyn_cast_or_null(ObjCImpDecl.getAs()); + = dyn_cast_or_null(ObjCImpDecl); if (!Container || (!isa(Container) && !isa(Container))) @@ -3889,18 +4789,20 @@ void Sema::CodeCompleteObjCPropertyDefinition(Scope *S, DeclPtrTy ObjCImpDecl) { false, CurContext, Results); Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); } void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S, IdentifierInfo *PropertyName, - DeclPtrTy ObjCImpDecl) { - typedef CodeCompleteConsumer::Result Result; + Decl *ObjCImpDecl) { + typedef CodeCompletionResult Result; ResultBuilder Results(*this); // Figure out where this @synthesize lives. ObjCContainerDecl *Container - = dyn_cast_or_null(ObjCImpDecl.getAs()); + = dyn_cast_or_null(ObjCImpDecl); if (!Container || (!isa(Container) && !isa(Container))) @@ -3927,10 +4829,15 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S, } Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); } -typedef llvm::DenseMap KnownMethodsMap; +// Mapping from selectors to the methods that implement that selector, along +// with the "in original class" flag. +typedef llvm::DenseMap > + KnownMethodsMap; /// \brief Find all of the methods that reside in the given container /// (and its superclasses, protocols, etc.) that meet the given @@ -3941,7 +4848,8 @@ static void FindImplementableMethods(ASTContext &Context, bool WantInstanceMethods, QualType ReturnType, bool IsInImplementation, - KnownMethodsMap &KnownMethods) { + KnownMethodsMap &KnownMethods, + bool InOriginalClass = true) { if (ObjCInterfaceDecl *IFace = dyn_cast(Container)) { // Recurse into protocols. const ObjCList &Protocols @@ -3950,14 +4858,16 @@ static void FindImplementableMethods(ASTContext &Context, E = Protocols.end(); I != E; ++I) FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType, - IsInImplementation, KnownMethods); + IsInImplementation, KnownMethods, + InOriginalClass); // If we're not in the implementation of a class, also visit the // superclass. if (!IsInImplementation && IFace->getSuperClass()) FindImplementableMethods(Context, IFace->getSuperClass(), WantInstanceMethods, ReturnType, - IsInImplementation, KnownMethods); + IsInImplementation, KnownMethods, + false); // Add methods from any class extensions (but not from categories; // those should go into category implementations). @@ -3965,7 +4875,8 @@ static void FindImplementableMethods(ASTContext &Context, Cat = Cat->getNextClassExtension()) FindImplementableMethods(Context, const_cast(Cat), WantInstanceMethods, ReturnType, - IsInImplementation, KnownMethods); + IsInImplementation, KnownMethods, + InOriginalClass); } if (ObjCCategoryDecl *Category = dyn_cast(Container)) { @@ -3976,7 +4887,8 @@ static void FindImplementableMethods(ASTContext &Context, E = Protocols.end(); I != E; ++I) FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType, - IsInImplementation, KnownMethods); + IsInImplementation, KnownMethods, + InOriginalClass); } if (ObjCProtocolDecl *Protocol = dyn_cast(Container)) { @@ -3987,7 +4899,7 @@ static void FindImplementableMethods(ASTContext &Context, E = Protocols.end(); I != E; ++I) FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType, - IsInImplementation, KnownMethods); + IsInImplementation, KnownMethods, false); } // Add methods in this container. This operation occurs last because @@ -4001,15 +4913,15 @@ static void FindImplementableMethods(ASTContext &Context, !Context.hasSameUnqualifiedType(ReturnType, (*M)->getResultType())) continue; - KnownMethods[(*M)->getSelector()] = *M; + KnownMethods[(*M)->getSelector()] = std::make_pair(*M, InOriginalClass); } } } void Sema::CodeCompleteObjCMethodDecl(Scope *S, bool IsInstanceMethod, - TypeTy *ReturnTy, - DeclPtrTy IDecl) { + ParsedType ReturnTy, + Decl *IDecl) { // Determine the return type of the method we're declaring, if // provided. QualType ReturnType = GetTypeFromParser(ReturnTy); @@ -4017,7 +4929,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, // Determine where we should start searching for methods, and where we ObjCContainerDecl *SearchDecl = 0, *CurrentDecl = 0; bool IsInImplementation = false; - if (Decl *D = IDecl.getAs()) { + if (Decl *D = IDecl) { if (ObjCImplementationDecl *Impl = dyn_cast(D)) { SearchDecl = Impl->getClassInterface(); CurrentDecl = Impl; @@ -4041,7 +4953,9 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, } if (!SearchDecl || !CurrentDecl) { - HandleCodeCompleteResults(this, CodeCompleter, 0, 0); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + 0, 0); return; } @@ -4064,7 +4978,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, } // Add declarations or definitions for each of the known methods. - typedef CodeCompleteConsumer::Result Result; + typedef CodeCompletionResult Result; ResultBuilder Results(*this); Results.EnterNewScope(); PrintingPolicy Policy(Context.PrintingPolicy); @@ -4072,7 +4986,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, for (KnownMethodsMap::iterator M = KnownMethods.begin(), MEnd = KnownMethods.end(); M != MEnd; ++M) { - ObjCMethodDecl *Method = M->second; + ObjCMethodDecl *Method = M->second.first; CodeCompletionString *Pattern = new CodeCompletionString; // If the result type was not already provided, add it to the @@ -4100,7 +5014,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Pattern->AddChunk(CodeCompletionString::CK_Colon); else if (I < Sel.getNumArgs()) { Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); - Pattern->AddTextChunk(Sel.getIdentifierInfoForSlot(1)->getName()); + Pattern->AddTextChunk(Sel.getIdentifierInfoForSlot(I)->getName()); Pattern->AddChunk(CodeCompletionString::CK_Colon); } else break; @@ -4113,14 +5027,14 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Pattern->AddChunk(CodeCompletionString::CK_RightParen); if (IdentifierInfo *Id = (*P)->getIdentifier()) - Pattern->AddTextChunk(Id->getName()); + Pattern->AddTextChunk(Id->getName()); } if (Method->isVariadic()) { if (Method->param_size() > 0) Pattern->AddChunk(CodeCompletionString::CK_Comma); Pattern->AddTextChunk("..."); - } + } if (IsInImplementation && Results.includeCodePatterns()) { // We will be defining the method here, so add a compound statement. @@ -4140,50 +5054,56 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Pattern->AddChunk(CodeCompletionString::CK_RightBrace); } - Results.AddResult(Result(Pattern)); + unsigned Priority = CCP_CodePattern; + if (!M->second.second) + Priority += CCD_InBaseClass; + + Results.AddResult(Result(Pattern, Priority, + Method->isInstanceMethod() + ? CXCursor_ObjCInstanceMethodDecl + : CXCursor_ObjCClassMethodDecl)); } Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); } void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S, bool IsInstanceMethod, bool AtParameterName, - TypeTy *ReturnTy, + ParsedType ReturnTy, IdentifierInfo **SelIdents, unsigned NumSelIdents) { - llvm::DenseMap &Pool - = IsInstanceMethod? InstanceMethodPool : FactoryMethodPool; - // If we have an external source, load the entire class method - // pool from the PCH file. + // pool from the AST file. if (ExternalSource) { for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); I != N; ++I) { Selector Sel = ExternalSource->GetExternalSelector(I); - if (Sel.isNull() || InstanceMethodPool.count(Sel) || - FactoryMethodPool.count(Sel)) + if (Sel.isNull() || MethodPool.count(Sel)) continue; - - ReadMethodPool(Sel, IsInstanceMethod); + + ReadMethodPool(Sel); } } // Build the set of methods we can see. - typedef CodeCompleteConsumer::Result Result; + typedef CodeCompletionResult Result; ResultBuilder Results(*this); if (ReturnTy) Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType()); - + Results.EnterNewScope(); - for (llvm::DenseMap::iterator M = Pool.begin(), - MEnd = Pool.end(); - M != MEnd; - ++M) { - for (ObjCMethodList *MethList = &M->second; MethList && MethList->Method; + for (GlobalMethodPool::iterator M = MethodPool.begin(), + MEnd = MethodPool.end(); + M != MEnd; ++M) { + for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first : + &M->second.second; + MethList && MethList->Method; MethList = MethList->Next) { if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents, NumSelIdents)) @@ -4212,5 +5132,270 @@ void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S, } Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); +} + +void Sema::CodeCompletePreprocessorDirective(bool InConditional) { + ResultBuilder Results(*this); + Results.EnterNewScope(); + + // #if + CodeCompletionString *Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk("if"); + Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); + Pattern->AddPlaceholderChunk("condition"); + Results.AddResult(Pattern); + + // #ifdef + Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk("ifdef"); + Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); + Pattern->AddPlaceholderChunk("macro"); + Results.AddResult(Pattern); + + // #ifndef + Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk("ifndef"); + Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); + Pattern->AddPlaceholderChunk("macro"); + Results.AddResult(Pattern); + + if (InConditional) { + // #elif + Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk("elif"); + Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); + Pattern->AddPlaceholderChunk("condition"); + Results.AddResult(Pattern); + + // #else + Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk("else"); + Results.AddResult(Pattern); + + // #endif + Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk("endif"); + Results.AddResult(Pattern); + } + + // #include "header" + Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk("include"); + Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); + Pattern->AddTextChunk("\""); + Pattern->AddPlaceholderChunk("header"); + Pattern->AddTextChunk("\""); + Results.AddResult(Pattern); + + // #include
+ Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk("include"); + Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); + Pattern->AddTextChunk("<"); + Pattern->AddPlaceholderChunk("header"); + Pattern->AddTextChunk(">"); + Results.AddResult(Pattern); + + // #define + Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk("define"); + Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); + Pattern->AddPlaceholderChunk("macro"); + Results.AddResult(Pattern); + + // #define () + Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk("define"); + Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); + Pattern->AddPlaceholderChunk("macro"); + Pattern->AddChunk(CodeCompletionString::CK_LeftParen); + Pattern->AddPlaceholderChunk("args"); + Pattern->AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Pattern); + + // #undef + Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk("undef"); + Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); + Pattern->AddPlaceholderChunk("macro"); + Results.AddResult(Pattern); + + // #line + Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk("line"); + Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); + Pattern->AddPlaceholderChunk("number"); + Results.AddResult(Pattern); + + // #line "filename" + Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk("line"); + Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); + Pattern->AddPlaceholderChunk("number"); + Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); + Pattern->AddTextChunk("\""); + Pattern->AddPlaceholderChunk("filename"); + Pattern->AddTextChunk("\""); + Results.AddResult(Pattern); + + // #error + Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk("error"); + Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); + Pattern->AddPlaceholderChunk("message"); + Results.AddResult(Pattern); + + // #pragma + Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk("pragma"); + Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); + Pattern->AddPlaceholderChunk("arguments"); + Results.AddResult(Pattern); + + if (getLangOptions().ObjC1) { + // #import "header" + Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk("import"); + Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); + Pattern->AddTextChunk("\""); + Pattern->AddPlaceholderChunk("header"); + Pattern->AddTextChunk("\""); + Results.AddResult(Pattern); + + // #import
+ Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk("import"); + Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); + Pattern->AddTextChunk("<"); + Pattern->AddPlaceholderChunk("header"); + Pattern->AddTextChunk(">"); + Results.AddResult(Pattern); + } + + // #include_next "header" + Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk("include_next"); + Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); + Pattern->AddTextChunk("\""); + Pattern->AddPlaceholderChunk("header"); + Pattern->AddTextChunk("\""); + Results.AddResult(Pattern); + + // #include_next
+ Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk("include_next"); + Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); + Pattern->AddTextChunk("<"); + Pattern->AddPlaceholderChunk("header"); + Pattern->AddTextChunk(">"); + Results.AddResult(Pattern); + + // #warning + Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk("warning"); + Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); + Pattern->AddPlaceholderChunk("message"); + Results.AddResult(Pattern); + + // Note: #ident and #sccs are such crazy anachronisms that we don't provide + // completions for them. And __include_macros is a Clang-internal extension + // that we don't want to encourage anyone to use. + + // FIXME: we don't support #assert or #unassert, so don't suggest them. + Results.ExitScope(); + + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_PreprocessorDirective, + Results.data(), Results.size()); +} + +void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) { + CodeCompleteOrdinaryName(S, + S->getFnParent()? Sema::PCC_RecoveryInFunction + : Sema::PCC_Namespace); +} + +void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) { + ResultBuilder Results(*this); + if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) { + // Add just the names of macros, not their arguments. + Results.EnterNewScope(); + for (Preprocessor::macro_iterator M = PP.macro_begin(), + MEnd = PP.macro_end(); + M != MEnd; ++M) { + CodeCompletionString *Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk(M->first->getName()); + Results.AddResult(Pattern); + } + Results.ExitScope(); + } else if (IsDefinition) { + // FIXME: Can we detect when the user just wrote an include guard above? + } + + HandleCodeCompleteResults(this, CodeCompleter, + IsDefinition? CodeCompletionContext::CCC_MacroName + : CodeCompletionContext::CCC_MacroNameUse, + Results.data(), Results.size()); +} + +void Sema::CodeCompletePreprocessorExpression() { + ResultBuilder Results(*this); + + if (!CodeCompleter || CodeCompleter->includeMacros()) + AddMacroResults(PP, Results); + + // defined () + Results.EnterNewScope(); + CodeCompletionString *Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk("defined"); + Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); + Pattern->AddChunk(CodeCompletionString::CK_LeftParen); + Pattern->AddPlaceholderChunk("macro"); + Pattern->AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Pattern); + Results.ExitScope(); + + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_PreprocessorExpression, + Results.data(), Results.size()); +} + +void Sema::CodeCompletePreprocessorMacroArgument(Scope *S, + IdentifierInfo *Macro, + MacroInfo *MacroInfo, + unsigned Argument) { + // FIXME: In the future, we could provide "overload" results, much like we + // do for function calls. + + CodeCompleteOrdinaryName(S, + S->getFnParent()? Sema::PCC_RecoveryInFunction + : Sema::PCC_Namespace); +} + +void Sema::CodeCompleteNaturalLanguage() { + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_NaturalLanguage, + 0, 0); +} + +void Sema::GatherGlobalCodeCompletions( + llvm::SmallVectorImpl &Results) { + ResultBuilder Builder(*this); + + if (!CodeCompleter || CodeCompleter->includeGlobals()) { + CodeCompletionDeclConsumer Consumer(Builder, + Context.getTranslationUnitDecl()); + LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName, + Consumer); + } + + if (!CodeCompleter || CodeCompleter->includeMacros()) + AddMacroResults(PP, Builder); + + Results.clear(); + Results.insert(Results.end(), + Builder.data(), Builder.data() + Builder.size()); } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index c1c898fac5f9..f5e045a722a0 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -11,19 +11,24 @@ // //===----------------------------------------------------------------------===// -#include "Sema.h" -#include "SemaInit.h" -#include "Lookup.h" +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/Initialization.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/CXXFieldCollector.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/ScopeInfo.h" #include "clang/AST/APValue.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/CXXInheritance.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/StmtCXX.h" -#include "clang/Parse/DeclSpec.h" +#include "clang/Sema/DeclSpec.h" +#include "clang/Sema/ParsedTemplate.h" #include "clang/Parse/ParseDiagnostic.h" -#include "clang/Parse/Template.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" @@ -35,18 +40,10 @@ #include #include using namespace clang; +using namespace sema; -/// getDeclName - Return a pretty name for the specified decl if possible, or -/// an empty string if not. This is used for pretty crash reporting. -std::string Sema::getDeclName(DeclPtrTy d) { - Decl *D = d.getAs(); - if (NamedDecl *DN = dyn_cast_or_null(D)) - return DN->getQualifiedNameAsString(); - return ""; -} - -Sema::DeclGroupPtrTy Sema::ConvertDeclToDeclGroup(DeclPtrTy Ptr) { - return DeclGroupPtrTy::make(DeclGroupRef(Ptr.getAs())); +Sema::DeclGroupPtrTy Sema::ConvertDeclToDeclGroup(Decl *Ptr) { + return DeclGroupPtrTy::make(DeclGroupRef(Ptr)); } /// \brief If the identifier refers to a type name within this scope, @@ -60,14 +57,14 @@ Sema::DeclGroupPtrTy Sema::ConvertDeclToDeclGroup(DeclPtrTy Ptr) { /// /// If name lookup results in an ambiguity, this routine will complain /// and then return NULL. -Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, - Scope *S, CXXScopeSpec *SS, - bool isClassName, - TypeTy *ObjectTypePtr) { +ParsedType Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, + Scope *S, CXXScopeSpec *SS, + bool isClassName, + ParsedType ObjectTypePtr) { // Determine where we will perform name lookup. DeclContext *LookupCtx = 0; if (ObjectTypePtr) { - QualType ObjectType = QualType::getFromOpaquePtr(ObjectTypePtr); + QualType ObjectType = ObjectTypePtr.get(); if (ObjectType->isRecordType()) LookupCtx = computeDeclContext(ObjectType); } else if (SS && SS->isNotEmpty()) { @@ -85,22 +82,22 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, // We therefore do not perform any name lookup if the result would // refer to a member of an unknown specialization. if (!isClassName) - return 0; + return ParsedType(); // We know from the grammar that this name refers to a type, // so build a dependent node to describe the type. - return CheckTypenameType(ETK_None, - (NestedNameSpecifier *)SS->getScopeRep(), II, - SourceLocation(), SS->getRange(), NameLoc - ).getAsOpaquePtr(); + QualType T = + CheckTypenameType(ETK_None, SS->getScopeRep(), II, + SourceLocation(), SS->getRange(), NameLoc); + return ParsedType::make(T); } - return 0; + return ParsedType(); } if (!LookupCtx->isDependentContext() && RequireCompleteDeclContext(*SS, LookupCtx)) - return 0; + return ParsedType(); } // FIXME: LookupNestedNameSpecifierName isn't the right kind of @@ -136,7 +133,7 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, case LookupResult::FoundOverloaded: case LookupResult::FoundUnresolvedValue: Result.suppressDiagnostics(); - return 0; + return ParsedType(); case LookupResult::Ambiguous: // Recover from type-hiding ambiguities by hiding the type. We'll @@ -146,7 +143,7 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, // that only makes sense if the identifier was treated like a type. if (Result.getAmbiguityKind() == LookupResult::AmbiguousTagHiding) { Result.suppressDiagnostics(); - return 0; + return ParsedType(); } // Look to see if we have a type anywhere in the list of results. @@ -168,7 +165,7 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, // will produce the ambiguity, or will complain that it expected // a type name. Result.suppressDiagnostics(); - return 0; + return ParsedType(); } // We found a type within the ambiguous lookup; diagnose the @@ -199,10 +196,10 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, } else { // If it's not plausibly a type, suppress diagnostics. Result.suppressDiagnostics(); - return 0; + return ParsedType(); } - return T.getAsOpaquePtr(); + return ParsedType::make(T); } /// isTagName() - This method is called *for error recovery purposes only* @@ -233,9 +230,9 @@ bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II, SourceLocation IILoc, Scope *S, CXXScopeSpec *SS, - TypeTy *&SuggestedType) { + ParsedType &SuggestedType) { // We don't have anything to suggest (yet). - SuggestedType = 0; + SuggestedType = ParsedType(); // There may have been a typo in the name of the type. Look up typo // results, in case we have something that we can suggest. @@ -282,7 +279,8 @@ bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II, CXXScopeSpec EmptySS; TemplateTy TemplateResult; bool MemberOfUnknownSpecialization; - if (isTemplateName(S, SS ? *SS : EmptySS, Name, 0, true, TemplateResult, + if (isTemplateName(S, SS ? *SS : EmptySS, /*hasTemplateKeyword=*/false, + Name, ParsedType(), true, TemplateResult, MemberOfUnknownSpecialization) == TNK_Type_template) { TemplateName TplName = TemplateResult.getAsVal(); Diag(IILoc, diag::err_template_missing_args) << TplName; @@ -343,8 +341,10 @@ DeclContext *Sema::getContainingDC(DeclContext *DC) { return DC; } + // ObjCMethodDecls are parsed (for some reason) outside the context + // of the class. if (isa(DC)) - return Context.getTranslationUnitDecl(); + return DC->getLexicalParent()->getLexicalParent(); return DC->getLexicalParent(); } @@ -360,6 +360,7 @@ void Sema::PopDeclContext() { assert(CurContext && "DeclContext imbalance!"); CurContext = getContainingDC(CurContext); + assert(CurContext && "Popped translation unit!"); } /// EnterDeclaratorContext - Used when we must lookup names in the context @@ -458,8 +459,8 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) { IdentifierResolver::iterator I = IdResolver.begin(D->getDeclName()), IEnd = IdResolver.end(); for (; I != IEnd; ++I) { - if (S->isDeclScope(DeclPtrTy::make(*I)) && D->declarationReplaces(*I)) { - S->RemoveDecl(DeclPtrTy::make(*I)); + if (S->isDeclScope(*I) && D->declarationReplaces(*I)) { + S->RemoveDecl(*I); IdResolver.RemoveDecl(*I); // Should only need to replace one decl. @@ -467,7 +468,7 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) { } } - S->AddDecl(DeclPtrTy::make(D)); + S->AddDecl(D); IdResolver.AddDecl(D); } @@ -475,6 +476,17 @@ bool Sema::isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S) { return IdResolver.isDeclInScope(D, Ctx, Context, S); } +Scope *Sema::getScopeForDeclContext(Scope *S, DeclContext *DC) { + DeclContext *TargetDC = DC->getPrimaryContext(); + do { + if (DeclContext *ScopeDC = (DeclContext*) S->getEntity()) + if (ScopeDC->getPrimaryContext() == TargetDC) + return S; + } while ((S = S->getParent())); + + return 0; +} + static bool isOutOfScopePreviousDeclaration(NamedDecl *, DeclContext*, ASTContext&); @@ -517,6 +529,90 @@ static void RemoveUsingDecls(LookupResult &R) { F.done(); } +/// \brief Check for this common pattern: +/// @code +/// class S { +/// S(const S&); // DO NOT IMPLEMENT +/// void operator=(const S&); // DO NOT IMPLEMENT +/// }; +/// @endcode +static bool IsDisallowedCopyOrAssign(const CXXMethodDecl *D) { + // FIXME: Should check for private access too but access is set after we get + // the decl here. + if (D->isThisDeclarationADefinition()) + return false; + + if (const CXXConstructorDecl *CD = dyn_cast(D)) + return CD->isCopyConstructor(); + return D->isCopyAssignment(); +} + +bool Sema::ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const { + assert(D); + + if (D->isInvalidDecl() || D->isUsed() || D->hasAttr()) + return false; + + // Ignore class templates. + if (D->getDeclContext()->isDependentContext()) + return false; + + // We warn for unused decls internal to the translation unit. + if (D->getLinkage() == ExternalLinkage) + return false; + + if (const FunctionDecl *FD = dyn_cast(D)) { + if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) + return false; + + if (const CXXMethodDecl *MD = dyn_cast(FD)) { + if (MD->isVirtual() || IsDisallowedCopyOrAssign(MD)) + return false; + } else { + // 'static inline' functions are used in headers; don't warn. + if (FD->getStorageClass() == SC_Static && + FD->isInlineSpecified()) + return false; + } + + if (FD->isThisDeclarationADefinition()) + return !Context.DeclMustBeEmitted(FD); + return true; + } + + if (const VarDecl *VD = dyn_cast(D)) { + if (VD->isStaticDataMember() && + VD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) + return false; + + if ( VD->isFileVarDecl() && + !VD->getType().isConstant(Context)) + return !Context.DeclMustBeEmitted(VD); + } + + return false; + } + + void Sema::MarkUnusedFileScopedDecl(const DeclaratorDecl *D) { + if (!D) + return; + + if (const FunctionDecl *FD = dyn_cast(D)) { + const FunctionDecl *First = FD->getFirstDeclaration(); + if (FD != First && ShouldWarnIfUnusedFileScopedDecl(First)) + return; // First should already be in the vector. + } + + if (const VarDecl *VD = dyn_cast(D)) { + const VarDecl *First = VD->getFirstDeclaration(); + if (VD != First && ShouldWarnIfUnusedFileScopedDecl(First)) + return; // First should already be in the vector. + } + + if (ShouldWarnIfUnusedFileScopedDecl(D)) + UnusedFileScopedDecls.push_back(D); + } + static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) { if (D->isInvalidDecl()) return false; @@ -585,7 +681,7 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { for (Scope::decl_iterator I = S->decl_begin(), E = S->decl_end(); I != E; ++I) { - Decl *TmpD = (*I).getAs(); + Decl *TmpD = (*I); assert(TmpD && "This decl didn't get pushed??"); assert(isa(TmpD) && "Decl isn't NamedDecl?"); @@ -731,8 +827,8 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, FunctionDecl *New = FunctionDecl::Create(Context, Context.getTranslationUnitDecl(), Loc, II, R, /*TInfo=*/0, - FunctionDecl::Extern, - FunctionDecl::None, false, + SC_Extern, + SC_None, false, /*hasPrototype=*/true); New->setImplicit(); @@ -743,7 +839,7 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i) Params.push_back(ParmVarDecl::Create(Context, New, SourceLocation(), 0, FT->getArgType(i), /*TInfo=*/0, - VarDecl::None, VarDecl::None, 0)); + SC_None, SC_None, 0)); New->setParams(Params.data(), Params.size()); } @@ -909,25 +1005,40 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls) { /// DeclhasAttr - returns true if decl Declaration already has the target /// attribute. static bool -DeclHasAttr(const Decl *decl, const Attr *target) { - for (const Attr *attr = decl->getAttrs(); attr; attr = attr->getNext()) - if (attr->getKind() == target->getKind()) +DeclHasAttr(const Decl *D, const Attr *A) { + const OwnershipAttr *OA = dyn_cast(A); + for (Decl::attr_iterator i = D->attr_begin(), e = D->attr_end(); i != e; ++i) + if ((*i)->getKind() == A->getKind()) { + // FIXME: Don't hardcode this check + if (OA && isa(*i)) + return OA->getOwnKind() == cast(*i)->getOwnKind(); return true; + } return false; } -/// MergeAttributes - append attributes from the Old decl to the New one. -static void MergeAttributes(Decl *New, Decl *Old, ASTContext &C) { - for (const Attr *attr = Old->getAttrs(); attr; attr = attr->getNext()) { - if (!DeclHasAttr(New, attr) && attr->isMerged()) { - Attr *NewAttr = attr->clone(C); +/// MergeDeclAttributes - append attributes from the Old decl to the New one. +static void MergeDeclAttributes(Decl *New, Decl *Old, ASTContext &C) { + if (!Old->hasAttrs()) + return; + // Ensure that any moving of objects within the allocated map is done before + // we process them. + if (!New->hasAttrs()) + New->setAttrs(AttrVec()); + for (Decl::attr_iterator i = Old->attr_begin(), e = Old->attr_end(); i != e; + ++i) { + // FIXME: Make this more general than just checking for Overloadable. + if (!DeclHasAttr(New, *i) && (*i)->getKind() != attr::Overloadable) { + Attr *NewAttr = (*i)->clone(C); NewAttr->setInherited(true); New->addAttr(NewAttr); } } } +namespace { + /// Used in MergeFunctionDecl to keep track of function parameters in /// C. struct GNUCompatibleParamWarning { @@ -936,6 +1047,7 @@ struct GNUCompatibleParamWarning { QualType PromotedType; }; +} /// getSpecialMember - get the special member enum for a method. Sema::CXXSpecialMember Sema::getSpecialMember(const CXXMethodDecl *MD) { @@ -960,7 +1072,7 @@ static bool canRedefineFunction(const FunctionDecl *FD, const LangOptions& LangOpts) { return (LangOpts.GNUMode && !LangOpts.C99 && !LangOpts.CPlusPlus && FD->isInlineSpecified() && - FD->getStorageClass() == FunctionDecl::Extern); + FD->getStorageClass() == SC_Extern); } /// MergeFunctionDecl - We just parsed a function 'New' from @@ -1014,8 +1126,8 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { // Don't complain about this if we're in GNU89 mode and the old function // is an extern inline function. if (!isa(New) && !isa(Old) && - New->getStorageClass() == FunctionDecl::Static && - Old->getStorageClass() != FunctionDecl::Static && + New->getStorageClass() == SC_Static && + Old->getStorageClass() != SC_Static && !canRedefineFunction(Old, getLangOptions())) { Diag(New->getLocation(), diag::err_static_non_static) << New; @@ -1196,7 +1308,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { ParmVarDecl *Param = ParmVarDecl::Create(Context, New, SourceLocation(), 0, *ParamType, /*TInfo=*/0, - VarDecl::None, VarDecl::None, + SC_None, SC_None, 0); Param->setImplicit(); Params.push_back(Param); @@ -1242,7 +1354,8 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { NewProto->getArgType(Idx))) { ArgTypes.push_back(NewParm->getType()); } else if (Context.typesAreCompatible(OldParm->getType(), - NewParm->getType())) { + NewParm->getType(), + /*CompareUnqualified=*/true)) { GNUCompatibleParamWarning Warn = { OldParm, NewParm, NewProto->getArgType(Idx) }; Warnings.push_back(Warn); @@ -1257,8 +1370,9 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { diag::ext_param_promoted_not_compatible_with_prototype) << Warnings[Warn].PromotedType << Warnings[Warn].OldParm->getType(); - Diag(Warnings[Warn].OldParm->getLocation(), - diag::note_previous_declaration); + if (Warnings[Warn].OldParm->getLocation().isValid()) + Diag(Warnings[Warn].OldParm->getLocation(), + diag::note_previous_declaration); } New->setType(Context.getFunctionType(MergedReturn, &ArgTypes[0], @@ -1309,11 +1423,11 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { /// \returns false bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) { // Merge the attributes - MergeAttributes(New, Old, Context); + MergeDeclAttributes(New, Old, Context); // Merge the storage class. - if (Old->getStorageClass() != FunctionDecl::Extern && - Old->getStorageClass() != FunctionDecl::None) + if (Old->getStorageClass() != SC_Extern && + Old->getStorageClass() != SC_None) New->setStorageClass(Old->getStorageClass()); // Merge "pure" flag. @@ -1354,7 +1468,18 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { return New->setInvalidDecl(); } - MergeAttributes(New, Old, Context); + // C++ [class.mem]p1: + // A member shall not be declared twice in the member-specification [...] + // + // Here, we need only consider static data members. + if (Old->isStaticDataMember() && !New->isOutOfLine()) { + Diag(New->getLocation(), diag::err_duplicate_member) + << New->getIdentifier(); + Diag(Old->getLocation(), diag::note_previous_declaration); + New->setInvalidDecl(); + } + + MergeDeclAttributes(New, Old, Context); // Merge the types QualType MergedT; @@ -1398,8 +1523,8 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { New->setType(MergedT); // C99 6.2.2p4: Check if we have a static decl followed by a non-static. - if (New->getStorageClass() == VarDecl::Static && - (Old->getStorageClass() == VarDecl::None || Old->hasExternalStorage())) { + if (New->getStorageClass() == SC_Static && + (Old->getStorageClass() == SC_None || Old->hasExternalStorage())) { Diag(New->getLocation(), diag::err_static_non_static) << New->getDeclName(); Diag(Old->getLocation(), diag::note_previous_definition); return New->setInvalidDecl(); @@ -1415,8 +1540,8 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { // identifier has external linkage. if (New->hasExternalStorage() && Old->hasLinkage()) /* Okay */; - else if (New->getStorageClass() != VarDecl::Static && - Old->getStorageClass() == VarDecl::Static) { + else if (New->getStorageClass() != SC_Static && + Old->getStorageClass() == SC_Static) { Diag(New->getLocation(), diag::err_non_static_static) << New->getDeclName(); Diag(Old->getLocation(), diag::note_previous_definition); return New->setInvalidDecl(); @@ -1475,8 +1600,8 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with /// no declarator (e.g. "struct foo;") is parsed. -Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, - DeclSpec &DS) { +Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, + DeclSpec &DS) { // FIXME: Error on auto/register at file scope // FIXME: Error on inline/virtual/explicit // FIXME: Warn on useless __thread @@ -1489,10 +1614,10 @@ Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DS.getTypeSpecType() == DeclSpec::TST_struct || DS.getTypeSpecType() == DeclSpec::TST_union || DS.getTypeSpecType() == DeclSpec::TST_enum) { - TagD = static_cast(DS.getTypeRep()); + TagD = DS.getRepAsDecl(); if (!TagD) // We probably had an error - return DeclPtrTy(); + return 0; // Note that the above type specs guarantee that the // type rep is a Decl, whereas in many of the others @@ -1513,14 +1638,12 @@ Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, // If we're dealing with a class template decl, assume that the // template routines are handling it. if (TagD && isa(TagD)) - return DeclPtrTy(); + return 0; return ActOnFriendTypeDecl(S, DS, MultiTemplateParamsArg(*this, 0, 0)); } if (RecordDecl *Record = dyn_cast_or_null(Tag)) { - // If there are attributes in the DeclSpec, apply them to the record. - if (const AttributeList *AL = DS.getAttributes()) - ProcessDeclAttributeList(S, Record, AL); + ProcessDeclAttributeList(S, Record, DS.getAttributes()); if (!Record->getDeclName() && Record->isDefinition() && DS.getStorageClassSpec() != DeclSpec::SCS_typedef) { @@ -1536,7 +1659,7 @@ Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, // about them. // FIXME: Should we support Microsoft's extensions in this area? if (Record->getDeclName() && getLangOptions().Microsoft) - return DeclPtrTy::make(Tag); + return Tag; } if (getLangOptions().CPlusPlus && @@ -1550,19 +1673,19 @@ Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, if (!DS.isMissingDeclaratorOk() && DS.getTypeSpecType() != DeclSpec::TST_error) { // Warn about typedefs of enums without names, since this is an - // extension in both Microsoft an GNU. + // extension in both Microsoft and GNU. if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef && Tag && isa(Tag)) { Diag(DS.getSourceRange().getBegin(), diag::ext_typedef_without_a_name) << DS.getSourceRange(); - return DeclPtrTy::make(Tag); + return Tag; } Diag(DS.getSourceRange().getBegin(), diag::ext_no_declarators) << DS.getSourceRange(); } - return DeclPtrTy::make(Tag); + return TagD; } /// We are trying to inject an anonymous member into the given scope; @@ -1639,7 +1762,7 @@ static bool InjectAnonymousStructOrUnionMembers(Sema &SemaRef, Scope *S, // considered to have been defined in the scope in which the // anonymous union is declared. Owner->makeDeclVisibleInContext(*F); - S->AddDecl(Sema::DeclPtrTy::make(*F)); + S->AddDecl(*F); SemaRef.IdResolver.AddDecl(*F); // That includes picking up the appropriate access specifier. @@ -1660,58 +1783,38 @@ static bool InjectAnonymousStructOrUnionMembers(Sema &SemaRef, Scope *S, /// StorageClassSpecToVarDeclStorageClass - Maps a DeclSpec::SCS to /// a VarDecl::StorageClass. Any error reporting is up to the caller: -/// illegal input values are mapped to VarDecl::None. -/// If the input declaration context is a linkage specification -/// with no braces, then Extern is mapped to None. -static VarDecl::StorageClass -StorageClassSpecToVarDeclStorageClass(DeclSpec::SCS StorageClassSpec, - DeclContext *DC) { +/// illegal input values are mapped to SC_None. +static StorageClass +StorageClassSpecToVarDeclStorageClass(DeclSpec::SCS StorageClassSpec) { switch (StorageClassSpec) { - case DeclSpec::SCS_unspecified: return VarDecl::None; - case DeclSpec::SCS_extern: - // If the current context is a C++ linkage specification - // having no braces, then the keyword "extern" is properly part - // of the linkage specification itself, rather than being - // the written storage class specifier. - return (DC && isa(DC) && - !cast(DC)->hasBraces()) - ? VarDecl::None : VarDecl::Extern; - case DeclSpec::SCS_static: return VarDecl::Static; - case DeclSpec::SCS_auto: return VarDecl::Auto; - case DeclSpec::SCS_register: return VarDecl::Register; - case DeclSpec::SCS_private_extern: return VarDecl::PrivateExtern; + case DeclSpec::SCS_unspecified: return SC_None; + case DeclSpec::SCS_extern: return SC_Extern; + case DeclSpec::SCS_static: return SC_Static; + case DeclSpec::SCS_auto: return SC_Auto; + case DeclSpec::SCS_register: return SC_Register; + case DeclSpec::SCS_private_extern: return SC_PrivateExtern; // Illegal SCSs map to None: error reporting is up to the caller. case DeclSpec::SCS_mutable: // Fall through. - case DeclSpec::SCS_typedef: return VarDecl::None; + case DeclSpec::SCS_typedef: return SC_None; } llvm_unreachable("unknown storage class specifier"); } /// StorageClassSpecToFunctionDeclStorageClass - Maps a DeclSpec::SCS to -/// a FunctionDecl::StorageClass. Any error reporting is up to the caller: -/// illegal input values are mapped to FunctionDecl::None. -/// If the input declaration context is a linkage specification -/// with no braces, then Extern is mapped to None. -static FunctionDecl::StorageClass -StorageClassSpecToFunctionDeclStorageClass(DeclSpec::SCS StorageClassSpec, - DeclContext *DC) { +/// a StorageClass. Any error reporting is up to the caller: +/// illegal input values are mapped to SC_None. +static StorageClass +StorageClassSpecToFunctionDeclStorageClass(DeclSpec::SCS StorageClassSpec) { switch (StorageClassSpec) { - case DeclSpec::SCS_unspecified: return FunctionDecl::None; - case DeclSpec::SCS_extern: - // If the current context is a C++ linkage specification - // having no braces, then the keyword "extern" is properly part - // of the linkage specification itself, rather than being - // the written storage class specifier. - return (DC && isa(DC) && - !cast(DC)->hasBraces()) - ? FunctionDecl::None : FunctionDecl::Extern; - case DeclSpec::SCS_static: return FunctionDecl::Static; - case DeclSpec::SCS_private_extern: return FunctionDecl::PrivateExtern; + case DeclSpec::SCS_unspecified: return SC_None; + case DeclSpec::SCS_extern: return SC_Extern; + case DeclSpec::SCS_static: return SC_Static; + case DeclSpec::SCS_private_extern: return SC_PrivateExtern; // Illegal SCSs map to None: error reporting is up to the caller. case DeclSpec::SCS_auto: // Fall through. case DeclSpec::SCS_mutable: // Fall through. case DeclSpec::SCS_register: // Fall through. - case DeclSpec::SCS_typedef: return FunctionDecl::None; + case DeclSpec::SCS_typedef: return SC_None; } llvm_unreachable("unknown storage class specifier"); } @@ -1720,9 +1823,9 @@ StorageClassSpecToFunctionDeclStorageClass(DeclSpec::SCS StorageClassSpec, /// anonymous structure or union. Anonymous unions are a C++ feature /// (C++ [class.union]) and a GNU C extension; anonymous structures /// are a GNU C and GNU C++ extension. -Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, - AccessSpecifier AS, - RecordDecl *Record) { +Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, + AccessSpecifier AS, + RecordDecl *Record) { DeclContext *Owner = Record->getDeclContext(); // Diagnose whether this anonymous struct/union is an extension. @@ -1782,6 +1885,9 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, << (int)Record->isUnion() << (int)(FD->getAccess() == AS_protected); Invalid = true; } + + if (CheckNontrivialField(FD)) + Invalid = true; } else if ((*Mem)->isImplicit()) { // Any implicit members are fine. } else if (isa(*Mem) && (*Mem)->getDeclContext() != Record) { @@ -1845,17 +1951,17 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, DeclSpec::SCS SCSpec = DS.getStorageClassSpec(); assert(SCSpec != DeclSpec::SCS_typedef && "Parser allowed 'typedef' as storage class VarDecl."); - VarDecl::StorageClass SC = StorageClassSpecToVarDeclStorageClass(SCSpec, 0); + VarDecl::StorageClass SC = StorageClassSpecToVarDeclStorageClass(SCSpec); if (SCSpec == DeclSpec::SCS_mutable) { // mutable can only appear on non-static class members, so it's always // an error here Diag(Record->getLocation(), diag::err_mutable_nonmember); Invalid = true; - SC = VarDecl::None; + SC = SC_None; } SCSpec = DS.getStorageClassSpecAsWritten(); VarDecl::StorageClass SCAsWritten - = StorageClassSpecToVarDeclStorageClass(SCSpec, 0); + = StorageClassSpecToVarDeclStorageClass(SCSpec); Anon = VarDecl::Create(Context, Owner, Record->getLocation(), /*IdentifierInfo=*/0, @@ -1886,85 +1992,115 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, if (Invalid) Anon->setInvalidDecl(); - return DeclPtrTy::make(Anon); + return Anon; } /// GetNameForDeclarator - Determine the full declaration name for the /// given Declarator. -DeclarationName Sema::GetNameForDeclarator(Declarator &D) { +DeclarationNameInfo Sema::GetNameForDeclarator(Declarator &D) { return GetNameFromUnqualifiedId(D.getName()); } -/// \brief Retrieves the canonicalized name from a parsed unqualified-id. -DeclarationName Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) { - switch (Name.getKind()) { - case UnqualifiedId::IK_Identifier: - return DeclarationName(Name.Identifier); - - case UnqualifiedId::IK_OperatorFunctionId: - return Context.DeclarationNames.getCXXOperatorName( - Name.OperatorFunctionId.Operator); - - case UnqualifiedId::IK_LiteralOperatorId: - return Context.DeclarationNames.getCXXLiteralOperatorName( - Name.Identifier); - - case UnqualifiedId::IK_ConversionFunctionId: { - QualType Ty = GetTypeFromParser(Name.ConversionFunctionId); - if (Ty.isNull()) - return DeclarationName(); - - return Context.DeclarationNames.getCXXConversionFunctionName( - Context.getCanonicalType(Ty)); - } - - case UnqualifiedId::IK_ConstructorName: { - QualType Ty = GetTypeFromParser(Name.ConstructorName); - if (Ty.isNull()) - return DeclarationName(); - - return Context.DeclarationNames.getCXXConstructorName( - Context.getCanonicalType(Ty)); - } - - case UnqualifiedId::IK_ConstructorTemplateId: { - // In well-formed code, we can only have a constructor - // template-id that refers to the current context, so go there - // to find the actual type being constructed. - CXXRecordDecl *CurClass = dyn_cast(CurContext); - if (!CurClass || CurClass->getIdentifier() != Name.TemplateId->Name) - return DeclarationName(); +/// \brief Retrieves the declaration name from a parsed unqualified-id. +DeclarationNameInfo +Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) { + DeclarationNameInfo NameInfo; + NameInfo.setLoc(Name.StartLocation); - // Determine the type of the class being constructed. - QualType CurClassType = Context.getTypeDeclType(CurClass); + switch (Name.getKind()) { - // FIXME: Check two things: that the template-id names the same type as - // CurClassType, and that the template-id does not occur when the name - // was qualified. + case UnqualifiedId::IK_Identifier: + NameInfo.setName(Name.Identifier); + NameInfo.setLoc(Name.StartLocation); + return NameInfo; + + case UnqualifiedId::IK_OperatorFunctionId: + NameInfo.setName(Context.DeclarationNames.getCXXOperatorName( + Name.OperatorFunctionId.Operator)); + NameInfo.setLoc(Name.StartLocation); + NameInfo.getInfo().CXXOperatorName.BeginOpNameLoc + = Name.OperatorFunctionId.SymbolLocations[0]; + NameInfo.getInfo().CXXOperatorName.EndOpNameLoc + = Name.EndLocation.getRawEncoding(); + return NameInfo; + + case UnqualifiedId::IK_LiteralOperatorId: + NameInfo.setName(Context.DeclarationNames.getCXXLiteralOperatorName( + Name.Identifier)); + NameInfo.setLoc(Name.StartLocation); + NameInfo.setCXXLiteralOperatorNameLoc(Name.EndLocation); + return NameInfo; + + case UnqualifiedId::IK_ConversionFunctionId: { + TypeSourceInfo *TInfo; + QualType Ty = GetTypeFromParser(Name.ConversionFunctionId, &TInfo); + if (Ty.isNull()) + return DeclarationNameInfo(); + NameInfo.setName(Context.DeclarationNames.getCXXConversionFunctionName( + Context.getCanonicalType(Ty))); + NameInfo.setLoc(Name.StartLocation); + NameInfo.setNamedTypeInfo(TInfo); + return NameInfo; + } + + case UnqualifiedId::IK_ConstructorName: { + TypeSourceInfo *TInfo; + QualType Ty = GetTypeFromParser(Name.ConstructorName, &TInfo); + if (Ty.isNull()) + return DeclarationNameInfo(); + NameInfo.setName(Context.DeclarationNames.getCXXConstructorName( + Context.getCanonicalType(Ty))); + NameInfo.setLoc(Name.StartLocation); + NameInfo.setNamedTypeInfo(TInfo); + return NameInfo; + } + + case UnqualifiedId::IK_ConstructorTemplateId: { + // In well-formed code, we can only have a constructor + // template-id that refers to the current context, so go there + // to find the actual type being constructed. + CXXRecordDecl *CurClass = dyn_cast(CurContext); + if (!CurClass || CurClass->getIdentifier() != Name.TemplateId->Name) + return DeclarationNameInfo(); + + // Determine the type of the class being constructed. + QualType CurClassType = Context.getTypeDeclType(CurClass); + + // FIXME: Check two things: that the template-id names the same type as + // CurClassType, and that the template-id does not occur when the name + // was qualified. + + NameInfo.setName(Context.DeclarationNames.getCXXConstructorName( + Context.getCanonicalType(CurClassType))); + NameInfo.setLoc(Name.StartLocation); + // FIXME: should we retrieve TypeSourceInfo? + NameInfo.setNamedTypeInfo(0); + return NameInfo; + } + + case UnqualifiedId::IK_DestructorName: { + TypeSourceInfo *TInfo; + QualType Ty = GetTypeFromParser(Name.DestructorName, &TInfo); + if (Ty.isNull()) + return DeclarationNameInfo(); + NameInfo.setName(Context.DeclarationNames.getCXXDestructorName( + Context.getCanonicalType(Ty))); + NameInfo.setLoc(Name.StartLocation); + NameInfo.setNamedTypeInfo(TInfo); + return NameInfo; + } + + case UnqualifiedId::IK_TemplateId: { + TemplateName TName = Name.TemplateId->Template.get(); + SourceLocation TNameLoc = Name.TemplateId->TemplateNameLoc; + return Context.getNameForTemplate(TName, TNameLoc); + } + + } // switch (Name.getKind()) - return Context.DeclarationNames.getCXXConstructorName( - Context.getCanonicalType(CurClassType)); - } - - case UnqualifiedId::IK_DestructorName: { - QualType Ty = GetTypeFromParser(Name.DestructorName); - if (Ty.isNull()) - return DeclarationName(); - - return Context.DeclarationNames.getCXXDestructorName( - Context.getCanonicalType(Ty)); - } - - case UnqualifiedId::IK_TemplateId: { - TemplateName TName - = TemplateName::getFromVoidPointer(Name.TemplateId->Template); - return Context.getNameForTemplate(TName); - } - } - assert(false && "Unknown name kind"); - return DeclarationName(); + return DeclarationNameInfo(); } /// isNearlyMatchingFunction - Determine whether the C++ functions @@ -2007,11 +2143,10 @@ static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D, switch (DS.getTypeSpecType()) { case DeclSpec::TST_typename: case DeclSpec::TST_typeofType: - case DeclSpec::TST_typeofExpr: case DeclSpec::TST_decltype: { // Grab the type from the parser. TypeSourceInfo *TSI = 0; - QualType T = S.GetTypeFromParser(DS.getTypeRep(), &TSI); + QualType T = S.GetTypeFromParser(DS.getRepAsType(), &TSI); if (T.isNull() || !T->isDependentType()) break; // Make sure there's a type source info. This isn't really much @@ -2025,8 +2160,16 @@ static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D, if (!TSI) return true; // Store the new type back in the decl spec. - QualType LocType = S.CreateLocInfoType(TSI->getType(), TSI); - DS.UpdateTypeRep(LocType.getAsOpaquePtr()); + ParsedType LocType = S.CreateParsedType(TSI->getType(), TSI); + DS.UpdateTypeRep(LocType); + break; + } + + case DeclSpec::TST_typeofExpr: { + Expr *E = DS.getRepAsExpr(); + ExprResult Result = S.RebuildExprInCurrentInstantiation(E); + if (Result.isInvalid()) return true; + DS.UpdateExprRep(Result.get()); break; } @@ -2054,11 +2197,16 @@ static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D, return false; } -Sema::DeclPtrTy -Sema::HandleDeclarator(Scope *S, Declarator &D, - MultiTemplateParamsArg TemplateParamLists, - bool IsFunctionDefinition) { - DeclarationName Name = GetNameForDeclarator(D); +Decl *Sema::ActOnDeclarator(Scope *S, Declarator &D) { + return HandleDeclarator(S, D, MultiTemplateParamsArg(*this), false); +} + +Decl *Sema::HandleDeclarator(Scope *S, Declarator &D, + MultiTemplateParamsArg TemplateParamLists, + bool IsFunctionDefinition) { + // TODO: consider using NameInfo for diagnostic. + DeclarationNameInfo NameInfo = GetNameForDeclarator(D); + DeclarationName Name = NameInfo.getName(); // All of these full declarators require an identifier. If it doesn't have // one, the ParsedFreeStandingDeclSpec action should be used. @@ -2067,7 +2215,7 @@ Sema::HandleDeclarator(Scope *S, Declarator &D, Diag(D.getDeclSpec().getSourceRange().getBegin(), diag::err_declarator_need_ident) << D.getDeclSpec().getSourceRange() << D.getSourceRange(); - return DeclPtrTy(); + return 0; } // The scope passed in may not be a decl scope. Zip up the scope tree until @@ -2091,14 +2239,14 @@ Sema::HandleDeclarator(Scope *S, Declarator &D, diag::err_template_qualified_declarator_no_match) << (NestedNameSpecifier*)D.getCXXScopeSpec().getScopeRep() << D.getCXXScopeSpec().getRange(); - return DeclPtrTy(); + return 0; } bool IsDependentContext = DC->isDependentContext(); if (!IsDependentContext && RequireCompleteDeclContext(D.getCXXScopeSpec(), DC)) - return DeclPtrTy(); + return 0; if (isa(DC) && !cast(DC)->hasDefinition()) { Diag(D.getIdentifierLoc(), @@ -2122,7 +2270,7 @@ Sema::HandleDeclarator(Scope *S, Declarator &D, TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); QualType R = TInfo->getType(); - LookupResult Previous(*this, Name, D.getIdentifierLoc(), LookupOrdinaryName, + LookupResult Previous(*this, NameInfo, LookupOrdinaryName, ForRedeclaration); // See if this is a redefinition of a variable in the same scope. @@ -2140,7 +2288,7 @@ Sema::HandleDeclarator(Scope *S, Declarator &D, IsLinkageLookup = true; } else if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_extern) IsLinkageLookup = true; - else if (CurContext->getLookupContext()->isTranslationUnit() && + else if (CurContext->getRedeclContext()->isTranslationUnit() && D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static) IsLinkageLookup = true; @@ -2225,7 +2373,7 @@ Sema::HandleDeclarator(Scope *S, Declarator &D, if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) { if (TemplateParamLists.size()) { Diag(D.getIdentifierLoc(), diag::err_template_typedef); - return DeclPtrTy(); + return 0; } New = ActOnTypedefDeclarator(S, D, DC, R, TInfo, Previous, Redeclaration); @@ -2240,14 +2388,14 @@ Sema::HandleDeclarator(Scope *S, Declarator &D, } if (New == 0) - return DeclPtrTy(); + return 0; // If this has an identifier and is not an invalid redeclaration or // function template specialization, add it to the scope stack. - if (Name && !(Redeclaration && New->isInvalidDecl())) + if (New->getDeclName() && !(Redeclaration && New->isInvalidDecl())) PushOnScopeChains(New, S); - return DeclPtrTy::make(New); + return New; } /// TryToFixInvalidVariablyModifiedType - Helper method to turn variable array @@ -2255,20 +2403,26 @@ Sema::HandleDeclarator(Scope *S, Declarator &D, /// be errors (for GCC compatibility). static QualType TryToFixInvalidVariablyModifiedType(QualType T, ASTContext &Context, - bool &SizeIsNegative) { + bool &SizeIsNegative, + llvm::APSInt &Oversized) { // This method tries to turn a variable array into a constant // array even when the size isn't an ICE. This is necessary // for compatibility with code that depends on gcc's buggy // constant expression folding, like struct {char x[(int)(char*)2];} SizeIsNegative = false; - + Oversized = 0; + + if (T->isDependentType()) + return QualType(); + QualifierCollector Qs; const Type *Ty = Qs.strip(T); if (const PointerType* PTy = dyn_cast(Ty)) { QualType Pointee = PTy->getPointeeType(); QualType FixedType = - TryToFixInvalidVariablyModifiedType(Pointee, Context, SizeIsNegative); + TryToFixInvalidVariablyModifiedType(Pointee, Context, SizeIsNegative, + Oversized); if (FixedType.isNull()) return FixedType; FixedType = Context.getPointerType(FixedType); return Qs.apply(FixedType); @@ -2287,15 +2441,24 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T, !EvalResult.Val.isInt()) return QualType(); + // Check whether the array size is negative. llvm::APSInt &Res = EvalResult.Val.getInt(); - if (Res >= llvm::APSInt(Res.getBitWidth(), Res.isUnsigned())) { - // TODO: preserve the size expression in declarator info - return Context.getConstantArrayType(VLATy->getElementType(), - Res, ArrayType::Normal, 0); + if (Res.isSigned() && Res.isNegative()) { + SizeIsNegative = true; + return QualType(); } - SizeIsNegative = true; - return QualType(); + // Check whether the array is too large to be addressed. + unsigned ActiveSizeBits + = ConstantArrayType::getNumAddressingBits(Context, VLATy->getElementType(), + Res); + if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) { + Oversized = Res; + return QualType(); + } + + return Context.getConstantArrayType(VLATy->getElementType(), + Res, ArrayType::Normal, 0); } /// \brief Register the given locally-scoped external C declaration so @@ -2320,11 +2483,11 @@ Sema::RegisterLocallyScopedExternCDecl(NamedDecl *ND, if (S && IdResolver.ReplaceDecl(PrevDecl, ND)) { // The previous declaration was found on the identifer resolver // chain, so remove it from its scope. - while (S && !S->isDeclScope(DeclPtrTy::make(PrevDecl))) + while (S && !S->isDeclScope(PrevDecl)) S = S->getParent(); if (S) - S->RemoveDecl(DeclPtrTy::make(PrevDecl)); + S->RemoveDecl(PrevDecl); } } @@ -2382,24 +2545,20 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, // Handle attributes prior to checking for duplicates in MergeVarDecl ProcessDeclAttributes(S, NewTD, D); - // Merge the decl with the existing one if appropriate. If the decl is - // in an outer scope, it isn't the same thing. - FilterLookupForScope(*this, Previous, DC, S, /*ConsiderLinkage*/ false); - if (!Previous.empty()) { - Redeclaration = true; - MergeTypeDefDecl(NewTD, Previous); - } - // C99 6.7.7p2: If a typedef name specifies a variably modified type // then it shall have block scope. + // Note that variably modified types must be fixed before merging the decl so + // that redeclarations will match. QualType T = NewTD->getUnderlyingType(); if (T->isVariablyModifiedType()) { - FunctionNeedsScopeChecking() = true; + getCurFunction()->setHasBranchProtectedScope(); if (S->getFnParent() == 0) { bool SizeIsNegative; + llvm::APSInt Oversized; QualType FixedTy = - TryToFixInvalidVariablyModifiedType(T, Context, SizeIsNegative); + TryToFixInvalidVariablyModifiedType(T, Context, SizeIsNegative, + Oversized); if (!FixedTy.isNull()) { Diag(D.getIdentifierLoc(), diag::warn_illegal_constant_array_size); NewTD->setTypeSourceInfo(Context.getTrivialTypeSourceInfo(FixedTy)); @@ -2408,6 +2567,9 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, Diag(D.getIdentifierLoc(), diag::err_typecheck_negative_array_size); else if (T->isVariableArrayType()) Diag(D.getIdentifierLoc(), diag::err_vla_decl_in_file_scope); + else if (Oversized.getBoolValue()) + Diag(D.getIdentifierLoc(), diag::err_array_too_large) + << Oversized.toString(10); else Diag(D.getIdentifierLoc(), diag::err_vm_decl_in_file_scope); NewTD->setInvalidDecl(); @@ -2415,10 +2577,18 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, } } + // Merge the decl with the existing one if appropriate. If the decl is + // in an outer scope, it isn't the same thing. + FilterLookupForScope(*this, Previous, DC, S, /*ConsiderLinkage*/ false); + if (!Previous.empty()) { + Redeclaration = true; + MergeTypeDefDecl(NewTD, Previous); + } + // If this is the C FILE type, notify the AST context. if (IdentifierInfo *II = NewTD->getIdentifier()) if (!NewTD->isInvalidDecl() && - NewTD->getDeclContext()->getLookupContext()->isTranslationUnit()) { + NewTD->getDeclContext()->getRedeclContext()->isTranslationUnit()) { if (II->isStr("FILE")) Context.setFILEDecl(NewTD); else if (II->isStr("jmp_buf")) @@ -2452,7 +2622,7 @@ static bool isOutOfScopePreviousDeclaration(NamedDecl *PrevDecl, DeclContext *DC, ASTContext &Context) { if (!PrevDecl) - return 0; + return false; if (!PrevDecl->hasLinkage()) return false; @@ -2464,30 +2634,25 @@ isOutOfScopePreviousDeclaration(NamedDecl *PrevDecl, DeclContext *DC, // outside the innermost enclosing namespace scope, the block // scope declaration declares that same entity and receives the // linkage of the previous declaration. - DeclContext *OuterContext = DC->getLookupContext(); + DeclContext *OuterContext = DC->getRedeclContext(); if (!OuterContext->isFunctionOrMethod()) // This rule only applies to block-scope declarations. return false; - else { - DeclContext *PrevOuterContext = PrevDecl->getDeclContext(); - if (PrevOuterContext->isRecord()) - // We found a member function: ignore it. - return false; - else { - // Find the innermost enclosing namespace for the new and - // previous declarations. - while (!OuterContext->isFileContext()) - OuterContext = OuterContext->getParent(); - while (!PrevOuterContext->isFileContext()) - PrevOuterContext = PrevOuterContext->getParent(); - - // The previous declaration is in a different namespace, so it - // isn't the same function. - if (OuterContext->getPrimaryContext() != - PrevOuterContext->getPrimaryContext()) - return false; - } - } + + DeclContext *PrevOuterContext = PrevDecl->getDeclContext(); + if (PrevOuterContext->isRecord()) + // We found a member function: ignore it. + return false; + + // Find the innermost enclosing namespace for the new and + // previous declarations. + OuterContext = OuterContext->getEnclosingNamespaceContext(); + PrevOuterContext = PrevOuterContext->getEnclosingNamespaceContext(); + + // The previous declaration is in a different namespace, so it + // isn't the same function. + if (!OuterContext->Equals(PrevOuterContext)) + return false; } return true; @@ -2506,7 +2671,7 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, LookupResult &Previous, MultiTemplateParamsArg TemplateParamLists, bool &Redeclaration) { - DeclarationName Name = GetNameForDeclarator(D); + DeclarationName Name = GetNameForDeclarator(D).getName(); // Check that there are no default arguments (C++ only). if (getLangOptions().CPlusPlus) @@ -2515,17 +2680,17 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpec(); assert(SCSpec != DeclSpec::SCS_typedef && "Parser allowed 'typedef' as storage class VarDecl."); - VarDecl::StorageClass SC = StorageClassSpecToVarDeclStorageClass(SCSpec, 0); + VarDecl::StorageClass SC = StorageClassSpecToVarDeclStorageClass(SCSpec); if (SCSpec == DeclSpec::SCS_mutable) { // mutable can only appear on non-static class members, so it's always // an error here Diag(D.getIdentifierLoc(), diag::err_mutable_nonmember); D.setInvalidType(); - SC = VarDecl::None; + SC = SC_None; } SCSpec = D.getDeclSpec().getStorageClassSpecAsWritten(); VarDecl::StorageClass SCAsWritten - = StorageClassSpecToVarDeclStorageClass(SCSpec, DC); + = StorageClassSpecToVarDeclStorageClass(SCSpec); IdentifierInfo *II = Name.getAsIdentifierInfo(); if (!II) { @@ -2539,11 +2704,11 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, if (!DC->isRecord() && S->getFnParent() == 0) { // C99 6.9p2: The storage-class specifiers auto and register shall not // appear in the declaration specifiers in an external declaration. - if (SC == VarDecl::Auto || SC == VarDecl::Register) { + if (SC == SC_Auto || SC == SC_Register) { // If this is a register variable with an asm label specified, then this // is a GNU extension. - if (SC == VarDecl::Register && D.getAsmLabel()) + if (SC == SC_Register && D.getAsmLabel()) Diag(D.getIdentifierLoc(), diag::err_unsupported_global_register); else Diag(D.getIdentifierLoc(), diag::err_typecheck_sclass_fscope); @@ -2552,14 +2717,14 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, } if (DC->isRecord() && !CurContext->isRecord()) { // This is an out-of-line definition of a static data member. - if (SC == VarDecl::Static) { + if (SC == SC_Static) { Diag(D.getDeclSpec().getStorageClassSpecLoc(), diag::err_static_out_of_line) << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc()); - } else if (SC == VarDecl::None) - SC = VarDecl::Static; + } else if (SC == SC_None) + SC = SC_Static; } - if (SC == VarDecl::Static) { + if (SC == SC_Static) { if (const CXXRecordDecl *RD = dyn_cast(DC)) { if (RD->isLocalClass()) Diag(D.getIdentifierLoc(), @@ -2613,7 +2778,7 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, SetNestedNameSpecifier(NewVD, D); - if (NumMatchedTemplateParamLists > 0) { + if (NumMatchedTemplateParamLists > 0 && D.getCXXScopeSpec().isSet()) { NewVD->setTemplateParameterListsInfo(Context, NumMatchedTemplateParamLists, (TemplateParameterList**)TemplateParamLists.release()); @@ -2639,7 +2804,8 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, if (Expr *E = (Expr*) D.getAsmLabel()) { // The parser guarantees this is a string. StringLiteral *SE = cast(E); - NewVD->addAttr(::new (Context) AsmLabelAttr(Context, SE->getString())); + NewVD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0), + Context, SE->getString())); } // Diagnose shadowed variables before filtering for scope. @@ -2679,6 +2845,8 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, NewVD->setInvalidDecl(); // attributes declared post-definition are currently ignored + // FIXME: This should be handled in attribute merging, not + // here. if (Previous.isSingleResult()) { VarDecl *Def = dyn_cast(Previous.getFoundDecl()); if (Def && (Def = Def->getDefinition()) && @@ -2694,6 +2862,13 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, !NewVD->isInvalidDecl()) RegisterLocallyScopedExternCDecl(NewVD, Previous, S); + // If there's a #pragma GCC visibility in scope, and this isn't a class + // member, set the visibility of this variable. + if (NewVD->getLinkage() == ExternalLinkage && !DC->isRecord()) + AddPushedVisibilityAttribute(NewVD); + + MarkUnusedFileScopedDecl(NewVD); + return NewVD; } @@ -2807,19 +2982,16 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD, bool isVM = T->isVariablyModifiedType(); if (isVM || NewVD->hasAttr() || - NewVD->hasAttr() || - // FIXME: We need to diagnose jumps passed initialized variables in C++. - // However, this turns on the scope checker for everything with a variable - // which may impact compile time. See if we can find a better solution - // to this, perhaps only checking functions that contain gotos in C++? - (LangOpts.CPlusPlus && NewVD->hasLocalStorage())) - FunctionNeedsScopeChecking() = true; + NewVD->hasAttr()) + getCurFunction()->setHasBranchProtectedScope(); if ((isVM && NewVD->hasLinkage()) || (T->isVariableArrayType() && NewVD->hasGlobalStorage())) { bool SizeIsNegative; + llvm::APSInt Oversized; QualType FixedTy = - TryToFixInvalidVariablyModifiedType(T, Context, SizeIsNegative); + TryToFixInvalidVariablyModifiedType(T, Context, SizeIsNegative, + Oversized); if (FixedTy.isNull() && T->isVariableArrayType()) { const VariableArrayType *VAT = Context.getAsVariableArrayType(T); @@ -2830,7 +3002,7 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD, if (NewVD->isFileVarDecl()) Diag(NewVD->getLocation(), diag::err_vla_decl_in_file_scope) << SizeRange; - else if (NewVD->getStorageClass() == VarDecl::Static) + else if (NewVD->getStorageClass() == SC_Static) Diag(NewVD->getLocation(), diag::err_vla_decl_has_static_storage) << SizeRange; else @@ -2970,8 +3142,10 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, bool IsFunctionDefinition, bool &Redeclaration) { assert(R.getTypePtr()->isFunctionType()); - DeclarationName Name = GetNameForDeclarator(D); - FunctionDecl::StorageClass SC = FunctionDecl::None; + // TODO: consider using NameInfo for diagnostic. + DeclarationNameInfo NameInfo = GetNameForDeclarator(D); + DeclarationName Name = NameInfo.getName(); + FunctionDecl::StorageClass SC = SC_None; switch (D.getDeclSpec().getStorageClassSpec()) { default: assert(0 && "Unknown storage class!"); case DeclSpec::SCS_auto: @@ -2981,10 +3155,10 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, diag::err_typecheck_sclass_func); D.setInvalidType(); break; - case DeclSpec::SCS_unspecified: SC = FunctionDecl::None; break; - case DeclSpec::SCS_extern: SC = FunctionDecl::Extern; break; + case DeclSpec::SCS_unspecified: SC = SC_None; break; + case DeclSpec::SCS_extern: SC = SC_Extern; break; case DeclSpec::SCS_static: { - if (CurContext->getLookupContext()->isFunctionOrMethod()) { + if (CurContext->getRedeclContext()->isFunctionOrMethod()) { // C99 6.7.1p5: // The declaration of an identifier for a function that has // block scope shall have no explicit storage-class specifier @@ -2992,12 +3166,12 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // See also (C++ [dcl.stc]p4). Diag(D.getDeclSpec().getStorageClassSpecLoc(), diag::err_static_block_func); - SC = FunctionDecl::None; + SC = SC_None; } else - SC = FunctionDecl::Static; + SC = SC_Static; break; } - case DeclSpec::SCS_private_extern: SC = FunctionDecl::PrivateExtern;break; + case DeclSpec::SCS_private_extern: SC = SC_PrivateExtern;break; } if (D.getDeclSpec().isThreadSpecified()) @@ -3010,7 +3184,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpecAsWritten(); FunctionDecl::StorageClass SCAsWritten - = StorageClassSpecToFunctionDeclStorageClass(SCSpec, DC); + = StorageClassSpecToFunctionDeclStorageClass(SCSpec); // Check that the return type is not an abstract class type. // For record types, this is done by the AbstractClassUsageDiagnoser once @@ -3050,7 +3224,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // Create the new declaration NewFD = CXXConstructorDecl::Create(Context, cast(DC), - D.getIdentifierLoc(), Name, R, TInfo, + NameInfo, R, TInfo, isExplicit, isInline, /*isImplicitlyDeclared=*/false); } else if (Name.getNameKind() == DeclarationName::CXXDestructorName) { @@ -3060,7 +3234,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, NewFD = CXXDestructorDecl::Create(Context, cast(DC), - D.getIdentifierLoc(), Name, R, + NameInfo, R, isInline, /*isImplicitlyDeclared=*/false); NewFD->setTypeSourceInfo(TInfo); @@ -3085,7 +3259,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, CheckConversionDeclarator(D, R, SC); NewFD = CXXConversionDecl::Create(Context, cast(DC), - D.getIdentifierLoc(), Name, R, TInfo, + NameInfo, R, TInfo, isInline, isExplicit); isVirtualOkay = true; @@ -3103,7 +3277,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, return 0; } - bool isStatic = SC == FunctionDecl::Static; + bool isStatic = SC == SC_Static; // [class.free]p1: // Any allocation function for a class T is a static member @@ -3120,7 +3294,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // This is a C++ method declaration. NewFD = CXXMethodDecl::Create(Context, cast(DC), - D.getIdentifierLoc(), Name, R, TInfo, + NameInfo, R, TInfo, isStatic, SCAsWritten, isInline); isVirtualOkay = !isStatic; @@ -3137,8 +3311,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, (!isa(R.getTypePtr()) && R->isFunctionProtoType()); NewFD = FunctionDecl::Create(Context, DC, - D.getIdentifierLoc(), - Name, R, TInfo, SC, SCAsWritten, isInline, + NameInfo, R, TInfo, SC, SCAsWritten, isInline, HasPrototype); } @@ -3212,7 +3385,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, } } - if (NumMatchedTemplateParamLists > 0) { + if (NumMatchedTemplateParamLists > 0 && D.getCXXScopeSpec().isSet()) { NewFD->setTemplateParameterListsInfo(Context, NumMatchedTemplateParamLists, (TemplateParameterList**)TemplateParamLists.release()); @@ -3244,6 +3417,17 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, } } + // C++ [dcl.fct.spec]p3: + // The inline specifier shall not appear on a block scope function declaration. + if (isInline && !NewFD->isInvalidDecl() && getLangOptions().CPlusPlus) { + if (CurContext->isFunctionOrMethod()) { + // 'inline' is not allowed on block scope function declaration. + Diag(D.getDeclSpec().getInlineSpecLoc(), + diag::err_inline_declaration_block_scope) << Name + << FixItHint::CreateRemoval(D.getDeclSpec().getInlineSpecLoc()); + } + } + // C++ [dcl.fct.spec]p6: // The explicit specifier shall be used only in the declaration of a // constructor or conversion function within its class definition; see 12.3.1 @@ -3282,7 +3466,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, NewFD->setAccess(AS_public); } - if (SC == FunctionDecl::Static && isa(NewFD) && + if (SC == SC_Static && isa(NewFD) && !CurContext->isRecord()) { // C++ [class.static]p1: // A data or function member of a class may be declared static @@ -3300,7 +3484,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, if (Expr *E = (Expr*) D.getAsmLabel()) { // The parser guarantees this is a string. StringLiteral *SE = cast(E); - NewFD->addAttr(::new (Context) AsmLabelAttr(Context, SE->getString())); + NewFD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0), Context, + SE->getString())); } // Copy the parameter declarations from the declarator D to the function @@ -3316,9 +3501,9 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // already checks for that case. if (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 && FTI.ArgInfo[0].Param && - FTI.ArgInfo[0].Param.getAs()->getType()->isVoidType()) { + cast(FTI.ArgInfo[0].Param)->getType()->isVoidType()) { // Empty arg list, don't push any params. - ParmVarDecl *Param = FTI.ArgInfo[0].Param.getAs(); + ParmVarDecl *Param = cast(FTI.ArgInfo[0].Param); // In C++, the empty parameter-type-list must be spelled "void"; a // typedef of void is not permitted. @@ -3328,7 +3513,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // FIXME: Leaks decl? } else if (FTI.NumArgs > 0 && FTI.ArgInfo[0].Param != 0) { for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) { - ParmVarDecl *Param = FTI.ArgInfo[i].Param.getAs(); + ParmVarDecl *Param = cast(FTI.ArgInfo[i].Param); assert(Param->getDeclContext() != NewFD && "Was set before ?"); Param->setDeclContext(NewFD); Params.push_back(Param); @@ -3479,14 +3664,14 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // definition (C++ [dcl.meaning]p1). // Note that this is not the case for explicit specializations of // function templates or member functions of class templates, per - // C++ [temp.expl.spec]p2. + // C++ [temp.expl.spec]p2. We also allow these declarations as an extension + // for compatibility with old SWIG code which likes to generate them. if (!IsFunctionDefinition && !isFriend && !isFunctionTemplateSpecialization && !isExplicitSpecialization) { - Diag(NewFD->getLocation(), diag::err_out_of_line_declaration) + Diag(NewFD->getLocation(), diag::ext_out_of_line_declaration) << D.getCXXScopeSpec().getRange(); - NewFD->setInvalidDecl(); - } else if (!Redeclaration && - !(isFriend && CurContext->isDependentContext())) { + } + if (!Redeclaration && !(isFriend && CurContext->isDependentContext())) { // The user tried to provide an out-of-line definition for a // function that is a member of a class or namespace, but there // was no such member function declared (C++ [class.mfct]p2, @@ -3526,6 +3711,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, ProcessDeclAttributes(S, NewFD, D); // attributes declared post-definition are currently ignored + // FIXME: This should happen during attribute merging if (Redeclaration && Previous.isSingleResult()) { const FunctionDecl *Def; FunctionDecl *PrevFD = dyn_cast(Previous.getFoundDecl()); @@ -3537,7 +3723,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, AddKnownFunctionAttributes(NewFD); - if (OverloadableAttrRequired && !NewFD->getAttr()) { + if (OverloadableAttrRequired && !NewFD->hasAttr()) { // If a function name is overloadable in C, then every function // with that name must be marked "overloadable". Diag(NewFD->getLocation(), diag::err_attribute_overloadable_missing) @@ -3545,9 +3731,28 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, if (!Previous.empty()) Diag(Previous.getRepresentativeDecl()->getLocation(), diag::note_attribute_overloadable_prev_overload); - NewFD->addAttr(::new (Context) OverloadableAttr()); + NewFD->addAttr(::new (Context) OverloadableAttr(SourceLocation(), Context)); + } + + if (NewFD->hasAttr() && + !NewFD->getType()->getAs()) { + Diag(NewFD->getLocation(), + diag::err_attribute_overloadable_no_prototype) + << NewFD; + + // Turn this into a variadic function with no parameters. + const FunctionType *FT = NewFD->getType()->getAs(); + QualType R = Context.getFunctionType(FT->getResultType(), + 0, 0, true, 0, false, false, 0, 0, + FT->getExtInfo()); + NewFD->setType(R); } + // If there's a #pragma GCC visibility in scope, and this isn't a class + // member, set the visibility of this function. + if (NewFD->getLinkage() == ExternalLinkage && !DC->isRecord()) + AddPushedVisibilityAttribute(NewFD); + // If this is a locally-scoped extern C function, update the // map of such names. if (CurContext->isFunctionOrMethod() && NewFD->isExternC() @@ -3563,17 +3768,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, if (FunctionTemplate) return FunctionTemplate; - - // Keep track of static, non-inlined function definitions that - // have not been used. We will warn later. - // FIXME: Also include static functions declared but not defined. - if (!NewFD->isInvalidDecl() && IsFunctionDefinition - && !NewFD->isInlined() && NewFD->getLinkage() == InternalLinkage - && !NewFD->isUsed() && !NewFD->hasAttr() - && !NewFD->hasAttr() - && !NewFD->hasAttr()) - UnusedStaticFuncs.push_back(NewFD); - + MarkUnusedFileScopedDecl(NewFD); + return NewFD; } @@ -3597,8 +3793,14 @@ void Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, bool &Redeclaration, bool &OverloadableAttrRequired) { // If NewFD is already known erroneous, don't do any of this checking. - if (NewFD->isInvalidDecl()) + if (NewFD->isInvalidDecl()) { + // If this is a class member, mark the class invalid immediately. + // This avoids some consistency errors later. + if (isa(NewFD)) + cast(NewFD)->getParent()->setInvalidDecl(); + return; + } if (NewFD->getResultType()->isVariablyModifiedType()) { // Functions returning a variably modified type violate C99 6.7.5.2p2 @@ -3634,27 +3836,9 @@ void Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, Redeclaration = true; OldDecl = Previous.getFoundDecl(); } else { - if (!getLangOptions().CPlusPlus) { + if (!getLangOptions().CPlusPlus) OverloadableAttrRequired = true; - // Functions marked "overloadable" must have a prototype (that - // we can't get through declaration merging). - if (!NewFD->getType()->getAs()) { - Diag(NewFD->getLocation(), - diag::err_attribute_overloadable_no_prototype) - << NewFD; - Redeclaration = true; - - // Turn this into a variadic function with no parameters. - QualType R = Context.getFunctionType( - NewFD->getType()->getAs()->getResultType(), - 0, 0, true, 0, false, false, 0, 0, - FunctionType::ExtInfo()); - NewFD->setType(R); - return NewFD->setInvalidDecl(); - } - } - switch (CheckOverload(S, NewFD, Previous, OldDecl, /*NewIsUsingDecl*/ false)) { case Ovl_Match: @@ -3723,6 +3907,8 @@ void Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, DeclarationName Name = Context.DeclarationNames.getCXXDestructorName( Context.getCanonicalType(ClassType)); +// NewFD->getDeclName().dump(); +// Name.dump(); if (NewFD->getDeclName() != Name) { Diag(NewFD->getLocation(), diag::err_destructor_name); return NewFD->setInvalidDecl(); @@ -3750,12 +3936,6 @@ void Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, AddOverriddenMethods(Method->getParent(), Method); } - // Additional checks for the destructor; make sure we do this after we - // figure out whether the destructor is virtual. - if (CXXDestructorDecl *Destructor = dyn_cast(NewFD)) - if (!Destructor->getParent()->isDependentType()) - CheckDestructor(Destructor); - // Extra checking for C++ overloaded operators (C++ [over.oper]). if (NewFD->isOverloadedOperator() && CheckOverloadedOperatorDeclaration(NewFD)) @@ -3781,7 +3961,7 @@ void Sema::CheckMain(FunctionDecl* FD) { // shall not appear in a declaration of main. // static main is not an error under C99, but we should warn about it. bool isInline = FD->isInlineSpecified(); - bool isStatic = FD->getStorageClass() == FunctionDecl::Static; + bool isStatic = FD->getStorageClass() == SC_Static; if (isInline || isStatic) { unsigned diagID = diag::warn_unusual_main_decl; if (isInline || getLangOptions().CPlusPlus) @@ -3874,22 +4054,21 @@ bool Sema::CheckForConstantInitializer(Expr *Init, QualType DclT) { // "may accept other forms of constant expressions" exception. // (We never end up here for C++, so the constant expression // rules there don't matter.) - if (Init->isConstantInitializer(Context)) + if (Init->isConstantInitializer(Context, false)) return false; Diag(Init->getExprLoc(), diag::err_init_element_not_constant) << Init->getSourceRange(); return true; } -void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init) { - AddInitializerToDecl(dcl, move(init), /*DirectInit=*/false); +void Sema::AddInitializerToDecl(Decl *dcl, Expr *init) { + AddInitializerToDecl(dcl, init, /*DirectInit=*/false); } /// AddInitializerToDecl - Adds the initializer Init to the /// declaration dcl. If DirectInit is true, this is C++ direct /// initialization rather than copy initialization. -void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) { - Decl *RealDecl = dcl.getAs(); +void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { // If there is no declaration, there was an error parsing it. Just ignore // the initializer. if (RealDecl == 0) @@ -3900,7 +4079,6 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) { // distinguish between a normal initializer and a pure-specifier. // Thus this grotesque test. IntegerLiteral *IL; - Expr *Init = static_cast(init.get()); if ((IL = dyn_cast(Init)) && IL->getValue() == 0 && Context.getCanonicalType(IL->getType()) == Context.IntTy) CheckPureMethod(Method, Init->getSourceRange()); @@ -3925,6 +4103,8 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) { return; } + + // A definition must end up with a complete type, which means it must be // complete with the restriction that an array type might be completed by the // initializer; note that later code assumes this restriction. @@ -3951,11 +4131,28 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) { VDecl->setInvalidDecl(); return; } + + // C++ [class.static.data]p4 + // If a static data member is of const integral or const + // enumeration type, its declaration in the class definition can + // specify a constant-initializer which shall be an integral + // constant expression (5.19). In that case, the member can appear + // in integral constant expressions. The member shall still be + // defined in a namespace scope if it is used in the program and the + // namespace scope definition shall not contain an initializer. + // + // We already performed a redefinition check above, but for static + // data members we also need to check whether there was an in-class + // declaration with an initializer. + const VarDecl* PrevInit = 0; + if (VDecl->isStaticDataMember() && VDecl->getAnyInitializer(PrevInit)) { + Diag(VDecl->getLocation(), diag::err_redefinition) << VDecl->getDeclName(); + Diag(PrevInit->getLocation(), diag::note_previous_definition); + return; + } - // Take ownership of the expression, now that we're sure we have somewhere - // to put it. - Expr *Init = init.takeAs(); - assert(Init && "missing initializer"); + if (getLangOptions().CPlusPlus && VDecl->hasLocalStorage()) + getCurFunction()->setHasBranchProtectedScope(); // Capture the variable that is being initialized and the style of // initialization. @@ -3978,8 +4175,8 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) { VDecl->setInvalidDecl(); } else if (!VDecl->isInvalidDecl()) { InitializationSequence InitSeq(*this, Entity, Kind, &Init, 1); - OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind, - MultiExprArg(*this, (void**)&Init, 1), + ExprResult Result = InitSeq.Perform(*this, Entity, Kind, + MultiExprArg(*this, &Init, 1), &DclT); if (Result.isInvalid()) { VDecl->setInvalidDecl(); @@ -3991,7 +4188,7 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) { // C++ 3.6.2p2, allow dynamic initialization of static initializers. // Don't check invalid declarations to avoid emitting useless diagnostics. if (!getLangOptions().CPlusPlus && !VDecl->isInvalidDecl()) { - if (VDecl->getStorageClass() == VarDecl::Static) // C99 6.7.8p4. + if (VDecl->getStorageClass() == SC_Static) // C99 6.7.8p4. CheckForConstantInitializer(Init, DclT); } } @@ -4039,18 +4236,18 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) { << Init->getSourceRange(); VDecl->setInvalidDecl(); } else if (!VDecl->getType()->isDependentType()) - ImpCastExprToType(Init, VDecl->getType(), CastExpr::CK_IntegralCast); + ImpCastExprToType(Init, VDecl->getType(), CK_IntegralCast); } } } else if (VDecl->isFileVarDecl()) { - if (VDecl->getStorageClass() == VarDecl::Extern && + if (VDecl->getStorageClass() == SC_Extern && (!getLangOptions().CPlusPlus || !Context.getBaseElementType(VDecl->getType()).isConstQualified())) Diag(VDecl->getLocation(), diag::warn_extern_init); if (!VDecl->isInvalidDecl()) { InitializationSequence InitSeq(*this, Entity, Kind, &Init, 1); - OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind, - MultiExprArg(*this, (void**)&Init, 1), + ExprResult Result = InitSeq.Perform(*this, Entity, Kind, + MultiExprArg(*this, &Init, 1), &DclT); if (Result.isInvalid()) { VDecl->setInvalidDecl(); @@ -4081,6 +4278,14 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) { VDecl->setInit(Init); if (getLangOptions().CPlusPlus) { + if (!VDecl->isInvalidDecl() && + !VDecl->getDeclContext()->isDependentContext() && + VDecl->hasGlobalStorage() && !VDecl->isStaticLocal() && + !Init->isConstantInitializer(Context, + VDecl->getType()->isReferenceType())) + Diag(VDecl->getLocation(), diag::warn_global_constructor) + << Init->getSourceRange(); + // Make sure we mark the destructor as used if necessary. QualType InitType = VDecl->getType(); while (const ArrayType *Array = Context.getAsArrayType(InitType)) @@ -4095,10 +4300,9 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) { /// ActOnInitializerError - Given that there was an error parsing an /// initializer for the given declaration, try to return to some form /// of sanity. -void Sema::ActOnInitializerError(DeclPtrTy dcl) { +void Sema::ActOnInitializerError(Decl *D) { // Our main concern here is re-establishing invariants like "a // variable's type is either dependent or complete". - Decl *D = dcl.getAs(); if (!D || D->isInvalidDecl()) return; VarDecl *VD = dyn_cast(D); @@ -4127,10 +4331,8 @@ void Sema::ActOnInitializerError(DeclPtrTy dcl) { // though. } -void Sema::ActOnUninitializedDecl(DeclPtrTy dcl, +void Sema::ActOnUninitializedDecl(Decl *RealDecl, bool TypeContainsUndeducedAuto) { - Decl *RealDecl = dcl.getAs(); - // If there is no declaration, there was an error parsing it. Just ignore it. if (RealDecl == 0) return; @@ -4190,7 +4392,7 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl, ArrayT->getElementType(), diag::err_illegal_decl_array_incomplete_type)) Var->setInvalidDecl(); - } else if (Var->getStorageClass() == VarDecl::Static) { + } else if (Var->getStorageClass() == SC_Static) { // C99 6.9.2p3: If the declaration of an identifier for an object is // a tentative definition and has internal linkage (C99 6.2.2p3), the // declared type shall not be an incomplete type. @@ -4221,15 +4423,15 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl, return; } - // Provide a specific diagnostic for uninitialized variable - // definitions with reference type. - if (Type->isReferenceType()) { - Diag(Var->getLocation(), diag::err_reference_var_requires_init) - << Var->getDeclName() - << SourceRange(Var->getLocation(), Var->getLocation()); - Var->setInvalidDecl(); - return; - } + // Provide a specific diagnostic for uninitialized variable + // definitions with reference type. + if (Type->isReferenceType()) { + Diag(Var->getLocation(), diag::err_reference_var_requires_init) + << Var->getDeclName() + << SourceRange(Var->getLocation(), Var->getLocation()); + Var->setInvalidDecl(); + return; + } // Do not attempt to type-check the default initializer for a // variable with dependent type. @@ -4271,17 +4473,30 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl, // program is ill-formed. // FIXME: DPG thinks it is very fishy that C++0x disables this. } else { + // Check for jumps past the implicit initializer. C++0x + // clarifies that this applies to a "variable with automatic + // storage duration", not a "local variable". + if (getLangOptions().CPlusPlus && Var->hasLocalStorage()) + getCurFunction()->setHasBranchProtectedScope(); + InitializedEntity Entity = InitializedEntity::InitializeVariable(Var); InitializationKind Kind = InitializationKind::CreateDefault(Var->getLocation()); InitializationSequence InitSeq(*this, Entity, Kind, 0, 0); - OwningExprResult Init = InitSeq.Perform(*this, Entity, Kind, - MultiExprArg(*this, 0, 0)); + ExprResult Init = InitSeq.Perform(*this, Entity, Kind, + MultiExprArg(*this, 0, 0)); if (Init.isInvalid()) Var->setInvalidDecl(); - else if (Init.get()) + else if (Init.get()) { Var->setInit(MaybeCreateCXXExprWithTemporaries(Init.takeAs())); + + if (getLangOptions().CPlusPlus && !Var->isInvalidDecl() && + Var->hasGlobalStorage() && !Var->isStaticLocal() && + !Var->getDeclContext()->isDependentContext() && + !Var->getInit()->isConstantInitializer(Context, false)) + Diag(Var->getLocation(), diag::warn_global_constructor); + } } if (!Var->isInvalidDecl() && getLangOptions().CPlusPlus && Record) @@ -4289,16 +4504,16 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl, } } -Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, - DeclPtrTy *Group, - unsigned NumDecls) { +Sema::DeclGroupPtrTy +Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, + Decl **Group, unsigned NumDecls) { llvm::SmallVector Decls; if (DS.isTypeSpecOwned()) - Decls.push_back((Decl*)DS.getTypeRep()); + Decls.push_back(DS.getRepAsDecl()); for (unsigned i = 0; i != NumDecls; ++i) - if (Decl *D = Group[i].getAs()) + if (Decl *D = Group[i]) Decls.push_back(D); return DeclGroupPtrTy::make(DeclGroupRef::Create(Context, @@ -4308,16 +4523,15 @@ Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, /// ActOnParamDeclarator - Called from Parser::ParseFunctionDeclarator() /// to introduce parameters into function prototype scope. -Sema::DeclPtrTy -Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { +Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { const DeclSpec &DS = D.getDeclSpec(); // Verify C99 6.7.5.3p2: The only SCS allowed is 'register'. - VarDecl::StorageClass StorageClass = VarDecl::None; - VarDecl::StorageClass StorageClassAsWritten = VarDecl::None; + VarDecl::StorageClass StorageClass = SC_None; + VarDecl::StorageClass StorageClassAsWritten = SC_None; if (DS.getStorageClassSpec() == DeclSpec::SCS_register) { - StorageClass = VarDecl::Register; - StorageClassAsWritten = VarDecl::Register; + StorageClass = SC_Register; + StorageClassAsWritten = SC_Register; } else if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified) { Diag(DS.getStorageClassSpecLoc(), diag::err_invalid_storage_class_in_func_decl); @@ -4358,7 +4572,7 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl); // Just pretend that we didn't see the previous declaration. PrevDecl = 0; - } else if (S->isDeclScope(DeclPtrTy::make(PrevDecl))) { + } else if (S->isDeclScope(PrevDecl)) { Diag(D.getIdentifierLoc(), diag::err_param_redefinition) << II; Diag(PrevDecl->getLocation(), diag::note_previous_declaration); @@ -4389,7 +4603,7 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { } // Add the parameter declaration into this scope. - S->AddDecl(DeclPtrTy::make(New)); + S->AddDecl(New); if (II) IdResolver.AddDecl(New); @@ -4398,7 +4612,7 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { if (New->hasAttr()) { Diag(New->getLocation(), diag::err_block_on_nonlocal); } - return DeclPtrTy::make(New); + return New; } /// \brief Synthesizes a variable for a parameter arising from a @@ -4408,11 +4622,31 @@ ParmVarDecl *Sema::BuildParmVarDeclForTypedef(DeclContext *DC, QualType T) { ParmVarDecl *Param = ParmVarDecl::Create(Context, DC, Loc, 0, T, Context.getTrivialTypeSourceInfo(T, Loc), - VarDecl::None, VarDecl::None, 0); + SC_None, SC_None, 0); Param->setImplicit(); return Param; } +void Sema::DiagnoseUnusedParameters(ParmVarDecl * const *Param, + ParmVarDecl * const *ParamEnd) { + if (Diags.getDiagnosticLevel(diag::warn_unused_parameter) == + Diagnostic::Ignored) + return; + + // Don't diagnose unused-parameter errors in template instantiations; we + // will already have done so in the template itself. + if (!ActiveTemplateInstantiations.empty()) + return; + + for (; Param != ParamEnd; ++Param) { + if (!(*Param)->isUsed() && (*Param)->getDeclName() && + !(*Param)->hasAttr()) { + Diag((*Param)->getLocation(), diag::warn_unused_parameter) + << (*Param)->getDeclName(); + } + } +} + ParmVarDecl *Sema::CheckParameter(DeclContext *DC, TypeSourceInfo *TSInfo, QualType T, IdentifierInfo *Name, @@ -4487,8 +4721,8 @@ void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D, } } -Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, - Declarator &D) { +Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, + Declarator &D) { assert(getCurFunctionDecl() == 0 && "Function parsing confused"); assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function && "Not a function declarator!"); @@ -4500,9 +4734,9 @@ Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Scope *ParentScope = FnBodyScope->getParent(); - DeclPtrTy DP = HandleDeclarator(ParentScope, D, - MultiTemplateParamsArg(*this), - /*IsFunctionDefinition=*/true); + Decl *DP = HandleDeclarator(ParentScope, D, + MultiTemplateParamsArg(*this), + /*IsFunctionDefinition=*/true); return ActOnStartOfFunctionDef(FnBodyScope, DP); } @@ -4550,7 +4784,7 @@ static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD) { return MissingPrototype; } -Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) { +Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) { // Clear the last template instantiation error context. LastTemplateInstantiationErrorContext = ActiveTemplateInstantiation(); @@ -4558,11 +4792,10 @@ Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) { return D; FunctionDecl *FD = 0; - if (FunctionTemplateDecl *FunTmpl - = dyn_cast(D.getAs())) + if (FunctionTemplateDecl *FunTmpl = dyn_cast(D)) FD = FunTmpl->getTemplatedDecl(); else - FD = cast(D.getAs()); + FD = cast(D); // Enter a new function scope PushFunctionScope(); @@ -4627,15 +4860,15 @@ Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) { // Checking attributes of current function definition // dllimport attribute. - if (FD->getAttr() && - (!FD->getAttr())) { - // dllimport attribute cannot be applied to definition. - if (!(FD->getAttr())->isInherited()) { + DLLImportAttr *DA = FD->getAttr(); + if (DA && (!FD->getAttr())) { + // dllimport attribute cannot be directly applied to definition. + if (!DA->isInherited()) { Diag(FD->getLocation(), diag::err_attribute_can_be_applied_only_to_symbol_declaration) << "dllimport"; FD->setInvalidDecl(); - return DeclPtrTy::make(FD); + return FD; } // Visual C++ appears to not think this is an issue, so only issue @@ -4646,10 +4879,10 @@ Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) { // emitted. Diag(FD->getLocation(), diag::warn_redeclaration_without_attribute_prev_attribute_ignored) - << FD->getNameAsCString() << "dllimport"; + << FD->getName() << "dllimport"; } } - return DeclPtrTy::make(FD); + return FD; } /// \brief Given the set of return statements within a function body, @@ -4668,9 +4901,11 @@ Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) { /// FIXME: Employ a smarter algorithm that accounts for multiple return /// statements and the lifetimes of the NRVO candidates. We should be able to /// find a maximal set of NRVO variables. -static void ComputeNRVO(Stmt *Body, ReturnStmt **Returns, unsigned NumReturns) { +static void ComputeNRVO(Stmt *Body, FunctionScopeInfo *Scope) { + ReturnStmt **Returns = Scope->Returns.data(); + const VarDecl *NRVOCandidate = 0; - for (unsigned I = 0; I != NumReturns; ++I) { + for (unsigned I = 0, E = Scope->Returns.size(); I != E; ++I) { if (!Returns[I]->getNRVOCandidate()) return; @@ -4684,15 +4919,12 @@ static void ComputeNRVO(Stmt *Body, ReturnStmt **Returns, unsigned NumReturns) { const_cast(NRVOCandidate)->setNRVOVariable(true); } -Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg) { +Decl *Sema::ActOnFinishFunctionBody(Decl *D, Stmt *BodyArg) { return ActOnFinishFunctionBody(D, move(BodyArg), false); } -Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg, - bool IsInstantiation) { - Decl *dcl = D.getAs(); - Stmt *Body = BodyArg.takeAs(); - +Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, + bool IsInstantiation) { FunctionDecl *FD = 0; FunctionTemplateDecl *FunTmpl = dyn_cast_or_null(dcl); if (FunTmpl) @@ -4718,8 +4950,7 @@ Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg, if (CXXConstructorDecl *Constructor = dyn_cast(FD)) MarkVTableUsed(FD->getLocation(), Constructor->getParent()); - ComputeNRVO(Body, FunctionScopes.back()->Returns.data(), - FunctionScopes.back()->Returns.size()); + ComputeNRVO(Body, getCurFunction()); } assert(FD == getCurFunctionDecl() && "Function parsing confused"); @@ -4730,15 +4961,15 @@ Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg, if (!MD->isInvalidDecl()) DiagnoseUnusedParameters(MD->param_begin(), MD->param_end()); } else { - Body->Destroy(Context); - return DeclPtrTy(); + return 0; } // Verify and clean out per-function state. // Check goto/label use. + FunctionScopeInfo *CurFn = getCurFunction(); for (llvm::DenseMap::iterator - I = getLabelMap().begin(), E = getLabelMap().end(); I != E; ++I) { + I = CurFn->LabelMap.begin(), E = CurFn->LabelMap.end(); I != E; ++I) { LabelStmt *L = I->second; // Verify that we have no forward references left. If so, there was a goto @@ -4754,8 +4985,7 @@ Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg, // the function body so that they aren't leaked and that the AST is well // formed. if (Body == 0) { - // The whole function wasn't parsed correctly, just delete this. - L->Destroy(Context); + // The whole function wasn't parsed correctly. continue; } @@ -4785,14 +5015,18 @@ Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg, // Verify that that gotos and switch cases don't jump into scopes illegally. // Verify that that gotos and switch cases don't jump into scopes illegally. - if (FunctionNeedsScopeChecking() && + if (getCurFunction()->NeedsScopeChecking() && !dcl->isInvalidDecl() && !hasAnyErrorsInThisFunction()) DiagnoseInvalidJumps(Body); - if (CXXDestructorDecl *Destructor = dyn_cast(dcl)) + if (CXXDestructorDecl *Destructor = dyn_cast(dcl)) { + if (!Destructor->getParent()->isDependentType()) + CheckDestructor(Destructor); + MarkBaseAndMemberDestructorsReferenced(Destructor->getLocation(), Destructor->getParent()); + } // If any errors have occurred, clear out any temporaries that may have // been leftover. This ensures that these temporaries won't be picked up for @@ -4804,13 +5038,11 @@ Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg, // enabled. QualType ResultType; if (const FunctionDecl *FD = dyn_cast(dcl)) { - ResultType = FD->getResultType(); - } - else { + AnalysisWarnings.IssueWarnings(WP, FD); + } else { ObjCMethodDecl *MD = cast(dcl); - ResultType = MD->getResultType(); + AnalysisWarnings.IssueWarnings(WP, MD); } - AnalysisWarnings.IssueWarnings(WP, dcl); } assert(ExprTemporaries.empty() && "Leftover temporaries in function"); @@ -4826,8 +5058,8 @@ Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg, // deletion in some later function. if (getDiagnostics().hasErrorOccurred()) ExprTemporaries.clear(); - - return D; + + return dcl; } /// ImplicitlyDefineFunction - An undeclared identifier was used in a function @@ -4873,8 +5105,7 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, DeclContext *PrevDC = CurContext; CurContext = Context.getTranslationUnitDecl(); - FunctionDecl *FD = - dyn_cast(ActOnDeclarator(TUScope, D).getAs()); + FunctionDecl *FD = dyn_cast(ActOnDeclarator(TUScope, D)); FD->setImplicit(); CurContext = PrevDC; @@ -4902,9 +5133,17 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { bool HasVAListArg; if (Context.BuiltinInfo.isPrintfLike(BuiltinID, FormatIdx, HasVAListArg)) { if (!FD->getAttr()) - FD->addAttr(::new (Context) FormatAttr(Context, "printf", FormatIdx+1, + FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context, + "printf", FormatIdx+1, HasVAListArg ? 0 : FormatIdx+2)); } + if (Context.BuiltinInfo.isScanfLike(BuiltinID, FormatIdx, + HasVAListArg)) { + if (!FD->getAttr()) + FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context, + "scanf", FormatIdx+1, + HasVAListArg ? 0 : FormatIdx+2)); + } // Mark const if we don't care about errno and that is the only // thing preventing the function from being const. This allows @@ -4912,15 +5151,15 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { if (!getLangOptions().MathErrno && Context.BuiltinInfo.isConstWithoutErrno(BuiltinID)) { if (!FD->getAttr()) - FD->addAttr(::new (Context) ConstAttr()); + FD->addAttr(::new (Context) ConstAttr(FD->getLocation(), Context)); } if (Context.BuiltinInfo.isNoReturn(BuiltinID)) FD->setType(Context.getNoReturnType(FD->getType())); if (Context.BuiltinInfo.isNoThrow(BuiltinID)) - FD->addAttr(::new (Context) NoThrowAttr()); + FD->addAttr(::new (Context) NoThrowAttr(FD->getLocation(), Context)); if (Context.BuiltinInfo.isConst(BuiltinID)) - FD->addAttr(::new (Context) ConstAttr()); + FD->addAttr(::new (Context) ConstAttr(FD->getLocation(), Context)); } IdentifierInfo *Name = FD->getIdentifier(); @@ -4942,13 +5181,15 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { // FIXME: We known better than our headers. const_cast(Format)->setType(Context, "printf"); } else - FD->addAttr(::new (Context) FormatAttr(Context, "printf", 1, + FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context, + "printf", 1, Name->isStr("NSLogv") ? 0 : 2)); } else if (Name->isStr("asprintf") || Name->isStr("vasprintf")) { // FIXME: asprintf and vasprintf aren't C99 functions. Should they be // target-specific builtins, perhaps? if (!FD->getAttr()) - FD->addAttr(::new (Context) FormatAttr(Context, "printf", 2, + FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context, + "printf", 2, Name->isStr("vasprintf") ? 0 : 3)); } } @@ -5031,7 +5272,7 @@ bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous, /// former case, Name will be non-null. In the later case, Name will be null. /// TagSpec indicates what kind of tag this is. TUK indicates whether this is a /// reference/declaration/definition of a tag. -Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, +Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, AttributeList *Attr, AccessSpecifier AS, @@ -5063,7 +5304,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // This is a declaration or definition of a class template (which may // be a member of another template). if (Invalid) - return DeclPtrTy(); + return 0; OwnedDecl = false; DeclResult Result = CheckClassTemplate(S, TagSpec, TUK, KWLoc, @@ -5106,26 +5347,26 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, DC = computeDeclContext(SS, false); if (!DC) { IsDependent = true; - return DeclPtrTy(); + return 0; } } else { DC = computeDeclContext(SS, true); if (!DC) { Diag(SS.getRange().getBegin(), diag::err_dependent_nested_name_spec) << SS.getRange(); - return DeclPtrTy(); + return 0; } } if (RequireCompleteDeclContext(SS, DC)) - return DeclPtrTy::make((Decl *)0); + return 0; SearchDC = DC; // Look-up name inside 'foo::'. LookupQualifiedName(Previous, DC); if (Previous.isAmbiguous()) - return DeclPtrTy(); + return 0; if (Previous.empty()) { // Name lookup did not find anything. However, if the @@ -5135,7 +5376,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // this as a dependent elaborated-type-specifier. if (Previous.wasNotFoundInCurrentInstantiation()) { IsDependent = true; - return DeclPtrTy(); + return 0; } // A tag 'foo::bar' must already exist. @@ -5155,7 +5396,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // Note: there used to be some attempt at recovery here. if (Previous.isAmbiguous()) - return DeclPtrTy(); + return 0; if (!getLangOptions().CPlusPlus && TUK != TUK_Reference) { // FIXME: This makes sure that we ignore the contexts associated @@ -5176,7 +5417,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, } if (getLangOptions().CPlusPlus && Name && DC && StdNamespace && - DC->Equals(StdNamespace) && Name->isStr("bad_alloc")) { + DC->Equals(getStdNamespace()) && Name->isStr("bad_alloc")) { // This is a declaration of or a reference to "std::bad_alloc". isStdBadAlloc = true; @@ -5184,7 +5425,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // std::bad_alloc has been implicitly declared (but made invisible to // name lookup). Fill in this implicit declaration as the previous // declaration, so that the declarations get chained appropriately. - Previous.addDecl(StdBadAlloc); + Previous.addDecl(getStdBadAlloc()); } } @@ -5271,11 +5512,12 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, if (const TagType *TT = TD->getUnderlyingType()->getAs()) { TagDecl *Tag = TT->getDecl(); if (Tag->getDeclName() == Name && - Tag->getDeclContext()->getLookupContext() - ->Equals(TD->getDeclContext()->getLookupContext())) { + Tag->getDeclContext()->getRedeclContext() + ->Equals(TD->getDeclContext()->getRedeclContext())) { PrevDecl = Tag; Previous.clear(); Previous.addDecl(Tag); + Previous.resolveKind(); } } } @@ -5321,7 +5563,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // need to be changed with DeclGroups. if ((TUK == TUK_Reference && !PrevTagDecl->getFriendObjectKind()) || TUK == TUK_Friend) - return DeclPtrTy::make(PrevTagDecl); + return PrevTagDecl; // Diagnose attempts to redefine a tag. if (TUK == TUK_Definition) { @@ -5475,7 +5717,7 @@ CreateNewDecl: New = CXXRecordDecl::Create(Context, Kind, SearchDC, Loc, Name, KWLoc, cast_or_null(PrevDecl)); - if (isStdBadAlloc && (!StdBadAlloc || StdBadAlloc->isImplicit())) + if (isStdBadAlloc && (!StdBadAlloc || getStdBadAlloc()->isImplicit())) StdBadAlloc = cast(New); } else New = RecordDecl::Create(Context, Kind, SearchDC, Loc, Name, KWLoc, @@ -5549,7 +5791,7 @@ CreateNewDecl: if (PrevDecl) New->setAccess(PrevDecl->getAccess()); - DeclContext *DC = New->getDeclContext()->getLookupContext(); + DeclContext *DC = New->getDeclContext()->getRedeclContext(); DC->makeDeclVisibleInContext(New, /* Recoverable = */ false); if (Name) // can be null along some error paths if (Scope *EnclosingScope = getScopeForDeclContext(S, DC)) @@ -5564,26 +5806,26 @@ CreateNewDecl: // If this is the C FILE type, notify the AST context. if (IdentifierInfo *II = New->getIdentifier()) if (!New->isInvalidDecl() && - New->getDeclContext()->getLookupContext()->isTranslationUnit() && + New->getDeclContext()->getRedeclContext()->isTranslationUnit() && II->isStr("FILE")) Context.setFILEDecl(New); OwnedDecl = true; - return DeclPtrTy::make(New); + return New; } -void Sema::ActOnTagStartDefinition(Scope *S, DeclPtrTy TagD) { +void Sema::ActOnTagStartDefinition(Scope *S, Decl *TagD) { AdjustDeclIfTemplate(TagD); - TagDecl *Tag = cast(TagD.getAs()); + TagDecl *Tag = cast(TagD); // Enter the tag context. PushDeclContext(S, Tag); } -void Sema::ActOnStartCXXMemberDeclarations(Scope *S, DeclPtrTy TagD, +void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD, SourceLocation LBraceLoc) { AdjustDeclIfTemplate(TagD); - CXXRecordDecl *Record = cast(TagD.getAs()); + CXXRecordDecl *Record = cast(TagD); FieldCollector->StartClass(); @@ -5610,10 +5852,10 @@ void Sema::ActOnStartCXXMemberDeclarations(Scope *S, DeclPtrTy TagD, "Broken injected-class-name"); } -void Sema::ActOnTagFinishDefinition(Scope *S, DeclPtrTy TagD, +void Sema::ActOnTagFinishDefinition(Scope *S, Decl *TagD, SourceLocation RBraceLoc) { AdjustDeclIfTemplate(TagD); - TagDecl *Tag = cast(TagD.getAs()); + TagDecl *Tag = cast(TagD); Tag->setRBraceLoc(RBraceLoc); if (isa(Tag)) @@ -5626,9 +5868,9 @@ void Sema::ActOnTagFinishDefinition(Scope *S, DeclPtrTy TagD, Consumer.HandleTagDeclDefinition(Tag); } -void Sema::ActOnTagDefinitionError(Scope *S, DeclPtrTy TagD) { +void Sema::ActOnTagDefinitionError(Scope *S, Decl *TagD) { AdjustDeclIfTemplate(TagD); - TagDecl *Tag = cast(TagD.getAs()); + TagDecl *Tag = cast(TagD); Tag->setInvalidDecl(); // We're undoing ActOnTagStartDefinition here, not @@ -5711,13 +5953,13 @@ bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, /// ActOnField - Each field of a struct/union/class is passed into this in order /// to create a FieldDecl object for it. -Sema::DeclPtrTy Sema::ActOnField(Scope *S, DeclPtrTy TagD, +Decl *Sema::ActOnField(Scope *S, Decl *TagD, SourceLocation DeclStart, Declarator &D, ExprTy *BitfieldWidth) { - FieldDecl *Res = HandleField(S, cast_or_null(TagD.getAs()), + FieldDecl *Res = HandleField(S, cast_or_null(TagD), DeclStart, D, static_cast(BitfieldWidth), AS_public); - return DeclPtrTy::make(Res); + return Res; } /// HandleField - Analyze a field of a C struct or a C++ data member. @@ -5739,9 +5981,17 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record, if (D.getDeclSpec().isThreadSpecified()) Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread); + + // Check to see if this name was declared as a member previously + LookupResult Previous(*this, II, Loc, LookupMemberName, ForRedeclaration); + LookupName(Previous, S); + assert((Previous.empty() || Previous.isOverloadedResult() || + Previous.isSingleResult()) + && "Lookup of member name should be either overloaded, single or null"); - NamedDecl *PrevDecl = LookupSingleName(S, II, Loc, LookupMemberName, - ForRedeclaration); + // If the name is overloaded then get any declaration else get the single result + NamedDecl *PrevDecl = Previous.isOverloadedResult() ? + Previous.getRepresentativeDecl() : Previous.getAsSingle(); if (PrevDecl && PrevDecl->isTemplateParameter()) { // Maybe we will complain about the shadowed template parameter. @@ -5804,21 +6054,29 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, QualType EltTy = Context.getBaseElementType(T); if (!EltTy->isDependentType() && - RequireCompleteType(Loc, EltTy, diag::err_field_incomplete)) + RequireCompleteType(Loc, EltTy, diag::err_field_incomplete)) { + // Fields of incomplete type force their record to be invalid. + Record->setInvalidDecl(); InvalidDecl = true; + } // C99 6.7.2.1p8: A member of a structure or union may have any type other // than a variably modified type. if (!InvalidDecl && T->isVariablyModifiedType()) { bool SizeIsNegative; + llvm::APSInt Oversized; QualType FixedTy = TryToFixInvalidVariablyModifiedType(T, Context, - SizeIsNegative); + SizeIsNegative, + Oversized); if (!FixedTy.isNull()) { Diag(Loc, diag::warn_illegal_constant_array_size); T = FixedTy; } else { if (SizeIsNegative) Diag(Loc, diag::err_typecheck_negative_array_size); + else if (Oversized.getBoolValue()) + Diag(Loc, diag::err_array_too_large) + << Oversized.toString(10); else Diag(Loc, diag::err_typecheck_field_variable_size); InvalidDecl = true; @@ -5836,7 +6094,6 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, if (!InvalidDecl && BitWidth && VerifyBitField(Loc, II, T, BitWidth, &ZeroWidth)) { InvalidDecl = true; - DeleteExpr(BitWidth); BitWidth = 0; ZeroWidth = false; } @@ -5877,6 +6134,8 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, CXXRecord->setPOD(false); if (!ZeroWidth) CXXRecord->setEmpty(false); + if (T->isReferenceType()) + CXXRecord->setHasTrivialConstructor(false); if (const RecordType *RT = EltTy->getAs()) { CXXRecordDecl* RDecl = cast(RT->getDecl()); @@ -5896,27 +6155,8 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, // cannot be a member of a union, nor can an array of such // objects. // TODO: C++0x alters this restriction significantly. - if (Record->isUnion()) { - // We check for copy constructors before constructors - // because otherwise we'll never get complaints about - // copy constructors. - - CXXSpecialMember member = CXXInvalid; - if (!RDecl->hasTrivialCopyConstructor()) - member = CXXCopyConstructor; - else if (!RDecl->hasTrivialConstructor()) - member = CXXConstructor; - else if (!RDecl->hasTrivialCopyAssignment()) - member = CXXCopyAssignment; - else if (!RDecl->hasTrivialDestructor()) - member = CXXDestructor; - - if (member != CXXInvalid) { - Diag(Loc, diag::err_illegal_union_member) << Name << member; - DiagnoseNontrivial(RT, member); - NewFD->setInvalidDecl(); - } - } + if (Record->isUnion() && CheckNontrivialField(NewFD)) + NewFD->setInvalidDecl(); } } } @@ -5946,6 +6186,43 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, return NewFD; } +bool Sema::CheckNontrivialField(FieldDecl *FD) { + assert(FD); + assert(getLangOptions().CPlusPlus && "valid check only for C++"); + + if (FD->isInvalidDecl()) + return true; + + QualType EltTy = Context.getBaseElementType(FD->getType()); + if (const RecordType *RT = EltTy->getAs()) { + CXXRecordDecl* RDecl = cast(RT->getDecl()); + if (RDecl->getDefinition()) { + // We check for copy constructors before constructors + // because otherwise we'll never get complaints about + // copy constructors. + + CXXSpecialMember member = CXXInvalid; + if (!RDecl->hasTrivialCopyConstructor()) + member = CXXCopyConstructor; + else if (!RDecl->hasTrivialConstructor()) + member = CXXConstructor; + else if (!RDecl->hasTrivialCopyAssignment()) + member = CXXCopyAssignment; + else if (!RDecl->hasTrivialDestructor()) + member = CXXDestructor; + + if (member != CXXInvalid) { + Diag(FD->getLocation(), diag::err_illegal_union_or_anon_struct_member) + << (int)FD->getParent()->isUnion() << FD->getDeclName() << member; + DiagnoseNontrivial(RT, member); + return true; + } + } + } + + return false; +} + /// DiagnoseNontrivial - Given that a class has a non-trivial /// special member, figure out why. void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) { @@ -6091,9 +6368,9 @@ TranslateIvarVisibility(tok::ObjCKeywordKind ivarVisibility) { /// ActOnIvar - Each ivar field of an objective-c class is passed into this /// in order to create an IvarDecl object for it. -Sema::DeclPtrTy Sema::ActOnIvar(Scope *S, +Decl *Sema::ActOnIvar(Scope *S, SourceLocation DeclStart, - DeclPtrTy IntfDecl, + Decl *IntfDecl, Declarator &D, ExprTy *BitfieldWidth, tok::ObjCKeywordKind Visibility) { @@ -6112,7 +6389,6 @@ Sema::DeclPtrTy Sema::ActOnIvar(Scope *S, // 6.7.2.1p3, 6.7.2.1p4 if (VerifyBitField(Loc, II, T, BitWidth)) { D.setInvalidType(); - DeleteExpr(BitWidth); BitWidth = 0; } } else { @@ -6137,19 +6413,23 @@ Sema::DeclPtrTy Sema::ActOnIvar(Scope *S, Visibility != tok::objc_not_keyword ? TranslateIvarVisibility(Visibility) : ObjCIvarDecl::None; // Must set ivar's DeclContext to its enclosing interface. - ObjCContainerDecl *EnclosingDecl = IntfDecl.getAs(); + ObjCContainerDecl *EnclosingDecl = cast(IntfDecl); ObjCContainerDecl *EnclosingContext; if (ObjCImplementationDecl *IMPDecl = dyn_cast(EnclosingDecl)) { + if (!LangOpts.ObjCNonFragileABI2) { // Case of ivar declared in an implementation. Context is that of its class. - EnclosingContext = IMPDecl->getClassInterface(); - assert(EnclosingContext && "Implementation has no class interface!"); + EnclosingContext = IMPDecl->getClassInterface(); + assert(EnclosingContext && "Implementation has no class interface!"); + } + else + EnclosingContext = EnclosingDecl; } else { if (ObjCCategoryDecl *CDecl = dyn_cast(EnclosingDecl)) { if (!LangOpts.ObjCNonFragileABI2 || !CDecl->IsClassExtension()) { Diag(Loc, diag::err_misplaced_ivar) << CDecl->IsClassExtension(); - return DeclPtrTy(); + return 0; } } EnclosingContext = EnclosingDecl; @@ -6180,19 +6460,59 @@ Sema::DeclPtrTy Sema::ActOnIvar(Scope *S, if (II) { // FIXME: When interfaces are DeclContexts, we'll need to add // these to the interface. - S->AddDecl(DeclPtrTy::make(NewID)); + S->AddDecl(NewID); IdResolver.AddDecl(NewID); } - return DeclPtrTy::make(NewID); + return NewID; +} + +/// ActOnLastBitfield - This routine handles synthesized bitfields rules for +/// class and class extensions. For every class @interface and class +/// extension @interface, if the last ivar is a bitfield of any type, +/// then add an implicit `char :0` ivar to the end of that interface. +void Sema::ActOnLastBitfield(SourceLocation DeclLoc, Decl *EnclosingDecl, + llvm::SmallVectorImpl &AllIvarDecls) { + if (!LangOpts.ObjCNonFragileABI2 || AllIvarDecls.empty()) + return; + + Decl *ivarDecl = AllIvarDecls[AllIvarDecls.size()-1]; + ObjCIvarDecl *Ivar = cast(ivarDecl); + + if (!Ivar->isBitField()) + return; + uint64_t BitFieldSize = + Ivar->getBitWidth()->EvaluateAsInt(Context).getZExtValue(); + if (BitFieldSize == 0) + return; + ObjCInterfaceDecl *ID = dyn_cast(EnclosingDecl); + if (!ID) { + if (ObjCCategoryDecl *CD = dyn_cast(EnclosingDecl)) { + if (!CD->IsClassExtension()) + return; + } + // No need to add this to end of @implementation. + else + return; + } + // All conditions are met. Add a new bitfield to the tail end of ivars. + llvm::APInt Zero(Context.getTypeSize(Context.CharTy), 0); + Expr * BW = IntegerLiteral::Create(Context, Zero, Context.CharTy, DeclLoc); + + Ivar = ObjCIvarDecl::Create(Context, cast(EnclosingDecl), + DeclLoc, 0, + Context.CharTy, + Context.CreateTypeSourceInfo(Context.CharTy), + ObjCIvarDecl::Private, BW, + true); + AllIvarDecls.push_back(Ivar); } void Sema::ActOnFields(Scope* S, - SourceLocation RecLoc, DeclPtrTy RecDecl, - DeclPtrTy *Fields, unsigned NumFields, + SourceLocation RecLoc, Decl *EnclosingDecl, + Decl **Fields, unsigned NumFields, SourceLocation LBrac, SourceLocation RBrac, AttributeList *Attr) { - Decl *EnclosingDecl = RecDecl.getAs(); assert(EnclosingDecl && "missing record or interface decl"); // If the decl this is being inserted into is invalid, then it may be a @@ -6209,7 +6529,7 @@ void Sema::ActOnFields(Scope* S, RecordDecl *Record = dyn_cast(EnclosingDecl); for (unsigned i = 0; i != NumFields; ++i) { - FieldDecl *FD = cast(Fields[i].getAs()); + FieldDecl *FD = cast(Fields[i]); // Get the type for the field. Type *FDTy = FD->getType().getTypePtr(); @@ -6244,7 +6564,7 @@ void Sema::ActOnFields(Scope* S, EnclosingDecl->setInvalidDecl(); continue; } else if (FDTy->isIncompleteArrayType() && i == NumFields - 1 && - Record && Record->isStruct()) { + Record && !Record->isUnion()) { // Flexible array member. if (NumNamedMembers < 1) { Diag(FD->getLocation(), diag::err_flexible_array_empty_struct) @@ -6360,6 +6680,11 @@ void Sema::ActOnFields(Scope* S, if (Attr) ProcessDeclAttributeList(S, Record, Attr); + + // If there's a #pragma GCC visibility in scope, and this isn't a subclass, + // set the visibility of this record. + if (Record && !Record->getDeclContext()->isRecord()) + AddPushedVisibilityAttribute(Record); } /// \brief Determine whether the given integral value is representable within @@ -6405,9 +6730,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, EnumConstantDecl *LastEnumConst, SourceLocation IdLoc, IdentifierInfo *Id, - ExprArg val) { - Expr *Val = (Expr *)val.get(); - + Expr *Val) { unsigned IntWidth = Context.Target.getIntWidth(); llvm::APSInt EnumVal(IntWidth); QualType EltTy; @@ -6434,12 +6757,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, << (EnumVal.isUnsigned() || EnumVal.isNonNegative()); else if (!Context.hasSameType(Val->getType(), Context.IntTy)) { // Force the type of the expression to 'int'. - ImpCastExprToType(Val, Context.IntTy, CastExpr::CK_IntegralCast); - - if (Val != val.get()) { - val.release(); - val = Val; - } + ImpCastExprToType(Val, Context.IntTy, CK_IntegralCast); } } @@ -6527,20 +6845,19 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, EnumVal.setIsSigned(EltTy->isSignedIntegerType()); } - val.release(); return EnumConstantDecl::Create(Context, Enum, IdLoc, Id, EltTy, Val, EnumVal); } -Sema::DeclPtrTy Sema::ActOnEnumConstant(Scope *S, DeclPtrTy theEnumDecl, - DeclPtrTy lastEnumConst, +Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, + Decl *lastEnumConst, SourceLocation IdLoc, IdentifierInfo *Id, SourceLocation EqualLoc, ExprTy *val) { - EnumDecl *TheEnumDecl = cast(theEnumDecl.getAs()); + EnumDecl *TheEnumDecl = cast(theEnumDecl); EnumConstantDecl *LastEnumConst = - cast_or_null(lastEnumConst.getAs()); + cast_or_null(lastEnumConst); Expr *Val = static_cast(val); // The scope passed in may not be a decl scope. Zip up the scope tree until @@ -6569,13 +6886,12 @@ Sema::DeclPtrTy Sema::ActOnEnumConstant(Scope *S, DeclPtrTy theEnumDecl, else Diag(IdLoc, diag::err_redefinition) << Id; Diag(PrevDecl->getLocation(), diag::note_previous_definition); - if (Val) Val->Destroy(Context); - return DeclPtrTy(); + return 0; } } EnumConstantDecl *New = CheckEnumConstant(TheEnumDecl, LastEnumConst, - IdLoc, Id, Owned(Val)); + IdLoc, Id, Val); // Register this decl in the current scope stack. if (New) { @@ -6583,14 +6899,14 @@ Sema::DeclPtrTy Sema::ActOnEnumConstant(Scope *S, DeclPtrTy theEnumDecl, PushOnScopeChains(New, S); } - return DeclPtrTy::make(New); + return New; } void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, - SourceLocation RBraceLoc, DeclPtrTy EnumDeclX, - DeclPtrTy *Elements, unsigned NumElements, + SourceLocation RBraceLoc, Decl *EnumDeclX, + Decl **Elements, unsigned NumElements, Scope *S, AttributeList *Attr) { - EnumDecl *Enum = cast(EnumDeclX.getAs()); + EnumDecl *Enum = cast(EnumDeclX); QualType EnumType = Context.getTypeDeclType(Enum); if (Attr) @@ -6599,7 +6915,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, if (Enum->isDependentType()) { for (unsigned i = 0; i != NumElements; ++i) { EnumConstantDecl *ECD = - cast_or_null(Elements[i].getAs()); + cast_or_null(Elements[i]); if (!ECD) continue; ECD->setType(EnumType); @@ -6626,7 +6942,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, for (unsigned i = 0; i != NumElements; ++i) { EnumConstantDecl *ECD = - cast_or_null(Elements[i].getAs()); + cast_or_null(Elements[i]); if (!ECD) continue; // Already issued a diagnostic. const llvm::APSInt &InitVal = ECD->getInitVal(); @@ -6728,8 +7044,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, // Loop over all of the enumerator constants, changing their types to match // the type of the enum if needed. for (unsigned i = 0; i != NumElements; ++i) { - EnumConstantDecl *ECD = - cast_or_null(Elements[i].getAs()); + EnumConstantDecl *ECD = cast_or_null(Elements[i]); if (!ECD) continue; // Already issued a diagnostic. // Standard C says the enumerators have int type, but we allow, as an @@ -6772,11 +7087,11 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, // Adjust the Expr initializer and type. if (ECD->getInitExpr()) - ECD->setInitExpr(new (Context) ImplicitCastExpr(NewTy, - CastExpr::CK_IntegralCast, - ECD->getInitExpr(), - CXXBaseSpecifierArray(), - /*isLvalue=*/false)); + ECD->setInitExpr(ImplicitCastExpr::Create(Context, NewTy, + CK_IntegralCast, + ECD->getInitExpr(), + /*base paths*/ 0, + VK_RValue)); if (getLangOptions().CPlusPlus) // C++ [dcl.enum]p4: Following the closing brace of an // enum-specifier, each enumerator has the type of its @@ -6790,14 +7105,13 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, NumPositiveBits, NumNegativeBits); } -Sema::DeclPtrTy Sema::ActOnFileScopeAsmDecl(SourceLocation Loc, - ExprArg expr) { - StringLiteral *AsmString = cast(expr.takeAs()); +Decl *Sema::ActOnFileScopeAsmDecl(SourceLocation Loc, Expr *expr) { + StringLiteral *AsmString = cast(expr); FileScopeAsmDecl *New = FileScopeAsmDecl::Create(Context, CurContext, Loc, AsmString); CurContext->addDecl(New); - return DeclPtrTy::make(New); + return New; } void Sema::ActOnPragmaWeakID(IdentifierInfo* Name, @@ -6806,7 +7120,7 @@ void Sema::ActOnPragmaWeakID(IdentifierInfo* Name, Decl *PrevDecl = LookupSingleName(TUScope, Name, NameLoc, LookupOrdinaryName); if (PrevDecl) { - PrevDecl->addAttr(::new (Context) WeakAttr()); + PrevDecl->addAttr(::new (Context) WeakAttr(PragmaLoc, Context)); } else { (void)WeakUndeclaredIdentifiers.insert( std::pair diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 3b82f58be43e..25af73ae13d3 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -11,15 +11,18 @@ // //===----------------------------------------------------------------------===// -#include "Sema.h" +#include "clang/Sema/SemaInternal.h" #include "TargetAttributesSema.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/Expr.h" #include "clang/Basic/TargetInfo.h" -#include "clang/Parse/DeclSpec.h" +#include "clang/Sema/DeclSpec.h" +#include "clang/Sema/DelayedDiagnostic.h" #include "llvm/ADT/StringExtras.h" using namespace clang; +using namespace sema; //===----------------------------------------------------------------------===// // Helper functions @@ -193,7 +196,7 @@ static void HandleExtVectorTypeAttr(Scope *scope, Decl *d, // Instantiate/Install the vector type, and let Sema build the type for us. // This will run the reguired checks. - QualType T = S.BuildExtVectorType(curType, S.Owned(sizeExpr), Attr.getLoc()); + QualType T = S.BuildExtVectorType(curType, sizeExpr, Attr.getLoc()); if (!T.isNull()) { // FIXME: preserve the old source info. tDecl->setTypeSourceInfo(S.Context.getTrivialTypeSourceInfo(T)); @@ -211,7 +214,7 @@ static void HandlePackedAttr(Decl *d, const AttributeList &Attr, Sema &S) { } if (TagDecl *TD = dyn_cast(d)) - TD->addAttr(::new (S.Context) PackedAttr); + TD->addAttr(::new (S.Context) PackedAttr(Attr.getLoc(), S.Context)); else if (FieldDecl *FD = dyn_cast(d)) { // If the alignment is less than or equal to 8 bits, the packed attribute // has no effect. @@ -220,7 +223,7 @@ static void HandlePackedAttr(Decl *d, const AttributeList &Attr, Sema &S) { S.Diag(Attr.getLoc(), diag::warn_attribute_ignored_for_field_of_type) << Attr.getName() << FD->getType(); else - FD->addAttr(::new (S.Context) PackedAttr); + FD->addAttr(::new (S.Context) PackedAttr(Attr.getLoc(), S.Context)); } else S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); } @@ -235,7 +238,7 @@ static void HandleIBAction(Decl *d, const AttributeList &Attr, Sema &S) { // The IBAction attributes only apply to instance methods. if (ObjCMethodDecl *MD = dyn_cast(d)) if (MD->isInstanceMethod()) { - d->addAttr(::new (S.Context) IBActionAttr()); + d->addAttr(::new (S.Context) IBActionAttr(Attr.getLoc(), S.Context)); return; } @@ -252,7 +255,7 @@ static void HandleIBOutlet(Decl *d, const AttributeList &Attr, Sema &S) { // The IBOutlet attributes only apply to instance variables of // Objective-C classes. if (isa(d) || isa(d)) { - d->addAttr(::new (S.Context) IBOutletAttr()); + d->addAttr(::new (S.Context) IBOutletAttr(Attr.getLoc(), S.Context)); return; } @@ -263,7 +266,7 @@ static void HandleIBOutletCollection(Decl *d, const AttributeList &Attr, Sema &S) { // The iboutletcollection attribute can have zero or one arguments. - if (Attr.getNumArgs() > 1) { + if (Attr.getParameterName() && Attr.getNumArgs() > 0) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; return; } @@ -274,9 +277,41 @@ static void HandleIBOutletCollection(Decl *d, const AttributeList &Attr, S.Diag(Attr.getLoc(), diag::err_attribute_iboutlet) << Attr.getName(); return; } - - // FIXME: Eventually accept the type argument. - d->addAttr(::new (S.Context) IBOutletCollectionAttr()); + if (const ValueDecl *VD = dyn_cast(d)) + if (!VD->getType()->getAs()) { + S.Diag(Attr.getLoc(), diag::err_iboutletcollection_object_type) + << VD->getType() << 0; + return; + } + if (const ObjCPropertyDecl *PD = dyn_cast(d)) + if (!PD->getType()->getAs()) { + S.Diag(Attr.getLoc(), diag::err_iboutletcollection_object_type) + << PD->getType() << 1; + return; + } + + IdentifierInfo *II = Attr.getParameterName(); + if (!II) + II = &S.Context.Idents.get("id"); + + ParsedType TypeRep = S.getTypeName(*II, Attr.getLoc(), + S.getScopeForContext(d->getDeclContext()->getParent())); + if (!TypeRep) { + S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << II; + return; + } + QualType QT = TypeRep.get(); + // Diagnose use of non-object type in iboutletcollection attribute. + // FIXME. Gnu attribute extension ignores use of builtin types in + // attributes. So, __attribute__((iboutletcollection(char))) will be + // treated as __attribute__((iboutletcollection())). + if (!QT->isObjCIdType() && !QT->isObjCClassType() && + !QT->isObjCObjectType()) { + S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << II; + return; + } + d->addAttr(::new (S.Context) IBOutletCollectionAttr(Attr.getLoc(), S.Context, + QT)); } static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -321,7 +356,7 @@ static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) { QualType T = getFunctionOrMethodArgType(d, x); if (!T->isAnyPointerType() && !T->isBlockPointerType()) { // FIXME: Should also highlight argument in decl. - S.Diag(Attr.getLoc(), diag::err_nonnull_pointers_only) + S.Diag(Attr.getLoc(), diag::warn_nonnull_pointers_only) << "nonnull" << Ex->getSourceRange(); continue; } @@ -346,15 +381,162 @@ static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) { unsigned* start = &NonNullArgs[0]; unsigned size = NonNullArgs.size(); - std::sort(start, start + size); - d->addAttr(::new (S.Context) NonNullAttr(S.Context, start, size)); + llvm::array_pod_sort(start, start + size); + d->addAttr(::new (S.Context) NonNullAttr(Attr.getLoc(), S.Context, start, + size)); +} + +static void HandleOwnershipAttr(Decl *d, const AttributeList &AL, Sema &S) { + // This attribute must be applied to a function declaration. + // The first argument to the attribute must be a string, + // the name of the resource, for example "malloc". + // The following arguments must be argument indexes, the arguments must be + // of integer type for Returns, otherwise of pointer type. + // The difference between Holds and Takes is that a pointer may still be used + // after being held. free() should be __attribute((ownership_takes)), whereas + // a list append function may well be __attribute((ownership_holds)). + + if (!AL.getParameterName()) { + S.Diag(AL.getLoc(), diag::err_attribute_argument_n_not_string) + << AL.getName()->getName() << 1; + return; + } + // Figure out our Kind, and check arguments while we're at it. + OwnershipAttr::OwnershipKind K; + switch (AL.getKind()) { + case AttributeList::AT_ownership_takes: + K = OwnershipAttr::Takes; + if (AL.getNumArgs() < 1) { + S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2; + return; + } + break; + case AttributeList::AT_ownership_holds: + K = OwnershipAttr::Holds; + if (AL.getNumArgs() < 1) { + S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2; + return; + } + break; + case AttributeList::AT_ownership_returns: + K = OwnershipAttr::Returns; + if (AL.getNumArgs() > 1) { + S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) + << AL.getNumArgs() + 1; + return; + } + break; + default: + // This should never happen given how we are called. + llvm_unreachable("Unknown ownership attribute"); + } + + if (!isFunction(d) || !hasFunctionProto(d)) { + S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) << AL.getName() + << 0 /*function*/; + return; + } + + unsigned NumArgs = getFunctionOrMethodNumArgs(d); + + llvm::StringRef Module = AL.getParameterName()->getName(); + + // Normalize the argument, __foo__ becomes foo. + if (Module.startswith("__") && Module.endswith("__")) + Module = Module.substr(2, Module.size() - 4); + + llvm::SmallVector OwnershipArgs; + + for (AttributeList::arg_iterator I = AL.arg_begin(), E = AL.arg_end(); I != E; + ++I) { + + Expr *IdxExpr = static_cast(*I); + llvm::APSInt ArgNum(32); + if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() + || !IdxExpr->isIntegerConstantExpr(ArgNum, S.Context)) { + S.Diag(AL.getLoc(), diag::err_attribute_argument_not_int) + << AL.getName()->getName() << IdxExpr->getSourceRange(); + continue; + } + + unsigned x = (unsigned) ArgNum.getZExtValue(); + + if (x > NumArgs || x < 1) { + S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds) + << AL.getName()->getName() << x << IdxExpr->getSourceRange(); + continue; + } + --x; + switch (K) { + case OwnershipAttr::Takes: + case OwnershipAttr::Holds: { + // Is the function argument a pointer type? + QualType T = getFunctionOrMethodArgType(d, x); + if (!T->isAnyPointerType() && !T->isBlockPointerType()) { + // FIXME: Should also highlight argument in decl. + S.Diag(AL.getLoc(), diag::err_ownership_type) + << ((K==OwnershipAttr::Takes)?"ownership_takes":"ownership_holds") + << "pointer" + << IdxExpr->getSourceRange(); + continue; + } + break; + } + case OwnershipAttr::Returns: { + if (AL.getNumArgs() > 1) { + // Is the function argument an integer type? + Expr *IdxExpr = static_cast(AL.getArg(0)); + llvm::APSInt ArgNum(32); + if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() + || !IdxExpr->isIntegerConstantExpr(ArgNum, S.Context)) { + S.Diag(AL.getLoc(), diag::err_ownership_type) + << "ownership_returns" << "integer" + << IdxExpr->getSourceRange(); + return; + } + } + break; + } + default: + llvm_unreachable("Unknown ownership attribute"); + } // switch + + // Check we don't have a conflict with another ownership attribute. + for (specific_attr_iterator + i = d->specific_attr_begin(), + e = d->specific_attr_end(); + i != e; ++i) { + if ((*i)->getOwnKind() != K) { + for (const unsigned *I = (*i)->args_begin(), *E = (*i)->args_end(); + I!=E; ++I) { + if (x == *I) { + S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible) + << AL.getName()->getName() << "ownership_*"; + } + } + } + } + OwnershipArgs.push_back(x); + } + + unsigned* start = OwnershipArgs.data(); + unsigned size = OwnershipArgs.size(); + llvm::array_pod_sort(start, start + size); + + if (K != OwnershipAttr::Returns && OwnershipArgs.empty()) { + S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2; + return; + } + + d->addAttr(::new (S.Context) OwnershipAttr(AL.getLoc(), S.Context, K, Module, + start, size)); } static bool isStaticVarOrStaticFunciton(Decl *D) { if (VarDecl *VD = dyn_cast(D)) - return VD->getStorageClass() == VarDecl::Static; + return VD->getStorageClass() == SC_Static; if (FunctionDecl *FD = dyn_cast(D)) - return FD->getStorageClass() == FunctionDecl::Static; + return FD->getStorageClass() == SC_Static; return false; } @@ -375,13 +557,11 @@ static void HandleWeakRefAttr(Decl *d, const AttributeList &Attr, Sema &S) { // static int a __attribute__((weakref ("v2"))); // } // we reject them - if (const DeclContext *Ctx = d->getDeclContext()) { - Ctx = Ctx->getLookupContext(); - if (!isa(Ctx) && !isa(Ctx) ) { - S.Diag(Attr.getLoc(), diag::err_attribute_weakref_not_global_context) << - dyn_cast(d)->getNameAsString(); - return; - } + const DeclContext *Ctx = d->getDeclContext()->getRedeclContext(); + if (!Ctx->isFileContext()) { + S.Diag(Attr.getLoc(), diag::err_attribute_weakref_not_global_context) << + dyn_cast(d)->getNameAsString(); + return; } // The GCC manual says @@ -424,10 +604,10 @@ static void HandleWeakRefAttr(Decl *d, const AttributeList &Attr, Sema &S) { } // GCC will accept anything as the argument of weakref. Should we // check for an existing decl? - d->addAttr(::new (S.Context) AliasAttr(S.Context, Str->getString())); + d->addAttr(::new (S.Context) AliasAttr(Attr.getLoc(), S.Context, Str->getString())); } - d->addAttr(::new (S.Context) WeakRefAttr()); + d->addAttr(::new (S.Context) WeakRefAttr(Attr.getLoc(), S.Context)); } static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -449,7 +629,7 @@ static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) { // FIXME: check if target symbol exists in current file - d->addAttr(::new (S.Context) AliasAttr(S.Context, Str->getString())); + d->addAttr(::new (S.Context) AliasAttr(Attr.getLoc(), S.Context, Str->getString())); } static void HandleAlwaysInlineAttr(Decl *d, const AttributeList &Attr, @@ -466,7 +646,7 @@ static void HandleAlwaysInlineAttr(Decl *d, const AttributeList &Attr, return; } - d->addAttr(::new (S.Context) AlwaysInlineAttr()); + d->addAttr(::new (S.Context) AlwaysInlineAttr(Attr.getLoc(), S.Context)); } static void HandleMallocAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -479,7 +659,7 @@ static void HandleMallocAttr(Decl *d, const AttributeList &Attr, Sema &S) { if (const FunctionDecl *FD = dyn_cast(d)) { QualType RetTy = FD->getResultType(); if (RetTy->isAnyPointerType() || RetTy->isBlockPointerType()) { - d->addAttr(::new (S.Context) MallocAttr()); + d->addAttr(::new (S.Context) MallocAttr(Attr.getLoc(), S.Context)); return; } } @@ -487,39 +667,75 @@ static void HandleMallocAttr(Decl *d, const AttributeList &Attr, Sema &S) { S.Diag(Attr.getLoc(), diag::warn_attribute_malloc_pointer_only); } -static bool HandleCommonNoReturnAttr(Decl *d, const AttributeList &Attr, - Sema &S) { - // check the attribute arguments. +static void HandleNoReturnAttr(Decl *d, const AttributeList &Attr, Sema &S) { + /* Diagnostics (if any) was emitted by Sema::ProcessFnAttr(). */ + assert(Attr.isInvalid() == false); + d->addAttr(::new (S.Context) NoReturnAttr(Attr.getLoc(), S.Context)); +} + +static void HandleAnalyzerNoReturnAttr(Decl *d, const AttributeList &Attr, + Sema &S) { + + // The checking path for 'noreturn' and 'analyzer_noreturn' are different + // because 'analyzer_noreturn' does not impact the type. + if (Attr.getNumArgs() != 0) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; - return false; + return; } - + if (!isFunctionOrMethod(d) && !isa(d)) { ValueDecl *VD = dyn_cast(d); if (VD == 0 || (!VD->getType()->isBlockPointerType() && !VD->getType()->isFunctionPointerType())) { S.Diag(Attr.getLoc(), Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type - : diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 0 /*function*/; - return false; + : diag::warn_attribute_wrong_decl_type) + << Attr.getName() << 0 /*function*/; + return; } } - - return true; -} - -static void HandleNoReturnAttr(Decl *d, const AttributeList &Attr, Sema &S) { - /* Diagnostics (if any) was emitted by Sema::ProcessFnAttr(). */ - assert(Attr.isInvalid() == false); - d->addAttr(::new (S.Context) NoReturnAttr()); + + d->addAttr(::new (S.Context) AnalyzerNoReturnAttr(Attr.getLoc(), S.Context)); } -static void HandleAnalyzerNoReturnAttr(Decl *d, const AttributeList &Attr, +// PS3 PPU-specific. +static void HandleVecReturnAttr(Decl *d, const AttributeList &Attr, Sema &S) { - if (HandleCommonNoReturnAttr(d, Attr, S)) - d->addAttr(::new (S.Context) AnalyzerNoReturnAttr()); +/* + Returning a Vector Class in Registers + + According to the PPU ABI specifications, a class with a single member of vector type is returned in + memory when used as the return value of a function. This results in inefficient code when implementing + vector classes. To return the value in a single vector register, add the vecreturn attribute to the class + definition. This attribute is also applicable to struct types. + + Example: + + struct Vector + { + __vector float xyzw; + } __attribute__((vecreturn)); + + Vector Add(Vector lhs, Vector rhs) + { + Vector result; + result.xyzw = vec_add(lhs.xyzw, rhs.xyzw); + return result; // This will be returned in a register + } +*/ + if (!isa(d)) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) + << Attr.getName() << 9 /*class*/; + return; + } + + if (d->getAttr()) { + S.Diag(Attr.getLoc(), diag::err_repeat_attribute) << "vecreturn"; + return; + } + + d->addAttr(::new (S.Context) VecReturnAttr(Attr.getLoc(), S.Context)); } static void HandleDependencyAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -545,7 +761,7 @@ static void HandleUnusedAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) UnusedAttr()); + d->addAttr(::new (S.Context) UnusedAttr(Attr.getLoc(), S.Context)); } static void HandleUsedAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -566,7 +782,7 @@ static void HandleUsedAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) UsedAttr()); + d->addAttr(::new (S.Context) UsedAttr(Attr.getLoc(), S.Context)); } static void HandleConstructorAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -596,7 +812,7 @@ static void HandleConstructorAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) ConstructorAttr(priority)); + d->addAttr(::new (S.Context) ConstructorAttr(Attr.getLoc(), S.Context, priority)); } static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -626,7 +842,7 @@ static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) DestructorAttr(priority)); + d->addAttr(::new (S.Context) DestructorAttr(Attr.getLoc(), S.Context, priority)); } static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -636,7 +852,7 @@ static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) DeprecatedAttr()); + d->addAttr(::new (S.Context) DeprecatedAttr(Attr.getLoc(), S.Context)); } static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -646,7 +862,7 @@ static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) UnavailableAttr()); + d->addAttr(::new (S.Context) UnavailableAttr(Attr.getLoc(), S.Context)); } static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -667,22 +883,22 @@ static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) { } llvm::StringRef TypeStr = Str->getString(); - VisibilityAttr::VisibilityTypes type; + VisibilityAttr::VisibilityType type; if (TypeStr == "default") - type = VisibilityAttr::DefaultVisibility; + type = VisibilityAttr::Default; else if (TypeStr == "hidden") - type = VisibilityAttr::HiddenVisibility; + type = VisibilityAttr::Hidden; else if (TypeStr == "internal") - type = VisibilityAttr::HiddenVisibility; // FIXME + type = VisibilityAttr::Hidden; // FIXME else if (TypeStr == "protected") - type = VisibilityAttr::ProtectedVisibility; + type = VisibilityAttr::Protected; else { S.Diag(Attr.getLoc(), diag::warn_attribute_unknown_visibility) << TypeStr; return; } - d->addAttr(::new (S.Context) VisibilityAttr(type)); + d->addAttr(::new (S.Context) VisibilityAttr(Attr.getLoc(), S.Context, type)); } static void HandleObjCExceptionAttr(Decl *D, const AttributeList &Attr, @@ -698,7 +914,7 @@ static void HandleObjCExceptionAttr(Decl *D, const AttributeList &Attr, return; } - D->addAttr(::new (S.Context) ObjCExceptionAttr()); + D->addAttr(::new (S.Context) ObjCExceptionAttr(Attr.getLoc(), S.Context)); } static void HandleObjCNSObject(Decl *D, const AttributeList &Attr, Sema &S) { @@ -714,7 +930,7 @@ static void HandleObjCNSObject(Decl *D, const AttributeList &Attr, Sema &S) { return; } } - D->addAttr(::new (S.Context) ObjCNSObjectAttr()); + D->addAttr(::new (S.Context) ObjCNSObjectAttr(Attr.getLoc(), S.Context)); } static void @@ -729,7 +945,7 @@ HandleOverloadableAttr(Decl *D, const AttributeList &Attr, Sema &S) { return; } - D->addAttr(::new (S.Context) OverloadableAttr()); + D->addAttr(::new (S.Context) OverloadableAttr(Attr.getLoc(), S.Context)); } static void HandleBlocksAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -744,7 +960,7 @@ static void HandleBlocksAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - BlocksAttr::BlocksAttrTypes type; + BlocksAttr::BlockType type; if (Attr.getParameterName()->isStr("byref")) type = BlocksAttr::ByRef; else { @@ -753,7 +969,7 @@ static void HandleBlocksAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) BlocksAttr(type)); + d->addAttr(::new (S.Context) BlocksAttr(Attr.getLoc(), S.Context, type)); } static void HandleSentinelAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -846,7 +1062,7 @@ static void HandleSentinelAttr(Decl *d, const AttributeList &Attr, Sema &S) { << Attr.getName() << 6 /*function, method or block */; return; } - d->addAttr(::new (S.Context) SentinelAttr(sentinel, nullPos)); + d->addAttr(::new (S.Context) SentinelAttr(Attr.getLoc(), S.Context, sentinel, nullPos)); } static void HandleWarnUnusedResult(Decl *D, const AttributeList &Attr, Sema &S) { @@ -874,7 +1090,7 @@ static void HandleWarnUnusedResult(Decl *D, const AttributeList &Attr, Sema &S) return; } - D->addAttr(::new (S.Context) WarnUnusedResultAttr()); + D->addAttr(::new (S.Context) WarnUnusedResultAttr(Attr.getLoc(), S.Context)); } static void HandleWeakAttr(Decl *D, const AttributeList &Attr, Sema &S) { @@ -898,7 +1114,7 @@ static void HandleWeakAttr(Decl *D, const AttributeList &Attr, Sema &S) { return; } - D->addAttr(::new (S.Context) WeakAttr()); + D->addAttr(::new (S.Context) WeakAttr(Attr.getLoc(), S.Context)); } static void HandleWeakImportAttr(Decl *D, const AttributeList &Attr, Sema &S) { @@ -934,7 +1150,7 @@ static void HandleWeakImportAttr(Decl *D, const AttributeList &Attr, Sema &S) { return; } - D->addAttr(::new (S.Context) WeakImportAttr()); + D->addAttr(::new (S.Context) WeakImportAttr(Attr.getLoc(), S.Context)); } static void HandleReqdWorkGroupSize(Decl *D, const AttributeList &Attr, @@ -957,7 +1173,8 @@ static void HandleReqdWorkGroupSize(Decl *D, const AttributeList &Attr, } WGSize[i] = (unsigned) ArgNum.getZExtValue(); } - D->addAttr(::new (S.Context) ReqdWorkGroupSizeAttr(WGSize[0], WGSize[1], + D->addAttr(::new (S.Context) ReqdWorkGroupSizeAttr(Attr.getLoc(), S.Context, + WGSize[0], WGSize[1], WGSize[2])); } @@ -991,7 +1208,7 @@ static void HandleSectionAttr(Decl *D, const AttributeList &Attr, Sema &S) { return; } - D->addAttr(::new (S.Context) SectionAttr(S.Context, SE->getString())); + D->addAttr(::new (S.Context) SectionAttr(Attr.getLoc(), S.Context, SE->getString())); } @@ -1002,7 +1219,7 @@ static void HandleNothrowAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) NoThrowAttr()); + d->addAttr(::new (S.Context) NoThrowAttr(Attr.getLoc(), S.Context)); } static void HandleConstAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -1012,7 +1229,7 @@ static void HandleConstAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) ConstAttr()); + d->addAttr(::new (S.Context) ConstAttr(Attr.getLoc(), S.Context)); } static void HandlePureAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -1022,7 +1239,7 @@ static void HandlePureAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) PureAttr()); + d->addAttr(::new (S.Context) PureAttr(Attr.getLoc(), S.Context)); } static void HandleCleanupAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -1080,7 +1297,7 @@ static void HandleCleanupAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) CleanupAttr(FD)); + d->addAttr(::new (S.Context) CleanupAttr(Attr.getLoc(), S.Context, FD)); } /// Handle __attribute__((format_arg((idx)))) attribute based on @@ -1143,7 +1360,7 @@ static void HandleFormatArgAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) FormatArgAttr(Idx.getZExtValue())); + d->addAttr(::new (S.Context) FormatArgAttr(Attr.getLoc(), S.Context, Idx.getZExtValue())); } enum FormatAttrKind { @@ -1225,7 +1442,7 @@ static void HandleInitPriorityAttr(Decl *d, const AttributeList &Attr, Attr.setInvalid(); return; } - d->addAttr(::new (S.Context) InitPriorityAttr(prioritynum)); + d->addAttr(::new (S.Context) InitPriorityAttr(Attr.getLoc(), S.Context, prioritynum)); } /// Handle __attribute__((format(type,idx,firstarg))) attributes based on @@ -1369,7 +1586,8 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) FormatAttr(S.Context, Format, Idx.getZExtValue(), + d->addAttr(::new (S.Context) FormatAttr(Attr.getLoc(), S.Context, Format, + Idx.getZExtValue(), FirstArg.getZExtValue())); } @@ -1438,7 +1656,7 @@ static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr, } } - RD->addAttr(::new (S.Context) TransparentUnionAttr()); + RD->addAttr(::new (S.Context) TransparentUnionAttr(Attr.getLoc(), S.Context)); } static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -1456,7 +1674,7 @@ static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) { S.Diag(ArgExpr->getLocStart(), diag::err_attribute_not_string) <<"annotate"; return; } - d->addAttr(::new (S.Context) AnnotateAttr(S.Context, SE->getString())); + d->addAttr(::new (S.Context) AnnotateAttr(Attr.getLoc(), S.Context, SE->getString())); } static void HandleAlignedAttr(Decl *D, const AttributeList &Attr, Sema &S) { @@ -1471,9 +1689,7 @@ static void HandleAlignedAttr(Decl *D, const AttributeList &Attr, Sema &S) { // weaker alignment, rather than being silently ignored. if (Attr.getNumArgs() == 0) { - // FIXME: This should be the target specific maximum alignment. - // (For now we just use 128 bits which is the maximum on X86). - D->addAttr(::new (S.Context) AlignedAttr(128)); + D->addAttr(::new (S.Context) AlignedAttr(Attr.getLoc(), S.Context, true, 0)); return; } @@ -1483,10 +1699,11 @@ static void HandleAlignedAttr(Decl *D, const AttributeList &Attr, Sema &S) { void Sema::AddAlignedAttr(SourceLocation AttrLoc, Decl *D, Expr *E) { if (E->isTypeDependent() || E->isValueDependent()) { // Save dependent expressions in the AST to be instantiated. - D->addAttr(::new (Context) AlignedAttr(E)); + D->addAttr(::new (Context) AlignedAttr(AttrLoc, Context, true, E)); return; } + // FIXME: Cache the number on the Attr object? llvm::APSInt Alignment(32); if (!E->isIntegerConstantExpr(Alignment, Context)) { Diag(AttrLoc, diag::err_attribute_argument_not_int) @@ -1499,7 +1716,14 @@ void Sema::AddAlignedAttr(SourceLocation AttrLoc, Decl *D, Expr *E) { return; } - D->addAttr(::new (Context) AlignedAttr(Alignment.getZExtValue() * 8)); + D->addAttr(::new (Context) AlignedAttr(AttrLoc, Context, true, E)); +} + +void Sema::AddAlignedAttr(SourceLocation AttrLoc, Decl *D, TypeSourceInfo *TS) { + // FIXME: Cache the number on the Attr object if non-dependent? + // FIXME: Perform checking of type validity + D->addAttr(::new (Context) AlignedAttr(AttrLoc, Context, false, TS)); + return; } /// HandleModeAttr - This attribute modifies the width of a decl with primitive @@ -1686,7 +1910,7 @@ static void HandleNoDebugAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) NoDebugAttr()); + d->addAttr(::new (S.Context) NoDebugAttr(Attr.getLoc(), S.Context)); } static void HandleNoInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -1702,7 +1926,7 @@ static void HandleNoInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) NoInlineAttr()); + d->addAttr(::new (S.Context) NoInlineAttr(Attr.getLoc(), S.Context)); } static void HandleNoInstrumentFunctionAttr(Decl *d, const AttributeList &Attr, @@ -1719,7 +1943,7 @@ static void HandleNoInstrumentFunctionAttr(Decl *d, const AttributeList &Attr, return; } - d->addAttr(::new (S.Context) NoInstrumentFunctionAttr()); + d->addAttr(::new (S.Context) NoInstrumentFunctionAttr(Attr.getLoc(), S.Context)); } static void HandleGNUInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -1741,7 +1965,7 @@ static void HandleGNUInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) GNUInlineAttr()); + d->addAttr(::new (S.Context) GNUInlineAttr(Attr.getLoc(), S.Context)); } static void HandleCallConvAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -1751,15 +1975,19 @@ static void HandleCallConvAttr(Decl *d, const AttributeList &Attr, Sema &S) { switch (Attr.getKind()) { case AttributeList::AT_fastcall: - d->addAttr(::new (S.Context) FastCallAttr()); + d->addAttr(::new (S.Context) FastCallAttr(Attr.getLoc(), S.Context)); return; case AttributeList::AT_stdcall: - d->addAttr(::new (S.Context) StdCallAttr()); + d->addAttr(::new (S.Context) StdCallAttr(Attr.getLoc(), S.Context)); return; case AttributeList::AT_thiscall: - d->addAttr(::new (S.Context) ThisCallAttr()); + d->addAttr(::new (S.Context) ThisCallAttr(Attr.getLoc(), S.Context)); + return; case AttributeList::AT_cdecl: - d->addAttr(::new (S.Context) CDeclAttr()); + d->addAttr(::new (S.Context) CDeclAttr(Attr.getLoc(), S.Context)); + return; + case AttributeList::AT_pascal: + d->addAttr(::new (S.Context) PascalAttr(Attr.getLoc(), S.Context)); return; default: llvm_unreachable("unexpected attribute kind"); @@ -1801,7 +2029,8 @@ static void HandleRegparmAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) RegparmAttr(NumParams.getZExtValue())); + d->addAttr(::new (S.Context) RegparmAttr(Attr.getLoc(), S.Context, + NumParams.getZExtValue())); } static void HandleFinalAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -1827,7 +2056,7 @@ static void HandleFinalAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) FinalAttr()); + d->addAttr(::new (S.Context) FinalAttr(Attr.getLoc(), S.Context)); } //===----------------------------------------------------------------------===// @@ -1853,7 +2082,7 @@ static void HandleBaseCheckAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) BaseCheckAttr()); + d->addAttr(::new (S.Context) BaseCheckAttr(Attr.getLoc(), S.Context)); } static void HandleHidingAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -1878,7 +2107,7 @@ static void HandleHidingAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) HidingAttr()); + d->addAttr(::new (S.Context) HidingAttr(Attr.getLoc(), S.Context)); } static void HandleOverrideAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -1903,7 +2132,7 @@ static void HandleOverrideAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) OverrideAttr()); + d->addAttr(::new (S.Context) OverrideAttr(Attr.getLoc(), S.Context)); } //===----------------------------------------------------------------------===// @@ -1939,16 +2168,16 @@ static void HandleNSReturnsRetainedAttr(Decl *d, const AttributeList &Attr, assert(0 && "invalid ownership attribute"); return; case AttributeList::AT_cf_returns_not_retained: - d->addAttr(::new (S.Context) CFReturnsNotRetainedAttr()); + d->addAttr(::new (S.Context) CFReturnsNotRetainedAttr(Attr.getLoc(), S.Context)); return; case AttributeList::AT_ns_returns_not_retained: - d->addAttr(::new (S.Context) NSReturnsNotRetainedAttr()); + d->addAttr(::new (S.Context) NSReturnsNotRetainedAttr(Attr.getLoc(), S.Context)); return; case AttributeList::AT_cf_returns_retained: - d->addAttr(::new (S.Context) CFReturnsRetainedAttr()); + d->addAttr(::new (S.Context) CFReturnsRetainedAttr(Attr.getLoc(), S.Context)); return; case AttributeList::AT_ns_returns_retained: - d->addAttr(::new (S.Context) NSReturnsRetainedAttr()); + d->addAttr(::new (S.Context) NSReturnsRetainedAttr(Attr.getLoc(), S.Context)); return; }; } @@ -2009,9 +2238,14 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D, case AttributeList::AT_mode: HandleModeAttr (D, Attr, S); break; case AttributeList::AT_malloc: HandleMallocAttr (D, Attr, S); break; case AttributeList::AT_nonnull: HandleNonNullAttr (D, Attr, S); break; + case AttributeList::AT_ownership_returns: + case AttributeList::AT_ownership_takes: + case AttributeList::AT_ownership_holds: + HandleOwnershipAttr (D, Attr, S); break; case AttributeList::AT_noreturn: HandleNoReturnAttr (D, Attr, S); break; case AttributeList::AT_nothrow: HandleNothrowAttr (D, Attr, S); break; case AttributeList::AT_override: HandleOverrideAttr (D, Attr, S); break; + case AttributeList::AT_vecreturn: HandleVecReturnAttr (D, Attr, S); break; // Checker-specific. case AttributeList::AT_ns_returns_not_retained: @@ -2063,6 +2297,7 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D, case AttributeList::AT_cdecl: case AttributeList::AT_fastcall: case AttributeList::AT_thiscall: + case AttributeList::AT_pascal: HandleCallConvAttr(D, Attr, S); break; default: @@ -2087,7 +2322,7 @@ void Sema::ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *Attr // but that looks really pointless. We reject it. if (D->hasAttr() && !D->hasAttr()) { Diag(AttrList->getLoc(), diag::err_attribute_weakref_without_alias) << - dyn_cast(D)->getNameAsString(); + dyn_cast(D)->getNameAsString(); return; } } @@ -2127,8 +2362,9 @@ void Sema::DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W) { if (W.getAlias()) { // clone decl, impersonate __attribute(weak,alias(...)) IdentifierInfo *NDId = ND->getIdentifier(); NamedDecl *NewD = DeclClonePragmaWeak(ND, W.getAlias()); - NewD->addAttr(::new (Context) AliasAttr(Context, NDId->getName())); - NewD->addAttr(::new (Context) WeakAttr()); + NewD->addAttr(::new (Context) AliasAttr(W.getLocation(), Context, + NDId->getName())); + NewD->addAttr(::new (Context) WeakAttr(W.getLocation(), Context)); WeakTopLevelDecl.push_back(NewD); // FIXME: "hideous" code from Sema::LazilyCreateBuiltin // to insert Decl at TU scope, sorry. @@ -2137,7 +2373,7 @@ void Sema::DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W) { PushOnScopeChains(NewD, S); CurContext = SavedContext; } else { // just add weak to existing - ND->addAttr(::new (Context) WeakAttr()); + ND->addAttr(::new (Context) WeakAttr(W.getLocation(), Context)); } } @@ -2179,12 +2415,12 @@ void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) { /// /// The state token we use is the start index of this scope /// on the warning stack. -Action::ParsingDeclStackState Sema::PushParsingDeclaration() { +Sema::ParsingDeclStackState Sema::PushParsingDeclaration() { ParsingDeclDepth++; return (ParsingDeclStackState) DelayedDiagnostics.size(); } -void Sema::PopParsingDeclaration(ParsingDeclStackState S, DeclPtrTy Ctx) { +void Sema::PopParsingDeclaration(ParsingDeclStackState S, Decl *D) { assert(ParsingDeclDepth > 0 && "empty ParsingDeclaration stack"); ParsingDeclDepth--; @@ -2199,7 +2435,6 @@ void Sema::PopParsingDeclaration(ParsingDeclStackState S, DeclPtrTy Ctx) { // We only want to actually emit delayed diagnostics when we // successfully parsed a decl. - Decl *D = Ctx ? Ctx.getAs() : 0; if (D) { // We really do want to start with 0 here. We get one push for a // decl spec and another for each declarator; in a decl group like: @@ -2238,7 +2473,7 @@ static bool isDeclDeprecated(Decl *D) { return false; } -void Sema::HandleDelayedDeprecationCheck(Sema::DelayedDiagnostic &DD, +void Sema::HandleDelayedDeprecationCheck(DelayedDiagnostic &DD, Decl *Ctx) { if (isDeclDeprecated(Ctx)) return; diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index bd97df2ce9d1..63acdb5f1cc6 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -11,9 +11,11 @@ // //===----------------------------------------------------------------------===// -#include "Sema.h" -#include "SemaInit.h" -#include "Lookup.h" +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/CXXFieldCollector.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/Initialization.h" +#include "clang/Sema/Lookup.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/CharUnits.h" @@ -23,10 +25,11 @@ #include "clang/AST/StmtVisitor.h" #include "clang/AST/TypeLoc.h" #include "clang/AST/TypeOrdering.h" -#include "clang/Parse/DeclSpec.h" -#include "clang/Parse/Template.h" +#include "clang/Sema/DeclSpec.h" +#include "clang/Sema/ParsedTemplate.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Lex/Preprocessor.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/STLExtras.h" #include #include @@ -108,7 +111,7 @@ namespace { } bool -Sema::SetParamDefaultArgument(ParmVarDecl *Param, ExprArg DefaultArg, +Sema::SetParamDefaultArgument(ParmVarDecl *Param, Expr *Arg, SourceLocation EqualLoc) { if (RequireCompleteType(Param->getLocation(), Param->getType(), diag::err_typecheck_decl_incomplete_type)) { @@ -116,8 +119,6 @@ Sema::SetParamDefaultArgument(ParmVarDecl *Param, ExprArg DefaultArg, return true; } - Expr *Arg = (Expr *)DefaultArg.get(); - // C++ [dcl.fct.default]p5 // A default argument expression is implicitly converted (clause // 4) to the parameter type. The default argument expression has @@ -128,8 +129,8 @@ Sema::SetParamDefaultArgument(ParmVarDecl *Param, ExprArg DefaultArg, InitializationKind Kind = InitializationKind::CreateCopy(Param->getLocation(), EqualLoc); InitializationSequence InitSeq(*this, Entity, Kind, &Arg, 1); - OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind, - MultiExprArg(*this, (void**)&Arg, 1)); + ExprResult Result = InitSeq.Perform(*this, Entity, Kind, + MultiExprArg(*this, &Arg, 1)); if (Result.isInvalid()) return true; Arg = Result.takeAs(); @@ -139,8 +140,6 @@ Sema::SetParamDefaultArgument(ParmVarDecl *Param, ExprArg DefaultArg, // Okay: add the default argument to the parameter Param->setDefaultArg(Arg); - DefaultArg.release(); - return false; } @@ -148,16 +147,14 @@ Sema::SetParamDefaultArgument(ParmVarDecl *Param, ExprArg DefaultArg, /// provided for a function parameter is well-formed. If so, attach it /// to the parameter declaration. void -Sema::ActOnParamDefaultArgument(DeclPtrTy param, SourceLocation EqualLoc, - ExprArg defarg) { - if (!param || !defarg.get()) +Sema::ActOnParamDefaultArgument(Decl *param, SourceLocation EqualLoc, + Expr *DefaultArg) { + if (!param || !DefaultArg) return; - ParmVarDecl *Param = cast(param.getAs()); + ParmVarDecl *Param = cast(param); UnparsedDefaultArgLocs.erase(Param); - ExprOwningPtr DefaultArg(this, defarg.takeAs()); - // Default arguments are only permitted in C++ if (!getLangOptions().CPlusPlus) { Diag(EqualLoc, diag::err_param_default_argument) @@ -167,26 +164,26 @@ Sema::ActOnParamDefaultArgument(DeclPtrTy param, SourceLocation EqualLoc, } // Check that the default argument is well-formed - CheckDefaultArgumentVisitor DefaultArgChecker(DefaultArg.get(), this); - if (DefaultArgChecker.Visit(DefaultArg.get())) { + CheckDefaultArgumentVisitor DefaultArgChecker(DefaultArg, this); + if (DefaultArgChecker.Visit(DefaultArg)) { Param->setInvalidDecl(); return; } - SetParamDefaultArgument(Param, move(DefaultArg), EqualLoc); + SetParamDefaultArgument(Param, DefaultArg, EqualLoc); } /// 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. -void Sema::ActOnParamUnparsedDefaultArgument(DeclPtrTy param, +void Sema::ActOnParamUnparsedDefaultArgument(Decl *param, SourceLocation EqualLoc, SourceLocation ArgLoc) { if (!param) return; - ParmVarDecl *Param = cast(param.getAs()); + ParmVarDecl *Param = cast(param); if (Param) Param->setUnparsedDefaultArg(); @@ -195,11 +192,11 @@ void Sema::ActOnParamUnparsedDefaultArgument(DeclPtrTy param, /// ActOnParamDefaultArgumentError - Parsing or semantic analysis of /// the default argument for the parameter param failed. -void Sema::ActOnParamDefaultArgumentError(DeclPtrTy param) { +void Sema::ActOnParamDefaultArgumentError(Decl *param) { if (!param) return; - ParmVarDecl *Param = cast(param.getAs()); + ParmVarDecl *Param = cast(param); Param->setInvalidDecl(); @@ -224,7 +221,7 @@ void Sema::CheckExtraCXXDefaultArguments(Declarator &D) { if (chunk.Kind == DeclaratorChunk::Function) { for (unsigned argIdx = 0, e = chunk.Fun.NumArgs; argIdx != e; ++argIdx) { ParmVarDecl *Param = - cast(chunk.Fun.ArgInfo[argIdx].Param.getAs()); + cast(chunk.Fun.ArgInfo[argIdx].Param); if (Param->hasUnparsedDefaultArg()) { CachedTokens *Toks = chunk.Fun.ArgInfo[argIdx].DefaultArgTokens; Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc) @@ -412,8 +409,6 @@ void Sema::CheckCXXDefaultArguments(FunctionDecl *FD) { for (p = 0; p <= LastMissingDefaultArg; ++p) { ParmVarDecl *Param = FD->getParamDecl(p); if (Param->hasDefaultArg()) { - if (!Param->hasUnparsedDefaultArg()) - Param->getDefaultArg()->Destroy(Context); Param->setDefaultArg(0); } } @@ -449,8 +444,9 @@ CXXBaseSpecifier * Sema::CheckBaseSpecifier(CXXRecordDecl *Class, SourceRange SpecifierRange, bool Virtual, AccessSpecifier Access, - QualType BaseType, - SourceLocation BaseLoc) { + TypeSourceInfo *TInfo) { + QualType BaseType = TInfo->getType(); + // C++ [class.union]p1: // A union shall not have base classes. if (Class->isUnion()) { @@ -461,8 +457,10 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, if (BaseType->isDependentType()) return new (Context) CXXBaseSpecifier(SpecifierRange, Virtual, - Class->getTagKind() == TTK_Class, - Access, BaseType); + Class->getTagKind() == TTK_Class, + Access, TInfo); + + SourceLocation BaseLoc = TInfo->getTypeLoc().getBeginLoc(); // Base specifiers must be record types. if (!BaseType->isRecordType()) { @@ -482,8 +480,10 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, // defined class. if (RequireCompleteType(BaseLoc, BaseType, PDiag(diag::err_incomplete_base_class) - << SpecifierRange)) + << SpecifierRange)) { + Class->setInvalidDecl(); return 0; + } // If the base class is polymorphic or isn't empty, the new one is/isn't, too. RecordDecl *BaseDecl = BaseType->getAs()->getDecl(); @@ -502,11 +502,14 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, } SetClassDeclAttributesFromBase(Class, CXXBaseDecl, Virtual); + + if (BaseDecl->isInvalidDecl()) + Class->setInvalidDecl(); // Create the base specifier. return new (Context) CXXBaseSpecifier(SpecifierRange, Virtual, - Class->getTagKind() == TTK_Class, - Access, BaseType); + Class->getTagKind() == TTK_Class, + Access, TInfo); } void Sema::SetClassDeclAttributesFromBase(CXXRecordDecl *Class, @@ -581,22 +584,22 @@ void Sema::SetClassDeclAttributesFromBase(CXXRecordDecl *Class, /// example: /// class foo : public bar, virtual private baz { /// 'public bar' and 'virtual private baz' are each base-specifiers. -Sema::BaseResult -Sema::ActOnBaseSpecifier(DeclPtrTy classdecl, SourceRange SpecifierRange, +BaseResult +Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange, bool Virtual, AccessSpecifier Access, - TypeTy *basetype, SourceLocation BaseLoc) { + ParsedType basetype, SourceLocation BaseLoc) { if (!classdecl) return true; AdjustDeclIfTemplate(classdecl); - CXXRecordDecl *Class = dyn_cast(classdecl.getAs()); + CXXRecordDecl *Class = dyn_cast(classdecl); if (!Class) return true; - QualType BaseType = GetTypeFromParser(basetype); + TypeSourceInfo *TInfo = 0; + GetTypeFromParser(basetype, &TInfo); if (CXXBaseSpecifier *BaseSpec = CheckBaseSpecifier(Class, SpecifierRange, - Virtual, Access, - BaseType, BaseLoc)) + Virtual, Access, TInfo)) return BaseSpec; return true; @@ -664,13 +667,13 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases, /// ActOnBaseSpecifiers - Attach the given base specifiers to the /// class, after checking whether there are any duplicate base /// classes. -void Sema::ActOnBaseSpecifiers(DeclPtrTy ClassDecl, BaseTy **Bases, +void Sema::ActOnBaseSpecifiers(Decl *ClassDecl, BaseTy **Bases, unsigned NumBases) { if (!ClassDecl || !Bases || !NumBases) return; AdjustDeclIfTemplate(ClassDecl); - AttachBaseSpecifiers(cast(ClassDecl.getAs()), + AttachBaseSpecifiers(cast(ClassDecl), (CXXBaseSpecifier**)(Bases), NumBases); } @@ -719,7 +722,7 @@ bool Sema::IsDerivedFrom(QualType Derived, QualType Base, CXXBasePaths &Paths) { } void Sema::BuildBasePathArray(const CXXBasePaths &Paths, - CXXBaseSpecifierArray &BasePathArray) { + CXXCastPath &BasePathArray) { assert(BasePathArray.empty() && "Base path array must be empty!"); assert(Paths.isRecordingPaths() && "Must record paths!"); @@ -738,14 +741,14 @@ void Sema::BuildBasePathArray(const CXXBasePaths &Paths, // Now add all bases. for (unsigned I = Start, E = Path.size(); I != E; ++I) - BasePathArray.push_back(Path[I].Base); + BasePathArray.push_back(const_cast(Path[I].Base)); } /// \brief Determine whether the given base path includes a virtual /// base class. -bool Sema::BasePathInvolvesVirtualBase(const CXXBaseSpecifierArray &BasePath) { - for (CXXBaseSpecifierArray::iterator B = BasePath.begin(), - BEnd = BasePath.end(); +bool Sema::BasePathInvolvesVirtualBase(const CXXCastPath &BasePath) { + for (CXXCastPath::const_iterator B = BasePath.begin(), + BEnd = BasePath.end(); B != BEnd; ++B) if ((*B)->isVirtual()) return true; @@ -767,7 +770,7 @@ Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, unsigned AmbigiousBaseConvID, SourceLocation Loc, SourceRange Range, DeclarationName Name, - CXXBaseSpecifierArray *BasePath) { + CXXCastPath *BasePath) { // First, determine whether the path from Derived to Base is // ambiguous. This is slightly more expensive than checking whether // the Derived to Base conversion exists, because here we need to @@ -825,7 +828,7 @@ Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, bool Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, SourceLocation Loc, SourceRange Range, - CXXBaseSpecifierArray *BasePath, + CXXCastPath *BasePath, bool IgnoreAccess) { return CheckDerivedToBaseConversion(Derived, Base, IgnoreAccess ? 0 @@ -872,30 +875,31 @@ std::string Sema::getAmbiguousPathsDisplayString(CXXBasePaths &Paths) { //===----------------------------------------------------------------------===// /// ActOnAccessSpecifier - Parsed an access specifier followed by a colon. -Sema::DeclPtrTy -Sema::ActOnAccessSpecifier(AccessSpecifier Access, - SourceLocation ASLoc, SourceLocation ColonLoc) { +Decl *Sema::ActOnAccessSpecifier(AccessSpecifier Access, + SourceLocation ASLoc, + SourceLocation ColonLoc) { assert(Access != AS_none && "Invalid kind for syntactic access specifier!"); - AccessSpecDecl* ASDecl = AccessSpecDecl::Create(Context, Access, CurContext, + AccessSpecDecl *ASDecl = AccessSpecDecl::Create(Context, Access, CurContext, ASLoc, ColonLoc); CurContext->addHiddenDecl(ASDecl); - return DeclPtrTy::make(ASDecl); + return ASDecl; } /// ActOnCXXMemberDeclarator - This is invoked when a C++ class member /// declarator is parsed. 'AS' is the access specifier, 'BW' specifies the /// bitfield width if there is one and 'InitExpr' specifies the initializer if /// any. -Sema::DeclPtrTy +Decl * Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, MultiTemplateParamsArg TemplateParameterLists, ExprTy *BW, ExprTy *InitExpr, bool IsDefinition, bool Deleted) { const DeclSpec &DS = D.getDeclSpec(); - DeclarationName Name = GetNameForDeclarator(D); + DeclarationNameInfo NameInfo = GetNameForDeclarator(D); + DeclarationName Name = NameInfo.getName(); + SourceLocation Loc = NameInfo.getLoc(); Expr *BitWidth = static_cast(BW); Expr *Init = static_cast(InitExpr); - SourceLocation Loc = D.getIdentifierLoc(); assert(isa(CurContext)); assert(!DS.isFriendSpecified()); @@ -905,7 +909,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, isFunc = true; else if (D.getNumTypeObjects() == 0 && D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_typename) { - QualType TDType = GetTypeFromParser(DS.getTypeRep()); + QualType TDType = GetTypeFromParser(DS.getRepAsType()); isFunc = TDType->isFunctionType(); } @@ -952,11 +956,9 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, AS); assert(Member && "HandleField never returns null"); } else { - Member = HandleDeclarator(S, D, move(TemplateParameterLists), IsDefinition) - .getAs(); + Member = HandleDeclarator(S, D, move(TemplateParameterLists), IsDefinition); if (!Member) { - if (BitWidth) DeleteExpr(BitWidth); - return DeclPtrTy(); + return 0; } // Non-instance-fields can't have a bitfield. @@ -980,7 +982,6 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, << BitWidth->getSourceRange(); } - DeleteExpr(BitWidth); BitWidth = 0; Member->setInvalidDecl(); } @@ -996,15 +997,15 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, assert((Name || isInstField) && "No identifier for non-field ?"); if (Init) - AddInitializerToDecl(DeclPtrTy::make(Member), ExprArg(*this, Init), false); + AddInitializerToDecl(Member, Init, false); if (Deleted) // FIXME: Source location is not very good. - SetDeclDeleted(DeclPtrTy::make(Member), D.getSourceRange().getBegin()); + SetDeclDeleted(Member, D.getSourceRange().getBegin()); if (isInstField) { FieldCollector->Add(cast(Member)); - return DeclPtrTy(); + return 0; } - return DeclPtrTy::make(Member); + return Member; } /// \brief Find the direct and/or virtual base specifiers that @@ -1053,12 +1054,12 @@ static bool FindBaseInitializer(Sema &SemaRef, } /// ActOnMemInitializer - Handle a C++ member initializer. -Sema::MemInitResult -Sema::ActOnMemInitializer(DeclPtrTy ConstructorD, +MemInitResult +Sema::ActOnMemInitializer(Decl *ConstructorD, Scope *S, CXXScopeSpec &SS, IdentifierInfo *MemberOrBase, - TypeTy *TemplateTypeTy, + ParsedType TemplateTypeTy, SourceLocation IdLoc, SourceLocation LParenLoc, ExprTy **Args, unsigned NumArgs, @@ -1070,7 +1071,7 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD, AdjustDeclIfTemplate(ConstructorD); CXXConstructorDecl *Constructor - = dyn_cast(ConstructorD.getAs()); + = dyn_cast(ConstructorD); if (!Constructor) { // The user wrote a constructor initializer on a function that is // not a C++ constructor. Ignore the error for now, because we may @@ -1148,7 +1149,7 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD, CorrectTypo(R, S, &SS, ClassDecl, 0, CTC_NoKeywords) && R.isSingleResult()) { if (FieldDecl *Member = R.getAsSingle()) { - if (Member->getDeclContext()->getLookupContext()->Equals(ClassDecl)) { + if (Member->getDeclContext()->getRedeclContext()->Equals(ClassDecl)) { // We have found a non-static data member with a similar // name to what was typed; complain and initialize that // member. @@ -1259,7 +1260,7 @@ static bool InitExprContainsUninitializedFields(const Stmt *S, return false; } -Sema::MemInitResult +MemInitResult Sema::BuildMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs, SourceLocation IdLoc, SourceLocation LParenLoc, @@ -1285,15 +1286,12 @@ Sema::BuildMemberInitializer(FieldDecl *Member, Expr **Args, for (unsigned i = 0; i < NumArgs; i++) HasDependentArg |= Args[i]->isTypeDependent(); - QualType FieldType = Member->getType(); - if (const ArrayType *Array = Context.getAsArrayType(FieldType)) - FieldType = Array->getElementType(); - if (FieldType->isDependentType() || HasDependentArg) { + if (Member->getType()->isDependentType() || HasDependentArg) { // Can't check initialization for a member of dependent type or when // any of the arguments are type-dependent expressions. - OwningExprResult Init - = Owned(new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs, - RParenLoc)); + Expr *Init + = new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs, + RParenLoc); // Erase any temporaries within this evaluation context; we're not // going to track them in the AST, since we'll be rebuilding the @@ -1304,7 +1302,7 @@ Sema::BuildMemberInitializer(FieldDecl *Member, Expr **Args, return new (Context) CXXBaseOrMemberInitializer(Context, Member, IdLoc, LParenLoc, - Init.takeAs(), + Init, RParenLoc); } @@ -1320,16 +1318,16 @@ Sema::BuildMemberInitializer(FieldDecl *Member, Expr **Args, InitializationSequence InitSeq(*this, MemberEntity, Kind, Args, NumArgs); - OwningExprResult MemberInit = + ExprResult MemberInit = InitSeq.Perform(*this, MemberEntity, Kind, - MultiExprArg(*this, (void**)Args, NumArgs), 0); + MultiExprArg(*this, Args, NumArgs), 0); if (MemberInit.isInvalid()) return true; // C++0x [class.base.init]p7: // The initialization of each base and member constitutes a // full-expression. - MemberInit = MaybeCreateCXXExprWithTemporaries(move(MemberInit)); + MemberInit = MaybeCreateCXXExprWithTemporaries(MemberInit.get()); if (MemberInit.isInvalid()) return true; @@ -1345,22 +1343,21 @@ Sema::BuildMemberInitializer(FieldDecl *Member, Expr **Args, for (unsigned I = 0; I != NumArgs; ++I) Args[I]->Retain(); - OwningExprResult Init - = Owned(new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs, - RParenLoc)); + Expr *Init = new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs, + RParenLoc); return new (Context) CXXBaseOrMemberInitializer(Context, Member, IdLoc, LParenLoc, - Init.takeAs(), + Init, RParenLoc); } return new (Context) CXXBaseOrMemberInitializer(Context, Member, IdLoc, LParenLoc, - MemberInit.takeAs(), + MemberInit.get(), RParenLoc); } -Sema::MemInitResult +MemInitResult Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, Expr **Args, unsigned NumArgs, SourceLocation LParenLoc, SourceLocation RParenLoc, @@ -1413,7 +1410,7 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, if (Dependent) { // Can't check initialization for a base of dependent type or when // any of the arguments are type-dependent expressions. - OwningExprResult BaseInit + ExprResult BaseInit = Owned(new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs, RParenLoc)); @@ -1452,16 +1449,16 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, InitializationSequence InitSeq(*this, BaseEntity, Kind, Args, NumArgs); - OwningExprResult BaseInit = + ExprResult BaseInit = InitSeq.Perform(*this, BaseEntity, Kind, - MultiExprArg(*this, (void**)Args, NumArgs), 0); + MultiExprArg(*this, Args, NumArgs), 0); if (BaseInit.isInvalid()) return true; // C++0x [class.base.init]p7: // The initialization of each base and member constitutes a // full-expression. - BaseInit = MaybeCreateCXXExprWithTemporaries(move(BaseInit)); + BaseInit = MaybeCreateCXXExprWithTemporaries(BaseInit.get()); if (BaseInit.isInvalid()) return true; @@ -1477,7 +1474,7 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, for (unsigned I = 0; I != NumArgs; ++I) Args[I]->Retain(); - OwningExprResult Init + ExprResult Init = Owned(new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs, RParenLoc)); return new (Context) CXXBaseOrMemberInitializer(Context, BaseTInfo, @@ -1512,7 +1509,7 @@ BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, = InitializedEntity::InitializeBase(SemaRef.Context, BaseSpec, IsInheritedVirtualBase); - Sema::OwningExprResult BaseInit(SemaRef); + ExprResult BaseInit; switch (ImplicitInitKind) { case IIK_Default: { @@ -1520,7 +1517,7 @@ BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, = InitializationKind::CreateDefault(Constructor->getLocation()); InitializationSequence InitSeq(SemaRef, InitEntity, InitKind, 0, 0); BaseInit = InitSeq.Perform(SemaRef, InitEntity, InitKind, - Sema::MultiExprArg(SemaRef, 0, 0)); + MultiExprArg(SemaRef, 0, 0)); break; } @@ -1536,10 +1533,12 @@ BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, QualType ArgTy = SemaRef.Context.getQualifiedType(BaseSpec->getType().getUnqualifiedType(), ParamType.getQualifiers()); - SemaRef.ImpCastExprToType(CopyCtorArg, ArgTy, - CastExpr::CK_UncheckedDerivedToBase, - /*isLvalue=*/true, - CXXBaseSpecifierArray(BaseSpec)); + + CXXCastPath BasePath; + BasePath.push_back(BaseSpec); + SemaRef.ImpCastExprToType(CopyCtorArg, ArgTy, + CK_UncheckedDerivedToBase, + VK_LValue, &BasePath); InitializationKind InitKind = InitializationKind::CreateDirect(Constructor->getLocation(), @@ -1547,16 +1546,18 @@ BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, InitializationSequence InitSeq(SemaRef, InitEntity, InitKind, &CopyCtorArg, 1); BaseInit = InitSeq.Perform(SemaRef, InitEntity, InitKind, - Sema::MultiExprArg(SemaRef, - (void**)&CopyCtorArg, 1)); + MultiExprArg(&CopyCtorArg, 1)); break; } case IIK_Move: assert(false && "Unhandled initializer kind!"); } + + if (BaseInit.isInvalid()) + return true; - BaseInit = SemaRef.MaybeCreateCXXExprWithTemporaries(move(BaseInit)); + BaseInit = SemaRef.MaybeCreateCXXExprWithTemporaries(BaseInit.get()); if (BaseInit.isInvalid()) return true; @@ -1596,8 +1597,8 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, Sema::LookupMemberName); MemberLookup.addDecl(Field, AS_public); MemberLookup.resolveKind(); - Sema::OwningExprResult CopyCtorArg - = SemaRef.BuildMemberReferenceExpr(SemaRef.Owned(MemberExprBase), + ExprResult CopyCtorArg + = SemaRef.BuildMemberReferenceExpr(MemberExprBase, ParamType, Loc, /*IsArrow=*/false, SS, @@ -1628,19 +1629,19 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, = VarDecl::Create(SemaRef.Context, SemaRef.CurContext, Loc, IterationVarName, SizeType, SemaRef.Context.getTrivialTypeSourceInfo(SizeType, Loc), - VarDecl::None, VarDecl::None); + SC_None, SC_None); IndexVariables.push_back(IterationVar); // Create a reference to the iteration variable. - Sema::OwningExprResult IterationVarRef + ExprResult IterationVarRef = SemaRef.BuildDeclRefExpr(IterationVar, SizeType, Loc); assert(!IterationVarRef.isInvalid() && "Reference to invented variable cannot fail!"); // Subscript the array with this iteration variable. - CopyCtorArg = SemaRef.CreateBuiltinArraySubscriptExpr(move(CopyCtorArg), + CopyCtorArg = SemaRef.CreateBuiltinArraySubscriptExpr(CopyCtorArg.take(), Loc, - move(IterationVarRef), + IterationVarRef.take(), Loc); if (CopyCtorArg.isInvalid()) return true; @@ -1667,10 +1668,10 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, InitializationSequence InitSeq(SemaRef, Entities.back(), InitKind, &CopyCtorArgE, 1); - Sema::OwningExprResult MemberInit + ExprResult MemberInit = InitSeq.Perform(SemaRef, Entities.back(), InitKind, - Sema::MultiExprArg(SemaRef, (void**)&CopyCtorArgE, 1)); - MemberInit = SemaRef.MaybeCreateCXXExprWithTemporaries(move(MemberInit)); + MultiExprArg(&CopyCtorArgE, 1)); + MemberInit = SemaRef.MaybeCreateCXXExprWithTemporaries(MemberInit.get()); if (MemberInit.isInvalid()) return true; @@ -1693,17 +1694,19 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, InitializationKind::CreateDefault(Loc); InitializationSequence InitSeq(SemaRef, InitEntity, InitKind, 0, 0); - Sema::OwningExprResult MemberInit = - InitSeq.Perform(SemaRef, InitEntity, InitKind, - Sema::MultiExprArg(SemaRef, 0, 0)); - MemberInit = SemaRef.MaybeCreateCXXExprWithTemporaries(move(MemberInit)); + ExprResult MemberInit = + InitSeq.Perform(SemaRef, InitEntity, InitKind, MultiExprArg()); + if (MemberInit.isInvalid()) + return true; + + MemberInit = SemaRef.MaybeCreateCXXExprWithTemporaries(MemberInit.get()); if (MemberInit.isInvalid()) return true; CXXMemberInit = new (SemaRef.Context) CXXBaseOrMemberInitializer(SemaRef.Context, Field, Loc, Loc, - MemberInit.takeAs(), + MemberInit.get(), Loc); return false; } @@ -1797,6 +1800,9 @@ static bool CollectFieldInitializer(BaseAndFieldInfo &Info, // Once we've initialized a field of an anonymous union, the union // field in the class is also initialized, so exit immediately. return false; + } else if ((*FA)->isAnonymousStructOrUnion()) { + if (CollectFieldInitializer(Info, Top, *FA)) + return true; } } @@ -2147,7 +2153,7 @@ bool CheckRedundantUnionInit(Sema &S, } /// ActOnMemInitializers - Handle the member initializers for a constructor. -void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl, +void Sema::ActOnMemInitializers(Decl *ConstructorDecl, SourceLocation ColonLoc, MemInitTy **meminits, unsigned NumMemInits, bool AnyErrors) { @@ -2157,7 +2163,7 @@ void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl, AdjustDeclIfTemplate(ConstructorDecl); CXXConstructorDecl *Constructor - = dyn_cast(ConstructorDecl.getAs()); + = dyn_cast(ConstructorDecl); if (!Constructor) { Diag(ColonLoc, diag::err_only_constructors_take_base_inits); @@ -2292,35 +2298,30 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location, } } -void Sema::ActOnDefaultCtorInitializers(DeclPtrTy CDtorDecl) { +void Sema::ActOnDefaultCtorInitializers(Decl *CDtorDecl) { if (!CDtorDecl) return; if (CXXConstructorDecl *Constructor - = dyn_cast(CDtorDecl.getAs())) + = dyn_cast(CDtorDecl)) SetBaseOrMemberInitializers(Constructor, 0, 0, /*AnyErrors=*/false); } bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T, - unsigned DiagID, AbstractDiagSelID SelID, - const CXXRecordDecl *CurrentRD) { + unsigned DiagID, AbstractDiagSelID SelID) { if (SelID == -1) - return RequireNonAbstractType(Loc, T, - PDiag(DiagID), CurrentRD); + return RequireNonAbstractType(Loc, T, PDiag(DiagID)); else - return RequireNonAbstractType(Loc, T, - PDiag(DiagID) << SelID, CurrentRD); + return RequireNonAbstractType(Loc, T, PDiag(DiagID) << SelID); } bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T, - const PartialDiagnostic &PD, - const CXXRecordDecl *CurrentRD) { + const PartialDiagnostic &PD) { if (!getLangOptions().CPlusPlus) return false; if (const ArrayType *AT = Context.getAsArrayType(T)) - return RequireNonAbstractType(Loc, AT->getElementType(), PD, - CurrentRD); + return RequireNonAbstractType(Loc, AT->getElementType(), PD); if (const PointerType *PT = T->getAs()) { // Find the innermost pointer type. @@ -2328,7 +2329,7 @@ bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T, PT = T; if (const ArrayType *AT = Context.getAsArrayType(PT->getPointeeType())) - return RequireNonAbstractType(Loc, AT->getElementType(), PD, CurrentRD); + return RequireNonAbstractType(Loc, AT->getElementType(), PD); } const RecordType *RT = T->getAs(); @@ -2337,22 +2338,27 @@ bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T, const CXXRecordDecl *RD = cast(RT->getDecl()); - if (CurrentRD && CurrentRD != RD) - return false; - - // FIXME: is this reasonable? It matches current behavior, but.... - if (!RD->getDefinition()) + // We can't answer whether something is abstract until it has a + // definition. If it's currently being defined, we'll walk back + // over all the declarations when we have a full definition. + const CXXRecordDecl *Def = RD->getDefinition(); + if (!Def || Def->isBeingDefined()) return false; if (!RD->isAbstract()) return false; Diag(Loc, PD) << RD->getDeclName(); + DiagnoseAbstractType(RD); - // Check if we've already emitted the list of pure virtual functions for this - // class. + return true; +} + +void Sema::DiagnoseAbstractType(const CXXRecordDecl *RD) { + // Check if we've already emitted the list of pure virtual functions + // for this class. if (PureVirtualClassDiagSet && PureVirtualClassDiagSet->count(RD)) - return true; + return; CXXFinalOverriderMap FinalOverriders; RD->getFinalOverriders(FinalOverriders); @@ -2392,69 +2398,168 @@ bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T, if (!PureVirtualClassDiagSet) PureVirtualClassDiagSet.reset(new RecordDeclSetTy); PureVirtualClassDiagSet->insert(RD); - - return true; } namespace { - class AbstractClassUsageDiagnoser - : public DeclVisitor { - Sema &SemaRef; - CXXRecordDecl *AbstractClass; +struct AbstractUsageInfo { + Sema &S; + CXXRecordDecl *Record; + CanQualType AbstractType; + bool Invalid; + + AbstractUsageInfo(Sema &S, CXXRecordDecl *Record) + : S(S), Record(Record), + AbstractType(S.Context.getCanonicalType( + S.Context.getTypeDeclType(Record))), + Invalid(false) {} + + void DiagnoseAbstractType() { + if (Invalid) return; + S.DiagnoseAbstractType(Record); + Invalid = true; + } - bool VisitDeclContext(const DeclContext *DC) { - bool Invalid = false; + void CheckType(const NamedDecl *D, TypeLoc TL, Sema::AbstractDiagSelID Sel); +}; - for (CXXRecordDecl::decl_iterator I = DC->decls_begin(), - E = DC->decls_end(); I != E; ++I) - Invalid |= Visit(*I); +struct CheckAbstractUsage { + AbstractUsageInfo &Info; + const NamedDecl *Ctx; - return Invalid; + CheckAbstractUsage(AbstractUsageInfo &Info, const NamedDecl *Ctx) + : Info(Info), Ctx(Ctx) {} + + void Visit(TypeLoc TL, Sema::AbstractDiagSelID Sel) { + switch (TL.getTypeLocClass()) { +#define ABSTRACT_TYPELOC(CLASS, PARENT) +#define TYPELOC(CLASS, PARENT) \ + case TypeLoc::CLASS: Check(cast(TL), Sel); break; +#include "clang/AST/TypeLocNodes.def" } + } - public: - AbstractClassUsageDiagnoser(Sema& SemaRef, CXXRecordDecl *ac) - : SemaRef(SemaRef), AbstractClass(ac) { - Visit(SemaRef.Context.getTranslationUnitDecl()); + void Check(FunctionProtoTypeLoc TL, Sema::AbstractDiagSelID Sel) { + Visit(TL.getResultLoc(), Sema::AbstractReturnType); + for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { + TypeSourceInfo *TSI = TL.getArg(I)->getTypeSourceInfo(); + if (TSI) Visit(TSI->getTypeLoc(), Sema::AbstractParamType); } + } - bool VisitFunctionDecl(const FunctionDecl *FD) { - if (FD->isThisDeclarationADefinition()) { - // No need to do the check if we're in a definition, because it requires - // that the return/param types are complete. - // because that requires - return VisitDeclContext(FD); - } + void Check(ArrayTypeLoc TL, Sema::AbstractDiagSelID Sel) { + Visit(TL.getElementLoc(), Sema::AbstractArrayType); + } - // Check the return type. - QualType RTy = FD->getType()->getAs()->getResultType(); - bool Invalid = - SemaRef.RequireNonAbstractType(FD->getLocation(), RTy, - diag::err_abstract_type_in_decl, - Sema::AbstractReturnType, - AbstractClass); - - for (FunctionDecl::param_const_iterator I = FD->param_begin(), - E = FD->param_end(); I != E; ++I) { - const ParmVarDecl *VD = *I; - Invalid |= - SemaRef.RequireNonAbstractType(VD->getLocation(), - VD->getOriginalType(), - diag::err_abstract_type_in_decl, - Sema::AbstractParamType, - AbstractClass); - } + void Check(TemplateSpecializationTypeLoc TL, Sema::AbstractDiagSelID Sel) { + // Visit the type parameters from a permissive context. + for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { + TemplateArgumentLoc TAL = TL.getArgLoc(I); + if (TAL.getArgument().getKind() == TemplateArgument::Type) + if (TypeSourceInfo *TSI = TAL.getTypeSourceInfo()) + Visit(TSI->getTypeLoc(), Sema::AbstractNone); + // TODO: other template argument types? + } + } - return Invalid; + // Visit pointee types from a permissive context. +#define CheckPolymorphic(Type) \ + void Check(Type TL, Sema::AbstractDiagSelID Sel) { \ + Visit(TL.getNextTypeLoc(), Sema::AbstractNone); \ + } + CheckPolymorphic(PointerTypeLoc) + CheckPolymorphic(ReferenceTypeLoc) + CheckPolymorphic(MemberPointerTypeLoc) + CheckPolymorphic(BlockPointerTypeLoc) + + /// Handle all the types we haven't given a more specific + /// implementation for above. + void Check(TypeLoc TL, Sema::AbstractDiagSelID Sel) { + // Every other kind of type that we haven't called out already + // that has an inner type is either (1) sugar or (2) contains that + // inner type in some way as a subobject. + if (TypeLoc Next = TL.getNextTypeLoc()) + return Visit(Next, Sel); + + // If there's no inner type and we're in a permissive context, + // don't diagnose. + if (Sel == Sema::AbstractNone) return; + + // Check whether the type matches the abstract type. + QualType T = TL.getType(); + if (T->isArrayType()) { + Sel = Sema::AbstractArrayType; + T = Info.S.Context.getBaseElementType(T); } + CanQualType CT = T->getCanonicalTypeUnqualified().getUnqualifiedType(); + if (CT != Info.AbstractType) return; - bool VisitDecl(const Decl* D) { - if (const DeclContext *DC = dyn_cast(D)) - return VisitDeclContext(DC); + // It matched; do some magic. + if (Sel == Sema::AbstractArrayType) { + Info.S.Diag(Ctx->getLocation(), diag::err_array_of_abstract_type) + << T << TL.getSourceRange(); + } else { + Info.S.Diag(Ctx->getLocation(), diag::err_abstract_type_in_decl) + << Sel << T << TL.getSourceRange(); + } + Info.DiagnoseAbstractType(); + } +}; - return false; +void AbstractUsageInfo::CheckType(const NamedDecl *D, TypeLoc TL, + Sema::AbstractDiagSelID Sel) { + CheckAbstractUsage(*this, D).Visit(TL, Sel); +} + +} + +/// Check for invalid uses of an abstract type in a method declaration. +static void CheckAbstractClassUsage(AbstractUsageInfo &Info, + CXXMethodDecl *MD) { + // No need to do the check on definitions, which require that + // the return/param types be complete. + if (MD->isThisDeclarationADefinition()) + return; + + // For safety's sake, just ignore it if we don't have type source + // information. This should never happen for non-implicit methods, + // but... + if (TypeSourceInfo *TSI = MD->getTypeSourceInfo()) + Info.CheckType(MD, TSI->getTypeLoc(), Sema::AbstractNone); +} + +/// Check for invalid uses of an abstract type within a class definition. +static void CheckAbstractClassUsage(AbstractUsageInfo &Info, + CXXRecordDecl *RD) { + for (CXXRecordDecl::decl_iterator + I = RD->decls_begin(), E = RD->decls_end(); I != E; ++I) { + Decl *D = *I; + if (D->isImplicit()) continue; + + // Methods and method templates. + if (isa(D)) { + CheckAbstractClassUsage(Info, cast(D)); + } else if (isa(D)) { + FunctionDecl *FD = cast(D)->getTemplatedDecl(); + CheckAbstractClassUsage(Info, cast(FD)); + + // Fields and static variables. + } else if (isa(D)) { + FieldDecl *FD = cast(D); + if (TypeSourceInfo *TSI = FD->getTypeSourceInfo()) + Info.CheckType(FD, TSI->getTypeLoc(), Sema::AbstractFieldType); + } else if (isa(D)) { + VarDecl *VD = cast(D); + if (TypeSourceInfo *TSI = VD->getTypeSourceInfo()) + Info.CheckType(VD, TSI->getTypeLoc(), Sema::AbstractVariableType); + + // Nested classes and class templates. + } else if (isa(D)) { + CheckAbstractClassUsage(Info, cast(D)); + } else if (isa(D)) { + CheckAbstractClassUsage(Info, + cast(D)->getTemplatedDecl()); } - }; + } } /// \brief Perform semantic checks on a class definition that has been @@ -2539,8 +2644,10 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { } } - if (Record->isAbstract() && !Record->isInvalidDecl()) - (void)AbstractClassUsageDiagnoser(*this, Record); + if (Record->isAbstract() && !Record->isInvalidDecl()) { + AbstractUsageInfo Info(*this, Record); + CheckAbstractClassUsage(Info, Record); + } // If this is not an aggregate type and has no user-declared constructor, // complain about any non-static data members of reference or const scalar @@ -2571,7 +2678,7 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { } void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, - DeclPtrTy TagDecl, + Decl *TagDecl, SourceLocation LBrac, SourceLocation RBrac, AttributeList *AttrList) { @@ -2581,11 +2688,12 @@ void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, AdjustDeclIfTemplate(TagDecl); ActOnFields(S, RLoc, TagDecl, - (DeclPtrTy*)FieldCollector->getCurFields(), + // strict aliasing violation! + reinterpret_cast(FieldCollector->getCurFields()), FieldCollector->getCurNumFields(), LBrac, RBrac, AttrList); CheckCompletedCXXClass( - dyn_cast_or_null(TagDecl.getAs())); + dyn_cast_or_null(TagDecl)); } namespace { @@ -2682,8 +2790,7 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { } } -void Sema::ActOnReenterTemplateScope(Scope *S, DeclPtrTy TemplateD) { - Decl *D = TemplateD.getAs(); +void Sema::ActOnReenterTemplateScope(Scope *S, Decl *D) { if (!D) return; @@ -2701,20 +2808,20 @@ void Sema::ActOnReenterTemplateScope(Scope *S, DeclPtrTy TemplateD) { Param != ParamEnd; ++Param) { NamedDecl *Named = cast(*Param); if (Named->getDeclName()) { - S->AddDecl(DeclPtrTy::make(Named)); + S->AddDecl(Named); IdResolver.AddDecl(Named); } } } -void Sema::ActOnStartDelayedMemberDeclarations(Scope *S, DeclPtrTy RecordD) { +void Sema::ActOnStartDelayedMemberDeclarations(Scope *S, Decl *RecordD) { if (!RecordD) return; AdjustDeclIfTemplate(RecordD); - CXXRecordDecl *Record = cast(RecordD.getAs()); + CXXRecordDecl *Record = cast(RecordD); PushDeclContext(S, Record); } -void Sema::ActOnFinishDelayedMemberDeclarations(Scope *S, DeclPtrTy RecordD) { +void Sema::ActOnFinishDelayedMemberDeclarations(Scope *S, Decl *RecordD) { if (!RecordD) return; PopDeclContext(); } @@ -2727,7 +2834,7 @@ void Sema::ActOnFinishDelayedMemberDeclarations(Scope *S, DeclPtrTy RecordD) { /// 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. -void Sema::ActOnStartDelayedCXXMethodDeclaration(Scope *S, DeclPtrTy MethodD) { +void Sema::ActOnStartDelayedCXXMethodDeclaration(Scope *S, Decl *MethodD) { } /// ActOnDelayedCXXMethodParameter - We've already started a delayed @@ -2735,18 +2842,18 @@ void Sema::ActOnStartDelayedCXXMethodDeclaration(Scope *S, DeclPtrTy MethodD) { /// 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. -void Sema::ActOnDelayedCXXMethodParameter(Scope *S, DeclPtrTy ParamD) { +void Sema::ActOnDelayedCXXMethodParameter(Scope *S, Decl *ParamD) { if (!ParamD) return; - ParmVarDecl *Param = cast(ParamD.getAs()); + ParmVarDecl *Param = cast(ParamD); // If this parameter has an unparsed default argument, clear it out // to make way for the parsed default argument. if (Param->hasUnparsedDefaultArg()) Param->setDefaultArg(0); - S->AddDecl(DeclPtrTy::make(Param)); + S->AddDecl(Param); if (Param->getDeclName()) IdResolver.AddDecl(Param); } @@ -2757,13 +2864,13 @@ void Sema::ActOnDelayedCXXMethodParameter(Scope *S, DeclPtrTy ParamD) { /// ActOnStartOfFunctionDef action later (not necessarily /// immediately!) for this method, if it was also defined inside the /// class body. -void Sema::ActOnFinishDelayedCXXMethodDeclaration(Scope *S, DeclPtrTy MethodD) { +void Sema::ActOnFinishDelayedCXXMethodDeclaration(Scope *S, Decl *MethodD) { if (!MethodD) return; AdjustDeclIfTemplate(MethodD); - FunctionDecl *Method = cast(MethodD.getAs()); + FunctionDecl *Method = cast(MethodD); // Now that we have our default arguments, check the constructor // again. It could produce additional diagnostics or affect whether @@ -2784,7 +2891,7 @@ void Sema::ActOnFinishDelayedCXXMethodDeclaration(Scope *S, DeclPtrTy MethodD) { /// will be updated to reflect a well-formed type for the constructor and /// returned. QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R, - FunctionDecl::StorageClass &SC) { + StorageClass &SC) { bool isVirtual = D.getDeclSpec().isVirtualSpecified(); // C++ [class.ctor]p3: @@ -2799,13 +2906,13 @@ QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R, << SourceRange(D.getIdentifierLoc()); D.setInvalidType(); } - if (SC == FunctionDecl::Static) { + if (SC == SC_Static) { if (!D.isInvalidType()) Diag(D.getIdentifierLoc(), diag::err_constructor_cannot_be) << "static" << SourceRange(D.getDeclSpec().getStorageClassSpecLoc()) << SourceRange(D.getIdentifierLoc()); D.setInvalidType(); - SC = FunctionDecl::None; + SC = SC_None; } DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun; @@ -2879,8 +2986,9 @@ void Sema::CheckConstructor(CXXConstructorDecl *Constructor) { ClassDecl->addedConstructor(Context, Constructor); } -/// CheckDestructor - Checks a fully-formed destructor for well-formedness, -/// issuing any diagnostics required. Returns true on error. +/// CheckDestructor - Checks a fully-formed destructor definition for +/// well-formedness, issuing any diagnostics required. Returns true +/// on error. bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) { CXXRecordDecl *RD = Destructor->getParent(); @@ -2911,7 +3019,7 @@ static inline bool FTIHasSingleVoidArgument(DeclaratorChunk::FunctionTypeInfo &FTI) { return (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 && FTI.ArgInfo[0].Param && - FTI.ArgInfo[0].Param.getAs()->getType()->isVoidType()); + cast(FTI.ArgInfo[0].Param)->getType()->isVoidType()); } /// CheckDestructorDeclarator - Called by ActOnDeclarator to check @@ -2921,7 +3029,7 @@ FTIHasSingleVoidArgument(DeclaratorChunk::FunctionTypeInfo &FTI) { /// will be updated to reflect a well-formed type for the destructor and /// returned. QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R, - FunctionDecl::StorageClass& SC) { + StorageClass& SC) { // C++ [class.dtor]p1: // [...] A typedef-name that names a class is a class-name // (7.1.3); however, a typedef-name that names a class shall not @@ -2940,14 +3048,14 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R, // destructor can be invoked for a const, volatile or const // volatile object. A destructor shall not be declared const, // volatile or const volatile (9.3.2). - if (SC == FunctionDecl::Static) { + if (SC == SC_Static) { if (!D.isInvalidType()) Diag(D.getIdentifierLoc(), diag::err_destructor_cannot_be) << "static" << SourceRange(D.getDeclSpec().getStorageClassSpecLoc()) << SourceRange(D.getIdentifierLoc()) << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc()); - SC = FunctionDecl::None; + SC = SC_None; } if (D.getDeclSpec().hasTypeSpecifier() && !D.isInvalidType()) { // Destructors don't have return types, but the parser will @@ -3015,18 +3123,18 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R, /// false. Either way, the type @p R will be updated to reflect a /// well-formed type for the conversion operator. void Sema::CheckConversionDeclarator(Declarator &D, QualType &R, - FunctionDecl::StorageClass& SC) { + StorageClass& SC) { // C++ [class.conv.fct]p1: // Neither parameter types nor return type can be specified. The // type of a conversion function (8.3.5) is "function taking no // parameter returning conversion-type-id." - if (SC == FunctionDecl::Static) { + if (SC == SC_Static) { if (!D.isInvalidType()) Diag(D.getIdentifierLoc(), diag::err_conv_function_not_member) << "static" << SourceRange(D.getDeclSpec().getStorageClassSpecLoc()) << SourceRange(D.getIdentifierLoc()); D.setInvalidType(); - SC = FunctionDecl::None; + SC = SC_None; } QualType ConvType = GetTypeFromParser(D.getName().ConversionFunctionId); @@ -3106,7 +3214,7 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R, /// the declaration of the given C++ conversion function. This routine /// is responsible for recording the conversion function in the C++ /// class, if possible. -Sema::DeclPtrTy Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) { +Decl *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) { assert(Conversion && "Expected to receive a conversion function declaration"); CXXRecordDecl *ClassDecl = cast(Conversion->getDeclContext()); @@ -3147,10 +3255,10 @@ Sema::DeclPtrTy Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) { if (ClassDecl->replaceConversion( ConversionTemplate->getPreviousDeclaration(), ConversionTemplate)) - return DeclPtrTy::make(ConversionTemplate); + return ConversionTemplate; } else if (ClassDecl->replaceConversion(Conversion->getPreviousDeclaration(), Conversion)) - return DeclPtrTy::make(Conversion); + return Conversion; assert(Conversion->isInvalidDecl() && "Conversion should not get here."); } else if (FunctionTemplateDecl *ConversionTemplate = Conversion->getDescribedFunctionTemplate()) @@ -3158,28 +3266,36 @@ Sema::DeclPtrTy Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) { else ClassDecl->addConversionFunction(Conversion); - return DeclPtrTy::make(Conversion); + return Conversion; } //===----------------------------------------------------------------------===// // Namespace Handling //===----------------------------------------------------------------------===// + + /// ActOnStartNamespaceDef - This is called at the start of a namespace /// definition. -Sema::DeclPtrTy Sema::ActOnStartNamespaceDef(Scope *NamespcScope, - SourceLocation IdentLoc, - IdentifierInfo *II, - SourceLocation LBrace, - AttributeList *AttrList) { - NamespaceDecl *Namespc = - NamespaceDecl::Create(Context, CurContext, IdentLoc, II); +Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, + SourceLocation InlineLoc, + SourceLocation IdentLoc, + IdentifierInfo *II, + SourceLocation LBrace, + AttributeList *AttrList) { + // anonymous namespace starts at its left brace + NamespaceDecl *Namespc = NamespaceDecl::Create(Context, CurContext, + (II ? IdentLoc : LBrace) , II); Namespc->setLBracLoc(LBrace); + Namespc->setInline(InlineLoc.isValid()); Scope *DeclRegionScope = NamespcScope->getParent(); ProcessDeclAttributeList(DeclRegionScope, Namespc, AttrList); + if (const VisibilityAttr *attr = Namespc->getAttr()) + PushVisibilityAttr(attr); + if (II) { // C++ [namespace.def]p2: // The identifier in an original-namespace-definition shall not have been @@ -3194,15 +3310,25 @@ Sema::DeclPtrTy Sema::ActOnStartNamespaceDef(Scope *NamespcScope, if (NamespaceDecl *OrigNS = dyn_cast_or_null(PrevDecl)) { // This is an extended namespace definition. + if (Namespc->isInline() != OrigNS->isInline()) { + // inline-ness must match + Diag(Namespc->getLocation(), diag::err_inline_namespace_mismatch) + << Namespc->isInline(); + Diag(OrigNS->getLocation(), diag::note_previous_definition); + Namespc->setInvalidDecl(); + // Recover by ignoring the new namespace's inline status. + Namespc->setInline(OrigNS->isInline()); + } + // Attach this namespace decl to the chain of extended namespace // definitions. OrigNS->setNextNamespace(Namespc); Namespc->setOriginalNamespace(OrigNS->getOriginalNamespace()); // Remove the previous declaration from the scope. - if (DeclRegionScope->isDeclScope(DeclPtrTy::make(OrigNS))) { + if (DeclRegionScope->isDeclScope(OrigNS)) { IdResolver.RemoveDecl(OrigNS); - DeclRegionScope->RemoveDecl(DeclPtrTy::make(OrigNS)); + DeclRegionScope->RemoveDecl(OrigNS); } } else if (PrevDecl) { // This is an invalid name redefinition. @@ -3212,15 +3338,15 @@ Sema::DeclPtrTy Sema::ActOnStartNamespaceDef(Scope *NamespcScope, Namespc->setInvalidDecl(); // Continue on to push Namespc as current DeclContext and return it. } else if (II->isStr("std") && - CurContext->getLookupContext()->isTranslationUnit()) { + CurContext->getRedeclContext()->isTranslationUnit()) { // This is the first "real" definition of the namespace "std", so update // our cache of the "std" namespace to point at this definition. - if (StdNamespace) { + if (NamespaceDecl *StdNS = getStdNamespace()) { // We had already defined a dummy namespace "std". Link this new // namespace definition to the dummy namespace "std". - StdNamespace->setNextNamespace(Namespc); - StdNamespace->setLocation(IdentLoc); - Namespc->setOriginalNamespace(StdNamespace->getOriginalNamespace()); + StdNS->setNextNamespace(Namespc); + StdNS->setLocation(IdentLoc); + Namespc->setOriginalNamespace(StdNS->getOriginalNamespace()); } // Make our StdNamespace cache point at the first real definition of the @@ -3235,7 +3361,7 @@ Sema::DeclPtrTy Sema::ActOnStartNamespaceDef(Scope *NamespcScope, // Link the anonymous namespace into its parent. NamespaceDecl *PrevDecl; - DeclContext *Parent = CurContext->getLookupContext(); + DeclContext *Parent = CurContext->getRedeclContext(); if (TranslationUnitDecl *TU = dyn_cast(Parent)) { PrevDecl = TU->getAnonymousNamespace(); TU->setAnonymousNamespace(Namespc); @@ -3251,6 +3377,16 @@ Sema::DeclPtrTy Sema::ActOnStartNamespaceDef(Scope *NamespcScope, assert(!PrevDecl->getNextNamespace()); Namespc->setOriginalNamespace(PrevDecl->getOriginalNamespace()); PrevDecl->setNextNamespace(Namespc); + + if (Namespc->isInline() != PrevDecl->isInline()) { + // inline-ness must match + Diag(Namespc->getLocation(), diag::err_inline_namespace_mismatch) + << Namespc->isInline(); + Diag(PrevDecl->getLocation(), diag::note_previous_definition); + Namespc->setInvalidDecl(); + // Recover by ignoring the new namespace's inline status. + Namespc->setInline(PrevDecl->isInline()); + } } CurContext->addDecl(Namespc); @@ -3292,7 +3428,7 @@ Sema::DeclPtrTy Sema::ActOnStartNamespaceDef(Scope *NamespcScope, // for the namespace has the declarations that showed up in that particular // namespace definition. PushDeclContext(NamespcScope, Namespc); - return DeclPtrTy::make(Namespc); + return Namespc; } /// getNamespaceDecl - Returns the namespace a decl represents. If the decl @@ -3305,30 +3441,41 @@ static inline NamespaceDecl *getNamespaceDecl(NamedDecl *D) { /// ActOnFinishNamespaceDef - This callback is called after a namespace is /// exited. Decl is the DeclTy returned by ActOnStartNamespaceDef. -void Sema::ActOnFinishNamespaceDef(DeclPtrTy D, SourceLocation RBrace) { - Decl *Dcl = D.getAs(); +void Sema::ActOnFinishNamespaceDef(Decl *Dcl, SourceLocation RBrace) { NamespaceDecl *Namespc = dyn_cast_or_null(Dcl); assert(Namespc && "Invalid parameter, expected NamespaceDecl"); Namespc->setRBracLoc(RBrace); PopDeclContext(); + if (Namespc->hasAttr()) + PopPragmaVisibility(); +} + +CXXRecordDecl *Sema::getStdBadAlloc() const { + return cast_or_null( + StdBadAlloc.get(Context.getExternalSource())); +} + +NamespaceDecl *Sema::getStdNamespace() const { + return cast_or_null( + StdNamespace.get(Context.getExternalSource())); } /// \brief Retrieve the special "std" namespace, which may require us to /// implicitly define the namespace. -NamespaceDecl *Sema::getStdNamespace() { +NamespaceDecl *Sema::getOrCreateStdNamespace() { if (!StdNamespace) { // The "std" namespace has not yet been defined, so build one implicitly. StdNamespace = NamespaceDecl::Create(Context, Context.getTranslationUnitDecl(), SourceLocation(), &PP.getIdentifierTable().get("std")); - StdNamespace->setImplicit(true); + getStdNamespace()->setImplicit(true); } - return StdNamespace; + return getStdNamespace(); } -Sema::DeclPtrTy Sema::ActOnUsingDirective(Scope *S, +Decl *Sema::ActOnUsingDirective(Scope *S, SourceLocation UsingLoc, SourceLocation NamespcLoc, CXXScopeSpec &SS, @@ -3349,7 +3496,7 @@ Sema::DeclPtrTy Sema::ActOnUsingDirective(Scope *S, LookupResult R(*this, NamespcName, IdentLoc, LookupNamespaceName); LookupParsedName(R, S, &SS); if (R.isAmbiguous()) - return DeclPtrTy(); + return 0; if (R.empty()) { // Allow "using namespace std;" or "using namespace ::std;" even if @@ -3357,7 +3504,7 @@ Sema::DeclPtrTy Sema::ActOnUsingDirective(Scope *S, if ((!Qualifier || Qualifier->getKind() == NestedNameSpecifier::Global) && NamespcName->isStr("std")) { Diag(IdentLoc, diag::ext_using_undefined_std); - R.addDecl(getStdNamespace()); + R.addDecl(getOrCreateStdNamespace()); R.resolveKind(); } // Otherwise, attempt typo correction. @@ -3416,7 +3563,7 @@ Sema::DeclPtrTy Sema::ActOnUsingDirective(Scope *S, // FIXME: We ignore attributes for now. delete AttrList; - return DeclPtrTy::make(UDir); + return UDir; } void Sema::PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir) { @@ -3428,11 +3575,11 @@ void Sema::PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir) { else // Otherwise it is block-sope. using-directives will affect lookup // only to the end of scope. - S->PushUsingDirective(DeclPtrTy::make(UDir)); + S->PushUsingDirective(UDir); } -Sema::DeclPtrTy Sema::ActOnUsingDeclaration(Scope *S, +Decl *Sema::ActOnUsingDeclaration(Scope *S, AccessSpecifier AS, bool HasUsingKeyword, SourceLocation UsingLoc, @@ -3457,22 +3604,23 @@ Sema::DeclPtrTy Sema::ActOnUsingDeclaration(Scope *S, Diag(Name.getSourceRange().getBegin(), diag::err_using_decl_constructor) << SS.getRange(); - return DeclPtrTy(); + return 0; case UnqualifiedId::IK_DestructorName: Diag(Name.getSourceRange().getBegin(), diag::err_using_decl_destructor) << SS.getRange(); - return DeclPtrTy(); + return 0; case UnqualifiedId::IK_TemplateId: Diag(Name.getSourceRange().getBegin(), diag::err_using_decl_template_id) << SourceRange(Name.TemplateId->LAngleLoc, Name.TemplateId->RAngleLoc); - return DeclPtrTy(); + return 0; } - - DeclarationName TargetName = GetNameFromUnqualifiedId(Name); + + DeclarationNameInfo TargetNameInfo = GetNameFromUnqualifiedId(Name); + DeclarationName TargetName = TargetNameInfo.getName(); if (!TargetName) - return DeclPtrTy(); + return 0; // Warn about using declarations. // TODO: store that the declaration was written without 'using' and @@ -3486,14 +3634,13 @@ Sema::DeclPtrTy Sema::ActOnUsingDeclaration(Scope *S, } NamedDecl *UD = BuildUsingDeclaration(S, AS, UsingLoc, SS, - Name.getSourceRange().getBegin(), - TargetName, AttrList, + TargetNameInfo, AttrList, /* IsInstantiation */ false, IsTypeName, TypenameLoc); if (UD) PushOnScopeChains(UD, S, /*AddToContext*/ false); - return DeclPtrTy::make(UD); + return UD; } /// \brief Determine whether a using declaration considers the given @@ -3717,7 +3864,7 @@ void Sema::HideUsingShadowDecl(Scope *S, UsingShadowDecl *Shadow) { // ...and the scope, if applicable... if (S) { - S->RemoveDecl(DeclPtrTy::make(static_cast(Shadow))); + S->RemoveDecl(Shadow); IdResolver.RemoveDecl(Shadow); } @@ -3736,13 +3883,13 @@ void Sema::HideUsingShadowDecl(Scope *S, UsingShadowDecl *Shadow) { NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, SourceLocation UsingLoc, CXXScopeSpec &SS, - SourceLocation IdentLoc, - DeclarationName Name, + const DeclarationNameInfo &NameInfo, AttributeList *AttrList, bool IsInstantiation, bool IsTypeName, SourceLocation TypenameLoc) { assert(!SS.isInvalid() && "Invalid CXXScopeSpec."); + SourceLocation IdentLoc = NameInfo.getLoc(); assert(IdentLoc.isValid() && "Invalid TargetName location."); // FIXME: We ignore attributes for now. @@ -3754,7 +3901,7 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, } // Do the redeclaration lookup in the current scope. - LookupResult Previous(*this, Name, IdentLoc, LookupUsingDeclName, + LookupResult Previous(*this, NameInfo, LookupUsingDeclName, ForRedeclaration); Previous.setHideTags(false); if (S) { @@ -3793,15 +3940,15 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, D = UnresolvedUsingTypenameDecl::Create(Context, CurContext, UsingLoc, TypenameLoc, SS.getRange(), NNS, - IdentLoc, Name); + IdentLoc, NameInfo.getName()); } else { D = UnresolvedUsingValueDecl::Create(Context, CurContext, - UsingLoc, SS.getRange(), NNS, - IdentLoc, Name); + UsingLoc, SS.getRange(), + NNS, NameInfo); } } else { - D = UsingDecl::Create(Context, CurContext, IdentLoc, - SS.getRange(), UsingLoc, NNS, Name, + D = UsingDecl::Create(Context, CurContext, + SS.getRange(), UsingLoc, NNS, NameInfo, IsTypeName); } D->setAccess(AS); @@ -3817,7 +3964,7 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, // Look up the target name. - LookupResult R(*this, Name, IdentLoc, LookupOrdinaryName); + LookupResult R(*this, NameInfo, LookupOrdinaryName); // Unlike most lookups, we don't always want to hide tag // declarations: tag names are visible through the using declaration @@ -3830,7 +3977,7 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, if (R.empty()) { Diag(IdentLoc, diag::err_no_member) - << Name << LookupContext << SS.getRange(); + << NameInfo.getName() << LookupContext << SS.getRange(); UD->setInvalidDecl(); return UD; } @@ -3894,7 +4041,7 @@ bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc, // allowed. // // That's in non-member contexts. - if (!CurContext->getLookupContext()->isRecord()) + if (!CurContext->getRedeclContext()->isRecord()) return false; NestedNameSpecifier *Qual @@ -4069,7 +4216,7 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc, return true; } -Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S, +Decl *Sema::ActOnNamespaceAliasDef(Scope *S, SourceLocation NamespaceLoc, SourceLocation AliasLoc, IdentifierInfo *Alias, @@ -4096,18 +4243,18 @@ Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S, // declaration to maintain better source information. if (!R.isAmbiguous() && !R.empty() && AD->getNamespace()->Equals(getNamespaceDecl(R.getFoundDecl()))) - return DeclPtrTy(); + return 0; } unsigned DiagID = isa(PrevDecl) ? diag::err_redefinition : diag::err_redefinition_different_kind; Diag(AliasLoc, DiagID) << Alias; Diag(PrevDecl->getLocation(), diag::note_previous_definition); - return DeclPtrTy(); + return 0; } if (R.isAmbiguous()) - return DeclPtrTy(); + return 0; if (R.empty()) { if (DeclarationName Corrected = CorrectTypo(R, S, &SS, 0, false, @@ -4135,7 +4282,7 @@ Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S, if (R.empty()) { Diag(NamespaceLoc, diag::err_expected_namespace_name) << SS.getRange(); - return DeclPtrTy(); + return 0; } } @@ -4146,7 +4293,7 @@ Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S, IdentLoc, R.getFoundDecl()); PushOnScopeChains(AliasDecl, S); - return DeclPtrTy::make(AliasDecl); + return AliasDecl; } namespace { @@ -4242,9 +4389,9 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl)); DeclarationName Name = Context.DeclarationNames.getCXXConstructorName(ClassType); + DeclarationNameInfo NameInfo(Name, ClassDecl->getLocation()); CXXConstructorDecl *DefaultCon - = CXXConstructorDecl::Create(Context, ClassDecl, - ClassDecl->getLocation(), Name, + = CXXConstructorDecl::Create(Context, ClassDecl, NameInfo, Context.getFunctionType(Context.VoidTy, 0, 0, false, 0, ExceptSpec.hasExceptionSpecification(), @@ -4348,9 +4495,9 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) { = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl)); DeclarationName Name = Context.DeclarationNames.getCXXDestructorName(ClassType); + DeclarationNameInfo NameInfo(Name, ClassDecl->getLocation()); CXXDestructorDecl *Destructor - = CXXDestructorDecl::Create(Context, ClassDecl, - ClassDecl->getLocation(), Name, Ty, + = CXXDestructorDecl::Create(Context, ClassDecl, NameInfo, Ty, /*isInline=*/true, /*isImplicitlyDeclared=*/true); Destructor->setAccess(AS_public); @@ -4426,13 +4573,10 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation, /// \param Depth Internal parameter recording the depth of the recursion. /// /// \returns A statement or a loop that copies the expressions. -static Sema::OwningStmtResult +static StmtResult BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, - Sema::OwningExprResult To, Sema::OwningExprResult From, + Expr *To, Expr *From, bool CopyingBaseSubobject, unsigned Depth = 0) { - typedef Sema::OwningStmtResult OwningStmtResult; - typedef Sema::OwningExprResult OwningExprResult; - // C++0x [class.copy]p30: // Each subobject is assigned in the manner appropriate to its type: // @@ -4489,21 +4633,21 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, T.getTypePtr())); // Create the reference to operator=. - OwningExprResult OpEqualRef - = S.BuildMemberReferenceExpr(move(To), T, Loc, /*isArrow=*/false, SS, + ExprResult OpEqualRef + = S.BuildMemberReferenceExpr(To, T, Loc, /*isArrow=*/false, SS, /*FirstQualifierInScope=*/0, OpLookup, /*TemplateArgs=*/0, /*SuppressQualifierCheck=*/true); if (OpEqualRef.isInvalid()) - return S.StmtError(); + return StmtError(); // Build the call to the assignment operator. - Expr *FromE = From.takeAs(); - OwningExprResult Call = S.BuildCallToMemberFunction(/*Scope=*/0, + + ExprResult Call = S.BuildCallToMemberFunction(/*Scope=*/0, OpEqualRef.takeAs(), - Loc, &FromE, 1, 0, Loc); + Loc, &From, 1, 0, Loc); if (Call.isInvalid()) - return S.StmtError(); + return StmtError(); return S.Owned(Call.takeAs()); } @@ -4512,12 +4656,9 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, // operator is used. const ConstantArrayType *ArrayTy = S.Context.getAsConstantArrayType(T); if (!ArrayTy) { - OwningExprResult Assignment = S.CreateBuiltinBinOp(Loc, - BinaryOperator::Assign, - To.takeAs(), - From.takeAs()); + ExprResult Assignment = S.CreateBuiltinBinOp(Loc, BO_Assign, To, From); if (Assignment.isInvalid()) - return S.StmtError(); + return StmtError(); return S.Owned(Assignment.takeAs()); } @@ -4543,11 +4684,11 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, VarDecl *IterationVar = VarDecl::Create(S.Context, S.CurContext, Loc, IterationVarName, SizeType, S.Context.getTrivialTypeSourceInfo(SizeType, Loc), - VarDecl::None, VarDecl::None); + SC_None, SC_None); // Initialize the iteration variable to zero. llvm::APInt Zero(S.Context.getTypeSize(SizeType), 0); - IterationVar->setInit(new (S.Context) IntegerLiteral(Zero, SizeType, Loc)); + IterationVar->setInit(IntegerLiteral::Create(S.Context, Zero, SizeType, Loc)); // Create a reference to the iteration variable; we'll use this several // times throughout. @@ -4561,43 +4702,37 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, // Create the comparison against the array bound. llvm::APInt Upper = ArrayTy->getSize(); Upper.zextOrTrunc(S.Context.getTypeSize(SizeType)); - OwningExprResult Comparison - = S.Owned(new (S.Context) BinaryOperator(IterationVarRef->Retain(), - new (S.Context) IntegerLiteral(Upper, SizeType, Loc), - BinaryOperator::NE, S.Context.BoolTy, Loc)); + Expr *Comparison + = new (S.Context) BinaryOperator(IterationVarRef->Retain(), + IntegerLiteral::Create(S.Context, + Upper, SizeType, Loc), + BO_NE, S.Context.BoolTy, Loc); // Create the pre-increment of the iteration variable. - OwningExprResult Increment - = S.Owned(new (S.Context) UnaryOperator(IterationVarRef->Retain(), - UnaryOperator::PreInc, - SizeType, Loc)); + Expr *Increment + = new (S.Context) UnaryOperator(IterationVarRef->Retain(), + UO_PreInc, + SizeType, Loc); // Subscript the "from" and "to" expressions with the iteration variable. - From = S.CreateBuiltinArraySubscriptExpr(move(From), Loc, - S.Owned(IterationVarRef->Retain()), - Loc); - To = S.CreateBuiltinArraySubscriptExpr(move(To), Loc, - S.Owned(IterationVarRef->Retain()), - Loc); - assert(!From.isInvalid() && "Builtin subscripting can't fail!"); - assert(!To.isInvalid() && "Builtin subscripting can't fail!"); + From = AssertSuccess(S.CreateBuiltinArraySubscriptExpr(From, Loc, + IterationVarRef, Loc)); + To = AssertSuccess(S.CreateBuiltinArraySubscriptExpr(To, Loc, + IterationVarRef, Loc)); // Build the copy for an individual element of the array. - OwningStmtResult Copy = BuildSingleCopyAssign(S, Loc, + StmtResult Copy = BuildSingleCopyAssign(S, Loc, ArrayTy->getElementType(), - move(To), move(From), + To, From, CopyingBaseSubobject, Depth+1); - if (Copy.isInvalid()) { - InitStmt->Destroy(S.Context); - return S.StmtError(); - } + if (Copy.isInvalid()) + return StmtError(); // Construct the loop that copies all elements of this array. - return S.ActOnForStmt(Loc, Loc, S.Owned(InitStmt), + return S.ActOnForStmt(Loc, Loc, InitStmt, S.MakeFullExpr(Comparison), - Sema::DeclPtrTy(), - S.MakeFullExpr(Increment), - Loc, move(Copy)); + 0, S.MakeFullExpr(Increment), + Loc, Copy.take()); } /// \brief Determine whether the given class has a copy assignment operator @@ -4747,8 +4882,9 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { // An implicitly-declared copy assignment operator is an inline public // member of its class. DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal); + DeclarationNameInfo NameInfo(Name, ClassDecl->getLocation()); CXXMethodDecl *CopyAssignment - = CXXMethodDecl::Create(Context, ClassDecl, ClassDecl->getLocation(), Name, + = CXXMethodDecl::Create(Context, ClassDecl, NameInfo, Context.getFunctionType(RetType, &ArgType, 1, false, 0, ExceptSpec.hasExceptionSpecification(), @@ -4757,7 +4893,7 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { ExceptSpec.data(), FunctionType::ExtInfo()), /*TInfo=*/0, /*isStatic=*/false, - /*StorageClassAsWritten=*/FunctionDecl::None, + /*StorageClassAsWritten=*/SC_None, /*isInline=*/true); CopyAssignment->setAccess(AS_public); CopyAssignment->setImplicit(); @@ -4769,8 +4905,8 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { ClassDecl->getLocation(), /*Id=*/0, ArgType, /*TInfo=*/0, - VarDecl::None, - VarDecl::None, 0); + SC_None, + SC_None, 0); CopyAssignment->setParams(&FromParam, 1); // Note that we have added this copy-assignment operator. @@ -4814,7 +4950,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, // which they were declared in the class definition. // The statements that form the synthesized function body. - ASTOwningVector<&ActionBase::DeleteStmt> Statements(*this); + ASTOwningVector Statements(*this); // The parameter for the "other" object, which we are copying from. ParmVarDecl *Other = CopyAssignOperator->getParamDecl(0); @@ -4854,30 +4990,32 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, continue; } + CXXCastPath BasePath; + BasePath.push_back(Base); + // Construct the "from" expression, which is an implicit cast to the // appropriately-qualified base type. Expr *From = OtherRef->Retain(); ImpCastExprToType(From, Context.getQualifiedType(BaseType, OtherQuals), - CastExpr::CK_UncheckedDerivedToBase, /*isLvalue=*/true, - CXXBaseSpecifierArray(Base)); + CK_UncheckedDerivedToBase, + VK_LValue, &BasePath); // Dereference "this". - OwningExprResult To = CreateBuiltinUnaryOp(Loc, UnaryOperator::Deref, - Owned(This->Retain())); + ExprResult To = CreateBuiltinUnaryOp(Loc, UO_Deref, This); // Implicitly cast "this" to the appropriately-qualified base type. Expr *ToE = To.takeAs(); ImpCastExprToType(ToE, Context.getCVRQualifiedType(BaseType, CopyAssignOperator->getTypeQualifiers()), - CastExpr::CK_UncheckedDerivedToBase, - /*isLvalue=*/true, CXXBaseSpecifierArray(Base)); + CK_UncheckedDerivedToBase, + VK_LValue, &BasePath); To = Owned(ToE); // Build the copy. - OwningStmtResult Copy = BuildSingleCopyAssign(*this, Loc, BaseType, - move(To), Owned(From), - /*CopyingBaseSubobject=*/true); + StmtResult Copy = BuildSingleCopyAssign(*this, Loc, BaseType, + To.get(), From, + /*CopyingBaseSubobject=*/true); if (Copy.isInvalid()) { Diag(CurrentLocation, diag::note_member_synthesized_at) << CXXCopyAssignment << Context.getTagDeclType(ClassDecl); @@ -4934,12 +5072,10 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, LookupMemberName); MemberLookup.addDecl(*Field); MemberLookup.resolveKind(); - OwningExprResult From = BuildMemberReferenceExpr(Owned(OtherRef->Retain()), - OtherRefType, + ExprResult From = BuildMemberReferenceExpr(OtherRef, OtherRefType, Loc, /*IsArrow=*/false, SS, 0, MemberLookup, 0); - OwningExprResult To = BuildMemberReferenceExpr(Owned(This->Retain()), - This->getType(), + ExprResult To = BuildMemberReferenceExpr(This, This->getType(), Loc, /*IsArrow=*/true, SS, 0, MemberLookup, 0); assert(!From.isInvalid() && "Implicit field reference cannot fail"); @@ -4967,8 +5103,8 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, } // Take the address of the field references for "from" and "to". - From = CreateBuiltinUnaryOp(Loc, UnaryOperator::AddrOf, move(From)); - To = CreateBuiltinUnaryOp(Loc, UnaryOperator::AddrOf, move(To)); + From = CreateBuiltinUnaryOp(Loc, UO_AddrOf, From.get()); + To = CreateBuiltinUnaryOp(Loc, UO_AddrOf, To.get()); bool NeedsCollectableMemCpy = (BaseType->isRecordType() && @@ -5016,22 +5152,22 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, assert(BuiltinMemCpyRef && "Builtin reference cannot fail"); } - ASTOwningVector<&ActionBase::DeleteExpr> CallArgs(*this); + ASTOwningVector CallArgs(*this); CallArgs.push_back(To.takeAs()); CallArgs.push_back(From.takeAs()); - CallArgs.push_back(new (Context) IntegerLiteral(Size, SizeType, Loc)); + CallArgs.push_back(IntegerLiteral::Create(Context, Size, SizeType, Loc)); llvm::SmallVector Commas; // FIXME: Silly Commas.push_back(Loc); Commas.push_back(Loc); - OwningExprResult Call = ExprError(); + ExprResult Call = ExprError(); if (NeedsCollectableMemCpy) Call = ActOnCallExpr(/*Scope=*/0, - Owned(CollectableMemCpyRef->Retain()), + CollectableMemCpyRef, Loc, move_arg(CallArgs), Commas.data(), Loc); else Call = ActOnCallExpr(/*Scope=*/0, - Owned(BuiltinMemCpyRef->Retain()), + BuiltinMemCpyRef, Loc, move_arg(CallArgs), Commas.data(), Loc); @@ -5041,8 +5177,8 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, } // Build the copy of this field. - OwningStmtResult Copy = BuildSingleCopyAssign(*this, Loc, FieldType, - move(To), move(From), + StmtResult Copy = BuildSingleCopyAssign(*this, Loc, FieldType, + To.get(), From.get(), /*CopyingBaseSubobject=*/false); if (Copy.isInvalid()) { Diag(CurrentLocation, diag::note_member_synthesized_at) @@ -5057,10 +5193,9 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, if (!Invalid) { // Add a "return *this;" - OwningExprResult ThisObj = CreateBuiltinUnaryOp(Loc, UnaryOperator::Deref, - Owned(This->Retain())); + ExprResult ThisObj = CreateBuiltinUnaryOp(Loc, UO_Deref, This); - OwningStmtResult Return = ActOnReturnStmt(Loc, move(ThisObj)); + StmtResult Return = ActOnReturnStmt(Loc, ThisObj.get()); if (Return.isInvalid()) Invalid = true; else { @@ -5079,7 +5214,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, return; } - OwningStmtResult Body = ActOnCompoundStmt(Loc, Loc, move_arg(Statements), + StmtResult Body = ActOnCompoundStmt(Loc, Loc, move_arg(Statements), /*isStmtExpr=*/false); assert(!Body.isInvalid() && "Compound statement creation cannot fail"); CopyAssignOperator->setBody(Body.takeAs()); @@ -5220,9 +5355,9 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( DeclarationName Name = Context.DeclarationNames.getCXXConstructorName( Context.getCanonicalType(ClassType)); + DeclarationNameInfo NameInfo(Name, ClassDecl->getLocation()); CXXConstructorDecl *CopyConstructor - = CXXConstructorDecl::Create(Context, ClassDecl, - ClassDecl->getLocation(), Name, + = CXXConstructorDecl::Create(Context, ClassDecl, NameInfo, Context.getFunctionType(Context.VoidTy, &ArgType, 1, false, 0, @@ -5248,8 +5383,8 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( ClassDecl->getLocation(), /*IdentifierInfo=*/0, ArgType, /*TInfo=*/0, - VarDecl::None, - VarDecl::None, 0); + SC_None, + SC_None, 0); CopyConstructor->setParams(&FromParam, 1); if (Scope *S = getScopeForContext(ClassDecl)) PushOnScopeChains(CopyConstructor, S, false); @@ -5288,12 +5423,12 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation, CopyConstructor->setUsed(); } -Sema::OwningExprResult +ExprResult Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, CXXConstructorDecl *Constructor, MultiExprArg ExprArgs, bool RequiresZeroInit, - CXXConstructExpr::ConstructionKind ConstructKind) { + unsigned ConstructKind) { bool Elidable = false; // C++0x [class.copy]p34: @@ -5309,6 +5444,7 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, if (Constructor->isCopyConstructor() && ExprArgs.size() >= 1) { Expr *SubExpr = ((Expr **)ExprArgs.get())[0]; Elidable = SubExpr->isTemporaryObject() && + ConstructKind == CXXConstructExpr::CK_Complete && Context.hasSameUnqualifiedType(SubExpr->getType(), Context.getTypeDeclType(Constructor->getParent())); } @@ -5320,27 +5456,28 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, /// BuildCXXConstructExpr - Creates a complete call to a constructor, /// including handling of its default argument expressions. -Sema::OwningExprResult +ExprResult Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, CXXConstructorDecl *Constructor, bool Elidable, MultiExprArg ExprArgs, bool RequiresZeroInit, - CXXConstructExpr::ConstructionKind ConstructKind) { + unsigned ConstructKind) { unsigned NumExprs = ExprArgs.size(); Expr **Exprs = (Expr **)ExprArgs.release(); MarkDeclarationReferenced(ConstructLoc, Constructor); return Owned(CXXConstructExpr::Create(Context, DeclInitType, ConstructLoc, Constructor, Elidable, Exprs, NumExprs, - RequiresZeroInit, ConstructKind)); + RequiresZeroInit, + static_cast(ConstructKind))); } bool Sema::InitializeVarWithConstructor(VarDecl *VD, CXXConstructorDecl *Constructor, MultiExprArg Exprs) { - OwningExprResult TempResult = + ExprResult TempResult = BuildCXXConstructExpr(VD->getLocation(), VD->getType(), Constructor, - move(Exprs)); + move(Exprs), false, CXXConstructExpr::CK_Complete); if (TempResult.isInvalid()) return true; @@ -5362,19 +5499,21 @@ void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) { PDiag(diag::err_access_dtor_var) << VD->getDeclName() << VD->getType()); + + if (!VD->isInvalidDecl() && VD->hasGlobalStorage()) + Diag(VD->getLocation(), diag::warn_global_destructor); } } /// AddCXXDirectInitializerToDecl - This action is called immediately after /// ActOnDeclarator, when a C++ direct initializer is present. /// e.g: "int x(1);" -void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl, +void Sema::AddCXXDirectInitializerToDecl(Decl *RealDecl, SourceLocation LParenLoc, MultiExprArg Exprs, SourceLocation *CommaLocs, SourceLocation RParenLoc) { assert(Exprs.size() != 0 && Exprs.get() && "missing expressions"); - Decl *RealDecl = Dcl.getAs(); // If there is no declaration, there was an error parsing it. Just ignore // the initializer. @@ -5402,9 +5541,6 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl, // The form of initialization (using parentheses or '=') is generally // insignificant, but does matter when the entity being initialized has a // class type. - QualType DeclInitType = VDecl->getType(); - if (const ArrayType *Array = Context.getAsArrayType(DeclInitType)) - DeclInitType = Context.getBaseElementType(Array); if (!VDecl->getType()->isDependentType() && RequireCompleteType(VDecl->getLocation(), VDecl->getType(), @@ -5428,6 +5564,25 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl, return; } + // C++ [class.static.data]p4 + // If a static data member is of const integral or const + // enumeration type, its declaration in the class definition can + // specify a constant-initializer which shall be an integral + // constant expression (5.19). In that case, the member can appear + // in integral constant expressions. The member shall still be + // defined in a namespace scope if it is used in the program and the + // namespace scope definition shall not contain an initializer. + // + // We already performed a redefinition check above, but for static + // data members we also need to check whether there was an in-class + // declaration with an initializer. + const VarDecl* PrevInit = 0; + if (VDecl->isStaticDataMember() && VDecl->getAnyInitializer(PrevInit)) { + Diag(VDecl->getLocation(), diag::err_redefinition) << VDecl->getDeclName(); + Diag(PrevInit->getLocation(), diag::note_previous_definition); + return; + } + // If either the declaration has a dependent type or if any of the // expressions is type-dependent, we represent the initialization // via a ParenListExpr for later use during template instantiation. @@ -5454,17 +5609,25 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl, LParenLoc, RParenLoc); InitializationSequence InitSeq(*this, Entity, Kind, - (Expr**)Exprs.get(), Exprs.size()); - OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind, move(Exprs)); + Exprs.get(), Exprs.size()); + ExprResult Result = InitSeq.Perform(*this, Entity, Kind, move(Exprs)); if (Result.isInvalid()) { VDecl->setInvalidDecl(); return; } - Result = MaybeCreateCXXExprWithTemporaries(move(Result)); + Result = MaybeCreateCXXExprWithTemporaries(Result.get()); VDecl->setInit(Result.takeAs()); VDecl->setCXXDirectInitializer(true); + if (!VDecl->isInvalidDecl() && + !VDecl->getDeclContext()->isDependentContext() && + VDecl->hasGlobalStorage() && + !VDecl->getInit()->isConstantInitializer(Context, + VDecl->getType()->isReferenceType())) + Diag(VDecl->getLocation(), diag::warn_global_constructor) + << VDecl->getInit()->getSourceRange(); + if (const RecordType *Record = VDecl->getType()->getAs()) FinalizeVarWithDestructor(VDecl, Record); } @@ -5478,7 +5641,7 @@ bool Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor, MultiExprArg ArgsPtr, SourceLocation Loc, - ASTOwningVector<&ActionBase::DeleteExpr> &ConvertedArgs) { + ASTOwningVector &ConvertedArgs) { // FIXME: This duplicates a lot of code from Sema::ConvertArgumentsForCall. unsigned NumArgs = ArgsPtr.size(); Expr **Args = (Expr **)ArgsPtr.get(); @@ -5508,7 +5671,7 @@ Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor, static inline bool CheckOperatorNewDeleteDeclarationScope(Sema &SemaRef, const FunctionDecl *FnDecl) { - const DeclContext *DC = FnDecl->getDeclContext()->getLookupContext(); + const DeclContext *DC = FnDecl->getDeclContext()->getRedeclContext(); if (isa(DC)) { return SemaRef.Diag(FnDecl->getLocation(), diag::err_operator_new_delete_declared_in_namespace) @@ -5516,7 +5679,7 @@ CheckOperatorNewDeleteDeclarationScope(Sema &SemaRef, } if (isa(DC) && - FnDecl->getStorageClass() == FunctionDecl::Static) { + FnDecl->getStorageClass() == SC_Static) { return SemaRef.Diag(FnDecl->getLocation(), diag::err_operator_new_delete_declared_static) << FnDecl->getDeclName(); @@ -5622,18 +5785,6 @@ CheckOperatorDeleteDeclaration(Sema &SemaRef, const FunctionDecl *FnDecl) { diag::err_operator_delete_param_type)) return true; - QualType FirstParamType = FnDecl->getParamDecl(0)->getType(); - if (FirstParamType->isDependentType()) - return SemaRef.Diag(FnDecl->getLocation(), - diag::err_operator_delete_dependent_param_type) - << FnDecl->getDeclName() << SemaRef.Context.VoidPtrTy; - - if (SemaRef.Context.getCanonicalType(FirstParamType) != - SemaRef.Context.VoidPtrTy) - return SemaRef.Diag(FnDecl->getLocation(), - diag::err_operator_delete_param_type) - << FnDecl->getDeclName() << SemaRef.Context.VoidPtrTy; - return false; } @@ -5891,7 +6042,7 @@ FinishedParams: /// by Lang/StrSize. LBraceLoc, if valid, provides the location of /// the '{' brace. Otherwise, this linkage specification does not /// have any braces. -Sema::DeclPtrTy Sema::ActOnStartLinkageSpecification(Scope *S, +Decl *Sema::ActOnStartLinkageSpecification(Scope *S, SourceLocation ExternLoc, SourceLocation LangLoc, llvm::StringRef Lang, @@ -5903,7 +6054,7 @@ Sema::DeclPtrTy Sema::ActOnStartLinkageSpecification(Scope *S, Language = LinkageSpecDecl::lang_cxx; else { Diag(LangLoc, diag::err_bad_language); - return DeclPtrTy(); + return 0; } // FIXME: Add all the various semantics of linkage specifications @@ -5913,15 +6064,15 @@ Sema::DeclPtrTy Sema::ActOnStartLinkageSpecification(Scope *S, LBraceLoc.isValid()); CurContext->addDecl(D); PushDeclContext(S, D); - return DeclPtrTy::make(D); + return D; } -/// ActOnFinishLinkageSpecification - Completely the definition of +/// ActOnFinishLinkageSpecification - Complete 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. -Sema::DeclPtrTy Sema::ActOnFinishLinkageSpecification(Scope *S, - DeclPtrTy LinkageSpec, +Decl *Sema::ActOnFinishLinkageSpecification(Scope *S, + Decl *LinkageSpec, SourceLocation RBraceLoc) { if (LinkageSpec) PopDeclContext(); @@ -5983,9 +6134,30 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, QualType ExDeclType, AbstractVariableType)) Invalid = true; + // Only the non-fragile NeXT runtime currently supports C++ catches + // of ObjC types, and no runtime supports catching ObjC types by value. + if (!Invalid && getLangOptions().ObjC1) { + QualType T = ExDeclType; + if (const ReferenceType *RT = T->getAs()) + T = RT->getPointeeType(); + + if (T->isObjCObjectType()) { + Diag(Loc, diag::err_objc_object_catch); + Invalid = true; + } else if (T->isObjCObjectPointerType()) { + if (!getLangOptions().NeXTRuntime) { + Diag(Loc, diag::err_objc_pointer_cxx_catch_gnu); + Invalid = true; + } else if (!getLangOptions().ObjCNonFragileABI) { + Diag(Loc, diag::err_objc_pointer_cxx_catch_fragile); + Invalid = true; + } + } + } + VarDecl *ExDecl = VarDecl::Create(Context, CurContext, Loc, - Name, ExDeclType, TInfo, VarDecl::None, - VarDecl::None); + Name, ExDeclType, TInfo, SC_None, + SC_None); ExDecl->setExceptionVariable(true); if (!Invalid) { @@ -6005,8 +6177,8 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, QualType ExDeclType, InitializationKind Kind = InitializationKind::CreateCopy(Loc, SourceLocation()); InitializationSequence InitSeq(*this, Entity, Kind, &ExDeclRef, 1); - OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind, - MultiExprArg(*this, (void**)&ExDeclRef, 1)); + ExprResult Result = InitSeq.Perform(*this, Entity, Kind, + MultiExprArg(*this, &ExDeclRef, 1)); if (Result.isInvalid()) Invalid = true; else @@ -6022,7 +6194,7 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, QualType ExDeclType, /// ActOnExceptionDeclarator - Parsed the exception-declarator in a C++ catch /// handler. -Sema::DeclPtrTy Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) { +Decl *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) { TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); QualType ExDeclType = TInfo->getType(); @@ -6033,7 +6205,7 @@ Sema::DeclPtrTy Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) { ForRedeclaration)) { // The scope should be freshly made just for us. There is just no way // it contains any previous declaration. - assert(!S->isDeclScope(DeclPtrTy::make(PrevDecl))); + assert(!S->isDeclScope(PrevDecl)); if (PrevDecl->isTemplateParameter()) { // Maybe we will complain about the shadowed template parameter. DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl); @@ -6061,22 +6233,20 @@ Sema::DeclPtrTy Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) { CurContext->addDecl(ExDecl); ProcessDeclAttributes(S, ExDecl, D); - return DeclPtrTy::make(ExDecl); + return ExDecl; } -Sema::DeclPtrTy Sema::ActOnStaticAssertDeclaration(SourceLocation AssertLoc, - ExprArg assertexpr, - ExprArg assertmessageexpr) { - Expr *AssertExpr = (Expr *)assertexpr.get(); - StringLiteral *AssertMessage = - cast((Expr *)assertmessageexpr.get()); +Decl *Sema::ActOnStaticAssertDeclaration(SourceLocation AssertLoc, + Expr *AssertExpr, + Expr *AssertMessageExpr_) { + StringLiteral *AssertMessage = cast(AssertMessageExpr_); if (!AssertExpr->isTypeDependent() && !AssertExpr->isValueDependent()) { llvm::APSInt Value(32); if (!AssertExpr->isIntegerConstantExpr(Value, Context)) { Diag(AssertLoc, diag::err_static_assert_expression_is_not_constant) << AssertExpr->getSourceRange(); - return DeclPtrTy(); + return 0; } if (Value == 0) { @@ -6085,13 +6255,11 @@ Sema::DeclPtrTy Sema::ActOnStaticAssertDeclaration(SourceLocation AssertLoc, } } - assertexpr.release(); - assertmessageexpr.release(); Decl *Decl = StaticAssertDecl::Create(Context, CurContext, AssertLoc, AssertExpr, AssertMessage); CurContext->addDecl(Decl); - return DeclPtrTy::make(Decl); + return Decl; } /// \brief Perform semantic analysis of the given friend type declaration. @@ -6167,7 +6335,7 @@ FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation FriendLoc, /// We permit this as a special case; if there are any template /// parameters present at all, require proper matching, i.e. /// template <> template friend class A::B; -Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, +Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, MultiTemplateParamsArg TempParams) { SourceLocation Loc = DS.getSourceRange().getBegin(); @@ -6181,7 +6349,7 @@ Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, TypeSourceInfo *TSI = GetTypeForDeclarator(TheDeclarator, S); QualType T = TSI->getType(); if (TheDeclarator.isInvalidType()) - return DeclPtrTy(); + return 0; // This is definitely an error in C++98. It's probably meant to // be forbidden in C++0x, too, but the specification is just @@ -6200,7 +6368,7 @@ Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, if (TempParams.size() && !T->isElaboratedTypeSpecifier()) { Diag(Loc, diag::err_tagless_friend_type_template) << DS.getSourceRange(); - return DeclPtrTy(); + return 0; } // C++98 [class.friend]p1: A friend of a class is a function @@ -6225,18 +6393,17 @@ Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, D = CheckFriendTypeDecl(DS.getFriendSpecLoc(), TSI); if (!D) - return DeclPtrTy(); + return 0; D->setAccess(AS_public); CurContext->addDecl(D); - return DeclPtrTy::make(D); + return D; } -Sema::DeclPtrTy -Sema::ActOnFriendFunctionDecl(Scope *S, - Declarator &D, - bool IsDefinition, +Decl *Sema::ActOnFriendFunctionDecl(Scope *S, + Declarator &D, + bool IsDefinition, MultiTemplateParamsArg TemplateParams) { const DeclSpec &DS = D.getDeclSpec(); @@ -6262,7 +6429,7 @@ Sema::ActOnFriendFunctionDecl(Scope *S, // It might be worthwhile to try to recover by creating an // appropriate declaration. - return DeclPtrTy(); + return 0; } // C++ [namespace.memdef]p3 @@ -6281,7 +6448,8 @@ Sema::ActOnFriendFunctionDecl(Scope *S, // namespace scope are not considered. CXXScopeSpec &ScopeQual = D.getCXXScopeSpec(); - DeclarationName Name = GetNameForDeclarator(D); + DeclarationNameInfo NameInfo = GetNameForDeclarator(D); + DeclarationName Name = NameInfo.getName(); assert(Name); // The context we found the declaration in, or in which we should @@ -6291,14 +6459,14 @@ Sema::ActOnFriendFunctionDecl(Scope *S, // FIXME: handle local classes // Recover from invalid scope qualifiers as if they just weren't there. - LookupResult Previous(*this, Name, D.getIdentifierLoc(), LookupOrdinaryName, + LookupResult Previous(*this, NameInfo, LookupOrdinaryName, ForRedeclaration); if (!ScopeQual.isInvalid() && ScopeQual.isSet()) { DC = computeDeclContext(ScopeQual); // FIXME: handle dependent contexts - if (!DC) return DeclPtrTy(); - if (RequireCompleteDeclContext(ScopeQual, DC)) return DeclPtrTy(); + if (!DC) return 0; + if (RequireCompleteDeclContext(ScopeQual, DC)) return 0; LookupQualifiedName(Previous, DC); @@ -6308,7 +6476,8 @@ Sema::ActOnFriendFunctionDecl(Scope *S, LookupResult::Filter F = Previous.makeFilter(); while (F.hasNext()) { NamedDecl *D = F.next(); - if (!D->getDeclContext()->getLookupContext()->Equals(DC)) + if (!DC->InEnclosingNamespaceSetOf( + D->getDeclContext()->getRedeclContext())) F.erase(); } F.done(); @@ -6316,7 +6485,7 @@ Sema::ActOnFriendFunctionDecl(Scope *S, if (Previous.empty()) { D.setInvalidType(); Diag(Loc, diag::err_qualified_friend_not_found) << Name << T; - return DeclPtrTy(); + return 0; } // C++ [class.friend]p1: A friend of a class is a function or @@ -6368,7 +6537,7 @@ Sema::ActOnFriendFunctionDecl(Scope *S, Diag(Loc, diag::err_introducing_special_friend) << (D.getName().getKind() == UnqualifiedId::IK_ConstructorName ? 0 : D.getName().getKind() == UnqualifiedId::IK_DestructorName ? 1 : 2); - return DeclPtrTy(); + return 0; } } @@ -6377,7 +6546,7 @@ Sema::ActOnFriendFunctionDecl(Scope *S, move(TemplateParams), IsDefinition, Redeclaration); - if (!ND) return DeclPtrTy(); + if (!ND) return 0; assert(ND->getDeclContext() == DC); assert(ND->getLexicalDeclContext() == CurContext); @@ -6389,7 +6558,7 @@ Sema::ActOnFriendFunctionDecl(Scope *S, // Also update the scope-based lookup if the target context's // lookup context is in lexical scope. if (!CurContext->isDependentContext()) { - DC = DC->getLookupContext(); + DC = DC->getRedeclContext(); DC->makeDeclVisibleInContext(ND, /* Recoverable=*/ false); if (Scope *EnclosingScope = getScopeForDeclContext(S, DC)) PushOnScopeChains(ND, EnclosingScope, /*AddToContext=*/ false); @@ -6401,13 +6570,12 @@ Sema::ActOnFriendFunctionDecl(Scope *S, FrD->setAccess(AS_public); CurContext->addDecl(FrD); - return DeclPtrTy::make(ND); + return ND; } -void Sema::SetDeclDeleted(DeclPtrTy dcl, SourceLocation DelLoc) { - AdjustDeclIfTemplate(dcl); +void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) { + AdjustDeclIfTemplate(Dcl); - Decl *Dcl = dcl.getAs(); FunctionDecl *Fn = dyn_cast(Dcl); if (!Fn) { Diag(DelLoc, diag::err_deleted_non_function); @@ -6575,9 +6743,8 @@ bool Sema::CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange) { /// 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 Sema::ActOnCXXEnterDeclInitializer(Scope *S, DeclPtrTy Dcl) { +void Sema::ActOnCXXEnterDeclInitializer(Scope *S, Decl *D) { // If there is no declaration, there was an error parsing it. - Decl *D = Dcl.getAs(); if (D == 0) return; // We should only get called for declarations with scope specifiers, like: @@ -6587,10 +6754,9 @@ void Sema::ActOnCXXEnterDeclInitializer(Scope *S, DeclPtrTy Dcl) { } /// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an -/// initializer for the out-of-line declaration 'Dcl'. -void Sema::ActOnCXXExitDeclInitializer(Scope *S, DeclPtrTy Dcl) { +/// initializer for the out-of-line declaration 'D'. +void Sema::ActOnCXXExitDeclInitializer(Scope *S, Decl *D) { // If there is no declaration, there was an error parsing it. - Decl *D = Dcl.getAs(); if (D == 0) return; assert(D->isOutOfLine()); @@ -6600,8 +6766,7 @@ void Sema::ActOnCXXExitDeclInitializer(Scope *S, DeclPtrTy Dcl) { /// ActOnCXXConditionDeclarationExpr - Parsed a condition declaration of a /// C++ if/switch/while/for statement. /// e.g: "if (int x = f()) {...}" -Action::DeclResult -Sema::ActOnCXXConditionDeclaration(Scope *S, Declarator &D) { +DeclResult Sema::ActOnCXXConditionDeclaration(Scope *S, Declarator &D) { // C++ 6.4p2: // The declarator shall not specify a function or an array. // The type-specifier-seq shall not contain typedef and shall not declare a @@ -6624,12 +6789,10 @@ Sema::ActOnCXXConditionDeclaration(Scope *S, Declarator &D) { Diag(OwnedTag->getLocation(), diag::err_type_defined_in_condition); } - DeclPtrTy Dcl = ActOnDeclarator(S, D); + Decl *Dcl = ActOnDeclarator(S, D); if (!Dcl) return DeclResult(); - VarDecl *VD = cast(Dcl.getAs()); - VD->setDeclaredInCondition(true); return Dcl; } @@ -6775,8 +6938,6 @@ void Sema::MarkVirtualMembersReferenced(SourceLocation Loc, e = RD->bases_end(); i != e; ++i) { const CXXRecordDecl *Base = cast(i->getType()->getAs()->getDecl()); - if (i->isVirtual()) - continue; if (Base->getNumVBases() == 0) continue; MarkVirtualMembersReferenced(Loc, Base); @@ -6788,7 +6949,7 @@ void Sema::MarkVirtualMembersReferenced(SourceLocation Loc, void Sema::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) { if (!getLangOptions().CPlusPlus) return; - if (const ObjCInterfaceDecl *OID = ObjCImplementation->getClassInterface()) { + if (ObjCInterfaceDecl *OID = ObjCImplementation->getClassInterface()) { llvm::SmallVector ivars; CollectIvarsToConstructOrDestruct(OID, ivars); if (ivars.empty()) @@ -6805,10 +6966,9 @@ void Sema::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) { InitializationKind::CreateDefault(ObjCImplementation->getLocation()); InitializationSequence InitSeq(*this, InitEntity, InitKind, 0, 0); - Sema::OwningExprResult MemberInit = - InitSeq.Perform(*this, InitEntity, InitKind, - Sema::MultiExprArg(*this, 0, 0)); - MemberInit = MaybeCreateCXXExprWithTemporaries(move(MemberInit)); + ExprResult MemberInit = + InitSeq.Perform(*this, InitEntity, InitKind, MultiExprArg()); + MemberInit = MaybeCreateCXXExprWithTemporaries(MemberInit.get()); // Note, MemberInit could actually come back empty if no initialization // is required (e.g., because it would call a trivial default constructor) if (!MemberInit.get() || MemberInit.isInvalid()) diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 21aeb59a0886..a6902a3e391c 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -11,20 +11,24 @@ // //===----------------------------------------------------------------------===// -#include "Sema.h" -#include "Lookup.h" +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/Lookup.h" #include "clang/Sema/ExternalSemaSource.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/ScopeInfo.h" #include "clang/AST/Expr.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" -#include "clang/Parse/DeclSpec.h" +#include "clang/Sema/DeclSpec.h" +#include "llvm/ADT/DenseSet.h" + using namespace clang; /// ActOnStartOfObjCMethodDef - This routine sets up parameters; invisible /// and user declared, in the method definition's AST. -void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, DeclPtrTy D) { +void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) { assert(getCurMethodDecl() == 0 && "Method parsing confused"); - ObjCMethodDecl *MDecl = dyn_cast_or_null(D.getAs()); + ObjCMethodDecl *MDecl = dyn_cast_or_null(D); // If we don't have a valid method decl, simply return. if (!MDecl) @@ -32,10 +36,10 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, DeclPtrTy D) { // Allow the rest of sema to find private method decl implementations. if (MDecl->isInstanceMethod()) - AddInstanceMethodToGlobalPool(MDecl); + AddInstanceMethodToGlobalPool(MDecl, true); else - AddFactoryMethodToGlobalPool(MDecl); - + AddFactoryMethodToGlobalPool(MDecl, true); + // Allow all of Sema to see that we are entering a method definition. PushDeclContext(FnBodyScope, MDecl); PushFunctionScope(); @@ -56,11 +60,11 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, DeclPtrTy D) { PushOnScopeChains(*PI, FnBodyScope); } -Sema::DeclPtrTy Sema:: +Decl *Sema:: ActOnStartClassInterface(SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName, SourceLocation ClassLoc, IdentifierInfo *SuperName, SourceLocation SuperLoc, - const DeclPtrTy *ProtoRefs, unsigned NumProtoRefs, + Decl * const *ProtoRefs, unsigned NumProtoRefs, const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc, AttributeList *AttrList) { assert(ClassName && "Missing class identifier"); @@ -84,11 +88,14 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, // Return the previous class interface. // FIXME: don't leak the objects passed in! - return DeclPtrTy::make(IDecl); + return IDecl; } else { IDecl->setLocation(AtInterfaceLoc); IDecl->setForwardDecl(false); IDecl->setClassLoc(ClassLoc); + // If the forward decl was in a PCH, we need to write it again in a + // dependent AST file. + IDecl->setChangedSinceDeserialization(true); // Since this ObjCInterfaceDecl was created by a forward declaration, // we now add it to the DeclContext since it wasn't added before @@ -176,7 +183,7 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, IDecl->setLocEnd(ClassLoc); } - /// Check then save referenced protocols. + // Check then save referenced protocols. if (NumProtoRefs) { IDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs, ProtoLocs, Context); @@ -184,16 +191,16 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, } CheckObjCDeclScope(IDecl); - return DeclPtrTy::make(IDecl); + return IDecl; } /// ActOnCompatiblityAlias - this action is called after complete parsing of /// @compatibility_alias declaration. It sets up the alias relationships. -Sema::DeclPtrTy Sema::ActOnCompatiblityAlias(SourceLocation AtLoc, - IdentifierInfo *AliasName, - SourceLocation AliasLocation, - IdentifierInfo *ClassName, - SourceLocation ClassLocation) { +Decl *Sema::ActOnCompatiblityAlias(SourceLocation AtLoc, + IdentifierInfo *AliasName, + SourceLocation AliasLocation, + IdentifierInfo *ClassName, + SourceLocation ClassLocation) { // Look for previous declaration of alias name NamedDecl *ADecl = LookupSingleName(TUScope, AliasName, AliasLocation, LookupOrdinaryName, ForRedeclaration); @@ -203,7 +210,7 @@ Sema::DeclPtrTy Sema::ActOnCompatiblityAlias(SourceLocation AtLoc, else Diag(AliasLocation, diag::err_conflicting_aliasing_type) << AliasName; Diag(ADecl->getLocation(), diag::note_previous_declaration); - return DeclPtrTy(); + return 0; } // Check for class declaration NamedDecl *CDeclU = LookupSingleName(TUScope, ClassName, ClassLocation, @@ -223,7 +230,7 @@ Sema::DeclPtrTy Sema::ActOnCompatiblityAlias(SourceLocation AtLoc, Diag(ClassLocation, diag::warn_undef_interface) << ClassName; if (CDeclU) Diag(CDeclU->getLocation(), diag::note_previous_declaration); - return DeclPtrTy(); + return 0; } // Everything checked out, instantiate a new alias declaration AST. @@ -233,7 +240,7 @@ Sema::DeclPtrTy Sema::ActOnCompatiblityAlias(SourceLocation AtLoc, if (!CheckObjCDeclScope(AliasDecl)) PushOnScopeChains(AliasDecl, TUScope); - return DeclPtrTy::make(AliasDecl); + return AliasDecl; } void Sema::CheckForwardProtocolDeclarationForCircularDependency( @@ -255,11 +262,11 @@ void Sema::CheckForwardProtocolDeclarationForCircularDependency( } } -Sema::DeclPtrTy +Decl * Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc, IdentifierInfo *ProtocolName, SourceLocation ProtocolLoc, - const DeclPtrTy *ProtoRefs, + Decl * const *ProtoRefs, unsigned NumProtoRefs, const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc, @@ -274,17 +281,19 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc, Diag(PDecl->getLocation(), diag::note_previous_definition); // Just return the protocol we already had. // FIXME: don't leak the objects passed in! - return DeclPtrTy::make(PDecl); + return PDecl; } ObjCList PList; PList.set((ObjCProtocolDecl *const*)ProtoRefs, NumProtoRefs, Context); CheckForwardProtocolDeclarationForCircularDependency( ProtocolName, ProtocolLoc, PDecl->getLocation(), PList); - PList.Destroy(Context); // Make sure the cached decl gets a valid start location. PDecl->setLocation(AtProtoInterfaceLoc); PDecl->setForwardDecl(false); + CurContext->addDecl(PDecl); + // Repeat in dependent AST files. + PDecl->setChangedSinceDeserialization(true); } else { PDecl = ObjCProtocolDecl::Create(Context, CurContext, AtProtoInterfaceLoc,ProtocolName); @@ -301,7 +310,7 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc, } CheckObjCDeclScope(PDecl); - return DeclPtrTy::make(PDecl); + return PDecl; } /// FindProtocolDeclaration - This routine looks up protocols and @@ -311,7 +320,7 @@ void Sema::FindProtocolDeclaration(bool WarnOnDeclarations, const IdentifierLocPair *ProtocolId, unsigned NumProtocols, - llvm::SmallVectorImpl &Protocols) { + llvm::SmallVectorImpl &Protocols) { for (unsigned i = 0; i != NumProtocols; ++i) { ObjCProtocolDecl *PDecl = LookupProtocol(ProtocolId[i].first, ProtocolId[i].second); @@ -340,7 +349,7 @@ Sema::FindProtocolDeclaration(bool WarnOnDeclarations, if (WarnOnDeclarations && PDecl->isForwardDecl()) Diag(ProtocolId[i].second, diag::warn_undef_protocolref) << ProtocolId[i].first; - Protocols.push_back(DeclPtrTy::make(PDecl)); + Protocols.push_back(PDecl); } } @@ -374,7 +383,7 @@ void Sema::DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT, } /// ActOnForwardProtocolDeclaration - Handle @protocol foo; -Action::DeclPtrTy +Decl * Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc, const IdentifierLocPair *IdentList, unsigned NumElts, @@ -385,13 +394,18 @@ Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc, for (unsigned i = 0; i != NumElts; ++i) { IdentifierInfo *Ident = IdentList[i].first; ObjCProtocolDecl *PDecl = LookupProtocol(Ident, IdentList[i].second); + bool isNew = false; if (PDecl == 0) { // Not already seen? PDecl = ObjCProtocolDecl::Create(Context, CurContext, IdentList[i].second, Ident); - PushOnScopeChains(PDecl, TUScope); + PushOnScopeChains(PDecl, TUScope, false); + isNew = true; } - if (attrList) + if (attrList) { ProcessDeclAttributeList(TUScope, PDecl, attrList); + if (!isNew) + PDecl->setChangedSinceDeserialization(true); + } Protocols.push_back(PDecl); ProtoLocs.push_back(IdentList[i].second); } @@ -402,15 +416,15 @@ Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc, ProtoLocs.data()); CurContext->addDecl(PDecl); CheckObjCDeclScope(PDecl); - return DeclPtrTy::make(PDecl); + return PDecl; } -Sema::DeclPtrTy Sema:: +Decl *Sema:: ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName, SourceLocation ClassLoc, IdentifierInfo *CategoryName, SourceLocation CategoryLoc, - const DeclPtrTy *ProtoRefs, + Decl * const *ProtoRefs, unsigned NumProtoRefs, const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc) { @@ -426,7 +440,7 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc, ClassLoc, CategoryLoc, CategoryName); CDecl->setInvalidDecl(); Diag(ClassLoc, diag::err_undef_interface) << ClassName; - return DeclPtrTy::make(CDecl); + return CDecl; } if (!CategoryName && IDecl->getImplementation()) { @@ -471,18 +485,17 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc, // Protocols in the class extension belong to the class. if (CDecl->IsClassExtension()) IDecl->mergeClassExtensionProtocolList((ObjCProtocolDecl**)ProtoRefs, - NumProtoRefs, ProtoLocs, - Context); + NumProtoRefs, Context); } CheckObjCDeclScope(CDecl); - return DeclPtrTy::make(CDecl); + return CDecl; } /// ActOnStartCategoryImplementation - Perform semantic checks on the /// category implementation declaration and build an ObjCCategoryImplDecl /// object. -Sema::DeclPtrTy Sema::ActOnStartCategoryImplementation( +Decl *Sema::ActOnStartCategoryImplementation( SourceLocation AtCatImplLoc, IdentifierInfo *ClassName, SourceLocation ClassLoc, IdentifierInfo *CatName, SourceLocation CatLoc) { @@ -523,10 +536,10 @@ Sema::DeclPtrTy Sema::ActOnStartCategoryImplementation( } CheckObjCDeclScope(CDecl); - return DeclPtrTy::make(CDecl); + return CDecl; } -Sema::DeclPtrTy Sema::ActOnStartClassImplementation( +Decl *Sema::ActOnStartClassImplementation( SourceLocation AtClassImplLoc, IdentifierInfo *ClassName, SourceLocation ClassLoc, IdentifierInfo *SuperClassname, @@ -617,7 +630,7 @@ Sema::DeclPtrTy Sema::ActOnStartClassImplementation( IDecl, SDecl); if (CheckObjCDeclScope(IMPDecl)) - return DeclPtrTy::make(IMPDecl); + return IMPDecl; // Check that there is no duplicate implementation of this class. if (IDecl->getImplementation()) { @@ -629,7 +642,7 @@ Sema::DeclPtrTy Sema::ActOnStartClassImplementation( IDecl->setImplementation(IMPDecl); PushOnScopeChains(IMPDecl, TUScope); } - return DeclPtrTy::make(IMPDecl); + return IMPDecl; } void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl, @@ -910,8 +923,9 @@ void Sema::MatchAllMethodDeclarations(const llvm::DenseSet &InsMap, } if (ObjCInterfaceDecl *I = dyn_cast (CDecl)) { // Check for any implementation of a methods declared in protocol. - for (ObjCInterfaceDecl::protocol_iterator PI = I->protocol_begin(), - E = I->protocol_end(); PI != E; ++PI) + for (ObjCInterfaceDecl::all_protocol_iterator + PI = I->all_referenced_protocol_begin(), + E = I->all_referenced_protocol_end(); PI != E; ++PI) MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen, IMPDecl, (*PI), IncompleteImpl, false); @@ -957,8 +971,9 @@ void Sema::ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl, // implemented in the implementation class. if (ObjCInterfaceDecl *I = dyn_cast (CDecl)) { - for (ObjCInterfaceDecl::protocol_iterator PI = I->protocol_begin(), - E = I->protocol_end(); PI != E; ++PI) + for (ObjCInterfaceDecl::all_protocol_iterator + PI = I->all_referenced_protocol_begin(), + E = I->all_referenced_protocol_end(); PI != E; ++PI) CheckProtocolMethodDefs(IMPDecl->getLocation(), *PI, IncompleteImpl, InsMap, ClsMap, I); // Check class extensions (unnamed categories) @@ -992,7 +1007,7 @@ void Sema::ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl, } /// ActOnForwardClassDeclaration - -Action::DeclPtrTy +Decl * Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc, IdentifierInfo **IdentList, SourceLocation *IdentLocs, @@ -1053,7 +1068,7 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc, Interfaces.size()); CurContext->addDecl(CDecl); CheckObjCDeclScope(CDecl); - return DeclPtrTy::make(CDecl); + return CDecl; } @@ -1062,13 +1077,14 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc, /// TODO: Handle protocol list; such as id in type comparisons bool Sema::MatchTwoMethodDeclarations(const ObjCMethodDecl *Method, const ObjCMethodDecl *PrevMethod, - bool matchBasedOnSizeAndAlignment) { + bool matchBasedOnSizeAndAlignment, + bool matchBasedOnStrictEqulity) { QualType T1 = Context.getCanonicalType(Method->getResultType()); QualType T2 = Context.getCanonicalType(PrevMethod->getResultType()); if (T1 != T2) { // The result types are different. - if (!matchBasedOnSizeAndAlignment) + if (!matchBasedOnSizeAndAlignment || matchBasedOnStrictEqulity) return false; // Incomplete types don't have a size and alignment. if (T1->isIncompleteType() || T2->isIncompleteType()) @@ -1088,7 +1104,7 @@ bool Sema::MatchTwoMethodDeclarations(const ObjCMethodDecl *Method, T2 = Context.getCanonicalType((*PrevI)->getType()); if (T1 != T2) { // The result types are different. - if (!matchBasedOnSizeAndAlignment) + if (!matchBasedOnSizeAndAlignment || matchBasedOnStrictEqulity) return false; // Incomplete types don't have a size and alignment. if (T1->isIncompleteType() || T2->isIncompleteType()) @@ -1101,47 +1117,34 @@ bool Sema::MatchTwoMethodDeclarations(const ObjCMethodDecl *Method, return true; } -/// \brief Read the contents of the instance and factory method pools -/// for a given selector from external storage. +/// \brief Read the contents of the method pool for a given selector from +/// external storage. /// -/// This routine should only be called once, when neither the instance -/// nor the factory method pool has an entry for this selector. -Sema::MethodPool::iterator Sema::ReadMethodPool(Selector Sel, - bool isInstance) { +/// This routine should only be called once, when the method pool has no entry +/// for this selector. +Sema::GlobalMethodPool::iterator Sema::ReadMethodPool(Selector Sel) { assert(ExternalSource && "We need an external AST source"); - assert(InstanceMethodPool.find(Sel) == InstanceMethodPool.end() && - "Selector data already loaded into the instance method pool"); - assert(FactoryMethodPool.find(Sel) == FactoryMethodPool.end() && - "Selector data already loaded into the factory method pool"); + assert(MethodPool.find(Sel) == MethodPool.end() && + "Selector data already loaded into the method pool"); // Read the method list from the external source. - std::pair Methods - = ExternalSource->ReadMethodPool(Sel); + GlobalMethods Methods = ExternalSource->ReadMethodPool(Sel); - if (isInstance) { - if (Methods.second.Method) - FactoryMethodPool[Sel] = Methods.second; - return InstanceMethodPool.insert(std::make_pair(Sel, Methods.first)).first; - } - - if (Methods.first.Method) - InstanceMethodPool[Sel] = Methods.first; - - return FactoryMethodPool.insert(std::make_pair(Sel, Methods.second)).first; + return MethodPool.insert(std::make_pair(Sel, Methods)).first; } -void Sema::AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method) { - llvm::DenseMap::iterator Pos - = InstanceMethodPool.find(Method->getSelector()); - if (Pos == InstanceMethodPool.end()) { - if (ExternalSource && !FactoryMethodPool.count(Method->getSelector())) - Pos = ReadMethodPool(Method->getSelector(), /*isInstance=*/true); +void Sema::AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl, + bool instance) { + GlobalMethodPool::iterator Pos = MethodPool.find(Method->getSelector()); + if (Pos == MethodPool.end()) { + if (ExternalSource) + Pos = ReadMethodPool(Method->getSelector()); else - Pos = InstanceMethodPool.insert(std::make_pair(Method->getSelector(), - ObjCMethodList())).first; + Pos = MethodPool.insert(std::make_pair(Method->getSelector(), + GlobalMethods())).first; } - - ObjCMethodList &Entry = Pos->second; + Method->setDefined(impl); + ObjCMethodList &Entry = instance ? Pos->second.first : Pos->second.second; if (Entry.Method == 0) { // Haven't seen a method with this selector name yet - add it. Entry.Method = Method; @@ -1152,8 +1155,10 @@ void Sema::AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method) { // We've seen a method with this name, see if we have already seen this type // signature. for (ObjCMethodList *List = &Entry; List; List = List->Next) - if (MatchTwoMethodDeclarations(Method, List->Method)) + if (MatchTwoMethodDeclarations(Method, List->Method)) { + List->Method->setDefined(impl); return; + } // We have a new signature for an existing method - add it. // This is extremely rare. Only 1% of Cocoa selectors are "overloaded". @@ -1161,102 +1166,65 @@ void Sema::AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method) { Entry.Next = new (Mem) ObjCMethodList(Method, Entry.Next); } -// FIXME: Finish implementing -Wno-strict-selector-match. -ObjCMethodDecl *Sema::LookupInstanceMethodInGlobalPool(Selector Sel, - SourceRange R, - bool warn) { - llvm::DenseMap::iterator Pos - = InstanceMethodPool.find(Sel); - if (Pos == InstanceMethodPool.end()) { - if (ExternalSource && !FactoryMethodPool.count(Sel)) - Pos = ReadMethodPool(Sel, /*isInstance=*/true); +ObjCMethodDecl *Sema::LookupMethodInGlobalPool(Selector Sel, SourceRange R, + bool receiverIdOrClass, + bool warn, bool instance) { + GlobalMethodPool::iterator Pos = MethodPool.find(Sel); + if (Pos == MethodPool.end()) { + if (ExternalSource) + Pos = ReadMethodPool(Sel); else return 0; } - ObjCMethodList &MethList = Pos->second; - bool issueWarning = false; + ObjCMethodList &MethList = instance ? Pos->second.first : Pos->second.second; - if (MethList.Method && MethList.Next) { - for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next) - // This checks if the methods differ by size & alignment. - if (!MatchTwoMethodDeclarations(MethList.Method, Next->Method, true)) - issueWarning = warn; - } - if (issueWarning && (MethList.Method && MethList.Next)) { - Diag(R.getBegin(), diag::warn_multiple_method_decl) << Sel << R; - Diag(MethList.Method->getLocStart(), diag::note_using) - << MethList.Method->getSourceRange(); - for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next) - Diag(Next->Method->getLocStart(), diag::note_also_found) - << Next->Method->getSourceRange(); - } - return MethList.Method; -} + bool strictSelectorMatch = receiverIdOrClass && warn && + (Diags.getDiagnosticLevel(diag::warn_strict_multiple_method_decl) != + Diagnostic::Ignored); + if (warn && MethList.Method && MethList.Next) { + bool issueWarning = false; + if (strictSelectorMatch) + for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next) { + // This checks if the methods differ in type mismatch. + if (!MatchTwoMethodDeclarations(MethList.Method, Next->Method, false, true)) + issueWarning = true; + } -void Sema::AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method) { - llvm::DenseMap::iterator Pos - = FactoryMethodPool.find(Method->getSelector()); - if (Pos == FactoryMethodPool.end()) { - if (ExternalSource && !InstanceMethodPool.count(Method->getSelector())) - Pos = ReadMethodPool(Method->getSelector(), /*isInstance=*/false); - else - Pos = FactoryMethodPool.insert(std::make_pair(Method->getSelector(), - ObjCMethodList())).first; - } + if (!issueWarning) + for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next) { + // This checks if the methods differ by size & alignment. + if (!MatchTwoMethodDeclarations(MethList.Method, Next->Method, true)) + issueWarning = true; + } - ObjCMethodList &FirstMethod = Pos->second; - if (!FirstMethod.Method) { - // Haven't seen a method with this selector name yet - add it. - FirstMethod.Method = Method; - FirstMethod.Next = 0; - } else { - // We've seen a method with this name, now check the type signature(s). - bool match = MatchTwoMethodDeclarations(Method, FirstMethod.Method); - - for (ObjCMethodList *Next = FirstMethod.Next; !match && Next; - Next = Next->Next) - match = MatchTwoMethodDeclarations(Method, Next->Method); - - if (!match) { - // We have a new signature for an existing method - add it. - // This is extremely rare. Only 1% of Cocoa selectors are "overloaded". - ObjCMethodList *Mem = BumpAlloc.Allocate(); - ObjCMethodList *OMI = new (Mem) ObjCMethodList(Method, FirstMethod.Next); - FirstMethod.Next = OMI; + if (issueWarning) { + if (strictSelectorMatch) + Diag(R.getBegin(), diag::warn_strict_multiple_method_decl) << Sel << R; + else + Diag(R.getBegin(), diag::warn_multiple_method_decl) << Sel << R; + Diag(MethList.Method->getLocStart(), diag::note_using) + << MethList.Method->getSourceRange(); + for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next) + Diag(Next->Method->getLocStart(), diag::note_also_found) + << Next->Method->getSourceRange(); } } + return MethList.Method; } -ObjCMethodDecl *Sema::LookupFactoryMethodInGlobalPool(Selector Sel, - SourceRange R) { - llvm::DenseMap::iterator Pos - = FactoryMethodPool.find(Sel); - if (Pos == FactoryMethodPool.end()) { - if (ExternalSource && !InstanceMethodPool.count(Sel)) - Pos = ReadMethodPool(Sel, /*isInstance=*/false); - else - return 0; - } +ObjCMethodDecl *Sema::LookupImplementedMethodInGlobalPool(Selector Sel) { + GlobalMethodPool::iterator Pos = MethodPool.find(Sel); + if (Pos == MethodPool.end()) + return 0; - ObjCMethodList &MethList = Pos->second; - bool issueWarning = false; + GlobalMethods &Methods = Pos->second; - if (MethList.Method && MethList.Next) { - for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next) - // This checks if the methods differ by size & alignment. - if (!MatchTwoMethodDeclarations(MethList.Method, Next->Method, true)) - issueWarning = true; - } - if (issueWarning && (MethList.Method && MethList.Next)) { - Diag(R.getBegin(), diag::warn_multiple_method_decl) << Sel << R; - Diag(MethList.Method->getLocStart(), diag::note_using) - << MethList.Method->getSourceRange(); - for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next) - Diag(Next->Method->getLocStart(), diag::note_also_found) - << Next->Method->getSourceRange(); - } - return MethList.Method; + if (Methods.first.Method && Methods.first.Method->isDefined()) + return Methods.first.Method; + if (Methods.second.Method && Methods.second.Method->isDefined()) + return Methods.second.Method; + return 0; } /// CompareMethodParamsInBaseAndSuper - This routine compares methods with @@ -1322,12 +1290,10 @@ void Sema::DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID, // Note: For class/category implemenations, allMethods/allProperties is // always null. void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, - DeclPtrTy classDecl, - DeclPtrTy *allMethods, unsigned allNum, - DeclPtrTy *allProperties, unsigned pNum, + Decl *ClassDecl, + Decl **allMethods, unsigned allNum, + Decl **allProperties, unsigned pNum, DeclGroupPtrTy *allTUVars, unsigned tuvNum) { - Decl *ClassDecl = classDecl.getAs(); - // FIXME: If we don't have a ClassDecl, we have an error. We should consider // always passing in a decl. If the decl has an error, isInvalidDecl() // should be true. @@ -1356,7 +1322,7 @@ void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, for (unsigned i = 0; i < allNum; i++ ) { ObjCMethodDecl *Method = - cast_or_null(allMethods[i].getAs()); + cast_or_null(allMethods[i]); if (!Method) continue; // Already issued a diagnostic. if (Method->isInstanceMethod()) { @@ -1403,14 +1369,14 @@ void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, // Compares properties declared in this class to those of its // super class. ComparePropertiesInBaseAndSuper(I); - CompareProperties(I, DeclPtrTy::make(I)); + CompareProperties(I, I); } else if (ObjCCategoryDecl *C = dyn_cast(ClassDecl)) { // Categories are used to extend the class by declaring new methods. // By the same token, they are also used to add new properties. No // need to compare the added property to those in the class. // Compare protocol properties with those in category - CompareProperties(C, DeclPtrTy::make(C)); + CompareProperties(C, C); if (C->IsClassExtension()) DiagnoseClassExtensionDupMethods(C, C->getClassInterface()); } @@ -1432,6 +1398,7 @@ void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, DefaultSynthesizeProperties(S, IC, IDecl); ImplMethodsVsClassMethods(S, IC, IDecl); AtomicPropertySetterGetterRules(IC, IDecl); + if (LangOpts.ObjCNonFragileABI2) while (IDecl->getSuperClass()) { DiagnoseDuplicateIvars(IDecl, IDecl->getSuperClass()); @@ -1491,19 +1458,20 @@ CvtQTToAstBitMask(ObjCDeclSpec::ObjCDeclQualifier PQTVal) { } static inline -bool containsInvalidMethodImplAttribute(const AttributeList *A) { +bool containsInvalidMethodImplAttribute(const AttrVec &A) { // The 'ibaction' attribute is allowed on method definitions because of // how the IBAction macro is used on both method declarations and definitions. // If the method definitions contains any other attributes, return true. - while (A && A->getKind() == AttributeList::AT_IBAction) - A = A->getNext(); - return A != NULL; + for (AttrVec::const_iterator i = A.begin(), e = A.end(); i != e; ++i) + if ((*i)->getKind() != attr::IBAction) + return true; + return false; } -Sema::DeclPtrTy Sema::ActOnMethodDeclaration( +Decl *Sema::ActOnMethodDeclaration( SourceLocation MethodLoc, SourceLocation EndLoc, - tok::TokenKind MethodType, DeclPtrTy classDecl, - ObjCDeclSpec &ReturnQT, TypeTy *ReturnType, + tok::TokenKind MethodType, Decl *ClassDecl, + ObjCDeclSpec &ReturnQT, ParsedType ReturnType, Selector Sel, // optional arguments. The number of types/arguments is obtained // from the Sel.getNumArgs(). @@ -1511,13 +1479,11 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration( DeclaratorChunk::ParamInfo *CParamInfo, unsigned CNumArgs, // c-style args AttributeList *AttrList, tok::ObjCKeywordKind MethodDeclKind, bool isVariadic) { - Decl *ClassDecl = classDecl.getAs(); - // Make sure we can establish a context for the method. if (!ClassDecl) { Diag(MethodLoc, diag::error_missing_method_context); - getLabelMap().clear(); - return DeclPtrTy(); + getCurFunction()->LabelMap.clear(); + return 0; } QualType resultDeclType; @@ -1530,7 +1496,7 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration( if (resultDeclType->isObjCObjectType()) { Diag(MethodLoc, diag::err_object_cannot_be_passed_returned_by_value) << 0 << resultDeclType; - return DeclPtrTy(); + return 0; } } else // get the type for "id". resultDeclType = Context.getObjCIdType(); @@ -1540,7 +1506,7 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration( ResultTInfo, cast(ClassDecl), MethodType == tok::minus, isVariadic, - false, + false, false, MethodDeclKind == tok::objc_optional ? ObjCMethodDecl::Optional : ObjCMethodDecl::Required); @@ -1563,7 +1529,7 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration( ParmVarDecl* Param = ParmVarDecl::Create(Context, ObjCMethod, ArgInfo[i].NameLoc, ArgInfo[i].Name, ArgType, DI, - VarDecl::None, VarDecl::None, 0); + SC_None, SC_None, 0); if (ArgType->isObjCObjectType()) { Diag(ArgInfo[i].NameLoc, @@ -1582,7 +1548,7 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration( } for (unsigned i = 0, e = CNumArgs; i != e; ++i) { - ParmVarDecl *Param = CParamInfo[i].Param.getAs(); + ParmVarDecl *Param = cast(CParamInfo[i].Param); QualType ArgType = Param->getType(); if (ArgType.isNull()) ArgType = Context.getObjCIdType(); @@ -1596,7 +1562,8 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration( Param->setInvalidDecl(); } Param->setDeclContext(ObjCMethod); - IdResolver.RemoveDecl(Param); + if (Param->getDeclName()) + IdResolver.RemoveDecl(Param); Params.push_back(Param); } @@ -1626,7 +1593,8 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration( } InterfaceMD = ImpDecl->getClassInterface()->getMethod(Sel, MethodType == tok::minus); - if (containsInvalidMethodImplAttribute(AttrList)) + if (ObjCMethod->hasAttrs() && + containsInvalidMethodImplAttribute(ObjCMethod->getAttrs())) Diag(EndLoc, diag::warn_attribute_method_def); } else if (ObjCCategoryImplDecl *CatImpDecl = dyn_cast(ClassDecl)) { @@ -1637,7 +1605,8 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration( PrevMethod = CatImpDecl->getClassMethod(Sel); CatImpDecl->addClassMethod(ObjCMethod); } - if (containsInvalidMethodImplAttribute(AttrList)) + if (ObjCMethod->hasAttrs() && + containsInvalidMethodImplAttribute(ObjCMethod->getAttrs())) Diag(EndLoc, diag::warn_attribute_method_def); } if (PrevMethod) { @@ -1649,14 +1618,16 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration( // If the interface declared this method, and it was deprecated there, // mark it deprecated here. - if (InterfaceMD && InterfaceMD->hasAttr()) - ObjCMethod->addAttr(::new (Context) DeprecatedAttr()); + if (InterfaceMD) + if (Attr *DA = InterfaceMD->getAttr()) + ObjCMethod->addAttr(::new (Context) DeprecatedAttr(DA->getLocation(), + Context)); - return DeclPtrTy::make(ObjCMethod); + return ObjCMethod; } bool Sema::CheckObjCDeclScope(Decl *D) { - if (isa(CurContext->getLookupContext())) + if (isa(CurContext->getRedeclContext())) return false; Diag(D->getLocation(), diag::err_objc_decls_may_only_appear_in_global_scope); @@ -1667,9 +1638,9 @@ bool Sema::CheckObjCDeclScope(Decl *D) { /// Called whenever @defs(ClassName) is encountered in the source. Inserts the /// instance variables of ClassName into Decls. -void Sema::ActOnDefs(Scope *S, DeclPtrTy TagD, SourceLocation DeclStart, +void Sema::ActOnDefs(Scope *S, Decl *TagD, SourceLocation DeclStart, IdentifierInfo *ClassName, - llvm::SmallVectorImpl &Decls) { + llvm::SmallVectorImpl &Decls) { // Check that ClassName is a valid class ObjCInterfaceDecl *Class = getObjCInterfaceDecl(ClassName, DeclStart); if (!Class) { @@ -1682,25 +1653,25 @@ void Sema::ActOnDefs(Scope *S, DeclPtrTy TagD, SourceLocation DeclStart, } // Collect the instance variables - llvm::SmallVector RecFields; - Context.CollectObjCIvars(Class, RecFields); + llvm::SmallVector Ivars; + Context.DeepCollectObjCIvars(Class, true, Ivars); // For each ivar, create a fresh ObjCAtDefsFieldDecl. - for (unsigned i = 0; i < RecFields.size(); i++) { - FieldDecl* ID = RecFields[i]; - RecordDecl *Record = dyn_cast(TagD.getAs()); + for (unsigned i = 0; i < Ivars.size(); i++) { + FieldDecl* ID = cast(Ivars[i]); + RecordDecl *Record = dyn_cast(TagD); Decl *FD = ObjCAtDefsFieldDecl::Create(Context, Record, ID->getLocation(), ID->getIdentifier(), ID->getType(), ID->getBitWidth()); - Decls.push_back(Sema::DeclPtrTy::make(FD)); + Decls.push_back(FD); } // Introduce all of these fields into the appropriate scope. - for (llvm::SmallVectorImpl::iterator D = Decls.begin(); + for (llvm::SmallVectorImpl::iterator D = Decls.begin(); D != Decls.end(); ++D) { - FieldDecl *FD = cast(D->getAs()); + FieldDecl *FD = cast(*D); if (getLangOptions().CPlusPlus) PushOnScopeChains(cast(FD), S); - else if (RecordDecl *Record = dyn_cast(TagD.getAs())) + else if (RecordDecl *Record = dyn_cast(TagD)) Record->addDecl(FD); } } @@ -1735,7 +1706,7 @@ VarDecl *Sema::BuildObjCExceptionDecl(TypeSourceInfo *TInfo, } VarDecl *New = VarDecl::Create(Context, CurContext, NameLoc, Name, T, TInfo, - VarDecl::None, VarDecl::None); + SC_None, SC_None); New->setExceptionVariable(true); if (Invalid) @@ -1743,7 +1714,7 @@ VarDecl *Sema::BuildObjCExceptionDecl(TypeSourceInfo *TInfo, return New; } -Sema::DeclPtrTy Sema::ActOnObjCExceptionDecl(Scope *S, Declarator &D) { +Decl *Sema::ActOnObjCExceptionDecl(Scope *S, Declarator &D) { const DeclSpec &DS = D.getDeclSpec(); // We allow the "register" storage class on exception variables because @@ -1788,7 +1759,7 @@ Sema::DeclPtrTy Sema::ActOnObjCExceptionDecl(Scope *S, Declarator &D) { } // Add the parameter declaration into this scope. - S->AddDecl(DeclPtrTy::make(New)); + S->AddDecl(New); if (D.getIdentifier()) IdResolver.AddDecl(New); @@ -1796,43 +1767,18 @@ Sema::DeclPtrTy Sema::ActOnObjCExceptionDecl(Scope *S, Declarator &D) { if (New->hasAttr()) Diag(New->getLocation(), diag::err_block_on_nonlocal); - return DeclPtrTy::make(New); + return New; } /// CollectIvarsToConstructOrDestruct - Collect those ivars which require /// initialization. -void Sema::CollectIvarsToConstructOrDestruct(const ObjCInterfaceDecl *OI, +void Sema::CollectIvarsToConstructOrDestruct(ObjCInterfaceDecl *OI, llvm::SmallVectorImpl &Ivars) { - for (ObjCInterfaceDecl::ivar_iterator I = OI->ivar_begin(), - E = OI->ivar_end(); I != E; ++I) { - ObjCIvarDecl *Iv = (*I); + for (ObjCIvarDecl *Iv = OI->all_declared_ivar_begin(); Iv; + Iv= Iv->getNextIvar()) { QualType QT = Context.getBaseElementType(Iv->getType()); if (QT->isRecordType()) - Ivars.push_back(*I); - } - - // Find ivars to construct/destruct in class extension. - for (const ObjCCategoryDecl *CDecl = OI->getFirstClassExtension(); CDecl; - CDecl = CDecl->getNextClassExtension()) { - for (ObjCCategoryDecl::ivar_iterator I = CDecl->ivar_begin(), - E = CDecl->ivar_end(); I != E; ++I) { - ObjCIvarDecl *Iv = (*I); - QualType QT = Context.getBaseElementType(Iv->getType()); - if (QT->isRecordType()) - Ivars.push_back(*I); - } - } - - // Also add any ivar defined in this class's implementation. This - // includes synthesized ivars. - if (ObjCImplementationDecl *ImplDecl = OI->getImplementation()) { - for (ObjCImplementationDecl::ivar_iterator I = ImplDecl->ivar_begin(), - E = ImplDecl->ivar_end(); I != E; ++I) { - ObjCIvarDecl *Iv = (*I); - QualType QT = Context.getBaseElementType(Iv->getType()); - if (QT->isRecordType()) - Ivars.push_back(*I); - } + Ivars.push_back(Iv); } } @@ -1849,3 +1795,15 @@ void ObjCImplementationDecl::setIvarInitializers(ASTContext &C, } } +void Sema::DiagnoseUseOfUnimplementedSelectors() { + if (ReferencedSelectors.empty()) + return; + for (llvm::DenseMap::iterator S = + ReferencedSelectors.begin(), + E = ReferencedSelectors.end(); S != E; ++S) { + Selector Sel = (*S).first; + if (!LookupImplementedMethodInGlobalPool(Sel)) + Diag((*S).second, diag::warn_unimplemented_selector) << Sel; + } + return; +} diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp index 34a479ae2a08..c902e7787096 100644 --- a/lib/Sema/SemaExceptionSpec.cpp +++ b/lib/Sema/SemaExceptionSpec.cpp @@ -11,7 +11,7 @@ // //===----------------------------------------------------------------------===// -#include "Sema.h" +#include "clang/Sema/SemaInternal.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" @@ -261,6 +261,14 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID, bool OldAny = !Old->hasExceptionSpec() || Old->hasAnyExceptionSpec(); bool NewAny = !New->hasExceptionSpec() || New->hasAnyExceptionSpec(); + if (getLangOptions().Microsoft) { + // Treat throw(whatever) as throw(...) to be compatible with MS headers. + if (New->hasExceptionSpec() && New->getNumExceptions() > 0) + NewAny = true; + if (Old->hasExceptionSpec() && Old->getNumExceptions() > 0) + OldAny = true; + } + if (OldAny && NewAny) return false; if (OldAny || NewAny) { diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 5f46a977b12c..80b465230e14 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -11,10 +11,10 @@ // //===----------------------------------------------------------------------===// -#include "Sema.h" -#include "SemaInit.h" -#include "Lookup.h" -#include "AnalysisBasedWarnings.h" +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/Initialization.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/AnalysisBasedWarnings.h" #include "clang/AST/ASTContext.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclObjC.h" @@ -29,11 +29,14 @@ #include "clang/Basic/TargetInfo.h" #include "clang/Lex/LiteralSupport.h" #include "clang/Lex/Preprocessor.h" -#include "clang/Parse/DeclSpec.h" -#include "clang/Parse/Designator.h" -#include "clang/Parse/Scope.h" -#include "clang/Parse/Template.h" +#include "clang/Sema/DeclSpec.h" +#include "clang/Sema/Designator.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/ParsedTemplate.h" +#include "clang/Sema/Template.h" using namespace clang; +using namespace sema; /// \brief Determine whether the use of this declaration is valid, and @@ -59,7 +62,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) { // See if the decl is unavailable if (D->getAttr()) { - Diag(Loc, diag::warn_unavailable) << D->getDeclName(); + Diag(Loc, diag::err_unavailable) << D->getDeclName(); Diag(D->getLocation(), diag::note_unavailable_here) << 0; } @@ -192,7 +195,7 @@ void Sema::DefaultFunctionArrayConversion(Expr *&E) { if (Ty->isFunctionType()) ImpCastExprToType(E, Context.getPointerType(Ty), - CastExpr::CK_FunctionToPointerDecay); + CK_FunctionToPointerDecay); else if (Ty->isArrayType()) { // In C90 mode, arrays only promote to pointers if the array expression is // an lvalue. The relevant legalese is C90 6.2.2.1p3: "an lvalue that has @@ -208,7 +211,7 @@ void Sema::DefaultFunctionArrayConversion(Expr *&E) { if (getLangOptions().C99 || getLangOptions().CPlusPlus || E->isLvalue(Context) == Expr::LV_Valid) ImpCastExprToType(E, Context.getArrayDecayedType(Ty), - CastExpr::CK_ArrayToPointerDecay); + CK_ArrayToPointerDecay); } } @@ -229,7 +232,7 @@ void Sema::DefaultFunctionArrayLvalueConversion(Expr *&E) { // If the lvalue has qualified type, the value has the unqualified // version of the type of the lvalue; otherwise, the value has the // type of the lvalue. - ImpCastExprToType(E, Ty.getUnqualifiedType(), CastExpr::CK_NoOp); + ImpCastExprToType(E, Ty.getUnqualifiedType(), CK_NoOp); } } @@ -258,12 +261,12 @@ Expr *Sema::UsualUnaryConversions(Expr *&Expr) { // other types are unchanged by the integer promotions. QualType PTy = Context.isPromotableBitField(Expr); if (!PTy.isNull()) { - ImpCastExprToType(Expr, PTy, CastExpr::CK_IntegralCast); + ImpCastExprToType(Expr, PTy, CK_IntegralCast); return Expr; } if (Ty->isPromotableIntegerType()) { QualType PT = Context.getPromotedIntegerType(Ty); - ImpCastExprToType(Expr, PT, CastExpr::CK_IntegralCast); + ImpCastExprToType(Expr, PT, CK_IntegralCast); return Expr; } @@ -281,7 +284,7 @@ void Sema::DefaultArgumentPromotion(Expr *&Expr) { // If this is a 'float' (CVR qualified or typedef) promote to double. if (Ty->isSpecificBuiltinType(BuiltinType::Float)) return ImpCastExprToType(Expr, Context.DoubleTy, - CastExpr::CK_FloatingCast); + CK_FloatingCast); UsualUnaryConversions(Expr); } @@ -355,8 +358,8 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr, QualType destType = Context.UsualArithmeticConversionsType(lhs, rhs); if (!isCompAssign) - ImpCastExprToType(lhsExpr, destType, CastExpr::CK_Unknown); - ImpCastExprToType(rhsExpr, destType, CastExpr::CK_Unknown); + ImpCastExprToType(lhsExpr, destType, CK_Unknown); + ImpCastExprToType(rhsExpr, destType, CK_Unknown); return destType; } @@ -371,7 +374,7 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr, /// multiple tokens. However, the common case is that StringToks points to one /// string. /// -Action::OwningExprResult +ExprResult Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks) { assert(NumStringToks && "Must have at least one string!"); @@ -459,13 +462,20 @@ static bool ShouldSnapshotBlockValueReference(Sema &S, BlockScopeInfo *CurBlock, } +ExprResult +Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, SourceLocation Loc, + const CXXScopeSpec *SS) { + DeclarationNameInfo NameInfo(D->getDeclName(), Loc); + return BuildDeclRefExpr(D, Ty, NameInfo, SS); +} /// BuildDeclRefExpr - Build a DeclRefExpr. -Sema::OwningExprResult -Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, SourceLocation Loc, +ExprResult +Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, + const DeclarationNameInfo &NameInfo, const CXXScopeSpec *SS) { if (Context.getCanonicalType(Ty) == Context.UndeducedAutoTy) { - Diag(Loc, + Diag(NameInfo.getLoc(), diag::err_auto_variable_cannot_appear_in_own_initializer) << D->getDeclName(); return ExprError(); @@ -479,7 +489,8 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, SourceLocation Loc, } else if (const CXXMethodDecl *MD = dyn_cast(CurContext)) { if (const FunctionDecl *FD = MD->getParent()->isLocalClass()) { if (VD->hasLocalStorage() && VD->getDeclContext() != CurContext) { - Diag(Loc, diag::err_reference_to_local_var_in_enclosing_function) + Diag(NameInfo.getLoc(), + diag::err_reference_to_local_var_in_enclosing_function) << D->getIdentifier() << FD->getDeclName(); Diag(D->getLocation(), diag::note_local_variable_declared_here) << D->getIdentifier(); @@ -489,12 +500,12 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, SourceLocation Loc, } } - MarkDeclarationReferenced(Loc, D); + MarkDeclarationReferenced(NameInfo.getLoc(), D); return Owned(DeclRefExpr::Create(Context, SS? (NestedNameSpecifier *)SS->getScopeRep() : 0, SS? SS->getRange() : SourceRange(), - D, Loc, Ty)); + D, NameInfo, Ty)); } /// \brief Given a field that represents a member of an anonymous @@ -535,7 +546,7 @@ VarDecl *Sema::BuildAnonymousStructUnionMemberPath(FieldDecl *Field, return BaseObject; } -Sema::OwningExprResult +ExprResult Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc, FieldDecl *Field, Expr *BaseObjectExpr, @@ -553,7 +564,6 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc, if (BaseObject) { // BaseObject is an anonymous struct/union variable (and is, // therefore, not part of another non-anonymous record). - if (BaseObjectExpr) BaseObjectExpr->Destroy(Context); MarkDeclarationReferenced(Loc, BaseObject); BaseObjectExpr = new (Context) DeclRefExpr(BaseObject,BaseObject->getType(), SourceLocation()); @@ -640,7 +650,7 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc, return Owned(Result); } -/// Decomposes the given name into a DeclarationName, its location, and +/// Decomposes the given name into a DeclarationNameInfo, its location, and /// possibly a list of template arguments. /// /// If this produces template arguments, it is permitted to call @@ -652,8 +662,7 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc, static void DecomposeUnqualifiedId(Sema &SemaRef, const UnqualifiedId &Id, TemplateArgumentListInfo &Buffer, - DeclarationName &Name, - SourceLocation &NameLoc, + DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *&TemplateArgs) { if (Id.getKind() == UnqualifiedId::IK_TemplateId) { Buffer.setLAngleLoc(Id.TemplateId->LAngleLoc); @@ -665,15 +674,12 @@ static void DecomposeUnqualifiedId(Sema &SemaRef, SemaRef.translateTemplateArguments(TemplateArgsPtr, Buffer); TemplateArgsPtr.release(); - TemplateName TName = - Sema::TemplateTy::make(Id.TemplateId->Template).getAsVal(); - - Name = SemaRef.Context.getNameForTemplate(TName); - NameLoc = Id.TemplateId->TemplateNameLoc; + TemplateName TName = Id.TemplateId->Template.get(); + SourceLocation TNameLoc = Id.TemplateId->TemplateNameLoc; + NameInfo = SemaRef.Context.getNameForTemplate(TName, TNameLoc); TemplateArgs = &Buffer; } else { - Name = SemaRef.GetNameFromUnqualifiedId(Id); - NameLoc = Id.StartLocation; + NameInfo = SemaRef.GetNameFromUnqualifiedId(Id); TemplateArgs = 0; } } @@ -700,23 +706,6 @@ static bool IsFullyFormedScope(Sema &SemaRef, CXXRecordDecl *Record) { return true; } -/// Determines whether we can lookup this id-expression now or whether -/// we have to wait until template instantiation is complete. -static bool IsDependentIdExpression(Sema &SemaRef, const CXXScopeSpec &SS) { - DeclContext *DC = SemaRef.computeDeclContext(SS, false); - - // If the qualifier scope isn't computable, it's definitely dependent. - if (!DC) return true; - - // If the qualifier scope doesn't name a record, we can always look into it. - if (!isa(DC)) return false; - - // We can't look into record types unless they're fully-formed. - if (!IsFullyFormedScope(SemaRef, cast(DC))) return true; - - return false; -} - /// Determines if the given class is provably not derived from all of /// the prospective base classes. static bool IsProvablyNotDerivedFrom(Sema &SemaRef, @@ -905,25 +894,30 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, // TODO: fixit for inserting 'Base::' in the other cases. // Actually quite difficult! if (isInstance) { - Diag(R.getNameLoc(), diagnostic) << Name - << FixItHint::CreateInsertion(R.getNameLoc(), "this->"); - UnresolvedLookupExpr *ULE = cast( CallsUndergoingInstantiation.back()->getCallee()); - CXXMethodDecl *DepMethod = cast( + CXXMethodDecl *DepMethod = cast_or_null( CurMethod->getInstantiatedFromMemberFunction()); - QualType DepThisType = DepMethod->getThisType(Context); - CXXThisExpr *DepThis = new (Context) CXXThisExpr(R.getNameLoc(), - DepThisType, false); - TemplateArgumentListInfo TList; - if (ULE->hasExplicitTemplateArgs()) - ULE->copyTemplateArgumentsInto(TList); - CXXDependentScopeMemberExpr *DepExpr = - CXXDependentScopeMemberExpr::Create( - Context, DepThis, DepThisType, true, SourceLocation(), - ULE->getQualifier(), ULE->getQualifierRange(), NULL, Name, - R.getNameLoc(), &TList); - CallsUndergoingInstantiation.back()->setCallee(DepExpr); + if (DepMethod) { + Diag(R.getNameLoc(), diagnostic) << Name + << FixItHint::CreateInsertion(R.getNameLoc(), "this->"); + QualType DepThisType = DepMethod->getThisType(Context); + CXXThisExpr *DepThis = new (Context) CXXThisExpr( + R.getNameLoc(), DepThisType, false); + TemplateArgumentListInfo TList; + if (ULE->hasExplicitTemplateArgs()) + ULE->copyTemplateArgumentsInto(TList); + CXXDependentScopeMemberExpr *DepExpr = + CXXDependentScopeMemberExpr::Create( + Context, DepThis, DepThisType, true, SourceLocation(), + ULE->getQualifier(), ULE->getQualifierRange(), NULL, + R.getLookupNameInfo(), &TList); + CallsUndergoingInstantiation.back()->setCallee(DepExpr); + } else { + // FIXME: we should be able to handle this case too. It is correct + // to add this-> here. This is a workaround for PR7947. + Diag(R.getNameLoc(), diagnostic) << Name; + } } else { Diag(R.getNameLoc(), diagnostic) << Name; } @@ -935,6 +929,8 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, // Tell the callee to try to recover. return false; } + + R.clear(); } } @@ -1005,11 +1001,74 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, return true; } -Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S, - CXXScopeSpec &SS, - UnqualifiedId &Id, - bool HasTrailingLParen, - bool isAddressOfOperand) { +static ObjCPropertyDecl *OkToSynthesizeProvisionalIvar(Sema &SemaRef, + IdentifierInfo *II, + SourceLocation NameLoc) { + ObjCMethodDecl *CurMeth = SemaRef.getCurMethodDecl(); + ObjCInterfaceDecl *IDecl = CurMeth->getClassInterface(); + if (!IDecl) + return 0; + ObjCImplementationDecl *ClassImpDecl = IDecl->getImplementation(); + if (!ClassImpDecl) + return 0; + ObjCPropertyDecl *property = SemaRef.LookupPropertyDecl(IDecl, II); + if (!property) + return 0; + if (ObjCPropertyImplDecl *PIDecl = ClassImpDecl->FindPropertyImplDecl(II)) + if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) + return 0; + return property; +} + +static ObjCIvarDecl *SynthesizeProvisionalIvar(Sema &SemaRef, + LookupResult &Lookup, + IdentifierInfo *II, + SourceLocation NameLoc) { + ObjCMethodDecl *CurMeth = SemaRef.getCurMethodDecl(); + bool LookForIvars; + if (Lookup.empty()) + LookForIvars = true; + else if (CurMeth->isClassMethod()) + LookForIvars = false; + else + LookForIvars = (Lookup.isSingleResult() && + Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod()); + if (!LookForIvars) + return 0; + + ObjCInterfaceDecl *IDecl = CurMeth->getClassInterface(); + if (!IDecl) + return 0; + ObjCImplementationDecl *ClassImpDecl = IDecl->getImplementation(); + if (!ClassImpDecl) + return 0; + bool DynamicImplSeen = false; + ObjCPropertyDecl *property = SemaRef.LookupPropertyDecl(IDecl, II); + if (!property) + return 0; + if (ObjCPropertyImplDecl *PIDecl = ClassImpDecl->FindPropertyImplDecl(II)) + DynamicImplSeen = + (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic); + if (!DynamicImplSeen) { + QualType PropType = SemaRef.Context.getCanonicalType(property->getType()); + ObjCIvarDecl *Ivar = ObjCIvarDecl::Create(SemaRef.Context, ClassImpDecl, + NameLoc, + II, PropType, /*Dinfo=*/0, + ObjCIvarDecl::Protected, + (Expr *)0, true); + ClassImpDecl->addDecl(Ivar); + IDecl->makeDeclVisibleInContext(Ivar, false); + property->setPropertyIvarDecl(Ivar); + return Ivar; + } + return 0; +} + +ExprResult Sema::ActOnIdExpression(Scope *S, + CXXScopeSpec &SS, + UnqualifiedId &Id, + bool HasTrailingLParen, + bool isAddressOfOperand) { assert(!(isAddressOfOperand && HasTrailingLParen) && "cannot be direct & operand and have a trailing lparen"); @@ -1019,13 +1078,13 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S, TemplateArgumentListInfo TemplateArgsBuffer; // Decompose the UnqualifiedId into the following data. - DeclarationName Name; - SourceLocation NameLoc; + DeclarationNameInfo NameInfo; const TemplateArgumentListInfo *TemplateArgs; - DecomposeUnqualifiedId(*this, Id, TemplateArgsBuffer, - Name, NameLoc, TemplateArgs); + DecomposeUnqualifiedId(*this, Id, TemplateArgsBuffer, NameInfo, TemplateArgs); + DeclarationName Name = NameInfo.getName(); IdentifierInfo *II = Name.getAsIdentifierInfo(); + SourceLocation NameLoc = NameInfo.getLoc(); // C++ [temp.dep.expr]p3: // An id-expression is type-dependent if it contains: @@ -1038,16 +1097,30 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S, // names a dependent type. // Determine whether this is a member of an unknown specialization; // we need to handle these differently. - if ((Name.getNameKind() == DeclarationName::CXXConversionFunctionName && - Name.getCXXNameType()->isDependentType()) || - (SS.isSet() && IsDependentIdExpression(*this, SS))) { - return ActOnDependentIdExpression(SS, Name, NameLoc, - isAddressOfOperand, - TemplateArgs); + bool DependentID = false; + if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName && + Name.getCXXNameType()->isDependentType()) { + DependentID = true; + } else if (SS.isSet()) { + DeclContext *DC = computeDeclContext(SS, false); + if (DC) { + if (RequireCompleteDeclContext(SS, DC)) + return ExprError(); + // FIXME: We should be checking whether DC is the current instantiation. + if (CXXRecordDecl *RD = dyn_cast(DC)) + DependentID = !IsFullyFormedScope(*this, RD); + } else { + DependentID = true; + } } + if (DependentID) { + return ActOnDependentIdExpression(SS, NameInfo, isAddressOfOperand, + TemplateArgs); + } + bool IvarLookupFollowUp = false; // Perform the required lookup. - LookupResult R(*this, Name, NameLoc, LookupOrdinaryName); + LookupResult R(*this, NameInfo, LookupOrdinaryName); if (TemplateArgs) { // Lookup the template name again to correctly establish the context in // which it was found. This is really unfortunate as we already did the @@ -1058,18 +1131,26 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S, LookupTemplateName(R, S, SS, QualType(), /*EnteringContext=*/false, MemberOfUnknownSpecialization); } else { - bool IvarLookupFollowUp = (!SS.isSet() && II && getCurMethodDecl()); + IvarLookupFollowUp = (!SS.isSet() && II && getCurMethodDecl()); LookupParsedName(R, S, &SS, !IvarLookupFollowUp); // If this reference is in an Objective-C method, then we need to do // some special Objective-C lookup, too. if (IvarLookupFollowUp) { - OwningExprResult E(LookupInObjCMethod(R, S, II, true)); + ExprResult E(LookupInObjCMethod(R, S, II, true)); if (E.isInvalid()) return ExprError(); Expr *Ex = E.takeAs(); if (Ex) return Owned(Ex); + // Synthesize ivars lazily + if (getLangOptions().ObjCNonFragileABI2) { + if (SynthesizeProvisionalIvar(*this, R, II, NameLoc)) + return ActOnIdExpression(S, SS, Id, HasTrailingLParen, + isAddressOfOperand); + } + // for further use, this must be set to false if in class method. + IvarLookupFollowUp = getCurMethodDecl()->isInstanceMethod(); } } @@ -1102,7 +1183,7 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S, // reference the ivar. if (ObjCIvarDecl *Ivar = R.getAsSingle()) { R.clear(); - OwningExprResult E(LookupInObjCMethod(R, S, Ivar->getIdentifier())); + ExprResult E(LookupInObjCMethod(R, S, Ivar->getIdentifier())); assert(E.isInvalid() || E.get()); return move(E); } @@ -1113,23 +1194,15 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S, assert(!R.empty() || ADL); if (VarDecl *Var = R.getAsSingle()) { - // Warn about constructs like: - // if (void *X = foo()) { ... } else { X }. - // In the else block, the pointer is always false. - if (Var->isDeclaredInCondition() && Var->getType()->isScalarType()) { - Scope *CheckS = S; - while (CheckS && CheckS->getControlParent()) { - if ((CheckS->getFlags() & Scope::ElseScope) && - CheckS->getControlParent()->isDeclScope(DeclPtrTy::make(Var))) { - ExprError(Diag(NameLoc, diag::warn_value_always_zero) - << Var->getDeclName() - << (Var->getType()->isPointerType() ? 2 : - Var->getType()->isBooleanType() ? 1 : 0)); - break; - } - - // Move to the parent of this scope. - CheckS = CheckS->getParent(); + if (getLangOptions().ObjCNonFragileABI && IvarLookupFollowUp && + !getLangOptions().ObjCNonFragileABI2 && + Var->isFileVarDecl()) { + ObjCPropertyDecl *Property = + OkToSynthesizeProvisionalIvar(*this, II, NameLoc); + if (Property) { + Diag(NameLoc, diag::warn_ivar_variable_conflict) << Var->getDeclName(); + Diag(Property->getLocation(), diag::note_property_declare); + Diag(Var->getLocation(), diag::note_global_declared_at); } } } else if (FunctionDecl *Func = R.getAsSingle()) { @@ -1152,15 +1225,43 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S, } // Check whether this might be a C++ implicit instance member access. - // C++ [expr.prim.general]p6: - // Within the definition of a non-static member function, an - // identifier that names a non-static member is transformed to a - // class member access expression. - // But note that &SomeClass::foo is grammatically distinct, even - // though we don't parse it that way. + // C++ [class.mfct.non-static]p3: + // When an id-expression that is not part of a class member access + // syntax and not used to form a pointer to member is used in the + // body of a non-static member function of class X, if name lookup + // resolves the name in the id-expression to a non-static non-type + // member of some class C, the id-expression is transformed into a + // class member access expression using (*this) as the + // postfix-expression to the left of the . operator. + // + // But we don't actually need to do this for '&' operands if R + // resolved to a function or overloaded function set, because the + // expression is ill-formed if it actually works out to be a + // non-static member function: + // + // C++ [expr.ref]p4: + // Otherwise, if E1.E2 refers to a non-static member function. . . + // [t]he expression can be used only as the left-hand operand of a + // member function call. + // + // There are other safeguards against such uses, but it's important + // to get this right here so that we don't end up making a + // spuriously dependent expression if we're inside a dependent + // instance method. if (!R.empty() && (*R.begin())->isCXXClassMember()) { - bool isAbstractMemberPointer = (isAddressOfOperand && !SS.isEmpty()); - if (!isAbstractMemberPointer) + bool MightBeImplicitMember; + if (!isAddressOfOperand) + MightBeImplicitMember = true; + else if (!SS.isEmpty()) + MightBeImplicitMember = false; + else if (R.isOverloadedResult()) + MightBeImplicitMember = false; + else if (R.isUnresolvableResult()) + MightBeImplicitMember = true; + else + MightBeImplicitMember = isa(R.getFoundDecl()); + + if (MightBeImplicitMember) return BuildPossibleImplicitMemberExpr(SS, R, TemplateArgs); } @@ -1171,7 +1272,7 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S, } /// Builds an expression which might be an implicit member expression. -Sema::OwningExprResult +ExprResult Sema::BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS, LookupResult &R, const TemplateArgumentListInfo *TemplateArgs) { @@ -1210,25 +1311,25 @@ Sema::BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS, /// declaration name, generally during template instantiation. /// There's a large number of things which don't need to be done along /// this path. -Sema::OwningExprResult +ExprResult Sema::BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS, - DeclarationName Name, - SourceLocation NameLoc) { + const DeclarationNameInfo &NameInfo) { DeclContext *DC; if (!(DC = computeDeclContext(SS, false)) || DC->isDependentContext()) - return BuildDependentDeclRefExpr(SS, Name, NameLoc, 0); + return BuildDependentDeclRefExpr(SS, NameInfo, 0); if (RequireCompleteDeclContext(SS, DC)) return ExprError(); - LookupResult R(*this, Name, NameLoc, LookupOrdinaryName); + LookupResult R(*this, NameInfo, LookupOrdinaryName); LookupQualifiedName(R, DC); if (R.isAmbiguous()) return ExprError(); if (R.empty()) { - Diag(NameLoc, diag::err_no_member) << Name << DC << SS.getRange(); + Diag(NameInfo.getLoc(), diag::err_no_member) + << NameInfo.getName() << DC << SS.getRange(); return ExprError(); } @@ -1243,7 +1344,7 @@ Sema::BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS, /// actually quite a lot of extra work involved. /// /// Returns a null sentinel to indicate trivial success. -Sema::OwningExprResult +ExprResult Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S, IdentifierInfo *II, bool AllowBuiltinCreation) { SourceLocation Loc = Lookup.getNameLoc(); @@ -1298,7 +1399,7 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S, UnqualifiedId SelfName; SelfName.setIdentifier(&II, SourceLocation()); CXXScopeSpec SelfScopeSpec; - OwningExprResult SelfExpr = ActOnIdExpression(S, SelfScopeSpec, + ExprResult SelfExpr = ActOnIdExpression(S, SelfScopeSpec, SelfName, false, false); MarkDeclarationReferenced(Loc, IV); return Owned(new (Context) @@ -1403,9 +1504,8 @@ Sema::PerformObjectMemberConversion(Expr *&From, SourceRange FromRange = From->getSourceRange(); SourceLocation FromLoc = FromRange.getBegin(); - bool isLvalue - = (From->isLvalue(Context) == Expr::LV_Valid) && !PointerConversions; - + ExprValueKind VK = CastCategory(From); + // C++ [class.member.lookup]p8: // [...] Ambiguities can often be resolved by qualifying a name with its // class name. @@ -1435,15 +1535,15 @@ Sema::PerformObjectMemberConversion(Expr *&From, // type of the object type, in which case we just ignore it. // Otherwise build the appropriate casts. if (IsDerivedFrom(FromRecordType, QRecordType)) { - CXXBaseSpecifierArray BasePath; + CXXCastPath BasePath; if (CheckDerivedToBaseConversion(FromRecordType, QRecordType, FromLoc, FromRange, &BasePath)) return true; if (PointerConversions) QType = Context.getPointerType(QType); - ImpCastExprToType(From, QType, CastExpr::CK_UncheckedDerivedToBase, - isLvalue, BasePath); + ImpCastExprToType(From, QType, CK_UncheckedDerivedToBase, + VK, &BasePath); FromType = QType; FromRecordType = QRecordType; @@ -1471,7 +1571,7 @@ Sema::PerformObjectMemberConversion(Expr *&From, // conversion is non-trivial. if (!Context.hasSameUnqualifiedType(FromRecordType, URecordType)) { assert(IsDerivedFrom(FromRecordType, URecordType)); - CXXBaseSpecifierArray BasePath; + CXXCastPath BasePath; if (CheckDerivedToBaseConversion(FromRecordType, URecordType, FromLoc, FromRange, &BasePath)) return true; @@ -1479,8 +1579,8 @@ Sema::PerformObjectMemberConversion(Expr *&From, QualType UType = URecordType; if (PointerConversions) UType = Context.getPointerType(UType); - ImpCastExprToType(From, UType, CastExpr::CK_UncheckedDerivedToBase, - isLvalue, BasePath); + ImpCastExprToType(From, UType, CK_UncheckedDerivedToBase, + VK, &BasePath); FromType = UType; FromRecordType = URecordType; } @@ -1490,14 +1590,14 @@ Sema::PerformObjectMemberConversion(Expr *&From, IgnoreAccess = true; } - CXXBaseSpecifierArray BasePath; + CXXCastPath BasePath; if (CheckDerivedToBaseConversion(FromRecordType, DestRecordType, FromLoc, FromRange, &BasePath, IgnoreAccess)) return true; - ImpCastExprToType(From, DestType, CastExpr::CK_UncheckedDerivedToBase, - isLvalue, BasePath); + ImpCastExprToType(From, DestType, CK_UncheckedDerivedToBase, + VK, &BasePath); return false; } @@ -1505,7 +1605,8 @@ Sema::PerformObjectMemberConversion(Expr *&From, static MemberExpr *BuildMemberExpr(ASTContext &C, Expr *Base, bool isArrow, const CXXScopeSpec &SS, ValueDecl *Member, DeclAccessPair FoundDecl, - SourceLocation Loc, QualType Ty, + const DeclarationNameInfo &MemberNameInfo, + QualType Ty, const TemplateArgumentListInfo *TemplateArgs = 0) { NestedNameSpecifier *Qualifier = 0; SourceRange QualifierRange; @@ -1515,14 +1616,15 @@ static MemberExpr *BuildMemberExpr(ASTContext &C, Expr *Base, bool isArrow, } return MemberExpr::Create(C, Base, isArrow, Qualifier, QualifierRange, - Member, FoundDecl, Loc, TemplateArgs, Ty); + Member, FoundDecl, MemberNameInfo, + TemplateArgs, Ty); } /// Builds an implicit member access expression. The current context /// is known to be an instance method, and the given unqualified lookup /// set is known to contain only instance members, at least one of which /// is from an appropriate type. -Sema::OwningExprResult +ExprResult Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS, LookupResult &R, const TemplateArgumentListInfo *TemplateArgs, @@ -1551,7 +1653,7 @@ Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS, This = new (Context) CXXThisExpr(Loc, ThisType, /*isImplicit=*/true); } - return BuildMemberReferenceExpr(ExprArg(*this, This), ThisType, + return BuildMemberReferenceExpr(This, ThisType, /*OpLoc*/ SourceLocation(), /*IsArrow*/ true, SS, @@ -1638,14 +1740,15 @@ static bool CheckDeclInExpr(Sema &S, SourceLocation Loc, NamedDecl *D) { return false; } -Sema::OwningExprResult +ExprResult Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, LookupResult &R, bool NeedsADL) { // If this is a single, fully-resolved result and we don't need ADL, // just build an ordinary singleton decl ref. if (!NeedsADL && R.isSingleResult() && !R.getAsSingle()) - return BuildDeclarationNameExpr(SS, R.getNameLoc(), R.getFoundDecl()); + return BuildDeclarationNameExpr(SS, R.getLookupNameInfo(), + R.getFoundDecl()); // We only need to check the declaration if there's exactly one // result, because in the overloaded case the results can only be @@ -1664,8 +1767,7 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, UnresolvedLookupExpr *ULE = UnresolvedLookupExpr::Create(Context, Dependent, R.getNamingClass(), (NestedNameSpecifier*) SS.getScopeRep(), - SS.getRange(), - R.getLookupName(), R.getNameLoc(), + SS.getRange(), R.getLookupNameInfo(), NeedsADL, R.isOverloadedResult(), R.begin(), R.end()); @@ -1674,13 +1776,15 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, /// \brief Complete semantic analysis for a reference to the given declaration. -Sema::OwningExprResult +ExprResult Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, - SourceLocation Loc, NamedDecl *D) { + const DeclarationNameInfo &NameInfo, + NamedDecl *D) { assert(D && "Cannot refer to a NULL declaration"); assert(!isa(D) && "Cannot refer unambiguously to a function template"); + SourceLocation Loc = NameInfo.getLoc(); if (CheckDeclInExpr(*this, Loc, D)) return ExprError(); @@ -1755,13 +1859,13 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, DeclRefExpr(const_cast(BDRE->getDecl()), T, SourceLocation()); - OwningExprResult Res = PerformCopyInitialization( + ExprResult Res = PerformCopyInitialization( InitializedEntity::InitializeBlock(VD->getLocation(), T, false), SourceLocation(), Owned(E)); if (!Res.isInvalid()) { - Res = MaybeCreateCXXExprWithTemporaries(move(Res)); + Res = MaybeCreateCXXExprWithTemporaries(Res.get()); Expr *Init = Res.takeAs(); BDRE->setCopyConstructorExpr(Init); } @@ -1772,10 +1876,11 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, // If this reference is not in a block or if the referenced variable is // within the block, create a normal DeclRefExpr. - return BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(), Loc, &SS); + return BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(), + NameInfo, &SS); } -Sema::OwningExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, +ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) { PredefinedExpr::IdentType IT; @@ -1790,6 +1895,8 @@ Sema::OwningExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, // string. Decl *currentDecl = getCurFunctionOrMethodDecl(); + if (!currentDecl && getCurBlock()) + currentDecl = getCurBlock()->TheDecl; if (!currentDecl) { Diag(Loc, diag::ext_predef_outside_function); currentDecl = Context.getTranslationUnitDecl(); @@ -1808,7 +1915,7 @@ Sema::OwningExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, return Owned(new (Context) PredefinedExpr(Loc, ResTy, IT)); } -Sema::OwningExprResult Sema::ActOnCharacterConstant(const Token &Tok) { +ExprResult Sema::ActOnCharacterConstant(const Token &Tok) { llvm::SmallString<16> CharBuffer; bool Invalid = false; llvm::StringRef ThisTok = PP.getSpelling(Tok, CharBuffer, &Invalid); @@ -1835,13 +1942,13 @@ Sema::OwningExprResult Sema::ActOnCharacterConstant(const Token &Tok) { Ty, Tok.getLocation())); } -Action::OwningExprResult Sema::ActOnNumericConstant(const Token &Tok) { +ExprResult Sema::ActOnNumericConstant(const Token &Tok) { // Fast path for a single digit (which is quite common). A single digit // cannot have a trigraph, escaped newline, radix prefix, or type suffix. if (Tok.getLength() == 1) { const char Val = PP.getSpellingOfSingleCharacterNumericConstant(Tok); unsigned IntSize = Context.Target.getIntWidth(); - return Owned(new (Context) IntegerLiteral(llvm::APInt(IntSize, Val-'0'), + return Owned(IntegerLiteral::Create(Context, llvm::APInt(IntSize, Val-'0'), Context.IntTy, Tok.getLocation())); } @@ -1899,7 +2006,7 @@ Action::OwningExprResult Sema::ActOnNumericConstant(const Token &Tok) { } bool isExact = (result == APFloat::opOK); - Res = new (Context) FloatingLiteral(Val, isExact, Ty, Tok.getLocation()); + Res = FloatingLiteral::Create(Context, Val, isExact, Ty, Tok.getLocation()); } else if (!Literal.isIntegerLiteral()) { return ExprError(); @@ -1986,7 +2093,7 @@ Action::OwningExprResult Sema::ActOnNumericConstant(const Token &Tok) { if (ResultVal.getBitWidth() != Width) ResultVal.trunc(Width); } - Res = new (Context) IntegerLiteral(ResultVal, Ty, Tok.getLocation()); + Res = IntegerLiteral::Create(Context, ResultVal, Ty, Tok.getLocation()); } // If this is an imaginary literal, create the ImaginaryLiteral wrapper. @@ -1997,9 +2104,8 @@ Action::OwningExprResult Sema::ActOnNumericConstant(const Token &Tok) { return Owned(Res); } -Action::OwningExprResult Sema::ActOnParenExpr(SourceLocation L, - SourceLocation R, ExprArg Val) { - Expr *E = Val.takeAs(); +ExprResult Sema::ActOnParenExpr(SourceLocation L, + SourceLocation R, Expr *E) { assert((E != 0) && "ActOnParenExpr() missing expr"); return Owned(new (Context) ParenExpr(L, R, E)); } @@ -2083,7 +2189,7 @@ bool Sema::CheckAlignOfExpr(Expr *E, SourceLocation OpLoc, } /// \brief Build a sizeof or alignof expression given a type operand. -Action::OwningExprResult +ExprResult Sema::CreateSizeOfAlignOfExpr(TypeSourceInfo *TInfo, SourceLocation OpLoc, bool isSizeOf, SourceRange R) { @@ -2104,7 +2210,7 @@ Sema::CreateSizeOfAlignOfExpr(TypeSourceInfo *TInfo, /// \brief Build a sizeof or alignof expression given an expression /// operand. -Action::OwningExprResult +ExprResult Sema::CreateSizeOfAlignOfExpr(Expr *E, SourceLocation OpLoc, bool isSizeOf, SourceRange R) { // Verify that the operand is valid. @@ -2132,7 +2238,7 @@ Sema::CreateSizeOfAlignOfExpr(Expr *E, SourceLocation OpLoc, /// ActOnSizeOfAlignOfExpr - Handle @c sizeof(type) and @c sizeof @c expr and /// the same for @c alignof and @c __alignof /// Note that the ArgRange is invalid if isType is false. -Action::OwningExprResult +ExprResult Sema::ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType, void *TyOrEx, const SourceRange &ArgRange) { // If error parsing type, ignore. @@ -2140,17 +2246,14 @@ Sema::ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType, if (isType) { TypeSourceInfo *TInfo; - (void) GetTypeFromParser(TyOrEx, &TInfo); + (void) GetTypeFromParser(ParsedType::getFromOpaquePtr(TyOrEx), &TInfo); return CreateSizeOfAlignOfExpr(TInfo, OpLoc, isSizeof, ArgRange); } Expr *ArgEx = (Expr *)TyOrEx; - Action::OwningExprResult Result + ExprResult Result = CreateSizeOfAlignOfExpr(ArgEx, OpLoc, isSizeof, ArgEx->getSourceRange()); - if (Result.isInvalid()) - DeleteExpr(ArgEx); - return move(Result); } @@ -2174,32 +2277,31 @@ QualType Sema::CheckRealImagOperand(Expr *&V, SourceLocation Loc, bool isReal) { -Action::OwningExprResult +ExprResult Sema::ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc, - tok::TokenKind Kind, ExprArg Input) { - UnaryOperator::Opcode Opc; + tok::TokenKind Kind, Expr *Input) { + UnaryOperatorKind Opc; switch (Kind) { default: assert(0 && "Unknown unary op!"); - case tok::plusplus: Opc = UnaryOperator::PostInc; break; - case tok::minusminus: Opc = UnaryOperator::PostDec; break; + case tok::plusplus: Opc = UO_PostInc; break; + case tok::minusminus: Opc = UO_PostDec; break; } - return BuildUnaryOp(S, OpLoc, Opc, move(Input)); + return BuildUnaryOp(S, OpLoc, Opc, Input); } -Action::OwningExprResult -Sema::ActOnArraySubscriptExpr(Scope *S, ExprArg Base, SourceLocation LLoc, - ExprArg Idx, SourceLocation RLoc) { +ExprResult +Sema::ActOnArraySubscriptExpr(Scope *S, Expr *Base, SourceLocation LLoc, + Expr *Idx, SourceLocation RLoc) { // Since this might be a postfix expression, get rid of ParenListExprs. - Base = MaybeConvertParenListExprToParenExpr(S, move(Base)); + ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Base); + if (Result.isInvalid()) return ExprError(); + Base = Result.take(); - Expr *LHSExp = static_cast(Base.get()), - *RHSExp = static_cast(Idx.get()); + Expr *LHSExp = Base, *RHSExp = Idx; if (getLangOptions().CPlusPlus && (LHSExp->isTypeDependent() || RHSExp->isTypeDependent())) { - Base.release(); - Idx.release(); return Owned(new (Context) ArraySubscriptExpr(LHSExp, RHSExp, Context.DependentTy, RLoc)); } @@ -2209,18 +2311,18 @@ Sema::ActOnArraySubscriptExpr(Scope *S, ExprArg Base, SourceLocation LLoc, LHSExp->getType()->isEnumeralType() || RHSExp->getType()->isRecordType() || RHSExp->getType()->isEnumeralType())) { - return CreateOverloadedArraySubscriptExpr(LLoc, RLoc, move(Base),move(Idx)); + return CreateOverloadedArraySubscriptExpr(LLoc, RLoc, Base, Idx); } - return CreateBuiltinArraySubscriptExpr(move(Base), LLoc, move(Idx), RLoc); + return CreateBuiltinArraySubscriptExpr(Base, LLoc, Idx, RLoc); } -Action::OwningExprResult -Sema::CreateBuiltinArraySubscriptExpr(ExprArg Base, SourceLocation LLoc, - ExprArg Idx, SourceLocation RLoc) { - Expr *LHSExp = static_cast(Base.get()); - Expr *RHSExp = static_cast(Idx.get()); +ExprResult +Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, + Expr *Idx, SourceLocation RLoc) { + Expr *LHSExp = Base; + Expr *RHSExp = Idx; // Perform default conversions. if (!LHSExp->getType()->getAs()) @@ -2274,7 +2376,7 @@ Sema::CreateBuiltinArraySubscriptExpr(ExprArg Base, SourceLocation LLoc, Diag(LHSExp->getLocStart(), diag::ext_subscript_non_lvalue) << LHSExp->getSourceRange(); ImpCastExprToType(LHSExp, Context.getArrayDecayedType(LHSTy), - CastExpr::CK_ArrayToPointerDecay); + CK_ArrayToPointerDecay); LHSTy = LHSExp->getType(); BaseExpr = LHSExp; @@ -2285,7 +2387,7 @@ Sema::CreateBuiltinArraySubscriptExpr(ExprArg Base, SourceLocation LLoc, Diag(RHSExp->getLocStart(), diag::ext_subscript_non_lvalue) << RHSExp->getSourceRange(); ImpCastExprToType(RHSExp, Context.getArrayDecayedType(RHSTy), - CastExpr::CK_ArrayToPointerDecay); + CK_ArrayToPointerDecay); RHSTy = RHSExp->getType(); BaseExpr = RHSExp; @@ -2296,8 +2398,7 @@ Sema::CreateBuiltinArraySubscriptExpr(ExprArg Base, SourceLocation LLoc, << LHSExp->getSourceRange() << RHSExp->getSourceRange()); } // C99 6.5.2.1p1 - if (!(IndexExpr->getType()->isIntegerType() && - IndexExpr->getType()->isScalarType()) && !IndexExpr->isTypeDependent()) + if (!IndexExpr->getType()->isIntegerType() && !IndexExpr->isTypeDependent()) return ExprError(Diag(LLoc, diag::err_typecheck_subscript_not_integer) << IndexExpr->getSourceRange()); @@ -2329,8 +2430,6 @@ Sema::CreateBuiltinArraySubscriptExpr(ExprArg Base, SourceLocation LLoc, return ExprError(); } - Base.release(); - Idx.release(); return Owned(new (Context) ArraySubscriptExpr(LHSExp, RHSExp, ResultType, RLoc)); } @@ -2377,7 +2476,7 @@ CheckExtVectorComponent(QualType baseType, SourceLocation OpLoc, // We didn't get to the end of the string. This means the component names // didn't come from the same set *or* we encountered an illegal name. Diag(OpLoc, diag::err_ext_vector_component_name_illegal) - << std::string(compStr,compStr+1) << SourceRange(CompLoc); + << llvm::StringRef(compStr, 1) << SourceRange(CompLoc); return QualType(); } @@ -2470,15 +2569,13 @@ static Decl *FindGetterNameDecl(const ObjCObjectPointerType *QIdTy, return GDecl; } -Sema::OwningExprResult -Sema::ActOnDependentMemberExpr(ExprArg Base, QualType BaseType, +ExprResult +Sema::ActOnDependentMemberExpr(Expr *BaseExpr, QualType BaseType, bool IsArrow, SourceLocation OpLoc, const CXXScopeSpec &SS, NamedDecl *FirstQualifierInScope, - DeclarationName Name, SourceLocation NameLoc, + const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs) { - Expr *BaseExpr = Base.takeAs(); - // Even in dependent contexts, try to diagnose base expressions with // obviously wrong types, e.g.: // @@ -2493,24 +2590,24 @@ Sema::ActOnDependentMemberExpr(ExprArg Base, QualType BaseType, if (PT && (!getLangOptions().ObjC1 || PT->getPointeeType()->isRecordType())) { assert(BaseExpr && "cannot happen with implicit member accesses"); - Diag(NameLoc, diag::err_typecheck_member_reference_struct_union) + Diag(NameInfo.getLoc(), diag::err_typecheck_member_reference_struct_union) << BaseType << BaseExpr->getSourceRange(); return ExprError(); } } - assert(BaseType->isDependentType() || Name.isDependentName() || + assert(BaseType->isDependentType() || + NameInfo.getName().isDependentName() || isDependentScopeSpecifier(SS)); // Get the type being accessed in BaseType. If this is an arrow, the BaseExpr // must have pointer type, and the accessed type is the pointee. return Owned(CXXDependentScopeMemberExpr::Create(Context, BaseExpr, BaseType, IsArrow, OpLoc, - static_cast(SS.getScopeRep()), + SS.getScopeRep(), SS.getRange(), FirstQualifierInScope, - Name, NameLoc, - TemplateArgs)); + NameInfo, TemplateArgs)); } /// We know that the given qualified member reference points only to @@ -2562,12 +2659,15 @@ bool Sema::CheckQualifiedMemberReference(Expr *BaseExpr, return false; // Note that we use the DC of the decl, not the underlying decl. - CXXRecordDecl *RecordD = cast((*I)->getDeclContext()); - while (RecordD->isAnonymousStructOrUnion()) - RecordD = cast(RecordD->getParent()); + DeclContext *DC = (*I)->getDeclContext(); + while (DC->isTransparentContext()) + DC = DC->getParent(); + if (!DC->isRecord()) + continue; + llvm::SmallPtrSet MemberRecord; - MemberRecord.insert(RecordD->getCanonicalDecl()); + MemberRecord.insert(cast(DC)->getCanonicalDecl()); if (!IsProvablyNotDerivedFrom(*this, BaseRecord, MemberRecord)) return false; @@ -2646,24 +2746,21 @@ LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R, return false; } -Sema::OwningExprResult -Sema::BuildMemberReferenceExpr(ExprArg BaseArg, QualType BaseType, +ExprResult +Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType, SourceLocation OpLoc, bool IsArrow, CXXScopeSpec &SS, NamedDecl *FirstQualifierInScope, - DeclarationName Name, SourceLocation NameLoc, + const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs) { - Expr *Base = BaseArg.takeAs(); - if (BaseType->isDependentType() || (SS.isSet() && isDependentScopeSpecifier(SS))) - return ActOnDependentMemberExpr(ExprArg(*this, Base), BaseType, + return ActOnDependentMemberExpr(Base, BaseType, IsArrow, OpLoc, SS, FirstQualifierInScope, - Name, NameLoc, - TemplateArgs); + NameInfo, TemplateArgs); - LookupResult R(*this, Name, NameLoc, LookupMemberName); + LookupResult R(*this, NameInfo, LookupMemberName); // Implicit member accesses. if (!Base) { @@ -2676,9 +2773,9 @@ Sema::BuildMemberReferenceExpr(ExprArg BaseArg, QualType BaseType, // Explicit member accesses. } else { - OwningExprResult Result = + ExprResult Result = LookupMemberExpr(R, Base, IsArrow, OpLoc, - SS, /*ObjCImpDecl*/ DeclPtrTy(), TemplateArgs != 0); + SS, /*ObjCImpDecl*/ 0, TemplateArgs != 0); if (Result.isInvalid()) { Owned(Base); @@ -2692,20 +2789,19 @@ Sema::BuildMemberReferenceExpr(ExprArg BaseArg, QualType BaseType, BaseType = Base->getType(); } - return BuildMemberReferenceExpr(ExprArg(*this, Base), BaseType, + return BuildMemberReferenceExpr(Base, BaseType, OpLoc, IsArrow, SS, FirstQualifierInScope, R, TemplateArgs); } -Sema::OwningExprResult -Sema::BuildMemberReferenceExpr(ExprArg Base, QualType BaseExprType, +ExprResult +Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, SourceLocation OpLoc, bool IsArrow, const CXXScopeSpec &SS, NamedDecl *FirstQualifierInScope, LookupResult &R, const TemplateArgumentListInfo *TemplateArgs, bool SuppressQualifierCheck) { - Expr *BaseExpr = Base.takeAs(); QualType BaseType = BaseExprType; if (IsArrow) { assert(BaseType->isPointerType()); @@ -2713,10 +2809,10 @@ Sema::BuildMemberReferenceExpr(ExprArg Base, QualType BaseExprType, } R.setBaseObjectType(BaseType); - NestedNameSpecifier *Qualifier = - static_cast(SS.getScopeRep()); - DeclarationName MemberName = R.getLookupName(); - SourceLocation MemberLoc = R.getNameLoc(); + NestedNameSpecifier *Qualifier = SS.getScopeRep(); + const DeclarationNameInfo &MemberNameInfo = R.getLookupNameInfo(); + DeclarationName MemberName = MemberNameInfo.getName(); + SourceLocation MemberLoc = MemberNameInfo.getLoc(); if (R.isAmbiguous()) return ExprError(); @@ -2765,7 +2861,7 @@ Sema::BuildMemberReferenceExpr(ExprArg Base, QualType BaseExprType, BaseExpr, BaseExprType, IsArrow, OpLoc, Qualifier, SS.getRange(), - MemberName, MemberLoc, + MemberNameInfo, TemplateArgs, R.begin(), R.end()); return Owned(MemExpr); @@ -2787,7 +2883,7 @@ Sema::BuildMemberReferenceExpr(ExprArg Base, QualType BaseExprType, if (!BaseExpr) { // If this is not an instance member, convert to a non-member access. if (!MemberDecl->isCXXInstanceMember()) - return BuildDeclarationNameExpr(SS, R.getNameLoc(), MemberDecl); + return BuildDeclarationNameExpr(SS, R.getLookupNameInfo(), MemberDecl); SourceLocation Loc = R.getNameLoc(); if (SS.getRange().isValid()) @@ -2838,34 +2934,36 @@ Sema::BuildMemberReferenceExpr(ExprArg Base, QualType BaseExprType, if (PerformObjectMemberConversion(BaseExpr, Qualifier, FoundDecl, FD)) return ExprError(); return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS, - FD, FoundDecl, MemberLoc, MemberType)); + FD, FoundDecl, MemberNameInfo, + MemberType)); } if (VarDecl *Var = dyn_cast(MemberDecl)) { MarkDeclarationReferenced(MemberLoc, Var); return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS, - Var, FoundDecl, MemberLoc, + Var, FoundDecl, MemberNameInfo, Var->getType().getNonReferenceType())); } if (FunctionDecl *MemberFn = dyn_cast(MemberDecl)) { MarkDeclarationReferenced(MemberLoc, MemberDecl); return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS, - MemberFn, FoundDecl, MemberLoc, + MemberFn, FoundDecl, MemberNameInfo, MemberFn->getType())); } if (EnumConstantDecl *Enum = dyn_cast(MemberDecl)) { MarkDeclarationReferenced(MemberLoc, MemberDecl); return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS, - Enum, FoundDecl, MemberLoc, Enum->getType())); + Enum, FoundDecl, MemberNameInfo, + Enum->getType())); } Owned(BaseExpr); // We found something that we didn't expect. Complain. if (isa(MemberDecl)) - Diag(MemberLoc,diag::err_typecheck_member_reference_type) + Diag(MemberLoc, diag::err_typecheck_member_reference_type) << MemberName << BaseType << int(IsArrow); else Diag(MemberLoc, diag::err_typecheck_member_reference_unknown) @@ -2887,11 +2985,11 @@ Sema::BuildMemberReferenceExpr(ExprArg Base, QualType BaseExprType, /// /// The ObjCImpDecl bit is a gross hack that will need to be properly /// fixed for ObjC++. -Sema::OwningExprResult +ExprResult Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, bool &IsArrow, SourceLocation OpLoc, CXXScopeSpec &SS, - DeclPtrTy ObjCImpDecl, bool HasTemplateArgs) { + Decl *ObjCImpDecl, bool HasTemplateArgs) { assert(BaseExpr && "no base expression"); // Perform default conversions. @@ -2921,8 +3019,8 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, << QualType(Fun, 0) << FixItHint::CreateInsertion(Loc, "()"); - OwningExprResult NewBase - = ActOnCallExpr(0, ExprArg(*this, BaseExpr), Loc, + ExprResult NewBase + = ActOnCallExpr(0, BaseExpr, Loc, MultiExprArg(*this, 0, 0), 0, Loc); BaseExpr = 0; if (NewBase.isInvalid()) @@ -2952,7 +3050,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, // is a reference to 'isa'. if (BaseType != Context.ObjCIdRedefinitionType) { BaseType = Context.ObjCIdRedefinitionType; - ImpCastExprToType(BaseExpr, BaseType, CastExpr::CK_BitCast); + ImpCastExprToType(BaseExpr, BaseType, CK_BitCast); } } @@ -2963,7 +3061,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, // is a reference to 'sel_id'. if (BaseType != Context.ObjCSelRedefinitionType) { BaseType = Context.ObjCSelRedefinitionType; - ImpCastExprToType(BaseExpr, BaseType, CastExpr::CK_BitCast); + ImpCastExprToType(BaseExpr, BaseType, CK_BitCast); } } @@ -3022,7 +3120,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, if (BaseType->isObjCClassType() && BaseType != Context.ObjCClassRedefinitionType) { BaseType = Context.ObjCClassRedefinitionType; - ImpCastExprToType(BaseExpr, BaseType, CastExpr::CK_BitCast); + ImpCastExprToType(BaseExpr, BaseType, CK_BitCast); } if (IsArrow) { @@ -3129,12 +3227,11 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, // down the context as argument to this routine. Ideally, this context // need be passed down in the AST node and somehow calculated from the // AST for a function decl. - Decl *ImplDecl = ObjCImpDecl.getAs(); if (ObjCImplementationDecl *IMPD = - dyn_cast(ImplDecl)) + dyn_cast(ObjCImpDecl)) ClassOfMethodDecl = IMPD->getClassInterface(); else if (ObjCCategoryImplDecl* CatImplClass = - dyn_cast(ImplDecl)) + dyn_cast(ObjCImpDecl)) ClassOfMethodDecl = CatImplClass->getClassInterface(); } @@ -3235,12 +3332,12 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, /// \param ObjCImpDecl the current ObjC @implementation decl; /// this is an ugly hack around the fact that ObjC @implementations /// aren't properly put in the context chain -Sema::OwningExprResult Sema::ActOnMemberAccessExpr(Scope *S, ExprArg BaseArg, +ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base, SourceLocation OpLoc, tok::TokenKind OpKind, CXXScopeSpec &SS, UnqualifiedId &Id, - DeclPtrTy ObjCImpDecl, + Decl *ObjCImpDecl, bool HasTrailingLParen) { if (SS.isSet() && SS.isInvalid()) return ExprError(); @@ -3248,12 +3345,12 @@ Sema::OwningExprResult Sema::ActOnMemberAccessExpr(Scope *S, ExprArg BaseArg, TemplateArgumentListInfo TemplateArgsBuffer; // Decompose the name into its component parts. - DeclarationName Name; - SourceLocation NameLoc; + DeclarationNameInfo NameInfo; const TemplateArgumentListInfo *TemplateArgs; DecomposeUnqualifiedId(*this, Id, TemplateArgsBuffer, - Name, NameLoc, TemplateArgs); + NameInfo, TemplateArgs); + DeclarationName Name = NameInfo.getName(); bool IsArrow = (OpKind == tok::arrow); NamedDecl *FirstQualifierInScope @@ -3261,19 +3358,18 @@ Sema::OwningExprResult Sema::ActOnMemberAccessExpr(Scope *S, ExprArg BaseArg, static_cast(SS.getScopeRep()))); // This is a postfix expression, so get rid of ParenListExprs. - BaseArg = MaybeConvertParenListExprToParenExpr(S, move(BaseArg)); + ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Base); + if (Result.isInvalid()) return ExprError(); + Base = Result.take(); - Expr *Base = BaseArg.takeAs(); - OwningExprResult Result(*this); if (Base->getType()->isDependentType() || Name.isDependentName() || isDependentScopeSpecifier(SS)) { - Result = ActOnDependentMemberExpr(ExprArg(*this, Base), Base->getType(), + Result = ActOnDependentMemberExpr(Base, Base->getType(), IsArrow, OpLoc, SS, FirstQualifierInScope, - Name, NameLoc, - TemplateArgs); + NameInfo, TemplateArgs); } else { - LookupResult R(*this, Name, NameLoc, LookupMemberName); + LookupResult R(*this, NameInfo, LookupMemberName); Result = LookupMemberExpr(R, Base, IsArrow, OpLoc, SS, ObjCImpDecl, TemplateArgs != 0); @@ -3289,12 +3385,12 @@ Sema::OwningExprResult Sema::ActOnMemberAccessExpr(Scope *S, ExprArg BaseArg, // call now. if (!HasTrailingLParen && Id.getKind() == UnqualifiedId::IK_DestructorName) - return DiagnoseDtorReference(NameLoc, move(Result)); + return DiagnoseDtorReference(NameInfo.getLoc(), Result.get()); return move(Result); } - Result = BuildMemberReferenceExpr(ExprArg(*this, Base), Base->getType(), + Result = BuildMemberReferenceExpr(Base, Base->getType(), OpLoc, IsArrow, SS, FirstQualifierInScope, R, TemplateArgs); } @@ -3302,7 +3398,7 @@ Sema::OwningExprResult Sema::ActOnMemberAccessExpr(Scope *S, ExprArg BaseArg, return move(Result); } -Sema::OwningExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, +ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD, ParmVarDecl *Param) { if (Param->hasUnparsedDefaultArg()) { @@ -3324,7 +3420,7 @@ Sema::OwningExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, InstantiatingTemplate Inst(*this, CallLoc, Param, Innermost.first, Innermost.second); - OwningExprResult Result = SubstExpr(UninstExpr, ArgList); + ExprResult Result = SubstExpr(UninstExpr, ArgList); if (Result.isInvalid()) return ExprError(); @@ -3338,7 +3434,7 @@ Sema::OwningExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, InitializationSequence InitSeq(*this, Entity, Kind, &ResultE, 1); Result = InitSeq.Perform(*this, Entity, Kind, - MultiExprArg(*this, (void**)&ResultE, 1)); + MultiExprArg(*this, &ResultE, 1)); if (Result.isInvalid()) return ExprError(); @@ -3457,7 +3553,7 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, InitializedEntity Entity = Param? InitializedEntity::InitializeParameter(Param) : InitializedEntity::InitializeParameter(ProtoArgType); - OwningExprResult ArgE = PerformCopyInitialization(Entity, + ExprResult ArgE = PerformCopyInitialization(Entity, SourceLocation(), Owned(Arg)); if (ArgE.isInvalid()) @@ -3467,7 +3563,7 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, } else { ParmVarDecl *Param = FDecl->getParamDecl(i); - OwningExprResult ArgExpr = + ExprResult ArgExpr = BuildCXXDefaultArgExpr(CallLoc, FDecl, Param); if (ArgExpr.isInvalid()) return true; @@ -3492,18 +3588,18 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, /// 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. -Action::OwningExprResult -Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, +ExprResult +Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, MultiExprArg args, SourceLocation *CommaLocs, SourceLocation RParenLoc) { unsigned NumArgs = args.size(); // Since this might be a postfix expression, get rid of ParenListExprs. - fn = MaybeConvertParenListExprToParenExpr(S, move(fn)); + ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Fn); + if (Result.isInvalid()) return ExprError(); + Fn = Result.take(); - Expr *Fn = fn.takeAs(); - Expr **Args = reinterpret_cast(args.release()); - assert(Fn && "no function call expression"); + Expr **Args = args.release(); if (getLangOptions().CPlusPlus) { // If this is a pseudo-destructor expression, build the call immediately. @@ -3515,9 +3611,6 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, SourceRange(Args[0]->getLocStart(), Args[NumArgs-1]->getLocEnd())); - for (unsigned I = 0; I != NumArgs; ++I) - Args[I]->Destroy(Context); - NumArgs = 0; } @@ -3572,27 +3665,27 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, // Determine whether this is a call to a pointer-to-member function. if (BinaryOperator *BO = dyn_cast(NakedFn)) { - if (BO->getOpcode() == BinaryOperator::PtrMemD || - BO->getOpcode() == BinaryOperator::PtrMemI) { + if (BO->getOpcode() == BO_PtrMemD || + BO->getOpcode() == BO_PtrMemI) { if (const FunctionProtoType *FPT = BO->getType()->getAs()) { QualType ResultTy = FPT->getCallResultType(Context); - ExprOwningPtr - TheCall(this, new (Context) CXXMemberCallExpr(Context, BO, Args, - NumArgs, ResultTy, - RParenLoc)); + CXXMemberCallExpr *TheCall + = new (Context) CXXMemberCallExpr(Context, BO, Args, + NumArgs, ResultTy, + RParenLoc); if (CheckCallReturnType(FPT->getResultType(), BO->getRHS()->getSourceRange().getBegin(), - TheCall.get(), 0)) + TheCall, 0)) return ExprError(); - if (ConvertArgumentsForCall(&*TheCall, BO, 0, FPT, Args, NumArgs, + if (ConvertArgumentsForCall(TheCall, BO, 0, FPT, Args, NumArgs, RParenLoc)) return ExprError(); - return Owned(MaybeBindToTemporary(TheCall.release()).release()); + return MaybeBindToTemporary(TheCall); } return ExprError(Diag(Fn->getLocStart(), diag::err_typecheck_call_not_function) @@ -3625,7 +3718,7 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, /// block-pointer type. /// /// \param NDecl the declaration being called, if available -Sema::OwningExprResult +ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, SourceLocation LParenLoc, Expr **Args, unsigned NumArgs, @@ -3637,10 +3730,10 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, // Make the call expr early, before semantic checks. This guarantees cleanup // of arguments and function on error. - ExprOwningPtr TheCall(this, new (Context) CallExpr(Context, Fn, - Args, NumArgs, - Context.BoolTy, - RParenLoc)); + CallExpr *TheCall = new (Context) CallExpr(Context, Fn, + Args, NumArgs, + Context.BoolTy, + RParenLoc); const FunctionType *FuncT; if (!Fn->getType()->isBlockPointerType()) { @@ -3661,7 +3754,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, // Check for a valid return type if (CheckCallReturnType(FuncT->getResultType(), - Fn->getSourceRange().getBegin(), TheCall.get(), + Fn->getSourceRange().getBegin(), TheCall, FDecl)) return ExprError(); @@ -3669,7 +3762,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, TheCall->setType(FuncT->getCallResultType(Context)); if (const FunctionProtoType *Proto = dyn_cast(FuncT)) { - if (ConvertArgumentsForCall(&*TheCall, Fn, FDecl, Proto, Args, NumArgs, + if (ConvertArgumentsForCall(TheCall, Fn, FDecl, Proto, Args, NumArgs, RParenLoc)) return ExprError(); } else { @@ -3713,22 +3806,22 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, // Do special checking on direct calls to functions. if (FDecl) { - if (CheckFunctionCall(FDecl, TheCall.get())) + if (CheckFunctionCall(FDecl, TheCall)) return ExprError(); if (unsigned BuiltinID = FDecl->getBuiltinID()) - return CheckBuiltinFunctionCall(BuiltinID, TheCall.take()); + return CheckBuiltinFunctionCall(BuiltinID, TheCall); } else if (NDecl) { - if (CheckBlockCall(NDecl, TheCall.get())) + if (CheckBlockCall(NDecl, TheCall)) return ExprError(); } - return MaybeBindToTemporary(TheCall.take()); + return MaybeBindToTemporary(TheCall); } -Action::OwningExprResult -Sema::ActOnCompoundLiteral(SourceLocation LParenLoc, TypeTy *Ty, - SourceLocation RParenLoc, ExprArg InitExpr) { +ExprResult +Sema::ActOnCompoundLiteral(SourceLocation LParenLoc, ParsedType Ty, + SourceLocation RParenLoc, Expr *InitExpr) { assert((Ty != 0) && "ActOnCompoundLiteral(): missing type"); // FIXME: put back this assert when initializers are worked out. //assert((InitExpr != 0) && "ActOnCompoundLiteral(): missing expression"); @@ -3738,14 +3831,13 @@ Sema::ActOnCompoundLiteral(SourceLocation LParenLoc, TypeTy *Ty, if (!TInfo) TInfo = Context.getTrivialTypeSourceInfo(literalType); - return BuildCompoundLiteralExpr(LParenLoc, TInfo, RParenLoc, move(InitExpr)); + return BuildCompoundLiteralExpr(LParenLoc, TInfo, RParenLoc, InitExpr); } -Action::OwningExprResult +ExprResult Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo, - SourceLocation RParenLoc, ExprArg InitExpr) { + SourceLocation RParenLoc, Expr *literalExpr) { QualType literalType = TInfo->getType(); - Expr *literalExpr = static_cast(InitExpr.get()); if (literalType->isArrayType()) { if (literalType->isVariableArrayType()) @@ -3764,13 +3856,12 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo, = InitializationKind::CreateCast(SourceRange(LParenLoc, RParenLoc), /*IsCStyleCast=*/true); InitializationSequence InitSeq(*this, Entity, Kind, &literalExpr, 1); - OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind, - MultiExprArg(*this, (void**)&literalExpr, 1), + ExprResult Result = InitSeq.Perform(*this, Entity, Kind, + MultiExprArg(*this, &literalExpr, 1), &literalType); if (Result.isInvalid()) return ExprError(); - InitExpr.release(); - literalExpr = static_cast(Result.get()); + literalExpr = Result.get(); bool isFileScope = getCurFunctionOrMethodDecl() == 0; if (isFileScope) { // 6.5.2.5p3 @@ -3778,17 +3869,15 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo, return ExprError(); } - Result.release(); - return Owned(new (Context) CompoundLiteralExpr(LParenLoc, TInfo, literalType, literalExpr, isFileScope)); } -Action::OwningExprResult +ExprResult Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg initlist, SourceLocation RBraceLoc) { unsigned NumInit = initlist.size(); - Expr **InitList = reinterpret_cast(initlist.release()); + Expr **InitList = initlist.release(); // Semantic analysis for initializers is done by ActOnDeclarator() and // CheckInitializer() - it requires knowledge of the object being intialized. @@ -3799,45 +3888,45 @@ Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg initlist, return Owned(E); } -static CastExpr::CastKind getScalarCastKind(ASTContext &Context, +static CastKind getScalarCastKind(ASTContext &Context, QualType SrcTy, QualType DestTy) { if (Context.hasSameUnqualifiedType(SrcTy, DestTy)) - return CastExpr::CK_NoOp; + return CK_NoOp; if (SrcTy->hasPointerRepresentation()) { if (DestTy->hasPointerRepresentation()) return DestTy->isObjCObjectPointerType() ? - CastExpr::CK_AnyPointerToObjCPointerCast : - CastExpr::CK_BitCast; + CK_AnyPointerToObjCPointerCast : + CK_BitCast; if (DestTy->isIntegerType()) - return CastExpr::CK_PointerToIntegral; + return CK_PointerToIntegral; } if (SrcTy->isIntegerType()) { if (DestTy->isIntegerType()) - return CastExpr::CK_IntegralCast; + return CK_IntegralCast; if (DestTy->hasPointerRepresentation()) - return CastExpr::CK_IntegralToPointer; + return CK_IntegralToPointer; if (DestTy->isRealFloatingType()) - return CastExpr::CK_IntegralToFloating; + return CK_IntegralToFloating; } if (SrcTy->isRealFloatingType()) { if (DestTy->isRealFloatingType()) - return CastExpr::CK_FloatingCast; + return CK_FloatingCast; if (DestTy->isIntegerType()) - return CastExpr::CK_FloatingToIntegral; + return CK_FloatingToIntegral; } // FIXME: Assert here. // assert(false && "Unhandled cast combination!"); - return CastExpr::CK_Unknown; + return CK_Unknown; } /// CheckCastTypes - Check type constraints for casting between types. bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr, - CastExpr::CastKind& Kind, - CXXBaseSpecifierArray &BasePath, + CastKind& Kind, + CXXCastPath &BasePath, bool FunctionalStyle) { if (getLangOptions().CPlusPlus) return CXXCheckCStyleCast(TyR, castType, castExpr, Kind, BasePath, @@ -3849,10 +3938,14 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr, // type needs to be scalar. if (castType->isVoidType()) { // Cast to void allows any expr type. - Kind = CastExpr::CK_ToVoid; + Kind = CK_ToVoid; return false; } + if (RequireCompleteType(TyR.getBegin(), castType, + diag::err_typecheck_cast_to_incomplete)) + return true; + if (!castType->isScalarType() && !castType->isVectorType()) { if (Context.hasSameUnqualifiedType(castType, castExpr->getType()) && (castType->isStructureType() || castType->isUnionType())) { @@ -3860,7 +3953,7 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr, // FIXME: Check that the cast destination type is complete. Diag(TyR.getBegin(), diag::ext_typecheck_cast_nonscalar) << castType << castExpr->getSourceRange(); - Kind = CastExpr::CK_NoOp; + Kind = CK_NoOp; return false; } @@ -3880,7 +3973,7 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr, if (Field == FieldEnd) return Diag(TyR.getBegin(), diag::err_typecheck_cast_to_union_no_type) << castExpr->getType() << castExpr->getSourceRange(); - Kind = CastExpr::CK_ToUnion; + Kind = CK_ToUnion; return false; } @@ -3922,11 +4015,15 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr, } Kind = getScalarCastKind(Context, castExpr->getType(), castType); + + if (Kind == CK_Unknown || Kind == CK_BitCast) + CheckCastAlign(castExpr, castType, TyR); + return false; } bool Sema::CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty, - CastExpr::CastKind &Kind) { + CastKind &Kind) { assert(VectorTy->isVectorType() && "Not a vector type!"); if (Ty->isVectorType() || Ty->isIntegerType()) { @@ -3941,12 +4038,12 @@ bool Sema::CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty, diag::err_invalid_conversion_between_vector_and_scalar) << VectorTy << Ty << R; - Kind = CastExpr::CK_BitCast; + Kind = CK_BitCast; return false; } bool Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, Expr *&CastExpr, - CastExpr::CastKind &Kind) { + CastKind &Kind) { assert(DestTy->isExtVectorType() && "Not an extended vector type!"); QualType SrcTy = CastExpr->getType(); @@ -3957,7 +4054,7 @@ bool Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, Expr *&CastExpr, if (Context.getTypeSize(DestTy) != Context.getTypeSize(SrcTy)) return Diag(R.getBegin(),diag::err_invalid_conversion_between_ext_vectors) << DestTy << SrcTy << R; - Kind = CastExpr::CK_BitCast; + Kind = CK_BitCast; return false; } @@ -3973,14 +4070,14 @@ bool Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, Expr *&CastExpr, ImpCastExprToType(CastExpr, DestElemTy, getScalarCastKind(Context, SrcTy, DestElemTy)); - Kind = CastExpr::CK_VectorSplat; + Kind = CK_VectorSplat; return false; } -Action::OwningExprResult -Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc, TypeTy *Ty, - SourceLocation RParenLoc, ExprArg Op) { - assert((Ty != 0) && (Op.get() != 0) && +ExprResult +Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc, ParsedType Ty, + SourceLocation RParenLoc, Expr *castExpr) { + assert((Ty != 0) && (castExpr != 0) && "ActOnCastExpr(): missing type or expr"); TypeSourceInfo *castTInfo; @@ -3989,55 +4086,52 @@ Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc, TypeTy *Ty, castTInfo = Context.getTrivialTypeSourceInfo(castType); // If the Expr being casted is a ParenListExpr, handle it specially. - Expr *castExpr = (Expr *)Op.get(); if (isa(castExpr)) - return ActOnCastOfParenListExpr(S, LParenLoc, RParenLoc, move(Op), + return ActOnCastOfParenListExpr(S, LParenLoc, RParenLoc, castExpr, castTInfo); - return BuildCStyleCastExpr(LParenLoc, castTInfo, RParenLoc, move(Op)); + return BuildCStyleCastExpr(LParenLoc, castTInfo, RParenLoc, castExpr); } -Action::OwningExprResult +ExprResult Sema::BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty, - SourceLocation RParenLoc, ExprArg Op) { - Expr *castExpr = static_cast(Op.get()); - - CastExpr::CastKind Kind = CastExpr::CK_Unknown; - CXXBaseSpecifierArray BasePath; + SourceLocation RParenLoc, Expr *castExpr) { + CastKind Kind = CK_Unknown; + CXXCastPath BasePath; if (CheckCastTypes(SourceRange(LParenLoc, RParenLoc), Ty->getType(), castExpr, Kind, BasePath)) return ExprError(); - Op.release(); - return Owned(new (Context) CStyleCastExpr( + return Owned(CStyleCastExpr::Create(Context, Ty->getType().getNonLValueExprType(Context), - Kind, castExpr, BasePath, Ty, - LParenLoc, RParenLoc)); + Kind, castExpr, &BasePath, Ty, + LParenLoc, RParenLoc)); } /// This is not an AltiVec-style cast, so turn the ParenListExpr into a sequence /// of comma binary operators. -Action::OwningExprResult -Sema::MaybeConvertParenListExprToParenExpr(Scope *S, ExprArg EA) { - Expr *expr = EA.takeAs(); +ExprResult +Sema::MaybeConvertParenListExprToParenExpr(Scope *S, Expr *expr) { ParenListExpr *E = dyn_cast(expr); if (!E) return Owned(expr); - OwningExprResult Result(*this, E->getExpr(0)); + ExprResult Result(E->getExpr(0)); for (unsigned i = 1, e = E->getNumExprs(); i != e && !Result.isInvalid(); ++i) - Result = ActOnBinOp(S, E->getExprLoc(), tok::comma, move(Result), - Owned(E->getExpr(i))); + Result = ActOnBinOp(S, E->getExprLoc(), tok::comma, Result.get(), + E->getExpr(i)); - return ActOnParenExpr(E->getLParenLoc(), E->getRParenLoc(), move(Result)); + if (Result.isInvalid()) return ExprError(); + + return ActOnParenExpr(E->getLParenLoc(), E->getRParenLoc(), Result.get()); } -Action::OwningExprResult +ExprResult Sema::ActOnCastOfParenListExpr(Scope *S, SourceLocation LParenLoc, - SourceLocation RParenLoc, ExprArg Op, + SourceLocation RParenLoc, Expr *Op, TypeSourceInfo *TInfo) { - ParenListExpr *PE = (ParenListExpr *)Op.get(); + ParenListExpr *PE = cast(Op); QualType Ty = TInfo->getType(); bool isAltiVecLiteral = false; @@ -4065,24 +4159,24 @@ Sema::ActOnCastOfParenListExpr(Scope *S, SourceLocation LParenLoc, // FIXME: This means that pretty-printing the final AST will produce curly // braces instead of the original commas. - Op.release(); InitListExpr *E = new (Context) InitListExpr(Context, LParenLoc, &initExprs[0], initExprs.size(), RParenLoc); E->setType(Ty); - return BuildCompoundLiteralExpr(LParenLoc, TInfo, RParenLoc, Owned(E)); + return BuildCompoundLiteralExpr(LParenLoc, TInfo, RParenLoc, E); } else { // This is not an AltiVec-style cast, so turn the ParenListExpr into a // sequence of BinOp comma operators. - Op = MaybeConvertParenListExprToParenExpr(S, move(Op)); - return BuildCStyleCastExpr(LParenLoc, TInfo, RParenLoc, move(Op)); + ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Op); + if (Result.isInvalid()) return ExprError(); + return BuildCStyleCastExpr(LParenLoc, TInfo, RParenLoc, Result.take()); } } -Action::OwningExprResult Sema::ActOnParenOrParenListExpr(SourceLocation L, +ExprResult Sema::ActOnParenOrParenListExpr(SourceLocation L, SourceLocation R, MultiExprArg Val, - TypeTy *TypeOfCast) { + ParsedType TypeOfCast) { unsigned nexprs = Val.size(); Expr **exprs = reinterpret_cast(Val.release()); assert((exprs != 0) && "ActOnParenOrParenListExpr() missing expr list"); @@ -4148,8 +4242,8 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, if (!RHSTy->isVoidType()) Diag(LHS->getLocStart(), diag::ext_typecheck_cond_one_void) << LHS->getSourceRange(); - ImpCastExprToType(LHS, Context.VoidTy, CastExpr::CK_ToVoid); - ImpCastExprToType(RHS, Context.VoidTy, CastExpr::CK_ToVoid); + ImpCastExprToType(LHS, Context.VoidTy, CK_ToVoid); + ImpCastExprToType(RHS, Context.VoidTy, CK_ToVoid); return Context.VoidTy; } // C99 6.5.15p6 - "if one operand is a null pointer constant, the result has @@ -4157,12 +4251,12 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, if ((LHSTy->isAnyPointerType() || LHSTy->isBlockPointerType()) && RHS->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { // promote the null to a pointer. - ImpCastExprToType(RHS, LHSTy, CastExpr::CK_Unknown); + ImpCastExprToType(RHS, LHSTy, CK_Unknown); return LHSTy; } if ((RHSTy->isAnyPointerType() || RHSTy->isBlockPointerType()) && LHS->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { - ImpCastExprToType(LHS, RHSTy, CastExpr::CK_Unknown); + ImpCastExprToType(LHS, RHSTy, CK_Unknown); return RHSTy; } @@ -4178,8 +4272,8 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, if (!LHSTy->isBlockPointerType() || !RHSTy->isBlockPointerType()) { if (LHSTy->isVoidPointerType() || RHSTy->isVoidPointerType()) { QualType destType = Context.getPointerType(Context.VoidTy); - ImpCastExprToType(LHS, destType, CastExpr::CK_BitCast); - ImpCastExprToType(RHS, destType, CastExpr::CK_BitCast); + ImpCastExprToType(LHS, destType, CK_BitCast); + ImpCastExprToType(RHS, destType, CK_BitCast); return destType; } Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands) @@ -4203,13 +4297,13 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, // reason, but this is what gcc does, and we do have to pick // to get a consistent AST. QualType incompatTy = Context.getPointerType(Context.VoidTy); - ImpCastExprToType(LHS, incompatTy, CastExpr::CK_BitCast); - ImpCastExprToType(RHS, incompatTy, CastExpr::CK_BitCast); + ImpCastExprToType(LHS, incompatTy, CK_BitCast); + ImpCastExprToType(RHS, incompatTy, CK_BitCast); return incompatTy; } // The block pointer types are compatible. - ImpCastExprToType(LHS, LHSTy, CastExpr::CK_BitCast); - ImpCastExprToType(RHS, LHSTy, CastExpr::CK_BitCast); + ImpCastExprToType(LHS, LHSTy, CK_BitCast); + ImpCastExprToType(RHS, LHSTy, CK_BitCast); return LHSTy; } @@ -4226,9 +4320,9 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, = Context.getQualifiedType(lhptee, rhptee.getQualifiers()); QualType destType = Context.getPointerType(destPointee); // Add qualifiers if necessary. - ImpCastExprToType(LHS, destType, CastExpr::CK_NoOp); + ImpCastExprToType(LHS, destType, CK_NoOp); // Promote to void*. - ImpCastExprToType(RHS, destType, CastExpr::CK_BitCast); + ImpCastExprToType(RHS, destType, CK_BitCast); return destType; } if (rhptee->isVoidType() && lhptee->isIncompleteOrObjectType()) { @@ -4236,9 +4330,9 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, = Context.getQualifiedType(rhptee, lhptee.getQualifiers()); QualType destType = Context.getPointerType(destPointee); // Add qualifiers if necessary. - ImpCastExprToType(RHS, destType, CastExpr::CK_NoOp); + ImpCastExprToType(RHS, destType, CK_NoOp); // Promote to void*. - ImpCastExprToType(LHS, destType, CastExpr::CK_BitCast); + ImpCastExprToType(LHS, destType, CK_BitCast); return destType; } @@ -4254,8 +4348,8 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, // reason, but this is what gcc does, and we do have to pick // to get a consistent AST. QualType incompatTy = Context.getPointerType(Context.VoidTy); - ImpCastExprToType(LHS, incompatTy, CastExpr::CK_BitCast); - ImpCastExprToType(RHS, incompatTy, CastExpr::CK_BitCast); + ImpCastExprToType(LHS, incompatTy, CK_BitCast); + ImpCastExprToType(RHS, incompatTy, CK_BitCast); return incompatTy; } // The pointer types are compatible. @@ -4265,8 +4359,8 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, // type. // FIXME: Need to calculate the composite type. // FIXME: Need to add qualifiers - ImpCastExprToType(LHS, LHSTy, CastExpr::CK_BitCast); - ImpCastExprToType(RHS, LHSTy, CastExpr::CK_BitCast); + ImpCastExprToType(LHS, LHSTy, CK_BitCast); + ImpCastExprToType(RHS, LHSTy, CK_BitCast); return LHSTy; } @@ -4274,13 +4368,13 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, if (RHSTy->isPointerType() && LHSTy->isIntegerType()) { Diag(QuestionLoc, diag::warn_typecheck_cond_pointer_integer_mismatch) << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange(); - ImpCastExprToType(LHS, RHSTy, CastExpr::CK_IntegralToPointer); + ImpCastExprToType(LHS, RHSTy, CK_IntegralToPointer); return RHSTy; } if (LHSTy->isPointerType() && RHSTy->isIntegerType()) { Diag(QuestionLoc, diag::warn_typecheck_cond_pointer_integer_mismatch) << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange(); - ImpCastExprToType(RHS, LHSTy, CastExpr::CK_IntegralToPointer); + ImpCastExprToType(RHS, LHSTy, CK_IntegralToPointer); return LHSTy; } @@ -4302,34 +4396,34 @@ QualType Sema::FindCompositeObjCPointerType(Expr *&LHS, Expr *&RHS, // redefinition type if an attempt is made to access its fields. if (LHSTy->isObjCClassType() && (RHSTy.getDesugaredType() == Context.ObjCClassRedefinitionType)) { - ImpCastExprToType(RHS, LHSTy, CastExpr::CK_BitCast); + ImpCastExprToType(RHS, LHSTy, CK_BitCast); return LHSTy; } if (RHSTy->isObjCClassType() && (LHSTy.getDesugaredType() == Context.ObjCClassRedefinitionType)) { - ImpCastExprToType(LHS, RHSTy, CastExpr::CK_BitCast); + ImpCastExprToType(LHS, RHSTy, CK_BitCast); return RHSTy; } // And the same for struct objc_object* / id if (LHSTy->isObjCIdType() && (RHSTy.getDesugaredType() == Context.ObjCIdRedefinitionType)) { - ImpCastExprToType(RHS, LHSTy, CastExpr::CK_BitCast); + ImpCastExprToType(RHS, LHSTy, CK_BitCast); return LHSTy; } if (RHSTy->isObjCIdType() && (LHSTy.getDesugaredType() == Context.ObjCIdRedefinitionType)) { - ImpCastExprToType(LHS, RHSTy, CastExpr::CK_BitCast); + ImpCastExprToType(LHS, RHSTy, CK_BitCast); return RHSTy; } // And the same for struct objc_selector* / SEL if (Context.isObjCSelType(LHSTy) && (RHSTy.getDesugaredType() == Context.ObjCSelRedefinitionType)) { - ImpCastExprToType(RHS, LHSTy, CastExpr::CK_BitCast); + ImpCastExprToType(RHS, LHSTy, CK_BitCast); return LHSTy; } if (Context.isObjCSelType(RHSTy) && (LHSTy.getDesugaredType() == Context.ObjCSelRedefinitionType)) { - ImpCastExprToType(LHS, RHSTy, CastExpr::CK_BitCast); + ImpCastExprToType(LHS, RHSTy, CK_BitCast); return RHSTy; } // Check constraints for Objective-C object pointers types. @@ -4378,13 +4472,13 @@ QualType Sema::FindCompositeObjCPointerType(Expr *&LHS, Expr *&RHS, << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange(); QualType incompatTy = Context.getObjCIdType(); - ImpCastExprToType(LHS, incompatTy, CastExpr::CK_BitCast); - ImpCastExprToType(RHS, incompatTy, CastExpr::CK_BitCast); + ImpCastExprToType(LHS, incompatTy, CK_BitCast); + ImpCastExprToType(RHS, incompatTy, CK_BitCast); return incompatTy; } // The object pointer types are compatible. - ImpCastExprToType(LHS, compositeType, CastExpr::CK_BitCast); - ImpCastExprToType(RHS, compositeType, CastExpr::CK_BitCast); + ImpCastExprToType(LHS, compositeType, CK_BitCast); + ImpCastExprToType(RHS, compositeType, CK_BitCast); return compositeType; } // Check Objective-C object pointer types and 'void *' @@ -4395,9 +4489,9 @@ QualType Sema::FindCompositeObjCPointerType(Expr *&LHS, Expr *&RHS, = Context.getQualifiedType(lhptee, rhptee.getQualifiers()); QualType destType = Context.getPointerType(destPointee); // Add qualifiers if necessary. - ImpCastExprToType(LHS, destType, CastExpr::CK_NoOp); + ImpCastExprToType(LHS, destType, CK_NoOp); // Promote to void*. - ImpCastExprToType(RHS, destType, CastExpr::CK_BitCast); + ImpCastExprToType(RHS, destType, CK_BitCast); return destType; } if (LHSTy->isObjCObjectPointerType() && RHSTy->isVoidPointerType()) { @@ -4407,9 +4501,9 @@ QualType Sema::FindCompositeObjCPointerType(Expr *&LHS, Expr *&RHS, = Context.getQualifiedType(rhptee, lhptee.getQualifiers()); QualType destType = Context.getPointerType(destPointee); // Add qualifiers if necessary. - ImpCastExprToType(RHS, destType, CastExpr::CK_NoOp); + ImpCastExprToType(RHS, destType, CK_NoOp); // Promote to void*. - ImpCastExprToType(LHS, destType, CastExpr::CK_BitCast); + ImpCastExprToType(LHS, destType, CK_BitCast); return destType; } return QualType(); @@ -4417,30 +4511,27 @@ QualType Sema::FindCompositeObjCPointerType(Expr *&LHS, Expr *&RHS, /// ActOnConditionalOp - Parse a ?: operation. Note that 'LHS' may be null /// in the case of a the GNU conditional expr extension. -Action::OwningExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc, +ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc, SourceLocation ColonLoc, - ExprArg Cond, ExprArg LHS, - ExprArg RHS) { - Expr *CondExpr = (Expr *) Cond.get(); - Expr *LHSExpr = (Expr *) LHS.get(), *RHSExpr = (Expr *) RHS.get(); - + Expr *CondExpr, Expr *LHSExpr, + Expr *RHSExpr) { // If this is the gnu "x ?: y" extension, analyze the types as though the LHS // was the condition. bool isLHSNull = LHSExpr == 0; - if (isLHSNull) - LHSExpr = CondExpr; + Expr *SAVEExpr = 0; + if (isLHSNull) { + LHSExpr = SAVEExpr = CondExpr; + } QualType result = CheckConditionalOperands(CondExpr, LHSExpr, RHSExpr, QuestionLoc); if (result.isNull()) return ExprError(); - Cond.release(); - LHS.release(); - RHS.release(); return Owned(new (Context) ConditionalOperator(CondExpr, QuestionLoc, - isLHSNull ? 0 : LHSExpr, - ColonLoc, RHSExpr, result)); + LHSExpr, ColonLoc, + RHSExpr, SAVEExpr, + result)); } // CheckPointerTypesForAssignment - This is a very tricky routine (despite @@ -4506,12 +4597,12 @@ Sema::CheckPointerTypesForAssignment(QualType lhsType, QualType rhsType) { // "unsigned char" on systems where "char" is unsigned. if (lhptee->isCharType()) lhptee = Context.UnsignedCharTy; - else if (lhptee->isSignedIntegerType()) + else if (lhptee->hasSignedIntegerRepresentation()) lhptee = Context.getCorrespondingUnsignedType(lhptee); if (rhptee->isCharType()) rhptee = Context.UnsignedCharTy; - else if (rhptee->isSignedIntegerType()) + else if (rhptee->hasSignedIntegerRepresentation()) rhptee = Context.getCorrespondingUnsignedType(rhptee); if (lhptee == rhptee) { @@ -4668,13 +4759,18 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) { } if (lhsType->isVectorType() || rhsType->isVectorType()) { - // If we are allowing lax vector conversions, and LHS and RHS are both - // vectors, the total size only needs to be the same. This is a bitcast; - // no bits are changed but the result type is different. - if (getLangOptions().LaxVectorConversions && - lhsType->isVectorType() && rhsType->isVectorType()) { - if (Context.getTypeSize(lhsType) == Context.getTypeSize(rhsType)) + if (lhsType->isVectorType() && rhsType->isVectorType()) { + // If we are allowing lax vector conversions, and LHS and RHS are both + // vectors, the total size only needs to be the same. This is a bitcast; + // no bits are changed but the result type is different. + if (getLangOptions().LaxVectorConversions && + (Context.getTypeSize(lhsType) == Context.getTypeSize(rhsType))) return IncompatibleVectors; + + // Allow assignments of an AltiVec vector type to an equivalent GCC + // vector type and vice versa + if (Context.areCompatibleVectorTypes(lhsType, rhsType)) + return Compatible; } return Incompatible; } @@ -4832,14 +4928,14 @@ Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType, Expr *&rExpr) { // 2) null pointer constant if (FromType->isPointerType()) if (FromType->getAs()->getPointeeType()->isVoidType()) { - ImpCastExprToType(rExpr, it->getType(), CastExpr::CK_BitCast); + ImpCastExprToType(rExpr, it->getType(), CK_BitCast); InitField = *it; break; } if (rExpr->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { - ImpCastExprToType(rExpr, it->getType(), CastExpr::CK_IntegralToPointer); + ImpCastExprToType(rExpr, it->getType(), CK_IntegralToPointer); InitField = *it; break; } @@ -4883,14 +4979,14 @@ Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) { lhsType->isBlockPointerType()) && rExpr->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { - ImpCastExprToType(rExpr, lhsType, CastExpr::CK_Unknown); + ImpCastExprToType(rExpr, lhsType, CK_Unknown); return Compatible; } // This check seems unnatural, however it is necessary to ensure the proper // conversion of functions/arrays. If the conversion were done for all // DeclExpr's (created by ActOnIdExpression), it would mess up the unary - // expressions that surpress this implicit conversion (&, sizeof). + // expressions that suppress this implicit conversion (&, sizeof). // // Suppress this for references: C++ 8.5.3p5. if (!lhsType->isReferenceType()) @@ -4907,7 +5003,7 @@ Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) { // does not have reference type. if (result != Incompatible && rExpr->getType() != lhsType) ImpCastExprToType(rExpr, lhsType.getNonLValueExprType(Context), - CastExpr::CK_Unknown); + CK_Unknown); return result; } @@ -4933,22 +5029,35 @@ QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex, Expr *&rex) { // Handle the case of a vector & extvector type of the same size and element // type. It would be nice if we only had one vector type someday. if (getLangOptions().LaxVectorConversions) { - // FIXME: Should we warn here? if (const VectorType *LV = lhsType->getAs()) { - if (const VectorType *RV = rhsType->getAs()) + if (const VectorType *RV = rhsType->getAs()) { if (LV->getElementType() == RV->getElementType() && LV->getNumElements() == RV->getNumElements()) { if (lhsType->isExtVectorType()) { - ImpCastExprToType(rex, lhsType, CastExpr::CK_BitCast); + ImpCastExprToType(rex, lhsType, CK_BitCast); return lhsType; } - ImpCastExprToType(lex, rhsType, CastExpr::CK_BitCast); + ImpCastExprToType(lex, rhsType, CK_BitCast); return rhsType; + } else if (Context.getTypeSize(lhsType) ==Context.getTypeSize(rhsType)){ + // If we are allowing lax vector conversions, and LHS and RHS are both + // vectors, the total size only needs to be the same. This is a + // bitcast; no bits are changed but the result type is different. + ImpCastExprToType(rex, lhsType, CK_BitCast); + return lhsType; } + } } } + // Handle the case of equivalent AltiVec and GCC vector types + if (lhsType->isVectorType() && rhsType->isVectorType() && + Context.areCompatibleVectorTypes(lhsType, rhsType)) { + ImpCastExprToType(lex, rhsType, CK_BitCast); + return rhsType; + } + // Canonicalize the ExtVector to the LHS, remember if we swapped so we can // swap back (so that we don't reverse the inputs to a subtract, for instance. bool swapped = false; @@ -4963,7 +5072,7 @@ QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex, Expr *&rex) { QualType EltTy = LV->getElementType(); if (EltTy->isIntegralType(Context) && rhsType->isIntegralType(Context)) { if (Context.getIntegerTypeOrder(EltTy, rhsType) >= 0) { - ImpCastExprToType(rex, lhsType, CastExpr::CK_IntegralCast); + ImpCastExprToType(rex, lhsType, CK_IntegralCast); if (swapped) std::swap(rex, lex); return lhsType; } @@ -4971,7 +5080,7 @@ QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex, Expr *&rex) { if (EltTy->isRealFloatingType() && rhsType->isScalarType() && rhsType->isRealFloatingType()) { if (Context.getFloatingTypeOrder(EltTy, rhsType) >= 0) { - ImpCastExprToType(rex, lhsType, CastExpr::CK_FloatingCast); + ImpCastExprToType(rex, lhsType, CK_FloatingCast); if (swapped) std::swap(rex, lex); return lhsType; } @@ -5008,7 +5117,8 @@ QualType Sema::CheckMultiplyDivideOperands( QualType Sema::CheckRemainderOperands( Expr *&lex, Expr *&rex, SourceLocation Loc, bool isCompAssign) { if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) { - if (lex->getType()->isIntegerType() && rex->getType()->isIntegerType()) + if (lex->getType()->hasIntegerRepresentation() && + rex->getType()->hasIntegerRepresentation()) return CheckVectorOperands(Loc, lex, rex); return InvalidOperands(Loc, lex, rex); } @@ -5253,7 +5363,8 @@ QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex, QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, bool isCompAssign) { // C99 6.5.7p2: Each of the operands shall have integer type. - if (!lex->getType()->isIntegerType() || !rex->getType()->isIntegerType()) + if (!lex->getType()->hasIntegerRepresentation() || + !rex->getType()->hasIntegerRepresentation()) return InvalidOperands(Loc, lex, rex); // Vector shifts promote their scalar inputs to vector type. @@ -5269,7 +5380,7 @@ QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, LHSTy = Context.getPromotedIntegerType(LHSTy); } if (!isCompAssign) - ImpCastExprToType(lex, LHSTy, CastExpr::CK_IntegralCast); + ImpCastExprToType(lex, LHSTy, CK_IntegralCast); UsualUnaryConversions(rex); @@ -5305,7 +5416,7 @@ static bool IsWithinTemplateSpecialization(Decl *D) { // C99 6.5.8, C++ [expr.rel] QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, unsigned OpaqueOpc, bool isRelational) { - BinaryOperator::Opcode Opc = (BinaryOperator::Opcode)OpaqueOpc; + BinaryOperatorKind Opc = (BinaryOperatorKind) OpaqueOpc; // Handle vector comparisons separately. if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) @@ -5334,19 +5445,19 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, !IsWithinTemplateSpecialization(DRL->getDecl())) { DiagRuntimeBehavior(Loc, PDiag(diag::warn_comparison_always) << 0 // self- - << (Opc == BinaryOperator::EQ - || Opc == BinaryOperator::LE - || Opc == BinaryOperator::GE)); + << (Opc == BO_EQ + || Opc == BO_LE + || Opc == BO_GE)); } else if (lType->isArrayType() && rType->isArrayType() && !DRL->getDecl()->getType()->isReferenceType() && !DRR->getDecl()->getType()->isReferenceType()) { // what is it always going to eval to? char always_evals_to; switch(Opc) { - case BinaryOperator::EQ: // e.g. array1 == array2 + case BO_EQ: // e.g. array1 == array2 always_evals_to = 0; // false break; - case BinaryOperator::NE: // e.g. array1 != array2 + case BO_NE: // e.g. array1 != array2 always_evals_to = 1; // true break; default: @@ -5386,12 +5497,12 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, if (literalString) { std::string resultComparison; switch (Opc) { - case BinaryOperator::LT: resultComparison = ") < 0"; break; - case BinaryOperator::GT: resultComparison = ") > 0"; break; - case BinaryOperator::LE: resultComparison = ") <= 0"; break; - case BinaryOperator::GE: resultComparison = ") >= 0"; break; - case BinaryOperator::EQ: resultComparison = ") == 0"; break; - case BinaryOperator::NE: resultComparison = ") != 0"; break; + case BO_LT: resultComparison = ") < 0"; break; + case BO_GT: resultComparison = ") > 0"; break; + case BO_LE: resultComparison = ") <= 0"; break; + case BO_GE: resultComparison = ") >= 0"; break; + case BO_EQ: resultComparison = ") == 0"; break; + case BO_NE: resultComparison = ") != 0"; break; default: assert(false && "Invalid comparison operator"); } @@ -5461,7 +5572,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, if (isSFINAEContext()) return QualType(); - ImpCastExprToType(rex, lType, CastExpr::CK_BitCast); + ImpCastExprToType(rex, lType, CK_BitCast); return ResultTy; } } @@ -5487,8 +5598,8 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, << lex->getSourceRange() << rex->getSourceRange(); } - ImpCastExprToType(lex, T, CastExpr::CK_BitCast); - ImpCastExprToType(rex, T, CastExpr::CK_BitCast); + ImpCastExprToType(lex, T, CK_BitCast); + ImpCastExprToType(rex, T, CK_BitCast); return ResultTy; } // C99 6.5.9p2 and C99 6.5.8p2 @@ -5513,7 +5624,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, << lType << rType << lex->getSourceRange() << rex->getSourceRange(); } if (LCanPointeeTy != RCanPointeeTy) - ImpCastExprToType(rex, lType, CastExpr::CK_BitCast); + ImpCastExprToType(rex, lType, CK_BitCast); return ResultTy; } @@ -5523,13 +5634,19 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, if (RHSIsNull && (lType->isPointerType() || (!isRelational && lType->isMemberPointerType()))) { - ImpCastExprToType(rex, lType, CastExpr::CK_NullToMemberPointer); + ImpCastExprToType(rex, lType, + lType->isMemberPointerType() + ? CK_NullToMemberPointer + : CK_IntegralToPointer); return ResultTy; } if (LHSIsNull && (rType->isPointerType() || (!isRelational && rType->isMemberPointerType()))) { - ImpCastExprToType(lex, rType, CastExpr::CK_NullToMemberPointer); + ImpCastExprToType(lex, rType, + rType->isMemberPointerType() + ? CK_NullToMemberPointer + : CK_IntegralToPointer); return ResultTy; } @@ -5560,8 +5677,8 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, << lex->getSourceRange() << rex->getSourceRange(); } - ImpCastExprToType(lex, T, CastExpr::CK_BitCast); - ImpCastExprToType(rex, T, CastExpr::CK_BitCast); + ImpCastExprToType(lex, T, CK_BitCast); + ImpCastExprToType(rex, T, CK_BitCast); return ResultTy; } @@ -5580,7 +5697,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, Diag(Loc, diag::err_typecheck_comparison_of_distinct_blocks) << lType << rType << lex->getSourceRange() << rex->getSourceRange(); } - ImpCastExprToType(rex, lType, CastExpr::CK_BitCast); + ImpCastExprToType(rex, lType, CK_BitCast); return ResultTy; } // Allow block pointers to be compared with null pointer constants. @@ -5595,7 +5712,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, Diag(Loc, diag::err_typecheck_comparison_of_distinct_blocks) << lType << rType << lex->getSourceRange() << rex->getSourceRange(); } - ImpCastExprToType(rex, lType, CastExpr::CK_BitCast); + ImpCastExprToType(rex, lType, CK_BitCast); return ResultTy; } @@ -5613,14 +5730,14 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers) << lType << rType << lex->getSourceRange() << rex->getSourceRange(); } - ImpCastExprToType(rex, lType, CastExpr::CK_BitCast); + ImpCastExprToType(rex, lType, CK_BitCast); return ResultTy; } if (lType->isObjCObjectPointerType() && rType->isObjCObjectPointerType()) { if (!Context.areComparableObjCPointerTypes(lType, rType)) Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers) << lType << rType << lex->getSourceRange() << rex->getSourceRange(); - ImpCastExprToType(rex, lType, CastExpr::CK_BitCast); + ImpCastExprToType(rex, lType, CK_BitCast); return ResultTy; } } @@ -5648,21 +5765,21 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, } if (lType->isIntegerType()) - ImpCastExprToType(lex, rType, CastExpr::CK_IntegralToPointer); + ImpCastExprToType(lex, rType, CK_IntegralToPointer); else - ImpCastExprToType(rex, lType, CastExpr::CK_IntegralToPointer); + ImpCastExprToType(rex, lType, CK_IntegralToPointer); return ResultTy; } // Handle block pointers. if (!isRelational && RHSIsNull && lType->isBlockPointerType() && rType->isIntegerType()) { - ImpCastExprToType(rex, lType, CastExpr::CK_IntegralToPointer); + ImpCastExprToType(rex, lType, CK_IntegralToPointer); return ResultTy; } if (!isRelational && LHSIsNull && lType->isIntegerType() && rType->isBlockPointerType()) { - ImpCastExprToType(lex, rType, CastExpr::CK_IntegralToPointer); + ImpCastExprToType(lex, rType, CK_IntegralToPointer); return ResultTy; } return InvalidOperands(Loc, lex, rex); @@ -5707,7 +5824,7 @@ QualType Sema::CheckVectorCompareOperands(Expr *&lex, Expr *&rex, // Return the type for the comparison, which is the same as vector type for // integer vectors, or an integer type of identical size and number of // elements for floating point vectors. - if (lType->isIntegerType()) + if (lType->hasIntegerRepresentation()) return lType; const VectorType *VTy = lType->getAs(); @@ -5724,8 +5841,13 @@ QualType Sema::CheckVectorCompareOperands(Expr *&lex, Expr *&rex, inline QualType Sema::CheckBitwiseOperands( Expr *&lex, Expr *&rex, SourceLocation Loc, bool isCompAssign) { - if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) - return CheckVectorOperands(Loc, lex, rex); + if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) { + if (lex->getType()->hasIntegerRepresentation() && + rex->getType()->hasIntegerRepresentation()) + return CheckVectorOperands(Loc, lex, rex); + + return InvalidOperands(Loc, lex, rex); + } QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign); @@ -5741,18 +5863,21 @@ inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14] // bitwise one. We do this when the LHS is a non-bool integer and the RHS // is a constant. if (lex->getType()->isIntegerType() && !lex->getType()->isBooleanType() && - rex->getType()->isIntegerType() && rex->isEvaluatable(Context) && - // Don't warn if the RHS is a (constant folded) boolean expression like - // "sizeof(int) == 4". - !rex->isKnownToHaveBooleanValue() && + rex->getType()->isIntegerType() && !rex->isValueDependent() && // Don't warn in macros. - !Loc.isMacroID()) - Diag(Loc, diag::warn_logical_instead_of_bitwise) - << rex->getSourceRange() - << (Opc == BinaryOperator::LAnd ? "&&" : "||") - << (Opc == BinaryOperator::LAnd ? "&" : "|"); - - + !Loc.isMacroID()) { + // If the RHS can be constant folded, and if it constant folds to something + // that isn't 0 or 1 (which indicate a potential logical operation that + // happened to fold to true/false) then warn. + Expr::EvalResult Result; + if (rex->Evaluate(Result, Context) && !Result.HasSideEffects && + Result.Val.getInt() != 0 && Result.Val.getInt() != 1) { + Diag(Loc, diag::warn_logical_instead_of_bitwise) + << rex->getSourceRange() + << (Opc == BO_LAnd ? "&&" : "||") + << (Opc == BO_LAnd ? "&" : "|"); + } + } if (!Context.getLangOptions().CPlusPlus) { UsualUnaryConversions(lex); @@ -5907,8 +6032,8 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS, if (ImplicitCastExpr *ICE = dyn_cast(RHSCheck)) RHSCheck = ICE->getSubExpr(); if (UnaryOperator *UO = dyn_cast(RHSCheck)) { - if ((UO->getOpcode() == UnaryOperator::Plus || - UO->getOpcode() == UnaryOperator::Minus) && + if ((UO->getOpcode() == UO_Plus || + UO->getOpcode() == UO_Minus) && Loc.isFileID() && UO->getOperatorLoc().isFileID() && // Only if the two operators are exactly adjacent. Loc.getFileLocWithOffset(1) == UO->getOperatorLoc() && @@ -5917,7 +6042,7 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS, Loc.getFileLocWithOffset(2) != UO->getSubExpr()->getLocStart() && UO->getSubExpr()->getLocStart().isFileID()) { Diag(Loc, diag::warn_not_compound_assign) - << (UO->getOpcode() == UnaryOperator::Plus ? "+" : "-") + << (UO->getOpcode() == UO_Plus ? "+" : "-") << SourceRange(UO->getOperatorLoc(), UO->getOperatorLoc()); } } @@ -5938,7 +6063,7 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS, // only handles the pattern "*null = whatever", which is a very syntactic // check. if (UnaryOperator *UO = dyn_cast(LHS->IgnoreParenCasts())) - if (UO->getOpcode() == UnaryOperator::Deref && + if (UO->getOpcode() == UO_Deref && UO->getSubExpr()->IgnoreParenCasts()-> isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull) && !UO->getType().isVolatileQualified()) { @@ -6083,9 +6208,9 @@ static NamedDecl *getPrimaryDecl(Expr *E) { UnaryOperator *UO = cast(E); switch(UO->getOpcode()) { - case UnaryOperator::Real: - case UnaryOperator::Imag: - case UnaryOperator::Extension: + case UO_Real: + case UO_Imag: + case UO_Extension: return getPrimaryDecl(UO->getSubExpr()); default: return 0; @@ -6109,17 +6234,19 @@ static NamedDecl *getPrimaryDecl(Expr *E) { /// operator (C99 6.3.2.1p[2-4]), and its result is never an lvalue. /// In C++, the operand might be an overloaded function name, in which case /// we allow the '&' but retain the overloaded-function type. -QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) { - // Make sure to ignore parentheses in subsequent checks - op = op->IgnoreParens(); - - if (op->isTypeDependent()) +QualType Sema::CheckAddressOfOperand(Expr *OrigOp, SourceLocation OpLoc) { + if (OrigOp->isTypeDependent()) return Context.DependentTy; + if (OrigOp->getType() == Context.OverloadTy) + return Context.OverloadTy; + + // Make sure to ignore parentheses in subsequent checks + Expr *op = OrigOp->IgnoreParens(); if (getLangOptions().C99) { // Implement C99-only parts of addressof rules. if (UnaryOperator* uOp = dyn_cast(op)) { - if (uOp->getOpcode() == UnaryOperator::Deref) + if (uOp->getOpcode() == UO_Deref) // Per C99 6.5.3.2, the address of a deref always returns a valid result // (assuming the deref expression is valid). return uOp->getSubExpr()->getType(); @@ -6130,32 +6257,41 @@ QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) { NamedDecl *dcl = getPrimaryDecl(op); Expr::isLvalueResult lval = op->isLvalue(Context); - MemberExpr *ME = dyn_cast(op); - if (lval == Expr::LV_MemberFunction && ME && - isa(ME->getMemberDecl())) { - ValueDecl *dcl = cast(op)->getMemberDecl(); - // &f where f is a member of the current object, or &o.f, or &p->f - // All these are not allowed, and we need to catch them before the dcl - // branch of the if, below. - Diag(OpLoc, diag::err_unqualified_pointer_member_function) - << dcl; - // FIXME: Improve this diagnostic and provide a fixit. - - // Now recover by acting as if the function had been accessed qualified. - return Context.getMemberPointerType(op->getType(), - Context.getTypeDeclType(cast(dcl->getDeclContext())) - .getTypePtr()); - } - if (lval == Expr::LV_ClassTemporary) { Diag(OpLoc, isSFINAEContext()? diag::err_typecheck_addrof_class_temporary : diag::ext_typecheck_addrof_class_temporary) << op->getType() << op->getSourceRange(); if (isSFINAEContext()) return QualType(); - } else if (isa(op)) + } else if (isa(op)) { return Context.getPointerType(op->getType()); - else if (lval != Expr::LV_Valid && lval != Expr::LV_IncompleteVoidType) { + } else if (lval == Expr::LV_MemberFunction) { + // If it's an instance method, make a member pointer. + // The expression must have exactly the form &A::foo. + + // If the underlying expression isn't a decl ref, give up. + if (!isa(op)) { + Diag(OpLoc, diag::err_invalid_form_pointer_member_function) + << OrigOp->getSourceRange(); + return QualType(); + } + DeclRefExpr *DRE = cast(op); + CXXMethodDecl *MD = cast(DRE->getDecl()); + + // The id-expression was parenthesized. + if (OrigOp != DRE) { + Diag(OpLoc, diag::err_parens_pointer_member_function) + << OrigOp->getSourceRange(); + + // The method was named without a qualifier. + } else if (!DRE->getQualifier()) { + Diag(OpLoc, diag::err_unqualified_pointer_member_function) + << op->getSourceRange(); + } + + return Context.getMemberPointerType(op->getType(), + Context.getTypeDeclType(MD->getParent()).getTypePtr()); + } else if (lval != Expr::LV_Valid && lval != Expr::LV_IncompleteVoidType) { // C99 6.5.3.2p1 // The operand must be either an l-value or a function designator if (!op->getType()->isFunctionType()) { @@ -6183,13 +6319,14 @@ QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) { // FIXME: Can LHS ever be null here? if (!CheckAddressOfOperand(CO->getTrueExpr(), OpLoc).isNull()) return CheckAddressOfOperand(CO->getFalseExpr(), OpLoc); - } else if (isa(op)) { - return Context.OverloadTy; } else if (dcl) { // C99 6.5.3.2p1 // We have an lvalue with a decl. Make sure the decl is not declared // with the register storage-class specifier. if (const VarDecl *vd = dyn_cast(dcl)) { - if (vd->getStorageClass() == VarDecl::Register) { + // in C++ it is not error to take address of a register + // variable (c++03 7.1.1P3) + if (vd->getStorageClass() == SC_Register && + !getLangOptions().CPlusPlus) { Diag(OpLoc, diag::err_typecheck_address_of) << "register variable" << op->getSourceRange(); return QualType(); @@ -6214,13 +6351,6 @@ QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) { Context.getTypeDeclType(cast(Ctx)).getTypePtr()); } } - } else if (CXXMethodDecl *MD = dyn_cast(dcl)) { - // Okay: we can take the address of a function. - // As above. - if (isa(op) && cast(op)->getQualifier() && - MD->isInstance()) - return Context.getMemberPointerType(op->getType(), - Context.getTypeDeclType(MD->getParent()).getTypePtr()); } else if (!isa(dcl)) assert(0 && "Unknown/unexpected decl type"); } @@ -6233,6 +6363,8 @@ QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) { } // If the operand has type "type", the result has type "pointer to type". + if (op->getType()->isObjCObjectType()) + return Context.getObjCObjectPointerType(op->getType()); return Context.getPointerType(op->getType()); } @@ -6264,63 +6396,63 @@ QualType Sema::CheckIndirectionOperand(Expr *Op, SourceLocation OpLoc) { return Result; } -static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode( +static inline BinaryOperatorKind ConvertTokenKindToBinaryOpcode( tok::TokenKind Kind) { - BinaryOperator::Opcode Opc; + BinaryOperatorKind Opc; switch (Kind) { default: assert(0 && "Unknown binop!"); - case tok::periodstar: Opc = BinaryOperator::PtrMemD; break; - case tok::arrowstar: Opc = BinaryOperator::PtrMemI; break; - case tok::star: Opc = BinaryOperator::Mul; break; - case tok::slash: Opc = BinaryOperator::Div; break; - case tok::percent: Opc = BinaryOperator::Rem; break; - case tok::plus: Opc = BinaryOperator::Add; break; - case tok::minus: Opc = BinaryOperator::Sub; break; - case tok::lessless: Opc = BinaryOperator::Shl; break; - case tok::greatergreater: Opc = BinaryOperator::Shr; break; - case tok::lessequal: Opc = BinaryOperator::LE; break; - case tok::less: Opc = BinaryOperator::LT; break; - case tok::greaterequal: Opc = BinaryOperator::GE; break; - case tok::greater: Opc = BinaryOperator::GT; break; - case tok::exclaimequal: Opc = BinaryOperator::NE; break; - case tok::equalequal: Opc = BinaryOperator::EQ; break; - case tok::amp: Opc = BinaryOperator::And; break; - case tok::caret: Opc = BinaryOperator::Xor; break; - case tok::pipe: Opc = BinaryOperator::Or; break; - case tok::ampamp: Opc = BinaryOperator::LAnd; break; - case tok::pipepipe: Opc = BinaryOperator::LOr; break; - case tok::equal: Opc = BinaryOperator::Assign; break; - case tok::starequal: Opc = BinaryOperator::MulAssign; break; - case tok::slashequal: Opc = BinaryOperator::DivAssign; break; - case tok::percentequal: Opc = BinaryOperator::RemAssign; break; - case tok::plusequal: Opc = BinaryOperator::AddAssign; break; - case tok::minusequal: Opc = BinaryOperator::SubAssign; break; - case tok::lesslessequal: Opc = BinaryOperator::ShlAssign; break; - case tok::greatergreaterequal: Opc = BinaryOperator::ShrAssign; break; - case tok::ampequal: Opc = BinaryOperator::AndAssign; break; - case tok::caretequal: Opc = BinaryOperator::XorAssign; break; - case tok::pipeequal: Opc = BinaryOperator::OrAssign; break; - case tok::comma: Opc = BinaryOperator::Comma; break; + case tok::periodstar: Opc = BO_PtrMemD; break; + case tok::arrowstar: Opc = BO_PtrMemI; break; + case tok::star: Opc = BO_Mul; break; + case tok::slash: Opc = BO_Div; break; + case tok::percent: Opc = BO_Rem; break; + case tok::plus: Opc = BO_Add; break; + case tok::minus: Opc = BO_Sub; break; + case tok::lessless: Opc = BO_Shl; break; + case tok::greatergreater: Opc = BO_Shr; break; + case tok::lessequal: Opc = BO_LE; break; + case tok::less: Opc = BO_LT; break; + case tok::greaterequal: Opc = BO_GE; break; + case tok::greater: Opc = BO_GT; break; + case tok::exclaimequal: Opc = BO_NE; break; + case tok::equalequal: Opc = BO_EQ; break; + case tok::amp: Opc = BO_And; break; + case tok::caret: Opc = BO_Xor; break; + case tok::pipe: Opc = BO_Or; break; + case tok::ampamp: Opc = BO_LAnd; break; + case tok::pipepipe: Opc = BO_LOr; break; + case tok::equal: Opc = BO_Assign; break; + case tok::starequal: Opc = BO_MulAssign; break; + case tok::slashequal: Opc = BO_DivAssign; break; + case tok::percentequal: Opc = BO_RemAssign; break; + case tok::plusequal: Opc = BO_AddAssign; break; + case tok::minusequal: Opc = BO_SubAssign; break; + case tok::lesslessequal: Opc = BO_ShlAssign; break; + case tok::greatergreaterequal: Opc = BO_ShrAssign; break; + case tok::ampequal: Opc = BO_AndAssign; break; + case tok::caretequal: Opc = BO_XorAssign; break; + case tok::pipeequal: Opc = BO_OrAssign; break; + case tok::comma: Opc = BO_Comma; break; } return Opc; } -static inline UnaryOperator::Opcode ConvertTokenKindToUnaryOpcode( +static inline UnaryOperatorKind ConvertTokenKindToUnaryOpcode( tok::TokenKind Kind) { - UnaryOperator::Opcode Opc; + UnaryOperatorKind Opc; switch (Kind) { default: assert(0 && "Unknown unary op!"); - case tok::plusplus: Opc = UnaryOperator::PreInc; break; - case tok::minusminus: Opc = UnaryOperator::PreDec; break; - case tok::amp: Opc = UnaryOperator::AddrOf; break; - case tok::star: Opc = UnaryOperator::Deref; break; - case tok::plus: Opc = UnaryOperator::Plus; break; - case tok::minus: Opc = UnaryOperator::Minus; break; - case tok::tilde: Opc = UnaryOperator::Not; break; - case tok::exclaim: Opc = UnaryOperator::LNot; break; - case tok::kw___real: Opc = UnaryOperator::Real; break; - case tok::kw___imag: Opc = UnaryOperator::Imag; break; - case tok::kw___extension__: Opc = UnaryOperator::Extension; break; + case tok::plusplus: Opc = UO_PreInc; break; + case tok::minusminus: Opc = UO_PreDec; break; + case tok::amp: Opc = UO_AddrOf; break; + case tok::star: Opc = UO_Deref; break; + case tok::plus: Opc = UO_Plus; break; + case tok::minus: Opc = UO_Minus; break; + case tok::tilde: Opc = UO_Not; break; + case tok::exclaim: Opc = UO_LNot; break; + case tok::kw___real: Opc = UO_Real; break; + case tok::kw___imag: Opc = UO_Imag; break; + case tok::kw___extension__: Opc = UO_Extension; break; } return Opc; } @@ -6328,106 +6460,111 @@ static inline UnaryOperator::Opcode ConvertTokenKindToUnaryOpcode( /// CreateBuiltinBinOp - Creates a new built-in binary operation with /// operator @p Opc at location @c TokLoc. This routine only supports /// built-in operations; ActOnBinOp handles overloaded operators. -Action::OwningExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, - unsigned Op, - Expr *lhs, Expr *rhs) { +ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, + unsigned Op, + Expr *lhs, Expr *rhs) { QualType ResultTy; // Result type of the binary operator. - BinaryOperator::Opcode Opc = (BinaryOperator::Opcode)Op; + BinaryOperatorKind Opc = (BinaryOperatorKind) Op; // The following two variables are used for compound assignment operators QualType CompLHSTy; // Type of LHS after promotions for computation QualType CompResultTy; // Type of computation result switch (Opc) { - case BinaryOperator::Assign: + case BO_Assign: ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, QualType()); break; - case BinaryOperator::PtrMemD: - case BinaryOperator::PtrMemI: + case BO_PtrMemD: + case BO_PtrMemI: ResultTy = CheckPointerToMemberOperands(lhs, rhs, OpLoc, - Opc == BinaryOperator::PtrMemI); + Opc == BO_PtrMemI); break; - case BinaryOperator::Mul: - case BinaryOperator::Div: + case BO_Mul: + case BO_Div: ResultTy = CheckMultiplyDivideOperands(lhs, rhs, OpLoc, false, - Opc == BinaryOperator::Div); + Opc == BO_Div); break; - case BinaryOperator::Rem: + case BO_Rem: ResultTy = CheckRemainderOperands(lhs, rhs, OpLoc); break; - case BinaryOperator::Add: + case BO_Add: ResultTy = CheckAdditionOperands(lhs, rhs, OpLoc); break; - case BinaryOperator::Sub: + case BO_Sub: ResultTy = CheckSubtractionOperands(lhs, rhs, OpLoc); break; - case BinaryOperator::Shl: - case BinaryOperator::Shr: + case BO_Shl: + case BO_Shr: ResultTy = CheckShiftOperands(lhs, rhs, OpLoc); break; - case BinaryOperator::LE: - case BinaryOperator::LT: - case BinaryOperator::GE: - case BinaryOperator::GT: + case BO_LE: + case BO_LT: + case BO_GE: + case BO_GT: ResultTy = CheckCompareOperands(lhs, rhs, OpLoc, Opc, true); break; - case BinaryOperator::EQ: - case BinaryOperator::NE: + case BO_EQ: + case BO_NE: ResultTy = CheckCompareOperands(lhs, rhs, OpLoc, Opc, false); break; - case BinaryOperator::And: - case BinaryOperator::Xor: - case BinaryOperator::Or: + case BO_And: + case BO_Xor: + case BO_Or: ResultTy = CheckBitwiseOperands(lhs, rhs, OpLoc); break; - case BinaryOperator::LAnd: - case BinaryOperator::LOr: + case BO_LAnd: + case BO_LOr: ResultTy = CheckLogicalOperands(lhs, rhs, OpLoc, Opc); break; - case BinaryOperator::MulAssign: - case BinaryOperator::DivAssign: + case BO_MulAssign: + case BO_DivAssign: CompResultTy = CheckMultiplyDivideOperands(lhs, rhs, OpLoc, true, - Opc == BinaryOperator::DivAssign); + Opc == BO_DivAssign); CompLHSTy = CompResultTy; if (!CompResultTy.isNull()) ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy); break; - case BinaryOperator::RemAssign: + case BO_RemAssign: CompResultTy = CheckRemainderOperands(lhs, rhs, OpLoc, true); CompLHSTy = CompResultTy; if (!CompResultTy.isNull()) ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy); break; - case BinaryOperator::AddAssign: + case BO_AddAssign: CompResultTy = CheckAdditionOperands(lhs, rhs, OpLoc, &CompLHSTy); if (!CompResultTy.isNull()) ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy); break; - case BinaryOperator::SubAssign: + case BO_SubAssign: CompResultTy = CheckSubtractionOperands(lhs, rhs, OpLoc, &CompLHSTy); if (!CompResultTy.isNull()) ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy); break; - case BinaryOperator::ShlAssign: - case BinaryOperator::ShrAssign: + case BO_ShlAssign: + case BO_ShrAssign: CompResultTy = CheckShiftOperands(lhs, rhs, OpLoc, true); CompLHSTy = CompResultTy; if (!CompResultTy.isNull()) ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy); break; - case BinaryOperator::AndAssign: - case BinaryOperator::XorAssign: - case BinaryOperator::OrAssign: + case BO_AndAssign: + case BO_XorAssign: + case BO_OrAssign: CompResultTy = CheckBitwiseOperands(lhs, rhs, OpLoc, true); CompLHSTy = CompResultTy; if (!CompResultTy.isNull()) ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy); break; - case BinaryOperator::Comma: + case BO_Comma: ResultTy = CheckCommaOperands(lhs, rhs, OpLoc); break; } if (ResultTy.isNull()) return ExprError(); + if (ResultTy->isObjCObjectType() && LangOpts.ObjCNonFragileABI) { + if (Opc >= BO_Assign && Opc <= BO_OrAssign) + Diag(OpLoc, diag::err_assignment_requires_nonfragile_object) + << ResultTy; + } if (CompResultTy.isNull()) return Owned(new (Context) BinaryOperator(lhs, rhs, Opc, ResultTy, OpLoc)); else @@ -6479,7 +6616,7 @@ static void SuggestParentheses(Sema &Self, SourceLocation Loc, /// operators are mixed in a way that suggests that the programmer forgot that /// comparison operators have higher precedence. The most typical example of /// such code is "flags & 0x0020 != 0", which is equivalent to "flags & 1". -static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperator::Opcode Opc, +static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperatorKind Opc, SourceLocation OpLoc,Expr *lhs,Expr *rhs){ typedef BinaryOperator BinOp; BinOp::Opcode lhsopc = static_cast(-1), @@ -6526,19 +6663,17 @@ static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperator::Opcode Opc, /// DiagnoseBinOpPrecedence - Emit warnings for expressions with tricky /// precedence. This currently diagnoses only "arg1 'bitwise' arg2 'eq' arg3". /// But it could also warn about arg1 && arg2 || arg3, as GCC 4.3+ does. -static void DiagnoseBinOpPrecedence(Sema &Self, BinaryOperator::Opcode Opc, +static void DiagnoseBinOpPrecedence(Sema &Self, BinaryOperatorKind Opc, SourceLocation OpLoc, Expr *lhs, Expr *rhs){ if (BinaryOperator::isBitwiseOp(Opc)) DiagnoseBitwisePrecedence(Self, Opc, OpLoc, lhs, rhs); } // Binary Operators. 'Tok' is the token for the operator. -Action::OwningExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc, - tok::TokenKind Kind, - ExprArg LHS, ExprArg RHS) { - BinaryOperator::Opcode Opc = ConvertTokenKindToBinaryOpcode(Kind); - Expr *lhs = LHS.takeAs(), *rhs = RHS.takeAs(); - +ExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc, + tok::TokenKind Kind, + Expr *lhs, Expr *rhs) { + BinaryOperatorKind Opc = ConvertTokenKindToBinaryOpcode(Kind); assert((lhs != 0) && "ActOnBinOp(): missing left expression"); assert((rhs != 0) && "ActOnBinOp(): missing right expression"); @@ -6548,9 +6683,9 @@ Action::OwningExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc, return BuildBinOp(S, TokLoc, Opc, lhs, rhs); } -Action::OwningExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc, - BinaryOperator::Opcode Opc, - Expr *lhs, Expr *rhs) { +ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc, + BinaryOperatorKind Opc, + Expr *lhs, Expr *rhs) { if (getLangOptions().CPlusPlus && (lhs->getType()->isOverloadableType() || rhs->getType()->isOverloadableType())) { @@ -6573,38 +6708,32 @@ Action::OwningExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc, return CreateBuiltinBinOp(OpLoc, Opc, lhs, rhs); } -Action::OwningExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, +ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, unsigned OpcIn, - ExprArg InputArg) { - UnaryOperator::Opcode Opc = static_cast(OpcIn); + Expr *Input) { + UnaryOperatorKind Opc = static_cast(OpcIn); - // FIXME: Input is modified below, but InputArg is not updated appropriately. - Expr *Input = (Expr *)InputArg.get(); QualType resultType; switch (Opc) { - case UnaryOperator::OffsetOf: - assert(false && "Invalid unary operator"); - break; - - case UnaryOperator::PreInc: - case UnaryOperator::PreDec: - case UnaryOperator::PostInc: - case UnaryOperator::PostDec: + case UO_PreInc: + case UO_PreDec: + case UO_PostInc: + case UO_PostDec: resultType = CheckIncrementDecrementOperand(Input, OpLoc, - Opc == UnaryOperator::PreInc || - Opc == UnaryOperator::PostInc, - Opc == UnaryOperator::PreInc || - Opc == UnaryOperator::PreDec); + Opc == UO_PreInc || + Opc == UO_PostInc, + Opc == UO_PreInc || + Opc == UO_PreDec); break; - case UnaryOperator::AddrOf: + case UO_AddrOf: resultType = CheckAddressOfOperand(Input, OpLoc); break; - case UnaryOperator::Deref: + case UO_Deref: DefaultFunctionArrayLvalueConversion(Input); resultType = CheckIndirectionOperand(Input, OpLoc); break; - case UnaryOperator::Plus: - case UnaryOperator::Minus: + case UO_Plus: + case UO_Minus: UsualUnaryConversions(Input); resultType = Input->getType(); if (resultType->isDependentType()) @@ -6616,13 +6745,13 @@ Action::OwningExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, resultType->isEnumeralType()) break; else if (getLangOptions().CPlusPlus && // C++ [expr.unary.op]p6 - Opc == UnaryOperator::Plus && + Opc == UO_Plus && resultType->isPointerType()) break; return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) << resultType << Input->getSourceRange()); - case UnaryOperator::Not: // bitwise complement + case UO_Not: // bitwise complement UsualUnaryConversions(Input); resultType = Input->getType(); if (resultType->isDependentType()) @@ -6632,11 +6761,11 @@ Action::OwningExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, // C99 does not support '~' for complex conjugation. Diag(OpLoc, diag::ext_integer_complement_complex) << resultType << Input->getSourceRange(); - else if (!resultType->isIntegerType()) + else if (!resultType->hasIntegerRepresentation()) return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) << resultType << Input->getSourceRange()); break; - case UnaryOperator::LNot: // logical negation + case UO_LNot: // logical negation // Unlike +/-/~, integer promotions aren't done here (C99 6.5.3.3p5). DefaultFunctionArrayLvalueConversion(Input); resultType = Input->getType(); @@ -6649,27 +6778,25 @@ Action::OwningExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, // In C++, it's bool. C++ 5.3.1p8 resultType = getLangOptions().CPlusPlus ? Context.BoolTy : Context.IntTy; break; - case UnaryOperator::Real: - case UnaryOperator::Imag: - resultType = CheckRealImagOperand(Input, OpLoc, Opc == UnaryOperator::Real); + case UO_Real: + case UO_Imag: + resultType = CheckRealImagOperand(Input, OpLoc, Opc == UO_Real); break; - case UnaryOperator::Extension: + case UO_Extension: resultType = Input->getType(); break; } if (resultType.isNull()) return ExprError(); - InputArg.release(); return Owned(new (Context) UnaryOperator(Input, Opc, resultType, OpLoc)); } -Action::OwningExprResult Sema::BuildUnaryOp(Scope *S, SourceLocation OpLoc, - UnaryOperator::Opcode Opc, - ExprArg input) { - Expr *Input = (Expr*)input.get(); +ExprResult Sema::BuildUnaryOp(Scope *S, SourceLocation OpLoc, + UnaryOperatorKind Opc, + Expr *Input) { if (getLangOptions().CPlusPlus && Input->getType()->isOverloadableType() && - Opc != UnaryOperator::Extension) { + UnaryOperator::getOverloadedOperator(Opc) != OO_None) { // Find all of the overloaded operators visible from this // point. We perform both an operator-name lookup from the local // scope and an argument-dependent lookup based on the types of @@ -6680,24 +6807,24 @@ Action::OwningExprResult Sema::BuildUnaryOp(Scope *S, SourceLocation OpLoc, LookupOverloadedOperatorName(OverOp, S, Input->getType(), QualType(), Functions); - return CreateOverloadedUnaryOp(OpLoc, Opc, Functions, move(input)); + return CreateOverloadedUnaryOp(OpLoc, Opc, Functions, Input); } - return CreateBuiltinUnaryOp(OpLoc, Opc, move(input)); + return CreateBuiltinUnaryOp(OpLoc, Opc, Input); } // Unary Operators. 'Tok' is the token for the operator. -Action::OwningExprResult Sema::ActOnUnaryOp(Scope *S, SourceLocation OpLoc, - tok::TokenKind Op, ExprArg input) { - return BuildUnaryOp(S, OpLoc, ConvertTokenKindToUnaryOpcode(Op), move(input)); +ExprResult Sema::ActOnUnaryOp(Scope *S, SourceLocation OpLoc, + tok::TokenKind Op, Expr *Input) { + return BuildUnaryOp(S, OpLoc, ConvertTokenKindToUnaryOpcode(Op), Input); } /// ActOnAddrLabel - Parse the GNU address of label extension: "&&foo". -Sema::OwningExprResult Sema::ActOnAddrLabel(SourceLocation OpLoc, +ExprResult Sema::ActOnAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc, IdentifierInfo *LabelII) { // Look up the record for this label identifier. - LabelStmt *&LabelDecl = getLabelMap()[LabelII]; + LabelStmt *&LabelDecl = getCurFunction()->LabelMap[LabelII]; // If we haven't seen this label yet, create a forward reference. It // will be validated and/or cleaned up in ActOnFinishFunctionBody. @@ -6709,10 +6836,9 @@ Sema::OwningExprResult Sema::ActOnAddrLabel(SourceLocation OpLoc, Context.getPointerType(Context.VoidTy))); } -Sema::OwningExprResult -Sema::ActOnStmtExpr(SourceLocation LPLoc, StmtArg substmt, +ExprResult +Sema::ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt, SourceLocation RPLoc) { // "({..})" - Stmt *SubStmt = static_cast(substmt.get()); assert(SubStmt && isa(SubStmt) && "Invalid action invocation!"); CompoundStmt *Compound = cast(SubStmt); @@ -6742,11 +6868,10 @@ Sema::ActOnStmtExpr(SourceLocation LPLoc, StmtArg substmt, // FIXME: Check that expression type is complete/non-abstract; statement // expressions are not lvalues. - substmt.release(); return Owned(new (Context) StmtExpr(Compound, Ty, LPLoc, RPLoc)); } -Sema::OwningExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc, +ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc, TypeSourceInfo *TInfo, OffsetOfComponent *CompPtr, unsigned NumComponents, @@ -6865,22 +6990,27 @@ Sema::OwningExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc, Diag(MemberDecl->getLocation(), diag::note_bitfield_decl); return ExprError(); } - + + RecordDecl *Parent = MemberDecl->getParent(); + bool AnonStructUnion = Parent->isAnonymousStructOrUnion(); + if (AnonStructUnion) { + do { + Parent = cast(Parent->getParent()); + } while (Parent->isAnonymousStructOrUnion()); + } + // If the member was found in a base class, introduce OffsetOfNodes for // the base class indirections. CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, /*DetectVirtual=*/false); - if (IsDerivedFrom(CurrentType, - Context.getTypeDeclType(MemberDecl->getParent()), - Paths)) { + if (IsDerivedFrom(CurrentType, Context.getTypeDeclType(Parent), Paths)) { CXXBasePath &Path = Paths.front(); for (CXXBasePath::iterator B = Path.begin(), BEnd = Path.end(); B != BEnd; ++B) Comps.push_back(OffsetOfNode(B->Base)); } - - if (cast(MemberDecl->getDeclContext())-> - isAnonymousStructOrUnion()) { + + if (AnonStructUnion) { llvm::SmallVector Path; BuildAnonymousStructUnionMemberPath(MemberDecl, Path); unsigned n = Path.size(); @@ -6897,10 +7027,10 @@ Sema::OwningExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc, Exprs.data(), Exprs.size(), RParenLoc)); } -Sema::OwningExprResult Sema::ActOnBuiltinOffsetOf(Scope *S, +ExprResult Sema::ActOnBuiltinOffsetOf(Scope *S, SourceLocation BuiltinLoc, SourceLocation TypeLoc, - TypeTy *argty, + ParsedType argty, OffsetOfComponent *CompPtr, unsigned NumComponents, SourceLocation RPLoc) { @@ -6910,151 +7040,32 @@ Sema::OwningExprResult Sema::ActOnBuiltinOffsetOf(Scope *S, if (ArgTy.isNull()) return ExprError(); - if (getLangOptions().CPlusPlus) { - if (!ArgTInfo) - ArgTInfo = Context.getTrivialTypeSourceInfo(ArgTy, TypeLoc); - - return BuildBuiltinOffsetOf(BuiltinLoc, ArgTInfo, CompPtr, NumComponents, - RPLoc); - } - - // FIXME: The code below is marked for death, once we have proper CodeGen - // support for non-constant OffsetOf expressions. - - bool Dependent = ArgTy->isDependentType(); - - // We must have at least one component that refers to the type, and the first - // one is known to be a field designator. Verify that the ArgTy represents - // a struct/union/class. - if (!Dependent && !ArgTy->isRecordType()) - return ExprError(Diag(TypeLoc, diag::err_offsetof_record_type) << ArgTy); - - // FIXME: Type must be complete per C99 7.17p3 because a declaring a variable - // with an incomplete type would be illegal. - - // Otherwise, create a null pointer as the base, and iteratively process - // the offsetof designators. - QualType ArgTyPtr = Context.getPointerType(ArgTy); - Expr* Res = new (Context) ImplicitValueInitExpr(ArgTyPtr); - Res = new (Context) UnaryOperator(Res, UnaryOperator::Deref, - ArgTy, SourceLocation()); - - // offsetof with non-identifier designators (e.g. "offsetof(x, a.b[c])") are a - // GCC extension, diagnose them. - // FIXME: This diagnostic isn't actually visible because the location is in - // a system header! - if (NumComponents != 1) - Diag(BuiltinLoc, diag::ext_offsetof_extended_field_designator) - << SourceRange(CompPtr[1].LocStart, CompPtr[NumComponents-1].LocEnd); - - if (!Dependent) { - bool DidWarnAboutNonPOD = false; - - if (RequireCompleteType(TypeLoc, Res->getType(), - diag::err_offsetof_incomplete_type)) - return ExprError(); - - // FIXME: Dependent case loses a lot of information here. And probably - // leaks like a sieve. - for (unsigned i = 0; i != NumComponents; ++i) { - const OffsetOfComponent &OC = CompPtr[i]; - if (OC.isBrackets) { - // Offset of an array sub-field. TODO: Should we allow vector elements? - const ArrayType *AT = Context.getAsArrayType(Res->getType()); - if (!AT) { - Res->Destroy(Context); - return ExprError(Diag(OC.LocEnd, diag::err_offsetof_array_type) - << Res->getType()); - } - - // FIXME: C++: Verify that operator[] isn't overloaded. - - // Promote the array so it looks more like a normal array subscript - // expression. - DefaultFunctionArrayLvalueConversion(Res); - - // C99 6.5.2.1p1 - Expr *Idx = static_cast(OC.U.E); - // FIXME: Leaks Res - if (!Idx->isTypeDependent() && !Idx->getType()->isIntegerType()) - return ExprError(Diag(Idx->getLocStart(), - diag::err_typecheck_subscript_not_integer) - << Idx->getSourceRange()); - - Res = new (Context) ArraySubscriptExpr(Res, Idx, AT->getElementType(), - OC.LocEnd); - continue; - } - - const RecordType *RC = Res->getType()->getAs(); - if (!RC) { - Res->Destroy(Context); - return ExprError(Diag(OC.LocEnd, diag::err_offsetof_record_type) - << Res->getType()); - } - - // Get the decl corresponding to this. - RecordDecl *RD = RC->getDecl(); - if (CXXRecordDecl *CRD = dyn_cast(RD)) { - if (!CRD->isPOD() && !DidWarnAboutNonPOD && - DiagRuntimeBehavior(BuiltinLoc, - PDiag(diag::warn_offsetof_non_pod_type) - << SourceRange(CompPtr[0].LocStart, OC.LocEnd) - << Res->getType())) - DidWarnAboutNonPOD = true; - } - - LookupResult R(*this, OC.U.IdentInfo, OC.LocStart, LookupMemberName); - LookupQualifiedName(R, RD); - - FieldDecl *MemberDecl = R.getAsSingle(); - // FIXME: Leaks Res - if (!MemberDecl) - return ExprError(Diag(BuiltinLoc, diag::err_no_member) - << OC.U.IdentInfo << RD << SourceRange(OC.LocStart, OC.LocEnd)); - - // C99 7.17p3: - // (If the specified member is a bit-field, the behavior is undefined.) - // - // We diagnose this as an error. - if (MemberDecl->getBitWidth()) { - Diag(OC.LocEnd, diag::err_offsetof_bitfield) - << MemberDecl->getDeclName() - << SourceRange(BuiltinLoc, RPLoc); - Diag(MemberDecl->getLocation(), diag::note_bitfield_decl); - return ExprError(); - } - - // FIXME: C++: Verify that MemberDecl isn't a static field. - // FIXME: Verify that MemberDecl isn't a bitfield. - if (cast(MemberDecl->getDeclContext())->isAnonymousStructOrUnion()) { - Res = BuildAnonymousStructUnionMemberReference( - OC.LocEnd, MemberDecl, Res, OC.LocEnd).takeAs(); - } else { - PerformObjectMemberConversion(Res, /*Qualifier=*/0, - *R.begin(), MemberDecl); - // MemberDecl->getType() doesn't get the right qualifiers, but it - // doesn't matter here. - Res = new (Context) MemberExpr(Res, false, MemberDecl, OC.LocEnd, - MemberDecl->getType().getNonReferenceType()); - } - } - } - - return Owned(new (Context) UnaryOperator(Res, UnaryOperator::OffsetOf, - Context.getSizeType(), BuiltinLoc)); + if (!ArgTInfo) + ArgTInfo = Context.getTrivialTypeSourceInfo(ArgTy, TypeLoc); + + return BuildBuiltinOffsetOf(BuiltinLoc, ArgTInfo, CompPtr, NumComponents, + RPLoc); } -Sema::OwningExprResult Sema::ActOnTypesCompatibleExpr(SourceLocation BuiltinLoc, - TypeTy *arg1,TypeTy *arg2, +ExprResult Sema::ActOnTypesCompatibleExpr(SourceLocation BuiltinLoc, + ParsedType arg1,ParsedType arg2, SourceLocation RPLoc) { - // FIXME: Preserve type source info. - QualType argT1 = GetTypeFromParser(arg1); - QualType argT2 = GetTypeFromParser(arg2); + TypeSourceInfo *argTInfo1; + QualType argT1 = GetTypeFromParser(arg1, &argTInfo1); + TypeSourceInfo *argTInfo2; + QualType argT2 = GetTypeFromParser(arg2, &argTInfo2); assert((!argT1.isNull() && !argT2.isNull()) && "Missing type argument(s)"); + return BuildTypesCompatibleExpr(BuiltinLoc, argTInfo1, argTInfo2, RPLoc); +} + +ExprResult +Sema::BuildTypesCompatibleExpr(SourceLocation BuiltinLoc, + TypeSourceInfo *argTInfo1, + TypeSourceInfo *argTInfo2, + SourceLocation RPLoc) { if (getLangOptions().CPlusPlus) { Diag(BuiltinLoc, diag::err_types_compatible_p_in_cplusplus) << SourceRange(BuiltinLoc, RPLoc); @@ -7062,17 +7073,14 @@ Sema::OwningExprResult Sema::ActOnTypesCompatibleExpr(SourceLocation BuiltinLoc, } return Owned(new (Context) TypesCompatibleExpr(Context.IntTy, BuiltinLoc, - argT1, argT2, RPLoc)); + argTInfo1, argTInfo2, RPLoc)); } -Sema::OwningExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc, - ExprArg cond, - ExprArg expr1, ExprArg expr2, - SourceLocation RPLoc) { - Expr *CondExpr = static_cast(cond.get()); - Expr *LHSExpr = static_cast(expr1.get()); - Expr *RHSExpr = static_cast(expr2.get()); +ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc, + Expr *CondExpr, + Expr *LHSExpr, Expr *RHSExpr, + SourceLocation RPLoc) { assert((CondExpr && LHSExpr && RHSExpr) && "Missing type argument(s)"); QualType resType; @@ -7095,7 +7103,6 @@ Sema::OwningExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc, : RHSExpr->isValueDependent(); } - cond.release(); expr1.release(); expr2.release(); return Owned(new (Context) ChooseExpr(BuiltinLoc, CondExpr, LHSExpr, RHSExpr, resType, RPLoc, resType->isDependentType(), @@ -7232,8 +7239,8 @@ void Sema::ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope) { /// ActOnBlockStmtExpr - This is called when the body of a block statement /// literal was successfully completed. ^(int x){...} -Sema::OwningExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, - StmtArg body, Scope *CurScope) { +ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, + Stmt *Body, Scope *CurScope) { // If blocks are disabled, emit an error. if (!LangOpts.Blocks) Diag(CaretLoc, diag::err_blocks_disable); @@ -7295,10 +7302,10 @@ Sema::OwningExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, BlockTy = Context.getBlockPointerType(BlockTy); // If needed, diagnose invalid gotos and switches in the block. - if (FunctionNeedsScopeChecking() && !hasAnyErrorsInThisFunction()) - DiagnoseInvalidJumps(static_cast(body.get())); + if (getCurFunction()->NeedsScopeChecking() && !hasAnyErrorsInThisFunction()) + DiagnoseInvalidJumps(cast(Body)); - BSI->TheDecl->setBody(body.takeAs()); + BSI->TheDecl->setBody(cast(Body)); bool Good = true; // Check goto/label use. @@ -7320,22 +7327,29 @@ Sema::OwningExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, return ExprError(); } + BlockExpr *Result = new (Context) BlockExpr(BSI->TheDecl, BlockTy, + BSI->hasBlockDeclRefExprs); + // Issue any analysis-based warnings. const sema::AnalysisBasedWarnings::Policy &WP = AnalysisWarnings.getDefaultPolicy(); - AnalysisWarnings.IssueWarnings(WP, BSI->TheDecl, BlockTy); + AnalysisWarnings.IssueWarnings(WP, Result); - Expr *Result = new (Context) BlockExpr(BSI->TheDecl, BlockTy, - BSI->hasBlockDeclRefExprs); PopFunctionOrBlockScope(); return Owned(Result); } -Sema::OwningExprResult Sema::ActOnVAArg(SourceLocation BuiltinLoc, - ExprArg expr, TypeTy *type, +ExprResult Sema::ActOnVAArg(SourceLocation BuiltinLoc, + Expr *expr, ParsedType type, SourceLocation RPLoc) { - QualType T = GetTypeFromParser(type); - Expr *E = static_cast(expr.get()); + TypeSourceInfo *TInfo; + QualType T = GetTypeFromParser(type, &TInfo); + return BuildVAArgExpr(BuiltinLoc, expr, TInfo, RPLoc); +} + +ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc, + Expr *E, TypeSourceInfo *TInfo, + SourceLocation RPLoc) { Expr *OrigExpr = E; InitBuiltinVaListType(); @@ -7367,13 +7381,11 @@ Sema::OwningExprResult Sema::ActOnVAArg(SourceLocation BuiltinLoc, // FIXME: Check that type is complete/non-abstract // FIXME: Warn if a non-POD type is passed in. - expr.release(); - return Owned(new (Context) VAArgExpr(BuiltinLoc, E, - T.getNonLValueExprType(Context), - RPLoc)); + QualType T = TInfo->getType().getNonLValueExprType(Context); + return Owned(new (Context) VAArgExpr(BuiltinLoc, E, TInfo, RPLoc, T)); } -Sema::OwningExprResult Sema::ActOnGNUNullExpr(SourceLocation TokenLoc) { +ExprResult Sema::ActOnGNUNullExpr(SourceLocation TokenLoc) { // The type of __null will be int or long, depending on the size of // pointers on the target. QualType Ty; @@ -7647,8 +7659,10 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) { if (CXXConstructorDecl *Constructor = dyn_cast(D)) { unsigned TypeQuals; if (Constructor->isImplicit() && Constructor->isDefaultConstructor()) { - if (!Constructor->isUsed(false)) - DefineImplicitDefaultConstructor(Loc, Constructor); + if (Constructor->getParent()->hasTrivialConstructor()) + return; + if (!Constructor->isUsed(false)) + DefineImplicitDefaultConstructor(Loc, Constructor); } else if (Constructor->isImplicit() && Constructor->isCopyConstructor(TypeQuals)) { if (!Constructor->isUsed(false)) @@ -7696,13 +7710,20 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) { PendingLocalImplicitInstantiations.push_back(std::make_pair(Function, Loc)); else - PendingImplicitInstantiations.push_back(std::make_pair(Function, - Loc)); + PendingInstantiations.push_back(std::make_pair(Function, Loc)); + } + } else // Walk redefinitions, as some of them may be instantiable. + for (FunctionDecl::redecl_iterator i(Function->redecls_begin()), + e(Function->redecls_end()); i != e; ++i) { + if (!i->isUsed(false) && i->isImplicitlyInstantiable()) + MarkDeclarationReferenced(Loc, *i); } - } // FIXME: keep track of references to static functions - Function->setUsed(true); + + // Recursive functions should be marked when used from another function. + if (CurContext != Function) + Function->setUsed(true); return; } @@ -7716,7 +7737,7 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) { if (MSInfo->getPointOfInstantiation().isInvalid() && MSInfo->getTemplateSpecializationKind()== TSK_ImplicitInstantiation) { MSInfo->setPointOfInstantiation(Loc); - PendingImplicitInstantiations.push_back(std::make_pair(Var, Loc)); + PendingInstantiations.push_back(std::make_pair(Var, Loc)); } } @@ -7836,7 +7857,7 @@ void Sema::DiagnoseAssignmentAsCondition(Expr *E) { if (isa(E)) { BinaryOperator *Op = cast(E); - if (Op->getOpcode() != BinaryOperator::Assign) + if (Op->getOpcode() != BO_Assign) return; // Greylist some idioms by putting them into a warning subcategory. @@ -7899,16 +7920,13 @@ bool Sema::CheckBooleanCondition(Expr *&E, SourceLocation Loc) { return false; } -Sema::OwningExprResult Sema::ActOnBooleanCondition(Scope *S, SourceLocation Loc, - ExprArg SubExpr) { - Expr *Sub = SubExpr.takeAs(); +ExprResult Sema::ActOnBooleanCondition(Scope *S, SourceLocation Loc, + Expr *Sub) { if (!Sub) return ExprError(); - if (CheckBooleanCondition(Sub, Loc)) { - Sub->Destroy(Context); + if (CheckBooleanCondition(Sub, Loc)) return ExprError(); - } return Owned(Sub); } diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 090400fc4e23..5720d931b66b 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -11,28 +11,31 @@ // //===----------------------------------------------------------------------===// -#include "Sema.h" -#include "SemaInit.h" -#include "Lookup.h" +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/DeclSpec.h" +#include "clang/Sema/Initialization.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/ParsedTemplate.h" +#include "clang/Sema/TemplateDeduction.h" #include "clang/AST/ASTContext.h" #include "clang/AST/CXXInheritance.h" +#include "clang/AST/DeclObjC.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/TargetInfo.h" #include "clang/Lex/Preprocessor.h" -#include "clang/Parse/DeclSpec.h" -#include "clang/Parse/Template.h" #include "llvm/ADT/STLExtras.h" using namespace clang; - -Action::TypeTy *Sema::getDestructorName(SourceLocation TildeLoc, - IdentifierInfo &II, - SourceLocation NameLoc, - Scope *S, CXXScopeSpec &SS, - TypeTy *ObjectTypePtr, - bool EnteringContext) { +using namespace sema; + +ParsedType Sema::getDestructorName(SourceLocation TildeLoc, + IdentifierInfo &II, + SourceLocation NameLoc, + Scope *S, CXXScopeSpec &SS, + ParsedType ObjectTypePtr, + bool EnteringContext) { // Determine where to perform name lookup. // FIXME: This area of the standard is very messy, and the current @@ -149,7 +152,7 @@ Action::TypeTy *Sema::getDestructorName(SourceLocation TildeLoc, // FIXME: Should we be suppressing ambiguities here? if (Found.isAmbiguous()) - return 0; + return ParsedType(); if (TypeDecl *Type = Found.getAsSingle()) { QualType T = Context.getTypeDeclType(Type); @@ -158,7 +161,7 @@ Action::TypeTy *Sema::getDestructorName(SourceLocation TildeLoc, Context.hasSameUnqualifiedType(T, SearchType)) { // We found our type! - return T.getAsOpaquePtr(); + return ParsedType::make(T); } } @@ -191,7 +194,7 @@ Action::TypeTy *Sema::getDestructorName(SourceLocation TildeLoc, = dyn_cast(Record->getDecl())) { if (Spec->getSpecializedTemplate()->getCanonicalDecl() == Template->getCanonicalDecl()) - return MemberOfType.getAsOpaquePtr(); + return ParsedType::make(MemberOfType); } continue; @@ -210,7 +213,7 @@ Action::TypeTy *Sema::getDestructorName(SourceLocation TildeLoc, // specialized. if (TemplateDecl *SpecTemplate = SpecName.getAsTemplateDecl()) { if (SpecTemplate->getCanonicalDecl() == Template->getCanonicalDecl()) - return MemberOfType.getAsOpaquePtr(); + return ParsedType::make(MemberOfType); continue; } @@ -221,7 +224,7 @@ Action::TypeTy *Sema::getDestructorName(SourceLocation TildeLoc, = SpecName.getAsDependentTemplateName()) { if (DepTemplate->isIdentifier() && DepTemplate->getIdentifier() == Template->getIdentifier()) - return MemberOfType.getAsOpaquePtr(); + return ParsedType::make(MemberOfType); continue; } @@ -242,8 +245,10 @@ Action::TypeTy *Sema::getDestructorName(SourceLocation TildeLoc, Range = SourceRange(NameLoc); } - return CheckTypenameType(ETK_None, NNS, II, SourceLocation(), - Range, NameLoc).getAsOpaquePtr(); + QualType T = CheckTypenameType(ETK_None, NNS, II, + SourceLocation(), + Range, NameLoc); + return ParsedType::make(T); } if (ObjectTypePtr) @@ -252,11 +257,11 @@ Action::TypeTy *Sema::getDestructorName(SourceLocation TildeLoc, else Diag(NameLoc, diag::err_destructor_class_name); - return 0; + return ParsedType(); } /// \brief Build a C++ typeid expression with a type operand. -Sema::OwningExprResult Sema::BuildCXXTypeId(QualType TypeInfoType, +ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType, SourceLocation TypeidLoc, TypeSourceInfo *Operand, SourceLocation RParenLoc) { @@ -279,12 +284,11 @@ Sema::OwningExprResult Sema::BuildCXXTypeId(QualType TypeInfoType, } /// \brief Build a C++ typeid expression with an expression operand. -Sema::OwningExprResult Sema::BuildCXXTypeId(QualType TypeInfoType, +ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType, SourceLocation TypeidLoc, - ExprArg Operand, + Expr *E, SourceLocation RParenLoc) { bool isUnevaluatedOperand = true; - Expr *E = static_cast(Operand.get()); if (E && !E->isTypeDependent()) { QualType T = E->getType(); if (const RecordType *RecordT = T->getAs()) { @@ -296,10 +300,10 @@ Sema::OwningExprResult Sema::BuildCXXTypeId(QualType TypeInfoType, return ExprError(); // C++ [expr.typeid]p3: - // When typeid is applied to an expression other than an lvalue of a + // When typeid is applied to an expression other than an glvalue of a // polymorphic class type [...] [the] expression is an unevaluated // operand. [...] - if (RecordD->isPolymorphic() && E->isLvalue(Context) == Expr::LV_Valid) { + if (RecordD->isPolymorphic() && E->Classify(Context).isGLValue()) { isUnevaluatedOperand = false; // We require a vtable to query the type at run time. @@ -316,9 +320,7 @@ Sema::OwningExprResult Sema::BuildCXXTypeId(QualType TypeInfoType, QualType UnqualT = Context.getUnqualifiedArrayType(T, Quals); if (!Context.hasSameType(T, UnqualT)) { T = UnqualT; - ImpCastExprToType(E, UnqualT, CastExpr::CK_NoOp, E->isLvalue(Context)); - Operand.release(); - Operand = Owned(E); + ImpCastExprToType(E, UnqualT, CK_NoOp, CastCategory(E)); } } @@ -329,12 +331,12 @@ Sema::OwningExprResult Sema::BuildCXXTypeId(QualType TypeInfoType, ExprEvalContexts.back().Context = Unevaluated; return Owned(new (Context) CXXTypeidExpr(TypeInfoType.withConst(), - Operand.takeAs(), + E, SourceRange(TypeidLoc, RParenLoc))); } /// ActOnCXXTypeidOfType - Parse typeid( type-id ) or typeid (expression); -Action::OwningExprResult +ExprResult Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc, bool isType, void *TyOrExpr, SourceLocation RParenLoc) { // Find the std::type_info type. @@ -343,7 +345,7 @@ Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc, IdentifierInfo *TypeInfoII = &PP.getIdentifierTable().get("type_info"); LookupResult R(*this, TypeInfoII, SourceLocation(), LookupTagName); - LookupQualifiedName(R, StdNamespace); + LookupQualifiedName(R, getStdNamespace()); RecordDecl *TypeInfoRecordDecl = R.getAsSingle(); if (!TypeInfoRecordDecl) return ExprError(Diag(OpLoc, diag::err_need_header_before_typeid)); @@ -353,7 +355,8 @@ Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc, if (isType) { // The operand is a type; handle it as such. TypeSourceInfo *TInfo = 0; - QualType T = GetTypeFromParser(TyOrExpr, &TInfo); + QualType T = GetTypeFromParser(ParsedType::getFromOpaquePtr(TyOrExpr), + &TInfo); if (T.isNull()) return ExprError(); @@ -364,11 +367,11 @@ Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc, } // The operand is an expression. - return BuildCXXTypeId(TypeInfoType, OpLoc, Owned((Expr*)TyOrExpr), RParenLoc); + return BuildCXXTypeId(TypeInfoType, OpLoc, (Expr*)TyOrExpr, RParenLoc); } /// ActOnCXXBoolLiteral - Parse {true,false} literals. -Action::OwningExprResult +ExprResult Sema::ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind) { assert((Kind == tok::kw_true || Kind == tok::kw_false) && "Unknown C++ Boolean value!"); @@ -377,15 +380,14 @@ Sema::ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind) { } /// ActOnCXXNullPtrLiteral - Parse 'nullptr'. -Action::OwningExprResult +ExprResult Sema::ActOnCXXNullPtrLiteral(SourceLocation Loc) { return Owned(new (Context) CXXNullPtrLiteralExpr(Context.NullPtrTy, Loc)); } /// ActOnCXXThrow - Parse throw expressions. -Action::OwningExprResult -Sema::ActOnCXXThrow(SourceLocation OpLoc, ExprArg E) { - Expr *Ex = E.takeAs(); +ExprResult +Sema::ActOnCXXThrow(SourceLocation OpLoc, Expr *Ex) { if (Ex && !Ex->isTypeDependent() && CheckCXXThrowOperand(OpLoc, Ex)) return ExprError(); return Owned(new (Context) CXXThrowExpr(Ex, Context.VoidTy, OpLoc)); @@ -400,8 +402,8 @@ bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *&E) { // the type from "array of T" or "function returning T" to "pointer to T" // or "pointer to function returning T", [...] if (E->getType().hasQualifiers()) - ImpCastExprToType(E, E->getType().getUnqualifiedType(), CastExpr::CK_NoOp, - E->isLvalue(Context) == Expr::LV_Valid); + ImpCastExprToType(E, E->getType().getUnqualifiedType(), CK_NoOp, + CastCategory(E)); DefaultFunctionArrayConversion(E); @@ -432,7 +434,7 @@ bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *&E) { InitializedEntity Entity = InitializedEntity::InitializeException(ThrowLoc, E->getType(), /*NRVO=*/false); - OwningExprResult Res = PerformCopyInitialization(Entity, + ExprResult Res = PerformCopyInitialization(Entity, SourceLocation(), Owned(E)); if (Res.isInvalid()) @@ -464,7 +466,7 @@ bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *&E) { return false; } -Action::OwningExprResult Sema::ActOnCXXThis(SourceLocation ThisLoc) { +ExprResult Sema::ActOnCXXThis(SourceLocation ThisLoc) { /// C++ 9.3.2: In the body of a non-static member function, the keyword this /// is a non-lvalue expression whose value is the address of the object for /// which the function is called. @@ -483,8 +485,8 @@ Action::OwningExprResult Sema::ActOnCXXThis(SourceLocation ThisLoc) { /// 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()"). -Action::OwningExprResult -Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep, +ExprResult +Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, ParsedType TypeRep, SourceLocation LParenLoc, MultiExprArg exprs, SourceLocation *CommaLocs, @@ -532,19 +534,19 @@ Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep, // corresponding cast expression. // if (NumExprs == 1) { - CastExpr::CastKind Kind = CastExpr::CK_Unknown; - CXXBaseSpecifierArray BasePath; + CastKind Kind = CK_Unknown; + CXXCastPath BasePath; if (CheckCastTypes(TypeRange, Ty, Exprs[0], Kind, BasePath, /*FunctionalStyle=*/true)) return ExprError(); exprs.release(); - return Owned(new (Context) CXXFunctionalCastExpr( + return Owned(CXXFunctionalCastExpr::Create(Context, Ty.getNonLValueExprType(Context), - TInfo, TyBeginLoc, Kind, - Exprs[0], BasePath, - RParenLoc)); + TInfo, TyBeginLoc, Kind, + Exprs[0], &BasePath, + RParenLoc)); } if (Ty->isRecordType()) { @@ -555,7 +557,7 @@ Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep, : InitializationKind::CreateValue(TypeRange.getBegin(), LParenLoc, RParenLoc); InitializationSequence InitSeq(*this, Entity, Kind, Exprs, NumExprs); - OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind, + ExprResult Result = InitSeq.Perform(*this, Entity, Kind, move(exprs)); // FIXME: Improve AST representation? @@ -587,7 +589,7 @@ Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep, /// or /// @code ::new Foo(23, "hello") @endcode /// For the interpretation of this heap of arguments, consult the base version. -Action::OwningExprResult +ExprResult Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, SourceLocation PlacementLParen, MultiExprArg PlacementArgs, SourceLocation PlacementRParen, SourceRange TypeIdParens, @@ -643,13 +645,13 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, AllocType, D.getSourceRange().getBegin(), R, - Owned(ArraySize), + ArraySize, ConstructorLParen, move(ConstructorArgs), ConstructorRParen); } -Sema::OwningExprResult +ExprResult Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, SourceLocation PlacementLParen, MultiExprArg PlacementArgs, @@ -658,7 +660,7 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, QualType AllocType, SourceLocation TypeLoc, SourceRange TypeRange, - ExprArg ArraySizeE, + Expr *ArraySize, SourceLocation ConstructorLParen, MultiExprArg ConstructorArgs, SourceLocation ConstructorRParen) { @@ -667,12 +669,12 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, // Per C++0x [expr.new]p5, the type being constructed may be a // typedef of an array type. - if (!ArraySizeE.get()) { + if (!ArraySize) { if (const ConstantArrayType *Array = Context.getAsConstantArrayType(AllocType)) { - ArraySizeE = Owned(new (Context) IntegerLiteral(Array->getSize(), - Context.getSizeType(), - TypeRange.getEnd())); + ArraySize = IntegerLiteral::Create(Context, Array->getSize(), + Context.getSizeType(), + TypeRange.getEnd()); AllocType = Array->getElementType(); } } @@ -681,13 +683,12 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, // C++ 5.3.4p6: "The expression in a direct-new-declarator shall have integral // or enumeration type with a non-negative value." - Expr *ArraySize = (Expr *)ArraySizeE.get(); if (ArraySize && !ArraySize->isTypeDependent()) { QualType SizeType = ArraySize->getType(); - OwningExprResult ConvertedSize - = ConvertToIntegralOrEnumerationType(StartLoc, move(ArraySizeE), + ExprResult ConvertedSize + = ConvertToIntegralOrEnumerationType(StartLoc, ArraySize, PDiag(diag::err_array_size_not_integral), PDiag(diag::err_array_size_incomplete_type) << ArraySize->getSourceRange(), @@ -700,8 +701,7 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, if (ConvertedSize.isInvalid()) return ExprError(); - ArraySize = ConvertedSize.takeAs(); - ArraySizeE = Owned(ArraySize); + ArraySize = ConvertedSize.take(); SizeType = ArraySize->getType(); if (!SizeType->isIntegralOrEnumerationType()) return ExprError(); @@ -716,8 +716,20 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, llvm::APInt::getNullValue(Value.getBitWidth()), Value.isUnsigned())) return ExprError(Diag(ArraySize->getSourceRange().getBegin(), - diag::err_typecheck_negative_array_size) + diag::err_typecheck_negative_array_size) << ArraySize->getSourceRange()); + + if (!AllocType->isDependentType()) { + unsigned ActiveSizeBits + = ConstantArrayType::getNumAddressingBits(Context, AllocType, Value); + if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) { + Diag(ArraySize->getSourceRange().getBegin(), + diag::err_array_too_large) + << Value.toString(10) + << ArraySize->getSourceRange(); + return ExprError(); + } + } } else if (TypeIdParens.isValid()) { // Can't have dynamic array size when the type-id is in parentheses. Diag(ArraySize->getLocStart(), diag::ext_new_paren_array_nonconst) @@ -730,7 +742,7 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, } ImpCastExprToType(ArraySize, Context.getSizeType(), - CastExpr::CK_IntegralCast); + CK_IntegralCast); } FunctionDecl *OperatorNew = 0; @@ -768,7 +780,7 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, CXXConstructorDecl *Constructor = 0; Expr **ConsArgs = (Expr**)ConstructorArgs.get(); unsigned NumConsArgs = ConstructorArgs.size(); - ASTOwningVector<&ActionBase::DeleteExpr> ConvertedConstructorArgs(*this); + ASTOwningVector ConvertedConstructorArgs(*this); // Array 'new' can't have any initializers. if (NumConsArgs && (ResultType->isArrayType() || ArraySize)) { @@ -798,7 +810,7 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, InitializedEntity Entity = InitializedEntity::InitializeNew(StartLoc, AllocType); InitializationSequence InitSeq(*this, Entity, Kind, ConsArgs, NumConsArgs); - OwningExprResult FullInit = InitSeq.Perform(*this, Entity, Kind, + ExprResult FullInit = InitSeq.Perform(*this, Entity, Kind, move(ConstructorArgs)); if (FullInit.isInvalid()) return ExprError(); @@ -839,7 +851,6 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, PlacementArgs.release(); ConstructorArgs.release(); - ArraySizeE.release(); // FIXME: The TypeSourceInfo should also be included in CXXNewExpr. return Owned(new (Context) CXXNewExpr(Context, UseGlobal, OperatorNew, @@ -911,7 +922,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, // We don't care about the actual value of this argument. // FIXME: Should the Sema create the expression and embed it in the syntax // tree? Or should the consumer just recalculate the value? - IntegerLiteral Size(llvm::APInt::getNullValue( + IntegerLiteral Size(Context, llvm::APInt::getNullValue( Context.Target.getPointerWidth(0)), Context.getSizeType(), SourceLocation()); @@ -929,9 +940,11 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, DeclarationName DeleteName = Context.DeclarationNames.getCXXOperatorName( IsArray ? OO_Array_Delete : OO_Delete); - if (AllocType->isRecordType() && !UseGlobal) { + QualType AllocElemType = Context.getBaseElementType(AllocType); + + if (AllocElemType->isRecordType() && !UseGlobal) { CXXRecordDecl *Record - = cast(AllocType->getAs()->getDecl()); + = cast(AllocElemType->getAs()->getDecl()); if (FindAllocationOverload(StartLoc, Range, NewName, &AllocArgs[0], AllocArgs.size(), Record, /*AllowMissing=*/true, OperatorNew)) @@ -969,9 +982,9 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, // the allocated type is not a class type or array thereof, the // deallocation function’s name is looked up in the global scope. LookupResult FoundDelete(*this, DeleteName, StartLoc, LookupOrdinaryName); - if (AllocType->isRecordType() && !UseGlobal) { + if (AllocElemType->isRecordType() && !UseGlobal) { CXXRecordDecl *RD - = cast(AllocType->getAs()->getDecl()); + = cast(AllocElemType->getAs()->getDecl()); LookupQualifiedName(FoundDelete, RD); } if (FoundDelete.isAmbiguous()) @@ -1115,7 +1128,7 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range, // Do the resolution. OverloadCandidateSet::iterator Best; - switch(BestViableFunction(Candidates, StartLoc, Best)) { + switch (Candidates.BestViableFunction(*this, StartLoc, Best)) { case OR_Success: { // Got one! FunctionDecl *FnDecl = Best->Function; @@ -1125,7 +1138,7 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range, // Watch out for variadic allocator function. unsigned NumArgsInFnDecl = FnDecl->getNumParams(); for (unsigned i = 0; (i < NumArgs && i < NumArgsInFnDecl); ++i) { - OwningExprResult Result + ExprResult Result = PerformCopyInitialization(InitializedEntity::InitializeParameter( FnDecl->getParamDecl(i)), SourceLocation(), @@ -1143,20 +1156,20 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range, case OR_No_Viable_Function: Diag(StartLoc, diag::err_ovl_no_viable_function_in_call) << Name << Range; - PrintOverloadCandidates(Candidates, OCD_AllCandidates, Args, NumArgs); + Candidates.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); return true; case OR_Ambiguous: Diag(StartLoc, diag::err_ovl_ambiguous_call) << Name << Range; - PrintOverloadCandidates(Candidates, OCD_ViableCandidates, Args, NumArgs); + Candidates.NoteCandidates(*this, OCD_ViableCandidates, Args, NumArgs); return true; case OR_Deleted: Diag(StartLoc, diag::err_ovl_deleted_call) << Best->Function->isDeleted() << Name << Range; - PrintOverloadCandidates(Candidates, OCD_AllCandidates, Args, NumArgs); + Candidates.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); return true; } assert(false && "Unreachable, bad result from BestViableFunction"); @@ -1199,11 +1212,11 @@ void Sema::DeclareGlobalNewDelete() { // The "std::bad_alloc" class has not yet been declared, so build it // implicitly. StdBadAlloc = CXXRecordDecl::Create(Context, TTK_Class, - getStdNamespace(), + getOrCreateStdNamespace(), SourceLocation(), &PP.getIdentifierTable().get("bad_alloc"), SourceLocation(), 0); - StdBadAlloc->setImplicit(true); + getStdBadAlloc()->setImplicit(true); } GlobalNewDeleteDeclared = true; @@ -1245,8 +1258,11 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, Context.getCanonicalType( Func->getParamDecl(0)->getType().getUnqualifiedType()); // FIXME: Do we need to check for default arguments here? - if (Func->getNumParams() == 1 && InitialParamType == Argument) + if (Func->getNumParams() == 1 && InitialParamType == Argument) { + if(AddMallocAttr && !Func->hasAttr()) + Func->addAttr(::new (Context) MallocAttr(SourceLocation(), Context)); return; + } } } } @@ -1257,7 +1273,7 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, Name.getCXXOverloadedOperator() == OO_Array_New); if (HasBadAllocExceptionSpec) { assert(StdBadAlloc && "Must have std::bad_alloc declared"); - BadAllocType = Context.getTypeDeclType(StdBadAlloc); + BadAllocType = Context.getTypeDeclType(getStdBadAlloc()); } QualType FnType = Context.getFunctionType(Return, &Argument, 1, false, 0, @@ -1267,23 +1283,23 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, FunctionType::ExtInfo()); FunctionDecl *Alloc = FunctionDecl::Create(Context, GlobalCtx, SourceLocation(), Name, - FnType, /*TInfo=*/0, FunctionDecl::None, - FunctionDecl::None, false, true); + FnType, /*TInfo=*/0, SC_None, + SC_None, false, true); Alloc->setImplicit(); if (AddMallocAttr) - Alloc->addAttr(::new (Context) MallocAttr()); + Alloc->addAttr(::new (Context) MallocAttr(SourceLocation(), Context)); ParmVarDecl *Param = ParmVarDecl::Create(Context, Alloc, SourceLocation(), 0, Argument, /*TInfo=*/0, - VarDecl::None, - VarDecl::None, 0); + SC_None, + SC_None, 0); Alloc->setParams(&Param, 1); // FIXME: Also add this declaration to the IdentifierResolver, but // make sure it is at the end of the chain to coincide with the // global scope. - ((DeclContext *)TUScope->getEntity())->addDecl(Alloc); + Context.getTranslationUnitDecl()->addDecl(Alloc); } bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, @@ -1298,15 +1314,37 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, Found.suppressDiagnostics(); + llvm::SmallVector Matches; for (LookupResult::iterator F = Found.begin(), FEnd = Found.end(); F != FEnd; ++F) { - if (CXXMethodDecl *Delete = dyn_cast(*F)) - if (Delete->isUsualDeallocationFunction()) { - Operator = Delete; - CheckAllocationAccess(StartLoc, SourceRange(), Found.getNamingClass(), - F.getPair()); - return false; - } + NamedDecl *ND = (*F)->getUnderlyingDecl(); + + // Ignore template operator delete members from the check for a usual + // deallocation function. + if (isa(ND)) + continue; + + if (cast(ND)->isUsualDeallocationFunction()) + Matches.push_back(F.getPair()); + } + + // There's exactly one suitable operator; pick it. + if (Matches.size() == 1) { + Operator = cast(Matches[0]->getUnderlyingDecl()); + CheckAllocationAccess(StartLoc, SourceRange(), Found.getNamingClass(), + Matches[0]); + return false; + + // We found multiple suitable operators; complain about the ambiguity. + } else if (!Matches.empty()) { + Diag(StartLoc, diag::err_ambiguous_suitable_delete_member_function_found) + << Name << RD; + + for (llvm::SmallVectorImpl::iterator + F = Matches.begin(), FEnd = Matches.end(); F != FEnd; ++F) + Diag((*F)->getUnderlyingDecl()->getLocation(), + diag::note_member_declared_here) << Name; + return true; } // We did find operator delete/operator delete[] declarations, but @@ -1316,10 +1354,9 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, << Name << RD; for (LookupResult::iterator F = Found.begin(), FEnd = Found.end(); - F != FEnd; ++F) { - Diag((*F)->getLocation(), diag::note_member_declared_here) - << Name; - } + F != FEnd; ++F) + Diag((*F)->getUnderlyingDecl()->getLocation(), + diag::note_member_declared_here) << Name; return true; } @@ -1344,9 +1381,9 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, /// @code ::delete ptr; @endcode /// or /// @code delete [] ptr; @endcode -Action::OwningExprResult +ExprResult Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, - bool ArrayForm, ExprArg Operand) { + bool ArrayForm, Expr *Ex) { // C++ [expr.delete]p1: // The operand shall have a pointer type, or a class type having a single // conversion function to a pointer type. The result has type void. @@ -1355,11 +1392,14 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, FunctionDecl *OperatorDelete = 0; - Expr *Ex = (Expr *)Operand.get(); if (!Ex->isTypeDependent()) { QualType Type = Ex->getType(); if (const RecordType *Record = Type->getAs()) { + if (RequireCompleteType(StartLoc, Type, + PDiag(diag::err_delete_incomplete_class_type))) + return ExprError(); + llvm::SmallVector ObjectPtrConversions; CXXRecordDecl *RD = cast(Record->getDecl()); @@ -1378,18 +1418,16 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, QualType ConvType = Conv->getConversionType().getNonReferenceType(); if (const PointerType *ConvPtrType = ConvType->getAs()) - if (ConvPtrType->getPointeeType()->isObjectType()) + if (ConvPtrType->getPointeeType()->isIncompleteOrObjectType()) ObjectPtrConversions.push_back(Conv); } if (ObjectPtrConversions.size() == 1) { // We have a single conversion to a pointer-to-object type. Perform // that conversion. // TODO: don't redo the conversion calculation. - Operand.release(); if (!PerformImplicitConversion(Ex, ObjectPtrConversions.front()->getConversionType(), AA_Converting)) { - Operand = Owned(Ex); Type = Ex->getType(); } } @@ -1428,16 +1466,13 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, // (5.2.11) of the pointer expression before it is used as the operand // of the delete-expression. ] ImpCastExprToType(Ex, Context.getPointerType(Context.VoidTy), - CastExpr::CK_NoOp); - - // Update the operand. - Operand.take(); - Operand = ExprArg(*this, Ex); + CK_NoOp); DeclarationName DeleteName = Context.DeclarationNames.getCXXOperatorName( ArrayForm ? OO_Array_Delete : OO_Delete); - if (const RecordType *RT = Pointee->getAs()) { + QualType PointeeElem = Context.getBaseElementType(Pointee); + if (const RecordType *RT = PointeeElem->getAs()) { CXXRecordDecl *RD = cast(RT->getDecl()); if (!UseGlobal && @@ -1465,14 +1500,13 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, // FIXME: Check access and ambiguity of operator delete and destructor. } - Operand.release(); return Owned(new (Context) CXXDeleteExpr(Context.VoidTy, UseGlobal, ArrayForm, OperatorDelete, Ex, StartLoc)); } /// \brief Check the use of the given variable as a C++ condition in an if, /// while, do-while, or switch statement. -Action::OwningExprResult Sema::CheckConditionVariable(VarDecl *ConditionVar, +ExprResult Sema::CheckConditionVariable(VarDecl *ConditionVar, SourceLocation StmtLoc, bool ConvertToBoolean) { QualType T = ConditionVar->getType(); @@ -1491,10 +1525,8 @@ Action::OwningExprResult Sema::CheckConditionVariable(VarDecl *ConditionVar, Expr *Condition = DeclRefExpr::Create(Context, 0, SourceRange(), ConditionVar, ConditionVar->getLocation(), ConditionVar->getType().getNonReferenceType()); - if (ConvertToBoolean && CheckBooleanCondition(Condition, StmtLoc)) { - Condition->Destroy(Context); + if (ConvertToBoolean && CheckBooleanCondition(Condition, StmtLoc)) return ExprError(); - } return Owned(Condition); } @@ -1543,34 +1575,33 @@ Sema::IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType) { return false; } -static Sema::OwningExprResult BuildCXXCastArgument(Sema &S, - SourceLocation CastLoc, - QualType Ty, - CastExpr::CastKind Kind, - CXXMethodDecl *Method, - Sema::ExprArg Arg) { - Expr *From = Arg.takeAs(); - +static ExprResult BuildCXXCastArgument(Sema &S, + SourceLocation CastLoc, + QualType Ty, + CastKind Kind, + CXXMethodDecl *Method, + Expr *From) { switch (Kind) { default: assert(0 && "Unhandled cast kind!"); - case CastExpr::CK_ConstructorConversion: { - ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(S); + case CK_ConstructorConversion: { + ASTOwningVector ConstructorArgs(S); if (S.CompleteConstructorCall(cast(Method), - Sema::MultiExprArg(S, (void **)&From, 1), + MultiExprArg(&From, 1), CastLoc, ConstructorArgs)) - return S.ExprError(); + return ExprError(); - Sema::OwningExprResult Result = + ExprResult Result = S.BuildCXXConstructExpr(CastLoc, Ty, cast(Method), - move_arg(ConstructorArgs)); + move_arg(ConstructorArgs), + /*ZeroInit*/ false, CXXConstructExpr::CK_Complete); if (Result.isInvalid()) - return S.ExprError(); + return ExprError(); return S.MaybeBindToTemporary(Result.takeAs()); } - case CastExpr::CK_UserDefinedConversion: { + case CK_UserDefinedConversion: { assert(!From->getType()->isPointerType() && "Arg can't have pointer type!"); // Create an implicit call expr that calls it. @@ -1601,10 +1632,10 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, case ImplicitConversionSequence::UserDefinedConversion: { FunctionDecl *FD = ICS.UserDefined.ConversionFunction; - CastExpr::CastKind CastKind = CastExpr::CK_Unknown; + CastKind CastKind = CK_Unknown; QualType BeforeToType; if (const CXXConversionDecl *Conv = dyn_cast(FD)) { - CastKind = CastExpr::CK_UserDefinedConversion; + CastKind = CK_UserDefinedConversion; // If the user-defined conversion is specified by a conversion function, // the initial standard conversion sequence converts the source type to @@ -1612,7 +1643,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, BeforeToType = Context.getTagDeclType(Conv->getParent()); } else if (const CXXConstructorDecl *Ctor = dyn_cast(FD)) { - CastKind = CastExpr::CK_ConstructorConversion; + CastKind = CK_ConstructorConversion; // Do no conversion if dealing with ... for the first conversion. if (!ICS.UserDefined.EllipsisConversion) { // If the user-defined conversion is specified by a constructor, the @@ -1631,12 +1662,12 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, return true; } - OwningExprResult CastArg + ExprResult CastArg = BuildCXXCastArgument(*this, From->getLocStart(), ToType.getNonReferenceType(), CastKind, cast(FD), - Owned(From)); + From); if (CastArg.isInvalid()) return true; @@ -1648,7 +1679,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, } case ImplicitConversionSequence::AmbiguousConversion: - DiagnoseAmbiguousConversion(ICS, From->getExprLoc(), + ICS.DiagnoseAmbiguousConversion(*this, From->getExprLoc(), PDiag(diag::err_typecheck_ambiguous_condition) << From->getSourceRange()); return true; @@ -1685,25 +1716,29 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, // FIXME: When can ToType be a reference type? assert(!ToType->isReferenceType()); if (SCS.Second == ICK_Derived_To_Base) { - ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this); + ASTOwningVector ConstructorArgs(*this); if (CompleteConstructorCall(cast(SCS.CopyConstructor), - MultiExprArg(*this, (void **)&From, 1), + MultiExprArg(*this, &From, 1), /*FIXME:ConstructLoc*/SourceLocation(), ConstructorArgs)) return true; - OwningExprResult FromResult = + ExprResult FromResult = BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(), ToType, SCS.CopyConstructor, - move_arg(ConstructorArgs)); + move_arg(ConstructorArgs), + /*ZeroInit*/ false, + CXXConstructExpr::CK_Complete); if (FromResult.isInvalid()) return true; From = FromResult.takeAs(); return false; } - OwningExprResult FromResult = + ExprResult FromResult = BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(), ToType, SCS.CopyConstructor, - MultiExprArg(*this, (void**)&From, 1)); + MultiExprArg(*this, &From, 1), + /*ZeroInit*/ false, + CXXConstructExpr::CK_Complete); if (FromResult.isInvalid()) return true; @@ -1736,12 +1771,12 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, case ICK_Array_To_Pointer: FromType = Context.getArrayDecayedType(FromType); - ImpCastExprToType(From, FromType, CastExpr::CK_ArrayToPointerDecay); + ImpCastExprToType(From, FromType, CK_ArrayToPointerDecay); break; case ICK_Function_To_Pointer: FromType = Context.getPointerType(FromType); - ImpCastExprToType(From, FromType, CastExpr::CK_FunctionToPointerDecay); + ImpCastExprToType(From, FromType, CK_FunctionToPointerDecay); break; default: @@ -1766,33 +1801,33 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, return true; ImpCastExprToType(From, Context.getNoReturnType(From->getType(), false), - CastExpr::CK_NoOp); + CK_NoOp); break; case ICK_Integral_Promotion: case ICK_Integral_Conversion: - ImpCastExprToType(From, ToType, CastExpr::CK_IntegralCast); + ImpCastExprToType(From, ToType, CK_IntegralCast); break; case ICK_Floating_Promotion: case ICK_Floating_Conversion: - ImpCastExprToType(From, ToType, CastExpr::CK_FloatingCast); + ImpCastExprToType(From, ToType, CK_FloatingCast); break; case ICK_Complex_Promotion: case ICK_Complex_Conversion: - ImpCastExprToType(From, ToType, CastExpr::CK_Unknown); + ImpCastExprToType(From, ToType, CK_Unknown); break; case ICK_Floating_Integral: if (ToType->isRealFloatingType()) - ImpCastExprToType(From, ToType, CastExpr::CK_IntegralToFloating); + ImpCastExprToType(From, ToType, CK_IntegralToFloating); else - ImpCastExprToType(From, ToType, CastExpr::CK_FloatingToIntegral); + ImpCastExprToType(From, ToType, CK_FloatingToIntegral); break; case ICK_Compatible_Conversion: - ImpCastExprToType(From, ToType, CastExpr::CK_NoOp); + ImpCastExprToType(From, ToType, CK_NoOp); break; case ICK_Pointer_Conversion: { @@ -1805,36 +1840,36 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, } - CastExpr::CastKind Kind = CastExpr::CK_Unknown; - CXXBaseSpecifierArray BasePath; + CastKind Kind = CK_Unknown; + CXXCastPath BasePath; if (CheckPointerConversion(From, ToType, Kind, BasePath, IgnoreBaseAccess)) return true; - ImpCastExprToType(From, ToType, Kind, /*isLvalue=*/false, BasePath); + ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath); break; } case ICK_Pointer_Member: { - CastExpr::CastKind Kind = CastExpr::CK_Unknown; - CXXBaseSpecifierArray BasePath; + CastKind Kind = CK_Unknown; + CXXCastPath BasePath; if (CheckMemberPointerConversion(From, ToType, Kind, BasePath, IgnoreBaseAccess)) return true; if (CheckExceptionSpecCompatibility(From, ToType)) return true; - ImpCastExprToType(From, ToType, Kind, /*isLvalue=*/false, BasePath); + ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath); break; } case ICK_Boolean_Conversion: { - CastExpr::CastKind Kind = CastExpr::CK_Unknown; + CastKind Kind = CK_Unknown; if (FromType->isMemberPointerType()) - Kind = CastExpr::CK_MemberPointerToBoolean; + Kind = CK_MemberPointerToBoolean; ImpCastExprToType(From, Context.BoolTy, Kind); break; } case ICK_Derived_To_Base: { - CXXBaseSpecifierArray BasePath; + CXXCastPath BasePath; if (CheckDerivedToBaseConversion(From->getType(), ToType.getNonReferenceType(), From->getLocStart(), @@ -1843,24 +1878,22 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, IgnoreBaseAccess)) return true; - ImpCastExprToType(From, ToType.getNonReferenceType(), - CastExpr::CK_DerivedToBase, - /*isLvalue=*/(From->getType()->isRecordType() && - From->isLvalue(Context) == Expr::LV_Valid), - BasePath); + ImpCastExprToType(From, ToType.getNonReferenceType(), + CK_DerivedToBase, CastCategory(From), + &BasePath); break; } case ICK_Vector_Conversion: - ImpCastExprToType(From, ToType, CastExpr::CK_BitCast); + ImpCastExprToType(From, ToType, CK_BitCast); break; case ICK_Vector_Splat: - ImpCastExprToType(From, ToType, CastExpr::CK_VectorSplat); + ImpCastExprToType(From, ToType, CK_VectorSplat); break; case ICK_Complex_Real: - ImpCastExprToType(From, ToType, CastExpr::CK_Unknown); + ImpCastExprToType(From, ToType, CK_Unknown); break; case ICK_Lvalue_To_Rvalue: @@ -1877,18 +1910,21 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, // Nothing to do. break; - case ICK_Qualification: - // FIXME: Not sure about lvalue vs rvalue here in the presence of rvalue - // references. + case ICK_Qualification: { + // The qualification keeps the category of the inner expression, unless the + // target type isn't a reference. + ExprValueKind VK = ToType->isReferenceType() ? + CastCategory(From) : VK_RValue; ImpCastExprToType(From, ToType.getNonLValueExprType(Context), - CastExpr::CK_NoOp, ToType->isLValueReferenceType()); + CK_NoOp, VK); if (SCS.DeprecatedStringLiteralToCharPtr) Diag(From->getLocStart(), diag::warn_deprecated_string_literal_conversion) << ToType.getNonReferenceType(); break; - + } + default: assert(false && "Improper third standard conversion"); break; @@ -1897,10 +1933,10 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, return false; } -Sema::OwningExprResult Sema::ActOnUnaryTypeTrait(UnaryTypeTrait OTT, +ExprResult Sema::ActOnUnaryTypeTrait(UnaryTypeTrait OTT, SourceLocation KWLoc, SourceLocation LParen, - TypeTy *Ty, + ParsedType Ty, SourceLocation RParen) { QualType T = GetTypeFromParser(Ty); @@ -1974,12 +2010,12 @@ QualType Sema::CheckPointerToMemberOperands( } // Cast LHS to type of use. QualType UseType = isIndirect ? Context.getPointerType(Class) : Class; - bool isLValue = !isIndirect && lex->isLvalue(Context) == Expr::LV_Valid; - - CXXBaseSpecifierArray BasePath; + ExprValueKind VK = + isIndirect ? VK_RValue : CastCategory(lex); + + CXXCastPath BasePath; BuildBasePathArray(Paths, BasePath); - ImpCastExprToType(lex, UseType, CastExpr::CK_DerivedToBase, isLValue, - BasePath); + ImpCastExprToType(lex, UseType, CK_DerivedToBase, VK, &BasePath); } if (isa(rex->IgnoreParens())) { @@ -2108,7 +2144,7 @@ static bool FindConditionalOverload(Sema &Self, Expr *&LHS, Expr *&RHS, Self.AddBuiltinOperatorCandidates(OO_Conditional, Loc, Args, 2, CandidateSet); OverloadCandidateSet::iterator Best; - switch (Self.BestViableFunction(CandidateSet, Loc, Best)) { + switch (CandidateSet.BestViableFunction(Self, Loc, Best)) { case OR_Success: // We found a match. Perform the conversions on the arguments and move on. if (Self.PerformImplicitConversion(LHS, Best->BuiltinTypes.ParamTypes[0], @@ -2146,8 +2182,7 @@ static bool ConvertForConditional(Sema &Self, Expr *&E, QualType T) { InitializationKind Kind = InitializationKind::CreateCopy(E->getLocStart(), SourceLocation()); InitializationSequence InitSeq(Self, Entity, Kind, &E, 1); - Sema::OwningExprResult Result = InitSeq.Perform(Self, Entity, Kind, - Sema::MultiExprArg(Self, (void **)&E, 1)); + ExprResult Result = InitSeq.Perform(Self, Entity, Kind, MultiExprArg(&E, 1)); if (Result.isInvalid()) return true; @@ -2286,13 +2321,13 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, if (LTy->isRecordType()) { // The operands have class type. Make a temporary copy. InitializedEntity Entity = InitializedEntity::InitializeTemporary(LTy); - OwningExprResult LHSCopy = PerformCopyInitialization(Entity, + ExprResult LHSCopy = PerformCopyInitialization(Entity, SourceLocation(), Owned(LHS)); if (LHSCopy.isInvalid()) return QualType(); - OwningExprResult RHSCopy = PerformCopyInitialization(Entity, + ExprResult RHSCopy = PerformCopyInitialization(Entity, SourceLocation(), Owned(RHS)); if (RHSCopy.isInvalid()) @@ -2385,16 +2420,16 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc, // the type of the other operand. if (E1->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { if (T2->isMemberPointerType()) - ImpCastExprToType(E1, T2, CastExpr::CK_NullToMemberPointer); + ImpCastExprToType(E1, T2, CK_NullToMemberPointer); else - ImpCastExprToType(E1, T2, CastExpr::CK_IntegralToPointer); + ImpCastExprToType(E1, T2, CK_IntegralToPointer); return T2; } if (E2->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { if (T1->isMemberPointerType()) - ImpCastExprToType(E2, T1, CastExpr::CK_NullToMemberPointer); + ImpCastExprToType(E2, T1, CK_NullToMemberPointer); else - ImpCastExprToType(E2, T1, CastExpr::CK_IntegralToPointer); + ImpCastExprToType(E2, T1, CK_IntegralToPointer); return T1; } @@ -2528,15 +2563,15 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc, } // Convert E1 to Composite1 - OwningExprResult E1Result - = E1ToC1.Perform(*this, Entity1, Kind, MultiExprArg(*this,(void**)&E1,1)); + ExprResult E1Result + = E1ToC1.Perform(*this, Entity1, Kind, MultiExprArg(*this,&E1,1)); if (E1Result.isInvalid()) return QualType(); E1 = E1Result.takeAs(); // Convert E2 to Composite1 - OwningExprResult E2Result - = E2ToC1.Perform(*this, Entity1, Kind, MultiExprArg(*this,(void**)&E2,1)); + ExprResult E2Result + = E2ToC1.Perform(*this, Entity1, Kind, MultiExprArg(*this,&E2,1)); if (E2Result.isInvalid()) return QualType(); E2 = E2Result.takeAs(); @@ -2553,15 +2588,15 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc, return QualType(); // Convert E1 to Composite2 - OwningExprResult E1Result - = E1ToC2.Perform(*this, Entity2, Kind, MultiExprArg(*this, (void**)&E1, 1)); + ExprResult E1Result + = E1ToC2.Perform(*this, Entity2, Kind, MultiExprArg(*this, &E1, 1)); if (E1Result.isInvalid()) return QualType(); E1 = E1Result.takeAs(); // Convert E2 to Composite2 - OwningExprResult E2Result - = E2ToC2.Perform(*this, Entity2, Kind, MultiExprArg(*this, (void**)&E2, 1)); + ExprResult E2Result + = E2ToC2.Perform(*this, Entity2, Kind, MultiExprArg(*this, &E2, 1)); if (E2Result.isInvalid()) return QualType(); E2 = E2Result.takeAs(); @@ -2569,7 +2604,7 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc, return Composite2; } -Sema::OwningExprResult Sema::MaybeBindToTemporary(Expr *E) { +ExprResult Sema::MaybeBindToTemporary(Expr *E) { if (!Context.getLangOptions().CPlusPlus) return Owned(E); @@ -2579,34 +2614,22 @@ Sema::OwningExprResult Sema::MaybeBindToTemporary(Expr *E) { if (!RT) return Owned(E); - // If this is the result of a call expression, our source might - // actually be a reference, in which case we shouldn't bind. + // If this is the result of a call or an Objective-C message send expression, + // our source might actually be a reference, in which case we shouldn't bind. if (CallExpr *CE = dyn_cast(E)) { - QualType Ty = CE->getCallee()->getType(); - if (const PointerType *PT = Ty->getAs()) - Ty = PT->getPointeeType(); - else if (const BlockPointerType *BPT = Ty->getAs()) - Ty = BPT->getPointeeType(); - - const FunctionType *FTy = Ty->getAs(); - if (FTy->getResultType()->isReferenceType()) + if (CE->getCallReturnType()->isReferenceType()) return Owned(E); + } else if (ObjCMessageExpr *ME = dyn_cast(E)) { + if (const ObjCMethodDecl *MD = ME->getMethodDecl()) { + if (MD->getResultType()->isReferenceType()) + return Owned(E); + } } - else if (ObjCMessageExpr *ME = dyn_cast(E)) { - QualType Ty = ME->getType(); - if (const PointerType *PT = Ty->getAs()) - Ty = PT->getPointeeType(); - else if (const BlockPointerType *BPT = Ty->getAs()) - Ty = BPT->getPointeeType(); - if (Ty->isReferenceType()) - return Owned(E); - } - // That should be enough to guarantee that this type is complete. // If it has a trivial destructor, we can avoid the extra copy. CXXRecordDecl *RD = cast(RT->getDecl()); - if (RD->hasTrivialDestructor()) + if (RD->isInvalidDecl() || RD->hasTrivialDestructor()) return Owned(E); CXXTemporary *Temp = CXXTemporary::Create(Context, LookupDestructor(RD)); @@ -2641,8 +2664,8 @@ Expr *Sema::MaybeCreateCXXExprWithTemporaries(Expr *SubExpr) { return E; } -Sema::OwningExprResult -Sema::MaybeCreateCXXExprWithTemporaries(OwningExprResult SubExpr) { +ExprResult +Sema::MaybeCreateCXXExprWithTemporaries(ExprResult SubExpr) { if (SubExpr.isInvalid()) return ExprError(); @@ -2665,17 +2688,16 @@ FullExpr Sema::CreateFullExpr(Expr *SubExpr) { return E; } -Sema::OwningExprResult -Sema::ActOnStartCXXMemberReference(Scope *S, ExprArg Base, SourceLocation OpLoc, - tok::TokenKind OpKind, TypeTy *&ObjectType, +ExprResult +Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, SourceLocation OpLoc, + tok::TokenKind OpKind, ParsedType &ObjectType, bool &MayBePseudoDestructor) { // Since this might be a postfix expression, get rid of ParenListExprs. - Base = MaybeConvertParenListExprToParenExpr(S, move(Base)); + ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Base); + if (Result.isInvalid()) return ExprError(); + Base = Result.get(); - Expr *BaseExpr = (Expr*)Base.get(); - assert(BaseExpr && "no record expansion"); - - QualType BaseType = BaseExpr->getType(); + QualType BaseType = Base->getType(); MayBePseudoDestructor = false; if (BaseType->isDependentType()) { // If we have a pointer to a dependent type and are using the -> operator, @@ -2685,9 +2707,9 @@ Sema::ActOnStartCXXMemberReference(Scope *S, ExprArg Base, SourceLocation OpLoc, if (const PointerType *Ptr = BaseType->getAs()) BaseType = Ptr->getPointeeType(); - ObjectType = BaseType.getAsOpaquePtr(); + ObjectType = ParsedType::make(BaseType); MayBePseudoDestructor = true; - return move(Base); + return Owned(Base); } // C++ [over.match.oper]p8: @@ -2700,13 +2722,13 @@ Sema::ActOnStartCXXMemberReference(Scope *S, ExprArg Base, SourceLocation OpLoc, CTypes.insert(Context.getCanonicalType(BaseType)); while (BaseType->isRecordType()) { - Base = BuildOverloadedArrowExpr(S, move(Base), OpLoc); - BaseExpr = (Expr*)Base.get(); - if (BaseExpr == NULL) + Result = BuildOverloadedArrowExpr(S, Base, OpLoc); + if (Result.isInvalid()) return ExprError(); - if (CXXOperatorCallExpr *OpCall = dyn_cast(BaseExpr)) + Base = Result.get(); + if (CXXOperatorCallExpr *OpCall = dyn_cast(Base)) Locations.push_back(OpCall->getDirectCallee()->getLocation()); - BaseType = BaseExpr->getType(); + BaseType = Base->getType(); CanQualType CBaseType = Context.getCanonicalType(BaseType); if (!CTypes.insert(CBaseType)) { Diag(OpLoc, diag::err_operator_arrow_circular); @@ -2731,9 +2753,9 @@ Sema::ActOnStartCXXMemberReference(Scope *S, ExprArg Base, SourceLocation OpLoc, // // This also indicates that we should be parsing a // pseudo-destructor-name. - ObjectType = 0; + ObjectType = ParsedType(); MayBePseudoDestructor = true; - return move(Base); + return Owned(Base); } // The object type must be complete (or dependent). @@ -2747,27 +2769,26 @@ Sema::ActOnStartCXXMemberReference(Scope *S, ExprArg Base, SourceLocation OpLoc, // unqualified-id, and the type of the object expression is of a class // type C (or of pointer to a class type C), the unqualified-id is looked // up in the scope of class C. [...] - ObjectType = BaseType.getAsOpaquePtr(); + ObjectType = ParsedType::make(BaseType); return move(Base); } -Sema::OwningExprResult Sema::DiagnoseDtorReference(SourceLocation NameLoc, - ExprArg MemExpr) { - Expr *E = (Expr *) MemExpr.get(); +ExprResult Sema::DiagnoseDtorReference(SourceLocation NameLoc, + Expr *MemExpr) { SourceLocation ExpectedLParenLoc = PP.getLocForEndOfToken(NameLoc); - Diag(E->getLocStart(), diag::err_dtor_expr_without_call) - << isa(E) + Diag(MemExpr->getLocStart(), diag::err_dtor_expr_without_call) + << isa(MemExpr) << FixItHint::CreateInsertion(ExpectedLParenLoc, "()"); return ActOnCallExpr(/*Scope*/ 0, - move(MemExpr), + MemExpr, /*LPLoc*/ ExpectedLParenLoc, - Sema::MultiExprArg(*this, 0, 0), + MultiExprArg(), /*CommaLocs*/ 0, /*RPLoc*/ ExpectedLParenLoc); } -Sema::OwningExprResult Sema::BuildPseudoDestructorExpr(ExprArg Base, +ExprResult Sema::BuildPseudoDestructorExpr(Expr *Base, SourceLocation OpLoc, tok::TokenKind OpKind, const CXXScopeSpec &SS, @@ -2782,12 +2803,11 @@ Sema::OwningExprResult Sema::BuildPseudoDestructorExpr(ExprArg Base, // The left-hand side of the dot operator shall be of scalar type. The // left-hand side of the arrow operator shall be of pointer to scalar type. // This scalar type is the object type. - Expr *BaseE = (Expr *)Base.get(); - QualType ObjectType = BaseE->getType(); + QualType ObjectType = Base->getType(); if (OpKind == tok::arrow) { if (const PointerType *Ptr = ObjectType->getAs()) { ObjectType = Ptr->getPointeeType(); - } else if (!BaseE->isTypeDependent()) { + } else if (!Base->isTypeDependent()) { // The user wrote "p->" when she probably meant "p."; fix it. Diag(OpLoc, diag::err_typecheck_member_reference_suggestion) << ObjectType << true @@ -2801,7 +2821,7 @@ Sema::OwningExprResult Sema::BuildPseudoDestructorExpr(ExprArg Base, if (!ObjectType->isDependentType() && !ObjectType->isScalarType()) { Diag(OpLoc, diag::err_pseudo_dtor_base_not_scalar) - << ObjectType << BaseE->getSourceRange(); + << ObjectType << Base->getSourceRange(); return ExprError(); } @@ -2815,7 +2835,7 @@ Sema::OwningExprResult Sema::BuildPseudoDestructorExpr(ExprArg Base, if (!DestructedType->isDependentType() && !ObjectType->isDependentType() && !Context.hasSameUnqualifiedType(DestructedType, ObjectType)) { Diag(DestructedTypeStart, diag::err_pseudo_dtor_type_mismatch) - << ObjectType << DestructedType << BaseE->getSourceRange() + << ObjectType << DestructedType << Base->getSourceRange() << DestructedTypeInfo->getTypeLoc().getLocalSourceRange(); // Recover by setting the destructed type to the object type. @@ -2840,7 +2860,7 @@ Sema::OwningExprResult Sema::BuildPseudoDestructorExpr(ExprArg Base, Diag(ScopeTypeInfo->getTypeLoc().getLocalSourceRange().getBegin(), diag::err_pseudo_dtor_type_mismatch) - << ObjectType << ScopeType << BaseE->getSourceRange() + << ObjectType << ScopeType << Base->getSourceRange() << ScopeTypeInfo->getTypeLoc().getLocalSourceRange(); ScopeType = QualType(); @@ -2848,25 +2868,22 @@ Sema::OwningExprResult Sema::BuildPseudoDestructorExpr(ExprArg Base, } } - OwningExprResult Result - = Owned(new (Context) CXXPseudoDestructorExpr(Context, - Base.takeAs(), - OpKind == tok::arrow, - OpLoc, - (NestedNameSpecifier *) SS.getScopeRep(), - SS.getRange(), - ScopeTypeInfo, - CCLoc, - TildeLoc, - Destructed)); + Expr *Result + = new (Context) CXXPseudoDestructorExpr(Context, Base, + OpKind == tok::arrow, OpLoc, + SS.getScopeRep(), SS.getRange(), + ScopeTypeInfo, + CCLoc, + TildeLoc, + Destructed); if (HasTrailingLParen) - return move(Result); + return Owned(Result); - return DiagnoseDtorReference(Destructed.getLocation(), move(Result)); + return DiagnoseDtorReference(Destructed.getLocation(), Result); } -Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base, +ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, SourceLocation OpLoc, tok::TokenKind OpKind, CXXScopeSpec &SS, @@ -2882,13 +2899,11 @@ Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base, SecondTypeName.getKind() == UnqualifiedId::IK_Identifier) && "Invalid second type name in pseudo-destructor"); - Expr *BaseE = (Expr *)Base.get(); - // C++ [expr.pseudo]p2: // The left-hand side of the dot operator shall be of scalar type. The // left-hand side of the arrow operator shall be of pointer to scalar type. // This scalar type is the object type. - QualType ObjectType = BaseE->getType(); + QualType ObjectType = Base->getType(); if (OpKind == tok::arrow) { if (const PointerType *Ptr = ObjectType->getAs()) { ObjectType = Ptr->getPointeeType(); @@ -2906,12 +2921,12 @@ Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base, // Compute the object type that we should use for name lookup purposes. Only // record types and dependent types matter. - void *ObjectTypePtrForLookup = 0; + ParsedType ObjectTypePtrForLookup; if (!SS.isSet()) { - ObjectTypePtrForLookup = const_cast( - ObjectType->getAs()); - if (!ObjectTypePtrForLookup && ObjectType->isDependentType()) - ObjectTypePtrForLookup = Context.DependentTy.getAsOpaquePtr(); + if (const Type *T = ObjectType->getAs()) + ObjectTypePtrForLookup = ParsedType::make(QualType(T, 0)); + else if (ObjectType->isDependentType()) + ObjectTypePtrForLookup = ParsedType::make(Context.DependentTy); } // Convert the name of the type being destructed (following the ~) into a @@ -2920,9 +2935,9 @@ Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base, TypeSourceInfo *DestructedTypeInfo = 0; PseudoDestructorTypeStorage Destructed; if (SecondTypeName.getKind() == UnqualifiedId::IK_Identifier) { - TypeTy *T = getTypeName(*SecondTypeName.Identifier, - SecondTypeName.StartLocation, - S, &SS, true, ObjectTypePtrForLookup); + ParsedType T = getTypeName(*SecondTypeName.Identifier, + SecondTypeName.StartLocation, + S, &SS, true, ObjectTypePtrForLookup); if (!T && ((SS.isSet() && !computeDeclContext(SS, false)) || (!SS.isSet() && ObjectType->isDependentType()))) { @@ -2949,7 +2964,7 @@ Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base, ASTTemplateArgsPtr TemplateArgsPtr(*this, TemplateId->getTemplateArgs(), TemplateId->NumArgs); - TypeResult T = ActOnTemplateIdType(TemplateTy::make(TemplateId->Template), + TypeResult T = ActOnTemplateIdType(TemplateId->Template, TemplateId->TemplateNameLoc, TemplateId->LAngleLoc, TemplateArgsPtr, @@ -2976,9 +2991,9 @@ Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base, if (FirstTypeName.getKind() == UnqualifiedId::IK_TemplateId || FirstTypeName.Identifier) { if (FirstTypeName.getKind() == UnqualifiedId::IK_Identifier) { - TypeTy *T = getTypeName(*FirstTypeName.Identifier, - FirstTypeName.StartLocation, - S, &SS, false, ObjectTypePtrForLookup); + ParsedType T = getTypeName(*FirstTypeName.Identifier, + FirstTypeName.StartLocation, + S, &SS, false, ObjectTypePtrForLookup); if (!T) { Diag(FirstTypeName.StartLocation, diag::err_pseudo_dtor_destructor_non_type) @@ -2997,7 +3012,7 @@ Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base, ASTTemplateArgsPtr TemplateArgsPtr(*this, TemplateId->getTemplateArgs(), TemplateId->NumArgs); - TypeResult T = ActOnTemplateIdType(TemplateTy::make(TemplateId->Template), + TypeResult T = ActOnTemplateIdType(TemplateId->Template, TemplateId->TemplateNameLoc, TemplateId->LAngleLoc, TemplateArgsPtr, @@ -3015,7 +3030,7 @@ Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base, FirstTypeName.StartLocation); - return BuildPseudoDestructorExpr(move(Base), OpLoc, OpKind, SS, + return BuildPseudoDestructorExpr(Base, OpLoc, OpKind, SS, ScopeTypeInfo, CCLoc, TildeLoc, Destructed, HasTrailingLParen); } @@ -3028,7 +3043,7 @@ CXXMemberCallExpr *Sema::BuildCXXMemberCallExpr(Expr *Exp, assert(0 && "Calling BuildCXXMemberCallExpr with invalid call?"); MemberExpr *ME = - new (Context) MemberExpr(Exp, /*IsArrow=*/false, Method, + new (Context) MemberExpr(Exp, /*IsArrow=*/false, Method, SourceLocation(), Method->getType()); QualType ResultType = Method->getCallResultType(); MarkDeclarationReferenced(Exp->getLocStart(), Method); @@ -3038,12 +3053,7 @@ CXXMemberCallExpr *Sema::BuildCXXMemberCallExpr(Expr *Exp, return CE; } -Sema::OwningExprResult Sema::ActOnFinishFullExpr(ExprArg Arg) { - Expr *FullExpr = Arg.takeAs(); - if (FullExpr) - FullExpr = MaybeCreateCXXExprWithTemporaries(FullExpr); - else - return ExprError(); - - return Owned(FullExpr); +ExprResult Sema::ActOnFinishFullExpr(Expr *FullExpr) { + if (!FullExpr) return ExprError(); + return MaybeCreateCXXExprWithTemporaries(FullExpr); } diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index 9f43471e0ade..b56159c453b5 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -11,9 +11,10 @@ // //===----------------------------------------------------------------------===// -#include "Sema.h" -#include "Lookup.h" -#include "SemaInit.h" +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/Initialization.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/ExprObjC.h" @@ -23,9 +24,9 @@ using namespace clang; -Sema::ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs, - ExprTy **strings, - unsigned NumStrings) { +ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs, + Expr **strings, + unsigned NumStrings) { StringLiteral **Strings = reinterpret_cast(strings); // Most ObjC strings are formed out of a single piece. However, we *can* @@ -50,14 +51,11 @@ Sema::ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs, return true; } - // Get the string data. - StrBuf.append(S->getStrData(), S->getStrData()+S->getByteLength()); + // Append the string. + StrBuf += S->getString(); // Get the locations of the string tokens. StrLocs.append(S->tokloc_begin(), S->tokloc_end()); - - // Free the temporary string. - S->Destroy(Context); } // Create the aggregate string with the appropriate content and location @@ -135,11 +133,11 @@ Expr *Sema::BuildObjCEncodeExpression(SourceLocation AtLoc, return new (Context) ObjCEncodeExpr(StrTy, EncodedTypeInfo, AtLoc, RParenLoc); } -Sema::ExprResult Sema::ParseObjCEncodeExpression(SourceLocation AtLoc, - SourceLocation EncodeLoc, - SourceLocation LParenLoc, - TypeTy *ty, - SourceLocation RParenLoc) { +ExprResult Sema::ParseObjCEncodeExpression(SourceLocation AtLoc, + SourceLocation EncodeLoc, + SourceLocation LParenLoc, + ParsedType ty, + SourceLocation RParenLoc) { // FIXME: Preserve type source info ? TypeSourceInfo *TInfo; QualType EncodedType = GetTypeFromParser(ty, &TInfo); @@ -150,28 +148,33 @@ Sema::ExprResult Sema::ParseObjCEncodeExpression(SourceLocation AtLoc, return BuildObjCEncodeExpression(AtLoc, TInfo, RParenLoc); } -Sema::ExprResult Sema::ParseObjCSelectorExpression(Selector Sel, - SourceLocation AtLoc, - SourceLocation SelLoc, - SourceLocation LParenLoc, - SourceLocation RParenLoc) { +ExprResult Sema::ParseObjCSelectorExpression(Selector Sel, + SourceLocation AtLoc, + SourceLocation SelLoc, + SourceLocation LParenLoc, + SourceLocation RParenLoc) { ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool(Sel, - SourceRange(LParenLoc, RParenLoc), false); + SourceRange(LParenLoc, RParenLoc), false, false); if (!Method) Method = LookupFactoryMethodInGlobalPool(Sel, SourceRange(LParenLoc, RParenLoc)); if (!Method) Diag(SelLoc, diag::warn_undeclared_selector) << Sel; + llvm::DenseMap::iterator Pos + = ReferencedSelectors.find(Sel); + if (Pos == ReferencedSelectors.end()) + ReferencedSelectors.insert(std::make_pair(Sel, SelLoc)); + QualType Ty = Context.getObjCSelType(); return new (Context) ObjCSelectorExpr(Ty, Sel, AtLoc, RParenLoc); } -Sema::ExprResult Sema::ParseObjCProtocolExpression(IdentifierInfo *ProtocolId, - SourceLocation AtLoc, - SourceLocation ProtoLoc, - SourceLocation LParenLoc, - SourceLocation RParenLoc) { +ExprResult Sema::ParseObjCProtocolExpression(IdentifierInfo *ProtocolId, + SourceLocation AtLoc, + SourceLocation ProtoLoc, + SourceLocation LParenLoc, + SourceLocation RParenLoc) { ObjCProtocolDecl* PDecl = LookupProtocol(ProtocolId, ProtoLoc); if (!PDecl) { Diag(ProtoLoc, diag::err_undeclared_protocol) << ProtocolId; @@ -239,7 +242,7 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, return true; InitializedEntity Entity = InitializedEntity::InitializeParameter(Param); - OwningExprResult ArgE = PerformCopyInitialization(Entity, + ExprResult ArgE = PerformCopyInitialization(Entity, SourceLocation(), Owned(argExpr->Retain())); if (ArgE.isInvalid()) @@ -329,7 +332,7 @@ ObjCMethodDecl *Sema::LookupPrivateInstanceMethod(Selector Sel, /// HandleExprPropertyRefExpr - Handle foo.bar where foo is a pointer to an /// objective C interface. This is a property reference expression. -Action::OwningExprResult Sema:: +ExprResult Sema:: HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, Expr *BaseExpr, DeclarationName MemberName, SourceLocation MemberLoc) { @@ -431,7 +434,7 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, -Action::OwningExprResult Sema:: +ExprResult Sema:: ActOnClassPropertyRefExpr(IdentifierInfo &receiverName, IdentifierInfo &propertyName, SourceLocation receiverNameLoc, @@ -529,8 +532,8 @@ Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S, SourceLocation NameLoc, bool IsSuper, bool HasTrailingDot, - TypeTy *&ReceiverType) { - ReceiverType = 0; + ParsedType &ReceiverType) { + ReceiverType = ParsedType(); // If the identifier is "super" and there is no trailing dot, we're // messaging super. @@ -577,7 +580,7 @@ Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S, // We have a class message, and T is the type we're // messaging. Build source-location information for it. TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(T, NameLoc); - ReceiverType = CreateLocInfoType(T, TSInfo).getAsOpaquePtr(); + ReceiverType = CreateParsedType(T, TSInfo); return ObjCClassMessage; } } @@ -604,7 +607,7 @@ Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S, QualType T = Context.getObjCInterfaceType(Class); TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(T, NameLoc); - ReceiverType = CreateLocInfoType(T, TSInfo).getAsOpaquePtr(); + ReceiverType = CreateParsedType(T, TSInfo); return ObjCClassMessage; } } else if (Result.empty() && Corrected.getAsIdentifierInfo() && @@ -622,7 +625,7 @@ Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S, return ObjCInstanceMessage; } -Sema::OwningExprResult Sema::ActOnSuperMessage(Scope *S, +ExprResult Sema::ActOnSuperMessage(Scope *S, SourceLocation SuperLoc, Selector Sel, SourceLocation LBracLoc, @@ -657,7 +660,7 @@ Sema::OwningExprResult Sema::ActOnSuperMessage(Scope *S, // message to the superclass instance. QualType SuperTy = Context.getObjCInterfaceType(Super); SuperTy = Context.getObjCObjectPointerType(SuperTy); - return BuildInstanceMessage(ExprArg(*this), SuperTy, SuperLoc, + return BuildInstanceMessage(0, SuperTy, SuperLoc, Sel, /*Method=*/0, LBracLoc, RBracLoc, move(Args)); } @@ -698,7 +701,7 @@ Sema::OwningExprResult Sema::ActOnSuperMessage(Scope *S, /// \param RBrac The location of the closing square bracket ']'. /// /// \param Args The message arguments. -Sema::OwningExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, +ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, QualType ReceiverType, SourceLocation SuperLoc, Selector Sel, @@ -757,11 +760,8 @@ Sema::OwningExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, unsigned NumArgs = ArgsIn.size(); Expr **Args = reinterpret_cast(ArgsIn.release()); if (CheckMessageArgumentTypes(Args, NumArgs, Sel, Method, true, - LBracLoc, RBracLoc, ReturnType)) { - for (unsigned I = 0; I != NumArgs; ++I) - Args[I]->Destroy(Context); + LBracLoc, RBracLoc, ReturnType)) return ExprError(); - } // Construct the appropriate ObjCMessageExpr. Expr *Result; @@ -780,8 +780,8 @@ Sema::OwningExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, // ActOnClassMessage - used for both unary and keyword messages. // ArgExprs is optional - if it is present, the number of expressions // is obtained from Sel.getNumArgs(). -Sema::OwningExprResult Sema::ActOnClassMessage(Scope *S, - TypeTy *Receiver, +ExprResult Sema::ActOnClassMessage(Scope *S, + ParsedType Receiver, Selector Sel, SourceLocation LBracLoc, SourceLocation SelectorLoc, @@ -829,7 +829,7 @@ Sema::OwningExprResult Sema::ActOnClassMessage(Scope *S, /// \param RBrac The location of the closing square bracket ']'. /// /// \param Args The message arguments. -Sema::OwningExprResult Sema::BuildInstanceMessage(ExprArg ReceiverE, +ExprResult Sema::BuildInstanceMessage(Expr *Receiver, QualType ReceiverType, SourceLocation SuperLoc, Selector Sel, @@ -839,7 +839,6 @@ Sema::OwningExprResult Sema::BuildInstanceMessage(ExprArg ReceiverE, MultiExprArg ArgsIn) { // If we have a receiver expression, perform appropriate promotions // and determine receiver type. - Expr *Receiver = ReceiverE.takeAs(); if (Receiver) { if (Receiver->isTypeDependent()) { // If the receiver is type-dependent, we can't type-check anything @@ -864,13 +863,16 @@ Sema::OwningExprResult Sema::BuildInstanceMessage(ExprArg ReceiverE, if (!Method) { // Handle messages to id. - if (ReceiverType->isObjCIdType() || ReceiverType->isBlockPointerType() || + bool receiverIsId = ReceiverType->isObjCIdType(); + if (receiverIsId || ReceiverType->isBlockPointerType() || (Receiver && Context.isObjCNSObjectType(Receiver->getType()))) { Method = LookupInstanceMethodInGlobalPool(Sel, - SourceRange(LBracLoc, RBracLoc)); + SourceRange(LBracLoc, RBracLoc), + receiverIsId); if (!Method) Method = LookupFactoryMethodInGlobalPool(Sel, - SourceRange(LBracLoc, RBracLoc)); + SourceRange(LBracLoc, RBracLoc), + receiverIsId); } else if (ReceiverType->isObjCClassType() || ReceiverType->isObjCQualifiedClassType()) { // Handle messages to Class. @@ -892,12 +894,14 @@ Sema::OwningExprResult Sema::BuildInstanceMessage(ExprArg ReceiverE, // If not messaging 'self', look for any factory method named 'Sel'. if (!Receiver || !isSelfExpr(Receiver)) { Method = LookupFactoryMethodInGlobalPool(Sel, - SourceRange(LBracLoc, RBracLoc)); + SourceRange(LBracLoc, RBracLoc), + true); if (!Method) { // If no class (factory) method was found, check if an _instance_ // method of the same name exists in the root class only. Method = LookupInstanceMethodInGlobalPool(Sel, - SourceRange(LBracLoc, RBracLoc)); + SourceRange(LBracLoc, RBracLoc), + true); if (Method) if (const ObjCInterfaceDecl *ID = dyn_cast(Method->getDeclContext())) { @@ -931,7 +935,7 @@ Sema::OwningExprResult Sema::BuildInstanceMessage(ExprArg ReceiverE, ClassDecl = OCIType->getInterfaceDecl(); // FIXME: consider using LookupInstanceMethodInGlobalPool, since it will be // faster than the following method (which can do *many* linear searches). - // The idea is to add class info to InstanceMethodPool. + // The idea is to add class info to MethodPool. Method = ClassDecl->lookupInstanceMethod(Sel); if (!Method) { @@ -952,7 +956,7 @@ Sema::OwningExprResult Sema::BuildInstanceMessage(ExprArg ReceiverE, // compatibility. FIXME: should we deviate?? if (OCIType->qual_empty()) { Method = LookupInstanceMethodInGlobalPool(Sel, - SourceRange(LBracLoc, RBracLoc)); + SourceRange(LBracLoc, RBracLoc)); if (Method && !OCIType->getInterfaceDecl()->isForwardDecl()) Diag(Loc, diag::warn_maynot_respond) << OCIType->getInterfaceDecl()->getIdentifier() << Sel; @@ -962,19 +966,18 @@ Sema::OwningExprResult Sema::BuildInstanceMessage(ExprArg ReceiverE, if (Method && DiagnoseUseOfDecl(Method, Loc)) return ExprError(); } else if (!Context.getObjCIdType().isNull() && - (ReceiverType->isPointerType() || - (ReceiverType->isIntegerType() && - ReceiverType->isScalarType()))) { + (ReceiverType->isPointerType() || + ReceiverType->isIntegerType())) { // Implicitly convert integers and pointers to 'id' but emit a warning. Diag(Loc, diag::warn_bad_receiver_type) << ReceiverType << Receiver->getSourceRange(); if (ReceiverType->isPointerType()) ImpCastExprToType(Receiver, Context.getObjCIdType(), - CastExpr::CK_BitCast); + CK_BitCast); else ImpCastExprToType(Receiver, Context.getObjCIdType(), - CastExpr::CK_IntegralToPointer); + CK_IntegralToPointer); ReceiverType = Receiver->getType(); } else if (getLangOptions().CPlusPlus && @@ -983,7 +986,7 @@ Sema::OwningExprResult Sema::BuildInstanceMessage(ExprArg ReceiverE, Receiver = ICE->getSubExpr(); ReceiverType = Receiver->getType(); } - return BuildInstanceMessage(Owned(Receiver), + return BuildInstanceMessage(Receiver, ReceiverType, SuperLoc, Sel, @@ -1030,18 +1033,17 @@ Sema::OwningExprResult Sema::BuildInstanceMessage(ExprArg ReceiverE, // ActOnInstanceMessage - used for both unary and keyword messages. // ArgExprs is optional - if it is present, the number of expressions // is obtained from Sel.getNumArgs(). -Sema::OwningExprResult Sema::ActOnInstanceMessage(Scope *S, - ExprArg ReceiverE, - Selector Sel, - SourceLocation LBracLoc, - SourceLocation SelectorLoc, - SourceLocation RBracLoc, - MultiExprArg Args) { - Expr *Receiver = static_cast(ReceiverE.get()); +ExprResult Sema::ActOnInstanceMessage(Scope *S, + Expr *Receiver, + Selector Sel, + SourceLocation LBracLoc, + SourceLocation SelectorLoc, + SourceLocation RBracLoc, + MultiExprArg Args) { if (!Receiver) return ExprError(); - return BuildInstanceMessage(move(ReceiverE), Receiver->getType(), + return BuildInstanceMessage(Receiver, Receiver->getType(), /*SuperLoc=*/SourceLocation(), Sel, /*Method=*/0, LBracLoc, RBracLoc, move(Args)); } diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 7ad177557ef4..a28fd7fe12bd 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -15,12 +15,13 @@ // //===----------------------------------------------------------------------===// -#include "SemaInit.h" -#include "Lookup.h" -#include "Sema.h" +#include "clang/Sema/Designator.h" +#include "clang/Sema/Initialization.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/SemaInternal.h" #include "clang/Lex/Preprocessor.h" -#include "clang/Parse/Designator.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/DeclObjC.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/TypeLoc.h" @@ -263,9 +264,8 @@ void InitListChecker::FillInValueInitForField(unsigned Init, FieldDecl *Field, return; } - Sema::OwningExprResult MemberInit - = InitSeq.Perform(SemaRef, MemberEntity, Kind, - Sema::MultiExprArg(SemaRef, 0, 0)); + ExprResult MemberInit + = InitSeq.Perform(SemaRef, MemberEntity, Kind, MultiExprArg()); if (MemberInit.isInvalid()) { hadError = true; return; @@ -373,9 +373,8 @@ InitListChecker::FillInValueInitializations(const InitializedEntity &Entity, return; } - Sema::OwningExprResult ElementInit - = InitSeq.Perform(SemaRef, ElementEntity, Kind, - Sema::MultiExprArg(SemaRef, 0, 0)); + ExprResult ElementInit + = InitSeq.Perform(SemaRef, ElementEntity, Kind, MultiExprArg()); if (ElementInit.isInvalid()) { hadError = true; return; @@ -678,9 +677,8 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity, InitializationSequence Seq(SemaRef, Entity, Kind, &expr, 1); if (Seq) { - Sema::OwningExprResult Result = - Seq.Perform(SemaRef, Entity, Kind, - Sema::MultiExprArg(SemaRef, (void **)&expr, 1)); + ExprResult Result = + Seq.Perform(SemaRef, Entity, Kind, MultiExprArg(&expr, 1)); if (Result.isInvalid()) hadError = true; @@ -740,13 +738,13 @@ void InitListChecker::CheckScalarType(const InitializedEntity &Entity, unsigned &StructuredIndex) { if (Index < IList->getNumInits()) { Expr *expr = IList->getInit(Index); - if (isa(expr)) { - SemaRef.Diag(IList->getLocStart(), - diag::err_many_braces_around_scalar_init) - << IList->getSourceRange(); - hadError = true; - ++Index; - ++StructuredIndex; + if (InitListExpr *SubIList = dyn_cast(expr)) { + SemaRef.Diag(SubIList->getLocStart(), + diag::warn_many_braces_around_scalar_init) + << SubIList->getSourceRange(); + + CheckScalarType(Entity, SubIList, DeclType, Index, StructuredList, + StructuredIndex); return; } else if (isa(expr)) { SemaRef.Diag(expr->getSourceRange().getBegin(), @@ -758,7 +756,7 @@ void InitListChecker::CheckScalarType(const InitializedEntity &Entity, return; } - Sema::OwningExprResult Result = + ExprResult Result = SemaRef.PerformCopyInitialization(Entity, expr->getLocStart(), SemaRef.Owned(expr)); @@ -805,7 +803,7 @@ void InitListChecker::CheckReferenceType(const InitializedEntity &Entity, return; } - Sema::OwningExprResult Result = + ExprResult Result = SemaRef.PerformCopyInitialization(Entity, expr->getLocStart(), SemaRef.Owned(expr)); @@ -1367,7 +1365,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, if (SemaRef.CorrectTypo(R, /*Scope=*/0, /*SS=*/0, RT->getDecl(), false, Sema::CTC_NoKeywords) && (ReplacementField = R.getAsSingle()) && - ReplacementField->getDeclContext()->getLookupContext() + ReplacementField->getDeclContext()->getRedeclContext() ->Equals(RT->getDecl())) { SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_unknown_suggest) @@ -1813,10 +1811,10 @@ CheckArrayDesignatorExpr(Sema &S, Expr *Index, llvm::APSInt &Value) { return false; } -Sema::OwningExprResult Sema::ActOnDesignatedInitializer(Designation &Desig, +ExprResult Sema::ActOnDesignatedInitializer(Designation &Desig, SourceLocation Loc, bool GNUSyntax, - OwningExprResult Init) { + ExprResult Init) { typedef DesignatedInitExpr::Designator ASTDesignator; bool Invalid = false; @@ -2021,18 +2019,21 @@ void InitializationSequence::Step::Destroy() { switch (Kind) { case SK_ResolveAddressOfOverloadedFunction: case SK_CastDerivedToBaseRValue: + case SK_CastDerivedToBaseXValue: case SK_CastDerivedToBaseLValue: case SK_BindReference: case SK_BindReferenceToTemporary: case SK_ExtraneousCopyToTemporary: case SK_UserConversion: case SK_QualificationConversionRValue: + case SK_QualificationConversionXValue: case SK_QualificationConversionLValue: case SK_ListInitialization: case SK_ConstructorInitialization: case SK_ZeroInitialization: case SK_CAssignment: case SK_StringInit: + case SK_ObjCObjectConversion: break; case SK_ConversionSequence: @@ -2091,9 +2092,14 @@ void InitializationSequence::AddAddressOverloadResolutionStep( } void InitializationSequence::AddDerivedToBaseCastStep(QualType BaseType, - bool IsLValue) { + ExprValueKind VK) { Step S; - S.Kind = IsLValue? SK_CastDerivedToBaseLValue : SK_CastDerivedToBaseRValue; + switch (VK) { + case VK_RValue: S.Kind = SK_CastDerivedToBaseRValue; break; + case VK_XValue: S.Kind = SK_CastDerivedToBaseXValue; break; + case VK_LValue: S.Kind = SK_CastDerivedToBaseLValue; break; + default: llvm_unreachable("No such category"); + } S.Type = BaseType; Steps.push_back(S); } @@ -2125,10 +2131,20 @@ void InitializationSequence::AddUserConversionStep(FunctionDecl *Function, } void InitializationSequence::AddQualificationConversionStep(QualType Ty, - bool IsLValue) { + ExprValueKind VK) { Step S; - S.Kind = IsLValue? SK_QualificationConversionLValue - : SK_QualificationConversionRValue; + S.Kind = SK_QualificationConversionRValue; // work around a gcc warning + switch (VK) { + case VK_RValue: + S.Kind = SK_QualificationConversionRValue; + break; + case VK_XValue: + S.Kind = SK_QualificationConversionXValue; + break; + case VK_LValue: + S.Kind = SK_QualificationConversionLValue; + break; + } S.Type = Ty; Steps.push_back(S); } @@ -2184,6 +2200,13 @@ void InitializationSequence::AddStringInitStep(QualType T) { Steps.push_back(S); } +void InitializationSequence::AddObjCObjectConversionStep(QualType T) { + Step S; + S.Kind = SK_ObjCObjectConversion; + S.Type = T; + Steps.push_back(S); +} + void InitializationSequence::SetOverloadFailure(FailureKind Failure, OverloadingResult Result) { SequenceKind = FailedSequence; @@ -2258,10 +2281,13 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, QualType T2 = cv2T2.getUnqualifiedType(); bool DerivedToBase; + bool ObjCConversion; assert(!S.CompareReferenceRelationship(Initializer->getLocStart(), - T1, T2, DerivedToBase) && + T1, T2, DerivedToBase, + ObjCConversion) && "Must have incompatible references when binding via conversion"); (void)DerivedToBase; + (void)ObjCConversion; // Build the candidate set directly in the initialization sequence // structure, so that it will persist if we fail. @@ -2278,6 +2304,7 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, // The type we're converting to is a class type. Enumerate its constructors // to see if there is a suitable conversion. CXXRecordDecl *T1RecordDecl = cast(T1RecordType->getDecl()); + DeclContext::lookup_iterator Con, ConEnd; for (llvm::tie(Con, ConEnd) = S.LookupConstructors(T1RecordDecl); Con != ConEnd; ++Con) { @@ -2305,6 +2332,8 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, } } } + if (T1RecordType && T1RecordType->getDecl()->isInvalidDecl()) + return OR_No_Viable_Function; const RecordType *T2RecordType = 0; if ((T2RecordType = T2->getAs()) && @@ -2352,13 +2381,15 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, } } } + if (T2RecordType && T2RecordType->getDecl()->isInvalidDecl()) + return OR_No_Viable_Function; SourceLocation DeclLoc = Initializer->getLocStart(); // Perform overload resolution. If it fails, return the failed result. OverloadCandidateSet::iterator Best; if (OverloadingResult Result - = S.BestViableFunction(CandidateSet, DeclLoc, Best)) + = CandidateSet.BestViableFunction(S, DeclLoc, Best)) return Result; FunctionDecl *Function = Best->Function; @@ -2375,11 +2406,18 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, // Determine whether we need to perform derived-to-base or // cv-qualification adjustments. + ExprValueKind VK = VK_RValue; + if (T2->isLValueReferenceType()) + VK = VK_LValue; + else if (const RValueReferenceType *RRef = T2->getAs()) + VK = RRef->getPointeeType()->isFunctionType() ? VK_LValue : VK_XValue; + bool NewDerivedToBase = false; + bool NewObjCConversion = false; Sema::ReferenceCompareResult NewRefRelationship = S.CompareReferenceRelationship(DeclLoc, T1, T2.getNonLValueExprType(S.Context), - NewDerivedToBase); + NewDerivedToBase, NewObjCConversion); if (NewRefRelationship == Sema::Ref_Incompatible) { // If the type we've converted to is not reference-related to the // type we're looking for, then there is another conversion step @@ -2394,10 +2432,14 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, Sequence.AddDerivedToBaseCastStep( S.Context.getQualifiedType(T1, T2.getNonReferenceType().getQualifiers()), - /*isLValue=*/true); - + VK); + else if (NewObjCConversion) + Sequence.AddObjCObjectConversionStep( + S.Context.getQualifiedType(T1, + T2.getNonReferenceType().getQualifiers())); + if (cv1T1.getQualifiers() != T2.getNonReferenceType().getQualifiers()) - Sequence.AddQualificationConversionStep(cv1T1, T2->isReferenceType()); + Sequence.AddQualificationConversionStep(cv1T1, VK); Sequence.AddReferenceBindingStep(cv1T1, !T2->isReferenceType()); return OR_Success; @@ -2443,9 +2485,11 @@ static void TryReferenceInitialization(Sema &S, bool isLValueRef = DestType->isLValueReferenceType(); bool isRValueRef = !isLValueRef; bool DerivedToBase = false; + bool ObjCConversion = false; Expr::Classification InitCategory = Initializer->Classify(S.Context); Sema::ReferenceCompareResult RefRelationship - = S.CompareReferenceRelationship(DeclLoc, cv1T1, cv2T2, DerivedToBase); + = S.CompareReferenceRelationship(DeclLoc, cv1T1, cv2T2, DerivedToBase, + ObjCConversion); // C++0x [dcl.init.ref]p5: // A reference to type "cv1 T1" is initialized by an expression of type @@ -2472,9 +2516,13 @@ static void TryReferenceInitialization(Sema &S, if (DerivedToBase) Sequence.AddDerivedToBaseCastStep( S.Context.getQualifiedType(T1, T2Quals), - /*isLValue=*/true); + VK_LValue); + else if (ObjCConversion) + Sequence.AddObjCObjectConversionStep( + S.Context.getQualifiedType(T1, T2Quals)); + if (T1Quals != T2Quals) - Sequence.AddQualificationConversionStep(cv1T1, /*IsLValue=*/true); + Sequence.AddQualificationConversionStep(cv1T1, VK_LValue); bool BindingTemporary = T1Quals.hasConst() && !T1Quals.hasVolatile() && (Initializer->getBitField() || Initializer->refersToVectorElement()); Sequence.AddReferenceBindingStep(cv1T1, BindingTemporary); @@ -2531,6 +2579,7 @@ static void TryReferenceInitialization(Sema &S, // - [If T1 is not a function type], if T2 is a class type and if (!T1Function && T2->isRecordType()) { + bool isXValue = InitCategory.isXValue(); // - the initializer expression is an rvalue and "cv1 T1" is // reference-compatible with "cv2 T2", or if (InitCategory.isRValue() && @@ -2550,10 +2599,15 @@ static void TryReferenceInitialization(Sema &S, if (DerivedToBase) Sequence.AddDerivedToBaseCastStep( S.Context.getQualifiedType(T1, T2Quals), - /*isLValue=*/false); + isXValue ? VK_XValue : VK_RValue); + else if (ObjCConversion) + Sequence.AddObjCObjectConversionStep( + S.Context.getQualifiedType(T1, T2Quals)); + if (T1Quals != T2Quals) - Sequence.AddQualificationConversionStep(cv1T1, /*IsLValue=*/false); - Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/true); + Sequence.AddQualificationConversionStep(cv1T1, + isXValue ? VK_XValue : VK_RValue); + Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/!isXValue); return; } @@ -2717,7 +2771,7 @@ static void TryConstructorInitialization(Sema &S, // Perform overload resolution. If it fails, return the failed result. OverloadCandidateSet::iterator Best; if (OverloadingResult Result - = S.BestViableFunction(CandidateSet, DeclLoc, Best)) { + = CandidateSet.BestViableFunction(S, DeclLoc, Best)) { Sequence.SetOverloadFailure( InitializationSequence::FK_ConstructorOverloadFailed, Result); @@ -2803,8 +2857,8 @@ static void TryDefaultInitialization(Sema &S, // constructor for T is called (and the initialization is ill-formed if // T has no accessible default constructor); if (DestType->isRecordType() && S.getLangOptions().CPlusPlus) { - return TryConstructorInitialization(S, Entity, Kind, 0, 0, DestType, - Sequence); + TryConstructorInitialization(S, Entity, Kind, 0, 0, DestType, Sequence); + return; } // - otherwise, no initialization is performed. @@ -2927,7 +2981,7 @@ static void TryUserDefinedConversion(Sema &S, // Perform overload resolution. If it fails, return the failed result. OverloadCandidateSet::iterator Best; if (OverloadingResult Result - = S.BestViableFunction(CandidateSet, DeclLoc, Best)) { + = CandidateSet.BestViableFunction(S, DeclLoc, Best)) { Sequence.SetOverloadFailure( InitializationSequence::FK_UserConversionOverloadFailed, Result); @@ -2969,24 +3023,6 @@ static void TryUserDefinedConversion(Sema &S, } } -bool Sema::TryImplicitConversion(InitializationSequence &Sequence, - const InitializedEntity &Entity, - Expr *Initializer, - bool SuppressUserConversions, - bool AllowExplicitConversions, - bool InOverloadResolution) { - ImplicitConversionSequence ICS - = TryImplicitConversion(Initializer, Entity.getType(), - SuppressUserConversions, - AllowExplicitConversions, - InOverloadResolution); - if (ICS.isBad()) return true; - - // Perform the actual conversion. - Sequence.AddConversionSequenceStep(ICS, Entity.getType()); - return false; -} - InitializationSequence::InitializationSequence(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, @@ -3239,10 +3275,10 @@ static bool shouldDestroyTemporary(const InitializedEntity &Entity) { /// \returns An expression that copies the initializer expression into /// a temporary object, or an error expression if a copy could not be /// created. -static Sema::OwningExprResult CopyObject(Sema &S, +static ExprResult CopyObject(Sema &S, QualType T, const InitializedEntity &Entity, - Sema::OwningExprResult CurInit, + ExprResult CurInit, bool IsExtraneousCopy) { // Determine which class type we're copying to. Expr *CurInitExpr = (Expr *)CurInit.get(); @@ -3318,7 +3354,7 @@ static Sema::OwningExprResult CopyObject(Sema &S, } OverloadCandidateSet::iterator Best; - switch (S.BestViableFunction(CandidateSet, Loc, Best)) { + switch (CandidateSet.BestViableFunction(S, Loc, Best)) { case OR_Success: break; @@ -3328,19 +3364,17 @@ static Sema::OwningExprResult CopyObject(Sema &S, : diag::err_temp_copy_no_viable) << (int)Entity.getKind() << CurInitExpr->getType() << CurInitExpr->getSourceRange(); - S.PrintOverloadCandidates(CandidateSet, Sema::OCD_AllCandidates, - &CurInitExpr, 1); + CandidateSet.NoteCandidates(S, OCD_AllCandidates, &CurInitExpr, 1); if (!IsExtraneousCopy || S.isSFINAEContext()) - return S.ExprError(); + return ExprError(); return move(CurInit); case OR_Ambiguous: S.Diag(Loc, diag::err_temp_copy_ambiguous) << (int)Entity.getKind() << CurInitExpr->getType() << CurInitExpr->getSourceRange(); - S.PrintOverloadCandidates(CandidateSet, Sema::OCD_ViableCandidates, - &CurInitExpr, 1); - return S.ExprError(); + CandidateSet.NoteCandidates(S, OCD_ViableCandidates, &CurInitExpr, 1); + return ExprError(); case OR_Deleted: S.Diag(Loc, diag::err_temp_copy_deleted) @@ -3348,11 +3382,11 @@ static Sema::OwningExprResult CopyObject(Sema &S, << CurInitExpr->getSourceRange(); S.Diag(Best->Function->getLocation(), diag::note_unavailable_here) << Best->Function->isDeleted(); - return S.ExprError(); + return ExprError(); } CXXConstructorDecl *Constructor = cast(Best->Function); - ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(S); + ASTOwningVector ConstructorArgs(S); CurInit.release(); // Ownership transferred into MultiExprArg, below. S.CheckConstructorAccess(Loc, Constructor, Entity, @@ -3387,16 +3421,15 @@ static Sema::OwningExprResult CopyObject(Sema &S, // Determine the arguments required to actually perform the // constructor call (we might have derived-to-base conversions, or // the copy constructor may have default arguments). - if (S.CompleteConstructorCall(Constructor, - Sema::MultiExprArg(S, - (void **)&CurInitExpr, - 1), + if (S.CompleteConstructorCall(Constructor, MultiExprArg(&CurInitExpr, 1), Loc, ConstructorArgs)) - return S.ExprError(); + return ExprError(); // Actually perform the constructor call. CurInit = S.BuildCXXConstructExpr(Loc, T, Constructor, Elidable, - move_arg(ConstructorArgs)); + move_arg(ConstructorArgs), + /*ZeroInit*/ false, + CXXConstructExpr::CK_Complete); // If we're supposed to bind temporaries, do so. if (!CurInit.isInvalid() && shouldBindAsTemporary(Entity)) @@ -3418,16 +3451,16 @@ void InitializationSequence::PrintInitLocationNote(Sema &S, } } -Action::OwningExprResult +ExprResult InitializationSequence::Perform(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, - Action::MultiExprArg Args, + MultiExprArg Args, QualType *ResultType) { if (SequenceKind == FailedSequence) { unsigned NumArgs = Args.size(); Diagnose(S, Entity, Kind, (Expr **)Args.release(), NumArgs); - return S.ExprError(); + return ExprError(); } if (SequenceKind == DependentSequence) { @@ -3471,7 +3504,7 @@ InitializationSequence::Perform(Sema &S, } if (Kind.getKind() == InitializationKind::IK_Copy || Kind.isExplicitCast()) - return Sema::OwningExprResult(S, Args.release()[0]); + return ExprResult(Args.release()[0]); if (Args.size() == 0) return S.Owned((Expr *)0); @@ -3495,7 +3528,7 @@ InitializationSequence::Perform(Sema &S, *ResultType = Entity.getDecl() ? Entity.getDecl()->getType() : Entity.getType(); - Sema::OwningExprResult CurInit = S.Owned((Expr *)0); + ExprResult CurInit = S.Owned((Expr *)0); assert(!Steps.empty() && "Cannot have an empty initialization sequence"); @@ -3505,21 +3538,24 @@ InitializationSequence::Perform(Sema &S, switch (Steps.front().Kind) { case SK_ResolveAddressOfOverloadedFunction: case SK_CastDerivedToBaseRValue: + case SK_CastDerivedToBaseXValue: case SK_CastDerivedToBaseLValue: case SK_BindReference: case SK_BindReferenceToTemporary: case SK_ExtraneousCopyToTemporary: case SK_UserConversion: case SK_QualificationConversionLValue: + case SK_QualificationConversionXValue: case SK_QualificationConversionRValue: case SK_ConversionSequence: case SK_ListInitialization: case SK_CAssignment: case SK_StringInit: + case SK_ObjCObjectConversion: assert(Args.size() == 1); - CurInit = Sema::OwningExprResult(S, ((Expr **)(Args.get()))[0]->Retain()); + CurInit = ExprResult(((Expr **)(Args.get()))[0]->Retain()); if (CurInit.isInvalid()) - return S.ExprError(); + return ExprError(); break; case SK_ConstructorInitialization: @@ -3533,7 +3569,7 @@ InitializationSequence::Perform(Sema &S, for (step_iterator Step = step_begin(), StepEnd = step_end(); Step != StepEnd; ++Step) { if (CurInit.isInvalid()) - return S.ExprError(); + return ExprError(); Expr *CurInitExpr = (Expr *)CurInit.get(); QualType SourceType = CurInitExpr? CurInitExpr->getType() : QualType(); @@ -3550,11 +3586,12 @@ InitializationSequence::Perform(Sema &S, break; case SK_CastDerivedToBaseRValue: + case SK_CastDerivedToBaseXValue: case SK_CastDerivedToBaseLValue: { // We have a derived-to-base cast that produces either an rvalue or an // lvalue. Perform that cast. - CXXBaseSpecifierArray BasePath; + CXXCastPath BasePath; // Casts to inaccessible base classes are allowed with C-style casts. bool IgnoreBaseAccess = Kind.isCStyleOrFunctionalCast(); @@ -3562,7 +3599,7 @@ InitializationSequence::Perform(Sema &S, CurInitExpr->getLocStart(), CurInitExpr->getSourceRange(), &BasePath, IgnoreBaseAccess)) - return S.ExprError(); + return ExprError(); if (S.BasePathInvolvesVirtualBase(BasePath)) { QualType T = SourceType; @@ -3573,11 +3610,17 @@ InitializationSequence::Perform(Sema &S, cast(RecordTy->getDecl())); } - CurInit = S.Owned(new (S.Context) ImplicitCastExpr(Step->Type, - CastExpr::CK_DerivedToBase, - (Expr*)CurInit.release(), - BasePath, - Step->Kind == SK_CastDerivedToBaseLValue)); + ExprValueKind VK = + Step->Kind == SK_CastDerivedToBaseLValue ? + VK_LValue : + (Step->Kind == SK_CastDerivedToBaseXValue ? + VK_XValue : + VK_RValue); + CurInit = S.Owned(ImplicitCastExpr::Create(S.Context, + Step->Type, + CK_DerivedToBase, + CurInit.get(), + &BasePath, VK)); break; } @@ -3589,7 +3632,7 @@ InitializationSequence::Perform(Sema &S, << BitField->getDeclName() << CurInitExpr->getSourceRange(); S.Diag(BitField->getLocation(), diag::note_bitfield_decl); - return S.ExprError(); + return ExprError(); } if (CurInitExpr->refersToVectorElement()) { @@ -3598,14 +3641,14 @@ InitializationSequence::Perform(Sema &S, << Entity.getType().isVolatileQualified() << CurInitExpr->getSourceRange(); PrintInitLocationNote(S, Entity); - return S.ExprError(); + return ExprError(); } // Reference binding does not have any corresponding ASTs. // Check exception specifications if (S.CheckExceptionSpecCompatibility(CurInitExpr, DestType)) - return S.ExprError(); + return ExprError(); break; @@ -3614,7 +3657,7 @@ InitializationSequence::Perform(Sema &S, // Check exception specifications if (S.CheckExceptionSpecCompatibility(CurInitExpr, DestType)) - return S.ExprError(); + return ExprError(); break; @@ -3626,7 +3669,7 @@ InitializationSequence::Perform(Sema &S, case SK_UserConversion: { // We have a user-defined conversion that invokes either a constructor // or a conversion function. - CastExpr::CastKind CastKind = CastExpr::CK_Unknown; + CastKind CastKind = CK_Unknown; bool IsCopy = false; FunctionDecl *Fn = Step->Function.Function; DeclAccessPair FoundFn = Step->Function.FoundDecl; @@ -3634,30 +3677,30 @@ InitializationSequence::Perform(Sema &S, bool IsLvalue = false; if (CXXConstructorDecl *Constructor = dyn_cast(Fn)) { // Build a call to the selected constructor. - ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(S); + ASTOwningVector ConstructorArgs(S); SourceLocation Loc = CurInitExpr->getLocStart(); CurInit.release(); // Ownership transferred into MultiExprArg, below. // Determine the arguments required to actually perform the constructor // call. if (S.CompleteConstructorCall(Constructor, - Sema::MultiExprArg(S, - (void **)&CurInitExpr, - 1), + MultiExprArg(&CurInitExpr, 1), Loc, ConstructorArgs)) - return S.ExprError(); + return ExprError(); // Build the an expression that constructs a temporary. CurInit = S.BuildCXXConstructExpr(Loc, Step->Type, Constructor, - move_arg(ConstructorArgs)); + move_arg(ConstructorArgs), + /*ZeroInit*/ false, + CXXConstructExpr::CK_Complete); if (CurInit.isInvalid()) - return S.ExprError(); + return ExprError(); S.CheckConstructorAccess(Kind.getLocation(), Constructor, Entity, FoundFn.getAccess()); S.DiagnoseUseOfDecl(FoundFn, Kind.getLocation()); - CastKind = CastExpr::CK_ConstructorConversion; + CastKind = CK_ConstructorConversion; QualType Class = S.Context.getTypeDeclType(Constructor->getParent()); if (S.Context.hasSameUnqualifiedType(SourceType, Class) || S.IsDerivedFrom(SourceType, Class)) @@ -3677,7 +3720,7 @@ InitializationSequence::Perform(Sema &S, // we don't want to turn off access control here for c-style casts. if (S.PerformObjectArgumentInitialization(CurInitExpr, /*Qualifier=*/0, FoundFn, Conversion)) - return S.ExprError(); + return ExprError(); // Do a little dance to make sure that CurInit has the proper // pointer. @@ -3687,9 +3730,9 @@ InitializationSequence::Perform(Sema &S, CurInit = S.Owned(S.BuildCXXMemberCallExpr(CurInitExpr, FoundFn, Conversion)); if (CurInit.isInvalid() || !CurInit.get()) - return S.ExprError(); + return ExprError(); - CastKind = CastExpr::CK_UserDefinedConversion; + CastKind = CK_UserDefinedConversion; CreatedObject = Conversion->getResultType()->isRecordType(); } @@ -3711,35 +3754,41 @@ InitializationSequence::Perform(Sema &S, } CurInitExpr = CurInit.takeAs(); - CurInit = S.Owned(new (S.Context) ImplicitCastExpr(CurInitExpr->getType(), - CastKind, - CurInitExpr, - CXXBaseSpecifierArray(), - IsLvalue)); + // FIXME: xvalues + CurInit = S.Owned(ImplicitCastExpr::Create(S.Context, + CurInitExpr->getType(), + CastKind, CurInitExpr, 0, + IsLvalue ? VK_LValue : VK_RValue)); if (RequiresCopy) CurInit = CopyObject(S, Entity.getType().getNonReferenceType(), Entity, move(CurInit), /*IsExtraneousCopy=*/false); - + break; } - + case SK_QualificationConversionLValue: - case SK_QualificationConversionRValue: + case SK_QualificationConversionXValue: + case SK_QualificationConversionRValue: { // Perform a qualification conversion; these can never go wrong. - S.ImpCastExprToType(CurInitExpr, Step->Type, - CastExpr::CK_NoOp, - Step->Kind == SK_QualificationConversionLValue); + ExprValueKind VK = + Step->Kind == SK_QualificationConversionLValue ? + VK_LValue : + (Step->Kind == SK_QualificationConversionXValue ? + VK_XValue : + VK_RValue); + S.ImpCastExprToType(CurInitExpr, Step->Type, CK_NoOp, VK); CurInit.release(); CurInit = S.Owned(CurInitExpr); break; - + } + case SK_ConversionSequence: { bool IgnoreBaseAccess = Kind.isCStyleOrFunctionalCast(); if (S.PerformImplicitConversion(CurInitExpr, Step->Type, *Step->ICS, Sema::AA_Converting, IgnoreBaseAccess)) - return S.ExprError(); + return ExprError(); CurInit.release(); CurInit = S.Owned(CurInitExpr); @@ -3750,7 +3799,7 @@ InitializationSequence::Perform(Sema &S, InitListExpr *InitList = cast(CurInitExpr); QualType Ty = Step->Type; if (S.CheckInitList(Entity, InitList, ResultType? *ResultType : Ty)) - return S.ExprError(); + return ExprError(); CurInit.release(); CurInit = S.Owned(InitList); @@ -3763,16 +3812,29 @@ InitializationSequence::Perform(Sema &S, = cast(Step->Function.Function); // Build a call to the selected constructor. - ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(S); - SourceLocation Loc = Kind.getLocation(); - + ASTOwningVector ConstructorArgs(S); + SourceLocation Loc = (Kind.isCopyInit() && Kind.getEqualLoc().isValid()) + ? Kind.getEqualLoc() + : Kind.getLocation(); + + if (Kind.getKind() == InitializationKind::IK_Default) { + // Force even a trivial, implicit default constructor to be + // semantically checked. We do this explicitly because we don't build + // the definition for completely trivial constructors. + CXXRecordDecl *ClassDecl = Constructor->getParent(); + assert(ClassDecl && "No parent class for constructor."); + if (Constructor->isImplicit() && Constructor->isDefaultConstructor() && + ClassDecl->hasTrivialConstructor() && !Constructor->isUsed(false)) + S.DefineImplicitDefaultConstructor(Loc, Constructor); + } + // Determine the arguments required to actually perform the constructor // call. if (S.CompleteConstructorCall(Constructor, move(Args), Loc, ConstructorArgs)) - return S.ExprError(); + return ExprError(); - // Build the expression that constructs a temporary. + if (Entity.getKind() == InitializedEntity::EK_Temporary && NumArgs != 1 && // FIXME: Hack to work around cast weirdness (Kind.getKind() == InitializationKind::IK_Direct || @@ -3780,11 +3842,11 @@ InitializationSequence::Perform(Sema &S, // An explicitly-constructed temporary, e.g., X(1, 2). unsigned NumExprs = ConstructorArgs.size(); Expr **Exprs = (Expr **)ConstructorArgs.take(); - S.MarkDeclarationReferenced(Kind.getLocation(), Constructor); + S.MarkDeclarationReferenced(Loc, Constructor); CurInit = S.Owned(new (S.Context) CXXTemporaryObjectExpr(S.Context, Constructor, Entity.getType(), - Kind.getLocation(), + Loc, Exprs, NumExprs, Kind.getParenRange().getEnd(), @@ -3815,7 +3877,7 @@ InitializationSequence::Perform(Sema &S, ConstructKind); } if (CurInit.isInvalid()) - return S.ExprError(); + return ExprError(); // Only check access if all of that succeeded. S.CheckConstructorAccess(Loc, Constructor, Entity, @@ -3867,7 +3929,7 @@ InitializationSequence::Perform(Sema &S, getAssignmentAction(Entity), &Complained)) { PrintInitLocationNote(S, Entity); - return S.ExprError(); + return ExprError(); } else if (Complained) PrintInitLocationNote(S, Entity); @@ -3881,6 +3943,14 @@ InitializationSequence::Perform(Sema &S, CheckStringInit(CurInitExpr, ResultType ? *ResultType : Ty, S); break; } + + case SK_ObjCObjectConversion: + S.ImpCastExprToType(CurInitExpr, Step->Type, + CK_ObjCObjectLValueCast, + S.CastCategory(CurInitExpr)); + CurInit.release(); + CurInit = S.Owned(CurInitExpr); + break; } } @@ -3937,16 +4007,14 @@ bool InitializationSequence::Diagnose(Sema &S, << DestType << Args[0]->getType() << Args[0]->getSourceRange(); - S.PrintOverloadCandidates(FailedCandidateSet, Sema::OCD_ViableCandidates, - Args, NumArgs); + FailedCandidateSet.NoteCandidates(S, OCD_ViableCandidates, Args, NumArgs); break; case OR_No_Viable_Function: S.Diag(Kind.getLocation(), diag::err_typecheck_nonviable_condition) << Args[0]->getType() << DestType.getNonReferenceType() << Args[0]->getSourceRange(); - S.PrintOverloadCandidates(FailedCandidateSet, Sema::OCD_AllCandidates, - Args, NumArgs); + FailedCandidateSet.NoteCandidates(S, OCD_AllCandidates, Args, NumArgs); break; case OR_Deleted: { @@ -3954,9 +4022,8 @@ bool InitializationSequence::Diagnose(Sema &S, << Args[0]->getType() << DestType.getNonReferenceType() << Args[0]->getSourceRange(); OverloadCandidateSet::iterator Best; - OverloadingResult Ovl = S.BestViableFunction(FailedCandidateSet, - Kind.getLocation(), - Best); + OverloadingResult Ovl + = FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best); if (Ovl == OR_Deleted) { S.Diag(Best->Function->getLocation(), diag::note_unavailable_here) << Best->Function->isDeleted(); @@ -4049,8 +4116,8 @@ bool InitializationSequence::Diagnose(Sema &S, case OR_Ambiguous: S.Diag(Kind.getLocation(), diag::err_ovl_ambiguous_init) << DestType << ArgsRange; - S.PrintOverloadCandidates(FailedCandidateSet, - Sema::OCD_ViableCandidates, Args, NumArgs); + FailedCandidateSet.NoteCandidates(S, OCD_ViableCandidates, + Args, NumArgs); break; case OR_No_Viable_Function: @@ -4095,17 +4162,15 @@ bool InitializationSequence::Diagnose(Sema &S, S.Diag(Kind.getLocation(), diag::err_ovl_no_viable_function_in_init) << DestType << ArgsRange; - S.PrintOverloadCandidates(FailedCandidateSet, Sema::OCD_AllCandidates, - Args, NumArgs); + FailedCandidateSet.NoteCandidates(S, OCD_AllCandidates, Args, NumArgs); break; case OR_Deleted: { S.Diag(Kind.getLocation(), diag::err_ovl_deleted_init) << true << DestType << ArgsRange; OverloadCandidateSet::iterator Best; - OverloadingResult Ovl = S.BestViableFunction(FailedCandidateSet, - Kind.getLocation(), - Best); + OverloadingResult Ovl + = FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best); if (Ovl == OR_Deleted) { S.Diag(Best->Function->getLocation(), diag::note_unavailable_here) << Best->Function->isDeleted(); @@ -4288,6 +4353,10 @@ void InitializationSequence::dump(llvm::raw_ostream &OS) const { OS << "derived-to-base case (rvalue" << S->Type.getAsString() << ")"; break; + case SK_CastDerivedToBaseXValue: + OS << "derived-to-base case (xvalue" << S->Type.getAsString() << ")"; + break; + case SK_CastDerivedToBaseLValue: OS << "derived-to-base case (lvalue" << S->Type.getAsString() << ")"; break; @@ -4307,10 +4376,13 @@ void InitializationSequence::dump(llvm::raw_ostream &OS) const { case SK_UserConversion: OS << "user-defined conversion via " << S->Function.Function; break; - + case SK_QualificationConversionRValue: OS << "qualification conversion (rvalue)"; + case SK_QualificationConversionXValue: + OS << "qualification conversion (xvalue)"; + case SK_QualificationConversionLValue: OS << "qualification conversion (lvalue)"; break; @@ -4340,6 +4412,10 @@ void InitializationSequence::dump(llvm::raw_ostream &OS) const { case SK_StringInit: OS << "string initialization"; break; + + case SK_ObjCObjectConversion: + OS << "Objective-C object conversion"; + break; } } } @@ -4351,10 +4427,10 @@ void InitializationSequence::dump() const { //===----------------------------------------------------------------------===// // Initialization helper functions //===----------------------------------------------------------------------===// -Sema::OwningExprResult +ExprResult Sema::PerformCopyInitialization(const InitializedEntity &Entity, SourceLocation EqualLoc, - OwningExprResult Init) { + ExprResult Init) { if (Init.isInvalid()) return ExprError(); @@ -4368,6 +4444,5 @@ Sema::PerformCopyInitialization(const InitializedEntity &Entity, EqualLoc); InitializationSequence Seq(*this, Entity, Kind, &InitE, 1); Init.release(); - return Seq.Perform(*this, Entity, Kind, - MultiExprArg(*this, (void**)&InitE, 1)); + return Seq.Perform(*this, Entity, Kind, MultiExprArg(&InitE, 1)); } diff --git a/lib/Sema/SemaInit.h b/lib/Sema/SemaInit.h deleted file mode 100644 index 44c36a735bc8..000000000000 --- a/lib/Sema/SemaInit.h +++ /dev/null @@ -1,765 +0,0 @@ -//===--- 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_INIT_H -#define LLVM_CLANG_SEMA_INIT_H - -#include "SemaOverload.h" -#include "clang/AST/Type.h" -#include "clang/AST/UnresolvedSet.h" -#include "clang/Parse/Action.h" -#include "clang/Basic/SourceLocation.h" -#include "llvm/ADT/PointerIntPair.h" -#include "llvm/ADT/SmallVector.h" -#include - -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(Var)) { } - - /// \brief Create the initialization entity for a parameter. - InitializedEntity(ParmVarDecl *Parm) - : Kind(EK_Parameter), Parent(0), Type(Parm->getType().getUnqualifiedType()), - VariableOrMember(reinterpret_cast(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(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(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]; - } - - /// \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 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 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 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 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. - Action::OwningExprResult Perform(Sema &S, - const InitializedEntity &Entity, - const InitializationKind &Kind, - Action::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::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, bool IsLValue); - - /// \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, bool IsLValue); - - /// \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 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_INIT_H diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 2e651838df95..306e95a497e8 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -11,8 +11,13 @@ // Objective-C++. // //===----------------------------------------------------------------------===// -#include "Sema.h" -#include "Lookup.h" +#include "clang/Sema/Sema.h" +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/DeclSpec.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/TemplateDeduction.h" #include "clang/AST/ASTContext.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/Decl.h" @@ -21,9 +26,9 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" -#include "clang/Parse/DeclSpec.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/LangOptions.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/ErrorHandling.h" @@ -35,6 +40,7 @@ #include using namespace clang; +using namespace sema; namespace { class UnqualUsingEntry { @@ -100,7 +106,7 @@ namespace { End = S->using_directives_end(); for (; I != End; ++I) - visit(I->getAs(), InnermostFileDC); + visit(*I, InnermostFileDC); } } } @@ -254,6 +260,12 @@ static inline unsigned getIDNS(Sema::LookupNameKind NameKind, case Sema::LookupObjCProtocolName: IDNS = Decl::IDNS_ObjCProtocol; break; + + case Sema::LookupAnyName: + IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Member + | Decl::IDNS_Using | Decl::IDNS_Namespace | Decl::IDNS_ObjCProtocol + | Decl::IDNS_Type; + break; } return IDNS; } @@ -267,7 +279,7 @@ void LookupResult::configure() { // operators, make sure that the implicitly-declared new and delete // operators can be found. if (!isForRedeclaration()) { - switch (Name.getCXXOverloadedOperator()) { + switch (NameInfo.getName().getCXXOverloadedOperator()) { case OO_New: case OO_Delete: case OO_Array_New: @@ -281,6 +293,22 @@ void LookupResult::configure() { } } +#ifndef NDEBUG +void LookupResult::sanity() const { + assert(ResultKind != NotFound || Decls.size() == 0); + assert(ResultKind != Found || Decls.size() == 1); + assert(ResultKind != FoundOverloaded || Decls.size() > 1 || + (Decls.size() == 1 && + isa((*begin())->getUnderlyingDecl()))); + assert(ResultKind != FoundUnresolvedValue || sanityCheckUnresolved()); + assert(ResultKind != Ambiguous || Decls.size() > 1 || + (Decls.size() == 1 && Ambiguity == AmbiguousBaseSubobjects)); + assert((Paths != NULL) == (ResultKind == Ambiguous && + (Ambiguity == AmbiguousBaseSubobjectTypes || + Ambiguity == AmbiguousBaseSubobjects))); +} +#endif + // Necessary because CXXBasePaths is not complete in Sema.h void LookupResult::deletePaths(CXXBasePaths *Paths) { delete Paths; @@ -311,7 +339,8 @@ void LookupResult::resolveKind() { if (ResultKind == Ambiguous) return; llvm::SmallPtrSet Unique; - + llvm::SmallPtrSet UniqueTypes; + bool Ambiguous = false; bool HasTag = false, HasFunction = false, HasNonFunction = false; bool HasFunctionTemplate = false, HasUnresolved = false; @@ -323,32 +352,49 @@ void LookupResult::resolveKind() { NamedDecl *D = Decls[I]->getUnderlyingDecl(); D = cast(D->getCanonicalDecl()); + // Redeclarations of types via typedef can occur both within a scope + // and, through using declarations and directives, across scopes. There is + // no ambiguity if they all refer to the same type, so unique based on the + // canonical type. + if (TypeDecl *TD = dyn_cast(D)) { + if (!TD->getDeclContext()->isRecord()) { + QualType T = SemaRef.Context.getTypeDeclType(TD); + if (!UniqueTypes.insert(SemaRef.Context.getCanonicalType(T))) { + // The type is not unique; pull something off the back and continue + // at this index. + Decls[I] = Decls[--N]; + continue; + } + } + } + if (!Unique.insert(D)) { // If it's not unique, pull something off the back (and // continue at this index). Decls[I] = Decls[--N]; + continue; + } + + // Otherwise, do some decl type analysis and then continue. + + if (isa(D)) { + HasUnresolved = true; + } else if (isa(D)) { + if (HasTag) + Ambiguous = true; + UniqueTagIndex = I; + HasTag = true; + } else if (isa(D)) { + HasFunction = true; + HasFunctionTemplate = true; + } else if (isa(D)) { + HasFunction = true; } else { - // Otherwise, do some decl type analysis and then continue. - - if (isa(D)) { - HasUnresolved = true; - } else if (isa(D)) { - if (HasTag) - Ambiguous = true; - UniqueTagIndex = I; - HasTag = true; - } else if (isa(D)) { - HasFunction = true; - HasFunctionTemplate = true; - } else if (isa(D)) { - HasFunction = true; - } else { - if (HasNonFunction) - Ambiguous = true; - HasNonFunction = true; - } - I++; + if (HasNonFunction) + Ambiguous = true; + HasNonFunction = true; } + I++; } // C++ [basic.scope.hiding]p2: @@ -451,6 +497,10 @@ static bool LookupBuiltin(Sema &S, LookupResult &R) { /// the class at this point. static bool CanDeclareSpecialMemberFunction(ASTContext &Context, const CXXRecordDecl *Class) { + // Don't do it if the class is invalid. + if (Class->isInvalidDecl()) + return false; + // We need to have a definition for the class. if (!Class->getDefinition() || Class->isDependentContext()) return false; @@ -608,7 +658,7 @@ static bool LookupDirect(Sema &S, LookupResult &R, const DeclContext *DC) { // result), perform template argument deduction and place the // specialization into the result set. We do this to avoid forcing all // callers to perform special deduction for conversion functions. - Sema::TemplateDeductionInfo Info(R.getSema().Context, R.getNameLoc()); + TemplateDeductionInfo Info(R.getSema().Context, R.getNameLoc()); FunctionDecl *Specialization = 0; const FunctionProtoType *ConvProto @@ -783,7 +833,7 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { // Check whether the IdResolver has anything in this scope. bool Found = false; - for (; I != IEnd && S->isDeclScope(DeclPtrTy::make(*I)); ++I) { + for (; I != IEnd && S->isDeclScope(*I); ++I) { if (R.isAcceptableDecl(*I)) { Found = true; R.addDecl(*I); @@ -881,7 +931,7 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { for (; S; S = S->getParent()) { // Check whether the IdResolver has anything in this scope. bool Found = false; - for (; I != IEnd && S->isDeclScope(DeclPtrTy::make(*I)); ++I) { + for (; I != IEnd && S->isDeclScope(*I); ++I) { if (R.isAcceptableDecl(*I)) { // We found something. Look for anything else in our scope // with this same name and in an acceptable identifier @@ -1017,7 +1067,7 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) { if (NameKind == LookupRedeclarationWithLinkage) { // Determine whether this (or a previous) declaration is // out-of-scope. - if (!LeftStartingScope && !S->isDeclScope(DeclPtrTy::make(*I))) + if (!LeftStartingScope && !S->isDeclScope(*I)) LeftStartingScope = true; // If we found something outside of our starting scope that @@ -1034,14 +1084,14 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) { // Figure out what scope the identifier is in. while (!(S->getFlags() & Scope::DeclScope) || - !S->isDeclScope(DeclPtrTy::make(*I))) + !S->isDeclScope(*I)) S = S->getParent(); // Find the last declaration in this scope (with the same // name, naturally). IdentifierResolver::iterator LastI = I; for (++LastI; LastI != IEnd; ++LastI) { - if (!S->isDeclScope(DeclPtrTy::make(*LastI))) + if (!S->isDeclScope(*LastI)) break; R.addDecl(*LastI); } @@ -1177,6 +1227,17 @@ static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R, return Found; } +/// \brief Callback that looks for any member of a class with the given name. +static bool LookupAnyMember(const CXXBaseSpecifier *Specifier, + CXXBasePath &Path, + void *Name) { + RecordDecl *BaseRecord = Specifier->getType()->getAs()->getDecl(); + + DeclarationName N = DeclarationName::getFromOpaquePtr(Name); + Path.Decls = BaseRecord->lookup(N); + return Path.Decls.first != Path.Decls.second; +} + /// \brief Perform qualified name lookup into a given context. /// /// Qualified name lookup (C++ [basic.lookup.qual]) is used to find @@ -1272,6 +1333,10 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, BaseCallback = &CXXRecordDecl::FindTagMember; break; + case LookupAnyName: + BaseCallback = &LookupAnyMember; + break; + case LookupUsingDeclName: // This lookup is for redeclarations only. @@ -1554,7 +1619,11 @@ static void CollectEnclosingNamespace(Sema::AssociatedNamespaceSet &Namespaces, // We don't use DeclContext::getEnclosingNamespaceContext() as this may // be a locally scoped record. - while (Ctx->isRecord() || Ctx->isTransparentContext()) + // We skip out of inline namespaces. The innermost non-inline namespace + // contains all names of all its nested inline namespaces anyway, so we can + // replace the entire inline namespace tree with its root. + while (Ctx->isRecord() || Ctx->isTransparentContext() || + Ctx->isInlineNamespace()) Ctx = Ctx->getParent(); if (Ctx->isFileContext()) @@ -1894,7 +1963,7 @@ Sema::FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs, // parameter types and return type. Arg = Arg->IgnoreParens(); if (UnaryOperator *unaryOp = dyn_cast(Arg)) - if (unaryOp->getOpcode() == UnaryOperator::AddrOf) + if (unaryOp->getOpcode() == UO_AddrOf) Arg = unaryOp->getSubExpr(); UnresolvedLookupExpr *ULE = dyn_cast(Arg); @@ -2201,6 +2270,10 @@ public: return !VisitedContexts.insert(Ctx); } + bool alreadyVisitedContext(DeclContext *Ctx) { + return VisitedContexts.count(Ctx); + } + /// \brief Determine whether the given declaration is hidden in the /// current scope. /// @@ -2354,9 +2427,9 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result, Visited.add(ND); } - // Visit transparent contexts inside this context. + // Visit transparent contexts and inline namespaces inside this context. if (DeclContext *InnerCtx = dyn_cast(*D)) { - if (InnerCtx->isTransparentContext()) + if (InnerCtx->isTransparentContext() || InnerCtx->isInlineNamespace()) LookupVisibleDecls(InnerCtx, Result, QualifiedNameLookup, InBaseClass, Consumer, Visited); } @@ -2429,8 +2502,9 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result, } // Traverse protocols. - for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(), - E = IFace->protocol_end(); I != E; ++I) { + for (ObjCInterfaceDecl::all_protocol_iterator + I = IFace->all_referenced_protocol_begin(), + E = IFace->all_referenced_protocol_end(); I != E; ++I) { ShadowContextRAII Shadow(Visited); LookupVisibleDecls(*I, Result, QualifiedNameLookup, false, Consumer, Visited); @@ -2481,12 +2555,14 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result, if (!S) return; - if (!S->getEntity() || !S->getParent() || + if (!S->getEntity() || + (!S->getParent() && + !Visited.alreadyVisitedContext((DeclContext *)S->getEntity())) || ((DeclContext *)S->getEntity())->isFunctionOrMethod()) { // Walk through the declarations in this Scope. for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end(); D != DEnd; ++D) { - if (NamedDecl *ND = dyn_cast((Decl *)((*D).get()))) + if (NamedDecl *ND = dyn_cast(*D)) if (Result.isAcceptableDecl(ND)) { Consumer.FoundDecl(ND, Visited.checkHidden(ND), false); Visited.add(ND); @@ -2559,7 +2635,8 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result, } void Sema::LookupVisibleDecls(Scope *S, LookupNameKind Kind, - VisibleDeclConsumer &Consumer) { + VisibleDeclConsumer &Consumer, + bool IncludeGlobalScope) { // Determine the set of using directives available during // unqualified name lookup. Scope *Initial = S; @@ -2576,14 +2653,19 @@ void Sema::LookupVisibleDecls(Scope *S, LookupNameKind Kind, // Look for visible declarations. LookupResult Result(*this, DeclarationName(), SourceLocation(), Kind); VisibleDeclsRecord Visited; + if (!IncludeGlobalScope) + Visited.visitedContext(Context.getTranslationUnitDecl()); ShadowContextRAII Shadow(Visited); ::LookupVisibleDecls(Initial, Result, UDirs, Consumer, Visited); } void Sema::LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind, - VisibleDeclConsumer &Consumer) { + VisibleDeclConsumer &Consumer, + bool IncludeGlobalScope) { LookupResult Result(*this, DeclarationName(), SourceLocation(), Kind); VisibleDeclsRecord Visited; + if (!IncludeGlobalScope) + Visited.visitedContext(Context.getTranslationUnitDecl()); ShadowContextRAII Shadow(Visited); ::LookupVisibleDecls(Ctx, Result, /*QualifiedNameLookup=*/true, /*InBaseClass=*/false, Consumer, Visited); @@ -2911,7 +2993,7 @@ DeclarationName Sema::CorrectTypo(LookupResult &Res, Scope *S, CXXScopeSpec *SS, if (S && S->getContinueParent()) Consumer.addKeywordResult(Context, "continue"); - if (!getSwitchStack().empty()) { + if (!getCurFunction()->SwitchStack.empty()) { Consumer.addKeywordResult(Context, "case"); Consumer.addKeywordResult(Context, "default"); } diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp index ff60599b8510..7181d58f7fb0 100644 --- a/lib/Sema/SemaObjCProperty.cpp +++ b/lib/Sema/SemaObjCProperty.cpp @@ -12,9 +12,11 @@ // //===----------------------------------------------------------------------===// -#include "Sema.h" -#include "SemaInit.h" +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/Initialization.h" +#include "clang/AST/DeclObjC.h" #include "clang/AST/ExprObjC.h" +#include "llvm/ADT/DenseSet.h" using namespace clang; @@ -22,14 +24,14 @@ using namespace clang; // Grammar actions. //===----------------------------------------------------------------------===// -Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, - FieldDeclarator &FD, - ObjCDeclSpec &ODS, - Selector GetterSel, - Selector SetterSel, - DeclPtrTy ClassCategory, - bool *isOverridingProperty, - tok::ObjCKeywordKind MethodImplKind) { +Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, + FieldDeclarator &FD, + ObjCDeclSpec &ODS, + Selector GetterSel, + Selector SetterSel, + Decl *ClassCategory, + bool *isOverridingProperty, + tok::ObjCKeywordKind MethodImplKind) { unsigned Attributes = ODS.getPropertyAttributes(); bool isReadWrite = ((Attributes & ObjCDeclSpec::DQ_PR_readwrite) || // default is readwrite! @@ -45,15 +47,15 @@ Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, QualType T = TSI->getType(); if (T->isReferenceType()) { Diag(AtLoc, diag::error_reference_property); - return DeclPtrTy(); + return 0; } // Proceed with constructing the ObjCPropertDecls. ObjCContainerDecl *ClassDecl = - cast(ClassCategory.getAs()); + cast(ClassCategory); if (ObjCCategoryDecl *CDecl = dyn_cast(ClassDecl)) if (CDecl->IsClassExtension()) { - DeclPtrTy Res = HandlePropertyInClassExtension(S, CDecl, AtLoc, + Decl *Res = HandlePropertyInClassExtension(S, CDecl, AtLoc, FD, GetterSel, SetterSel, isAssign, isReadWrite, Attributes, @@ -64,16 +66,16 @@ Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, return Res; } - DeclPtrTy Res = DeclPtrTy::make(CreatePropertyDecl(S, ClassDecl, AtLoc, FD, - GetterSel, SetterSel, - isAssign, isReadWrite, - Attributes, TSI, MethodImplKind)); + Decl *Res = CreatePropertyDecl(S, ClassDecl, AtLoc, FD, + GetterSel, SetterSel, + isAssign, isReadWrite, + Attributes, TSI, MethodImplKind); // Validate the attributes on the @property. CheckObjCPropertyAttributes(Res, AtLoc, Attributes); return Res; } -Sema::DeclPtrTy +Decl * Sema::HandlePropertyInClassExtension(Scope *S, ObjCCategoryDecl *CDecl, SourceLocation AtLoc, FieldDeclarator &FD, Selector GetterSel, Selector SetterSel, @@ -92,7 +94,7 @@ Sema::HandlePropertyInClassExtension(Scope *S, ObjCCategoryDecl *CDecl, ObjCPropertyDecl::findPropertyDecl(DC, PropertyId)) { Diag(AtLoc, diag::err_duplicate_property); Diag(prevDecl->getLocation(), diag::note_property_declare); - return DeclPtrTy(); + return 0; } // Create a new ObjCPropertyDecl with the DeclContext being @@ -113,7 +115,7 @@ Sema::HandlePropertyInClassExtension(Scope *S, ObjCCategoryDecl *CDecl, if (!CCPrimary) { Diag(CDecl->getLocation(), diag::err_continuation_class); *isOverridingProperty = true; - return DeclPtrTy(); + return 0; } // Find the property in continuation class's primary class only. @@ -136,7 +138,7 @@ Sema::HandlePropertyInClassExtension(Scope *S, ObjCCategoryDecl *CDecl, // is not what it was meant for. However, gcc supports it and so should we. // Make sure setter/getters are declared here. ProcessPropertyDecl(PDecl, CCPrimary); - return DeclPtrTy::make(PDecl); + return PDecl; } @@ -165,13 +167,13 @@ Sema::HandlePropertyInClassExtension(Scope *S, ObjCCategoryDecl *CDecl, setPropertyAttributes((ObjCDeclSpec::ObjCPropertyAttributeKind) PIkind); - DeclPtrTy ProtocolPtrTy = + Decl *ProtocolPtrTy = ActOnProperty(S, AtLoc, FD, ProtocolPropertyODS, PIDecl->getGetterName(), PIDecl->getSetterName(), - DeclPtrTy::make(CCPrimary), isOverridingProperty, + CCPrimary, isOverridingProperty, MethodImplKind); - PIDecl = cast(ProtocolPtrTy.getAs()); + PIDecl = cast(ProtocolPtrTy); } PIDecl->makeitReadWriteAttribute(); if (Attributes & ObjCDeclSpec::DQ_PR_retain) @@ -187,7 +189,7 @@ Sema::HandlePropertyInClassExtension(Scope *S, ObjCCategoryDecl *CDecl, *isOverridingProperty = true; // Make sure setter decl is synthesized, and added to primary class's list. ProcessPropertyDecl(PIDecl, CCPrimary); - return DeclPtrTy(); + return 0; } ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S, @@ -289,19 +291,19 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S, /// builds the AST node for a property implementation declaration; declared /// as @synthesize or @dynamic. /// -Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(Scope *S, - SourceLocation AtLoc, - SourceLocation PropertyLoc, - bool Synthesize, - DeclPtrTy ClassCatImpDecl, - IdentifierInfo *PropertyId, - IdentifierInfo *PropertyIvar) { +Decl *Sema::ActOnPropertyImplDecl(Scope *S, + SourceLocation AtLoc, + SourceLocation PropertyLoc, + bool Synthesize, + Decl *ClassCatImpDecl, + IdentifierInfo *PropertyId, + IdentifierInfo *PropertyIvar) { ObjCContainerDecl *ClassImpDecl = - cast_or_null(ClassCatImpDecl.getAs()); + cast_or_null(ClassCatImpDecl); // Make sure we have a context for the property implementation declaration. if (!ClassImpDecl) { Diag(AtLoc, diag::error_missing_property_context); - return DeclPtrTy(); + return 0; } ObjCPropertyDecl *property = 0; ObjCInterfaceDecl* IDecl = 0; @@ -320,25 +322,25 @@ Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(Scope *S, property = IDecl->FindPropertyDeclaration(PropertyId); if (!property) { Diag(PropertyLoc, diag::error_bad_property_decl) << IDecl->getDeclName(); - return DeclPtrTy(); + return 0; } if (const ObjCCategoryDecl *CD = dyn_cast(property->getDeclContext())) { if (!CD->IsClassExtension()) { Diag(PropertyLoc, diag::error_category_property) << CD->getDeclName(); Diag(property->getLocation(), diag::note_property_declare); - return DeclPtrTy(); + return 0; } } } else if ((CatImplClass = dyn_cast(ClassImpDecl))) { if (Synthesize) { Diag(AtLoc, diag::error_synthesize_category_decl); - return DeclPtrTy(); + return 0; } IDecl = CatImplClass->getClassInterface(); if (!IDecl) { Diag(AtLoc, diag::error_missing_property_interface); - return DeclPtrTy(); + return 0; } ObjCCategoryDecl *Category = IDecl->FindCategoryDeclaration(CatImplClass->getIdentifier()); @@ -346,17 +348,17 @@ Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(Scope *S, // If category for this implementation not found, it is an error which // has already been reported eralier. if (!Category) - return DeclPtrTy(); + return 0; // Look for this property declaration in @implementation's category property = Category->FindPropertyDeclaration(PropertyId); if (!property) { Diag(PropertyLoc, diag::error_bad_category_property_decl) << Category->getDeclName(); - return DeclPtrTy(); + return 0; } } else { Diag(AtLoc, diag::error_bad_property_context); - return DeclPtrTy(); + return 0; } ObjCIvarDecl *Ivar = 0; // Check that we have a valid, previously declared ivar for @synthesize @@ -372,7 +374,7 @@ Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(Scope *S, Ivar = ObjCIvarDecl::Create(Context, ClassImpDecl, PropertyLoc, PropertyIvar, PropType, /*Dinfo=*/0, ObjCIvarDecl::Protected, - (Expr *)0); + (Expr *)0, true); ClassImpDecl->addDecl(Ivar); IDecl->makeDeclVisibleInContext(Ivar, false); property->setPropertyIvarDecl(Ivar); @@ -387,7 +389,7 @@ Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(Scope *S, << property->getDeclName() << Ivar->getDeclName() << ClassDeclared->getDeclName(); Diag(Ivar->getLocation(), diag::note_previous_access_declaration) - << Ivar << Ivar->getNameAsCString(); + << Ivar << Ivar->getName(); // Note! I deliberately want it to fall thru so more errors are caught. } QualType IvarType = Context.getCanonicalType(Ivar->getType()); @@ -464,7 +466,7 @@ Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(Scope *S, Expr *IvarRefExpr = new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), AtLoc, SelfExpr, true, true); - OwningExprResult Res = + ExprResult Res = PerformCopyInitialization(InitializedEntity::InitializeResult( SourceLocation(), getterMethod->getResultType(), @@ -494,8 +496,8 @@ Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(Scope *S, ParmVarDecl *Param = (*P); Expr *rhs = new (Context) DeclRefExpr(Param,Param->getType(), SourceLocation()); - OwningExprResult Res = BuildBinOp(S, SourceLocation(), - BinaryOperator::Assign, lhs, rhs); + ExprResult Res = BuildBinOp(S, SourceLocation(), + BO_Assign, lhs, rhs); PIDecl->setSetterCXXAssignment(Res.takeAs()); } } @@ -514,9 +516,29 @@ Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(Scope *S, = IC->FindPropertyImplDecl(PropertyId)) { Diag(PropertyLoc, diag::error_property_implemented) << PropertyId; Diag(PPIDecl->getLocation(), diag::note_previous_declaration); - return DeclPtrTy(); + return 0; } IC->addPropertyImplementation(PIDecl); + if (getLangOptions().ObjCNonFragileABI2) { + // Diagnose if an ivar was lazily synthesdized due to a previous + // use and if 1) property is @dynamic or 2) property is synthesized + // but it requires an ivar of different name. + ObjCInterfaceDecl *ClassDeclared; + ObjCIvarDecl *Ivar = 0; + if (!Synthesize) + Ivar = IDecl->lookupInstanceVariable(PropertyId, ClassDeclared); + else { + if (PropertyIvar && PropertyIvar != PropertyId) + Ivar = IDecl->lookupInstanceVariable(PropertyId, ClassDeclared); + } + // Issue diagnostics only if Ivar belongs to current class. + if (Ivar && Ivar->getSynthesize() && + IC->getClassInterface() == ClassDeclared) { + Diag(Ivar->getLocation(), diag::err_undeclared_var_use) + << PropertyId; + Ivar->setInvalidDecl(); + } + } } else { if (Synthesize) if (ObjCPropertyImplDecl *PPIDecl = @@ -531,12 +553,12 @@ Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(Scope *S, CatImplClass->FindPropertyImplDecl(PropertyId)) { Diag(PropertyLoc, diag::error_property_implemented) << PropertyId; Diag(PPIDecl->getLocation(), diag::note_previous_declaration); - return DeclPtrTy(); + return 0; } CatImplClass->addPropertyImplementation(PIDecl); } - return DeclPtrTy::make(PIDecl); + return PIDecl; } //===----------------------------------------------------------------------===// @@ -680,9 +702,8 @@ Sema::MatchOneProtocolPropertiesInClass(Decl *CDecl, /// declared in 'ClassOrProtocol' objects (which can be a class or an /// inherited protocol with the list of properties for class/category 'CDecl' /// -void Sema::CompareProperties(Decl *CDecl, - DeclPtrTy ClassOrProtocol) { - Decl *ClassDecl = ClassOrProtocol.getAs(); +void Sema::CompareProperties(Decl *CDecl, Decl *ClassOrProtocol) { + Decl *ClassDecl = ClassOrProtocol; ObjCInterfaceDecl *IDecl = dyn_cast_or_null(CDecl); if (!IDecl) { @@ -699,7 +720,7 @@ void Sema::CompareProperties(Decl *CDecl, // their properties with those in the category. for (ObjCCategoryDecl::protocol_iterator P = CatDecl->protocol_begin(), E = CatDecl->protocol_end(); P != E; ++P) - CompareProperties(CatDecl, DeclPtrTy::make(*P)); + CompareProperties(CatDecl, *P); } else { ObjCProtocolDecl *MD = cast(ClassDecl); for (ObjCProtocolDecl::protocol_iterator P = MD->protocol_begin(), @@ -710,16 +731,18 @@ void Sema::CompareProperties(Decl *CDecl, } if (ObjCInterfaceDecl *MDecl = dyn_cast(ClassDecl)) { - for (ObjCInterfaceDecl::protocol_iterator P = MDecl->protocol_begin(), - E = MDecl->protocol_end(); P != E; ++P) + for (ObjCInterfaceDecl::all_protocol_iterator + P = MDecl->all_referenced_protocol_begin(), + E = MDecl->all_referenced_protocol_end(); P != E; ++P) // Match properties of class IDecl with those of protocol (*P). MatchOneProtocolPropertiesInClass(IDecl, *P); // Go thru the list of protocols for this class and recursively match // their properties with those declared in the class. - for (ObjCInterfaceDecl::protocol_iterator P = IDecl->protocol_begin(), - E = IDecl->protocol_end(); P != E; ++P) - CompareProperties(IDecl, DeclPtrTy::make(*P)); + for (ObjCInterfaceDecl::all_protocol_iterator + P = IDecl->all_referenced_protocol_begin(), + E = IDecl->all_referenced_protocol_end(); P != E; ++P) + CompareProperties(IDecl, *P); } else { ObjCProtocolDecl *MD = cast(ClassDecl); for (ObjCProtocolDecl::protocol_iterator P = MD->protocol_begin(), @@ -791,8 +814,9 @@ void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl, PropMap[Prop->getIdentifier()] = Prop; } // scan through class's protocols. - for (ObjCInterfaceDecl::protocol_iterator PI = IDecl->protocol_begin(), - E = IDecl->protocol_end(); PI != E; ++PI) + for (ObjCInterfaceDecl::all_protocol_iterator + PI = IDecl->all_referenced_protocol_begin(), + E = IDecl->all_referenced_protocol_end(); PI != E; ++PI) CollectImmediateProperties((*PI), PropMap, SuperPropMap); } if (ObjCCategoryDecl *CATDecl = dyn_cast(CDecl)) { @@ -803,7 +827,7 @@ void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl, PropMap[Prop->getIdentifier()] = Prop; } // scan through class's protocols. - for (ObjCInterfaceDecl::protocol_iterator PI = CATDecl->protocol_begin(), + for (ObjCCategoryDecl::protocol_iterator PI = CATDecl->protocol_begin(), E = CATDecl->protocol_end(); PI != E; ++PI) CollectImmediateProperties((*PI), PropMap, SuperPropMap); } @@ -838,8 +862,9 @@ static void CollectClassPropertyImplementations(ObjCContainerDecl *CDecl, ObjCPropertyDecl *Prop = (*P); PropMap[Prop->getIdentifier()] = Prop; } - for (ObjCInterfaceDecl::protocol_iterator PI = IDecl->protocol_begin(), - E = IDecl->protocol_end(); PI != E; ++PI) + for (ObjCInterfaceDecl::all_protocol_iterator + PI = IDecl->all_referenced_protocol_begin(), + E = IDecl->all_referenced_protocol_end(); PI != E; ++PI) CollectClassPropertyImplementations((*PI), PropMap); } else if (ObjCProtocolDecl *PDecl = dyn_cast(CDecl)) { @@ -881,8 +906,9 @@ ObjCPropertyDecl *Sema::LookupPropertyDecl(const ObjCContainerDecl *CDecl, return Prop; } // scan through class's protocols. - for (ObjCInterfaceDecl::protocol_iterator PI = IDecl->protocol_begin(), - E = IDecl->protocol_end(); PI != E; ++PI) { + for (ObjCInterfaceDecl::all_protocol_iterator + PI = IDecl->all_referenced_protocol_begin(), + E = IDecl->all_referenced_protocol_end(); PI != E; ++PI) { ObjCPropertyDecl *Prop = LookupPropertyDecl((*PI), II); if (Prop) return Prop; @@ -933,9 +959,15 @@ void Sema::DefaultSynthesizeProperties (Scope *S, ObjCImplDecl* IMPDecl, // Property may have been synthesized by user. if (IMPDecl->FindPropertyImplDecl(Prop->getIdentifier())) continue; + if (IMPDecl->getInstanceMethod(Prop->getGetterName())) { + if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_readonly) + continue; + if (IMPDecl->getInstanceMethod(Prop->getSetterName())) + continue; + } ActOnPropertyImplDecl(S, IMPDecl->getLocation(), IMPDecl->getLocation(), - true, DeclPtrTy::make(IMPDecl), + true, IMPDecl, Prop->getIdentifier(), Prop->getIdentifier()); } } @@ -1066,7 +1098,8 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property, // for this class. GetterMethod = ObjCMethodDecl::Create(Context, property->getLocation(), property->getLocation(), property->getGetterName(), - property->getType(), 0, CD, true, false, true, + property->getType(), 0, CD, true, false, true, + false, (property->getPropertyImplementation() == ObjCPropertyDecl::Optional) ? ObjCMethodDecl::Optional : @@ -1094,6 +1127,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property, property->getLocation(), property->getSetterName(), Context.VoidTy, 0, CD, true, false, true, + false, (property->getPropertyImplementation() == ObjCPropertyDecl::Optional) ? ObjCMethodDecl::Optional : @@ -1105,8 +1139,8 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property, property->getIdentifier(), property->getType(), /*TInfo=*/0, - VarDecl::None, - VarDecl::None, + SC_None, + SC_None, 0); SetterMethod->setMethodParams(Context, &Argument, 1, 1); CD->addDecl(SetterMethod); @@ -1138,11 +1172,10 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property, AddInstanceMethodToGlobalPool(SetterMethod); } -void Sema::CheckObjCPropertyAttributes(DeclPtrTy PropertyPtrTy, +void Sema::CheckObjCPropertyAttributes(Decl *PDecl, SourceLocation Loc, unsigned &Attributes) { // FIXME: Improve the reported location. - Decl *PDecl = PropertyPtrTy.getAs(); if (!PDecl) return; diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index c4ab9061b445..11b4bb3b92c6 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -11,13 +11,16 @@ // //===----------------------------------------------------------------------===// -#include "Sema.h" -#include "Lookup.h" -#include "SemaInit.h" +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/Initialization.h" +#include "clang/Sema/Template.h" +#include "clang/Sema/TemplateDeduction.h" #include "clang/Basic/Diagnostic.h" #include "clang/Lex/Preprocessor.h" #include "clang/AST/ASTContext.h" #include "clang/AST/CXXInheritance.h" +#include "clang/AST/DeclObjC.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/TypeOrdering.h" @@ -27,6 +30,34 @@ #include namespace clang { +using namespace sema; + +static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, + bool InOverloadResolution, + StandardConversionSequence &SCS); +static OverloadingResult +IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, + UserDefinedConversionSequence& User, + OverloadCandidateSet& Conversions, + bool AllowExplicit); + + +static ImplicitConversionSequence::CompareKind +CompareStandardConversionSequences(Sema &S, + const StandardConversionSequence& SCS1, + const StandardConversionSequence& SCS2); + +static ImplicitConversionSequence::CompareKind +CompareQualificationConversions(Sema &S, + const StandardConversionSequence& SCS1, + const StandardConversionSequence& SCS2); + +static ImplicitConversionSequence::CompareKind +CompareDerivedToBaseConversions(Sema &S, + const StandardConversionSequence& SCS1, + const StandardConversionSequence& SCS2); + + /// GetConversionCategory - Retrieve the implicit conversion /// category corresponding to the given implicit conversion kind. @@ -298,7 +329,7 @@ namespace { OverloadCandidate::DeductionFailureInfo static MakeDeductionFailureInfo(ASTContext &Context, Sema::TemplateDeductionResult TDK, - Sema::TemplateDeductionInfo &Info) { + TemplateDeductionInfo &Info) { OverloadCandidate::DeductionFailureInfo Result; Result.Result = static_cast(TDK); Result.Data = 0; @@ -315,7 +346,7 @@ static MakeDeductionFailureInfo(ASTContext &Context, break; case Sema::TDK_Inconsistent: - case Sema::TDK_InconsistentQuals: { + case Sema::TDK_Underqualified: { // FIXME: Should allocate from normal heap so that we can free this later. DFIParamWithArguments *Saved = new (Context) DFIParamWithArguments; Saved->Param = Info.Param; @@ -348,7 +379,7 @@ void OverloadCandidate::DeductionFailureInfo::Destroy() { break; case Sema::TDK_Inconsistent: - case Sema::TDK_InconsistentQuals: + case Sema::TDK_Underqualified: // FIXME: Destroy the data? Data = 0; break; @@ -380,7 +411,7 @@ OverloadCandidate::DeductionFailureInfo::getTemplateParameter() { return TemplateParameter::getFromOpaqueValue(Data); case Sema::TDK_Inconsistent: - case Sema::TDK_InconsistentQuals: + case Sema::TDK_Underqualified: return static_cast(Data)->Param; // Unhandled @@ -402,7 +433,7 @@ OverloadCandidate::DeductionFailureInfo::getTemplateArgumentList() { case Sema::TDK_Incomplete: case Sema::TDK_InvalidExplicitArguments: case Sema::TDK_Inconsistent: - case Sema::TDK_InconsistentQuals: + case Sema::TDK_Underqualified: return 0; case Sema::TDK_SubstitutionFailure: @@ -429,7 +460,7 @@ const TemplateArgument *OverloadCandidate::DeductionFailureInfo::getFirstArg() { return 0; case Sema::TDK_Inconsistent: - case Sema::TDK_InconsistentQuals: + case Sema::TDK_Underqualified: return &static_cast(Data)->FirstArg; // Unhandled @@ -454,7 +485,7 @@ OverloadCandidate::DeductionFailureInfo::getSecondArg() { return 0; case Sema::TDK_Inconsistent: - case Sema::TDK_InconsistentQuals: + case Sema::TDK_Underqualified: return &static_cast(Data)->SecondArg; // Unhandled @@ -573,6 +604,11 @@ Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old, bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old, bool UseUsingDeclRules) { + // If both of the functions are extern "C", then they are not + // overloads. + if (Old->isExternC() && New->isExternC()) + return false; + FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate(); FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate(); @@ -669,40 +705,34 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old, /// not permitted. /// If @p AllowExplicit, then explicit user-defined conversions are /// permitted. -ImplicitConversionSequence -Sema::TryImplicitConversion(Expr* From, QualType ToType, - bool SuppressUserConversions, - bool AllowExplicit, - bool InOverloadResolution) { +static ImplicitConversionSequence +TryImplicitConversion(Sema &S, Expr *From, QualType ToType, + bool SuppressUserConversions, + bool AllowExplicit, + bool InOverloadResolution) { ImplicitConversionSequence ICS; - if (IsStandardConversion(From, ToType, InOverloadResolution, ICS.Standard)) { + if (IsStandardConversion(S, From, ToType, InOverloadResolution, + ICS.Standard)) { ICS.setStandard(); return ICS; } - if (!getLangOptions().CPlusPlus) { + if (!S.getLangOptions().CPlusPlus) { ICS.setBad(BadConversionSequence::no_conversion, From, ToType); return ICS; } - if (SuppressUserConversions) { - // C++ [over.ics.user]p4: - // A conversion of an expression of class type to the same class - // type is given Exact Match rank, and a conversion of an - // expression of class type to a base class of that type is - // given Conversion rank, in spite of the fact that a copy/move - // constructor (i.e., a user-defined conversion function) is - // called for those cases. - QualType FromType = From->getType(); - if (!ToType->getAs() || !FromType->getAs() || - !(Context.hasSameUnqualifiedType(FromType, ToType) || - IsDerivedFrom(FromType, ToType))) { - // We're not in the case above, so there is no conversion that - // we can perform. - ICS.setBad(BadConversionSequence::no_conversion, From, ToType); - return ICS; - } - + // C++ [over.ics.user]p4: + // A conversion of an expression of class type to the same class + // type is given Exact Match rank, and a conversion of an + // expression of class type to a base class of that type is + // given Conversion rank, in spite of the fact that a copy/move + // constructor (i.e., a user-defined conversion function) is + // called for those cases. + QualType FromType = From->getType(); + if (ToType->getAs() && FromType->getAs() && + (S.Context.hasSameUnqualifiedType(FromType, ToType) || + S.IsDerivedFrom(FromType, ToType))) { ICS.setStandard(); ICS.Standard.setAsIdentityConversion(); ICS.Standard.setFromType(FromType); @@ -713,18 +743,25 @@ Sema::TryImplicitConversion(Expr* From, QualType ToType, // exists. When we actually perform initialization, we'll find the // appropriate constructor to copy the returned object, if needed. ICS.Standard.CopyConstructor = 0; - + // Determine whether this is considered a derived-to-base conversion. - if (!Context.hasSameUnqualifiedType(FromType, ToType)) + if (!S.Context.hasSameUnqualifiedType(FromType, ToType)) ICS.Standard.Second = ICK_Derived_To_Base; - + + return ICS; + } + + if (SuppressUserConversions) { + // We're not in the case above, so there is no conversion that + // we can perform. + ICS.setBad(BadConversionSequence::no_conversion, From, ToType); return ICS; } // Attempt user-defined conversion. OverloadCandidateSet Conversions(From->getExprLoc()); OverloadingResult UserDefResult - = IsUserDefinedConversion(From, ToType, ICS.UserDefined, Conversions, + = IsUserDefinedConversion(S, From, ToType, ICS.UserDefined, Conversions, AllowExplicit); if (UserDefResult == OR_Success) { @@ -739,10 +776,11 @@ Sema::TryImplicitConversion(Expr* From, QualType ToType, if (CXXConstructorDecl *Constructor = dyn_cast(ICS.UserDefined.ConversionFunction)) { QualType FromCanon - = Context.getCanonicalType(From->getType().getUnqualifiedType()); - QualType ToCanon = Context.getCanonicalType(ToType).getUnqualifiedType(); + = S.Context.getCanonicalType(From->getType().getUnqualifiedType()); + QualType ToCanon + = S.Context.getCanonicalType(ToType).getUnqualifiedType(); if (Constructor->isCopyConstructor() && - (FromCanon == ToCanon || IsDerivedFrom(FromCanon, ToCanon))) { + (FromCanon == ToCanon || S.IsDerivedFrom(FromCanon, ToCanon))) { // Turn this into a "standard" conversion sequence, so that it // gets ranked with standard conversion sequences. ICS.setStandard(); @@ -780,6 +818,24 @@ Sema::TryImplicitConversion(Expr* From, QualType ToType, return ICS; } +bool Sema::TryImplicitConversion(InitializationSequence &Sequence, + const InitializedEntity &Entity, + Expr *Initializer, + bool SuppressUserConversions, + bool AllowExplicitConversions, + bool InOverloadResolution) { + ImplicitConversionSequence ICS + = clang::TryImplicitConversion(*this, Initializer, Entity.getType(), + SuppressUserConversions, + AllowExplicitConversions, + InOverloadResolution); + if (ICS.isBad()) return true; + + // Perform the actual conversion. + Sequence.AddConversionSequenceStep(ICS, Entity.getType()); + return false; +} + /// PerformImplicitConversion - Perform an implicit conversion of the /// expression From to the type ToType. Returns true if there was an /// error, false otherwise. The expression From is replaced with the @@ -797,10 +853,10 @@ bool Sema::PerformImplicitConversion(Expr *&From, QualType ToType, AssignmentAction Action, bool AllowExplicit, ImplicitConversionSequence& ICS) { - ICS = TryImplicitConversion(From, ToType, - /*SuppressUserConversions=*/false, - AllowExplicit, - /*InOverloadResolution=*/false); + ICS = clang::TryImplicitConversion(*this, From, ToType, + /*SuppressUserConversions=*/false, + AllowExplicit, + /*InOverloadResolution=*/false); return PerformImplicitConversion(From, ToType, ICS, Action); } @@ -850,16 +906,20 @@ static bool IsVectorConversion(ASTContext &Context, QualType FromType, return true; } } - - // If lax vector conversions are permitted and the vector types are of the - // same size, we can perform the conversion. - if (Context.getLangOptions().LaxVectorConversions && - FromType->isVectorType() && ToType->isVectorType() && - Context.getTypeSize(FromType) == Context.getTypeSize(ToType)) { - ICK = ICK_Vector_Conversion; - return true; + + // We can perform the conversion between vector types in the following cases: + // 1)vector types are equivalent AltiVec and GCC vector types + // 2)lax vector conversions are permitted and the vector types are of the + // same size + if (ToType->isVectorType() && FromType->isVectorType()) { + if (Context.areCompatibleVectorTypes(FromType, ToType) || + (Context.getLangOptions().LaxVectorConversions && + (Context.getTypeSize(FromType) == Context.getTypeSize(ToType)))) { + ICK = ICK_Vector_Conversion; + return true; + } } - + return false; } @@ -871,12 +931,11 @@ static bool IsVectorConversion(ASTContext &Context, QualType FromType, /// contain the standard conversion sequence required to perform this /// conversion and this routine will return true. Otherwise, this /// routine will return false and the value of SCS is unspecified. -bool -Sema::IsStandardConversion(Expr* From, QualType ToType, - bool InOverloadResolution, - StandardConversionSequence &SCS) { +static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, + bool InOverloadResolution, + StandardConversionSequence &SCS) { QualType FromType = From->getType(); - + // Standard conversions (C++ [conv]) SCS.setAsIdentityConversion(); SCS.DeprecatedStringLiteralToCharPtr = false; @@ -887,7 +946,7 @@ Sema::IsStandardConversion(Expr* From, QualType ToType, // There are no standard conversions for class types in C++, so // abort early. When overloading in C, however, we do permit if (FromType->isRecordType() || ToType->isRecordType()) { - if (getLangOptions().CPlusPlus) + if (S.getLangOptions().CPlusPlus) return false; // When we're overloading in C, we allow, as standard conversions, @@ -897,19 +956,19 @@ Sema::IsStandardConversion(Expr* From, QualType ToType, // array-to-pointer conversion, or function-to-pointer conversion // (C++ 4p1). - if (FromType == Context.OverloadTy) { + if (FromType == S.Context.OverloadTy) { DeclAccessPair AccessPair; if (FunctionDecl *Fn - = ResolveAddressOfOverloadedFunction(From, ToType, false, - AccessPair)) { + = S.ResolveAddressOfOverloadedFunction(From, ToType, false, + AccessPair)) { // We were able to resolve the address of the overloaded function, // so we can convert to the type of that function. FromType = Fn->getType(); if (CXXMethodDecl *Method = dyn_cast(Fn)) { if (!Method->isStatic()) { Type *ClassType - = Context.getTypeDeclType(Method->getParent()).getTypePtr(); - FromType = Context.getMemberPointerType(FromType, ClassType); + = S.Context.getTypeDeclType(Method->getParent()).getTypePtr(); + FromType = S.Context.getMemberPointerType(FromType, ClassType); } } @@ -917,12 +976,12 @@ Sema::IsStandardConversion(Expr* From, QualType ToType, // function, update the type of the resulting expression accordingly. if (FromType->getAs()) if (UnaryOperator *UnOp = dyn_cast(From->IgnoreParens())) - if (UnOp->getOpcode() == UnaryOperator::AddrOf) - FromType = Context.getPointerType(FromType); + if (UnOp->getOpcode() == UO_AddrOf) + FromType = S.Context.getPointerType(FromType); // Check that we've computed the proper type after overload resolution. - assert(Context.hasSameType(FromType, - FixOverloadedFunctionReference(From, AccessPair, Fn)->getType())); + assert(S.Context.hasSameType(FromType, + S.FixOverloadedFunctionReference(From, AccessPair, Fn)->getType())); } else { return false; } @@ -930,10 +989,10 @@ Sema::IsStandardConversion(Expr* From, QualType ToType, // Lvalue-to-rvalue conversion (C++ 4.1): // An lvalue (3.10) of a non-function, non-array type T can be // converted to an rvalue. - Expr::isLvalueResult argIsLvalue = From->isLvalue(Context); + Expr::isLvalueResult argIsLvalue = From->isLvalue(S.Context); if (argIsLvalue == Expr::LV_Valid && !FromType->isFunctionType() && !FromType->isArrayType() && - Context.getCanonicalType(FromType) != Context.OverloadTy) { + S.Context.getCanonicalType(FromType) != S.Context.OverloadTy) { SCS.First = ICK_Lvalue_To_Rvalue; // If T is a non-class type, the type of the rvalue is the @@ -948,9 +1007,9 @@ Sema::IsStandardConversion(Expr* From, QualType ToType, // An lvalue or rvalue of type "array of N T" or "array of unknown // bound of T" can be converted to an rvalue of type "pointer to // T" (C++ 4.2p1). - FromType = Context.getArrayDecayedType(FromType); + FromType = S.Context.getArrayDecayedType(FromType); - if (IsStringLiteralToNonConstPointerConversion(From, ToType)) { + if (S.IsStringLiteralToNonConstPointerConversion(From, ToType)) { // This conversion is deprecated. (C++ D.4). SCS.DeprecatedStringLiteralToCharPtr = true; @@ -970,7 +1029,7 @@ Sema::IsStandardConversion(Expr* From, QualType ToType, // An lvalue of function type T can be converted to an rvalue of // type "pointer to T." The result is a pointer to the // function. (C++ 4.3p1). - FromType = Context.getPointerType(FromType); + FromType = S.Context.getPointerType(FromType); } else { // We don't require any conversions for the first step. SCS.First = ICK_Identity; @@ -985,24 +1044,24 @@ Sema::IsStandardConversion(Expr* From, QualType ToType, // conversion. bool IncompatibleObjC = false; ImplicitConversionKind SecondICK = ICK_Identity; - if (Context.hasSameUnqualifiedType(FromType, ToType)) { + if (S.Context.hasSameUnqualifiedType(FromType, ToType)) { // The unqualified versions of the types are the same: there's no // conversion to do. SCS.Second = ICK_Identity; - } else if (IsIntegralPromotion(From, FromType, ToType)) { + } else if (S.IsIntegralPromotion(From, FromType, ToType)) { // Integral promotion (C++ 4.5). SCS.Second = ICK_Integral_Promotion; FromType = ToType.getUnqualifiedType(); - } else if (IsFloatingPointPromotion(FromType, ToType)) { + } else if (S.IsFloatingPointPromotion(FromType, ToType)) { // Floating point promotion (C++ 4.6). SCS.Second = ICK_Floating_Promotion; FromType = ToType.getUnqualifiedType(); - } else if (IsComplexPromotion(FromType, ToType)) { + } else if (S.IsComplexPromotion(FromType, ToType)) { // Complex promotion (Clang extension) SCS.Second = ICK_Complex_Promotion; FromType = ToType.getUnqualifiedType(); } else if (FromType->isIntegralOrEnumerationType() && - ToType->isIntegralType(Context)) { + ToType->isIntegralType(S.Context)) { // Integral conversions (C++ 4.7). SCS.Second = ICK_Integral_Conversion; FromType = ToType.getUnqualifiedType(); @@ -1020,19 +1079,19 @@ Sema::IsStandardConversion(Expr* From, QualType ToType, SCS.Second = ICK_Floating_Conversion; FromType = ToType.getUnqualifiedType(); } else if ((FromType->isRealFloatingType() && - ToType->isIntegralType(Context) && !ToType->isBooleanType()) || + ToType->isIntegralType(S.Context) && !ToType->isBooleanType()) || (FromType->isIntegralOrEnumerationType() && ToType->isRealFloatingType())) { // Floating-integral conversions (C++ 4.9). SCS.Second = ICK_Floating_Integral; FromType = ToType.getUnqualifiedType(); - } else if (IsPointerConversion(From, FromType, ToType, InOverloadResolution, - FromType, IncompatibleObjC)) { + } else if (S.IsPointerConversion(From, FromType, ToType, InOverloadResolution, + FromType, IncompatibleObjC)) { // Pointer conversions (C++ 4.10). SCS.Second = ICK_Pointer_Conversion; SCS.IncompatibleObjC = IncompatibleObjC; - } else if (IsMemberPointerConversion(From, FromType, ToType, - InOverloadResolution, FromType)) { + } else if (S.IsMemberPointerConversion(From, FromType, ToType, + InOverloadResolution, FromType)) { // Pointer to member conversions (4.11). SCS.Second = ICK_Pointer_Member; } else if (ToType->isBooleanType() && @@ -1044,16 +1103,16 @@ Sema::IsStandardConversion(Expr* From, QualType ToType, FromType->isNullPtrType())) { // Boolean conversions (C++ 4.12). SCS.Second = ICK_Boolean_Conversion; - FromType = Context.BoolTy; - } else if (IsVectorConversion(Context, FromType, ToType, SecondICK)) { + FromType = S.Context.BoolTy; + } else if (IsVectorConversion(S.Context, FromType, ToType, SecondICK)) { SCS.Second = SecondICK; FromType = ToType.getUnqualifiedType(); - } else if (!getLangOptions().CPlusPlus && - Context.typesAreCompatible(ToType, FromType)) { + } else if (!S.getLangOptions().CPlusPlus && + S.Context.typesAreCompatible(ToType, FromType)) { // Compatible conversions (Clang extension for C function overloading) SCS.Second = ICK_Compatible_Conversion; FromType = ToType.getUnqualifiedType(); - } else if (IsNoReturnConversion(Context, FromType, ToType, FromType)) { + } else if (IsNoReturnConversion(S.Context, FromType, ToType, FromType)) { // Treat a conversion that strips "noreturn" as an identity conversion. SCS.Second = ICK_NoReturn_Adjustment; } else { @@ -1065,11 +1124,11 @@ Sema::IsStandardConversion(Expr* From, QualType ToType, QualType CanonFrom; QualType CanonTo; // The third conversion can be a qualification conversion (C++ 4p1). - if (IsQualificationConversion(FromType, ToType)) { + if (S.IsQualificationConversion(FromType, ToType)) { SCS.Third = ICK_Qualification; FromType = ToType; - CanonFrom = Context.getCanonicalType(FromType); - CanonTo = Context.getCanonicalType(ToType); + CanonFrom = S.Context.getCanonicalType(FromType); + CanonTo = S.Context.getCanonicalType(ToType); } else { // No conversion required SCS.Third = ICK_Identity; @@ -1078,8 +1137,8 @@ Sema::IsStandardConversion(Expr* From, QualType ToType, // [...] Any difference in top-level cv-qualification is // subsumed by the initialization itself and does not constitute // a conversion. [...] - CanonFrom = Context.getCanonicalType(FromType); - CanonTo = Context.getCanonicalType(ToType); + CanonFrom = S.Context.getCanonicalType(FromType); + CanonTo = S.Context.getCanonicalType(ToType); if (CanonFrom.getLocalUnqualifiedType() == CanonTo.getLocalUnqualifiedType() && (CanonFrom.getLocalCVRQualifiers() != CanonTo.getLocalCVRQualifiers() @@ -1397,10 +1456,16 @@ bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType, QualType FromPointeeType = FromTypePtr->getPointeeType(); + // If the unqualified pointee types are the same, this can't be a + // pointer conversion, so don't do all of the work below. + if (Context.hasSameUnqualifiedType(FromPointeeType, ToPointeeType)) + return false; + // An rvalue of type "pointer to cv T," where T is an object type, // can be converted to an rvalue of type "pointer to cv void" (C++ // 4.10p2). - if (FromPointeeType->isObjectType() && ToPointeeType->isVoidType()) { + if (FromPointeeType->isIncompleteOrObjectType() && + ToPointeeType->isVoidType()) { ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr, ToPointeeType, ToType, Context); @@ -1657,8 +1722,8 @@ bool Sema::FunctionArgTypesAreEqual(FunctionProtoType* OldType, /// true. It returns true and produces a diagnostic if there was an /// error, or returns false otherwise. bool Sema::CheckPointerConversion(Expr *From, QualType ToType, - CastExpr::CastKind &Kind, - CXXBaseSpecifierArray& BasePath, + CastKind &Kind, + CXXCastPath& BasePath, bool IgnoreBaseAccess) { QualType FromType = From->getType(); @@ -1684,7 +1749,7 @@ bool Sema::CheckPointerConversion(Expr *From, QualType ToType, return true; // The conversion was successful. - Kind = CastExpr::CK_DerivedToBase; + Kind = CK_DerivedToBase; } } if (const ObjCObjectPointerType *FromPtrType = @@ -1749,8 +1814,8 @@ bool Sema::IsMemberPointerConversion(Expr *From, QualType FromType, /// true and produces a diagnostic if there was an error, or returns false /// otherwise. bool Sema::CheckMemberPointerConversion(Expr *From, QualType ToType, - CastExpr::CastKind &Kind, - CXXBaseSpecifierArray &BasePath, + CastKind &Kind, + CXXCastPath &BasePath, bool IgnoreBaseAccess) { QualType FromType = From->getType(); const MemberPointerType *FromPtrType = FromType->getAs(); @@ -1759,7 +1824,7 @@ bool Sema::CheckMemberPointerConversion(Expr *From, QualType ToType, assert(From->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull) && "Expr must be null pointer constant!"); - Kind = CastExpr::CK_NullToMemberPointer; + Kind = CK_NullToMemberPointer; return false; } @@ -1803,7 +1868,7 @@ bool Sema::CheckMemberPointerConversion(Expr *From, QualType ToType, // Must be a base to derived member conversion. BuildBasePathArray(Paths, BasePath); - Kind = CastExpr::CK_BaseToDerivedMemberPointer; + Kind = CK_BaseToDerivedMemberPointer; return false; } @@ -1869,10 +1934,11 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType) { /// \param AllowExplicit true if the conversion should consider C++0x /// "explicit" conversion functions as well as non-explicit conversion /// functions (C++0x [class.conv.fct]p2). -OverloadingResult Sema::IsUserDefinedConversion(Expr *From, QualType ToType, - UserDefinedConversionSequence& User, - OverloadCandidateSet& CandidateSet, - bool AllowExplicit) { +static OverloadingResult +IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, + UserDefinedConversionSequence& User, + OverloadCandidateSet& CandidateSet, + bool AllowExplicit) { // Whether we will only visit constructors. bool ConstructorsOnly = false; @@ -1887,17 +1953,17 @@ OverloadingResult Sema::IsUserDefinedConversion(Expr *From, QualType ToType, // functions are all the converting constructors (12.3.1) of // that class. The argument list is the expression-list within // the parentheses of the initializer. - if (Context.hasSameUnqualifiedType(ToType, From->getType()) || + if (S.Context.hasSameUnqualifiedType(ToType, From->getType()) || (From->getType()->getAs() && - IsDerivedFrom(From->getType(), ToType))) + S.IsDerivedFrom(From->getType(), ToType))) ConstructorsOnly = true; - if (RequireCompleteType(From->getLocStart(), ToType, PDiag())) { + if (S.RequireCompleteType(From->getLocStart(), ToType, S.PDiag())) { // We're not going to find any constructors. } else if (CXXRecordDecl *ToRecordDecl = dyn_cast(ToRecordType->getDecl())) { DeclContext::lookup_iterator Con, ConEnd; - for (llvm::tie(Con, ConEnd) = LookupConstructors(ToRecordDecl); + for (llvm::tie(Con, ConEnd) = S.LookupConstructors(ToRecordDecl); Con != ConEnd; ++Con) { NamedDecl *D = *Con; DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess()); @@ -1915,16 +1981,18 @@ OverloadingResult Sema::IsUserDefinedConversion(Expr *From, QualType ToType, if (!Constructor->isInvalidDecl() && Constructor->isConvertingConstructor(AllowExplicit)) { if (ConstructorTmpl) - AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, - /*ExplicitArgs*/ 0, - &From, 1, CandidateSet, - /*SuppressUserConversions=*/!ConstructorsOnly); + S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, + /*ExplicitArgs*/ 0, + &From, 1, CandidateSet, + /*SuppressUserConversions=*/ + !ConstructorsOnly); else // Allow one user-defined conversion when user specifies a // From->ToType conversion via an static cast (c-style, etc). - AddOverloadCandidate(Constructor, FoundDecl, - &From, 1, CandidateSet, - /*SuppressUserConversions=*/!ConstructorsOnly); + S.AddOverloadCandidate(Constructor, FoundDecl, + &From, 1, CandidateSet, + /*SuppressUserConversions=*/ + !ConstructorsOnly); } } } @@ -1932,8 +2000,8 @@ OverloadingResult Sema::IsUserDefinedConversion(Expr *From, QualType ToType, // Enumerate conversion functions, if we're allowed to. if (ConstructorsOnly) { - } else if (RequireCompleteType(From->getLocStart(), From->getType(), - PDiag(0) << From->getSourceRange())) { + } else if (S.RequireCompleteType(From->getLocStart(), From->getType(), + S.PDiag(0) << From->getSourceRange())) { // No conversion functions from incomplete types. } else if (const RecordType *FromRecordType = From->getType()->getAs()) { @@ -1959,80 +2027,79 @@ OverloadingResult Sema::IsUserDefinedConversion(Expr *From, QualType ToType, if (AllowExplicit || !Conv->isExplicit()) { if (ConvTemplate) - AddTemplateConversionCandidate(ConvTemplate, FoundDecl, - ActingContext, From, ToType, - CandidateSet); + S.AddTemplateConversionCandidate(ConvTemplate, FoundDecl, + ActingContext, From, ToType, + CandidateSet); else - AddConversionCandidate(Conv, FoundDecl, ActingContext, - From, ToType, CandidateSet); + S.AddConversionCandidate(Conv, FoundDecl, ActingContext, + From, ToType, CandidateSet); } } } } OverloadCandidateSet::iterator Best; - switch (BestViableFunction(CandidateSet, From->getLocStart(), Best)) { - case OR_Success: - // Record the standard conversion we used and the conversion function. - if (CXXConstructorDecl *Constructor - = dyn_cast(Best->Function)) { - // C++ [over.ics.user]p1: - // 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. - // - QualType ThisType = Constructor->getThisType(Context); - if (Best->Conversions[0].isEllipsis()) - User.EllipsisConversion = true; - else { - User.Before = Best->Conversions[0].Standard; - User.EllipsisConversion = false; - } - User.ConversionFunction = Constructor; - User.After.setAsIdentityConversion(); - User.After.setFromType( - ThisType->getAs()->getPointeeType()); - User.After.setAllToTypes(ToType); - return OR_Success; - } else if (CXXConversionDecl *Conversion - = dyn_cast(Best->Function)) { - // C++ [over.ics.user]p1: - // - // [...] 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. + switch (CandidateSet.BestViableFunction(S, From->getLocStart(), Best)) { + case OR_Success: + // Record the standard conversion we used and the conversion function. + if (CXXConstructorDecl *Constructor + = dyn_cast(Best->Function)) { + // C++ [over.ics.user]p1: + // 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. + // + QualType ThisType = Constructor->getThisType(S.Context); + if (Best->Conversions[0].isEllipsis()) + User.EllipsisConversion = true; + else { User.Before = Best->Conversions[0].Standard; - User.ConversionFunction = Conversion; User.EllipsisConversion = false; - - // C++ [over.ics.user]p2: - // The second standard conversion sequence converts the - // result of the user-defined conversion to the target type - // for the sequence. Since an implicit conversion sequence - // is an initialization, the special rules for - // initialization by user-defined conversion apply when - // selecting the best user-defined conversion for a - // user-defined conversion sequence (see 13.3.3 and - // 13.3.3.1). - User.After = Best->FinalConversion; - return OR_Success; - } else { - assert(false && "Not a constructor or conversion function?"); - return OR_No_Viable_Function; } - - case OR_No_Viable_Function: + User.ConversionFunction = Constructor; + User.After.setAsIdentityConversion(); + User.After.setFromType(ThisType->getAs()->getPointeeType()); + User.After.setAllToTypes(ToType); + return OR_Success; + } else if (CXXConversionDecl *Conversion + = dyn_cast(Best->Function)) { + // C++ [over.ics.user]p1: + // + // [...] 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. + User.Before = Best->Conversions[0].Standard; + User.ConversionFunction = Conversion; + User.EllipsisConversion = false; + + // C++ [over.ics.user]p2: + // The second standard conversion sequence converts the + // result of the user-defined conversion to the target type + // for the sequence. Since an implicit conversion sequence + // is an initialization, the special rules for + // initialization by user-defined conversion apply when + // selecting the best user-defined conversion for a + // user-defined conversion sequence (see 13.3.3 and + // 13.3.3.1). + User.After = Best->FinalConversion; + return OR_Success; + } else { + llvm_unreachable("Not a constructor or conversion function?"); return OR_No_Viable_Function; - case OR_Deleted: - // No conversion here! We're done. - return OR_Deleted; - - case OR_Ambiguous: - return OR_Ambiguous; } + case OR_No_Viable_Function: + return OR_No_Viable_Function; + case OR_Deleted: + // No conversion here! We're done. + return OR_Deleted; + + case OR_Ambiguous: + return OR_Ambiguous; + } + return OR_No_Viable_Function; } @@ -2041,7 +2108,7 @@ Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) { ImplicitConversionSequence ICS; OverloadCandidateSet CandidateSet(From->getExprLoc()); OverloadingResult OvResult = - IsUserDefinedConversion(From, ToType, ICS.UserDefined, + IsUserDefinedConversion(*this, From, ToType, ICS.UserDefined, CandidateSet, false); if (OvResult == OR_Ambiguous) Diag(From->getSourceRange().getBegin(), @@ -2053,16 +2120,17 @@ Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) { << From->getType() << ToType << From->getSourceRange(); else return false; - PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, &From, 1); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, &From, 1); return true; } /// CompareImplicitConversionSequences - Compare two implicit /// conversion sequences to determine whether one is better than the /// other or if they are indistinguishable (C++ 13.3.3.2). -ImplicitConversionSequence::CompareKind -Sema::CompareImplicitConversionSequences(const ImplicitConversionSequence& ICS1, - const ImplicitConversionSequence& ICS2) +static ImplicitConversionSequence::CompareKind +CompareImplicitConversionSequences(Sema &S, + const ImplicitConversionSequence& ICS1, + const ImplicitConversionSequence& ICS2) { // (C++ 13.3.3.2p2): When comparing the basic forms of implicit // conversion sequences (as defined in 13.3.3.1) @@ -2092,7 +2160,7 @@ Sema::CompareImplicitConversionSequences(const ImplicitConversionSequence& ICS1, // indistinguishable conversion sequences unless one of the // following rules apply: (C++ 13.3.3.2p3): if (ICS1.isStandard()) - return CompareStandardConversionSequences(ICS1.Standard, ICS2.Standard); + return CompareStandardConversionSequences(S, ICS1.Standard, ICS2.Standard); else if (ICS1.isUserDefined()) { // User-defined conversion sequence U1 is a better conversion // sequence than another user-defined conversion sequence U2 if @@ -2102,7 +2170,8 @@ Sema::CompareImplicitConversionSequences(const ImplicitConversionSequence& ICS1, // U2 (C++ 13.3.3.2p3). if (ICS1.UserDefined.ConversionFunction == ICS2.UserDefined.ConversionFunction) - return CompareStandardConversionSequences(ICS1.UserDefined.After, + return CompareStandardConversionSequences(S, + ICS1.UserDefined.After, ICS2.UserDefined.After); } @@ -2168,9 +2237,10 @@ compareStandardConversionSubsets(ASTContext &Context, /// CompareStandardConversionSequences - Compare two standard /// conversion sequences to determine whether one is better than the /// other or if they are indistinguishable (C++ 13.3.3.2p3). -ImplicitConversionSequence::CompareKind -Sema::CompareStandardConversionSequences(const StandardConversionSequence& SCS1, - const StandardConversionSequence& SCS2) +static ImplicitConversionSequence::CompareKind +CompareStandardConversionSequences(Sema &S, + const StandardConversionSequence& SCS1, + const StandardConversionSequence& SCS2) { // Standard conversion sequence S1 is a better conversion sequence // than standard conversion sequence S2 if (C++ 13.3.3.2p3): @@ -2181,7 +2251,7 @@ Sema::CompareStandardConversionSequences(const StandardConversionSequence& SCS1, // sequence is considered to be a subsequence of any // non-identity conversion sequence) or, if not that, if (ImplicitConversionSequence::CompareKind CK - = compareStandardConversionSubsets(Context, SCS1, SCS2)) + = compareStandardConversionSubsets(S.Context, SCS1, SCS2)) return CK; // -- the rank of S1 is better than the rank of S2 (by the rules @@ -2212,9 +2282,9 @@ Sema::CompareStandardConversionSequences(const StandardConversionSequence& SCS1, // void*, and conversion of A* to void* is better than conversion // of B* to void*. bool SCS1ConvertsToVoid - = SCS1.isPointerConversionToVoidPointer(Context); + = SCS1.isPointerConversionToVoidPointer(S.Context); bool SCS2ConvertsToVoid - = SCS2.isPointerConversionToVoidPointer(Context); + = SCS2.isPointerConversionToVoidPointer(S.Context); if (SCS1ConvertsToVoid != SCS2ConvertsToVoid) { // Exactly one of the conversion sequences is a conversion to // a void pointer; it's the worse conversion. @@ -2224,7 +2294,7 @@ Sema::CompareStandardConversionSequences(const StandardConversionSequence& SCS1, // Neither conversion sequence converts to a void pointer; compare // their derived-to-base conversions. if (ImplicitConversionSequence::CompareKind DerivedCK - = CompareDerivedToBaseConversions(SCS1, SCS2)) + = CompareDerivedToBaseConversions(S, SCS1, SCS2)) return DerivedCK; } else if (SCS1ConvertsToVoid && SCS2ConvertsToVoid) { // Both conversion sequences are conversions to void @@ -2236,18 +2306,18 @@ Sema::CompareStandardConversionSequences(const StandardConversionSequence& SCS1, // Adjust the types we're converting from via the array-to-pointer // conversion, if we need to. if (SCS1.First == ICK_Array_To_Pointer) - FromType1 = Context.getArrayDecayedType(FromType1); + FromType1 = S.Context.getArrayDecayedType(FromType1); if (SCS2.First == ICK_Array_To_Pointer) - FromType2 = Context.getArrayDecayedType(FromType2); + FromType2 = S.Context.getArrayDecayedType(FromType2); QualType FromPointee1 = FromType1->getAs()->getPointeeType().getUnqualifiedType(); QualType FromPointee2 = FromType2->getAs()->getPointeeType().getUnqualifiedType(); - if (IsDerivedFrom(FromPointee2, FromPointee1)) + if (S.IsDerivedFrom(FromPointee2, FromPointee1)) return ImplicitConversionSequence::Better; - else if (IsDerivedFrom(FromPointee1, FromPointee2)) + else if (S.IsDerivedFrom(FromPointee1, FromPointee2)) return ImplicitConversionSequence::Worse; // Objective-C++: If one interface is more specific than the @@ -2255,9 +2325,9 @@ Sema::CompareStandardConversionSequences(const StandardConversionSequence& SCS1, const ObjCObjectType* FromIface1 = FromPointee1->getAs(); const ObjCObjectType* FromIface2 = FromPointee2->getAs(); if (FromIface1 && FromIface1) { - if (Context.canAssignObjCInterfaces(FromIface2, FromIface1)) + if (S.Context.canAssignObjCInterfaces(FromIface2, FromIface1)) return ImplicitConversionSequence::Better; - else if (Context.canAssignObjCInterfaces(FromIface1, FromIface2)) + else if (S.Context.canAssignObjCInterfaces(FromIface1, FromIface2)) return ImplicitConversionSequence::Worse; } } @@ -2265,7 +2335,7 @@ Sema::CompareStandardConversionSequences(const StandardConversionSequence& SCS1, // Compare based on qualification conversions (C++ 13.3.3.2p3, // bullet 3). if (ImplicitConversionSequence::CompareKind QualCK - = CompareQualificationConversions(SCS1, SCS2)) + = CompareQualificationConversions(S, SCS1, SCS2)) return QualCK; if (SCS1.ReferenceBinding && SCS2.ReferenceBinding) { @@ -2289,18 +2359,18 @@ Sema::CompareStandardConversionSequences(const StandardConversionSequence& SCS1, // to which the reference initialized by S1 refers. QualType T1 = SCS1.getToType(2); QualType T2 = SCS2.getToType(2); - T1 = Context.getCanonicalType(T1); - T2 = Context.getCanonicalType(T2); + T1 = S.Context.getCanonicalType(T1); + T2 = S.Context.getCanonicalType(T2); Qualifiers T1Quals, T2Quals; - QualType UnqualT1 = Context.getUnqualifiedArrayType(T1, T1Quals); - QualType UnqualT2 = Context.getUnqualifiedArrayType(T2, T2Quals); + QualType UnqualT1 = S.Context.getUnqualifiedArrayType(T1, T1Quals); + QualType UnqualT2 = S.Context.getUnqualifiedArrayType(T2, T2Quals); if (UnqualT1 == UnqualT2) { // If the type is an array type, promote the element qualifiers to the type // for comparison. if (isa(T1) && T1Quals) - T1 = Context.getQualifiedType(UnqualT1, T1Quals); + T1 = S.Context.getQualifiedType(UnqualT1, T1Quals); if (isa(T2) && T2Quals) - T2 = Context.getQualifiedType(UnqualT2, T2Quals); + T2 = S.Context.getQualifiedType(UnqualT2, T2Quals); if (T2.isMoreQualifiedThan(T1)) return ImplicitConversionSequence::Better; else if (T1.isMoreQualifiedThan(T2)) @@ -2315,8 +2385,9 @@ Sema::CompareStandardConversionSequences(const StandardConversionSequence& SCS1, /// sequences to determine whether they can be ranked based on their /// qualification conversions (C++ 13.3.3.2p3 bullet 3). ImplicitConversionSequence::CompareKind -Sema::CompareQualificationConversions(const StandardConversionSequence& SCS1, - const StandardConversionSequence& SCS2) { +CompareQualificationConversions(Sema &S, + const StandardConversionSequence& SCS1, + const StandardConversionSequence& SCS2) { // C++ 13.3.3.2p3: // -- S1 and S2 differ only in their qualification conversion and // yield similar types T1 and T2 (C++ 4.4), respectively, and the @@ -2331,11 +2402,11 @@ Sema::CompareQualificationConversions(const StandardConversionSequence& SCS1, // conversion (!) QualType T1 = SCS1.getToType(2); QualType T2 = SCS2.getToType(2); - T1 = Context.getCanonicalType(T1); - T2 = Context.getCanonicalType(T2); + T1 = S.Context.getCanonicalType(T1); + T2 = S.Context.getCanonicalType(T2); Qualifiers T1Quals, T2Quals; - QualType UnqualT1 = Context.getUnqualifiedArrayType(T1, T1Quals); - QualType UnqualT2 = Context.getUnqualifiedArrayType(T2, T2Quals); + QualType UnqualT1 = S.Context.getUnqualifiedArrayType(T1, T1Quals); + QualType UnqualT2 = S.Context.getUnqualifiedArrayType(T2, T2Quals); // If the types are the same, we won't learn anything by unwrapped // them. @@ -2345,13 +2416,13 @@ Sema::CompareQualificationConversions(const StandardConversionSequence& SCS1, // If the type is an array type, promote the element qualifiers to the type // for comparison. if (isa(T1) && T1Quals) - T1 = Context.getQualifiedType(UnqualT1, T1Quals); + T1 = S.Context.getQualifiedType(UnqualT1, T1Quals); if (isa(T2) && T2Quals) - T2 = Context.getQualifiedType(UnqualT2, T2Quals); + T2 = S.Context.getQualifiedType(UnqualT2, T2Quals); ImplicitConversionSequence::CompareKind Result = ImplicitConversionSequence::Indistinguishable; - while (Context.UnwrapSimilarPointerTypes(T1, T2)) { + while (S.Context.UnwrapSimilarPointerTypes(T1, T2)) { // Within each iteration of the loop, we check the qualifiers to // determine if this still looks like a qualification // conversion. Then, if all is well, we unwrap one more level of @@ -2386,7 +2457,7 @@ Sema::CompareQualificationConversions(const StandardConversionSequence& SCS1, } // If the types after this point are equivalent, we're done. - if (Context.hasSameUnqualifiedType(T1, T2)) + if (S.Context.hasSameUnqualifiedType(T1, T2)) break; } @@ -2416,8 +2487,9 @@ Sema::CompareQualificationConversions(const StandardConversionSequence& SCS1, /// [over.ics.rank]p4b3). As part of these checks, we also look at /// conversions between Objective-C interface types. ImplicitConversionSequence::CompareKind -Sema::CompareDerivedToBaseConversions(const StandardConversionSequence& SCS1, - const StandardConversionSequence& SCS2) { +CompareDerivedToBaseConversions(Sema &S, + const StandardConversionSequence& SCS1, + const StandardConversionSequence& SCS2) { QualType FromType1 = SCS1.getFromType(); QualType ToType1 = SCS1.getToType(1); QualType FromType2 = SCS2.getFromType(); @@ -2426,15 +2498,15 @@ Sema::CompareDerivedToBaseConversions(const StandardConversionSequence& SCS1, // Adjust the types we're converting from via the array-to-pointer // conversion, if we need to. if (SCS1.First == ICK_Array_To_Pointer) - FromType1 = Context.getArrayDecayedType(FromType1); + FromType1 = S.Context.getArrayDecayedType(FromType1); if (SCS2.First == ICK_Array_To_Pointer) - FromType2 = Context.getArrayDecayedType(FromType2); + FromType2 = S.Context.getArrayDecayedType(FromType2); // Canonicalize all of the types. - FromType1 = Context.getCanonicalType(FromType1); - ToType1 = Context.getCanonicalType(ToType1); - FromType2 = Context.getCanonicalType(FromType2); - ToType2 = Context.getCanonicalType(ToType2); + FromType1 = S.Context.getCanonicalType(FromType1); + ToType1 = S.Context.getCanonicalType(ToType1); + FromType2 = S.Context.getCanonicalType(FromType2); + ToType2 = S.Context.getCanonicalType(ToType2); // C++ [over.ics.rank]p4b3: // @@ -2466,30 +2538,30 @@ Sema::CompareDerivedToBaseConversions(const StandardConversionSequence& SCS1, // -- conversion of C* to B* is better than conversion of C* to A*, if (FromPointee1 == FromPointee2 && ToPointee1 != ToPointee2) { - if (IsDerivedFrom(ToPointee1, ToPointee2)) + if (S.IsDerivedFrom(ToPointee1, ToPointee2)) return ImplicitConversionSequence::Better; - else if (IsDerivedFrom(ToPointee2, ToPointee1)) + else if (S.IsDerivedFrom(ToPointee2, ToPointee1)) return ImplicitConversionSequence::Worse; if (ToIface1 && ToIface2) { - if (Context.canAssignObjCInterfaces(ToIface2, ToIface1)) + if (S.Context.canAssignObjCInterfaces(ToIface2, ToIface1)) return ImplicitConversionSequence::Better; - else if (Context.canAssignObjCInterfaces(ToIface1, ToIface2)) + else if (S.Context.canAssignObjCInterfaces(ToIface1, ToIface2)) return ImplicitConversionSequence::Worse; } } // -- conversion of B* to A* is better than conversion of C* to A*, if (FromPointee1 != FromPointee2 && ToPointee1 == ToPointee2) { - if (IsDerivedFrom(FromPointee2, FromPointee1)) + if (S.IsDerivedFrom(FromPointee2, FromPointee1)) return ImplicitConversionSequence::Better; - else if (IsDerivedFrom(FromPointee1, FromPointee2)) + else if (S.IsDerivedFrom(FromPointee1, FromPointee2)) return ImplicitConversionSequence::Worse; if (FromIface1 && FromIface2) { - if (Context.canAssignObjCInterfaces(FromIface1, FromIface2)) + if (S.Context.canAssignObjCInterfaces(FromIface1, FromIface2)) return ImplicitConversionSequence::Better; - else if (Context.canAssignObjCInterfaces(FromIface2, FromIface1)) + else if (S.Context.canAssignObjCInterfaces(FromIface2, FromIface1)) return ImplicitConversionSequence::Worse; } } @@ -2517,16 +2589,16 @@ Sema::CompareDerivedToBaseConversions(const StandardConversionSequence& SCS1, QualType ToPointee2 = QualType(ToPointeeType2, 0).getUnqualifiedType(); // conversion of A::* to B::* is better than conversion of A::* to C::*, if (FromPointee1 == FromPointee2 && ToPointee1 != ToPointee2) { - if (IsDerivedFrom(ToPointee1, ToPointee2)) + if (S.IsDerivedFrom(ToPointee1, ToPointee2)) return ImplicitConversionSequence::Worse; - else if (IsDerivedFrom(ToPointee2, ToPointee1)) + else if (S.IsDerivedFrom(ToPointee2, ToPointee1)) return ImplicitConversionSequence::Better; } // conversion of B::* to C::* is better than conversion of A::* to C::* if (ToPointee1 == ToPointee2 && FromPointee1 != FromPointee2) { - if (IsDerivedFrom(FromPointee1, FromPointee2)) + if (S.IsDerivedFrom(FromPointee1, FromPointee2)) return ImplicitConversionSequence::Better; - else if (IsDerivedFrom(FromPointee2, FromPointee1)) + else if (S.IsDerivedFrom(FromPointee2, FromPointee1)) return ImplicitConversionSequence::Worse; } } @@ -2536,11 +2608,11 @@ Sema::CompareDerivedToBaseConversions(const StandardConversionSequence& SCS1, // -- binding of an expression of type C to a reference of type // B& is better than binding an expression of type C to a // reference of type A&, - if (Context.hasSameUnqualifiedType(FromType1, FromType2) && - !Context.hasSameUnqualifiedType(ToType1, ToType2)) { - if (IsDerivedFrom(ToType1, ToType2)) + if (S.Context.hasSameUnqualifiedType(FromType1, FromType2) && + !S.Context.hasSameUnqualifiedType(ToType1, ToType2)) { + if (S.IsDerivedFrom(ToType1, ToType2)) return ImplicitConversionSequence::Better; - else if (IsDerivedFrom(ToType2, ToType1)) + else if (S.IsDerivedFrom(ToType2, ToType1)) return ImplicitConversionSequence::Worse; } @@ -2548,11 +2620,11 @@ Sema::CompareDerivedToBaseConversions(const StandardConversionSequence& SCS1, // -- binding of an expression of type B to a reference of type // A& is better than binding an expression of type C to a // reference of type A&, - if (!Context.hasSameUnqualifiedType(FromType1, FromType2) && - Context.hasSameUnqualifiedType(ToType1, ToType2)) { - if (IsDerivedFrom(FromType2, FromType1)) + if (!S.Context.hasSameUnqualifiedType(FromType1, FromType2) && + S.Context.hasSameUnqualifiedType(ToType1, ToType2)) { + if (S.IsDerivedFrom(FromType2, FromType1)) return ImplicitConversionSequence::Better; - else if (IsDerivedFrom(FromType1, FromType2)) + else if (S.IsDerivedFrom(FromType1, FromType2)) return ImplicitConversionSequence::Worse; } } @@ -2570,7 +2642,8 @@ Sema::CompareDerivedToBaseConversions(const StandardConversionSequence& SCS1, Sema::ReferenceCompareResult Sema::CompareReferenceRelationship(SourceLocation Loc, QualType OrigT1, QualType OrigT2, - bool& DerivedToBase) { + bool &DerivedToBase, + bool &ObjCConversion) { assert(!OrigT1->isReferenceType() && "T1 must be the pointee type of the reference type"); assert(!OrigT2->isReferenceType() && "T2 cannot be a reference type"); @@ -2585,11 +2658,17 @@ Sema::CompareReferenceRelationship(SourceLocation Loc, // Given types "cv1 T1" and "cv2 T2," "cv1 T1" is // reference-related to "cv2 T2" if T1 is the same type as T2, or // T1 is a base class of T2. - if (UnqualT1 == UnqualT2) - DerivedToBase = false; - else if (!RequireCompleteType(Loc, OrigT2, PDiag()) && + DerivedToBase = false; + ObjCConversion = false; + if (UnqualT1 == UnqualT2) { + // Nothing to do. + } else if (!RequireCompleteType(Loc, OrigT2, PDiag()) && IsDerivedFrom(UnqualT2, UnqualT1)) DerivedToBase = true; + else if (UnqualT1->isObjCObjectOrInterfaceType() && + UnqualT2->isObjCObjectOrInterfaceType() && + Context.canBindObjCObjectType(UnqualT1, UnqualT2)) + ObjCConversion = true; else return Ref_Incompatible; @@ -2618,16 +2697,21 @@ Sema::CompareReferenceRelationship(SourceLocation Loc, return Ref_Related; } -/// \brief Look for a user-defined conversion to an lvalue reference-compatible +/// \brief Look for a user-defined conversion to an value reference-compatible /// with DeclType. Return true if something definite is found. static bool -FindConversionToLValue(Sema &S, ImplicitConversionSequence &ICS, - QualType DeclType, SourceLocation DeclLoc, - Expr *Init, QualType T2, bool AllowExplicit) { +FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS, + QualType DeclType, SourceLocation DeclLoc, + Expr *Init, QualType T2, bool AllowRvalues, + bool AllowExplicit) { assert(T2->isRecordType() && "Can only find conversions of record types."); CXXRecordDecl *T2RecordDecl = dyn_cast(T2->getAs()->getDecl()); + QualType ToType + = AllowRvalues? DeclType->getAs()->getPointeeType() + : DeclType; + OverloadCandidateSet CandidateSet(DeclLoc); const UnresolvedSetImpl *Conversions = T2RecordDecl->getVisibleConversionFunctions(); @@ -2646,25 +2730,44 @@ FindConversionToLValue(Sema &S, ImplicitConversionSequence &ICS, else Conv = cast(D); - // If the conversion function doesn't return a reference type, - // it can't be considered for this conversion. An rvalue reference - // is only acceptable if its referencee is a function type. - const ReferenceType *RefType = - Conv->getConversionType()->getAs(); - if (RefType && (RefType->isLValueReferenceType() || - RefType->getPointeeType()->isFunctionType()) && - (AllowExplicit || !Conv->isExplicit())) { - if (ConvTemplate) - S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(), ActingDC, - Init, DeclType, CandidateSet); - else - S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Init, - DeclType, CandidateSet); + // If this is an explicit conversion, and we're not allowed to consider + // explicit conversions, skip it. + if (!AllowExplicit && Conv->isExplicit()) + continue; + + if (AllowRvalues) { + bool DerivedToBase = false; + bool ObjCConversion = false; + if (!ConvTemplate && + S.CompareReferenceRelationship(DeclLoc, + Conv->getConversionType().getNonReferenceType().getUnqualifiedType(), + DeclType.getNonReferenceType().getUnqualifiedType(), + DerivedToBase, ObjCConversion) + == Sema::Ref_Incompatible) + continue; + } else { + // If the conversion function doesn't return a reference type, + // it can't be considered for this conversion. An rvalue reference + // is only acceptable if its referencee is a function type. + + const ReferenceType *RefType = + Conv->getConversionType()->getAs(); + if (!RefType || + (!RefType->isLValueReferenceType() && + !RefType->getPointeeType()->isFunctionType())) + continue; } + + if (ConvTemplate) + S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(), ActingDC, + Init, ToType, CandidateSet); + else + S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Init, + ToType, CandidateSet); } OverloadCandidateSet::iterator Best; - switch (S.BestViableFunction(CandidateSet, DeclLoc, Best)) { + switch (CandidateSet.BestViableFunction(S, DeclLoc, Best)) { case OR_Success: // C++ [over.ics.ref]p1: // @@ -2736,9 +2839,11 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType, // Compute some basic properties of the types and the initializer. bool isRValRef = DeclType->isRValueReferenceType(); bool DerivedToBase = false; + bool ObjCConversion = false; Expr::Classification InitCategory = Init->Classify(S.Context); Sema::ReferenceCompareResult RefRelationship - = S.CompareReferenceRelationship(DeclLoc, T1, T2, DerivedToBase); + = S.CompareReferenceRelationship(DeclLoc, T1, T2, DerivedToBase, + ObjCConversion); // C++0x [dcl.init.ref]p5: @@ -2764,7 +2869,9 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType, // derived-to-base Conversion (13.3.3.1). ICS.setStandard(); ICS.Standard.First = ICK_Identity; - ICS.Standard.Second = DerivedToBase? ICK_Derived_To_Base : ICK_Identity; + ICS.Standard.Second = DerivedToBase? ICK_Derived_To_Base + : ObjCConversion? ICK_Compatible_Conversion + : ICK_Identity; ICS.Standard.Third = ICK_Identity; ICS.Standard.FromTypePtr = T2.getAsOpaquePtr(); ICS.Standard.setToType(0, T2); @@ -2792,8 +2899,9 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType, if (!SuppressUserConversions && T2->isRecordType() && !S.RequireCompleteType(DeclLoc, T2, 0) && RefRelationship == Sema::Ref_Incompatible) { - if (FindConversionToLValue(S, ICS, DeclType, DeclLoc, - Init, T2, AllowExplicit)) + if (FindConversionForRefInit(S, ICS, DeclType, DeclLoc, + Init, T2, /*AllowRvalues=*/false, + AllowExplicit)) return ICS; } } @@ -2845,26 +2953,37 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType, // that is the result of the conversion in the second case // (or, in either case, to the appropriate base class // subobject of the object). - // - // We're only checking the first case here, which is a direct - // binding in C++0x but not in C++03. - if (InitCategory.isRValue() && T2->isRecordType() && - RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification) { - ICS.setStandard(); - ICS.Standard.First = ICK_Identity; - ICS.Standard.Second = DerivedToBase? ICK_Derived_To_Base : ICK_Identity; - ICS.Standard.Third = ICK_Identity; - ICS.Standard.FromTypePtr = T2.getAsOpaquePtr(); - ICS.Standard.setToType(0, T2); - ICS.Standard.setToType(1, T1); - ICS.Standard.setToType(2, T1); - ICS.Standard.ReferenceBinding = true; - ICS.Standard.DirectBinding = S.getLangOptions().CPlusPlus0x; - ICS.Standard.RRefBinding = isRValRef; - ICS.Standard.CopyConstructor = 0; - return ICS; + if (T2->isRecordType()) { + // First case: "cv1 T1" is reference-compatible with "cv2 T2". This is a + // direct binding in C++0x but not in C++03. + if (InitCategory.isRValue() && + RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification) { + ICS.setStandard(); + ICS.Standard.First = ICK_Identity; + ICS.Standard.Second = DerivedToBase? ICK_Derived_To_Base + : ObjCConversion? ICK_Compatible_Conversion + : ICK_Identity; + ICS.Standard.Third = ICK_Identity; + ICS.Standard.FromTypePtr = T2.getAsOpaquePtr(); + ICS.Standard.setToType(0, T2); + ICS.Standard.setToType(1, T1); + ICS.Standard.setToType(2, T1); + ICS.Standard.ReferenceBinding = true; + ICS.Standard.DirectBinding = S.getLangOptions().CPlusPlus0x; + ICS.Standard.RRefBinding = isRValRef; + ICS.Standard.CopyConstructor = 0; + return ICS; + } + + // Second case: not reference-related. + if (RefRelationship == Sema::Ref_Incompatible && + !S.RequireCompleteType(DeclLoc, T2, 0) && + FindConversionForRefInit(S, ICS, DeclType, DeclLoc, + Init, T2, /*AllowRvalues=*/true, + AllowExplicit)) + return ICS; } - + // -- Otherwise, a temporary of type "cv1 T1" is created and // initialized from the initializer expression using the // rules for a non-reference copy initialization (8.5). The @@ -2899,9 +3018,9 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType, // the argument expression. Any difference in top-level // cv-qualification is subsumed by the initialization itself // and does not constitute a conversion. - ICS = S.TryImplicitConversion(Init, T1, SuppressUserConversions, - /*AllowExplicit=*/false, - /*InOverloadResolution=*/false); + ICS = TryImplicitConversion(S, Init, T1, SuppressUserConversions, + /*AllowExplicit=*/false, + /*InOverloadResolution=*/false); // Of course, that's still a reference binding. if (ICS.isStandard()) { @@ -2930,25 +3049,25 @@ TryCopyInitialization(Sema &S, Expr *From, QualType ToType, SuppressUserConversions, /*AllowExplicit=*/false); - return S.TryImplicitConversion(From, ToType, - SuppressUserConversions, - /*AllowExplicit=*/false, - InOverloadResolution); + return TryImplicitConversion(S, From, ToType, + SuppressUserConversions, + /*AllowExplicit=*/false, + InOverloadResolution); } /// TryObjectArgumentInitialization - Try to initialize the object /// parameter of the given member function (@c Method) from the /// expression @p From. -ImplicitConversionSequence -Sema::TryObjectArgumentInitialization(QualType OrigFromType, - CXXMethodDecl *Method, - CXXRecordDecl *ActingContext) { - QualType ClassType = Context.getTypeDeclType(ActingContext); +static ImplicitConversionSequence +TryObjectArgumentInitialization(Sema &S, QualType OrigFromType, + CXXMethodDecl *Method, + CXXRecordDecl *ActingContext) { + QualType ClassType = S.Context.getTypeDeclType(ActingContext); // [class.dtor]p2: A destructor can be invoked for a const, volatile or // const volatile object. unsigned Quals = isa(Method) ? Qualifiers::Const | Qualifiers::Volatile : Method->getTypeQualifiers(); - QualType ImplicitParamType = Context.getCVRQualifiedType(ClassType, Quals); + QualType ImplicitParamType = S.Context.getCVRQualifiedType(ClassType, Quals); // Set up the conversion sequence as a "bad" conversion, to allow us // to exit early. @@ -2972,7 +3091,7 @@ Sema::TryObjectArgumentInitialization(QualType OrigFromType, // First check the qualifiers. We don't care about lvalue-vs-rvalue // with the implicit object parameter (C++ [over.match.funcs]p5). - QualType FromTypeCanon = Context.getCanonicalType(FromType); + QualType FromTypeCanon = S.Context.getCanonicalType(FromType); if (ImplicitParamType.getCVRQualifiers() != FromTypeCanon.getLocalCVRQualifiers() && !ImplicitParamType.isAtLeastAsQualifiedAs(FromTypeCanon)) { @@ -2983,11 +3102,11 @@ Sema::TryObjectArgumentInitialization(QualType OrigFromType, // Check that we have either the same type or a derived type. It // affects the conversion rank. - QualType ClassTypeCanon = Context.getCanonicalType(ClassType); + QualType ClassTypeCanon = S.Context.getCanonicalType(ClassType); ImplicitConversionKind SecondKind; if (ClassTypeCanon == FromTypeCanon.getLocalUnqualifiedType()) { SecondKind = ICK_Identity; - } else if (IsDerivedFrom(FromType, ClassType)) + } else if (S.IsDerivedFrom(FromType, ClassType)) SecondKind = ICK_Derived_To_Base; else { ICS.setBad(BadConversionSequence::unrelated_class, @@ -3030,7 +3149,7 @@ Sema::PerformObjectArgumentInitialization(Expr *&From, // Note that we always use the true parent context when performing // the actual argument initialization. ImplicitConversionSequence ICS - = TryObjectArgumentInitialization(From->getType(), Method, + = TryObjectArgumentInitialization(*this, From->getType(), Method, Method->getParent()); if (ICS.isBad()) return Diag(From->getSourceRange().getBegin(), @@ -3041,16 +3160,17 @@ Sema::PerformObjectArgumentInitialization(Expr *&From, return PerformObjectMemberConversion(From, Qualifier, FoundDecl, Method); if (!Context.hasSameType(From->getType(), DestType)) - ImpCastExprToType(From, DestType, CastExpr::CK_NoOp, - /*isLvalue=*/!From->getType()->isPointerType()); + ImpCastExprToType(From, DestType, CK_NoOp, + From->getType()->isPointerType() ? VK_RValue : VK_LValue); return false; } /// TryContextuallyConvertToBool - Attempt to contextually convert the /// expression From to bool (C++0x [conv]p3). -ImplicitConversionSequence Sema::TryContextuallyConvertToBool(Expr *From) { +static ImplicitConversionSequence +TryContextuallyConvertToBool(Sema &S, Expr *From) { // FIXME: This is pretty broken. - return TryImplicitConversion(From, Context.BoolTy, + return TryImplicitConversion(S, From, S.Context.BoolTy, // FIXME: Are these flags correct? /*SuppressUserConversions=*/false, /*AllowExplicit=*/true, @@ -3060,7 +3180,7 @@ ImplicitConversionSequence Sema::TryContextuallyConvertToBool(Expr *From) { /// PerformContextuallyConvertToBool - Perform a contextual conversion /// of the expression From to bool (C++0x [conv]p3). bool Sema::PerformContextuallyConvertToBool(Expr *&From) { - ImplicitConversionSequence ICS = TryContextuallyConvertToBool(From); + ImplicitConversionSequence ICS = TryContextuallyConvertToBool(*this, From); if (!ICS.isBad()) return PerformImplicitConversion(From, Context.BoolTy, ICS, AA_Converting); @@ -3073,20 +3193,21 @@ bool Sema::PerformContextuallyConvertToBool(Expr *&From) { /// TryContextuallyConvertToObjCId - Attempt to contextually convert the /// expression From to 'id'. -ImplicitConversionSequence Sema::TryContextuallyConvertToObjCId(Expr *From) { - QualType Ty = Context.getObjCIdType(); - return TryImplicitConversion(From, Ty, - // FIXME: Are these flags correct? - /*SuppressUserConversions=*/false, - /*AllowExplicit=*/true, - /*InOverloadResolution=*/false); +static ImplicitConversionSequence +TryContextuallyConvertToObjCId(Sema &S, Expr *From) { + QualType Ty = S.Context.getObjCIdType(); + return TryImplicitConversion(S, From, Ty, + // FIXME: Are these flags correct? + /*SuppressUserConversions=*/false, + /*AllowExplicit=*/true, + /*InOverloadResolution=*/false); } - + /// PerformContextuallyConvertToObjCId - Perform a contextual conversion /// of the expression From to 'id'. bool Sema::PerformContextuallyConvertToObjCId(Expr *&From) { QualType Ty = Context.getObjCIdType(); - ImplicitConversionSequence ICS = TryContextuallyConvertToObjCId(From); + ImplicitConversionSequence ICS = TryContextuallyConvertToObjCId(*this, From); if (!ICS.isBad()) return PerformImplicitConversion(From, Ty, ICS, AA_Converting); return true; @@ -3128,8 +3249,8 @@ bool Sema::PerformContextuallyConvertToObjCId(Expr *&From) { /// /// \returns The expression, converted to an integral or enumeration type if /// successful. -Sema::OwningExprResult -Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, ExprArg FromE, +ExprResult +Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From, const PartialDiagnostic &NotIntDiag, const PartialDiagnostic &IncompleteDiag, const PartialDiagnostic &ExplicitConvDiag, @@ -3137,16 +3258,14 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, ExprArg FromE, const PartialDiagnostic &AmbigDiag, const PartialDiagnostic &AmbigNote, const PartialDiagnostic &ConvDiag) { - Expr *From = static_cast(FromE.get()); - // We can't perform any more checking for type-dependent expressions. if (From->isTypeDependent()) - return move(FromE); + return Owned(From); // If the expression already has integral or enumeration type, we're golden. QualType T = From->getType(); if (T->isIntegralOrEnumerationType()) - return move(FromE); + return Owned(From); // FIXME: Check for missing '()' if T is a function type? @@ -3156,12 +3275,12 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, ExprArg FromE, if (!RecordTy || !getLangOptions().CPlusPlus) { Diag(Loc, NotIntDiag) << T << From->getSourceRange(); - return move(FromE); + return Owned(From); } // We must have a complete class type. if (RequireCompleteType(Loc, T, IncompleteDiag)) - return move(FromE); + return Owned(From); // Look for a conversion to an integral or enumeration type. UnresolvedSet<4> ViableConversions; @@ -3213,8 +3332,7 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, ExprArg FromE, return ExprError(); CheckMemberOperatorAccess(From->getExprLoc(), From, 0, Found); - From = BuildCXXMemberCallExpr(FromE.takeAs(), Found, Conversion); - FromE = Owned(From); + From = BuildCXXMemberCallExpr(From, Found, Conversion); } // We'll complain below about a non-integral condition type. @@ -3237,9 +3355,8 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, ExprArg FromE, << T << ConvTy->isEnumeralType() << ConvTy << From->getSourceRange(); } - From = BuildCXXMemberCallExpr(FromE.takeAs(), Found, + From = BuildCXXMemberCallExpr(From, Found, cast(Found->getUnderlyingDecl())); - FromE = Owned(From); break; } @@ -3253,14 +3370,14 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, ExprArg FromE, Diag(Conv->getLocation(), AmbigNote) << ConvTy->isEnumeralType() << ConvTy; } - return move(FromE); + return Owned(From); } if (!From->getType()->isIntegralOrEnumerationType()) Diag(Loc, NotIntDiag) << From->getType() << From->getSourceRange(); - return move(FromE); + return Owned(From); } /// AddOverloadCandidate - Adds the given function to the set of @@ -3306,7 +3423,7 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, return; // Overload resolution is always an unevaluated context. - EnterExpressionEvaluationContext Unevaluated(*this, Action::Unevaluated); + EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated); if (CXXConstructorDecl *Constructor = dyn_cast(Function)){ // C++ [class.copy]p3: @@ -3469,7 +3586,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, return; // Overload resolution is always an unevaluated context. - EnterExpressionEvaluationContext Unevaluated(*this, Action::Unevaluated); + EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated); // Add this candidate CandidateSet.push_back(OverloadCandidate()); @@ -3513,7 +3630,8 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, // Determine the implicit conversion sequence for the object // parameter. Candidate.Conversions[0] - = TryObjectArgumentInitialization(ObjectType, Method, ActingContext); + = TryObjectArgumentInitialization(*this, ObjectType, Method, + ActingContext); if (Candidate.Conversions[0].isBad()) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_bad_conversion; @@ -3666,7 +3784,7 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion, return; // Overload resolution is always an unevaluated context. - EnterExpressionEvaluationContext Unevaluated(*this, Action::Unevaluated); + EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated); // Add this candidate CandidateSet.push_back(OverloadCandidate()); @@ -3678,25 +3796,32 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion, Candidate.FinalConversion.setAsIdentityConversion(); Candidate.FinalConversion.setFromType(ConvType); Candidate.FinalConversion.setAllToTypes(ToType); + Candidate.Viable = true; + Candidate.Conversions.resize(1); + // C++ [over.match.funcs]p4: + // For conversion functions, the function is considered to be a member of + // the class of the implicit implied object argument for the purpose of + // defining the type of the implicit object parameter. + // // Determine the implicit conversion sequence for the implicit // object parameter. - Candidate.Viable = true; - Candidate.Conversions.resize(1); + QualType ImplicitParamType = From->getType(); + if (const PointerType *FromPtrType = ImplicitParamType->getAs()) + ImplicitParamType = FromPtrType->getPointeeType(); + CXXRecordDecl *ConversionContext + = cast(ImplicitParamType->getAs()->getDecl()); + Candidate.Conversions[0] - = TryObjectArgumentInitialization(From->getType(), Conversion, - ActingContext); - // Conversion functions to a different type in the base class is visible in - // the derived class. So, a derived to base conversion should not participate - // in overload resolution. - if (Candidate.Conversions[0].Standard.Second == ICK_Derived_To_Base) - Candidate.Conversions[0].Standard.Second = ICK_Identity; + = TryObjectArgumentInitialization(*this, From->getType(), Conversion, + ConversionContext); + if (Candidate.Conversions[0].isBad()) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_bad_conversion; return; } - + // We won't go through a user-define type conversion function to convert a // derived to base as such conversions are given Conversion Rank. They only // go through a copy constructor. 13.3.3.1.2-p4 [over.ics.user] @@ -3719,9 +3844,10 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion, // well-formed. DeclRefExpr ConversionRef(Conversion, Conversion->getType(), From->getLocStart()); - ImplicitCastExpr ConversionFn(Context.getPointerType(Conversion->getType()), - CastExpr::CK_FunctionToPointerDecay, - &ConversionRef, CXXBaseSpecifierArray(), false); + ImplicitCastExpr ConversionFn(ImplicitCastExpr::OnStack, + Context.getPointerType(Conversion->getType()), + CK_FunctionToPointerDecay, + &ConversionRef, VK_RValue); // Note that it is safe to allocate CallExpr on the stack here because // there are 0 arguments (i.e., nothing is allocated using ASTContext's @@ -3819,7 +3945,7 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion, return; // Overload resolution is always an unevaluated context. - EnterExpressionEvaluationContext Unevaluated(*this, Action::Unevaluated); + EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated); CandidateSet.push_back(OverloadCandidate()); OverloadCandidate& Candidate = CandidateSet.back(); @@ -3834,7 +3960,8 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion, // Determine the implicit conversion sequence for the implicit // object parameter. ImplicitConversionSequence ObjectInit - = TryObjectArgumentInitialization(ObjectType, Conversion, ActingContext); + = TryObjectArgumentInitialization(*this, ObjectType, Conversion, + ActingContext); if (ObjectInit.isBad()) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_bad_conversion; @@ -3925,9 +4052,6 @@ void Sema::AddMemberOperatorCandidates(OverloadedOperatorKind Op, // candidates, non-member candidates and built-in candidates, are // constructed as follows: QualType T1 = Args[0]->getType(); - QualType T2; - if (NumArgs > 1) - T2 = Args[1]->getType(); // -- If T1 is a class type, the set of member candidates is the // result of the qualified lookup of T1::operator@ @@ -3966,7 +4090,7 @@ void Sema::AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys, bool IsAssignmentOperator, unsigned NumContextualBoolArguments) { // Overload resolution is always an unevaluated context. - EnterExpressionEvaluationContext Unevaluated(*this, Action::Unevaluated); + EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated); // Add this candidate CandidateSet.push_back(OverloadCandidate()); @@ -3999,7 +4123,8 @@ void Sema::AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys, if (ArgIdx < NumContextualBoolArguments) { assert(ParamTys[ArgIdx] == Context.BoolTy && "Contextual conversion to bool requires bool type"); - Candidate.Conversions[ArgIdx] = TryContextuallyConvertToBool(Args[ArgIdx]); + Candidate.Conversions[ArgIdx] + = TryContextuallyConvertToBool(*this, Args[ArgIdx]); } else { Candidate.Conversions[ArgIdx] = TryCopyInitialization(*this, Args[ArgIdx], ParamTys[ArgIdx], @@ -4100,11 +4225,21 @@ BuiltinCandidateTypeSet::AddPointerWithMoreQualifiedTypeVariants(QualType Ty, // Insert this type. if (!PointerTypes.insert(Ty)) return false; - + + QualType PointeeTy; const PointerType *PointerTy = Ty->getAs(); - assert(PointerTy && "type was not a pointer type!"); - - QualType PointeeTy = PointerTy->getPointeeType(); + bool buildObjCPtr = false; + if (!PointerTy) { + if (const ObjCObjectPointerType *PTy = Ty->getAs()) { + PointeeTy = PTy->getPointeeType(); + buildObjCPtr = true; + } + else + assert(false && "type was not a pointer type!"); + } + else + PointeeTy = PointerTy->getPointeeType(); + // Don't add qualified variants of arrays. For one, they're not allowed // (the qualifier would sink to the element type), and for another, the // only overload situation where it matters is subscript or pointer +- int, @@ -4125,7 +4260,10 @@ BuiltinCandidateTypeSet::AddPointerWithMoreQualifiedTypeVariants(QualType Ty, if ((CVR & Qualifiers::Volatile) && !hasVolatile) continue; if ((CVR & Qualifiers::Restrict) && !hasRestrict) continue; QualType QPointeeTy = Context.getCVRQualifiedType(PointeeTy, CVR); - PointerTypes.insert(Context.getPointerType(QPointeeTy)); + if (!buildObjCPtr) + PointerTypes.insert(Context.getPointerType(QPointeeTy)); + else + PointerTypes.insert(Context.getObjCObjectPointerType(QPointeeTy)); } return true; @@ -4200,10 +4338,9 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty, // If we're dealing with an array type, decay to the pointer. if (Ty->isArrayType()) Ty = SemaRef.Context.getArrayDecayedType(Ty); - - if (const PointerType *PointerTy = Ty->getAs()) { - QualType PointeeTy = PointerTy->getPointeeType(); - + if (Ty->isObjCIdType() || Ty->isObjCClassType()) + PointerTypes.insert(Ty); + else if (Ty->getAs() || Ty->getAs()) { // Insert our type, and its more-qualified variants, into the set // of types. if (!AddPointerWithMoreQualifiedTypeVariants(Ty, VisibleQuals)) @@ -4479,7 +4616,7 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, for (BuiltinCandidateTypeSet::iterator Ptr = CandidateTypes.pointer_begin(); Ptr != CandidateTypes.pointer_end(); ++Ptr) { // Skip pointer types that aren't pointers to object types. - if (!(*Ptr)->getAs()->getPointeeType()->isObjectType()) + if (!(*Ptr)->getPointeeType()->isIncompleteOrObjectType()) continue; QualType ParamTypes[2] = { @@ -4519,7 +4656,7 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, for (BuiltinCandidateTypeSet::iterator Ptr = CandidateTypes.pointer_begin(); Ptr != CandidateTypes.pointer_end(); ++Ptr) { QualType ParamTy = *Ptr; - QualType PointeeTy = ParamTy->getAs()->getPointeeType(); + QualType PointeeTy = ParamTy->getPointeeType(); AddBuiltinCandidate(Context.getLValueReferenceType(PointeeTy), &ParamTy, Args, 1, CandidateSet); } @@ -5000,7 +5137,7 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, for (BuiltinCandidateTypeSet::iterator Ptr = CandidateTypes.pointer_begin(); Ptr != CandidateTypes.pointer_end(); ++Ptr) { QualType ParamTypes[2] = { *Ptr, Context.getPointerDiffType() }; - QualType PointeeType = (*Ptr)->getAs()->getPointeeType(); + QualType PointeeType = (*Ptr)->getPointeeType(); QualType ResultTy = Context.getLValueReferenceType(PointeeType); // T& operator[](T*, ptrdiff_t) @@ -5028,18 +5165,16 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, QualType C1Ty = (*Ptr); QualType C1; QualifierCollector Q1; - if (const PointerType *PointerTy = C1Ty->getAs()) { - C1 = QualType(Q1.strip(PointerTy->getPointeeType()), 0); - if (!isa(C1)) - continue; - // heuristic to reduce number of builtin candidates in the set. - // Add volatile/restrict version only if there are conversions to a - // volatile/restrict type. - if (!VisibleTypeConversionsQuals.hasVolatile() && Q1.hasVolatile()) - continue; - if (!VisibleTypeConversionsQuals.hasRestrict() && Q1.hasRestrict()) - continue; - } + C1 = QualType(Q1.strip(C1Ty->getPointeeType()), 0); + if (!isa(C1)) + continue; + // heuristic to reduce number of builtin candidates in the set. + // Add volatile/restrict version only if there are conversions to a + // volatile/restrict type. + if (!VisibleTypeConversionsQuals.hasVolatile() && Q1.hasVolatile()) + continue; + if (!VisibleTypeConversionsQuals.hasRestrict() && Q1.hasRestrict()) + continue; for (BuiltinCandidateTypeSet::iterator MemPtr = CandidateTypes.member_pointer_begin(), MemPtrEnd = CandidateTypes.member_pointer_end(); @@ -5148,9 +5283,10 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, /// isBetterOverloadCandidate - Determines whether the first overload /// candidate is a better candidate than the second (C++ 13.3.3p1). bool -Sema::isBetterOverloadCandidate(const OverloadCandidate& Cand1, - const OverloadCandidate& Cand2, - SourceLocation Loc) { +isBetterOverloadCandidate(Sema &S, + const OverloadCandidate& Cand1, + const OverloadCandidate& Cand2, + SourceLocation Loc) { // Define viable functions to be better candidates than non-viable // functions. if (!Cand2.Viable) @@ -5176,7 +5312,8 @@ Sema::isBetterOverloadCandidate(const OverloadCandidate& Cand1, assert(Cand2.Conversions.size() == NumArgs && "Overload candidate mismatch"); bool HasBetterConversion = false; for (unsigned ArgIdx = StartArg; ArgIdx < NumArgs; ++ArgIdx) { - switch (CompareImplicitConversionSequences(Cand1.Conversions[ArgIdx], + switch (CompareImplicitConversionSequences(S, + Cand1.Conversions[ArgIdx], Cand2.Conversions[ArgIdx])) { case ImplicitConversionSequence::Better: // Cand1 has a better conversion sequence. @@ -5211,9 +5348,9 @@ Sema::isBetterOverloadCandidate(const OverloadCandidate& Cand1, if (Cand1.Function && Cand1.Function->getPrimaryTemplate() && Cand2.Function && Cand2.Function->getPrimaryTemplate()) if (FunctionTemplateDecl *BetterTemplate - = getMoreSpecializedTemplate(Cand1.Function->getPrimaryTemplate(), - Cand2.Function->getPrimaryTemplate(), - Loc, + = S.getMoreSpecializedTemplate(Cand1.Function->getPrimaryTemplate(), + Cand2.Function->getPrimaryTemplate(), + Loc, isa(Cand1.Function)? TPOC_Conversion : TPOC_Call)) return BetterTemplate == Cand1.Function->getPrimaryTemplate(); @@ -5227,7 +5364,8 @@ Sema::isBetterOverloadCandidate(const OverloadCandidate& Cand1, if (Cand1.Function && Cand2.Function && isa(Cand1.Function) && isa(Cand2.Function)) { - switch (CompareStandardConversionSequences(Cand1.FinalConversion, + switch (CompareStandardConversionSequences(S, + Cand1.FinalConversion, Cand2.FinalConversion)) { case ImplicitConversionSequence::Better: // Cand1 has a better conversion sequence. @@ -5258,32 +5396,28 @@ Sema::isBetterOverloadCandidate(const OverloadCandidate& Cand1, /// function, Best points to the candidate function found. /// /// \returns The result of overload resolution. -OverloadingResult Sema::BestViableFunction(OverloadCandidateSet& CandidateSet, - SourceLocation Loc, - OverloadCandidateSet::iterator& Best) { +OverloadingResult +OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc, + iterator& Best) { // Find the best viable function. - Best = CandidateSet.end(); - for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(); - Cand != CandidateSet.end(); ++Cand) { - if (Cand->Viable) { - if (Best == CandidateSet.end() || - isBetterOverloadCandidate(*Cand, *Best, Loc)) + Best = end(); + for (iterator Cand = begin(); Cand != end(); ++Cand) { + if (Cand->Viable) + if (Best == end() || isBetterOverloadCandidate(S, *Cand, *Best, Loc)) Best = Cand; - } } // If we didn't find any viable functions, abort. - if (Best == CandidateSet.end()) + if (Best == end()) return OR_No_Viable_Function; // Make sure that this function is better than every other viable // function. If not, we have an ambiguity. - for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(); - Cand != CandidateSet.end(); ++Cand) { + for (iterator Cand = begin(); Cand != end(); ++Cand) { if (Cand->Viable && Cand != Best && - !isBetterOverloadCandidate(*Best, *Cand, Loc)) { - Best = CandidateSet.end(); + !isBetterOverloadCandidate(S, *Best, *Cand, Loc)) { + Best = end(); return OR_Ambiguous; } } @@ -5301,7 +5435,7 @@ OverloadingResult Sema::BestViableFunction(OverloadCandidateSet& CandidateSet, // (clause 13), user-defined conversions (12.3.2), allocation function for // placement new (5.3.4), as well as non-default initialization (8.5). if (Best->Function) - MarkDeclarationReferenced(Loc, Best->Function); + S.MarkDeclarationReferenced(Loc, Best->Function); return OR_Success; } @@ -5365,14 +5499,15 @@ void Sema::NoteOverloadCandidate(FunctionDecl *Fn) { /// Diagnoses an ambiguous conversion. The partial diagnostic is the /// "lead" diagnostic; it will be given two arguments, the source and /// target types of the conversion. -void Sema::DiagnoseAmbiguousConversion(const ImplicitConversionSequence &ICS, - SourceLocation CaretLoc, - const PartialDiagnostic &PDiag) { - Diag(CaretLoc, PDiag) - << ICS.Ambiguous.getFromType() << ICS.Ambiguous.getToType(); +void ImplicitConversionSequence::DiagnoseAmbiguousConversion( + Sema &S, + SourceLocation CaretLoc, + const PartialDiagnostic &PDiag) const { + S.Diag(CaretLoc, PDiag) + << Ambiguous.getFromType() << Ambiguous.getToType(); for (AmbiguousConversionSequence::const_iterator - I = ICS.Ambiguous.begin(), E = ICS.Ambiguous.end(); I != E; ++I) { - NoteOverloadCandidate(*I); + I = Ambiguous.begin(), E = Ambiguous.end(); I != E; ++I) { + S.NoteOverloadCandidate(*I); } } @@ -5589,8 +5724,31 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand, return; } - case Sema::TDK_Inconsistent: - case Sema::TDK_InconsistentQuals: { + case Sema::TDK_Underqualified: { + assert(ParamD && "no parameter found for bad qualifiers deduction result"); + TemplateTypeParmDecl *TParam = cast(ParamD); + + QualType Param = Cand->DeductionFailure.getFirstArg()->getAsType(); + + // Param will have been canonicalized, but it should just be a + // qualified version of ParamD, so move the qualifiers to that. + QualifierCollector Qs(S.Context); + Qs.strip(Param); + QualType NonCanonParam = Qs.apply(TParam->getTypeForDecl()); + assert(S.Context.hasSameType(Param, NonCanonParam)); + + // Arg has also been canonicalized, but there's nothing we can do + // about that. It also doesn't matter as much, because it won't + // have any template parameters in it (because deduction isn't + // done on dependent types). + QualType Arg = Cand->DeductionFailure.getSecondArg()->getAsType(); + + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_underqualified) + << ParamD->getDeclName() << Arg << NonCanonParam; + return; + } + + case Sema::TDK_Inconsistent: { assert(ParamD && "no parameter found for inconsistent deduction result"); int which = 0; if (isa(ParamD)) @@ -5779,7 +5937,7 @@ void NoteAmbiguousUserConversions(Sema &S, SourceLocation OpLoc, if (ICS.isBad()) break; // all meaningless after first invalid if (!ICS.isAmbiguous()) continue; - S.DiagnoseAmbiguousConversion(ICS, OpLoc, + ICS.DiagnoseAmbiguousConversion(S, OpLoc, S.PDiag(diag::note_ambiguous_type_conversion)); } } @@ -5808,8 +5966,8 @@ struct CompareOverloadCandidatesForDisplay { // TODO: introduce a tri-valued comparison for overload // candidates. Would be more worthwhile if we had a sort // that could exploit it. - if (S.isBetterOverloadCandidate(*L, *R, SourceLocation())) return true; - if (S.isBetterOverloadCandidate(*R, *L, SourceLocation())) return false; + if (isBetterOverloadCandidate(S, *L, *R, SourceLocation())) return true; + if (isBetterOverloadCandidate(S, *R, *L, SourceLocation())) return false; } else if (R->Viable) return false; @@ -5838,8 +5996,9 @@ struct CompareOverloadCandidatesForDisplay { int leftBetter = 0; unsigned I = (L->IgnoreObjectArgument || R->IgnoreObjectArgument); for (unsigned E = L->Conversions.size(); I != E; ++I) { - switch (S.CompareImplicitConversionSequences(L->Conversions[I], - R->Conversions[I])) { + switch (CompareImplicitConversionSequences(S, + L->Conversions[I], + R->Conversions[I])) { case ImplicitConversionSequence::Better: leftBetter++; break; @@ -5947,23 +6106,20 @@ void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand, /// PrintOverloadCandidates - When overload resolution fails, prints /// diagnostic messages containing the candidates in the candidate /// set. -void -Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet, - OverloadCandidateDisplayKind OCD, - Expr **Args, unsigned NumArgs, - const char *Opc, - SourceLocation OpLoc) { +void OverloadCandidateSet::NoteCandidates(Sema &S, + OverloadCandidateDisplayKind OCD, + Expr **Args, unsigned NumArgs, + const char *Opc, + SourceLocation OpLoc) { // Sort the candidates by viability and position. Sorting directly would // be prohibitive, so we make a set of pointers and sort those. llvm::SmallVector Cands; - if (OCD == OCD_AllCandidates) Cands.reserve(CandidateSet.size()); - for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(), - LastCand = CandidateSet.end(); - Cand != LastCand; ++Cand) { + if (OCD == OCD_AllCandidates) Cands.reserve(size()); + for (iterator Cand = begin(), LastCand = end(); Cand != LastCand; ++Cand) { if (Cand->Viable) Cands.push_back(Cand); else if (OCD == OCD_AllCandidates) { - CompleteNonViableCandidate(*this, Cand, Args, NumArgs); + CompleteNonViableCandidate(S, Cand, Args, NumArgs); if (Cand->Function || Cand->IsSurrogate) Cands.push_back(Cand); // Otherwise, this a non-viable builtin candidate. We do not, in general, @@ -5972,12 +6128,12 @@ Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet, } std::sort(Cands.begin(), Cands.end(), - CompareOverloadCandidatesForDisplay(*this)); + CompareOverloadCandidatesForDisplay(S)); bool ReportedAmbiguousConversions = false; llvm::SmallVectorImpl::iterator I, E; - const Diagnostic::OverloadsShown ShowOverloads = Diags.getShowOverloads(); + const Diagnostic::OverloadsShown ShowOverloads = S.Diags.getShowOverloads(); unsigned CandsShown = 0; for (I = Cands.begin(), E = Cands.end(); I != E; ++I) { OverloadCandidate *Cand = *I; @@ -5991,9 +6147,9 @@ Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet, ++CandsShown; if (Cand->Function) - NoteFunctionCandidate(*this, Cand, Args, NumArgs); + NoteFunctionCandidate(S, Cand, Args, NumArgs); else if (Cand->IsSurrogate) - NoteSurrogateCandidate(*this, Cand); + NoteSurrogateCandidate(S, Cand); else { assert(Cand->Viable && "Non-viable built-in candidates are not added to Cands."); @@ -6004,17 +6160,17 @@ Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet, // FIXME: It's quite possible for different conversions to see // different ambiguities, though. if (!ReportedAmbiguousConversions) { - NoteAmbiguousUserConversions(*this, OpLoc, Cand); + NoteAmbiguousUserConversions(S, OpLoc, Cand); ReportedAmbiguousConversions = true; } // If this is a viable builtin, print it. - NoteBuiltinOperatorCandidate(*this, Opc, OpLoc, Cand); + NoteBuiltinOperatorCandidate(S, Opc, OpLoc, Cand); } } if (I != E) - Diag(OpLoc, diag::note_ovl_too_many_candidates) << int(E - I); + S.Diag(OpLoc, diag::note_ovl_too_many_candidates) << int(E - I); } static bool CheckUnresolvedAccess(Sema &S, OverloadExpr *E, DeclAccessPair D) { @@ -6061,12 +6217,13 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, // C++ [over.over]p1: // [...] The overloaded function name can be preceded by the & // operator. - OverloadExpr *OvlExpr = OverloadExpr::find(From).getPointer(); - TemplateArgumentListInfo ETABuffer, *ExplicitTemplateArgs = 0; - if (OvlExpr->hasExplicitTemplateArgs()) { - OvlExpr->getExplicitTemplateArgs().copyInto(ETABuffer); - ExplicitTemplateArgs = &ETABuffer; - } + // However, remember whether the expression has member-pointer form: + // C++ [expr.unary.op]p4: + // A pointer to member is only formed when an explicit & is used + // and its operand is a qualified-id not enclosed in + // parentheses. + OverloadExpr::FindResult Ovl = OverloadExpr::find(From); + OverloadExpr *OvlExpr = Ovl.Expression; // We expect a pointer or reference to function, or a function pointer. FunctionType = Context.getCanonicalType(FunctionType).getUnqualifiedType(); @@ -6078,6 +6235,25 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, return 0; } + // If the overload expression doesn't have the form of a pointer to + // member, don't try to convert it to a pointer-to-member type. + if (IsMember && !Ovl.HasFormOfMemberPointer) { + if (!Complain) return 0; + + // TODO: Should we condition this on whether any functions might + // have matched, or is it more appropriate to do that in callers? + // TODO: a fixit wouldn't hurt. + Diag(OvlExpr->getNameLoc(), diag::err_addr_ovl_no_qualifier) + << ToType << OvlExpr->getSourceRange(); + return 0; + } + + TemplateArgumentListInfo ETABuffer, *ExplicitTemplateArgs = 0; + if (OvlExpr->hasExplicitTemplateArgs()) { + OvlExpr->getExplicitTemplateArgs().copyInto(ETABuffer); + ExplicitTemplateArgs = &ETABuffer; + } + assert(From->getType() == Context.OverloadTy); // Look through all of the overloaded functions, searching for one @@ -6267,7 +6443,7 @@ FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From) { if (From->getType() != Context.OverloadTy) return 0; - OverloadExpr *OvlExpr = OverloadExpr::find(From).getPointer(); + OverloadExpr *OvlExpr = OverloadExpr::find(From).Expression; // If we didn't actually find any template-ids, we're done. if (!OvlExpr->hasExplicitTemplateArgs()) @@ -6405,18 +6581,10 @@ void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE, PartialOverloading); } -static Sema::OwningExprResult Destroy(Sema &SemaRef, Expr *Fn, - Expr **Args, unsigned NumArgs) { - Fn->Destroy(SemaRef.Context); - for (unsigned Arg = 0; Arg < NumArgs; ++Arg) - Args[Arg]->Destroy(SemaRef.Context); - return SemaRef.ExprError(); -} - /// Attempts to recover from a call where no functions were found. /// /// Returns true if new candidates were found. -static Sema::OwningExprResult +static ExprResult BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, SourceLocation LParenLoc, @@ -6440,13 +6608,13 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, LookupResult R(SemaRef, ULE->getName(), ULE->getNameLoc(), Sema::LookupOrdinaryName); if (SemaRef.DiagnoseEmptyLookup(S, SS, R, Sema::CTC_Expression)) - return Destroy(SemaRef, Fn, Args, NumArgs); + return ExprError(); assert(!R.empty() && "lookup results empty despite recovery"); // Build an implicit member call if appropriate. Just drop the // casts and such from the call, we don't really care. - Sema::OwningExprResult NewFn = SemaRef.ExprError(); + ExprResult NewFn = ExprError(); if ((*R.begin())->isCXXClassMember()) NewFn = SemaRef.BuildPossibleImplicitMemberExpr(SS, R, ExplicitTemplateArgs); else if (ExplicitTemplateArgs) @@ -6455,15 +6623,13 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, NewFn = SemaRef.BuildDeclarationNameExpr(SS, R, false); if (NewFn.isInvalid()) - return Destroy(SemaRef, Fn, Args, NumArgs); - - Fn->Destroy(SemaRef.Context); + return ExprError(); // This shouldn't cause an infinite loop because we're giving it // an expression with non-empty lookup results, which should never // end up here. - return SemaRef.ActOnCallExpr(/*Scope*/ 0, move(NewFn), LParenLoc, - Sema::MultiExprArg(SemaRef, (void**) Args, NumArgs), + return SemaRef.ActOnCallExpr(/*Scope*/ 0, NewFn.take(), LParenLoc, + MultiExprArg(Args, NumArgs), CommaLocs, RParenLoc); } @@ -6474,7 +6640,7 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, /// the function declaration produced by overload /// resolution. Otherwise, emits diagnostics, deletes all of the /// arguments and Fn, and returns NULL. -Sema::OwningExprResult +ExprResult Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, SourceLocation LParenLoc, Expr **Args, unsigned NumArgs, @@ -6512,7 +6678,7 @@ Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, CommaLocs, RParenLoc); OverloadCandidateSet::iterator Best; - switch (BestViableFunction(CandidateSet, Fn->getLocStart(), Best)) { + switch (CandidateSet.BestViableFunction(*this, Fn->getLocStart(), Best)) { case OR_Success: { FunctionDecl *FDecl = Best->Function; CheckUnresolvedLookupAccess(ULE, Best->FoundDecl); @@ -6525,13 +6691,13 @@ Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, Diag(Fn->getSourceRange().getBegin(), diag::err_ovl_no_viable_function_in_call) << ULE->getName() << Fn->getSourceRange(); - PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, Args, NumArgs); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); break; case OR_Ambiguous: Diag(Fn->getSourceRange().getBegin(), diag::err_ovl_ambiguous_call) << ULE->getName() << Fn->getSourceRange(); - PrintOverloadCandidates(CandidateSet, OCD_ViableCandidates, Args, NumArgs); + CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args, NumArgs); break; case OR_Deleted: @@ -6539,15 +6705,11 @@ Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, << Best->Function->isDeleted() << ULE->getName() << Fn->getSourceRange(); - PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, Args, NumArgs); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); break; } - // Overload resolution failed. Destroy all of the subexpressions and - // return NULL. - Fn->Destroy(Context); - for (unsigned Arg = 0; Arg < NumArgs; ++Arg) - Args[Arg]->Destroy(Context); + // Overload resolution failed. return ExprError(); } @@ -6572,16 +6734,17 @@ static bool IsOverloaded(const UnresolvedSetImpl &Functions) { /// by CreateOverloadedUnaryOp(). /// /// \param input The input argument. -Sema::OwningExprResult +ExprResult Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, const UnresolvedSetImpl &Fns, - ExprArg input) { + Expr *Input) { UnaryOperator::Opcode Opc = static_cast(OpcIn); - Expr *Input = (Expr *)input.get(); OverloadedOperatorKind Op = UnaryOperator::getOverloadedOperator(Opc); assert(Op != OO_None && "Invalid opcode for overloaded unary operator"); DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op); + // TODO: provide better source location info. + DeclarationNameInfo OpNameInfo(OpName, OpLoc); Expr *Args[2] = { Input, 0 }; unsigned NumArgs = 1; @@ -6589,16 +6752,16 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, // For post-increment and post-decrement, add the implicit '0' as // the second argument, so that we know this is a post-increment or // post-decrement. - if (Opc == UnaryOperator::PostInc || Opc == UnaryOperator::PostDec) { + if (Opc == UO_PostInc || Opc == UO_PostDec) { llvm::APSInt Zero(Context.getTypeSize(Context.IntTy), false); - Args[1] = new (Context) IntegerLiteral(Zero, Context.IntTy, - SourceLocation()); + Args[1] = IntegerLiteral::Create(Context, Zero, Context.IntTy, + SourceLocation()); NumArgs = 2; } if (Input->isTypeDependent()) { if (Fns.empty()) - return Owned(new (Context) UnaryOperator(input.takeAs(), + return Owned(new (Context) UnaryOperator(Input, Opc, Context.DependentTy, OpLoc)); @@ -6606,10 +6769,9 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators UnresolvedLookupExpr *Fn = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true, NamingClass, - 0, SourceRange(), OpName, OpLoc, + 0, SourceRange(), OpNameInfo, /*ADL*/ true, IsOverloaded(Fns), Fns.begin(), Fns.end()); - input.release(); return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn, &Args[0], NumArgs, Context.DependentTy, @@ -6636,7 +6798,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, // Perform overload resolution. OverloadCandidateSet::iterator Best; - switch (BestViableFunction(CandidateSet, OpLoc, Best)) { + switch (CandidateSet.BestViableFunction(*this, OpLoc, Best)) { case OR_Success: { // We found a built-in operator or an overloaded operator. FunctionDecl *FnDecl = Best->Function; @@ -6654,16 +6816,14 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, return ExprError(); } else { // Convert the arguments. - OwningExprResult InputInit + ExprResult InputInit = PerformCopyInitialization(InitializedEntity::InitializeParameter( FnDecl->getParamDecl(0)), SourceLocation(), - move(input)); + Input); if (InputInit.isInvalid()) return ExprError(); - - input = move(InputInit); - Input = (Expr *)input.get(); + Input = InputInit.take(); } DiagnoseUseOfDecl(Best->FoundDecl, OpLoc); @@ -6676,17 +6836,16 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, SourceLocation()); UsualUnaryConversions(FnExpr); - input.release(); Args[0] = Input; - ExprOwningPtr TheCall(this, + CallExpr *TheCall = new (Context) CXXOperatorCallExpr(Context, Op, FnExpr, - Args, NumArgs, ResultTy, OpLoc)); + Args, NumArgs, ResultTy, OpLoc); - if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall.get(), + if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall, FnDecl)) return ExprError(); - return MaybeBindToTemporary(TheCall.release()); + return MaybeBindToTemporary(TheCall); } else { // We matched a built-in operator. Convert the arguments, then // break out so that we will build the appropriate built-in @@ -6708,8 +6867,9 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, Diag(OpLoc, diag::err_ovl_ambiguous_oper) << UnaryOperator::getOpcodeStr(Opc) << Input->getSourceRange(); - PrintOverloadCandidates(CandidateSet, OCD_ViableCandidates, Args, NumArgs, - UnaryOperator::getOpcodeStr(Opc), OpLoc); + CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, + Args, NumArgs, + UnaryOperator::getOpcodeStr(Opc), OpLoc); return ExprError(); case OR_Deleted: @@ -6717,15 +6877,14 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, << Best->Function->isDeleted() << UnaryOperator::getOpcodeStr(Opc) << Input->getSourceRange(); - PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, Args, NumArgs); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); return ExprError(); } // Either we found no viable overloaded operator or we matched a // built-in operator. In either case, fall through to trying to // build a built-in operation. - input.release(); - return CreateBuiltinUnaryOp(OpLoc, Opc, Owned(Input)); + return CreateBuiltinUnaryOp(OpLoc, Opc, Input); } /// \brief Create a binary operation that may resolve to an overloaded @@ -6745,7 +6904,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, /// /// \param LHS Left-hand argument. /// \param RHS Right-hand argument. -Sema::OwningExprResult +ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc, unsigned OpcIn, const UnresolvedSetImpl &Fns, @@ -6763,7 +6922,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, if (Fns.empty()) { // If there are no functions to store, just build a dependent // BinaryOperator or CompoundAssignment. - if (Opc <= BinaryOperator::Assign || Opc > BinaryOperator::OrAssign) + if (Opc <= BO_Assign || Opc > BO_OrAssign) return Owned(new (Context) BinaryOperator(Args[0], Args[1], Opc, Context.DependentTy, OpLoc)); @@ -6776,9 +6935,11 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // FIXME: save results of ADL from here? CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators + // TODO: provide better source location info in DNLoc component. + DeclarationNameInfo OpNameInfo(OpName, OpLoc); UnresolvedLookupExpr *Fn = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true, NamingClass, - 0, SourceRange(), OpName, OpLoc, + 0, SourceRange(), OpNameInfo, /*ADL*/ true, IsOverloaded(Fns), Fns.begin(), Fns.end()); return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn, @@ -6789,7 +6950,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // If this is the .* operator, which is not overloadable, just // create a built-in binary operator. - if (Opc == BinaryOperator::PtrMemD) + if (Opc == BO_PtrMemD) return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]); // If this is the assignment operator, we only perform overload resolution @@ -6798,7 +6959,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // various built-in candidates, but as DR507 points out, this can lead to // problems. So we do it this way, which pretty much follows what GCC does. // Note that we go the traditional code path for compound assignment forms. - if (Opc==BinaryOperator::Assign && !Args[0]->getType()->isOverloadableType()) + if (Opc == BO_Assign && !Args[0]->getType()->isOverloadableType()) return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]); // Build an empty overload set. @@ -6821,7 +6982,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // Perform overload resolution. OverloadCandidateSet::iterator Best; - switch (BestViableFunction(CandidateSet, OpLoc, Best)) { + switch (CandidateSet.BestViableFunction(*this, OpLoc, Best)) { case OR_Success: { // We found a built-in operator or an overloaded operator. FunctionDecl *FnDecl = Best->Function; @@ -6835,7 +6996,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // Best->Access is only meaningful for class members. CheckMemberOperatorAccess(OpLoc, Args[0], Args[1], Best->FoundDecl); - OwningExprResult Arg1 + ExprResult Arg1 = PerformCopyInitialization( InitializedEntity::InitializeParameter( FnDecl->getParamDecl(0)), @@ -6851,7 +7012,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, Args[1] = RHS = Arg1.takeAs(); } else { // Convert the arguments. - OwningExprResult Arg0 + ExprResult Arg0 = PerformCopyInitialization( InitializedEntity::InitializeParameter( FnDecl->getParamDecl(0)), @@ -6860,7 +7021,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, if (Arg0.isInvalid()) return ExprError(); - OwningExprResult Arg1 + ExprResult Arg1 = PerformCopyInitialization( InitializedEntity::InitializeParameter( FnDecl->getParamDecl(1)), @@ -6884,16 +7045,15 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, OpLoc); UsualUnaryConversions(FnExpr); - ExprOwningPtr - TheCall(this, new (Context) CXXOperatorCallExpr(Context, Op, FnExpr, - Args, 2, ResultTy, - OpLoc)); + CXXOperatorCallExpr *TheCall = + new (Context) CXXOperatorCallExpr(Context, Op, FnExpr, + Args, 2, ResultTy, OpLoc); - if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall.get(), + if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall, FnDecl)) return ExprError(); - return MaybeBindToTemporary(TheCall.release()); + return MaybeBindToTemporary(TheCall); } else { // We matched a built-in operator. Convert the arguments, then // break out so that we will build the appropriate built-in @@ -6913,15 +7073,15 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // If the operator is the operator , [...] and there are no // viable functions, then the operator is assumed to be the // built-in operator and interpreted according to clause 5. - if (Opc == BinaryOperator::Comma) + if (Opc == BO_Comma) break; // For class as left operand for assignment or compound assigment operator // do not fall through to handling in built-in, but report that no overloaded // assignment operator found - OwningExprResult Result = ExprError(); + ExprResult Result = ExprError(); if (Args[0]->getType()->isRecordType() && - Opc >= BinaryOperator::Assign && Opc <= BinaryOperator::OrAssign) { + Opc >= BO_Assign && Opc <= BO_OrAssign) { Diag(OpLoc, diag::err_ovl_no_viable_oper) << BinaryOperator::getOpcodeStr(Opc) << Args[0]->getSourceRange() << Args[1]->getSourceRange(); @@ -6933,8 +7093,8 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, assert(Result.isInvalid() && "C++ binary operator overloading is missing candidates!"); if (Result.isInvalid()) - PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, Args, 2, - BinaryOperator::getOpcodeStr(Opc), OpLoc); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, 2, + BinaryOperator::getOpcodeStr(Opc), OpLoc); return move(Result); } @@ -6942,8 +7102,8 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, Diag(OpLoc, diag::err_ovl_ambiguous_oper) << BinaryOperator::getOpcodeStr(Opc) << Args[0]->getSourceRange() << Args[1]->getSourceRange(); - PrintOverloadCandidates(CandidateSet, OCD_ViableCandidates, Args, 2, - BinaryOperator::getOpcodeStr(Opc), OpLoc); + CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args, 2, + BinaryOperator::getOpcodeStr(Opc), OpLoc); return ExprError(); case OR_Deleted: @@ -6951,7 +7111,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, << Best->Function->isDeleted() << BinaryOperator::getOpcodeStr(Opc) << Args[0]->getSourceRange() << Args[1]->getSourceRange(); - PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, Args, 2); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, 2); return ExprError(); } @@ -6959,12 +7119,11 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]); } -Action::OwningExprResult +ExprResult Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, SourceLocation RLoc, - ExprArg Base, ExprArg Idx) { - Expr *Args[2] = { static_cast(Base.get()), - static_cast(Idx.get()) }; + Expr *Base, Expr *Idx) { + Expr *Args[2] = { Base, Idx }; DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Subscript); @@ -6973,16 +7132,17 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, if (Args[0]->isTypeDependent() || Args[1]->isTypeDependent()) { CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators + // CHECKME: no 'operator' keyword? + DeclarationNameInfo OpNameInfo(OpName, LLoc); + OpNameInfo.setCXXOperatorNameRange(SourceRange(LLoc, RLoc)); UnresolvedLookupExpr *Fn = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true, NamingClass, - 0, SourceRange(), OpName, LLoc, + 0, SourceRange(), OpNameInfo, /*ADL*/ true, /*Overloaded*/ false, UnresolvedSetIterator(), UnresolvedSetIterator()); // Can't add any actual overloads yet - Base.release(); - Idx.release(); return Owned(new (Context) CXXOperatorCallExpr(Context, OO_Subscript, Fn, Args, 2, Context.DependentTy, @@ -7002,7 +7162,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, // Perform overload resolution. OverloadCandidateSet::iterator Best; - switch (BestViableFunction(CandidateSet, LLoc, Best)) { + switch (CandidateSet.BestViableFunction(*this, LLoc, Best)) { case OR_Success: { // We found a built-in operator or an overloaded operator. FunctionDecl *FnDecl = Best->Function; @@ -7021,7 +7181,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, return ExprError(); // Convert the arguments. - OwningExprResult InputInit + ExprResult InputInit = PerformCopyInitialization(InitializedEntity::InitializeParameter( FnDecl->getParamDecl(0)), SourceLocation(), @@ -7041,18 +7201,16 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, LLoc); UsualUnaryConversions(FnExpr); - Base.release(); - Idx.release(); - ExprOwningPtr - TheCall(this, new (Context) CXXOperatorCallExpr(Context, OO_Subscript, - FnExpr, Args, 2, - ResultTy, RLoc)); + CXXOperatorCallExpr *TheCall = + new (Context) CXXOperatorCallExpr(Context, OO_Subscript, + FnExpr, Args, 2, + ResultTy, RLoc); - if (CheckCallReturnType(FnDecl->getResultType(), LLoc, TheCall.get(), + if (CheckCallReturnType(FnDecl->getResultType(), LLoc, TheCall, FnDecl)) return ExprError(); - return MaybeBindToTemporary(TheCall.release()); + return MaybeBindToTemporary(TheCall); } else { // We matched a built-in operator. Convert the arguments, then // break out so that we will build the appropriate built-in @@ -7076,32 +7234,29 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, Diag(LLoc, diag::err_ovl_no_viable_subscript) << Args[0]->getType() << Args[0]->getSourceRange() << Args[1]->getSourceRange(); - PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, Args, 2, - "[]", LLoc); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, 2, + "[]", LLoc); return ExprError(); } case OR_Ambiguous: Diag(LLoc, diag::err_ovl_ambiguous_oper) << "[]" << Args[0]->getSourceRange() << Args[1]->getSourceRange(); - PrintOverloadCandidates(CandidateSet, OCD_ViableCandidates, Args, 2, - "[]", LLoc); + CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args, 2, + "[]", LLoc); return ExprError(); case OR_Deleted: Diag(LLoc, diag::err_ovl_deleted_oper) << Best->Function->isDeleted() << "[]" << Args[0]->getSourceRange() << Args[1]->getSourceRange(); - PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, Args, 2, - "[]", LLoc); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, 2, + "[]", LLoc); return ExprError(); } // We matched a built-in operator; build it. - Base.release(); - Idx.release(); - return CreateBuiltinArraySubscriptExpr(Owned(Args[0]), LLoc, - Owned(Args[1]), RLoc); + return CreateBuiltinArraySubscriptExpr(Args[0], LLoc, Args[1], RLoc); } /// BuildCallToMemberFunction - Build a call to a member @@ -7111,7 +7266,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, /// parameter). The caller needs to validate that the member /// expression refers to a member function or an overloaded member /// function. -Sema::OwningExprResult +ExprResult Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, SourceLocation LParenLoc, Expr **Args, unsigned NumArgs, SourceLocation *CommaLocs, @@ -7174,7 +7329,8 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, DeclarationName DeclName = UnresExpr->getMemberName(); OverloadCandidateSet::iterator Best; - switch (BestViableFunction(CandidateSet, UnresExpr->getLocStart(), Best)) { + switch (CandidateSet.BestViableFunction(*this, UnresExpr->getLocStart(), + Best)) { case OR_Success: Method = cast(Best->Function); FoundDecl = Best->FoundDecl; @@ -7186,14 +7342,14 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, Diag(UnresExpr->getMemberLoc(), diag::err_ovl_no_viable_member_function_in_call) << DeclName << MemExprE->getSourceRange(); - PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, Args, NumArgs); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); // FIXME: Leaking incoming expressions! return ExprError(); case OR_Ambiguous: Diag(UnresExpr->getMemberLoc(), diag::err_ovl_ambiguous_member_call) << DeclName << MemExprE->getSourceRange(); - PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, Args, NumArgs); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); // FIXME: Leaking incoming expressions! return ExprError(); @@ -7201,7 +7357,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, Diag(UnresExpr->getMemberLoc(), diag::err_ovl_deleted_member_call) << Best->Function->isDeleted() << DeclName << MemExprE->getSourceRange(); - PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, Args, NumArgs); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); // FIXME: Leaking incoming expressions! return ExprError(); } @@ -7219,15 +7375,14 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, } assert(Method && "Member call to something that isn't a method?"); - ExprOwningPtr - TheCall(this, new (Context) CXXMemberCallExpr(Context, MemExprE, Args, - NumArgs, - Method->getCallResultType(), - RParenLoc)); + CXXMemberCallExpr *TheCall = + new (Context) CXXMemberCallExpr(Context, MemExprE, Args, NumArgs, + Method->getCallResultType(), + RParenLoc); // Check for a valid return type. if (CheckCallReturnType(Method->getResultType(), MemExpr->getMemberLoc(), - TheCall.get(), Method)) + TheCall, Method)) return ExprError(); // Convert the object argument (for a non-static member function call). @@ -7242,21 +7397,21 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, // Convert the rest of the arguments const FunctionProtoType *Proto = Method->getType()->getAs(); - if (ConvertArgumentsForCall(&*TheCall, MemExpr, Method, Proto, Args, NumArgs, + if (ConvertArgumentsForCall(TheCall, MemExpr, Method, Proto, Args, NumArgs, RParenLoc)) return ExprError(); - if (CheckFunctionCall(Method, TheCall.get())) + if (CheckFunctionCall(Method, TheCall)) return ExprError(); - return MaybeBindToTemporary(TheCall.release()); + return MaybeBindToTemporary(TheCall); } /// BuildCallToObjectOfClassType - Build a call to an object of class /// type (C++ [over.call.object]), which can end up invoking an /// overloaded function call operator (@c operator()) or performing a /// user-defined conversion on the object argument. -Sema::ExprResult +ExprResult Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, SourceLocation LParenLoc, Expr **Args, unsigned NumArgs, @@ -7338,7 +7493,8 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, // Perform overload resolution. OverloadCandidateSet::iterator Best; - switch (BestViableFunction(CandidateSet, Object->getLocStart(), Best)) { + switch (CandidateSet.BestViableFunction(*this, Object->getLocStart(), + Best)) { case OR_Success: // Overload resolution succeeded; we'll build the appropriate call // below. @@ -7353,14 +7509,14 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, Diag(Object->getSourceRange().getBegin(), diag::err_ovl_no_viable_object_call) << Object->getType() << Object->getSourceRange(); - PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, Args, NumArgs); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); break; case OR_Ambiguous: Diag(Object->getSourceRange().getBegin(), diag::err_ovl_ambiguous_object_call) << Object->getType() << Object->getSourceRange(); - PrintOverloadCandidates(CandidateSet, OCD_ViableCandidates, Args, NumArgs); + CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args, NumArgs); break; case OR_Deleted: @@ -7368,18 +7524,12 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, diag::err_ovl_deleted_object_call) << Best->Function->isDeleted() << Object->getType() << Object->getSourceRange(); - PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, Args, NumArgs); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); break; } - if (Best == CandidateSet.end()) { - // We had an error; delete all of the subexpressions and return - // the error. - Object->Destroy(Context); - for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) - Args[ArgIdx]->Destroy(Context); + if (Best == CandidateSet.end()) return true; - } if (Best->Function == 0) { // Since there is no function declaration, this is one of the @@ -7400,9 +7550,8 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, CXXMemberCallExpr *CE = BuildCXXMemberCallExpr(Object, Best->FoundDecl, Conv); - return ActOnCallExpr(S, ExprArg(*this, CE), LParenLoc, - MultiExprArg(*this, (ExprTy**)Args, NumArgs), - CommaLocs, RParenLoc).result(); + return ActOnCallExpr(S, CE, LParenLoc, MultiExprArg(Args, NumArgs), + CommaLocs, RParenLoc); } CheckMemberOperatorAccess(LParenLoc, Object, 0, Best->FoundDecl); @@ -7438,13 +7587,13 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, // Once we've built TheCall, all of the expressions are properly // owned. QualType ResultTy = Method->getCallResultType(); - ExprOwningPtr - TheCall(this, new (Context) CXXOperatorCallExpr(Context, OO_Call, NewFn, - MethodArgs, NumArgs + 1, - ResultTy, RParenLoc)); + CXXOperatorCallExpr *TheCall = + new (Context) CXXOperatorCallExpr(Context, OO_Call, NewFn, + MethodArgs, NumArgs + 1, + ResultTy, RParenLoc); delete [] MethodArgs; - if (CheckCallReturnType(Method->getResultType(), LParenLoc, TheCall.get(), + if (CheckCallReturnType(Method->getResultType(), LParenLoc, TheCall, Method)) return true; @@ -7471,15 +7620,15 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, // Pass the argument. - OwningExprResult InputInit + ExprResult InputInit = PerformCopyInitialization(InitializedEntity::InitializeParameter( Method->getParamDecl(i)), - SourceLocation(), Owned(Arg)); + SourceLocation(), Arg); IsError |= InputInit.isInvalid(); Arg = InputInit.takeAs(); } else { - OwningExprResult DefArg + ExprResult DefArg = BuildCXXDefaultArgExpr(LParenLoc, Method, Method->getParamDecl(i)); if (DefArg.isInvalid()) { IsError = true; @@ -7504,18 +7653,17 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, if (IsError) return true; - if (CheckFunctionCall(Method, TheCall.get())) + if (CheckFunctionCall(Method, TheCall)) return true; - return MaybeBindToTemporary(TheCall.release()).result(); + return MaybeBindToTemporary(TheCall); } /// BuildOverloadedArrowExpr - Build a call to an overloaded @c operator-> /// (if one exists), where @c Base is an expression of class type and /// @c Member is the name of the member we're trying to find. -Sema::OwningExprResult -Sema::BuildOverloadedArrowExpr(Scope *S, ExprArg BaseIn, SourceLocation OpLoc) { - Expr *Base = static_cast(BaseIn.get()); +ExprResult +Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) { assert(Base->getType()->isRecordType() && "left-hand side must have class type"); SourceLocation Loc = Base->getExprLoc(); @@ -7547,7 +7695,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, ExprArg BaseIn, SourceLocation OpLoc) { // Perform overload resolution. OverloadCandidateSet::iterator Best; - switch (BestViableFunction(CandidateSet, OpLoc, Best)) { + switch (CandidateSet.BestViableFunction(*this, OpLoc, Best)) { case OR_Success: // Overload resolution succeeded; we'll build the call below. break; @@ -7559,20 +7707,20 @@ Sema::BuildOverloadedArrowExpr(Scope *S, ExprArg BaseIn, SourceLocation OpLoc) { else Diag(OpLoc, diag::err_ovl_no_viable_oper) << "operator->" << Base->getSourceRange(); - PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, &Base, 1); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, &Base, 1); return ExprError(); case OR_Ambiguous: Diag(OpLoc, diag::err_ovl_ambiguous_oper) << "->" << Base->getSourceRange(); - PrintOverloadCandidates(CandidateSet, OCD_ViableCandidates, &Base, 1); + CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, &Base, 1); return ExprError(); case OR_Deleted: Diag(OpLoc, diag::err_ovl_deleted_oper) << Best->Function->isDeleted() << "->" << Base->getSourceRange(); - PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, &Base, 1); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, &Base, 1); return ExprError(); } @@ -7585,23 +7733,20 @@ Sema::BuildOverloadedArrowExpr(Scope *S, ExprArg BaseIn, SourceLocation OpLoc) { Best->FoundDecl, Method)) return ExprError(); - // No concerns about early exits now. - BaseIn.release(); - // Build the operator call. Expr *FnExpr = new (Context) DeclRefExpr(Method, Method->getType(), SourceLocation()); UsualUnaryConversions(FnExpr); QualType ResultTy = Method->getCallResultType(); - ExprOwningPtr - TheCall(this, new (Context) CXXOperatorCallExpr(Context, OO_Arrow, FnExpr, - &Base, 1, ResultTy, OpLoc)); + CXXOperatorCallExpr *TheCall = + new (Context) CXXOperatorCallExpr(Context, OO_Arrow, FnExpr, + &Base, 1, ResultTy, OpLoc); - if (CheckCallReturnType(Method->getResultType(), OpLoc, TheCall.get(), + if (CheckCallReturnType(Method->getResultType(), OpLoc, TheCall, Method)) return ExprError(); - return move(TheCall); + return Owned(TheCall); } /// FixOverloadedFunctionReference - E is an expression that refers to @@ -7626,17 +7771,18 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, assert(Context.hasSameType(ICE->getSubExpr()->getType(), SubExpr->getType()) && "Implicit cast type cannot be determined from overload"); + assert(ICE->path_empty() && "fixing up hierarchy conversion?"); if (SubExpr == ICE->getSubExpr()) return ICE->Retain(); - return new (Context) ImplicitCastExpr(ICE->getType(), - ICE->getCastKind(), - SubExpr, CXXBaseSpecifierArray(), - ICE->isLvalueCast()); + return ImplicitCastExpr::Create(Context, ICE->getType(), + ICE->getCastKind(), + SubExpr, 0, + ICE->getValueKind()); } if (UnaryOperator *UnOp = dyn_cast(E)) { - assert(UnOp->getOpcode() == UnaryOperator::AddrOf && + assert(UnOp->getOpcode() == UO_AddrOf && "Can only take the address of an overloaded function"); if (CXXMethodDecl *Method = dyn_cast(Fn)) { if (Method->isStatic()) { @@ -7664,7 +7810,7 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, QualType MemPtrType = Context.getMemberPointerType(Fn->getType(), ClassType.getTypePtr()); - return new (Context) UnaryOperator(SubExpr, UnaryOperator::AddrOf, + return new (Context) UnaryOperator(SubExpr, UO_AddrOf, MemPtrType, UnOp->getOperatorLoc()); } } @@ -7673,7 +7819,7 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, if (SubExpr == UnOp->getSubExpr()) return UnOp->Retain(); - return new (Context) UnaryOperator(SubExpr, UnaryOperator::AddrOf, + return new (Context) UnaryOperator(SubExpr, UO_AddrOf, Context.getPointerType(SubExpr->getType()), UnOp->getOperatorLoc()); } @@ -7732,7 +7878,7 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, MemExpr->getQualifierRange(), Fn, Found, - MemExpr->getMemberLoc(), + MemExpr->getMemberNameInfo(), TemplateArgs, Fn->getType()); } @@ -7741,9 +7887,9 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, return E->Retain(); } -Sema::OwningExprResult Sema::FixOverloadedFunctionReference(OwningExprResult E, - DeclAccessPair Found, - FunctionDecl *Fn) { +ExprResult Sema::FixOverloadedFunctionReference(ExprResult E, + DeclAccessPair Found, + FunctionDecl *Fn) { return Owned(FixOverloadedFunctionReference((Expr *)E.get(), Found, Fn)); } diff --git a/lib/Sema/SemaOverload.h b/lib/Sema/SemaOverload.h deleted file mode 100644 index eb4fc6581796..000000000000 --- a/lib/Sema/SemaOverload.h +++ /dev/null @@ -1,617 +0,0 @@ -//===--- 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; - - /// 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. - }; - - /// 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. - struct StandardConversionSequence { - /// 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 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(Buffer); - } - - const ConversionSet &conversions() const { - return *reinterpret_cast(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). - struct ImplicitConversionSequence { - /// 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 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 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::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 { - typedef llvm::SmallVector inherited; - llvm::SmallPtrSet 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(); } - }; -} // end namespace clang - -#endif // LLVM_CLANG_SEMA_OVERLOAD_H diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 9c8f48bfea17..083e4dba85e3 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -11,8 +11,10 @@ // //===----------------------------------------------------------------------===// -#include "Sema.h" -#include "SemaInit.h" +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/Initialization.h" #include "clang/AST/APValue.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" @@ -26,19 +28,11 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" using namespace clang; +using namespace sema; -Sema::OwningStmtResult Sema::ActOnExprStmt(FullExprArg expr) { - Expr *E = expr->takeAs(); +StmtResult Sema::ActOnExprStmt(FullExprArg expr) { + Expr *E = expr.get(); assert(E && "ActOnExprStmt(): missing expression"); - if (E->getType()->isObjCObjectType()) { - if (LangOpts.ObjCNonFragileABI) - Diag(E->getLocEnd(), diag::err_indirection_requires_nonfragile_object) - << E->getType(); - else - Diag(E->getLocEnd(), diag::err_direct_interface_unsupported) - << E->getType(); - return StmtError(); - } // C99 6.8.3p2: The expression in an expression statement is evaluated as a // void expression for its side effects. Conversion to void allows any // operand, even incomplete types. @@ -48,11 +42,11 @@ Sema::OwningStmtResult Sema::ActOnExprStmt(FullExprArg expr) { } -Sema::OwningStmtResult Sema::ActOnNullStmt(SourceLocation SemiLoc) { +StmtResult Sema::ActOnNullStmt(SourceLocation SemiLoc) { return Owned(new (Context) NullStmt(SemiLoc)); } -Sema::OwningStmtResult Sema::ActOnDeclStmt(DeclGroupPtrTy dg, +StmtResult Sema::ActOnDeclStmt(DeclGroupPtrTy dg, SourceLocation StartLoc, SourceLocation EndLoc) { DeclGroupRef DG = dg.getAsVal(); @@ -141,10 +135,10 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) { } } - Diag(Loc, DiagID) << R1 << R2; + DiagRuntimeBehavior(Loc, PDiag(DiagID) << R1 << R2); } -Action::OwningStmtResult +StmtResult Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R, MultiStmtArg elts, bool isStmtExpr) { unsigned NumElts = elts.size(); @@ -179,70 +173,60 @@ Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R, return Owned(new (Context) CompoundStmt(Context, Elts, NumElts, L, R)); } -Action::OwningStmtResult -Sema::ActOnCaseStmt(SourceLocation CaseLoc, ExprArg lhsval, - SourceLocation DotDotDotLoc, ExprArg rhsval, +StmtResult +Sema::ActOnCaseStmt(SourceLocation CaseLoc, Expr *LHSVal, + SourceLocation DotDotDotLoc, Expr *RHSVal, SourceLocation ColonLoc) { - assert((lhsval.get() != 0) && "missing expression in case statement"); + assert((LHSVal != 0) && "missing expression in case statement"); // C99 6.8.4.2p3: The expression shall be an integer constant. // However, GCC allows any evaluatable integer expression. - Expr *LHSVal = static_cast(lhsval.get()); if (!LHSVal->isTypeDependent() && !LHSVal->isValueDependent() && VerifyIntegerConstantExpression(LHSVal)) return StmtError(); // GCC extension: The expression shall be an integer constant. - Expr *RHSVal = static_cast(rhsval.get()); if (RHSVal && !RHSVal->isTypeDependent() && !RHSVal->isValueDependent() && VerifyIntegerConstantExpression(RHSVal)) { RHSVal = 0; // Recover by just forgetting about it. - rhsval = 0; } - if (getSwitchStack().empty()) { + if (getCurFunction()->SwitchStack.empty()) { Diag(CaseLoc, diag::err_case_not_in_switch); return StmtError(); } - // Only now release the smart pointers. - lhsval.release(); - rhsval.release(); CaseStmt *CS = new (Context) CaseStmt(LHSVal, RHSVal, CaseLoc, DotDotDotLoc, ColonLoc); - getSwitchStack().back()->addSwitchCase(CS); + getCurFunction()->SwitchStack.back()->addSwitchCase(CS); return Owned(CS); } /// ActOnCaseStmtBody - This installs a statement as the body of a case. -void Sema::ActOnCaseStmtBody(StmtTy *caseStmt, StmtArg subStmt) { +void Sema::ActOnCaseStmtBody(Stmt *caseStmt, Stmt *SubStmt) { CaseStmt *CS = static_cast(caseStmt); - Stmt *SubStmt = subStmt.takeAs(); CS->setSubStmt(SubStmt); } -Action::OwningStmtResult +StmtResult Sema::ActOnDefaultStmt(SourceLocation DefaultLoc, SourceLocation ColonLoc, - StmtArg subStmt, Scope *CurScope) { - Stmt *SubStmt = subStmt.takeAs(); - - if (getSwitchStack().empty()) { + Stmt *SubStmt, Scope *CurScope) { + if (getCurFunction()->SwitchStack.empty()) { Diag(DefaultLoc, diag::err_default_not_in_switch); return Owned(SubStmt); } DefaultStmt *DS = new (Context) DefaultStmt(DefaultLoc, ColonLoc, SubStmt); - getSwitchStack().back()->addSwitchCase(DS); + getCurFunction()->SwitchStack.back()->addSwitchCase(DS); return Owned(DS); } -Action::OwningStmtResult +StmtResult Sema::ActOnLabelStmt(SourceLocation IdentLoc, IdentifierInfo *II, - SourceLocation ColonLoc, StmtArg subStmt) { - Stmt *SubStmt = subStmt.takeAs(); + SourceLocation ColonLoc, Stmt *SubStmt) { // Look up the record for this label identifier. - LabelStmt *&LabelDecl = getLabelMap()[II]; + LabelStmt *&LabelDecl = getCurFunction()->LabelMap[II]; // If not forward referenced or defined already, just create a new LabelStmt. if (LabelDecl == 0) @@ -265,15 +249,15 @@ Sema::ActOnLabelStmt(SourceLocation IdentLoc, IdentifierInfo *II, return Owned(LabelDecl); } -Action::OwningStmtResult -Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, DeclPtrTy CondVar, - StmtArg ThenVal, SourceLocation ElseLoc, - StmtArg ElseVal) { - OwningExprResult CondResult(CondVal.release()); +StmtResult +Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar, + Stmt *thenStmt, SourceLocation ElseLoc, + Stmt *elseStmt) { + ExprResult CondResult(CondVal.release()); VarDecl *ConditionVar = 0; - if (CondVar.get()) { - ConditionVar = CondVar.getAs(); + if (CondVar) { + ConditionVar = cast(CondVar); CondResult = CheckConditionVariable(ConditionVar, IfLoc, true); if (CondResult.isInvalid()) return StmtError(); @@ -282,22 +266,19 @@ Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, DeclPtrTy CondVar, if (!ConditionExpr) return StmtError(); - Stmt *thenStmt = ThenVal.takeAs(); DiagnoseUnusedExprResult(thenStmt); // Warn if the if block has a null body without an else value. // this helps prevent bugs due to typos, such as // if (condition); // do_stuff(); - if (!ElseVal.get()) { + if (!elseStmt) { if (NullStmt* stmt = dyn_cast(thenStmt)) Diag(stmt->getSemiLoc(), diag::warn_empty_if_body); } - Stmt *elseStmt = ElseVal.takeAs(); DiagnoseUnusedExprResult(elseStmt); - CondResult.release(); return Owned(new (Context) IfStmt(Context, IfLoc, ConditionVar, ConditionExpr, thenStmt, ElseLoc, elseStmt)); } @@ -404,64 +385,63 @@ static QualType GetTypeBeforeIntegralPromotion(const Expr* expr) { return expr->getType(); } -Action::OwningStmtResult -Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, ExprArg Cond, - DeclPtrTy CondVar) { +StmtResult +Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, Expr *Cond, + Decl *CondVar) { + ExprResult CondResult; + VarDecl *ConditionVar = 0; - if (CondVar.get()) { - ConditionVar = CondVar.getAs(); - OwningExprResult CondE = CheckConditionVariable(ConditionVar, SourceLocation(), false); - if (CondE.isInvalid()) + if (CondVar) { + ConditionVar = cast(CondVar); + CondResult = CheckConditionVariable(ConditionVar, SourceLocation(), false); + if (CondResult.isInvalid()) return StmtError(); - Cond = move(CondE); + Cond = CondResult.release(); } - if (!Cond.get()) + if (!Cond) return StmtError(); - Expr *CondExpr = static_cast(Cond.get()); - OwningExprResult ConvertedCond - = ConvertToIntegralOrEnumerationType(SwitchLoc, move(Cond), + CondResult + = ConvertToIntegralOrEnumerationType(SwitchLoc, Cond, PDiag(diag::err_typecheck_statement_requires_integer), PDiag(diag::err_switch_incomplete_class_type) - << CondExpr->getSourceRange(), + << Cond->getSourceRange(), PDiag(diag::err_switch_explicit_conversion), PDiag(diag::note_switch_conversion), PDiag(diag::err_switch_multiple_conversions), PDiag(diag::note_switch_conversion), PDiag(0)); - if (ConvertedCond.isInvalid()) - return StmtError(); + if (CondResult.isInvalid()) return StmtError(); + Cond = CondResult.take(); - CondExpr = ConvertedCond.takeAs(); - - if (!CondVar.get()) { - CondExpr = MaybeCreateCXXExprWithTemporaries(CondExpr); - if (!CondExpr) + if (!CondVar) { + CondResult = MaybeCreateCXXExprWithTemporaries(Cond); + if (CondResult.isInvalid()) return StmtError(); + Cond = CondResult.take(); } + + getCurFunction()->setHasBranchIntoScope(); - SwitchStmt *SS = new (Context) SwitchStmt(Context, ConditionVar, CondExpr); - getSwitchStack().push_back(SS); + SwitchStmt *SS = new (Context) SwitchStmt(Context, ConditionVar, Cond); + getCurFunction()->SwitchStack.push_back(SS); return Owned(SS); } -Action::OwningStmtResult -Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch, - StmtArg Body) { - Stmt *BodyStmt = Body.takeAs(); - - SwitchStmt *SS = getSwitchStack().back(); - assert(SS == (SwitchStmt*)Switch.get() && "switch stack missing push/pop!"); +StmtResult +Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, + Stmt *BodyStmt) { + SwitchStmt *SS = cast(Switch); + assert(SS == getCurFunction()->SwitchStack.back() && + "switch stack missing push/pop!"); SS->setBody(BodyStmt, SwitchLoc); - getSwitchStack().pop_back(); + getCurFunction()->SwitchStack.pop_back(); - if (SS->getCond() == 0) { - SS->Destroy(Context); + if (SS->getCond() == 0) return StmtError(); - } Expr *CondExpr = SS->getCond(); Expr *CondExprBeforePromotion = CondExpr; @@ -556,7 +536,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch, // If the LHS is not the same type as the condition, insert an implicit // cast. - ImpCastExprToType(Lo, CondType, CastExpr::CK_IntegralCast); + ImpCastExprToType(Lo, CondType, CK_IntegralCast); CS->setLHS(Lo); // If this is a case range, remember it in CaseRanges, otherwise CaseVals. @@ -635,7 +615,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch, // If the LHS is not the same type as the condition, insert an implicit // cast. - ImpCastExprToType(Hi, CondType, CastExpr::CK_IntegralCast); + ImpCastExprToType(Hi, CondType, CK_IntegralCast); CR->setRHS(Hi); // If the low value is bigger than the high value, the case is empty. @@ -804,65 +784,55 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch, if (CaseListIsErroneous) return StmtError(); - Switch.release(); return Owned(SS); } -Action::OwningStmtResult +StmtResult Sema::ActOnWhileStmt(SourceLocation WhileLoc, FullExprArg Cond, - DeclPtrTy CondVar, StmtArg Body) { - OwningExprResult CondResult(Cond.release()); + Decl *CondVar, Stmt *Body) { + ExprResult CondResult(Cond.release()); VarDecl *ConditionVar = 0; - if (CondVar.get()) { - ConditionVar = CondVar.getAs(); + if (CondVar) { + ConditionVar = cast(CondVar); CondResult = CheckConditionVariable(ConditionVar, WhileLoc, true); if (CondResult.isInvalid()) return StmtError(); } - Expr *ConditionExpr = CondResult.takeAs(); + Expr *ConditionExpr = CondResult.take(); if (!ConditionExpr) return StmtError(); - Stmt *bodyStmt = Body.takeAs(); - DiagnoseUnusedExprResult(bodyStmt); + DiagnoseUnusedExprResult(Body); - CondResult.release(); return Owned(new (Context) WhileStmt(Context, ConditionVar, ConditionExpr, - bodyStmt, WhileLoc)); + Body, WhileLoc)); } -Action::OwningStmtResult -Sema::ActOnDoStmt(SourceLocation DoLoc, StmtArg Body, +StmtResult +Sema::ActOnDoStmt(SourceLocation DoLoc, Stmt *Body, SourceLocation WhileLoc, SourceLocation CondLParen, - ExprArg Cond, SourceLocation CondRParen) { - Expr *condExpr = Cond.takeAs(); - assert(condExpr && "ActOnDoStmt(): missing expression"); + Expr *Cond, SourceLocation CondRParen) { + assert(Cond && "ActOnDoStmt(): missing expression"); - if (CheckBooleanCondition(condExpr, DoLoc)) { - Cond = condExpr; + if (CheckBooleanCondition(Cond, DoLoc)) return StmtError(); - } - condExpr = MaybeCreateCXXExprWithTemporaries(condExpr); - if (!condExpr) + ExprResult CondResult = MaybeCreateCXXExprWithTemporaries(Cond); + if (CondResult.isInvalid()) return StmtError(); + Cond = CondResult.take(); - Stmt *bodyStmt = Body.takeAs(); - DiagnoseUnusedExprResult(bodyStmt); + DiagnoseUnusedExprResult(Body); - Cond.release(); - return Owned(new (Context) DoStmt(bodyStmt, condExpr, DoLoc, - WhileLoc, CondRParen)); + return Owned(new (Context) DoStmt(Body, Cond, DoLoc, WhileLoc, CondRParen)); } -Action::OwningStmtResult +StmtResult Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, - StmtArg first, FullExprArg second, DeclPtrTy secondVar, + Stmt *First, FullExprArg second, Decl *secondVar, FullExprArg third, - SourceLocation RParenLoc, StmtArg body) { - Stmt *First = static_cast(first.get()); - + SourceLocation RParenLoc, Stmt *Body) { if (!getLangOptions().CPlusPlus) { if (DeclStmt *DS = dyn_cast_or_null(First)) { // C99 6.8.5p3: The declaration part of a 'for' statement shall only @@ -880,38 +850,32 @@ Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, } } - OwningExprResult SecondResult(second.release()); + ExprResult SecondResult(second.release()); VarDecl *ConditionVar = 0; - if (secondVar.get()) { - ConditionVar = secondVar.getAs(); + if (secondVar) { + ConditionVar = cast(secondVar); SecondResult = CheckConditionVariable(ConditionVar, ForLoc, true); if (SecondResult.isInvalid()) return StmtError(); } Expr *Third = third.release().takeAs(); - Stmt *Body = static_cast(body.get()); DiagnoseUnusedExprResult(First); DiagnoseUnusedExprResult(Third); DiagnoseUnusedExprResult(Body); - first.release(); - body.release(); return Owned(new (Context) ForStmt(Context, First, - SecondResult.takeAs(), ConditionVar, + SecondResult.take(), ConditionVar, Third, Body, ForLoc, LParenLoc, RParenLoc)); } -Action::OwningStmtResult +StmtResult Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc, SourceLocation LParenLoc, - StmtArg first, ExprArg second, - SourceLocation RParenLoc, StmtArg body) { - Stmt *First = static_cast(first.get()); - Expr *Second = static_cast(second.get()); - Stmt *Body = static_cast(body.get()); + Stmt *First, Expr *Second, + SourceLocation RParenLoc, Stmt *Body) { if (First) { QualType FirstType; if (DeclStmt *DS = dyn_cast(First)) { @@ -950,19 +914,39 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc, if (!SecondType->isObjCObjectPointerType()) Diag(ForLoc, diag::err_collection_expr_type) << SecondType << Second->getSourceRange(); + else if (const ObjCObjectPointerType *OPT = + SecondType->getAsObjCInterfacePointerType()) { + llvm::SmallVector KeyIdents; + IdentifierInfo* selIdent = + &Context.Idents.get("countByEnumeratingWithState"); + KeyIdents.push_back(selIdent); + selIdent = &Context.Idents.get("objects"); + KeyIdents.push_back(selIdent); + selIdent = &Context.Idents.get("count"); + KeyIdents.push_back(selIdent); + Selector CSelector = Context.Selectors.getSelector(3, &KeyIdents[0]); + if (ObjCInterfaceDecl *IDecl = OPT->getInterfaceDecl()) { + if (!IDecl->isForwardDecl() && + !IDecl->lookupInstanceMethod(CSelector)) { + // Must further look into private implementation methods. + if (!LookupPrivateInstanceMethod(CSelector, IDecl)) + Diag(ForLoc, diag::warn_collection_expr_type) + << SecondType << CSelector << Second->getSourceRange(); + } + } + } } - first.release(); - second.release(); - body.release(); return Owned(new (Context) ObjCForCollectionStmt(First, Second, Body, ForLoc, RParenLoc)); } -Action::OwningStmtResult +StmtResult Sema::ActOnGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc, IdentifierInfo *LabelII) { // Look up the record for this label identifier. - LabelStmt *&LabelDecl = getLabelMap()[LabelII]; + LabelStmt *&LabelDecl = getCurFunction()->LabelMap[LabelII]; + + getCurFunction()->setHasBranchIntoScope(); // If we haven't seen this label yet, create a forward reference. if (LabelDecl == 0) @@ -971,11 +955,10 @@ Sema::ActOnGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc, return Owned(new (Context) GotoStmt(LabelDecl, GotoLoc, LabelLoc)); } -Action::OwningStmtResult +StmtResult Sema::ActOnIndirectGotoStmt(SourceLocation GotoLoc, SourceLocation StarLoc, - ExprArg DestExp) { + Expr *E) { // Convert operand to void* - Expr* E = DestExp.takeAs(); if (!E->isTypeDependent()) { QualType ETy = E->getType(); QualType DestTy = Context.getPointerType(Context.VoidTy.withConst()); @@ -984,10 +967,13 @@ Sema::ActOnIndirectGotoStmt(SourceLocation GotoLoc, SourceLocation StarLoc, if (DiagnoseAssignmentResult(ConvTy, StarLoc, DestTy, ETy, E, AA_Passing)) return StmtError(); } + + getCurFunction()->setHasIndirectGoto(); + return Owned(new (Context) IndirectGotoStmt(GotoLoc, StarLoc, E)); } -Action::OwningStmtResult +StmtResult Sema::ActOnContinueStmt(SourceLocation ContinueLoc, Scope *CurScope) { Scope *S = CurScope->getContinueParent(); if (!S) { @@ -998,7 +984,7 @@ Sema::ActOnContinueStmt(SourceLocation ContinueLoc, Scope *CurScope) { return Owned(new (Context) ContinueStmt(ContinueLoc)); } -Action::OwningStmtResult +StmtResult Sema::ActOnBreakStmt(SourceLocation BreakLoc, Scope *CurScope) { Scope *S = CurScope->getBreakParent(); if (!S) { @@ -1050,7 +1036,7 @@ static const VarDecl *getNRVOCandidate(ASTContext &Ctx, QualType RetType, /// ActOnBlockReturnStmt - Utility routine to figure out block's return type. /// -Action::OwningStmtResult +StmtResult Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { // If this is the first return we've seen in the block, infer the type of // the block from it. @@ -1086,7 +1072,6 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { if (CurBlock->ReturnType->isVoidType()) { if (RetValExp) { Diag(ReturnLoc, diag::err_return_block_has_expr); - RetValExp->Destroy(Context); RetValExp = 0; } Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, 0); @@ -1105,7 +1090,7 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { // In C++ the return statement is handled via a copy initialization. // the C version of which boils down to CheckSingleAssignmentConstraints. NRVOCandidate = getNRVOCandidate(Context, FnRetType, RetValExp); - OwningExprResult Res = PerformCopyInitialization( + ExprResult Res = PerformCopyInitialization( InitializedEntity::InitializeResult(ReturnLoc, FnRetType, NRVOCandidate != 0), @@ -1136,9 +1121,8 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { return Owned(Result); } -Action::OwningStmtResult -Sema::ActOnReturnStmt(SourceLocation ReturnLoc, ExprArg rex) { - Expr *RetValExp = rex.takeAs(); +StmtResult +Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { if (getCurBlock()) return ActOnBlockReturnStmt(ReturnLoc, RetValExp); @@ -1197,7 +1181,7 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, ExprArg rex) { // In C++ the return statement is handled via a copy initialization. // the C version of which boils down to CheckSingleAssignmentConstraints. NRVOCandidate = getNRVOCandidate(Context, FnRetType, RetValExp); - OwningExprResult Res = PerformCopyInitialization( + ExprResult Res = PerformCopyInitialization( InitializedEntity::InitializeResult(ReturnLoc, FnRetType, NRVOCandidate != 0), @@ -1261,7 +1245,7 @@ static bool CheckAsmLValue(const Expr *E, Sema &S) { } -Sema::OwningStmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, +StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple, bool IsVolatile, unsigned NumOutputs, @@ -1269,15 +1253,15 @@ Sema::OwningStmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, IdentifierInfo **Names, MultiExprArg constraints, MultiExprArg exprs, - ExprArg asmString, + Expr *asmString, MultiExprArg clobbers, SourceLocation RParenLoc, bool MSAsm) { unsigned NumClobbers = clobbers.size(); StringLiteral **Constraints = reinterpret_cast(constraints.get()); - Expr **Exprs = reinterpret_cast(exprs.get()); - StringLiteral *AsmString = cast((Expr *)asmString.get()); + Expr **Exprs = exprs.get(); + StringLiteral *AsmString = cast(asmString); StringLiteral **Clobbers = reinterpret_cast(clobbers.get()); llvm::SmallVector OutputConstraintInfos; @@ -1373,10 +1357,6 @@ Sema::OwningStmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, diag::err_asm_unknown_register_name) << Clobber); } - constraints.release(); - exprs.release(); - asmString.release(); - clobbers.release(); AsmStmt *NS = new (Context) AsmStmt(Context, AsmLoc, IsSimple, IsVolatile, MSAsm, NumOutputs, NumInputs, Names, Constraints, Exprs, @@ -1388,7 +1368,6 @@ Sema::OwningStmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, if (unsigned DiagID = NS->AnalyzeAsmString(Pieces, Context, DiagOffs)) { Diag(getLocationOfStringLiteralByte(AsmString, DiagOffs), DiagID) << AsmString->getSourceRange(); - DeleteStmt(NS); return StmtError(); } @@ -1479,45 +1458,41 @@ Sema::OwningStmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, diag::err_asm_tying_incompatible_types) << InTy << OutTy << OutputExpr->getSourceRange() << InputExpr->getSourceRange(); - DeleteStmt(NS); return StmtError(); } return Owned(NS); } -Action::OwningStmtResult +StmtResult Sema::ActOnObjCAtCatchStmt(SourceLocation AtLoc, - SourceLocation RParen, DeclPtrTy Parm, - StmtArg Body) { - VarDecl *Var = cast_or_null(Parm.getAs()); + SourceLocation RParen, Decl *Parm, + Stmt *Body) { + VarDecl *Var = cast_or_null(Parm); if (Var && Var->isInvalidDecl()) return StmtError(); - return Owned(new (Context) ObjCAtCatchStmt(AtLoc, RParen, Var, - Body.takeAs())); + return Owned(new (Context) ObjCAtCatchStmt(AtLoc, RParen, Var, Body)); } -Action::OwningStmtResult -Sema::ActOnObjCAtFinallyStmt(SourceLocation AtLoc, StmtArg Body) { - return Owned(new (Context) ObjCAtFinallyStmt(AtLoc, - static_cast(Body.release()))); +StmtResult +Sema::ActOnObjCAtFinallyStmt(SourceLocation AtLoc, Stmt *Body) { + return Owned(new (Context) ObjCAtFinallyStmt(AtLoc, Body)); } -Action::OwningStmtResult -Sema::ActOnObjCAtTryStmt(SourceLocation AtLoc, StmtArg Try, - MultiStmtArg CatchStmts, StmtArg Finally) { - FunctionNeedsScopeChecking() = true; +StmtResult +Sema::ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try, + MultiStmtArg CatchStmts, Stmt *Finally) { + getCurFunction()->setHasBranchProtectedScope(); unsigned NumCatchStmts = CatchStmts.size(); - return Owned(ObjCAtTryStmt::Create(Context, AtLoc, Try.takeAs(), - (Stmt **)CatchStmts.release(), + return Owned(ObjCAtTryStmt::Create(Context, AtLoc, Try, + CatchStmts.release(), NumCatchStmts, - Finally.takeAs())); + Finally)); } -Sema::OwningStmtResult Sema::BuildObjCAtThrowStmt(SourceLocation AtLoc, - ExprArg ThrowE) { - Expr *Throw = static_cast(ThrowE.get()); +StmtResult Sema::BuildObjCAtThrowStmt(SourceLocation AtLoc, + Expr *Throw) { if (Throw) { QualType ThrowType = Throw->getType(); // Make sure the expression type is an ObjC pointer or "void *". @@ -1530,13 +1505,13 @@ Sema::OwningStmtResult Sema::BuildObjCAtThrowStmt(SourceLocation AtLoc, } } - return Owned(new (Context) ObjCAtThrowStmt(AtLoc, ThrowE.takeAs())); + return Owned(new (Context) ObjCAtThrowStmt(AtLoc, Throw)); } -Action::OwningStmtResult -Sema::ActOnObjCAtThrowStmt(SourceLocation AtLoc, ExprArg Throw, +StmtResult +Sema::ActOnObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw, Scope *CurScope) { - if (!Throw.get()) { + if (!Throw) { // @throw without an expression designates a rethrow (which much occur // in the context of an @catch clause). Scope *AtCatchParent = CurScope; @@ -1546,16 +1521,15 @@ Sema::ActOnObjCAtThrowStmt(SourceLocation AtLoc, ExprArg Throw, return StmtError(Diag(AtLoc, diag::error_rethrow_used_outside_catch)); } - return BuildObjCAtThrowStmt(AtLoc, move(Throw)); + return BuildObjCAtThrowStmt(AtLoc, Throw); } -Action::OwningStmtResult -Sema::ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, ExprArg SynchExpr, - StmtArg SynchBody) { - FunctionNeedsScopeChecking() = true; +StmtResult +Sema::ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, Expr *SyncExpr, + Stmt *SyncBody) { + getCurFunction()->setHasBranchProtectedScope(); // Make sure the expression type is an ObjC pointer or "void *". - Expr *SyncExpr = static_cast(SynchExpr.get()); if (!SyncExpr->getType()->isDependentType() && !SyncExpr->getType()->isObjCObjectPointerType()) { const PointerType *PT = SyncExpr->getType()->getAs(); @@ -1564,22 +1538,22 @@ Sema::ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, ExprArg SynchExpr, << SyncExpr->getType() << SyncExpr->getSourceRange()); } - return Owned(new (Context) ObjCAtSynchronizedStmt(AtLoc, - SynchExpr.takeAs(), - SynchBody.takeAs())); + return Owned(new (Context) ObjCAtSynchronizedStmt(AtLoc, SyncExpr, SyncBody)); } /// ActOnCXXCatchBlock - Takes an exception declaration and a handler block /// and creates a proper catch handler from them. -Action::OwningStmtResult -Sema::ActOnCXXCatchBlock(SourceLocation CatchLoc, DeclPtrTy ExDecl, - StmtArg HandlerBlock) { +StmtResult +Sema::ActOnCXXCatchBlock(SourceLocation CatchLoc, Decl *ExDecl, + Stmt *HandlerBlock) { // There's nothing to test that ActOnExceptionDecl didn't already test. return Owned(new (Context) CXXCatchStmt(CatchLoc, - cast_or_null(ExDecl.getAs()), - HandlerBlock.takeAs())); + cast_or_null(ExDecl), + HandlerBlock)); } +namespace { + class TypeWithHandler { QualType t; CXXCatchStmt *stmt; @@ -1602,22 +1576,23 @@ public: return t == other.t; } - QualType getQualType() const { return t; } CXXCatchStmt *getCatchStmt() const { return stmt; } SourceLocation getTypeSpecStartLoc() const { return stmt->getExceptionDecl()->getTypeSpecStartLoc(); } }; +} + /// ActOnCXXTryBlock - Takes a try compound-statement and a number of /// handlers and creates a try statement from them. -Action::OwningStmtResult -Sema::ActOnCXXTryBlock(SourceLocation TryLoc, StmtArg TryBlock, +StmtResult +Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, MultiStmtArg RawHandlers) { unsigned NumHandlers = RawHandlers.size(); assert(NumHandlers > 0 && "The parser shouldn't call this if there are no handlers."); - Stmt **Handlers = reinterpret_cast(RawHandlers.get()); + Stmt **Handlers = RawHandlers.get(); llvm::SmallVector TypesWithHandlers; @@ -1657,15 +1632,14 @@ Sema::ActOnCXXTryBlock(SourceLocation TryLoc, StmtArg TryBlock, } } + getCurFunction()->setHasBranchProtectedScope(); + // FIXME: We should detect handlers that cannot catch anything because an // earlier handler catches a superclass. Need to find a method that is not // quadratic for this. // Neither of these are explicitly forbidden, but every compiler detects them // and warns. - FunctionNeedsScopeChecking() = true; - RawHandlers.release(); - return Owned(CXXTryStmt::Create(Context, TryLoc, - static_cast(TryBlock.release()), + return Owned(CXXTryStmt::Create(Context, TryLoc, TryBlock, Handlers, NumHandlers)); } diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index f121954eed6e..0fc83927b79c 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -9,20 +9,24 @@ // This file implements semantic analysis for C++ templates. //===----------------------------------------------------------------------===/ -#include "Sema.h" -#include "Lookup.h" +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/Template.h" +#include "clang/Sema/TemplateDeduction.h" #include "TreeTransform.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/DeclFriend.h" #include "clang/AST/DeclTemplate.h" -#include "clang/Parse/DeclSpec.h" -#include "clang/Parse/Template.h" +#include "clang/Sema/DeclSpec.h" +#include "clang/Sema/ParsedTemplate.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/PartialDiagnostic.h" #include "llvm/ADT/StringExtras.h" using namespace clang; +using namespace sema; /// \brief Determine whether the declaration found is acceptable as the name /// of a template and, if so, return that template declaration. Otherwise, @@ -88,8 +92,13 @@ static void FilterAcceptableTemplateNames(ASTContext &C, LookupResult &R) { filter.erase(); continue; } - - filter.replace(Repl); + + // FIXME: we promote access to public here as a workaround to + // the fact that LookupResult doesn't let us remember that we + // found this template through a particular injected class name, + // which means we end up doing nasty things to the invariants. + // Pretending that access is public is *much* safer. + filter.replace(Repl, AS_public); } } filter.done(); @@ -97,8 +106,9 @@ static void FilterAcceptableTemplateNames(ASTContext &C, LookupResult &R) { TemplateNameKind Sema::isTemplateName(Scope *S, CXXScopeSpec &SS, + bool hasTemplateKeyword, UnqualifiedId &Name, - TypeTy *ObjectTypePtr, + ParsedType ObjectTypePtr, bool EnteringContext, TemplateTy &TemplateResult, bool &MemberOfUnknownSpecialization) { @@ -125,15 +135,21 @@ TemplateNameKind Sema::isTemplateName(Scope *S, return TNK_Non_template; } - QualType ObjectType = QualType::getFromOpaquePtr(ObjectTypePtr); + QualType ObjectType = ObjectTypePtr.get(); LookupResult R(*this, TName, Name.getSourceRange().getBegin(), LookupOrdinaryName); - R.suppressDiagnostics(); LookupTemplateName(R, S, SS, ObjectType, EnteringContext, MemberOfUnknownSpecialization); - if (R.empty() || R.isAmbiguous()) + if (R.empty()) return TNK_Non_template; + if (R.isAmbiguous()) { + // Suppress diagnostics; we'll redo this lookup later. + R.suppressDiagnostics(); + + // FIXME: we might have ambiguous templates, in which case we + // should at least parse them properly! return TNK_Non_template; + } TemplateName Template; TemplateNameKind TemplateKind; @@ -144,20 +160,27 @@ TemplateNameKind Sema::isTemplateName(Scope *S, // template name in other ways. Template = Context.getOverloadedTemplateName(R.begin(), R.end()); TemplateKind = TNK_Function_template; + + // We'll do this lookup again later. + R.suppressDiagnostics(); } else { TemplateDecl *TD = cast((*R.begin())->getUnderlyingDecl()); if (SS.isSet() && !SS.isInvalid()) { NestedNameSpecifier *Qualifier = static_cast(SS.getScopeRep()); - Template = Context.getQualifiedTemplateName(Qualifier, false, TD); + Template = Context.getQualifiedTemplateName(Qualifier, + hasTemplateKeyword, TD); } else { Template = TemplateName(TD); } - if (isa(TD)) + if (isa(TD)) { TemplateKind = TNK_Function_template; - else { + + // We'll do this lookup again later. + R.suppressDiagnostics(); + } else { assert(isa(TD) || isa(TD)); TemplateKind = TNK_Type_template; } @@ -238,13 +261,10 @@ void Sema::LookupTemplateName(LookupResult &Found, // expression. If the identifier is not found, it is then looked up in // the context of the entire postfix-expression and shall name a class // or function template. - // - // FIXME: When we're instantiating a template, do we actually have to - // look in the scope of the template? Seems fishy... if (S) LookupName(Found, S); ObjectTypeSearchedInScope = true; } - } else if (isDependent) { + } else if (isDependent && (!S || ObjectType.isNull())) { // We cannot look into a dependent object type or nested nme // specifier. MemberOfUnknownSpecialization = true; @@ -282,8 +302,11 @@ void Sema::LookupTemplateName(LookupResult &Found, } FilterAcceptableTemplateNames(Context, Found); - if (Found.empty()) + if (Found.empty()) { + if (isDependent) + MemberOfUnknownSpecialization = true; return; + } if (S && !ObjectType.isNull() && !ObjectTypeSearchedInScope) { // C++ [basic.lookup.classref]p1: @@ -330,10 +353,9 @@ void Sema::LookupTemplateName(LookupResult &Found, /// ActOnDependentIdExpression - Handle a dependent id-expression that /// was just parsed. This is only possible with an explicit scope /// specifier naming a dependent type. -Sema::OwningExprResult +ExprResult Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS, - DeclarationName Name, - SourceLocation NameLoc, + const DeclarationNameInfo &NameInfo, bool isAddressOfOperand, const TemplateArgumentListInfo *TemplateArgs) { NestedNameSpecifier *Qualifier @@ -356,22 +378,21 @@ Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS, /*Op*/ SourceLocation(), Qualifier, SS.getRange(), FirstQualifierInScope, - Name, NameLoc, + NameInfo, TemplateArgs)); } - return BuildDependentDeclRefExpr(SS, Name, NameLoc, TemplateArgs); + return BuildDependentDeclRefExpr(SS, NameInfo, TemplateArgs); } -Sema::OwningExprResult +ExprResult Sema::BuildDependentDeclRefExpr(const CXXScopeSpec &SS, - DeclarationName Name, - SourceLocation NameLoc, + const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs) { return Owned(DependentScopeDeclRefExpr::Create(Context, static_cast(SS.getScopeRep()), SS.getRange(), - Name, NameLoc, + NameInfo, TemplateArgs)); } @@ -398,9 +419,9 @@ bool Sema::DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl) { /// AdjustDeclIfTemplate - If the given decl happens to be a template, reset /// the parameter D to reference the templated declaration and return a pointer /// to the template declaration. Otherwise, do nothing to D and return null. -TemplateDecl *Sema::AdjustDeclIfTemplate(DeclPtrTy &D) { - if (TemplateDecl *Temp = dyn_cast_or_null(D.getAs())) { - D = DeclPtrTy::make(Temp->getTemplatedDecl()); +TemplateDecl *Sema::AdjustDeclIfTemplate(Decl *&D) { + if (TemplateDecl *Temp = dyn_cast_or_null(D)) { + D = Temp->getTemplatedDecl(); return Temp; } return 0; @@ -424,8 +445,7 @@ static TemplateArgumentLoc translateTemplateArgument(Sema &SemaRef, } case ParsedTemplateArgument::Template: { - TemplateName Template - = TemplateName::getFromVoidPointer(Arg.getAsTemplate().get()); + TemplateName Template = Arg.getAsTemplate().get(); return TemplateArgumentLoc(TemplateArgument(Template), Arg.getScopeSpec().getRange(), Arg.getLocation()); @@ -454,14 +474,14 @@ void Sema::translateTemplateArguments(const ASTTemplateArgsPtr &TemplateArgsIn, /// ParamName is the location of the parameter name (if any). /// If the type parameter has a default argument, it will be added /// later via ActOnTypeParameterDefault. -Sema::DeclPtrTy Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis, - SourceLocation EllipsisLoc, - SourceLocation KeyLoc, - IdentifierInfo *ParamName, - SourceLocation ParamNameLoc, - unsigned Depth, unsigned Position, - SourceLocation EqualLoc, - TypeTy *DefaultArg) { +Decl *Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis, + SourceLocation EllipsisLoc, + SourceLocation KeyLoc, + IdentifierInfo *ParamName, + SourceLocation ParamNameLoc, + unsigned Depth, unsigned Position, + SourceLocation EqualLoc, + ParsedType DefaultArg) { assert(S->isTemplateParamScope() && "Template type parameter not in template parameter scope!"); bool Invalid = false; @@ -488,7 +508,7 @@ Sema::DeclPtrTy Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis, if (ParamName) { // Add the template parameter into the current scope. - S->AddDecl(DeclPtrTy::make(Param)); + S->AddDecl(Param); IdResolver.AddDecl(Param); } @@ -504,19 +524,19 @@ Sema::DeclPtrTy Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis, // template-parameter that is not a template parameter pack. if (Ellipsis) { Diag(EqualLoc, diag::err_template_param_pack_default_arg); - return DeclPtrTy::make(Param); + return Param; } // Check the template argument itself. if (CheckTemplateArgument(Param, DefaultTInfo)) { Param->setInvalidDecl(); - return DeclPtrTy::make(Param);; + return Param; } Param->setDefaultArgument(DefaultTInfo, false); } - return DeclPtrTy::make(Param); + return Param; } /// \brief Check that the type of a non-type template parameter is @@ -542,9 +562,7 @@ Sema::CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc) { // -- integral or enumeration type, if (T->isIntegralOrEnumerationType() || // -- pointer to object or pointer to function, - (T->isPointerType() && - (T->getAs()->getPointeeType()->isObjectType() || - T->getAs()->getPointeeType()->isFunctionType())) || + T->isPointerType() || // -- reference to object or reference to function, T->isReferenceType() || // -- pointer to member. @@ -571,11 +589,11 @@ Sema::CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc) { return QualType(); } -Sema::DeclPtrTy Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, - unsigned Depth, - unsigned Position, - SourceLocation EqualLoc, - ExprArg DefaultArg) { +Decl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, + unsigned Depth, + unsigned Position, + SourceLocation EqualLoc, + Expr *Default) { TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); QualType T = TInfo->getType(); @@ -608,35 +626,35 @@ Sema::DeclPtrTy Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, if (D.getIdentifier()) { // Add the template parameter into the current scope. - S->AddDecl(DeclPtrTy::make(Param)); + S->AddDecl(Param); IdResolver.AddDecl(Param); } // Check the well-formedness of the default template argument, if provided. - if (Expr *Default = static_cast(DefaultArg.get())) { + if (Default) { TemplateArgument Converted; if (CheckTemplateArgument(Param, Param->getType(), Default, Converted)) { Param->setInvalidDecl(); - return DeclPtrTy::make(Param);; + return Param; } - Param->setDefaultArgument(DefaultArg.takeAs(), false); + Param->setDefaultArgument(Default, false); } - return DeclPtrTy::make(Param); + return Param; } /// ActOnTemplateTemplateParameter - Called when a C++ template template /// parameter (e.g. T in template