From 222e2a7620e6520ffaf4fc4e69d79c18da31542e Mon Sep 17 00:00:00 2001 From: "Zancanaro; Carlo" Date: Mon, 24 Sep 2012 09:58:17 +1000 Subject: Add the clang library to the repo (with some of my changes, too). --- clang/lib/Sema/AnalysisBasedWarnings.cpp | 1016 ++ clang/lib/Sema/AttributeList.cpp | 126 + clang/lib/Sema/CMakeLists.txt | 58 + clang/lib/Sema/CodeCompleteConsumer.cpp | 641 ++ clang/lib/Sema/DeclSpec.cpp | 986 ++ clang/lib/Sema/DelayedDiagnostic.cpp | 56 + clang/lib/Sema/IdentifierResolver.cpp | 444 + clang/lib/Sema/JumpDiagnostics.cpp | 770 ++ clang/lib/Sema/Makefile | 19 + clang/lib/Sema/Scope.cpp | 71 + clang/lib/Sema/Sema.cpp | 1102 +++ clang/lib/Sema/SemaAccess.cpp | 1850 ++++ clang/lib/Sema/SemaAttr.cpp | 426 + clang/lib/Sema/SemaCXXScopeSpec.cpp | 958 ++ clang/lib/Sema/SemaCast.cpp | 2112 +++++ clang/lib/Sema/SemaChecking.cpp | 5153 ++++++++++ clang/lib/Sema/SemaCodeComplete.cpp | 7178 ++++++++++++++ clang/lib/Sema/SemaConsumer.cpp | 14 + clang/lib/Sema/SemaDecl.cpp | 10462 +++++++++++++++++++++ clang/lib/Sema/SemaDeclAttr.cpp | 4171 +++++++++ clang/lib/Sema/SemaDeclCXX.cpp | 11340 +++++++++++++++++++++++ clang/lib/Sema/SemaDeclObjC.cpp | 3121 +++++++ clang/lib/Sema/SemaExceptionSpec.cpp | 1086 +++ clang/lib/Sema/SemaExpr.cpp | 11280 ++++++++++++++++++++++ clang/lib/Sema/SemaExprCXX.cpp | 5362 +++++++++++ clang/lib/Sema/SemaExprMember.cpp | 1618 ++++ clang/lib/Sema/SemaExprObjC.cpp | 3049 ++++++ clang/lib/Sema/SemaFixItUtils.cpp | 204 + clang/lib/Sema/SemaInit.cpp | 6167 ++++++++++++ clang/lib/Sema/SemaLambda.cpp | 820 ++ clang/lib/Sema/SemaLookup.cpp | 4060 ++++++++ clang/lib/Sema/SemaObjCProperty.cpp | 1953 ++++ clang/lib/Sema/SemaOverload.cpp | 11229 ++++++++++++++++++++++ clang/lib/Sema/SemaPseudoObject.cpp | 1373 +++ clang/lib/Sema/SemaStmt.cpp | 2663 ++++++ clang/lib/Sema/SemaStmtAttr.cpp | 48 + clang/lib/Sema/SemaTemplate.cpp | 7192 ++++++++++++++ clang/lib/Sema/SemaTemplateDeduction.cpp | 4515 +++++++++ clang/lib/Sema/SemaTemplateInstantiate.cpp | 2621 ++++++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 3502 +++++++ clang/lib/Sema/SemaTemplateVariadic.cpp | 794 ++ clang/lib/Sema/SemaType.cpp | 4514 +++++++++ clang/lib/Sema/TargetAttributesSema.cpp | 278 + clang/lib/Sema/TargetAttributesSema.h | 27 + clang/lib/Sema/TreeTransform.h | 9268 ++++++++++++++++++ clang/lib/Sema/TypeLocBuilder.h | 201 + 46 files changed, 135898 insertions(+) create mode 100644 clang/lib/Sema/AnalysisBasedWarnings.cpp create mode 100644 clang/lib/Sema/AttributeList.cpp create mode 100644 clang/lib/Sema/CMakeLists.txt create mode 100644 clang/lib/Sema/CodeCompleteConsumer.cpp create mode 100644 clang/lib/Sema/DeclSpec.cpp create mode 100644 clang/lib/Sema/DelayedDiagnostic.cpp create mode 100644 clang/lib/Sema/IdentifierResolver.cpp create mode 100644 clang/lib/Sema/JumpDiagnostics.cpp create mode 100644 clang/lib/Sema/Makefile create mode 100644 clang/lib/Sema/Scope.cpp create mode 100644 clang/lib/Sema/Sema.cpp create mode 100644 clang/lib/Sema/SemaAccess.cpp create mode 100644 clang/lib/Sema/SemaAttr.cpp create mode 100644 clang/lib/Sema/SemaCXXScopeSpec.cpp create mode 100644 clang/lib/Sema/SemaCast.cpp create mode 100644 clang/lib/Sema/SemaChecking.cpp create mode 100644 clang/lib/Sema/SemaCodeComplete.cpp create mode 100644 clang/lib/Sema/SemaConsumer.cpp create mode 100644 clang/lib/Sema/SemaDecl.cpp create mode 100644 clang/lib/Sema/SemaDeclAttr.cpp create mode 100644 clang/lib/Sema/SemaDeclCXX.cpp create mode 100644 clang/lib/Sema/SemaDeclObjC.cpp create mode 100644 clang/lib/Sema/SemaExceptionSpec.cpp create mode 100644 clang/lib/Sema/SemaExpr.cpp create mode 100644 clang/lib/Sema/SemaExprCXX.cpp create mode 100644 clang/lib/Sema/SemaExprMember.cpp create mode 100644 clang/lib/Sema/SemaExprObjC.cpp create mode 100644 clang/lib/Sema/SemaFixItUtils.cpp create mode 100644 clang/lib/Sema/SemaInit.cpp create mode 100644 clang/lib/Sema/SemaLambda.cpp create mode 100644 clang/lib/Sema/SemaLookup.cpp create mode 100644 clang/lib/Sema/SemaObjCProperty.cpp create mode 100644 clang/lib/Sema/SemaOverload.cpp create mode 100644 clang/lib/Sema/SemaPseudoObject.cpp create mode 100644 clang/lib/Sema/SemaStmt.cpp create mode 100644 clang/lib/Sema/SemaStmtAttr.cpp create mode 100644 clang/lib/Sema/SemaTemplate.cpp create mode 100644 clang/lib/Sema/SemaTemplateDeduction.cpp create mode 100644 clang/lib/Sema/SemaTemplateInstantiate.cpp create mode 100644 clang/lib/Sema/SemaTemplateInstantiateDecl.cpp create mode 100644 clang/lib/Sema/SemaTemplateVariadic.cpp create mode 100644 clang/lib/Sema/SemaType.cpp create mode 100644 clang/lib/Sema/TargetAttributesSema.cpp create mode 100644 clang/lib/Sema/TargetAttributesSema.h create mode 100644 clang/lib/Sema/TreeTransform.h create mode 100644 clang/lib/Sema/TypeLocBuilder.h (limited to 'clang/lib/Sema') diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp new file mode 100644 index 0000000..a8e6791 --- /dev/null +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -0,0 +1,1016 @@ +//=- AnalysisBasedWarnings.cpp - 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 analysis_warnings::[Policy,Executor]. +// Together they are used by Sema to issue warnings based on inexpensive +// static analysis algorithms in libAnalysis. +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/AnalysisBasedWarnings.h" +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/ScopeInfo.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Lex/Preprocessor.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" +#include "clang/AST/StmtCXX.h" +#include "clang/AST/EvaluatedExprVisitor.h" +#include "clang/AST/StmtVisitor.h" +#include "clang/Analysis/AnalysisContext.h" +#include "clang/Analysis/CFG.h" +#include "clang/Analysis/Analyses/ReachableCode.h" +#include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h" +#include "clang/Analysis/Analyses/ThreadSafety.h" +#include "clang/Analysis/CFGStmtMap.h" +#include "clang/Analysis/Analyses/UninitializedValues.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/ImmutableMap.h" +#include "llvm/ADT/PostOrderIterator.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Casting.h" +#include +#include + +using namespace clang; + +//===----------------------------------------------------------------------===// +// Unreachable code analysis. +//===----------------------------------------------------------------------===// + +namespace { + class UnreachableCodeHandler : public reachable_code::Callback { + Sema &S; + public: + UnreachableCodeHandler(Sema &s) : S(s) {} + + void HandleUnreachable(SourceLocation L, SourceRange R1, SourceRange R2) { + S.Diag(L, diag::warn_unreachable) << R1 << R2; + } + }; +} + +/// CheckUnreachable - Check for unreachable code. +static void CheckUnreachable(Sema &S, AnalysisDeclContext &AC) { + UnreachableCodeHandler UC(S); + reachable_code::FindUnreachableCode(AC, UC); +} + +//===----------------------------------------------------------------------===// +// Check for missing return value. +//===----------------------------------------------------------------------===// + +enum ControlFlowKind { + UnknownFallThrough, + NeverFallThrough, + MaybeFallThrough, + AlwaysFallThrough, + NeverFallThroughOrReturn +}; + +/// CheckFallThrough - Check that we don't fall off the end of a +/// Statement that should return a value. +/// +/// \returns AlwaysFallThrough iff we always fall off the end of the statement, +/// MaybeFallThrough iff we might or might not fall off the end, +/// NeverFallThroughOrReturn iff we never fall off the end of the statement or +/// return. We assume NeverFallThrough iff we never fall off the end of the +/// statement but we may return. We assume that functions not marked noreturn +/// will return. +static ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC) { + CFG *cfg = AC.getCFG(); + if (cfg == 0) return UnknownFallThrough; + + // The CFG leaves in dead things, and we don't want the dead code paths to + // confuse us, so we mark all live things first. + llvm::BitVector live(cfg->getNumBlockIDs()); + unsigned count = reachable_code::ScanReachableFromBlock(&cfg->getEntry(), + live); + + bool AddEHEdges = AC.getAddEHEdges(); + if (!AddEHEdges && count != cfg->getNumBlockIDs()) + // When there are things remaining dead, and we didn't add EH edges + // from CallExprs to the catch clauses, we have to go back and + // mark them as live. + for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) { + CFGBlock &b = **I; + if (!live[b.getBlockID()]) { + if (b.pred_begin() == b.pred_end()) { + if (b.getTerminator() && isa(b.getTerminator())) + // When not adding EH edges from calls, catch clauses + // can otherwise seem dead. Avoid noting them as dead. + count += reachable_code::ScanReachableFromBlock(&b, live); + continue; + } + } + } + + // Now we know what is live, we check the live precessors of the exit block + // and look for fall through paths, being careful to ignore normal returns, + // and exceptional paths. + bool HasLiveReturn = false; + bool HasFakeEdge = false; + bool HasPlainEdge = false; + bool HasAbnormalEdge = false; + + // Ignore default cases that aren't likely to be reachable because all + // enums in a switch(X) have explicit case statements. + CFGBlock::FilterOptions FO; + FO.IgnoreDefaultsWithCoveredEnums = 1; + + for (CFGBlock::filtered_pred_iterator + I = cfg->getExit().filtered_pred_start_end(FO); I.hasMore(); ++I) { + const CFGBlock& B = **I; + if (!live[B.getBlockID()]) + continue; + + // Skip blocks which contain an element marked as no-return. They don't + // represent actually viable edges into the exit block, so mark them as + // abnormal. + if (B.hasNoReturnElement()) { + HasAbnormalEdge = true; + continue; + } + + // Destructors can appear after the 'return' in the CFG. This is + // normal. We need to look pass the destructors for the return + // statement (if it exists). + CFGBlock::const_reverse_iterator ri = B.rbegin(), re = B.rend(); + + for ( ; ri != re ; ++ri) + if (isa(*ri)) + break; + + // No more CFGElements in the block? + if (ri == re) { + if (B.getTerminator() && isa(B.getTerminator())) { + HasAbnormalEdge = true; + continue; + } + // A labeled empty statement, or the entry block... + HasPlainEdge = true; + continue; + } + + CFGStmt CS = cast(*ri); + const Stmt *S = CS.getStmt(); + if (isa(S)) { + HasLiveReturn = true; + continue; + } + if (isa(S)) { + HasFakeEdge = true; + continue; + } + if (isa(S)) { + HasFakeEdge = true; + continue; + } + if (const AsmStmt *AS = dyn_cast(S)) { + if (AS->isMSAsm()) { + HasFakeEdge = true; + HasLiveReturn = true; + continue; + } + } + if (isa(S)) { + HasAbnormalEdge = true; + continue; + } + if (std::find(B.succ_begin(), B.succ_end(), &cfg->getExit()) + == B.succ_end()) { + HasAbnormalEdge = true; + continue; + } + + HasPlainEdge = true; + } + if (!HasPlainEdge) { + if (HasLiveReturn) + return NeverFallThrough; + return NeverFallThroughOrReturn; + } + if (HasAbnormalEdge || HasFakeEdge || HasLiveReturn) + return MaybeFallThrough; + // This says AlwaysFallThrough for calls to functions that are not marked + // noreturn, that don't return. If people would like this warning to be more + // accurate, such functions should be marked as noreturn. + return AlwaysFallThrough; +} + +namespace { + +struct CheckFallThroughDiagnostics { + unsigned diag_MaybeFallThrough_HasNoReturn; + unsigned diag_MaybeFallThrough_ReturnsNonVoid; + unsigned diag_AlwaysFallThrough_HasNoReturn; + unsigned diag_AlwaysFallThrough_ReturnsNonVoid; + unsigned diag_NeverFallThroughOrReturn; + enum { Function, Block, Lambda } funMode; + SourceLocation FuncLoc; + + static CheckFallThroughDiagnostics MakeForFunction(const Decl *Func) { + CheckFallThroughDiagnostics D; + D.FuncLoc = Func->getLocation(); + D.diag_MaybeFallThrough_HasNoReturn = + diag::warn_falloff_noreturn_function; + D.diag_MaybeFallThrough_ReturnsNonVoid = + diag::warn_maybe_falloff_nonvoid_function; + D.diag_AlwaysFallThrough_HasNoReturn = + diag::warn_falloff_noreturn_function; + D.diag_AlwaysFallThrough_ReturnsNonVoid = + diag::warn_falloff_nonvoid_function; + + // Don't suggest that virtual functions be marked "noreturn", since they + // might be overridden by non-noreturn functions. + bool isVirtualMethod = false; + if (const CXXMethodDecl *Method = dyn_cast(Func)) + isVirtualMethod = Method->isVirtual(); + + // Don't suggest that template instantiations be marked "noreturn" + bool isTemplateInstantiation = false; + if (const FunctionDecl *Function = dyn_cast(Func)) + isTemplateInstantiation = Function->isTemplateInstantiation(); + + if (!isVirtualMethod && !isTemplateInstantiation) + D.diag_NeverFallThroughOrReturn = + diag::warn_suggest_noreturn_function; + else + D.diag_NeverFallThroughOrReturn = 0; + + D.funMode = Function; + return D; + } + + static CheckFallThroughDiagnostics MakeForBlock() { + CheckFallThroughDiagnostics D; + D.diag_MaybeFallThrough_HasNoReturn = + diag::err_noreturn_block_has_return_expr; + D.diag_MaybeFallThrough_ReturnsNonVoid = + diag::err_maybe_falloff_nonvoid_block; + D.diag_AlwaysFallThrough_HasNoReturn = + diag::err_noreturn_block_has_return_expr; + D.diag_AlwaysFallThrough_ReturnsNonVoid = + diag::err_falloff_nonvoid_block; + D.diag_NeverFallThroughOrReturn = + diag::warn_suggest_noreturn_block; + D.funMode = Block; + return D; + } + + static CheckFallThroughDiagnostics MakeForLambda() { + CheckFallThroughDiagnostics D; + D.diag_MaybeFallThrough_HasNoReturn = + diag::err_noreturn_lambda_has_return_expr; + D.diag_MaybeFallThrough_ReturnsNonVoid = + diag::warn_maybe_falloff_nonvoid_lambda; + D.diag_AlwaysFallThrough_HasNoReturn = + diag::err_noreturn_lambda_has_return_expr; + D.diag_AlwaysFallThrough_ReturnsNonVoid = + diag::warn_falloff_nonvoid_lambda; + D.diag_NeverFallThroughOrReturn = 0; + D.funMode = Lambda; + return D; + } + + bool checkDiagnostics(DiagnosticsEngine &D, bool ReturnsVoid, + bool HasNoReturn) const { + if (funMode == Function) { + return (ReturnsVoid || + D.getDiagnosticLevel(diag::warn_maybe_falloff_nonvoid_function, + FuncLoc) == DiagnosticsEngine::Ignored) + && (!HasNoReturn || + D.getDiagnosticLevel(diag::warn_noreturn_function_has_return_expr, + FuncLoc) == DiagnosticsEngine::Ignored) + && (!ReturnsVoid || + D.getDiagnosticLevel(diag::warn_suggest_noreturn_block, FuncLoc) + == DiagnosticsEngine::Ignored); + } + + // For blocks / lambdas. + return ReturnsVoid && !HasNoReturn + && ((funMode == Lambda) || + D.getDiagnosticLevel(diag::warn_suggest_noreturn_block, FuncLoc) + == DiagnosticsEngine::Ignored); + } +}; + +} + +/// 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 +/// noreturn will return. +static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body, + const BlockExpr *blkExpr, + const CheckFallThroughDiagnostics& CD, + AnalysisDeclContext &AC) { + + bool ReturnsVoid = false; + bool HasNoReturn = false; + + if (const FunctionDecl *FD = dyn_cast(D)) { + ReturnsVoid = FD->getResultType()->isVoidType(); + HasNoReturn = FD->hasAttr() || + FD->getType()->getAs()->getNoReturnAttr(); + } + else if (const ObjCMethodDecl *MD = dyn_cast(D)) { + ReturnsVoid = MD->getResultType()->isVoidType(); + HasNoReturn = MD->hasAttr(); + } + else if (isa(D)) { + QualType BlockTy = blkExpr->getType(); + if (const FunctionType *FT = + BlockTy->getPointeeType()->getAs()) { + if (FT->getResultType()->isVoidType()) + ReturnsVoid = true; + if (FT->getNoReturnAttr()) + HasNoReturn = true; + } + } + + DiagnosticsEngine &Diags = S.getDiagnostics(); + + // Short circuit for compilation speed. + if (CD.checkDiagnostics(Diags, ReturnsVoid, HasNoReturn)) + return; + + // FIXME: Function try block + if (const CompoundStmt *Compound = dyn_cast(Body)) { + switch (CheckFallThrough(AC)) { + case UnknownFallThrough: + break; + + case MaybeFallThrough: + if (HasNoReturn) + S.Diag(Compound->getRBracLoc(), + CD.diag_MaybeFallThrough_HasNoReturn); + else if (!ReturnsVoid) + S.Diag(Compound->getRBracLoc(), + CD.diag_MaybeFallThrough_ReturnsNonVoid); + break; + case AlwaysFallThrough: + if (HasNoReturn) + S.Diag(Compound->getRBracLoc(), + CD.diag_AlwaysFallThrough_HasNoReturn); + else if (!ReturnsVoid) + S.Diag(Compound->getRBracLoc(), + CD.diag_AlwaysFallThrough_ReturnsNonVoid); + break; + case NeverFallThroughOrReturn: + if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn) { + if (const FunctionDecl *FD = dyn_cast(D)) { + S.Diag(Compound->getLBracLoc(), CD.diag_NeverFallThroughOrReturn) + << 0 << FD; + } else if (const ObjCMethodDecl *MD = dyn_cast(D)) { + S.Diag(Compound->getLBracLoc(), CD.diag_NeverFallThroughOrReturn) + << 1 << MD; + } else { + S.Diag(Compound->getLBracLoc(), CD.diag_NeverFallThroughOrReturn); + } + } + break; + case NeverFallThrough: + break; + } + } +} + +//===----------------------------------------------------------------------===// +// -Wuninitialized +//===----------------------------------------------------------------------===// + +namespace { +/// ContainsReference - A visitor class to search for references to +/// a particular declaration (the needle) within any evaluated component of an +/// expression (recursively). +class ContainsReference : public EvaluatedExprVisitor { + bool FoundReference; + const DeclRefExpr *Needle; + +public: + ContainsReference(ASTContext &Context, const DeclRefExpr *Needle) + : EvaluatedExprVisitor(Context), + FoundReference(false), Needle(Needle) {} + + void VisitExpr(Expr *E) { + // Stop evaluating if we already have a reference. + if (FoundReference) + return; + + EvaluatedExprVisitor::VisitExpr(E); + } + + void VisitDeclRefExpr(DeclRefExpr *E) { + if (E == Needle) + FoundReference = true; + else + EvaluatedExprVisitor::VisitDeclRefExpr(E); + } + + bool doesContainReference() const { return FoundReference; } +}; +} + +static bool SuggestInitializationFixit(Sema &S, const VarDecl *VD) { + QualType VariableTy = VD->getType().getCanonicalType(); + if (VariableTy->isBlockPointerType() && + !VD->hasAttr()) { + S.Diag(VD->getLocation(), diag::note_block_var_fixit_add_initialization) << VD->getDeclName() + << FixItHint::CreateInsertion(VD->getLocation(), "__block "); + return true; + } + + // Don't issue a fixit if there is already an initializer. + if (VD->getInit()) + return false; + + // Suggest possible initialization (if any). + const char *Init = S.getFixItZeroInitializerForType(VariableTy); + if (!Init) + return false; + SourceLocation Loc = S.PP.getLocForEndOfToken(VD->getLocEnd()); + + S.Diag(Loc, diag::note_var_fixit_add_initialization) << VD->getDeclName() + << FixItHint::CreateInsertion(Loc, Init); + return true; +} + +/// DiagnoseUninitializedUse -- Helper function for diagnosing uses of an +/// uninitialized variable. This manages the different forms of diagnostic +/// emitted for particular types of uses. Returns true if the use was diagnosed +/// as a warning. If a pariticular use is one we omit warnings for, returns +/// false. +static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD, + const Expr *E, bool isAlwaysUninit, + bool alwaysReportSelfInit = false) { + bool isSelfInit = false; + + if (const DeclRefExpr *DRE = dyn_cast(E)) { + if (isAlwaysUninit) { + // Inspect the initializer of the variable declaration which is + // being referenced prior to its initialization. We emit + // specialized diagnostics for self-initialization, and we + // specifically avoid warning about self references which take the + // form of: + // + // int x = x; + // + // This is used to indicate to GCC that 'x' is intentionally left + // uninitialized. Proven code paths which access 'x' in + // an uninitialized state after this will still warn. + // + // TODO: Should we suppress maybe-uninitialized warnings for + // variables initialized in this way? + if (const Expr *Initializer = VD->getInit()) { + if (!alwaysReportSelfInit && DRE == Initializer->IgnoreParenImpCasts()) + return false; + + ContainsReference CR(S.Context, DRE); + CR.Visit(const_cast(Initializer)); + isSelfInit = CR.doesContainReference(); + } + if (isSelfInit) { + S.Diag(DRE->getLocStart(), + diag::warn_uninit_self_reference_in_init) + << VD->getDeclName() << VD->getLocation() << DRE->getSourceRange(); + } else { + S.Diag(DRE->getLocStart(), diag::warn_uninit_var) + << VD->getDeclName() << DRE->getSourceRange(); + } + } else { + S.Diag(DRE->getLocStart(), diag::warn_maybe_uninit_var) + << VD->getDeclName() << DRE->getSourceRange(); + } + } else { + const BlockExpr *BE = cast(E); + if (VD->getType()->isBlockPointerType() && + !VD->hasAttr()) + S.Diag(BE->getLocStart(), diag::warn_uninit_byref_blockvar_captured_by_block) + << VD->getDeclName(); + else + S.Diag(BE->getLocStart(), + isAlwaysUninit ? diag::warn_uninit_var_captured_by_block + : diag::warn_maybe_uninit_var_captured_by_block) + << VD->getDeclName(); + } + + // Report where the variable was declared when the use wasn't within + // the initializer of that declaration & we didn't already suggest + // an initialization fixit. + if (!isSelfInit && !SuggestInitializationFixit(S, VD)) + S.Diag(VD->getLocStart(), diag::note_uninit_var_def) + << VD->getDeclName(); + + return true; +} + +typedef std::pair UninitUse; + +namespace { +struct SLocSort { + bool operator()(const UninitUse &a, const UninitUse &b) { + SourceLocation aLoc = a.first->getLocStart(); + SourceLocation bLoc = b.first->getLocStart(); + return aLoc.getRawEncoding() < bLoc.getRawEncoding(); + } +}; + +class UninitValsDiagReporter : public UninitVariablesHandler { + Sema &S; + typedef SmallVector UsesVec; + typedef llvm::DenseMap > UsesMap; + UsesMap *uses; + +public: + UninitValsDiagReporter(Sema &S) : S(S), uses(0) {} + ~UninitValsDiagReporter() { + flushDiagnostics(); + } + + std::pair &getUses(const VarDecl *vd) { + if (!uses) + uses = new UsesMap(); + + UsesMap::mapped_type &V = (*uses)[vd]; + UsesVec *&vec = V.first; + if (!vec) + vec = new UsesVec(); + + return V; + } + + void handleUseOfUninitVariable(const Expr *ex, const VarDecl *vd, + bool isAlwaysUninit) { + getUses(vd).first->push_back(std::make_pair(ex, isAlwaysUninit)); + } + + void handleSelfInit(const VarDecl *vd) { + getUses(vd).second = true; + } + + void flushDiagnostics() { + if (!uses) + return; + + for (UsesMap::iterator i = uses->begin(), e = uses->end(); i != e; ++i) { + const VarDecl *vd = i->first; + const UsesMap::mapped_type &V = i->second; + + UsesVec *vec = V.first; + bool hasSelfInit = V.second; + + // Specially handle the case where we have uses of an uninitialized + // variable, but the root cause is an idiomatic self-init. We want + // to report the diagnostic at the self-init since that is the root cause. + if (!vec->empty() && hasSelfInit && hasAlwaysUninitializedUse(vec)) + DiagnoseUninitializedUse(S, vd, vd->getInit()->IgnoreParenCasts(), + /* isAlwaysUninit */ true, + /* alwaysReportSelfInit */ true); + else { + // Sort the uses by their SourceLocations. While not strictly + // guaranteed to produce them in line/column order, this will provide + // a stable ordering. + std::sort(vec->begin(), vec->end(), SLocSort()); + + for (UsesVec::iterator vi = vec->begin(), ve = vec->end(); vi != ve; + ++vi) { + if (DiagnoseUninitializedUse(S, vd, vi->first, + /*isAlwaysUninit=*/vi->second)) + // Skip further diagnostics for this variable. We try to warn only + // on the first point at which a variable is used uninitialized. + break; + } + } + + // Release the uses vector. + delete vec; + } + delete uses; + } + +private: + static bool hasAlwaysUninitializedUse(const UsesVec* vec) { + for (UsesVec::const_iterator i = vec->begin(), e = vec->end(); i != e; ++i) { + if (i->second) { + return true; + } + } + return false; +} +}; +} + + +//===----------------------------------------------------------------------===// +// -Wthread-safety +//===----------------------------------------------------------------------===// +namespace clang { +namespace thread_safety { +typedef llvm::SmallVector OptionalNotes; +typedef std::pair DelayedDiag; +typedef std::list DiagList; + +struct SortDiagBySourceLocation { + SourceManager &SM; + SortDiagBySourceLocation(SourceManager &SM) : SM(SM) {} + + bool operator()(const DelayedDiag &left, const DelayedDiag &right) { + // Although this call will be slow, this is only called when outputting + // multiple warnings. + return SM.isBeforeInTranslationUnit(left.first.first, right.first.first); + } +}; + +namespace { +class ThreadSafetyReporter : public clang::thread_safety::ThreadSafetyHandler { + Sema &S; + DiagList Warnings; + SourceLocation FunLocation, FunEndLocation; + + // Helper functions + void warnLockMismatch(unsigned DiagID, Name LockName, SourceLocation Loc) { + // Gracefully handle rare cases when the analysis can't get a more + // precise source location. + if (!Loc.isValid()) + Loc = FunLocation; + PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << LockName); + Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); + } + + public: + ThreadSafetyReporter(Sema &S, SourceLocation FL, SourceLocation FEL) + : S(S), FunLocation(FL), FunEndLocation(FEL) {} + + /// \brief Emit all buffered diagnostics in order of sourcelocation. + /// We need to output diagnostics produced while iterating through + /// the lockset in deterministic order, so this function orders diagnostics + /// and outputs them. + void emitDiagnostics() { + Warnings.sort(SortDiagBySourceLocation(S.getSourceManager())); + for (DiagList::iterator I = Warnings.begin(), E = Warnings.end(); + I != E; ++I) { + S.Diag(I->first.first, I->first.second); + const OptionalNotes &Notes = I->second; + for (unsigned NoteI = 0, NoteN = Notes.size(); NoteI != NoteN; ++NoteI) + S.Diag(Notes[NoteI].first, Notes[NoteI].second); + } + } + + void handleInvalidLockExp(SourceLocation Loc) { + PartialDiagnosticAt Warning(Loc, + S.PDiag(diag::warn_cannot_resolve_lock) << Loc); + Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); + } + void handleUnmatchedUnlock(Name LockName, SourceLocation Loc) { + warnLockMismatch(diag::warn_unlock_but_no_lock, LockName, Loc); + } + + void handleDoubleLock(Name LockName, SourceLocation Loc) { + warnLockMismatch(diag::warn_double_lock, LockName, Loc); + } + + void handleMutexHeldEndOfScope(Name LockName, SourceLocation LocLocked, + SourceLocation LocEndOfScope, + LockErrorKind LEK){ + unsigned DiagID = 0; + switch (LEK) { + case LEK_LockedSomePredecessors: + DiagID = diag::warn_lock_some_predecessors; + break; + case LEK_LockedSomeLoopIterations: + DiagID = diag::warn_expecting_lock_held_on_loop; + break; + case LEK_LockedAtEndOfFunction: + DiagID = diag::warn_no_unlock; + break; + } + if (LocEndOfScope.isInvalid()) + LocEndOfScope = FunEndLocation; + + PartialDiagnosticAt Warning(LocEndOfScope, S.PDiag(DiagID) << LockName); + PartialDiagnosticAt Note(LocLocked, S.PDiag(diag::note_locked_here)); + Warnings.push_back(DelayedDiag(Warning, OptionalNotes(1, Note))); + } + + + void handleExclusiveAndShared(Name LockName, SourceLocation Loc1, + SourceLocation Loc2) { + PartialDiagnosticAt Warning( + Loc1, S.PDiag(diag::warn_lock_exclusive_and_shared) << LockName); + PartialDiagnosticAt Note( + Loc2, S.PDiag(diag::note_lock_exclusive_and_shared) << LockName); + Warnings.push_back(DelayedDiag(Warning, OptionalNotes(1, Note))); + } + + void handleNoMutexHeld(const NamedDecl *D, ProtectedOperationKind POK, + AccessKind AK, SourceLocation Loc) { + assert((POK == POK_VarAccess || POK == POK_VarDereference) + && "Only works for variables"); + unsigned DiagID = POK == POK_VarAccess? + diag::warn_variable_requires_any_lock: + diag::warn_var_deref_requires_any_lock; + PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) + << D->getName() << getLockKindFromAccessKind(AK)); + Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); + } + + void handleMutexNotHeld(const NamedDecl *D, ProtectedOperationKind POK, + Name LockName, LockKind LK, SourceLocation Loc) { + unsigned DiagID = 0; + switch (POK) { + case POK_VarAccess: + DiagID = diag::warn_variable_requires_lock; + break; + case POK_VarDereference: + DiagID = diag::warn_var_deref_requires_lock; + break; + case POK_FunctionCall: + DiagID = diag::warn_fun_requires_lock; + break; + } + PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) + << D->getName() << LockName << LK); + Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); + } + + void handleFunExcludesLock(Name FunName, Name LockName, SourceLocation Loc) { + PartialDiagnosticAt Warning(Loc, + S.PDiag(diag::warn_fun_excludes_mutex) << FunName << LockName); + Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); + } +}; +} +} +} + +//===----------------------------------------------------------------------===// +// AnalysisBasedWarnings - Worker object used by Sema to execute analysis-based +// warnings on a function, method, or block. +//===----------------------------------------------------------------------===// + +clang::sema::AnalysisBasedWarnings::Policy::Policy() { + enableCheckFallThrough = 1; + enableCheckUnreachable = 0; + enableThreadSafetyAnalysis = 0; +} + +clang::sema::AnalysisBasedWarnings::AnalysisBasedWarnings(Sema &s) + : S(s), + NumFunctionsAnalyzed(0), + NumFunctionsWithBadCFGs(0), + NumCFGBlocks(0), + MaxCFGBlocksPerFunction(0), + NumUninitAnalysisFunctions(0), + NumUninitAnalysisVariables(0), + MaxUninitAnalysisVariablesPerFunction(0), + NumUninitAnalysisBlockVisits(0), + MaxUninitAnalysisBlockVisitsPerFunction(0) { + DiagnosticsEngine &D = S.getDiagnostics(); + DefaultPolicy.enableCheckUnreachable = (unsigned) + (D.getDiagnosticLevel(diag::warn_unreachable, SourceLocation()) != + DiagnosticsEngine::Ignored); + DefaultPolicy.enableThreadSafetyAnalysis = (unsigned) + (D.getDiagnosticLevel(diag::warn_double_lock, SourceLocation()) != + DiagnosticsEngine::Ignored); + +} + +static void flushDiagnostics(Sema &S, sema::FunctionScopeInfo *fscope) { + for (SmallVectorImpl::iterator + i = fscope->PossiblyUnreachableDiags.begin(), + e = fscope->PossiblyUnreachableDiags.end(); + i != e; ++i) { + const sema::PossiblyUnreachableDiag &D = *i; + S.Diag(D.Loc, D.PD); + } +} + +void clang::sema:: +AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, + sema::FunctionScopeInfo *fscope, + const Decl *D, const BlockExpr *blkExpr) { + + // We avoid doing analysis-based warnings when there are errors for + // two reasons: + // (1) The CFGs often can't be constructed (if the body is invalid), so + // don't bother trying. + // (2) The code already has problems; running the analysis just takes more + // time. + DiagnosticsEngine &Diags = S.getDiagnostics(); + + // Do not do any analysis for declarations in system headers if we are + // going to just ignore them. + if (Diags.getSuppressSystemWarnings() && + S.SourceMgr.isInSystemHeader(D->getLocation())) + return; + + // For code in dependent contexts, we'll do this at instantiation time. + if (cast(D)->isDependentContext()) + return; + + if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred()) { + // Flush out any possibly unreachable diagnostics. + flushDiagnostics(S, fscope); + return; + } + + const Stmt *Body = D->getBody(); + assert(Body); + + AnalysisDeclContext AC(/* AnalysisDeclContextManager */ 0, D, 0); + + // 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. + AC.getCFGBuildOptions().PruneTriviallyFalseEdges = true; + AC.getCFGBuildOptions().AddEHEdges = false; + AC.getCFGBuildOptions().AddInitializers = true; + AC.getCFGBuildOptions().AddImplicitDtors = true; + + // Force that certain expressions appear as CFGElements in the CFG. This + // is used to speed up various analyses. + // FIXME: This isn't the right factoring. This is here for initial + // prototyping, but we need a way for analyses to say what expressions they + // expect to always be CFGElements and then fill in the BuildOptions + // appropriately. This is essentially a layering violation. + if (P.enableCheckUnreachable || P.enableThreadSafetyAnalysis) { + // Unreachable code analysis and thread safety require a linearized CFG. + AC.getCFGBuildOptions().setAllAlwaysAdd(); + } + else { + AC.getCFGBuildOptions() + .setAlwaysAdd(Stmt::BinaryOperatorClass) + .setAlwaysAdd(Stmt::BlockExprClass) + .setAlwaysAdd(Stmt::CStyleCastExprClass) + .setAlwaysAdd(Stmt::DeclRefExprClass) + .setAlwaysAdd(Stmt::ImplicitCastExprClass) + .setAlwaysAdd(Stmt::UnaryOperatorClass); + } + + // Construct the analysis context with the specified CFG build options. + + // Emit delayed diagnostics. + if (!fscope->PossiblyUnreachableDiags.empty()) { + bool analyzed = false; + + // Register the expressions with the CFGBuilder. + for (SmallVectorImpl::iterator + i = fscope->PossiblyUnreachableDiags.begin(), + e = fscope->PossiblyUnreachableDiags.end(); + i != e; ++i) { + if (const Stmt *stmt = i->stmt) + AC.registerForcedBlockExpression(stmt); + } + + if (AC.getCFG()) { + analyzed = true; + for (SmallVectorImpl::iterator + i = fscope->PossiblyUnreachableDiags.begin(), + e = fscope->PossiblyUnreachableDiags.end(); + i != e; ++i) + { + const sema::PossiblyUnreachableDiag &D = *i; + bool processed = false; + if (const Stmt *stmt = i->stmt) { + const CFGBlock *block = AC.getBlockForRegisteredExpression(stmt); + CFGReverseBlockReachabilityAnalysis *cra = + AC.getCFGReachablityAnalysis(); + // FIXME: We should be able to assert that block is non-null, but + // the CFG analysis can skip potentially-evaluated expressions in + // edge cases; see test/Sema/vla-2.c. + if (block && cra) { + // Can this block be reached from the entrance? + if (cra->isReachable(&AC.getCFG()->getEntry(), block)) + S.Diag(D.Loc, D.PD); + processed = true; + } + } + if (!processed) { + // Emit the warning anyway if we cannot map to a basic block. + S.Diag(D.Loc, D.PD); + } + } + } + + if (!analyzed) + flushDiagnostics(S, fscope); + } + + + // Warning: check missing 'return' + if (P.enableCheckFallThrough) { + const CheckFallThroughDiagnostics &CD = + (isa(D) ? CheckFallThroughDiagnostics::MakeForBlock() + : (isa(D) && + cast(D)->getOverloadedOperator() == OO_Call && + cast(D)->getParent()->isLambda()) + ? CheckFallThroughDiagnostics::MakeForLambda() + : CheckFallThroughDiagnostics::MakeForFunction(D)); + CheckFallThroughForBody(S, D, Body, blkExpr, CD, AC); + } + + // Warning: check for unreachable code + if (P.enableCheckUnreachable) { + // Only check for unreachable code on non-template instantiations. + // Different template instantiations can effectively change the control-flow + // and it is very difficult to prove that a snippet of code in a template + // is unreachable for all instantiations. + bool isTemplateInstantiation = false; + if (const FunctionDecl *Function = dyn_cast(D)) + isTemplateInstantiation = Function->isTemplateInstantiation(); + if (!isTemplateInstantiation) + CheckUnreachable(S, AC); + } + + // Check for thread safety violations + if (P.enableThreadSafetyAnalysis) { + SourceLocation FL = AC.getDecl()->getLocation(); + SourceLocation FEL = AC.getDecl()->getLocEnd(); + thread_safety::ThreadSafetyReporter Reporter(S, FL, FEL); + thread_safety::runThreadSafetyAnalysis(AC, Reporter); + Reporter.emitDiagnostics(); + } + + if (Diags.getDiagnosticLevel(diag::warn_uninit_var, D->getLocStart()) + != DiagnosticsEngine::Ignored || + Diags.getDiagnosticLevel(diag::warn_maybe_uninit_var, D->getLocStart()) + != DiagnosticsEngine::Ignored) { + if (CFG *cfg = AC.getCFG()) { + UninitValsDiagReporter reporter(S); + UninitVariablesAnalysisStats stats; + std::memset(&stats, 0, sizeof(UninitVariablesAnalysisStats)); + runUninitializedVariablesAnalysis(*cast(D), *cfg, AC, + reporter, stats); + + if (S.CollectStats && stats.NumVariablesAnalyzed > 0) { + ++NumUninitAnalysisFunctions; + NumUninitAnalysisVariables += stats.NumVariablesAnalyzed; + NumUninitAnalysisBlockVisits += stats.NumBlockVisits; + MaxUninitAnalysisVariablesPerFunction = + std::max(MaxUninitAnalysisVariablesPerFunction, + stats.NumVariablesAnalyzed); + MaxUninitAnalysisBlockVisitsPerFunction = + std::max(MaxUninitAnalysisBlockVisitsPerFunction, + stats.NumBlockVisits); + } + } + } + + // Collect statistics about the CFG if it was built. + if (S.CollectStats && AC.isCFGBuilt()) { + ++NumFunctionsAnalyzed; + if (CFG *cfg = AC.getCFG()) { + // If we successfully built a CFG for this context, record some more + // detail information about it. + NumCFGBlocks += cfg->getNumBlockIDs(); + MaxCFGBlocksPerFunction = std::max(MaxCFGBlocksPerFunction, + cfg->getNumBlockIDs()); + } else { + ++NumFunctionsWithBadCFGs; + } + } +} + +void clang::sema::AnalysisBasedWarnings::PrintStats() const { + llvm::errs() << "\n*** Analysis Based Warnings Stats:\n"; + + unsigned NumCFGsBuilt = NumFunctionsAnalyzed - NumFunctionsWithBadCFGs; + unsigned AvgCFGBlocksPerFunction = + !NumCFGsBuilt ? 0 : NumCFGBlocks/NumCFGsBuilt; + llvm::errs() << NumFunctionsAnalyzed << " functions analyzed (" + << NumFunctionsWithBadCFGs << " w/o CFGs).\n" + << " " << NumCFGBlocks << " CFG blocks built.\n" + << " " << AvgCFGBlocksPerFunction + << " average CFG blocks per function.\n" + << " " << MaxCFGBlocksPerFunction + << " max CFG blocks per function.\n"; + + unsigned AvgUninitVariablesPerFunction = !NumUninitAnalysisFunctions ? 0 + : NumUninitAnalysisVariables/NumUninitAnalysisFunctions; + unsigned AvgUninitBlockVisitsPerFunction = !NumUninitAnalysisFunctions ? 0 + : NumUninitAnalysisBlockVisits/NumUninitAnalysisFunctions; + llvm::errs() << NumUninitAnalysisFunctions + << " functions analyzed for uninitialiazed variables\n" + << " " << NumUninitAnalysisVariables << " variables analyzed.\n" + << " " << AvgUninitVariablesPerFunction + << " average variables per function.\n" + << " " << MaxUninitAnalysisVariablesPerFunction + << " max variables per function.\n" + << " " << NumUninitAnalysisBlockVisits << " block visits.\n" + << " " << AvgUninitBlockVisitsPerFunction + << " average block visits per function.\n" + << " " << MaxUninitAnalysisBlockVisitsPerFunction + << " max block visits per function.\n"; +} diff --git a/clang/lib/Sema/AttributeList.cpp b/clang/lib/Sema/AttributeList.cpp new file mode 100644 index 0000000..f142ab4 --- /dev/null +++ b/clang/lib/Sema/AttributeList.cpp @@ -0,0 +1,126 @@ +//===--- 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/AST/Expr.h" +#include "clang/Basic/IdentifierTable.h" +#include "llvm/ADT/StringSwitch.h" +using namespace clang; + +size_t AttributeList::allocated_size() const { + if (IsAvailability) return AttributeFactory::AvailabilityAllocSize; + return (sizeof(AttributeList) + NumArgs * sizeof(Expr*)); +} + +AttributeFactory::AttributeFactory() { + // Go ahead and configure all the inline capacity. This is just a memset. + FreeLists.resize(InlineFreeListsCapacity); +} +AttributeFactory::~AttributeFactory() {} + +static size_t getFreeListIndexForSize(size_t size) { + assert(size >= sizeof(AttributeList)); + assert((size % sizeof(void*)) == 0); + return ((size - sizeof(AttributeList)) / sizeof(void*)); +} + +void *AttributeFactory::allocate(size_t size) { + // Check for a previously reclaimed attribute. + size_t index = getFreeListIndexForSize(size); + if (index < FreeLists.size()) { + if (AttributeList *attr = FreeLists[index]) { + FreeLists[index] = attr->NextInPool; + return attr; + } + } + + // Otherwise, allocate something new. + return Alloc.Allocate(size, llvm::AlignOf::Alignment); +} + +void AttributeFactory::reclaimPool(AttributeList *cur) { + assert(cur && "reclaiming empty pool!"); + do { + // Read this here, because we're going to overwrite NextInPool + // when we toss 'cur' into the appropriate queue. + AttributeList *next = cur->NextInPool; + + size_t size = cur->allocated_size(); + size_t freeListIndex = getFreeListIndexForSize(size); + + // Expand FreeLists to the appropriate size, if required. + if (freeListIndex >= FreeLists.size()) + FreeLists.resize(freeListIndex+1); + + // Add 'cur' to the appropriate free-list. + cur->NextInPool = FreeLists[freeListIndex]; + FreeLists[freeListIndex] = cur; + + cur = next; + } while (cur); +} + +void AttributePool::takePool(AttributeList *pool) { + assert(pool); + + // Fast path: this pool is empty. + if (!Head) { + Head = pool; + return; + } + + // Reverse the pool onto the current head. This optimizes for the + // pattern of pulling a lot of pools into a single pool. + do { + AttributeList *next = pool->NextInPool; + pool->NextInPool = Head; + Head = pool; + pool = next; + } while (pool); +} + +AttributeList * +AttributePool::createIntegerAttribute(ASTContext &C, IdentifierInfo *Name, + SourceLocation TokLoc, int Arg) { + Expr *IArg = IntegerLiteral::Create(C, llvm::APInt(32, (uint64_t) Arg), + C.IntTy, TokLoc); + return create(Name, TokLoc, 0, TokLoc, 0, TokLoc, &IArg, 1, 0); +} + +AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) { + StringRef AttrName = Name->getName(); + + // Normalize the attribute name, __foo__ becomes foo. + if (AttrName.startswith("__") && AttrName.endswith("__") && + AttrName.size() >= 4) + AttrName = AttrName.substr(2, AttrName.size() - 4); + + return llvm::StringSwitch(AttrName) + #include "clang/Sema/AttrParsedAttrKinds.inc" + .Case("address_space", AT_address_space) + .Case("align", AT_aligned) // FIXME - should it be "aligned"? + .Case("base_check", AT_base_check) + .Case("bounded", IgnoredAttribute) // OpenBSD + .Case("__const", AT_const) // some GCC headers do contain this spelling + .Case("cf_returns_autoreleased", AT_cf_returns_autoreleased) + .Case("mode", AT_mode) + .Case("vec_type_hint", IgnoredAttribute) + .Case("ext_vector_type", AT_ext_vector_type) + .Case("neon_vector_type", AT_neon_vector_type) + .Case("neon_polyvector_type", AT_neon_polyvector_type) + .Case("opencl_image_access", AT_opencl_image_access) + .Case("objc_gc", AT_objc_gc) + .Case("objc_ownership", AT_objc_ownership) + .Case("vector_size", AT_vector_size) + .Default(UnknownAttribute); +} diff --git a/clang/lib/Sema/CMakeLists.txt b/clang/lib/Sema/CMakeLists.txt new file mode 100644 index 0000000..07734c7 --- /dev/null +++ b/clang/lib/Sema/CMakeLists.txt @@ -0,0 +1,58 @@ +set(LLVM_USED_LIBS + clangAST + clangAnalysis + clangBasic + clangEdit + clangLex + ) + +add_clang_library(clangSema + AnalysisBasedWarnings.cpp + AttributeList.cpp + CodeCompleteConsumer.cpp + DeclSpec.cpp + DelayedDiagnostic.cpp + IdentifierResolver.cpp + JumpDiagnostics.cpp + Scope.cpp + Sema.cpp + SemaAccess.cpp + SemaAttr.cpp + SemaCXXScopeSpec.cpp + SemaCast.cpp + SemaChecking.cpp + SemaCodeComplete.cpp + SemaConsumer.cpp + SemaDecl.cpp + SemaDeclAttr.cpp + SemaDeclCXX.cpp + SemaDeclObjC.cpp + SemaExceptionSpec.cpp + SemaExpr.cpp + SemaExprCXX.cpp + SemaExprMember.cpp + SemaExprObjC.cpp + SemaFixItUtils.cpp + SemaInit.cpp + SemaLambda.cpp + SemaLookup.cpp + SemaObjCProperty.cpp + SemaOverload.cpp + SemaPseudoObject.cpp + SemaStmt.cpp + SemaStmtAttr.cpp + SemaTemplate.cpp + SemaTemplateDeduction.cpp + SemaTemplateInstantiate.cpp + SemaTemplateInstantiateDecl.cpp + SemaTemplateVariadic.cpp + SemaType.cpp + TargetAttributesSema.cpp + ) + +add_dependencies(clangSema ClangARMNeon ClangAttrClasses ClangAttrList + ClangDiagnosticSema ClangDeclNodes ClangStmtNodes + ClangAttrTemplateInstantiate ClangAttrParsedAttrList + ClangAttrParsedAttrKinds) + + diff --git a/clang/lib/Sema/CodeCompleteConsumer.cpp b/clang/lib/Sema/CodeCompleteConsumer.cpp new file mode 100644 index 0000000..ce9bbb9 --- /dev/null +++ b/clang/lib/Sema/CodeCompleteConsumer.cpp @@ -0,0 +1,641 @@ +//===--- CodeCompleteConsumer.cpp - Code Completion Interface ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the CodeCompleteConsumer class. +// +//===----------------------------------------------------------------------===// +#include "clang/Sema/CodeCompleteConsumer.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/Sema.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/Lex/Preprocessor.h" +#include "clang-c/Index.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/raw_ostream.h" +#include +#include +#include + +using namespace clang; + +//===----------------------------------------------------------------------===// +// Code completion context implementation +//===----------------------------------------------------------------------===// + +bool CodeCompletionContext::wantConstructorResults() const { + switch (Kind) { + case CCC_Recovery: + case CCC_Statement: + case CCC_Expression: + case CCC_ObjCMessageReceiver: + case CCC_ParenthesizedExpression: + return true; + + case CCC_TopLevel: + case CCC_ObjCInterface: + case CCC_ObjCImplementation: + case CCC_ObjCIvarList: + case CCC_ClassStructUnion: + case CCC_DotMemberAccess: + case CCC_ArrowMemberAccess: + case CCC_ObjCPropertyAccess: + case CCC_EnumTag: + case CCC_UnionTag: + case CCC_ClassOrStructTag: + case CCC_ObjCProtocolName: + case CCC_Namespace: + case CCC_Type: + case CCC_Name: + case CCC_PotentiallyQualifiedName: + case CCC_MacroName: + case CCC_MacroNameUse: + case CCC_PreprocessorExpression: + case CCC_PreprocessorDirective: + case CCC_NaturalLanguage: + case CCC_SelectorName: + case CCC_TypeQualifiers: + case CCC_Other: + case CCC_OtherWithMacros: + case CCC_ObjCInstanceMessage: + case CCC_ObjCClassMessage: + case CCC_ObjCInterfaceName: + case CCC_ObjCCategoryName: + return false; + } + + llvm_unreachable("Invalid CodeCompletionContext::Kind!"); +} + +//===----------------------------------------------------------------------===// +// Code completion string implementation +//===----------------------------------------------------------------------===// +CodeCompletionString::Chunk::Chunk(ChunkKind Kind, const char *Text) + : Kind(Kind), Text("") +{ + switch (Kind) { + case CK_TypedText: + case CK_Text: + case CK_Placeholder: + case CK_Informative: + case CK_ResultType: + case CK_CurrentParameter: + this->Text = Text; + break; + + case CK_Optional: + llvm_unreachable("Optional strings cannot be created from text"); + + case CK_LeftParen: + this->Text = "("; + break; + + case CK_RightParen: + this->Text = ")"; + break; + + case CK_LeftBracket: + this->Text = "["; + break; + + case CK_RightBracket: + this->Text = "]"; + break; + + case CK_LeftBrace: + this->Text = "{"; + break; + + case CK_RightBrace: + this->Text = "}"; + break; + + case CK_LeftAngle: + this->Text = "<"; + break; + + case CK_RightAngle: + this->Text = ">"; + break; + + case CK_Comma: + this->Text = ", "; + break; + + case CK_Colon: + this->Text = ":"; + break; + + case CK_SemiColon: + this->Text = ";"; + break; + + case CK_Equal: + this->Text = " = "; + break; + + case CK_HorizontalSpace: + this->Text = " "; + break; + + case CK_VerticalSpace: + this->Text = "\n"; + break; + } +} + +CodeCompletionString::Chunk +CodeCompletionString::Chunk::CreateText(const char *Text) { + return Chunk(CK_Text, Text); +} + +CodeCompletionString::Chunk +CodeCompletionString::Chunk::CreateOptional(CodeCompletionString *Optional) { + Chunk Result; + Result.Kind = CK_Optional; + Result.Optional = Optional; + return Result; +} + +CodeCompletionString::Chunk +CodeCompletionString::Chunk::CreatePlaceholder(const char *Placeholder) { + return Chunk(CK_Placeholder, Placeholder); +} + +CodeCompletionString::Chunk +CodeCompletionString::Chunk::CreateInformative(const char *Informative) { + return Chunk(CK_Informative, Informative); +} + +CodeCompletionString::Chunk +CodeCompletionString::Chunk::CreateResultType(const char *ResultType) { + return Chunk(CK_ResultType, ResultType); +} + +CodeCompletionString::Chunk +CodeCompletionString::Chunk::CreateCurrentParameter( + const char *CurrentParameter) { + return Chunk(CK_CurrentParameter, CurrentParameter); +} + +CodeCompletionString::CodeCompletionString(const Chunk *Chunks, + unsigned NumChunks, + unsigned Priority, + CXAvailabilityKind Availability, + const char **Annotations, + unsigned NumAnnotations, + CXCursorKind ParentKind, + StringRef ParentName) + : NumChunks(NumChunks), NumAnnotations(NumAnnotations), + Priority(Priority), Availability(Availability), ParentKind(ParentKind), + ParentName(ParentName) +{ + assert(NumChunks <= 0xffff); + assert(NumAnnotations <= 0xffff); + + Chunk *StoredChunks = reinterpret_cast(this + 1); + for (unsigned I = 0; I != NumChunks; ++I) + StoredChunks[I] = Chunks[I]; + + const char **StoredAnnotations = reinterpret_cast(StoredChunks + NumChunks); + for (unsigned I = 0; I != NumAnnotations; ++I) + StoredAnnotations[I] = Annotations[I]; +} + +unsigned CodeCompletionString::getAnnotationCount() const { + return NumAnnotations; +} + +const char *CodeCompletionString::getAnnotation(unsigned AnnotationNr) const { + if (AnnotationNr < NumAnnotations) + return reinterpret_cast(end())[AnnotationNr]; + else + return 0; +} + + +std::string CodeCompletionString::getAsString() const { + std::string Result; + llvm::raw_string_ostream OS(Result); + + for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) { + switch (C->Kind) { + case CK_Optional: OS << "{#" << C->Optional->getAsString() << "#}"; break; + case CK_Placeholder: OS << "<#" << C->Text << "#>"; break; + + case CK_Informative: + case CK_ResultType: + OS << "[#" << C->Text << "#]"; + break; + + case CK_CurrentParameter: OS << "<#" << C->Text << "#>"; break; + default: OS << C->Text; break; + } + } + return OS.str(); +} + +const char *CodeCompletionString::getTypedText() const { + for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) + if (C->Kind == CK_TypedText) + return C->Text; + + return 0; +} + +const char *CodeCompletionAllocator::CopyString(StringRef String) { + char *Mem = (char *)Allocate(String.size() + 1, 1); + std::copy(String.begin(), String.end(), Mem); + Mem[String.size()] = 0; + return Mem; +} + +const char *CodeCompletionAllocator::CopyString(Twine String) { + // FIXME: It would be more efficient to teach Twine to tell us its size and + // then add a routine there to fill in an allocated char* with the contents + // of the string. + SmallString<128> Data; + return CopyString(String.toStringRef(Data)); +} + +StringRef CodeCompletionTUInfo::getParentName(DeclContext *DC) { + NamedDecl *ND = dyn_cast(DC); + if (!ND) + return StringRef(); + + // Check whether we've already cached the parent name. + StringRef &CachedParentName = ParentNames[DC]; + if (!CachedParentName.empty()) + return CachedParentName; + + // If we already processed this DeclContext and assigned empty to it, the + // data pointer will be non-null. + if (CachedParentName.data() != 0) + return StringRef(); + + // Find the interesting names. + llvm::SmallVector Contexts; + while (DC && !DC->isFunctionOrMethod()) { + if (NamedDecl *ND = dyn_cast(DC)) { + if (ND->getIdentifier()) + Contexts.push_back(DC); + } + + DC = DC->getParent(); + } + + { + llvm::SmallString<128> S; + llvm::raw_svector_ostream OS(S); + bool First = true; + for (unsigned I = Contexts.size(); I != 0; --I) { + if (First) + First = false; + else { + OS << "::"; + } + + DeclContext *CurDC = Contexts[I-1]; + if (ObjCCategoryImplDecl *CatImpl = dyn_cast(CurDC)) + CurDC = CatImpl->getCategoryDecl(); + + if (ObjCCategoryDecl *Cat = dyn_cast(CurDC)) { + ObjCInterfaceDecl *Interface = Cat->getClassInterface(); + if (!Interface) { + // Assign an empty StringRef but with non-null data to distinguish + // between empty because we didn't process the DeclContext yet. + CachedParentName = StringRef((const char *)~0U, 0); + return StringRef(); + } + + OS << Interface->getName() << '(' << Cat->getName() << ')'; + } else { + OS << cast(CurDC)->getName(); + } + } + + CachedParentName = AllocatorRef->CopyString(OS.str()); + } + + return CachedParentName; +} + +CodeCompletionString *CodeCompletionBuilder::TakeString() { + void *Mem = getAllocator().Allocate( + sizeof(CodeCompletionString) + sizeof(Chunk) * Chunks.size() + + sizeof(const char *) * Annotations.size(), + llvm::alignOf()); + CodeCompletionString *Result + = new (Mem) CodeCompletionString(Chunks.data(), Chunks.size(), + Priority, Availability, + Annotations.data(), Annotations.size(), + ParentKind, ParentName); + Chunks.clear(); + return Result; +} + +void CodeCompletionBuilder::AddTypedTextChunk(const char *Text) { + Chunks.push_back(Chunk(CodeCompletionString::CK_TypedText, Text)); +} + +void CodeCompletionBuilder::AddTextChunk(const char *Text) { + Chunks.push_back(Chunk::CreateText(Text)); +} + +void CodeCompletionBuilder::AddOptionalChunk(CodeCompletionString *Optional) { + Chunks.push_back(Chunk::CreateOptional(Optional)); +} + +void CodeCompletionBuilder::AddPlaceholderChunk(const char *Placeholder) { + Chunks.push_back(Chunk::CreatePlaceholder(Placeholder)); +} + +void CodeCompletionBuilder::AddInformativeChunk(const char *Text) { + Chunks.push_back(Chunk::CreateInformative(Text)); +} + +void CodeCompletionBuilder::AddResultTypeChunk(const char *ResultType) { + Chunks.push_back(Chunk::CreateResultType(ResultType)); +} + +void +CodeCompletionBuilder::AddCurrentParameterChunk(const char *CurrentParameter) { + Chunks.push_back(Chunk::CreateCurrentParameter(CurrentParameter)); +} + +void CodeCompletionBuilder::AddChunk(CodeCompletionString::ChunkKind CK, + const char *Text) { + Chunks.push_back(Chunk(CK, Text)); +} + +void CodeCompletionBuilder::addParentContext(DeclContext *DC) { + if (DC->isTranslationUnit()) { + ParentKind = CXCursor_TranslationUnit; + return; + } + + if (DC->isFunctionOrMethod()) + return; + + NamedDecl *ND = dyn_cast(DC); + if (!ND) + return; + + ParentKind = getCursorKindForDecl(ND); + ParentName = getCodeCompletionTUInfo().getParentName(DC); +} + +unsigned CodeCompletionResult::getPriorityFromDecl(NamedDecl *ND) { + if (!ND) + return CCP_Unlikely; + + // Context-based decisions. + DeclContext *DC = ND->getDeclContext()->getRedeclContext(); + if (DC->isFunctionOrMethod() || isa(DC)) { + // _cmd is relatively rare + if (ImplicitParamDecl *ImplicitParam = dyn_cast(ND)) + if (ImplicitParam->getIdentifier() && + ImplicitParam->getIdentifier()->isStr("_cmd")) + return CCP_ObjC_cmd; + + return CCP_LocalDeclaration; + } + if (DC->isRecord() || isa(DC)) + return CCP_MemberDeclaration; + + // Content-based decisions. + if (isa(ND)) + return CCP_Constant; + if (isa(ND) || isa(ND)) + return CCP_Type; + + return CCP_Declaration; +} + +//===----------------------------------------------------------------------===// +// Code completion overload candidate implementation +//===----------------------------------------------------------------------===// +FunctionDecl * +CodeCompleteConsumer::OverloadCandidate::getFunction() const { + if (getKind() == CK_Function) + return Function; + else if (getKind() == CK_FunctionTemplate) + return FunctionTemplate->getTemplatedDecl(); + else + return 0; +} + +const FunctionType * +CodeCompleteConsumer::OverloadCandidate::getFunctionType() const { + switch (Kind) { + case CK_Function: + return Function->getType()->getAs(); + + case CK_FunctionTemplate: + return FunctionTemplate->getTemplatedDecl()->getType() + ->getAs(); + + case CK_FunctionType: + return Type; + } + + llvm_unreachable("Invalid CandidateKind!"); +} + +//===----------------------------------------------------------------------===// +// Code completion consumer implementation +//===----------------------------------------------------------------------===// + +CodeCompleteConsumer::~CodeCompleteConsumer() { } + +void +PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef, + 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 CodeCompletionResult::RK_Declaration: + OS << *Results[I].Declaration; + if (Results[I].Hidden) + OS << " (Hidden)"; + if (CodeCompletionString *CCS + = Results[I].CreateCodeCompletionString(SemaRef, getAllocator(), + CCTUInfo)) { + OS << " : " << CCS->getAsString(); + } + + OS << '\n'; + break; + + case CodeCompletionResult::RK_Keyword: + OS << Results[I].Keyword << '\n'; + break; + + case CodeCompletionResult::RK_Macro: { + OS << Results[I].Macro->getName(); + if (CodeCompletionString *CCS + = Results[I].CreateCodeCompletionString(SemaRef, getAllocator(), + CCTUInfo)) { + OS << " : " << CCS->getAsString(); + } + OS << '\n'; + break; + } + + case CodeCompletionResult::RK_Pattern: { + OS << "Pattern : " + << Results[I].Pattern->getAsString() << '\n'; + break; + } + } + } +} + +void +PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef, + unsigned CurrentArg, + OverloadCandidate *Candidates, + unsigned NumCandidates) { + for (unsigned I = 0; I != NumCandidates; ++I) { + if (CodeCompletionString *CCS + = Candidates[I].CreateSignatureString(CurrentArg, SemaRef, + getAllocator(), CCTUInfo)) { + OS << "OVERLOAD: " << CCS->getAsString() << "\n"; + } + } +} + +/// \brief Retrieve the effective availability of the given declaration. +static AvailabilityResult getDeclAvailability(Decl *D) { + AvailabilityResult AR = D->getAvailability(); + if (isa(D)) + AR = std::max(AR, cast(D->getDeclContext())->getAvailability()); + return AR; +} + +void CodeCompletionResult::computeCursorKindAndAvailability(bool Accessible) { + switch (Kind) { + case RK_Pattern: + if (!Declaration) { + // Do nothing: Patterns can come with cursor kinds! + break; + } + // Fall through + + case RK_Declaration: { + // Set the availability based on attributes. + switch (getDeclAvailability(Declaration)) { + case AR_Available: + case AR_NotYetIntroduced: + Availability = CXAvailability_Available; + break; + + case AR_Deprecated: + Availability = CXAvailability_Deprecated; + break; + + case AR_Unavailable: + Availability = CXAvailability_NotAvailable; + break; + } + + if (FunctionDecl *Function = dyn_cast(Declaration)) + if (Function->isDeleted()) + Availability = CXAvailability_NotAvailable; + + CursorKind = getCursorKindForDecl(Declaration); + if (CursorKind == CXCursor_UnexposedDecl) { + // FIXME: Forward declarations of Objective-C classes and protocols + // are not directly exposed, but we want code completion to treat them + // like a definition. + if (isa(Declaration)) + CursorKind = CXCursor_ObjCInterfaceDecl; + else if (isa(Declaration)) + CursorKind = CXCursor_ObjCProtocolDecl; + else + CursorKind = CXCursor_NotImplemented; + } + break; + } + + case RK_Macro: + Availability = CXAvailability_Available; + CursorKind = CXCursor_MacroDefinition; + break; + + case RK_Keyword: + Availability = CXAvailability_Available; + CursorKind = CXCursor_NotImplemented; + break; + } + + if (!Accessible) + Availability = CXAvailability_NotAccessible; +} + +/// \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 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; + StringRef XStr = getOrderedName(X, XSaved); + 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; +} diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp new file mode 100644 index 0000000..b531acc --- /dev/null +++ b/clang/lib/Sema/DeclSpec.cpp @@ -0,0 +1,986 @@ +//===--- 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/LocInfoType.h" +#include "clang/Sema/ParsedTemplate.h" +#include "clang/Sema/SemaDiagnostic.h" +#include "clang/Sema/Sema.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/Expr.h" +#include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/TypeLoc.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(DiagnosticsEngine &D, SourceLocation Loc, + unsigned DiagID) { + return D.Report(Loc, 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; +} + +void CXXScopeSpec::Extend(ASTContext &Context, SourceLocation TemplateKWLoc, + TypeLoc TL, SourceLocation ColonColonLoc) { + Builder.Extend(Context, TemplateKWLoc, TL, ColonColonLoc); + if (Range.getBegin().isInvalid()) + Range.setBegin(TL.getBeginLoc()); + Range.setEnd(ColonColonLoc); + + assert(Range == Builder.getSourceRange() && + "NestedNameSpecifierLoc range computation incorrect"); +} + +void CXXScopeSpec::Extend(ASTContext &Context, IdentifierInfo *Identifier, + SourceLocation IdentifierLoc, + SourceLocation ColonColonLoc) { + Builder.Extend(Context, Identifier, IdentifierLoc, ColonColonLoc); + + if (Range.getBegin().isInvalid()) + Range.setBegin(IdentifierLoc); + Range.setEnd(ColonColonLoc); + + assert(Range == Builder.getSourceRange() && + "NestedNameSpecifierLoc range computation incorrect"); +} + +void CXXScopeSpec::Extend(ASTContext &Context, NamespaceDecl *Namespace, + SourceLocation NamespaceLoc, + SourceLocation ColonColonLoc) { + Builder.Extend(Context, Namespace, NamespaceLoc, ColonColonLoc); + + if (Range.getBegin().isInvalid()) + Range.setBegin(NamespaceLoc); + Range.setEnd(ColonColonLoc); + + assert(Range == Builder.getSourceRange() && + "NestedNameSpecifierLoc range computation incorrect"); +} + +void CXXScopeSpec::Extend(ASTContext &Context, NamespaceAliasDecl *Alias, + SourceLocation AliasLoc, + SourceLocation ColonColonLoc) { + Builder.Extend(Context, Alias, AliasLoc, ColonColonLoc); + + if (Range.getBegin().isInvalid()) + Range.setBegin(AliasLoc); + Range.setEnd(ColonColonLoc); + + assert(Range == Builder.getSourceRange() && + "NestedNameSpecifierLoc range computation incorrect"); +} + +void CXXScopeSpec::MakeGlobal(ASTContext &Context, + SourceLocation ColonColonLoc) { + Builder.MakeGlobal(Context, ColonColonLoc); + + Range = SourceRange(ColonColonLoc); + + assert(Range == Builder.getSourceRange() && + "NestedNameSpecifierLoc range computation incorrect"); +} + +void CXXScopeSpec::MakeTrivial(ASTContext &Context, + NestedNameSpecifier *Qualifier, SourceRange R) { + Builder.MakeTrivial(Context, Qualifier, R); + Range = R; +} + +void CXXScopeSpec::Adopt(NestedNameSpecifierLoc Other) { + if (!Other) { + Range = SourceRange(); + Builder.Clear(); + return; + } + + Range = Other.getSourceRange(); + Builder.Adopt(Other); +} + +SourceLocation CXXScopeSpec::getLastQualifierNameLoc() const { + if (!Builder.getRepresentation()) + return SourceLocation(); + return Builder.getTemporary().getLocalBeginLoc(); +} + +NestedNameSpecifierLoc +CXXScopeSpec::getWithLocInContext(ASTContext &Context) const { + if (!Builder.getRepresentation()) + return NestedNameSpecifierLoc(); + + return Builder.getWithLocInContext(Context); +} + +/// 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 RefQualifierIsLvalueRef, + SourceLocation RefQualifierLoc, + SourceLocation ConstQualifierLoc, + SourceLocation + VolatileQualifierLoc, + SourceLocation MutableLoc, + ExceptionSpecificationType + ESpecType, + SourceLocation ESpecLoc, + ParsedType *Exceptions, + SourceRange *ExceptionRanges, + unsigned NumExceptions, + Expr *NoexceptExpr, + SourceLocation LocalRangeBegin, + SourceLocation LocalRangeEnd, + Declarator &TheDeclarator, + ParsedType TrailingReturnType) { + DeclaratorChunk I; + I.Kind = Function; + I.Loc = LocalRangeBegin; + I.EndLoc = LocalRangeEnd; + I.Fun.AttrList = 0; + 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.RefQualifierIsLValueRef = RefQualifierIsLvalueRef; + I.Fun.RefQualifierLoc = RefQualifierLoc.getRawEncoding(); + I.Fun.ConstQualifierLoc = ConstQualifierLoc.getRawEncoding(); + I.Fun.VolatileQualifierLoc = VolatileQualifierLoc.getRawEncoding(); + I.Fun.MutableLoc = MutableLoc.getRawEncoding(); + I.Fun.ExceptionSpecType = ESpecType; + I.Fun.ExceptionSpecLoc = ESpecLoc.getRawEncoding(); + I.Fun.NumExceptions = 0; + I.Fun.Exceptions = 0; + I.Fun.NoexceptExpr = 0; + I.Fun.TrailingReturnType = TrailingReturnType.getAsOpaquePtr(); + + // 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); + } + + // Check what exception specification information we should actually store. + switch (ESpecType) { + default: break; // By default, save nothing. + case EST_Dynamic: + // new[] an exception array if needed + if (NumExceptions) { + I.Fun.NumExceptions = 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]; + } + } + break; + + case EST_ComputedNoexcept: + I.Fun.NoexceptExpr = NoexceptExpr; + break; + } + return I; +} + +bool Declarator::isDeclarationOfFunction() const { + for (unsigned i = 0, i_end = DeclTypeInfo.size(); i < i_end; ++i) { + switch (DeclTypeInfo[i].Kind) { + case DeclaratorChunk::Function: + return true; + case DeclaratorChunk::Paren: + continue; + case DeclaratorChunk::Pointer: + case DeclaratorChunk::Reference: + case DeclaratorChunk::Array: + case DeclaratorChunk::BlockPointer: + case DeclaratorChunk::MemberPointer: + return false; + } + llvm_unreachable("Invalid type chunk"); + } + + switch (DS.getTypeSpecType()) { + case TST_atomic: + case TST_auto: + case TST_bool: + case TST_char: + case TST_char16: + case TST_char32: + case TST_class: + case TST_decimal128: + case TST_decimal32: + case TST_decimal64: + case TST_double: + case TST_enum: + case TST_error: + case TST_float: + case TST_half: + case TST_int: + case TST_int128: + case TST_struct: + case TST_union: + case TST_unknown_anytype: + case TST_unspecified: + case TST_void: + case TST_wchar: + return false; + + case TST_decltype: + case TST_typeofExpr: + if (Expr *E = DS.getRepAsExpr()) + return E->getType()->isFunctionType(); + return false; + + case TST_underlyingType: + case TST_typename: + case TST_typeofType: { + QualType QT = DS.getRepAsType().get(); + if (QT.isNull()) + return false; + + if (const LocInfoType *LIT = dyn_cast(QT)) + QT = LIT->getType(); + + if (QT.isNull()) + return false; + + return QT->isFunctionType(); + } + } + + llvm_unreachable("Invalid TypeSpecType!"); +} + +/// 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_int128: return "__int128"; + case DeclSpec::TST_half: return "half"; + 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_underlyingType: return "__underlying_type"; + case DeclSpec::TST_unknown_anytype: return "__unknown_anytype"; + case DeclSpec::TST_atomic: return "_Atomic"; + 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(Sema &S, SCS SC, SourceLocation Loc, + const char *&PrevSpec, + unsigned &DiagID) { + // OpenCL 1.1 6.8g: "The extern, static, auto and register storage-class + // specifiers are not supported." + // It seems sensible to prohibit private_extern too + // The cl_clang_storage_class_specifiers extension enables support for + // these storage-class specifiers. + if (S.getLangOpts().OpenCL && + !S.getOpenCLOptions().cl_clang_storage_class_specifiers) { + switch (SC) { + case SCS_extern: + case SCS_private_extern: + case SCS_auto: + case SCS_register: + case SCS_static: + DiagID = diag::err_not_opencl_storage_class_specifier; + PrevSpec = getSpecifierName(SC); + return true; + default: + break; + } + } + + if (StorageClassSpec != SCS_unspecified) { + // Maybe this is an attempt to use C++0x 'auto' outside of C++0x mode. + bool isInvalid = true; + if (TypeSpecType == TST_unspecified && S.getLangOpts().CPlusPlus) { + if (SC == SCS_auto) + return SetTypeSpecType(TST_auto, Loc, PrevSpec, DiagID); + if (StorageClassSpec == SCS_auto) { + isInvalid = SetTypeSpecType(TST_auto, StorageClassSpecLoc, + PrevSpec, DiagID); + assert(!isInvalid && "auto SCS -> TST recovery failed"); + } + } + + // 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 (isInvalid && + !(SCS_extern_in_linkage_spec && + StorageClassSpec == SCS_extern && + SC == SCS_typedef)) + return BadSpecifier(SC, (SCS)StorageClassSpec, PrevSpec, DiagID); + } + StorageClassSpec = SC; + StorageClassSpecLoc = Loc; + assert((unsigned)SC == 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) { + // Overwrite TSWLoc only if TypeSpecWidth was unspecified, so that + // for 'long long' we will keep the source location of the first 'long'. + if (TypeSpecWidth == TSW_unspecified) + TSWLoc = Loc; + // Allow turning long -> long long. + else if (W != TSW_longlong || TypeSpecWidth != TSW_long) + return BadSpecifier(W, (TSW)TypeSpecWidth, PrevSpec, DiagID); + TypeSpecWidth = W; + 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) { + return SetTypeSpecType(T, Loc, Loc, PrevSpec, DiagID, Rep); +} + +bool DeclSpec::SetTypeSpecType(TST T, SourceLocation TagKwLoc, + SourceLocation TagNameLoc, + 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 = TagKwLoc; + TSTNameLoc = TagNameLoc; + 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; + TSTNameLoc = Loc; + TypeSpecOwned = false; + return false; +} + +bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc, + const char *&PrevSpec, + unsigned &DiagID, + Decl *Rep, bool Owned) { + return SetTypeSpecType(T, Loc, Loc, PrevSpec, DiagID, Rep, Owned); +} + +bool DeclSpec::SetTypeSpecType(TST T, SourceLocation TagKwLoc, + SourceLocation TagNameLoc, + 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 = TagKwLoc; + TSTNameLoc = TagNameLoc; + 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; + } + TSTLoc = Loc; + TSTNameLoc = Loc; + if (TypeAltiVecVector && (T == TST_bool) && !TypeAltiVecBool) { + TypeAltiVecBool = true; + return false; + } + TypeSpecType = T; + 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; + TSTNameLoc = Loc; + return false; +} + +bool DeclSpec::SetTypeSpecError() { + TypeSpecType = TST_error; + TypeSpecOwned = false; + TSTLoc = SourceLocation(); + TSTNameLoc = 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: llvm_unreachable("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::setModulePrivateSpec(SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID) { + if (isModulePrivateSpecified()) { + PrevSpec = "__module_private__"; + DiagID = diag::ext_duplicate_declspec; + return true; + } + + ModulePrivateLoc = 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().getList(); + 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(DiagnosticsEngine &D, Preprocessor &PP) { + // Before possibly changing their values, save specs as written. + SaveWrittenBuiltinSpecs(); + SaveStorageSpecifierAsWritten(); + + // Check the type specifier components first. + + // 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, 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, 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, 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_int128 && + TypeSpecType != TST_char && TypeSpecType != TST_wchar) { + Diag(D, TSSLoc, 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, + 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, 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, 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. + if (!PP.getLangOpts().CPlusPlus) + Diag(D, TSTLoc, diag::ext_integer_complex); + } else if (TypeSpecType != TST_float && TypeSpecType != TST_double) { + Diag(D, TSCLoc, diag::err_invalid_complex_spec) + << getSpecifierName((TST)TypeSpecType); + TypeSpecComplex = TSC_unspecified; + } + } + + // If no type specifier was provided and we're parsing a language where + // the type specifier is not optional, but we got 'auto' as a storage + // class specifier, then assume this is an attempt to use C++0x's 'auto' + // type specifier. + // FIXME: Does Microsoft really support implicit int in C++? + if (PP.getLangOpts().CPlusPlus && !PP.getLangOpts().MicrosoftExt && + TypeSpecType == TST_unspecified && StorageClassSpec == SCS_auto) { + TypeSpecType = TST_auto; + StorageClassSpec = StorageClassSpecAsWritten = SCS_unspecified; + TSTLoc = TSTNameLoc = StorageClassSpecLoc; + StorageClassSpecLoc = SourceLocation(); + } + // Diagnose if we've recovered from an ill-formed 'auto' storage class + // specifier in a pre-C++0x dialect of C++. + if (!PP.getLangOpts().CPlusPlus0x && TypeSpecType == TST_auto) + Diag(D, TSTLoc, diag::ext_auto_type_specifier); + if (PP.getLangOpts().CPlusPlus && !PP.getLangOpts().CPlusPlus0x && + StorageClassSpec == SCS_auto) + Diag(D, StorageClassSpecLoc, diag::warn_auto_storage_class) + << FixItHint::CreateRemoval(StorageClassSpecLoc); + if (TypeSpecType == TST_char16 || TypeSpecType == TST_char32) + Diag(D, TSTLoc, diag::warn_cxx98_compat_unicode_type) + << (TypeSpecType == TST_char16 ? "char16_t" : "char32_t"); + if (Constexpr_specified) + Diag(D, ConstexprLoc, diag::warn_cxx98_compat_constexpr); + + // 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.getLocWithOffset(strlen(SpecName)); + + Diag(D, SCLoc, 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() { + 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]; + } +} + +bool VirtSpecifiers::SetSpecifier(Specifier VS, SourceLocation Loc, + const char *&PrevSpec) { + LastLocation = Loc; + + if (Specifiers & VS) { + PrevSpec = getSpecifierName(VS); + return true; + } + + Specifiers |= VS; + + switch (VS) { + default: llvm_unreachable("Unknown specifier!"); + case VS_Override: VS_overrideLoc = Loc; break; + case VS_Final: VS_finalLoc = Loc; break; + } + + return false; +} + +const char *VirtSpecifiers::getSpecifierName(Specifier VS) { + switch (VS) { + default: llvm_unreachable("Unknown specifier"); + case VS_Override: return "override"; + case VS_Final: return "final"; + } +} diff --git a/clang/lib/Sema/DelayedDiagnostic.cpp b/clang/lib/Sema/DelayedDiagnostic.cpp new file mode 100644 index 0000000..876f9d7 --- /dev/null +++ b/clang/lib/Sema/DelayedDiagnostic.cpp @@ -0,0 +1,56 @@ +//===--- DelayedDiagnostic.cpp - Delayed declarator diagnostics -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the DelayedDiagnostic class implementation, which +// is used to record diagnostics that are being conditionally produced +// during declarator parsing. +// +// This file also defines AccessedEntity. +// +//===----------------------------------------------------------------------===// +#include "clang/Sema/DelayedDiagnostic.h" +#include +using namespace clang; +using namespace sema; + +DelayedDiagnostic DelayedDiagnostic::makeDeprecation(SourceLocation Loc, + const NamedDecl *D, + const ObjCInterfaceDecl *UnknownObjCClass, + StringRef Msg) { + DelayedDiagnostic DD; + DD.Kind = Deprecation; + DD.Triggered = false; + DD.Loc = Loc; + DD.DeprecationData.Decl = D; + DD.DeprecationData.UnknownObjCClass = UnknownObjCClass; + char *MessageData = 0; + if (Msg.size()) { + MessageData = new char [Msg.size()]; + memcpy(MessageData, Msg.data(), Msg.size()); + } + + DD.DeprecationData.Message = MessageData; + DD.DeprecationData.MessageLen = Msg.size(); + return DD; +} + +void DelayedDiagnostic::Destroy() { + switch (Kind) { + case Access: + getAccessData().~AccessedEntity(); + break; + + case Deprecation: + delete [] DeprecationData.Message; + break; + + case ForbiddenType: + break; + } +} diff --git a/clang/lib/Sema/IdentifierResolver.cpp b/clang/lib/Sema/IdentifierResolver.cpp new file mode 100644 index 0000000..4d62cab --- /dev/null +++ b/clang/lib/Sema/IdentifierResolver.cpp @@ -0,0 +1,444 @@ +//===- IdentifierResolver.cpp - 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 implements the IdentifierResolver class, which is used for lexical +// scoped lookup, based on declaration names. +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/IdentifierResolver.h" +#include "clang/Sema/Scope.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclObjC.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Lex/ExternalPreprocessorSource.h" +#include "clang/Lex/Preprocessor.h" + +using namespace clang; + +//===----------------------------------------------------------------------===// +// IdDeclInfoMap class +//===----------------------------------------------------------------------===// + +/// IdDeclInfoMap - Associates IdDeclInfos with declaration names. +/// Allocates 'pools' (vectors of IdDeclInfos) to avoid allocating each +/// individual IdDeclInfo to heap. +class IdentifierResolver::IdDeclInfoMap { + static const unsigned int POOL_SIZE = 512; + + /// We use our own linked-list implementation because it is sadly + /// impossible to add something to a pre-C++0x STL container without + /// a completely unnecessary copy. + struct IdDeclInfoPool { + IdDeclInfoPool(IdDeclInfoPool *Next) : Next(Next) {} + + IdDeclInfoPool *Next; + IdDeclInfo Pool[POOL_SIZE]; + }; + + IdDeclInfoPool *CurPool; + unsigned int CurIndex; + +public: + IdDeclInfoMap() : CurPool(0), CurIndex(POOL_SIZE) {} + + ~IdDeclInfoMap() { + IdDeclInfoPool *Cur = CurPool; + while (IdDeclInfoPool *P = Cur) { + Cur = Cur->Next; + delete P; + } + } + + /// Returns the IdDeclInfo associated to the DeclarationName. + /// It creates a new IdDeclInfo if one was not created before for this id. + IdDeclInfo &operator[](DeclarationName Name); +}; + + +//===----------------------------------------------------------------------===// +// IdDeclInfo Implementation +//===----------------------------------------------------------------------===// + +/// RemoveDecl - Remove the decl from the scope chain. +/// The decl must already be part of the decl chain. +void IdentifierResolver::IdDeclInfo::RemoveDecl(NamedDecl *D) { + for (DeclsTy::iterator I = Decls.end(); I != Decls.begin(); --I) { + if (D == *(I-1)) { + Decls.erase(I-1); + return; + } + } + + llvm_unreachable("Didn't find this decl on its identifier's chain!"); +} + +bool +IdentifierResolver::IdDeclInfo::ReplaceDecl(NamedDecl *Old, NamedDecl *New) { + for (DeclsTy::iterator I = Decls.end(); I != Decls.begin(); --I) { + if (Old == *(I-1)) { + *(I - 1) = New; + return true; + } + } + + return false; +} + + +//===----------------------------------------------------------------------===// +// IdentifierResolver Implementation +//===----------------------------------------------------------------------===// + +IdentifierResolver::IdentifierResolver(Preprocessor &PP) + : LangOpt(PP.getLangOpts()), PP(PP), + IdDeclInfos(new IdDeclInfoMap) { +} + +IdentifierResolver::~IdentifierResolver() { + delete IdDeclInfos; +} + +/// 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 IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx, + ASTContext &Context, Scope *S, + bool ExplicitInstantiationOrSpecialization) const { + Ctx = Ctx->getRedeclContext(); + + if (Ctx->isFunctionOrMethod() || S->isFunctionPrototypeScope()) { + // Ignore the scopes associated within transparent declaration contexts. + while (S->getEntity() && + ((DeclContext *)S->getEntity())->isTransparentContext()) + S = S->getParent(); + + if (S->isDeclScope(D)) + return true; + if (LangOpt.CPlusPlus) { + // C++ 3.3.2p3: + // The name declared in a catch exception-declaration is local to the + // handler and shall not be redeclared in the outermost block of the + // handler. + // C++ 3.3.2p4: + // Names declared in the for-init-statement, and in the condition of if, + // while, for, and switch statements are local to the if, while, for, or + // switch statement (including the controlled statement), and shall not be + // redeclared in a subsequent condition of that statement nor in the + // outermost block (or, for the if statement, any of the outermost blocks) + // of the controlled statement. + // + assert(S->getParent() && "No TUScope?"); + if (S->getParent()->getFlags() & Scope::ControlScope) + return S->getParent()->isDeclScope(D); + } + return false; + } + + DeclContext *DCtx = D->getDeclContext()->getRedeclContext(); + return ExplicitInstantiationOrSpecialization + ? Ctx->InEnclosingNamespaceSetOf(DCtx) + : Ctx->Equals(DCtx); +} + +/// AddDecl - Link the decl to its shadowed decl chain. +void IdentifierResolver::AddDecl(NamedDecl *D) { + DeclarationName Name = D->getDeclName(); + if (IdentifierInfo *II = Name.getAsIdentifierInfo()) + updatingIdentifier(*II); + + void *Ptr = Name.getFETokenInfo(); + + if (!Ptr) { + Name.setFETokenInfo(D); + return; + } + + IdDeclInfo *IDI; + + if (isDeclPtr(Ptr)) { + Name.setFETokenInfo(NULL); + IDI = &(*IdDeclInfos)[Name]; + NamedDecl *PrevD = static_cast(Ptr); + IDI->AddDecl(PrevD); + } else + IDI = toIdDeclInfo(Ptr); + + IDI->AddDecl(D); +} + +void IdentifierResolver::InsertDeclAfter(iterator Pos, NamedDecl *D) { + DeclarationName Name = D->getDeclName(); + if (IdentifierInfo *II = Name.getAsIdentifierInfo()) + updatingIdentifier(*II); + + void *Ptr = Name.getFETokenInfo(); + + if (!Ptr) { + AddDecl(D); + return; + } + + if (isDeclPtr(Ptr)) { + // We only have a single declaration: insert before or after it, + // as appropriate. + if (Pos == iterator()) { + // Add the new declaration before the existing declaration. + NamedDecl *PrevD = static_cast(Ptr); + RemoveDecl(PrevD); + AddDecl(D); + AddDecl(PrevD); + } else { + // Add new declaration after the existing declaration. + AddDecl(D); + } + + return; + } + + // General case: insert the declaration at the appropriate point in the + // list, which already has at least two elements. + IdDeclInfo *IDI = toIdDeclInfo(Ptr); + if (Pos.isIterator()) { + IDI->InsertDecl(Pos.getIterator() + 1, D); + } else + IDI->InsertDecl(IDI->decls_begin(), D); +} + +/// RemoveDecl - Unlink the decl from its shadowed decl chain. +/// The decl must already be part of the decl chain. +void IdentifierResolver::RemoveDecl(NamedDecl *D) { + assert(D && "null param passed"); + DeclarationName Name = D->getDeclName(); + if (IdentifierInfo *II = Name.getAsIdentifierInfo()) + updatingIdentifier(*II); + + void *Ptr = Name.getFETokenInfo(); + + assert(Ptr && "Didn't find this decl on its identifier's chain!"); + + if (isDeclPtr(Ptr)) { + assert(D == Ptr && "Didn't find this decl on its identifier's chain!"); + Name.setFETokenInfo(NULL); + return; + } + + return toIdDeclInfo(Ptr)->RemoveDecl(D); +} + +bool IdentifierResolver::ReplaceDecl(NamedDecl *Old, NamedDecl *New) { + assert(Old->getDeclName() == New->getDeclName() && + "Cannot replace a decl with another decl of a different name"); + + DeclarationName Name = Old->getDeclName(); + if (IdentifierInfo *II = Name.getAsIdentifierInfo()) + updatingIdentifier(*II); + + void *Ptr = Name.getFETokenInfo(); + + if (!Ptr) + return false; + + if (isDeclPtr(Ptr)) { + if (Ptr == Old) { + Name.setFETokenInfo(New); + return true; + } + return false; + } + + return toIdDeclInfo(Ptr)->ReplaceDecl(Old, New); +} + +/// begin - Returns an iterator for decls with name 'Name'. +IdentifierResolver::iterator +IdentifierResolver::begin(DeclarationName Name) { + if (IdentifierInfo *II = Name.getAsIdentifierInfo()) + readingIdentifier(*II); + + void *Ptr = Name.getFETokenInfo(); + if (!Ptr) return end(); + + if (isDeclPtr(Ptr)) + return iterator(static_cast(Ptr)); + + IdDeclInfo *IDI = toIdDeclInfo(Ptr); + + IdDeclInfo::DeclsTy::iterator I = IDI->decls_end(); + if (I != IDI->decls_begin()) + return iterator(I-1); + // No decls found. + return end(); +} + +namespace { + enum DeclMatchKind { + DMK_Different, + DMK_Replace, + DMK_Ignore + }; +} + +/// \brief Compare two declarations to see whether they are different or, +/// if they are the same, whether the new declaration should replace the +/// existing declaration. +static DeclMatchKind compareDeclarations(NamedDecl *Existing, NamedDecl *New) { + // If the declarations are identical, ignore the new one. + if (Existing == New) + return DMK_Ignore; + + // If the declarations have different kinds, they're obviously different. + if (Existing->getKind() != New->getKind()) + return DMK_Different; + + // If the declarations are redeclarations of each other, keep the newest one. + if (Existing->getCanonicalDecl() == New->getCanonicalDecl()) { + // If the existing declaration is somewhere in the previous declaration + // chain of the new declaration, then prefer the new declaration. + for (Decl::redecl_iterator RD = New->redecls_begin(), + RDEnd = New->redecls_end(); + RD != RDEnd; ++RD) { + if (*RD == Existing) + return DMK_Replace; + + if (RD->isCanonicalDecl()) + break; + } + + return DMK_Ignore; + } + + return DMK_Different; +} + +bool IdentifierResolver::tryAddTopLevelDecl(NamedDecl *D, DeclarationName Name){ + if (IdentifierInfo *II = Name.getAsIdentifierInfo()) + readingIdentifier(*II); + + void *Ptr = Name.getFETokenInfo(); + + if (!Ptr) { + Name.setFETokenInfo(D); + return true; + } + + IdDeclInfo *IDI; + + if (isDeclPtr(Ptr)) { + NamedDecl *PrevD = static_cast(Ptr); + + switch (compareDeclarations(PrevD, D)) { + case DMK_Different: + break; + + case DMK_Ignore: + return false; + + case DMK_Replace: + Name.setFETokenInfo(D); + return true; + } + + Name.setFETokenInfo(NULL); + IDI = &(*IdDeclInfos)[Name]; + + // If the existing declaration is not visible in translation unit scope, + // then add the new top-level declaration first. + if (!PrevD->getDeclContext()->getRedeclContext()->isTranslationUnit()) { + IDI->AddDecl(D); + IDI->AddDecl(PrevD); + } else { + IDI->AddDecl(PrevD); + IDI->AddDecl(D); + } + return true; + } + + IDI = toIdDeclInfo(Ptr); + + // See whether this declaration is identical to any existing declarations. + // If not, find the right place to insert it. + for (IdDeclInfo::DeclsTy::iterator I = IDI->decls_begin(), + IEnd = IDI->decls_end(); + I != IEnd; ++I) { + + switch (compareDeclarations(*I, D)) { + case DMK_Different: + break; + + case DMK_Ignore: + return false; + + case DMK_Replace: + *I = D; + return true; + } + + if (!(*I)->getDeclContext()->getRedeclContext()->isTranslationUnit()) { + // We've found a declaration that is not visible from the translation + // unit (it's in an inner scope). Insert our declaration here. + IDI->InsertDecl(I, D); + return true; + } + } + + // Add the declaration to the end. + IDI->AddDecl(D); + return true; +} + +void IdentifierResolver::readingIdentifier(IdentifierInfo &II) { + if (II.isOutOfDate()) + PP.getExternalSource()->updateOutOfDateIdentifier(II); +} + +void IdentifierResolver::updatingIdentifier(IdentifierInfo &II) { + if (II.isOutOfDate()) + PP.getExternalSource()->updateOutOfDateIdentifier(II); + + if (II.isFromAST()) + II.setChangedSinceDeserialization(); +} + +//===----------------------------------------------------------------------===// +// IdDeclInfoMap Implementation +//===----------------------------------------------------------------------===// + +/// Returns the IdDeclInfo associated to the DeclarationName. +/// It creates a new IdDeclInfo if one was not created before for this id. +IdentifierResolver::IdDeclInfo & +IdentifierResolver::IdDeclInfoMap::operator[](DeclarationName Name) { + void *Ptr = Name.getFETokenInfo(); + + if (Ptr) return *toIdDeclInfo(Ptr); + + if (CurIndex == POOL_SIZE) { + CurPool = new IdDeclInfoPool(CurPool); + CurIndex = 0; + } + IdDeclInfo *IDI = &CurPool->Pool[CurIndex]; + Name.setFETokenInfo(reinterpret_cast( + reinterpret_cast(IDI) | 0x1) + ); + ++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/clang/lib/Sema/JumpDiagnostics.cpp b/clang/lib/Sema/JumpDiagnostics.cpp new file mode 100644 index 0000000..ab786c6 --- /dev/null +++ b/clang/lib/Sema/JumpDiagnostics.cpp @@ -0,0 +1,770 @@ +//===--- JumpDiagnostics.cpp - Protected scope jump analysis ------*- C++ -*-=// +// +// 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 JumpScopeChecker class, which is used to diagnose +// jumps that enter a protected scope in an invalid way. +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/SemaInternal.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/StmtObjC.h" +#include "clang/AST/StmtCXX.h" +#include "llvm/ADT/BitVector.h" +using namespace clang; + +namespace { + +/// JumpScopeChecker - This object is used by Sema to diagnose invalid jumps +/// into VLA and other protected scopes. For example, this rejects: +/// goto L; +/// int a[n]; +/// L: +/// +class JumpScopeChecker { + Sema &S; + + /// GotoScope - This is a record that we use to keep track of all of the + /// scopes that are introduced by VLAs and other things that scope jumps like + /// gotos. This scope tree has nothing to do with the source scope tree, + /// because you can have multiple VLA scopes per compound statement, and most + /// compound statements don't introduce any scopes. + struct GotoScope { + /// ParentScope - The index in ScopeMap of the parent scope. This is 0 for + /// the parent scope is the function body. + unsigned ParentScope; + + /// InDiag - The note to emit if there is a jump into this scope. + unsigned InDiag; + + /// OutDiag - The note to emit if there is an indirect jump out + /// of this scope. Direct jumps always clean up their current scope + /// in an orderly way. + unsigned OutDiag; + + /// Loc - Location to emit the diagnostic. + SourceLocation Loc; + + GotoScope(unsigned parentScope, unsigned InDiag, unsigned OutDiag, + SourceLocation L) + : ParentScope(parentScope), InDiag(InDiag), OutDiag(OutDiag), Loc(L) {} + }; + + SmallVector Scopes; + llvm::DenseMap LabelAndGotoScopes; + SmallVector Jumps; + + SmallVector IndirectJumps; + SmallVector IndirectJumpTargets; +public: + JumpScopeChecker(Stmt *Body, Sema &S); +private: + void BuildScopeInformation(Decl *D, unsigned &ParentScope); + void BuildScopeInformation(VarDecl *D, const BlockDecl *BDecl, + unsigned &ParentScope); + void BuildScopeInformation(Stmt *S, unsigned &origParentScope); + + void VerifyJumps(); + void VerifyIndirectJumps(); + void NoteJumpIntoScopes(ArrayRef ToScopes); + void DiagnoseIndirectJump(IndirectGotoStmt *IG, unsigned IGScope, + LabelDecl *Target, unsigned TargetScope); + void CheckJump(Stmt *From, Stmt *To, SourceLocation DiagLoc, + unsigned JumpDiag, unsigned JumpDiagWarning, + unsigned JumpDiagCXX98Compat); + + unsigned GetDeepestCommonScope(unsigned A, unsigned B); +}; +} // end anonymous namespace + + +JumpScopeChecker::JumpScopeChecker(Stmt *Body, Sema &s) : S(s) { + // Add a scope entry for function scope. + Scopes.push_back(GotoScope(~0U, ~0U, ~0U, SourceLocation())); + + // Build information for the top level compound statement, so that we have a + // defined scope record for every "goto" and label. + unsigned BodyParentScope = 0; + BuildScopeInformation(Body, BodyParentScope); + + // Check that all jumps we saw are kosher. + VerifyJumps(); + VerifyIndirectJumps(); +} + +/// GetDeepestCommonScope - Finds the innermost scope enclosing the +/// two scopes. +unsigned JumpScopeChecker::GetDeepestCommonScope(unsigned A, unsigned B) { + while (A != B) { + // Inner scopes are created after outer scopes and therefore have + // higher indices. + if (A < B) { + assert(Scopes[B].ParentScope < B); + B = Scopes[B].ParentScope; + } else { + assert(Scopes[A].ParentScope < A); + A = Scopes[A].ParentScope; + } + } + return A; +} + +typedef std::pair ScopePair; + +/// GetDiagForGotoScopeDecl - If this decl induces a new goto scope, return a +/// diagnostic that should be emitted if control goes over it. If not, return 0. +static ScopePair GetDiagForGotoScopeDecl(ASTContext &Context, const Decl *D) { + if (const VarDecl *VD = dyn_cast(D)) { + unsigned InDiag = 0, OutDiag = 0; + if (VD->getType()->isVariablyModifiedType()) + InDiag = diag::note_protected_by_vla; + + if (VD->hasAttr()) + return ScopePair(diag::note_protected_by___block, + diag::note_exits___block); + + if (VD->hasAttr()) + return ScopePair(diag::note_protected_by_cleanup, + diag::note_exits_cleanup); + + if (Context.getLangOpts().ObjCAutoRefCount && VD->hasLocalStorage()) { + switch (VD->getType().getObjCLifetime()) { + case Qualifiers::OCL_None: + case Qualifiers::OCL_ExplicitNone: + case Qualifiers::OCL_Autoreleasing: + break; + + case Qualifiers::OCL_Strong: + case Qualifiers::OCL_Weak: + return ScopePair(diag::note_protected_by_objc_ownership, + diag::note_exits_objc_ownership); + } + } + + if (Context.getLangOpts().CPlusPlus && VD->hasLocalStorage()) { + // C++11 [stmt.dcl]p3: + // A program that jumps from a point where a variable with automatic + // storage duration is not in scope to a point where it is in scope + // is ill-formed unless the variable has scalar type, class type with + // a trivial default constructor and a trivial destructor, a + // cv-qualified version of one of these types, or an array of one of + // the preceding types and is declared without an initializer. + + // C++03 [stmt.dcl.p3: + // A program that jumps from a point where a local variable + // with automatic storage duration is not in scope to a point + // where it is in scope is ill-formed unless the variable has + // POD type and is declared without an initializer. + + if (const Expr *init = VD->getInit()) { + // We actually give variables of record type (or array thereof) + // an initializer even if that initializer only calls a trivial + // ctor. Detect that case. + // FIXME: With generalized initializer lists, this may + // classify "X x{};" as having no initializer. + unsigned inDiagToUse = diag::note_protected_by_variable_init; + + const CXXRecordDecl *record = 0; + + if (const CXXConstructExpr *cce = dyn_cast(init)) { + const CXXConstructorDecl *ctor = cce->getConstructor(); + record = ctor->getParent(); + + if (ctor->isTrivial() && ctor->isDefaultConstructor()) { + if (!record->hasTrivialDestructor()) + inDiagToUse = diag::note_protected_by_variable_nontriv_destructor; + else if (!record->isPOD()) + inDiagToUse = diag::note_protected_by_variable_non_pod; + else + inDiagToUse = 0; + } + } else if (VD->getType()->isArrayType()) { + record = VD->getType()->getBaseElementTypeUnsafe() + ->getAsCXXRecordDecl(); + } + + if (inDiagToUse) + InDiag = inDiagToUse; + + // Also object to indirect jumps which leave scopes with dtors. + if (record && !record->hasTrivialDestructor()) + OutDiag = diag::note_exits_dtor; + } + } + + return ScopePair(InDiag, OutDiag); + } + + if (const TypedefDecl *TD = dyn_cast(D)) { + if (TD->getUnderlyingType()->isVariablyModifiedType()) + return ScopePair(diag::note_protected_by_vla_typedef, 0); + } + + if (const TypeAliasDecl *TD = dyn_cast(D)) { + if (TD->getUnderlyingType()->isVariablyModifiedType()) + return ScopePair(diag::note_protected_by_vla_type_alias, 0); + } + + return ScopePair(0U, 0U); +} + +/// \brief Build scope information for a declaration that is part of a DeclStmt. +void JumpScopeChecker::BuildScopeInformation(Decl *D, unsigned &ParentScope) { + // If this decl causes a new scope, push and switch to it. + std::pair Diags = GetDiagForGotoScopeDecl(S.Context, D); + if (Diags.first || Diags.second) { + Scopes.push_back(GotoScope(ParentScope, Diags.first, Diags.second, + D->getLocation())); + ParentScope = Scopes.size()-1; + } + + // If the decl has an initializer, walk it with the potentially new + // scope we just installed. + if (VarDecl *VD = dyn_cast(D)) + if (Expr *Init = VD->getInit()) + BuildScopeInformation(Init, ParentScope); +} + +/// \brief Build scope information for a captured block literal variables. +void JumpScopeChecker::BuildScopeInformation(VarDecl *D, + const BlockDecl *BDecl, + unsigned &ParentScope) { + // exclude captured __block variables; there's no destructor + // associated with the block literal for them. + if (D->hasAttr()) + return; + QualType T = D->getType(); + QualType::DestructionKind destructKind = T.isDestructedType(); + if (destructKind != QualType::DK_none) { + std::pair Diags; + switch (destructKind) { + case QualType::DK_cxx_destructor: + Diags = ScopePair(diag::note_enters_block_captures_cxx_obj, + diag::note_exits_block_captures_cxx_obj); + break; + case QualType::DK_objc_strong_lifetime: + Diags = ScopePair(diag::note_enters_block_captures_strong, + diag::note_exits_block_captures_strong); + break; + case QualType::DK_objc_weak_lifetime: + Diags = ScopePair(diag::note_enters_block_captures_weak, + diag::note_exits_block_captures_weak); + break; + case QualType::DK_none: + llvm_unreachable("non-lifetime captured variable"); + } + SourceLocation Loc = D->getLocation(); + if (Loc.isInvalid()) + Loc = BDecl->getLocation(); + Scopes.push_back(GotoScope(ParentScope, + Diags.first, Diags.second, Loc)); + ParentScope = Scopes.size()-1; + } +} + +/// BuildScopeInformation - The statements from CI to CE are known to form a +/// coherent VLA scope with a specified parent node. Walk through the +/// statements, adding any labels or gotos to LabelAndGotoScopes and recursively +/// walking the AST as needed. +void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned &origParentScope) { + // If this is a statement, rather than an expression, scopes within it don't + // propagate out into the enclosing scope. Otherwise we have to worry + // about block literals, which have the lifetime of their enclosing statement. + unsigned independentParentScope = origParentScope; + unsigned &ParentScope = ((isa(S) && !isa(S)) + ? origParentScope : independentParentScope); + + bool SkipFirstSubStmt = false; + + // If we found a label, remember that it is in ParentScope scope. + switch (S->getStmtClass()) { + case Stmt::AddrLabelExprClass: + IndirectJumpTargets.push_back(cast(S)->getLabel()); + break; + + case Stmt::IndirectGotoStmtClass: + // "goto *&&lbl;" is a special case which we treat as equivalent + // to a normal goto. In addition, we don't calculate scope in the + // operand (to avoid recording the address-of-label use), which + // works only because of the restricted set of expressions which + // we detect as constant targets. + if (cast(S)->getConstantTarget()) { + LabelAndGotoScopes[S] = ParentScope; + Jumps.push_back(S); + return; + } + + LabelAndGotoScopes[S] = ParentScope; + IndirectJumps.push_back(cast(S)); + break; + + case Stmt::SwitchStmtClass: + // Evaluate the condition variable before entering the scope of the switch + // statement. + if (VarDecl *Var = cast(S)->getConditionVariable()) { + BuildScopeInformation(Var, ParentScope); + SkipFirstSubStmt = true; + } + // Fall through + + case Stmt::GotoStmtClass: + // Remember both what scope a goto is in as well as the fact that we have + // it. This makes the second scan not have to walk the AST again. + LabelAndGotoScopes[S] = ParentScope; + Jumps.push_back(S); + break; + + default: + break; + } + + for (Stmt::child_range CI = S->children(); CI; ++CI) { + if (SkipFirstSubStmt) { + SkipFirstSubStmt = false; + continue; + } + + 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 (CaseStmt *CS = dyn_cast(SubStmt)) + Next = CS->getSubStmt(); + else if (DefaultStmt *DS = dyn_cast(SubStmt)) + Next = DS->getSubStmt(); + else if (LabelStmt *LS = dyn_cast(SubStmt)) + Next = LS->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)) { + // The decl statement creates a scope if any of the decls in it are VLAs + // or have the cleanup attribute. + for (DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end(); + I != E; ++I) + BuildScopeInformation(*I, ParentScope); + continue; + } + // Disallow jumps into any part of an @try statement by pushing a scope and + // walking all sub-stmts in that scope. + if (ObjCAtTryStmt *AT = dyn_cast(SubStmt)) { + unsigned newParentScope; + // Recursively walk the AST for the @try part. + Scopes.push_back(GotoScope(ParentScope, + diag::note_protected_by_objc_try, + diag::note_exits_objc_try, + AT->getAtTryLoc())); + if (Stmt *TryPart = AT->getTryBody()) + BuildScopeInformation(TryPart, (newParentScope = Scopes.size()-1)); + + // Jump from the catch to the finally or try is not valid. + for (unsigned I = 0, N = AT->getNumCatchStmts(); I != N; ++I) { + ObjCAtCatchStmt *AC = AT->getCatchStmt(I); + Scopes.push_back(GotoScope(ParentScope, + diag::note_protected_by_objc_catch, + diag::note_exits_objc_catch, + AC->getAtCatchLoc())); + // @catches are nested and it isn't + BuildScopeInformation(AC->getCatchBody(), + (newParentScope = Scopes.size()-1)); + } + + // Jump from the finally to the try or catch is not valid. + if (ObjCAtFinallyStmt *AF = AT->getFinallyStmt()) { + Scopes.push_back(GotoScope(ParentScope, + diag::note_protected_by_objc_finally, + diag::note_exits_objc_finally, + AF->getAtFinallyLoc())); + BuildScopeInformation(AF, (newParentScope = Scopes.size()-1)); + } + + continue; + } + + unsigned newParentScope; + // Disallow jumps into the protected statement of an @synchronized, but + // allow jumps into the object expression it protects. + if (ObjCAtSynchronizedStmt *AS = dyn_cast(SubStmt)){ + // Recursively walk the AST for the @synchronized object expr, it is + // evaluated in the normal scope. + BuildScopeInformation(AS->getSynchExpr(), ParentScope); + + // Recursively walk the AST for the @synchronized part, protected by a new + // scope. + Scopes.push_back(GotoScope(ParentScope, + diag::note_protected_by_objc_synchronized, + diag::note_exits_objc_synchronized, + AS->getAtSynchronizedLoc())); + BuildScopeInformation(AS->getSynchBody(), + (newParentScope = Scopes.size()-1)); + continue; + } + + // Disallow jumps into any part of a C++ try statement. This is pretty + // much the same as for Obj-C. + if (CXXTryStmt *TS = dyn_cast(SubStmt)) { + Scopes.push_back(GotoScope(ParentScope, + diag::note_protected_by_cxx_try, + diag::note_exits_cxx_try, + TS->getSourceRange().getBegin())); + if (Stmt *TryBlock = TS->getTryBlock()) + BuildScopeInformation(TryBlock, (newParentScope = Scopes.size()-1)); + + // Jump from the catch into the try is not allowed either. + for (unsigned I = 0, E = TS->getNumHandlers(); I != E; ++I) { + CXXCatchStmt *CS = TS->getHandler(I); + Scopes.push_back(GotoScope(ParentScope, + diag::note_protected_by_cxx_catch, + diag::note_exits_cxx_catch, + CS->getSourceRange().getBegin())); + BuildScopeInformation(CS->getHandlerBlock(), + (newParentScope = Scopes.size()-1)); + } + + continue; + } + + // Disallow jumps into the protected statement of an @autoreleasepool. + if (ObjCAutoreleasePoolStmt *AS = dyn_cast(SubStmt)){ + // Recursively walk the AST for the @autoreleasepool part, protected by a new + // scope. + Scopes.push_back(GotoScope(ParentScope, + diag::note_protected_by_objc_autoreleasepool, + diag::note_exits_objc_autoreleasepool, + AS->getAtLoc())); + BuildScopeInformation(AS->getSubStmt(), (newParentScope = Scopes.size()-1)); + continue; + } + + if (const BlockExpr *BE = dyn_cast(SubStmt)) { + const BlockDecl *BDecl = BE->getBlockDecl(); + for (BlockDecl::capture_const_iterator ci = BDecl->capture_begin(), + ce = BDecl->capture_end(); ci != ce; ++ci) { + VarDecl *variable = ci->getVariable(); + BuildScopeInformation(variable, BDecl, ParentScope); + } + } + + // Recursively walk the AST. + BuildScopeInformation(SubStmt, ParentScope); + } +} + +/// VerifyJumps - Verify each element of the Jumps array to see if they are +/// valid, emitting diagnostics if not. +void JumpScopeChecker::VerifyJumps() { + while (!Jumps.empty()) { + Stmt *Jump = Jumps.pop_back_val(); + + // With a goto, + if (GotoStmt *GS = dyn_cast(Jump)) { + CheckJump(GS, GS->getLabel()->getStmt(), GS->getGotoLoc(), + diag::err_goto_into_protected_scope, + diag::warn_goto_into_protected_scope, + diag::warn_cxx98_compat_goto_into_protected_scope); + continue; + } + + // We only get indirect gotos here when they have a constant target. + if (IndirectGotoStmt *IGS = dyn_cast(Jump)) { + LabelDecl *Target = IGS->getConstantTarget(); + CheckJump(IGS, Target->getStmt(), IGS->getGotoLoc(), + diag::err_goto_into_protected_scope, + diag::warn_goto_into_protected_scope, + diag::warn_cxx98_compat_goto_into_protected_scope); + continue; + } + + SwitchStmt *SS = cast(Jump); + for (SwitchCase *SC = SS->getSwitchCaseList(); SC; + SC = SC->getNextSwitchCase()) { + assert(LabelAndGotoScopes.count(SC) && "Case not visited?"); + CheckJump(SS, SC, SC->getLocStart(), + diag::err_switch_into_protected_scope, 0, + diag::warn_cxx98_compat_switch_into_protected_scope); + } + } +} + +/// VerifyIndirectJumps - Verify whether any possible indirect jump +/// might cross a protection boundary. Unlike direct jumps, indirect +/// jumps count cleanups as protection boundaries: since there's no +/// way to know where the jump is going, we can't implicitly run the +/// right cleanups the way we can with direct jumps. +/// +/// Thus, an indirect jump is "trivial" if it bypasses no +/// initializations and no teardowns. More formally, an indirect jump +/// from A to B is trivial if the path out from A to DCA(A,B) is +/// trivial and the path in from DCA(A,B) to B is trivial, where +/// DCA(A,B) is the deepest common ancestor of A and B. +/// Jump-triviality is transitive but asymmetric. +/// +/// A path in is trivial if none of the entered scopes have an InDiag. +/// A path out is trivial is none of the exited scopes have an OutDiag. +/// +/// Under these definitions, this function checks that the indirect +/// jump between A and B is trivial for every indirect goto statement A +/// and every label B whose address was taken in the function. +void JumpScopeChecker::VerifyIndirectJumps() { + if (IndirectJumps.empty()) return; + + // If there aren't any address-of-label expressions in this function, + // complain about the first indirect goto. + if (IndirectJumpTargets.empty()) { + S.Diag(IndirectJumps[0]->getGotoLoc(), + diag::err_indirect_goto_without_addrlabel); + return; + } + + // Collect a single representative of every scope containing an + // indirect goto. For most code bases, this substantially cuts + // down on the number of jump sites we'll have to consider later. + typedef std::pair JumpScope; + SmallVector JumpScopes; + { + llvm::DenseMap JumpScopesMap; + for (SmallVectorImpl::iterator + I = IndirectJumps.begin(), E = IndirectJumps.end(); I != E; ++I) { + IndirectGotoStmt *IG = *I; + assert(LabelAndGotoScopes.count(IG) && + "indirect jump didn't get added to scopes?"); + unsigned IGScope = LabelAndGotoScopes[IG]; + IndirectGotoStmt *&Entry = JumpScopesMap[IGScope]; + if (!Entry) Entry = IG; + } + JumpScopes.reserve(JumpScopesMap.size()); + for (llvm::DenseMap::iterator + I = JumpScopesMap.begin(), E = JumpScopesMap.end(); I != E; ++I) + JumpScopes.push_back(*I); + } + + // Collect a single representative of every scope containing a + // label whose address was taken somewhere in the function. + // For most code bases, there will be only one such scope. + llvm::DenseMap TargetScopes; + for (SmallVectorImpl::iterator + I = IndirectJumpTargets.begin(), E = IndirectJumpTargets.end(); + I != E; ++I) { + LabelDecl *TheLabel = *I; + assert(LabelAndGotoScopes.count(TheLabel->getStmt()) && + "Referenced label didn't get added to scopes?"); + unsigned LabelScope = LabelAndGotoScopes[TheLabel->getStmt()]; + LabelDecl *&Target = TargetScopes[LabelScope]; + if (!Target) Target = TheLabel; + } + + // For each target scope, make sure it's trivially reachable from + // every scope containing a jump site. + // + // A path between scopes always consists of exitting zero or more + // scopes, then entering zero or more scopes. We build a set of + // of scopes S from which the target scope can be trivially + // entered, then verify that every jump scope can be trivially + // exitted to reach a scope in S. + llvm::BitVector Reachable(Scopes.size(), false); + for (llvm::DenseMap::iterator + TI = TargetScopes.begin(), TE = TargetScopes.end(); TI != TE; ++TI) { + unsigned TargetScope = TI->first; + LabelDecl *TargetLabel = TI->second; + + Reachable.reset(); + + // Mark all the enclosing scopes from which you can safely jump + // into the target scope. 'Min' will end up being the index of + // the shallowest such scope. + unsigned Min = TargetScope; + while (true) { + Reachable.set(Min); + + // Don't go beyond the outermost scope. + if (Min == 0) break; + + // Stop if we can't trivially enter the current scope. + if (Scopes[Min].InDiag) break; + + Min = Scopes[Min].ParentScope; + } + + // Walk through all the jump sites, checking that they can trivially + // reach this label scope. + for (SmallVectorImpl::iterator + I = JumpScopes.begin(), E = JumpScopes.end(); I != E; ++I) { + unsigned Scope = I->first; + + // Walk out the "scope chain" for this scope, looking for a scope + // we've marked reachable. For well-formed code this amortizes + // to O(JumpScopes.size() / Scopes.size()): we only iterate + // when we see something unmarked, and in well-formed code we + // mark everything we iterate past. + bool IsReachable = false; + while (true) { + if (Reachable.test(Scope)) { + // If we find something reachable, mark all the scopes we just + // walked through as reachable. + for (unsigned S = I->first; S != Scope; S = Scopes[S].ParentScope) + Reachable.set(S); + IsReachable = true; + break; + } + + // Don't walk out if we've reached the top-level scope or we've + // gotten shallower than the shallowest reachable scope. + if (Scope == 0 || Scope < Min) break; + + // Don't walk out through an out-diagnostic. + if (Scopes[Scope].OutDiag) break; + + Scope = Scopes[Scope].ParentScope; + } + + // Only diagnose if we didn't find something. + if (IsReachable) continue; + + DiagnoseIndirectJump(I->second, I->first, TargetLabel, TargetScope); + } + } +} + +/// Return true if a particular error+note combination must be downgraded to a +/// warning in Microsoft mode. +static bool IsMicrosoftJumpWarning(unsigned JumpDiag, unsigned InDiagNote) { + return (JumpDiag == diag::err_goto_into_protected_scope && + (InDiagNote == diag::note_protected_by_variable_init || + InDiagNote == diag::note_protected_by_variable_nontriv_destructor)); +} + +/// Return true if a particular note should be downgraded to a compatibility +/// warning in C++11 mode. +static bool IsCXX98CompatWarning(Sema &S, unsigned InDiagNote) { + return S.getLangOpts().CPlusPlus0x && + InDiagNote == diag::note_protected_by_variable_non_pod; +} + +/// Produce primary diagnostic for an indirect jump statement. +static void DiagnoseIndirectJumpStmt(Sema &S, IndirectGotoStmt *Jump, + LabelDecl *Target, bool &Diagnosed) { + if (Diagnosed) + return; + S.Diag(Jump->getGotoLoc(), diag::err_indirect_goto_in_protected_scope); + S.Diag(Target->getStmt()->getIdentLoc(), diag::note_indirect_goto_target); + Diagnosed = true; +} + +/// Produce note diagnostics for a jump into a protected scope. +void JumpScopeChecker::NoteJumpIntoScopes(ArrayRef ToScopes) { + assert(!ToScopes.empty()); + for (unsigned I = 0, E = ToScopes.size(); I != E; ++I) + if (Scopes[ToScopes[I]].InDiag) + S.Diag(Scopes[ToScopes[I]].Loc, Scopes[ToScopes[I]].InDiag); +} + +/// Diagnose an indirect jump which is known to cross scopes. +void JumpScopeChecker::DiagnoseIndirectJump(IndirectGotoStmt *Jump, + unsigned JumpScope, + LabelDecl *Target, + unsigned TargetScope) { + assert(JumpScope != TargetScope); + + unsigned Common = GetDeepestCommonScope(JumpScope, TargetScope); + bool Diagnosed = false; + + // Walk out the scope chain until we reach the common ancestor. + for (unsigned I = JumpScope; I != Common; I = Scopes[I].ParentScope) + if (Scopes[I].OutDiag) { + DiagnoseIndirectJumpStmt(S, Jump, Target, Diagnosed); + S.Diag(Scopes[I].Loc, Scopes[I].OutDiag); + } + + SmallVector ToScopesCXX98Compat; + + // Now walk into the scopes containing the label whose address was taken. + for (unsigned I = TargetScope; I != Common; I = Scopes[I].ParentScope) + if (IsCXX98CompatWarning(S, Scopes[I].InDiag)) + ToScopesCXX98Compat.push_back(I); + else if (Scopes[I].InDiag) { + DiagnoseIndirectJumpStmt(S, Jump, Target, Diagnosed); + S.Diag(Scopes[I].Loc, Scopes[I].InDiag); + } + + // Diagnose this jump if it would be ill-formed in C++98. + if (!Diagnosed && !ToScopesCXX98Compat.empty()) { + S.Diag(Jump->getGotoLoc(), + diag::warn_cxx98_compat_indirect_goto_in_protected_scope); + S.Diag(Target->getStmt()->getIdentLoc(), diag::note_indirect_goto_target); + NoteJumpIntoScopes(ToScopesCXX98Compat); + } +} + +/// CheckJump - Validate that the specified jump statement is valid: that it is +/// jumping within or out of its current scope, not into a deeper one. +void JumpScopeChecker::CheckJump(Stmt *From, Stmt *To, SourceLocation DiagLoc, + unsigned JumpDiagError, unsigned JumpDiagWarning, + unsigned JumpDiagCXX98Compat) { + assert(LabelAndGotoScopes.count(From) && "Jump didn't get added to scopes?"); + unsigned FromScope = LabelAndGotoScopes[From]; + + assert(LabelAndGotoScopes.count(To) && "Jump didn't get added to scopes?"); + unsigned ToScope = LabelAndGotoScopes[To]; + + // Common case: exactly the same scope, which is fine. + if (FromScope == ToScope) return; + + unsigned CommonScope = GetDeepestCommonScope(FromScope, ToScope); + + // It's okay to jump out from a nested scope. + if (CommonScope == ToScope) return; + + // Pull out (and reverse) any scopes we might need to diagnose skipping. + SmallVector ToScopesCXX98Compat; + SmallVector ToScopesError; + SmallVector ToScopesWarning; + for (unsigned I = ToScope; I != CommonScope; I = Scopes[I].ParentScope) { + if (S.getLangOpts().MicrosoftMode && JumpDiagWarning != 0 && + IsMicrosoftJumpWarning(JumpDiagError, Scopes[I].InDiag)) + ToScopesWarning.push_back(I); + else if (IsCXX98CompatWarning(S, Scopes[I].InDiag)) + ToScopesCXX98Compat.push_back(I); + else if (Scopes[I].InDiag) + ToScopesError.push_back(I); + } + + // Handle warnings. + if (!ToScopesWarning.empty()) { + S.Diag(DiagLoc, JumpDiagWarning); + NoteJumpIntoScopes(ToScopesWarning); + } + + // Handle errors. + if (!ToScopesError.empty()) { + S.Diag(DiagLoc, JumpDiagError); + NoteJumpIntoScopes(ToScopesError); + } + + // Handle -Wc++98-compat warnings if the jump is well-formed. + if (ToScopesError.empty() && !ToScopesCXX98Compat.empty()) { + S.Diag(DiagLoc, JumpDiagCXX98Compat); + NoteJumpIntoScopes(ToScopesCXX98Compat); + } +} + +void Sema::DiagnoseInvalidJumps(Stmt *Body) { + (void)JumpScopeChecker(Body, *this); +} diff --git a/clang/lib/Sema/Makefile b/clang/lib/Sema/Makefile new file mode 100644 index 0000000..2c02739 --- /dev/null +++ b/clang/lib/Sema/Makefile @@ -0,0 +1,19 @@ +##===- clang/lib/Sema/Makefile -----------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +# +# This implements the semantic analyzer and AST builder library for the +# C-Language front-end. +# +##===----------------------------------------------------------------------===## + +CLANG_LEVEL := ../.. +LIBRARYNAME := clangSema + +include $(CLANG_LEVEL)/Makefile + diff --git a/clang/lib/Sema/Scope.cpp b/clang/lib/Sema/Scope.cpp new file mode 100644 index 0000000..10f12ce --- /dev/null +++ b/clang/lib/Sema/Scope.cpp @@ -0,0 +1,71 @@ +//===- Scope.cpp - Lexical scope information --------------------*- C++ -*-===// +// +// 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 Scope class, which is used for recording +// information about a lexical scope. +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/Scope.h" + +using namespace clang; + +void Scope::Init(Scope *parent, unsigned flags) { + AnyParent = parent; + Flags = flags; + + if (parent && !(flags & FnScope)) { + BreakParent = parent->BreakParent; + ContinueParent = parent->ContinueParent; + } else { + // Control scopes do not contain the contents of nested function scopes for + // control flow purposes. + BreakParent = ContinueParent = 0; + } + + if (parent) { + Depth = parent->Depth + 1; + PrototypeDepth = parent->PrototypeDepth; + PrototypeIndex = 0; + FnParent = parent->FnParent; + BlockParent = parent->BlockParent; + TemplateParamParent = parent->TemplateParamParent; + } else { + Depth = 0; + PrototypeDepth = 0; + PrototypeIndex = 0; + FnParent = BlockParent = 0; + TemplateParamParent = 0; + } + + // If this scope is a function or contains breaks/continues, remember it. + if (flags & FnScope) FnParent = this; + if (flags & BreakScope) BreakParent = this; + if (flags & ContinueScope) ContinueParent = this; + if (flags & BlockScope) BlockParent = this; + if (flags & TemplateParamScope) TemplateParamParent = this; + + // If this is a prototype scope, record that. + if (flags & FunctionPrototypeScope) PrototypeDepth++; + + DeclsInScope.clear(); + UsingDirectives.clear(); + Entity = 0; + ErrorTrap.reset(); +} + +bool Scope::containedInPrototypeScope() const { + const Scope *S = this; + while (S) { + if (S->isFunctionPrototypeScope()) + return true; + S = S->getParent(); + } + return false; +} diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp new file mode 100644 index 0000000..30a9cd7 --- /dev/null +++ b/clang/lib/Sema/Sema.cpp @@ -0,0 +1,1102 @@ +//===--- Sema.cpp - AST Builder and Semantic Analysis Implementation ------===// +// +// 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 actions class which performs semantic analysis and +// builds an AST out of a parse stream. +// +//===----------------------------------------------------------------------===// + +#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/TemplateDeduction.h" +#include "clang/Sema/ExternalSemaSource.h" +#include "clang/Sema/ObjCMethodList.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/AST/ExprCXX.h" +#include "clang/AST/StmtCXX.h" +#include "clang/Lex/HeaderSearch.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Basic/FileManager.h" +#include "clang/Basic/PartialDiagnostic.h" +#include "clang/Basic/TargetInfo.h" +using namespace clang; +using namespace sema; + +FunctionScopeInfo::~FunctionScopeInfo() { } + +void FunctionScopeInfo::Clear() { + HasBranchProtectedScope = false; + HasBranchIntoScope = false; + HasIndirectGoto = false; + + SwitchStack.clear(); + Returns.clear(); + ErrorTrap.reset(); + PossiblyUnreachableDiags.clear(); +} + +BlockScopeInfo::~BlockScopeInfo() { } +LambdaScopeInfo::~LambdaScopeInfo() { } + +PrintingPolicy Sema::getPrintingPolicy(const ASTContext &Context, + const Preprocessor &PP) { + PrintingPolicy Policy = Context.getPrintingPolicy(); + Policy.Bool = Context.getLangOpts().Bool; + if (!Policy.Bool) { + if (MacroInfo *BoolMacro = PP.getMacroInfo(&Context.Idents.get("bool"))) { + Policy.Bool = BoolMacro->isObjectLike() && + BoolMacro->getNumTokens() == 1 && + BoolMacro->getReplacementToken(0).is(tok::kw__Bool); + } + } + + return Policy; +} + +void Sema::ActOnTranslationUnitScope(Scope *S) { + TUScope = S; + PushDeclContext(S, Context.getTranslationUnitDecl()); + + VAListTagName = PP.getIdentifierInfo("__va_list_tag"); +} + +Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, + TranslationUnitKind TUKind, + CodeCompleteConsumer *CodeCompleter) + : TheTargetAttributesSema(0), FPFeatures(pp.getLangOpts()), + LangOpts(pp.getLangOpts()), PP(pp), Context(ctxt), Consumer(consumer), + Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()), + CollectStats(false), ExternalSource(0), CodeCompleter(CodeCompleter), + CurContext(0), OriginalLexicalContext(0), + PackContext(0), MSStructPragmaOn(false), VisContext(0), + ExprNeedsCleanups(false), LateTemplateParser(0), OpaqueParser(0), + IdResolver(pp), StdInitializerList(0), CXXTypeInfoDecl(0), MSVCGuidDecl(0), + NSNumberDecl(0), NSArrayDecl(0), ArrayWithObjectsMethod(0), + NSDictionaryDecl(0), DictionaryWithObjectsMethod(0), + GlobalNewDeleteDeclared(false), + ObjCShouldCallSuperDealloc(false), + ObjCShouldCallSuperFinalize(false), + TUKind(TUKind), + NumSFINAEErrors(0), InFunctionDeclarator(0), SuppressAccessChecking(false), + AccessCheckingSFINAE(false), InNonInstantiationSFINAEContext(false), + NonInstantiationEntries(0), ArgumentPackSubstitutionIndex(-1), + CurrentInstantiationScope(0), TyposCorrected(0), + AnalysisWarnings(*this) +{ + TUScope = 0; + + LoadedExternalKnownNamespaces = false; + for (unsigned I = 0; I != NSAPI::NumNSNumberLiteralMethods; ++I) + NSNumberLiteralMethods[I] = 0; + + if (getLangOpts().ObjC1) + NSAPIObj.reset(new NSAPI(Context)); + + if (getLangOpts().CPlusPlus) + FieldCollector.reset(new CXXFieldCollector()); + + // Tell diagnostics how to render things from the AST library. + PP.getDiagnostics().SetArgToStringFn(&FormatASTNodeDiagnosticArgument, + &Context); + + ExprEvalContexts.push_back( + ExpressionEvaluationContextRecord(PotentiallyEvaluated, 0, + false, 0, false)); + + FunctionScopes.push_back(new FunctionScopeInfo(Diags)); +} + +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); + + // Initialize predefined 128-bit integer types, if needed. + if (PP.getTargetInfo().getPointerWidth(0) >= 64) { + // If either of the 128-bit integer types are unavailable to name lookup, + // define them now. + DeclarationName Int128 = &Context.Idents.get("__int128_t"); + if (IdResolver.begin(Int128) == IdResolver.end()) + PushOnScopeChains(Context.getInt128Decl(), TUScope); + + DeclarationName UInt128 = &Context.Idents.get("__uint128_t"); + if (IdResolver.begin(UInt128) == IdResolver.end()) + PushOnScopeChains(Context.getUInt128Decl(), TUScope); + } + + + // Initialize predefined Objective-C types: + if (PP.getLangOpts().ObjC1) { + // If 'SEL' does not yet refer to any declarations, make it refer to the + // predefined 'SEL'. + DeclarationName SEL = &Context.Idents.get("SEL"); + if (IdResolver.begin(SEL) == IdResolver.end()) + PushOnScopeChains(Context.getObjCSelDecl(), TUScope); + + // If 'id' does not yet refer to any declarations, make it refer to the + // predefined 'id'. + DeclarationName Id = &Context.Idents.get("id"); + if (IdResolver.begin(Id) == IdResolver.end()) + PushOnScopeChains(Context.getObjCIdDecl(), TUScope); + + // Create the built-in typedef for 'Class'. + DeclarationName Class = &Context.Idents.get("Class"); + if (IdResolver.begin(Class) == IdResolver.end()) + PushOnScopeChains(Context.getObjCClassDecl(), TUScope); + + // Create the built-in forward declaratino for 'Protocol'. + DeclarationName Protocol = &Context.Idents.get("Protocol"); + if (IdResolver.begin(Protocol) == IdResolver.end()) + PushOnScopeChains(Context.getObjCProtocolDecl(), TUScope); + } +} + +Sema::~Sema() { + if (PackContext) FreePackedContext(); + if (VisContext) FreeVisContext(); + delete TheTargetAttributesSema; + MSStructPragmaOn = false; + // 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(); +} + + +/// makeUnavailableInSystemHeader - There is an error in the current +/// context. If we're still in a system header, and we can plausibly +/// make the relevant declaration unavailable instead of erroring, do +/// so and return true. +bool Sema::makeUnavailableInSystemHeader(SourceLocation loc, + StringRef msg) { + // If we're not in a function, it's an error. + FunctionDecl *fn = dyn_cast(CurContext); + if (!fn) return false; + + // If we're in template instantiation, it's an error. + if (!ActiveTemplateInstantiations.empty()) + return false; + + // If that function's not in a system header, it's an error. + if (!Context.getSourceManager().isInSystemHeader(loc)) + return false; + + // If the function is already unavailable, it's not an error. + if (fn->hasAttr()) return true; + + fn->addAttr(new (Context) UnavailableAttr(loc, Context, msg)); + return true; +} + +ASTMutationListener *Sema::getASTMutationListener() const { + return getASTConsumer().GetASTMutationListener(); +} + +/// \brief Print out statistics about the semantic analysis. +void Sema::PrintStats() const { + llvm::errs() << "\n*** Semantic Analysis Stats:\n"; + llvm::errs() << NumSFINAEErrors << " SFINAE diagnostics trapped.\n"; + + BumpAlloc.PrintStats(); + AnalysisWarnings.PrintStats(); +} + +/// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast. +/// If there is already an implicit cast, merge into the existing one. +/// The result is of the given category. +ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty, + CastKind Kind, ExprValueKind VK, + const CXXCastPath *BasePath, + CheckedConversionKind CCK) { +#ifndef NDEBUG + if (VK == VK_RValue && !E->isRValue()) { + switch (Kind) { + default: + assert(0 && "can't implicitly cast lvalue to rvalue with this cast kind"); + case CK_LValueToRValue: + case CK_ArrayToPointerDecay: + case CK_FunctionToPointerDecay: + case CK_ToVoid: + break; + } + } + assert((VK == VK_RValue || !E->isRValue()) && "can't cast rvalue to lvalue"); +#endif + + QualType ExprTy = Context.getCanonicalType(E->getType()); + QualType TypeTy = Context.getCanonicalType(Ty); + + if (ExprTy == TypeTy) + return Owned(E); + + if (getLangOpts().ObjCAutoRefCount) + CheckObjCARCConversion(SourceRange(), Ty, E, CCK); + + // If this is a derived-to-base cast to a through a virtual base, we + // need a vtable. + if (Kind == CK_DerivedToBase && + BasePathInvolvesVirtualBase(*BasePath)) { + QualType T = E->getType(); + if (const PointerType *Pointer = T->getAs()) + T = Pointer->getPointeeType(); + if (const RecordType *RecordTy = T->getAs()) + MarkVTableUsed(E->getLocStart(), + cast(RecordTy->getDecl())); + } + + if (ImplicitCastExpr *ImpCast = dyn_cast(E)) { + if (ImpCast->getCastKind() == Kind && (!BasePath || BasePath->empty())) { + ImpCast->setType(Ty); + ImpCast->setValueKind(VK); + return Owned(E); + } + } + + return Owned(ImplicitCastExpr::Create(Context, Ty, Kind, E, BasePath, VK)); +} + +/// ScalarTypeToBooleanCastKind - Returns the cast kind corresponding +/// to the conversion from scalar type ScalarTy to the Boolean type. +CastKind Sema::ScalarTypeToBooleanCastKind(QualType ScalarTy) { + switch (ScalarTy->getScalarTypeKind()) { + case Type::STK_Bool: return CK_NoOp; + case Type::STK_CPointer: return CK_PointerToBoolean; + case Type::STK_BlockPointer: return CK_PointerToBoolean; + case Type::STK_ObjCObjectPointer: return CK_PointerToBoolean; + case Type::STK_MemberPointer: return CK_MemberPointerToBoolean; + case Type::STK_Integral: return CK_IntegralToBoolean; + case Type::STK_Floating: return CK_FloatingToBoolean; + case Type::STK_IntegralComplex: return CK_IntegralComplexToBoolean; + case Type::STK_FloatingComplex: return CK_FloatingComplexToBoolean; + } + return CK_Invalid; +} + +/// \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->getMostRecentDecl(); + 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->getMostRecentDecl(); + if (DeclToCheck != VD) + return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck); + } + + return false; +} + +namespace { + struct UndefinedInternal { + NamedDecl *decl; + FullSourceLoc useLoc; + + UndefinedInternal(NamedDecl *decl, FullSourceLoc useLoc) + : decl(decl), useLoc(useLoc) {} + }; + + bool operator<(const UndefinedInternal &l, const UndefinedInternal &r) { + return l.useLoc.isBeforeInTranslationUnitThan(r.useLoc); + } +} + +/// checkUndefinedInternals - Check for undefined objects with internal linkage. +static void checkUndefinedInternals(Sema &S) { + if (S.UndefinedInternals.empty()) return; + + // Collect all the still-undefined entities with internal linkage. + SmallVector undefined; + for (llvm::DenseMap::iterator + i = S.UndefinedInternals.begin(), e = S.UndefinedInternals.end(); + i != e; ++i) { + NamedDecl *decl = i->first; + + // Ignore attributes that have become invalid. + if (decl->isInvalidDecl()) continue; + + // __attribute__((weakref)) is basically a definition. + if (decl->hasAttr()) continue; + + if (FunctionDecl *fn = dyn_cast(decl)) { + if (fn->isPure() || fn->hasBody()) + continue; + } else { + if (cast(decl)->hasDefinition() != VarDecl::DeclarationOnly) + continue; + } + + // We build a FullSourceLoc so that we can sort with array_pod_sort. + FullSourceLoc loc(i->second, S.Context.getSourceManager()); + undefined.push_back(UndefinedInternal(decl, loc)); + } + + if (undefined.empty()) return; + + // Sort (in order of use site) so that we're not (as) dependent on + // the iteration order through an llvm::DenseMap. + llvm::array_pod_sort(undefined.begin(), undefined.end()); + + for (SmallVectorImpl::iterator + i = undefined.begin(), e = undefined.end(); i != e; ++i) { + NamedDecl *decl = i->decl; + S.Diag(decl->getLocation(), diag::warn_undefined_internal) + << isa(decl) << decl; + S.Diag(i->useLoc, diag::note_used_here); + } +} + +void Sema::LoadExternalWeakUndeclaredIdentifiers() { + if (!ExternalSource) + return; + + SmallVector, 4> WeakIDs; + ExternalSource->ReadWeakUndeclaredIdentifiers(WeakIDs); + for (unsigned I = 0, N = WeakIDs.size(); I != N; ++I) { + llvm::DenseMap::iterator Pos + = WeakUndeclaredIdentifiers.find(WeakIDs[I].first); + if (Pos != WeakUndeclaredIdentifiers.end()) + continue; + + WeakUndeclaredIdentifiers.insert(WeakIDs[I]); + } +} + +/// 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() { + // Only complete translation units define vtables and perform implicit + // instantiations. + if (TUKind == TU_Complete) { + DiagnoseUseOfUnimplementedSelectors(); + + // If any dynamic classes have their key function defined within + // this translation unit, then those vtables are considered "used" and must + // be emitted. + for (DynamicClassesType::iterator I = DynamicClasses.begin(ExternalSource), + E = DynamicClasses.end(); + I != E; ++I) { + assert(!(*I)->isDependentType() && + "Should not see dependent types here!"); + if (const CXXMethodDecl *KeyFunction = Context.getKeyFunction(*I)) { + const FunctionDecl *Definition = 0; + if (KeyFunction->hasBody(Definition)) + MarkVTableUsed(Definition->getLocation(), *I, true); + } + } + + // If DefinedUsedVTables ends up marking any virtual member functions it + // might lead to more pending template instantiations, which we then need + // to instantiate. + DefineUsedVTables(); + + // 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(); + } + + // Remove file scoped decls that turned out to be used. + UnusedFileScopedDecls.erase(std::remove_if(UnusedFileScopedDecls.begin(0, + true), + UnusedFileScopedDecls.end(), + std::bind1st(std::ptr_fun(ShouldRemoveFromUnused), + this)), + UnusedFileScopedDecls.end()); + + if (TUKind == TU_Prefix) { + // Translation unit prefixes don't need any of the checking below. + TUScope = 0; + return; + } + + // Check for #pragma weak identifiers that were never declared + // FIXME: This will cause diagnostics to be emitted in a non-determinstic + // order! Iterating over a densemap like this is bad. + LoadExternalWeakUndeclaredIdentifiers(); + for (llvm::DenseMap::iterator + I = WeakUndeclaredIdentifiers.begin(), + E = WeakUndeclaredIdentifiers.end(); I != E; ++I) { + if (I->second.getUsed()) continue; + + Diag(I->second.getLocation(), diag::warn_weak_identifier_undeclared) + << I->first; + } + + if (TUKind == TU_Module) { + // If we are building a module, resolve all of the exported declarations + // now. + if (Module *CurrentModule = PP.getCurrentModule()) { + ModuleMap &ModMap = PP.getHeaderSearchInfo().getModuleMap(); + + llvm::SmallVector Stack; + Stack.push_back(CurrentModule); + while (!Stack.empty()) { + Module *Mod = Stack.back(); + Stack.pop_back(); + + // Resolve the exported declarations. + // FIXME: Actually complain, once we figure out how to teach the + // diagnostic client to deal with complains in the module map at this + // point. + ModMap.resolveExports(Mod, /*Complain=*/false); + + // Queue the submodules, so their exports will also be resolved. + for (Module::submodule_iterator Sub = Mod->submodule_begin(), + SubEnd = Mod->submodule_end(); + Sub != SubEnd; ++Sub) { + Stack.push_back(*Sub); + } + } + } + + // Modules don't need any of the checking below. + TUScope = 0; + 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 + // specifier or with the storage-class specifier static, + // constitutes a tentative definition. If a translation unit + // contains one or more tentative definitions for an identifier, + // and the translation unit contains no external definition for + // that identifier, then the behavior is exactly as if the + // translation unit contains a file scope declaration of that + // identifier, with the composite type as of the end of the + // translation unit, with an initializer equal to 0. + llvm::SmallSet Seen; + for (TentativeDefinitionsType::iterator + T = TentativeDefinitions.begin(ExternalSource), + TEnd = TentativeDefinitions.end(); + T != TEnd; ++T) + { + VarDecl *VD = (*T)->getActingDefinition(); + + // If the tentative definition was completed, getActingDefinition() returns + // null. If we've already seen this variable before, insert()'s second + // return value is false. + if (VD == 0 || VD->isInvalidDecl() || !Seen.insert(VD)) + continue; + + if (const IncompleteArrayType *ArrayT + = Context.getAsIncompleteArrayType(VD->getType())) { + if (RequireCompleteType(VD->getLocation(), + ArrayT->getElementType(), + diag::err_tentative_def_incomplete_type_arr)) { + VD->setInvalidDecl(); + continue; + } + + // Set the length of the array to 1 (C99 6.9.2p5). + Diag(VD->getLocation(), diag::warn_tentative_incomplete_array); + llvm::APInt One(Context.getTypeSize(Context.getSizeType()), true); + QualType T = Context.getConstantArrayType(ArrayT->getElementType(), + One, ArrayType::Normal, 0); + VD->setType(T); + } else if (RequireCompleteType(VD->getLocation(), VD->getType(), + diag::err_tentative_def_incomplete_type)) + VD->setInvalidDecl(); + + // Notify the consumer that we've completed a tentative definition. + if (!VD->isInvalidDecl()) + Consumer.CompleteTentativeDefinition(VD); + + } + + if (LangOpts.CPlusPlus0x && + Diags.getDiagnosticLevel(diag::warn_delegating_ctor_cycle, + SourceLocation()) + != DiagnosticsEngine::Ignored) + CheckDelegatingCtorCycles(); + + // If there were errors, disable 'unused' warnings since they will mostly be + // noise. + if (!Diags.hasErrorOccurred()) { + // Output warning for unused file scoped decls. + for (UnusedFileScopedDeclsType::iterator + I = UnusedFileScopedDecls.begin(ExternalSource), + E = UnusedFileScopedDecls.end(); I != E; ++I) { + if (ShouldRemoveFromUnused(this, *I)) + continue; + + if (const FunctionDecl *FD = dyn_cast(*I)) { + const FunctionDecl *DiagD; + if (!FD->hasBody(DiagD)) + DiagD = FD; + if (DiagD->isDeleted()) + continue; // Deleted functions are supposed to be unused. + if (DiagD->isReferenced()) { + if (isa(DiagD)) + Diag(DiagD->getLocation(), diag::warn_unneeded_member_function) + << DiagD->getDeclName(); + else + Diag(DiagD->getLocation(), diag::warn_unneeded_internal_decl) + << /*function*/0 << DiagD->getDeclName(); + } else { + 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); + if (DiagD->isReferenced()) { + Diag(DiagD->getLocation(), diag::warn_unneeded_internal_decl) + << /*variable*/1 << DiagD->getDeclName(); + } else { + Diag(DiagD->getLocation(), diag::warn_unused_variable) + << DiagD->getDeclName(); + } + } + } + + checkUndefinedInternals(*this); + } + + // Check we've noticed that we're no longer parsing the initializer for every + // variable. If we miss cases, then at best we have a performance issue and + // at worst a rejects-valid bug. + assert(ParsingInitForAutoVars.empty() && + "Didn't unmark var as having its initializer parsed"); + + TUScope = 0; +} + + +//===----------------------------------------------------------------------===// +// Helper functions. +//===----------------------------------------------------------------------===// + +DeclContext *Sema::getFunctionLevelDeclContext() { + DeclContext *DC = CurContext; + + while (true) { + if (isa(DC) || isa(DC)) { + DC = DC->getParent(); + } else if (isa(DC) && + cast(DC)->getOverloadedOperator() == OO_Call && + cast(DC->getParent())->isLambda()) { + DC = DC->getParent()->getParent(); + } + else break; + } + + return DC; +} + +/// 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 *Sema::getCurFunctionDecl() { + DeclContext *DC = getFunctionLevelDeclContext(); + return dyn_cast(DC); +} + +ObjCMethodDecl *Sema::getCurMethodDecl() { + DeclContext *DC = getFunctionLevelDeclContext(); + return dyn_cast(DC); +} + +NamedDecl *Sema::getCurFunctionOrMethodDecl() { + DeclContext *DC = getFunctionLevelDeclContext(); + if (isa(DC) || isa(DC)) + return cast(DC); + return 0; +} + +void Sema::EmitCurrentDiagnostic(unsigned DiagID) { + // FIXME: It doesn't make sense to me that DiagID is an incoming argument here + // and yet we also use the current diag ID on the DiagnosticsEngine. This has + // been made more painfully obvious by the refactor that introduced this + // function, but it is possible that the incoming argument can be + // eliminnated. If it truly cannot be (for example, there is some reentrancy + // issue I am not seeing yet), then there should at least be a clarifying + // comment somewhere. + if (llvm::Optional Info = isSFINAEContext()) { + switch (DiagnosticIDs::getDiagnosticSFINAEResponse( + Diags.getCurrentDiagID())) { + case DiagnosticIDs::SFINAE_Report: + // We'll report the diagnostic below. + break; + + case DiagnosticIDs::SFINAE_SubstitutionFailure: + // Count this failure so that we know that template argument deduction + // has failed. + ++NumSFINAEErrors; + Diags.setLastDiagnosticIgnored(); + Diags.Clear(); + return; + + case DiagnosticIDs::SFINAE_AccessControl: { + // Per C++ Core Issue 1170, access control is part of SFINAE. + // Additionally, the AccessCheckingSFINAE flag can be used to temporarily + // make access control a part of SFINAE for the purposes of checking + // type traits. + if (!AccessCheckingSFINAE && !getLangOpts().CPlusPlus0x) + break; + + SourceLocation Loc = Diags.getCurrentDiagLoc(); + + // Suppress this diagnostic. + ++NumSFINAEErrors; + Diags.setLastDiagnosticIgnored(); + Diags.Clear(); + + // Now the diagnostic state is clear, produce a C++98 compatibility + // warning. + Diag(Loc, diag::warn_cxx98_compat_sfinae_access_control); + + // The last diagnostic which Sema produced was ignored. Suppress any + // notes attached to it. + Diags.setLastDiagnosticIgnored(); + return; + } + + case DiagnosticIDs::SFINAE_Suppress: + // Make a copy of this suppressed diagnostic and store it with the + // template-deduction information; + Diagnostic DiagInfo(&Diags); + + if (*Info) + (*Info)->addSuppressedDiagnostic(DiagInfo.getLocation(), + PartialDiagnostic(DiagInfo,Context.getDiagAllocator())); + + // Suppress this diagnostic. + Diags.setLastDiagnosticIgnored(); + Diags.Clear(); + return; + } + } + + // Set up the context's printing policy based on our current state. + Context.setPrintingPolicy(getPrintingPolicy()); + + // Emit the diagnostic. + if (!Diags.EmitCurrentDiagnostic()) + return; + + // If this is not a note, and we're in a template instantiation + // that is different from the last template instantiation where + // we emitted an error, print a template instantiation + // backtrace. + if (!DiagnosticIDs::isBuiltinNote(DiagID) && + !ActiveTemplateInstantiations.empty() && + ActiveTemplateInstantiations.back() + != LastTemplateInstantiationErrorContext) { + PrintInstantiationStack(); + LastTemplateInstantiationErrorContext = ActiveTemplateInstantiations.back(); + } +} + +Sema::SemaDiagnosticBuilder +Sema::Diag(SourceLocation Loc, const PartialDiagnostic& PD) { + SemaDiagnosticBuilder Builder(Diag(Loc, PD.getDiagID())); + PD.Emit(Builder); + + return Builder; +} + +/// \brief Looks through the macro-expansion chain for the given +/// location, looking for a macro expansion with the given name. +/// If one is found, returns true and sets the location to that +/// expansion loc. +bool Sema::findMacroSpelling(SourceLocation &locref, StringRef name) { + SourceLocation loc = locref; + if (!loc.isMacroID()) return false; + + // There's no good way right now to look at the intermediate + // expansions, so just jump to the expansion location. + loc = getSourceManager().getExpansionLoc(loc); + + // If that's written with the name, stop here. + SmallVector buffer; + if (getPreprocessor().getSpelling(loc, buffer) == name) { + locref = loc; + return true; + } + return false; +} + +/// \brief Determines the active Scope associated with the given declaration +/// context. +/// +/// This routine maps a declaration context to the active Scope object that +/// represents that declaration context in the parser. It is typically used +/// from "scope-less" code (e.g., template instantiation, lazy creation of +/// declarations) that injects a name for name-lookup purposes and, therefore, +/// must update the Scope. +/// +/// \returns The scope corresponding to the given declaraion context, or NULL +/// if no such scope is open. +Scope *Sema::getScopeForContext(DeclContext *Ctx) { + + if (!Ctx) + return 0; + + Ctx = Ctx->getPrimaryContext(); + for (Scope *S = getCurScope(); S; S = S->getParent()) { + // Ignore scopes that cannot have declarations. This is important for + // out-of-line definitions of static class members. + if (S->getFlags() & (Scope::DeclScope | Scope::TemplateParamScope)) + if (DeclContext *Entity = static_cast (S->getEntity())) + if (Ctx == Entity->getPrimaryContext()) + return S; + } + + return 0; +} + +/// \brief Enter a new function scope +void Sema::PushFunctionScope() { + if (FunctionScopes.size() == 1) { + // Use the "top" function scope rather than having to allocate + // memory for a new scope. + FunctionScopes.back()->Clear(); + FunctionScopes.push_back(FunctionScopes.back()); + return; + } + + FunctionScopes.push_back(new FunctionScopeInfo(getDiagnostics())); +} + +void Sema::PushBlockScope(Scope *BlockScope, BlockDecl *Block) { + FunctionScopes.push_back(new BlockScopeInfo(getDiagnostics(), + BlockScope, Block)); +} + +void Sema::PushLambdaScope(CXXRecordDecl *Lambda, + CXXMethodDecl *CallOperator) { + FunctionScopes.push_back(new LambdaScopeInfo(getDiagnostics(), Lambda, + CallOperator)); +} + +void Sema::PopFunctionScopeInfo(const AnalysisBasedWarnings::Policy *WP, + const Decl *D, const BlockExpr *blkExpr) { + FunctionScopeInfo *Scope = FunctionScopes.pop_back_val(); + assert(!FunctionScopes.empty() && "mismatched push/pop!"); + + // Issue any analysis-based warnings. + if (WP && D) + AnalysisWarnings.IssueWarnings(*WP, Scope, D, blkExpr); + else { + for (SmallVectorImpl::iterator + i = Scope->PossiblyUnreachableDiags.begin(), + e = Scope->PossiblyUnreachableDiags.end(); + i != e; ++i) { + const sema::PossiblyUnreachableDiag &D = *i; + Diag(D.Loc, D.PD); + } + } + + if (FunctionScopes.back() != Scope) { + delete Scope; + } +} + +void Sema::PushCompoundScope() { + getCurFunction()->CompoundScopes.push_back(CompoundScopeInfo()); +} + +void Sema::PopCompoundScope() { + FunctionScopeInfo *CurFunction = getCurFunction(); + assert(!CurFunction->CompoundScopes.empty() && "mismatched push/pop"); + + CurFunction->CompoundScopes.pop_back(); +} + +/// \brief Determine whether any errors occurred within this function/method/ +/// block. +bool Sema::hasAnyUnrecoverableErrorsInThisFunction() const { + return getCurFunction()->ErrorTrap.hasUnrecoverableErrorOccurred(); +} + +BlockScopeInfo *Sema::getCurBlock() { + if (FunctionScopes.empty()) + return 0; + + return dyn_cast(FunctionScopes.back()); +} + +LambdaScopeInfo *Sema::getCurLambda() { + if (FunctionScopes.empty()) + return 0; + + return dyn_cast(FunctionScopes.back()); +} + +// Pin this vtable to this file. +ExternalSemaSource::~ExternalSemaSource() {} + +void ExternalSemaSource::ReadMethodPool(Selector Sel) { } + +void ExternalSemaSource::ReadKnownNamespaces( + SmallVectorImpl &Namespaces) { +} + +void PrettyDeclStackTraceEntry::print(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'; +} + +/// \brief Figure out if an expression could be turned into a call. +/// +/// Use this when trying to recover from an error where the programmer may have +/// written just the name of a function instead of actually calling it. +/// +/// \param E - The expression to examine. +/// \param ZeroArgCallReturnTy - If the expression can be turned into a call +/// with no arguments, this parameter is set to the type returned by such a +/// call; otherwise, it is set to an empty QualType. +/// \param OverloadSet - If the expression is an overloaded function +/// name, this parameter is populated with the decls of the various overloads. +bool Sema::isExprCallable(const Expr &E, QualType &ZeroArgCallReturnTy, + UnresolvedSetImpl &OverloadSet) { + ZeroArgCallReturnTy = QualType(); + OverloadSet.clear(); + + if (E.getType() == Context.OverloadTy) { + OverloadExpr::FindResult FR = OverloadExpr::find(const_cast(&E)); + const OverloadExpr *Overloads = FR.Expression; + + for (OverloadExpr::decls_iterator it = Overloads->decls_begin(), + DeclsEnd = Overloads->decls_end(); it != DeclsEnd; ++it) { + OverloadSet.addDecl(*it); + + // Check whether the function is a non-template which takes no + // arguments. + if (const FunctionDecl *OverloadDecl + = dyn_cast((*it)->getUnderlyingDecl())) { + if (OverloadDecl->getMinRequiredArguments() == 0) + ZeroArgCallReturnTy = OverloadDecl->getResultType(); + } + } + + // Ignore overloads that are pointer-to-member constants. + if (FR.HasFormOfMemberPointer) + return false; + + return true; + } + + if (const DeclRefExpr *DeclRef = dyn_cast(E.IgnoreParens())) { + if (const FunctionDecl *Fun = dyn_cast(DeclRef->getDecl())) { + if (Fun->getMinRequiredArguments() == 0) + ZeroArgCallReturnTy = Fun->getResultType(); + return true; + } + } + + // We don't have an expression that's convenient to get a FunctionDecl from, + // but we can at least check if the type is "function of 0 arguments". + QualType ExprTy = E.getType(); + const FunctionType *FunTy = NULL; + QualType PointeeTy = ExprTy->getPointeeType(); + if (!PointeeTy.isNull()) + FunTy = PointeeTy->getAs(); + if (!FunTy) + FunTy = ExprTy->getAs(); + if (!FunTy && ExprTy == Context.BoundMemberTy) { + // Look for the bound-member type. If it's still overloaded, give up, + // although we probably should have fallen into the OverloadExpr case above + // if we actually have an overloaded bound member. + QualType BoundMemberTy = Expr::findBoundMemberType(&E); + if (!BoundMemberTy.isNull()) + FunTy = BoundMemberTy->castAs(); + } + + if (const FunctionProtoType *FPT = + dyn_cast_or_null(FunTy)) { + if (FPT->getNumArgs() == 0) + ZeroArgCallReturnTy = FunTy->getResultType(); + return true; + } + return false; +} + +/// \brief Give notes for a set of overloads. +/// +/// A companion to isExprCallable. In cases when the name that the programmer +/// wrote was an overloaded function, we may be able to make some guesses about +/// plausible overloads based on their return types; such guesses can be handed +/// off to this method to be emitted as notes. +/// +/// \param Overloads - The overloads to note. +/// \param FinalNoteLoc - If we've suppressed printing some overloads due to +/// -fshow-overloads=best, this is the location to attach to the note about too +/// many candidates. Typically this will be the location of the original +/// ill-formed expression. +static void noteOverloads(Sema &S, const UnresolvedSetImpl &Overloads, + const SourceLocation FinalNoteLoc) { + int ShownOverloads = 0; + int SuppressedOverloads = 0; + for (UnresolvedSetImpl::iterator It = Overloads.begin(), + DeclsEnd = Overloads.end(); It != DeclsEnd; ++It) { + // FIXME: Magic number for max shown overloads stolen from + // OverloadCandidateSet::NoteCandidates. + if (ShownOverloads >= 4 && + S.Diags.getShowOverloads() == DiagnosticsEngine::Ovl_Best) { + ++SuppressedOverloads; + continue; + } + + NamedDecl *Fn = (*It)->getUnderlyingDecl(); + S.Diag(Fn->getLocation(), diag::note_possible_target_of_call); + ++ShownOverloads; + } + + if (SuppressedOverloads) + S.Diag(FinalNoteLoc, diag::note_ovl_too_many_candidates) + << SuppressedOverloads; +} + +static void notePlausibleOverloads(Sema &S, SourceLocation Loc, + const UnresolvedSetImpl &Overloads, + bool (*IsPlausibleResult)(QualType)) { + if (!IsPlausibleResult) + return noteOverloads(S, Overloads, Loc); + + UnresolvedSet<2> PlausibleOverloads; + for (OverloadExpr::decls_iterator It = Overloads.begin(), + DeclsEnd = Overloads.end(); It != DeclsEnd; ++It) { + const FunctionDecl *OverloadDecl = cast(*It); + QualType OverloadResultTy = OverloadDecl->getResultType(); + if (IsPlausibleResult(OverloadResultTy)) + PlausibleOverloads.addDecl(It.getDecl()); + } + noteOverloads(S, PlausibleOverloads, Loc); +} + +/// Determine whether the given expression can be called by just +/// putting parentheses after it. Notably, expressions with unary +/// operators can't be because the unary operator will start parsing +/// outside the call. +static bool IsCallableWithAppend(Expr *E) { + E = E->IgnoreImplicit(); + return (!isa(E) && + !isa(E) && + !isa(E) && + !isa(E)); +} + +bool Sema::tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD, + bool ForceComplain, + bool (*IsPlausibleResult)(QualType)) { + SourceLocation Loc = E.get()->getExprLoc(); + SourceRange Range = E.get()->getSourceRange(); + + QualType ZeroArgCallTy; + UnresolvedSet<4> Overloads; + if (isExprCallable(*E.get(), ZeroArgCallTy, Overloads) && + !ZeroArgCallTy.isNull() && + (!IsPlausibleResult || IsPlausibleResult(ZeroArgCallTy))) { + // At this point, we know E is potentially callable with 0 + // arguments and that it returns something of a reasonable type, + // so we can emit a fixit and carry on pretending that E was + // actually a CallExpr. + SourceLocation ParenInsertionLoc = + PP.getLocForEndOfToken(Range.getEnd()); + Diag(Loc, PD) + << /*zero-arg*/ 1 << Range + << (IsCallableWithAppend(E.get()) + ? FixItHint::CreateInsertion(ParenInsertionLoc, "()") + : FixItHint()); + notePlausibleOverloads(*this, Loc, Overloads, IsPlausibleResult); + + // FIXME: Try this before emitting the fixit, and suppress diagnostics + // while doing so. + E = ActOnCallExpr(0, E.take(), ParenInsertionLoc, + MultiExprArg(*this, 0, 0), + ParenInsertionLoc.getLocWithOffset(1)); + return true; + } + + if (!ForceComplain) return false; + + Diag(Loc, PD) << /*not zero-arg*/ 0 << Range; + notePlausibleOverloads(*this, Loc, Overloads, IsPlausibleResult); + E = ExprError(); + return true; +} diff --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp new file mode 100644 index 0000000..01c141e --- /dev/null +++ b/clang/lib/Sema/SemaAccess.cpp @@ -0,0 +1,1850 @@ +//===---- SemaAccess.cpp - C++ Access Control -------------------*- 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 Sema routines for C++ access control semantics. +// +//===----------------------------------------------------------------------===// + +#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" +#include "clang/AST/DeclFriend.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DependentDiagnostic.h" +#include "clang/AST/ExprCXX.h" + +using namespace clang; +using namespace sema; + +/// A copy of Sema's enum without AR_delayed. +enum AccessResult { + AR_accessible, + AR_inaccessible, + AR_dependent +}; + +/// SetMemberAccessSpecifier - Set the access specifier of a member. +/// Returns true on error (when the previous member decl access specifier +/// is different from the new member decl access specifier). +bool Sema::SetMemberAccessSpecifier(NamedDecl *MemberDecl, + NamedDecl *PrevMemberDecl, + AccessSpecifier LexicalAS) { + if (!PrevMemberDecl) { + // Use the lexical access specifier. + MemberDecl->setAccess(LexicalAS); + return false; + } + + // C++ [class.access.spec]p3: When a member is redeclared its access + // specifier must be same as its initial declaration. + if (LexicalAS != AS_none && LexicalAS != PrevMemberDecl->getAccess()) { + Diag(MemberDecl->getLocation(), + diag::err_class_redeclared_with_different_access) + << MemberDecl << LexicalAS; + Diag(PrevMemberDecl->getLocation(), diag::note_previous_access_declaration) + << PrevMemberDecl << PrevMemberDecl->getAccess(); + + MemberDecl->setAccess(LexicalAS); + return true; + } + + MemberDecl->setAccess(PrevMemberDecl->getAccess()); + return false; +} + +static CXXRecordDecl *FindDeclaringClass(NamedDecl *D) { + DeclContext *DC = D->getDeclContext(); + + // This can only happen at top: enum decls only "publish" their + // immediate members. + if (isa(DC)) + DC = cast(DC)->getDeclContext(); + + CXXRecordDecl *DeclaringClass = cast(DC); + while (DeclaringClass->isAnonymousStructOrUnion()) + DeclaringClass = cast(DeclaringClass->getDeclContext()); + return DeclaringClass; +} + +namespace { +struct EffectiveContext { + EffectiveContext() : Inner(0), Dependent(false) {} + + explicit EffectiveContext(DeclContext *DC) + : Inner(DC), + Dependent(DC->isDependentContext()) { + + // C++ [class.access.nest]p1: + // A nested class is a member and as such has the same access + // rights as any other member. + // C++ [class.access]p2: + // A member of a class can also access all the names to which + // the class has access. A local class of a member function + // may access the same names that the member function itself + // may access. + // This almost implies that the privileges of nesting are transitive. + // Technically it says nothing about the local classes of non-member + // functions (which can gain privileges through friendship), but we + // take that as an oversight. + while (true) { + if (isa(DC)) { + CXXRecordDecl *Record = cast(DC)->getCanonicalDecl(); + Records.push_back(Record); + DC = Record->getDeclContext(); + } else if (isa(DC)) { + FunctionDecl *Function = cast(DC)->getCanonicalDecl(); + Functions.push_back(Function); + + if (Function->getFriendObjectKind()) + DC = Function->getLexicalDeclContext(); + else + DC = Function->getDeclContext(); + } else if (DC->isFileContext()) { + break; + } else { + DC = DC->getParent(); + } + } + } + + bool isDependent() const { return Dependent; } + + bool includesClass(const CXXRecordDecl *R) const { + R = R->getCanonicalDecl(); + return std::find(Records.begin(), Records.end(), R) + != Records.end(); + } + + /// Retrieves the innermost "useful" context. Can be null if we're + /// doing access-control without privileges. + DeclContext *getInnerContext() const { + return Inner; + } + + typedef SmallVectorImpl::const_iterator record_iterator; + + DeclContext *Inner; + SmallVector Functions; + SmallVector Records; + bool Dependent; +}; + +/// Like sema::AccessedEntity, but kindly lets us scribble all over +/// it. +struct AccessTarget : public AccessedEntity { + AccessTarget(const AccessedEntity &Entity) + : AccessedEntity(Entity) { + initialize(); + } + + AccessTarget(ASTContext &Context, + MemberNonce _, + CXXRecordDecl *NamingClass, + DeclAccessPair FoundDecl, + QualType BaseObjectType) + : AccessedEntity(Context, Member, NamingClass, FoundDecl, BaseObjectType) { + initialize(); + } + + AccessTarget(ASTContext &Context, + BaseNonce _, + CXXRecordDecl *BaseClass, + CXXRecordDecl *DerivedClass, + AccessSpecifier Access) + : AccessedEntity(Context, Base, BaseClass, DerivedClass, Access) { + initialize(); + } + + bool isInstanceMember() const { + return (isMemberAccess() && getTargetDecl()->isCXXInstanceMember()); + } + + bool hasInstanceContext() const { + return HasInstanceContext; + } + + class SavedInstanceContext { + public: + ~SavedInstanceContext() { + Target.HasInstanceContext = Has; + } + + private: + friend struct AccessTarget; + explicit SavedInstanceContext(AccessTarget &Target) + : Target(Target), Has(Target.HasInstanceContext) {} + AccessTarget &Target; + bool Has; + }; + + SavedInstanceContext saveInstanceContext() { + return SavedInstanceContext(*this); + } + + void suppressInstanceContext() { + HasInstanceContext = false; + } + + const CXXRecordDecl *resolveInstanceContext(Sema &S) const { + assert(HasInstanceContext); + if (CalculatedInstanceContext) + return InstanceContext; + + CalculatedInstanceContext = true; + DeclContext *IC = S.computeDeclContext(getBaseObjectType()); + InstanceContext = (IC ? cast(IC)->getCanonicalDecl() : 0); + return InstanceContext; + } + + const CXXRecordDecl *getDeclaringClass() const { + return DeclaringClass; + } + +private: + void initialize() { + HasInstanceContext = (isMemberAccess() && + !getBaseObjectType().isNull() && + getTargetDecl()->isCXXInstanceMember()); + CalculatedInstanceContext = false; + InstanceContext = 0; + + if (isMemberAccess()) + DeclaringClass = FindDeclaringClass(getTargetDecl()); + else + DeclaringClass = getBaseClass(); + DeclaringClass = DeclaringClass->getCanonicalDecl(); + } + + bool HasInstanceContext : 1; + mutable bool CalculatedInstanceContext : 1; + mutable const CXXRecordDecl *InstanceContext; + const CXXRecordDecl *DeclaringClass; +}; + +} + +/// Checks whether one class might instantiate to the other. +static bool MightInstantiateTo(const CXXRecordDecl *From, + const CXXRecordDecl *To) { + // Declaration names are always preserved by instantiation. + if (From->getDeclName() != To->getDeclName()) + return false; + + const DeclContext *FromDC = From->getDeclContext()->getPrimaryContext(); + const DeclContext *ToDC = To->getDeclContext()->getPrimaryContext(); + if (FromDC == ToDC) return true; + if (FromDC->isFileContext() || ToDC->isFileContext()) return false; + + // Be conservative. + return true; +} + +/// Checks whether one class is derived from another, inclusively. +/// Properly indicates when it couldn't be determined due to +/// dependence. +/// +/// This should probably be donated to AST or at least Sema. +static AccessResult IsDerivedFromInclusive(const CXXRecordDecl *Derived, + const CXXRecordDecl *Target) { + assert(Derived->getCanonicalDecl() == Derived); + assert(Target->getCanonicalDecl() == Target); + + if (Derived == Target) return AR_accessible; + + bool CheckDependent = Derived->isDependentContext(); + if (CheckDependent && MightInstantiateTo(Derived, Target)) + return AR_dependent; + + AccessResult OnFailure = AR_inaccessible; + SmallVector Queue; // actually a stack + + while (true) { + if (Derived->isDependentContext() && !Derived->hasDefinition()) + return AR_dependent; + + for (CXXRecordDecl::base_class_const_iterator + I = Derived->bases_begin(), E = Derived->bases_end(); I != E; ++I) { + + 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?"); + OnFailure = AR_dependent; + continue; + } + + RD = RD->getCanonicalDecl(); + if (RD == Target) return AR_accessible; + if (CheckDependent && MightInstantiateTo(RD, Target)) + OnFailure = AR_dependent; + + Queue.push_back(RD); + } + + if (Queue.empty()) break; + + Derived = Queue.back(); + Queue.pop_back(); + } + + return OnFailure; +} + + +static bool MightInstantiateTo(Sema &S, DeclContext *Context, + DeclContext *Friend) { + if (Friend == Context) + return true; + + assert(!Friend->isDependentContext() && + "can't handle friends with dependent contexts here"); + + if (!Context->isDependentContext()) + return false; + + if (Friend->isFileContext()) + return false; + + // TODO: this is very conservative + return true; +} + +// Asks whether the type in 'context' can ever instantiate to the type +// in 'friend'. +static bool MightInstantiateTo(Sema &S, CanQualType Context, CanQualType Friend) { + if (Friend == Context) + return true; + + if (!Friend->isDependentType() && !Context->isDependentType()) + return false; + + // TODO: this is very conservative. + return true; +} + +static bool MightInstantiateTo(Sema &S, + FunctionDecl *Context, + FunctionDecl *Friend) { + if (Context->getDeclName() != Friend->getDeclName()) + return false; + + if (!MightInstantiateTo(S, + Context->getDeclContext(), + Friend->getDeclContext())) + return false; + + CanQual FriendTy + = S.Context.getCanonicalType(Friend->getType()) + ->getAs(); + CanQual ContextTy + = S.Context.getCanonicalType(Context->getType()) + ->getAs(); + + // There isn't any way that I know of to add qualifiers + // during instantiation. + if (FriendTy.getQualifiers() != ContextTy.getQualifiers()) + return false; + + if (FriendTy->getNumArgs() != ContextTy->getNumArgs()) + return false; + + if (!MightInstantiateTo(S, + ContextTy->getResultType(), + FriendTy->getResultType())) + return false; + + for (unsigned I = 0, E = FriendTy->getNumArgs(); I != E; ++I) + if (!MightInstantiateTo(S, + ContextTy->getArgType(I), + FriendTy->getArgType(I))) + return false; + + return true; +} + +static bool MightInstantiateTo(Sema &S, + FunctionTemplateDecl *Context, + FunctionTemplateDecl *Friend) { + return MightInstantiateTo(S, + Context->getTemplatedDecl(), + Friend->getTemplatedDecl()); +} + +static AccessResult MatchesFriend(Sema &S, + const EffectiveContext &EC, + const CXXRecordDecl *Friend) { + if (EC.includesClass(Friend)) + return AR_accessible; + + if (EC.isDependent()) { + CanQualType FriendTy + = S.Context.getCanonicalType(S.Context.getTypeDeclType(Friend)); + + for (EffectiveContext::record_iterator + I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { + CanQualType ContextTy + = S.Context.getCanonicalType(S.Context.getTypeDeclType(*I)); + if (MightInstantiateTo(S, ContextTy, FriendTy)) + return AR_dependent; + } + } + + return AR_inaccessible; +} + +static AccessResult MatchesFriend(Sema &S, + const EffectiveContext &EC, + CanQualType Friend) { + if (const RecordType *RT = Friend->getAs()) + return MatchesFriend(S, EC, cast(RT->getDecl())); + + // TODO: we can do better than this + if (Friend->isDependentType()) + return AR_dependent; + + return AR_inaccessible; +} + +/// Determines whether the given friend class template matches +/// anything in the effective context. +static AccessResult MatchesFriend(Sema &S, + const EffectiveContext &EC, + ClassTemplateDecl *Friend) { + AccessResult OnFailure = AR_inaccessible; + + // Check whether the friend is the template of a class in the + // context chain. + for (SmallVectorImpl::const_iterator + I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { + CXXRecordDecl *Record = *I; + + // Figure out whether the current class has a template: + ClassTemplateDecl *CTD; + + // A specialization of the template... + if (isa(Record)) { + CTD = cast(Record) + ->getSpecializedTemplate(); + + // ... or the template pattern itself. + } else { + CTD = Record->getDescribedClassTemplate(); + if (!CTD) continue; + } + + // It's a match. + if (Friend == CTD->getCanonicalDecl()) + return AR_accessible; + + // If the context isn't dependent, it can't be a dependent match. + if (!EC.isDependent()) + continue; + + // If the template names don't match, it can't be a dependent + // match. + if (CTD->getDeclName() != Friend->getDeclName()) + continue; + + // If the class's context can't instantiate to the friend's + // context, it can't be a dependent match. + if (!MightInstantiateTo(S, CTD->getDeclContext(), + Friend->getDeclContext())) + continue; + + // Otherwise, it's a dependent match. + OnFailure = AR_dependent; + } + + return OnFailure; +} + +/// Determines whether the given friend function matches anything in +/// the effective context. +static AccessResult MatchesFriend(Sema &S, + const EffectiveContext &EC, + FunctionDecl *Friend) { + AccessResult OnFailure = AR_inaccessible; + + for (SmallVectorImpl::const_iterator + I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) { + if (Friend == *I) + return AR_accessible; + + if (EC.isDependent() && MightInstantiateTo(S, *I, Friend)) + OnFailure = AR_dependent; + } + + return OnFailure; +} + +/// Determines whether the given friend function template matches +/// anything in the effective context. +static AccessResult MatchesFriend(Sema &S, + const EffectiveContext &EC, + FunctionTemplateDecl *Friend) { + if (EC.Functions.empty()) return AR_inaccessible; + + AccessResult OnFailure = AR_inaccessible; + + for (SmallVectorImpl::const_iterator + I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) { + + FunctionTemplateDecl *FTD = (*I)->getPrimaryTemplate(); + if (!FTD) + FTD = (*I)->getDescribedFunctionTemplate(); + if (!FTD) + continue; + + FTD = FTD->getCanonicalDecl(); + + if (Friend == FTD) + return AR_accessible; + + if (EC.isDependent() && MightInstantiateTo(S, FTD, Friend)) + OnFailure = AR_dependent; + } + + return OnFailure; +} + +/// Determines whether the given friend declaration matches anything +/// in the effective context. +static AccessResult MatchesFriend(Sema &S, + const EffectiveContext &EC, + FriendDecl *FriendD) { + // Whitelist accesses if there's an invalid or unsupported friend + // declaration. + if (FriendD->isInvalidDecl() || FriendD->isUnsupportedFriend()) + return AR_accessible; + + if (TypeSourceInfo *T = FriendD->getFriendType()) + return MatchesFriend(S, EC, T->getType()->getCanonicalTypeUnqualified()); + + NamedDecl *Friend + = cast(FriendD->getFriendDecl()->getCanonicalDecl()); + + // FIXME: declarations with dependent or templated scope. + + if (isa(Friend)) + return MatchesFriend(S, EC, cast(Friend)); + + if (isa(Friend)) + return MatchesFriend(S, EC, cast(Friend)); + + if (isa(Friend)) + return MatchesFriend(S, EC, cast(Friend)); + + assert(isa(Friend) && "unknown friend decl kind"); + return MatchesFriend(S, EC, cast(Friend)); +} + +static AccessResult GetFriendKind(Sema &S, + const EffectiveContext &EC, + const CXXRecordDecl *Class) { + AccessResult OnFailure = AR_inaccessible; + + // Okay, check friends. + for (CXXRecordDecl::friend_iterator I = Class->friend_begin(), + E = Class->friend_end(); I != E; ++I) { + FriendDecl *Friend = *I; + + switch (MatchesFriend(S, EC, Friend)) { + case AR_accessible: + return AR_accessible; + + case AR_inaccessible: + continue; + + case AR_dependent: + OnFailure = AR_dependent; + break; + } + } + + // That's it, give up. + 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. + 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 +/// if InstanceContext exists, or else +/// NamingClass <= P +/// and with the additional restriction that a protected member of +/// NamingClass would have some natural access in P, which implicitly +/// imposes the constraint that P <= NamingClass. +/// +/// This isn't quite the condition laid out in the standard. +/// Instead of saying that a notional protected member of NamingClass +/// would have to have some natural access in P, it says the actual +/// target has to have some natural access in P, which opens up the +/// possibility that the target (which is not necessarily a member +/// of NamingClass) might be more accessible along some path not +/// passing through it. That's really a bad idea, though, because it +/// introduces two problems: +/// - Most importantly, it breaks encapsulation because you can +/// access a forbidden base class's members by directly subclassing +/// it elsewhere. +/// - It also 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 == 0 || + InstanceContext->getCanonicalDecl() == InstanceContext); + assert(NamingClass->getCanonicalDecl() == NamingClass); + + // If we don't have an instance context, our constraints give us + // that NamingClass <= P <= NamingClass, i.e. P == NamingClass. + // This is just the usual friendship check. + if (!InstanceContext) return GetFriendKind(S, EC, 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, + AccessSpecifier Access, + const AccessTarget &Target) { + assert(NamingClass->getCanonicalDecl() == NamingClass && + "declaration should be canonicalized before being passed here"); + + if (Access == AS_public) return AR_accessible; + assert(Access == AS_private || Access == AS_protected); + + AccessResult OnFailure = AR_inaccessible; + + for (EffectiveContext::record_iterator + I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { + // All the declarations in EC have been canonicalized, so pointer + // equality from this point on will work fine. + const CXXRecordDecl *ECRecord = *I; + + // [B2] and [M2] + if (Access == AS_private) { + if (ECRecord == NamingClass) + return AR_accessible; + + if (EC.isDependent() && MightInstantiateTo(ECRecord, NamingClass)) + OnFailure = AR_dependent; + + // [B3] and [M3] + } else { + assert(Access == AS_protected); + switch (IsDerivedFromInclusive(ECRecord, NamingClass)) { + case AR_accessible: break; + case AR_inaccessible: continue; + case AR_dependent: OnFailure = AR_dependent; continue; + } + + // C++ [class.protected]p1: + // An additional access check beyond those described earlier in + // [class.access] is applied when a non-static data member or + // non-static member function is a protected member of its naming + // class. As described earlier, access to a protected member is + // granted because the reference occurs in a friend or member of + // some class C. If the access is to form a pointer to member, + // the nested-name-specifier shall name C or a class derived from + // C. All other accesses involve a (possibly implicit) object + // expression. In this case, the class of the object expression + // shall be C or a class derived from C. + // + // We interpret this as a restriction on [M3]. + + // In this part of the code, 'C' is just our context class ECRecord. + + // These rules are different if we don't have an instance context. + if (!Target.hasInstanceContext()) { + // If it's not an instance member, these restrictions don't apply. + if (!Target.isInstanceMember()) return AR_accessible; + + // If it's an instance member, use the pointer-to-member rule + // that the naming class has to be derived from the effective + // context. + + // Emulate a MSVC bug where the creation of pointer-to-member + // to protected member of base class is allowed but only from + // a static function member functions. + if (S.getLangOpts().MicrosoftMode && !EC.Functions.empty()) + if (CXXMethodDecl* MD = dyn_cast(EC.Functions.front())) + if (MD->isStatic()) return AR_accessible; + + // Despite the standard's confident wording, there is a case + // where you can have an instance member that's neither in a + // pointer-to-member expression nor in a member access: when + // it names a field in an unevaluated context that can't be an + // implicit member. Pending clarification, we just apply the + // same naming-class restriction here. + // FIXME: we're probably not correctly adding the + // protected-member restriction when we retroactively convert + // an expression to being evaluated. + + // We know that ECRecord derives from NamingClass. The + // restriction says to check whether NamingClass derives from + // ECRecord, but that's not really necessary: two distinct + // classes can't be recursively derived from each other. So + // along this path, we just need to check whether the classes + // are equal. + if (NamingClass == ECRecord) return AR_accessible; + + // Otherwise, this context class tells us nothing; on to the next. + continue; + } + + assert(Target.isInstanceMember()); + + const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S); + if (!InstanceContext) { + OnFailure = AR_dependent; + continue; + } + + switch (IsDerivedFromInclusive(InstanceContext, ECRecord)) { + case AR_accessible: return AR_accessible; + case AR_inaccessible: continue; + case AR_dependent: OnFailure = AR_dependent; continue; + } + } + } + + // [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.isInstanceMember()) { + // Compute the instance context if possible. + const CXXRecordDecl *InstanceContext = 0; + if (Target.hasInstanceContext()) { + InstanceContext = Target.resolveInstanceContext(S); + if (!InstanceContext) return AR_dependent; + } + + 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)) { + case AR_accessible: return AR_accessible; + case AR_inaccessible: return OnFailure; + case AR_dependent: return AR_dependent; + } + + // Silence bogus warnings + llvm_unreachable("impossible friendship kind"); +} + +/// Finds the best path from the naming class to the declaring class, +/// taking friend declarations into account. +/// +/// C++0x [class.access.base]p5: +/// A member m is accessible at the point R when named in class N if +/// [M1] m as a member of N is public, or +/// [M2] m as a member of N is private, and R occurs in a member or +/// friend of class N, or +/// [M3] m as a member of N is protected, and R occurs in a member or +/// friend of class N, or in a member or friend of a class P +/// derived from N, where m as a member of P is public, private, +/// or protected, or +/// [M4] there exists a base class B of N that is accessible at R, and +/// m is accessible at R when named in class B. +/// +/// C++0x [class.access.base]p4: +/// A base class B of N is accessible at R, if +/// [B1] an invented public member of B would be a public member of N, or +/// [B2] R occurs in a member or friend of class N, and an invented public +/// member of B would be a private or protected member of N, or +/// [B3] R occurs in a member or friend of a class P derived from N, and an +/// invented public member of B would be a private or protected member +/// of P, or +/// [B4] there exists a class S such that B is a base class of S accessible +/// at R and S is a base class of N accessible at R. +/// +/// Along a single inheritance path we can restate both of these +/// iteratively: +/// +/// First, we note that M1-4 are equivalent to B1-4 if the member is +/// treated as a notional base of its declaring class with inheritance +/// access equivalent to the member's access. Therefore we need only +/// ask whether a class B is accessible from a class N in context R. +/// +/// Let B_1 .. B_n be the inheritance path in question (i.e. where +/// B_1 = N, B_n = B, and for all i, B_{i+1} is a direct base class of +/// B_i). For i in 1..n, we will calculate ACAB(i), the access to the +/// closest accessible base in the path: +/// Access(a, b) = (* access on the base specifier from a to b *) +/// Merge(a, forbidden) = forbidden +/// Merge(a, private) = forbidden +/// Merge(a, b) = min(a,b) +/// Accessible(c, forbidden) = false +/// Accessible(c, private) = (R is c) || IsFriend(c, R) +/// Accessible(c, protected) = (R derived from c) || IsFriend(c, R) +/// Accessible(c, public) = true +/// ACAB(n) = public +/// ACAB(i) = +/// let AccessToBase = Merge(Access(B_i, B_{i+1}), ACAB(i+1)) in +/// if Accessible(B_i, AccessToBase) then public else AccessToBase +/// +/// B is an accessible base of N at R iff ACAB(1) = public. +/// +/// \param FinalAccess the access of the "final step", or AS_public if +/// there is no final step. +/// \return null if friendship is dependent +static CXXBasePath *FindBestPath(Sema &S, + const EffectiveContext &EC, + AccessTarget &Target, + AccessSpecifier FinalAccess, + CXXBasePaths &Paths) { + // Derive the paths to the desired base. + const CXXRecordDecl *Derived = Target.getNamingClass(); + const CXXRecordDecl *Base = Target.getDeclaringClass(); + + // FIXME: fail correctly when there are dependent paths. + bool isDerived = Derived->isDerivedFrom(const_cast(Base), + Paths); + assert(isDerived && "derived class not actually derived from base"); + (void) isDerived; + + CXXBasePath *BestPath = 0; + + assert(FinalAccess != AS_none && "forbidden access after declaring class"); + + bool AnyDependent = false; + + // Derive the friend-modified access along each path. + for (CXXBasePaths::paths_iterator PI = Paths.begin(), PE = Paths.end(); + PI != PE; ++PI) { + AccessTarget::SavedInstanceContext _ = Target.saveInstanceContext(); + + // Walk through the path backwards. + AccessSpecifier PathAccess = FinalAccess; + CXXBasePath::iterator I = PI->end(), E = PI->begin(); + while (I != E) { + --I; + + assert(PathAccess != AS_none); + + // If the declaration is a private member of a base class, there + // is no level of friendship in derived classes that can make it + // accessible. + if (PathAccess == AS_private) { + PathAccess = AS_none; + break; + } + + const CXXRecordDecl *NC = I->Class->getCanonicalDecl(); + + AccessSpecifier BaseAccess = I->Base->getAccessSpecifier(); + PathAccess = std::max(PathAccess, BaseAccess); + + switch (HasAccess(S, EC, NC, PathAccess, Target)) { + case AR_inaccessible: break; + case AR_accessible: + PathAccess = AS_public; + + // Future tests are not against members and so do not have + // instance context. + Target.suppressInstanceContext(); + break; + case AR_dependent: + AnyDependent = true; + goto Next; + } + } + + // Note that we modify the path's Access field to the + // friend-modified access. + if (BestPath == 0 || PathAccess < BestPath->Access) { + BestPath = &*PI; + BestPath->Access = PathAccess; + + // Short-circuit if we found a public path. + if (BestPath->Access == AS_public) + return BestPath; + } + + Next: ; + } + + assert((!BestPath || BestPath->Access != AS_public) && + "fell out of loop with public path"); + + // We didn't find a public path, but at least one path was subject + // to dependent friendship, so delay the check. + if (AnyDependent) + return 0; + + 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.isInstanceMember()) + return false; + + assert(Target.isMemberAccess()); + + const CXXRecordDecl *NamingClass = Target.getNamingClass(); + NamingClass = NamingClass->getCanonicalDecl(); + + for (EffectiveContext::record_iterator + I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { + const CXXRecordDecl *ECRecord = *I; + switch (IsDerivedFromInclusive(ECRecord, NamingClass)) { + case AR_accessible: break; + case AR_inaccessible: continue; + case AR_dependent: continue; + } + + // The effective context is a subclass of the declaring class. + // Check whether the [class.protected] restriction is limiting + // access. + + // 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. + + NamedDecl *D = Target.getTargetDecl(); + + // If we don't have an instance context, [class.protected] says the + // naming class has to equal the context class. + if (!Target.hasInstanceContext()) { + // If it does, the restriction doesn't apply. + if (NamingClass == ECRecord) continue; + + // TODO: it would be great to have a fixit here, since this is + // such an obvious error. + S.Diag(D->getLocation(), diag::note_access_protected_restricted_noobject) + << S.Context.getTypeDeclType(ECRecord); + return true; + } + + 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: + break; + } + + // Okay, the restriction seems to be what's limiting us. + + // Use a special diagnostic for constructors and destructors. + if (isa(D) || isa(D) || + (isa(D) && + isa( + cast(D)->getTemplatedDecl()))) { + S.Diag(D->getLocation(), diag::note_access_protected_restricted_ctordtor) + << isa(D); + return true; + } + + // Otherwise, use the generic diagnostic. + S.Diag(D->getLocation(), diag::note_access_protected_restricted_object) + << 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, + const EffectiveContext &EC, + AccessTarget &Entity) { + AccessSpecifier Access = Entity.getAccess(); + + NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : 0); + const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass(); + + // Easy case: the decl's natural access determined its path access. + // We have to check against AS_private here in case Access is AS_none, + // indicating a non-public member of a private base class. + 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; + + // Find an original declaration. + while (D->isOutOfLine()) { + NamedDecl *PrevDecl = 0; + if (VarDecl *VD = dyn_cast(D)) + PrevDecl = VD->getPreviousDecl(); + else if (FunctionDecl *FD = dyn_cast(D)) + PrevDecl = FD->getPreviousDecl(); + else if (TypedefNameDecl *TND = dyn_cast(D)) + PrevDecl = TND->getPreviousDecl(); + else if (TagDecl *TD = dyn_cast(D)) { + if (isa(D) && cast(D)->isInjectedClassName()) + break; + PrevDecl = TD->getPreviousDecl(); + } + if (!PrevDecl) break; + D = PrevDecl; + } + + CXXRecordDecl *DeclaringClass = FindDeclaringClass(D); + Decl *ImmediateChild; + if (D->getDeclContext() == DeclaringClass) + ImmediateChild = D; + else { + DeclContext *DC = D->getDeclContext(); + while (DC->getParent() != DeclaringClass) + DC = DC->getParent(); + ImmediateChild = cast(DC); + } + + // Check whether there's an AccessSpecDecl preceding this in the + // chain of the DeclContext. + bool Implicit = true; + for (CXXRecordDecl::decl_iterator + I = DeclaringClass->decls_begin(), E = DeclaringClass->decls_end(); + I != E; ++I) { + if (*I == ImmediateChild) break; + if (isa(*I)) { + Implicit = false; + break; + } + } + + S.Diag(D->getLocation(), diag::note_access_natural) + << (unsigned) (Access == AS_protected) + << Implicit; + return; + } + + case AR_accessible: break; + + case AR_dependent: + llvm_unreachable("can't diagnose dependent access failures"); + } + } + + CXXBasePaths Paths; + CXXBasePath &Path = *FindBestPath(S, EC, Entity, AS_public, Paths); + + CXXBasePath::iterator I = Path.end(), E = Path.begin(); + while (I != E) { + --I; + + const CXXBaseSpecifier *BS = I->Base; + AccessSpecifier BaseAccess = BS->getAccessSpecifier(); + + // If this is public inheritance, or the derived class is a friend, + // skip this step. + if (BaseAccess == AS_public) + continue; + + switch (GetFriendKind(S, EC, I->Class)) { + case AR_accessible: continue; + case AR_inaccessible: break; + case AR_dependent: + llvm_unreachable("can't diagnose dependent access failures"); + } + + // Check whether this base specifier is the tighest point + // constraining access. We have to check against AS_private for + // the same reasons as above. + if (BaseAccess == AS_private || BaseAccess >= Access) { + + // We're constrained by inheritance, but we want to say + // "declared private here" if we're diagnosing a hierarchy + // conversion and this is the final step. + unsigned diagnostic; + if (D) diagnostic = diag::note_access_constrained_by_path; + else if (I + 1 == Path.end()) diagnostic = diag::note_access_natural; + else diagnostic = diag::note_access_constrained_by_path; + + S.Diag(BS->getSourceRange().getBegin(), diagnostic) + << BS->getSourceRange() + << (BaseAccess == AS_protected) + << (BS->getAccessSpecifierAsWritten() == AS_none); + + if (D) + S.Diag(D->getLocation(), diag::note_field_decl); + + return; + } + } + + llvm_unreachable("access not apparently constrained by path"); +} + +static void DiagnoseBadAccess(Sema &S, SourceLocation Loc, + const EffectiveContext &EC, + AccessTarget &Entity) { + const CXXRecordDecl *NamingClass = Entity.getNamingClass(); + const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass(); + NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : 0); + + S.Diag(Loc, Entity.getDiag()) + << (Entity.getAccess() == AS_protected) + << (D ? D->getDeclName() : DeclarationName()) + << S.Context.getTypeDeclType(NamingClass) + << S.Context.getTypeDeclType(DeclaringClass); + DiagnoseAccessPath(S, EC, Entity); +} + +/// MSVC has a bug where if during an using declaration name lookup, +/// the declaration found is unaccessible (private) and that declaration +/// was bring into scope via another using declaration whose target +/// declaration is accessible (public) then no error is generated. +/// Example: +/// class A { +/// public: +/// int f(); +/// }; +/// class B : public A { +/// private: +/// using A::f; +/// }; +/// class C : public B { +/// private: +/// using B::f; +/// }; +/// +/// Here, B::f is private so this should fail in Standard C++, but +/// because B::f refers to A::f which is public MSVC accepts it. +static bool IsMicrosoftUsingDeclarationAccessBug(Sema& S, + SourceLocation AccessLoc, + AccessTarget &Entity) { + if (UsingShadowDecl *Shadow = + dyn_cast(Entity.getTargetDecl())) { + const NamedDecl *OrigDecl = Entity.getTargetDecl()->getUnderlyingDecl(); + if (Entity.getTargetDecl()->getAccess() == AS_private && + (OrigDecl->getAccess() == AS_public || + OrigDecl->getAccess() == AS_protected)) { + S.Diag(AccessLoc, diag::ext_ms_using_declaration_inaccessible) + << Shadow->getUsingDecl()->getQualifiedNameAsString() + << OrigDecl->getQualifiedNameAsString(); + return true; + } + } + return false; +} + +/// Determines whether the accessed entity is accessible. Public members +/// have been weeded out by this point. +static AccessResult IsAccessible(Sema &S, + const EffectiveContext &EC, + AccessTarget &Entity) { + // Determine the actual naming class. + CXXRecordDecl *NamingClass = Entity.getNamingClass(); + while (NamingClass->isAnonymousStructOrUnion()) + NamingClass = cast(NamingClass->getParent()); + NamingClass = NamingClass->getCanonicalDecl(); + + AccessSpecifier UnprivilegedAccess = Entity.getAccess(); + assert(UnprivilegedAccess != AS_public && "public access not weeded out"); + + // Before we try to recalculate access paths, try to white-list + // accesses which just trade in on the final step, i.e. accesses + // which don't require [M4] or [B4]. These are by far the most + // common forms of privileged access. + if (UnprivilegedAccess != AS_none) { + switch (HasAccess(S, EC, NamingClass, UnprivilegedAccess, Entity)) { + case AR_dependent: + // This is actually an interesting policy decision. We don't + // *have* to delay immediately here: we can do the full access + // calculation in the hope that friendship on some intermediate + // class will make the declaration accessible non-dependently. + // But that's not cheap, and odds are very good (note: assertion + // made without data) that the friend declaration will determine + // access. + return AR_dependent; + + case AR_accessible: return AR_accessible; + case AR_inaccessible: break; + } + } + + AccessTarget::SavedInstanceContext _ = Entity.saveInstanceContext(); + + // We lower member accesses to base accesses by pretending that the + // member is a base class of its declaring class. + AccessSpecifier FinalAccess; + + if (Entity.isMemberAccess()) { + // Determine if the declaration is accessible from EC when named + // in its declaring class. + NamedDecl *Target = Entity.getTargetDecl(); + const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass(); + + FinalAccess = Target->getAccess(); + switch (HasAccess(S, EC, DeclaringClass, FinalAccess, Entity)) { + case AR_accessible: + FinalAccess = AS_public; + break; + case AR_inaccessible: break; + case AR_dependent: return AR_dependent; // see above + } + + if (DeclaringClass == NamingClass) + return (FinalAccess == AS_public ? AR_accessible : AR_inaccessible); + + Entity.suppressInstanceContext(); + } else { + FinalAccess = AS_public; + } + + assert(Entity.getDeclaringClass() != NamingClass); + + // Append the declaration's access if applicable. + CXXBasePaths Paths; + CXXBasePath *Path = FindBestPath(S, EC, Entity, FinalAccess, Paths); + if (!Path) + return AR_dependent; + + assert(Path->Access <= UnprivilegedAccess && + "access along best path worse than direct?"); + if (Path->Access == AS_public) + return AR_accessible; + return AR_inaccessible; +} + +static void DelayDependentAccess(Sema &S, + const EffectiveContext &EC, + SourceLocation Loc, + const AccessTarget &Entity) { + assert(EC.isDependent() && "delaying non-dependent access"); + DeclContext *DC = EC.getInnerContext(); + assert(DC->isDependentContext() && "delaying non-dependent access"); + DependentDiagnostic::Create(S.Context, DC, DependentDiagnostic::Access, + Loc, + Entity.isMemberAccess(), + Entity.getAccess(), + Entity.getTargetDecl(), + Entity.getNamingClass(), + Entity.getBaseObjectType(), + Entity.getDiag()); +} + +/// Checks access to an entity from the given effective context. +static AccessResult CheckEffectiveAccess(Sema &S, + const EffectiveContext &EC, + SourceLocation Loc, + AccessTarget &Entity) { + assert(Entity.getAccess() != AS_public && "called for public access!"); + + if (S.getLangOpts().MicrosoftMode && + IsMicrosoftUsingDeclarationAccessBug(S, Loc, Entity)) + return AR_accessible; + + switch (IsAccessible(S, EC, Entity)) { + case AR_dependent: + DelayDependentAccess(S, EC, Loc, Entity); + return AR_dependent; + + case AR_inaccessible: + if (!Entity.isQuiet()) + DiagnoseBadAccess(S, Loc, EC, Entity); + return AR_inaccessible; + + case AR_accessible: + return AR_accessible; + } + + // silence unnecessary warning + llvm_unreachable("invalid access result"); +} + +static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc, + AccessTarget &Entity) { + // If the access path is public, it's accessible everywhere. + if (Entity.getAccess() == AS_public) + return Sema::AR_accessible; + + if (S.SuppressAccessChecking) + return Sema::AR_accessible; + + // If we're currently parsing a declaration, we may need to delay + // access control checking, because our effective context might be + // different based on what the declaration comes out as. + // + // For example, we might be parsing a declaration with a scope + // specifier, like this: + // A::private_type A::foo() { ... } + // + // Or we might be parsing something that will turn out to be a friend: + // void foo(A::private_type); + // void B::foo(A::private_type); + if (S.DelayedDiagnostics.shouldDelayDiagnostics()) { + S.DelayedDiagnostics.add(DelayedDiagnostic::makeAccess(Loc, Entity)); + return Sema::AR_delayed; + } + + EffectiveContext EC(S.CurContext); + switch (CheckEffectiveAccess(S, EC, Loc, Entity)) { + case AR_accessible: return Sema::AR_accessible; + case AR_inaccessible: return Sema::AR_inaccessible; + case AR_dependent: return Sema::AR_dependent; + } + llvm_unreachable("falling off end"); +} + +void Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *decl) { + // Access control for names used in the declarations of functions + // and function templates should normally be evaluated in the context + // of the declaration, just in case it's a friend of something. + // However, this does not apply to local extern declarations. + + DeclContext *DC = decl->getDeclContext(); + if (FunctionDecl *fn = dyn_cast(decl)) { + if (!DC->isFunctionOrMethod()) DC = fn; + } else if (FunctionTemplateDecl *fnt = dyn_cast(decl)) { + // Never a local declaration. + DC = fnt->getTemplatedDecl(); + } + + EffectiveContext EC(DC); + + AccessTarget Target(DD.getAccessData()); + + if (CheckEffectiveAccess(*this, EC, DD.Loc, Target) == ::AR_inaccessible) + DD.Triggered = true; +} + +void Sema::HandleDependentAccessCheck(const DependentDiagnostic &DD, + const MultiLevelTemplateArgumentList &TemplateArgs) { + SourceLocation Loc = DD.getAccessLoc(); + AccessSpecifier Access = DD.getAccess(); + + Decl *NamingD = FindInstantiatedDecl(Loc, DD.getAccessNamingClass(), + TemplateArgs); + if (!NamingD) return; + Decl *TargetD = FindInstantiatedDecl(Loc, DD.getAccessTarget(), + TemplateArgs); + if (!TargetD) return; + + if (DD.isAccessToMember()) { + CXXRecordDecl *NamingClass = cast(NamingD); + NamedDecl *TargetDecl = cast(TargetD); + QualType BaseObjectType = DD.getAccessBaseObjectType(); + if (!BaseObjectType.isNull()) { + BaseObjectType = SubstType(BaseObjectType, TemplateArgs, Loc, + DeclarationName()); + if (BaseObjectType.isNull()) return; + } + + AccessTarget Entity(Context, + AccessTarget::Member, + NamingClass, + DeclAccessPair::make(TargetDecl, Access), + BaseObjectType); + Entity.setDiag(DD.getDiagnostic()); + CheckAccess(*this, Loc, Entity); + } else { + AccessTarget Entity(Context, + AccessTarget::Base, + cast(TargetD), + cast(NamingD), + Access); + Entity.setDiag(DD.getDiagnostic()); + CheckAccess(*this, Loc, Entity); + } +} + +Sema::AccessResult Sema::CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E, + DeclAccessPair Found) { + if (!getLangOpts().AccessControl || + !E->getNamingClass() || + Found.getAccess() == AS_public) + return AR_accessible; + + AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(), + Found, QualType()); + Entity.setDiag(diag::err_access) << E->getSourceRange(); + + return CheckAccess(*this, E->getNameLoc(), Entity); +} + +/// Perform access-control checking on a previously-unresolved member +/// access which has now been resolved to a member. +Sema::AccessResult Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E, + DeclAccessPair Found) { + if (!getLangOpts().AccessControl || + Found.getAccess() == AS_public) + return AR_accessible; + + QualType BaseType = E->getBaseType(); + if (E->isArrow()) + BaseType = BaseType->getAs()->getPointeeType(); + + AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(), + Found, BaseType); + Entity.setDiag(diag::err_access) << E->getSourceRange(); + + return CheckAccess(*this, E->getMemberLoc(), Entity); +} + +/// Is the given special member function accessible for the purposes of +/// deciding whether to define a special member function as deleted? +bool Sema::isSpecialMemberAccessibleForDeletion(CXXMethodDecl *decl, + AccessSpecifier access, + QualType objectType) { + // Fast path. + if (access == AS_public || !getLangOpts().AccessControl) return true; + + AccessTarget entity(Context, AccessTarget::Member, decl->getParent(), + DeclAccessPair::make(decl, access), objectType); + + // Suppress diagnostics. + entity.setDiag(PDiag()); + + switch (CheckAccess(*this, SourceLocation(), entity)) { + case AR_accessible: return true; + case AR_inaccessible: return false; + case AR_dependent: llvm_unreachable("dependent for =delete computation"); + case AR_delayed: llvm_unreachable("cannot delay =delete computation"); + } + llvm_unreachable("bad access result"); +} + +Sema::AccessResult Sema::CheckDestructorAccess(SourceLocation Loc, + CXXDestructorDecl *Dtor, + const PartialDiagnostic &PDiag, + QualType ObjectTy) { + if (!getLangOpts().AccessControl) + return AR_accessible; + + // There's never a path involved when checking implicit destructor access. + AccessSpecifier Access = Dtor->getAccess(); + if (Access == AS_public) + return AR_accessible; + + CXXRecordDecl *NamingClass = Dtor->getParent(); + if (ObjectTy.isNull()) ObjectTy = Context.getTypeDeclType(NamingClass); + + AccessTarget Entity(Context, AccessTarget::Member, NamingClass, + DeclAccessPair::make(Dtor, Access), + ObjectTy); + Entity.setDiag(PDiag); // TODO: avoid copy + + return CheckAccess(*this, Loc, Entity); +} + +/// Checks access to a constructor. +Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc, + CXXConstructorDecl *Constructor, + const InitializedEntity &Entity, + AccessSpecifier Access, + bool IsCopyBindingRefToTemp) { + if (!getLangOpts().AccessControl || Access == AS_public) + return AR_accessible; + + PartialDiagnostic PD(PDiag()); + switch (Entity.getKind()) { + default: + PD = PDiag(IsCopyBindingRefToTemp + ? diag::ext_rvalue_to_reference_access_ctor + : diag::err_access_ctor); + + break; + + case InitializedEntity::EK_Base: + PD = PDiag(diag::err_access_base_ctor); + PD << Entity.isInheritedVirtualBase() + << Entity.getBaseSpecifier()->getType() << getSpecialMember(Constructor); + break; + + case InitializedEntity::EK_Member: { + const FieldDecl *Field = cast(Entity.getDecl()); + PD = PDiag(diag::err_access_field_ctor); + PD << Field->getType() << getSpecialMember(Constructor); + break; + } + + case InitializedEntity::EK_LambdaCapture: { + const VarDecl *Var = Entity.getCapturedVar(); + PD = PDiag(diag::err_access_lambda_capture); + PD << Var->getName() << Entity.getType() << getSpecialMember(Constructor); + break; + } + + } + + return CheckConstructorAccess(UseLoc, Constructor, Entity, Access, PD); +} + +/// Checks access to a constructor. +Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc, + CXXConstructorDecl *Constructor, + const InitializedEntity &Entity, + AccessSpecifier Access, + const PartialDiagnostic &PD) { + if (!getLangOpts().AccessControl || + Access == AS_public) + return AR_accessible; + + CXXRecordDecl *NamingClass = Constructor->getParent(); + + // Initializing a base sub-object is an instance method call on an + // object of the derived class. Otherwise, we have an instance method + // call on an object of the constructed type. + CXXRecordDecl *ObjectClass; + if (Entity.getKind() == InitializedEntity::EK_Base) { + ObjectClass = cast(CurContext)->getParent(); + } else { + ObjectClass = NamingClass; + } + + AccessTarget AccessEntity(Context, AccessTarget::Member, NamingClass, + DeclAccessPair::make(Constructor, Access), + Context.getTypeDeclType(ObjectClass)); + AccessEntity.setDiag(PD); + + return CheckAccess(*this, UseLoc, AccessEntity); +} + +/// Checks direct (i.e. non-inherited) access to an arbitrary class +/// member. +Sema::AccessResult Sema::CheckDirectMemberAccess(SourceLocation UseLoc, + NamedDecl *Target, + const PartialDiagnostic &Diag) { + AccessSpecifier Access = Target->getAccess(); + if (!getLangOpts().AccessControl || + Access == AS_public) + return AR_accessible; + + CXXRecordDecl *NamingClass = cast(Target->getDeclContext()); + AccessTarget Entity(Context, AccessTarget::Member, NamingClass, + DeclAccessPair::make(Target, Access), + QualType()); + Entity.setDiag(Diag); + return CheckAccess(*this, UseLoc, Entity); +} + + +/// Checks access to an overloaded operator new or delete. +Sema::AccessResult Sema::CheckAllocationAccess(SourceLocation OpLoc, + SourceRange PlacementRange, + CXXRecordDecl *NamingClass, + DeclAccessPair Found, + bool Diagnose) { + if (!getLangOpts().AccessControl || + !NamingClass || + Found.getAccess() == AS_public) + return AR_accessible; + + AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found, + QualType()); + if (Diagnose) + Entity.setDiag(diag::err_access) + << PlacementRange; + + return CheckAccess(*this, OpLoc, Entity); +} + +/// Checks access to an overloaded member operator, including +/// conversion operators. +Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc, + Expr *ObjectExpr, + Expr *ArgExpr, + DeclAccessPair Found) { + if (!getLangOpts().AccessControl || + Found.getAccess() == AS_public) + return AR_accessible; + + const RecordType *RT = ObjectExpr->getType()->castAs(); + CXXRecordDecl *NamingClass = cast(RT->getDecl()); + + AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found, + ObjectExpr->getType()); + Entity.setDiag(diag::err_access) + << ObjectExpr->getSourceRange() + << (ArgExpr ? ArgExpr->getSourceRange() : SourceRange()); + + return CheckAccess(*this, OpLoc, Entity); +} + +Sema::AccessResult Sema::CheckAddressOfMemberAccess(Expr *OvlExpr, + DeclAccessPair Found) { + if (!getLangOpts().AccessControl || + Found.getAccess() == AS_none || + Found.getAccess() == AS_public) + return AR_accessible; + + OverloadExpr *Ovl = OverloadExpr::find(OvlExpr).Expression; + CXXRecordDecl *NamingClass = Ovl->getNamingClass(); + + AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found, + /*no instance context*/ QualType()); + Entity.setDiag(diag::err_access) + << Ovl->getSourceRange(); + + return CheckAccess(*this, Ovl->getNameLoc(), Entity); +} + +/// Checks access for a hierarchy conversion. +/// +/// \param IsBaseToDerived whether this is a base-to-derived conversion (true) +/// or a derived-to-base conversion (false) +/// \param ForceCheck true if this check should be performed even if access +/// control is disabled; some things rely on this for semantics +/// \param ForceUnprivileged true if this check should proceed as if the +/// context had no special privileges +/// \param ADK controls the kind of diagnostics that are used +Sema::AccessResult Sema::CheckBaseClassAccess(SourceLocation AccessLoc, + QualType Base, + QualType Derived, + const CXXBasePath &Path, + unsigned DiagID, + bool ForceCheck, + bool ForceUnprivileged) { + if (!ForceCheck && !getLangOpts().AccessControl) + return AR_accessible; + + if (Path.Access == AS_public) + return AR_accessible; + + CXXRecordDecl *BaseD, *DerivedD; + BaseD = cast(Base->getAs()->getDecl()); + DerivedD = cast(Derived->getAs()->getDecl()); + + AccessTarget Entity(Context, AccessTarget::Base, BaseD, DerivedD, + Path.Access); + if (DiagID) + Entity.setDiag(DiagID) << Derived << Base; + + if (ForceUnprivileged) { + switch (CheckEffectiveAccess(*this, EffectiveContext(), + AccessLoc, Entity)) { + case ::AR_accessible: return Sema::AR_accessible; + case ::AR_inaccessible: return Sema::AR_inaccessible; + case ::AR_dependent: return Sema::AR_dependent; + } + llvm_unreachable("unexpected result from CheckEffectiveAccess"); + } + return CheckAccess(*this, AccessLoc, Entity); +} + +/// Checks access to all the declarations in the given result set. +void Sema::CheckLookupAccess(const LookupResult &R) { + assert(getLangOpts().AccessControl + && "performing access check without access control"); + assert(R.getNamingClass() && "performing access check without naming class"); + + for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { + if (I.getAccess() != AS_public) { + AccessTarget Entity(Context, AccessedEntity::Member, + R.getNamingClass(), I.getPair(), + R.getBaseObjectType()); + Entity.setDiag(diag::err_access); + CheckAccess(*this, R.getNameLoc(), Entity); + } + } +} + +/// Checks access to Decl from the given class. The check will take access +/// specifiers into account, but no member access expressions and such. +/// +/// \param Decl the declaration to check if it can be accessed +/// \param Class the class/context from which to start the search +/// \return true if the Decl is accessible from the Class, false otherwise. +bool Sema::IsSimplyAccessible(NamedDecl *Decl, DeclContext *Ctx) { + if (CXXRecordDecl *Class = dyn_cast(Ctx)) { + if (!Decl->isCXXClassMember()) + return true; + + QualType qType = Class->getTypeForDecl()->getCanonicalTypeInternal(); + AccessTarget Entity(Context, AccessedEntity::Member, Class, + DeclAccessPair::make(Decl, Decl->getAccess()), + qType); + if (Entity.getAccess() == AS_public) + return true; + + EffectiveContext EC(CurContext); + return ::IsAccessible(*this, EC, Entity) != ::AR_inaccessible; + } + + if (ObjCIvarDecl *Ivar = dyn_cast(Decl)) { + // @public and @package ivars are always accessible. + if (Ivar->getCanonicalAccessControl() == ObjCIvarDecl::Public || + Ivar->getCanonicalAccessControl() == ObjCIvarDecl::Package) + return true; + + + + // If we are inside a class or category implementation, determine the + // interface we're in. + ObjCInterfaceDecl *ClassOfMethodDecl = 0; + if (ObjCMethodDecl *MD = getCurMethodDecl()) + ClassOfMethodDecl = MD->getClassInterface(); + else if (FunctionDecl *FD = getCurFunctionDecl()) { + if (ObjCImplDecl *Impl + = dyn_cast(FD->getLexicalDeclContext())) { + if (ObjCImplementationDecl *IMPD + = dyn_cast(Impl)) + ClassOfMethodDecl = IMPD->getClassInterface(); + else if (ObjCCategoryImplDecl* CatImplClass + = dyn_cast(Impl)) + ClassOfMethodDecl = CatImplClass->getClassInterface(); + } + } + + // If we're not in an interface, this ivar is inaccessible. + if (!ClassOfMethodDecl) + return false; + + // If we're inside the same interface that owns the ivar, we're fine. + if (declaresSameEntity(ClassOfMethodDecl, Ivar->getContainingInterface())) + return true; + + // If the ivar is private, it's inaccessible. + if (Ivar->getCanonicalAccessControl() == ObjCIvarDecl::Private) + return false; + + return Ivar->getContainingInterface()->isSuperClassOf(ClassOfMethodDecl); + } + + return true; +} + +void Sema::ActOnStartSuppressingAccessChecks() { + assert(!SuppressAccessChecking && + "Tried to start access check suppression when already started."); + SuppressAccessChecking = true; +} + +void Sema::ActOnStopSuppressingAccessChecks() { + assert(SuppressAccessChecking && + "Tried to stop access check suprression when already stopped."); + SuppressAccessChecking = false; +} diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp new file mode 100644 index 0000000..e935fc7 --- /dev/null +++ b/clang/lib/Sema/SemaAttr.cpp @@ -0,0 +1,426 @@ +//===--- SemaAttr.cpp - Semantic Analysis for Attributes ------------------===// +// +// 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 non-trivial attributes and +// pragmas. +// +//===----------------------------------------------------------------------===// + +#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" +using namespace clang; + +//===----------------------------------------------------------------------===// +// Pragma 'pack' and 'options align' +//===----------------------------------------------------------------------===// + +namespace { + struct PackStackEntry { + // We just use a sentinel to represent when the stack is set to mac68k + // alignment. + static const unsigned kMac68kAlignmentSentinel = ~0U; + + unsigned Alignment; + IdentifierInfo *Name; + }; + + /// PragmaPackStack - Simple class to wrap the stack used by #pragma + /// pack. + class PragmaPackStack { + typedef std::vector stack_ty; + + /// Alignment - The current user specified alignment. + unsigned Alignment; + + /// Stack - Entries in the #pragma pack stack, consisting of saved + /// alignments and optional names. + stack_ty Stack; + + public: + PragmaPackStack() : Alignment(0) {} + + void setAlignment(unsigned A) { Alignment = A; } + unsigned getAlignment() { return Alignment; } + + /// push - Push the current alignment onto the stack, optionally + /// using the given \arg Name for the record, if non-zero. + void push(IdentifierInfo *Name) { + PackStackEntry PSE = { Alignment, Name }; + Stack.push_back(PSE); + } + + /// pop - Pop a record from the stack and restore the current + /// 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 IsReset); + }; +} // end anonymous namespace. + +bool PragmaPackStack::pop(IdentifierInfo *Name, bool IsReset) { + // If name is empty just pop top. + if (!Name) { + // 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; + } + + // Otherwise, find the named record. + for (unsigned i = Stack.size(); i != 0; ) { + --i; + if (Stack[i].Name == Name) { + // Found it, pop up to and including this record. + Alignment = Stack[i].Alignment; + Stack.erase(Stack.begin() + i, Stack.end()); + return true; + } + } + + return false; +} + + +/// FreePackedContext - Deallocate and null out PackContext. +void Sema::FreePackedContext() { + delete static_cast(PackContext); + PackContext = 0; +} + +void Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) { + // If there is no pack context, we don't need any attributes. + if (!PackContext) + return; + + PragmaPackStack *Stack = static_cast(PackContext); + + // 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(SourceLocation(), Context)); + else + RD->addAttr(::new (Context) MaxFieldAlignmentAttr(SourceLocation(), + Context, + Alignment * 8)); + } +} + +void Sema::AddMsStructLayoutForRecord(RecordDecl *RD) { + if (!MSStructPragmaOn) + return; + RD->addAttr(::new (Context) MsStructAttr(SourceLocation(), Context)); +} + +void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind, + SourceLocation PragmaLoc, + SourceLocation KindLoc) { + if (PackContext == 0) + PackContext = new PragmaPackStack(); + + PragmaPackStack *Context = static_cast(PackContext); + + // 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"; + } + return; + } + + switch (Kind) { + // For all targets we support native and natural are the same. + // + // FIXME: This is not true on Darwin/PPC. + case POAK_Native: + case POAK_Power: + case POAK_Natural: + Context->push(0); + Context->setAlignment(0); + break; + + // Note that '#pragma options align=packed' is not equivalent to attribute + // packed, it has a different precedence relative to attribute aligned. + case POAK_Packed: + Context->push(0); + Context->setAlignment(1); + break; + + case POAK_Mac68k: + // Check if the target supports this. + if (!PP.getTargetInfo().hasAlignMac68kSupport()) { + Diag(PragmaLoc, diag::err_pragma_options_align_mac68k_target_unsupported); + return; + } + Context->push(0); + Context->setAlignment(PackStackEntry::kMac68kAlignmentSentinel); + break; + + default: + Diag(PragmaLoc, diag::warn_pragma_options_align_unsupported_option) + << KindLoc; + break; + } +} + +void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name, + Expr *alignment, SourceLocation PragmaLoc, + SourceLocation LParenLoc, SourceLocation RParenLoc) { + Expr *Alignment = static_cast(alignment); + + // If specified then alignment must be a "small" power of two. + unsigned AlignmentVal = 0; + if (Alignment) { + llvm::APSInt Val; + + // pack(0) is like pack(), which just works out since that is what + // we use 0 for in PackAttr. + if (Alignment->isTypeDependent() || + Alignment->isValueDependent() || + !Alignment->isIntegerConstantExpr(Val, Context) || + !(Val == 0 || Val.isPowerOf2()) || + Val.getZExtValue() > 16) { + Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment); + return; // Ignore + } + + AlignmentVal = (unsigned) Val.getZExtValue(); + } + + if (PackContext == 0) + PackContext = new PragmaPackStack(); + + PragmaPackStack *Context = static_cast(PackContext); + + switch (Kind) { + case Sema::PPK_Default: // pack([n]) + Context->setAlignment(AlignmentVal); + break; + + case Sema::PPK_Show: // pack(show) + // Show the current alignment, making sure to show the right value + // for the default. + AlignmentVal = Context->getAlignment(); + // FIXME: This should come from the target. + if (AlignmentVal == 0) + AlignmentVal = 8; + if (AlignmentVal == PackStackEntry::kMac68kAlignmentSentinel) + Diag(PragmaLoc, diag::warn_pragma_pack_show) << "mac68k"; + else + Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal; + break; + + case Sema::PPK_Push: // pack(push [, id] [, [n]) + Context->push(Name); + // Set the new alignment if specified. + if (Alignment) + Context->setAlignment(AlignmentVal); + break; + + 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, /*IsReset=*/false)) { + // If a name was specified then failure indicates the name + // wasn't found. Otherwise failure indicates the stack was + // empty. + Diag(PragmaLoc, diag::warn_pragma_pack_pop_failed) + << (Name ? "no record matching name" : "stack empty"); + + // FIXME: Warn about popping named records as MSVC does. + } else { + // Pop succeeded, set the new alignment if specified. + if (Alignment) + Context->setAlignment(AlignmentVal); + } + break; + } +} + +void Sema::ActOnPragmaMSStruct(PragmaMSStructKind Kind) { + MSStructPragmaOn = (Kind == PMSST_ON); +} + +void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope, + SourceLocation PragmaLoc) { + + IdentifierInfo *Name = IdTok.getIdentifierInfo(); + LookupResult Lookup(*this, Name, IdTok.getLocation(), LookupOrdinaryName); + LookupParsedName(Lookup, curScope, NULL, true); + + if (Lookup.empty()) { + Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var) + << Name << SourceRange(IdTok.getLocation()); + return; + } + + VarDecl *VD = Lookup.getAsSingle(); + if (!VD) { + Diag(PragmaLoc, diag::warn_pragma_unused_expected_var_arg) + << Name << SourceRange(IdTok.getLocation()); + return; + } + + // Warn if this was used before being marked unused. + if (VD->isUsed()) + Diag(PragmaLoc, diag::warn_used_but_marked_unused) << Name; + + VD->addAttr(::new (Context) UnusedAttr(IdTok.getLocation(), Context)); +} + +void Sema::AddCFAuditedAttribute(Decl *D) { + SourceLocation Loc = PP.getPragmaARCCFCodeAuditedLoc(); + if (!Loc.isValid()) return; + + // Don't add a redundant or conflicting attribute. + if (D->hasAttr() || + D->hasAttr()) + return; + + D->addAttr(::new (Context) CFAuditedTransferAttr(Loc, Context)); +} + +typedef std::vector > VisStack; +enum { NoVisibility = (unsigned) -1 }; + +void Sema::AddPushedVisibilityAttribute(Decl *D) { + if (!VisContext) + return; + + if (isa(D) && cast(D)->getExplicitVisibility()) + return; + + VisStack *Stack = static_cast(VisContext); + unsigned rawType = Stack->back().first; + if (rawType == NoVisibility) return; + + VisibilityAttr::VisibilityType type + = (VisibilityAttr::VisibilityType) rawType; + 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, unsigned 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(const IdentifierInfo* VisType, + SourceLocation PragmaLoc) { + if (VisType) { + // 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(false, PragmaLoc); + } +} + +void Sema::ActOnPragmaFPContract(tok::OnOffSwitch OOS) { + switch (OOS) { + case tok::OOS_ON: + FPFeatures.fp_contract = 1; + break; + case tok::OOS_OFF: + FPFeatures.fp_contract = 0; + break; + case tok::OOS_DEFAULT: + FPFeatures.fp_contract = getLangOpts().DefaultFPContract; + break; + } +} + +void Sema::PushNamespaceVisibilityAttr(const VisibilityAttr *Attr, + SourceLocation Loc) { + // Visibility calculations will consider the namespace's visibility. + // Here we just want to note that we're in a visibility context + // which overrides any enclosing #pragma context, but doesn't itself + // contribute visibility. + PushPragmaVisibility(*this, NoVisibility, Loc); +} + +void Sema::PopPragmaVisibility(bool IsNamespaceEnd, SourceLocation EndLoc) { + if (!VisContext) { + Diag(EndLoc, diag::err_pragma_pop_visibility_mismatch); + return; + } + + // Pop visibility from stack + VisStack *Stack = static_cast(VisContext); + + const std::pair *Back = &Stack->back(); + bool StartsWithPragma = Back->first != NoVisibility; + if (StartsWithPragma && IsNamespaceEnd) { + Diag(Back->second, diag::err_pragma_push_visibility_mismatch); + Diag(EndLoc, diag::note_surrounding_namespace_ends_here); + + // For better error recovery, eat all pushes inside the namespace. + do { + Stack->pop_back(); + Back = &Stack->back(); + StartsWithPragma = Back->first != NoVisibility; + } while (StartsWithPragma); + } else if (!StartsWithPragma && !IsNamespaceEnd) { + Diag(EndLoc, diag::err_pragma_pop_visibility_mismatch); + Diag(Back->second, diag::note_surrounding_namespace_starts_here); + return; + } + + Stack->pop_back(); + // To simplify the implementation, never keep around an empty stack. + if (Stack->empty()) + FreeVisContext(); +} diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp new file mode 100644 index 0000000..5a0fcec --- /dev/null +++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -0,0 +1,958 @@ +//===--- SemaCXXScopeSpec.cpp - Semantic Analysis for C++ scope specifiers-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements C++ semantic analysis for scope specifiers. +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/Template.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/Sema/DeclSpec.h" +#include "TypeLocBuilder.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/raw_ostream.h" +using namespace clang; + +/// \brief Find the current instantiation that associated with the given type. +static CXXRecordDecl *getCurrentInstantiationOf(QualType T, + DeclContext *CurContext) { + if (T.isNull()) + return 0; + + const Type *Ty = T->getCanonicalTypeInternal().getTypePtr(); + if (const RecordType *RecordTy = dyn_cast(Ty)) { + CXXRecordDecl *Record = cast(RecordTy->getDecl()); + if (!T->isDependentType()) + return Record; + + // This may be a member of a class template or class template partial + // specialization. If it's part of the current semantic context, then it's + // an injected-class-name; + for (; !CurContext->isFileContext(); CurContext = CurContext->getParent()) + if (CurContext->Equals(Record)) + return Record; + + return 0; + } else if (isa(Ty)) + return cast(Ty)->getDecl(); + else + return 0; +} + +/// \brief Compute the DeclContext that is associated with the given type. +/// +/// \param T the type for which we are attempting to find a DeclContext. +/// +/// \returns the declaration context represented by the type T, +/// or NULL if the declaration context cannot be computed (e.g., because it is +/// dependent and not the current instantiation). +DeclContext *Sema::computeDeclContext(QualType T) { + if (!T->isDependentType()) + if (const TagType *Tag = T->getAs()) + return Tag->getDecl(); + + return ::getCurrentInstantiationOf(T, CurContext); +} + +/// \brief Compute the DeclContext that is associated with the given +/// scope specifier. +/// +/// \param SS the C++ scope specifier as it appears in the source +/// +/// \param EnteringContext when true, we will be entering the context of +/// this scope specifier, so we can retrieve the declaration context of a +/// class template or class template partial specialization even if it is +/// not the current instantiation. +/// +/// \returns the declaration context represented by the scope specifier @p SS, +/// or NULL if the declaration context cannot be computed (e.g., because it is +/// dependent and not the current instantiation). +DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS, + bool EnteringContext) { + if (!SS.isSet() || SS.isInvalid()) + return 0; + + NestedNameSpecifier *NNS + = static_cast(SS.getScopeRep()); + if (NNS->isDependent()) { + // If this nested-name-specifier refers to the current + // instantiation, return its DeclContext. + if (CXXRecordDecl *Record = getCurrentInstantiationOf(NNS)) + return Record; + + if (EnteringContext) { + const Type *NNSType = NNS->getAsType(); + if (!NNSType) { + return 0; + } + + // Look through type alias templates, per C++0x [temp.dep.type]p1. + NNSType = Context.getCanonicalType(NNSType); + if (const TemplateSpecializationType *SpecType + = NNSType->getAs()) { + // We are entering the context of the nested name specifier, so try to + // match the nested name specifier to either a primary class template + // or a class template partial specialization. + if (ClassTemplateDecl *ClassTemplate + = dyn_cast_or_null( + SpecType->getTemplateName().getAsTemplateDecl())) { + QualType ContextType + = Context.getCanonicalType(QualType(SpecType, 0)); + + // If the type of the nested name specifier is the same as the + // injected class name of the named class template, we're entering + // into that class template definition. + QualType Injected + = ClassTemplate->getInjectedClassNameSpecialization(); + if (Context.hasSameType(Injected, ContextType)) + return ClassTemplate->getTemplatedDecl(); + + // If the type of the nested name specifier is the same as the + // type of one of the class template's class template partial + // specializations, we're entering into the definition of that + // class template partial specialization. + if (ClassTemplatePartialSpecializationDecl *PartialSpec + = ClassTemplate->findPartialSpecialization(ContextType)) + return PartialSpec; + } + } else if (const RecordType *RecordT = NNSType->getAs()) { + // The nested name specifier refers to a member of a class template. + return RecordT->getDecl(); + } + } + + return 0; + } + + switch (NNS->getKind()) { + case NestedNameSpecifier::Identifier: + llvm_unreachable("Dependent nested-name-specifier has no DeclContext"); + + case NestedNameSpecifier::Namespace: + return NNS->getAsNamespace(); + + case NestedNameSpecifier::NamespaceAlias: + return NNS->getAsNamespaceAlias()->getNamespace(); + + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: { + const TagType *Tag = NNS->getAsType()->getAs(); + assert(Tag && "Non-tag type in nested-name-specifier"); + return Tag->getDecl(); + } + + case NestedNameSpecifier::Global: + return Context.getTranslationUnitDecl(); + } + + llvm_unreachable("Invalid NestedNameSpecifier::Kind!"); +} + +bool Sema::isDependentScopeSpecifier(const CXXScopeSpec &SS) { + if (!SS.isSet() || SS.isInvalid()) + return false; + + NestedNameSpecifier *NNS + = static_cast(SS.getScopeRep()); + return NNS->isDependent(); +} + +// \brief Determine whether this C++ scope specifier refers to an +// unknown specialization, i.e., a dependent type that is not the +// current instantiation. +bool Sema::isUnknownSpecialization(const CXXScopeSpec &SS) { + if (!isDependentScopeSpecifier(SS)) + return false; + + NestedNameSpecifier *NNS + = static_cast(SS.getScopeRep()); + return getCurrentInstantiationOf(NNS) == 0; +} + +/// \brief If the given nested name specifier refers to the current +/// instantiation, return the declaration that corresponds to that +/// current instantiation (C++0x [temp.dep.type]p1). +/// +/// \param NNS a dependent nested name specifier. +CXXRecordDecl *Sema::getCurrentInstantiationOf(NestedNameSpecifier *NNS) { + assert(getLangOpts().CPlusPlus && "Only callable in C++"); + assert(NNS->isDependent() && "Only dependent nested-name-specifier allowed"); + + if (!NNS->getAsType()) + return 0; + + QualType T = QualType(NNS->getAsType(), 0); + return ::getCurrentInstantiationOf(T, CurContext); +} + +/// \brief Require that the context specified by SS be complete. +/// +/// If SS refers to a type, this routine checks whether the type is +/// complete enough (or can be made complete enough) for name lookup +/// into the DeclContext. A type that is not yet completed can be +/// considered "complete enough" if it is a class/struct/union/enum +/// that is currently being defined. Or, if we have a type that names +/// a class template specialization that is not a complete type, we +/// will attempt to instantiate that class template. +bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS, + DeclContext *DC) { + assert(DC != 0 && "given null context"); + + TagDecl *tag = dyn_cast(DC); + + // If this is a dependent type, then we consider it complete. + if (!tag || tag->isDependentContext()) + return false; + + // If we're currently defining this type, then lookup into the + // type is okay: don't complain that it isn't complete yet. + QualType type = Context.getTypeDeclType(tag); + const TagType *tagType = type->getAs(); + if (tagType && tagType->isBeingDefined()) + return false; + + SourceLocation loc = SS.getLastQualifierNameLoc(); + if (loc.isInvalid()) loc = SS.getRange().getBegin(); + + // The type must be complete. + if (RequireCompleteType(loc, type, + PDiag(diag::err_incomplete_nested_name_spec) + << SS.getRange())) { + SS.SetInvalid(SS.getRange()); + return true; + } + + // Fixed enum types are complete, but they aren't valid as scopes + // until we see a definition, so awkwardly pull out this special + // case. + const EnumType *enumType = dyn_cast_or_null(tagType); + if (!enumType || enumType->getDecl()->isCompleteDefinition()) + return false; + + // Try to instantiate the definition, if this is a specialization of an + // enumeration temploid. + EnumDecl *ED = enumType->getDecl(); + if (EnumDecl *Pattern = ED->getInstantiatedFromMemberEnum()) { + MemberSpecializationInfo *MSI = ED->getMemberSpecializationInfo(); + if (MSI->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) { + if (InstantiateEnum(loc, ED, Pattern, getTemplateInstantiationArgs(ED), + TSK_ImplicitInstantiation)) { + SS.SetInvalid(SS.getRange()); + return true; + } + return false; + } + } + + Diag(loc, diag::err_incomplete_nested_name_spec) + << type << SS.getRange(); + SS.SetInvalid(SS.getRange()); + return true; +} + +bool Sema::ActOnCXXGlobalScopeSpecifier(Scope *S, SourceLocation CCLoc, + CXXScopeSpec &SS) { + SS.MakeGlobal(Context, CCLoc); + return false; +} + +/// \brief Determines whether the given declaration is an valid acceptable +/// result for name lookup of a nested-name-specifier. +bool Sema::isAcceptableNestedNameSpecifier(NamedDecl *SD) { + if (!SD) + return false; + + // Namespace and namespace aliases are fine. + if (isa(SD) || isa(SD)) + return true; + + if (!isa(SD)) + return false; + + // Determine whether we have a class (or, in C++11, an enum) or + // a typedef thereof. If so, build the nested-name-specifier. + QualType T = Context.getTypeDeclType(cast(SD)); + if (T->isDependentType()) + return true; + else if (TypedefNameDecl *TD = dyn_cast(SD)) { + if (TD->getUnderlyingType()->isRecordType() || + (Context.getLangOpts().CPlusPlus0x && + TD->getUnderlyingType()->isEnumeralType())) + return true; + } else if (isa(SD) || + (Context.getLangOpts().CPlusPlus0x && isa(SD))) + return true; + + return false; +} + +/// \brief If the given nested-name-specifier begins with a bare identifier +/// (e.g., Base::), perform name lookup for that identifier as a +/// nested-name-specifier within the given scope, and return the result of that +/// name lookup. +NamedDecl *Sema::FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS) { + if (!S || !NNS) + return 0; + + while (NNS->getPrefix()) + NNS = NNS->getPrefix(); + + if (NNS->getKind() != NestedNameSpecifier::Identifier) + return 0; + + LookupResult Found(*this, NNS->getAsIdentifier(), SourceLocation(), + LookupNestedNameSpecifierName); + LookupName(Found, S); + assert(!Found.isAmbiguous() && "Cannot handle ambiguities here yet"); + + if (!Found.isSingleResult()) + return 0; + + NamedDecl *Result = Found.getFoundDecl(); + if (isAcceptableNestedNameSpecifier(Result)) + return Result; + + return 0; +} + +bool Sema::isNonTypeNestedNameSpecifier(Scope *S, CXXScopeSpec &SS, + SourceLocation IdLoc, + IdentifierInfo &II, + ParsedType ObjectTypePtr) { + QualType ObjectType = GetTypeFromParser(ObjectTypePtr); + LookupResult Found(*this, &II, IdLoc, LookupNestedNameSpecifierName); + + // Determine where to perform name lookup + DeclContext *LookupCtx = 0; + bool isDependent = false; + if (!ObjectType.isNull()) { + // This nested-name-specifier occurs in a member access expression, e.g., + // x->B::f, and we are looking into the type of the object. + assert(!SS.isSet() && "ObjectType and scope specifier cannot coexist"); + LookupCtx = computeDeclContext(ObjectType); + isDependent = ObjectType->isDependentType(); + } else if (SS.isSet()) { + // This nested-name-specifier occurs after another nested-name-specifier, + // so long into the context associated with the prior nested-name-specifier. + LookupCtx = computeDeclContext(SS, false); + isDependent = isDependentScopeSpecifier(SS); + Found.setContextRange(SS.getRange()); + } + + if (LookupCtx) { + // Perform "qualified" name lookup into the declaration context we + // computed, which is either the type of the base of a member access + // expression or the declaration context associated with a prior + // nested-name-specifier. + + // The declaration context must be complete. + if (!LookupCtx->isDependentContext() && + RequireCompleteDeclContext(SS, LookupCtx)) + return false; + + LookupQualifiedName(Found, LookupCtx); + } else if (isDependent) { + return false; + } else { + LookupName(Found, S); + } + Found.suppressDiagnostics(); + + if (NamedDecl *ND = Found.getAsSingle()) + return isa(ND) || isa(ND); + + return false; +} + +namespace { + +// Callback to only accept typo corrections that can be a valid C++ member +// intializer: either a non-static field member or a base class. +class NestedNameSpecifierValidatorCCC : public CorrectionCandidateCallback { + public: + explicit NestedNameSpecifierValidatorCCC(Sema &SRef) + : SRef(SRef) {} + + virtual bool ValidateCandidate(const TypoCorrection &candidate) { + return SRef.isAcceptableNestedNameSpecifier(candidate.getCorrectionDecl()); + } + + private: + Sema &SRef; +}; + +} + +/// \brief Build a new nested-name-specifier for "identifier::", as described +/// by ActOnCXXNestedNameSpecifier. +/// +/// This routine differs only slightly from ActOnCXXNestedNameSpecifier, in +/// that it contains an extra parameter \p ScopeLookupResult, which provides +/// the result of name lookup within the scope of the nested-name-specifier +/// that was computed at template definition time. +/// +/// If ErrorRecoveryLookup is true, then this call is used to improve error +/// recovery. This means that it should not emit diagnostics, it should +/// just return true on failure. It also means it should only return a valid +/// scope if it *knows* that the result is correct. It should not return in a +/// dependent context, for example. Nor will it extend \p SS with the scope +/// specifier. +bool Sema::BuildCXXNestedNameSpecifier(Scope *S, + IdentifierInfo &Identifier, + SourceLocation IdentifierLoc, + SourceLocation CCLoc, + QualType ObjectType, + bool EnteringContext, + CXXScopeSpec &SS, + NamedDecl *ScopeLookupResult, + bool ErrorRecoveryLookup) { + LookupResult Found(*this, &Identifier, IdentifierLoc, + LookupNestedNameSpecifierName); + + // Determine where to perform name lookup + DeclContext *LookupCtx = 0; + bool isDependent = false; + if (!ObjectType.isNull()) { + // This nested-name-specifier occurs in a member access expression, e.g., + // x->B::f, and we are looking into the type of the object. + assert(!SS.isSet() && "ObjectType and scope specifier cannot coexist"); + LookupCtx = computeDeclContext(ObjectType); + isDependent = ObjectType->isDependentType(); + } else if (SS.isSet()) { + // This nested-name-specifier occurs after another nested-name-specifier, + // so look into the context associated with the prior nested-name-specifier. + LookupCtx = computeDeclContext(SS, EnteringContext); + isDependent = isDependentScopeSpecifier(SS); + Found.setContextRange(SS.getRange()); + } + + + bool ObjectTypeSearchedInScope = false; + if (LookupCtx) { + // Perform "qualified" name lookup into the declaration context we + // computed, which is either the type of the base of a member access + // expression or the declaration context associated with a prior + // nested-name-specifier. + + // The declaration context must be complete. + if (!LookupCtx->isDependentContext() && + RequireCompleteDeclContext(SS, LookupCtx)) + return true; + + LookupQualifiedName(Found, LookupCtx); + + if (!ObjectType.isNull() && Found.empty()) { + // C++ [basic.lookup.classref]p4: + // If the id-expression in a class member access is a qualified-id of + // the form + // + // class-name-or-namespace-name::... + // + // the class-name-or-namespace-name following the . or -> operator is + // looked up both in the context of the entire postfix-expression and in + // the scope of the class of the object expression. If the name is found + // only in the scope of the class of the object expression, the name + // shall refer to a class-name. If the name is found only in the + // context of the entire postfix-expression, the name shall refer to a + // class-name or namespace-name. [...] + // + // Qualified name lookup into a class will not find a namespace-name, + // so we do not need to diagnose that case specifically. However, + // this qualified name lookup may find nothing. In that case, perform + // unqualified name lookup in the given scope (if available) or + // reconstruct the result from when name lookup was performed at template + // definition time. + if (S) + LookupName(Found, S); + else if (ScopeLookupResult) + Found.addDecl(ScopeLookupResult); + + ObjectTypeSearchedInScope = true; + } + } 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 true; + + // We were not able to compute the declaration context for a dependent + // base object type or prior nested-name-specifier, so this + // nested-name-specifier refers to an unknown specialization. Just build + // a dependent nested-name-specifier. + SS.Extend(Context, &Identifier, IdentifierLoc, CCLoc); + return false; + } + + // FIXME: Deal with ambiguities cleanly. + + if (Found.empty() && !ErrorRecoveryLookup) { + // We haven't found anything, and we're not recovering from a + // different kind of error, so look for typos. + DeclarationName Name = Found.getLookupName(); + NestedNameSpecifierValidatorCCC Validator(*this); + TypoCorrection Corrected; + Found.clear(); + if ((Corrected = CorrectTypo(Found.getLookupNameInfo(), + Found.getLookupKind(), S, &SS, Validator, + LookupCtx, EnteringContext))) { + std::string CorrectedStr(Corrected.getAsString(getLangOpts())); + std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOpts())); + if (LookupCtx) + Diag(Found.getNameLoc(), diag::err_no_member_suggest) + << Name << LookupCtx << CorrectedQuotedStr << SS.getRange() + << FixItHint::CreateReplacement(Found.getNameLoc(), CorrectedStr); + else + Diag(Found.getNameLoc(), diag::err_undeclared_var_use_suggest) + << Name << CorrectedQuotedStr + << FixItHint::CreateReplacement(Found.getNameLoc(), CorrectedStr); + + if (NamedDecl *ND = Corrected.getCorrectionDecl()) { + Diag(ND->getLocation(), diag::note_previous_decl) << CorrectedQuotedStr; + Found.addDecl(ND); + } + Found.setLookupName(Corrected.getCorrection()); + } else { + Found.setLookupName(&Identifier); + } + } + + NamedDecl *SD = Found.getAsSingle(); + if (isAcceptableNestedNameSpecifier(SD)) { + if (!ObjectType.isNull() && !ObjectTypeSearchedInScope) { + // C++ [basic.lookup.classref]p4: + // [...] If the name is found in both contexts, the + // class-name-or-namespace-name shall refer to the same entity. + // + // We already found the name in the scope of the object. Now, look + // into the current scope (the scope of the postfix-expression) to + // see if we can find the same name there. As above, if there is no + // scope, reconstruct the result from the template instantiation itself. + NamedDecl *OuterDecl; + if (S) { + LookupResult FoundOuter(*this, &Identifier, IdentifierLoc, + LookupNestedNameSpecifierName); + LookupName(FoundOuter, S); + OuterDecl = FoundOuter.getAsSingle(); + } else + OuterDecl = ScopeLookupResult; + + if (isAcceptableNestedNameSpecifier(OuterDecl) && + OuterDecl->getCanonicalDecl() != SD->getCanonicalDecl() && + (!isa(OuterDecl) || !isa(SD) || + !Context.hasSameType( + Context.getTypeDeclType(cast(OuterDecl)), + Context.getTypeDeclType(cast(SD))))) { + if (ErrorRecoveryLookup) + return true; + + Diag(IdentifierLoc, + diag::err_nested_name_member_ref_lookup_ambiguous) + << &Identifier; + Diag(SD->getLocation(), diag::note_ambig_member_ref_object_type) + << ObjectType; + Diag(OuterDecl->getLocation(), diag::note_ambig_member_ref_scope); + + // Fall through so that we'll pick the name we found in the object + // type, since that's probably what the user wanted anyway. + } + } + + // If we're just performing this lookup for error-recovery purposes, + // don't extend the nested-name-specifier. Just return now. + if (ErrorRecoveryLookup) + return false; + + if (NamespaceDecl *Namespace = dyn_cast(SD)) { + SS.Extend(Context, Namespace, IdentifierLoc, CCLoc); + return false; + } + + if (NamespaceAliasDecl *Alias = dyn_cast(SD)) { + SS.Extend(Context, Alias, IdentifierLoc, CCLoc); + return false; + } + + QualType T = Context.getTypeDeclType(cast(SD)); + TypeLocBuilder TLB; + if (isa(T)) { + InjectedClassNameTypeLoc InjectedTL + = TLB.push(T); + InjectedTL.setNameLoc(IdentifierLoc); + } else if (isa(T)) { + RecordTypeLoc RecordTL = TLB.push(T); + RecordTL.setNameLoc(IdentifierLoc); + } else if (isa(T)) { + TypedefTypeLoc TypedefTL = TLB.push(T); + TypedefTL.setNameLoc(IdentifierLoc); + } else if (isa(T)) { + EnumTypeLoc EnumTL = TLB.push(T); + EnumTL.setNameLoc(IdentifierLoc); + } else if (isa(T)) { + TemplateTypeParmTypeLoc TemplateTypeTL + = TLB.push(T); + TemplateTypeTL.setNameLoc(IdentifierLoc); + } else if (isa(T)) { + UnresolvedUsingTypeLoc UnresolvedTL + = TLB.push(T); + UnresolvedTL.setNameLoc(IdentifierLoc); + } else if (isa(T)) { + SubstTemplateTypeParmTypeLoc TL + = TLB.push(T); + TL.setNameLoc(IdentifierLoc); + } else if (isa(T)) { + SubstTemplateTypeParmPackTypeLoc TL + = TLB.push(T); + TL.setNameLoc(IdentifierLoc); + } else { + llvm_unreachable("Unhandled TypeDecl node in nested-name-specifier"); + } + + if (T->isEnumeralType()) + Diag(IdentifierLoc, diag::warn_cxx98_compat_enum_nested_name_spec); + + SS.Extend(Context, SourceLocation(), TLB.getTypeLocInContext(Context, T), + CCLoc); + return false; + } + + // Otherwise, we have an error case. If we don't want diagnostics, just + // return an error now. + if (ErrorRecoveryLookup) + return true; + + // If we didn't find anything during our lookup, try again with + // ordinary name lookup, which can help us produce better error + // messages. + if (Found.empty()) { + Found.clear(LookupOrdinaryName); + LookupName(Found, S); + } + + // In Microsoft mode, if we are within a templated function and we can't + // resolve Identifier, then extend the SS with Identifier. This will have + // the effect of resolving Identifier during template instantiation. + // The goal is to be able to resolve a function call whose + // nested-name-specifier is located inside a dependent base class. + // Example: + // + // class C { + // public: + // static void foo2() { } + // }; + // template class A { public: typedef C D; }; + // + // template class B : public A { + // public: + // void foo() { D::foo2(); } + // }; + if (getLangOpts().MicrosoftExt) { + DeclContext *DC = LookupCtx ? LookupCtx : CurContext; + if (DC->isDependentContext() && DC->isFunctionOrMethod()) { + SS.Extend(Context, &Identifier, IdentifierLoc, CCLoc); + return false; + } + } + + unsigned DiagID; + if (!Found.empty()) + DiagID = diag::err_expected_class_or_namespace; + else if (SS.isSet()) { + Diag(IdentifierLoc, diag::err_no_member) + << &Identifier << LookupCtx << SS.getRange(); + return true; + } else + DiagID = diag::err_undeclared_var_use; + + if (SS.isSet()) + Diag(IdentifierLoc, DiagID) << &Identifier << SS.getRange(); + else + Diag(IdentifierLoc, DiagID) << &Identifier; + + return true; +} + +bool Sema::ActOnCXXNestedNameSpecifier(Scope *S, + IdentifierInfo &Identifier, + SourceLocation IdentifierLoc, + SourceLocation CCLoc, + ParsedType ObjectType, + bool EnteringContext, + CXXScopeSpec &SS) { + if (SS.isInvalid()) + return true; + + return BuildCXXNestedNameSpecifier(S, Identifier, IdentifierLoc, CCLoc, + GetTypeFromParser(ObjectType), + EnteringContext, SS, + /*ScopeLookupResult=*/0, false); +} + +bool Sema::ActOnCXXNestedNameSpecifierDecltype(CXXScopeSpec &SS, + const DeclSpec &DS, + SourceLocation ColonColonLoc) { + if (SS.isInvalid() || DS.getTypeSpecType() == DeclSpec::TST_error) + return true; + + assert(DS.getTypeSpecType() == DeclSpec::TST_decltype); + + QualType T = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc()); + if (!T->isDependentType() && !T->getAs()) { + Diag(DS.getTypeSpecTypeLoc(), diag::err_expected_class) + << T << getLangOpts().CPlusPlus; + return true; + } + + TypeLocBuilder TLB; + DecltypeTypeLoc DecltypeTL = TLB.push(T); + DecltypeTL.setNameLoc(DS.getTypeSpecTypeLoc()); + SS.Extend(Context, SourceLocation(), TLB.getTypeLocInContext(Context, T), + ColonColonLoc); + return false; +} + +/// IsInvalidUnlessNestedName - This method is used for error recovery +/// purposes to determine whether the specified identifier is only valid as +/// a nested name specifier, for example a namespace name. It is +/// conservatively correct to always return false from this method. +/// +/// The arguments are the same as those passed to ActOnCXXNestedNameSpecifier. +bool Sema::IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS, + IdentifierInfo &Identifier, + SourceLocation IdentifierLoc, + SourceLocation ColonLoc, + ParsedType ObjectType, + bool EnteringContext) { + if (SS.isInvalid()) + return false; + + return !BuildCXXNestedNameSpecifier(S, Identifier, IdentifierLoc, ColonLoc, + GetTypeFromParser(ObjectType), + EnteringContext, SS, + /*ScopeLookupResult=*/0, true); +} + +bool Sema::ActOnCXXNestedNameSpecifier(Scope *S, + CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, + TemplateTy Template, + SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, + ASTTemplateArgsPtr TemplateArgsIn, + SourceLocation RAngleLoc, + SourceLocation CCLoc, + bool EnteringContext) { + if (SS.isInvalid()) + return true; + + // Translate the parser's template argument list in our AST format. + TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc); + translateTemplateArguments(TemplateArgsIn, TemplateArgs); + + if (DependentTemplateName *DTN = Template.get().getAsDependentTemplateName()){ + // Handle a dependent template specialization for which we cannot resolve + // the template name. + assert(DTN->getQualifier() + == static_cast(SS.getScopeRep())); + QualType T = Context.getDependentTemplateSpecializationType(ETK_None, + DTN->getQualifier(), + DTN->getIdentifier(), + TemplateArgs); + + // Create source-location information for this type. + TypeLocBuilder Builder; + DependentTemplateSpecializationTypeLoc SpecTL + = Builder.push(T); + SpecTL.setElaboratedKeywordLoc(SourceLocation()); + SpecTL.setQualifierLoc(SS.getWithLocInContext(Context)); + SpecTL.setTemplateKeywordLoc(TemplateKWLoc); + SpecTL.setTemplateNameLoc(TemplateNameLoc); + SpecTL.setLAngleLoc(LAngleLoc); + SpecTL.setRAngleLoc(RAngleLoc); + for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) + SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo()); + + SS.Extend(Context, TemplateKWLoc, Builder.getTypeLocInContext(Context, T), + CCLoc); + return false; + } + + + if (Template.get().getAsOverloadedTemplate() || + isa(Template.get().getAsTemplateDecl())) { + SourceRange R(TemplateNameLoc, RAngleLoc); + if (SS.getRange().isValid()) + R.setBegin(SS.getRange().getBegin()); + + Diag(CCLoc, diag::err_non_type_template_in_nested_name_specifier) + << Template.get() << R; + NoteAllFoundTemplates(Template.get()); + return true; + } + + // We were able to resolve the template name to an actual template. + // Build an appropriate nested-name-specifier. + QualType T = CheckTemplateIdType(Template.get(), TemplateNameLoc, + TemplateArgs); + if (T.isNull()) + return true; + + // Alias template specializations can produce types which are not valid + // nested name specifiers. + if (!T->isDependentType() && !T->getAs()) { + Diag(TemplateNameLoc, diag::err_nested_name_spec_non_tag) << T; + NoteAllFoundTemplates(Template.get()); + return true; + } + + // Provide source-location information for the template specialization type. + TypeLocBuilder Builder; + TemplateSpecializationTypeLoc SpecTL + = Builder.push(T); + SpecTL.setTemplateKeywordLoc(TemplateKWLoc); + SpecTL.setTemplateNameLoc(TemplateNameLoc); + SpecTL.setLAngleLoc(LAngleLoc); + SpecTL.setRAngleLoc(RAngleLoc); + for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) + SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo()); + + + SS.Extend(Context, TemplateKWLoc, Builder.getTypeLocInContext(Context, T), + CCLoc); + return false; +} + +namespace { + /// \brief A structure that stores a nested-name-specifier annotation, + /// including both the nested-name-specifier + struct NestedNameSpecifierAnnotation { + NestedNameSpecifier *NNS; + }; +} + +void *Sema::SaveNestedNameSpecifierAnnotation(CXXScopeSpec &SS) { + if (SS.isEmpty() || SS.isInvalid()) + return 0; + + void *Mem = Context.Allocate((sizeof(NestedNameSpecifierAnnotation) + + SS.location_size()), + llvm::alignOf()); + NestedNameSpecifierAnnotation *Annotation + = new (Mem) NestedNameSpecifierAnnotation; + Annotation->NNS = SS.getScopeRep(); + memcpy(Annotation + 1, SS.location_data(), SS.location_size()); + return Annotation; +} + +void Sema::RestoreNestedNameSpecifierAnnotation(void *AnnotationPtr, + SourceRange AnnotationRange, + CXXScopeSpec &SS) { + if (!AnnotationPtr) { + SS.SetInvalid(AnnotationRange); + return; + } + + NestedNameSpecifierAnnotation *Annotation + = static_cast(AnnotationPtr); + SS.Adopt(NestedNameSpecifierLoc(Annotation->NNS, Annotation + 1)); +} + +bool Sema::ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) { + assert(SS.isSet() && "Parser passed invalid CXXScopeSpec."); + + NestedNameSpecifier *Qualifier = + static_cast(SS.getScopeRep()); + + // There are only two places a well-formed program may qualify a + // declarator: first, when defining a namespace or class member + // out-of-line, and second, when naming an explicitly-qualified + // friend function. The latter case is governed by + // C++03 [basic.lookup.unqual]p10: + // In a friend declaration naming a member function, a name used + // in the function declarator and not part of a template-argument + // in a template-id is first looked up in the scope of the member + // function's class. If it is not found, or if the name is part of + // a template-argument in a template-id, the look up is as + // described for unqualified names in the definition of the class + // granting friendship. + // i.e. we don't push a scope unless it's a class member. + + switch (Qualifier->getKind()) { + case NestedNameSpecifier::Global: + case NestedNameSpecifier::Namespace: + case NestedNameSpecifier::NamespaceAlias: + // These are always namespace scopes. We never want to enter a + // namespace scope from anything but a file context. + return CurContext->getRedeclContext()->isFileContext(); + + case NestedNameSpecifier::Identifier: + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: + // These are never namespace scopes. + return true; + } + + llvm_unreachable("Invalid NestedNameSpecifier::Kind!"); +} + +/// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global +/// scope or nested-name-specifier) is parsed, part of a declarator-id. +/// After this method is called, according to [C++ 3.4.3p3], names should be +/// looked up in the declarator-id's scope, until the declarator is parsed and +/// ActOnCXXExitDeclaratorScope is called. +/// The 'SS' should be a non-empty valid CXXScopeSpec. +bool Sema::ActOnCXXEnterDeclaratorScope(Scope *S, CXXScopeSpec &SS) { + assert(SS.isSet() && "Parser passed invalid CXXScopeSpec."); + + if (SS.isInvalid()) return true; + + DeclContext *DC = computeDeclContext(SS, true); + if (!DC) return true; + + // Before we enter a declarator's context, we need to make sure that + // it is a complete declaration context. + if (!DC->isDependentContext() && RequireCompleteDeclContext(SS, DC)) + return true; + + EnterDeclaratorContext(S, DC); + + // Rebuild the nested name specifier for the new scope. + if (DC->isDependentContext()) + RebuildNestedNameSpecifierInCurrentInstantiation(SS); + + return false; +} + +/// ActOnCXXExitDeclaratorScope - Called when a declarator that previously +/// invoked ActOnCXXEnterDeclaratorScope(), is finished. 'SS' is the same +/// CXXScopeSpec that was passed to ActOnCXXEnterDeclaratorScope as well. +/// Used to indicate that names should revert to being looked up in the +/// defining scope. +void Sema::ActOnCXXExitDeclaratorScope(Scope *S, const CXXScopeSpec &SS) { + assert(SS.isSet() && "Parser passed invalid CXXScopeSpec."); + if (SS.isInvalid()) + return; + assert(!SS.isInvalid() && computeDeclContext(SS, true) && + "exiting declarator scope we never really entered"); + ExitDeclaratorContext(S); +} diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp new file mode 100644 index 0000000..54683e1 --- /dev/null +++ b/clang/lib/Sema/SemaCast.cpp @@ -0,0 +1,2112 @@ +//===--- SemaCast.cpp - Semantic Analysis for Casts -----------------------===// +// +// 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 cast expressions, including +// 1) C-style casts like '(int) x' +// 2) C++ functional casts like 'int(x)' +// 3) C++ named casts like 'static_cast(x)' +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/Initialization.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprObjC.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/CXXInheritance.h" +#include "clang/Basic/PartialDiagnostic.h" +#include "llvm/ADT/SmallVector.h" +#include +using namespace clang; + + + +enum TryCastResult { + TC_NotApplicable, ///< The cast method is not applicable. + TC_Success, ///< The cast method is appropriate and successful. + TC_Failed ///< The cast method is appropriate, but failed. A + ///< diagnostic has been emitted. +}; + +enum CastType { + CT_Const, ///< const_cast + CT_Static, ///< static_cast + CT_Reinterpret, ///< reinterpret_cast + CT_Dynamic, ///< dynamic_cast + CT_CStyle, ///< (Type)expr + CT_Functional ///< Type(expr) +}; + +namespace { + struct CastOperation { + CastOperation(Sema &S, QualType destType, ExprResult src) + : Self(S), SrcExpr(src), DestType(destType), + ResultType(destType.getNonLValueExprType(S.Context)), + ValueKind(Expr::getValueKindForType(destType)), + Kind(CK_Dependent), IsARCUnbridgedCast(false) { + + if (const BuiltinType *placeholder = + src.get()->getType()->getAsPlaceholderType()) { + PlaceholderKind = placeholder->getKind(); + } else { + PlaceholderKind = (BuiltinType::Kind) 0; + } + } + + Sema &Self; + ExprResult SrcExpr; + QualType DestType; + QualType ResultType; + ExprValueKind ValueKind; + CastKind Kind; + BuiltinType::Kind PlaceholderKind; + CXXCastPath BasePath; + bool IsARCUnbridgedCast; + + SourceRange OpRange; + SourceRange DestRange; + + // Top-level semantics-checking routines. + void CheckConstCast(); + void CheckReinterpretCast(); + void CheckStaticCast(); + void CheckDynamicCast(); + void CheckCXXCStyleCast(bool FunctionalCast, bool ListInitialization); + void CheckCStyleCast(); + + /// Complete an apparently-successful cast operation that yields + /// the given expression. + ExprResult complete(CastExpr *castExpr) { + // If this is an unbridged cast, wrap the result in an implicit + // cast that yields the unbridged-cast placeholder type. + if (IsARCUnbridgedCast) { + castExpr = ImplicitCastExpr::Create(Self.Context, + Self.Context.ARCUnbridgedCastTy, + CK_Dependent, castExpr, 0, + castExpr->getValueKind()); + } + return Self.Owned(castExpr); + } + + // Internal convenience methods. + + /// Try to handle the given placeholder expression kind. Return + /// true if the source expression has the appropriate placeholder + /// kind. A placeholder can only be claimed once. + bool claimPlaceholder(BuiltinType::Kind K) { + if (PlaceholderKind != K) return false; + + PlaceholderKind = (BuiltinType::Kind) 0; + return true; + } + + bool isPlaceholder() const { + return PlaceholderKind != 0; + } + bool isPlaceholder(BuiltinType::Kind K) const { + return PlaceholderKind == K; + } + + void checkCastAlign() { + Self.CheckCastAlign(SrcExpr.get(), DestType, OpRange); + } + + void checkObjCARCConversion(Sema::CheckedConversionKind CCK) { + assert(Self.getLangOpts().ObjCAutoRefCount); + + Expr *src = SrcExpr.get(); + if (Self.CheckObjCARCConversion(OpRange, DestType, src, CCK) == + Sema::ACR_unbridged) + IsARCUnbridgedCast = true; + SrcExpr = src; + } + + /// Check for and handle non-overload placeholder expressions. + void checkNonOverloadPlaceholders() { + if (!isPlaceholder() || isPlaceholder(BuiltinType::Overload)) + return; + + SrcExpr = Self.CheckPlaceholderExpr(SrcExpr.take()); + if (SrcExpr.isInvalid()) + return; + PlaceholderKind = (BuiltinType::Kind) 0; + } + }; +} + +static bool CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType, + bool CheckCVR, bool CheckObjCLifetime); + +// The Try functions attempt a specific way of casting. If they succeed, they +// return TC_Success. If their way of casting is not appropriate for the given +// arguments, they return TC_NotApplicable and *may* set diag to a diagnostic +// to emit if no other way succeeds. If their way of casting is appropriate but +// fails, they return TC_Failed and *must* set diag; they can set it to 0 if +// they emit a specialized diagnostic. +// All diagnostics returned by these functions must expect the same three +// arguments: +// %0: Cast Type (a value from the CastType enumeration) +// %1: Source Type +// %2: Destination Type +static TryCastResult TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, + QualType DestType, bool CStyle, + CastKind &Kind, + CXXCastPath &BasePath, + unsigned &msg); +static TryCastResult TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr, + QualType DestType, bool CStyle, + const SourceRange &OpRange, + unsigned &msg, + CastKind &Kind, + CXXCastPath &BasePath); +static TryCastResult TryStaticPointerDowncast(Sema &Self, QualType SrcType, + QualType DestType, bool CStyle, + const SourceRange &OpRange, + unsigned &msg, + CastKind &Kind, + CXXCastPath &BasePath); +static TryCastResult TryStaticDowncast(Sema &Self, CanQualType SrcType, + CanQualType DestType, bool CStyle, + const SourceRange &OpRange, + QualType OrigSrcType, + QualType OrigDestType, unsigned &msg, + CastKind &Kind, + CXXCastPath &BasePath); +static TryCastResult TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, + QualType SrcType, + QualType DestType,bool CStyle, + const SourceRange &OpRange, + unsigned &msg, + CastKind &Kind, + CXXCastPath &BasePath); + +static TryCastResult TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, + QualType DestType, + Sema::CheckedConversionKind CCK, + const SourceRange &OpRange, + unsigned &msg, CastKind &Kind, + bool ListInitialization); +static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr, + QualType DestType, + Sema::CheckedConversionKind CCK, + const SourceRange &OpRange, + unsigned &msg, CastKind &Kind, + CXXCastPath &BasePath, + bool ListInitialization); +static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType, + bool CStyle, unsigned &msg); +static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, + QualType DestType, bool CStyle, + const SourceRange &OpRange, + unsigned &msg, + CastKind &Kind); + + +/// ActOnCXXNamedCast - Parse {dynamic,static,reinterpret,const}_cast's. +ExprResult +Sema::ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, + SourceLocation LAngleBracketLoc, Declarator &D, + SourceLocation RAngleBracketLoc, + SourceLocation LParenLoc, Expr *E, + SourceLocation RParenLoc) { + + assert(!D.isInvalidType()); + + TypeSourceInfo *TInfo = GetTypeForDeclaratorCast(D, E->getType()); + if (D.isInvalidType()) + return ExprError(); + + if (getLangOpts().CPlusPlus) { + // Check that there are no default arguments (C++ only). + CheckExtraCXXDefaultArguments(D); + } + + return BuildCXXNamedCast(OpLoc, Kind, TInfo, move(E), + SourceRange(LAngleBracketLoc, RAngleBracketLoc), + SourceRange(LParenLoc, RParenLoc)); +} + +ExprResult +Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, + TypeSourceInfo *DestTInfo, Expr *E, + SourceRange AngleBrackets, SourceRange Parens) { + ExprResult Ex = Owned(E); + QualType DestType = DestTInfo->getType(); + + // If the type is dependent, we won't do the semantic analysis now. + // FIXME: should we check this in a more fine-grained manner? + bool TypeDependent = DestType->isDependentType() || Ex.get()->isTypeDependent(); + + CastOperation Op(*this, DestType, E); + Op.OpRange = SourceRange(OpLoc, Parens.getEnd()); + Op.DestRange = AngleBrackets; + + switch (Kind) { + default: llvm_unreachable("Unknown C++ cast!"); + + case tok::kw_const_cast: + if (!TypeDependent) { + Op.CheckConstCast(); + if (Op.SrcExpr.isInvalid()) + return ExprError(); + } + return Op.complete(CXXConstCastExpr::Create(Context, Op.ResultType, + Op.ValueKind, Op.SrcExpr.take(), DestTInfo, + OpLoc, Parens.getEnd())); + + case tok::kw_dynamic_cast: { + if (!TypeDependent) { + Op.CheckDynamicCast(); + if (Op.SrcExpr.isInvalid()) + return ExprError(); + } + return Op.complete(CXXDynamicCastExpr::Create(Context, Op.ResultType, + Op.ValueKind, Op.Kind, Op.SrcExpr.take(), + &Op.BasePath, DestTInfo, + OpLoc, Parens.getEnd())); + } + case tok::kw_reinterpret_cast: { + if (!TypeDependent) { + Op.CheckReinterpretCast(); + if (Op.SrcExpr.isInvalid()) + return ExprError(); + } + return Op.complete(CXXReinterpretCastExpr::Create(Context, Op.ResultType, + Op.ValueKind, Op.Kind, Op.SrcExpr.take(), + 0, DestTInfo, OpLoc, + Parens.getEnd())); + } + case tok::kw_static_cast: { + if (!TypeDependent) { + Op.CheckStaticCast(); + if (Op.SrcExpr.isInvalid()) + return ExprError(); + } + + return Op.complete(CXXStaticCastExpr::Create(Context, Op.ResultType, + Op.ValueKind, Op.Kind, Op.SrcExpr.take(), + &Op.BasePath, DestTInfo, + OpLoc, Parens.getEnd())); + } + } +} + +/// Try to diagnose a failed overloaded cast. Returns true if +/// diagnostics were emitted. +static bool tryDiagnoseOverloadedCast(Sema &S, CastType CT, + SourceRange range, Expr *src, + QualType destType, + bool listInitialization) { + switch (CT) { + // These cast kinds don't consider user-defined conversions. + case CT_Const: + case CT_Reinterpret: + case CT_Dynamic: + return false; + + // These do. + case CT_Static: + case CT_CStyle: + case CT_Functional: + break; + } + + QualType srcType = src->getType(); + if (!destType->isRecordType() && !srcType->isRecordType()) + return false; + + InitializedEntity entity = InitializedEntity::InitializeTemporary(destType); + InitializationKind initKind + = (CT == CT_CStyle)? InitializationKind::CreateCStyleCast(range.getBegin(), + range, listInitialization) + : (CT == CT_Functional)? InitializationKind::CreateFunctionalCast(range, + listInitialization) + : InitializationKind::CreateCast(/*type range?*/ range); + InitializationSequence sequence(S, entity, initKind, &src, 1); + + assert(sequence.Failed() && "initialization succeeded on second try?"); + switch (sequence.getFailureKind()) { + default: return false; + + case InitializationSequence::FK_ConstructorOverloadFailed: + case InitializationSequence::FK_UserConversionOverloadFailed: + break; + } + + OverloadCandidateSet &candidates = sequence.getFailedCandidateSet(); + + unsigned msg = 0; + OverloadCandidateDisplayKind howManyCandidates = OCD_AllCandidates; + + switch (sequence.getFailedOverloadResult()) { + case OR_Success: llvm_unreachable("successful failed overload"); + case OR_No_Viable_Function: + if (candidates.empty()) + msg = diag::err_ovl_no_conversion_in_cast; + else + msg = diag::err_ovl_no_viable_conversion_in_cast; + howManyCandidates = OCD_AllCandidates; + break; + + case OR_Ambiguous: + msg = diag::err_ovl_ambiguous_conversion_in_cast; + howManyCandidates = OCD_ViableCandidates; + break; + + case OR_Deleted: + msg = diag::err_ovl_deleted_conversion_in_cast; + howManyCandidates = OCD_ViableCandidates; + break; + } + + S.Diag(range.getBegin(), msg) + << CT << srcType << destType + << range << src->getSourceRange(); + + candidates.NoteCandidates(S, howManyCandidates, src); + + return true; +} + +/// Diagnose a failed cast. +static void diagnoseBadCast(Sema &S, unsigned msg, CastType castType, + SourceRange opRange, Expr *src, QualType destType, + bool listInitialization) { + if (src->getType() == S.Context.BoundMemberTy) { + (void) S.CheckPlaceholderExpr(src); // will always fail + return; + } + + if (msg == diag::err_bad_cxx_cast_generic && + tryDiagnoseOverloadedCast(S, castType, opRange, src, destType, + listInitialization)) + return; + + S.Diag(opRange.getBegin(), msg) << castType + << src->getType() << destType << opRange << src->getSourceRange(); +} + +/// UnwrapDissimilarPointerTypes - Like Sema::UnwrapSimilarPointerTypes, +/// this removes one level of indirection from both types, provided that they're +/// 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. +static bool UnwrapDissimilarPointerTypes(QualType& T1, QualType& T2) { + const PointerType *T1PtrType = T1->getAs(), + *T2PtrType = T2->getAs(); + if (T1PtrType && T2PtrType) { + T1 = T1PtrType->getPointeeType(); + T2 = T2PtrType->getPointeeType(); + return true; + } + const ObjCObjectPointerType *T1ObjCPtrType = + T1->getAs(), + *T2ObjCPtrType = + T2->getAs(); + if (T1ObjCPtrType) { + if (T2ObjCPtrType) { + T1 = T1ObjCPtrType->getPointeeType(); + T2 = T2ObjCPtrType->getPointeeType(); + return true; + } + else if (T2PtrType) { + T1 = T1ObjCPtrType->getPointeeType(); + T2 = T2PtrType->getPointeeType(); + return true; + } + } + else if (T2ObjCPtrType) { + if (T1PtrType) { + T2 = T2ObjCPtrType->getPointeeType(); + T1 = T1PtrType->getPointeeType(); + return true; + } + } + + const MemberPointerType *T1MPType = T1->getAs(), + *T2MPType = T2->getAs(); + if (T1MPType && T2MPType) { + T1 = T1MPType->getPointeeType(); + T2 = T2MPType->getPointeeType(); + return true; + } + + const BlockPointerType *T1BPType = T1->getAs(), + *T2BPType = T2->getAs(); + if (T1BPType && T2BPType) { + T1 = T1BPType->getPointeeType(); + T2 = T2BPType->getPointeeType(); + return true; + } + + return false; +} + +/// CastsAwayConstness - Check if the pointer conversion from SrcType to +/// DestType casts away constness as defined in C++ 5.2.11p8ff. This is used by +/// the cast checkers. Both arguments must denote pointer (possibly to member) +/// types. +/// +/// \param CheckCVR Whether to check for const/volatile/restrict qualifiers. +/// +/// \param CheckObjCLifetime Whether to check Objective-C lifetime qualifiers. +static bool +CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType, + bool CheckCVR, bool CheckObjCLifetime) { + // If the only checking we care about is for Objective-C lifetime qualifiers, + // and we're not in ARC mode, there's nothing to check. + if (!CheckCVR && CheckObjCLifetime && + !Self.Context.getLangOpts().ObjCAutoRefCount) + return false; + + // Casting away constness is defined in C++ 5.2.11p8 with reference to + // C++ 4.4. We piggyback on Sema::IsQualificationConversion for this, since + // the rules are non-trivial. So first we construct Tcv *...cv* as described + // in C++ 5.2.11p8. + assert((SrcType->isAnyPointerType() || SrcType->isMemberPointerType() || + SrcType->isBlockPointerType()) && + "Source type is not pointer or pointer to member."); + assert((DestType->isAnyPointerType() || DestType->isMemberPointerType() || + DestType->isBlockPointerType()) && + "Destination type is not pointer or pointer to member."); + + QualType UnwrappedSrcType = Self.Context.getCanonicalType(SrcType), + UnwrappedDestType = Self.Context.getCanonicalType(DestType); + SmallVector cv1, cv2; + + // Find the qualifiers. We only care about cvr-qualifiers for the + // purpose of this check, because other qualifiers (address spaces, + // Objective-C GC, etc.) are part of the type's identity. + while (UnwrapDissimilarPointerTypes(UnwrappedSrcType, UnwrappedDestType)) { + // Determine the relevant qualifiers at this level. + Qualifiers SrcQuals, DestQuals; + Self.Context.getUnqualifiedArrayType(UnwrappedSrcType, SrcQuals); + Self.Context.getUnqualifiedArrayType(UnwrappedDestType, DestQuals); + + Qualifiers RetainedSrcQuals, RetainedDestQuals; + if (CheckCVR) { + RetainedSrcQuals.setCVRQualifiers(SrcQuals.getCVRQualifiers()); + RetainedDestQuals.setCVRQualifiers(DestQuals.getCVRQualifiers()); + } + + if (CheckObjCLifetime && + !DestQuals.compatiblyIncludesObjCLifetime(SrcQuals)) + return true; + + cv1.push_back(RetainedSrcQuals); + cv2.push_back(RetainedDestQuals); + } + if (cv1.empty()) + return false; + + // Construct void pointers with those qualifiers (in reverse order of + // unwrapping, of course). + QualType SrcConstruct = Self.Context.VoidTy; + QualType DestConstruct = Self.Context.VoidTy; + ASTContext &Context = Self.Context; + for (SmallVector::reverse_iterator i1 = cv1.rbegin(), + i2 = cv2.rbegin(); + i1 != cv1.rend(); ++i1, ++i2) { + SrcConstruct + = Context.getPointerType(Context.getQualifiedType(SrcConstruct, *i1)); + DestConstruct + = Context.getPointerType(Context.getQualifiedType(DestConstruct, *i2)); + } + + // Test if they're compatible. + bool ObjCLifetimeConversion; + return SrcConstruct != DestConstruct && + !Self.IsQualificationConversion(SrcConstruct, DestConstruct, false, + ObjCLifetimeConversion); +} + +/// CheckDynamicCast - Check that a dynamic_cast\(SrcExpr) is valid. +/// Refer to C++ 5.2.7 for details. Dynamic casts are used mostly for runtime- +/// checked downcasts in class hierarchies. +void CastOperation::CheckDynamicCast() { + if (ValueKind == VK_RValue) + SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take()); + else if (isPlaceholder()) + SrcExpr = Self.CheckPlaceholderExpr(SrcExpr.take()); + if (SrcExpr.isInvalid()) // if conversion failed, don't report another error + return; + + QualType OrigSrcType = SrcExpr.get()->getType(); + QualType DestType = Self.Context.getCanonicalType(this->DestType); + + // C++ 5.2.7p1: T shall be a pointer or reference to a complete class type, + // or "pointer to cv void". + + QualType DestPointee; + const PointerType *DestPointer = DestType->getAs(); + const ReferenceType *DestReference = 0; + if (DestPointer) { + DestPointee = DestPointer->getPointeeType(); + } else if ((DestReference = DestType->getAs())) { + DestPointee = DestReference->getPointeeType(); + } else { + Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_ref_or_ptr) + << this->DestType << DestRange; + return; + } + + const RecordType *DestRecord = DestPointee->getAs(); + if (DestPointee->isVoidType()) { + assert(DestPointer && "Reference to void is not possible"); + } else if (DestRecord) { + if (Self.RequireCompleteType(OpRange.getBegin(), DestPointee, + Self.PDiag(diag::err_bad_dynamic_cast_incomplete) + << DestRange)) + return; + } else { + Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_class) + << DestPointee.getUnqualifiedType() << DestRange; + return; + } + + // C++0x 5.2.7p2: If T is a pointer type, v shall be an rvalue of a pointer to + // complete class type, [...]. If T is an lvalue reference type, v shall be + // an lvalue of a complete class type, [...]. If T is an rvalue reference + // type, v shall be an expression having a complete class type, [...] + QualType SrcType = Self.Context.getCanonicalType(OrigSrcType); + QualType SrcPointee; + if (DestPointer) { + if (const PointerType *SrcPointer = SrcType->getAs()) { + SrcPointee = SrcPointer->getPointeeType(); + } else { + Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_ptr) + << OrigSrcType << SrcExpr.get()->getSourceRange(); + return; + } + } else if (DestReference->isLValueReferenceType()) { + if (!SrcExpr.get()->isLValue()) { + Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_rvalue) + << CT_Dynamic << OrigSrcType << this->DestType << OpRange; + } + SrcPointee = SrcType; + } else { + SrcPointee = SrcType; + } + + const RecordType *SrcRecord = SrcPointee->getAs(); + if (SrcRecord) { + if (Self.RequireCompleteType(OpRange.getBegin(), SrcPointee, + Self.PDiag(diag::err_bad_dynamic_cast_incomplete) + << SrcExpr.get()->getSourceRange())) + return; + } else { + Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_class) + << SrcPointee.getUnqualifiedType() << SrcExpr.get()->getSourceRange(); + return; + } + + assert((DestPointer || DestReference) && + "Bad destination non-ptr/ref slipped through."); + assert((DestRecord || DestPointee->isVoidType()) && + "Bad destination pointee slipped through."); + assert(SrcRecord && "Bad source pointee slipped through."); + + // C++ 5.2.7p1: The dynamic_cast operator shall not cast away constness. + if (!DestPointee.isAtLeastAsQualifiedAs(SrcPointee)) { + Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_qualifiers_away) + << CT_Dynamic << OrigSrcType << this->DestType << OpRange; + return; + } + + // 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; + } + + // C++ 5.2.7p5 + // Upcasts are resolved statically. + if (DestRecord && Self.IsDerivedFrom(SrcPointee, DestPointee)) { + if (Self.CheckDerivedToBaseConversion(SrcPointee, DestPointee, + OpRange.getBegin(), OpRange, + &BasePath)) + return; + + Kind = CK_DerivedToBase; + + // If we are casting to or through a virtual base class, we need a + // vtable. + if (Self.BasePathInvolvesVirtualBase(BasePath)) + Self.MarkVTableUsed(OpRange.getBegin(), + cast(SrcRecord->getDecl())); + return; + } + + // C++ 5.2.7p6: Otherwise, v shall be [polymorphic]. + const RecordDecl *SrcDecl = SrcRecord->getDecl()->getDefinition(); + assert(SrcDecl && "Definition missing"); + if (!cast(SrcDecl)->isPolymorphic()) { + Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_polymorphic) + << SrcPointee.getUnqualifiedType() << SrcExpr.get()->getSourceRange(); + } + Self.MarkVTableUsed(OpRange.getBegin(), + cast(SrcRecord->getDecl())); + + // Done. Everything else is run-time checks. + Kind = CK_Dynamic; +} + +/// CheckConstCast - Check that a const_cast\(SrcExpr) is valid. +/// Refer to C++ 5.2.11 for details. const_cast is typically used in code +/// like this: +/// const char *str = "literal"; +/// legacy_function(const_cast\(str)); +void CastOperation::CheckConstCast() { + if (ValueKind == VK_RValue) + SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take()); + else if (isPlaceholder()) + SrcExpr = Self.CheckPlaceholderExpr(SrcExpr.take()); + if (SrcExpr.isInvalid()) // if conversion failed, don't report another error + return; + + unsigned msg = diag::err_bad_cxx_cast_generic; + if (TryConstCast(Self, SrcExpr.get(), DestType, /*CStyle*/false, msg) != TC_Success + && msg != 0) + Self.Diag(OpRange.getBegin(), msg) << CT_Const + << SrcExpr.get()->getType() << DestType << OpRange; +} + +/// CheckReinterpretCast - Check that a reinterpret_cast\(SrcExpr) is +/// valid. +/// Refer to C++ 5.2.10 for details. reinterpret_cast is typically used in code +/// like this: +/// char *bytes = reinterpret_cast\(int_ptr); +void CastOperation::CheckReinterpretCast() { + if (ValueKind == VK_RValue && !isPlaceholder(BuiltinType::Overload)) + SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take()); + else + checkNonOverloadPlaceholders(); + if (SrcExpr.isInvalid()) // if conversion failed, don't report another error + return; + + unsigned msg = diag::err_bad_cxx_cast_generic; + TryCastResult tcr = + TryReinterpretCast(Self, SrcExpr, DestType, + /*CStyle*/false, OpRange, msg, Kind); + if (tcr != TC_Success && msg != 0) + { + if (SrcExpr.isInvalid()) // if conversion failed, don't report another error + return; + if (SrcExpr.get()->getType() == Self.Context.OverloadTy) { + //FIXME: &f; is overloaded and resolvable + Self.Diag(OpRange.getBegin(), diag::err_bad_reinterpret_cast_overload) + << OverloadExpr::find(SrcExpr.get()).Expression->getName() + << DestType << OpRange; + Self.NoteAllOverloadCandidates(SrcExpr.get()); + + } else { + diagnoseBadCast(Self, msg, CT_Reinterpret, OpRange, SrcExpr.get(), + DestType, /*listInitialization=*/false); + } + } else if (tcr == TC_Success && Self.getLangOpts().ObjCAutoRefCount) { + checkObjCARCConversion(Sema::CCK_OtherCast); + } +} + + +/// CheckStaticCast - Check that a static_cast\(SrcExpr) is valid. +/// Refer to C++ 5.2.9 for details. Static casts are mostly used for making +/// implicit conversions explicit and getting rid of data loss warnings. +void CastOperation::CheckStaticCast() { + if (isPlaceholder()) { + checkNonOverloadPlaceholders(); + if (SrcExpr.isInvalid()) + return; + } + + // 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 = CK_ToVoid; + + if (claimPlaceholder(BuiltinType::Overload)) { + Self.ResolveAndFixSingleFunctionTemplateSpecialization(SrcExpr, + false, // Decay Function to ptr + true, // Complain + OpRange, DestType, diag::err_bad_static_cast_overload); + if (SrcExpr.isInvalid()) + return; + } + + SrcExpr = Self.IgnoredValueConversions(SrcExpr.take()); + return; + } + + if (ValueKind == VK_RValue && !DestType->isRecordType() && + !isPlaceholder(BuiltinType::Overload)) { + SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take()); + if (SrcExpr.isInvalid()) // if conversion failed, don't report another error + return; + } + + unsigned msg = diag::err_bad_cxx_cast_generic; + TryCastResult tcr + = TryStaticCast(Self, SrcExpr, DestType, Sema::CCK_OtherCast, OpRange, msg, + Kind, BasePath, /*ListInitialization=*/false); + if (tcr != TC_Success && msg != 0) { + if (SrcExpr.isInvalid()) + return; + if (SrcExpr.get()->getType() == Self.Context.OverloadTy) { + OverloadExpr* oe = OverloadExpr::find(SrcExpr.get()).Expression; + Self.Diag(OpRange.getBegin(), diag::err_bad_static_cast_overload) + << oe->getName() << DestType << OpRange + << oe->getQualifierLoc().getSourceRange(); + Self.NoteAllOverloadCandidates(SrcExpr.get()); + } else { + diagnoseBadCast(Self, msg, CT_Static, OpRange, SrcExpr.get(), DestType, + /*listInitialization=*/false); + } + } else if (tcr == TC_Success) { + if (Kind == CK_BitCast) + checkCastAlign(); + if (Self.getLangOpts().ObjCAutoRefCount) + checkObjCARCConversion(Sema::CCK_OtherCast); + } else if (Kind == CK_BitCast) { + checkCastAlign(); + } +} + +/// TryStaticCast - Check if a static cast can be performed, and do so if +/// possible. If @p CStyle, ignore access restrictions on hierarchy casting +/// and casting away constness. +static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr, + QualType DestType, + Sema::CheckedConversionKind CCK, + const SourceRange &OpRange, unsigned &msg, + CastKind &Kind, CXXCastPath &BasePath, + bool ListInitialization) { + // Determine whether we have the semantics of a C-style cast. + bool CStyle + = (CCK == Sema::CCK_CStyleCast || CCK == Sema::CCK_FunctionalCast); + + // The order the tests is not entirely arbitrary. There is one conversion + // that can be handled in two different ways. Given: + // struct A {}; + // struct B : public A { + // B(); B(const A&); + // }; + // const A &a = B(); + // the cast static_cast(a) could be seen as either a static + // reference downcast, or an explicit invocation of the user-defined + // conversion using B's conversion constructor. + // DR 427 specifies that the downcast is to be applied here. + + // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void". + // Done outside this function. + + TryCastResult tcr; + + // C++ 5.2.9p5, reference downcast. + // See the function for details. + // DR 427 specifies that this is to be applied before paragraph 2. + tcr = TryStaticReferenceDowncast(Self, SrcExpr.get(), DestType, CStyle, + OpRange, msg, Kind, BasePath); + if (tcr != TC_NotApplicable) + return tcr; + + // C++0x [expr.static.cast]p3: + // A glvalue of type "cv1 T1" can be cast to type "rvalue reference to cv2 + // T2" if "cv2 T2" is reference-compatible with "cv1 T1". + tcr = TryLValueToRValueCast(Self, SrcExpr.get(), DestType, CStyle, Kind, + BasePath, msg); + if (tcr != TC_NotApplicable) + return tcr; + + // C++ 5.2.9p2: An expression e can be explicitly converted to a type T + // [...] if the declaration "T t(e);" is well-formed, [...]. + tcr = TryStaticImplicitCast(Self, SrcExpr, DestType, CCK, OpRange, msg, + Kind, ListInitialization); + if (SrcExpr.isInvalid()) + return TC_Failed; + if (tcr != TC_NotApplicable) + return tcr; + + // C++ 5.2.9p6: May apply the reverse of any standard conversion, except + // lvalue-to-rvalue, array-to-pointer, function-to-pointer, and boolean + // conversions, subject to further restrictions. + // Also, C++ 5.2.9p1 forbids casting away constness, which makes reversal + // of qualification conversions impossible. + // In the CStyle case, the earlier attempt to const_cast should have taken + // care of reverse qualification conversions. + + QualType SrcType = Self.Context.getCanonicalType(SrcExpr.get()->getType()); + + // C++0x 5.2.9p9: A value of a scoped enumeration type can be explicitly + // converted to an integral type. [...] A value of a scoped enumeration type + // can also be explicitly converted to a floating-point type [...]. + if (const EnumType *Enum = SrcType->getAs()) { + if (Enum->getDecl()->isScoped()) { + if (DestType->isBooleanType()) { + Kind = CK_IntegralToBoolean; + return TC_Success; + } else if (DestType->isIntegralType(Self.Context)) { + Kind = CK_IntegralCast; + return TC_Success; + } else if (DestType->isRealFloatingType()) { + Kind = CK_IntegralToFloating; + return TC_Success; + } + } + } + + // Reverse integral promotion/conversion. All such conversions are themselves + // again integral promotions or conversions and are thus already handled by + // p2 (TryDirectInitialization above). + // (Note: any data loss warnings should be suppressed.) + // The exception is the reverse of enum->integer, i.e. integer->enum (and + // enum->enum). See also C++ 5.2.9p7. + // The same goes for reverse floating point promotion/conversion and + // floating-integral conversions. Again, only floating->enum is relevant. + if (DestType->isEnumeralType()) { + if (SrcType->isIntegralOrEnumerationType()) { + Kind = CK_IntegralCast; + return TC_Success; + } else if (SrcType->isRealFloatingType()) { + Kind = CK_FloatingToIntegral; + return TC_Success; + } + } + + // Reverse pointer upcast. C++ 4.10p3 specifies pointer upcast. + // C++ 5.2.9p8 additionally disallows a cast path through virtual inheritance. + tcr = TryStaticPointerDowncast(Self, SrcType, DestType, CStyle, OpRange, msg, + Kind, BasePath); + if (tcr != TC_NotApplicable) + return tcr; + + // Reverse member pointer conversion. C++ 4.11 specifies member pointer + // conversion. C++ 5.2.9p9 has additional information. + // DR54's access restrictions apply here also. + tcr = TryStaticMemberPointerUpcast(Self, SrcExpr, SrcType, DestType, CStyle, + OpRange, msg, Kind, BasePath); + if (tcr != TC_NotApplicable) + return tcr; + + // Reverse pointer conversion to void*. C++ 4.10.p2 specifies conversion to + // void*. C++ 5.2.9p10 specifies additional restrictions, which really is + // just the usual constness stuff. + if (const PointerType *SrcPointer = SrcType->getAs()) { + QualType SrcPointee = SrcPointer->getPointeeType(); + if (SrcPointee->isVoidType()) { + if (const PointerType *DestPointer = DestType->getAs()) { + QualType DestPointee = DestPointer->getPointeeType(); + if (DestPointee->isIncompleteOrObjectType()) { + // This is definitely the intended conversion, but it might fail due + // to a qualifier violation. Note that we permit Objective-C lifetime + // and GC qualifier mismatches here. + if (!CStyle) { + Qualifiers DestPointeeQuals = DestPointee.getQualifiers(); + Qualifiers SrcPointeeQuals = SrcPointee.getQualifiers(); + DestPointeeQuals.removeObjCGCAttr(); + DestPointeeQuals.removeObjCLifetime(); + SrcPointeeQuals.removeObjCGCAttr(); + SrcPointeeQuals.removeObjCLifetime(); + if (DestPointeeQuals != SrcPointeeQuals && + !DestPointeeQuals.compatiblyIncludes(SrcPointeeQuals)) { + msg = diag::err_bad_cxx_cast_qualifiers_away; + return TC_Failed; + } + } + 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 = CK_CPointerToObjCPointerCast; + return TC_Success; + } + else if (CStyle && DestType->isBlockPointerType()) { + // allow c-style cast of void * to block pointers. + Kind = CK_AnyPointerToBlockPointerCast; + return TC_Success; + } + } + } + // Allow arbitray objective-c pointer conversion with static casts. + if (SrcType->isObjCObjectPointerType() && + DestType->isObjCObjectPointerType()) { + Kind = CK_BitCast; + return TC_Success; + } + + // We tried everything. Everything! Nothing works! :-( + return TC_NotApplicable; +} + +/// Tests whether a conversion according to N2844 is valid. +TryCastResult +TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, QualType DestType, + bool CStyle, CastKind &Kind, CXXCastPath &BasePath, + unsigned &msg) { + // C++0x [expr.static.cast]p3: + // A glvalue of type "cv1 T1" can be cast to type "rvalue reference to + // cv2 T2" if "cv2 T2" is reference-compatible with "cv1 T1". + const RValueReferenceType *R = DestType->getAs(); + if (!R) + return TC_NotApplicable; + + if (!SrcExpr->isGLValue()) + return TC_NotApplicable; + + // Because we try the reference downcast before this function, from now on + // 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; + bool ObjCLifetimeConversion; + QualType FromType = SrcExpr->getType(); + QualType ToType = R->getPointeeType(); + if (CStyle) { + FromType = FromType.getUnqualifiedType(); + ToType = ToType.getUnqualifiedType(); + } + + if (Self.CompareReferenceRelationship(SrcExpr->getLocStart(), + ToType, FromType, + DerivedToBase, ObjCConversion, + ObjCLifetimeConversion) + < Sema::Ref_Compatible_With_Added_Qualification) { + msg = diag::err_bad_lvalue_to_rvalue_cast; + return TC_Failed; + } + + if (DerivedToBase) { + Kind = CK_DerivedToBase; + CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, + /*DetectVirtual=*/true); + if (!Self.IsDerivedFrom(SrcExpr->getType(), R->getPointeeType(), Paths)) + return TC_NotApplicable; + + Self.BuildBasePathArray(Paths, BasePath); + } else + Kind = CK_NoOp; + + return TC_Success; +} + +/// Tests whether a conversion according to C++ 5.2.9p5 is valid. +TryCastResult +TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr, QualType DestType, + bool CStyle, const SourceRange &OpRange, + 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" + // exists, cv2 >= cv1, and B is not a virtual base class of D. + // In addition, DR54 clarifies that the base must be accessible in the + // current context. Although the wording of DR54 only applies to the pointer + // variant of this rule, the intent is clearly for it to apply to the this + // conversion as well. + + const ReferenceType *DestReference = DestType->getAs(); + if (!DestReference) { + return TC_NotApplicable; + } + bool RValueRef = DestReference->isRValueReferenceType(); + if (!RValueRef && !SrcExpr->isLValue()) { + // We know the left side is an lvalue reference, so we can suggest a reason. + msg = diag::err_bad_cxx_cast_rvalue; + return TC_NotApplicable; + } + + QualType DestPointee = DestReference->getPointeeType(); + + return TryStaticDowncast(Self, + Self.Context.getCanonicalType(SrcExpr->getType()), + Self.Context.getCanonicalType(DestPointee), CStyle, + OpRange, SrcExpr->getType(), DestType, msg, Kind, + BasePath); +} + +/// Tests whether a conversion according to C++ 5.2.9p8 is valid. +TryCastResult +TryStaticPointerDowncast(Sema &Self, QualType SrcType, QualType DestType, + bool CStyle, const SourceRange &OpRange, + 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 + // to D" to "pointer to B" exists, cv2 >= cv1, and B is not a virtual base + // class of D. + // In addition, DR54 clarifies that the base must be accessible in the + // current context. + + const PointerType *DestPointer = DestType->getAs(); + if (!DestPointer) { + return TC_NotApplicable; + } + + const PointerType *SrcPointer = SrcType->getAs(); + if (!SrcPointer) { + msg = diag::err_bad_static_cast_pointer_nonpointer; + return TC_NotApplicable; + } + + return TryStaticDowncast(Self, + Self.Context.getCanonicalType(SrcPointer->getPointeeType()), + Self.Context.getCanonicalType(DestPointer->getPointeeType()), + CStyle, OpRange, SrcType, DestType, msg, Kind, + BasePath); +} + +/// TryStaticDowncast - Common functionality of TryStaticReferenceDowncast and +/// TryStaticPointerDowncast. Tests whether a static downcast from SrcType to +/// DestType is possible and allowed. +TryCastResult +TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType, + bool CStyle, const SourceRange &OpRange, QualType OrigSrcType, + QualType OrigDestType, unsigned &msg, + 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))) + return TC_NotApplicable; + + // Downcast can only happen in class hierarchies, so we need classes. + if (!DestType->getAs() || !SrcType->getAs()) { + return TC_NotApplicable; + } + + CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, + /*DetectVirtual=*/true); + if (!Self.IsDerivedFrom(DestType, SrcType, Paths)) { + return TC_NotApplicable; + } + + // Target type does derive from source type. Now we're serious. If an error + // appears now, it's not ignored. + // This may not be entirely in line with the standard. Take for example: + // struct A {}; + // struct B : virtual A { + // B(A&); + // }; + // + // void f() + // { + // (void)static_cast(*((A*)0)); + // } + // As far as the standard is concerned, p5 does not apply (A is virtual), so + // p2 should be used instead - "const B& t(*((A*)0));" is perfectly valid. + // However, both GCC and Comeau reject this example, and accepting it would + // mean more complex code if we're to preserve the nice error message. + // FIXME: Being 100% compliant here would be nice to have. + + // Must preserve cv, as always, unless we're in C-style mode. + if (!CStyle && !DestType.isAtLeastAsQualifiedAs(SrcType)) { + msg = diag::err_bad_cxx_cast_qualifiers_away; + return TC_Failed; + } + + if (Paths.isAmbiguous(SrcType.getUnqualifiedType())) { + // This code is analoguous to that in CheckDerivedToBaseConversion, except + // that it builds the paths in reverse order. + // To sum up: record all paths to the base and build a nice string from + // them. Use it to spice up the error message. + if (!Paths.isRecordingPaths()) { + Paths.clear(); + Paths.setRecordingPaths(true); + Self.IsDerivedFrom(DestType, SrcType, Paths); + } + std::string PathDisplayStr; + std::set DisplayedPaths; + for (CXXBasePaths::paths_iterator PI = Paths.begin(), PE = Paths.end(); + PI != PE; ++PI) { + if (DisplayedPaths.insert(PI->back().SubobjectNumber).second) { + // We haven't displayed a path to this particular base + // class subobject yet. + PathDisplayStr += "\n "; + for (CXXBasePath::const_reverse_iterator EI = PI->rbegin(), + EE = PI->rend(); + EI != EE; ++EI) + PathDisplayStr += EI->Base->getType().getAsString() + " -> "; + PathDisplayStr += QualType(DestType).getAsString(); + } + } + + Self.Diag(OpRange.getBegin(), diag::err_ambiguous_base_to_derived_cast) + << QualType(SrcType).getUnqualifiedType() + << QualType(DestType).getUnqualifiedType() + << PathDisplayStr << OpRange; + msg = 0; + return TC_Failed; + } + + if (Paths.getDetectedVirtual() != 0) { + QualType VirtualBase(Paths.getDetectedVirtual(), 0); + Self.Diag(OpRange.getBegin(), diag::err_static_downcast_via_virtual) + << OrigSrcType << OrigDestType << VirtualBase << OpRange; + msg = 0; + return TC_Failed; + } + + if (!CStyle) { + switch (Self.CheckBaseClassAccess(OpRange.getBegin(), + SrcType, DestType, + Paths.front(), + diag::err_downcast_from_inaccessible_base)) { + case Sema::AR_accessible: + case Sema::AR_delayed: // be optimistic + case Sema::AR_dependent: // be optimistic + break; + + case Sema::AR_inaccessible: + msg = 0; + return TC_Failed; + } + } + + Self.BuildBasePathArray(Paths, BasePath); + Kind = CK_BaseToDerived; + return TC_Success; +} + +/// TryStaticMemberPointerUpcast - Tests whether a conversion according to +/// C++ 5.2.9p9 is valid: +/// +/// An rvalue of type "pointer to member of D of type cv1 T" can be +/// converted to an rvalue of type "pointer to member of B of type cv2 T", +/// where B is a base class of D [...]. +/// +TryCastResult +TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, QualType SrcType, + QualType DestType, bool CStyle, + const SourceRange &OpRange, + unsigned &msg, CastKind &Kind, + CXXCastPath &BasePath) { + const MemberPointerType *DestMemPtr = DestType->getAs(); + if (!DestMemPtr) + return TC_NotApplicable; + + bool WasOverloadedFunction = false; + DeclAccessPair FoundOverload; + if (SrcExpr.get()->getType() == Self.Context.OverloadTy) { + if (FunctionDecl *Fn + = Self.ResolveAddressOfOverloadedFunction(SrcExpr.get(), DestType, false, + FoundOverload)) { + CXXMethodDecl *M = cast(Fn); + SrcType = Self.Context.getMemberPointerType(Fn->getType(), + Self.Context.getTypeDeclType(M->getParent()).getTypePtr()); + WasOverloadedFunction = true; + } + } + + const MemberPointerType *SrcMemPtr = SrcType->getAs(); + if (!SrcMemPtr) { + msg = diag::err_bad_static_cast_member_pointer_nonmp; + return TC_NotApplicable; + } + + // T == T, modulo cv + if (!Self.Context.hasSameUnqualifiedType(SrcMemPtr->getPointeeType(), + DestMemPtr->getPointeeType())) + return TC_NotApplicable; + + // B base of D + QualType SrcClass(SrcMemPtr->getClass(), 0); + QualType DestClass(DestMemPtr->getClass(), 0); + CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, + /*DetectVirtual=*/true); + if (!Self.IsDerivedFrom(SrcClass, DestClass, Paths)) { + return TC_NotApplicable; + } + + // B is a base of D. But is it an allowed base? If not, it's a hard error. + if (Paths.isAmbiguous(Self.Context.getCanonicalType(DestClass))) { + Paths.clear(); + Paths.setRecordingPaths(true); + bool StillOkay = Self.IsDerivedFrom(SrcClass, DestClass, Paths); + assert(StillOkay); + (void)StillOkay; + std::string PathDisplayStr = Self.getAmbiguousPathsDisplayString(Paths); + Self.Diag(OpRange.getBegin(), diag::err_ambiguous_memptr_conv) + << 1 << SrcClass << DestClass << PathDisplayStr << OpRange; + msg = 0; + return TC_Failed; + } + + if (const RecordType *VBase = Paths.getDetectedVirtual()) { + Self.Diag(OpRange.getBegin(), diag::err_memptr_conv_via_virtual) + << SrcClass << DestClass << QualType(VBase, 0) << OpRange; + msg = 0; + return TC_Failed; + } + + if (!CStyle) { + switch (Self.CheckBaseClassAccess(OpRange.getBegin(), + DestClass, SrcClass, + Paths.front(), + diag::err_upcast_to_inaccessible_base)) { + case Sema::AR_accessible: + case Sema::AR_delayed: + case Sema::AR_dependent: + // Optimistically assume that the delayed and dependent cases + // will work out. + break; + + case Sema::AR_inaccessible: + msg = 0; + return TC_Failed; + } + } + + if (WasOverloadedFunction) { + // Resolve the address of the overloaded function again, this time + // allowing complaints if something goes wrong. + FunctionDecl *Fn = Self.ResolveAddressOfOverloadedFunction(SrcExpr.get(), + DestType, + true, + FoundOverload); + if (!Fn) { + msg = 0; + return TC_Failed; + } + + SrcExpr = Self.FixOverloadedFunctionReference(SrcExpr, FoundOverload, Fn); + if (!SrcExpr.isUsable()) { + msg = 0; + return TC_Failed; + } + } + + Self.BuildBasePathArray(Paths, BasePath); + Kind = CK_DerivedToBaseMemberPointer; + return TC_Success; +} + +/// TryStaticImplicitCast - Tests whether a conversion according to C++ 5.2.9p2 +/// is valid: +/// +/// An expression e can be explicitly converted to a type T using a +/// @c static_cast if the declaration "T t(e);" is well-formed [...]. +TryCastResult +TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, + Sema::CheckedConversionKind CCK, + const SourceRange &OpRange, unsigned &msg, + CastKind &Kind, bool ListInitialization) { + if (DestType->isRecordType()) { + if (Self.RequireCompleteType(OpRange.getBegin(), DestType, + diag::err_bad_dynamic_cast_incomplete)) { + msg = 0; + return TC_Failed; + } + } + + InitializedEntity Entity = InitializedEntity::InitializeTemporary(DestType); + InitializationKind InitKind + = (CCK == Sema::CCK_CStyleCast) + ? InitializationKind::CreateCStyleCast(OpRange.getBegin(), OpRange, + ListInitialization) + : (CCK == Sema::CCK_FunctionalCast) + ? InitializationKind::CreateFunctionalCast(OpRange, ListInitialization) + : InitializationKind::CreateCast(OpRange); + Expr *SrcExprRaw = SrcExpr.get(); + InitializationSequence InitSeq(Self, Entity, InitKind, &SrcExprRaw, 1); + + // At this point of CheckStaticCast, if the destination is a reference, + // or the expression is an overload expression this has to work. + // There is no other way that works. + // On the other hand, if we're checking a C-style cast, we've still got + // the reinterpret_cast way. + bool CStyle + = (CCK == Sema::CCK_CStyleCast || CCK == Sema::CCK_FunctionalCast); + if (InitSeq.Failed() && (CStyle || !DestType->isReferenceType())) + return TC_NotApplicable; + + ExprResult Result + = InitSeq.Perform(Self, Entity, InitKind, MultiExprArg(Self, &SrcExprRaw, 1)); + if (Result.isInvalid()) { + msg = 0; + return TC_Failed; + } + + if (InitSeq.isConstructorInitialization()) + Kind = CK_ConstructorConversion; + else + Kind = CK_NoOp; + + SrcExpr = move(Result); + return TC_Success; +} + +/// TryConstCast - See if a const_cast from source to destination is allowed, +/// and perform it if it is. +static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType, + bool CStyle, unsigned &msg) { + DestType = Self.Context.getCanonicalType(DestType); + QualType SrcType = SrcExpr->getType(); + if (const ReferenceType *DestTypeTmp =DestType->getAs()) { + if (DestTypeTmp->isLValueReferenceType() && !SrcExpr->isLValue()) { + // Cannot const_cast non-lvalue to lvalue reference type. But if this + // is C-style, static_cast might find a way, so we simply suggest a + // message and tell the parent to keep searching. + msg = diag::err_bad_cxx_cast_rvalue; + return TC_NotApplicable; + } + + // C++ 5.2.11p4: An lvalue of type T1 can be [cast] to an lvalue of type T2 + // [...] if a pointer to T1 can be [cast] to the type pointer to T2. + DestType = Self.Context.getPointerType(DestTypeTmp->getPointeeType()); + SrcType = Self.Context.getPointerType(SrcType); + } + + // C++ 5.2.11p5: For a const_cast involving pointers to data members [...] + // the rules for const_cast are the same as those used for pointers. + + if (!DestType->isPointerType() && + !DestType->isMemberPointerType() && + !DestType->isObjCObjectPointerType()) { + // Cannot cast to non-pointer, non-reference type. Note that, if DestType + // was a reference type, we converted it to a pointer above. + // The status of rvalue references isn't entirely clear, but it looks like + // conversion to them is simply invalid. + // C++ 5.2.11p3: For two pointer types [...] + if (!CStyle) + msg = diag::err_bad_const_cast_dest; + return TC_NotApplicable; + } + if (DestType->isFunctionPointerType() || + DestType->isMemberFunctionPointerType()) { + // Cannot cast direct function pointers. + // C++ 5.2.11p2: [...] where T is any object type or the void type [...] + // T is the ultimate pointee of source and target type. + if (!CStyle) + msg = diag::err_bad_const_cast_dest; + return TC_NotApplicable; + } + SrcType = Self.Context.getCanonicalType(SrcType); + + // Unwrap the pointers. Ignore qualifiers. Terminate early if the types are + // completely equal. + // C++ 5.2.11p3 describes the core semantics of const_cast. All cv specifiers + // in multi-level pointers may change, but the level count must be the same, + // as must be the final pointee type. + while (SrcType != DestType && + Self.Context.UnwrapSimilarPointerTypes(SrcType, DestType)) { + Qualifiers SrcQuals, DestQuals; + SrcType = Self.Context.getUnqualifiedArrayType(SrcType, SrcQuals); + DestType = Self.Context.getUnqualifiedArrayType(DestType, DestQuals); + + // const_cast is permitted to strip cvr-qualifiers, only. Make sure that + // the other qualifiers (e.g., address spaces) are identical. + SrcQuals.removeCVRQualifiers(); + DestQuals.removeCVRQualifiers(); + if (SrcQuals != DestQuals) + return TC_NotApplicable; + } + + // Since we're dealing in canonical types, the remainder must be the same. + if (SrcType != DestType) + return TC_NotApplicable; + + return TC_Success; +} + +// Checks for undefined behavior in reinterpret_cast. +// The cases that is checked for is: +// *reinterpret_cast(&a) +// reinterpret_cast(a) +// where accessing 'a' as type 'T' will result in undefined behavior. +void Sema::CheckCompatibleReinterpretCast(QualType SrcType, QualType DestType, + bool IsDereference, + SourceRange Range) { + unsigned DiagID = IsDereference ? + diag::warn_pointer_indirection_from_incompatible_type : + diag::warn_undefined_reinterpret_cast; + + if (Diags.getDiagnosticLevel(DiagID, Range.getBegin()) == + DiagnosticsEngine::Ignored) { + return; + } + + QualType SrcTy, DestTy; + if (IsDereference) { + if (!SrcType->getAs() || !DestType->getAs()) { + return; + } + SrcTy = SrcType->getPointeeType(); + DestTy = DestType->getPointeeType(); + } else { + if (!DestType->getAs()) { + return; + } + SrcTy = SrcType; + DestTy = DestType->getPointeeType(); + } + + // Cast is compatible if the types are the same. + if (Context.hasSameUnqualifiedType(DestTy, SrcTy)) { + return; + } + // or one of the types is a char or void type + if (DestTy->isAnyCharacterType() || DestTy->isVoidType() || + SrcTy->isAnyCharacterType() || SrcTy->isVoidType()) { + return; + } + // or one of the types is a tag type. + if (SrcTy->getAs() || DestTy->getAs()) { + return; + } + + // FIXME: Scoped enums? + if ((SrcTy->isUnsignedIntegerType() && DestTy->isSignedIntegerType()) || + (SrcTy->isSignedIntegerType() && DestTy->isUnsignedIntegerType())) { + if (Context.getTypeSize(DestTy) == Context.getTypeSize(SrcTy)) { + return; + } + } + + Diag(Range.getBegin(), DiagID) << SrcType << DestType << Range; +} + +static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, + QualType DestType, bool CStyle, + const SourceRange &OpRange, + unsigned &msg, + CastKind &Kind) { + bool IsLValueCast = false; + + DestType = Self.Context.getCanonicalType(DestType); + QualType SrcType = SrcExpr.get()->getType(); + + // Is the source an overloaded name? (i.e. &foo) + // If so, reinterpret_cast can not help us here (13.4, p1, bullet 5) ... + if (SrcType == Self.Context.OverloadTy) { + // ... unless foo resolves to an lvalue unambiguously. + // TODO: what if this fails because of DiagnoseUseOfDecl or something + // like it? + ExprResult SingleFunctionExpr = SrcExpr; + if (Self.ResolveAndFixSingleFunctionTemplateSpecialization( + SingleFunctionExpr, + Expr::getValueKindForType(DestType) == VK_RValue // Convert Fun to Ptr + ) && SingleFunctionExpr.isUsable()) { + SrcExpr = move(SingleFunctionExpr); + SrcType = SrcExpr.get()->getType(); + } else { + return TC_NotApplicable; + } + } + + if (const ReferenceType *DestTypeTmp = DestType->getAs()) { + bool LValue = DestTypeTmp->isLValueReferenceType(); + if (LValue && !SrcExpr.get()->isLValue()) { + // Cannot cast non-lvalue to lvalue reference type. See the similar + // comment in const_cast. + msg = diag::err_bad_cxx_cast_rvalue; + return TC_NotApplicable; + } + + if (!CStyle) { + Self.CheckCompatibleReinterpretCast(SrcType, DestType, + /*isDereference=*/false, OpRange); + } + + // C++ 5.2.10p10: [...] a reference cast reinterpret_cast(x) has the + // same effect as the conversion *reinterpret_cast(&x) with the + // built-in & and * operators. + + const char *inappropriate = 0; + switch (SrcExpr.get()->getObjectKind()) { + case OK_Ordinary: + break; + case OK_BitField: inappropriate = "bit-field"; break; + case OK_VectorComponent: inappropriate = "vector element"; break; + case OK_ObjCProperty: inappropriate = "property expression"; break; + case OK_ObjCSubscript: inappropriate = "container subscripting expression"; + break; + } + if (inappropriate) { + Self.Diag(OpRange.getBegin(), diag::err_bad_reinterpret_cast_reference) + << inappropriate << DestType + << OpRange << SrcExpr.get()->getSourceRange(); + msg = 0; SrcExpr = ExprError(); + return TC_NotApplicable; + } + + // This code does this transformation for the checked types. + DestType = Self.Context.getPointerType(DestTypeTmp->getPointeeType()); + SrcType = Self.Context.getPointerType(SrcType); + + IsLValueCast = true; + } + + // Canonicalize source for comparison. + SrcType = Self.Context.getCanonicalType(SrcType); + + const MemberPointerType *DestMemPtr = DestType->getAs(), + *SrcMemPtr = SrcType->getAs(); + if (DestMemPtr && SrcMemPtr) { + // C++ 5.2.10p9: An rvalue of type "pointer to member of X of type T1" + // can be explicitly converted to an rvalue of type "pointer to member + // of Y of type T2" if T1 and T2 are both function types or both object + // types. + if (DestMemPtr->getPointeeType()->isFunctionType() != + SrcMemPtr->getPointeeType()->isFunctionType()) + return TC_NotApplicable; + + // C++ 5.2.10p2: The reinterpret_cast operator shall not cast away + // constness. + // A reinterpret_cast followed by a const_cast can, though, so in C-style, + // we accept it. + if (CastsAwayConstness(Self, SrcType, DestType, /*CheckCVR=*/!CStyle, + /*CheckObjCLifetime=*/CStyle)) { + msg = diag::err_bad_cxx_cast_qualifiers_away; + 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. + assert(!IsLValueCast); + Kind = CK_ReinterpretMemberPointer; + return TC_Success; + } + + // See below for the enumeral issue. + if (SrcType->isNullPtrType() && DestType->isIntegralType(Self.Context)) { + // C++0x 5.2.10p4: A pointer can be explicitly converted to any integral + // type large enough to hold it. A value of std::nullptr_t can be + // converted to an integral type; the conversion has the same meaning + // and validity as a conversion of (void*)0 to the integral type. + if (Self.Context.getTypeSize(SrcType) > + Self.Context.getTypeSize(DestType)) { + msg = diag::err_bad_reinterpret_cast_small_int; + return TC_Failed; + } + Kind = CK_PointerToIntegral; + return TC_Success; + } + + bool destIsVector = DestType->isVectorType(); + bool srcIsVector = SrcType->isVectorType(); + if (srcIsVector || destIsVector) { + // FIXME: Should this also apply to floating point types? + bool srcIsScalar = SrcType->isIntegralType(Self.Context); + bool destIsScalar = DestType->isIntegralType(Self.Context); + + // Check if this is a cast between a vector and something else. + if (!(srcIsScalar && destIsVector) && !(srcIsVector && destIsScalar) && + !(srcIsVector && destIsVector)) + return TC_NotApplicable; + + // If both types have the same size, we can successfully cast. + if (Self.Context.getTypeSize(SrcType) + == Self.Context.getTypeSize(DestType)) { + Kind = CK_BitCast; + return TC_Success; + } + + if (destIsScalar) + msg = diag::err_bad_cxx_cast_vector_to_scalar_different_size; + else if (srcIsScalar) + msg = diag::err_bad_cxx_cast_scalar_to_vector_different_size; + else + msg = diag::err_bad_cxx_cast_vector_to_vector_different_size; + + return TC_Failed; + } + + if (SrcType == DestType) { + // C++ 5.2.10p2 has a note that mentions that, subject to all other + // restrictions, a cast to the same type is allowed so long as it does not + // cast away constness. In C++98, the intent was not entirely clear here, + // since all other paragraphs explicitly forbid casts to the same type. + // C++11 clarifies this case with p2. + // + // The only allowed types are: integral, enumeration, pointer, or + // pointer-to-member types. We also won't restrict Obj-C pointers either. + Kind = CK_NoOp; + TryCastResult Result = TC_NotApplicable; + if (SrcType->isIntegralOrEnumerationType() || + SrcType->isAnyPointerType() || + SrcType->isMemberPointerType() || + SrcType->isBlockPointerType()) { + Result = TC_Success; + } + return Result; + } + + bool destIsPtr = DestType->isAnyPointerType() || + DestType->isBlockPointerType(); + bool srcIsPtr = SrcType->isAnyPointerType() || + SrcType->isBlockPointerType(); + if (!destIsPtr && !srcIsPtr) { + // Except for std::nullptr_t->integer and lvalue->reference, which are + // handled above, at least one of the two arguments must be a pointer. + return TC_NotApplicable; + } + + if (DestType->isIntegralType(Self.Context)) { + assert(srcIsPtr && "One type must be a pointer"); + // C++ 5.2.10p4: A pointer can be explicitly converted to any integral + // type large enough to hold it; except in Microsoft mode, where the + // integral type size doesn't matter. + if ((Self.Context.getTypeSize(SrcType) > + Self.Context.getTypeSize(DestType)) && + !Self.getLangOpts().MicrosoftExt) { + msg = diag::err_bad_reinterpret_cast_small_int; + return TC_Failed; + } + Kind = CK_PointerToIntegral; + return TC_Success; + } + + if (SrcType->isIntegralOrEnumerationType()) { + 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. + // C++ 5.2.10p9: [Note: ...a null pointer constant of integral type is not + // necessarily converted to a null pointer value.] + Kind = CK_IntegralToPointer; + return TC_Success; + } + + if (!destIsPtr || !srcIsPtr) { + // With the valid non-pointer conversions out of the way, we can be even + // more stringent. + return TC_NotApplicable; + } + + // C++ 5.2.10p2: The reinterpret_cast operator shall not cast away constness. + // The C-style cast operator can. + if (CastsAwayConstness(Self, SrcType, DestType, /*CheckCVR=*/!CStyle, + /*CheckObjCLifetime=*/CStyle)) { + msg = diag::err_bad_cxx_cast_qualifiers_away; + return TC_Failed; + } + + // Cannot convert between block pointers and Objective-C object pointers. + if ((SrcType->isBlockPointerType() && DestType->isObjCObjectPointerType()) || + (DestType->isBlockPointerType() && SrcType->isObjCObjectPointerType())) + return TC_NotApplicable; + + if (IsLValueCast) { + Kind = CK_LValueBitCast; + } else if (DestType->isObjCObjectPointerType()) { + Kind = Self.PrepareCastToObjCObjectPointer(SrcExpr); + } else if (DestType->isBlockPointerType()) { + if (!SrcType->isBlockPointerType()) { + Kind = CK_AnyPointerToBlockPointerCast; + } else { + Kind = CK_BitCast; + } + } else { + Kind = CK_BitCast; + } + + // Any pointer can be cast to an Objective-C pointer type with a C-style + // cast. + if (CStyle && DestType->isObjCObjectPointerType()) { + return TC_Success; + } + + // Not casting away constness, so the only remaining check is for compatible + // pointer categories. + + if (SrcType->isFunctionPointerType()) { + if (DestType->isFunctionPointerType()) { + // C++ 5.2.10p6: A pointer to a function can be explicitly converted to + // a pointer to a function of a different type. + return TC_Success; + } + + // C++0x 5.2.10p8: Converting a pointer to a function into a pointer to + // an object type or vice versa is conditionally-supported. + // Compilers support it in C++03 too, though, because it's necessary for + // casting the return value of dlsym() and GetProcAddress(). + // FIXME: Conditionally-supported behavior should be configurable in the + // TargetInfo or similar. + Self.Diag(OpRange.getBegin(), + Self.getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_cast_fn_obj : diag::ext_cast_fn_obj) + << OpRange; + return TC_Success; + } + + if (DestType->isFunctionPointerType()) { + // See above. + Self.Diag(OpRange.getBegin(), + Self.getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_cast_fn_obj : diag::ext_cast_fn_obj) + << OpRange; + return TC_Success; + } + + // C++ 5.2.10p7: A pointer to an object can be explicitly converted to + // a pointer to an object of different type. + // Void pointers are not specified, but supported by every compiler out there. + // So we finish by allowing everything that remains - it's got to be two + // object pointers. + return TC_Success; +} + +void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle, + bool ListInitialization) { + // Handle placeholders. + if (isPlaceholder()) { + // C-style casts can resolve __unknown_any types. + if (claimPlaceholder(BuiltinType::UnknownAny)) { + SrcExpr = Self.checkUnknownAnyCast(DestRange, DestType, + SrcExpr.get(), Kind, + ValueKind, BasePath); + return; + } + + checkNonOverloadPlaceholders(); + if (SrcExpr.isInvalid()) + return; + } + + // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void". + // This test is outside everything else because it's the only case where + // a non-lvalue-reference target type does not lead to decay. + if (DestType->isVoidType()) { + Kind = CK_ToVoid; + + if (claimPlaceholder(BuiltinType::Overload)) { + Self.ResolveAndFixSingleFunctionTemplateSpecialization( + SrcExpr, /* Decay Function to ptr */ false, + /* Complain */ true, DestRange, DestType, + diag::err_bad_cstyle_cast_overload); + if (SrcExpr.isInvalid()) + return; + } + + SrcExpr = Self.IgnoredValueConversions(SrcExpr.take()); + if (SrcExpr.isInvalid()) + return; + + return; + } + + // If the type is dependent, we won't do any other semantic analysis now. + if (DestType->isDependentType() || SrcExpr.get()->isTypeDependent()) { + assert(Kind == CK_Dependent); + return; + } + + if (ValueKind == VK_RValue && !DestType->isRecordType() && + !isPlaceholder(BuiltinType::Overload)) { + SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take()); + if (SrcExpr.isInvalid()) + return; + } + + // AltiVec vector initialization with a single literal. + if (const VectorType *vecTy = DestType->getAs()) + if (vecTy->getVectorKind() == VectorType::AltiVecVector + && (SrcExpr.get()->getType()->isIntegerType() + || SrcExpr.get()->getType()->isFloatingType())) { + Kind = CK_VectorSplat; + return; + } + + // C++ [expr.cast]p5: The conversions performed by + // - a const_cast, + // - a static_cast, + // - a static_cast followed by a const_cast, + // - a reinterpret_cast, or + // - a reinterpret_cast followed by a const_cast, + // can be performed using the cast notation of explicit type conversion. + // [...] If a conversion can be interpreted in more than one of the ways + // listed above, the interpretation that appears first in the list is used, + // even if a cast resulting from that interpretation is ill-formed. + // In plain language, this means trying a const_cast ... + unsigned msg = diag::err_bad_cxx_cast_generic; + TryCastResult tcr = TryConstCast(Self, SrcExpr.get(), DestType, + /*CStyle*/true, msg); + if (tcr == TC_Success) + Kind = CK_NoOp; + + Sema::CheckedConversionKind CCK + = FunctionalStyle? Sema::CCK_FunctionalCast + : Sema::CCK_CStyleCast; + if (tcr == TC_NotApplicable) { + // ... or if that is not possible, a static_cast, ignoring const, ... + tcr = TryStaticCast(Self, SrcExpr, DestType, CCK, OpRange, + msg, Kind, BasePath, ListInitialization); + if (SrcExpr.isInvalid()) + return; + + if (tcr == TC_NotApplicable) { + // ... and finally a reinterpret_cast, ignoring const. + tcr = TryReinterpretCast(Self, SrcExpr, DestType, /*CStyle*/true, + OpRange, msg, Kind); + if (SrcExpr.isInvalid()) + return; + } + } + + if (Self.getLangOpts().ObjCAutoRefCount && tcr == TC_Success) + checkObjCARCConversion(CCK); + + if (tcr != TC_Success && msg != 0) { + if (SrcExpr.get()->getType() == Self.Context.OverloadTy) { + DeclAccessPair Found; + FunctionDecl *Fn = Self.ResolveAddressOfOverloadedFunction(SrcExpr.get(), + DestType, + /*Complain*/ true, + Found); + + assert(!Fn && "cast failed but able to resolve overload expression!!"); + (void)Fn; + + } else { + diagnoseBadCast(Self, msg, (FunctionalStyle ? CT_Functional : CT_CStyle), + OpRange, SrcExpr.get(), DestType, ListInitialization); + } + } else if (Kind == CK_BitCast) { + checkCastAlign(); + } + + // Clear out SrcExpr if there was a fatal error. + if (tcr != TC_Success) + SrcExpr = ExprError(); +} + +/// Check the semantics of a C-style cast operation, in C. +void CastOperation::CheckCStyleCast() { + assert(!Self.getLangOpts().CPlusPlus); + + // C-style casts can resolve __unknown_any types. + if (claimPlaceholder(BuiltinType::UnknownAny)) { + SrcExpr = Self.checkUnknownAnyCast(DestRange, DestType, + SrcExpr.get(), Kind, + ValueKind, BasePath); + return; + } + + // C99 6.5.4p2: the cast type needs to be void or scalar and the expression + // type needs to be scalar. + if (DestType->isVoidType()) { + // We don't necessarily do lvalue-to-rvalue conversions on this. + SrcExpr = Self.IgnoredValueConversions(SrcExpr.take()); + if (SrcExpr.isInvalid()) + return; + + // Cast to void allows any expr type. + Kind = CK_ToVoid; + return; + } + + SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take()); + if (SrcExpr.isInvalid()) + return; + QualType SrcType = SrcExpr.get()->getType(); + + // You can cast an _Atomic(T) to anything you can cast a T to. + if (const AtomicType *AtomicSrcType = SrcType->getAs()) + SrcType = AtomicSrcType->getValueType(); + + assert(!SrcType->isPlaceholderType()); + + if (Self.RequireCompleteType(OpRange.getBegin(), DestType, + diag::err_typecheck_cast_to_incomplete)) { + SrcExpr = ExprError(); + return; + } + + if (!DestType->isScalarType() && !DestType->isVectorType()) { + const RecordType *DestRecordTy = DestType->getAs(); + + if (DestRecordTy && Self.Context.hasSameUnqualifiedType(DestType, SrcType)){ + // GCC struct/union extension: allow cast to self. + Self.Diag(OpRange.getBegin(), diag::ext_typecheck_cast_nonscalar) + << DestType << SrcExpr.get()->getSourceRange(); + Kind = CK_NoOp; + return; + } + + // GCC's cast to union extension. + if (DestRecordTy && DestRecordTy->getDecl()->isUnion()) { + RecordDecl *RD = DestRecordTy->getDecl(); + RecordDecl::field_iterator Field, FieldEnd; + for (Field = RD->field_begin(), FieldEnd = RD->field_end(); + Field != FieldEnd; ++Field) { + if (Self.Context.hasSameUnqualifiedType(Field->getType(), SrcType) && + !Field->isUnnamedBitfield()) { + Self.Diag(OpRange.getBegin(), diag::ext_typecheck_cast_to_union) + << SrcExpr.get()->getSourceRange(); + break; + } + } + if (Field == FieldEnd) { + Self.Diag(OpRange.getBegin(), diag::err_typecheck_cast_to_union_no_type) + << SrcType << SrcExpr.get()->getSourceRange(); + SrcExpr = ExprError(); + return; + } + Kind = CK_ToUnion; + return; + } + + // Reject any other conversions to non-scalar types. + Self.Diag(OpRange.getBegin(), diag::err_typecheck_cond_expect_scalar) + << DestType << SrcExpr.get()->getSourceRange(); + SrcExpr = ExprError(); + return; + } + + // The type we're casting to is known to be a scalar or vector. + + // Require the operand to be a scalar or vector. + if (!SrcType->isScalarType() && !SrcType->isVectorType()) { + Self.Diag(SrcExpr.get()->getExprLoc(), + diag::err_typecheck_expect_scalar_operand) + << SrcType << SrcExpr.get()->getSourceRange(); + SrcExpr = ExprError(); + return; + } + + if (DestType->isExtVectorType()) { + SrcExpr = Self.CheckExtVectorCast(OpRange, DestType, SrcExpr.take(), Kind); + return; + } + + if (const VectorType *DestVecTy = DestType->getAs()) { + if (DestVecTy->getVectorKind() == VectorType::AltiVecVector && + (SrcType->isIntegerType() || SrcType->isFloatingType())) { + Kind = CK_VectorSplat; + } else if (Self.CheckVectorCast(OpRange, DestType, SrcType, Kind)) { + SrcExpr = ExprError(); + } + return; + } + + if (SrcType->isVectorType()) { + if (Self.CheckVectorCast(OpRange, SrcType, DestType, Kind)) + SrcExpr = ExprError(); + return; + } + + // The source and target types are both scalars, i.e. + // - arithmetic types (fundamental, enum, and complex) + // - all kinds of pointers + // Note that member pointers were filtered out with C++, above. + + if (isa(SrcExpr.get())) { + Self.Diag(SrcExpr.get()->getExprLoc(), diag::err_cast_selector_expr); + SrcExpr = ExprError(); + return; + } + + // If either type is a pointer, the other type has to be either an + // integer or a pointer. + if (!DestType->isArithmeticType()) { + if (!SrcType->isIntegralType(Self.Context) && SrcType->isArithmeticType()) { + Self.Diag(SrcExpr.get()->getExprLoc(), + diag::err_cast_pointer_from_non_pointer_int) + << SrcType << SrcExpr.get()->getSourceRange(); + SrcExpr = ExprError(); + return; + } + } else if (!SrcType->isArithmeticType()) { + if (!DestType->isIntegralType(Self.Context) && + DestType->isArithmeticType()) { + Self.Diag(SrcExpr.get()->getLocStart(), + diag::err_cast_pointer_to_non_pointer_int) + << DestType << SrcExpr.get()->getSourceRange(); + SrcExpr = ExprError(); + return; + } + } + + // ARC imposes extra restrictions on casts. + if (Self.getLangOpts().ObjCAutoRefCount) { + checkObjCARCConversion(Sema::CCK_CStyleCast); + if (SrcExpr.isInvalid()) + return; + + if (const PointerType *CastPtr = DestType->getAs()) { + if (const PointerType *ExprPtr = SrcType->getAs()) { + Qualifiers CastQuals = CastPtr->getPointeeType().getQualifiers(); + Qualifiers ExprQuals = ExprPtr->getPointeeType().getQualifiers(); + if (CastPtr->getPointeeType()->isObjCLifetimeType() && + ExprPtr->getPointeeType()->isObjCLifetimeType() && + !CastQuals.compatiblyIncludesObjCLifetime(ExprQuals)) { + Self.Diag(SrcExpr.get()->getLocStart(), + diag::err_typecheck_incompatible_ownership) + << SrcType << DestType << Sema::AA_Casting + << SrcExpr.get()->getSourceRange(); + return; + } + } + } + else if (!Self.CheckObjCARCUnavailableWeakConversion(DestType, SrcType)) { + Self.Diag(SrcExpr.get()->getLocStart(), + diag::err_arc_convesion_of_weak_unavailable) + << 1 << SrcType << DestType << SrcExpr.get()->getSourceRange(); + SrcExpr = ExprError(); + return; + } + } + + Kind = Self.PrepareScalarCast(SrcExpr, DestType); + if (SrcExpr.isInvalid()) + return; + + if (Kind == CK_BitCast) + checkCastAlign(); +} + +ExprResult Sema::BuildCStyleCastExpr(SourceLocation LPLoc, + TypeSourceInfo *CastTypeInfo, + SourceLocation RPLoc, + Expr *CastExpr) { + CastOperation Op(*this, CastTypeInfo->getType(), CastExpr); + Op.DestRange = CastTypeInfo->getTypeLoc().getSourceRange(); + Op.OpRange = SourceRange(LPLoc, CastExpr->getLocEnd()); + + if (getLangOpts().CPlusPlus) { + Op.CheckCXXCStyleCast(/*FunctionalStyle=*/ false, + isa(CastExpr)); + } else { + Op.CheckCStyleCast(); + } + + if (Op.SrcExpr.isInvalid()) + return ExprError(); + + return Op.complete(CStyleCastExpr::Create(Context, Op.ResultType, + Op.ValueKind, Op.Kind, Op.SrcExpr.take(), + &Op.BasePath, CastTypeInfo, LPLoc, RPLoc)); +} + +ExprResult Sema::BuildCXXFunctionalCastExpr(TypeSourceInfo *CastTypeInfo, + SourceLocation LPLoc, + Expr *CastExpr, + SourceLocation RPLoc) { + assert(LPLoc.isValid() && "List-initialization shouldn't get here."); + CastOperation Op(*this, CastTypeInfo->getType(), CastExpr); + Op.DestRange = CastTypeInfo->getTypeLoc().getSourceRange(); + Op.OpRange = SourceRange(Op.DestRange.getBegin(), CastExpr->getLocEnd()); + + Op.CheckCXXCStyleCast(/*FunctionalStyle=*/true, /*ListInit=*/false); + if (Op.SrcExpr.isInvalid()) + return ExprError(); + + return Op.complete(CXXFunctionalCastExpr::Create(Context, Op.ResultType, + Op.ValueKind, CastTypeInfo, Op.DestRange.getBegin(), + Op.Kind, Op.SrcExpr.take(), &Op.BasePath, RPLoc)); +} diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp new file mode 100644 index 0000000..0d15ce2 --- /dev/null +++ b/clang/lib/Sema/SemaChecking.cpp @@ -0,0 +1,5153 @@ +//===--- SemaChecking.cpp - Extra Semantic Checking -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements extra semantic analysis beyond what is enforced +// by the C type system. +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/Initialization.h" +#include "clang/Sema/Sema.h" +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/Initialization.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" +#include "clang/AST/EvaluatedExprVisitor.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/StmtCXX.h" +#include "clang/AST/StmtObjC.h" +#include "clang/Lex/Preprocessor.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/raw_ostream.h" +#include "clang/Basic/TargetBuiltins.h" +#include "clang/Basic/TargetInfo.h" +#include "clang/Basic/ConvertUTF.h" +#include +using namespace clang; +using namespace sema; + +SourceLocation Sema::getLocationOfStringLiteralByte(const StringLiteral *SL, + unsigned ByteNo) const { + return SL->getLocationOfByte(ByteNo, PP.getSourceManager(), + PP.getLangOpts(), PP.getTargetInfo()); +} + +/// Checks that a call expression's argument count is the desired number. +/// This is useful when doing custom type-checking. Returns true on error. +static bool checkArgCount(Sema &S, CallExpr *call, unsigned desiredArgCount) { + unsigned argCount = call->getNumArgs(); + if (argCount == desiredArgCount) return false; + + if (argCount < desiredArgCount) + return S.Diag(call->getLocEnd(), diag::err_typecheck_call_too_few_args) + << 0 /*function call*/ << desiredArgCount << argCount + << call->getSourceRange(); + + // Highlight all the excess arguments. + SourceRange range(call->getArg(desiredArgCount)->getLocStart(), + call->getArg(argCount - 1)->getLocEnd()); + + return S.Diag(range.getBegin(), diag::err_typecheck_call_too_many_args) + << 0 /*function call*/ << desiredArgCount << argCount + << call->getArg(1)->getSourceRange(); +} + +/// CheckBuiltinAnnotationString - Checks that string argument to the builtin +/// annotation is a non wide string literal. +static bool CheckBuiltinAnnotationString(Sema &S, Expr *Arg) { + Arg = Arg->IgnoreParenCasts(); + StringLiteral *Literal = dyn_cast(Arg); + if (!Literal || !Literal->isAscii()) { + S.Diag(Arg->getLocStart(), diag::err_builtin_annotation_not_string_constant) + << Arg->getSourceRange(); + return true; + } + return false; +} + +ExprResult +Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { + ExprResult TheCallResult(Owned(TheCall)); + + // Find out if any arguments are required to be integer constant expressions. + unsigned ICEArguments = 0; + ASTContext::GetBuiltinTypeError Error; + Context.GetBuiltinType(BuiltinID, Error, &ICEArguments); + if (Error != ASTContext::GE_None) + ICEArguments = 0; // Don't diagnose previously diagnosed errors. + + // If any arguments are required to be ICE's, check and diagnose. + for (unsigned ArgNo = 0; ICEArguments != 0; ++ArgNo) { + // Skip arguments not required to be ICE's. + if ((ICEArguments & (1 << ArgNo)) == 0) continue; + + llvm::APSInt Result; + if (SemaBuiltinConstantArg(TheCall, ArgNo, Result)) + return true; + ICEArguments &= ~(1 << ArgNo); + } + + switch (BuiltinID) { + case Builtin::BI__builtin___CFStringMakeConstantString: + assert(TheCall->getNumArgs() == 1 && + "Wrong # arguments to builtin CFStringMakeConstantString"); + if (CheckObjCString(TheCall->getArg(0))) + return ExprError(); + break; + case Builtin::BI__builtin_stdarg_start: + case Builtin::BI__builtin_va_start: + if (SemaBuiltinVAStart(TheCall)) + return ExprError(); + break; + case Builtin::BI__builtin_isgreater: + case Builtin::BI__builtin_isgreaterequal: + case Builtin::BI__builtin_isless: + case Builtin::BI__builtin_islessequal: + case Builtin::BI__builtin_islessgreater: + case Builtin::BI__builtin_isunordered: + if (SemaBuiltinUnorderedCompare(TheCall)) + return ExprError(); + break; + case Builtin::BI__builtin_fpclassify: + if (SemaBuiltinFPClassification(TheCall, 6)) + return ExprError(); + break; + case Builtin::BI__builtin_isfinite: + case Builtin::BI__builtin_isinf: + case Builtin::BI__builtin_isinf_sign: + case Builtin::BI__builtin_isnan: + case Builtin::BI__builtin_isnormal: + if (SemaBuiltinFPClassification(TheCall, 1)) + return ExprError(); + break; + case Builtin::BI__builtin_shufflevector: + return SemaBuiltinShuffleVector(TheCall); + // TheCall will be freed by the smart pointer here, but that's fine, since + // SemaBuiltinShuffleVector guts it, but then doesn't release it. + case Builtin::BI__builtin_prefetch: + if (SemaBuiltinPrefetch(TheCall)) + return ExprError(); + break; + case Builtin::BI__builtin_object_size: + if (SemaBuiltinObjectSize(TheCall)) + return ExprError(); + break; + case Builtin::BI__builtin_longjmp: + if (SemaBuiltinLongjmp(TheCall)) + return ExprError(); + break; + + case Builtin::BI__builtin_classify_type: + if (checkArgCount(*this, TheCall, 1)) return true; + TheCall->setType(Context.IntTy); + break; + case Builtin::BI__builtin_constant_p: + if (checkArgCount(*this, TheCall, 1)) return true; + TheCall->setType(Context.IntTy); + break; + case Builtin::BI__sync_fetch_and_add: + case Builtin::BI__sync_fetch_and_add_1: + case Builtin::BI__sync_fetch_and_add_2: + case Builtin::BI__sync_fetch_and_add_4: + case Builtin::BI__sync_fetch_and_add_8: + case Builtin::BI__sync_fetch_and_add_16: + case Builtin::BI__sync_fetch_and_sub: + case Builtin::BI__sync_fetch_and_sub_1: + case Builtin::BI__sync_fetch_and_sub_2: + case Builtin::BI__sync_fetch_and_sub_4: + case Builtin::BI__sync_fetch_and_sub_8: + case Builtin::BI__sync_fetch_and_sub_16: + case Builtin::BI__sync_fetch_and_or: + case Builtin::BI__sync_fetch_and_or_1: + case Builtin::BI__sync_fetch_and_or_2: + case Builtin::BI__sync_fetch_and_or_4: + case Builtin::BI__sync_fetch_and_or_8: + case Builtin::BI__sync_fetch_and_or_16: + case Builtin::BI__sync_fetch_and_and: + case Builtin::BI__sync_fetch_and_and_1: + case Builtin::BI__sync_fetch_and_and_2: + case Builtin::BI__sync_fetch_and_and_4: + case Builtin::BI__sync_fetch_and_and_8: + case Builtin::BI__sync_fetch_and_and_16: + case Builtin::BI__sync_fetch_and_xor: + case Builtin::BI__sync_fetch_and_xor_1: + case Builtin::BI__sync_fetch_and_xor_2: + case Builtin::BI__sync_fetch_and_xor_4: + case Builtin::BI__sync_fetch_and_xor_8: + case Builtin::BI__sync_fetch_and_xor_16: + case Builtin::BI__sync_add_and_fetch: + case Builtin::BI__sync_add_and_fetch_1: + case Builtin::BI__sync_add_and_fetch_2: + case Builtin::BI__sync_add_and_fetch_4: + case Builtin::BI__sync_add_and_fetch_8: + case Builtin::BI__sync_add_and_fetch_16: + case Builtin::BI__sync_sub_and_fetch: + case Builtin::BI__sync_sub_and_fetch_1: + case Builtin::BI__sync_sub_and_fetch_2: + case Builtin::BI__sync_sub_and_fetch_4: + case Builtin::BI__sync_sub_and_fetch_8: + case Builtin::BI__sync_sub_and_fetch_16: + case Builtin::BI__sync_and_and_fetch: + case Builtin::BI__sync_and_and_fetch_1: + case Builtin::BI__sync_and_and_fetch_2: + case Builtin::BI__sync_and_and_fetch_4: + case Builtin::BI__sync_and_and_fetch_8: + case Builtin::BI__sync_and_and_fetch_16: + case Builtin::BI__sync_or_and_fetch: + case Builtin::BI__sync_or_and_fetch_1: + case Builtin::BI__sync_or_and_fetch_2: + case Builtin::BI__sync_or_and_fetch_4: + case Builtin::BI__sync_or_and_fetch_8: + case Builtin::BI__sync_or_and_fetch_16: + case Builtin::BI__sync_xor_and_fetch: + case Builtin::BI__sync_xor_and_fetch_1: + case Builtin::BI__sync_xor_and_fetch_2: + case Builtin::BI__sync_xor_and_fetch_4: + case Builtin::BI__sync_xor_and_fetch_8: + case Builtin::BI__sync_xor_and_fetch_16: + case Builtin::BI__sync_val_compare_and_swap: + case Builtin::BI__sync_val_compare_and_swap_1: + case Builtin::BI__sync_val_compare_and_swap_2: + case Builtin::BI__sync_val_compare_and_swap_4: + case Builtin::BI__sync_val_compare_and_swap_8: + case Builtin::BI__sync_val_compare_and_swap_16: + case Builtin::BI__sync_bool_compare_and_swap: + case Builtin::BI__sync_bool_compare_and_swap_1: + case Builtin::BI__sync_bool_compare_and_swap_2: + case Builtin::BI__sync_bool_compare_and_swap_4: + case Builtin::BI__sync_bool_compare_and_swap_8: + case Builtin::BI__sync_bool_compare_and_swap_16: + case Builtin::BI__sync_lock_test_and_set: + case Builtin::BI__sync_lock_test_and_set_1: + case Builtin::BI__sync_lock_test_and_set_2: + case Builtin::BI__sync_lock_test_and_set_4: + case Builtin::BI__sync_lock_test_and_set_8: + case Builtin::BI__sync_lock_test_and_set_16: + case Builtin::BI__sync_lock_release: + case Builtin::BI__sync_lock_release_1: + case Builtin::BI__sync_lock_release_2: + case Builtin::BI__sync_lock_release_4: + case Builtin::BI__sync_lock_release_8: + case Builtin::BI__sync_lock_release_16: + case Builtin::BI__sync_swap: + case Builtin::BI__sync_swap_1: + case Builtin::BI__sync_swap_2: + case Builtin::BI__sync_swap_4: + case Builtin::BI__sync_swap_8: + case Builtin::BI__sync_swap_16: + return SemaBuiltinAtomicOverloaded(move(TheCallResult)); +#define BUILTIN(ID, TYPE, ATTRS) +#define ATOMIC_BUILTIN(ID, TYPE, ATTRS) \ + case Builtin::BI##ID: \ + return SemaAtomicOpsOverloaded(move(TheCallResult), AtomicExpr::AO##ID); +#include "clang/Basic/Builtins.def" + case Builtin::BI__builtin_annotation: + if (CheckBuiltinAnnotationString(*this, TheCall->getArg(1))) + return ExprError(); + break; + } + + // Since the target specific builtins for each arch overlap, only check those + // of the arch we are compiling for. + if (BuiltinID >= Builtin::FirstTSBuiltin) { + switch (Context.getTargetInfo().getTriple().getArch()) { + case llvm::Triple::arm: + case llvm::Triple::thumb: + if (CheckARMBuiltinFunctionCall(BuiltinID, TheCall)) + return ExprError(); + break; + default: + break; + } + } + + return move(TheCallResult); +} + +// Get the valid immediate range for the specified NEON type code. +static unsigned RFT(unsigned t, bool shift = false) { + NeonTypeFlags Type(t); + int IsQuad = Type.isQuad(); + switch (Type.getEltType()) { + case NeonTypeFlags::Int8: + case NeonTypeFlags::Poly8: + return shift ? 7 : (8 << IsQuad) - 1; + case NeonTypeFlags::Int16: + case NeonTypeFlags::Poly16: + return shift ? 15 : (4 << IsQuad) - 1; + case NeonTypeFlags::Int32: + return shift ? 31 : (2 << IsQuad) - 1; + case NeonTypeFlags::Int64: + return shift ? 63 : (1 << IsQuad) - 1; + case NeonTypeFlags::Float16: + assert(!shift && "cannot shift float types!"); + return (4 << IsQuad) - 1; + case NeonTypeFlags::Float32: + assert(!shift && "cannot shift float types!"); + return (2 << IsQuad) - 1; + } + llvm_unreachable("Invalid NeonTypeFlag!"); +} + +/// getNeonEltType - Return the QualType corresponding to the elements of +/// the vector type specified by the NeonTypeFlags. This is used to check +/// the pointer arguments for Neon load/store intrinsics. +static QualType getNeonEltType(NeonTypeFlags Flags, ASTContext &Context) { + switch (Flags.getEltType()) { + case NeonTypeFlags::Int8: + return Flags.isUnsigned() ? Context.UnsignedCharTy : Context.SignedCharTy; + case NeonTypeFlags::Int16: + return Flags.isUnsigned() ? Context.UnsignedShortTy : Context.ShortTy; + case NeonTypeFlags::Int32: + return Flags.isUnsigned() ? Context.UnsignedIntTy : Context.IntTy; + case NeonTypeFlags::Int64: + return Flags.isUnsigned() ? Context.UnsignedLongLongTy : Context.LongLongTy; + case NeonTypeFlags::Poly8: + return Context.SignedCharTy; + case NeonTypeFlags::Poly16: + return Context.ShortTy; + case NeonTypeFlags::Float16: + return Context.UnsignedShortTy; + case NeonTypeFlags::Float32: + return Context.FloatTy; + } + llvm_unreachable("Invalid NeonTypeFlag!"); +} + +bool Sema::CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { + llvm::APSInt Result; + + unsigned mask = 0; + unsigned TV = 0; + int PtrArgNum = -1; + bool HasConstPtr = false; + switch (BuiltinID) { +#define GET_NEON_OVERLOAD_CHECK +#include "clang/Basic/arm_neon.inc" +#undef GET_NEON_OVERLOAD_CHECK + } + + // For NEON intrinsics which are overloaded on vector element type, validate + // the immediate which specifies which variant to emit. + unsigned ImmArg = TheCall->getNumArgs()-1; + if (mask) { + if (SemaBuiltinConstantArg(TheCall, ImmArg, Result)) + return true; + + TV = Result.getLimitedValue(64); + if ((TV > 63) || (mask & (1 << TV)) == 0) + return Diag(TheCall->getLocStart(), diag::err_invalid_neon_type_code) + << TheCall->getArg(ImmArg)->getSourceRange(); + } + + if (PtrArgNum >= 0) { + // Check that pointer arguments have the specified type. + Expr *Arg = TheCall->getArg(PtrArgNum); + if (ImplicitCastExpr *ICE = dyn_cast(Arg)) + Arg = ICE->getSubExpr(); + ExprResult RHS = DefaultFunctionArrayLvalueConversion(Arg); + QualType RHSTy = RHS.get()->getType(); + QualType EltTy = getNeonEltType(NeonTypeFlags(TV), Context); + if (HasConstPtr) + EltTy = EltTy.withConst(); + QualType LHSTy = Context.getPointerType(EltTy); + AssignConvertType ConvTy; + ConvTy = CheckSingleAssignmentConstraints(LHSTy, RHS); + if (RHS.isInvalid()) + return true; + if (DiagnoseAssignmentResult(ConvTy, Arg->getLocStart(), LHSTy, RHSTy, + RHS.get(), AA_Assigning)) + return true; + } + + // For NEON intrinsics which take an immediate value as part of the + // instruction, range check them here. + 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 + }; + + // Check that the immediate argument is actually a constant. + if (SemaBuiltinConstantArg(TheCall, i, Result)) + return true; + + // Range check against the upper/lower values for this isntruction. + unsigned Val = Result.getZExtValue(); + if (Val < l || Val > (u + l)) + return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range) + << l << u+l << TheCall->getArg(i)->getSourceRange(); + + // FIXME: VFP Intrinsics should error if VFP not present. + return false; +} + +/// CheckFunctionCall - Check a direct function call for various correctness +/// and safety properties not strictly enforced by the C type system. +bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) { + // Get the IdentifierInfo* for the called function. + IdentifierInfo *FnInfo = FDecl->getIdentifier(); + + // None of the checks below are needed for functions that don't have + // simple names (e.g., C++ conversion functions). + if (!FnInfo) + return false; + + // FIXME: This mechanism should be abstracted to be less fragile and + // more efficient. For example, just map function ids to custom + // handlers. + + // Printf and scanf checking. + for (specific_attr_iterator + i = FDecl->specific_attr_begin(), + e = FDecl->specific_attr_end(); i != e ; ++i) { + CheckFormatArguments(*i, TheCall); + } + + for (specific_attr_iterator + i = FDecl->specific_attr_begin(), + e = FDecl->specific_attr_end(); i != e; ++i) { + CheckNonNullArguments(*i, TheCall->getArgs(), + TheCall->getCallee()->getLocStart()); + } + + unsigned CMId = FDecl->getMemoryFunctionKind(); + if (CMId == 0) + return false; + + // Handle memory setting and copying functions. + if (CMId == Builtin::BIstrlcpy || CMId == Builtin::BIstrlcat) + CheckStrlcpycatArguments(TheCall, FnInfo); + else if (CMId == Builtin::BIstrncat) + CheckStrncatArguments(TheCall, FnInfo); + else + CheckMemaccessArguments(TheCall, CMId, FnInfo); + + return false; +} + +bool Sema::CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation lbrac, + Expr **Args, unsigned NumArgs) { + for (specific_attr_iterator + i = Method->specific_attr_begin(), + e = Method->specific_attr_end(); i != e ; ++i) { + + CheckFormatArguments(*i, Args, NumArgs, false, lbrac, + Method->getSourceRange()); + } + + // diagnose nonnull arguments. + for (specific_attr_iterator + i = Method->specific_attr_begin(), + e = Method->specific_attr_end(); i != e; ++i) { + CheckNonNullArguments(*i, Args, lbrac); + } + + return false; +} + +bool Sema::CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall) { + const VarDecl *V = dyn_cast(NDecl); + if (!V) + return false; + + QualType Ty = V->getType(); + if (!Ty->isBlockPointerType()) + return false; + + // format string checking. + for (specific_attr_iterator + i = NDecl->specific_attr_begin(), + e = NDecl->specific_attr_end(); i != e ; ++i) { + CheckFormatArguments(*i, TheCall); + } + + return false; +} + +ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, + AtomicExpr::AtomicOp Op) { + CallExpr *TheCall = cast(TheCallResult.get()); + DeclRefExpr *DRE =cast(TheCall->getCallee()->IgnoreParenCasts()); + + // All these operations take one of the following forms: + enum { + // C __c11_atomic_init(A *, C) + Init, + // C __c11_atomic_load(A *, int) + Load, + // void __atomic_load(A *, CP, int) + Copy, + // C __c11_atomic_add(A *, M, int) + Arithmetic, + // C __atomic_exchange_n(A *, CP, int) + Xchg, + // void __atomic_exchange(A *, C *, CP, int) + GNUXchg, + // bool __c11_atomic_compare_exchange_strong(A *, C *, CP, int, int) + C11CmpXchg, + // bool __atomic_compare_exchange(A *, C *, CP, bool, int, int) + GNUCmpXchg + } Form = Init; + const unsigned NumArgs[] = { 2, 2, 3, 3, 3, 4, 5, 6 }; + const unsigned NumVals[] = { 1, 0, 1, 1, 1, 2, 2, 3 }; + // where: + // C is an appropriate type, + // A is volatile _Atomic(C) for __c11 builtins and is C for GNU builtins, + // CP is C for __c11 builtins and GNU _n builtins and is C * otherwise, + // M is C if C is an integer, and ptrdiff_t if C is a pointer, and + // the int parameters are for orderings. + + assert(AtomicExpr::AO__c11_atomic_init == 0 && + AtomicExpr::AO__c11_atomic_fetch_xor + 1 == AtomicExpr::AO__atomic_load + && "need to update code for modified C11 atomics"); + bool IsC11 = Op >= AtomicExpr::AO__c11_atomic_init && + Op <= AtomicExpr::AO__c11_atomic_fetch_xor; + bool IsN = Op == AtomicExpr::AO__atomic_load_n || + Op == AtomicExpr::AO__atomic_store_n || + Op == AtomicExpr::AO__atomic_exchange_n || + Op == AtomicExpr::AO__atomic_compare_exchange_n; + bool IsAddSub = false; + + switch (Op) { + case AtomicExpr::AO__c11_atomic_init: + Form = Init; + break; + + case AtomicExpr::AO__c11_atomic_load: + case AtomicExpr::AO__atomic_load_n: + Form = Load; + break; + + case AtomicExpr::AO__c11_atomic_store: + case AtomicExpr::AO__atomic_load: + case AtomicExpr::AO__atomic_store: + case AtomicExpr::AO__atomic_store_n: + Form = Copy; + break; + + case AtomicExpr::AO__c11_atomic_fetch_add: + case AtomicExpr::AO__c11_atomic_fetch_sub: + case AtomicExpr::AO__atomic_fetch_add: + case AtomicExpr::AO__atomic_fetch_sub: + case AtomicExpr::AO__atomic_add_fetch: + case AtomicExpr::AO__atomic_sub_fetch: + IsAddSub = true; + // Fall through. + case AtomicExpr::AO__c11_atomic_fetch_and: + case AtomicExpr::AO__c11_atomic_fetch_or: + case AtomicExpr::AO__c11_atomic_fetch_xor: + case AtomicExpr::AO__atomic_fetch_and: + case AtomicExpr::AO__atomic_fetch_or: + case AtomicExpr::AO__atomic_fetch_xor: + case AtomicExpr::AO__atomic_fetch_nand: + case AtomicExpr::AO__atomic_and_fetch: + case AtomicExpr::AO__atomic_or_fetch: + case AtomicExpr::AO__atomic_xor_fetch: + case AtomicExpr::AO__atomic_nand_fetch: + Form = Arithmetic; + break; + + case AtomicExpr::AO__c11_atomic_exchange: + case AtomicExpr::AO__atomic_exchange_n: + Form = Xchg; + break; + + case AtomicExpr::AO__atomic_exchange: + Form = GNUXchg; + break; + + case AtomicExpr::AO__c11_atomic_compare_exchange_strong: + case AtomicExpr::AO__c11_atomic_compare_exchange_weak: + Form = C11CmpXchg; + break; + + case AtomicExpr::AO__atomic_compare_exchange: + case AtomicExpr::AO__atomic_compare_exchange_n: + Form = GNUCmpXchg; + break; + } + + // Check we have the right number of arguments. + if (TheCall->getNumArgs() < NumArgs[Form]) { + Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args) + << 0 << NumArgs[Form] << TheCall->getNumArgs() + << TheCall->getCallee()->getSourceRange(); + return ExprError(); + } else if (TheCall->getNumArgs() > NumArgs[Form]) { + Diag(TheCall->getArg(NumArgs[Form])->getLocStart(), + diag::err_typecheck_call_too_many_args) + << 0 << NumArgs[Form] << TheCall->getNumArgs() + << TheCall->getCallee()->getSourceRange(); + return ExprError(); + } + + // Inspect the first argument of the atomic operation. + Expr *Ptr = TheCall->getArg(0); + Ptr = DefaultFunctionArrayLvalueConversion(Ptr).get(); + const PointerType *pointerType = Ptr->getType()->getAs(); + if (!pointerType) { + Diag(DRE->getLocStart(), diag::err_atomic_builtin_must_be_pointer) + << Ptr->getType() << Ptr->getSourceRange(); + return ExprError(); + } + + // For a __c11 builtin, this should be a pointer to an _Atomic type. + QualType AtomTy = pointerType->getPointeeType(); // 'A' + QualType ValType = AtomTy; // 'C' + if (IsC11) { + if (!AtomTy->isAtomicType()) { + Diag(DRE->getLocStart(), diag::err_atomic_op_needs_atomic) + << Ptr->getType() << Ptr->getSourceRange(); + return ExprError(); + } + ValType = AtomTy->getAs()->getValueType(); + } + + // For an arithmetic operation, the implied arithmetic must be well-formed. + if (Form == Arithmetic) { + // gcc does not enforce these rules for GNU atomics, but we do so for sanity. + if (IsAddSub && !ValType->isIntegerType() && !ValType->isPointerType()) { + Diag(DRE->getLocStart(), diag::err_atomic_op_needs_atomic_int_or_ptr) + << IsC11 << Ptr->getType() << Ptr->getSourceRange(); + return ExprError(); + } + if (!IsAddSub && !ValType->isIntegerType()) { + Diag(DRE->getLocStart(), diag::err_atomic_op_bitwise_needs_atomic_int) + << IsC11 << Ptr->getType() << Ptr->getSourceRange(); + return ExprError(); + } + } else if (IsN && !ValType->isIntegerType() && !ValType->isPointerType()) { + // For __atomic_*_n operations, the value type must be a scalar integral or + // pointer type which is 1, 2, 4, 8 or 16 bytes in length. + Diag(DRE->getLocStart(), diag::err_atomic_op_needs_atomic_int_or_ptr) + << IsC11 << Ptr->getType() << Ptr->getSourceRange(); + return ExprError(); + } + + if (!IsC11 && !AtomTy.isTriviallyCopyableType(Context)) { + // For GNU atomics, require a trivially-copyable type. This is not part of + // the GNU atomics specification, but we enforce it for sanity. + Diag(DRE->getLocStart(), diag::err_atomic_op_needs_trivial_copy) + << Ptr->getType() << Ptr->getSourceRange(); + return ExprError(); + } + + // FIXME: For any builtin other than a load, the ValType must not be + // const-qualified. + + switch (ValType.getObjCLifetime()) { + case Qualifiers::OCL_None: + case Qualifiers::OCL_ExplicitNone: + // okay + break; + + case Qualifiers::OCL_Weak: + case Qualifiers::OCL_Strong: + case Qualifiers::OCL_Autoreleasing: + // FIXME: Can this happen? By this point, ValType should be known + // to be trivially copyable. + Diag(DRE->getLocStart(), diag::err_arc_atomic_ownership) + << ValType << Ptr->getSourceRange(); + return ExprError(); + } + + QualType ResultType = ValType; + if (Form == Copy || Form == GNUXchg || Form == Init) + ResultType = Context.VoidTy; + else if (Form == C11CmpXchg || Form == GNUCmpXchg) + ResultType = Context.BoolTy; + + // The type of a parameter passed 'by value'. In the GNU atomics, such + // arguments are actually passed as pointers. + QualType ByValType = ValType; // 'CP' + if (!IsC11 && !IsN) + ByValType = Ptr->getType(); + + // 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 = 1; i != NumArgs[Form]; ++i) { + QualType Ty; + if (i < NumVals[Form] + 1) { + switch (i) { + case 1: + // The second argument is the non-atomic operand. For arithmetic, this + // is always passed by value, and for a compare_exchange it is always + // passed by address. For the rest, GNU uses by-address and C11 uses + // by-value. + assert(Form != Load); + if (Form == Init || (Form == Arithmetic && ValType->isIntegerType())) + Ty = ValType; + else if (Form == Copy || Form == Xchg) + Ty = ByValType; + else if (Form == Arithmetic) + Ty = Context.getPointerDiffType(); + else + Ty = Context.getPointerType(ValType.getUnqualifiedType()); + break; + case 2: + // The third argument to compare_exchange / GNU exchange is a + // (pointer to a) desired value. + Ty = ByValType; + break; + case 3: + // The fourth argument to GNU compare_exchange is a 'weak' flag. + Ty = Context.BoolTy; + break; + } + } else { + // The order(s) are always converted to int. + Ty = Context.IntTy; + } + + InitializedEntity Entity = + InitializedEntity::InitializeParameter(Context, Ty, false); + ExprResult Arg = TheCall->getArg(i); + Arg = PerformCopyInitialization(Entity, SourceLocation(), Arg); + if (Arg.isInvalid()) + return true; + TheCall->setArg(i, Arg.get()); + } + + // Permute the arguments into a 'consistent' order. + SmallVector SubExprs; + SubExprs.push_back(Ptr); + switch (Form) { + case Init: + // Note, AtomicExpr::getVal1() has a special case for this atomic. + SubExprs.push_back(TheCall->getArg(1)); // Val1 + break; + case Load: + SubExprs.push_back(TheCall->getArg(1)); // Order + break; + case Copy: + case Arithmetic: + case Xchg: + SubExprs.push_back(TheCall->getArg(2)); // Order + SubExprs.push_back(TheCall->getArg(1)); // Val1 + break; + case GNUXchg: + // Note, AtomicExpr::getVal2() has a special case for this atomic. + SubExprs.push_back(TheCall->getArg(3)); // Order + SubExprs.push_back(TheCall->getArg(1)); // Val1 + SubExprs.push_back(TheCall->getArg(2)); // Val2 + break; + case C11CmpXchg: + SubExprs.push_back(TheCall->getArg(3)); // Order + SubExprs.push_back(TheCall->getArg(1)); // Val1 + SubExprs.push_back(TheCall->getArg(4)); // OrderFail + SubExprs.push_back(TheCall->getArg(2)); // Val2 + break; + case GNUCmpXchg: + SubExprs.push_back(TheCall->getArg(4)); // Order + SubExprs.push_back(TheCall->getArg(1)); // Val1 + SubExprs.push_back(TheCall->getArg(5)); // OrderFail + SubExprs.push_back(TheCall->getArg(2)); // Val2 + SubExprs.push_back(TheCall->getArg(3)); // Weak + break; + } + + return Owned(new (Context) AtomicExpr(TheCall->getCallee()->getLocStart(), + SubExprs.data(), SubExprs.size(), + ResultType, Op, + TheCall->getRParenLoc())); +} + + +/// checkBuiltinArgument - Given a call to a builtin function, perform +/// normal type-checking on the given argument, updating the call in +/// place. This is useful when a builtin function requires custom +/// type-checking for some of its arguments but not necessarily all of +/// them. +/// +/// Returns true on error. +static bool checkBuiltinArgument(Sema &S, CallExpr *E, unsigned ArgIndex) { + FunctionDecl *Fn = E->getDirectCallee(); + assert(Fn && "builtin call without direct callee!"); + + ParmVarDecl *Param = Fn->getParamDecl(ArgIndex); + InitializedEntity Entity = + InitializedEntity::InitializeParameter(S.Context, Param); + + ExprResult Arg = E->getArg(0); + Arg = S.PerformCopyInitialization(Entity, SourceLocation(), Arg); + if (Arg.isInvalid()) + return true; + + E->setArg(ArgIndex, Arg.take()); + return false; +} + +/// SemaBuiltinAtomicOverloaded - We have a call to a function like +/// __sync_fetch_and_add, which is an overloaded function based on the pointer +/// type of its first argument. The main ActOnCallExpr routines have already +/// promoted the types of arguments because all of these calls are prototyped as +/// void(...). +/// +/// This function goes through and does final semantic checking for these +/// builtins, +ExprResult +Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) { + CallExpr *TheCall = (CallExpr *)TheCallResult.get(); + DeclRefExpr *DRE =cast(TheCall->getCallee()->IgnoreParenCasts()); + FunctionDecl *FDecl = cast(DRE->getDecl()); + + // Ensure that we have at least one argument to do type inference from. + if (TheCall->getNumArgs() < 1) { + Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args_at_least) + << 0 << 1 << TheCall->getNumArgs() + << TheCall->getCallee()->getSourceRange(); + return ExprError(); + } + + // Inspect the first argument of the atomic builtin. This should always be + // a pointer type, whose element is an integral scalar or pointer type. + // Because it is a pointer type, we don't have to worry about any implicit + // casts here. + // FIXME: We don't allow floating point scalars as input. + Expr *FirstArg = TheCall->getArg(0); + ExprResult FirstArgResult = DefaultFunctionArrayLvalueConversion(FirstArg); + if (FirstArgResult.isInvalid()) + return ExprError(); + FirstArg = FirstArgResult.take(); + TheCall->setArg(0, FirstArg); + + const PointerType *pointerType = FirstArg->getType()->getAs(); + if (!pointerType) { + Diag(DRE->getLocStart(), diag::err_atomic_builtin_must_be_pointer) + << FirstArg->getType() << FirstArg->getSourceRange(); + return ExprError(); + } + + QualType ValType = pointerType->getPointeeType(); + if (!ValType->isIntegerType() && !ValType->isAnyPointerType() && + !ValType->isBlockPointerType()) { + Diag(DRE->getLocStart(), diag::err_atomic_builtin_must_be_pointer_intptr) + << FirstArg->getType() << FirstArg->getSourceRange(); + return ExprError(); + } + + switch (ValType.getObjCLifetime()) { + case Qualifiers::OCL_None: + case Qualifiers::OCL_ExplicitNone: + // okay + break; + + case Qualifiers::OCL_Weak: + case Qualifiers::OCL_Strong: + case Qualifiers::OCL_Autoreleasing: + Diag(DRE->getLocStart(), diag::err_arc_atomic_ownership) + << ValType << FirstArg->getSourceRange(); + return ExprError(); + } + + // Strip any qualifiers off ValType. + ValType = ValType.getUnqualifiedType(); + + // 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. +#define BUILTIN_ROW(x) \ + { Builtin::BI##x##_1, Builtin::BI##x##_2, Builtin::BI##x##_4, \ + Builtin::BI##x##_8, Builtin::BI##x##_16 } + + static const unsigned BuiltinIndices[][5] = { + BUILTIN_ROW(__sync_fetch_and_add), + BUILTIN_ROW(__sync_fetch_and_sub), + BUILTIN_ROW(__sync_fetch_and_or), + BUILTIN_ROW(__sync_fetch_and_and), + BUILTIN_ROW(__sync_fetch_and_xor), + + BUILTIN_ROW(__sync_add_and_fetch), + BUILTIN_ROW(__sync_sub_and_fetch), + BUILTIN_ROW(__sync_and_and_fetch), + BUILTIN_ROW(__sync_or_and_fetch), + BUILTIN_ROW(__sync_xor_and_fetch), + + BUILTIN_ROW(__sync_val_compare_and_swap), + BUILTIN_ROW(__sync_bool_compare_and_swap), + BUILTIN_ROW(__sync_lock_test_and_set), + BUILTIN_ROW(__sync_lock_release), + BUILTIN_ROW(__sync_swap) + }; +#undef BUILTIN_ROW + + // Determine the index of the size. + unsigned SizeIndex; + switch (Context.getTypeSizeInChars(ValType).getQuantity()) { + case 1: SizeIndex = 0; break; + case 2: SizeIndex = 1; break; + case 4: SizeIndex = 2; break; + case 8: SizeIndex = 3; break; + case 16: SizeIndex = 4; break; + default: + Diag(DRE->getLocStart(), diag::err_atomic_builtin_pointer_size) + << FirstArg->getType() << FirstArg->getSourceRange(); + return ExprError(); + } + + // Each of these builtins has one pointer argument, followed by some number of + // values (0, 1 or 2) followed by a potentially empty varags list of stuff + // that we ignore. Find out which row of BuiltinIndices to read from as well + // as the number of fixed args. + unsigned BuiltinID = FDecl->getBuiltinID(); + unsigned BuiltinIndex, NumFixed = 1; + switch (BuiltinID) { + default: llvm_unreachable("Unknown overloaded atomic builtin!"); + case Builtin::BI__sync_fetch_and_add: + case Builtin::BI__sync_fetch_and_add_1: + case Builtin::BI__sync_fetch_and_add_2: + case Builtin::BI__sync_fetch_and_add_4: + case Builtin::BI__sync_fetch_and_add_8: + case Builtin::BI__sync_fetch_and_add_16: + BuiltinIndex = 0; + break; + + case Builtin::BI__sync_fetch_and_sub: + case Builtin::BI__sync_fetch_and_sub_1: + case Builtin::BI__sync_fetch_and_sub_2: + case Builtin::BI__sync_fetch_and_sub_4: + case Builtin::BI__sync_fetch_and_sub_8: + case Builtin::BI__sync_fetch_and_sub_16: + BuiltinIndex = 1; + break; + + case Builtin::BI__sync_fetch_and_or: + case Builtin::BI__sync_fetch_and_or_1: + case Builtin::BI__sync_fetch_and_or_2: + case Builtin::BI__sync_fetch_and_or_4: + case Builtin::BI__sync_fetch_and_or_8: + case Builtin::BI__sync_fetch_and_or_16: + BuiltinIndex = 2; + break; + + case Builtin::BI__sync_fetch_and_and: + case Builtin::BI__sync_fetch_and_and_1: + case Builtin::BI__sync_fetch_and_and_2: + case Builtin::BI__sync_fetch_and_and_4: + case Builtin::BI__sync_fetch_and_and_8: + case Builtin::BI__sync_fetch_and_and_16: + BuiltinIndex = 3; + break; + + case Builtin::BI__sync_fetch_and_xor: + case Builtin::BI__sync_fetch_and_xor_1: + case Builtin::BI__sync_fetch_and_xor_2: + case Builtin::BI__sync_fetch_and_xor_4: + case Builtin::BI__sync_fetch_and_xor_8: + case Builtin::BI__sync_fetch_and_xor_16: + BuiltinIndex = 4; + break; + + case Builtin::BI__sync_add_and_fetch: + case Builtin::BI__sync_add_and_fetch_1: + case Builtin::BI__sync_add_and_fetch_2: + case Builtin::BI__sync_add_and_fetch_4: + case Builtin::BI__sync_add_and_fetch_8: + case Builtin::BI__sync_add_and_fetch_16: + BuiltinIndex = 5; + break; + + case Builtin::BI__sync_sub_and_fetch: + case Builtin::BI__sync_sub_and_fetch_1: + case Builtin::BI__sync_sub_and_fetch_2: + case Builtin::BI__sync_sub_and_fetch_4: + case Builtin::BI__sync_sub_and_fetch_8: + case Builtin::BI__sync_sub_and_fetch_16: + BuiltinIndex = 6; + break; + + case Builtin::BI__sync_and_and_fetch: + case Builtin::BI__sync_and_and_fetch_1: + case Builtin::BI__sync_and_and_fetch_2: + case Builtin::BI__sync_and_and_fetch_4: + case Builtin::BI__sync_and_and_fetch_8: + case Builtin::BI__sync_and_and_fetch_16: + BuiltinIndex = 7; + break; + + case Builtin::BI__sync_or_and_fetch: + case Builtin::BI__sync_or_and_fetch_1: + case Builtin::BI__sync_or_and_fetch_2: + case Builtin::BI__sync_or_and_fetch_4: + case Builtin::BI__sync_or_and_fetch_8: + case Builtin::BI__sync_or_and_fetch_16: + BuiltinIndex = 8; + break; + + case Builtin::BI__sync_xor_and_fetch: + case Builtin::BI__sync_xor_and_fetch_1: + case Builtin::BI__sync_xor_and_fetch_2: + case Builtin::BI__sync_xor_and_fetch_4: + case Builtin::BI__sync_xor_and_fetch_8: + case Builtin::BI__sync_xor_and_fetch_16: + BuiltinIndex = 9; + break; + + case Builtin::BI__sync_val_compare_and_swap: + case Builtin::BI__sync_val_compare_and_swap_1: + case Builtin::BI__sync_val_compare_and_swap_2: + case Builtin::BI__sync_val_compare_and_swap_4: + case Builtin::BI__sync_val_compare_and_swap_8: + case Builtin::BI__sync_val_compare_and_swap_16: + BuiltinIndex = 10; + NumFixed = 2; + break; + + case Builtin::BI__sync_bool_compare_and_swap: + case Builtin::BI__sync_bool_compare_and_swap_1: + case Builtin::BI__sync_bool_compare_and_swap_2: + case Builtin::BI__sync_bool_compare_and_swap_4: + case Builtin::BI__sync_bool_compare_and_swap_8: + case Builtin::BI__sync_bool_compare_and_swap_16: + BuiltinIndex = 11; + NumFixed = 2; + ResultType = Context.BoolTy; + break; + + case Builtin::BI__sync_lock_test_and_set: + case Builtin::BI__sync_lock_test_and_set_1: + case Builtin::BI__sync_lock_test_and_set_2: + case Builtin::BI__sync_lock_test_and_set_4: + case Builtin::BI__sync_lock_test_and_set_8: + case Builtin::BI__sync_lock_test_and_set_16: + BuiltinIndex = 12; + break; + + case Builtin::BI__sync_lock_release: + case Builtin::BI__sync_lock_release_1: + case Builtin::BI__sync_lock_release_2: + case Builtin::BI__sync_lock_release_4: + case Builtin::BI__sync_lock_release_8: + case Builtin::BI__sync_lock_release_16: + BuiltinIndex = 13; + NumFixed = 0; + ResultType = Context.VoidTy; + break; + + case Builtin::BI__sync_swap: + case Builtin::BI__sync_swap_1: + case Builtin::BI__sync_swap_2: + case Builtin::BI__sync_swap_4: + case Builtin::BI__sync_swap_8: + case Builtin::BI__sync_swap_16: + BuiltinIndex = 14; + break; + } + + // Now that we know how many fixed arguments we expect, first check that we + // have at least that many. + if (TheCall->getNumArgs() < 1+NumFixed) { + Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args_at_least) + << 0 << 1+NumFixed << TheCall->getNumArgs() + << TheCall->getCallee()->getSourceRange(); + return ExprError(); + } + + // Get the decl for the concrete builtin from this, we can tell what the + // concrete integer type we should convert to is. + unsigned NewBuiltinID = BuiltinIndices[BuiltinIndex][SizeIndex]; + const char *NewBuiltinName = Context.BuiltinInfo.GetName(NewBuiltinID); + IdentifierInfo *NewBuiltinII = PP.getIdentifierInfo(NewBuiltinName); + FunctionDecl *NewBuiltinDecl = + cast(LazilyCreateBuiltin(NewBuiltinII, NewBuiltinID, + TUScope, false, DRE->getLocStart())); + + // 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) { + ExprResult Arg = TheCall->getArg(i+1); + + // 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. + // Initialize the argument. + InitializedEntity Entity = InitializedEntity::InitializeParameter(Context, + ValType, /*consume*/ false); + Arg = PerformCopyInitialization(Entity, SourceLocation(), Arg); + if (Arg.isInvalid()) + return ExprError(); + + // Okay, we have something that *can* be converted to the right type. Check + // to see if there is a potentially weird extension going on here. This can + // happen when you do an atomic operation on something like an char* and + // 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. + TheCall->setArg(i+1, Arg.take()); + } + + ASTContext& Context = this->getASTContext(); + + // Create a new DeclRefExpr to refer to the new decl. + DeclRefExpr* NewDRE = DeclRefExpr::Create( + Context, + DRE->getQualifierLoc(), + SourceLocation(), + NewBuiltinDecl, + /*enclosing*/ false, + DRE->getLocation(), + NewBuiltinDecl->getType(), + DRE->getValueKind()); + + // Set the callee in the CallExpr. + // FIXME: This leaks the original parens and implicit casts. + ExprResult PromotedCall = UsualUnaryConversions(NewDRE); + if (PromotedCall.isInvalid()) + return ExprError(); + TheCall->setCallee(PromotedCall.take()); + + // 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); +} + +/// CheckObjCString - Checks that the argument to the builtin +/// CFString constructor is correct +/// Note: It might also make sense to do the UTF-16 conversion here (would +/// simplify the backend). +bool Sema::CheckObjCString(Expr *Arg) { + Arg = Arg->IgnoreParenCasts(); + StringLiteral *Literal = dyn_cast(Arg); + + if (!Literal || !Literal->isAscii()) { + Diag(Arg->getLocStart(), diag::err_cfstring_literal_not_string_constant) + << Arg->getSourceRange(); + return true; + } + + if (Literal->containsNonAsciiOrNull()) { + StringRef String = Literal->getString(); + unsigned NumBytes = String.size(); + SmallVector ToBuf(NumBytes); + const UTF8 *FromPtr = (UTF8 *)String.data(); + UTF16 *ToPtr = &ToBuf[0]; + + ConversionResult Result = ConvertUTF8toUTF16(&FromPtr, FromPtr + NumBytes, + &ToPtr, ToPtr + NumBytes, + strictConversion); + // Check for conversion failure. + if (Result != conversionOK) + Diag(Arg->getLocStart(), + diag::warn_cfstring_truncated) << Arg->getSourceRange(); + } + return false; +} + +/// SemaBuiltinVAStart - Check the arguments to __builtin_va_start for validity. +/// Emit an error and return true on failure, return false on success. +bool Sema::SemaBuiltinVAStart(CallExpr *TheCall) { + Expr *Fn = TheCall->getCallee(); + if (TheCall->getNumArgs() > 2) { + Diag(TheCall->getArg(2)->getLocStart(), + diag::err_typecheck_call_too_many_args) + << 0 /*function call*/ << 2 << TheCall->getNumArgs() + << Fn->getSourceRange() + << SourceRange(TheCall->getArg(2)->getLocStart(), + (*(TheCall->arg_end()-1))->getLocEnd()); + return true; + } + + if (TheCall->getNumArgs() < 2) { + return Diag(TheCall->getLocEnd(), + diag::err_typecheck_call_too_few_args_at_least) + << 0 /*function call*/ << 2 << TheCall->getNumArgs(); + } + + // Type-check the first argument normally. + if (checkBuiltinArgument(*this, TheCall, 0)) + return true; + + // Determine whether the current function is variadic or not. + BlockScopeInfo *CurBlock = getCurBlock(); + bool isVariadic; + if (CurBlock) + isVariadic = CurBlock->TheDecl->isVariadic(); + else if (FunctionDecl *FD = getCurFunctionDecl()) + isVariadic = FD->isVariadic(); + else + isVariadic = getCurMethodDecl()->isVariadic(); + + if (!isVariadic) { + Diag(Fn->getLocStart(), diag::err_va_start_used_in_non_variadic_function); + return true; + } + + // Verify that the second argument to the builtin is the last argument of the + // current function or method. + bool SecondArgIsLastNamedArgument = false; + const Expr *Arg = TheCall->getArg(1)->IgnoreParenCasts(); + + if (const DeclRefExpr *DR = dyn_cast(Arg)) { + if (const ParmVarDecl *PV = dyn_cast(DR->getDecl())) { + // FIXME: This isn't correct for methods (results in bogus warning). + // Get the last formal in the current function. + const ParmVarDecl *LastArg; + if (CurBlock) + LastArg = *(CurBlock->TheDecl->param_end()-1); + else if (FunctionDecl *FD = getCurFunctionDecl()) + LastArg = *(FD->param_end()-1); + else + LastArg = *(getCurMethodDecl()->param_end()-1); + SecondArgIsLastNamedArgument = PV == LastArg; + } + } + + if (!SecondArgIsLastNamedArgument) + Diag(TheCall->getArg(1)->getLocStart(), + diag::warn_second_parameter_of_va_start_not_last_named_argument); + return false; +} + +/// SemaBuiltinUnorderedCompare - Handle functions like __builtin_isgreater and +/// friends. This is declared to take (...), so we have to check everything. +bool Sema::SemaBuiltinUnorderedCompare(CallExpr *TheCall) { + if (TheCall->getNumArgs() < 2) + return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args) + << 0 << 2 << TheCall->getNumArgs()/*function call*/; + if (TheCall->getNumArgs() > 2) + return Diag(TheCall->getArg(2)->getLocStart(), + diag::err_typecheck_call_too_many_args) + << 0 /*function call*/ << 2 << TheCall->getNumArgs() + << SourceRange(TheCall->getArg(2)->getLocStart(), + (*(TheCall->arg_end()-1))->getLocEnd()); + + ExprResult OrigArg0 = TheCall->getArg(0); + ExprResult OrigArg1 = TheCall->getArg(1); + + // Do standard promotions between the two arguments, returning their common + // type. + QualType Res = UsualArithmeticConversions(OrigArg0, OrigArg1, false); + if (OrigArg0.isInvalid() || OrigArg1.isInvalid()) + return true; + + // Make sure any conversions are pushed back into the call; this is + // type safe since unordered compare builtins are declared as "_Bool + // foo(...)". + TheCall->setArg(0, OrigArg0.get()); + TheCall->setArg(1, OrigArg1.get()); + + if (OrigArg0.get()->isTypeDependent() || OrigArg1.get()->isTypeDependent()) + return false; + + // If the common type isn't a real floating type, then the arguments were + // invalid for this operation. + if (!Res->isRealFloatingType()) + return Diag(OrigArg0.get()->getLocStart(), + diag::err_typecheck_call_invalid_ordered_compare) + << OrigArg0.get()->getType() << OrigArg1.get()->getType() + << SourceRange(OrigArg0.get()->getLocStart(), OrigArg1.get()->getLocEnd()); + + return false; +} + +/// SemaBuiltinSemaBuiltinFPClassification - Handle functions like +/// __builtin_isnan and friends. This is declared to take (...), so we have +/// to check everything. We expect the last argument to be a floating point +/// value. +bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs) { + if (TheCall->getNumArgs() < NumArgs) + return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args) + << 0 << NumArgs << TheCall->getNumArgs()/*function call*/; + if (TheCall->getNumArgs() > NumArgs) + return Diag(TheCall->getArg(NumArgs)->getLocStart(), + diag::err_typecheck_call_too_many_args) + << 0 /*function call*/ << NumArgs << TheCall->getNumArgs() + << SourceRange(TheCall->getArg(NumArgs)->getLocStart(), + (*(TheCall->arg_end()-1))->getLocEnd()); + + Expr *OrigArg = TheCall->getArg(NumArgs-1); + + if (OrigArg->isTypeDependent()) + return false; + + // This operation requires a non-_Complex floating-point number. + if (!OrigArg->getType()->isRealFloatingType()) + return Diag(OrigArg->getLocStart(), + diag::err_typecheck_call_invalid_unary_fp) + << OrigArg->getType() << OrigArg->getSourceRange(); + + // If this is an implicit conversion from float -> double, remove it. + if (ImplicitCastExpr *Cast = dyn_cast(OrigArg)) { + Expr *CastArg = Cast->getSubExpr(); + if (CastArg->getType()->isSpecificBuiltinType(BuiltinType::Float)) { + assert(Cast->getType()->isSpecificBuiltinType(BuiltinType::Double) && + "promotion from float to double is the only expected cast here"); + Cast->setSubExpr(0); + TheCall->setArg(NumArgs-1, CastArg); + } + } + + return false; +} + +/// SemaBuiltinShuffleVector - Handle __builtin_shufflevector. +// This is declared to take (...), so we have to check everything. +ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) { + if (TheCall->getNumArgs() < 2) + return ExprError(Diag(TheCall->getLocEnd(), + diag::err_typecheck_call_too_few_args_at_least) + << 0 /*function call*/ << 2 << TheCall->getNumArgs() + << TheCall->getSourceRange()); + + // Determine which of the following types of shufflevector we're checking: + // 1) unary, vector mask: (lhs, mask) + // 2) binary, vector mask: (lhs, rhs, mask) + // 3) binary, scalar mask: (lhs, rhs, index, ..., index) + QualType resType = TheCall->getArg(0)->getType(); + unsigned numElements = 0; + + if (!TheCall->getArg(0)->isTypeDependent() && + !TheCall->getArg(1)->isTypeDependent()) { + QualType LHSType = TheCall->getArg(0)->getType(); + QualType RHSType = TheCall->getArg(1)->getType(); + + if (!LHSType->isVectorType() || !RHSType->isVectorType()) { + Diag(TheCall->getLocStart(), diag::err_shufflevector_non_vector) + << SourceRange(TheCall->getArg(0)->getLocStart(), + TheCall->getArg(1)->getLocEnd()); + return ExprError(); + } + + numElements = LHSType->getAs()->getNumElements(); + unsigned numResElements = TheCall->getNumArgs() - 2; + + // Check to see if we have a call with 2 vector arguments, the unary shuffle + // 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->hasIntegerRepresentation() || + RHSType->getAs()->getNumElements() != numElements) + Diag(TheCall->getLocStart(), diag::err_shufflevector_incompatible_vector) + << SourceRange(TheCall->getArg(1)->getLocStart(), + TheCall->getArg(1)->getLocEnd()); + numResElements = numElements; + } + else if (!Context.hasSameUnqualifiedType(LHSType, RHSType)) { + Diag(TheCall->getLocStart(), diag::err_shufflevector_incompatible_vector) + << SourceRange(TheCall->getArg(0)->getLocStart(), + TheCall->getArg(1)->getLocEnd()); + return ExprError(); + } else if (numElements != numResElements) { + QualType eltType = LHSType->getAs()->getElementType(); + resType = Context.getVectorType(eltType, numResElements, + VectorType::GenericVector); + } + } + + for (unsigned i = 2; i < TheCall->getNumArgs(); i++) { + if (TheCall->getArg(i)->isTypeDependent() || + TheCall->getArg(i)->isValueDependent()) + continue; + + llvm::APSInt Result(32); + if (!TheCall->getArg(i)->isIntegerConstantExpr(Result, Context)) + return ExprError(Diag(TheCall->getLocStart(), + diag::err_shufflevector_nonconstant_argument) + << TheCall->getArg(i)->getSourceRange()); + + if (Result.getActiveBits() > 64 || Result.getZExtValue() >= numElements*2) + return ExprError(Diag(TheCall->getLocStart(), + diag::err_shufflevector_argument_too_large) + << TheCall->getArg(i)->getSourceRange()); + } + + SmallVector exprs; + + for (unsigned i = 0, e = TheCall->getNumArgs(); i != e; i++) { + exprs.push_back(TheCall->getArg(i)); + TheCall->setArg(i, 0); + } + + return Owned(new (Context) ShuffleVectorExpr(Context, exprs.begin(), + exprs.size(), resType, + TheCall->getCallee()->getLocStart(), + TheCall->getRParenLoc())); +} + +/// SemaBuiltinPrefetch - Handle __builtin_prefetch. +// This is declared to take (const void*, ...) and can take two +// optional constant int args. +bool Sema::SemaBuiltinPrefetch(CallExpr *TheCall) { + unsigned NumArgs = TheCall->getNumArgs(); + + if (NumArgs > 3) + return Diag(TheCall->getLocEnd(), + diag::err_typecheck_call_too_many_args_at_most) + << 0 /*function call*/ << 3 << NumArgs + << TheCall->getSourceRange(); + + // Argument 0 is checked for us and the remaining arguments must be + // constant integers. + for (unsigned i = 1; i != NumArgs; ++i) { + Expr *Arg = TheCall->getArg(i); + + llvm::APSInt Result; + if (SemaBuiltinConstantArg(TheCall, i, Result)) + return true; + + // FIXME: gcc issues a warning and rewrites these to 0. These + // seems especially odd for the third argument since the default + // is 3. + if (i == 1) { + if (Result.getLimitedValue() > 1) + return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range) + << "0" << "1" << Arg->getSourceRange(); + } else { + if (Result.getLimitedValue() > 3) + return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range) + << "0" << "3" << Arg->getSourceRange(); + } + } + + return false; +} + +/// SemaBuiltinConstantArg - Handle a check if argument ArgNum of CallExpr +/// TheCall is a constant expression. +bool Sema::SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum, + llvm::APSInt &Result) { + Expr *Arg = TheCall->getArg(ArgNum); + DeclRefExpr *DRE =cast(TheCall->getCallee()->IgnoreParenCasts()); + FunctionDecl *FDecl = cast(DRE->getDecl()); + + if (Arg->isTypeDependent() || Arg->isValueDependent()) return false; + + if (!Arg->isIntegerConstantExpr(Result, Context)) + return Diag(TheCall->getLocStart(), diag::err_constant_integer_arg_type) + << FDecl->getDeclName() << Arg->getSourceRange(); + + return false; +} + +/// SemaBuiltinObjectSize - Handle __builtin_object_size(void *ptr, +/// int type). This simply type checks that type is one of the defined +/// constants (0-3). +// For compatibility check 0-3, llvm only handles 0 and 2. +bool Sema::SemaBuiltinObjectSize(CallExpr *TheCall) { + llvm::APSInt Result; + + // Check constant-ness first. + if (SemaBuiltinConstantArg(TheCall, 1, Result)) + return true; + + Expr *Arg = TheCall->getArg(1); + if (Result.getSExtValue() < 0 || Result.getSExtValue() > 3) { + return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range) + << "0" << "3" << SourceRange(Arg->getLocStart(), Arg->getLocEnd()); + } + + return false; +} + +/// SemaBuiltinLongjmp - Handle __builtin_longjmp(void *env[5], int val). +/// This checks that val is a constant 1. +bool Sema::SemaBuiltinLongjmp(CallExpr *TheCall) { + Expr *Arg = TheCall->getArg(1); + llvm::APSInt Result; + + // TODO: This is less than ideal. Overload this to take a value. + if (SemaBuiltinConstantArg(TheCall, 1, Result)) + return true; + + if (Result != 1) + return Diag(TheCall->getLocStart(), diag::err_builtin_longjmp_invalid_val) + << SourceRange(Arg->getLocStart(), Arg->getLocEnd()); + + return false; +} + +// Handle i > 1 ? "x" : "y", recursively. +bool Sema::SemaCheckStringLiteral(const Expr *E, Expr **Args, + unsigned NumArgs, bool HasVAListArg, + unsigned format_idx, unsigned firstDataArg, + FormatStringType Type, bool inFunctionCall) { + tryAgain: + if (E->isTypeDependent() || E->isValueDependent()) + return false; + + E = E->IgnoreParenCasts(); + + if (E->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull)) + // Technically -Wformat-nonliteral does not warn about this case. + // The behavior of printf and friends in this case is implementation + // dependent. Ideally if the format string cannot be null then + // it should have a 'nonnull' attribute in the function prototype. + return true; + + switch (E->getStmtClass()) { + case Stmt::BinaryConditionalOperatorClass: + case Stmt::ConditionalOperatorClass: { + const AbstractConditionalOperator *C = cast(E); + return SemaCheckStringLiteral(C->getTrueExpr(), Args, NumArgs, HasVAListArg, + format_idx, firstDataArg, Type, + inFunctionCall) + && SemaCheckStringLiteral(C->getFalseExpr(), Args, NumArgs, HasVAListArg, + format_idx, firstDataArg, Type, + inFunctionCall); + } + + case Stmt::ImplicitCastExprClass: { + E = cast(E)->getSubExpr(); + goto tryAgain; + } + + case Stmt::OpaqueValueExprClass: + if (const Expr *src = cast(E)->getSourceExpr()) { + E = src; + goto tryAgain; + } + return false; + + case Stmt::PredefinedExprClass: + // While __func__, etc., are technically not string literals, they + // cannot contain format specifiers and thus are not a security + // liability. + return true; + + case Stmt::DeclRefExprClass: { + const DeclRefExpr *DR = cast(E); + + // As an exception, do not flag errors for variables binding to + // const string literals. + if (const VarDecl *VD = dyn_cast(DR->getDecl())) { + bool isConstant = false; + QualType T = DR->getType(); + + if (const ArrayType *AT = Context.getAsArrayType(T)) { + isConstant = AT->getElementType().isConstant(Context); + } else if (const PointerType *PT = T->getAs()) { + isConstant = T.isConstant(Context) && + PT->getPointeeType().isConstant(Context); + } else if (T->isObjCObjectPointerType()) { + // In ObjC, there is usually no "const ObjectPointer" type, + // so don't check if the pointee type is constant. + isConstant = T.isConstant(Context); + } + + if (isConstant) { + if (const Expr *Init = VD->getAnyInitializer()) + return SemaCheckStringLiteral(Init, Args, NumArgs, + HasVAListArg, format_idx, firstDataArg, + Type, /*inFunctionCall*/false); + } + + // For vprintf* functions (i.e., HasVAListArg==true), we add a + // special check to see if the format string is a function parameter + // of the function calling the printf function. If the function + // has an attribute indicating it is a printf-like function, then we + // should suppress warnings concerning non-literals being used in a call + // to a vprintf function. For example: + // + // void + // logmessage(char const *fmt __attribute__ (format (printf, 1, 2)), ...){ + // va_list ap; + // va_start(ap, fmt); + // vprintf(fmt, ap); // Do NOT emit a warning about "fmt". + // ... + // + if (HasVAListArg) { + if (const ParmVarDecl *PV = dyn_cast(VD)) { + if (const NamedDecl *ND = dyn_cast(PV->getDeclContext())) { + int PVIndex = PV->getFunctionScopeIndex() + 1; + for (specific_attr_iterator + i = ND->specific_attr_begin(), + e = ND->specific_attr_end(); i != e ; ++i) { + FormatAttr *PVFormat = *i; + // adjust for implicit parameter + if (const CXXMethodDecl *MD = dyn_cast(ND)) + if (MD->isInstance()) + ++PVIndex; + // We also check if the formats are compatible. + // We can't pass a 'scanf' string to a 'printf' function. + if (PVIndex == PVFormat->getFormatIdx() && + Type == GetFormatStringType(PVFormat)) + return true; + } + } + } + } + } + + return false; + } + + case Stmt::CallExprClass: + case Stmt::CXXMemberCallExprClass: { + const CallExpr *CE = cast(E); + if (const NamedDecl *ND = dyn_cast_or_null(CE->getCalleeDecl())) { + if (const FormatArgAttr *FA = ND->getAttr()) { + unsigned ArgIndex = FA->getFormatIdx(); + if (const CXXMethodDecl *MD = dyn_cast(ND)) + if (MD->isInstance()) + --ArgIndex; + const Expr *Arg = CE->getArg(ArgIndex - 1); + + return SemaCheckStringLiteral(Arg, Args, NumArgs, HasVAListArg, + format_idx, firstDataArg, Type, + inFunctionCall); + } + } + + return false; + } + case Stmt::ObjCStringLiteralClass: + case Stmt::StringLiteralClass: { + const StringLiteral *StrE = NULL; + + if (const ObjCStringLiteral *ObjCFExpr = dyn_cast(E)) + StrE = ObjCFExpr->getString(); + else + StrE = cast(E); + + if (StrE) { + CheckFormatString(StrE, E, Args, NumArgs, HasVAListArg, format_idx, + firstDataArg, Type, inFunctionCall); + return true; + } + + return false; + } + + default: + return false; + } +} + +void +Sema::CheckNonNullArguments(const NonNullAttr *NonNull, + const Expr * const *ExprArgs, + SourceLocation CallSiteLoc) { + for (NonNullAttr::args_iterator i = NonNull->args_begin(), + e = NonNull->args_end(); + i != e; ++i) { + const Expr *ArgExpr = ExprArgs[*i]; + if (ArgExpr->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNotNull)) + Diag(CallSiteLoc, diag::warn_null_arg) << ArgExpr->getSourceRange(); + } +} + +Sema::FormatStringType Sema::GetFormatStringType(const FormatAttr *Format) { + return llvm::StringSwitch(Format->getType()) + .Case("scanf", FST_Scanf) + .Cases("printf", "printf0", FST_Printf) + .Cases("NSString", "CFString", FST_NSString) + .Case("strftime", FST_Strftime) + .Case("strfmon", FST_Strfmon) + .Cases("kprintf", "cmn_err", "vcmn_err", "zcmn_err", FST_Kprintf) + .Default(FST_Unknown); +} + +/// CheckPrintfScanfArguments - Check calls to printf and scanf (and similar +/// functions) for correct use of format strings. +void Sema::CheckFormatArguments(const FormatAttr *Format, CallExpr *TheCall) { + bool IsCXXMember = false; + // The way the format attribute works in GCC, the implicit this argument + // of member functions is counted. However, it doesn't appear in our own + // lists, so decrement format_idx in that case. + IsCXXMember = isa(TheCall); + CheckFormatArguments(Format, TheCall->getArgs(), TheCall->getNumArgs(), + IsCXXMember, TheCall->getRParenLoc(), + TheCall->getCallee()->getSourceRange()); +} + +void Sema::CheckFormatArguments(const FormatAttr *Format, Expr **Args, + unsigned NumArgs, bool IsCXXMember, + SourceLocation Loc, SourceRange Range) { + bool HasVAListArg = Format->getFirstArg() == 0; + unsigned format_idx = Format->getFormatIdx() - 1; + unsigned firstDataArg = HasVAListArg ? 0 : Format->getFirstArg() - 1; + if (IsCXXMember) { + if (format_idx == 0) + return; + --format_idx; + if(firstDataArg != 0) + --firstDataArg; + } + CheckFormatArguments(Args, NumArgs, HasVAListArg, format_idx, + firstDataArg, GetFormatStringType(Format), Loc, Range); +} + +void Sema::CheckFormatArguments(Expr **Args, unsigned NumArgs, + bool HasVAListArg, unsigned format_idx, + unsigned firstDataArg, FormatStringType Type, + SourceLocation Loc, SourceRange Range) { + // CHECK: printf/scanf-like function is called with no format string. + if (format_idx >= NumArgs) { + Diag(Loc, diag::warn_missing_format_string) << Range; + return; + } + + const Expr *OrigFormatExpr = Args[format_idx]->IgnoreParenCasts(); + + // CHECK: format string is not a string literal. + // + // Dynamically generated format strings are difficult to + // automatically vet at compile time. Requiring that format strings + // are string literals: (1) permits the checking of format strings by + // the compiler and thereby (2) can practically remove the source of + // many format string exploits. + + // Format string can be either ObjC string (e.g. @"%d") or + // C string (e.g. "%d") + // 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, Args, NumArgs, HasVAListArg, + format_idx, firstDataArg, Type)) + return; // Literal format string found, check done! + + // Strftime is particular as it always uses a single 'time' argument, + // so it is safe to pass a non-literal string. + if (Type == FST_Strftime) + return; + + // Do not emit diag when the string param is a macro expansion and the + // format is either NSString or CFString. This is a hack to prevent + // diag when using the NSLocalizedString and CFCopyLocalizedString macros + // which are usually used in place of NS and CF string literals. + if (Type == FST_NSString && Args[format_idx]->getLocStart().isMacroID()) + return; + + // If there are no arguments specified, warn with -Wformat-security, otherwise + // warn only with -Wformat-nonliteral. + if (NumArgs == format_idx+1) + Diag(Args[format_idx]->getLocStart(), + diag::warn_format_nonliteral_noargs) + << OrigFormatExpr->getSourceRange(); + else + Diag(Args[format_idx]->getLocStart(), + diag::warn_format_nonliteral) + << OrigFormatExpr->getSourceRange(); +} + +namespace { +class CheckFormatHandler : public analyze_format_string::FormatStringHandler { +protected: + Sema &S; + const StringLiteral *FExpr; + const Expr *OrigFormatExpr; + const unsigned FirstDataArg; + const unsigned NumDataArgs; + const bool IsObjCLiteral; + const char *Beg; // Start of format string. + const bool HasVAListArg; + const Expr * const *Args; + const unsigned NumArgs; + unsigned FormatIdx; + llvm::BitVector CoveredArgs; + bool usesPositionalArgs; + bool atFirstArg; + bool inFunctionCall; +public: + CheckFormatHandler(Sema &s, const StringLiteral *fexpr, + const Expr *origFormatExpr, unsigned firstDataArg, + unsigned numDataArgs, bool isObjCLiteral, + const char *beg, bool hasVAListArg, + Expr **args, unsigned numArgs, + unsigned formatIdx, bool inFunctionCall) + : S(s), FExpr(fexpr), OrigFormatExpr(origFormatExpr), + FirstDataArg(firstDataArg), + NumDataArgs(numDataArgs), + IsObjCLiteral(isObjCLiteral), Beg(beg), + HasVAListArg(hasVAListArg), + Args(args), NumArgs(numArgs), FormatIdx(formatIdx), + usesPositionalArgs(false), atFirstArg(true), + inFunctionCall(inFunctionCall) { + CoveredArgs.resize(numDataArgs); + CoveredArgs.reset(); + } + + void DoneProcessing(); + + void HandleIncompleteSpecifier(const char *startSpecifier, + unsigned specifierLen); + + void HandleNonStandardLengthModifier( + const analyze_format_string::LengthModifier &LM, + const char *startSpecifier, unsigned specifierLen); + + void HandleNonStandardConversionSpecifier( + const analyze_format_string::ConversionSpecifier &CS, + const char *startSpecifier, unsigned specifierLen); + + void HandleNonStandardConversionSpecification( + const analyze_format_string::LengthModifier &LM, + const analyze_format_string::ConversionSpecifier &CS, + const char *startSpecifier, unsigned specifierLen); + + virtual void HandlePosition(const char *startPos, unsigned posLen); + + virtual void HandleInvalidPosition(const char *startSpecifier, + unsigned specifierLen, + analyze_format_string::PositionContext p); + + virtual void HandleZeroPosition(const char *startPos, unsigned posLen); + + void HandleNullChar(const char *nullCharacter); + + template + static void EmitFormatDiagnostic(Sema &S, bool inFunctionCall, + const Expr *ArgumentExpr, + PartialDiagnostic PDiag, + SourceLocation StringLoc, + bool IsStringLocation, Range StringRange, + FixItHint Fixit = FixItHint()); + +protected: + bool HandleInvalidConversionSpecifier(unsigned argIndex, SourceLocation Loc, + const char *startSpec, + unsigned specifierLen, + const char *csStart, unsigned csLen); + + void HandlePositionalNonpositionalArgs(SourceLocation Loc, + const char *startSpec, + unsigned specifierLen); + + SourceRange getFormatStringRange(); + CharSourceRange getSpecifierRange(const char *startSpecifier, + unsigned specifierLen); + SourceLocation getLocationOfByte(const char *x); + + 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); + + template + void EmitFormatDiagnostic(PartialDiagnostic PDiag, SourceLocation StringLoc, + bool IsStringLocation, Range StringRange, + FixItHint Fixit = FixItHint()); + + void CheckPositionalAndNonpositionalArgs( + const analyze_format_string::FormatSpecifier *FS); +}; +} + +SourceRange CheckFormatHandler::getFormatStringRange() { + return OrigFormatExpr->getSourceRange(); +} + +CharSourceRange CheckFormatHandler:: +getSpecifierRange(const char *startSpecifier, unsigned specifierLen) { + SourceLocation Start = getLocationOfByte(startSpecifier); + SourceLocation End = getLocationOfByte(startSpecifier + specifierLen - 1); + + // Advance the end SourceLocation by one due to half-open ranges. + End = End.getLocWithOffset(1); + + return CharSourceRange::getCharRange(Start, End); +} + +SourceLocation CheckFormatHandler::getLocationOfByte(const char *x) { + return S.getLocationOfStringLiteralByte(FExpr, x - Beg); +} + +void CheckFormatHandler::HandleIncompleteSpecifier(const char *startSpecifier, + unsigned specifierLen){ + EmitFormatDiagnostic(S.PDiag(diag::warn_printf_incomplete_specifier), + getLocationOfByte(startSpecifier), + /*IsStringLocation*/true, + getSpecifierRange(startSpecifier, specifierLen)); +} + +void CheckFormatHandler::HandleNonStandardLengthModifier( + const analyze_format_string::LengthModifier &LM, + const char *startSpecifier, unsigned specifierLen) { + EmitFormatDiagnostic(S.PDiag(diag::warn_format_non_standard) << LM.toString() + << 0, + getLocationOfByte(LM.getStart()), + /*IsStringLocation*/true, + getSpecifierRange(startSpecifier, specifierLen)); +} + +void CheckFormatHandler::HandleNonStandardConversionSpecifier( + const analyze_format_string::ConversionSpecifier &CS, + const char *startSpecifier, unsigned specifierLen) { + EmitFormatDiagnostic(S.PDiag(diag::warn_format_non_standard) << CS.toString() + << 1, + getLocationOfByte(CS.getStart()), + /*IsStringLocation*/true, + getSpecifierRange(startSpecifier, specifierLen)); +} + +void CheckFormatHandler::HandleNonStandardConversionSpecification( + const analyze_format_string::LengthModifier &LM, + const analyze_format_string::ConversionSpecifier &CS, + const char *startSpecifier, unsigned specifierLen) { + EmitFormatDiagnostic(S.PDiag(diag::warn_format_non_standard_conversion_spec) + << LM.toString() << CS.toString(), + getLocationOfByte(LM.getStart()), + /*IsStringLocation*/true, + getSpecifierRange(startSpecifier, specifierLen)); +} + +void CheckFormatHandler::HandlePosition(const char *startPos, + unsigned posLen) { + EmitFormatDiagnostic(S.PDiag(diag::warn_format_non_standard_positional_arg), + getLocationOfByte(startPos), + /*IsStringLocation*/true, + getSpecifierRange(startPos, posLen)); +} + +void +CheckFormatHandler::HandleInvalidPosition(const char *startPos, unsigned posLen, + analyze_format_string::PositionContext p) { + EmitFormatDiagnostic(S.PDiag(diag::warn_format_invalid_positional_specifier) + << (unsigned) p, + getLocationOfByte(startPos), /*IsStringLocation*/true, + getSpecifierRange(startPos, posLen)); +} + +void CheckFormatHandler::HandleZeroPosition(const char *startPos, + unsigned posLen) { + EmitFormatDiagnostic(S.PDiag(diag::warn_format_zero_positional_specifier), + getLocationOfByte(startPos), + /*IsStringLocation*/true, + getSpecifierRange(startPos, posLen)); +} + +void CheckFormatHandler::HandleNullChar(const char *nullCharacter) { + if (!IsObjCLiteral) { + // The presence of a null character is likely an error. + EmitFormatDiagnostic( + S.PDiag(diag::warn_printf_format_string_contains_null_char), + getLocationOfByte(nullCharacter), /*IsStringLocation*/true, + getFormatStringRange()); + } +} + +const Expr *CheckFormatHandler::getDataArg(unsigned i) const { + return Args[FirstDataArg + i]; +} + +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); + EmitFormatDiagnostic(S.PDiag(diag::warn_printf_data_arg_not_used), + getDataArg((unsigned) notCoveredArg)->getLocStart(), + /*IsStringLocation*/false, 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 + // make sense. + CoveredArgs.set(argIndex); + } + else { + // If argIndex exceeds the number of data arguments we + // don't issue a warning because that is just a cascade of warnings (and + // they may have intended '%%' anyway). We don't want to continue processing + // the format string after this point, however, as we will like just get + // gibberish when trying to match arguments. + keepGoing = false; + } + + EmitFormatDiagnostic(S.PDiag(diag::warn_format_invalid_conversion) + << StringRef(csStart, csLen), + Loc, /*IsStringLocation*/true, + getSpecifierRange(startSpec, specifierLen)); + + return keepGoing; +} + +void +CheckFormatHandler::HandlePositionalNonpositionalArgs(SourceLocation Loc, + const char *startSpec, + unsigned specifierLen) { + EmitFormatDiagnostic( + S.PDiag(diag::warn_format_mix_positional_nonpositional_args), + Loc, /*isStringLoc*/true, getSpecifierRange(startSpec, specifierLen)); +} + +bool +CheckFormatHandler::CheckNumArgs( + const analyze_format_string::FormatSpecifier &FS, + const analyze_format_string::ConversionSpecifier &CS, + const char *startSpecifier, unsigned specifierLen, unsigned argIndex) { + + if (argIndex >= NumDataArgs) { + PartialDiagnostic PDiag = FS.usesPositionalArg() + ? (S.PDiag(diag::warn_printf_positional_arg_exceeds_data_args) + << (argIndex+1) << NumDataArgs) + : S.PDiag(diag::warn_printf_insufficient_data_args); + EmitFormatDiagnostic( + PDiag, getLocationOfByte(CS.getStart()), /*IsStringLocation*/true, + getSpecifierRange(startSpecifier, specifierLen)); + return false; + } + return true; +} + +template +void CheckFormatHandler::EmitFormatDiagnostic(PartialDiagnostic PDiag, + SourceLocation Loc, + bool IsStringLocation, + Range StringRange, + FixItHint FixIt) { + EmitFormatDiagnostic(S, inFunctionCall, Args[FormatIdx], PDiag, + Loc, IsStringLocation, StringRange, FixIt); +} + +/// \brief If the format string is not within the funcion call, emit a note +/// so that the function call and string are in diagnostic messages. +/// +/// \param inFunctionCall if true, the format string is within the function +/// call and only one diagnostic message will be produced. Otherwise, an +/// extra note will be emitted pointing to location of the format string. +/// +/// \param ArgumentExpr the expression that is passed as the format string +/// argument in the function call. Used for getting locations when two +/// diagnostics are emitted. +/// +/// \param PDiag the callee should already have provided any strings for the +/// diagnostic message. This function only adds locations and fixits +/// to diagnostics. +/// +/// \param Loc primary location for diagnostic. If two diagnostics are +/// required, one will be at Loc and a new SourceLocation will be created for +/// the other one. +/// +/// \param IsStringLocation if true, Loc points to the format string should be +/// used for the note. Otherwise, Loc points to the argument list and will +/// be used with PDiag. +/// +/// \param StringRange some or all of the string to highlight. This is +/// templated so it can accept either a CharSourceRange or a SourceRange. +/// +/// \param Fixit optional fix it hint for the format string. +template +void CheckFormatHandler::EmitFormatDiagnostic(Sema &S, bool InFunctionCall, + const Expr *ArgumentExpr, + PartialDiagnostic PDiag, + SourceLocation Loc, + bool IsStringLocation, + Range StringRange, + FixItHint FixIt) { + if (InFunctionCall) + S.Diag(Loc, PDiag) << StringRange << FixIt; + else { + S.Diag(IsStringLocation ? ArgumentExpr->getExprLoc() : Loc, PDiag) + << ArgumentExpr->getSourceRange(); + S.Diag(IsStringLocation ? Loc : StringRange.getBegin(), + diag::note_format_string_defined) + << StringRange << FixIt; + } +} + +//===--- 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, + Expr **Args, unsigned NumArgs, + unsigned formatIdx, bool inFunctionCall) + : CheckFormatHandler(s, fexpr, origFormatExpr, firstDataArg, + numDataArgs, isObjCLiteral, beg, hasVAListArg, + Args, NumArgs, formatIdx, inFunctionCall) {} + + + 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); +}; +} + +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_format_string::OptionalAmount &Amt, + unsigned k, const char *startSpecifier, + unsigned specifierLen) { + + if (Amt.hasDataArgument()) { + if (!HasVAListArg) { + unsigned argIndex = Amt.getArgIndex(); + if (argIndex >= NumDataArgs) { + EmitFormatDiagnostic(S.PDiag(diag::warn_printf_asterisk_missing_arg) + << k, + getLocationOfByte(Amt.getStart()), + /*IsStringLocation*/true, + getSpecifierRange(startSpecifier, specifierLen)); + // Don't do any more checking. We will just emit + // spurious errors. + return false; + } + + // Type check the data argument. It should be an 'int'. + // Although not in conformance with C99, we also allow the argument to be + // an 'unsigned int' as that is a reasonably safe case. GCC also + // doesn't emit a warning for that case. + CoveredArgs.set(argIndex); + const Expr *Arg = getDataArg(argIndex); + QualType T = Arg->getType(); + + const analyze_printf::ArgTypeResult &ATR = Amt.getArgType(S.Context); + assert(ATR.isValid()); + + if (!ATR.matchesType(S.Context, T)) { + EmitFormatDiagnostic(S.PDiag(diag::warn_printf_asterisk_wrong_type) + << k << ATR.getRepresentativeTypeName(S.Context) + << T << Arg->getSourceRange(), + getLocationOfByte(Amt.getStart()), + /*IsStringLocation*/true, + getSpecifierRange(startSpecifier, specifierLen)); + // Don't do any more checking. We will just emit + // spurious errors. + return false; + } + } + } + return true; +} + +void CheckPrintfHandler::HandleInvalidAmount( + const analyze_printf::PrintfSpecifier &FS, + const analyze_printf::OptionalAmount &Amt, + unsigned type, + const char *startSpecifier, + unsigned specifierLen) { + const analyze_printf::PrintfConversionSpecifier &CS = + FS.getConversionSpecifier(); + + FixItHint fixit = + Amt.getHowSpecified() == analyze_printf::OptionalAmount::Constant + ? FixItHint::CreateRemoval(getSpecifierRange(Amt.getStart(), + Amt.getConstantLength())) + : FixItHint(); + + EmitFormatDiagnostic(S.PDiag(diag::warn_printf_nonsensical_optional_amount) + << type << CS.toString(), + getLocationOfByte(Amt.getStart()), + /*IsStringLocation*/true, + getSpecifierRange(startSpecifier, specifierLen), + fixit); +} + +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::PrintfConversionSpecifier &CS = + FS.getConversionSpecifier(); + EmitFormatDiagnostic(S.PDiag(diag::warn_printf_nonsensical_flag) + << flag.toString() << CS.toString(), + getLocationOfByte(flag.getPosition()), + /*IsStringLocation*/true, + getSpecifierRange(startSpecifier, specifierLen), + FixItHint::CreateRemoval( + getSpecifierRange(flag.getPosition(), 1))); +} + +void CheckPrintfHandler::HandleIgnoredFlag( + const analyze_printf::PrintfSpecifier &FS, + const analyze_printf::OptionalFlag &ignoredFlag, + const analyze_printf::OptionalFlag &flag, + const char *startSpecifier, + unsigned specifierLen) { + // Warn about ignored flag with a fixit removal. + EmitFormatDiagnostic(S.PDiag(diag::warn_printf_ignored_flag) + << ignoredFlag.toString() << flag.toString(), + getLocationOfByte(ignoredFlag.getPosition()), + /*IsStringLocation*/true, + getSpecifierRange(startSpecifier, specifierLen), + FixItHint::CreateRemoval( + getSpecifierRange(ignoredFlag.getPosition(), 1))); +} + +bool +CheckPrintfHandler::HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier + &FS, + const char *startSpecifier, + unsigned specifierLen) { + + using namespace analyze_format_string; + using namespace analyze_printf; + const PrintfConversionSpecifier &CS = FS.getConversionSpecifier(); + + if (FS.consumesDataArgument()) { + if (atFirstArg) { + atFirstArg = false; + usesPositionalArgs = FS.usesPositionalArg(); + } + else if (usesPositionalArgs != FS.usesPositionalArg()) { + HandlePositionalNonpositionalArgs(getLocationOfByte(CS.getStart()), + startSpecifier, specifierLen); + return false; + } + } + + // First check if the field width, precision, and conversion specifier + // have matching data arguments. + if (!HandleAmount(FS.getFieldWidth(), /* field width */ 0, + startSpecifier, specifierLen)) { + return false; + } + + if (!HandleAmount(FS.getPrecision(), /* precision */ 1, + startSpecifier, specifierLen)) { + return false; + } + + if (!CS.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 for using an Objective-C specific conversion specifier + // in a non-ObjC literal. + if (!IsObjCLiteral && CS.isObjCArg()) { + return HandleInvalidPrintfConversionSpecifier(FS, startSpecifier, + specifierLen); + } + + // Check for invalid use of field width + if (!FS.hasValidFieldWidth()) { + HandleInvalidAmount(FS, FS.getFieldWidth(), /* field width */ 0, + startSpecifier, specifierLen); + } + + // Check for invalid use of precision + if (!FS.hasValidPrecision()) { + HandleInvalidAmount(FS, FS.getPrecision(), /* precision */ 1, + startSpecifier, specifierLen); + } + + // Check each flag does not conflict with any other component. + if (!FS.hasValidThousandsGroupingPrefix()) + HandleFlag(FS, FS.hasThousandsGrouping(), startSpecifier, specifierLen); + if (!FS.hasValidLeadingZeros()) + HandleFlag(FS, FS.hasLeadingZeros(), startSpecifier, specifierLen); + if (!FS.hasValidPlusPrefix()) + HandleFlag(FS, FS.hasPlusPrefix(), startSpecifier, specifierLen); + if (!FS.hasValidSpacePrefix()) + HandleFlag(FS, FS.hasSpacePrefix(), startSpecifier, specifierLen); + if (!FS.hasValidAlternativeForm()) + HandleFlag(FS, FS.hasAlternativeForm(), startSpecifier, specifierLen); + if (!FS.hasValidLeftJustified()) + HandleFlag(FS, FS.isLeftJustified(), startSpecifier, specifierLen); + + // Check that flags are not ignored by another flag + if (FS.hasSpacePrefix() && FS.hasPlusPrefix()) // ' ' ignored by '+' + HandleIgnoredFlag(FS, FS.hasSpacePrefix(), FS.hasPlusPrefix(), + startSpecifier, specifierLen); + if (FS.hasLeadingZeros() && FS.isLeftJustified()) // '0' ignored by '-' + HandleIgnoredFlag(FS, FS.hasLeadingZeros(), FS.isLeftJustified(), + startSpecifier, specifierLen); + + // Check the length modifier is valid with the given conversion specifier. + const LengthModifier &LM = FS.getLengthModifier(); + if (!FS.hasValidLengthModifier()) + EmitFormatDiagnostic(S.PDiag(diag::warn_format_nonsensical_length) + << LM.toString() << CS.toString(), + getLocationOfByte(LM.getStart()), + /*IsStringLocation*/true, + getSpecifierRange(startSpecifier, specifierLen), + FixItHint::CreateRemoval( + getSpecifierRange(LM.getStart(), + LM.getLength()))); + if (!FS.hasStandardLengthModifier()) + HandleNonStandardLengthModifier(LM, startSpecifier, specifierLen); + if (!FS.hasStandardConversionSpecifier(S.getLangOpts())) + HandleNonStandardConversionSpecifier(CS, startSpecifier, specifierLen); + if (!FS.hasStandardLengthConversionCombination()) + HandleNonStandardConversionSpecification(LM, CS, startSpecifier, + specifierLen); + + // Are we using '%n'? + if (CS.getKind() == ConversionSpecifier::nArg) { + // Issue a warning about this being a possible security issue. + EmitFormatDiagnostic(S.PDiag(diag::warn_printf_write_back), + getLocationOfByte(CS.getStart()), + /*IsStringLocation*/true, + getSpecifierRange(startSpecifier, specifierLen)); + // Continue checking the other format specifiers. + return true; + } + + // The remaining checks depend on the data arguments. + if (HasVAListArg) + return true; + + if (!CheckNumArgs(FS, CS, startSpecifier, specifierLen, argIndex)) + return false; + + // Now type check the data expression that matches the + // format specifier. + const Expr *Ex = getDataArg(argIndex); + const analyze_printf::ArgTypeResult &ATR = FS.getArgType(S.Context, + IsObjCLiteral); + if (ATR.isValid() && !ATR.matchesType(S.Context, Ex->getType())) { + // Check if we didn't match because of an implicit cast from a 'char' + // or 'short' to an 'int'. This is done because printf is a varargs + // function. + if (const ImplicitCastExpr *ICE = dyn_cast(Ex)) + if (ICE->getType() == S.Context.IntTy) { + // All further checking is done on the subexpression. + Ex = ICE->getSubExpr(); + if (ATR.matchesType(S.Context, Ex->getType())) + return true; + } + + // We may be able to offer a FixItHint if it is a supported type. + PrintfSpecifier fixedFS = FS; + bool success = fixedFS.fixType(Ex->getType(), S.getLangOpts(), + S.Context, IsObjCLiteral); + + if (success) { + // Get the fix string from the fixed format specifier + SmallString<128> buf; + llvm::raw_svector_ostream os(buf); + fixedFS.toString(os); + + EmitFormatDiagnostic( + S.PDiag(diag::warn_printf_conversion_argument_type_mismatch) + << ATR.getRepresentativeTypeName(S.Context) << Ex->getType() + << Ex->getSourceRange(), + getLocationOfByte(CS.getStart()), + /*IsStringLocation*/true, + getSpecifierRange(startSpecifier, specifierLen), + FixItHint::CreateReplacement( + getSpecifierRange(startSpecifier, specifierLen), + os.str())); + } + else { + EmitFormatDiagnostic( + S.PDiag(diag::warn_printf_conversion_argument_type_mismatch) + << ATR.getRepresentativeTypeName(S.Context) << Ex->getType() + << getSpecifierRange(startSpecifier, specifierLen) + << Ex->getSourceRange(), + getLocationOfByte(CS.getStart()), + true, + getSpecifierRange(startSpecifier, specifierLen)); + } + } + + return true; +} + +//===--- 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, + Expr **Args, unsigned NumArgs, + unsigned formatIdx, bool inFunctionCall) + : CheckFormatHandler(s, fexpr, origFormatExpr, firstDataArg, + numDataArgs, isObjCLiteral, beg, hasVAListArg, + Args, NumArgs, formatIdx, inFunctionCall) {} + + 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) { + EmitFormatDiagnostic(S.PDiag(diag::warn_scanf_scanlist_incomplete), + getLocationOfByte(end), /*IsStringLocation*/true, + 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()) { + HandlePositionalNonpositionalArgs(getLocationOfByte(CS.getStart()), + 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()); + EmitFormatDiagnostic(S.PDiag(diag::warn_scanf_nonzero_width), + getLocationOfByte(Amt.getStart()), + /*IsStringLocation*/true, 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()) { + const CharSourceRange &R = getSpecifierRange(LM.getStart(), LM.getLength()); + EmitFormatDiagnostic(S.PDiag(diag::warn_format_nonsensical_length) + << LM.toString() << CS.toString() + << getSpecifierRange(startSpecifier, specifierLen), + getLocationOfByte(LM.getStart()), + /*IsStringLocation*/true, R, + FixItHint::CreateRemoval(R)); + } + + if (!FS.hasStandardLengthModifier()) + HandleNonStandardLengthModifier(LM, startSpecifier, specifierLen); + if (!FS.hasStandardConversionSpecifier(S.getLangOpts())) + HandleNonStandardConversionSpecifier(CS, startSpecifier, specifierLen); + if (!FS.hasStandardLengthConversionCombination()) + HandleNonStandardConversionSpecification(LM, CS, startSpecifier, + specifierLen); + + // The remaining checks depend on the data arguments. + if (HasVAListArg) + return true; + + if (!CheckNumArgs(FS, CS, startSpecifier, specifierLen, argIndex)) + return false; + + // Check that the argument type matches the format specifier. + const Expr *Ex = getDataArg(argIndex); + const analyze_scanf::ScanfArgTypeResult &ATR = FS.getArgType(S.Context); + if (ATR.isValid() && !ATR.matchesType(S.Context, Ex->getType())) { + ScanfSpecifier fixedFS = FS; + bool success = fixedFS.fixType(Ex->getType(), S.getLangOpts(), + S.Context); + + if (success) { + // Get the fix string from the fixed format specifier. + SmallString<128> buf; + llvm::raw_svector_ostream os(buf); + fixedFS.toString(os); + + EmitFormatDiagnostic( + S.PDiag(diag::warn_printf_conversion_argument_type_mismatch) + << ATR.getRepresentativeTypeName(S.Context) << Ex->getType() + << Ex->getSourceRange(), + getLocationOfByte(CS.getStart()), + /*IsStringLocation*/true, + getSpecifierRange(startSpecifier, specifierLen), + FixItHint::CreateReplacement( + getSpecifierRange(startSpecifier, specifierLen), + os.str())); + } else { + EmitFormatDiagnostic( + S.PDiag(diag::warn_printf_conversion_argument_type_mismatch) + << ATR.getRepresentativeTypeName(S.Context) << Ex->getType() + << Ex->getSourceRange(), + getLocationOfByte(CS.getStart()), + /*IsStringLocation*/true, + getSpecifierRange(startSpecifier, specifierLen)); + } + } + + return true; +} + +void Sema::CheckFormatString(const StringLiteral *FExpr, + const Expr *OrigFormatExpr, + Expr **Args, unsigned NumArgs, + bool HasVAListArg, unsigned format_idx, + unsigned firstDataArg, FormatStringType Type, + bool inFunctionCall) { + + // CHECK: is the format string a wide literal? + if (!FExpr->isAscii()) { + CheckFormatHandler::EmitFormatDiagnostic( + *this, inFunctionCall, Args[format_idx], + PDiag(diag::warn_format_string_is_wide_literal), FExpr->getLocStart(), + /*IsStringLocation*/true, OrigFormatExpr->getSourceRange()); + return; + } + + // Str - The format string. NOTE: this is NOT null-terminated! + StringRef StrRef = FExpr->getString(); + const char *Str = StrRef.data(); + unsigned StrLen = StrRef.size(); + const unsigned numDataArgs = NumArgs - firstDataArg; + + // CHECK: empty format string? + if (StrLen == 0 && numDataArgs > 0) { + CheckFormatHandler::EmitFormatDiagnostic( + *this, inFunctionCall, Args[format_idx], + PDiag(diag::warn_empty_format_string), FExpr->getLocStart(), + /*IsStringLocation*/true, OrigFormatExpr->getSourceRange()); + return; + } + + if (Type == FST_Printf || Type == FST_NSString) { + CheckPrintfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg, + numDataArgs, isa(OrigFormatExpr), + Str, HasVAListArg, Args, NumArgs, format_idx, + inFunctionCall); + + if (!analyze_format_string::ParsePrintfString(H, Str, Str + StrLen, + getLangOpts())) + H.DoneProcessing(); + } else if (Type == FST_Scanf) { + CheckScanfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg, + numDataArgs, isa(OrigFormatExpr), + Str, HasVAListArg, Args, NumArgs, format_idx, + inFunctionCall); + + if (!analyze_format_string::ParseScanfString(H, Str, Str + StrLen, + getLangOpts())) + H.DoneProcessing(); + } // TODO: handle other formats +} + +//===--- CHECK: Standard memory functions ---------------------------------===// + +/// \brief Determine whether the given type is a dynamic class type (e.g., +/// whether it has a vtable). +static bool isDynamicClassType(QualType T) { + if (CXXRecordDecl *Record = T->getAsCXXRecordDecl()) + if (CXXRecordDecl *Definition = Record->getDefinition()) + if (Definition->isDynamicClass()) + return true; + + return false; +} + +/// \brief If E is a sizeof expression, returns its argument expression, +/// otherwise returns NULL. +static const Expr *getSizeOfExprArg(const Expr* E) { + if (const UnaryExprOrTypeTraitExpr *SizeOf = + dyn_cast(E)) + if (SizeOf->getKind() == clang::UETT_SizeOf && !SizeOf->isArgumentType()) + return SizeOf->getArgumentExpr()->IgnoreParenImpCasts(); + + return 0; +} + +/// \brief If E is a sizeof expression, returns its argument type. +static QualType getSizeOfArgType(const Expr* E) { + if (const UnaryExprOrTypeTraitExpr *SizeOf = + dyn_cast(E)) + if (SizeOf->getKind() == clang::UETT_SizeOf) + return SizeOf->getTypeOfArgument(); + + return QualType(); +} + +/// \brief Check for dangerous or invalid arguments to memset(). +/// +/// This issues warnings on known problematic, dangerous or unspecified +/// arguments to the standard 'memset', 'memcpy', 'memmove', and 'memcmp' +/// function calls. +/// +/// \param Call The call expression to diagnose. +void Sema::CheckMemaccessArguments(const CallExpr *Call, + unsigned BId, + IdentifierInfo *FnName) { + assert(BId != 0); + + // It is possible to have a non-standard definition of memset. Validate + // we have enough arguments, and if not, abort further checking. + unsigned ExpectedNumArgs = (BId == Builtin::BIstrndup ? 2 : 3); + if (Call->getNumArgs() < ExpectedNumArgs) + return; + + unsigned LastArg = (BId == Builtin::BImemset || + BId == Builtin::BIstrndup ? 1 : 2); + unsigned LenArg = (BId == Builtin::BIstrndup ? 1 : 2); + const Expr *LenExpr = Call->getArg(LenArg)->IgnoreParenImpCasts(); + + // We have special checking when the length is a sizeof expression. + QualType SizeOfArgTy = getSizeOfArgType(LenExpr); + const Expr *SizeOfArg = getSizeOfExprArg(LenExpr); + llvm::FoldingSetNodeID SizeOfArgID; + + for (unsigned ArgIdx = 0; ArgIdx != LastArg; ++ArgIdx) { + const Expr *Dest = Call->getArg(ArgIdx)->IgnoreParenImpCasts(); + SourceRange ArgRange = Call->getArg(ArgIdx)->getSourceRange(); + + QualType DestTy = Dest->getType(); + if (const PointerType *DestPtrTy = DestTy->getAs()) { + QualType PointeeTy = DestPtrTy->getPointeeType(); + + // Never warn about void type pointers. This can be used to suppress + // false positives. + if (PointeeTy->isVoidType()) + continue; + + // Catch "memset(p, 0, sizeof(p))" -- needs to be sizeof(*p). Do this by + // actually comparing the expressions for equality. Because computing the + // expression IDs can be expensive, we only do this if the diagnostic is + // enabled. + if (SizeOfArg && + Diags.getDiagnosticLevel(diag::warn_sizeof_pointer_expr_memaccess, + SizeOfArg->getExprLoc())) { + // We only compute IDs for expressions if the warning is enabled, and + // cache the sizeof arg's ID. + if (SizeOfArgID == llvm::FoldingSetNodeID()) + SizeOfArg->Profile(SizeOfArgID, Context, true); + llvm::FoldingSetNodeID DestID; + Dest->Profile(DestID, Context, true); + if (DestID == SizeOfArgID) { + // TODO: For strncpy() and friends, this could suggest sizeof(dst) + // over sizeof(src) as well. + unsigned ActionIdx = 0; // Default is to suggest dereferencing. + if (const UnaryOperator *UnaryOp = dyn_cast(Dest)) + if (UnaryOp->getOpcode() == UO_AddrOf) + ActionIdx = 1; // If its an address-of operator, just remove it. + if (Context.getTypeSize(PointeeTy) == Context.getCharWidth()) + ActionIdx = 2; // If the pointee's size is sizeof(char), + // suggest an explicit length. + unsigned DestSrcSelect = + (BId == Builtin::BIstrndup ? 1 : ArgIdx); + DiagRuntimeBehavior(SizeOfArg->getExprLoc(), Dest, + PDiag(diag::warn_sizeof_pointer_expr_memaccess) + << FnName << DestSrcSelect << ActionIdx + << Dest->getSourceRange() + << SizeOfArg->getSourceRange()); + break; + } + } + + // Also check for cases where the sizeof argument is the exact same + // type as the memory argument, and where it points to a user-defined + // record type. + if (SizeOfArgTy != QualType()) { + if (PointeeTy->isRecordType() && + Context.typesAreCompatible(SizeOfArgTy, DestTy)) { + DiagRuntimeBehavior(LenExpr->getExprLoc(), Dest, + PDiag(diag::warn_sizeof_pointer_type_memaccess) + << FnName << SizeOfArgTy << ArgIdx + << PointeeTy << Dest->getSourceRange() + << LenExpr->getSourceRange()); + break; + } + } + + // Always complain about dynamic classes. + if (isDynamicClassType(PointeeTy)) { + + unsigned OperationType = 0; + // "overwritten" if we're warning about the destination for any call + // but memcmp; otherwise a verb appropriate to the call. + if (ArgIdx != 0 || BId == Builtin::BImemcmp) { + if (BId == Builtin::BImemcpy) + OperationType = 1; + else if(BId == Builtin::BImemmove) + OperationType = 2; + else if (BId == Builtin::BImemcmp) + OperationType = 3; + } + + DiagRuntimeBehavior( + Dest->getExprLoc(), Dest, + PDiag(diag::warn_dyn_class_memaccess) + << (BId == Builtin::BImemcmp ? ArgIdx + 2 : ArgIdx) + << FnName << PointeeTy + << OperationType + << Call->getCallee()->getSourceRange()); + } else if (PointeeTy.hasNonTrivialObjCLifetime() && + BId != Builtin::BImemset) + DiagRuntimeBehavior( + Dest->getExprLoc(), Dest, + PDiag(diag::warn_arc_object_memaccess) + << ArgIdx << FnName << PointeeTy + << Call->getCallee()->getSourceRange()); + else + continue; + + DiagRuntimeBehavior( + Dest->getExprLoc(), Dest, + PDiag(diag::note_bad_memaccess_silence) + << FixItHint::CreateInsertion(ArgRange.getBegin(), "(void*)")); + break; + } + } +} + +// A little helper routine: ignore addition and subtraction of integer literals. +// This intentionally does not ignore all integer constant expressions because +// we don't want to remove sizeof(). +static const Expr *ignoreLiteralAdditions(const Expr *Ex, ASTContext &Ctx) { + Ex = Ex->IgnoreParenCasts(); + + for (;;) { + const BinaryOperator * BO = dyn_cast(Ex); + if (!BO || !BO->isAdditiveOp()) + break; + + const Expr *RHS = BO->getRHS()->IgnoreParenCasts(); + const Expr *LHS = BO->getLHS()->IgnoreParenCasts(); + + if (isa(RHS)) + Ex = LHS; + else if (isa(LHS)) + Ex = RHS; + else + break; + } + + return Ex; +} + +// Warn if the user has made the 'size' argument to strlcpy or strlcat +// be the size of the source, instead of the destination. +void Sema::CheckStrlcpycatArguments(const CallExpr *Call, + IdentifierInfo *FnName) { + + // Don't crash if the user has the wrong number of arguments + if (Call->getNumArgs() != 3) + return; + + const Expr *SrcArg = ignoreLiteralAdditions(Call->getArg(1), Context); + const Expr *SizeArg = ignoreLiteralAdditions(Call->getArg(2), Context); + const Expr *CompareWithSrc = NULL; + + // Look for 'strlcpy(dst, x, sizeof(x))' + if (const Expr *Ex = getSizeOfExprArg(SizeArg)) + CompareWithSrc = Ex; + else { + // Look for 'strlcpy(dst, x, strlen(x))' + if (const CallExpr *SizeCall = dyn_cast(SizeArg)) { + if (SizeCall->isBuiltinCall() == Builtin::BIstrlen + && SizeCall->getNumArgs() == 1) + CompareWithSrc = ignoreLiteralAdditions(SizeCall->getArg(0), Context); + } + } + + if (!CompareWithSrc) + return; + + // Determine if the argument to sizeof/strlen is equal to the source + // argument. In principle there's all kinds of things you could do + // here, for instance creating an == expression and evaluating it with + // EvaluateAsBooleanCondition, but this uses a more direct technique: + const DeclRefExpr *SrcArgDRE = dyn_cast(SrcArg); + if (!SrcArgDRE) + return; + + const DeclRefExpr *CompareWithSrcDRE = dyn_cast(CompareWithSrc); + if (!CompareWithSrcDRE || + SrcArgDRE->getDecl() != CompareWithSrcDRE->getDecl()) + return; + + const Expr *OriginalSizeArg = Call->getArg(2); + Diag(CompareWithSrcDRE->getLocStart(), diag::warn_strlcpycat_wrong_size) + << OriginalSizeArg->getSourceRange() << FnName; + + // Output a FIXIT hint if the destination is an array (rather than a + // pointer to an array). This could be enhanced to handle some + // pointers if we know the actual size, like if DstArg is 'array+2' + // we could say 'sizeof(array)-2'. + const Expr *DstArg = Call->getArg(0)->IgnoreParenImpCasts(); + QualType DstArgTy = DstArg->getType(); + + // Only handle constant-sized or VLAs, but not flexible members. + if (const ConstantArrayType *CAT = Context.getAsConstantArrayType(DstArgTy)) { + // Only issue the FIXIT for arrays of size > 1. + if (CAT->getSize().getSExtValue() <= 1) + return; + } else if (!DstArgTy->isVariableArrayType()) { + return; + } + + SmallString<128> sizeString; + llvm::raw_svector_ostream OS(sizeString); + OS << "sizeof("; + DstArg->printPretty(OS, Context, 0, getPrintingPolicy()); + OS << ")"; + + Diag(OriginalSizeArg->getLocStart(), diag::note_strlcpycat_wrong_size) + << FixItHint::CreateReplacement(OriginalSizeArg->getSourceRange(), + OS.str()); +} + +/// Check if two expressions refer to the same declaration. +static bool referToTheSameDecl(const Expr *E1, const Expr *E2) { + if (const DeclRefExpr *D1 = dyn_cast_or_null(E1)) + if (const DeclRefExpr *D2 = dyn_cast_or_null(E2)) + return D1->getDecl() == D2->getDecl(); + return false; +} + +static const Expr *getStrlenExprArg(const Expr *E) { + if (const CallExpr *CE = dyn_cast(E)) { + const FunctionDecl *FD = CE->getDirectCallee(); + if (!FD || FD->getMemoryFunctionKind() != Builtin::BIstrlen) + return 0; + return CE->getArg(0)->IgnoreParenCasts(); + } + return 0; +} + +// Warn on anti-patterns as the 'size' argument to strncat. +// The correct size argument should look like following: +// strncat(dst, src, sizeof(dst) - strlen(dest) - 1); +void Sema::CheckStrncatArguments(const CallExpr *CE, + IdentifierInfo *FnName) { + // Don't crash if the user has the wrong number of arguments. + if (CE->getNumArgs() < 3) + return; + const Expr *DstArg = CE->getArg(0)->IgnoreParenCasts(); + const Expr *SrcArg = CE->getArg(1)->IgnoreParenCasts(); + const Expr *LenArg = CE->getArg(2)->IgnoreParenCasts(); + + // Identify common expressions, which are wrongly used as the size argument + // to strncat and may lead to buffer overflows. + unsigned PatternType = 0; + if (const Expr *SizeOfArg = getSizeOfExprArg(LenArg)) { + // - sizeof(dst) + if (referToTheSameDecl(SizeOfArg, DstArg)) + PatternType = 1; + // - sizeof(src) + else if (referToTheSameDecl(SizeOfArg, SrcArg)) + PatternType = 2; + } else if (const BinaryOperator *BE = dyn_cast(LenArg)) { + if (BE->getOpcode() == BO_Sub) { + const Expr *L = BE->getLHS()->IgnoreParenCasts(); + const Expr *R = BE->getRHS()->IgnoreParenCasts(); + // - sizeof(dst) - strlen(dst) + if (referToTheSameDecl(DstArg, getSizeOfExprArg(L)) && + referToTheSameDecl(DstArg, getStrlenExprArg(R))) + PatternType = 1; + // - sizeof(src) - (anything) + else if (referToTheSameDecl(SrcArg, getSizeOfExprArg(L))) + PatternType = 2; + } + } + + if (PatternType == 0) + return; + + // Generate the diagnostic. + SourceLocation SL = LenArg->getLocStart(); + SourceRange SR = LenArg->getSourceRange(); + SourceManager &SM = PP.getSourceManager(); + + // If the function is defined as a builtin macro, do not show macro expansion. + if (SM.isMacroArgExpansion(SL)) { + SL = SM.getSpellingLoc(SL); + SR = SourceRange(SM.getSpellingLoc(SR.getBegin()), + SM.getSpellingLoc(SR.getEnd())); + } + + if (PatternType == 1) + Diag(SL, diag::warn_strncat_large_size) << SR; + else + Diag(SL, diag::warn_strncat_src_size) << SR; + + // Output a FIXIT hint if the destination is an array (rather than a + // pointer to an array). This could be enhanced to handle some + // pointers if we know the actual size, like if DstArg is 'array+2' + // we could say 'sizeof(array)-2'. + QualType DstArgTy = DstArg->getType(); + + // Only handle constant-sized or VLAs, but not flexible members. + if (const ConstantArrayType *CAT = Context.getAsConstantArrayType(DstArgTy)) { + // Only issue the FIXIT for arrays of size > 1. + if (CAT->getSize().getSExtValue() <= 1) + return; + } else if (!DstArgTy->isVariableArrayType()) { + return; + } + + SmallString<128> sizeString; + llvm::raw_svector_ostream OS(sizeString); + OS << "sizeof("; + DstArg->printPretty(OS, Context, 0, getPrintingPolicy()); + OS << ") - "; + OS << "strlen("; + DstArg->printPretty(OS, Context, 0, getPrintingPolicy()); + OS << ") - 1"; + + Diag(SL, diag::note_strncat_wrong_size) + << FixItHint::CreateReplacement(SR, OS.str()); +} + +//===--- CHECK: Return Address of Stack Variable --------------------------===// + +static Expr *EvalVal(Expr *E, SmallVectorImpl &refVars); +static Expr *EvalAddr(Expr* E, SmallVectorImpl &refVars); + +/// CheckReturnStackAddr - Check if a return statement returns the address +/// of a stack variable. +void +Sema::CheckReturnStackAddr(Expr *RetValExp, QualType lhsType, + SourceLocation ReturnLoc) { + + Expr *stackE = 0; + SmallVector refVars; + + // Perform checking for returned stack addresses, local blocks, + // label addresses or references to temporaries. + if (lhsType->isPointerType() || + (!getLangOpts().ObjCAutoRefCount && lhsType->isBlockPointerType())) { + stackE = EvalAddr(RetValExp, refVars); + } else if (lhsType->isReferenceType()) { + stackE = EvalVal(RetValExp, refVars); + } + + if (stackE == 0) + return; // Nothing suspicious was found. + + SourceLocation diagLoc; + SourceRange diagRange; + if (refVars.empty()) { + diagLoc = stackE->getLocStart(); + diagRange = stackE->getSourceRange(); + } else { + // We followed through a reference variable. 'stackE' contains the + // problematic expression but we will warn at the return statement pointing + // at the reference variable. We will later display the "trail" of + // reference variables using notes. + diagLoc = refVars[0]->getLocStart(); + diagRange = refVars[0]->getSourceRange(); + } + + if (DeclRefExpr *DR = dyn_cast(stackE)) { //address of local var. + Diag(diagLoc, lhsType->isReferenceType() ? diag::warn_ret_stack_ref + : diag::warn_ret_stack_addr) + << DR->getDecl()->getDeclName() << diagRange; + } else if (isa(stackE)) { // local block. + Diag(diagLoc, diag::err_ret_local_block) << diagRange; + } else if (isa(stackE)) { // address of label. + Diag(diagLoc, diag::warn_ret_addr_label) << diagRange; + } else { // local temporary. + Diag(diagLoc, lhsType->isReferenceType() ? diag::warn_ret_local_temp_ref + : diag::warn_ret_local_temp_addr) + << diagRange; + } + + // Display the "trail" of reference variables that we followed until we + // found the problematic expression using notes. + for (unsigned i = 0, e = refVars.size(); i != e; ++i) { + VarDecl *VD = cast(refVars[i]->getDecl()); + // If this var binds to another reference var, show the range of the next + // var, otherwise the var binds to the problematic expression, in which case + // show the range of the expression. + SourceRange range = (i < e-1) ? refVars[i+1]->getSourceRange() + : stackE->getSourceRange(); + Diag(VD->getLocation(), diag::note_ref_var_local_bind) + << VD->getDeclName() << range; + } +} + +/// EvalAddr - EvalAddr and EvalVal are mutually recursive functions that +/// check if the expression in a return statement evaluates to an address +/// to a location on the stack, a local block, an address of a label, or a +/// reference to local temporary. The recursion is used to traverse the +/// AST of the return expression, with recursion backtracking when we +/// encounter a subexpression that (1) clearly does not lead to one of the +/// above problematic expressions (2) is something we cannot determine leads to +/// a problematic expression based on such local checking. +/// +/// Both EvalAddr and EvalVal follow through reference variables to evaluate +/// the expression that they point to. Such variables are added to the +/// 'refVars' vector so that we know what the reference variable "trail" was. +/// +/// EvalAddr processes expressions that are pointers that are used as +/// references (and not L-values). EvalVal handles all other values. +/// At the base case of the recursion is a check for the above problematic +/// expressions. +/// +/// This implementation handles: +/// +/// * pointer-to-pointer casts +/// * implicit conversions from array references to pointers +/// * taking the address of fields +/// * arbitrary interplay between "&" and "*" operators +/// * pointer arithmetic from an address of a stack variable +/// * taking the address of an array element where the array is on the stack +static Expr *EvalAddr(Expr *E, SmallVectorImpl &refVars) { + if (E->isTypeDependent()) + return NULL; + + // We should only be called for evaluating pointer expressions. + assert((E->getType()->isAnyPointerType() || + E->getType()->isBlockPointerType() || + E->getType()->isObjCQualifiedIdType()) && + "EvalAddr only works on pointers"); + + E = E->IgnoreParens(); + + // Our "symbolic interpreter" is just a dispatch off the currently + // viewed AST node. We then recursively traverse the AST by calling + // EvalAddr and EvalVal appropriately. + switch (E->getStmtClass()) { + case Stmt::DeclRefExprClass: { + DeclRefExpr *DR = cast(E); + + if (VarDecl *V = dyn_cast(DR->getDecl())) + // If this is a reference variable, follow through to the expression that + // it points to. + if (V->hasLocalStorage() && + V->getType()->isReferenceType() && V->hasInit()) { + // Add the reference variable to the "trail". + refVars.push_back(DR); + return EvalAddr(V->getInit(), refVars); + } + + return NULL; + } + + case Stmt::UnaryOperatorClass: { + // The only unary operator that make sense to handle here + // is AddrOf. All others don't make sense as pointers. + UnaryOperator *U = cast(E); + + if (U->getOpcode() == UO_AddrOf) + return EvalVal(U->getSubExpr(), refVars); + else + return NULL; + } + + case Stmt::BinaryOperatorClass: { + // Handle pointer arithmetic. All other binary operators are not valid + // in this context. + BinaryOperator *B = cast(E); + BinaryOperatorKind op = B->getOpcode(); + + if (op != BO_Add && op != BO_Sub) + return NULL; + + Expr *Base = B->getLHS(); + + // Determine which argument is the real pointer base. It could be + // the RHS argument instead of the LHS. + if (!Base->getType()->isPointerType()) Base = B->getRHS(); + + assert (Base->getType()->isPointerType()); + return EvalAddr(Base, refVars); + } + + // For conditional operators we need to see if either the LHS or RHS are + // valid DeclRefExpr*s. If one of them is valid, we return it. + case Stmt::ConditionalOperatorClass: { + ConditionalOperator *C = cast(E); + + // Handle the GNU extension for missing LHS. + if (Expr *lhsExpr = C->getLHS()) { + // In C++, we can have a throw-expression, which has 'void' type. + if (!lhsExpr->getType()->isVoidType()) + if (Expr* LHS = EvalAddr(lhsExpr, refVars)) + return LHS; + } + + // In C++, we can have a throw-expression, which has 'void' type. + if (C->getRHS()->getType()->isVoidType()) + return NULL; + + return EvalAddr(C->getRHS(), refVars); + } + + case Stmt::BlockExprClass: + if (cast(E)->getBlockDecl()->hasCaptures()) + return E; // local block. + return NULL; + + case Stmt::AddrLabelExprClass: + return E; // address of label. + + case Stmt::ExprWithCleanupsClass: + return EvalAddr(cast(E)->getSubExpr(), refVars); + + // For casts, we need to handle conversions from arrays to + // pointer values, and pointer-to-pointer conversions. + case Stmt::ImplicitCastExprClass: + case Stmt::CStyleCastExprClass: + case Stmt::CXXFunctionalCastExprClass: + case Stmt::ObjCBridgedCastExprClass: + case Stmt::CXXStaticCastExprClass: + case Stmt::CXXDynamicCastExprClass: + case Stmt::CXXConstCastExprClass: + case Stmt::CXXReinterpretCastExprClass: { + Expr* SubExpr = cast(E)->getSubExpr(); + switch (cast(E)->getCastKind()) { + case CK_BitCast: + case CK_LValueToRValue: + case CK_NoOp: + case CK_BaseToDerived: + case CK_DerivedToBase: + case CK_UncheckedDerivedToBase: + case CK_Dynamic: + case CK_CPointerToObjCPointerCast: + case CK_BlockPointerToObjCPointerCast: + case CK_AnyPointerToBlockPointerCast: + return EvalAddr(SubExpr, refVars); + + case CK_ArrayToPointerDecay: + return EvalVal(SubExpr, refVars); + + default: + return 0; + } + } + + case Stmt::MaterializeTemporaryExprClass: + if (Expr *Result = EvalAddr( + cast(E)->GetTemporaryExpr(), + refVars)) + return Result; + + return E; + + // Everything else: we simply don't reason about them. + default: + return NULL; + } +} + + +/// EvalVal - This function is complements EvalAddr in the mutual recursion. +/// See the comments for EvalAddr for more details. +static Expr *EvalVal(Expr *E, SmallVectorImpl &refVars) { +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). + + // Our "symbolic interpreter" is just a dispatch off the currently + // viewed AST node. We then recursively traverse the AST by calling + // EvalAddr and EvalVal appropriately. + + E = E->IgnoreParens(); + switch (E->getStmtClass()) { + case Stmt::ImplicitCastExprClass: { + ImplicitCastExpr *IE = cast(E); + if (IE->getValueKind() == VK_LValue) { + E = IE->getSubExpr(); + continue; + } + return NULL; + } + + case Stmt::ExprWithCleanupsClass: + return EvalVal(cast(E)->getSubExpr(), refVars); + + case Stmt::DeclRefExprClass: { + // When we hit a DeclRefExpr we are looking at code that refers to a + // variable's name. If it's not a reference variable we check if it has + // local storage within the function, and if so, return the expression. + DeclRefExpr *DR = cast(E); + + if (VarDecl *V = dyn_cast(DR->getDecl())) + if (V->hasLocalStorage()) { + if (!V->getType()->isReferenceType()) + return DR; + + // Reference variable, follow through to the expression that + // it points to. + if (V->hasInit()) { + // Add the reference variable to the "trail". + refVars.push_back(DR); + return EvalVal(V->getInit(), refVars); + } + } + + return NULL; + } + + case Stmt::UnaryOperatorClass: { + // The only unary operator that make sense to handle here + // is Deref. All others don't resolve to a "name." This includes + // handling all sorts of rvalues passed to a unary operator. + UnaryOperator *U = cast(E); + + if (U->getOpcode() == UO_Deref) + return EvalAddr(U->getSubExpr(), refVars); + + return NULL; + } + + case Stmt::ArraySubscriptExprClass: { + // Array subscripts are potential references to data on the stack. We + // retrieve the DeclRefExpr* for the array variable if it indeed + // has local storage. + return EvalAddr(cast(E)->getBase(), refVars); + } + + case Stmt::ConditionalOperatorClass: { + // For conditional operators we need to see if either the LHS or RHS are + // non-NULL Expr's. If one is non-NULL, we return it. + ConditionalOperator *C = cast(E); + + // Handle the GNU extension for missing LHS. + if (Expr *lhsExpr = C->getLHS()) + if (Expr *LHS = EvalVal(lhsExpr, refVars)) + return LHS; + + return EvalVal(C->getRHS(), refVars); + } + + // Accesses to members are potential references to data on the stack. + case Stmt::MemberExprClass: { + MemberExpr *M = cast(E); + + // Check for indirect access. We only want direct field accesses. + 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(), refVars); + } + + case Stmt::MaterializeTemporaryExprClass: + if (Expr *Result = EvalVal( + cast(E)->GetTemporaryExpr(), + refVars)) + return Result; + + return E; + + default: + // Check that we don't return or take the address of a reference to a + // temporary. This is only useful in C++. + if (!E->isTypeDependent() && E->isRValue()) + return E; + + // Everything else: we simply don't reason about them. + return NULL; + } +} while (true); +} + +//===--- CHECK: Floating-Point comparisons (-Wfloat-equal) ---------------===// + +/// Check for comparisons of floating point operands using != and ==. +/// Issue a warning if these are no self-comparisons, as they are not likely +/// to do what the programmer intended. +void Sema::CheckFloatComparison(SourceLocation Loc, Expr* LHS, Expr *RHS) { + bool EmitWarning = true; + + Expr* LeftExprSansParen = LHS->IgnoreParenImpCasts(); + Expr* RightExprSansParen = RHS->IgnoreParenImpCasts(); + + // Special case: check for x == x (which is OK). + // Do not emit warnings for such cases. + if (DeclRefExpr* DRL = dyn_cast(LeftExprSansParen)) + if (DeclRefExpr* DRR = dyn_cast(RightExprSansParen)) + if (DRL->getDecl() == DRR->getDecl()) + EmitWarning = false; + + + // Special case: check for comparisons against literals that can be exactly + // represented by APFloat. In such cases, do not emit a warning. This + // is a heuristic: often comparison against such literals are used to + // detect if a value in a variable has not changed. This clearly can + // lead to false negatives. + if (EmitWarning) { + if (FloatingLiteral* FLL = dyn_cast(LeftExprSansParen)) { + if (FLL->isExact()) + EmitWarning = false; + } else + if (FloatingLiteral* FLR = dyn_cast(RightExprSansParen)){ + if (FLR->isExact()) + EmitWarning = false; + } + } + + // Check for comparisons with builtin types. + if (EmitWarning) + if (CallExpr* CL = dyn_cast(LeftExprSansParen)) + if (CL->isBuiltinCall()) + EmitWarning = false; + + if (EmitWarning) + if (CallExpr* CR = dyn_cast(RightExprSansParen)) + if (CR->isBuiltinCall()) + EmitWarning = false; + + // Emit the diagnostic. + if (EmitWarning) + Diag(Loc, diag::warn_floatingpoint_eq) + << LHS->getSourceRange() << RHS->getSourceRange(); +} + +//===--- CHECK: Integer mixed-sign comparisons (-Wsign-compare) --------===// +//===--- CHECK: Lossy implicit conversions (-Wconversion) --------------===// + +namespace { + +/// Structure recording the 'active' range of an integer-valued +/// expression. +struct IntRange { + /// The number of bits active in the int. + unsigned Width; + + /// True if the int is known not to have negative values. + bool NonNegative; + + IntRange(unsigned Width, bool NonNegative) + : Width(Width), NonNegative(NonNegative) + {} + + /// Returns the range of the bool type. + static IntRange forBoolType() { + return IntRange(1, true); + } + + /// Returns the range of an opaque value of the given integral type. + static IntRange forValueOfType(ASTContext &C, QualType T) { + return forValueOfCanonicalType(C, + T->getCanonicalTypeInternal().getTypePtr()); + } + + /// Returns the range of an opaque value of a canonical integral type. + static IntRange forValueOfCanonicalType(ASTContext &C, const Type *T) { + assert(T->isCanonicalUnqualified()); + + if (const VectorType *VT = dyn_cast(T)) + T = VT->getElementType().getTypePtr(); + if (const ComplexType *CT = dyn_cast(T)) + T = CT->getElementType().getTypePtr(); + + // For enum types, use the known bit width of the enumerators. + if (const EnumType *ET = dyn_cast(T)) { + EnumDecl *Enum = ET->getDecl(); + if (!Enum->isCompleteDefinition()) + return IntRange(C.getIntWidth(QualType(T, 0)), false); + + unsigned NumPositive = Enum->getNumPositiveBits(); + unsigned NumNegative = Enum->getNumNegativeBits(); + + return IntRange(std::max(NumPositive, NumNegative), NumNegative == 0); + } + + const BuiltinType *BT = cast(T); + assert(BT->isInteger()); + + return IntRange(C.getIntWidth(QualType(T, 0)), BT->isUnsignedInteger()); + } + + /// Returns the "target" range of a canonical integral type, i.e. + /// the range of values expressible in the type. + /// + /// This matches forValueOfCanonicalType except that enums have the + /// full range of their type, not the range of their enumerators. + static IntRange forTargetOfCanonicalType(ASTContext &C, const Type *T) { + assert(T->isCanonicalUnqualified()); + + if (const VectorType *VT = dyn_cast(T)) + T = VT->getElementType().getTypePtr(); + if (const ComplexType *CT = dyn_cast(T)) + T = CT->getElementType().getTypePtr(); + if (const EnumType *ET = dyn_cast(T)) + T = C.getCanonicalType(ET->getDecl()->getIntegerType()).getTypePtr(); + + const BuiltinType *BT = cast(T); + assert(BT->isInteger()); + + return IntRange(C.getIntWidth(QualType(T, 0)), BT->isUnsignedInteger()); + } + + /// Returns the supremum of two ranges: i.e. their conservative merge. + static IntRange join(IntRange L, IntRange R) { + return IntRange(std::max(L.Width, R.Width), + L.NonNegative && R.NonNegative); + } + + /// Returns the infinum of two ranges: i.e. their aggressive merge. + static IntRange meet(IntRange L, IntRange R) { + return IntRange(std::min(L.Width, R.Width), + L.NonNegative || R.NonNegative); + } +}; + +static IntRange GetValueRange(ASTContext &C, llvm::APSInt &value, + unsigned MaxWidth) { + if (value.isSigned() && value.isNegative()) + return IntRange(value.getMinSignedBits(), false); + + if (value.getBitWidth() > MaxWidth) + value = value.trunc(MaxWidth); + + // isNonNegative() just checks the sign bit without considering + // signedness. + return IntRange(value.getActiveBits(), true); +} + +static IntRange GetValueRange(ASTContext &C, APValue &result, QualType Ty, + unsigned MaxWidth) { + if (result.isInt()) + return GetValueRange(C, result.getInt(), MaxWidth); + + if (result.isVector()) { + IntRange R = GetValueRange(C, result.getVectorElt(0), Ty, MaxWidth); + for (unsigned i = 1, e = result.getVectorLength(); i != e; ++i) { + IntRange El = GetValueRange(C, result.getVectorElt(i), Ty, MaxWidth); + R = IntRange::join(R, El); + } + return R; + } + + if (result.isComplexInt()) { + IntRange R = GetValueRange(C, result.getComplexIntReal(), MaxWidth); + IntRange I = GetValueRange(C, result.getComplexIntImag(), MaxWidth); + return IntRange::join(R, I); + } + + // This can happen with lossless casts to intptr_t of "based" lvalues. + // Assume it might use arbitrary bits. + // FIXME: The only reason we need to pass the type in here is to get + // the sign right on this one case. It would be nice if APValue + // preserved this. + assert(result.isLValue() || result.isAddrLabelDiff()); + return IntRange(MaxWidth, Ty->isUnsignedIntegerOrEnumerationType()); +} + +/// Pseudo-evaluate the given integer expression, estimating the +/// range of values it might take. +/// +/// \param MaxWidth - the width to which the value will be truncated +static IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) { + E = E->IgnoreParens(); + + // Try a full evaluation first. + Expr::EvalResult result; + if (E->EvaluateAsRValue(result, C)) + return GetValueRange(C, result.Val, E->getType(), MaxWidth); + + // I think we only want to look through implicit casts here; if the + // 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() == CK_NoOp || CE->getCastKind() == CK_LValueToRValue) + return GetExprRange(C, CE->getSubExpr(), MaxWidth); + + IntRange OutputTypeRange = IntRange::forValueOfType(C, CE->getType()); + + bool isIntegerCast = (CE->getCastKind() == CK_IntegralCast); + + // Assume that non-integer casts can span the full range of the type. + if (!isIntegerCast) + return OutputTypeRange; + + IntRange SubRange + = GetExprRange(C, CE->getSubExpr(), + std::min(MaxWidth, OutputTypeRange.Width)); + + // Bail out if the subexpr's range is as wide as the cast type. + if (SubRange.Width >= OutputTypeRange.Width) + return OutputTypeRange; + + // Otherwise, we take the smaller width, and we're non-negative if + // either the output type or the subexpr is. + return IntRange(SubRange.Width, + SubRange.NonNegative || OutputTypeRange.NonNegative); + } + + if (ConditionalOperator *CO = dyn_cast(E)) { + // If we can fold the condition, just take that operand. + bool CondResult; + if (CO->getCond()->EvaluateAsBooleanCondition(CondResult, C)) + return GetExprRange(C, CondResult ? CO->getTrueExpr() + : CO->getFalseExpr(), + MaxWidth); + + // Otherwise, conservatively merge. + IntRange L = GetExprRange(C, CO->getTrueExpr(), MaxWidth); + IntRange R = GetExprRange(C, CO->getFalseExpr(), MaxWidth); + return IntRange::join(L, R); + } + + if (BinaryOperator *BO = dyn_cast(E)) { + switch (BO->getOpcode()) { + + // Boolean-valued operations are single-bit and positive. + 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 the assignments is the type of the LHS, so the RHS + // is not necessarily the same type. + case BO_MulAssign: + case BO_DivAssign: + case BO_RemAssign: + case BO_AddAssign: + case BO_SubAssign: + case BO_XorAssign: + case BO_OrAssign: + // TODO: bitfields? + return IntRange::forValueOfType(C, E->getType()); + + // Simple assignments just pass through the RHS, which will have + // been coerced to the LHS type. + case BO_Assign: + // TODO: bitfields? + return GetExprRange(C, BO->getRHS(), MaxWidth); + + // Operations with opaque sources are black-listed. + case BO_PtrMemD: + case BO_PtrMemI: + return IntRange::forValueOfType(C, E->getType()); + + // Bitwise-and uses the *infinum* of the two source ranges. + 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 BO_Shl: + // ...except that we want to treat '1 << (blah)' as logically + // positive. It's an important idiom. + if (IntegerLiteral *I + = dyn_cast(BO->getLHS()->IgnoreParenCasts())) { + if (I->getValue() == 1) { + IntRange R = IntRange::forValueOfType(C, E->getType()); + return IntRange(R.Width, /*NonNegative*/ true); + } + } + // fallthrough + + case BO_ShlAssign: + return IntRange::forValueOfType(C, E->getType()); + + // Right shift by a constant can narrow its left argument. + 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 + // that much. + llvm::APSInt shift; + if (BO->getRHS()->isIntegerConstantExpr(shift, C) && + shift.isNonNegative()) { + unsigned zext = shift.getZExtValue(); + if (zext >= L.Width) + L.Width = (L.NonNegative ? 0 : 1); + else + L.Width -= zext; + } + + return L; + } + + // Comma acts as its right operand. + case BO_Comma: + return GetExprRange(C, BO->getRHS(), MaxWidth); + + // Black-list pointer subtractions. + case BO_Sub: + if (BO->getLHS()->getType()->isPointerType()) + return IntRange::forValueOfType(C, E->getType()); + break; + + // The width of a division result is mostly determined by the size + // of the LHS. + case BO_Div: { + // Don't 'pre-truncate' the operands. + unsigned opWidth = C.getIntWidth(E->getType()); + IntRange L = GetExprRange(C, BO->getLHS(), opWidth); + + // If the divisor is constant, use that. + llvm::APSInt divisor; + if (BO->getRHS()->isIntegerConstantExpr(divisor, C)) { + unsigned log2 = divisor.logBase2(); // floor(log_2(divisor)) + if (log2 >= L.Width) + L.Width = (L.NonNegative ? 0 : 1); + else + L.Width = std::min(L.Width - log2, MaxWidth); + return L; + } + + // Otherwise, just use the LHS's width. + IntRange R = GetExprRange(C, BO->getRHS(), opWidth); + return IntRange(L.Width, L.NonNegative && R.NonNegative); + } + + // The result of a remainder can't be larger than the result of + // either side. + case BO_Rem: { + // Don't 'pre-truncate' the operands. + unsigned opWidth = C.getIntWidth(E->getType()); + IntRange L = GetExprRange(C, BO->getLHS(), opWidth); + IntRange R = GetExprRange(C, BO->getRHS(), opWidth); + + IntRange meet = IntRange::meet(L, R); + meet.Width = std::min(meet.Width, MaxWidth); + return meet; + } + + // The default behavior is okay for these. + case BO_Mul: + case BO_Add: + case BO_Xor: + case BO_Or: + break; + } + + // The default case is to treat the operation as if it were closed + // on the narrowest type that encompasses both operands. + IntRange L = GetExprRange(C, BO->getLHS(), MaxWidth); + IntRange R = GetExprRange(C, BO->getRHS(), MaxWidth); + return IntRange::join(L, R); + } + + if (UnaryOperator *UO = dyn_cast(E)) { + switch (UO->getOpcode()) { + // Boolean-valued operations are white-listed. + case UO_LNot: + return IntRange::forBoolType(); + + // Operations with opaque sources are black-listed. + case UO_Deref: + case UO_AddrOf: // should be impossible + return IntRange::forValueOfType(C, E->getType()); + + default: + return GetExprRange(C, UO->getSubExpr(), MaxWidth); + } + } + + if (dyn_cast(E)) { + IntRange::forValueOfType(C, E->getType()); + } + + if (FieldDecl *BitField = E->getBitField()) + return IntRange(BitField->getBitWidthValue(C), + BitField->getType()->isUnsignedIntegerOrEnumerationType()); + + return IntRange::forValueOfType(C, E->getType()); +} + +static IntRange GetExprRange(ASTContext &C, Expr *E) { + return GetExprRange(C, E, C.getIntWidth(E->getType())); +} + +/// Checks whether the given value, which currently has the given +/// source semantics, has the same value when coerced through the +/// target semantics. +static bool IsSameFloatAfterCast(const llvm::APFloat &value, + const llvm::fltSemantics &Src, + const llvm::fltSemantics &Tgt) { + llvm::APFloat truncated = value; + + bool ignored; + truncated.convert(Src, llvm::APFloat::rmNearestTiesToEven, &ignored); + truncated.convert(Tgt, llvm::APFloat::rmNearestTiesToEven, &ignored); + + return truncated.bitwiseIsEqual(value); +} + +/// Checks whether the given value, which currently has the given +/// source semantics, has the same value when coerced through the +/// target semantics. +/// +/// The value might be a vector of floats (or a complex number). +static bool IsSameFloatAfterCast(const APValue &value, + const llvm::fltSemantics &Src, + const llvm::fltSemantics &Tgt) { + if (value.isFloat()) + return IsSameFloatAfterCast(value.getFloat(), Src, Tgt); + + if (value.isVector()) { + for (unsigned i = 0, e = value.getVectorLength(); i != e; ++i) + if (!IsSameFloatAfterCast(value.getVectorElt(i), Src, Tgt)) + return false; + return true; + } + + assert(value.isComplexFloat()); + return (IsSameFloatAfterCast(value.getComplexFloatReal(), Src, Tgt) && + IsSameFloatAfterCast(value.getComplexFloatImag(), Src, Tgt)); +} + +static void AnalyzeImplicitConversions(Sema &S, Expr *E, SourceLocation CC); + +static bool IsZero(Sema &S, Expr *E) { + // Suppress cases where we are comparing against an enum constant. + if (const DeclRefExpr *DR = + dyn_cast(E->IgnoreParenImpCasts())) + if (isa(DR->getDecl())) + return false; + + // Suppress cases where the '0' value is expanded from a macro. + if (E->getLocStart().isMacroID()) + return false; + + llvm::APSInt Value; + return E->isIntegerConstantExpr(Value, S.Context) && Value == 0; +} + +static bool HasEnumType(Expr *E) { + // Strip off implicit integral promotions. + while (ImplicitCastExpr *ICE = dyn_cast(E)) { + if (ICE->getCastKind() != CK_IntegralCast && + ICE->getCastKind() != CK_NoOp) + break; + E = ICE->getSubExpr(); + } + + return E->getType()->isEnumeralType(); +} + +static void CheckTrivialUnsignedComparison(Sema &S, BinaryOperator *E) { + BinaryOperatorKind op = E->getOpcode(); + if (E->isValueDependent()) + return; + + if (op == BO_LT && IsZero(S, E->getRHS())) { + S.Diag(E->getOperatorLoc(), diag::warn_lunsigned_always_true_comparison) + << "< 0" << "false" << HasEnumType(E->getLHS()) + << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange(); + } else if (op == BO_GE && IsZero(S, E->getRHS())) { + S.Diag(E->getOperatorLoc(), diag::warn_lunsigned_always_true_comparison) + << ">= 0" << "true" << HasEnumType(E->getLHS()) + << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange(); + } else if (op == BO_GT && IsZero(S, E->getLHS())) { + S.Diag(E->getOperatorLoc(), diag::warn_runsigned_always_true_comparison) + << "0 >" << "false" << HasEnumType(E->getRHS()) + << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange(); + } else if (op == BO_LE && IsZero(S, E->getLHS())) { + S.Diag(E->getOperatorLoc(), diag::warn_runsigned_always_true_comparison) + << "0 <=" << "true" << HasEnumType(E->getRHS()) + << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange(); + } +} + +/// Analyze the operands of the given comparison. Implements the +/// fallback case from AnalyzeComparison. +static void AnalyzeImpConvsInComparison(Sema &S, BinaryOperator *E) { + AnalyzeImplicitConversions(S, E->getLHS(), E->getOperatorLoc()); + AnalyzeImplicitConversions(S, E->getRHS(), E->getOperatorLoc()); +} + +/// \brief Implements -Wsign-compare. +/// +/// \param E the binary operator to check for warnings +static void AnalyzeComparison(Sema &S, BinaryOperator *E) { + // The type the comparison is being performed in. + QualType T = E->getLHS()->getType(); + assert(S.Context.hasSameUnqualifiedType(T, E->getRHS()->getType()) + && "comparison with mismatched types"); + + // 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. + // + // We also don't care about value-dependent expressions or expressions + // whose result is a constant. + if (!T->hasUnsignedIntegerRepresentation() + || E->isValueDependent() || E->isIntegerConstantExpr(S.Context)) + return AnalyzeImpConvsInComparison(S, E); + + Expr *LHS = E->getLHS()->IgnoreParenImpCasts(); + Expr *RHS = E->getRHS()->IgnoreParenImpCasts(); + + // Check to see if one of the (unmodified) operands is of different + // signedness. + Expr *signedOperand, *unsignedOperand; + if (LHS->getType()->hasSignedIntegerRepresentation()) { + assert(!RHS->getType()->hasSignedIntegerRepresentation() && + "unsigned comparison between two signed integer expressions?"); + signedOperand = LHS; + unsignedOperand = RHS; + } else if (RHS->getType()->hasSignedIntegerRepresentation()) { + signedOperand = RHS; + unsignedOperand = LHS; + } else { + CheckTrivialUnsignedComparison(S, E); + return AnalyzeImpConvsInComparison(S, E); + } + + // Otherwise, calculate the effective range of the signed operand. + IntRange signedRange = GetExprRange(S.Context, signedOperand); + + // Go ahead and analyze implicit conversions in the operands. Note + // that we skip the implicit conversions on both sides. + AnalyzeImplicitConversions(S, LHS, E->getOperatorLoc()); + AnalyzeImplicitConversions(S, RHS, E->getOperatorLoc()); + + // If the signed range is non-negative, -Wsign-compare won't fire, + // but we should still check for comparisons which are always true + // or false. + if (signedRange.NonNegative) + return CheckTrivialUnsignedComparison(S, E); + + // For (in)equality comparisons, if the unsigned operand is a + // constant which cannot collide with a overflowed signed operand, + // then reinterpreting the signed operand as unsigned will not + // change the result of the comparison. + if (E->isEqualityOp()) { + unsigned comparisonWidth = S.Context.getIntWidth(T); + IntRange unsignedRange = GetExprRange(S.Context, unsignedOperand); + + // We should never be unable to prove that the unsigned operand is + // non-negative. + assert(unsignedRange.NonNegative && "unsigned range includes negative?"); + + if (unsignedRange.Width < comparisonWidth) + return; + } + + S.Diag(E->getOperatorLoc(), diag::warn_mixed_sign_comparison) + << LHS->getType() << RHS->getType() + << LHS->getSourceRange() << RHS->getSourceRange(); +} + +/// Analyzes an attempt to assign the given value to a bitfield. +/// +/// Returns true if there was something fishy about the attempt. +static bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init, + SourceLocation InitLoc) { + assert(Bitfield->isBitField()); + if (Bitfield->isInvalidDecl()) + return false; + + // White-list bool bitfields. + if (Bitfield->getType()->isBooleanType()) + return false; + + // Ignore value- or type-dependent expressions. + if (Bitfield->getBitWidth()->isValueDependent() || + Bitfield->getBitWidth()->isTypeDependent() || + Init->isValueDependent() || + Init->isTypeDependent()) + return false; + + Expr *OriginalInit = Init->IgnoreParenImpCasts(); + + llvm::APSInt Value; + if (!OriginalInit->EvaluateAsInt(Value, S.Context, Expr::SE_AllowSideEffects)) + return false; + + unsigned OriginalWidth = Value.getBitWidth(); + unsigned FieldWidth = Bitfield->getBitWidthValue(S.Context); + + if (OriginalWidth <= FieldWidth) + return false; + + // Compute the value which the bitfield will contain. + llvm::APSInt TruncatedValue = Value.trunc(FieldWidth); + TruncatedValue.setIsSigned(Bitfield->getType()->isSignedIntegerType()); + + // Check whether the stored value is equal to the original value. + TruncatedValue = TruncatedValue.extend(OriginalWidth); + if (Value == TruncatedValue) + return false; + + // Special-case bitfields of width 1: booleans are naturally 0/1, and + // therefore don't strictly fit into a signed bitfield of width 1. + if (FieldWidth == 1 && Value == 1) + return false; + + std::string PrettyValue = Value.toString(10); + std::string PrettyTrunc = TruncatedValue.toString(10); + + S.Diag(InitLoc, diag::warn_impcast_bitfield_precision_constant) + << PrettyValue << PrettyTrunc << OriginalInit->getType() + << Init->getSourceRange(); + + return true; +} + +/// Analyze the given simple or compound assignment for warning-worthy +/// operations. +static void AnalyzeAssignment(Sema &S, BinaryOperator *E) { + // Just recurse on the LHS. + AnalyzeImplicitConversions(S, E->getLHS(), E->getOperatorLoc()); + + // We want to recurse on the RHS as normal unless we're assigning to + // a bitfield. + if (FieldDecl *Bitfield = E->getLHS()->getBitField()) { + if (AnalyzeBitFieldAssignment(S, Bitfield, E->getRHS(), + E->getOperatorLoc())) { + // Recurse, ignoring any implicit conversions on the RHS. + return AnalyzeImplicitConversions(S, E->getRHS()->IgnoreParenImpCasts(), + E->getOperatorLoc()); + } + } + + AnalyzeImplicitConversions(S, E->getRHS(), E->getOperatorLoc()); +} + +/// Diagnose an implicit cast; purely a helper for CheckImplicitConversion. +static void DiagnoseImpCast(Sema &S, Expr *E, QualType SourceType, QualType T, + SourceLocation CContext, unsigned diag, + bool pruneControlFlow = false) { + if (pruneControlFlow) { + S.DiagRuntimeBehavior(E->getExprLoc(), E, + S.PDiag(diag) + << SourceType << T << E->getSourceRange() + << SourceRange(CContext)); + return; + } + S.Diag(E->getExprLoc(), diag) + << SourceType << T << E->getSourceRange() << SourceRange(CContext); +} + +/// Diagnose an implicit cast; purely a helper for CheckImplicitConversion. +static void DiagnoseImpCast(Sema &S, Expr *E, QualType T, + SourceLocation CContext, unsigned diag, + bool pruneControlFlow = false) { + DiagnoseImpCast(S, E, E->getType(), T, CContext, diag, pruneControlFlow); +} + +/// Diagnose an implicit cast from a literal expression. Does not warn when the +/// cast wouldn't lose information. +void DiagnoseFloatingLiteralImpCast(Sema &S, FloatingLiteral *FL, QualType T, + SourceLocation CContext) { + // Try to convert the literal exactly to an integer. If we can, don't warn. + bool isExact = false; + const llvm::APFloat &Value = FL->getValue(); + llvm::APSInt IntegerValue(S.Context.getIntWidth(T), + T->hasUnsignedIntegerRepresentation()); + if (Value.convertToInteger(IntegerValue, + llvm::APFloat::rmTowardZero, &isExact) + == llvm::APFloat::opOK && isExact) + return; + + S.Diag(FL->getExprLoc(), diag::warn_impcast_literal_float_to_integer) + << FL->getType() << T << FL->getSourceRange() << SourceRange(CContext); +} + +std::string PrettyPrintInRange(const llvm::APSInt &Value, IntRange Range) { + if (!Range.Width) return "0"; + + llvm::APSInt ValueInRange = Value; + ValueInRange.setIsSigned(!Range.NonNegative); + ValueInRange = ValueInRange.trunc(Range.Width); + return ValueInRange.toString(10); +} + +void CheckImplicitConversion(Sema &S, Expr *E, QualType T, + SourceLocation CC, bool *ICContext = 0) { + if (E->isTypeDependent() || E->isValueDependent()) return; + + const Type *Source = S.Context.getCanonicalType(E->getType()).getTypePtr(); + const Type *Target = S.Context.getCanonicalType(T).getTypePtr(); + if (Source == Target) return; + if (Target->isDependentType()) return; + + // If the conversion context location is invalid don't complain. We also + // don't want to emit a warning if the issue occurs from the expansion of + // a system macro. The problem is that 'getSpellingLoc()' is slow, so we + // delay this check as long as possible. Once we detect we are in that + // scenario, we just return. + if (CC.isInvalid()) + return; + + // Diagnose implicit casts to bool. + if (Target->isSpecificBuiltinType(BuiltinType::Bool)) { + if (isa(E)) + // Warn on string literal to bool. Checks for string literals in logical + // expressions, for instances, assert(0 && "error here"), is prevented + // by a check in AnalyzeImplicitConversions(). + return DiagnoseImpCast(S, E, T, CC, + diag::warn_impcast_string_literal_to_bool); + if (Source->isFunctionType()) { + // Warn on function to bool. Checks free functions and static member + // functions. Weakly imported functions are excluded from the check, + // since it's common to test their value to check whether the linker + // found a definition for them. + ValueDecl *D = 0; + if (DeclRefExpr* R = dyn_cast(E)) { + D = R->getDecl(); + } else if (MemberExpr *M = dyn_cast(E)) { + D = M->getMemberDecl(); + } + + if (D && !D->isWeak()) { + if (FunctionDecl* F = dyn_cast(D)) { + S.Diag(E->getExprLoc(), diag::warn_impcast_function_to_bool) + << F << E->getSourceRange() << SourceRange(CC); + S.Diag(E->getExprLoc(), diag::note_function_to_bool_silence) + << FixItHint::CreateInsertion(E->getExprLoc(), "&"); + QualType ReturnType; + UnresolvedSet<4> NonTemplateOverloads; + S.isExprCallable(*E, ReturnType, NonTemplateOverloads); + if (!ReturnType.isNull() + && ReturnType->isSpecificBuiltinType(BuiltinType::Bool)) + S.Diag(E->getExprLoc(), diag::note_function_to_bool_call) + << FixItHint::CreateInsertion( + S.getPreprocessor().getLocForEndOfToken(E->getLocEnd()), "()"); + return; + } + } + } + return; // Other casts to bool are not checked. + } + + // Strip vector types. + if (isa(Source)) { + if (!isa(Target)) { + if (S.SourceMgr.isInSystemMacro(CC)) + return; + return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_vector_scalar); + } + + // If the vector cast is cast between two vectors of the same size, it is + // a bitcast, not a conversion. + if (S.Context.getTypeSize(Source) == S.Context.getTypeSize(Target)) + return; + + Source = cast(Source)->getElementType().getTypePtr(); + Target = cast(Target)->getElementType().getTypePtr(); + } + + // Strip complex types. + if (isa(Source)) { + if (!isa(Target)) { + if (S.SourceMgr.isInSystemMacro(CC)) + return; + + return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_complex_scalar); + } + + Source = cast(Source)->getElementType().getTypePtr(); + Target = cast(Target)->getElementType().getTypePtr(); + } + + const BuiltinType *SourceBT = dyn_cast(Source); + const BuiltinType *TargetBT = dyn_cast(Target); + + // If the source is floating point... + if (SourceBT && SourceBT->isFloatingPoint()) { + // ...and the target is floating point... + if (TargetBT && TargetBT->isFloatingPoint()) { + // ...then warn if we're dropping FP rank. + + // Builtin FP kinds are ordered by increasing FP rank. + if (SourceBT->getKind() > TargetBT->getKind()) { + // Don't warn about float constants that are precisely + // representable in the target type. + Expr::EvalResult result; + if (E->EvaluateAsRValue(result, S.Context)) { + // Value might be a float, a float vector, or a float complex. + if (IsSameFloatAfterCast(result.Val, + S.Context.getFloatTypeSemantics(QualType(TargetBT, 0)), + S.Context.getFloatTypeSemantics(QualType(SourceBT, 0)))) + return; + } + + if (S.SourceMgr.isInSystemMacro(CC)) + return; + + DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_float_precision); + } + return; + } + + // If the target is integral, always warn. + if ((TargetBT && TargetBT->isInteger())) { + if (S.SourceMgr.isInSystemMacro(CC)) + return; + + Expr *InnerE = E->IgnoreParenImpCasts(); + // We also want to warn on, e.g., "int i = -1.234" + if (UnaryOperator *UOp = dyn_cast(InnerE)) + if (UOp->getOpcode() == UO_Minus || UOp->getOpcode() == UO_Plus) + InnerE = UOp->getSubExpr()->IgnoreParenImpCasts(); + + if (FloatingLiteral *FL = dyn_cast(InnerE)) { + DiagnoseFloatingLiteralImpCast(S, FL, T, CC); + } else { + DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_float_integer); + } + } + + return; + } + + if (!Source->isIntegerType() || !Target->isIntegerType()) + return; + + if ((E->isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull) + == Expr::NPCK_GNUNull) && Target->isIntegerType()) { + SourceLocation Loc = E->getSourceRange().getBegin(); + if (Loc.isMacroID()) + Loc = S.SourceMgr.getImmediateExpansionRange(Loc).first; + S.Diag(Loc, diag::warn_impcast_null_pointer_to_integer) + << T << Loc << clang::SourceRange(CC); + return; + } + + IntRange SourceRange = GetExprRange(S.Context, E); + IntRange TargetRange = IntRange::forTargetOfCanonicalType(S.Context, Target); + + if (SourceRange.Width > TargetRange.Width) { + // If the source is a constant, use a default-on diagnostic. + // TODO: this should happen for bitfield stores, too. + llvm::APSInt Value(32); + if (E->isIntegerConstantExpr(Value, S.Context)) { + if (S.SourceMgr.isInSystemMacro(CC)) + return; + + std::string PrettySourceValue = Value.toString(10); + std::string PrettyTargetValue = PrettyPrintInRange(Value, TargetRange); + + S.DiagRuntimeBehavior(E->getExprLoc(), E, + S.PDiag(diag::warn_impcast_integer_precision_constant) + << PrettySourceValue << PrettyTargetValue + << E->getType() << T << E->getSourceRange() + << clang::SourceRange(CC)); + return; + } + + // People want to build with -Wshorten-64-to-32 and not -Wconversion. + if (S.SourceMgr.isInSystemMacro(CC)) + return; + + if (TargetRange.Width == 32 && S.Context.getIntWidth(E->getType()) == 64) + return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_integer_64_32, + /* pruneControlFlow */ true); + return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_integer_precision); + } + + if ((TargetRange.NonNegative && !SourceRange.NonNegative) || + (!TargetRange.NonNegative && SourceRange.NonNegative && + SourceRange.Width == TargetRange.Width)) { + + if (S.SourceMgr.isInSystemMacro(CC)) + return; + + unsigned DiagID = diag::warn_impcast_integer_sign; + + // Traditionally, gcc has warned about this under -Wsign-compare. + // We also want to warn about it in -Wconversion. + // So if -Wconversion is off, use a completely identical diagnostic + // in the sign-compare group. + // The conditional-checking code will + if (ICContext) { + DiagID = diag::warn_impcast_integer_sign_conditional; + *ICContext = true; + } + + return DiagnoseImpCast(S, E, T, CC, DiagID); + } + + // Diagnose conversions between different enumeration types. + // In C, we pretend that the type of an EnumConstantDecl is its enumeration + // type, to give us better diagnostics. + QualType SourceType = E->getType(); + if (!S.getLangOpts().CPlusPlus) { + if (DeclRefExpr *DRE = dyn_cast(E)) + if (EnumConstantDecl *ECD = dyn_cast(DRE->getDecl())) { + EnumDecl *Enum = cast(ECD->getDeclContext()); + SourceType = S.Context.getTypeDeclType(Enum); + Source = S.Context.getCanonicalType(SourceType).getTypePtr(); + } + } + + if (const EnumType *SourceEnum = Source->getAs()) + if (const EnumType *TargetEnum = Target->getAs()) + if ((SourceEnum->getDecl()->getIdentifier() || + SourceEnum->getDecl()->getTypedefNameForAnonDecl()) && + (TargetEnum->getDecl()->getIdentifier() || + TargetEnum->getDecl()->getTypedefNameForAnonDecl()) && + SourceEnum != TargetEnum) { + if (S.SourceMgr.isInSystemMacro(CC)) + return; + + return DiagnoseImpCast(S, E, SourceType, T, CC, + diag::warn_impcast_different_enum_types); + } + + return; +} + +void CheckConditionalOperator(Sema &S, ConditionalOperator *E, QualType T); + +void CheckConditionalOperand(Sema &S, Expr *E, QualType T, + SourceLocation CC, bool &ICContext) { + E = E->IgnoreParenImpCasts(); + + if (isa(E)) + return CheckConditionalOperator(S, cast(E), T); + + AnalyzeImplicitConversions(S, E, CC); + if (E->getType() != T) + return CheckImplicitConversion(S, E, T, CC, &ICContext); + return; +} + +void CheckConditionalOperator(Sema &S, ConditionalOperator *E, QualType T) { + SourceLocation CC = E->getQuestionLoc(); + + AnalyzeImplicitConversions(S, E->getCond(), CC); + + bool Suspicious = false; + CheckConditionalOperand(S, E->getTrueExpr(), T, CC, Suspicious); + CheckConditionalOperand(S, E->getFalseExpr(), T, CC, Suspicious); + + // If -Wconversion would have warned about either of the candidates + // for a signedness conversion to the context type... + if (!Suspicious) return; + + // ...but it's currently ignored... + if (S.Diags.getDiagnosticLevel(diag::warn_impcast_integer_sign_conditional, + CC)) + return; + + // ...then check whether it would have warned about either of the + // candidates for a signedness conversion to the condition type. + if (E->getType() == T) return; + + Suspicious = false; + CheckImplicitConversion(S, E->getTrueExpr()->IgnoreParenImpCasts(), + E->getType(), CC, &Suspicious); + if (!Suspicious) + CheckImplicitConversion(S, E->getFalseExpr()->IgnoreParenImpCasts(), + E->getType(), CC, &Suspicious); +} + +/// AnalyzeImplicitConversions - Find and report any interesting +/// implicit conversions in the given expression. There are a couple +/// of competing diagnostics here, -Wconversion and -Wsign-compare. +void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) { + QualType T = OrigE->getType(); + Expr *E = OrigE->IgnoreParenImpCasts(); + + if (E->isTypeDependent() || E->isValueDependent()) + return; + + // For conditional operators, we analyze the arguments as if they + // were being fed directly into the output. + if (isa(E)) { + ConditionalOperator *CO = cast(E); + CheckConditionalOperator(S, CO, T); + return; + } + + // Go ahead and check any implicit conversions we might have skipped. + // The non-canonical typecheck is just an optimization; + // CheckImplicitConversion will filter out dead implicit conversions. + if (E->getType() != T) + CheckImplicitConversion(S, E, T, CC); + + // Now continue drilling into this expression. + + // Skip past explicit casts. + if (isa(E)) { + E = cast(E)->getSubExpr()->IgnoreParenImpCasts(); + return AnalyzeImplicitConversions(S, E, CC); + } + + if (BinaryOperator *BO = dyn_cast(E)) { + // Do a somewhat different check with comparison operators. + if (BO->isComparisonOp()) + return AnalyzeComparison(S, BO); + + // And with simple assignments. + if (BO->getOpcode() == BO_Assign) + return AnalyzeAssignment(S, BO); + } + + // These break the otherwise-useful invariant below. Fortunately, + // we don't really need to recurse into them, because any internal + // expressions should have been analyzed already when they were + // built into statements. + if (isa(E)) return; + + // Don't descend into unevaluated contexts. + if (isa(E)) return; + + // Now just recurse over the expression's children. + CC = E->getExprLoc(); + BinaryOperator *BO = dyn_cast(E); + bool IsLogicalOperator = BO && BO->isLogicalOp(); + for (Stmt::child_range I = E->children(); I; ++I) { + Expr *ChildExpr = dyn_cast_or_null(*I); + if (!ChildExpr) + continue; + + if (IsLogicalOperator && + isa(ChildExpr->IgnoreParenImpCasts())) + // Ignore checking string literals that are in logical operators. + continue; + AnalyzeImplicitConversions(S, ChildExpr, CC); + } +} + +} // end anonymous namespace + +/// Diagnoses "dangerous" implicit conversions within the given +/// expression (which is a full expression). Implements -Wconversion +/// and -Wsign-compare. +/// +/// \param CC the "context" location of the implicit conversion, i.e. +/// the most location of the syntactic entity requiring the implicit +/// conversion +void Sema::CheckImplicitConversions(Expr *E, SourceLocation CC) { + // Don't diagnose in unevaluated contexts. + if (ExprEvalContexts.back().Context == Sema::Unevaluated) + return; + + // Don't diagnose for value- or type-dependent expressions. + if (E->isTypeDependent() || E->isValueDependent()) + return; + + // Check for array bounds violations in cases where the check isn't triggered + // elsewhere for other Expr types (like BinaryOperators), e.g. when an + // ArraySubscriptExpr is on the RHS of a variable initialization. + CheckArrayAccess(E); + + // This is not the right CC for (e.g.) a variable initialization. + AnalyzeImplicitConversions(*this, E, CC); +} + +void Sema::CheckBitFieldInitialization(SourceLocation InitLoc, + FieldDecl *BitField, + Expr *Init) { + (void) AnalyzeBitFieldAssignment(*this, BitField, Init, InitLoc); +} + +/// CheckParmsForFunctionDef - Check that the parameters of the given +/// function are appropriate for the definition of a function. This +/// takes care of any checks that cannot be performed on the +/// declaration itself, e.g., that the types of each of the function +/// parameters are complete. +bool Sema::CheckParmsForFunctionDef(ParmVarDecl **P, ParmVarDecl **PEnd, + bool CheckParameterNames) { + bool HasInvalidParm = false; + for (; P != PEnd; ++P) { + ParmVarDecl *Param = *P; + + // C99 6.7.5.3p4: the parameters in a parameter type list in a + // function declarator that is part of a function definition of + // that function shall not have incomplete type. + // + // This is also C++ [dcl.fct]p6. + if (!Param->isInvalidDecl() && + RequireCompleteType(Param->getLocation(), Param->getType(), + diag::err_typecheck_decl_incomplete_type)) { + Param->setInvalidDecl(); + HasInvalidParm = true; + } + + // C99 6.9.1p5: If the declarator includes a parameter type list, the + // declaration of each parameter shall include an identifier. + if (CheckParameterNames && + Param->getIdentifier() == 0 && + !Param->isImplicit() && + !getLangOpts().CPlusPlus) + Diag(Param->getLocation(), diag::err_parameter_name_omitted); + + // C99 6.7.5.3p12: + // If the function declarator is not part of a definition of that + // function, parameters may have incomplete type and may use the [*] + // notation in their sequences of declarator specifiers to specify + // variable length array types. + QualType PType = Param->getOriginalType(); + if (const ArrayType *AT = Context.getAsArrayType(PType)) { + if (AT->getSizeModifier() == ArrayType::Star) { + // FIXME: This diagnosic should point the the '[*]' if source-location + // information is added for it. + Diag(Param->getLocation(), diag::err_array_star_in_function_definition); + } + } + } + + 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, + TRange.getBegin()) + == DiagnosticsEngine::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(); +} + +static const Type* getElementType(const Expr *BaseExpr) { + const Type* EltType = BaseExpr->getType().getTypePtr(); + if (EltType->isAnyPointerType()) + return EltType->getPointeeType().getTypePtr(); + else if (EltType->isArrayType()) + return EltType->getBaseElementTypeUnsafe(); + return EltType; +} + +/// \brief Check whether this array fits the idiom of a size-one tail padded +/// array member of a struct. +/// +/// We avoid emitting out-of-bounds access warnings for such arrays as they are +/// commonly used to emulate flexible arrays in C89 code. +static bool IsTailPaddedMemberArray(Sema &S, llvm::APInt Size, + const NamedDecl *ND) { + if (Size != 1 || !ND) return false; + + const FieldDecl *FD = dyn_cast(ND); + if (!FD) return false; + + // Don't consider sizes resulting from macro expansions or template argument + // substitution to form C89 tail-padded arrays. + ConstantArrayTypeLoc TL = + cast(FD->getTypeSourceInfo()->getTypeLoc()); + const Expr *SizeExpr = dyn_cast(TL.getSizeExpr()); + if (!SizeExpr || SizeExpr->getExprLoc().isMacroID()) + return false; + + const RecordDecl *RD = dyn_cast(FD->getDeclContext()); + if (!RD) return false; + if (RD->isUnion()) return false; + if (const CXXRecordDecl *CRD = dyn_cast(RD)) { + if (!CRD->isStandardLayout()) return false; + } + + // See if this is the last field decl in the record. + const Decl *D = FD; + while ((D = D->getNextDeclInContext())) + if (isa(D)) + return false; + return true; +} + +void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr, + const ArraySubscriptExpr *ASE, + bool AllowOnePastEnd, bool IndexNegated) { + IndexExpr = IndexExpr->IgnoreParenImpCasts(); + if (IndexExpr->isValueDependent()) + return; + + const Type *EffectiveType = getElementType(BaseExpr); + BaseExpr = BaseExpr->IgnoreParenCasts(); + const ConstantArrayType *ArrayTy = + Context.getAsConstantArrayType(BaseExpr->getType()); + if (!ArrayTy) + return; + + llvm::APSInt index; + if (!IndexExpr->EvaluateAsInt(index, Context)) + return; + if (IndexNegated) + index = -index; + + const NamedDecl *ND = NULL; + if (const DeclRefExpr *DRE = dyn_cast(BaseExpr)) + ND = dyn_cast(DRE->getDecl()); + if (const MemberExpr *ME = dyn_cast(BaseExpr)) + ND = dyn_cast(ME->getMemberDecl()); + + if (index.isUnsigned() || !index.isNegative()) { + llvm::APInt size = ArrayTy->getSize(); + if (!size.isStrictlyPositive()) + return; + + const Type* BaseType = getElementType(BaseExpr); + if (BaseType != EffectiveType) { + // Make sure we're comparing apples to apples when comparing index to size + uint64_t ptrarith_typesize = Context.getTypeSize(EffectiveType); + uint64_t array_typesize = Context.getTypeSize(BaseType); + // Handle ptrarith_typesize being zero, such as when casting to void* + if (!ptrarith_typesize) ptrarith_typesize = 1; + if (ptrarith_typesize != array_typesize) { + // There's a cast to a different size type involved + uint64_t ratio = array_typesize / ptrarith_typesize; + // TODO: Be smarter about handling cases where array_typesize is not a + // multiple of ptrarith_typesize + if (ptrarith_typesize * ratio == array_typesize) + size *= llvm::APInt(size.getBitWidth(), ratio); + } + } + + if (size.getBitWidth() > index.getBitWidth()) + index = index.zext(size.getBitWidth()); + else if (size.getBitWidth() < index.getBitWidth()) + size = size.zext(index.getBitWidth()); + + // For array subscripting the index must be less than size, but for pointer + // arithmetic also allow the index (offset) to be equal to size since + // computing the next address after the end of the array is legal and + // commonly done e.g. in C++ iterators and range-based for loops. + if (AllowOnePastEnd ? index.ule(size) : index.ult(size)) + return; + + // Also don't warn for arrays of size 1 which are members of some + // structure. These are often used to approximate flexible arrays in C89 + // code. + if (IsTailPaddedMemberArray(*this, size, ND)) + return; + + // Suppress the warning if the subscript expression (as identified by the + // ']' location) and the index expression are both from macro expansions + // within a system header. + if (ASE) { + SourceLocation RBracketLoc = SourceMgr.getSpellingLoc( + ASE->getRBracketLoc()); + if (SourceMgr.isInSystemHeader(RBracketLoc)) { + SourceLocation IndexLoc = SourceMgr.getSpellingLoc( + IndexExpr->getLocStart()); + if (SourceMgr.isFromSameFile(RBracketLoc, IndexLoc)) + return; + } + } + + unsigned DiagID = diag::warn_ptr_arith_exceeds_bounds; + if (ASE) + DiagID = diag::warn_array_index_exceeds_bounds; + + DiagRuntimeBehavior(BaseExpr->getLocStart(), BaseExpr, + PDiag(DiagID) << index.toString(10, true) + << size.toString(10, true) + << (unsigned)size.getLimitedValue(~0U) + << IndexExpr->getSourceRange()); + } else { + unsigned DiagID = diag::warn_array_index_precedes_bounds; + if (!ASE) { + DiagID = diag::warn_ptr_arith_precedes_bounds; + if (index.isNegative()) index = -index; + } + + DiagRuntimeBehavior(BaseExpr->getLocStart(), BaseExpr, + PDiag(DiagID) << index.toString(10, true) + << IndexExpr->getSourceRange()); + } + + if (!ND) { + // Try harder to find a NamedDecl to point at in the note. + while (const ArraySubscriptExpr *ASE = + dyn_cast(BaseExpr)) + BaseExpr = ASE->getBase()->IgnoreParenCasts(); + if (const DeclRefExpr *DRE = dyn_cast(BaseExpr)) + ND = dyn_cast(DRE->getDecl()); + if (const MemberExpr *ME = dyn_cast(BaseExpr)) + ND = dyn_cast(ME->getMemberDecl()); + } + + if (ND) + DiagRuntimeBehavior(ND->getLocStart(), BaseExpr, + PDiag(diag::note_array_index_out_of_bounds) + << ND->getDeclName()); +} + +void Sema::CheckArrayAccess(const Expr *expr) { + int AllowOnePastEnd = 0; + while (expr) { + expr = expr->IgnoreParenImpCasts(); + switch (expr->getStmtClass()) { + case Stmt::ArraySubscriptExprClass: { + const ArraySubscriptExpr *ASE = cast(expr); + CheckArrayAccess(ASE->getBase(), ASE->getIdx(), ASE, + AllowOnePastEnd > 0); + return; + } + case Stmt::UnaryOperatorClass: { + // Only unwrap the * and & unary operators + const UnaryOperator *UO = cast(expr); + expr = UO->getSubExpr(); + switch (UO->getOpcode()) { + case UO_AddrOf: + AllowOnePastEnd++; + break; + case UO_Deref: + AllowOnePastEnd--; + break; + default: + return; + } + break; + } + case Stmt::ConditionalOperatorClass: { + const ConditionalOperator *cond = cast(expr); + if (const Expr *lhs = cond->getLHS()) + CheckArrayAccess(lhs); + if (const Expr *rhs = cond->getRHS()) + CheckArrayAccess(rhs); + return; + } + default: + return; + } + } +} + +//===--- CHECK: Objective-C retain cycles ----------------------------------// + +namespace { + struct RetainCycleOwner { + RetainCycleOwner() : Variable(0), Indirect(false) {} + VarDecl *Variable; + SourceRange Range; + SourceLocation Loc; + bool Indirect; + + void setLocsFrom(Expr *e) { + Loc = e->getExprLoc(); + Range = e->getSourceRange(); + } + }; +} + +/// Consider whether capturing the given variable can possibly lead to +/// a retain cycle. +static bool considerVariable(VarDecl *var, Expr *ref, RetainCycleOwner &owner) { + // In ARC, it's captured strongly iff the variable has __strong + // lifetime. In MRR, it's captured strongly if the variable is + // __block and has an appropriate type. + if (var->getType().getObjCLifetime() != Qualifiers::OCL_Strong) + return false; + + owner.Variable = var; + owner.setLocsFrom(ref); + return true; +} + +static bool findRetainCycleOwner(Sema &S, Expr *e, RetainCycleOwner &owner) { + while (true) { + e = e->IgnoreParens(); + if (CastExpr *cast = dyn_cast(e)) { + switch (cast->getCastKind()) { + case CK_BitCast: + case CK_LValueBitCast: + case CK_LValueToRValue: + case CK_ARCReclaimReturnedObject: + e = cast->getSubExpr(); + continue; + + default: + return false; + } + } + + if (ObjCIvarRefExpr *ref = dyn_cast(e)) { + ObjCIvarDecl *ivar = ref->getDecl(); + if (ivar->getType().getObjCLifetime() != Qualifiers::OCL_Strong) + return false; + + // Try to find a retain cycle in the base. + if (!findRetainCycleOwner(S, ref->getBase(), owner)) + return false; + + if (ref->isFreeIvar()) owner.setLocsFrom(ref); + owner.Indirect = true; + return true; + } + + if (DeclRefExpr *ref = dyn_cast(e)) { + VarDecl *var = dyn_cast(ref->getDecl()); + if (!var) return false; + return considerVariable(var, ref, owner); + } + + if (MemberExpr *member = dyn_cast(e)) { + if (member->isArrow()) return false; + + // Don't count this as an indirect ownership. + e = member->getBase(); + continue; + } + + if (PseudoObjectExpr *pseudo = dyn_cast(e)) { + // Only pay attention to pseudo-objects on property references. + ObjCPropertyRefExpr *pre + = dyn_cast(pseudo->getSyntacticForm() + ->IgnoreParens()); + if (!pre) return false; + if (pre->isImplicitProperty()) return false; + ObjCPropertyDecl *property = pre->getExplicitProperty(); + if (!property->isRetaining() && + !(property->getPropertyIvarDecl() && + property->getPropertyIvarDecl()->getType() + .getObjCLifetime() == Qualifiers::OCL_Strong)) + return false; + + owner.Indirect = true; + if (pre->isSuperReceiver()) { + owner.Variable = S.getCurMethodDecl()->getSelfDecl(); + if (!owner.Variable) + return false; + owner.Loc = pre->getLocation(); + owner.Range = pre->getSourceRange(); + return true; + } + e = const_cast(cast(pre->getBase()) + ->getSourceExpr()); + continue; + } + + // Array ivars? + + return false; + } +} + +namespace { + struct FindCaptureVisitor : EvaluatedExprVisitor { + FindCaptureVisitor(ASTContext &Context, VarDecl *variable) + : EvaluatedExprVisitor(Context), + Variable(variable), Capturer(0) {} + + VarDecl *Variable; + Expr *Capturer; + + void VisitDeclRefExpr(DeclRefExpr *ref) { + if (ref->getDecl() == Variable && !Capturer) + Capturer = ref; + } + + void VisitObjCIvarRefExpr(ObjCIvarRefExpr *ref) { + if (Capturer) return; + Visit(ref->getBase()); + if (Capturer && ref->isFreeIvar()) + Capturer = ref; + } + + void VisitBlockExpr(BlockExpr *block) { + // Look inside nested blocks + if (block->getBlockDecl()->capturesVariable(Variable)) + Visit(block->getBlockDecl()->getBody()); + } + }; +} + +/// Check whether the given argument is a block which captures a +/// variable. +static Expr *findCapturingExpr(Sema &S, Expr *e, RetainCycleOwner &owner) { + assert(owner.Variable && owner.Loc.isValid()); + + e = e->IgnoreParenCasts(); + BlockExpr *block = dyn_cast(e); + if (!block || !block->getBlockDecl()->capturesVariable(owner.Variable)) + return 0; + + FindCaptureVisitor visitor(S.Context, owner.Variable); + visitor.Visit(block->getBlockDecl()->getBody()); + return visitor.Capturer; +} + +static void diagnoseRetainCycle(Sema &S, Expr *capturer, + RetainCycleOwner &owner) { + assert(capturer); + assert(owner.Variable && owner.Loc.isValid()); + + S.Diag(capturer->getExprLoc(), diag::warn_arc_retain_cycle) + << owner.Variable << capturer->getSourceRange(); + S.Diag(owner.Loc, diag::note_arc_retain_cycle_owner) + << owner.Indirect << owner.Range; +} + +/// Check for a keyword selector that starts with the word 'add' or +/// 'set'. +static bool isSetterLikeSelector(Selector sel) { + if (sel.isUnarySelector()) return false; + + StringRef str = sel.getNameForSlot(0); + while (!str.empty() && str.front() == '_') str = str.substr(1); + if (str.startswith("set")) + str = str.substr(3); + else if (str.startswith("add")) { + // Specially whitelist 'addOperationWithBlock:'. + if (sel.getNumArgs() == 1 && str.startswith("addOperationWithBlock")) + return false; + str = str.substr(3); + } + else + return false; + + if (str.empty()) return true; + return !islower(str.front()); +} + +/// Check a message send to see if it's likely to cause a retain cycle. +void Sema::checkRetainCycles(ObjCMessageExpr *msg) { + // Only check instance methods whose selector looks like a setter. + if (!msg->isInstanceMessage() || !isSetterLikeSelector(msg->getSelector())) + return; + + // Try to find a variable that the receiver is strongly owned by. + RetainCycleOwner owner; + if (msg->getReceiverKind() == ObjCMessageExpr::Instance) { + if (!findRetainCycleOwner(*this, msg->getInstanceReceiver(), owner)) + return; + } else { + assert(msg->getReceiverKind() == ObjCMessageExpr::SuperInstance); + owner.Variable = getCurMethodDecl()->getSelfDecl(); + owner.Loc = msg->getSuperLoc(); + owner.Range = msg->getSuperLoc(); + } + + // Check whether the receiver is captured by any of the arguments. + for (unsigned i = 0, e = msg->getNumArgs(); i != e; ++i) + if (Expr *capturer = findCapturingExpr(*this, msg->getArg(i), owner)) + return diagnoseRetainCycle(*this, capturer, owner); +} + +/// Check a property assign to see if it's likely to cause a retain cycle. +void Sema::checkRetainCycles(Expr *receiver, Expr *argument) { + RetainCycleOwner owner; + if (!findRetainCycleOwner(*this, receiver, owner)) + return; + + if (Expr *capturer = findCapturingExpr(*this, argument, owner)) + diagnoseRetainCycle(*this, capturer, owner); +} + +bool Sema::checkUnsafeAssigns(SourceLocation Loc, + QualType LHS, Expr *RHS) { + Qualifiers::ObjCLifetime LT = LHS.getObjCLifetime(); + if (LT != Qualifiers::OCL_Weak && LT != Qualifiers::OCL_ExplicitNone) + return false; + // strip off any implicit cast added to get to the one arc-specific + while (ImplicitCastExpr *cast = dyn_cast(RHS)) { + if (cast->getCastKind() == CK_ARCConsumeObject) { + Diag(Loc, diag::warn_arc_retained_assign) + << (LT == Qualifiers::OCL_ExplicitNone) + << RHS->getSourceRange(); + return true; + } + RHS = cast->getSubExpr(); + } + return false; +} + +void Sema::checkUnsafeExprAssigns(SourceLocation Loc, + Expr *LHS, Expr *RHS) { + QualType LHSType; + // PropertyRef on LHS type need be directly obtained from + // its declaration as it has a PsuedoType. + ObjCPropertyRefExpr *PRE + = dyn_cast(LHS->IgnoreParens()); + if (PRE && !PRE->isImplicitProperty()) { + const ObjCPropertyDecl *PD = PRE->getExplicitProperty(); + if (PD) + LHSType = PD->getType(); + } + + if (LHSType.isNull()) + LHSType = LHS->getType(); + if (checkUnsafeAssigns(Loc, LHSType, RHS)) + return; + Qualifiers::ObjCLifetime LT = LHSType.getObjCLifetime(); + // FIXME. Check for other life times. + if (LT != Qualifiers::OCL_None) + return; + + if (PRE) { + if (PRE->isImplicitProperty()) + return; + const ObjCPropertyDecl *PD = PRE->getExplicitProperty(); + if (!PD) + return; + + unsigned Attributes = PD->getPropertyAttributes(); + if (Attributes & ObjCPropertyDecl::OBJC_PR_assign) { + // when 'assign' attribute was not explicitly specified + // by user, ignore it and rely on property type itself + // for lifetime info. + unsigned AsWrittenAttr = PD->getPropertyAttributesAsWritten(); + if (!(AsWrittenAttr & ObjCPropertyDecl::OBJC_PR_assign) && + LHSType->isObjCRetainableType()) + return; + + while (ImplicitCastExpr *cast = dyn_cast(RHS)) { + if (cast->getCastKind() == CK_ARCConsumeObject) { + Diag(Loc, diag::warn_arc_retained_property_assign) + << RHS->getSourceRange(); + return; + } + RHS = cast->getSubExpr(); + } + } + } +} + +//===--- CHECK: Empty statement body (-Wempty-body) ---------------------===// + +namespace { +bool ShouldDiagnoseEmptyStmtBody(const SourceManager &SourceMgr, + SourceLocation StmtLoc, + const NullStmt *Body) { + // Do not warn if the body is a macro that expands to nothing, e.g: + // + // #define CALL(x) + // if (condition) + // CALL(0); + // + if (Body->hasLeadingEmptyMacro()) + return false; + + // Get line numbers of statement and body. + bool StmtLineInvalid; + unsigned StmtLine = SourceMgr.getSpellingLineNumber(StmtLoc, + &StmtLineInvalid); + if (StmtLineInvalid) + return false; + + bool BodyLineInvalid; + unsigned BodyLine = SourceMgr.getSpellingLineNumber(Body->getSemiLoc(), + &BodyLineInvalid); + if (BodyLineInvalid) + return false; + + // Warn if null statement and body are on the same line. + if (StmtLine != BodyLine) + return false; + + return true; +} +} // Unnamed namespace + +void Sema::DiagnoseEmptyStmtBody(SourceLocation StmtLoc, + const Stmt *Body, + unsigned DiagID) { + // Since this is a syntactic check, don't emit diagnostic for template + // instantiations, this just adds noise. + if (CurrentInstantiationScope) + return; + + // The body should be a null statement. + const NullStmt *NBody = dyn_cast(Body); + if (!NBody) + return; + + // Do the usual checks. + if (!ShouldDiagnoseEmptyStmtBody(SourceMgr, StmtLoc, NBody)) + return; + + Diag(NBody->getSemiLoc(), DiagID); + Diag(NBody->getSemiLoc(), diag::note_empty_body_on_separate_line); +} + +void Sema::DiagnoseEmptyLoopBody(const Stmt *S, + const Stmt *PossibleBody) { + assert(!CurrentInstantiationScope); // Ensured by caller + + SourceLocation StmtLoc; + const Stmt *Body; + unsigned DiagID; + if (const ForStmt *FS = dyn_cast(S)) { + StmtLoc = FS->getRParenLoc(); + Body = FS->getBody(); + DiagID = diag::warn_empty_for_body; + } else if (const WhileStmt *WS = dyn_cast(S)) { + StmtLoc = WS->getCond()->getSourceRange().getEnd(); + Body = WS->getBody(); + DiagID = diag::warn_empty_while_body; + } else + return; // Neither `for' nor `while'. + + // The body should be a null statement. + const NullStmt *NBody = dyn_cast(Body); + if (!NBody) + return; + + // Skip expensive checks if diagnostic is disabled. + if (Diags.getDiagnosticLevel(DiagID, NBody->getSemiLoc()) == + DiagnosticsEngine::Ignored) + return; + + // Do the usual checks. + if (!ShouldDiagnoseEmptyStmtBody(SourceMgr, StmtLoc, NBody)) + return; + + // `for(...);' and `while(...);' are popular idioms, so in order to keep + // noise level low, emit diagnostics only if for/while is followed by a + // CompoundStmt, e.g.: + // for (int i = 0; i < n; i++); + // { + // a(i); + // } + // or if for/while is followed by a statement with more indentation + // than for/while itself: + // for (int i = 0; i < n; i++); + // a(i); + bool ProbableTypo = isa(PossibleBody); + if (!ProbableTypo) { + bool BodyColInvalid; + unsigned BodyCol = SourceMgr.getPresumedColumnNumber( + PossibleBody->getLocStart(), + &BodyColInvalid); + if (BodyColInvalid) + return; + + bool StmtColInvalid; + unsigned StmtCol = SourceMgr.getPresumedColumnNumber( + S->getLocStart(), + &StmtColInvalid); + if (StmtColInvalid) + return; + + if (BodyCol > StmtCol) + ProbableTypo = true; + } + + if (ProbableTypo) { + Diag(NBody->getSemiLoc(), DiagID); + Diag(NBody->getSemiLoc(), diag::note_empty_body_on_separate_line); + } +} diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp new file mode 100644 index 0000000..1ee7532 --- /dev/null +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -0,0 +1,7178 @@ +//===---------------- SemaCodeComplete.cpp - Code Completion ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the code-completion semantic actions. +// +//===----------------------------------------------------------------------===// +#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/HeaderSearch.h" +#include "clang/Lex/MacroInfo.h" +#include "clang/Lex/Preprocessor.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/SmallBitVector.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallString.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. + class ResultBuilder { + public: + /// \brief The type of a name-lookup filter, which can be provided to the + /// name-lookup routines to specify which declarations should be included in + /// the result set (when it returns true) and which declarations should be + /// filtered out (returns false). + typedef bool (ResultBuilder::*LookupFilter)(NamedDecl *) const; + + typedef CodeCompletionResult Result; + + private: + /// \brief The actual results we have found. + std::vector Results; + + /// \brief A record of all of the declarations we have found and placed + /// into the result set, used to ensure that no declaration ever gets into + /// the result set twice. + llvm::SmallPtrSet AllDeclsFound; + + typedef std::pair DeclIndexPair; + + /// \brief An entry in the shadow map, which is optimized to store + /// a single (declaration, index) mapping (the common case) but + /// can also store a list of (declaration, index) mappings. + class ShadowMapEntry { + typedef SmallVector DeclIndexPairVector; + + /// \brief Contains either the solitary NamedDecl * or a vector + /// of (declaration, index) pairs. + llvm::PointerUnion DeclOrVector; + + /// \brief When the entry contains a single declaration, this is + /// the index associated with that entry. + unsigned SingleDeclIndex; + + public: + ShadowMapEntry() : DeclOrVector(), SingleDeclIndex(0) { } + + void Add(NamedDecl *ND, unsigned Index) { + if (DeclOrVector.isNull()) { + // 0 - > 1 elements: just set the single element information. + DeclOrVector = ND; + SingleDeclIndex = Index; + return; + } + + if (NamedDecl *PrevND = DeclOrVector.dyn_cast()) { + // 1 -> 2 elements: create the vector of results and push in the + // existing declaration. + DeclIndexPairVector *Vec = new DeclIndexPairVector; + Vec->push_back(DeclIndexPair(PrevND, SingleDeclIndex)); + DeclOrVector = Vec; + } + + // Add the new element to the end of the vector. + DeclOrVector.get()->push_back( + DeclIndexPair(ND, Index)); + } + + void Destroy() { + if (DeclIndexPairVector *Vec + = DeclOrVector.dyn_cast()) { + delete Vec; + DeclOrVector = ((NamedDecl *)0); + } + } + + // Iteration. + class iterator; + iterator begin() const; + iterator end() const; + }; + + /// \brief A mapping from declaration names to the declarations that have + /// this name within a particular scope and their index within the list of + /// results. + typedef llvm::DenseMap ShadowMap; + + /// \brief The semantic analysis object for which results are being + /// produced. + Sema &SemaRef; + + /// \brief The allocator used to allocate new code-completion strings. + CodeCompletionAllocator &Allocator; + + CodeCompletionTUInfo &CCTUInfo; + + /// \brief If non-NULL, a filter function used to remove any code-completion + /// results that are not desirable. + LookupFilter Filter; + + /// \brief Whether we should allow declarations as + /// nested-name-specifiers that would otherwise be filtered out. + bool AllowNestedNameSpecifiers; + + /// \brief If set, the type that we would prefer our resulting value + /// declarations to have. + /// + /// Closely matching the preferred type gives a boost to a result's + /// priority. + CanQualType PreferredType; + + /// \brief A list of shadow maps, which is used to model name hiding at + /// 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; + + /// \brief The completion context in which we are gathering results. + CodeCompletionContext CompletionContext; + + /// \brief If we are in an instance method definition, the @implementation + /// object. + ObjCImplementationDecl *ObjCImplementation; + + void AdjustResultPriorityForDecl(Result &R); + + void MaybeAddConstructorResults(Result R); + + public: + explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator, + CodeCompletionTUInfo &CCTUInfo, + const CodeCompletionContext &CompletionContext, + LookupFilter Filter = 0) + : SemaRef(SemaRef), Allocator(Allocator), CCTUInfo(CCTUInfo), + Filter(Filter), + AllowNestedNameSpecifiers(false), HasObjectTypeQualifiers(false), + CompletionContext(CompletionContext), + ObjCImplementation(0) + { + // If this is an Objective-C instance method definition, dig out the + // corresponding implementation. + switch (CompletionContext.getKind()) { + case CodeCompletionContext::CCC_Expression: + case CodeCompletionContext::CCC_ObjCMessageReceiver: + case CodeCompletionContext::CCC_ParenthesizedExpression: + case CodeCompletionContext::CCC_Statement: + case CodeCompletionContext::CCC_Recovery: + if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) + if (Method->isInstanceMethod()) + if (ObjCInterfaceDecl *Interface = Method->getClassInterface()) + ObjCImplementation = Interface->getImplementation(); + break; + + default: + break; + } + } + + /// \brief Whether we should include code patterns in the completion + /// results. + bool includeCodePatterns() const { + return SemaRef.CodeCompleter && + SemaRef.CodeCompleter->includeCodePatterns(); + } + + /// \brief Set the filter used for code-completion results. + void setFilter(LookupFilter Filter) { + this->Filter = Filter; + } + + Result *data() { return Results.empty()? 0 : &Results.front(); } + unsigned size() const { return Results.size(); } + bool empty() const { return Results.empty(); } + + /// \brief Specify the preferred type. + void setPreferredType(QualType T) { + 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 Retrieve the code-completion context for which results are + /// being collected. + const CodeCompletionContext &getCompletionContext() const { + return CompletionContext; + } + + /// \brief Specify whether nested-name-specifiers are allowed. + void allowNestedNameSpecifiers(bool Allow = true) { + AllowNestedNameSpecifiers = Allow; + } + + /// \brief Return the semantic analysis object for which we are collecting + /// code completion results. + Sema &getSema() const { return SemaRef; } + + /// \brief Retrieve the allocator used to allocate code completion strings. + CodeCompletionAllocator &getAllocator() const { return Allocator; } + + CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; } + + /// \brief Determine whether the given declaration is at all interesting + /// as a code-completion result. + /// + /// \param ND the declaration that we are inspecting. + /// + /// \param AsNestedNameSpecifier will be set true if this declaration is + /// only interesting when it is a nested-name-specifier. + bool isInterestingDecl(NamedDecl *ND, bool &AsNestedNameSpecifier) const; + + /// \brief Check whether the result is hidden by the Hiding declaration. + /// + /// \returns true if the result is hidden and cannot be found, false if + /// the hidden result could still be found. When false, \p R may be + /// modified to describe how the result can be found (e.g., via extra + /// qualification). + bool CheckHiddenResult(Result &R, DeclContext *CurContext, + NamedDecl *Hiding); + + /// \brief Add a new result to this result set (if it isn't already in one + /// of the shadow maps), or replace an existing result (for, e.g., a + /// redeclaration). + /// + /// \param R the result to add (if it is unique). + /// + /// \param CurContext the context in which this result will be named. + void MaybeAddResult(Result R, DeclContext *CurContext = 0); + + /// \brief Add a new result to this result set, where we already know + /// the hiding declation (if any). + /// + /// \param R the result to add (if it is unique). + /// + /// \param CurContext the context in which this result will be named. + /// + /// \param Hiding the declaration that hides the result. + /// + /// \param InBaseClass whether the result was found in a base + /// class of the searched context. + void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding, + bool InBaseClass); + + /// \brief Add a new non-declaration result to this result set. + void AddResult(Result R); + + /// \brief Enter into a new scope. + void EnterNewScope(); + + /// \brief Exit from the current scope. + void ExitScope(); + + /// \brief Ignore this declaration, if it is seen again. + void Ignore(Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); } + + /// \name Name lookup predicates + /// + /// These predicates can be passed to the name lookup functions to filter the + /// results of name lookup. All of the predicates have the same type, so that + /// + //@{ + 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; + bool IsClassOrStruct(NamedDecl *ND) const; + bool IsUnion(NamedDecl *ND) const; + bool IsNamespace(NamedDecl *ND) const; + bool IsNamespaceOrAlias(NamedDecl *ND) const; + bool IsType(NamedDecl *ND) const; + bool IsMember(NamedDecl *ND) const; + bool IsObjCIvar(NamedDecl *ND) const; + bool IsObjCMessageReceiver(NamedDecl *ND) const; + bool IsObjCMessageReceiverOrLambdaCapture(NamedDecl *ND) const; + bool IsObjCCollection(NamedDecl *ND) const; + bool IsImpossibleToSatisfy(NamedDecl *ND) const; + //@} + }; +} + +class ResultBuilder::ShadowMapEntry::iterator { + llvm::PointerUnion DeclOrIterator; + unsigned SingleDeclIndex; + +public: + typedef DeclIndexPair value_type; + typedef value_type reference; + typedef std::ptrdiff_t difference_type; + typedef std::input_iterator_tag iterator_category; + + class pointer { + DeclIndexPair Value; + + public: + pointer(const DeclIndexPair &Value) : Value(Value) { } + + const DeclIndexPair *operator->() const { + return &Value; + } + }; + + iterator() : DeclOrIterator((NamedDecl *)0), SingleDeclIndex(0) { } + + iterator(NamedDecl *SingleDecl, unsigned Index) + : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) { } + + iterator(const DeclIndexPair *Iterator) + : DeclOrIterator(Iterator), SingleDeclIndex(0) { } + + iterator &operator++() { + if (DeclOrIterator.is()) { + DeclOrIterator = (NamedDecl *)0; + SingleDeclIndex = 0; + return *this; + } + + const DeclIndexPair *I = DeclOrIterator.get(); + ++I; + DeclOrIterator = I; + return *this; + } + + /*iterator operator++(int) { + iterator tmp(*this); + ++(*this); + return tmp; + }*/ + + reference operator*() const { + if (NamedDecl *ND = DeclOrIterator.dyn_cast()) + return reference(ND, SingleDeclIndex); + + return *DeclOrIterator.get(); + } + + pointer operator->() const { + return pointer(**this); + } + + friend bool operator==(const iterator &X, const iterator &Y) { + return X.DeclOrIterator.getOpaqueValue() + == Y.DeclOrIterator.getOpaqueValue() && + X.SingleDeclIndex == Y.SingleDeclIndex; + } + + friend bool operator!=(const iterator &X, const iterator &Y) { + return !(X == Y); + } +}; + +ResultBuilder::ShadowMapEntry::iterator +ResultBuilder::ShadowMapEntry::begin() const { + if (DeclOrVector.isNull()) + return iterator(); + + if (NamedDecl *ND = DeclOrVector.dyn_cast()) + return iterator(ND, SingleDeclIndex); + + return iterator(DeclOrVector.get()->begin()); +} + +ResultBuilder::ShadowMapEntry::iterator +ResultBuilder::ShadowMapEntry::end() const { + if (DeclOrVector.is() || DeclOrVector.isNull()) + return iterator(); + + return iterator(DeclOrVector.get()->end()); +} + +/// \brief Compute the qualification required to get from the current context +/// (\p CurContext) to the target context (\p TargetContext). +/// +/// \param Context the AST context in which the qualification will be used. +/// +/// \param CurContext the context where an entity is being named, which is +/// typically based on the current scope. +/// +/// \param TargetContext the context in which the named entity actually +/// resides. +/// +/// \returns a nested name specifier that refers into the target context, or +/// NULL if no qualification is needed. +static NestedNameSpecifier * +getRequiredQualification(ASTContext &Context, + DeclContext *CurContext, + DeclContext *TargetContext) { + SmallVector TargetParents; + + for (DeclContext *CommonAncestor = TargetContext; + CommonAncestor && !CommonAncestor->Encloses(CurContext); + CommonAncestor = CommonAncestor->getLookupParent()) { + if (CommonAncestor->isTransparentContext() || + CommonAncestor->isFunctionOrMethod()) + continue; + + TargetParents.push_back(CommonAncestor); + } + + NestedNameSpecifier *Result = 0; + while (!TargetParents.empty()) { + DeclContext *Parent = TargetParents.back(); + TargetParents.pop_back(); + + 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, + Context.getTypeDeclType(TD).getTypePtr()); + } + return Result; +} + +bool ResultBuilder::isInterestingDecl(NamedDecl *ND, + bool &AsNestedNameSpecifier) const { + AsNestedNameSpecifier = false; + + ND = ND->getUnderlyingDecl(); + unsigned IDNS = ND->getIdentifierNamespace(); + + // Skip unnamed entities. + if (!ND->getDeclName()) + return false; + + // Friend declarations and declarations introduced due to friends are never + // added as results. + if (IDNS & (Decl::IDNS_OrdinaryFriend | Decl::IDNS_TagFriend)) + return false; + + // Class template (partial) specializations are never added as results. + if (isa(ND) || + isa(ND)) + return false; + + // Using declarations themselves are never added as results. + if (isa(ND)) + return false; + + // Some declarations have reserved names that we don't want to ever show. + if (const IdentifierInfo *Id = ND->getIdentifier()) { + // __va_list_tag is a freak of nature. Find it and skip it. + if (Id->isStr("__va_list_tag") || Id->isStr("__builtin_va_list")) + return false; + + // Filter out names reserved for the implementation (C99 7.1.3, + // C++ [lib.global.names]) if they come from a system header. + // + // FIXME: Add predicate for this. + if (Id->getLength() >= 2) { + const char *Name = Id->getNameStart(); + if (Name[0] == '_' && + (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z')) && + (ND->getLocation().isInvalid() || + SemaRef.SourceMgr.isInSystemHeader( + SemaRef.SourceMgr.getSpellingLoc(ND->getLocation())))) + return false; + } + } + + if (Filter == &ResultBuilder::IsNestedNameSpecifier || + ((isa(ND) || isa(ND)) && + Filter != &ResultBuilder::IsNamespace && + Filter != &ResultBuilder::IsNamespaceOrAlias && + Filter != 0)) + AsNestedNameSpecifier = true; + + // Filter out any unwanted results. + if (Filter && !(this->*Filter)(ND)) { + // Check whether it is interesting as a nested-name-specifier. + if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus && + IsNestedNameSpecifier(ND) && + (Filter != &ResultBuilder::IsMember || + (isa(ND) && + cast(ND)->isInjectedClassName()))) { + AsNestedNameSpecifier = true; + return true; + } + + return false; + } + // ... then it must be interesting! + return true; +} + +bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext, + NamedDecl *Hiding) { + // In C, there is no way to refer to a hidden name. + // FIXME: This isn't true; we can find a tag name hidden by an ordinary + // name if we introduce the tag type. + if (!SemaRef.getLangOpts().CPlusPlus) + return true; + + 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()->getRedeclContext()) + return true; + + // We can refer to the result with the appropriate qualification. Do it. + R.Hidden = true; + R.QualifierIsInformative = false; + + if (!R.Qualifier) + R.Qualifier = getRequiredQualification(SemaRef.Context, + CurContext, + R.Declaration->getDeclContext()); + return false; +} + +/// \brief A simplified classification of types used to determine whether two +/// types are "similar enough" when adjusting priorities. +SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) { + switch (T->getTypeClass()) { + case Type::Builtin: + switch (cast(T)->getKind()) { + case BuiltinType::Void: + return STC_Void; + + case BuiltinType::NullPtr: + return STC_Pointer; + + case BuiltinType::Overload: + case BuiltinType::Dependent: + return STC_Other; + + case BuiltinType::ObjCId: + case BuiltinType::ObjCClass: + case BuiltinType::ObjCSel: + return STC_ObjectiveC; + + default: + return STC_Arithmetic; + } + + case Type::Complex: + return STC_Arithmetic; + + case Type::Pointer: + return STC_Pointer; + + case Type::BlockPointer: + return STC_Block; + + case Type::LValueReference: + case Type::RValueReference: + return getSimplifiedTypeClass(T->getAs()->getPointeeType()); + + case Type::ConstantArray: + case Type::IncompleteArray: + case Type::VariableArray: + case Type::DependentSizedArray: + return STC_Array; + + case Type::DependentSizedExtVector: + case Type::Vector: + case Type::ExtVector: + return STC_Arithmetic; + + case Type::FunctionProto: + case Type::FunctionNoProto: + return STC_Function; + + case Type::Record: + return STC_Record; + + case Type::Enum: + return STC_Arithmetic; + + case Type::ObjCObject: + case Type::ObjCInterface: + case Type::ObjCObjectPointer: + return STC_ObjectiveC; + + default: + return STC_Other; + } +} + +/// \brief Get the type that a given expression will have if this declaration +/// is used as an expression in its "typical" code-completion form. +QualType clang::getDeclUsageType(ASTContext &C, NamedDecl *ND) { + ND = cast(ND->getUnderlyingDecl()); + + if (TypeDecl *Type = dyn_cast(ND)) + return C.getTypeDeclType(Type); + if (ObjCInterfaceDecl *Iface = dyn_cast(ND)) + return C.getObjCInterfaceType(Iface); + + QualType T; + if (FunctionDecl *Function = dyn_cast(ND)) + T = Function->getCallResultType(); + else if (ObjCMethodDecl *Method = dyn_cast(ND)) + T = Method->getSendResultType(); + else if (FunctionTemplateDecl *FunTmpl = dyn_cast(ND)) + T = FunTmpl->getTemplatedDecl()->getCallResultType(); + else if (EnumConstantDecl *Enumerator = dyn_cast(ND)) + T = C.getTypeDeclType(cast(Enumerator->getDeclContext())); + else if (ObjCPropertyDecl *Property = dyn_cast(ND)) + T = Property->getType(); + else if (ValueDecl *Value = dyn_cast(ND)) + T = Value->getType(); + else + return QualType(); + + // Dig through references, function pointers, and block pointers to + // get down to the likely type of an expression when the entity is + // used. + do { + if (const ReferenceType *Ref = T->getAs()) { + T = Ref->getPointeeType(); + continue; + } + + if (const PointerType *Pointer = T->getAs()) { + if (Pointer->getPointeeType()->isFunctionType()) { + T = Pointer->getPointeeType(); + continue; + } + + break; + } + + if (const BlockPointerType *Block = T->getAs()) { + T = Block->getPointeeType(); + continue; + } + + if (const FunctionType *Function = T->getAs()) { + T = Function->getResultType(); + continue; + } + + break; + } while (true); + + return T; +} + +void ResultBuilder::AdjustResultPriorityForDecl(Result &R) { + // 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 we have a preferred type, adjust the priority for results with exactly- + // matching or nearly-matching types. + if (!PreferredType.isNull()) { + QualType T = getDeclUsageType(SemaRef.Context, R.Declaration); + if (!T.isNull()) { + 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. + else if ((getSimplifiedTypeClass(PreferredType) + == getSimplifiedTypeClass(TC)) && + !(PreferredType->isEnumeralType() && TC->isEnumeralType())) + R.Priority /= CCF_SimilarTypeMatch; + } + } +} + +void ResultBuilder::MaybeAddConstructorResults(Result R) { + if (!SemaRef.getLangOpts().CPlusPlus || !R.Declaration || + !CompletionContext.wantConstructorResults()) + return; + + ASTContext &Context = SemaRef.Context; + NamedDecl *D = R.Declaration; + CXXRecordDecl *Record = 0; + if (ClassTemplateDecl *ClassTemplate = dyn_cast(D)) + Record = ClassTemplate->getTemplatedDecl(); + else if ((Record = dyn_cast(D))) { + // Skip specializations and partial specializations. + if (isa(Record)) + return; + } else { + // There are no constructors here. + return; + } + + Record = Record->getDefinition(); + if (!Record) + return; + + + QualType RecordTy = Context.getTypeDeclType(Record); + DeclarationName ConstructorName + = Context.DeclarationNames.getCXXConstructorName( + Context.getCanonicalType(RecordTy)); + for (DeclContext::lookup_result Ctors = Record->lookup(ConstructorName); + Ctors.first != Ctors.second; ++Ctors.first) { + R.Declaration = *Ctors.first; + R.CursorKind = getCursorKindForDecl(R.Declaration); + Results.push_back(R); + } +} + +void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) { + assert(!ShadowMaps.empty() && "Must enter into a results scope"); + + if (R.Kind != Result::RK_Declaration) { + // For non-declaration results, just add the result. + Results.push_back(R); + return; + } + + // Look through using declarations. + if (UsingShadowDecl *Using = dyn_cast(R.Declaration)) { + MaybeAddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext); + return; + } + + Decl *CanonDecl = R.Declaration->getCanonicalDecl(); + unsigned IDNS = CanonDecl->getIdentifierNamespace(); + + bool AsNestedNameSpecifier = false; + if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier)) + return; + + // C++ constructors are never found by name lookup. + if (isa(R.Declaration)) + return; + + ShadowMap &SMap = ShadowMaps.back(); + ShadowMapEntry::iterator I, IEnd; + ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName()); + if (NamePos != SMap.end()) { + I = NamePos->second.begin(); + IEnd = NamePos->second.end(); + } + + for (; I != IEnd; ++I) { + NamedDecl *ND = I->first; + unsigned Index = I->second; + if (ND->getCanonicalDecl() == CanonDecl) { + // This is a redeclaration. Always pick the newer declaration. + Results[Index].Declaration = R.Declaration; + + // We're done. + return; + } + } + + // This is a new declaration in this scope. However, check whether this + // declaration name is hidden by a similarly-named declaration in an outer + // scope. + std::list::iterator SM, SMEnd = ShadowMaps.end(); + --SMEnd; + for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) { + ShadowMapEntry::iterator I, IEnd; + ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName()); + if (NamePos != SM->end()) { + I = NamePos->second.begin(); + IEnd = NamePos->second.end(); + } + for (; I != IEnd; ++I) { + // A tag declaration does not hide a non-tag declaration. + if (I->first->hasTagIdentifierNamespace() && + (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary | + Decl::IDNS_ObjCProtocol))) + continue; + + // Protocols are in distinct namespaces from everything else. + if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol) + || (IDNS & Decl::IDNS_ObjCProtocol)) && + I->first->getIdentifierNamespace() != IDNS) + continue; + + // The newly-added result is hidden by an entry in the shadow map. + if (CheckHiddenResult(R, CurContext, I->first)) + return; + + break; + } + } + + // Make sure that any given declaration only shows up in the result set once. + if (!AllDeclsFound.insert(CanonDecl)) + return; + + // If the filter is for nested-name-specifiers, then this result starts a + // nested-name-specifier. + if (AsNestedNameSpecifier) { + R.StartsNestedNameSpecifier = true; + R.Priority = CCP_NestedNameSpecifier; + } else + AdjustResultPriorityForDecl(R); + + // If this result is supposed to have an informative qualifier, add one. + if (R.QualifierIsInformative && !R.Qualifier && + !R.StartsNestedNameSpecifier) { + DeclContext *Ctx = R.Declaration->getDeclContext(); + if (NamespaceDecl *Namespace = dyn_cast(Ctx)) + R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace); + else if (TagDecl *Tag = dyn_cast(Ctx)) + R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false, + SemaRef.Context.getTypeDeclType(Tag).getTypePtr()); + else + R.QualifierIsInformative = false; + } + + // Insert this result into the set of results and into the current shadow + // map. + SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size()); + Results.push_back(R); + + if (!AsNestedNameSpecifier) + MaybeAddConstructorResults(R); +} + +void ResultBuilder::AddResult(Result R, DeclContext *CurContext, + NamedDecl *Hiding, bool InBaseClass = false) { + if (R.Kind != Result::RK_Declaration) { + // For non-declaration results, just add the result. + Results.push_back(R); + return; + } + + // Look through using declarations. + if (UsingShadowDecl *Using = dyn_cast(R.Declaration)) { + AddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext, Hiding); + return; + } + + bool AsNestedNameSpecifier = false; + if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier)) + return; + + // C++ constructors are never found by name lookup. + if (isa(R.Declaration)) + return; + + if (Hiding && CheckHiddenResult(R, CurContext, Hiding)) + return; + + // Make sure that any given declaration only shows up in the result set once. + if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl())) + return; + + // If the filter is for nested-name-specifiers, then this result starts a + // nested-name-specifier. + if (AsNestedNameSpecifier) { + R.StartsNestedNameSpecifier = true; + R.Priority = CCP_NestedNameSpecifier; + } + else if (Filter == &ResultBuilder::IsMember && !R.Qualifier && InBaseClass && + isa(R.Declaration->getDeclContext() + ->getRedeclContext())) + R.QualifierIsInformative = true; + + // If this result is supposed to have an informative qualifier, add one. + if (R.QualifierIsInformative && !R.Qualifier && + !R.StartsNestedNameSpecifier) { + DeclContext *Ctx = R.Declaration->getDeclContext(); + if (NamespaceDecl *Namespace = dyn_cast(Ctx)) + R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace); + else if (TagDecl *Tag = dyn_cast(Ctx)) + R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false, + SemaRef.Context.getTypeDeclType(Tag).getTypePtr()); + else + R.QualifierIsInformative = false; + } + + // Adjust the priority if this result comes from a base class. + if (InBaseClass) + R.Priority += CCD_InBaseClass; + + AdjustResultPriorityForDecl(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); + + if (!AsNestedNameSpecifier) + MaybeAddConstructorResults(R); +} + +void ResultBuilder::AddResult(Result R) { + assert(R.Kind != Result::RK_Declaration && + "Declaration results need more context"); + Results.push_back(R); +} + +/// \brief Enter into a new scope. +void ResultBuilder::EnterNewScope() { + ShadowMaps.push_back(ShadowMap()); +} + +/// \brief Exit from the current scope. +void ResultBuilder::ExitScope() { + for (ShadowMap::iterator E = ShadowMaps.back().begin(), + EEnd = ShadowMaps.back().end(); + E != EEnd; + ++E) + E->second.Destroy(); + + ShadowMaps.pop_back(); +} + +/// \brief Determines whether this given declaration will be found by +/// ordinary name lookup. +bool ResultBuilder::IsOrdinaryName(NamedDecl *ND) const { + ND = cast(ND->getUnderlyingDecl()); + + unsigned IDNS = Decl::IDNS_Ordinary; + if (SemaRef.getLangOpts().CPlusPlus) + IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member; + else if (SemaRef.getLangOpts().ObjC1) { + if (isa(ND)) + return true; + } + + return ND->getIdentifierNamespace() & IDNS; +} + +/// \brief Determines whether this given declaration will be found by +/// ordinary name lookup but is not a type name. +bool ResultBuilder::IsOrdinaryNonTypeName(NamedDecl *ND) const { + ND = cast(ND->getUnderlyingDecl()); + if (isa(ND) || isa(ND)) + return false; + + unsigned IDNS = Decl::IDNS_Ordinary; + if (SemaRef.getLangOpts().CPlusPlus) + IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member; + else if (SemaRef.getLangOpts().ObjC1) { + if (isa(ND)) + return true; + } + + 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 { + ND = cast(ND->getUnderlyingDecl()); + + unsigned IDNS = Decl::IDNS_Ordinary; + if (SemaRef.getLangOpts().CPlusPlus) + IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace; + + return (ND->getIdentifierNamespace() & IDNS) && + !isa(ND) && !isa(ND) && + !isa(ND); +} + +/// \brief Determines whether the given declaration is suitable as the +/// start of a C++ nested-name-specifier, e.g., a class or namespace. +bool ResultBuilder::IsNestedNameSpecifier(NamedDecl *ND) const { + // Allow us to find class templates, too. + if (ClassTemplateDecl *ClassTemplate = dyn_cast(ND)) + ND = ClassTemplate->getTemplatedDecl(); + + return SemaRef.isAcceptableNestedNameSpecifier(ND); +} + +/// \brief Determines whether the given declaration is an enumeration. +bool ResultBuilder::IsEnum(NamedDecl *ND) const { + return isa(ND); +} + +/// \brief Determines whether the given declaration is a class or struct. +bool ResultBuilder::IsClassOrStruct(NamedDecl *ND) const { + // Allow us to find class templates, too. + if (ClassTemplateDecl *ClassTemplate = dyn_cast(ND)) + ND = ClassTemplate->getTemplatedDecl(); + + if (RecordDecl *RD = dyn_cast(ND)) + return RD->getTagKind() == TTK_Class || + RD->getTagKind() == TTK_Struct; + + return false; +} + +/// \brief Determines whether the given declaration is a union. +bool ResultBuilder::IsUnion(NamedDecl *ND) const { + // Allow us to find class templates, too. + if (ClassTemplateDecl *ClassTemplate = dyn_cast(ND)) + ND = ClassTemplate->getTemplatedDecl(); + + if (RecordDecl *RD = dyn_cast(ND)) + return RD->getTagKind() == TTK_Union; + + return false; +} + +/// \brief Determines whether the given declaration is a namespace. +bool ResultBuilder::IsNamespace(NamedDecl *ND) const { + return isa(ND); +} + +/// \brief Determines whether the given declaration is a namespace or +/// namespace alias. +bool ResultBuilder::IsNamespaceOrAlias(NamedDecl *ND) const { + return isa(ND) || isa(ND); +} + +/// \brief Determines whether the given declaration is a type. +bool ResultBuilder::IsType(NamedDecl *ND) const { + 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 +/// "." or "->". Only value declarations, nested name specifiers, and +/// using declarations thereof should show up. +bool ResultBuilder::IsMember(NamedDecl *ND) const { + if (UsingShadowDecl *Using = dyn_cast(ND)) + ND = Using->getTargetDecl(); + + return isa(ND) || isa(ND) || + isa(ND); +} + +static bool isObjCReceiverType(ASTContext &C, QualType T) { + T = C.getCanonicalType(T); + switch (T->getTypeClass()) { + case Type::ObjCObject: + case Type::ObjCInterface: + case Type::ObjCObjectPointer: + return true; + + case Type::Builtin: + switch (cast(T)->getKind()) { + case BuiltinType::ObjCId: + case BuiltinType::ObjCClass: + case BuiltinType::ObjCSel: + return true; + + default: + break; + } + return false; + + default: + break; + } + + if (!C.getLangOpts().CPlusPlus) + return false; + + // FIXME: We could perform more analysis here to determine whether a + // particular class type has any conversions to Objective-C types. For now, + // just accept all class types. + return T->isDependentType() || T->isRecordType(); +} + +bool ResultBuilder::IsObjCMessageReceiver(NamedDecl *ND) const { + QualType T = getDeclUsageType(SemaRef.Context, ND); + if (T.isNull()) + return false; + + T = SemaRef.Context.getBaseElementType(T); + return isObjCReceiverType(SemaRef.Context, T); +} + +bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(NamedDecl *ND) const { + if (IsObjCMessageReceiver(ND)) + return true; + + VarDecl *Var = dyn_cast(ND); + if (!Var) + return false; + + return Var->hasLocalStorage() && !Var->hasAttr(); +} + +bool ResultBuilder::IsObjCCollection(NamedDecl *ND) const { + if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) || + (!SemaRef.getLangOpts().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.getLangOpts().CPlusPlus && T->isRecordType()); +} + +bool ResultBuilder::IsImpossibleToSatisfy(NamedDecl *ND) const { + return false; +} + +/// \rief Determines whether the given declaration is an Objective-C +/// instance variable. +bool ResultBuilder::IsObjCIvar(NamedDecl *ND) const { + return isa(ND); +} + +namespace { + /// \brief Visible declaration consumer that adds a code-completion result + /// for each visible declaration. + class CodeCompletionDeclConsumer : public VisibleDeclConsumer { + ResultBuilder &Results; + DeclContext *CurContext; + + public: + CodeCompletionDeclConsumer(ResultBuilder &Results, DeclContext *CurContext) + : Results(Results), CurContext(CurContext) { } + + virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx, + bool InBaseClass) { + bool Accessible = true; + if (Ctx) + Accessible = Results.getSema().IsSimplyAccessible(ND, Ctx); + + ResultBuilder::Result Result(ND, 0, false, Accessible); + Results.AddResult(Result, CurContext, Hiding, InBaseClass); + } + }; +} + +/// \brief Add type specifiers for the current language as keyword results. +static void AddTypeSpecifierResults(const LangOptions &LangOpts, + ResultBuilder &Results) { + typedef CodeCompletionResult Result; + Results.AddResult(Result("short", CCP_Type)); + Results.AddResult(Result("long", CCP_Type)); + Results.AddResult(Result("signed", CCP_Type)); + Results.AddResult(Result("unsigned", CCP_Type)); + Results.AddResult(Result("void", CCP_Type)); + Results.AddResult(Result("char", CCP_Type)); + Results.AddResult(Result("int", CCP_Type)); + Results.AddResult(Result("float", CCP_Type)); + Results.AddResult(Result("double", CCP_Type)); + Results.AddResult(Result("enum", CCP_Type)); + Results.AddResult(Result("struct", CCP_Type)); + Results.AddResult(Result("union", CCP_Type)); + Results.AddResult(Result("const", CCP_Type)); + Results.AddResult(Result("volatile", CCP_Type)); + + if (LangOpts.C99) { + // C99-specific + Results.AddResult(Result("_Complex", CCP_Type)); + Results.AddResult(Result("_Imaginary", CCP_Type)); + Results.AddResult(Result("_Bool", CCP_Type)); + Results.AddResult(Result("restrict", CCP_Type)); + } + + CodeCompletionBuilder Builder(Results.getAllocator(), + Results.getCodeCompletionTUInfo()); + if (LangOpts.CPlusPlus) { + // C++-specific + Results.AddResult(Result("bool", CCP_Type + + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0))); + Results.AddResult(Result("class", CCP_Type)); + Results.AddResult(Result("wchar_t", CCP_Type)); + + // typename qualified-id + Builder.AddTypedTextChunk("typename"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("qualifier"); + Builder.AddTextChunk("::"); + Builder.AddPlaceholderChunk("name"); + Results.AddResult(Result(Builder.TakeString())); + + if (LangOpts.CPlusPlus0x) { + Results.AddResult(Result("auto", CCP_Type)); + Results.AddResult(Result("char16_t", CCP_Type)); + Results.AddResult(Result("char32_t", CCP_Type)); + + Builder.AddTypedTextChunk("decltype"); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("expression"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Builder.TakeString())); + } + } + + // GNU extensions + if (LangOpts.GNUMode) { + // FIXME: Enable when we actually support decimal floating point. + // Results.AddResult(Result("_Decimal32")); + // Results.AddResult(Result("_Decimal64")); + // Results.AddResult(Result("_Decimal128")); + + Builder.AddTypedTextChunk("typeof"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("expression"); + Results.AddResult(Result(Builder.TakeString())); + + Builder.AddTypedTextChunk("typeof"); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("type"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Builder.TakeString())); + } +} + +static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC, + const LangOptions &LangOpts, + ResultBuilder &Results) { + 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. + Results.AddResult(Result("extern")); + Results.AddResult(Result("static")); +} + +static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC, + const LangOptions &LangOpts, + ResultBuilder &Results) { + typedef CodeCompletionResult Result; + switch (CCC) { + case Sema::PCC_Class: + case Sema::PCC_MemberTemplate: + if (LangOpts.CPlusPlus) { + Results.AddResult(Result("explicit")); + Results.AddResult(Result("friend")); + Results.AddResult(Result("mutable")); + Results.AddResult(Result("virtual")); + } + // Fall through + + 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 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: + case Sema::PCC_ParenthesizedExpression: + case Sema::PCC_LocalDeclarationSpecifiers: + break; + } +} + +static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt); +static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt); +static void AddObjCVisibilityResults(const LangOptions &LangOpts, + ResultBuilder &Results, + bool NeedAt); +static void AddObjCImplementationResults(const LangOptions &LangOpts, + ResultBuilder &Results, + bool NeedAt); +static void AddObjCInterfaceResults(const LangOptions &LangOpts, + ResultBuilder &Results, + bool NeedAt); +static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt); + +static void AddTypedefResult(ResultBuilder &Results) { + CodeCompletionBuilder Builder(Results.getAllocator(), + Results.getCodeCompletionTUInfo()); + Builder.AddTypedTextChunk("typedef"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("type"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("name"); + Results.AddResult(CodeCompletionResult(Builder.TakeString())); +} + +static bool WantTypesInContext(Sema::ParserCompletionContext CCC, + const LangOptions &LangOpts) { + switch (CCC) { + 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: + case Sema::PCC_ParenthesizedExpression: + case Sema::PCC_LocalDeclarationSpecifiers: + return true; + + case Sema::PCC_Expression: + case Sema::PCC_Condition: + return LangOpts.CPlusPlus; + + case Sema::PCC_ObjCInterface: + case Sema::PCC_ObjCImplementation: + return false; + + case Sema::PCC_ForInit: + return LangOpts.CPlusPlus || LangOpts.ObjC1 || LangOpts.C99; + } + + llvm_unreachable("Invalid ParserCompletionContext!"); +} + +static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context, + const Preprocessor &PP) { + PrintingPolicy Policy = Sema::getPrintingPolicy(Context, PP); + Policy.AnonymousTagLocations = false; + Policy.SuppressStrongLifetime = true; + Policy.SuppressUnwrittenScope = true; + return Policy; +} + +/// \brief Retrieve a printing policy suitable for code completion. +static PrintingPolicy getCompletionPrintingPolicy(Sema &S) { + return getCompletionPrintingPolicy(S.Context, S.PP); +} + +/// \brief Retrieve the string representation of the given type as a string +/// that has the appropriate lifetime for code completion. +/// +/// This routine provides a fast path where we provide constant strings for +/// common type names. +static const char *GetCompletionTypeString(QualType T, + ASTContext &Context, + const PrintingPolicy &Policy, + CodeCompletionAllocator &Allocator) { + if (!T.getLocalQualifiers()) { + // Built-in type names are constant strings. + if (const BuiltinType *BT = dyn_cast(T)) + return BT->getName(Policy); + + // Anonymous tag types are constant strings. + if (const TagType *TagT = dyn_cast(T)) + if (TagDecl *Tag = TagT->getDecl()) + if (!Tag->getIdentifier() && !Tag->getTypedefNameForAnonDecl()) { + switch (Tag->getTagKind()) { + case TTK_Struct: return "struct "; + case TTK_Class: return "class "; + case TTK_Union: return "union "; + case TTK_Enum: return "enum "; + } + } + } + + // Slow path: format the type as a string. + std::string Result; + T.getAsStringInternal(Result, Policy); + return Allocator.CopyString(Result); +} + +/// \brief Add a completion for "this", if we're in a member function. +static void addThisCompletion(Sema &S, ResultBuilder &Results) { + QualType ThisTy = S.getCurrentThisType(); + if (ThisTy.isNull()) + return; + + CodeCompletionAllocator &Allocator = Results.getAllocator(); + CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo()); + PrintingPolicy Policy = getCompletionPrintingPolicy(S); + Builder.AddResultTypeChunk(GetCompletionTypeString(ThisTy, + S.Context, + Policy, + Allocator)); + Builder.AddTypedTextChunk("this"); + Results.AddResult(CodeCompletionResult(Builder.TakeString())); +} + +/// \brief Add language constructs that show up for "ordinary" names. +static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, + Scope *S, + Sema &SemaRef, + ResultBuilder &Results) { + CodeCompletionAllocator &Allocator = Results.getAllocator(); + CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo()); + PrintingPolicy Policy = getCompletionPrintingPolicy(SemaRef); + + typedef CodeCompletionResult Result; + switch (CCC) { + case Sema::PCC_Namespace: + if (SemaRef.getLangOpts().CPlusPlus) { + if (Results.includeCodePatterns()) { + // namespace { declarations } + Builder.AddTypedTextChunk("namespace"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("identifier"); + Builder.AddChunk(CodeCompletionString::CK_LeftBrace); + Builder.AddPlaceholderChunk("declarations"); + Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); + Builder.AddChunk(CodeCompletionString::CK_RightBrace); + Results.AddResult(Result(Builder.TakeString())); + } + + // namespace identifier = identifier ; + Builder.AddTypedTextChunk("namespace"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("name"); + Builder.AddChunk(CodeCompletionString::CK_Equal); + Builder.AddPlaceholderChunk("namespace"); + Results.AddResult(Result(Builder.TakeString())); + + // Using directives + Builder.AddTypedTextChunk("using"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddTextChunk("namespace"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("identifier"); + Results.AddResult(Result(Builder.TakeString())); + + // asm(string-literal) + Builder.AddTypedTextChunk("asm"); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("string-literal"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Builder.TakeString())); + + if (Results.includeCodePatterns()) { + // Explicit template instantiation + Builder.AddTypedTextChunk("template"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("declaration"); + Results.AddResult(Result(Builder.TakeString())); + } + } + + if (SemaRef.getLangOpts().ObjC1) + AddObjCTopLevelResults(Results, true); + + AddTypedefResult(Results); + // Fall through + + case Sema::PCC_Class: + if (SemaRef.getLangOpts().CPlusPlus) { + // Using declaration + Builder.AddTypedTextChunk("using"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("qualifier"); + Builder.AddTextChunk("::"); + Builder.AddPlaceholderChunk("name"); + Results.AddResult(Result(Builder.TakeString())); + + // using typename qualifier::name (only in a dependent context) + if (SemaRef.CurContext->isDependentContext()) { + Builder.AddTypedTextChunk("using"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddTextChunk("typename"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("qualifier"); + Builder.AddTextChunk("::"); + Builder.AddPlaceholderChunk("name"); + Results.AddResult(Result(Builder.TakeString())); + } + + if (CCC == Sema::PCC_Class) { + AddTypedefResult(Results); + + // public: + Builder.AddTypedTextChunk("public"); + if (Results.includeCodePatterns()) + Builder.AddChunk(CodeCompletionString::CK_Colon); + Results.AddResult(Result(Builder.TakeString())); + + // protected: + Builder.AddTypedTextChunk("protected"); + if (Results.includeCodePatterns()) + Builder.AddChunk(CodeCompletionString::CK_Colon); + Results.AddResult(Result(Builder.TakeString())); + + // private: + Builder.AddTypedTextChunk("private"); + if (Results.includeCodePatterns()) + Builder.AddChunk(CodeCompletionString::CK_Colon); + Results.AddResult(Result(Builder.TakeString())); + } + } + // Fall through + + case Sema::PCC_Template: + case Sema::PCC_MemberTemplate: + if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns()) { + // template < parameters > + Builder.AddTypedTextChunk("template"); + Builder.AddChunk(CodeCompletionString::CK_LeftAngle); + Builder.AddPlaceholderChunk("parameters"); + Builder.AddChunk(CodeCompletionString::CK_RightAngle); + Results.AddResult(Result(Builder.TakeString())); + } + + AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results); + AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results); + break; + + case Sema::PCC_ObjCInterface: + AddObjCInterfaceResults(SemaRef.getLangOpts(), Results, true); + AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results); + AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results); + break; + + case Sema::PCC_ObjCImplementation: + AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true); + AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results); + AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results); + break; + + case Sema::PCC_ObjCInstanceVariableList: + AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true); + break; + + case Sema::PCC_RecoveryInFunction: + case Sema::PCC_Statement: { + AddTypedefResult(Results); + + if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns() && + SemaRef.getLangOpts().CXXExceptions) { + Builder.AddTypedTextChunk("try"); + Builder.AddChunk(CodeCompletionString::CK_LeftBrace); + Builder.AddPlaceholderChunk("statements"); + Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); + Builder.AddChunk(CodeCompletionString::CK_RightBrace); + Builder.AddTextChunk("catch"); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("declaration"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddChunk(CodeCompletionString::CK_LeftBrace); + Builder.AddPlaceholderChunk("statements"); + Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); + Builder.AddChunk(CodeCompletionString::CK_RightBrace); + Results.AddResult(Result(Builder.TakeString())); + } + if (SemaRef.getLangOpts().ObjC1) + AddObjCStatementResults(Results, true); + + if (Results.includeCodePatterns()) { + // if (condition) { statements } + Builder.AddTypedTextChunk("if"); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + if (SemaRef.getLangOpts().CPlusPlus) + Builder.AddPlaceholderChunk("condition"); + else + Builder.AddPlaceholderChunk("expression"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddChunk(CodeCompletionString::CK_LeftBrace); + Builder.AddPlaceholderChunk("statements"); + Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); + Builder.AddChunk(CodeCompletionString::CK_RightBrace); + Results.AddResult(Result(Builder.TakeString())); + + // switch (condition) { } + Builder.AddTypedTextChunk("switch"); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + if (SemaRef.getLangOpts().CPlusPlus) + Builder.AddPlaceholderChunk("condition"); + else + Builder.AddPlaceholderChunk("expression"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddChunk(CodeCompletionString::CK_LeftBrace); + Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); + Builder.AddChunk(CodeCompletionString::CK_RightBrace); + Results.AddResult(Result(Builder.TakeString())); + } + + // Switch-specific statements. + if (!SemaRef.getCurFunction()->SwitchStack.empty()) { + // case expression: + Builder.AddTypedTextChunk("case"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("expression"); + Builder.AddChunk(CodeCompletionString::CK_Colon); + Results.AddResult(Result(Builder.TakeString())); + + // default: + Builder.AddTypedTextChunk("default"); + Builder.AddChunk(CodeCompletionString::CK_Colon); + Results.AddResult(Result(Builder.TakeString())); + } + + if (Results.includeCodePatterns()) { + /// while (condition) { statements } + Builder.AddTypedTextChunk("while"); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + if (SemaRef.getLangOpts().CPlusPlus) + Builder.AddPlaceholderChunk("condition"); + else + Builder.AddPlaceholderChunk("expression"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddChunk(CodeCompletionString::CK_LeftBrace); + Builder.AddPlaceholderChunk("statements"); + Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); + Builder.AddChunk(CodeCompletionString::CK_RightBrace); + Results.AddResult(Result(Builder.TakeString())); + + // do { statements } while ( expression ); + Builder.AddTypedTextChunk("do"); + Builder.AddChunk(CodeCompletionString::CK_LeftBrace); + Builder.AddPlaceholderChunk("statements"); + Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); + Builder.AddChunk(CodeCompletionString::CK_RightBrace); + Builder.AddTextChunk("while"); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("expression"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Builder.TakeString())); + + // for ( for-init-statement ; condition ; expression ) { statements } + Builder.AddTypedTextChunk("for"); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + if (SemaRef.getLangOpts().CPlusPlus || SemaRef.getLangOpts().C99) + Builder.AddPlaceholderChunk("init-statement"); + else + Builder.AddPlaceholderChunk("init-expression"); + Builder.AddChunk(CodeCompletionString::CK_SemiColon); + Builder.AddPlaceholderChunk("condition"); + Builder.AddChunk(CodeCompletionString::CK_SemiColon); + Builder.AddPlaceholderChunk("inc-expression"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddChunk(CodeCompletionString::CK_LeftBrace); + Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); + Builder.AddPlaceholderChunk("statements"); + Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); + Builder.AddChunk(CodeCompletionString::CK_RightBrace); + Results.AddResult(Result(Builder.TakeString())); + } + + if (S->getContinueParent()) { + // continue ; + Builder.AddTypedTextChunk("continue"); + Results.AddResult(Result(Builder.TakeString())); + } + + if (S->getBreakParent()) { + // break ; + Builder.AddTypedTextChunk("break"); + Results.AddResult(Result(Builder.TakeString())); + } + + // "return expression ;" or "return ;", depending on whether we + // know the function is void or not. + bool isVoid = false; + if (FunctionDecl *Function = dyn_cast(SemaRef.CurContext)) + isVoid = Function->getResultType()->isVoidType(); + else if (ObjCMethodDecl *Method + = dyn_cast(SemaRef.CurContext)) + isVoid = Method->getResultType()->isVoidType(); + else if (SemaRef.getCurBlock() && + !SemaRef.getCurBlock()->ReturnType.isNull()) + isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType(); + Builder.AddTypedTextChunk("return"); + if (!isVoid) { + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("expression"); + } + Results.AddResult(Result(Builder.TakeString())); + + // goto identifier ; + Builder.AddTypedTextChunk("goto"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("label"); + Results.AddResult(Result(Builder.TakeString())); + + // Using directives + Builder.AddTypedTextChunk("using"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddTextChunk("namespace"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("identifier"); + Results.AddResult(Result(Builder.TakeString())); + } + + // Fall through (for statement expressions). + case Sema::PCC_ForInit: + case Sema::PCC_Condition: + AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results); + // Fall through: conditions and statements can have expressions. + + case Sema::PCC_ParenthesizedExpression: + if (SemaRef.getLangOpts().ObjCAutoRefCount && + CCC == Sema::PCC_ParenthesizedExpression) { + // (__bridge ) + Builder.AddTypedTextChunk("__bridge"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("type"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddPlaceholderChunk("expression"); + Results.AddResult(Result(Builder.TakeString())); + + // (__bridge_transfer ) + Builder.AddTypedTextChunk("__bridge_transfer"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("Objective-C type"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddPlaceholderChunk("expression"); + Results.AddResult(Result(Builder.TakeString())); + + // (__bridge_retained ) + Builder.AddTypedTextChunk("__bridge_retained"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("CF type"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddPlaceholderChunk("expression"); + Results.AddResult(Result(Builder.TakeString())); + } + // Fall through + + case Sema::PCC_Expression: { + if (SemaRef.getLangOpts().CPlusPlus) { + // 'this', if we're in a non-static member function. + addThisCompletion(SemaRef, Results); + + // true + Builder.AddResultTypeChunk("bool"); + Builder.AddTypedTextChunk("true"); + Results.AddResult(Result(Builder.TakeString())); + + // false + Builder.AddResultTypeChunk("bool"); + Builder.AddTypedTextChunk("false"); + Results.AddResult(Result(Builder.TakeString())); + + if (SemaRef.getLangOpts().RTTI) { + // dynamic_cast < type-id > ( expression ) + Builder.AddTypedTextChunk("dynamic_cast"); + Builder.AddChunk(CodeCompletionString::CK_LeftAngle); + Builder.AddPlaceholderChunk("type"); + Builder.AddChunk(CodeCompletionString::CK_RightAngle); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("expression"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Builder.TakeString())); + } + + // static_cast < type-id > ( expression ) + Builder.AddTypedTextChunk("static_cast"); + Builder.AddChunk(CodeCompletionString::CK_LeftAngle); + Builder.AddPlaceholderChunk("type"); + Builder.AddChunk(CodeCompletionString::CK_RightAngle); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("expression"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Builder.TakeString())); + + // reinterpret_cast < type-id > ( expression ) + Builder.AddTypedTextChunk("reinterpret_cast"); + Builder.AddChunk(CodeCompletionString::CK_LeftAngle); + Builder.AddPlaceholderChunk("type"); + Builder.AddChunk(CodeCompletionString::CK_RightAngle); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("expression"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Builder.TakeString())); + + // const_cast < type-id > ( expression ) + Builder.AddTypedTextChunk("const_cast"); + Builder.AddChunk(CodeCompletionString::CK_LeftAngle); + Builder.AddPlaceholderChunk("type"); + Builder.AddChunk(CodeCompletionString::CK_RightAngle); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("expression"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Builder.TakeString())); + + if (SemaRef.getLangOpts().RTTI) { + // typeid ( expression-or-type ) + Builder.AddResultTypeChunk("std::type_info"); + Builder.AddTypedTextChunk("typeid"); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("expression-or-type"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Builder.TakeString())); + } + + // new T ( ... ) + Builder.AddTypedTextChunk("new"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("type"); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("expressions"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Builder.TakeString())); + + // new T [ ] ( ... ) + Builder.AddTypedTextChunk("new"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("type"); + Builder.AddChunk(CodeCompletionString::CK_LeftBracket); + Builder.AddPlaceholderChunk("size"); + Builder.AddChunk(CodeCompletionString::CK_RightBracket); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("expressions"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Builder.TakeString())); + + // delete expression + Builder.AddResultTypeChunk("void"); + Builder.AddTypedTextChunk("delete"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("expression"); + Results.AddResult(Result(Builder.TakeString())); + + // delete [] expression + Builder.AddResultTypeChunk("void"); + Builder.AddTypedTextChunk("delete"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddChunk(CodeCompletionString::CK_LeftBracket); + Builder.AddChunk(CodeCompletionString::CK_RightBracket); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("expression"); + Results.AddResult(Result(Builder.TakeString())); + + if (SemaRef.getLangOpts().CXXExceptions) { + // throw expression + Builder.AddResultTypeChunk("void"); + Builder.AddTypedTextChunk("throw"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("expression"); + Results.AddResult(Result(Builder.TakeString())); + } + + // FIXME: Rethrow? + + if (SemaRef.getLangOpts().CPlusPlus0x) { + // nullptr + Builder.AddResultTypeChunk("std::nullptr_t"); + Builder.AddTypedTextChunk("nullptr"); + Results.AddResult(Result(Builder.TakeString())); + + // alignof + Builder.AddResultTypeChunk("size_t"); + Builder.AddTypedTextChunk("alignof"); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("type"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Builder.TakeString())); + + // noexcept + Builder.AddResultTypeChunk("bool"); + Builder.AddTypedTextChunk("noexcept"); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("expression"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Builder.TakeString())); + + // sizeof... expression + Builder.AddResultTypeChunk("size_t"); + Builder.AddTypedTextChunk("sizeof..."); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("parameter-pack"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Builder.TakeString())); + } + } + + if (SemaRef.getLangOpts().ObjC1) { + // Add "super", if we're in an Objective-C class with a superclass. + if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) { + // The interface can be NULL. + if (ObjCInterfaceDecl *ID = Method->getClassInterface()) + if (ID->getSuperClass()) { + std::string SuperType; + SuperType = ID->getSuperClass()->getNameAsString(); + if (Method->isInstanceMethod()) + SuperType += " *"; + + Builder.AddResultTypeChunk(Allocator.CopyString(SuperType)); + Builder.AddTypedTextChunk("super"); + Results.AddResult(Result(Builder.TakeString())); + } + } + + AddObjCExpressionResults(Results, true); + } + + // sizeof expression + Builder.AddResultTypeChunk("size_t"); + Builder.AddTypedTextChunk("sizeof"); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("expression-or-type"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Builder.TakeString())); + break; + } + + case Sema::PCC_Type: + case Sema::PCC_LocalDeclarationSpecifiers: + break; + } + + if (WantTypesInContext(CCC, SemaRef.getLangOpts())) + AddTypeSpecifierResults(SemaRef.getLangOpts(), Results); + + if (SemaRef.getLangOpts().CPlusPlus && CCC != Sema::PCC_Type) + Results.AddResult(Result("operator")); +} + +/// \brief If the given declaration has an associated type, add it as a result +/// type chunk. +static void AddResultTypeChunk(ASTContext &Context, + const PrintingPolicy &Policy, + NamedDecl *ND, + CodeCompletionBuilder &Result) { + if (!ND) + return; + + // Skip constructors and conversion functions, which have their return types + // built into their names. + if (isa(ND) || isa(ND)) + return; + + // Determine the type of the declaration (if it has a type). + QualType T; + if (FunctionDecl *Function = dyn_cast(ND)) + T = Function->getResultType(); + else if (ObjCMethodDecl *Method = dyn_cast(ND)) + T = Method->getResultType(); + else if (FunctionTemplateDecl *FunTmpl = dyn_cast(ND)) + T = FunTmpl->getTemplatedDecl()->getResultType(); + else if (EnumConstantDecl *Enumerator = dyn_cast(ND)) + T = Context.getTypeDeclType(cast(Enumerator->getDeclContext())); + else if (isa(ND)) { + /* Do nothing: ignore unresolved using declarations*/ + } else if (ValueDecl *Value = dyn_cast(ND)) { + T = Value->getType(); + } else if (ObjCPropertyDecl *Property = dyn_cast(ND)) + T = Property->getType(); + + if (T.isNull() || Context.hasSameType(T, Context.DependentTy)) + return; + + Result.AddResultTypeChunk(GetCompletionTypeString(T, Context, Policy, + Result.getAllocator())); +} + +static void MaybeAddSentinel(ASTContext &Context, NamedDecl *FunctionOrMethod, + CodeCompletionBuilder &Result) { + if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr()) + if (Sentinel->getSentinel() == 0) { + if (Context.getLangOpts().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 formatObjCParamQualifiers(unsigned ObjCQuals) { + std::string Result; + if (ObjCQuals & Decl::OBJC_TQ_In) + Result += "in "; + else if (ObjCQuals & Decl::OBJC_TQ_Inout) + Result += "inout "; + else if (ObjCQuals & Decl::OBJC_TQ_Out) + Result += "out "; + if (ObjCQuals & Decl::OBJC_TQ_Bycopy) + Result += "bycopy "; + else if (ObjCQuals & Decl::OBJC_TQ_Byref) + Result += "byref "; + if (ObjCQuals & Decl::OBJC_TQ_Oneway) + Result += "oneway "; + return Result; +} + +static std::string FormatFunctionParameter(ASTContext &Context, + const PrintingPolicy &Policy, + ParmVarDecl *Param, + bool SuppressName = false, + bool SuppressBlock = 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, Policy); + + if (ObjCMethodParam) { + Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier()) + + 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. + FunctionTypeLoc *Block = 0; + FunctionProtoTypeLoc *BlockProto = 0; + TypeLoc TL; + if (TypeSourceInfo *TSInfo = Param->getTypeSourceInfo()) { + TL = TSInfo->getTypeLoc().getUnqualifiedLoc(); + while (true) { + // Look through typedefs. + if (!SuppressBlock) { + if (TypedefTypeLoc *TypedefTL = dyn_cast(&TL)) { + if (TypeSourceInfo *InnerTSInfo + = TypedefTL->getTypedefNameDecl()->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().IgnoreParens(); + Block = dyn_cast(&TL); + BlockProto = 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; + if (!ObjCMethodParam && Param->getIdentifier()) + Result = Param->getIdentifier()->getName(); + + Param->getType().getUnqualifiedType().getAsStringInternal(Result, Policy); + + if (ObjCMethodParam) { + Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier()) + + 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; + QualType ResultType = Block->getTypePtr()->getResultType(); + if (!ResultType->isVoidType() || SuppressBlock) + ResultType.getAsStringInternal(Result, Policy); + + // Format the parameter list. + std::string Params; + if (!BlockProto || Block->getNumArgs() == 0) { + if (BlockProto && BlockProto->getTypePtr()->isVariadic()) + Params = "(...)"; + else + Params = "(void)"; + } else { + Params += "("; + for (unsigned I = 0, N = Block->getNumArgs(); I != N; ++I) { + if (I) + Params += ", "; + Params += FormatFunctionParameter(Context, Policy, Block->getArg(I), + /*SuppressName=*/false, + /*SuppressBlock=*/true); + + if (I == N - 1 && BlockProto->getTypePtr()->isVariadic()) + Params += ", ..."; + } + Params += ")"; + } + + if (SuppressBlock) { + // Format as a parameter. + Result = Result + " (^"; + if (Param->getIdentifier()) + Result += Param->getIdentifier()->getName(); + Result += ")"; + Result += Params; + } else { + // Format as a block literal argument. + Result = '^' + Result; + Result += Params; + + if (Param->getIdentifier()) + Result += Param->getIdentifier()->getName(); + } + + return Result; +} + +/// \brief Add function parameter chunks to the given code completion string. +static void AddFunctionParameterChunks(ASTContext &Context, + const PrintingPolicy &Policy, + FunctionDecl *Function, + CodeCompletionBuilder &Result, + unsigned Start = 0, + bool InOptional = false) { + bool FirstParameter = true; + + for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) { + ParmVarDecl *Param = Function->getParamDecl(P); + + if (Param->hasDefaultArg() && !InOptional) { + // When we see an optional default argument, put that argument and + // the remaining default arguments into a new, optional string. + CodeCompletionBuilder Opt(Result.getAllocator(), + Result.getCodeCompletionTUInfo()); + if (!FirstParameter) + Opt.AddChunk(CodeCompletionString::CK_Comma); + AddFunctionParameterChunks(Context, Policy, Function, Opt, P, true); + Result.AddOptionalChunk(Opt.TakeString()); + break; + } + + if (FirstParameter) + FirstParameter = false; + else + Result.AddChunk(CodeCompletionString::CK_Comma); + + InOptional = false; + + // Format the placeholder string. + std::string PlaceholderStr = FormatFunctionParameter(Context, Policy, + Param); + + if (Function->isVariadic() && P == N - 1) + PlaceholderStr += ", ..."; + + // Add the placeholder string. + Result.AddPlaceholderChunk( + Result.getAllocator().CopyString(PlaceholderStr)); + } + + if (const FunctionProtoType *Proto + = Function->getType()->getAs()) + if (Proto->isVariadic()) { + if (Proto->getNumArgs() == 0) + Result.AddPlaceholderChunk("..."); + + MaybeAddSentinel(Context, Function, Result); + } +} + +/// \brief Add template parameter chunks to the given code completion string. +static void AddTemplateParameterChunks(ASTContext &Context, + const PrintingPolicy &Policy, + TemplateDecl *Template, + CodeCompletionBuilder &Result, + unsigned MaxParameters = 0, + unsigned Start = 0, + bool InDefaultArg = false) { + bool FirstParameter = true; + + TemplateParameterList *Params = Template->getTemplateParameters(); + TemplateParameterList::iterator PEnd = Params->end(); + if (MaxParameters) + PEnd = Params->begin() + MaxParameters; + for (TemplateParameterList::iterator P = Params->begin() + Start; + P != PEnd; ++P) { + bool HasDefaultArg = false; + std::string PlaceholderStr; + if (TemplateTypeParmDecl *TTP = dyn_cast(*P)) { + if (TTP->wasDeclaredWithTypename()) + PlaceholderStr = "typename"; + else + PlaceholderStr = "class"; + + if (TTP->getIdentifier()) { + PlaceholderStr += ' '; + PlaceholderStr += TTP->getIdentifier()->getName(); + } + + HasDefaultArg = TTP->hasDefaultArgument(); + } else if (NonTypeTemplateParmDecl *NTTP + = dyn_cast(*P)) { + if (NTTP->getIdentifier()) + PlaceholderStr = NTTP->getIdentifier()->getName(); + NTTP->getType().getAsStringInternal(PlaceholderStr, Policy); + HasDefaultArg = NTTP->hasDefaultArgument(); + } else { + assert(isa(*P)); + TemplateTemplateParmDecl *TTP = cast(*P); + + // Since putting the template argument list into the placeholder would + // be very, very long, we just use an abbreviation. + PlaceholderStr = "template<...> class"; + if (TTP->getIdentifier()) { + PlaceholderStr += ' '; + PlaceholderStr += TTP->getIdentifier()->getName(); + } + + HasDefaultArg = TTP->hasDefaultArgument(); + } + + if (HasDefaultArg && !InDefaultArg) { + // When we see an optional default argument, put that argument and + // the remaining default arguments into a new, optional string. + CodeCompletionBuilder Opt(Result.getAllocator(), + Result.getCodeCompletionTUInfo()); + if (!FirstParameter) + Opt.AddChunk(CodeCompletionString::CK_Comma); + AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters, + P - Params->begin(), true); + Result.AddOptionalChunk(Opt.TakeString()); + break; + } + + InDefaultArg = false; + + if (FirstParameter) + FirstParameter = false; + else + Result.AddChunk(CodeCompletionString::CK_Comma); + + // Add the placeholder string. + Result.AddPlaceholderChunk( + Result.getAllocator().CopyString(PlaceholderStr)); + } +} + +/// \brief Add a qualifier to the given code-completion string, if the +/// provided nested-name-specifier is non-NULL. +static void +AddQualifierToCompletionString(CodeCompletionBuilder &Result, + NestedNameSpecifier *Qualifier, + bool QualifierIsInformative, + ASTContext &Context, + const PrintingPolicy &Policy) { + if (!Qualifier) + return; + + std::string PrintedNNS; + { + llvm::raw_string_ostream OS(PrintedNNS); + Qualifier->print(OS, Policy); + } + if (QualifierIsInformative) + Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS)); + else + Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS)); +} + +static void +AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result, + FunctionDecl *Function) { + const FunctionProtoType *Proto + = Function->getType()->getAs(); + if (!Proto || !Proto->getTypeQuals()) + return; + + // FIXME: Add ref-qualifier! + + // Handle single qualifiers without copying + if (Proto->getTypeQuals() == Qualifiers::Const) { + Result.AddInformativeChunk(" const"); + return; + } + + if (Proto->getTypeQuals() == Qualifiers::Volatile) { + Result.AddInformativeChunk(" volatile"); + return; + } + + if (Proto->getTypeQuals() == Qualifiers::Restrict) { + Result.AddInformativeChunk(" restrict"); + return; + } + + // Handle multiple qualifiers. + std::string QualsStr; + if (Proto->getTypeQuals() & Qualifiers::Const) + QualsStr += " const"; + if (Proto->getTypeQuals() & Qualifiers::Volatile) + QualsStr += " volatile"; + if (Proto->getTypeQuals() & Qualifiers::Restrict) + QualsStr += " restrict"; + Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr)); +} + +/// \brief Add the name of the given declaration +static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy, + NamedDecl *ND, CodeCompletionBuilder &Result) { + DeclarationName Name = ND->getDeclName(); + if (!Name) + return; + + switch (Name.getNameKind()) { + case DeclarationName::CXXOperatorName: { + const char *OperatorName = 0; + switch (Name.getCXXOverloadedOperator()) { + case OO_None: + case OO_Conditional: + case NUM_OVERLOADED_OPERATORS: + OperatorName = "operator"; + break; + +#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ + case OO_##Name: OperatorName = "operator" Spelling; break; +#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly) +#include "clang/Basic/OperatorKinds.def" + + case OO_New: OperatorName = "operator new"; break; + case OO_Delete: OperatorName = "operator delete"; break; + case OO_Array_New: OperatorName = "operator new[]"; break; + case OO_Array_Delete: OperatorName = "operator delete[]"; break; + case OO_Call: OperatorName = "operator()"; break; + case OO_Subscript: OperatorName = "operator[]"; break; + } + Result.AddTypedTextChunk(OperatorName); + break; + } + + case DeclarationName::Identifier: + case DeclarationName::CXXConversionFunctionName: + case DeclarationName::CXXDestructorName: + case DeclarationName::CXXLiteralOperatorName: + Result.AddTypedTextChunk( + Result.getAllocator().CopyString(ND->getNameAsString())); + break; + + case DeclarationName::CXXUsingDirective: + case DeclarationName::ObjCZeroArgSelector: + case DeclarationName::ObjCOneArgSelector: + case DeclarationName::ObjCMultiArgSelector: + break; + + case DeclarationName::CXXConstructorName: { + CXXRecordDecl *Record = 0; + QualType Ty = Name.getCXXNameType(); + if (const RecordType *RecordTy = Ty->getAs()) + Record = cast(RecordTy->getDecl()); + else if (const InjectedClassNameType *InjectedTy + = Ty->getAs()) + Record = InjectedTy->getDecl(); + else { + Result.AddTypedTextChunk( + Result.getAllocator().CopyString(ND->getNameAsString())); + break; + } + + Result.AddTypedTextChunk( + Result.getAllocator().CopyString(Record->getNameAsString())); + if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) { + Result.AddChunk(CodeCompletionString::CK_LeftAngle); + AddTemplateParameterChunks(Context, Policy, Template, Result); + Result.AddChunk(CodeCompletionString::CK_RightAngle); + } + break; + } + } +} + +CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(Sema &S, + CodeCompletionAllocator &Allocator, + CodeCompletionTUInfo &CCTUInfo) { + return CreateCodeCompletionString(S.Context, S.PP, Allocator, CCTUInfo); +} + +/// \brief If possible, create a new code completion string for the given +/// result. +/// +/// \returns Either a new, heap-allocated code completion string describing +/// how to use this result, or NULL to indicate that the string or name of the +/// result is all that is needed. +CodeCompletionString * +CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, + Preprocessor &PP, + CodeCompletionAllocator &Allocator, + CodeCompletionTUInfo &CCTUInfo) { + CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability); + + PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP); + if (Kind == RK_Pattern) { + Pattern->Priority = Priority; + Pattern->Availability = Availability; + + if (Declaration) { + Result.addParentContext(Declaration->getDeclContext()); + Pattern->ParentKind = Result.getParentKind(); + Pattern->ParentName = Result.getParentName(); + } + + return Pattern; + } + + if (Kind == RK_Keyword) { + Result.AddTypedTextChunk(Keyword); + return Result.TakeString(); + } + + if (Kind == RK_Macro) { + MacroInfo *MI = PP.getMacroInfo(Macro); + assert(MI && "Not a macro?"); + + Result.AddTypedTextChunk( + Result.getAllocator().CopyString(Macro->getName())); + + if (!MI->isFunctionLike()) + return Result.TakeString(); + + // Format a function-like macro with placeholders for the arguments. + Result.AddChunk(CodeCompletionString::CK_LeftParen); + MacroInfo::arg_iterator A = MI->arg_begin(), AEnd = MI->arg_end(); + + // C99 variadic macros add __VA_ARGS__ at the end. Skip it. + if (MI->isC99Varargs()) { + --AEnd; + + if (A == AEnd) { + Result.AddPlaceholderChunk("..."); + } + } + + for (MacroInfo::arg_iterator A = MI->arg_begin(); A != AEnd; ++A) { + if (A != MI->arg_begin()) + Result.AddChunk(CodeCompletionString::CK_Comma); + + if (MI->isVariadic() && (A+1) == AEnd) { + SmallString<32> Arg = (*A)->getName(); + if (MI->isC99Varargs()) + Arg += ", ..."; + else + Arg += "..."; + Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg)); + break; + } + + // Non-variadic macros are simple. + Result.AddPlaceholderChunk( + Result.getAllocator().CopyString((*A)->getName())); + } + Result.AddChunk(CodeCompletionString::CK_RightParen); + return Result.TakeString(); + } + + assert(Kind == RK_Declaration && "Missed a result kind?"); + NamedDecl *ND = Declaration; + Result.addParentContext(ND->getDeclContext()); + + if (StartsNestedNameSpecifier) { + Result.AddTypedTextChunk( + Result.getAllocator().CopyString(ND->getNameAsString())); + Result.AddTextChunk("::"); + return Result.TakeString(); + } + + for (Decl::attr_iterator i = ND->attr_begin(); i != ND->attr_end(); ++i) { + if (AnnotateAttr *Attr = dyn_cast_or_null(*i)) { + Result.AddAnnotation(Result.getAllocator().CopyString(Attr->getAnnotation())); + } + } + + AddResultTypeChunk(Ctx, Policy, ND, Result); + + if (FunctionDecl *Function = dyn_cast(ND)) { + AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, + Ctx, Policy); + AddTypedNameChunk(Ctx, Policy, ND, Result); + Result.AddChunk(CodeCompletionString::CK_LeftParen); + AddFunctionParameterChunks(Ctx, Policy, Function, Result); + Result.AddChunk(CodeCompletionString::CK_RightParen); + AddFunctionTypeQualsToCompletionString(Result, Function); + return Result.TakeString(); + } + + if (FunctionTemplateDecl *FunTmpl = dyn_cast(ND)) { + AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, + Ctx, Policy); + FunctionDecl *Function = FunTmpl->getTemplatedDecl(); + AddTypedNameChunk(Ctx, Policy, Function, Result); + + // Figure out which template parameters are deduced (or have default + // arguments). + llvm::SmallBitVector Deduced; + Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced); + unsigned LastDeducibleArgument; + for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0; + --LastDeducibleArgument) { + if (!Deduced[LastDeducibleArgument - 1]) { + // C++0x: Figure out if the template argument has a default. If so, + // the user doesn't need to type this argument. + // FIXME: We need to abstract template parameters better! + bool HasDefaultArg = false; + NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam( + LastDeducibleArgument - 1); + if (TemplateTypeParmDecl *TTP = dyn_cast(Param)) + HasDefaultArg = TTP->hasDefaultArgument(); + else if (NonTypeTemplateParmDecl *NTTP + = dyn_cast(Param)) + HasDefaultArg = NTTP->hasDefaultArgument(); + else { + assert(isa(Param)); + HasDefaultArg + = cast(Param)->hasDefaultArgument(); + } + + if (!HasDefaultArg) + break; + } + } + + if (LastDeducibleArgument) { + // Some of the function template arguments cannot be deduced from a + // function call, so we introduce an explicit template argument list + // containing all of the arguments up to the first deducible argument. + Result.AddChunk(CodeCompletionString::CK_LeftAngle); + AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result, + LastDeducibleArgument); + Result.AddChunk(CodeCompletionString::CK_RightAngle); + } + + // Add the function parameters + Result.AddChunk(CodeCompletionString::CK_LeftParen); + AddFunctionParameterChunks(Ctx, Policy, Function, Result); + Result.AddChunk(CodeCompletionString::CK_RightParen); + AddFunctionTypeQualsToCompletionString(Result, Function); + return Result.TakeString(); + } + + if (TemplateDecl *Template = dyn_cast(ND)) { + AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, + Ctx, Policy); + Result.AddTypedTextChunk( + Result.getAllocator().CopyString(Template->getNameAsString())); + Result.AddChunk(CodeCompletionString::CK_LeftAngle); + AddTemplateParameterChunks(Ctx, Policy, Template, Result); + Result.AddChunk(CodeCompletionString::CK_RightAngle); + return Result.TakeString(); + } + + if (ObjCMethodDecl *Method = dyn_cast(ND)) { + Selector Sel = Method->getSelector(); + if (Sel.isUnarySelector()) { + Result.AddTypedTextChunk(Result.getAllocator().CopyString( + Sel.getNameForSlot(0))); + return Result.TakeString(); + } + + std::string SelName = Sel.getNameForSlot(0).str(); + SelName += ':'; + if (StartParameter == 0) + Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName)); + else { + Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName)); + + // If there is only one parameter, and we're past it, add an empty + // typed-text chunk since there is nothing to type. + if (Method->param_size() == 1) + Result.AddTypedTextChunk(""); + } + unsigned Idx = 0; + for (ObjCMethodDecl::param_iterator P = Method->param_begin(), + PEnd = Method->param_end(); + P != PEnd; (void)++P, ++Idx) { + if (Idx > 0) { + std::string Keyword; + if (Idx > StartParameter) + Result.AddChunk(CodeCompletionString::CK_HorizontalSpace); + if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx)) + Keyword += II->getName(); + Keyword += ":"; + if (Idx < StartParameter || AllParametersAreInformative) + Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword)); + else + Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword)); + } + + // If we're before the starting parameter, skip the placeholder. + if (Idx < StartParameter) + continue; + + std::string Arg; + + if ((*P)->getType()->isBlockPointerType() && !DeclaringEntity) + Arg = FormatFunctionParameter(Ctx, Policy, *P, true); + else { + (*P)->getType().getAsStringInternal(Arg, Policy); + Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier()) + + Arg + ")"; + if (IdentifierInfo *II = (*P)->getIdentifier()) + if (DeclaringEntity || AllParametersAreInformative) + Arg += II->getName(); + } + + if (Method->isVariadic() && (P + 1) == PEnd) + Arg += ", ..."; + + if (DeclaringEntity) + Result.AddTextChunk(Result.getAllocator().CopyString(Arg)); + else if (AllParametersAreInformative) + Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg)); + else + Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg)); + } + + if (Method->isVariadic()) { + if (Method->param_size() == 0) { + if (DeclaringEntity) + Result.AddTextChunk(", ..."); + else if (AllParametersAreInformative) + Result.AddInformativeChunk(", ..."); + else + Result.AddPlaceholderChunk(", ..."); + } + + MaybeAddSentinel(Ctx, Method, Result); + } + + return Result.TakeString(); + } + + if (Qualifier) + AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, + Ctx, Policy); + + Result.AddTypedTextChunk( + Result.getAllocator().CopyString(ND->getNameAsString())); + return Result.TakeString(); +} + +CodeCompletionString * +CodeCompleteConsumer::OverloadCandidate::CreateSignatureString( + unsigned CurrentArg, + Sema &S, + CodeCompletionAllocator &Allocator, + CodeCompletionTUInfo &CCTUInfo) const { + PrintingPolicy Policy = getCompletionPrintingPolicy(S); + + // FIXME: Set priority, availability appropriately. + CodeCompletionBuilder Result(Allocator,CCTUInfo, 1, CXAvailability_Available); + FunctionDecl *FDecl = getFunction(); + AddResultTypeChunk(S.Context, Policy, FDecl, Result); + const FunctionProtoType *Proto + = dyn_cast(getFunctionType()); + if (!FDecl && !Proto) { + // Function without a prototype. Just give the return type and a + // highlighted ellipsis. + const FunctionType *FT = getFunctionType(); + Result.AddTextChunk(GetCompletionTypeString(FT->getResultType(), + S.Context, Policy, + Result.getAllocator())); + Result.AddChunk(CodeCompletionString::CK_LeftParen); + Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "..."); + Result.AddChunk(CodeCompletionString::CK_RightParen); + return Result.TakeString(); + } + + if (FDecl) + Result.AddTextChunk( + Result.getAllocator().CopyString(FDecl->getNameAsString())); + else + Result.AddTextChunk( + Result.getAllocator().CopyString( + Proto->getResultType().getAsString(Policy))); + + Result.AddChunk(CodeCompletionString::CK_LeftParen); + unsigned NumParams = FDecl? FDecl->getNumParams() : Proto->getNumArgs(); + for (unsigned I = 0; I != NumParams; ++I) { + if (I) + Result.AddChunk(CodeCompletionString::CK_Comma); + + std::string ArgString; + QualType ArgType; + + if (FDecl) { + ArgString = FDecl->getParamDecl(I)->getNameAsString(); + ArgType = FDecl->getParamDecl(I)->getOriginalType(); + } else { + ArgType = Proto->getArgType(I); + } + + ArgType.getAsStringInternal(ArgString, Policy); + + if (I == CurrentArg) + Result.AddChunk(CodeCompletionString::CK_CurrentParameter, + Result.getAllocator().CopyString(ArgString)); + else + Result.AddTextChunk(Result.getAllocator().CopyString(ArgString)); + } + + if (Proto && Proto->isVariadic()) { + Result.AddChunk(CodeCompletionString::CK_Comma); + if (CurrentArg < NumParams) + Result.AddTextChunk("..."); + else + Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "..."); + } + Result.AddChunk(CodeCompletionString::CK_RightParen); + + return Result.TakeString(); +} + +unsigned clang::getMacroUsagePriority(StringRef MacroName, + const LangOptions &LangOpts, + bool PreferredTypeIsPointer) { + unsigned Priority = CCP_Macro; + + // Treat the "nil", "Nil" and "NULL" macros as null pointer constants. + if (MacroName.equals("nil") || MacroName.equals("NULL") || + MacroName.equals("Nil")) { + Priority = CCP_Constant; + if (PreferredTypeIsPointer) + Priority = Priority / CCF_SimilarTypeMatch; + } + // Treat "YES", "NO", "true", and "false" as constants. + else if (MacroName.equals("YES") || MacroName.equals("NO") || + MacroName.equals("true") || MacroName.equals("false")) + Priority = CCP_Constant; + // Treat "bool" as a type. + else if (MacroName.equals("bool")) + Priority = CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0); + + + return Priority; +} + +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::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::TypeAlias: return CXCursor_TypeAliasDecl; + 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::AccessSpec: return CXCursor_CXXAccessSpecifier; + case Decl::ClassTemplatePartialSpecialization: + return CXCursor_ClassTemplatePartialSpecialization; + case Decl::UsingDirective: return CXCursor_UsingDirective; + + case Decl::Using: + case Decl::UnresolvedUsingValue: + case Decl::UnresolvedUsingTypename: + return CXCursor_UsingDeclaration; + + case Decl::ObjCPropertyImpl: + switch (cast(D)->getPropertyImplementation()) { + case ObjCPropertyImplDecl::Dynamic: + return CXCursor_ObjCDynamicDecl; + + case ObjCPropertyImplDecl::Synthesize: + return CXCursor_ObjCSynthesizeDecl; + } + + 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 CodeCompletionResult Result; + + Results.EnterNewScope(); + + for (Preprocessor::macro_iterator M = PP.macro_begin(), + MEnd = PP.macro_end(); + M != MEnd; ++M) { + Results.AddResult(Result(M->first, + getMacroUsagePriority(M->first->getName(), + PP.getLangOpts(), + 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, + CodeCompletionContext Context, + CodeCompletionResult *Results, + unsigned NumResults) { + if (CodeCompleter) + CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults); +} + +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: + if (S.CurContext->isFileContext()) + return CodeCompletionContext::CCC_TopLevel; + if (S.CurContext->isRecord()) + return CodeCompletionContext::CCC_ClassStructUnion; + return CodeCompletionContext::CCC_Other; + + case Sema::PCC_RecoveryInFunction: + return CodeCompletionContext::CCC_Recovery; + + case Sema::PCC_ForInit: + if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 || + S.getLangOpts().ObjC1) + return CodeCompletionContext::CCC_ParenthesizedExpression; + else + return CodeCompletionContext::CCC_Expression; + + case Sema::PCC_Expression: + case Sema::PCC_Condition: + return CodeCompletionContext::CCC_Expression; + + case Sema::PCC_Statement: + return CodeCompletionContext::CCC_Statement; + + case Sema::PCC_Type: + return CodeCompletionContext::CCC_Type; + + case Sema::PCC_ParenthesizedExpression: + return CodeCompletionContext::CCC_ParenthesizedExpression; + + case Sema::PCC_LocalDeclarationSpecifiers: + return CodeCompletionContext::CCC_Type; + } + + llvm_unreachable("Invalid ParserCompletionContext!"); +} + +/// \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; + } + + PrintingPolicy Policy = getCompletionPrintingPolicy(S); + for (CXXMethodDecl::method_iterator M = Method->begin_overridden_methods(), + MEnd = Method->end_overridden_methods(); + M != MEnd; ++M) { + CodeCompletionBuilder Builder(Results.getAllocator(), + Results.getCodeCompletionTUInfo()); + 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, Policy); + Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str())); + } + } else if (!InContext->Equals(Overridden->getDeclContext())) + continue; + + Builder.AddTypedTextChunk(Results.getAllocator().CopyString( + Overridden->getNameAsString())); + Builder.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 + Builder.AddChunk(CodeCompletionString::CK_Comma); + + Builder.AddPlaceholderChunk(Results.getAllocator().CopyString( + (*P)->getIdentifier()->getName())); + } + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(CodeCompletionResult(Builder.TakeString(), + CCP_SuperCompletion, + CXCursor_CXXMethod, + CXAvailability_Available, + Overridden)); + Results.Ignore(Overridden); + } +} + +void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc, + ModuleIdPath Path) { + typedef CodeCompletionResult Result; + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_Other); + Results.EnterNewScope(); + + CodeCompletionAllocator &Allocator = Results.getAllocator(); + CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo()); + typedef CodeCompletionResult Result; + if (Path.empty()) { + // Enumerate all top-level modules. + llvm::SmallVector Modules; + PP.getHeaderSearchInfo().collectAllModules(Modules); + for (unsigned I = 0, N = Modules.size(); I != N; ++I) { + Builder.AddTypedTextChunk( + Builder.getAllocator().CopyString(Modules[I]->Name)); + Results.AddResult(Result(Builder.TakeString(), + CCP_Declaration, + CXCursor_NotImplemented, + Modules[I]->isAvailable() + ? CXAvailability_Available + : CXAvailability_NotAvailable)); + } + } else { + // Load the named module. + Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path, + Module::AllVisible, + /*IsInclusionDirective=*/false); + // Enumerate submodules. + if (Mod) { + for (Module::submodule_iterator Sub = Mod->submodule_begin(), + SubEnd = Mod->submodule_end(); + Sub != SubEnd; ++Sub) { + + Builder.AddTypedTextChunk( + Builder.getAllocator().CopyString((*Sub)->Name)); + Results.AddResult(Result(Builder.TakeString(), + CCP_Declaration, + CXCursor_NotImplemented, + (*Sub)->isAvailable() + ? CXAvailability_Available + : CXAvailability_NotAvailable)); + } + } + } + Results.ExitScope(); + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(),Results.size()); +} + +void Sema::CodeCompleteOrdinaryName(Scope *S, + ParserCompletionContext CompletionContext) { + typedef CodeCompletionResult Result; + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + mapCodeCompletionContext(*this, CompletionContext)); + 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 PCC_Namespace: + case PCC_Class: + case PCC_ObjCInterface: + case PCC_ObjCImplementation: + case PCC_ObjCInstanceVariableList: + case PCC_Template: + case PCC_MemberTemplate: + case PCC_Type: + case PCC_LocalDeclarationSpecifiers: + Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName); + break; + + case PCC_Statement: + case PCC_ParenthesizedExpression: + case PCC_Expression: + case PCC_ForInit: + case PCC_Condition: + if (WantTypesInContext(CompletionContext, getLangOpts())) + Results.setFilter(&ResultBuilder::IsOrdinaryName); + else + Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName); + + if (getLangOpts().CPlusPlus) + MaybeAddOverrideCalls(*this, /*InContext=*/0, Results); + break; + + 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, + CodeCompleter->includeGlobals()); + + AddOrdinaryNameResults(CompletionContext, S, *this, Results); + Results.ExitScope(); + + switch (CompletionContext) { + case PCC_ParenthesizedExpression: + case PCC_Expression: + case PCC_Statement: + case PCC_RecoveryInFunction: + if (S->getFnParent()) + AddPrettyFunctionResults(PP.getLangOpts(), 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: + case PCC_LocalDeclarationSpecifiers: + break; + } + + if (CodeCompleter->includeMacros()) + AddMacroResults(PP, Results); + + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(),Results.size()); +} + +static void AddClassMessageCompletions(Sema &SemaRef, Scope *S, + ParsedType Receiver, + IdentifierInfo **SelIdents, + unsigned NumSelIdents, + bool AtArgumentExpression, + bool IsSuper, + ResultBuilder &Results); + +void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS, + bool AllowNonIdentifiers, + bool AllowNestedNameSpecifiers) { + typedef CodeCompletionResult Result; + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + AllowNestedNameSpecifiers + ? CodeCompletionContext::CCC_PotentiallyQualifiedName + : CodeCompletionContext::CCC_Name); + Results.EnterNewScope(); + + // Type qualifiers can come after names. + Results.AddResult(Result("const")); + Results.AddResult(Result("volatile")); + if (getLangOpts().C99) + Results.AddResult(Result("restrict")); + + if (getLangOpts().CPlusPlus) { + if (AllowNonIdentifiers) { + Results.AddResult(Result("operator")); + } + + // Add nested-name-specifiers. + if (AllowNestedNameSpecifiers) { + Results.allowNestedNameSpecifiers(); + Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy); + CodeCompletionDeclConsumer Consumer(Results, CurContext); + LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer, + CodeCompleter->includeGlobals()); + Results.setFilter(0); + } + } + Results.ExitScope(); + + // If we're in a context where we might have an expression (rather than a + // declaration), and what we've seen so far is an Objective-C type that could + // be a receiver of a class message, this may be a class message send with + // the initial opening bracket '[' missing. Add appropriate completions. + if (AllowNonIdentifiers && !AllowNestedNameSpecifiers && + DS.getTypeSpecType() == DeclSpec::TST_typename && + DS.getStorageClassSpecAsWritten() == DeclSpec::SCS_unspecified && + !DS.isThreadSpecified() && !DS.isExternInLinkageSpec() && + DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified && + DS.getTypeSpecSign() == DeclSpec::TSS_unspecified && + DS.getTypeQualifiers() == 0 && + S && + (S->getFlags() & Scope::DeclScope) != 0 && + (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope | + Scope::FunctionPrototypeScope | + Scope::AtCatchScope)) == 0) { + ParsedType T = DS.getRepAsType(); + if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType()) + AddClassMessageCompletions(*this, S, T, 0, 0, false, false, Results); + } + + // Note that we intentionally suppress macro results here, since we do not + // encourage using macros to produce the names of entities. + + HandleCodeCompleteResults(this, CodeCompleter, + Results.getCompletionContext(), + Results.data(), Results.size()); +} + +struct Sema::CodeCompleteExpressionData { + CodeCompleteExpressionData(QualType PreferredType = QualType()) + : PreferredType(PreferredType), IntegralConstantExpression(false), + ObjCCollection(false) { } + + QualType PreferredType; + bool IntegralConstantExpression; + bool ObjCCollection; + SmallVector IgnoreDecls; +}; + +/// \brief Perform code-completion in an expression context when we know what +/// type we're looking for. +/// +/// \param IntegralConstantExpression Only permit integral constant +/// expressions. +void Sema::CodeCompleteExpression(Scope *S, + const CodeCompleteExpressionData &Data) { + typedef CodeCompletionResult Result; + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_Expression); + if (Data.ObjCCollection) + Results.setFilter(&ResultBuilder::IsObjCCollection); + else if (Data.IntegralConstantExpression) + Results.setFilter(&ResultBuilder::IsIntegralConstantValue); + else if (WantTypesInContext(PCC_Expression, getLangOpts())) + Results.setFilter(&ResultBuilder::IsOrdinaryName); + else + Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName); + + 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, + CodeCompleter->includeGlobals()); + + Results.EnterNewScope(); + AddOrdinaryNameResults(PCC_Expression, S, *this, Results); + Results.ExitScope(); + + bool PreferredTypeIsPointer = false; + if (!Data.PreferredType.isNull()) + PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType() + || Data.PreferredType->isMemberPointerType() + || Data.PreferredType->isBlockPointerType(); + + if (S->getFnParent() && + !Data.ObjCCollection && + !Data.IntegralConstantExpression) + AddPrettyFunctionResults(PP.getLangOpts(), Results); + + if (CodeCompleter->includeMacros()) + AddMacroResults(PP, Results, PreferredTypeIsPointer); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext(CodeCompletionContext::CCC_Expression, + Data.PreferredType), + Results.data(),Results.size()); +} + +void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) { + if (E.isInvalid()) + CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction); + else if (getLangOpts().ObjC1) + CodeCompleteObjCInstanceMessage(S, E.take(), 0, 0, false); +} + +/// \brief The set of properties that have already been added, referenced by +/// property name. +typedef llvm::SmallPtrSet AddedPropertiesSet; + +static void AddObjCProperties(ObjCContainerDecl *Container, + bool AllowCategories, + bool AllowNullaryMethods, + DeclContext *CurContext, + AddedPropertiesSet &AddedProperties, + ResultBuilder &Results) { + typedef CodeCompletionResult Result; + + // Add properties in this container. + for (ObjCContainerDecl::prop_iterator P = Container->prop_begin(), + PEnd = Container->prop_end(); + P != PEnd; + ++P) { + if (AddedProperties.insert(P->getIdentifier())) + Results.MaybeAddResult(Result(*P, 0), CurContext); + } + + // Add nullary methods + if (AllowNullaryMethods) { + ASTContext &Context = Container->getASTContext(); + PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema()); + for (ObjCContainerDecl::method_iterator M = Container->meth_begin(), + MEnd = Container->meth_end(); + M != MEnd; ++M) { + if (M->getSelector().isUnarySelector()) + if (IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0)) + if (AddedProperties.insert(Name)) { + CodeCompletionBuilder Builder(Results.getAllocator(), + Results.getCodeCompletionTUInfo()); + AddResultTypeChunk(Context, Policy, *M, Builder); + Builder.AddTypedTextChunk( + Results.getAllocator().CopyString(Name->getName())); + + Results.MaybeAddResult(Result(Builder.TakeString(), *M, + CCP_MemberDeclaration + CCD_MethodAsProperty), + CurContext); + } + } + } + + + // Add properties in referenced protocols. + if (ObjCProtocolDecl *Protocol = dyn_cast(Container)) { + for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(), + PEnd = Protocol->protocol_end(); + P != PEnd; ++P) + AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext, + AddedProperties, Results); + } else if (ObjCInterfaceDecl *IFace = dyn_cast(Container)){ + if (AllowCategories) { + // Look through categories. + for (ObjCCategoryDecl *Category = IFace->getCategoryList(); + Category; Category = Category->getNextClassCategory()) + AddObjCProperties(Category, AllowCategories, AllowNullaryMethods, + CurContext, AddedProperties, Results); + } + + // Look through protocols. + for (ObjCInterfaceDecl::all_protocol_iterator + I = IFace->all_referenced_protocol_begin(), + E = IFace->all_referenced_protocol_end(); I != E; ++I) + AddObjCProperties(*I, AllowCategories, AllowNullaryMethods, CurContext, + AddedProperties, Results); + + // Look in the superclass. + if (IFace->getSuperClass()) + AddObjCProperties(IFace->getSuperClass(), AllowCategories, + AllowNullaryMethods, CurContext, + AddedProperties, Results); + } else if (const ObjCCategoryDecl *Category + = dyn_cast(Container)) { + // Look through protocols. + for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(), + PEnd = Category->protocol_end(); + P != PEnd; ++P) + AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext, + AddedProperties, Results); + } +} + +void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, + SourceLocation OpLoc, + bool IsArrow) { + if (!Base || !CodeCompleter) + return; + + ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow); + if (ConvertedBase.isInvalid()) + return; + Base = ConvertedBase.get(); + + typedef CodeCompletionResult Result; + + QualType BaseType = Base->getType(); + + if (IsArrow) { + if (const PointerType *Ptr = BaseType->getAs()) + BaseType = Ptr->getPointeeType(); + else if (BaseType->isObjCObjectPointerType()) + /*Do nothing*/ ; + else + return; + } + + enum CodeCompletionContext::Kind contextKind; + + if (IsArrow) { + contextKind = CodeCompletionContext::CCC_ArrowMemberAccess; + } + else { + if (BaseType->isObjCObjectPointerType() || + BaseType->isObjCObjectOrInterfaceType()) { + contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess; + } + else { + contextKind = CodeCompletionContext::CCC_DotMemberAccess; + } + } + + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext(contextKind, + BaseType), + &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, + CodeCompleter->includeGlobals()); + + if (getLangOpts().CPlusPlus) { + if (!Results.empty()) { + // The "template" keyword can follow "->" or "." in the grammar. + // However, we only want to suggest the template keyword if something + // is dependent. + bool IsDependent = BaseType->isDependentType(); + if (!IsDependent) { + for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent()) + if (DeclContext *Ctx = (DeclContext *)DepScope->getEntity()) { + IsDependent = Ctx->isDependentContext(); + break; + } + } + + if (IsDependent) + Results.AddResult(Result("template")); + } + } + } else if (!IsArrow && BaseType->getAsObjCInterfacePointerType()) { + // Objective-C property reference. + AddedPropertiesSet AddedProperties; + + // Add property results based on our interface. + const ObjCObjectPointerType *ObjCPtr + = BaseType->getAsObjCInterfacePointerType(); + assert(ObjCPtr && "Non-NULL pointer guaranteed above!"); + AddObjCProperties(ObjCPtr->getInterfaceDecl(), true, + /*AllowNullaryMethods=*/true, CurContext, + AddedProperties, Results); + + // Add properties from the protocols in a qualified interface. + for (ObjCObjectPointerType::qual_iterator I = ObjCPtr->qual_begin(), + E = ObjCPtr->qual_end(); + I != E; ++I) + AddObjCProperties(*I, true, /*AllowNullaryMethods=*/true, CurContext, + AddedProperties, Results); + } else if ((IsArrow && BaseType->isObjCObjectPointerType()) || + (!IsArrow && BaseType->isObjCObjectType())) { + // Objective-C instance variable access. + ObjCInterfaceDecl *Class = 0; + if (const ObjCObjectPointerType *ObjCPtr + = BaseType->getAs()) + Class = ObjCPtr->getInterfaceDecl(); + else + Class = BaseType->getAs()->getInterface(); + + // Add all ivars from this class and its superclasses. + if (Class) { + CodeCompletionDeclConsumer Consumer(Results, CurContext); + Results.setFilter(&ResultBuilder::IsObjCIvar); + LookupVisibleDecls(Class, LookupMemberName, Consumer, + CodeCompleter->includeGlobals()); + } + } + + // FIXME: How do we cope with isa? + + Results.ExitScope(); + + // Hand off the results found for code completion. + HandleCodeCompleteResults(this, CodeCompleter, + Results.getCompletionContext(), + Results.data(),Results.size()); +} + +void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) { + if (!CodeCompleter) + return; + + 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: + llvm_unreachable("Unknown type specifier kind in CodeCompleteTag"); + } + + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), ContextKind); + CodeCompletionDeclConsumer Consumer(Results, CurContext); + + // First pass: look for tags. + Results.setFilter(Filter); + LookupVisibleDecls(S, LookupTagName, Consumer, + CodeCompleter->includeGlobals()); + + if (CodeCompleter->includeGlobals()) { + // Second pass: look for nested name specifiers. + Results.setFilter(&ResultBuilder::IsNestedNameSpecifier); + LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer); + } + + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(),Results.size()); +} + +void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) { + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_TypeQualifiers); + Results.EnterNewScope(); + if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const)) + Results.AddResult("const"); + if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile)) + Results.AddResult("volatile"); + if (getLangOpts().C99 && + !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict)) + Results.AddResult("restrict"); + Results.ExitScope(); + HandleCodeCompleteResults(this, CodeCompleter, + Results.getCompletionContext(), + Results.data(), Results.size()); +} + +void Sema::CodeCompleteCase(Scope *S) { + if (getCurFunction()->SwitchStack.empty() || !CodeCompleter) + return; + + SwitchStmt *Switch = getCurFunction()->SwitchStack.back(); + QualType type = Switch->getCond()->IgnoreImplicit()->getType(); + if (!type->isEnumeralType()) { + CodeCompleteExpressionData Data(type); + Data.IntegralConstantExpression = true; + CodeCompleteExpression(S, Data); + return; + } + + // Code-complete the cases of a switch statement over an enumeration type + // by providing the list of + EnumDecl *Enum = type->castAs()->getDecl(); + + // Determine which enumerators we have already seen in the switch statement. + // FIXME: Ideally, we would also be able to look *past* the code-completion + // token, in case we are code-completing in the middle of the switch and not + // at the end. However, we aren't able to do so at the moment. + llvm::SmallPtrSet EnumeratorsSeen; + NestedNameSpecifier *Qualifier = 0; + for (SwitchCase *SC = Switch->getSwitchCaseList(); SC; + SC = SC->getNextSwitchCase()) { + CaseStmt *Case = dyn_cast(SC); + if (!Case) + continue; + + Expr *CaseVal = Case->getLHS()->IgnoreParenCasts(); + if (DeclRefExpr *DRE = dyn_cast(CaseVal)) + if (EnumConstantDecl *Enumerator + = dyn_cast(DRE->getDecl())) { + // We look into the AST of the case statement to determine which + // enumerator was named. Alternatively, we could compute the value of + // the integral constant expression, then compare it against the + // values of each enumerator. However, value-based approach would not + // work as well with C++ templates where enumerators declared within a + // template are type- and value-dependent. + EnumeratorsSeen.insert(Enumerator); + + // If this is a qualified-id, keep track of the nested-name-specifier + // so that we can reproduce it as part of code completion, e.g., + // + // switch (TagD.getKind()) { + // case TagDecl::TK_enum: + // break; + // case XXX + // + // At the XXX, our completions are TagDecl::TK_union, + // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union, + // TK_struct, and TK_class. + Qualifier = DRE->getQualifier(); + } + } + + if (getLangOpts().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) { + // If there are no prior enumerators in C++, check whether we have to + // qualify the names of the enumerators that we suggest, because they + // may not be visible in this scope. + Qualifier = getRequiredQualification(Context, CurContext, Enum); + } + + // Add any enumerators that have not yet been mentioned. + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_Expression); + Results.EnterNewScope(); + for (EnumDecl::enumerator_iterator E = Enum->enumerator_begin(), + EEnd = Enum->enumerator_end(); + E != EEnd; ++E) { + if (EnumeratorsSeen.count(*E)) + continue; + + CodeCompletionResult R(*E, Qualifier); + R.Priority = CCP_EnumInCase; + Results.AddResult(R, CurContext, 0, false); + } + Results.ExitScope(); + + //We need to make sure we're setting the right context, + //so only say we include macros if the code completer says we do + enum CodeCompletionContext::Kind kind = CodeCompletionContext::CCC_Other; + if (CodeCompleter->includeMacros()) { + AddMacroResults(PP, Results); + kind = CodeCompletionContext::CCC_OtherWithMacros; + } + + HandleCodeCompleteResults(this, CodeCompleter, + kind, + Results.data(),Results.size()); +} + +namespace { + struct IsBetterOverloadCandidate { + Sema &S; + SourceLocation Loc; + + public: + explicit IsBetterOverloadCandidate(Sema &S, SourceLocation Loc) + : S(S), Loc(Loc) { } + + bool + operator()(const OverloadCandidate &X, const OverloadCandidate &Y) const { + return isBetterOverloadCandidate(S, X, Y, Loc); + } + }; +} + +static bool anyNullArguments(llvm::ArrayRef Args) { + if (Args.size() && !Args.data()) + return true; + + for (unsigned I = 0; I != Args.size(); ++I) + if (!Args[I]) + return true; + + return false; +} + +void Sema::CodeCompleteCall(Scope *S, Expr *FnIn, + llvm::ArrayRef Args) { + if (!CodeCompleter) + return; + + // When we're code-completing for a call, we fall back to ordinary + // name code-completion whenever we can't produce specific + // results. We may want to revisit this strategy in the future, + // e.g., by merging the two kinds of results. + + Expr *Fn = (Expr *)FnIn; + + // Ignore type-dependent call expressions entirely. + if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) || + Expr::hasAnyTypeDependentArguments(Args)) { + CodeCompleteOrdinaryName(S, PCC_Expression); + return; + } + + // Build an overload candidate set based on the functions we find. + SourceLocation Loc = Fn->getExprLoc(); + OverloadCandidateSet CandidateSet(Loc); + + // FIXME: What if we're calling something that isn't a function declaration? + // FIXME: What if we're calling a pseudo-destructor? + // FIXME: What if we're calling a member function? + + typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate; + SmallVector Results; + + Expr *NakedFn = Fn->IgnoreParenCasts(); + if (UnresolvedLookupExpr *ULE = dyn_cast(NakedFn)) + AddOverloadedCallCandidates(ULE, Args, CandidateSet, + /*PartialOverloading=*/ true); + else if (DeclRefExpr *DRE = dyn_cast(NakedFn)) { + FunctionDecl *FDecl = dyn_cast(DRE->getDecl()); + if (FDecl) { + if (!getLangOpts().CPlusPlus || + !FDecl->getType()->getAs()) + Results.push_back(ResultCandidate(FDecl)); + else + // FIXME: access? + AddOverloadCandidate(FDecl, DeclAccessPair::make(FDecl, AS_none), Args, + CandidateSet, false, /*PartialOverloading*/true); + } + } + + QualType ParamType; + + if (!CandidateSet.empty()) { + // Sort the overload candidate set by placing the best overloads first. + std::stable_sort(CandidateSet.begin(), CandidateSet.end(), + IsBetterOverloadCandidate(*this, Loc)); + + // Add the remaining viable overload candidates as code-completion reslults. + for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(), + CandEnd = CandidateSet.end(); + Cand != CandEnd; ++Cand) { + if (Cand->Viable) + Results.push_back(ResultCandidate(Cand->Function)); + } + + // From the viable candidates, try to determine the type of this parameter. + for (unsigned I = 0, N = Results.size(); I != N; ++I) { + if (const FunctionType *FType = Results[I].getFunctionType()) + if (const FunctionProtoType *Proto = dyn_cast(FType)) + if (Args.size() < Proto->getNumArgs()) { + if (ParamType.isNull()) + ParamType = Proto->getArgType(Args.size()); + else if (!Context.hasSameUnqualifiedType( + ParamType.getNonReferenceType(), + Proto->getArgType(Args.size()).getNonReferenceType())) { + ParamType = QualType(); + break; + } + } + } + } else { + // Try to determine the parameter type from the type of the expression + // being called. + QualType FunctionType = Fn->getType(); + if (const PointerType *Ptr = FunctionType->getAs()) + FunctionType = Ptr->getPointeeType(); + else if (const BlockPointerType *BlockPtr + = FunctionType->getAs()) + FunctionType = BlockPtr->getPointeeType(); + else if (const MemberPointerType *MemPtr + = FunctionType->getAs()) + FunctionType = MemPtr->getPointeeType(); + + if (const FunctionProtoType *Proto + = FunctionType->getAs()) { + if (Args.size() < Proto->getNumArgs()) + ParamType = Proto->getArgType(Args.size()); + } + } + + if (ParamType.isNull()) + CodeCompleteOrdinaryName(S, PCC_Expression); + else + CodeCompleteExpression(S, ParamType); + + if (!Results.empty()) + CodeCompleter->ProcessOverloadCandidates(*this, Args.size(), Results.data(), + Results.size()); +} + +void Sema::CodeCompleteInitializer(Scope *S, Decl *D) { + ValueDecl *VD = dyn_cast_or_null(D); + if (!VD) { + CodeCompleteOrdinaryName(S, PCC_Expression); + return; + } + + CodeCompleteExpression(S, VD->getType()); +} + +void Sema::CodeCompleteReturn(Scope *S) { + QualType ResultType; + if (isa(CurContext)) { + if (BlockScopeInfo *BSI = getCurBlock()) + ResultType = BSI->ReturnType; + } else if (FunctionDecl *Function = dyn_cast(CurContext)) + ResultType = Function->getResultType(); + else if (ObjCMethodDecl *Method = dyn_cast(CurContext)) + ResultType = Method->getResultType(); + + if (ResultType.isNull()) + CodeCompleteOrdinaryName(S, PCC_Expression); + else + CodeCompleteExpression(S, ResultType); +} + +void Sema::CodeCompleteAfterIf(Scope *S) { + typedef CodeCompletionResult Result; + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + mapCodeCompletionContext(*this, PCC_Statement)); + Results.setFilter(&ResultBuilder::IsOrdinaryName); + Results.EnterNewScope(); + + CodeCompletionDeclConsumer Consumer(Results, CurContext); + LookupVisibleDecls(S, LookupOrdinaryName, Consumer, + CodeCompleter->includeGlobals()); + + AddOrdinaryNameResults(PCC_Statement, S, *this, Results); + + // "else" block + CodeCompletionBuilder Builder(Results.getAllocator(), + Results.getCodeCompletionTUInfo()); + Builder.AddTypedTextChunk("else"); + if (Results.includeCodePatterns()) { + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddChunk(CodeCompletionString::CK_LeftBrace); + Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); + Builder.AddPlaceholderChunk("statements"); + Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); + Builder.AddChunk(CodeCompletionString::CK_RightBrace); + } + Results.AddResult(Builder.TakeString()); + + // "else if" block + Builder.AddTypedTextChunk("else"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddTextChunk("if"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + if (getLangOpts().CPlusPlus) + Builder.AddPlaceholderChunk("condition"); + else + Builder.AddPlaceholderChunk("expression"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + if (Results.includeCodePatterns()) { + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddChunk(CodeCompletionString::CK_LeftBrace); + Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); + Builder.AddPlaceholderChunk("statements"); + Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); + Builder.AddChunk(CodeCompletionString::CK_RightBrace); + } + Results.AddResult(Builder.TakeString()); + + Results.ExitScope(); + + if (S->getFnParent()) + AddPrettyFunctionResults(PP.getLangOpts(), Results); + + if (CodeCompleter->includeMacros()) + AddMacroResults(PP, Results); + + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(),Results.size()); +} + +void Sema::CodeCompleteAssignmentRHS(Scope *S, Expr *LHS) { + if (LHS) + CodeCompleteExpression(S, static_cast(LHS)->getType()); + else + CodeCompleteOrdinaryName(S, PCC_Expression); +} + +void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, + bool EnteringContext) { + if (!SS.getScopeRep() || !CodeCompleter) + return; + + DeclContext *Ctx = computeDeclContext(SS, EnteringContext); + if (!Ctx) + return; + + // Try to instantiate any non-dependent declaration contexts before + // we look in them. + if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx)) + return; + + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_Name); + 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(); + + CodeCompletionDeclConsumer Consumer(Results, CurContext); + LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer); + + HandleCodeCompleteResults(this, CodeCompleter, + Results.getCompletionContext(), + Results.data(),Results.size()); +} + +void Sema::CodeCompleteUsing(Scope *S) { + if (!CodeCompleter) + return; + + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_PotentiallyQualifiedName, + &ResultBuilder::IsNestedNameSpecifier); + Results.EnterNewScope(); + + // If we aren't in class scope, we could see the "namespace" keyword. + if (!S->isClassScope()) + 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, + CodeCompleter->includeGlobals()); + Results.ExitScope(); + + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_PotentiallyQualifiedName, + Results.data(),Results.size()); +} + +void Sema::CodeCompleteUsingDirective(Scope *S) { + if (!CodeCompleter) + return; + + // After "using namespace", we expect to see a namespace name or namespace + // alias. + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_Namespace, + &ResultBuilder::IsNamespaceOrAlias); + Results.EnterNewScope(); + CodeCompletionDeclConsumer Consumer(Results, CurContext); + LookupVisibleDecls(S, LookupOrdinaryName, Consumer, + CodeCompleter->includeGlobals()); + Results.ExitScope(); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Namespace, + Results.data(),Results.size()); +} + +void Sema::CodeCompleteNamespaceDecl(Scope *S) { + if (!CodeCompleter) + return; + + DeclContext *Ctx = (DeclContext *)S->getEntity(); + if (!S->getParent()) + Ctx = Context.getTranslationUnitDecl(); + + bool SuppressedGlobalResults + = Ctx && !CodeCompleter->includeGlobals() && isa(Ctx); + + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + SuppressedGlobalResults + ? CodeCompletionContext::CCC_Namespace + : CodeCompletionContext::CCC_Other, + &ResultBuilder::IsNamespace); + + if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) { + // We only want to see those namespaces that have already been defined + // within this scope, because its likely that the user is creating an + // extended namespace declaration. Keep track of the most recent + // definition of each namespace. + std::map OrigToLatest; + for (DeclContext::specific_decl_iterator + NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end()); + NS != NSEnd; ++NS) + OrigToLatest[NS->getOriginalNamespace()] = *NS; + + // Add the most recent definition (or extended definition) of each + // namespace to the list of results. + Results.EnterNewScope(); + for (std::map::iterator + NS = OrigToLatest.begin(), + NSEnd = OrigToLatest.end(); + NS != NSEnd; ++NS) + Results.AddResult(CodeCompletionResult(NS->second, 0), + CurContext, 0, false); + Results.ExitScope(); + } + + HandleCodeCompleteResults(this, CodeCompleter, + Results.getCompletionContext(), + Results.data(),Results.size()); +} + +void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) { + if (!CodeCompleter) + return; + + // After "namespace", we expect to see a namespace or alias. + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_Namespace, + &ResultBuilder::IsNamespaceOrAlias); + CodeCompletionDeclConsumer Consumer(Results, CurContext); + LookupVisibleDecls(S, LookupOrdinaryName, Consumer, + CodeCompleter->includeGlobals()); + HandleCodeCompleteResults(this, CodeCompleter, + Results.getCompletionContext(), + Results.data(),Results.size()); +} + +void Sema::CodeCompleteOperatorName(Scope *S) { + if (!CodeCompleter) + return; + + typedef CodeCompletionResult Result; + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_Type, + &ResultBuilder::IsType); + Results.EnterNewScope(); + + // Add the names of overloadable operators. +#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ + if (std::strcmp(Spelling, "?")) \ + Results.AddResult(Result(Spelling)); +#include "clang/Basic/OperatorKinds.def" + + // Add any type names visible from the current scope + Results.allowNestedNameSpecifiers(); + CodeCompletionDeclConsumer Consumer(Results, CurContext); + LookupVisibleDecls(S, LookupOrdinaryName, Consumer, + CodeCompleter->includeGlobals()); + + // Add any type specifiers + AddTypeSpecifierResults(getLangOpts(), Results); + Results.ExitScope(); + + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Type, + Results.data(),Results.size()); +} + +void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD, + CXXCtorInitializer** Initializers, + unsigned NumInitializers) { + PrintingPolicy Policy = getCompletionPrintingPolicy(*this); + CXXConstructorDecl *Constructor + = static_cast(ConstructorD); + if (!Constructor) + return; + + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_PotentiallyQualifiedName); + 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]->getAnyMember())); + } + + // Add completions for base classes. + CodeCompletionBuilder Builder(Results.getAllocator(), + Results.getCodeCompletionTUInfo()); + 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; + } + + Builder.AddTypedTextChunk( + Results.getAllocator().CopyString( + Base->getType().getAsString(Policy))); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("args"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(CodeCompletionResult(Builder.TakeString(), + 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; + } + + Builder.AddTypedTextChunk( + Builder.getAllocator().CopyString( + Base->getType().getAsString(Policy))); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("args"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(CodeCompletionResult(Builder.TakeString(), + 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]->isAnyMemberInitializer() && + Initializers[NumInitializers - 1]->getAnyMember() == *Field; + continue; + } + + if (!Field->getDeclName()) + continue; + + Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( + Field->getIdentifier()->getName())); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("args"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(CodeCompletionResult(Builder.TakeString(), + SawLastInitializer? CCP_NextInitializer + : CCP_MemberDeclaration, + CXCursor_MemberRef, + CXAvailability_Available, + *Field)); + SawLastInitializer = false; + } + Results.ExitScope(); + + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(), Results.size()); +} + +/// \brief Determine whether this scope denotes a namespace. +static bool isNamespaceScope(Scope *S) { + DeclContext *DC = static_cast(S->getEntity()); + if (!DC) + return false; + + return DC->isFileContext(); +} + +void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro, + bool AfterAmpersand) { + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_Other); + Results.EnterNewScope(); + + // Note what has already been captured. + llvm::SmallPtrSet Known; + bool IncludedThis = false; + for (SmallVectorImpl::iterator C = Intro.Captures.begin(), + CEnd = Intro.Captures.end(); + C != CEnd; ++C) { + if (C->Kind == LCK_This) { + IncludedThis = true; + continue; + } + + Known.insert(C->Id); + } + + // Look for other capturable variables. + for (; S && !isNamespaceScope(S); S = S->getParent()) { + for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end(); + D != DEnd; ++D) { + VarDecl *Var = dyn_cast(*D); + if (!Var || + !Var->hasLocalStorage() || + Var->hasAttr()) + continue; + + if (Known.insert(Var->getIdentifier())) + Results.AddResult(CodeCompletionResult(Var), CurContext, 0, false); + } + } + + // Add 'this', if it would be valid. + if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy) + addThisCompletion(*this, Results); + + Results.ExitScope(); + + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(), Results.size()); +} + +// Macro that expands to @Keyword or Keyword, depending on whether NeedAt is +// true or false. +#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) NeedAt? "@" #Keyword : #Keyword +static void AddObjCImplementationResults(const LangOptions &LangOpts, + ResultBuilder &Results, + bool NeedAt) { + typedef CodeCompletionResult Result; + // Since we have an implementation, we can end it. + Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end))); + + CodeCompletionBuilder Builder(Results.getAllocator(), + Results.getCodeCompletionTUInfo()); + if (LangOpts.ObjC2) { + // @dynamic + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,dynamic)); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("property"); + Results.AddResult(Result(Builder.TakeString())); + + // @synthesize + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,synthesize)); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("property"); + Results.AddResult(Result(Builder.TakeString())); + } +} + +static void AddObjCInterfaceResults(const LangOptions &LangOpts, + ResultBuilder &Results, + bool NeedAt) { + typedef CodeCompletionResult Result; + + // Since we have an interface or protocol, we can end it. + Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end))); + + if (LangOpts.ObjC2) { + // @property + Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,property))); + + // @required + Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,required))); + + // @optional + Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,optional))); + } +} + +static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) { + typedef CodeCompletionResult Result; + CodeCompletionBuilder Builder(Results.getAllocator(), + Results.getCodeCompletionTUInfo()); + + // @class name ; + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,class)); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("name"); + Results.AddResult(Result(Builder.TakeString())); + + if (Results.includeCodePatterns()) { + // @interface name + // FIXME: Could introduce the whole pattern, including superclasses and + // such. + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,interface)); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("class"); + Results.AddResult(Result(Builder.TakeString())); + + // @protocol name + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,protocol)); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("protocol"); + Results.AddResult(Result(Builder.TakeString())); + + // @implementation name + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,implementation)); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("class"); + Results.AddResult(Result(Builder.TakeString())); + } + + // @compatibility_alias name + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,compatibility_alias)); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("alias"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("class"); + Results.AddResult(Result(Builder.TakeString())); +} + +void Sema::CodeCompleteObjCAtDirective(Scope *S) { + typedef CodeCompletionResult Result; + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_Other); + Results.EnterNewScope(); + if (isa(CurContext)) + AddObjCImplementationResults(getLangOpts(), Results, false); + else if (CurContext->isObjCContainer()) + AddObjCInterfaceResults(getLangOpts(), Results, false); + else + AddObjCTopLevelResults(Results, false); + Results.ExitScope(); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); +} + +static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) { + typedef CodeCompletionResult Result; + CodeCompletionBuilder Builder(Results.getAllocator(), + Results.getCodeCompletionTUInfo()); + + // @encode ( type-name ) + const char *EncodeType = "char[]"; + if (Results.getSema().getLangOpts().CPlusPlus || + Results.getSema().getLangOpts().ConstStrings) + EncodeType = " const char[]"; + Builder.AddResultTypeChunk(EncodeType); + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,encode)); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("type-name"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Builder.TakeString())); + + // @protocol ( protocol-name ) + Builder.AddResultTypeChunk("Protocol *"); + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,protocol)); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("protocol-name"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Builder.TakeString())); + + // @selector ( selector ) + Builder.AddResultTypeChunk("SEL"); + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,selector)); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("selector"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Builder.TakeString())); + + // @[ objects, ... ] + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,[)); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("objects, ..."); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddChunk(CodeCompletionString::CK_RightBracket); + Results.AddResult(Result(Builder.TakeString())); + + // @{ key : object, ... } + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,{)); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("key"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddChunk(CodeCompletionString::CK_Colon); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("object, ..."); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddChunk(CodeCompletionString::CK_RightBrace); + Results.AddResult(Result(Builder.TakeString())); +} + +static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) { + typedef CodeCompletionResult Result; + CodeCompletionBuilder Builder(Results.getAllocator(), + Results.getCodeCompletionTUInfo()); + + if (Results.includeCodePatterns()) { + // @try { statements } @catch ( declaration ) { statements } @finally + // { statements } + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,try)); + Builder.AddChunk(CodeCompletionString::CK_LeftBrace); + Builder.AddPlaceholderChunk("statements"); + Builder.AddChunk(CodeCompletionString::CK_RightBrace); + Builder.AddTextChunk("@catch"); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("parameter"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddChunk(CodeCompletionString::CK_LeftBrace); + Builder.AddPlaceholderChunk("statements"); + Builder.AddChunk(CodeCompletionString::CK_RightBrace); + Builder.AddTextChunk("@finally"); + Builder.AddChunk(CodeCompletionString::CK_LeftBrace); + Builder.AddPlaceholderChunk("statements"); + Builder.AddChunk(CodeCompletionString::CK_RightBrace); + Results.AddResult(Result(Builder.TakeString())); + } + + // @throw + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,throw)); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("expression"); + Results.AddResult(Result(Builder.TakeString())); + + if (Results.includeCodePatterns()) { + // @synchronized ( expression ) { statements } + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,synchronized)); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("expression"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddChunk(CodeCompletionString::CK_LeftBrace); + Builder.AddPlaceholderChunk("statements"); + Builder.AddChunk(CodeCompletionString::CK_RightBrace); + Results.AddResult(Result(Builder.TakeString())); + } +} + +static void AddObjCVisibilityResults(const LangOptions &LangOpts, + ResultBuilder &Results, + bool NeedAt) { + 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))); + if (LangOpts.ObjC2) + Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,package))); +} + +void Sema::CodeCompleteObjCAtVisibility(Scope *S) { + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_Other); + Results.EnterNewScope(); + AddObjCVisibilityResults(getLangOpts(), Results, false); + Results.ExitScope(); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); +} + +void Sema::CodeCompleteObjCAtStatement(Scope *S) { + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_Other); + Results.EnterNewScope(); + AddObjCStatementResults(Results, false); + AddObjCExpressionResults(Results, false); + Results.ExitScope(); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); +} + +void Sema::CodeCompleteObjCAtExpression(Scope *S) { + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_Other); + Results.EnterNewScope(); + AddObjCExpressionResults(Results, false); + Results.ExitScope(); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); +} + +/// \brief Determine whether the addition of the given flag to an Objective-C +/// property's attributes will cause a conflict. +static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) { + // Check if we've already added this flag. + if (Attributes & NewFlag) + return true; + + Attributes |= NewFlag; + + // Check for collisions with "readonly". + if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) && + (Attributes & (ObjCDeclSpec::DQ_PR_readwrite | + ObjCDeclSpec::DQ_PR_assign | + ObjCDeclSpec::DQ_PR_unsafe_unretained | + ObjCDeclSpec::DQ_PR_copy | + ObjCDeclSpec::DQ_PR_retain | + ObjCDeclSpec::DQ_PR_strong))) + return true; + + // Check for more than one of { assign, copy, retain, strong }. + unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign | + ObjCDeclSpec::DQ_PR_unsafe_unretained | + ObjCDeclSpec::DQ_PR_copy | + ObjCDeclSpec::DQ_PR_retain| + ObjCDeclSpec::DQ_PR_strong); + if (AssignCopyRetMask && + AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign && + AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained && + AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy && + AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain && + AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong) + return true; + + return false; +} + +void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) { + if (!CodeCompleter) + return; + + unsigned Attributes = ODS.getPropertyAttributes(); + + typedef CodeCompletionResult Result; + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_Other); + Results.EnterNewScope(); + if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly)) + Results.AddResult(CodeCompletionResult("readonly")); + if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign)) + Results.AddResult(CodeCompletionResult("assign")); + if (!ObjCPropertyFlagConflicts(Attributes, + ObjCDeclSpec::DQ_PR_unsafe_unretained)) + Results.AddResult(CodeCompletionResult("unsafe_unretained")); + if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite)) + Results.AddResult(CodeCompletionResult("readwrite")); + if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain)) + Results.AddResult(CodeCompletionResult("retain")); + if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong)) + Results.AddResult(CodeCompletionResult("strong")); + if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy)) + Results.AddResult(CodeCompletionResult("copy")); + if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic)) + Results.AddResult(CodeCompletionResult("nonatomic")); + if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic)) + Results.AddResult(CodeCompletionResult("atomic")); + if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) { + CodeCompletionBuilder Setter(Results.getAllocator(), + Results.getCodeCompletionTUInfo()); + Setter.AddTypedTextChunk("setter"); + Setter.AddTextChunk(" = "); + Setter.AddPlaceholderChunk("method"); + Results.AddResult(CodeCompletionResult(Setter.TakeString())); + } + if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) { + CodeCompletionBuilder Getter(Results.getAllocator(), + Results.getCodeCompletionTUInfo()); + Getter.AddTypedTextChunk("getter"); + Getter.AddTextChunk(" = "); + Getter.AddPlaceholderChunk("method"); + Results.AddResult(CodeCompletionResult(Getter.TakeString())); + } + Results.ExitScope(); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); +} + +/// \brief Descripts the kind of Objective-C method that we want to find +/// via code completion. +enum ObjCMethodKind { + MK_Any, //< Any kind of method, provided it means other specified criteria. + MK_ZeroArgSelector, //< Zero-argument (unary) selector. + MK_OneArgSelector //< One-argument selector. +}; + +static bool isAcceptableObjCSelector(Selector Sel, + ObjCMethodKind WantKind, + IdentifierInfo **SelIdents, + unsigned NumSelIdents, + bool AllowSameLength = true) { + 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; + } + + if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs()) + return false; + + 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, + bool AllowSameLength = true) { + return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents, + NumSelIdents, AllowSameLength); +} + +namespace { + /// \brief A set of selectors, which is used to avoid introducing multiple + /// completions with the same selector into the result set. + typedef llvm::SmallPtrSet VisitedSelectorSet; +} + +/// \brief Add all of the Objective-C methods in the given Objective-C +/// container to the set of results. +/// +/// The container will be a class, protocol, category, or implementation of +/// any of the above. This mether will recurse to include methods from +/// the superclasses of classes along with their categories, protocols, and +/// implementations. +/// +/// \param Container the container in which we'll look to find methods. +/// +/// \param WantInstance whether to add instance methods (only); if false, this +/// routine will add factory methods (only). +/// +/// \param CurContext the context in which we're performing the lookup that +/// finds methods. +/// +/// \param AllowSameLength Whether we allow a method to be added to the list +/// when it has the same number of parameters as we have selector identifiers. +/// +/// \param Results the structure into which we'll add results. +static void AddObjCMethods(ObjCContainerDecl *Container, + bool WantInstanceMethods, + ObjCMethodKind WantKind, + IdentifierInfo **SelIdents, + unsigned NumSelIdents, + DeclContext *CurContext, + VisitedSelectorSet &Selectors, + bool AllowSameLength, + ResultBuilder &Results, + bool InOriginalClass = true) { + typedef CodeCompletionResult Result; + for (ObjCContainerDecl::method_iterator M = Container->meth_begin(), + MEnd = Container->meth_end(); + M != MEnd; ++M) { + if ((*M)->isInstanceMethod() == WantInstanceMethods) { + // Check whether the selector identifiers we've been given are a + // subset of the identifiers for this particular method. + if (!isAcceptableObjCMethod(*M, WantKind, SelIdents, NumSelIdents, + AllowSameLength)) + continue; + + if (!Selectors.insert((*M)->getSelector())) + continue; + + Result R = Result(*M, 0); + R.StartParameter = NumSelIdents; + R.AllParametersAreInformative = (WantKind != MK_Any); + if (!InOriginalClass) + R.Priority += CCD_InBaseClass; + Results.MaybeAddResult(R, CurContext); + } + } + + // Visit the protocols of protocols. + if (ObjCProtocolDecl *Protocol = dyn_cast(Container)) { + if (Protocol->hasDefinition()) { + const ObjCList &Protocols + = Protocol->getReferencedProtocols(); + for (ObjCList::iterator I = Protocols.begin(), + E = Protocols.end(); + I != E; ++I) + AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, + NumSelIdents, CurContext, Selectors, AllowSameLength, + Results, false); + } + } + + ObjCInterfaceDecl *IFace = dyn_cast(Container); + if (!IFace || !IFace->hasDefinition()) + return; + + // Add methods in protocols. + for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(), + E = IFace->protocol_end(); + I != E; ++I) + AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents, + CurContext, Selectors, AllowSameLength, Results, false); + + // Add methods in categories. + for (ObjCCategoryDecl *CatDecl = IFace->getCategoryList(); CatDecl; + CatDecl = CatDecl->getNextClassCategory()) { + AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents, + NumSelIdents, CurContext, Selectors, AllowSameLength, + Results, InOriginalClass); + + // Add a categories protocol methods. + const ObjCList &Protocols + = CatDecl->getReferencedProtocols(); + for (ObjCList::iterator I = Protocols.begin(), + E = Protocols.end(); + I != E; ++I) + AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, + NumSelIdents, CurContext, Selectors, AllowSameLength, + Results, false); + + // Add methods in category implementations. + if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation()) + AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, + NumSelIdents, CurContext, Selectors, AllowSameLength, + Results, InOriginalClass); + } + + // Add methods in superclass. + if (IFace->getSuperClass()) + AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind, + SelIdents, NumSelIdents, CurContext, Selectors, + AllowSameLength, Results, false); + + // Add methods in our implementation, if any. + if (ObjCImplementationDecl *Impl = IFace->getImplementation()) + AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, + NumSelIdents, CurContext, Selectors, AllowSameLength, + Results, InOriginalClass); +} + + +void Sema::CodeCompleteObjCPropertyGetter(Scope *S) { + typedef CodeCompletionResult Result; + + // Try to find the interface where getters might live. + ObjCInterfaceDecl *Class = dyn_cast_or_null(CurContext); + if (!Class) { + if (ObjCCategoryDecl *Category + = dyn_cast_or_null(CurContext)) + Class = Category->getClassInterface(); + + if (!Class) + return; + } + + // Find all of the potential getters. + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_Other); + Results.EnterNewScope(); + + VisitedSelectorSet Selectors; + AddObjCMethods(Class, true, MK_ZeroArgSelector, 0, 0, CurContext, Selectors, + /*AllowSameLength=*/true, Results); + Results.ExitScope(); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); +} + +void Sema::CodeCompleteObjCPropertySetter(Scope *S) { + typedef CodeCompletionResult Result; + + // Try to find the interface where setters might live. + ObjCInterfaceDecl *Class + = dyn_cast_or_null(CurContext); + if (!Class) { + if (ObjCCategoryDecl *Category + = dyn_cast_or_null(CurContext)) + Class = Category->getClassInterface(); + + if (!Class) + return; + } + + // Find all of the potential getters. + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_Other); + Results.EnterNewScope(); + + VisitedSelectorSet Selectors; + AddObjCMethods(Class, true, MK_OneArgSelector, 0, 0, CurContext, + Selectors, /*AllowSameLength=*/true, Results); + + Results.ExitScope(); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); +} + +void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS, + bool IsParameter) { + typedef CodeCompletionResult Result; + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_Type); + 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"); + } + + // If we're completing the return type of an Objective-C method and the + // identifier IBAction refers to a macro, provide a completion item for + // an action, e.g., + // IBAction)<#selector#>:(id)sender + if (DS.getObjCDeclQualifier() == 0 && !IsParameter && + Context.Idents.get("IBAction").hasMacroDefinition()) { + CodeCompletionBuilder Builder(Results.getAllocator(), + Results.getCodeCompletionTUInfo(), + CCP_CodePattern, CXAvailability_Available); + Builder.AddTypedTextChunk("IBAction"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddPlaceholderChunk("selector"); + Builder.AddChunk(CodeCompletionString::CK_Colon); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("id"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddTextChunk("sender"); + Results.AddResult(CodeCompletionResult(Builder.TakeString())); + } + + // 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 +/// that it has some more-specific class type based on knowledge of +/// common uses of Objective-C. This routine returns that class type, +/// or NULL if no better result could be determined. +static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) { + ObjCMessageExpr *Msg = dyn_cast_or_null(E); + if (!Msg) + return 0; + + Selector Sel = Msg->getSelector(); + if (Sel.isNull()) + return 0; + + IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0); + if (!Id) + return 0; + + ObjCMethodDecl *Method = Msg->getMethodDecl(); + if (!Method) + return 0; + + // Determine the class that we're sending the message to. + ObjCInterfaceDecl *IFace = 0; + switch (Msg->getReceiverKind()) { + case ObjCMessageExpr::Class: + if (const ObjCObjectType *ObjType + = Msg->getClassReceiver()->getAs()) + IFace = ObjType->getInterface(); + break; + + case ObjCMessageExpr::Instance: { + QualType T = Msg->getInstanceReceiver()->getType(); + if (const ObjCObjectPointerType *Ptr = T->getAs()) + IFace = Ptr->getInterfaceDecl(); + break; + } + + case ObjCMessageExpr::SuperInstance: + case ObjCMessageExpr::SuperClass: + break; + } + + if (!IFace) + return 0; + + ObjCInterfaceDecl *Super = IFace->getSuperClass(); + if (Method->isInstanceMethod()) + return llvm::StringSwitch(Id->getName()) + .Case("retain", IFace) + .Case("strong", IFace) + .Case("autorelease", IFace) + .Case("copy", IFace) + .Case("copyWithZone", IFace) + .Case("mutableCopy", IFace) + .Case("mutableCopyWithZone", IFace) + .Case("awakeFromCoder", IFace) + .Case("replacementObjectFromCoder", IFace) + .Case("class", IFace) + .Case("classForCoder", IFace) + .Case("superclass", Super) + .Default(0); + + return llvm::StringSwitch(Id->getName()) + .Case("new", IFace) + .Case("alloc", IFace) + .Case("allocWithZone", IFace) + .Case("class", IFace) + .Case("superclass", Super) + .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) { + // Check in the class + SuperMethod = Class->getMethod(CurMethod->getSelector(), + CurMethod->isInstanceMethod()); + + // Check in categories or class extensions. + if (!SuperMethod) { + for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category; + Category = Category->getNextClassCategory()) + if ((SuperMethod = Category->getMethod(CurMethod->getSelector(), + CurMethod->isInstanceMethod()))) + break; + } + } + + 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. + CodeCompletionBuilder Builder(Results.getAllocator(), + Results.getCodeCompletionTUInfo()); + + // Give this completion a return type. + AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod, + Builder); + + // If we need the "super" keyword, add it (plus some spacing). + if (NeedSuperKeyword) { + Builder.AddTypedTextChunk("super"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + } + + Selector Sel = CurMethod->getSelector(); + if (Sel.isUnarySelector()) { + if (NeedSuperKeyword) + Builder.AddTextChunk(Builder.getAllocator().CopyString( + Sel.getNameForSlot(0))); + else + Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( + Sel.getNameForSlot(0))); + } else { + ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(); + for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) { + if (I > NumSelIdents) + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + + if (I < NumSelIdents) + Builder.AddInformativeChunk( + Builder.getAllocator().CopyString( + Sel.getNameForSlot(I) + ":")); + else if (NeedSuperKeyword || I > NumSelIdents) { + Builder.AddTextChunk( + Builder.getAllocator().CopyString( + Sel.getNameForSlot(I) + ":")); + Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString( + (*CurP)->getIdentifier()->getName())); + } else { + Builder.AddTypedTextChunk( + Builder.getAllocator().CopyString( + Sel.getNameForSlot(I) + ":")); + Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString( + (*CurP)->getIdentifier()->getName())); + } + } + } + + Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod, + CCP_SuperCompletion)); + return SuperMethod; +} + +void Sema::CodeCompleteObjCMessageReceiver(Scope *S) { + typedef CodeCompletionResult Result; + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_ObjCMessageReceiver, + getLangOpts().CPlusPlus0x + ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture + : &ResultBuilder::IsObjCMessageReceiver); + + CodeCompletionDeclConsumer Consumer(Results, CurContext); + Results.EnterNewScope(); + 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()) { + Results.AddResult(Result("super")); + + AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, 0, 0, Results); + } + + if (getLangOpts().CPlusPlus0x) + addThisCompletion(*this, Results); + + Results.ExitScope(); + + if (CodeCompleter->includeMacros()) + AddMacroResults(PP, Results); + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(), Results.size()); + +} + +void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, + IdentifierInfo **SelIdents, + unsigned NumSelIdents, + bool AtArgumentExpression) { + ObjCInterfaceDecl *CDecl = 0; + if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) { + // Figure out which interface we're in. + CDecl = CurMethod->getClassInterface(); + if (!CDecl) + return; + + // Find the superclass of this class. + CDecl = CDecl->getSuperClass(); + if (!CDecl) + return; + + if (CurMethod->isInstanceMethod()) { + // We are inside an instance method, which means that the message + // send [super ...] is actually calling an instance method on the + // current object. + return CodeCompleteObjCInstanceMessage(S, 0, + SelIdents, NumSelIdents, + AtArgumentExpression, + CDecl); + } + + // Fall through to send to the superclass in CDecl. + } else { + // "super" may be the name of a type or variable. Figure out which + // it is. + IdentifierInfo *Super = &Context.Idents.get("super"); + NamedDecl *ND = LookupSingleName(S, Super, SuperLoc, + LookupOrdinaryName); + if ((CDecl = dyn_cast_or_null(ND))) { + // "super" names an interface. Use it. + } else if (TypeDecl *TD = dyn_cast_or_null(ND)) { + if (const ObjCObjectType *Iface + = Context.getTypeDeclType(TD)->getAs()) + CDecl = Iface->getInterface(); + } else if (ND && isa(ND)) { + // "super" names an unresolved type; we can't be more specific. + } else { + // Assume that "super" names some kind of value and parse that way. + CXXScopeSpec SS; + SourceLocation TemplateKWLoc; + UnqualifiedId id; + id.setIdentifier(Super, SuperLoc); + ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id, + false, false); + return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(), + SelIdents, NumSelIdents, + AtArgumentExpression); + } + + // Fall through + } + + ParsedType Receiver; + if (CDecl) + Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl)); + return CodeCompleteObjCClassMessage(S, Receiver, SelIdents, + NumSelIdents, AtArgumentExpression, + /*IsSuper=*/true); +} + +/// \brief Given a set of code-completion results for the argument of a message +/// send, determine the preferred type (if any) for that argument expression. +static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results, + unsigned NumSelIdents) { + typedef CodeCompletionResult Result; + ASTContext &Context = Results.getSema().Context; + + QualType PreferredType; + unsigned BestPriority = CCP_Unlikely * 2; + Result *ResultsData = Results.data(); + for (unsigned I = 0, N = Results.size(); I != N; ++I) { + Result &R = ResultsData[I]; + if (R.Kind == Result::RK_Declaration && + isa(R.Declaration)) { + if (R.Priority <= BestPriority) { + ObjCMethodDecl *Method = cast(R.Declaration); + if (NumSelIdents <= Method->param_size()) { + QualType MyPreferredType = Method->param_begin()[NumSelIdents - 1] + ->getType(); + if (R.Priority < BestPriority || PreferredType.isNull()) { + BestPriority = R.Priority; + PreferredType = MyPreferredType; + } else if (!Context.hasSameUnqualifiedType(PreferredType, + MyPreferredType)) { + PreferredType = QualType(); + } + } + } + } + } + + return PreferredType; +} + +static void AddClassMessageCompletions(Sema &SemaRef, Scope *S, + ParsedType Receiver, + IdentifierInfo **SelIdents, + unsigned NumSelIdents, + bool AtArgumentExpression, + bool IsSuper, + ResultBuilder &Results) { + typedef CodeCompletionResult Result; + ObjCInterfaceDecl *CDecl = 0; + + // If the given name refers to an interface type, retrieve the + // corresponding declaration. + if (Receiver) { + QualType T = SemaRef.GetTypeFromParser(Receiver, 0); + if (!T.isNull()) + if (const ObjCObjectType *Interface = T->getAs()) + CDecl = Interface->getInterface(); + } + + // Add all of the factory methods in this Objective-C class, its protocols, + // superclasses, categories, implementation, etc. + Results.EnterNewScope(); + + // If this is a send-to-super, try to add the special "super" send + // completion. + if (IsSuper) { + if (ObjCMethodDecl *SuperMethod + = AddSuperSendCompletion(SemaRef, false, SelIdents, NumSelIdents, + Results)) + Results.Ignore(SuperMethod); + } + + // If we're inside an Objective-C method definition, prefer its selector to + // others. + if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl()) + Results.setPreferredSelector(CurMethod->getSelector()); + + VisitedSelectorSet Selectors; + if (CDecl) + AddObjCMethods(CDecl, false, MK_Any, SelIdents, NumSelIdents, + SemaRef.CurContext, Selectors, AtArgumentExpression, + Results); + else { + // 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 AST file. + if (SemaRef.ExternalSource) { + for (uint32_t I = 0, + N = SemaRef.ExternalSource->GetNumExternalSelectors(); + I != N; ++I) { + Selector Sel = SemaRef.ExternalSource->GetExternalSelector(I); + if (Sel.isNull() || SemaRef.MethodPool.count(Sel)) + continue; + + SemaRef.ReadMethodPool(Sel); + } + } + + for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(), + MEnd = SemaRef.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)) + continue; + + Result R(MethList->Method, 0); + R.StartParameter = NumSelIdents; + R.AllParametersAreInformative = false; + Results.MaybeAddResult(R, SemaRef.CurContext); + } + } + } + + Results.ExitScope(); +} + +void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver, + IdentifierInfo **SelIdents, + unsigned NumSelIdents, + bool AtArgumentExpression, + bool IsSuper) { + + QualType T = this->GetTypeFromParser(Receiver); + + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage, + T, SelIdents, NumSelIdents)); + + AddClassMessageCompletions(*this, S, Receiver, SelIdents, NumSelIdents, + AtArgumentExpression, IsSuper, Results); + + // If we're actually at the argument expression (rather than prior to the + // selector), we're actually performing code completion for an expression. + // Determine whether we have a single, best method. If so, we can + // code-complete the expression using the corresponding parameter type as + // our preferred type, improving completion results. + if (AtArgumentExpression) { + QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results, + NumSelIdents); + if (PreferredType.isNull()) + CodeCompleteOrdinaryName(S, PCC_Expression); + else + CodeCompleteExpression(S, PreferredType); + return; + } + + HandleCodeCompleteResults(this, CodeCompleter, + Results.getCompletionContext(), + Results.data(), Results.size()); +} + +void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver, + IdentifierInfo **SelIdents, + unsigned NumSelIdents, + bool AtArgumentExpression, + ObjCInterfaceDecl *Super) { + typedef CodeCompletionResult Result; + + Expr *RecExpr = static_cast(Receiver); + + // If necessary, apply function/array conversion to the receiver. + // C99 6.7.5.3p[7,8]. + if (RecExpr) { + ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr); + if (Conv.isInvalid()) // conversion failed. bail. + return; + RecExpr = Conv.take(); + } + QualType ReceiverType = RecExpr? RecExpr->getType() + : Super? Context.getObjCObjectPointerType( + Context.getObjCInterfaceType(Super)) + : Context.getObjCIdType(); + + // 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. + if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType()) + if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) { + if (ReceiverType->isObjCClassType()) + return CodeCompleteObjCClassMessage(S, + ParsedType::make(Context.getObjCInterfaceType(IFace)), + SelIdents, NumSelIdents, + AtArgumentExpression, Super); + + ReceiverType = Context.getObjCObjectPointerType( + Context.getObjCInterfaceType(IFace)); + } + + // Build the set of methods we can see. + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage, + ReceiverType, SelIdents, NumSelIdents)); + + Results.EnterNewScope(); + + // If this is a send-to-super, try to add the special "super" send + // completion. + if (Super) { + 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()); + + // Keep track of the selectors we've already added. + VisitedSelectorSet Selectors; + + // Handle messages to Class. This really isn't a message to an instance + // method, so we treat it the same way we would treat a message send to a + // class method. + if (ReceiverType->isObjCClassType() || + ReceiverType->isObjCQualifiedClassType()) { + if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) { + if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface()) + AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, NumSelIdents, + CurContext, Selectors, AtArgumentExpression, Results); + } + } + // Handle messages to a qualified ID ("id"). + else if (const ObjCObjectPointerType *QualID + = ReceiverType->getAsObjCQualifiedIdType()) { + // Search protocols for instance methods. + for (ObjCObjectPointerType::qual_iterator I = QualID->qual_begin(), + E = QualID->qual_end(); + I != E; ++I) + AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext, + Selectors, AtArgumentExpression, Results); + } + // Handle messages to a pointer to interface type. + else if (const ObjCObjectPointerType *IFacePtr + = ReceiverType->getAsObjCInterfacePointerType()) { + // Search the class, its superclasses, etc., for instance methods. + AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents, + NumSelIdents, CurContext, Selectors, AtArgumentExpression, + Results); + + // Search protocols for instance methods. + for (ObjCObjectPointerType::qual_iterator I = IFacePtr->qual_begin(), + E = IFacePtr->qual_end(); + I != E; ++I) + AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext, + Selectors, AtArgumentExpression, Results); + } + // Handle messages to "id". + else if (ReceiverType->isObjCIdType()) { + // We're messaging "id", so provide all instance methods we know + // about as code-completion results. + + // 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); + } + } + + 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)) + continue; + + if (!Selectors.insert(MethList->Method->getSelector())) + continue; + + Result R(MethList->Method, 0); + R.StartParameter = NumSelIdents; + R.AllParametersAreInformative = false; + Results.MaybeAddResult(R, CurContext); + } + } + } + Results.ExitScope(); + + + // If we're actually at the argument expression (rather than prior to the + // selector), we're actually performing code completion for an expression. + // Determine whether we have a single, best method. If so, we can + // code-complete the expression using the corresponding parameter type as + // our preferred type, improving completion results. + if (AtArgumentExpression) { + QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results, + NumSelIdents); + if (PreferredType.isNull()) + CodeCompleteOrdinaryName(S, PCC_Expression); + else + CodeCompleteExpression(S, PreferredType); + return; + } + + HandleCodeCompleteResults(this, CodeCompleter, + Results.getCompletionContext(), + 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, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_SelectorName); + 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; + + CodeCompletionBuilder Builder(Results.getAllocator(), + Results.getCodeCompletionTUInfo()); + if (Sel.isUnarySelector()) { + Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( + Sel.getNameForSlot(0))); + Results.AddResult(Builder.TakeString()); + continue; + } + + std::string Accumulator; + for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) { + if (I == NumSelIdents) { + if (!Accumulator.empty()) { + Builder.AddInformativeChunk(Builder.getAllocator().CopyString( + Accumulator)); + Accumulator.clear(); + } + } + + Accumulator += Sel.getNameForSlot(I); + Accumulator += ':'; + } + Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Accumulator)); + Results.AddResult(Builder.TakeString()); + } + 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 +/// (translation unit) context. +static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext, + bool OnlyForwardDeclarations, + ResultBuilder &Results) { + typedef CodeCompletionResult Result; + + for (DeclContext::decl_iterator D = Ctx->decls_begin(), + DEnd = Ctx->decls_end(); + D != DEnd; ++D) { + // Record any protocols we find. + if (ObjCProtocolDecl *Proto = dyn_cast(*D)) + if (!OnlyForwardDeclarations || !Proto->hasDefinition()) + Results.AddResult(Result(Proto, 0), CurContext, 0, false); + } +} + +void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols, + unsigned NumProtocols) { + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_ObjCProtocolName); + + if (CodeCompleter && CodeCompleter->includeGlobals()) { + Results.EnterNewScope(); + + // Tell the result set to ignore all of the protocols we have + // already seen. + // FIXME: This doesn't work when caching code-completion results. + for (unsigned I = 0; I != NumProtocols; ++I) + if (ObjCProtocolDecl *Protocol = LookupProtocol(Protocols[I].first, + Protocols[I].second)) + Results.Ignore(Protocol); + + // Add all protocols. + AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false, + Results); + + Results.ExitScope(); + } + + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_ObjCProtocolName, + Results.data(),Results.size()); +} + +void Sema::CodeCompleteObjCProtocolDecl(Scope *) { + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_ObjCProtocolName); + + if (CodeCompleter && CodeCompleter->includeGlobals()) { + Results.EnterNewScope(); + + // Add all protocols. + AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true, + Results); + + Results.ExitScope(); + } + + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_ObjCProtocolName, + Results.data(),Results.size()); +} + +/// \brief Add all of the Objective-C interface declarations that we find in +/// the given (translation unit) context. +static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext, + bool OnlyForwardDeclarations, + bool OnlyUnimplemented, + ResultBuilder &Results) { + typedef CodeCompletionResult Result; + + for (DeclContext::decl_iterator D = Ctx->decls_begin(), + DEnd = Ctx->decls_end(); + D != DEnd; ++D) { + // Record any interfaces we find. + if (ObjCInterfaceDecl *Class = dyn_cast(*D)) + if ((!OnlyForwardDeclarations || !Class->hasDefinition()) && + (!OnlyUnimplemented || !Class->getImplementation())) + Results.AddResult(Result(Class, 0), CurContext, 0, false); + } +} + +void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) { + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_Other); + Results.EnterNewScope(); + + if (CodeCompleter->includeGlobals()) { + // Add all classes. + AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false, + false, Results); + } + + Results.ExitScope(); + + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_ObjCInterfaceName, + Results.data(),Results.size()); +} + +void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName, + SourceLocation ClassNameLoc) { + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_ObjCInterfaceName); + Results.EnterNewScope(); + + // Make sure that we ignore the class we're currently defining. + NamedDecl *CurClass + = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName); + if (CurClass && isa(CurClass)) + Results.Ignore(CurClass); + + if (CodeCompleter->includeGlobals()) { + // Add all classes. + AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false, + false, Results); + } + + Results.ExitScope(); + + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_ObjCInterfaceName, + Results.data(),Results.size()); +} + +void Sema::CodeCompleteObjCImplementationDecl(Scope *S) { + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_Other); + Results.EnterNewScope(); + + if (CodeCompleter->includeGlobals()) { + // Add all unimplemented classes. + AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false, + true, Results); + } + + Results.ExitScope(); + + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_ObjCInterfaceName, + Results.data(),Results.size()); +} + +void Sema::CodeCompleteObjCInterfaceCategory(Scope *S, + IdentifierInfo *ClassName, + SourceLocation ClassNameLoc) { + typedef CodeCompletionResult Result; + + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_ObjCCategoryName); + + // Ignore any categories we find that have already been implemented by this + // interface. + llvm::SmallPtrSet CategoryNames; + NamedDecl *CurClass + = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName); + if (ObjCInterfaceDecl *Class = dyn_cast_or_null(CurClass)) + for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category; + Category = Category->getNextClassCategory()) + CategoryNames.insert(Category->getIdentifier()); + + // Add all of the categories we know about. + Results.EnterNewScope(); + TranslationUnitDecl *TU = Context.getTranslationUnitDecl(); + for (DeclContext::decl_iterator D = TU->decls_begin(), + DEnd = TU->decls_end(); + D != DEnd; ++D) + if (ObjCCategoryDecl *Category = dyn_cast(*D)) + if (CategoryNames.insert(Category->getIdentifier())) + Results.AddResult(Result(Category, 0), CurContext, 0, false); + Results.ExitScope(); + + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_ObjCCategoryName, + Results.data(),Results.size()); +} + +void Sema::CodeCompleteObjCImplementationCategory(Scope *S, + IdentifierInfo *ClassName, + SourceLocation ClassNameLoc) { + 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 + // providing the list of all of the categories we know about. + NamedDecl *CurClass + = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName); + ObjCInterfaceDecl *Class = dyn_cast_or_null(CurClass); + if (!Class) + return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc); + + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_ObjCCategoryName); + + // Add all of the categories that have have corresponding interface + // declarations in this class and any of its superclasses, except for + // already-implemented categories in the class itself. + llvm::SmallPtrSet CategoryNames; + Results.EnterNewScope(); + bool IgnoreImplemented = true; + while (Class) { + for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category; + Category = Category->getNextClassCategory()) + if ((!IgnoreImplemented || !Category->getImplementation()) && + CategoryNames.insert(Category->getIdentifier())) + Results.AddResult(Result(Category, 0), CurContext, 0, false); + + Class = Class->getSuperClass(); + IgnoreImplemented = false; + } + Results.ExitScope(); + + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_ObjCCategoryName, + Results.data(),Results.size()); +} + +void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) { + typedef CodeCompletionResult Result; + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_Other); + + // Figure out where this @synthesize lives. + ObjCContainerDecl *Container + = dyn_cast_or_null(CurContext); + if (!Container || + (!isa(Container) && + !isa(Container))) + return; + + // Ignore any properties that have already been implemented. + for (DeclContext::decl_iterator D = Container->decls_begin(), + DEnd = Container->decls_end(); + D != DEnd; ++D) + if (ObjCPropertyImplDecl *PropertyImpl = dyn_cast(*D)) + Results.Ignore(PropertyImpl->getPropertyDecl()); + + // Add any properties that we find. + AddedPropertiesSet AddedProperties; + Results.EnterNewScope(); + if (ObjCImplementationDecl *ClassImpl + = dyn_cast(Container)) + AddObjCProperties(ClassImpl->getClassInterface(), false, + /*AllowNullaryMethods=*/false, CurContext, + AddedProperties, Results); + else + AddObjCProperties(cast(Container)->getCategoryDecl(), + false, /*AllowNullaryMethods=*/false, CurContext, + AddedProperties, Results); + Results.ExitScope(); + + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); +} + +void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S, + IdentifierInfo *PropertyName) { + typedef CodeCompletionResult Result; + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_Other); + + // Figure out where this @synthesize lives. + ObjCContainerDecl *Container + = dyn_cast_or_null(CurContext); + if (!Container || + (!isa(Container) && + !isa(Container))) + return; + + // Figure out which interface we're looking into. + ObjCInterfaceDecl *Class = 0; + if (ObjCImplementationDecl *ClassImpl + = dyn_cast(Container)) + Class = ClassImpl->getClassInterface(); + else + Class = cast(Container)->getCategoryDecl() + ->getClassInterface(); + + // Determine the type of the property we're synthesizing. + QualType PropertyType = Context.getObjCIdType(); + if (Class) { + if (ObjCPropertyDecl *Property + = Class->FindPropertyDeclaration(PropertyName)) { + PropertyType + = Property->getType().getNonReferenceType().getUnqualifiedType(); + + // Give preference to ivars + Results.setPreferredType(PropertyType); + } + } + + // Add all of the instance variables in this class and its superclasses. + Results.EnterNewScope(); + bool SawSimilarlyNamedIvar = false; + std::string NameWithPrefix; + NameWithPrefix += '_'; + NameWithPrefix += PropertyName->getName(); + std::string NameWithSuffix = PropertyName->getName().str(); + NameWithSuffix += '_'; + for(; Class; Class = Class->getSuperClass()) { + for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar; + Ivar = Ivar->getNextIvar()) { + Results.AddResult(Result(Ivar, 0), CurContext, 0, false); + + // Determine whether we've seen an ivar with a name similar to the + // property. + if ((PropertyName == Ivar->getIdentifier() || + NameWithPrefix == Ivar->getName() || + NameWithSuffix == Ivar->getName())) { + SawSimilarlyNamedIvar = true; + + // Reduce the priority of this result by one, to give it a slight + // advantage over other results whose names don't match so closely. + if (Results.size() && + Results.data()[Results.size() - 1].Kind + == CodeCompletionResult::RK_Declaration && + Results.data()[Results.size() - 1].Declaration == Ivar) + Results.data()[Results.size() - 1].Priority--; + } + } + } + + if (!SawSimilarlyNamedIvar) { + // Create ivar result _propName, that the user can use to synthesize + // an ivar of the appropriate type. + unsigned Priority = CCP_MemberDeclaration + 1; + typedef CodeCompletionResult Result; + CodeCompletionAllocator &Allocator = Results.getAllocator(); + CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(), + Priority,CXAvailability_Available); + + PrintingPolicy Policy = getCompletionPrintingPolicy(*this); + Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context, + Policy, Allocator)); + Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix)); + Results.AddResult(Result(Builder.TakeString(), Priority, + CXCursor_ObjCIvarDecl)); + } + + Results.ExitScope(); + + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); +} + +// 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 +/// criteria. Insert those methods into the map of known methods, +/// indexed by selector so they can be easily found. +static void FindImplementableMethods(ASTContext &Context, + ObjCContainerDecl *Container, + bool WantInstanceMethods, + QualType ReturnType, + KnownMethodsMap &KnownMethods, + bool InOriginalClass = true) { + if (ObjCInterfaceDecl *IFace = dyn_cast(Container)) { + // Recurse into protocols. + if (!IFace->hasDefinition()) + return; + + const ObjCList &Protocols + = IFace->getReferencedProtocols(); + for (ObjCList::iterator I = Protocols.begin(), + E = Protocols.end(); + I != E; ++I) + FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType, + KnownMethods, InOriginalClass); + + // Add methods from any class extensions and categories. + for (const ObjCCategoryDecl *Cat = IFace->getCategoryList(); Cat; + Cat = Cat->getNextClassCategory()) + FindImplementableMethods(Context, const_cast(Cat), + WantInstanceMethods, ReturnType, + KnownMethods, false); + + // Visit the superclass. + if (IFace->getSuperClass()) + FindImplementableMethods(Context, IFace->getSuperClass(), + WantInstanceMethods, ReturnType, + KnownMethods, false); + } + + if (ObjCCategoryDecl *Category = dyn_cast(Container)) { + // Recurse into protocols. + const ObjCList &Protocols + = Category->getReferencedProtocols(); + for (ObjCList::iterator I = Protocols.begin(), + E = Protocols.end(); + I != E; ++I) + FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType, + KnownMethods, InOriginalClass); + + // If this category is the original class, jump to the interface. + if (InOriginalClass && Category->getClassInterface()) + FindImplementableMethods(Context, Category->getClassInterface(), + WantInstanceMethods, ReturnType, KnownMethods, + false); + } + + if (ObjCProtocolDecl *Protocol = dyn_cast(Container)) { + if (Protocol->hasDefinition()) { + // Recurse into protocols. + const ObjCList &Protocols + = Protocol->getReferencedProtocols(); + for (ObjCList::iterator I = Protocols.begin(), + E = Protocols.end(); + I != E; ++I) + FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType, + KnownMethods, false); + } + } + + // Add methods in this container. This operation occurs last because + // we want the methods from this container to override any methods + // we've previously seen with the same selector. + for (ObjCContainerDecl::method_iterator M = Container->meth_begin(), + MEnd = Container->meth_end(); + M != MEnd; ++M) { + if ((*M)->isInstanceMethod() == WantInstanceMethods) { + if (!ReturnType.isNull() && + !Context.hasSameUnqualifiedType(ReturnType, (*M)->getResultType())) + continue; + + KnownMethods[(*M)->getSelector()] = std::make_pair(*M, InOriginalClass); + } + } +} + +/// \brief Add the parenthesized return or parameter type chunk to a code +/// completion string. +static void AddObjCPassingTypeChunk(QualType Type, + unsigned ObjCDeclQuals, + ASTContext &Context, + const PrintingPolicy &Policy, + CodeCompletionBuilder &Builder) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals); + if (!Quals.empty()) + Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals)); + Builder.AddTextChunk(GetCompletionTypeString(Type, Context, Policy, + Builder.getAllocator())); + Builder.AddChunk(CodeCompletionString::CK_RightParen); +} + +/// \brief Determine whether the given class is or inherits from a class by +/// the given name. +static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class, + StringRef Name) { + if (!Class) + return false; + + if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name) + return true; + + return InheritsFromClassNamed(Class->getSuperClass(), Name); +} + +/// \brief Add code completions for Objective-C Key-Value Coding (KVC) and +/// Key-Value Observing (KVO). +static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, + bool IsInstanceMethod, + QualType ReturnType, + ASTContext &Context, + VisitedSelectorSet &KnownSelectors, + ResultBuilder &Results) { + IdentifierInfo *PropName = Property->getIdentifier(); + if (!PropName || PropName->getLength() == 0) + return; + + PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema()); + + // Builder that will create each code completion. + typedef CodeCompletionResult Result; + CodeCompletionAllocator &Allocator = Results.getAllocator(); + CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo()); + + // The selector table. + SelectorTable &Selectors = Context.Selectors; + + // The property name, copied into the code completion allocation region + // on demand. + struct KeyHolder { + CodeCompletionAllocator &Allocator; + StringRef Key; + const char *CopiedKey; + + KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key) + : Allocator(Allocator), Key(Key), CopiedKey(0) { } + + operator const char *() { + if (CopiedKey) + return CopiedKey; + + return CopiedKey = Allocator.CopyString(Key); + } + } Key(Allocator, PropName->getName()); + + // The uppercased name of the property name. + std::string UpperKey = PropName->getName(); + if (!UpperKey.empty()) + UpperKey[0] = toupper(UpperKey[0]); + + bool ReturnTypeMatchesProperty = ReturnType.isNull() || + Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(), + Property->getType()); + bool ReturnTypeMatchesVoid + = ReturnType.isNull() || ReturnType->isVoidType(); + + // Add the normal accessor -(type)key. + if (IsInstanceMethod && + KnownSelectors.insert(Selectors.getNullarySelector(PropName)) && + ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) { + if (ReturnType.isNull()) + AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, + Context, Policy, Builder); + + Builder.AddTypedTextChunk(Key); + Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, + CXCursor_ObjCInstanceMethodDecl)); + } + + // If we have an integral or boolean property (or the user has provided + // an integral or boolean return type), add the accessor -(type)isKey. + if (IsInstanceMethod && + ((!ReturnType.isNull() && + (ReturnType->isIntegerType() || ReturnType->isBooleanType())) || + (ReturnType.isNull() && + (Property->getType()->isIntegerType() || + Property->getType()->isBooleanType())))) { + std::string SelectorName = (Twine("is") + UpperKey).str(); + IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); + if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) { + if (ReturnType.isNull()) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("BOOL"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + } + + Builder.AddTypedTextChunk( + Allocator.CopyString(SelectorId->getName())); + Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, + CXCursor_ObjCInstanceMethodDecl)); + } + } + + // Add the normal mutator. + if (IsInstanceMethod && ReturnTypeMatchesVoid && + !Property->getSetterMethodDecl()) { + std::string SelectorName = (Twine("set") + UpperKey).str(); + IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); + if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) { + if (ReturnType.isNull()) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("void"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + } + + Builder.AddTypedTextChunk( + Allocator.CopyString(SelectorId->getName())); + Builder.AddTypedTextChunk(":"); + AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, + Context, Policy, Builder); + Builder.AddTextChunk(Key); + Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, + CXCursor_ObjCInstanceMethodDecl)); + } + } + + // Indexed and unordered accessors + unsigned IndexedGetterPriority = CCP_CodePattern; + unsigned IndexedSetterPriority = CCP_CodePattern; + unsigned UnorderedGetterPriority = CCP_CodePattern; + unsigned UnorderedSetterPriority = CCP_CodePattern; + if (const ObjCObjectPointerType *ObjCPointer + = Property->getType()->getAs()) { + if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) { + // If this interface type is not provably derived from a known + // collection, penalize the corresponding completions. + if (!InheritsFromClassNamed(IFace, "NSMutableArray")) { + IndexedSetterPriority += CCD_ProbablyNotObjCCollection; + if (!InheritsFromClassNamed(IFace, "NSArray")) + IndexedGetterPriority += CCD_ProbablyNotObjCCollection; + } + + if (!InheritsFromClassNamed(IFace, "NSMutableSet")) { + UnorderedSetterPriority += CCD_ProbablyNotObjCCollection; + if (!InheritsFromClassNamed(IFace, "NSSet")) + UnorderedGetterPriority += CCD_ProbablyNotObjCCollection; + } + } + } else { + IndexedGetterPriority += CCD_ProbablyNotObjCCollection; + IndexedSetterPriority += CCD_ProbablyNotObjCCollection; + UnorderedGetterPriority += CCD_ProbablyNotObjCCollection; + UnorderedSetterPriority += CCD_ProbablyNotObjCCollection; + } + + // Add -(NSUInteger)countOf + if (IsInstanceMethod && + (ReturnType.isNull() || ReturnType->isIntegerType())) { + std::string SelectorName = (Twine("countOf") + UpperKey).str(); + IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); + if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) { + if (ReturnType.isNull()) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("NSUInteger"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + } + + Builder.AddTypedTextChunk( + Allocator.CopyString(SelectorId->getName())); + Results.AddResult(Result(Builder.TakeString(), + std::min(IndexedGetterPriority, + UnorderedGetterPriority), + CXCursor_ObjCInstanceMethodDecl)); + } + } + + // Indexed getters + // Add -(id)objectInKeyAtIndex:(NSUInteger)index + if (IsInstanceMethod && + (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) { + std::string SelectorName + = (Twine("objectIn") + UpperKey + "AtIndex").str(); + IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); + if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) { + if (ReturnType.isNull()) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("id"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + } + + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("NSUInteger"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddTextChunk("index"); + Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority, + CXCursor_ObjCInstanceMethodDecl)); + } + } + + // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes + if (IsInstanceMethod && + (ReturnType.isNull() || + (ReturnType->isObjCObjectPointerType() && + ReturnType->getAs()->getInterfaceDecl() && + ReturnType->getAs()->getInterfaceDecl() + ->getName() == "NSArray"))) { + std::string SelectorName + = (Twine(Property->getName()) + "AtIndexes").str(); + IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); + if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) { + if (ReturnType.isNull()) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("NSArray *"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + } + + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("NSIndexSet *"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddTextChunk("indexes"); + Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority, + CXCursor_ObjCInstanceMethodDecl)); + } + } + + // Add -(void)getKey:(type **)buffer range:(NSRange)inRange + if (IsInstanceMethod && ReturnTypeMatchesVoid) { + std::string SelectorName = (Twine("get") + UpperKey).str(); + IdentifierInfo *SelectorIds[2] = { + &Context.Idents.get(SelectorName), + &Context.Idents.get("range") + }; + + if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) { + if (ReturnType.isNull()) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("void"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + } + + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("object-type"); + Builder.AddTextChunk(" **"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddTextChunk("buffer"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddTypedTextChunk("range:"); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("NSRange"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddTextChunk("inRange"); + Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority, + CXCursor_ObjCInstanceMethodDecl)); + } + } + + // Mutable indexed accessors + + // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index + if (IsInstanceMethod && ReturnTypeMatchesVoid) { + std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str(); + IdentifierInfo *SelectorIds[2] = { + &Context.Idents.get("insertObject"), + &Context.Idents.get(SelectorName) + }; + + if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) { + if (ReturnType.isNull()) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("void"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + } + + Builder.AddTypedTextChunk("insertObject:"); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("object-type"); + Builder.AddTextChunk(" *"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddTextChunk("object"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("NSUInteger"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddTextChunk("index"); + Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority, + CXCursor_ObjCInstanceMethodDecl)); + } + } + + // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes + if (IsInstanceMethod && ReturnTypeMatchesVoid) { + std::string SelectorName = (Twine("insert") + UpperKey).str(); + IdentifierInfo *SelectorIds[2] = { + &Context.Idents.get(SelectorName), + &Context.Idents.get("atIndexes") + }; + + if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) { + if (ReturnType.isNull()) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("void"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + } + + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("NSArray *"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddTextChunk("array"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddTypedTextChunk("atIndexes:"); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("NSIndexSet *"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddTextChunk("indexes"); + Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority, + CXCursor_ObjCInstanceMethodDecl)); + } + } + + // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index + if (IsInstanceMethod && ReturnTypeMatchesVoid) { + std::string SelectorName + = (Twine("removeObjectFrom") + UpperKey + "AtIndex").str(); + IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); + if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) { + if (ReturnType.isNull()) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("void"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + } + + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("NSUInteger"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddTextChunk("index"); + Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority, + CXCursor_ObjCInstanceMethodDecl)); + } + } + + // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes + if (IsInstanceMethod && ReturnTypeMatchesVoid) { + std::string SelectorName + = (Twine("remove") + UpperKey + "AtIndexes").str(); + IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); + if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) { + if (ReturnType.isNull()) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("void"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + } + + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("NSIndexSet *"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddTextChunk("indexes"); + Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority, + CXCursor_ObjCInstanceMethodDecl)); + } + } + + // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object + if (IsInstanceMethod && ReturnTypeMatchesVoid) { + std::string SelectorName + = (Twine("replaceObjectIn") + UpperKey + "AtIndex").str(); + IdentifierInfo *SelectorIds[2] = { + &Context.Idents.get(SelectorName), + &Context.Idents.get("withObject") + }; + + if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) { + if (ReturnType.isNull()) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("void"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + } + + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("NSUInteger"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddTextChunk("index"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddTypedTextChunk("withObject:"); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("id"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddTextChunk("object"); + Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority, + CXCursor_ObjCInstanceMethodDecl)); + } + } + + // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array + if (IsInstanceMethod && ReturnTypeMatchesVoid) { + std::string SelectorName1 + = (Twine("replace") + UpperKey + "AtIndexes").str(); + std::string SelectorName2 = (Twine("with") + UpperKey).str(); + IdentifierInfo *SelectorIds[2] = { + &Context.Idents.get(SelectorName1), + &Context.Idents.get(SelectorName2) + }; + + if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) { + if (ReturnType.isNull()) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("void"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + } + + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":")); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("NSIndexSet *"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddTextChunk("indexes"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":")); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("NSArray *"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddTextChunk("array"); + Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority, + CXCursor_ObjCInstanceMethodDecl)); + } + } + + // Unordered getters + // - (NSEnumerator *)enumeratorOfKey + if (IsInstanceMethod && + (ReturnType.isNull() || + (ReturnType->isObjCObjectPointerType() && + ReturnType->getAs()->getInterfaceDecl() && + ReturnType->getAs()->getInterfaceDecl() + ->getName() == "NSEnumerator"))) { + std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str(); + IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); + if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) { + if (ReturnType.isNull()) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("NSEnumerator *"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + } + + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName)); + Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority, + CXCursor_ObjCInstanceMethodDecl)); + } + } + + // - (type *)memberOfKey:(type *)object + if (IsInstanceMethod && + (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) { + std::string SelectorName = (Twine("memberOf") + UpperKey).str(); + IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); + if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) { + if (ReturnType.isNull()) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("object-type"); + Builder.AddTextChunk(" *"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + } + + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + if (ReturnType.isNull()) { + Builder.AddPlaceholderChunk("object-type"); + Builder.AddTextChunk(" *"); + } else { + Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context, + Policy, + Builder.getAllocator())); + } + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddTextChunk("object"); + Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority, + CXCursor_ObjCInstanceMethodDecl)); + } + } + + // Mutable unordered accessors + // - (void)addKeyObject:(type *)object + if (IsInstanceMethod && ReturnTypeMatchesVoid) { + std::string SelectorName + = (Twine("add") + UpperKey + Twine("Object")).str(); + IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); + if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) { + if (ReturnType.isNull()) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("void"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + } + + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("object-type"); + Builder.AddTextChunk(" *"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddTextChunk("object"); + Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority, + CXCursor_ObjCInstanceMethodDecl)); + } + } + + // - (void)addKey:(NSSet *)objects + if (IsInstanceMethod && ReturnTypeMatchesVoid) { + std::string SelectorName = (Twine("add") + UpperKey).str(); + IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); + if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) { + if (ReturnType.isNull()) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("void"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + } + + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("NSSet *"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddTextChunk("objects"); + Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority, + CXCursor_ObjCInstanceMethodDecl)); + } + } + + // - (void)removeKeyObject:(type *)object + if (IsInstanceMethod && ReturnTypeMatchesVoid) { + std::string SelectorName + = (Twine("remove") + UpperKey + Twine("Object")).str(); + IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); + if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) { + if (ReturnType.isNull()) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("void"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + } + + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("object-type"); + Builder.AddTextChunk(" *"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddTextChunk("object"); + Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority, + CXCursor_ObjCInstanceMethodDecl)); + } + } + + // - (void)removeKey:(NSSet *)objects + if (IsInstanceMethod && ReturnTypeMatchesVoid) { + std::string SelectorName = (Twine("remove") + UpperKey).str(); + IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); + if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) { + if (ReturnType.isNull()) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("void"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + } + + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("NSSet *"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddTextChunk("objects"); + Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority, + CXCursor_ObjCInstanceMethodDecl)); + } + } + + // - (void)intersectKey:(NSSet *)objects + if (IsInstanceMethod && ReturnTypeMatchesVoid) { + std::string SelectorName = (Twine("intersect") + UpperKey).str(); + IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); + if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) { + if (ReturnType.isNull()) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("void"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + } + + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("NSSet *"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddTextChunk("objects"); + Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority, + CXCursor_ObjCInstanceMethodDecl)); + } + } + + // Key-Value Observing + // + (NSSet *)keyPathsForValuesAffectingKey + if (!IsInstanceMethod && + (ReturnType.isNull() || + (ReturnType->isObjCObjectPointerType() && + ReturnType->getAs()->getInterfaceDecl() && + ReturnType->getAs()->getInterfaceDecl() + ->getName() == "NSSet"))) { + std::string SelectorName + = (Twine("keyPathsForValuesAffecting") + UpperKey).str(); + IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); + if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) { + if (ReturnType.isNull()) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("NSSet *"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + } + + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName)); + Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, + CXCursor_ObjCClassMethodDecl)); + } + } + + // + (BOOL)automaticallyNotifiesObserversForKey + if (!IsInstanceMethod && + (ReturnType.isNull() || + ReturnType->isIntegerType() || + ReturnType->isBooleanType())) { + std::string SelectorName + = (Twine("automaticallyNotifiesObserversOf") + UpperKey).str(); + IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); + if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) { + if (ReturnType.isNull()) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("BOOL"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + } + + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName)); + Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, + CXCursor_ObjCClassMethodDecl)); + } + } +} + +void Sema::CodeCompleteObjCMethodDecl(Scope *S, + bool IsInstanceMethod, + ParsedType ReturnTy) { + // Determine the return type of the method we're declaring, if + // provided. + QualType ReturnType = GetTypeFromParser(ReturnTy); + Decl *IDecl = 0; + if (CurContext->isObjCContainer()) { + ObjCContainerDecl *OCD = dyn_cast(CurContext); + IDecl = cast(OCD); + } + // Determine where we should start searching for methods. + ObjCContainerDecl *SearchDecl = 0; + bool IsInImplementation = false; + if (Decl *D = IDecl) { + if (ObjCImplementationDecl *Impl = dyn_cast(D)) { + SearchDecl = Impl->getClassInterface(); + IsInImplementation = true; + } else if (ObjCCategoryImplDecl *CatImpl + = dyn_cast(D)) { + SearchDecl = CatImpl->getCategoryDecl(); + IsInImplementation = true; + } else + SearchDecl = dyn_cast(D); + } + + if (!SearchDecl && S) { + if (DeclContext *DC = static_cast(S->getEntity())) + SearchDecl = dyn_cast(DC); + } + + if (!SearchDecl) { + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + 0, 0); + return; + } + + // Find all of the methods that we could declare/implement here. + KnownMethodsMap KnownMethods; + FindImplementableMethods(Context, SearchDecl, IsInstanceMethod, + ReturnType, KnownMethods); + + // Add declarations or definitions for each of the known methods. + typedef CodeCompletionResult Result; + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_Other); + Results.EnterNewScope(); + PrintingPolicy Policy = getCompletionPrintingPolicy(*this); + for (KnownMethodsMap::iterator M = KnownMethods.begin(), + MEnd = KnownMethods.end(); + M != MEnd; ++M) { + ObjCMethodDecl *Method = M->second.first; + CodeCompletionBuilder Builder(Results.getAllocator(), + Results.getCodeCompletionTUInfo()); + + // If the result type was not already provided, add it to the + // pattern as (type). + if (ReturnType.isNull()) + AddObjCPassingTypeChunk(Method->getResultType(), + Method->getObjCDeclQualifier(), + Context, Policy, + Builder); + + Selector Sel = Method->getSelector(); + + // Add the first part of the selector to the pattern. + Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( + Sel.getNameForSlot(0))); + + // Add parameters to the pattern. + unsigned I = 0; + for (ObjCMethodDecl::param_iterator P = Method->param_begin(), + PEnd = Method->param_end(); + P != PEnd; (void)++P, ++I) { + // Add the part of the selector name. + if (I == 0) + Builder.AddTypedTextChunk(":"); + else if (I < Sel.getNumArgs()) { + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddTypedTextChunk( + Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":")); + } else + break; + + // Add the parameter type. + AddObjCPassingTypeChunk((*P)->getOriginalType(), + (*P)->getObjCDeclQualifier(), + Context, Policy, + Builder); + + if (IdentifierInfo *Id = (*P)->getIdentifier()) + Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName())); + } + + if (Method->isVariadic()) { + if (Method->param_size() > 0) + Builder.AddChunk(CodeCompletionString::CK_Comma); + Builder.AddTextChunk("..."); + } + + if (IsInImplementation && Results.includeCodePatterns()) { + // We will be defining the method here, so add a compound statement. + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddChunk(CodeCompletionString::CK_LeftBrace); + Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); + if (!Method->getResultType()->isVoidType()) { + // If the result type is not void, add a return clause. + Builder.AddTextChunk("return"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("expression"); + Builder.AddChunk(CodeCompletionString::CK_SemiColon); + } else + Builder.AddPlaceholderChunk("statements"); + + Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); + Builder.AddChunk(CodeCompletionString::CK_RightBrace); + } + + unsigned Priority = CCP_CodePattern; + if (!M->second.second) + Priority += CCD_InBaseClass; + + Results.AddResult(Result(Builder.TakeString(), Method, Priority)); + } + + // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of + // the properties in this class and its categories. + if (Context.getLangOpts().ObjC2) { + SmallVector Containers; + Containers.push_back(SearchDecl); + + VisitedSelectorSet KnownSelectors; + for (KnownMethodsMap::iterator M = KnownMethods.begin(), + MEnd = KnownMethods.end(); + M != MEnd; ++M) + KnownSelectors.insert(M->first); + + + ObjCInterfaceDecl *IFace = dyn_cast(SearchDecl); + if (!IFace) + if (ObjCCategoryDecl *Category = dyn_cast(SearchDecl)) + IFace = Category->getClassInterface(); + + if (IFace) { + for (ObjCCategoryDecl *Category = IFace->getCategoryList(); Category; + Category = Category->getNextClassCategory()) + Containers.push_back(Category); + } + + for (unsigned I = 0, N = Containers.size(); I != N; ++I) { + for (ObjCContainerDecl::prop_iterator P = Containers[I]->prop_begin(), + PEnd = Containers[I]->prop_end(); + P != PEnd; ++P) { + AddObjCKeyValueCompletions(*P, IsInstanceMethod, ReturnType, Context, + KnownSelectors, Results); + } + } + } + + Results.ExitScope(); + + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); +} + +void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S, + bool IsInstanceMethod, + bool AtParameterName, + ParsedType ReturnTy, + 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); + } + } + + // Build the set of methods we can see. + typedef CodeCompletionResult Result; + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_Other); + + if (ReturnTy) + Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType()); + + Results.EnterNewScope(); + 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)) + continue; + + if (AtParameterName) { + // Suggest parameter names we've seen before. + if (NumSelIdents && NumSelIdents <= MethList->Method->param_size()) { + ParmVarDecl *Param = MethList->Method->param_begin()[NumSelIdents-1]; + if (Param->getIdentifier()) { + CodeCompletionBuilder Builder(Results.getAllocator(), + Results.getCodeCompletionTUInfo()); + Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( + Param->getIdentifier()->getName())); + Results.AddResult(Builder.TakeString()); + } + } + + continue; + } + + Result R(MethList->Method, 0); + R.StartParameter = NumSelIdents; + R.AllParametersAreInformative = false; + R.DeclaringEntity = true; + Results.MaybeAddResult(R, CurContext); + } + } + + Results.ExitScope(); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); +} + +void Sema::CodeCompletePreprocessorDirective(bool InConditional) { + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_PreprocessorDirective); + Results.EnterNewScope(); + + // #if + CodeCompletionBuilder Builder(Results.getAllocator(), + Results.getCodeCompletionTUInfo()); + Builder.AddTypedTextChunk("if"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("condition"); + Results.AddResult(Builder.TakeString()); + + // #ifdef + Builder.AddTypedTextChunk("ifdef"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("macro"); + Results.AddResult(Builder.TakeString()); + + // #ifndef + Builder.AddTypedTextChunk("ifndef"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("macro"); + Results.AddResult(Builder.TakeString()); + + if (InConditional) { + // #elif + Builder.AddTypedTextChunk("elif"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("condition"); + Results.AddResult(Builder.TakeString()); + + // #else + Builder.AddTypedTextChunk("else"); + Results.AddResult(Builder.TakeString()); + + // #endif + Builder.AddTypedTextChunk("endif"); + Results.AddResult(Builder.TakeString()); + } + + // #include "header" + Builder.AddTypedTextChunk("include"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddTextChunk("\""); + Builder.AddPlaceholderChunk("header"); + Builder.AddTextChunk("\""); + Results.AddResult(Builder.TakeString()); + + // #include
+ Builder.AddTypedTextChunk("include"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddTextChunk("<"); + Builder.AddPlaceholderChunk("header"); + Builder.AddTextChunk(">"); + Results.AddResult(Builder.TakeString()); + + // #define + Builder.AddTypedTextChunk("define"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("macro"); + Results.AddResult(Builder.TakeString()); + + // #define () + Builder.AddTypedTextChunk("define"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("macro"); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("args"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Builder.TakeString()); + + // #undef + Builder.AddTypedTextChunk("undef"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("macro"); + Results.AddResult(Builder.TakeString()); + + // #line + Builder.AddTypedTextChunk("line"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("number"); + Results.AddResult(Builder.TakeString()); + + // #line "filename" + Builder.AddTypedTextChunk("line"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("number"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddTextChunk("\""); + Builder.AddPlaceholderChunk("filename"); + Builder.AddTextChunk("\""); + Results.AddResult(Builder.TakeString()); + + // #error + Builder.AddTypedTextChunk("error"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("message"); + Results.AddResult(Builder.TakeString()); + + // #pragma + Builder.AddTypedTextChunk("pragma"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("arguments"); + Results.AddResult(Builder.TakeString()); + + if (getLangOpts().ObjC1) { + // #import "header" + Builder.AddTypedTextChunk("import"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddTextChunk("\""); + Builder.AddPlaceholderChunk("header"); + Builder.AddTextChunk("\""); + Results.AddResult(Builder.TakeString()); + + // #import
+ Builder.AddTypedTextChunk("import"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddTextChunk("<"); + Builder.AddPlaceholderChunk("header"); + Builder.AddTextChunk(">"); + Results.AddResult(Builder.TakeString()); + } + + // #include_next "header" + Builder.AddTypedTextChunk("include_next"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddTextChunk("\""); + Builder.AddPlaceholderChunk("header"); + Builder.AddTextChunk("\""); + Results.AddResult(Builder.TakeString()); + + // #include_next
+ Builder.AddTypedTextChunk("include_next"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddTextChunk("<"); + Builder.AddPlaceholderChunk("header"); + Builder.AddTextChunk(">"); + Results.AddResult(Builder.TakeString()); + + // #warning + Builder.AddTypedTextChunk("warning"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("message"); + Results.AddResult(Builder.TakeString()); + + // 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, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + IsDefinition? CodeCompletionContext::CCC_MacroName + : CodeCompletionContext::CCC_MacroNameUse); + if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) { + // Add just the names of macros, not their arguments. + CodeCompletionBuilder Builder(Results.getAllocator(), + Results.getCodeCompletionTUInfo()); + Results.EnterNewScope(); + for (Preprocessor::macro_iterator M = PP.macro_begin(), + MEnd = PP.macro_end(); + M != MEnd; ++M) { + Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( + M->first->getName())); + Results.AddResult(Builder.TakeString()); + } + Results.ExitScope(); + } else if (IsDefinition) { + // FIXME: Can we detect when the user just wrote an include guard above? + } + + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(), Results.size()); +} + +void Sema::CodeCompletePreprocessorExpression() { + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_PreprocessorExpression); + + if (!CodeCompleter || CodeCompleter->includeMacros()) + AddMacroResults(PP, Results); + + // defined () + Results.EnterNewScope(); + CodeCompletionBuilder Builder(Results.getAllocator(), + Results.getCodeCompletionTUInfo()); + Builder.AddTypedTextChunk("defined"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("macro"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Builder.TakeString()); + 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. + + // Now just ignore this. There will be another code-completion callback + // for the expanded tokens. +} + +void Sema::CodeCompleteNaturalLanguage() { + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_NaturalLanguage, + 0, 0); +} + +void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator, + CodeCompletionTUInfo &CCTUInfo, + SmallVectorImpl &Results) { + ResultBuilder Builder(*this, Allocator, CCTUInfo, + CodeCompletionContext::CCC_Recovery); + 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/clang/lib/Sema/SemaConsumer.cpp b/clang/lib/Sema/SemaConsumer.cpp new file mode 100644 index 0000000..d83a13e --- /dev/null +++ b/clang/lib/Sema/SemaConsumer.cpp @@ -0,0 +1,14 @@ +//===-- SemaConsumer.cpp - Abstract interface for AST semantics -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/SemaConsumer.h" + +using namespace clang; + +void SemaConsumer::anchor() { } diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp new file mode 100644 index 0000000..1227e92 --- /dev/null +++ b/clang/lib/Sema/SemaDecl.cpp @@ -0,0 +1,10462 @@ +//===--- SemaDecl.cpp - Semantic Analysis for Declarations ----------------===// +// +// 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 declarations. +// +//===----------------------------------------------------------------------===// + +#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 "TypeLocBuilder.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/EvaluatedExprVisitor.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/StmtCXX.h" +#include "clang/AST/CharUnits.h" +#include "clang/Sema/DeclSpec.h" +#include "clang/Sema/ParsedTemplate.h" +#include "clang/Parse/ParseDiagnostic.h" +#include "clang/Basic/PartialDiagnostic.h" +#include "clang/Sema/DelayedDiagnostic.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Basic/TargetInfo.h" +// FIXME: layering (ideally, Sema shouldn't be dependent on Lex API's) +#include "clang/Lex/Preprocessor.h" +#include "clang/Lex/HeaderSearch.h" +#include "clang/Lex/ModuleLoader.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Triple.h" +#include +#include +#include +using namespace clang; +using namespace sema; + +Sema::DeclGroupPtrTy Sema::ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType) { + if (OwnedType) { + Decl *Group[2] = { OwnedType, Ptr }; + return DeclGroupPtrTy::make(DeclGroupRef::Create(Context, Group, 2)); + } + + return DeclGroupPtrTy::make(DeclGroupRef(Ptr)); +} + +namespace { + +class TypeNameValidatorCCC : public CorrectionCandidateCallback { + public: + TypeNameValidatorCCC(bool AllowInvalid) : AllowInvalidDecl(AllowInvalid) { + WantExpressionKeywords = false; + WantCXXNamedCasts = false; + WantRemainingKeywords = false; + } + + virtual bool ValidateCandidate(const TypoCorrection &candidate) { + if (NamedDecl *ND = candidate.getCorrectionDecl()) + return (isa(ND) || isa(ND)) && + (AllowInvalidDecl || !ND->isInvalidDecl()); + else + return candidate.isKeyword(); + } + + private: + bool AllowInvalidDecl; +}; + +} + +/// \brief If the identifier refers to a type name within this scope, +/// return the declaration of that type. +/// +/// This routine performs ordinary name lookup of the identifier II +/// within the given scope, with optional C++ scope specifier SS, to +/// determine whether the name refers to a type. If so, returns an +/// opaque pointer (actually a QualType) corresponding to that +/// type. Otherwise, returns NULL. +/// +/// If name lookup results in an ambiguity, this routine will complain +/// and then return NULL. +ParsedType Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, + Scope *S, CXXScopeSpec *SS, + bool isClassName, bool HasTrailingDot, + ParsedType ObjectTypePtr, + bool IsCtorOrDtorName, + bool WantNontrivialTypeSourceInfo, + IdentifierInfo **CorrectedII) { + // Determine where we will perform name lookup. + DeclContext *LookupCtx = 0; + if (ObjectTypePtr) { + QualType ObjectType = ObjectTypePtr.get(); + if (ObjectType->isRecordType()) + LookupCtx = computeDeclContext(ObjectType); + } else if (SS && SS->isNotEmpty()) { + LookupCtx = computeDeclContext(*SS, false); + + if (!LookupCtx) { + if (isDependentScopeSpecifier(*SS)) { + // C++ [temp.res]p3: + // A qualified-id that refers to a type and in which the + // nested-name-specifier depends on a template-parameter (14.6.2) + // shall be prefixed by the keyword typename to indicate that the + // qualified-id denotes a type, forming an + // elaborated-type-specifier (7.1.5.3). + // + // We therefore do not perform any name lookup if the result would + // refer to a member of an unknown specialization. + if (!isClassName && !IsCtorOrDtorName) + return ParsedType(); + + // We know from the grammar that this name refers to a type, + // so build a dependent node to describe the type. + if (WantNontrivialTypeSourceInfo) + return ActOnTypenameType(S, SourceLocation(), *SS, II, NameLoc).get(); + + NestedNameSpecifierLoc QualifierLoc = SS->getWithLocInContext(Context); + QualType T = + CheckTypenameType(ETK_None, SourceLocation(), QualifierLoc, + II, NameLoc); + + return ParsedType::make(T); + } + + return ParsedType(); + } + + if (!LookupCtx->isDependentContext() && + RequireCompleteDeclContext(*SS, LookupCtx)) + return ParsedType(); + } + + // FIXME: LookupNestedNameSpecifierName isn't the right kind of + // lookup for class-names. + LookupNameKind Kind = isClassName ? LookupNestedNameSpecifierName : + LookupOrdinaryName; + LookupResult Result(*this, &II, NameLoc, Kind); + if (LookupCtx) { + // Perform "qualified" name lookup into the declaration context we + // computed, which is either the type of the base of a member access + // expression or the declaration context associated with a prior + // nested-name-specifier. + LookupQualifiedName(Result, LookupCtx); + + if (ObjectTypePtr && Result.empty()) { + // C++ [basic.lookup.classref]p3: + // If the unqualified-id is ~type-name, the type-name is looked up + // in the context of the entire postfix-expression. If the type T of + // the object expression is of a class type C, the type-name is also + // looked up in the scope of class C. At least one of the lookups shall + // find a name that refers to (possibly cv-qualified) T. + LookupName(Result, S); + } + } else { + // Perform unqualified name lookup. + LookupName(Result, S); + } + + NamedDecl *IIDecl = 0; + switch (Result.getResultKind()) { + case LookupResult::NotFound: + case LookupResult::NotFoundInCurrentInstantiation: + if (CorrectedII) { + TypeNameValidatorCCC Validator(true); + TypoCorrection Correction = CorrectTypo(Result.getLookupNameInfo(), + Kind, S, SS, Validator); + IdentifierInfo *NewII = Correction.getCorrectionAsIdentifierInfo(); + TemplateTy Template; + bool MemberOfUnknownSpecialization; + UnqualifiedId TemplateName; + TemplateName.setIdentifier(NewII, NameLoc); + NestedNameSpecifier *NNS = Correction.getCorrectionSpecifier(); + CXXScopeSpec NewSS, *NewSSPtr = SS; + if (SS && NNS) { + NewSS.MakeTrivial(Context, NNS, SourceRange(NameLoc)); + NewSSPtr = &NewSS; + } + if (Correction && (NNS || NewII != &II) && + // Ignore a correction to a template type as the to-be-corrected + // identifier is not a template (typo correction for template names + // is handled elsewhere). + !(getLangOpts().CPlusPlus && NewSSPtr && + isTemplateName(S, *NewSSPtr, false, TemplateName, ParsedType(), + false, Template, MemberOfUnknownSpecialization))) { + ParsedType Ty = getTypeName(*NewII, NameLoc, S, NewSSPtr, + isClassName, HasTrailingDot, ObjectTypePtr, + IsCtorOrDtorName, + WantNontrivialTypeSourceInfo); + if (Ty) { + std::string CorrectedStr(Correction.getAsString(getLangOpts())); + std::string CorrectedQuotedStr( + Correction.getQuoted(getLangOpts())); + Diag(NameLoc, diag::err_unknown_typename_suggest) + << Result.getLookupName() << CorrectedQuotedStr + << FixItHint::CreateReplacement(SourceRange(NameLoc), + CorrectedStr); + if (NamedDecl *FirstDecl = Correction.getCorrectionDecl()) + Diag(FirstDecl->getLocation(), diag::note_previous_decl) + << CorrectedQuotedStr; + + if (SS && NNS) + SS->MakeTrivial(Context, NNS, SourceRange(NameLoc)); + *CorrectedII = NewII; + return Ty; + } + } + } + // If typo correction failed or was not performed, fall through + case LookupResult::FoundOverloaded: + case LookupResult::FoundUnresolvedValue: + Result.suppressDiagnostics(); + return ParsedType(); + + case LookupResult::Ambiguous: + // Recover from type-hiding ambiguities by hiding the type. We'll + // do the lookup again when looking for an object, and we can + // diagnose the error then. If we don't do this, then the error + // about hiding the type will be immediately followed by an error + // that only makes sense if the identifier was treated like a type. + if (Result.getAmbiguityKind() == LookupResult::AmbiguousTagHiding) { + Result.suppressDiagnostics(); + return ParsedType(); + } + + // Look to see if we have a type anywhere in the list of results. + for (LookupResult::iterator Res = Result.begin(), ResEnd = Result.end(); + Res != ResEnd; ++Res) { + if (isa(*Res) || isa(*Res)) { + if (!IIDecl || + (*Res)->getLocation().getRawEncoding() < + IIDecl->getLocation().getRawEncoding()) + IIDecl = *Res; + } + } + + if (!IIDecl) { + // None of the entities we found is a type, so there is no way + // to even assume that the result is a type. In this case, don't + // complain about the ambiguity. The parser will either try to + // perform this lookup again (e.g., as an object name), which + // will produce the ambiguity, or will complain that it expected + // a type name. + Result.suppressDiagnostics(); + return ParsedType(); + } + + // We found a type within the ambiguous lookup; diagnose the + // ambiguity and then return that type. This might be the right + // answer, or it might not be, but it suppresses any attempt to + // perform the name lookup again. + break; + + case LookupResult::Found: + IIDecl = Result.getFoundDecl(); + break; + } + + assert(IIDecl && "Didn't find decl"); + + QualType T; + if (TypeDecl *TD = dyn_cast(IIDecl)) { + DiagnoseUseOfDecl(IIDecl, NameLoc); + + if (T.isNull()) + T = Context.getTypeDeclType(TD); + + // NOTE: avoid constructing an ElaboratedType(Loc) if this is a + // constructor or destructor name (in such a case, the scope specifier + // will be attached to the enclosing Expr or Decl node). + if (SS && SS->isNotEmpty() && !IsCtorOrDtorName) { + if (WantNontrivialTypeSourceInfo) { + // Construct a type with type-source information. + TypeLocBuilder Builder; + Builder.pushTypeSpec(T).setNameLoc(NameLoc); + + T = getElaboratedType(ETK_None, *SS, T); + ElaboratedTypeLoc ElabTL = Builder.push(T); + ElabTL.setElaboratedKeywordLoc(SourceLocation()); + ElabTL.setQualifierLoc(SS->getWithLocInContext(Context)); + return CreateParsedType(T, Builder.getTypeSourceInfo(Context, T)); + } else { + T = getElaboratedType(ETK_None, *SS, T); + } + } + } else if (ObjCInterfaceDecl *IDecl = dyn_cast(IIDecl)) { + (void)DiagnoseUseOfDecl(IDecl, NameLoc); + if (!HasTrailingDot) + T = Context.getObjCInterfaceType(IDecl); + } + + if (T.isNull()) { + // If it's not plausibly a type, suppress diagnostics. + Result.suppressDiagnostics(); + return ParsedType(); + } + return ParsedType::make(T); +} + +/// isTagName() - This method is called *for error recovery purposes only* +/// to determine if the specified name is a valid tag name ("struct foo"). If +/// so, this returns the TST for the tag corresponding to it (TST_enum, +/// TST_union, TST_struct, TST_class). This is used to diagnose cases in C +/// where the user forgot to specify the tag. +DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) { + // Do a tag name lookup in this scope. + LookupResult R(*this, &II, SourceLocation(), LookupTagName); + LookupName(R, S, false); + R.suppressDiagnostics(); + if (R.getResultKind() == LookupResult::Found) + if (const TagDecl *TD = R.getAsSingle()) { + switch (TD->getTagKind()) { + case TTK_Struct: return DeclSpec::TST_struct; + case TTK_Union: return DeclSpec::TST_union; + case TTK_Class: return DeclSpec::TST_class; + case TTK_Enum: return DeclSpec::TST_enum; + } + } + + return DeclSpec::TST_unspecified; +} + +/// isMicrosoftMissingTypename - In Microsoft mode, within class scope, +/// if a CXXScopeSpec's type is equal to the type of one of the base classes +/// then downgrade the missing typename error to a warning. +/// This is needed for MSVC compatibility; Example: +/// @code +/// template class A { +/// public: +/// typedef int TYPE; +/// }; +/// template class B : public A { +/// public: +/// A::TYPE a; // no typename required because A is a base class. +/// }; +/// @endcode +bool Sema::isMicrosoftMissingTypename(const CXXScopeSpec *SS, Scope *S) { + if (CurContext->isRecord()) { + const Type *Ty = SS->getScopeRep()->getAsType(); + + CXXRecordDecl *RD = cast(CurContext); + for (CXXRecordDecl::base_class_const_iterator Base = RD->bases_begin(), + BaseEnd = RD->bases_end(); Base != BaseEnd; ++Base) + if (Context.hasSameUnqualifiedType(QualType(Ty, 1), Base->getType())) + return true; + return S->isFunctionPrototypeScope(); + } + return CurContext->isFunctionOrMethod() || S->isFunctionPrototypeScope(); +} + +bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II, + SourceLocation IILoc, + Scope *S, + CXXScopeSpec *SS, + ParsedType &SuggestedType) { + // We don't have anything to suggest (yet). + 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. + TypeNameValidatorCCC Validator(false); + if (TypoCorrection Corrected = CorrectTypo(DeclarationNameInfo(&II, IILoc), + LookupOrdinaryName, S, SS, + Validator)) { + std::string CorrectedStr(Corrected.getAsString(getLangOpts())); + std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOpts())); + + if (Corrected.isKeyword()) { + // We corrected to a keyword. + // FIXME: Actually recover with the keyword we suggest, and emit a fix-it. + Diag(IILoc, diag::err_unknown_typename_suggest) + << &II << CorrectedQuotedStr; + } else { + NamedDecl *Result = Corrected.getCorrectionDecl(); + // We found a similarly-named type or interface; suggest that. + if (!SS || !SS->isSet()) + Diag(IILoc, diag::err_unknown_typename_suggest) + << &II << CorrectedQuotedStr + << FixItHint::CreateReplacement(SourceRange(IILoc), CorrectedStr); + else if (DeclContext *DC = computeDeclContext(*SS, false)) + Diag(IILoc, diag::err_unknown_nested_typename_suggest) + << &II << DC << CorrectedQuotedStr << SS->getRange() + << FixItHint::CreateReplacement(SourceRange(IILoc), CorrectedStr); + else + llvm_unreachable("could not have corrected a typo here"); + + Diag(Result->getLocation(), diag::note_previous_decl) + << CorrectedQuotedStr; + + SuggestedType = getTypeName(*Result->getIdentifier(), IILoc, S, SS, + false, false, ParsedType(), + /*IsCtorOrDtorName=*/false, + /*NonTrivialTypeSourceInfo=*/true); + } + return true; + } + + if (getLangOpts().CPlusPlus) { + // See if II is a class template that the user forgot to pass arguments to. + UnqualifiedId Name; + Name.setIdentifier(&II, IILoc); + CXXScopeSpec EmptySS; + TemplateTy TemplateResult; + bool MemberOfUnknownSpecialization; + 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; + if (TemplateDecl *TplDecl = TplName.getAsTemplateDecl()) { + Diag(TplDecl->getLocation(), diag::note_template_decl_here) + << TplDecl->getTemplateParameters()->getSourceRange(); + } + return true; + } + } + + // FIXME: Should we move the logic that tries to recover from a missing tag + // (struct, union, enum) from Parser::ParseImplicitInt here, instead? + + if (!SS || (!SS->isSet() && !SS->isInvalid())) + Diag(IILoc, diag::err_unknown_typename) << &II; + else if (DeclContext *DC = computeDeclContext(*SS, false)) + Diag(IILoc, diag::err_typename_nested_not_found) + << &II << DC << SS->getRange(); + else if (isDependentScopeSpecifier(*SS)) { + unsigned DiagID = diag::err_typename_missing; + if (getLangOpts().MicrosoftMode && isMicrosoftMissingTypename(SS, S)) + DiagID = diag::warn_typename_missing; + + Diag(SS->getRange().getBegin(), DiagID) + << (NestedNameSpecifier *)SS->getScopeRep() << II.getName() + << SourceRange(SS->getRange().getBegin(), IILoc) + << FixItHint::CreateInsertion(SS->getRange().getBegin(), "typename "); + SuggestedType = ActOnTypenameType(S, SourceLocation(), *SS, II, IILoc) + .get(); + } else { + assert(SS && SS->isInvalid() && + "Invalid scope specifier has already been diagnosed"); + } + + return true; +} + +/// \brief Determine whether the given result set contains either a type name +/// or +static bool isResultTypeOrTemplate(LookupResult &R, const Token &NextToken) { + bool CheckTemplate = R.getSema().getLangOpts().CPlusPlus && + NextToken.is(tok::less); + + for (LookupResult::iterator I = R.begin(), IEnd = R.end(); I != IEnd; ++I) { + if (isa(*I) || isa(*I)) + return true; + + if (CheckTemplate && isa(*I)) + return true; + } + + return false; +} + +Sema::NameClassification Sema::ClassifyName(Scope *S, + CXXScopeSpec &SS, + IdentifierInfo *&Name, + SourceLocation NameLoc, + const Token &NextToken) { + DeclarationNameInfo NameInfo(Name, NameLoc); + ObjCMethodDecl *CurMethod = getCurMethodDecl(); + + if (NextToken.is(tok::coloncolon)) { + BuildCXXNestedNameSpecifier(S, *Name, NameLoc, NextToken.getLocation(), + QualType(), false, SS, 0, false); + + } + + LookupResult Result(*this, Name, NameLoc, LookupOrdinaryName); + LookupParsedName(Result, S, &SS, !CurMethod); + + // Perform lookup for Objective-C instance variables (including automatically + // synthesized instance variables), if we're in an Objective-C method. + // FIXME: This lookup really, really needs to be folded in to the normal + // unqualified lookup mechanism. + if (!SS.isSet() && CurMethod && !isResultTypeOrTemplate(Result, NextToken)) { + ExprResult E = LookupInObjCMethod(Result, S, Name, true); + if (E.get() || E.isInvalid()) + return E; + } + + bool SecondTry = false; + bool IsFilteredTemplateName = false; + +Corrected: + switch (Result.getResultKind()) { + case LookupResult::NotFound: + // If an unqualified-id is followed by a '(', then we have a function + // call. + if (!SS.isSet() && NextToken.is(tok::l_paren)) { + // In C++, this is an ADL-only call. + // FIXME: Reference? + if (getLangOpts().CPlusPlus) + return BuildDeclarationNameExpr(SS, Result, /*ADL=*/true); + + // C90 6.3.2.2: + // If the expression that precedes the parenthesized argument list in a + // function call consists solely of an identifier, and if no + // declaration is visible for this identifier, the identifier is + // implicitly declared exactly as if, in the innermost block containing + // the function call, the declaration + // + // extern int identifier (); + // + // appeared. + // + // We also allow this in C99 as an extension. + if (NamedDecl *D = ImplicitlyDefineFunction(NameLoc, *Name, S)) { + Result.addDecl(D); + Result.resolveKind(); + return BuildDeclarationNameExpr(SS, Result, /*ADL=*/false); + } + } + + // In C, we first see whether there is a tag type by the same name, in + // which case it's likely that the user just forget to write "enum", + // "struct", or "union". + if (!getLangOpts().CPlusPlus && !SecondTry) { + Result.clear(LookupTagName); + LookupParsedName(Result, S, &SS); + if (TagDecl *Tag = Result.getAsSingle()) { + const char *TagName = 0; + const char *FixItTagName = 0; + switch (Tag->getTagKind()) { + case TTK_Class: + TagName = "class"; + FixItTagName = "class "; + break; + + case TTK_Enum: + TagName = "enum"; + FixItTagName = "enum "; + break; + + case TTK_Struct: + TagName = "struct"; + FixItTagName = "struct "; + break; + + case TTK_Union: + TagName = "union"; + FixItTagName = "union "; + break; + } + + Diag(NameLoc, diag::err_use_of_tag_name_without_tag) + << Name << TagName << getLangOpts().CPlusPlus + << FixItHint::CreateInsertion(NameLoc, FixItTagName); + break; + } + + Result.clear(LookupOrdinaryName); + } + + // Perform typo correction to determine if there is another name that is + // close to this name. + if (!SecondTry) { + SecondTry = true; + CorrectionCandidateCallback DefaultValidator; + if (TypoCorrection Corrected = CorrectTypo(Result.getLookupNameInfo(), + Result.getLookupKind(), S, + &SS, DefaultValidator)) { + unsigned UnqualifiedDiag = diag::err_undeclared_var_use_suggest; + unsigned QualifiedDiag = diag::err_no_member_suggest; + std::string CorrectedStr(Corrected.getAsString(getLangOpts())); + std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOpts())); + + NamedDecl *FirstDecl = Corrected.getCorrectionDecl(); + NamedDecl *UnderlyingFirstDecl + = FirstDecl? FirstDecl->getUnderlyingDecl() : 0; + if (getLangOpts().CPlusPlus && NextToken.is(tok::less) && + UnderlyingFirstDecl && isa(UnderlyingFirstDecl)) { + UnqualifiedDiag = diag::err_no_template_suggest; + QualifiedDiag = diag::err_no_member_template_suggest; + } else if (UnderlyingFirstDecl && + (isa(UnderlyingFirstDecl) || + isa(UnderlyingFirstDecl) || + isa(UnderlyingFirstDecl))) { + UnqualifiedDiag = diag::err_unknown_typename_suggest; + QualifiedDiag = diag::err_unknown_nested_typename_suggest; + } + + if (SS.isEmpty()) + Diag(NameLoc, UnqualifiedDiag) + << Name << CorrectedQuotedStr + << FixItHint::CreateReplacement(NameLoc, CorrectedStr); + else + Diag(NameLoc, QualifiedDiag) + << Name << computeDeclContext(SS, false) << CorrectedQuotedStr + << SS.getRange() + << FixItHint::CreateReplacement(NameLoc, CorrectedStr); + + // Update the name, so that the caller has the new name. + Name = Corrected.getCorrectionAsIdentifierInfo(); + + // Typo correction corrected to a keyword. + if (Corrected.isKeyword()) + return Corrected.getCorrectionAsIdentifierInfo(); + + // Also update the LookupResult... + // FIXME: This should probably go away at some point + Result.clear(); + Result.setLookupName(Corrected.getCorrection()); + if (FirstDecl) { + Result.addDecl(FirstDecl); + Diag(FirstDecl->getLocation(), diag::note_previous_decl) + << CorrectedQuotedStr; + } + + // If we found an Objective-C instance variable, let + // LookupInObjCMethod build the appropriate expression to + // reference the ivar. + // FIXME: This is a gross hack. + if (ObjCIvarDecl *Ivar = Result.getAsSingle()) { + Result.clear(); + ExprResult E(LookupInObjCMethod(Result, S, Ivar->getIdentifier())); + return move(E); + } + + goto Corrected; + } + } + + // We failed to correct; just fall through and let the parser deal with it. + Result.suppressDiagnostics(); + return NameClassification::Unknown(); + + case LookupResult::NotFoundInCurrentInstantiation: { + // We performed name lookup into the current instantiation, and there were + // dependent bases, so we treat this result the same way as any other + // dependent nested-name-specifier. + + // C++ [temp.res]p2: + // A name used in a template declaration or definition and that is + // dependent on a template-parameter is assumed not to name a type + // unless the applicable name lookup finds a type name or the name is + // qualified by the keyword typename. + // + // FIXME: If the next token is '<', we might want to ask the parser to + // perform some heroics to see if we actually have a + // template-argument-list, which would indicate a missing 'template' + // keyword here. + return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(), + NameInfo, /*TemplateArgs=*/0); + } + + case LookupResult::Found: + case LookupResult::FoundOverloaded: + case LookupResult::FoundUnresolvedValue: + break; + + case LookupResult::Ambiguous: + if (getLangOpts().CPlusPlus && NextToken.is(tok::less) && + hasAnyAcceptableTemplateNames(Result)) { + // C++ [temp.local]p3: + // A lookup that finds an injected-class-name (10.2) can result in an + // ambiguity in certain cases (for example, if it is found in more than + // one base class). If all of the injected-class-names that are found + // refer to specializations of the same class template, and if the name + // is followed by a template-argument-list, the reference refers to the + // class template itself and not a specialization thereof, and is not + // ambiguous. + // + // This filtering can make an ambiguous result into an unambiguous one, + // so try again after filtering out template names. + FilterAcceptableTemplateNames(Result); + if (!Result.isAmbiguous()) { + IsFilteredTemplateName = true; + break; + } + } + + // Diagnose the ambiguity and return an error. + return NameClassification::Error(); + } + + if (getLangOpts().CPlusPlus && NextToken.is(tok::less) && + (IsFilteredTemplateName || hasAnyAcceptableTemplateNames(Result))) { + // C++ [temp.names]p3: + // After name lookup (3.4) finds that a name is a template-name or that + // an operator-function-id or a literal- operator-id refers to a set of + // overloaded functions any member of which is a function template if + // this is followed by a <, the < is always taken as the delimiter of a + // template-argument-list and never as the less-than operator. + if (!IsFilteredTemplateName) + FilterAcceptableTemplateNames(Result); + + if (!Result.empty()) { + bool IsFunctionTemplate; + TemplateName Template; + if (Result.end() - Result.begin() > 1) { + IsFunctionTemplate = true; + Template = Context.getOverloadedTemplateName(Result.begin(), + Result.end()); + } else { + TemplateDecl *TD + = cast((*Result.begin())->getUnderlyingDecl()); + IsFunctionTemplate = isa(TD); + + if (SS.isSet() && !SS.isInvalid()) + Template = Context.getQualifiedTemplateName(SS.getScopeRep(), + /*TemplateKeyword=*/false, + TD); + else + Template = TemplateName(TD); + } + + if (IsFunctionTemplate) { + // Function templates always go through overload resolution, at which + // point we'll perform the various checks (e.g., accessibility) we need + // to based on which function we selected. + Result.suppressDiagnostics(); + + return NameClassification::FunctionTemplate(Template); + } + + return NameClassification::TypeTemplate(Template); + } + } + + NamedDecl *FirstDecl = (*Result.begin())->getUnderlyingDecl(); + if (TypeDecl *Type = dyn_cast(FirstDecl)) { + DiagnoseUseOfDecl(Type, NameLoc); + QualType T = Context.getTypeDeclType(Type); + return ParsedType::make(T); + } + + ObjCInterfaceDecl *Class = dyn_cast(FirstDecl); + if (!Class) { + // FIXME: It's unfortunate that we don't have a Type node for handling this. + if (ObjCCompatibleAliasDecl *Alias + = dyn_cast(FirstDecl)) + Class = Alias->getClassInterface(); + } + + if (Class) { + DiagnoseUseOfDecl(Class, NameLoc); + + if (NextToken.is(tok::period)) { + // Interface. is parsed as a property reference expression. + // Just return "unknown" as a fall-through for now. + Result.suppressDiagnostics(); + return NameClassification::Unknown(); + } + + QualType T = Context.getObjCInterfaceType(Class); + return ParsedType::make(T); + } + + if (!Result.empty() && (*Result.begin())->isCXXClassMember()) + return BuildPossibleImplicitMemberExpr(SS, SourceLocation(), Result, 0); + + bool ADL = UseArgumentDependentLookup(SS, Result, NextToken.is(tok::l_paren)); + return BuildDeclarationNameExpr(SS, Result, ADL); +} + +// Determines the context to return to after temporarily entering a +// context. This depends in an unnecessarily complicated way on the +// exact ordering of callbacks from the parser. +DeclContext *Sema::getContainingDC(DeclContext *DC) { + + // Functions defined inline within classes aren't parsed until we've + // finished parsing the top-level class, so the top-level class is + // the context we'll need to return to. + if (isa(DC)) { + DC = DC->getLexicalParent(); + + // A function not defined within a class will always return to its + // lexical context. + if (!isa(DC)) + return DC; + + // A C++ inline method/friend is parsed *after* the topmost class + // it was declared in is fully parsed ("complete"); the topmost + // class is the context we need to return to. + while (CXXRecordDecl *RD = dyn_cast(DC->getLexicalParent())) + DC = RD; + + // Return the declaration context of the topmost class the inline method is + // declared in. + return DC; + } + + return DC->getLexicalParent(); +} + +void Sema::PushDeclContext(Scope *S, DeclContext *DC) { + assert(getContainingDC(DC) == CurContext && + "The next DeclContext should be lexically contained in the current one."); + CurContext = DC; + S->setEntity(DC); +} + +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 +/// of a declarator's nested name specifier. +/// +void Sema::EnterDeclaratorContext(Scope *S, DeclContext *DC) { + // C++0x [basic.lookup.unqual]p13: + // A name used in the definition of a static data member of class + // X (after the qualified-id of the static member) is looked up as + // if the name was used in a member function of X. + // C++0x [basic.lookup.unqual]p14: + // If a variable member of a namespace is defined outside of the + // scope of its namespace then any name used in the definition of + // the variable member (after the declarator-id) is looked up as + // if the definition of the variable member occurred in its + // namespace. + // Both of these imply that we should push a scope whose context + // is the semantic context of the declaration. We can't use + // PushDeclContext here because that context is not necessarily + // lexically contained in the current context. Fortunately, + // the containing scope should have the appropriate information. + + assert(!S->getEntity() && "scope already has entity"); + +#ifndef NDEBUG + Scope *Ancestor = S->getParent(); + while (!Ancestor->getEntity()) Ancestor = Ancestor->getParent(); + assert(Ancestor->getEntity() == CurContext && "ancestor context mismatch"); +#endif + + CurContext = DC; + S->setEntity(DC); +} + +void Sema::ExitDeclaratorContext(Scope *S) { + assert(S->getEntity() == CurContext && "Context imbalance!"); + + // Switch back to the lexical context. The safety of this is + // enforced by an assert in EnterDeclaratorContext. + Scope *Ancestor = S->getParent(); + while (!Ancestor->getEntity()) Ancestor = Ancestor->getParent(); + CurContext = (DeclContext*) Ancestor->getEntity(); + + // We don't need to do anything with the scope, which is going to + // disappear. +} + + +void Sema::ActOnReenterFunctionContext(Scope* S, Decl *D) { + FunctionDecl *FD = dyn_cast(D); + if (FunctionTemplateDecl *TFD = dyn_cast_or_null(D)) { + // We assume that the caller has already called + // ActOnReenterTemplateScope + FD = TFD->getTemplatedDecl(); + } + if (!FD) + return; + + // Same implementation as PushDeclContext, but enters the context + // from the lexical parent, rather than the top-level class. + assert(CurContext == FD->getLexicalParent() && + "The next DeclContext should be lexically contained in the current one."); + CurContext = FD; + S->setEntity(CurContext); + + for (unsigned P = 0, NumParams = FD->getNumParams(); P < NumParams; ++P) { + ParmVarDecl *Param = FD->getParamDecl(P); + // If the parameter has an identifier, then add it to the scope + if (Param->getIdentifier()) { + S->AddDecl(Param); + IdResolver.AddDecl(Param); + } + } +} + + +void Sema::ActOnExitFunctionContext() { + // Same implementation as PopDeclContext, but returns to the lexical parent, + // rather than the top-level class. + assert(CurContext && "DeclContext imbalance!"); + CurContext = CurContext->getLexicalParent(); + assert(CurContext && "Popped translation unit!"); +} + + +/// \brief Determine whether we allow overloading of the function +/// PrevDecl with another declaration. +/// +/// This routine determines whether overloading is possible, not +/// whether some new function is actually an overload. It will return +/// true in C++ (where we can always provide overloads) or, as an +/// extension, in C when the previous function is already an +/// overloaded function declaration or has the "overloadable" +/// attribute. +static bool AllowOverloadingOfFunction(LookupResult &Previous, + ASTContext &Context) { + if (Context.getLangOpts().CPlusPlus) + return true; + + if (Previous.getResultKind() == LookupResult::FoundOverloaded) + return true; + + return (Previous.getResultKind() == LookupResult::Found + && Previous.getFoundDecl()->hasAttr()); +} + +/// Add this decl to the scope shadowed decl chains. +void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) { + // Move up the scope chain until we find the nearest enclosing + // non-transparent context. The declaration will be introduced into this + // scope. + while (S->getEntity() && + ((DeclContext *)S->getEntity())->isTransparentContext()) + S = S->getParent(); + + // Add scoped declarations into their context, so that they can be + // found later. Declarations without a context won't be inserted + // into any context. + if (AddToContext) + CurContext->addDecl(D); + + // Out-of-line definitions shouldn't be pushed into scope in C++. + // Out-of-line variable and function definitions shouldn't even in C. + if ((getLangOpts().CPlusPlus || isa(D) || isa(D)) && + D->isOutOfLine() && + !D->getDeclContext()->getRedeclContext()->Equals( + D->getLexicalDeclContext()->getRedeclContext())) + return; + + // Template instantiations should also not be pushed into scope. + if (isa(D) && + cast(D)->isFunctionTemplateSpecialization()) + return; + + // If this replaces anything in the current scope, + IdentifierResolver::iterator I = IdResolver.begin(D->getDeclName()), + IEnd = IdResolver.end(); + for (; I != IEnd; ++I) { + if (S->isDeclScope(*I) && D->declarationReplaces(*I)) { + S->RemoveDecl(*I); + IdResolver.RemoveDecl(*I); + + // Should only need to replace one decl. + break; + } + } + + S->AddDecl(D); + + if (isa(D) && !cast(D)->isGnuLocal()) { + // Implicitly-generated labels may end up getting generated in an order that + // isn't strictly lexical, which breaks name lookup. Be careful to insert + // the label at the appropriate place in the identifier chain. + for (I = IdResolver.begin(D->getDeclName()); I != IEnd; ++I) { + DeclContext *IDC = (*I)->getLexicalDeclContext()->getRedeclContext(); + if (IDC == CurContext) { + if (!S->isDeclScope(*I)) + continue; + } else if (IDC->Encloses(CurContext)) + break; + } + + IdResolver.InsertDeclAfter(I, D); + } else { + IdResolver.AddDecl(D); + } +} + +void Sema::pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name) { + if (IdResolver.tryAddTopLevelDecl(D, Name) && TUScope) + TUScope->AddDecl(D); +} + +bool Sema::isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S, + bool ExplicitInstantiationOrSpecialization) { + return IdResolver.isDeclInScope(D, Ctx, Context, S, + ExplicitInstantiationOrSpecialization); +} + +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&); + +/// Filters out lookup results that don't fall within the given scope +/// as determined by isDeclInScope. +void Sema::FilterLookupForScope(LookupResult &R, + DeclContext *Ctx, Scope *S, + bool ConsiderLinkage, + bool ExplicitInstantiationOrSpecialization) { + LookupResult::Filter F = R.makeFilter(); + while (F.hasNext()) { + NamedDecl *D = F.next(); + + if (isDeclInScope(D, Ctx, S, ExplicitInstantiationOrSpecialization)) + continue; + + if (ConsiderLinkage && + isOutOfScopePreviousDeclaration(D, Ctx, Context)) + continue; + + F.erase(); + } + + F.done(); +} + +static bool isUsingDecl(NamedDecl *D) { + return isa(D) || + isa(D) || + isa(D); +} + +/// Removes using shadow declarations from the lookup results. +static void RemoveUsingDecls(LookupResult &R) { + LookupResult::Filter F = R.makeFilter(); + while (F.hasNext()) + if (isUsingDecl(F.next())) + F.erase(); + + 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->doesThisDeclarationHaveABody()) + return false; + + if (const CXXConstructorDecl *CD = dyn_cast(D)) + return CD->isCopyConstructor(); + if (const CXXMethodDecl *Method = dyn_cast(D)) + return Method->isCopyAssignmentOperator(); + return false; +} + +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() || + D->getLexicalDeclContext()->isDependentContext()) + 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->doesThisDeclarationHaveABody() && + Context.DeclMustBeEmitted(FD)) + return false; + } else if (const VarDecl *VD = dyn_cast(D)) { + if (!VD->isFileVarDecl() || + VD->getType().isConstant(Context) || + Context.DeclMustBeEmitted(VD)) + return false; + + if (VD->isStaticDataMember() && + VD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) + return false; + + } else { + return false; + } + + // Only warn for unused decls internal to the translation unit. + if (D->getLinkage() == ExternalLinkage) + return false; + + return true; +} + +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; + + if (D->isReferenced() || D->isUsed() || D->hasAttr()) + return false; + + if (isa(D)) + return true; + + // White-list anything that isn't a local variable. + if (!isa(D) || isa(D) || isa(D) || + !D->getDeclContext()->isFunctionOrMethod()) + return false; + + // Types of valid local variables should be complete, so this should succeed. + if (const VarDecl *VD = dyn_cast(D)) { + + // White-list anything with an __attribute__((unused)) type. + QualType Ty = VD->getType(); + + // Only look at the outermost level of typedef. + if (const TypedefType *TT = dyn_cast(Ty)) { + if (TT->getDecl()->hasAttr()) + return false; + } + + // If we failed to complete the type for some reason, or if the type is + // dependent, don't diagnose the variable. + if (Ty->isIncompleteType() || Ty->isDependentType()) + return false; + + if (const TagType *TT = Ty->getAs()) { + const TagDecl *Tag = TT->getDecl(); + if (Tag->hasAttr()) + return false; + + if (const CXXRecordDecl *RD = dyn_cast(Tag)) { + if (!RD->hasTrivialDestructor()) + return false; + + if (const Expr *Init = VD->getInit()) { + const CXXConstructExpr *Construct = + dyn_cast(Init); + if (Construct && !Construct->isElidable()) { + CXXConstructorDecl *CD = Construct->getConstructor(); + if (!CD->isTrivial()) + return false; + } + } + } + } + + // TODO: __attribute__((unused)) templates? + } + + return true; +} + +static void GenerateFixForUnusedDecl(const NamedDecl *D, ASTContext &Ctx, + FixItHint &Hint) { + if (isa(D)) { + SourceLocation AfterColon = Lexer::findLocationAfterToken(D->getLocEnd(), + tok::colon, Ctx.getSourceManager(), Ctx.getLangOpts(), true); + if (AfterColon.isInvalid()) + return; + Hint = FixItHint::CreateRemoval(CharSourceRange:: + getCharRange(D->getLocStart(), AfterColon)); + } + return; +} + +/// DiagnoseUnusedDecl - Emit warnings about declarations that are not used +/// unless they are marked attr(unused). +void Sema::DiagnoseUnusedDecl(const NamedDecl *D) { + FixItHint Hint; + if (!ShouldDiagnoseUnusedDecl(D)) + return; + + GenerateFixForUnusedDecl(D, Context, Hint); + + unsigned DiagID; + if (isa(D) && cast(D)->isExceptionVariable()) + DiagID = diag::warn_unused_exception_param; + else if (isa(D)) + DiagID = diag::warn_unused_label; + else + DiagID = diag::warn_unused_variable; + + Diag(D->getLocation(), DiagID) << D->getDeclName() << Hint; +} + +static void CheckPoppedLabel(LabelDecl *L, Sema &S) { + // Verify that we have no forward references left. If so, there was a goto + // or address of a label taken, but no definition of it. Label fwd + // definitions are indicated with a null substmt. + if (L->getStmt() == 0) + S.Diag(L->getLocation(), diag::err_undeclared_label_use) <getDeclName(); +} + +void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { + if (S->decl_empty()) return; + assert((S->getFlags() & (Scope::DeclScope | Scope::TemplateParamScope)) && + "Scope shouldn't contain decls!"); + + for (Scope::decl_iterator I = S->decl_begin(), E = S->decl_end(); + I != E; ++I) { + Decl *TmpD = (*I); + assert(TmpD && "This decl didn't get pushed??"); + + assert(isa(TmpD) && "Decl isn't NamedDecl?"); + NamedDecl *D = cast(TmpD); + + if (!D->getDeclName()) continue; + + // Diagnose unused variables in this scope. + if (!S->hasErrorOccurred()) + DiagnoseUnusedDecl(D); + + // If this was a forward reference to a label, verify it was defined. + if (LabelDecl *LD = dyn_cast(D)) + CheckPoppedLabel(LD, *this); + + // Remove this name from our lexical scope. + IdResolver.RemoveDecl(D); + } +} + +void Sema::ActOnStartFunctionDeclarator() { + ++InFunctionDeclarator; +} + +void Sema::ActOnEndFunctionDeclarator() { + assert(InFunctionDeclarator); + --InFunctionDeclarator; +} + +/// \brief Look for an Objective-C class in the translation unit. +/// +/// \param Id The name of the Objective-C class we're looking for. If +/// typo-correction fixes this name, the Id will be updated +/// to the fixed name. +/// +/// \param IdLoc The location of the name in the translation unit. +/// +/// \param TypoCorrection If true, this routine will attempt typo correction +/// if there is no class with the given name. +/// +/// \returns The declaration of the named Objective-C class, or NULL if the +/// class could not be found. +ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *&Id, + SourceLocation IdLoc, + bool DoTypoCorrection) { + // The third "scope" argument is 0 since we aren't enabling lazy built-in + // creation from this context. + NamedDecl *IDecl = LookupSingleName(TUScope, Id, IdLoc, LookupOrdinaryName); + + if (!IDecl && DoTypoCorrection) { + // Perform typo correction at the given location, but only if we + // find an Objective-C class name. + DeclFilterCCC Validator; + if (TypoCorrection C = CorrectTypo(DeclarationNameInfo(Id, IdLoc), + LookupOrdinaryName, TUScope, NULL, + Validator)) { + IDecl = C.getCorrectionDeclAs(); + Diag(IdLoc, diag::err_undef_interface_suggest) + << Id << IDecl->getDeclName() + << FixItHint::CreateReplacement(IdLoc, IDecl->getNameAsString()); + Diag(IDecl->getLocation(), diag::note_previous_decl) + << IDecl->getDeclName(); + + Id = IDecl->getIdentifier(); + } + } + ObjCInterfaceDecl *Def = dyn_cast_or_null(IDecl); + // This routine must always return a class definition, if any. + if (Def && Def->getDefinition()) + Def = Def->getDefinition(); + return Def; +} + +/// getNonFieldDeclScope - Retrieves the innermost scope, starting +/// from S, where a non-field would be declared. This routine copes +/// with the difference between C and C++ scoping rules in structs and +/// unions. For example, the following code is well-formed in C but +/// ill-formed in C++: +/// @code +/// struct S6 { +/// enum { BAR } e; +/// }; +/// +/// void test_S6() { +/// struct S6 a; +/// a.e = BAR; +/// } +/// @endcode +/// For the declaration of BAR, this routine will return a different +/// scope. The scope S will be the scope of the unnamed enumeration +/// within S6. In C++, this routine will return the scope associated +/// with S6, because the enumeration's scope is a transparent +/// context but structures can contain non-field names. In C, this +/// routine will return the translation unit scope, since the +/// enumeration's scope is a transparent context and structures cannot +/// contain non-field names. +Scope *Sema::getNonFieldDeclScope(Scope *S) { + while (((S->getFlags() & Scope::DeclScope) == 0) || + (S->getEntity() && + ((DeclContext *)S->getEntity())->isTransparentContext()) || + (S->isClassScope() && !getLangOpts().CPlusPlus)) + S = S->getParent(); + return S; +} + +/// LazilyCreateBuiltin - The specified Builtin-ID was first used at +/// file scope. lazily create a decl for it. ForRedeclaration is true +/// if we're creating this built-in in anticipation of redeclaring the +/// built-in. +NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, + Scope *S, bool ForRedeclaration, + SourceLocation Loc) { + Builtin::ID BID = (Builtin::ID)bid; + + ASTContext::GetBuiltinTypeError Error; + QualType R = Context.GetBuiltinType(BID, Error); + switch (Error) { + case ASTContext::GE_None: + // Okay + break; + + case ASTContext::GE_Missing_stdio: + if (ForRedeclaration) + Diag(Loc, diag::warn_implicit_decl_requires_stdio) + << Context.BuiltinInfo.GetName(BID); + return 0; + + case ASTContext::GE_Missing_setjmp: + if (ForRedeclaration) + Diag(Loc, diag::warn_implicit_decl_requires_setjmp) + << Context.BuiltinInfo.GetName(BID); + return 0; + + case ASTContext::GE_Missing_ucontext: + if (ForRedeclaration) + Diag(Loc, diag::warn_implicit_decl_requires_ucontext) + << Context.BuiltinInfo.GetName(BID); + return 0; + } + + if (!ForRedeclaration && Context.BuiltinInfo.isPredefinedLibFunction(BID)) { + Diag(Loc, diag::ext_implicit_lib_function_decl) + << Context.BuiltinInfo.GetName(BID) + << R; + if (Context.BuiltinInfo.getHeaderName(BID) && + Diags.getDiagnosticLevel(diag::ext_implicit_lib_function_decl, Loc) + != DiagnosticsEngine::Ignored) + Diag(Loc, diag::note_please_include_header) + << Context.BuiltinInfo.getHeaderName(BID) + << Context.BuiltinInfo.GetName(BID); + } + + FunctionDecl *New = FunctionDecl::Create(Context, + Context.getTranslationUnitDecl(), + Loc, Loc, II, R, /*TInfo=*/0, + SC_Extern, + SC_None, false, + /*hasPrototype=*/true); + New->setImplicit(); + + // Create Decl objects for each parameter, adding them to the + // FunctionDecl. + if (const FunctionProtoType *FT = dyn_cast(R)) { + SmallVector Params; + for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i) { + ParmVarDecl *parm = + ParmVarDecl::Create(Context, New, SourceLocation(), + SourceLocation(), 0, + FT->getArgType(i), /*TInfo=*/0, + SC_None, SC_None, 0); + parm->setScopeInfo(0, i); + Params.push_back(parm); + } + New->setParams(Params); + } + + AddKnownFunctionAttributes(New); + + // TUScope is the translation-unit scope to insert this function into. + // FIXME: This is hideous. We need to teach PushOnScopeChains to + // relate Scopes to DeclContexts, and probably eliminate CurContext + // entirely, but we're not there yet. + DeclContext *SavedContext = CurContext; + CurContext = Context.getTranslationUnitDecl(); + PushOnScopeChains(New, TUScope); + CurContext = SavedContext; + return New; +} + +bool Sema::isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New) { + QualType OldType; + if (TypedefNameDecl *OldTypedef = dyn_cast(Old)) + OldType = OldTypedef->getUnderlyingType(); + else + OldType = Context.getTypeDeclType(Old); + QualType NewType = New->getUnderlyingType(); + + if (NewType->isVariablyModifiedType()) { + // Must not redefine a typedef with a variably-modified type. + int Kind = isa(Old) ? 1 : 0; + Diag(New->getLocation(), diag::err_redefinition_variably_modified_typedef) + << Kind << NewType; + if (Old->getLocation().isValid()) + Diag(Old->getLocation(), diag::note_previous_definition); + New->setInvalidDecl(); + return true; + } + + if (OldType != NewType && + !OldType->isDependentType() && + !NewType->isDependentType() && + !Context.hasSameType(OldType, NewType)) { + int Kind = isa(Old) ? 1 : 0; + Diag(New->getLocation(), diag::err_redefinition_different_typedef) + << Kind << NewType << OldType; + if (Old->getLocation().isValid()) + Diag(Old->getLocation(), diag::note_previous_definition); + New->setInvalidDecl(); + return true; + } + return false; +} + +/// MergeTypedefNameDecl - We just parsed a typedef 'New' which has the +/// same name and scope as a previous declaration 'Old'. Figure out +/// how to resolve this situation, merging decls or emitting +/// diagnostics as appropriate. If there was an error, set New to be invalid. +/// +void Sema::MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls) { + // If the new decl is known invalid already, don't bother doing any + // merging checks. + if (New->isInvalidDecl()) return; + + // Allow multiple definitions for ObjC built-in typedefs. + // FIXME: Verify the underlying types are equivalent! + if (getLangOpts().ObjC1) { + const IdentifierInfo *TypeID = New->getIdentifier(); + switch (TypeID->getLength()) { + default: break; + case 2: + if (!TypeID->isStr("id")) + break; + Context.setObjCIdRedefinitionType(New->getUnderlyingType()); + // Install the built-in type for 'id', ignoring the current definition. + New->setTypeForDecl(Context.getObjCIdType().getTypePtr()); + return; + case 5: + if (!TypeID->isStr("Class")) + break; + Context.setObjCClassRedefinitionType(New->getUnderlyingType()); + // Install the built-in type for 'Class', ignoring the current definition. + New->setTypeForDecl(Context.getObjCClassType().getTypePtr()); + return; + case 3: + if (!TypeID->isStr("SEL")) + break; + Context.setObjCSelRedefinitionType(New->getUnderlyingType()); + // Install the built-in type for 'SEL', ignoring the current definition. + New->setTypeForDecl(Context.getObjCSelType().getTypePtr()); + return; + } + // Fall through - the typedef name was not a builtin type. + } + + // Verify the old decl was also a type. + TypeDecl *Old = OldDecls.getAsSingle(); + if (!Old) { + Diag(New->getLocation(), diag::err_redefinition_different_kind) + << New->getDeclName(); + + NamedDecl *OldD = OldDecls.getRepresentativeDecl(); + if (OldD->getLocation().isValid()) + Diag(OldD->getLocation(), diag::note_previous_definition); + + return New->setInvalidDecl(); + } + + // If the old declaration is invalid, just give up here. + if (Old->isInvalidDecl()) + return New->setInvalidDecl(); + + // If the typedef types are not identical, reject them in all languages and + // with any extensions enabled. + if (isIncompatibleTypedef(Old, New)) + return; + + // The types match. Link up the redeclaration chain if the old + // declaration was a typedef. + if (TypedefNameDecl *Typedef = dyn_cast(Old)) + New->setPreviousDeclaration(Typedef); + + if (getLangOpts().MicrosoftExt) + return; + + if (getLangOpts().CPlusPlus) { + // C++ [dcl.typedef]p2: + // In a given non-class scope, a typedef specifier can be used to + // redefine the name of any type declared in that scope to refer + // to the type to which it already refers. + if (!isa(CurContext)) + return; + + // C++0x [dcl.typedef]p4: + // In a given class scope, a typedef specifier can be used to redefine + // any class-name declared in that scope that is not also a typedef-name + // to refer to the type to which it already refers. + // + // This wording came in via DR424, which was a correction to the + // wording in DR56, which accidentally banned code like: + // + // struct S { + // typedef struct A { } A; + // }; + // + // in the C++03 standard. We implement the C++0x semantics, which + // allow the above but disallow + // + // struct S { + // typedef int I; + // typedef int I; + // }; + // + // since that was the intent of DR56. + if (!isa(Old)) + return; + + Diag(New->getLocation(), diag::err_redefinition) + << New->getDeclName(); + Diag(Old->getLocation(), diag::note_previous_definition); + return New->setInvalidDecl(); + } + + // Modules always permit redefinition of typedefs, as does C11. + if (getLangOpts().Modules || getLangOpts().C11) + return; + + // If we have a redefinition of a typedef in C, emit a warning. This warning + // is normally mapped to an error, but can be controlled with + // -Wtypedef-redefinition. If either the original or the redefinition is + // in a system header, don't emit this for compatibility with GCC. + if (getDiagnostics().getSuppressSystemWarnings() && + (Context.getSourceManager().isInSystemHeader(Old->getLocation()) || + Context.getSourceManager().isInSystemHeader(New->getLocation()))) + return; + + Diag(New->getLocation(), diag::warn_redefinition_of_typedef) + << New->getDeclName(); + Diag(Old->getLocation(), diag::note_previous_definition); + return; +} + +/// DeclhasAttr - returns true if decl Declaration already has the target +/// attribute. +static bool +DeclHasAttr(const Decl *D, const Attr *A) { + const OwnershipAttr *OA = dyn_cast(A); + const AnnotateAttr *Ann = dyn_cast(A); + for (Decl::attr_iterator i = D->attr_begin(), e = D->attr_end(); i != e; ++i) + if ((*i)->getKind() == A->getKind()) { + if (Ann) { + if (Ann->getAnnotation() == cast(*i)->getAnnotation()) + return true; + continue; + } + // FIXME: Don't hardcode this check + if (OA && isa(*i)) + return OA->getOwnKind() == cast(*i)->getOwnKind(); + return true; + } + + return false; +} + +/// mergeDeclAttributes - Copy attributes from the Old decl to the New one. +void Sema::mergeDeclAttributes(Decl *New, Decl *Old, + bool MergeDeprecation) { + if (!Old->hasAttrs()) + return; + + bool foundAny = New->hasAttrs(); + + // Ensure that any moving of objects within the allocated map is done before + // we process them. + if (!foundAny) New->setAttrs(AttrVec()); + + for (specific_attr_iterator + i = Old->specific_attr_begin(), + e = Old->specific_attr_end(); + i != e; ++i) { + // Ignore deprecated/unavailable/availability attributes if requested. + if (!MergeDeprecation && + (isa(*i) || + isa(*i) || + isa(*i))) + continue; + + if (!DeclHasAttr(New, *i)) { + InheritableAttr *newAttr = cast((*i)->clone(Context)); + newAttr->setInherited(true); + New->addAttr(newAttr); + foundAny = true; + } + } + + if (!foundAny) New->dropAttrs(); +} + +/// mergeParamDeclAttributes - Copy attributes from the old parameter +/// to the new one. +static void mergeParamDeclAttributes(ParmVarDecl *newDecl, + const ParmVarDecl *oldDecl, + ASTContext &C) { + if (!oldDecl->hasAttrs()) + return; + + bool foundAny = newDecl->hasAttrs(); + + // Ensure that any moving of objects within the allocated map is + // done before we process them. + if (!foundAny) newDecl->setAttrs(AttrVec()); + + for (specific_attr_iterator + i = oldDecl->specific_attr_begin(), + e = oldDecl->specific_attr_end(); i != e; ++i) { + if (!DeclHasAttr(newDecl, *i)) { + InheritableAttr *newAttr = cast((*i)->clone(C)); + newAttr->setInherited(true); + newDecl->addAttr(newAttr); + foundAny = true; + } + } + + if (!foundAny) newDecl->dropAttrs(); +} + +namespace { + +/// Used in MergeFunctionDecl to keep track of function parameters in +/// C. +struct GNUCompatibleParamWarning { + ParmVarDecl *OldParm; + ParmVarDecl *NewParm; + QualType PromotedType; +}; + +} + +/// getSpecialMember - get the special member enum for a method. +Sema::CXXSpecialMember Sema::getSpecialMember(const CXXMethodDecl *MD) { + if (const CXXConstructorDecl *Ctor = dyn_cast(MD)) { + if (Ctor->isDefaultConstructor()) + return Sema::CXXDefaultConstructor; + + if (Ctor->isCopyConstructor()) + return Sema::CXXCopyConstructor; + + if (Ctor->isMoveConstructor()) + return Sema::CXXMoveConstructor; + } else if (isa(MD)) { + return Sema::CXXDestructor; + } else if (MD->isCopyAssignmentOperator()) { + return Sema::CXXCopyAssignment; + } else if (MD->isMoveAssignmentOperator()) { + return Sema::CXXMoveAssignment; + } + + return Sema::CXXInvalid; +} + +/// canRedefineFunction - checks if a function can be redefined. Currently, +/// only extern inline functions can be redefined, and even then only in +/// GNU89 mode. +static bool canRedefineFunction(const FunctionDecl *FD, + const LangOptions& LangOpts) { + return ((FD->hasAttr() || LangOpts.GNUInline) && + !LangOpts.CPlusPlus && + FD->isInlineSpecified() && + FD->getStorageClass() == SC_Extern); +} + +/// MergeFunctionDecl - We just parsed a function 'New' from +/// declarator D which has the same name and scope as a previous +/// declaration 'Old'. Figure out how to resolve this situation, +/// merging decls or emitting diagnostics as appropriate. +/// +/// In C++, New and Old must be declarations that are not +/// overloaded. Use IsOverload to determine whether New and Old are +/// overloaded, and to select the Old declaration that New should be +/// merged with. +/// +/// Returns true if there was an error, false otherwise. +bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) { + // Verify the old decl was also a function. + FunctionDecl *Old = 0; + if (FunctionTemplateDecl *OldFunctionTemplate + = dyn_cast(OldD)) + Old = OldFunctionTemplate->getTemplatedDecl(); + else + Old = dyn_cast(OldD); + if (!Old) { + if (UsingShadowDecl *Shadow = dyn_cast(OldD)) { + Diag(New->getLocation(), diag::err_using_decl_conflict_reverse); + Diag(Shadow->getTargetDecl()->getLocation(), + diag::note_using_decl_target); + Diag(Shadow->getUsingDecl()->getLocation(), + diag::note_using_decl) << 0; + return true; + } + + Diag(New->getLocation(), diag::err_redefinition_different_kind) + << New->getDeclName(); + Diag(OldD->getLocation(), diag::note_previous_definition); + return true; + } + + // Determine whether the previous declaration was a definition, + // implicit declaration, or a declaration. + diag::kind PrevDiag; + if (Old->isThisDeclarationADefinition()) + PrevDiag = diag::note_previous_definition; + else if (Old->isImplicit()) + PrevDiag = diag::note_previous_implicit_declaration; + else + PrevDiag = diag::note_previous_declaration; + + QualType OldQType = Context.getCanonicalType(Old->getType()); + QualType NewQType = Context.getCanonicalType(New->getType()); + + // 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() == SC_Static && + Old->getStorageClass() != SC_Static && + !canRedefineFunction(Old, getLangOpts())) { + if (getLangOpts().MicrosoftExt) { + Diag(New->getLocation(), diag::warn_static_non_static) << New; + Diag(Old->getLocation(), PrevDiag); + } else { + Diag(New->getLocation(), diag::err_static_non_static) << New; + Diag(Old->getLocation(), PrevDiag); + return true; + } + } + + // If a function is first declared with a calling convention, but is + // later declared or defined without one, the second decl assumes the + // calling convention of the first. + // + // For the new decl, we have to look at the NON-canonical type to tell the + // difference between a function that really doesn't have a calling + // convention and one that is declared cdecl. That's because in + // canonicalization (see ASTContext.cpp), cdecl is canonicalized away + // because it is the default calling convention. + // + // Note also that we DO NOT return at this point, because we still have + // other tests to run. + const FunctionType *OldType = cast(OldQType); + const FunctionType *NewType = New->getType()->getAs(); + FunctionType::ExtInfo OldTypeInfo = OldType->getExtInfo(); + FunctionType::ExtInfo NewTypeInfo = NewType->getExtInfo(); + bool RequiresAdjustment = false; + if (OldTypeInfo.getCC() != CC_Default && + NewTypeInfo.getCC() == CC_Default) { + NewTypeInfo = NewTypeInfo.withCallingConv(OldTypeInfo.getCC()); + RequiresAdjustment = true; + } else if (!Context.isSameCallConv(OldTypeInfo.getCC(), + NewTypeInfo.getCC())) { + // Calling conventions really aren't compatible, so complain. + Diag(New->getLocation(), diag::err_cconv_change) + << FunctionType::getNameForCallConv(NewTypeInfo.getCC()) + << (OldTypeInfo.getCC() == CC_Default) + << (OldTypeInfo.getCC() == CC_Default ? "" : + FunctionType::getNameForCallConv(OldTypeInfo.getCC())); + Diag(Old->getLocation(), diag::note_previous_declaration); + return true; + } + + // FIXME: diagnose the other way around? + if (OldTypeInfo.getNoReturn() && !NewTypeInfo.getNoReturn()) { + NewTypeInfo = NewTypeInfo.withNoReturn(true); + RequiresAdjustment = true; + } + + // Merge regparm attribute. + if (OldTypeInfo.getHasRegParm() != NewTypeInfo.getHasRegParm() || + OldTypeInfo.getRegParm() != NewTypeInfo.getRegParm()) { + if (NewTypeInfo.getHasRegParm()) { + Diag(New->getLocation(), diag::err_regparm_mismatch) + << NewType->getRegParmType() + << OldType->getRegParmType(); + Diag(Old->getLocation(), diag::note_previous_declaration); + return true; + } + + NewTypeInfo = NewTypeInfo.withRegParm(OldTypeInfo.getRegParm()); + RequiresAdjustment = true; + } + + // Merge ns_returns_retained attribute. + if (OldTypeInfo.getProducesResult() != NewTypeInfo.getProducesResult()) { + if (NewTypeInfo.getProducesResult()) { + Diag(New->getLocation(), diag::err_returns_retained_mismatch); + Diag(Old->getLocation(), diag::note_previous_declaration); + return true; + } + + NewTypeInfo = NewTypeInfo.withProducesResult(true); + RequiresAdjustment = true; + } + + if (RequiresAdjustment) { + NewType = Context.adjustFunctionType(NewType, NewTypeInfo); + New->setType(QualType(NewType, 0)); + NewQType = Context.getCanonicalType(New->getType()); + } + + if (getLangOpts().CPlusPlus) { + // (C++98 13.1p2): + // Certain function declarations cannot be overloaded: + // -- Function declarations that differ only in the return type + // cannot be overloaded. + QualType OldReturnType = OldType->getResultType(); + QualType NewReturnType = cast(NewQType)->getResultType(); + QualType ResQT; + if (OldReturnType != NewReturnType) { + if (NewReturnType->isObjCObjectPointerType() + && OldReturnType->isObjCObjectPointerType()) + ResQT = Context.mergeObjCGCQualifiers(NewQType, OldQType); + if (ResQT.isNull()) { + if (New->isCXXClassMember() && New->isOutOfLine()) + Diag(New->getLocation(), + diag::err_member_def_does_not_match_ret_type) << New; + else + Diag(New->getLocation(), diag::err_ovl_diff_return_type); + Diag(Old->getLocation(), PrevDiag) << Old << Old->getType(); + return true; + } + else + NewQType = ResQT; + } + + const CXXMethodDecl* OldMethod = dyn_cast(Old); + CXXMethodDecl* NewMethod = dyn_cast(New); + if (OldMethod && NewMethod) { + // Preserve triviality. + NewMethod->setTrivial(OldMethod->isTrivial()); + + // MSVC allows explicit template specialization at class scope: + // 2 CXMethodDecls referring to the same function will be injected. + // We don't want a redeclartion error. + bool IsClassScopeExplicitSpecialization = + OldMethod->isFunctionTemplateSpecialization() && + NewMethod->isFunctionTemplateSpecialization(); + bool isFriend = NewMethod->getFriendObjectKind(); + + if (!isFriend && NewMethod->getLexicalDeclContext()->isRecord() && + !IsClassScopeExplicitSpecialization) { + // -- Member function declarations with the same name and the + // same parameter types cannot be overloaded if any of them + // is a static member function declaration. + if (OldMethod->isStatic() || NewMethod->isStatic()) { + Diag(New->getLocation(), diag::err_ovl_static_nonstatic_member); + Diag(Old->getLocation(), PrevDiag) << Old << Old->getType(); + return true; + } + + // C++ [class.mem]p1: + // [...] A member shall not be declared twice in the + // member-specification, except that a nested class or member + // class template can be declared and then later defined. + unsigned NewDiag; + if (isa(OldMethod)) + NewDiag = diag::err_constructor_redeclared; + else if (isa(NewMethod)) + NewDiag = diag::err_destructor_redeclared; + else if (isa(NewMethod)) + NewDiag = diag::err_conv_function_redeclared; + else + NewDiag = diag::err_member_redeclared; + + Diag(New->getLocation(), NewDiag); + Diag(Old->getLocation(), PrevDiag) << Old << Old->getType(); + + // Complain if this is an explicit declaration of a special + // member that was initially declared implicitly. + // + // As an exception, it's okay to befriend such methods in order + // to permit the implicit constructor/destructor/operator calls. + } else if (OldMethod->isImplicit()) { + if (isFriend) { + NewMethod->setImplicit(); + } else { + Diag(NewMethod->getLocation(), + diag::err_definition_of_implicitly_declared_member) + << New << getSpecialMember(OldMethod); + return true; + } + } else if (OldMethod->isExplicitlyDefaulted()) { + Diag(NewMethod->getLocation(), + diag::err_definition_of_explicitly_defaulted_member) + << getSpecialMember(OldMethod); + return true; + } + } + + // (C++98 8.3.5p3): + // All declarations for a function shall agree exactly in both the + // return type and the parameter-type-list. + // We also want to respect all the extended bits except noreturn. + + // noreturn should now match unless the old type info didn't have it. + QualType OldQTypeForComparison = OldQType; + if (!OldTypeInfo.getNoReturn() && NewTypeInfo.getNoReturn()) { + assert(OldQType == QualType(OldType, 0)); + const FunctionType *OldTypeForComparison + = Context.adjustFunctionType(OldType, OldTypeInfo.withNoReturn(true)); + OldQTypeForComparison = QualType(OldTypeForComparison, 0); + assert(OldQTypeForComparison.isCanonical()); + } + + if (OldQTypeForComparison == NewQType) + return MergeCompatibleFunctionDecls(New, Old, S); + + // Fall through for conflicting redeclarations and redefinitions. + } + + // C: Function types need to be compatible, not identical. This handles + // duplicate function decls like "void f(int); void f(enum X);" properly. + if (!getLangOpts().CPlusPlus && + Context.typesAreCompatible(OldQType, NewQType)) { + const FunctionType *OldFuncType = OldQType->getAs(); + const FunctionType *NewFuncType = NewQType->getAs(); + const FunctionProtoType *OldProto = 0; + if (isa(NewFuncType) && + (OldProto = dyn_cast(OldFuncType))) { + // The old declaration provided a function prototype, but the + // new declaration does not. Merge in the prototype. + assert(!OldProto->hasExceptionSpec() && "Exception spec in C"); + SmallVector ParamTypes(OldProto->arg_type_begin(), + OldProto->arg_type_end()); + NewQType = Context.getFunctionType(NewFuncType->getResultType(), + ParamTypes.data(), ParamTypes.size(), + OldProto->getExtProtoInfo()); + New->setType(NewQType); + New->setHasInheritedPrototype(); + + // Synthesize a parameter for each argument type. + SmallVector Params; + for (FunctionProtoType::arg_type_iterator + ParamType = OldProto->arg_type_begin(), + ParamEnd = OldProto->arg_type_end(); + ParamType != ParamEnd; ++ParamType) { + ParmVarDecl *Param = ParmVarDecl::Create(Context, New, + SourceLocation(), + SourceLocation(), 0, + *ParamType, /*TInfo=*/0, + SC_None, SC_None, + 0); + Param->setScopeInfo(0, Params.size()); + Param->setImplicit(); + Params.push_back(Param); + } + + New->setParams(Params); + } + + return MergeCompatibleFunctionDecls(New, Old, S); + } + + // GNU C permits a K&R definition to follow a prototype declaration + // if the declared types of the parameters in the K&R definition + // match the types in the prototype declaration, even when the + // promoted types of the parameters from the K&R definition differ + // from the types in the prototype. GCC then keeps the types from + // the prototype. + // + // If a variadic prototype is followed by a non-variadic K&R definition, + // the K&R definition becomes variadic. This is sort of an edge case, but + // it's legal per the standard depending on how you read C99 6.7.5.3p15 and + // C99 6.9.1p8. + if (!getLangOpts().CPlusPlus && + Old->hasPrototype() && !New->hasPrototype() && + New->getType()->getAs() && + Old->getNumParams() == New->getNumParams()) { + SmallVector ArgTypes; + SmallVector Warnings; + const FunctionProtoType *OldProto + = Old->getType()->getAs(); + const FunctionProtoType *NewProto + = New->getType()->getAs(); + + // Determine whether this is the GNU C extension. + QualType MergedReturn = Context.mergeTypes(OldProto->getResultType(), + NewProto->getResultType()); + bool LooseCompatible = !MergedReturn.isNull(); + for (unsigned Idx = 0, End = Old->getNumParams(); + LooseCompatible && Idx != End; ++Idx) { + ParmVarDecl *OldParm = Old->getParamDecl(Idx); + ParmVarDecl *NewParm = New->getParamDecl(Idx); + if (Context.typesAreCompatible(OldParm->getType(), + NewProto->getArgType(Idx))) { + ArgTypes.push_back(NewParm->getType()); + } else if (Context.typesAreCompatible(OldParm->getType(), + NewParm->getType(), + /*CompareUnqualified=*/true)) { + GNUCompatibleParamWarning Warn + = { OldParm, NewParm, NewProto->getArgType(Idx) }; + Warnings.push_back(Warn); + ArgTypes.push_back(NewParm->getType()); + } else + LooseCompatible = false; + } + + if (LooseCompatible) { + for (unsigned Warn = 0; Warn < Warnings.size(); ++Warn) { + Diag(Warnings[Warn].NewParm->getLocation(), + diag::ext_param_promoted_not_compatible_with_prototype) + << Warnings[Warn].PromotedType + << Warnings[Warn].OldParm->getType(); + if (Warnings[Warn].OldParm->getLocation().isValid()) + Diag(Warnings[Warn].OldParm->getLocation(), + diag::note_previous_declaration); + } + + New->setType(Context.getFunctionType(MergedReturn, &ArgTypes[0], + ArgTypes.size(), + OldProto->getExtProtoInfo())); + return MergeCompatibleFunctionDecls(New, Old, S); + } + + // Fall through to diagnose conflicting types. + } + + // A function that has already been declared has been redeclared or defined + // with a different type- show appropriate diagnostic + if (unsigned BuiltinID = Old->getBuiltinID()) { + // The user has declared a builtin function with an incompatible + // signature. + if (Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) { + // The function the user is redeclaring is a library-defined + // function like 'malloc' or 'printf'. Warn about the + // redeclaration, then pretend that we don't know about this + // library built-in. + Diag(New->getLocation(), diag::warn_redecl_library_builtin) << New; + Diag(Old->getLocation(), diag::note_previous_builtin_declaration) + << Old << Old->getType(); + New->getIdentifier()->setBuiltinID(Builtin::NotBuiltin); + Old->setInvalidDecl(); + return false; + } + + PrevDiag = diag::note_previous_builtin_declaration; + } + + Diag(New->getLocation(), diag::err_conflicting_types) << New->getDeclName(); + Diag(Old->getLocation(), PrevDiag) << Old << Old->getType(); + return true; +} + +/// \brief Completes the merge of two function declarations that are +/// known to be compatible. +/// +/// This routine handles the merging of attributes and other +/// properties of function declarations form the old declaration to +/// the new declaration, once we know that New is in fact a +/// redeclaration of Old. +/// +/// \returns false +bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old, + Scope *S) { + // Merge the attributes + mergeDeclAttributes(New, Old); + + // Merge the storage class. + if (Old->getStorageClass() != SC_Extern && + Old->getStorageClass() != SC_None) + New->setStorageClass(Old->getStorageClass()); + + // Merge "pure" flag. + if (Old->isPure()) + New->setPure(); + + // Merge attributes from the parameters. These can mismatch with K&R + // declarations. + if (New->getNumParams() == Old->getNumParams()) + for (unsigned i = 0, e = New->getNumParams(); i != e; ++i) + mergeParamDeclAttributes(New->getParamDecl(i), Old->getParamDecl(i), + Context); + + if (getLangOpts().CPlusPlus) + return MergeCXXFunctionDecl(New, Old, S); + + return false; +} + + +void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod, + ObjCMethodDecl *oldMethod) { + // We don't want to merge unavailable and deprecated attributes + // except from interface to implementation. + bool mergeDeprecation = isa(newMethod->getDeclContext()); + + // Merge the attributes. + mergeDeclAttributes(newMethod, oldMethod, mergeDeprecation); + + // Merge attributes from the parameters. + ObjCMethodDecl::param_const_iterator oi = oldMethod->param_begin(); + for (ObjCMethodDecl::param_iterator + ni = newMethod->param_begin(), ne = newMethod->param_end(); + ni != ne; ++ni, ++oi) + mergeParamDeclAttributes(*ni, *oi, Context); + + CheckObjCMethodOverride(newMethod, oldMethod, true); +} + +/// MergeVarDeclTypes - We parsed a variable 'New' which has the same name and +/// scope as a previous declaration 'Old'. Figure out how to merge their types, +/// emitting diagnostics as appropriate. +/// +/// Declarations using the auto type specifier (C++ [decl.spec.auto]) call back +/// to here in AddInitializerToDecl. We can't check them before the initializer +/// is attached. +void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old) { + if (New->isInvalidDecl() || Old->isInvalidDecl()) + return; + + QualType MergedT; + if (getLangOpts().CPlusPlus) { + AutoType *AT = New->getType()->getContainedAutoType(); + if (AT && !AT->isDeduced()) { + // We don't know what the new type is until the initializer is attached. + return; + } else if (Context.hasSameType(New->getType(), Old->getType())) { + // These could still be something that needs exception specs checked. + return MergeVarDeclExceptionSpecs(New, Old); + } + // C++ [basic.link]p10: + // [...] the types specified by all declarations referring to a given + // object or function shall be identical, except that declarations for an + // array object can specify array types that differ by the presence or + // absence of a major array bound (8.3.4). + else if (Old->getType()->isIncompleteArrayType() && + New->getType()->isArrayType()) { + CanQual OldArray + = Context.getCanonicalType(Old->getType())->getAs(); + CanQual NewArray + = Context.getCanonicalType(New->getType())->getAs(); + if (OldArray->getElementType() == NewArray->getElementType()) + MergedT = New->getType(); + } else if (Old->getType()->isArrayType() && + New->getType()->isIncompleteArrayType()) { + CanQual OldArray + = Context.getCanonicalType(Old->getType())->getAs(); + CanQual NewArray + = Context.getCanonicalType(New->getType())->getAs(); + if (OldArray->getElementType() == NewArray->getElementType()) + MergedT = Old->getType(); + } else if (New->getType()->isObjCObjectPointerType() + && Old->getType()->isObjCObjectPointerType()) { + MergedT = Context.mergeObjCGCQualifiers(New->getType(), + Old->getType()); + } + } else { + MergedT = Context.mergeTypes(New->getType(), Old->getType()); + } + if (MergedT.isNull()) { + Diag(New->getLocation(), diag::err_redefinition_different_type) + << New->getDeclName(); + Diag(Old->getLocation(), diag::note_previous_definition); + return New->setInvalidDecl(); + } + New->setType(MergedT); +} + +/// MergeVarDecl - We just parsed a variable 'New' which has the same name +/// and scope as a previous declaration 'Old'. Figure out how to resolve this +/// situation, merging decls or emitting diagnostics as appropriate. +/// +/// Tentative definition rules (C99 6.9.2p2) are checked by +/// FinalizeDeclaratorGroup. Unfortunately, we can't analyze tentative +/// definitions here, since the initializer hasn't been attached. +/// +void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { + // If the new decl is already invalid, don't do any other checking. + if (New->isInvalidDecl()) + return; + + // Verify the old decl was also a variable. + VarDecl *Old = 0; + if (!Previous.isSingleResult() || + !(Old = dyn_cast(Previous.getFoundDecl()))) { + Diag(New->getLocation(), diag::err_redefinition_different_kind) + << New->getDeclName(); + Diag(Previous.getRepresentativeDecl()->getLocation(), + diag::note_previous_definition); + return New->setInvalidDecl(); + } + + // 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); + // Warn if an already-declared variable is made a weak_import in a subsequent + // declaration + if (New->getAttr() && + Old->getStorageClass() == SC_None && + !Old->getAttr()) { + Diag(New->getLocation(), diag::warn_weak_import) << New->getDeclName(); + Diag(Old->getLocation(), diag::note_previous_definition); + // Remove weak_import attribute on new declaration. + New->dropAttr(); + } + + // Merge the types. + MergeVarDeclTypes(New, Old); + if (New->isInvalidDecl()) + return; + + // C99 6.2.2p4: Check if we have a static decl followed by a non-static. + 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(); + } + // C99 6.2.2p4: + // For an identifier declared with the storage-class specifier + // extern in a scope in which a prior declaration of that + // identifier is visible,23) if the prior declaration specifies + // internal or external linkage, the linkage of the identifier at + // the later declaration is the same as the linkage specified at + // the prior declaration. If no prior declaration is visible, or + // if the prior declaration specifies no linkage, then the + // identifier has external linkage. + if (New->hasExternalStorage() && Old->hasLinkage()) + /* Okay */; + 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(); + } + + // Check if extern is followed by non-extern and vice-versa. + if (New->hasExternalStorage() && + !Old->hasLinkage() && Old->isLocalVarDecl()) { + Diag(New->getLocation(), diag::err_extern_non_extern) << New->getDeclName(); + Diag(Old->getLocation(), diag::note_previous_definition); + return New->setInvalidDecl(); + } + if (Old->hasExternalStorage() && + !New->hasLinkage() && New->isLocalVarDecl()) { + Diag(New->getLocation(), diag::err_non_extern_extern) << New->getDeclName(); + Diag(Old->getLocation(), diag::note_previous_definition); + return New->setInvalidDecl(); + } + + // Variables with external linkage are analyzed in FinalizeDeclaratorGroup. + + // FIXME: The test for external storage here seems wrong? We still + // need to check for mismatches. + if (!New->hasExternalStorage() && !New->isFileVarDecl() && + // Don't complain about out-of-line definitions of static members. + !(Old->getLexicalDeclContext()->isRecord() && + !New->getLexicalDeclContext()->isRecord())) { + Diag(New->getLocation(), diag::err_redefinition) << New->getDeclName(); + Diag(Old->getLocation(), diag::note_previous_definition); + return New->setInvalidDecl(); + } + + if (New->isThreadSpecified() && !Old->isThreadSpecified()) { + Diag(New->getLocation(), diag::err_thread_non_thread) << New->getDeclName(); + Diag(Old->getLocation(), diag::note_previous_definition); + } else if (!New->isThreadSpecified() && Old->isThreadSpecified()) { + Diag(New->getLocation(), diag::err_non_thread_thread) << New->getDeclName(); + Diag(Old->getLocation(), diag::note_previous_definition); + } + + // C++ doesn't have tentative definitions, so go right ahead and check here. + const VarDecl *Def; + if (getLangOpts().CPlusPlus && + New->isThisDeclarationADefinition() == VarDecl::Definition && + (Def = Old->getDefinition())) { + Diag(New->getLocation(), diag::err_redefinition) + << New->getDeclName(); + Diag(Def->getLocation(), diag::note_previous_definition); + New->setInvalidDecl(); + return; + } + // c99 6.2.2 P4. + // For an identifier declared with the storage-class specifier extern in a + // scope in which a prior declaration of that identifier is visible, if + // the prior declaration specifies internal or external linkage, the linkage + // of the identifier at the later declaration is the same as the linkage + // specified at the prior declaration. + // FIXME. revisit this code. + if (New->hasExternalStorage() && + Old->getLinkage() == InternalLinkage && + New->getDeclContext() == Old->getDeclContext()) + New->setStorageClass(Old->getStorageClass()); + + // Keep a chain of previous declarations. + New->setPreviousDeclaration(Old); + + // Inherit access appropriately. + New->setAccess(Old->getAccess()); +} + +/// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with +/// no declarator (e.g. "struct foo;") is parsed. +Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, + DeclSpec &DS) { + return ParsedFreeStandingDeclSpec(S, AS, DS, + MultiTemplateParamsArg(*this, 0, 0)); +} + +/// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with +/// no declarator (e.g. "struct foo;") is parsed. It also accopts template +/// parameters to cope with template friend declarations. +Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, + DeclSpec &DS, + MultiTemplateParamsArg TemplateParams) { + Decl *TagD = 0; + TagDecl *Tag = 0; + if (DS.getTypeSpecType() == DeclSpec::TST_class || + DS.getTypeSpecType() == DeclSpec::TST_struct || + DS.getTypeSpecType() == DeclSpec::TST_union || + DS.getTypeSpecType() == DeclSpec::TST_enum) { + TagD = DS.getRepAsDecl(); + + if (!TagD) // We probably had an error + return 0; + + // Note that the above type specs guarantee that the + // type rep is a Decl, whereas in many of the others + // it's a Type. + if (isa(TagD)) + Tag = cast(TagD); + else if (ClassTemplateDecl *CTD = dyn_cast(TagD)) + Tag = CTD->getTemplatedDecl(); + } + + if (Tag) { + Tag->setFreeStanding(); + if (Tag->isInvalidDecl()) + return Tag; + } + + if (unsigned TypeQuals = DS.getTypeQualifiers()) { + // Enforce C99 6.7.3p2: "Types other than pointer types derived from object + // or incomplete types shall not be restrict-qualified." + if (TypeQuals & DeclSpec::TQ_restrict) + Diag(DS.getRestrictSpecLoc(), + diag::err_typecheck_invalid_restrict_not_pointer_noarg) + << DS.getSourceRange(); + } + + if (DS.isConstexprSpecified()) { + // C++0x [dcl.constexpr]p1: constexpr can only be applied to declarations + // and definitions of functions and variables. + if (Tag) + Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_tag) + << (DS.getTypeSpecType() == DeclSpec::TST_class ? 0 : + DS.getTypeSpecType() == DeclSpec::TST_struct ? 1 : + DS.getTypeSpecType() == DeclSpec::TST_union ? 2 : 3); + else + Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_no_declarators); + // Don't emit warnings after this error. + return TagD; + } + + if (DS.isFriendSpecified()) { + // If we're dealing with a decl but not a TagDecl, assume that + // whatever routines created it handled the friendship aspect. + if (TagD && !Tag) + return 0; + return ActOnFriendTypeDecl(S, DS, TemplateParams); + } + + // Track whether we warned about the fact that there aren't any + // declarators. + bool emittedWarning = false; + + if (RecordDecl *Record = dyn_cast_or_null(Tag)) { + if (!Record->getDeclName() && Record->isCompleteDefinition() && + DS.getStorageClassSpec() != DeclSpec::SCS_typedef) { + if (getLangOpts().CPlusPlus || + Record->getDeclContext()->isRecord()) + return BuildAnonymousStructOrUnion(S, DS, AS, Record); + + Diag(DS.getLocStart(), diag::ext_no_declarators) + << DS.getSourceRange(); + emittedWarning = true; + } + } + + // Check for Microsoft C extension: anonymous struct. + if (getLangOpts().MicrosoftExt && !getLangOpts().CPlusPlus && + CurContext->isRecord() && + DS.getStorageClassSpec() == DeclSpec::SCS_unspecified) { + // Handle 2 kinds of anonymous struct: + // struct STRUCT; + // and + // STRUCT_TYPE; <- where STRUCT_TYPE is a typedef struct. + RecordDecl *Record = dyn_cast_or_null(Tag); + if ((Record && Record->getDeclName() && !Record->isCompleteDefinition()) || + (DS.getTypeSpecType() == DeclSpec::TST_typename && + DS.getRepAsType().get()->isStructureType())) { + Diag(DS.getLocStart(), diag::ext_ms_anonymous_struct) + << DS.getSourceRange(); + return BuildMicrosoftCAnonymousStruct(S, DS, Record); + } + } + + if (getLangOpts().CPlusPlus && + DS.getStorageClassSpec() != DeclSpec::SCS_typedef) + if (EnumDecl *Enum = dyn_cast_or_null(Tag)) + if (Enum->enumerator_begin() == Enum->enumerator_end() && + !Enum->getIdentifier() && !Enum->isInvalidDecl()) { + Diag(Enum->getLocation(), diag::ext_no_declarators) + << DS.getSourceRange(); + emittedWarning = true; + } + + // Skip all the checks below if we have a type error. + if (DS.getTypeSpecType() == DeclSpec::TST_error) return TagD; + + if (!DS.isMissingDeclaratorOk()) { + // Warn about typedefs of enums without names, since this is an + // extension in both Microsoft and GNU. + if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef && + Tag && isa(Tag)) { + Diag(DS.getLocStart(), diag::ext_typedef_without_a_name) + << DS.getSourceRange(); + return Tag; + } + + Diag(DS.getLocStart(), diag::ext_no_declarators) + << DS.getSourceRange(); + emittedWarning = true; + } + + // We're going to complain about a bunch of spurious specifiers; + // only do this if we're declaring a tag, because otherwise we + // should be getting diag::ext_no_declarators. + if (emittedWarning || (TagD && TagD->isInvalidDecl())) + return TagD; + + // Note that a linkage-specification sets a storage class, but + // 'extern "C" struct foo;' is actually valid and not theoretically + // useless. + if (DeclSpec::SCS scs = DS.getStorageClassSpec()) + if (!DS.isExternInLinkageSpec()) + Diag(DS.getStorageClassSpecLoc(), diag::warn_standalone_specifier) + << DeclSpec::getSpecifierName(scs); + + if (DS.isThreadSpecified()) + Diag(DS.getThreadSpecLoc(), diag::warn_standalone_specifier) << "__thread"; + if (DS.getTypeQualifiers()) { + if (DS.getTypeQualifiers() & DeclSpec::TQ_const) + Diag(DS.getConstSpecLoc(), diag::warn_standalone_specifier) << "const"; + if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile) + Diag(DS.getConstSpecLoc(), diag::warn_standalone_specifier) << "volatile"; + // Restrict is covered above. + } + if (DS.isInlineSpecified()) + Diag(DS.getInlineSpecLoc(), diag::warn_standalone_specifier) << "inline"; + if (DS.isVirtualSpecified()) + Diag(DS.getVirtualSpecLoc(), diag::warn_standalone_specifier) << "virtual"; + if (DS.isExplicitSpecified()) + Diag(DS.getExplicitSpecLoc(), diag::warn_standalone_specifier) <<"explicit"; + + if (DS.isModulePrivateSpecified() && + Tag && Tag->getDeclContext()->isFunctionOrMethod()) + Diag(DS.getModulePrivateSpecLoc(), diag::err_module_private_local_class) + << Tag->getTagKind() + << FixItHint::CreateRemoval(DS.getModulePrivateSpecLoc()); + + // Warn about ignored type attributes, for example: + // __attribute__((aligned)) struct A; + // Attributes should be placed after tag to apply to type declaration. + if (!DS.getAttributes().empty()) { + DeclSpec::TST TypeSpecType = DS.getTypeSpecType(); + if (TypeSpecType == DeclSpec::TST_class || + TypeSpecType == DeclSpec::TST_struct || + TypeSpecType == DeclSpec::TST_union || + TypeSpecType == DeclSpec::TST_enum) { + AttributeList* attrs = DS.getAttributes().getList(); + while (attrs) { + Diag(attrs->getScopeLoc(), + diag::warn_declspec_attribute_ignored) + << attrs->getName() + << (TypeSpecType == DeclSpec::TST_class ? 0 : + TypeSpecType == DeclSpec::TST_struct ? 1 : + TypeSpecType == DeclSpec::TST_union ? 2 : 3); + attrs = attrs->getNext(); + } + } + } + + return TagD; +} + +/// We are trying to inject an anonymous member into the given scope; +/// check if there's an existing declaration that can't be overloaded. +/// +/// \return true if this is a forbidden redeclaration +static bool CheckAnonMemberRedeclaration(Sema &SemaRef, + Scope *S, + DeclContext *Owner, + DeclarationName Name, + SourceLocation NameLoc, + unsigned diagnostic) { + LookupResult R(SemaRef, Name, NameLoc, Sema::LookupMemberName, + Sema::ForRedeclaration); + if (!SemaRef.LookupName(R, S)) return false; + + if (R.getAsSingle()) + return false; + + // Pick a representative declaration. + NamedDecl *PrevDecl = R.getRepresentativeDecl()->getUnderlyingDecl(); + assert(PrevDecl && "Expected a non-null Decl"); + + if (!SemaRef.isDeclInScope(PrevDecl, Owner, S)) + return false; + + SemaRef.Diag(NameLoc, diagnostic) << Name; + SemaRef.Diag(PrevDecl->getLocation(), diag::note_previous_declaration); + + return true; +} + +/// InjectAnonymousStructOrUnionMembers - Inject the members of the +/// anonymous struct or union AnonRecord into the owning context Owner +/// and scope S. This routine will be invoked just after we realize +/// that an unnamed union or struct is actually an anonymous union or +/// struct, e.g., +/// +/// @code +/// union { +/// int i; +/// float f; +/// }; // InjectAnonymousStructOrUnionMembers called here to inject i and +/// // f into the surrounding scope.x +/// @endcode +/// +/// This routine is recursive, injecting the names of nested anonymous +/// structs/unions into the owning context and scope as well. +static bool InjectAnonymousStructOrUnionMembers(Sema &SemaRef, Scope *S, + DeclContext *Owner, + RecordDecl *AnonRecord, + AccessSpecifier AS, + SmallVector &Chaining, + bool MSAnonStruct) { + unsigned diagKind + = AnonRecord->isUnion() ? diag::err_anonymous_union_member_redecl + : diag::err_anonymous_struct_member_redecl; + + bool Invalid = false; + + // Look every FieldDecl and IndirectFieldDecl with a name. + for (RecordDecl::decl_iterator D = AnonRecord->decls_begin(), + DEnd = AnonRecord->decls_end(); + D != DEnd; ++D) { + if ((isa(*D) || isa(*D)) && + cast(*D)->getDeclName()) { + ValueDecl *VD = cast(*D); + if (CheckAnonMemberRedeclaration(SemaRef, S, Owner, VD->getDeclName(), + VD->getLocation(), diagKind)) { + // C++ [class.union]p2: + // The names of the members of an anonymous union shall be + // distinct from the names of any other entity in the + // scope in which the anonymous union is declared. + Invalid = true; + } else { + // C++ [class.union]p2: + // For the purpose of name lookup, after the anonymous union + // definition, the members of the anonymous union are + // considered to have been defined in the scope in which the + // anonymous union is declared. + unsigned OldChainingSize = Chaining.size(); + if (IndirectFieldDecl *IF = dyn_cast(VD)) + for (IndirectFieldDecl::chain_iterator PI = IF->chain_begin(), + PE = IF->chain_end(); PI != PE; ++PI) + Chaining.push_back(*PI); + else + Chaining.push_back(VD); + + assert(Chaining.size() >= 2); + NamedDecl **NamedChain = + new (SemaRef.Context)NamedDecl*[Chaining.size()]; + for (unsigned i = 0; i < Chaining.size(); i++) + NamedChain[i] = Chaining[i]; + + IndirectFieldDecl* IndirectField = + IndirectFieldDecl::Create(SemaRef.Context, Owner, VD->getLocation(), + VD->getIdentifier(), VD->getType(), + NamedChain, Chaining.size()); + + IndirectField->setAccess(AS); + IndirectField->setImplicit(); + SemaRef.PushOnScopeChains(IndirectField, S); + + // That includes picking up the appropriate access specifier. + if (AS != AS_none) IndirectField->setAccess(AS); + + Chaining.resize(OldChainingSize); + } + } + } + + return Invalid; +} + +/// StorageClassSpecToVarDeclStorageClass - Maps a DeclSpec::SCS to +/// a VarDecl::StorageClass. Any error reporting is up to the caller: +/// illegal input values are mapped to SC_None. +static StorageClass +StorageClassSpecToVarDeclStorageClass(DeclSpec::SCS StorageClassSpec) { + switch (StorageClassSpec) { + 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 SC_None; + } + llvm_unreachable("unknown storage class specifier"); +} + +/// StorageClassSpecToFunctionDeclStorageClass - Maps a DeclSpec::SCS to +/// 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 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 SC_None; + } + llvm_unreachable("unknown storage class specifier"); +} + +/// BuildAnonymousStructOrUnion - Handle the declaration of an +/// anonymous structure or union. Anonymous unions are a C++ feature +/// (C++ [class.union]) and a C11 feature; anonymous structures +/// are a C11 feature and GNU C++ extension. +Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, + AccessSpecifier AS, + RecordDecl *Record) { + DeclContext *Owner = Record->getDeclContext(); + + // Diagnose whether this anonymous struct/union is an extension. + if (Record->isUnion() && !getLangOpts().CPlusPlus && !getLangOpts().C11) + Diag(Record->getLocation(), diag::ext_anonymous_union); + else if (!Record->isUnion() && getLangOpts().CPlusPlus) + Diag(Record->getLocation(), diag::ext_gnu_anonymous_struct); + else if (!Record->isUnion() && !getLangOpts().C11) + Diag(Record->getLocation(), diag::ext_c11_anonymous_struct); + + // C and C++ require different kinds of checks for anonymous + // structs/unions. + bool Invalid = false; + if (getLangOpts().CPlusPlus) { + const char* PrevSpec = 0; + unsigned DiagID; + if (Record->isUnion()) { + // C++ [class.union]p6: + // Anonymous unions declared in a named namespace or in the + // global namespace shall be declared static. + if (DS.getStorageClassSpec() != DeclSpec::SCS_static && + (isa(Owner) || + (isa(Owner) && + cast(Owner)->getDeclName()))) { + Diag(Record->getLocation(), diag::err_anonymous_union_not_static) + << FixItHint::CreateInsertion(Record->getLocation(), "static "); + + // Recover by adding 'static'. + DS.SetStorageClassSpec(*this, DeclSpec::SCS_static, SourceLocation(), + PrevSpec, DiagID); + } + // C++ [class.union]p6: + // A storage class is not allowed in a declaration of an + // anonymous union in a class scope. + else if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified && + isa(Owner)) { + Diag(DS.getStorageClassSpecLoc(), + diag::err_anonymous_union_with_storage_spec) + << FixItHint::CreateRemoval(DS.getStorageClassSpecLoc()); + + // Recover by removing the storage specifier. + DS.SetStorageClassSpec(*this, DeclSpec::SCS_unspecified, + SourceLocation(), + PrevSpec, DiagID); + } + } + + // Ignore const/volatile/restrict qualifiers. + if (DS.getTypeQualifiers()) { + if (DS.getTypeQualifiers() & DeclSpec::TQ_const) + Diag(DS.getConstSpecLoc(), diag::ext_anonymous_struct_union_qualified) + << Record->isUnion() << 0 + << FixItHint::CreateRemoval(DS.getConstSpecLoc()); + if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile) + Diag(DS.getVolatileSpecLoc(), + diag::ext_anonymous_struct_union_qualified) + << Record->isUnion() << 1 + << FixItHint::CreateRemoval(DS.getVolatileSpecLoc()); + if (DS.getTypeQualifiers() & DeclSpec::TQ_restrict) + Diag(DS.getRestrictSpecLoc(), + diag::ext_anonymous_struct_union_qualified) + << Record->isUnion() << 2 + << FixItHint::CreateRemoval(DS.getRestrictSpecLoc()); + + DS.ClearTypeQualifiers(); + } + + // C++ [class.union]p2: + // The member-specification of an anonymous union shall only + // define non-static data members. [Note: nested types and + // functions cannot be declared within an anonymous union. ] + for (DeclContext::decl_iterator Mem = Record->decls_begin(), + MemEnd = Record->decls_end(); + Mem != MemEnd; ++Mem) { + if (FieldDecl *FD = dyn_cast(*Mem)) { + // C++ [class.union]p3: + // An anonymous union shall not have private or protected + // members (clause 11). + assert(FD->getAccess() != AS_none); + if (FD->getAccess() != AS_public) { + Diag(FD->getLocation(), diag::err_anonymous_record_nonpublic_member) + << (int)Record->isUnion() << (int)(FD->getAccess() == AS_protected); + Invalid = true; + } + + // C++ [class.union]p1 + // An object of a class with a non-trivial constructor, a non-trivial + // copy constructor, a non-trivial destructor, or a non-trivial copy + // assignment operator cannot be a member of a union, nor can an + // array of such objects. + if (CheckNontrivialField(FD)) + Invalid = true; + } else if ((*Mem)->isImplicit()) { + // Any implicit members are fine. + } else if (isa(*Mem) && (*Mem)->getDeclContext() != Record) { + // This is a type that showed up in an + // elaborated-type-specifier inside the anonymous struct or + // union, but which actually declares a type outside of the + // anonymous struct or union. It's okay. + } else if (RecordDecl *MemRecord = dyn_cast(*Mem)) { + if (!MemRecord->isAnonymousStructOrUnion() && + MemRecord->getDeclName()) { + // Visual C++ allows type definition in anonymous struct or union. + if (getLangOpts().MicrosoftExt) + Diag(MemRecord->getLocation(), diag::ext_anonymous_record_with_type) + << (int)Record->isUnion(); + else { + // This is a nested type declaration. + Diag(MemRecord->getLocation(), diag::err_anonymous_record_with_type) + << (int)Record->isUnion(); + Invalid = true; + } + } + } else if (isa(*Mem)) { + // Any access specifier is fine. + } else { + // We have something that isn't a non-static data + // member. Complain about it. + unsigned DK = diag::err_anonymous_record_bad_member; + if (isa(*Mem)) + DK = diag::err_anonymous_record_with_type; + else if (isa(*Mem)) + DK = diag::err_anonymous_record_with_function; + else if (isa(*Mem)) + DK = diag::err_anonymous_record_with_static; + + // Visual C++ allows type definition in anonymous struct or union. + if (getLangOpts().MicrosoftExt && + DK == diag::err_anonymous_record_with_type) + Diag((*Mem)->getLocation(), diag::ext_anonymous_record_with_type) + << (int)Record->isUnion(); + else { + Diag((*Mem)->getLocation(), DK) + << (int)Record->isUnion(); + Invalid = true; + } + } + } + } + + if (!Record->isUnion() && !Owner->isRecord()) { + Diag(Record->getLocation(), diag::err_anonymous_struct_not_member) + << (int)getLangOpts().CPlusPlus; + Invalid = true; + } + + // Mock up a declarator. + Declarator Dc(DS, Declarator::MemberContext); + TypeSourceInfo *TInfo = GetTypeForDeclarator(Dc, S); + assert(TInfo && "couldn't build declarator info for anonymous struct/union"); + + // Create a declaration for this anonymous struct/union. + NamedDecl *Anon = 0; + if (RecordDecl *OwningClass = dyn_cast(Owner)) { + Anon = FieldDecl::Create(Context, OwningClass, + DS.getLocStart(), + Record->getLocation(), + /*IdentifierInfo=*/0, + Context.getTypeDeclType(Record), + TInfo, + /*BitWidth=*/0, /*Mutable=*/false, + /*HasInit=*/false); + Anon->setAccess(AS); + if (getLangOpts().CPlusPlus) + FieldCollector->Add(cast(Anon)); + } else { + DeclSpec::SCS SCSpec = DS.getStorageClassSpec(); + assert(SCSpec != DeclSpec::SCS_typedef && + "Parser allowed 'typedef' as storage class VarDecl."); + 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 = SC_None; + } + SCSpec = DS.getStorageClassSpecAsWritten(); + VarDecl::StorageClass SCAsWritten + = StorageClassSpecToVarDeclStorageClass(SCSpec); + + Anon = VarDecl::Create(Context, Owner, + DS.getLocStart(), + Record->getLocation(), /*IdentifierInfo=*/0, + Context.getTypeDeclType(Record), + TInfo, SC, SCAsWritten); + + // Default-initialize the implicit variable. This initialization will be + // trivial in almost all cases, except if a union member has an in-class + // initializer: + // union { int n = 0; }; + ActOnUninitializedDecl(Anon, /*TypeMayContainAuto=*/false); + } + Anon->setImplicit(); + + // Add the anonymous struct/union object to the current + // context. We'll be referencing this object when we refer to one of + // its members. + Owner->addDecl(Anon); + + // Inject the members of the anonymous struct/union into the owning + // context and into the identifier resolver chain for name lookup + // purposes. + SmallVector Chain; + Chain.push_back(Anon); + + if (InjectAnonymousStructOrUnionMembers(*this, S, Owner, Record, AS, + Chain, false)) + Invalid = true; + + // Mark this as an anonymous struct/union type. Note that we do not + // do this until after we have already checked and injected the + // members of this anonymous struct/union type, because otherwise + // the members could be injected twice: once by DeclContext when it + // builds its lookup table, and once by + // InjectAnonymousStructOrUnionMembers. + Record->setAnonymousStructOrUnion(true); + + if (Invalid) + Anon->setInvalidDecl(); + + return Anon; +} + +/// BuildMicrosoftCAnonymousStruct - Handle the declaration of an +/// Microsoft C anonymous structure. +/// Ref: http://msdn.microsoft.com/en-us/library/z2cx9y4f.aspx +/// Example: +/// +/// struct A { int a; }; +/// struct B { struct A; int b; }; +/// +/// void foo() { +/// B var; +/// var.a = 3; +/// } +/// +Decl *Sema::BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS, + RecordDecl *Record) { + + // If there is no Record, get the record via the typedef. + if (!Record) + Record = DS.getRepAsType().get()->getAsStructureType()->getDecl(); + + // Mock up a declarator. + Declarator Dc(DS, Declarator::TypeNameContext); + TypeSourceInfo *TInfo = GetTypeForDeclarator(Dc, S); + assert(TInfo && "couldn't build declarator info for anonymous struct"); + + // Create a declaration for this anonymous struct. + NamedDecl* Anon = FieldDecl::Create(Context, + cast(CurContext), + DS.getLocStart(), + DS.getLocStart(), + /*IdentifierInfo=*/0, + Context.getTypeDeclType(Record), + TInfo, + /*BitWidth=*/0, /*Mutable=*/false, + /*HasInit=*/false); + Anon->setImplicit(); + + // Add the anonymous struct object to the current context. + CurContext->addDecl(Anon); + + // Inject the members of the anonymous struct into the current + // context and into the identifier resolver chain for name lookup + // purposes. + SmallVector Chain; + Chain.push_back(Anon); + + RecordDecl *RecordDef = Record->getDefinition(); + if (!RecordDef || InjectAnonymousStructOrUnionMembers(*this, S, CurContext, + RecordDef, AS_none, + Chain, true)) + Anon->setInvalidDecl(); + + return Anon; +} + +/// GetNameForDeclarator - Determine the full declaration name for the +/// given Declarator. +DeclarationNameInfo Sema::GetNameForDeclarator(Declarator &D) { + return GetNameFromUnqualifiedId(D.getName()); +} + +/// \brief Retrieves the declaration name from a parsed unqualified-id. +DeclarationNameInfo +Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) { + DeclarationNameInfo NameInfo; + NameInfo.setLoc(Name.StartLocation); + + switch (Name.getKind()) { + + case UnqualifiedId::IK_ImplicitSelfParam: + 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()) + + llvm_unreachable("Unknown name kind"); +} + +static QualType getCoreType(QualType Ty) { + do { + if (Ty->isPointerType() || Ty->isReferenceType()) + Ty = Ty->getPointeeType(); + else if (Ty->isArrayType()) + Ty = Ty->castAsArrayTypeUnsafe()->getElementType(); + else + return Ty.withoutLocalFastQualifiers(); + } while (true); +} + +/// hasSimilarParameters - Determine whether the C++ functions Declaration +/// and Definition have "nearly" matching parameters. This heuristic is +/// used to improve diagnostics in the case where an out-of-line function +/// definition doesn't match any declaration within the class or namespace. +/// Also sets Params to the list of indices to the parameters that differ +/// between the declaration and the definition. If hasSimilarParameters +/// returns true and Params is empty, then all of the parameters match. +static bool hasSimilarParameters(ASTContext &Context, + FunctionDecl *Declaration, + FunctionDecl *Definition, + llvm::SmallVectorImpl &Params) { + Params.clear(); + if (Declaration->param_size() != Definition->param_size()) + return false; + for (unsigned Idx = 0; Idx < Declaration->param_size(); ++Idx) { + QualType DeclParamTy = Declaration->getParamDecl(Idx)->getType(); + QualType DefParamTy = Definition->getParamDecl(Idx)->getType(); + + // The parameter types are identical + if (Context.hasSameType(DefParamTy, DeclParamTy)) + continue; + + QualType DeclParamBaseTy = getCoreType(DeclParamTy); + QualType DefParamBaseTy = getCoreType(DefParamTy); + const IdentifierInfo *DeclTyName = DeclParamBaseTy.getBaseTypeIdentifier(); + const IdentifierInfo *DefTyName = DefParamBaseTy.getBaseTypeIdentifier(); + + if (Context.hasSameUnqualifiedType(DeclParamBaseTy, DefParamBaseTy) || + (DeclTyName && DeclTyName == DefTyName)) + Params.push_back(Idx); + else // The two parameters aren't even close + return false; + } + + return true; +} + +/// NeedsRebuildingInCurrentInstantiation - Checks whether the given +/// declarator needs to be rebuilt in the current instantiation. +/// Any bits of declarator which appear before the name are valid for +/// consideration here. That's specifically the type in the decl spec +/// and the base type in any member-pointer chunks. +static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D, + DeclarationName Name) { + // The types we specifically need to rebuild are: + // - typenames, typeofs, and decltypes + // - types which will become injected class names + // Of course, we also need to rebuild any type referencing such a + // type. It's safest to just say "dependent", but we call out a + // few cases here. + + DeclSpec &DS = D.getMutableDeclSpec(); + switch (DS.getTypeSpecType()) { + case DeclSpec::TST_typename: + case DeclSpec::TST_typeofType: + case DeclSpec::TST_decltype: + case DeclSpec::TST_underlyingType: + case DeclSpec::TST_atomic: { + // Grab the type from the parser. + TypeSourceInfo *TSI = 0; + 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 + // of a waste; most dependent types should have type source info + // attached already. + if (!TSI) + TSI = S.Context.getTrivialTypeSourceInfo(T, DS.getTypeSpecTypeLoc()); + + // Rebuild the type in the current instantiation. + TSI = S.RebuildTypeInCurrentInstantiation(TSI, D.getIdentifierLoc(), Name); + if (!TSI) return true; + + // Store the new type back in the decl spec. + 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; + } + + default: + // Nothing to do for these decl specs. + break; + } + + // It doesn't matter what order we do this in. + for (unsigned I = 0, E = D.getNumTypeObjects(); I != E; ++I) { + DeclaratorChunk &Chunk = D.getTypeObject(I); + + // The only type information in the declarator which can come + // before the declaration name is the base type of a member + // pointer. + if (Chunk.Kind != DeclaratorChunk::MemberPointer) + continue; + + // Rebuild the scope specifier in-place. + CXXScopeSpec &SS = Chunk.Mem.Scope(); + if (S.RebuildNestedNameSpecifierInCurrentInstantiation(SS)) + return true; + } + + return false; +} + +Decl *Sema::ActOnDeclarator(Scope *S, Declarator &D) { + D.setFunctionDefinitionKind(FDK_Declaration); + Decl *Dcl = HandleDeclarator(S, D, MultiTemplateParamsArg(*this)); + + if (OriginalLexicalContext && OriginalLexicalContext->isObjCContainer() && + Dcl->getDeclContext()->isFileContext()) + Dcl->setTopLevelDeclInObjCContainer(); + + return Dcl; +} + +/// DiagnoseClassNameShadow - Implement C++ [class.mem]p13: +/// If T is the name of a class, then each of the following shall have a +/// name different from T: +/// - every static data member of class T; +/// - every member function of class T +/// - every member of class T that is itself a type; +/// \returns true if the declaration name violates these rules. +bool Sema::DiagnoseClassNameShadow(DeclContext *DC, + DeclarationNameInfo NameInfo) { + DeclarationName Name = NameInfo.getName(); + + if (CXXRecordDecl *Record = dyn_cast(DC)) + if (Record->getIdentifier() && Record->getDeclName() == Name) { + Diag(NameInfo.getLoc(), diag::err_member_name_of_class) << Name; + return true; + } + + return false; +} + +/// \brief Diagnose a declaration whose declarator-id has the given +/// nested-name-specifier. +/// +/// \param SS The nested-name-specifier of the declarator-id. +/// +/// \param DC The declaration context to which the nested-name-specifier +/// resolves. +/// +/// \param Name The name of the entity being declared. +/// +/// \param Loc The location of the name of the entity being declared. +/// +/// \returns true if we cannot safely recover from this error, false otherwise. +bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC, + DeclarationName Name, + SourceLocation Loc) { + DeclContext *Cur = CurContext; + while (isa(Cur)) + Cur = Cur->getParent(); + + // C++ [dcl.meaning]p1: + // A declarator-id shall not be qualified except for the definition + // of a member function (9.3) or static data member (9.4) outside of + // its class, the definition or explicit instantiation of a function + // or variable member of a namespace outside of its namespace, or the + // definition of an explicit specialization outside of its namespace, + // or the declaration of a friend function that is a member of + // another class or namespace (11.3). [...] + + // The user provided a superfluous scope specifier that refers back to the + // class or namespaces in which the entity is already declared. + // + // class X { + // void X::f(); + // }; + if (Cur->Equals(DC)) { + Diag(Loc, diag::warn_member_extra_qualification) + << Name << FixItHint::CreateRemoval(SS.getRange()); + SS.clear(); + return false; + } + + // Check whether the qualifying scope encloses the scope of the original + // declaration. + if (!Cur->Encloses(DC)) { + if (Cur->isRecord()) + Diag(Loc, diag::err_member_qualification) + << Name << SS.getRange(); + else if (isa(DC)) + Diag(Loc, diag::err_invalid_declarator_global_scope) + << Name << SS.getRange(); + else if (isa(Cur)) + Diag(Loc, diag::err_invalid_declarator_in_function) + << Name << SS.getRange(); + else + Diag(Loc, diag::err_invalid_declarator_scope) + << Name << cast(Cur) << cast(DC) << SS.getRange(); + + return true; + } + + if (Cur->isRecord()) { + // Cannot qualify members within a class. + Diag(Loc, diag::err_member_qualification) + << Name << SS.getRange(); + SS.clear(); + + // C++ constructors and destructors with incorrect scopes can break + // our AST invariants by having the wrong underlying types. If + // that's the case, then drop this declaration entirely. + if ((Name.getNameKind() == DeclarationName::CXXConstructorName || + Name.getNameKind() == DeclarationName::CXXDestructorName) && + !Context.hasSameType(Name.getCXXNameType(), + Context.getTypeDeclType(cast(Cur)))) + return true; + + return false; + } + + // C++11 [dcl.meaning]p1: + // [...] "The nested-name-specifier of the qualified declarator-id shall + // not begin with a decltype-specifer" + NestedNameSpecifierLoc SpecLoc(SS.getScopeRep(), SS.location_data()); + while (SpecLoc.getPrefix()) + SpecLoc = SpecLoc.getPrefix(); + if (dyn_cast_or_null( + SpecLoc.getNestedNameSpecifier()->getAsType())) + Diag(Loc, diag::err_decltype_in_declarator) + << SpecLoc.getTypeLoc().getSourceRange(); + + return false; +} + +Decl *Sema::HandleDeclarator(Scope *S, Declarator &D, + MultiTemplateParamsArg TemplateParamLists) { + // 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. + if (!Name) { + if (!D.isInvalidType()) // Reject this if we think it is valid. + Diag(D.getDeclSpec().getLocStart(), + diag::err_declarator_need_ident) + << D.getDeclSpec().getSourceRange() << D.getSourceRange(); + return 0; + } else if (DiagnoseUnexpandedParameterPack(NameInfo, UPPC_DeclarationType)) + return 0; + + // The scope passed in may not be a decl scope. Zip up the scope tree until + // we find one that is. + while ((S->getFlags() & Scope::DeclScope) == 0 || + (S->getFlags() & Scope::TemplateParamScope) != 0) + S = S->getParent(); + + DeclContext *DC = CurContext; + if (D.getCXXScopeSpec().isInvalid()) + D.setInvalidType(); + else if (D.getCXXScopeSpec().isSet()) { + if (DiagnoseUnexpandedParameterPack(D.getCXXScopeSpec(), + UPPC_DeclarationQualifier)) + return 0; + + bool EnteringContext = !D.getDeclSpec().isFriendSpecified(); + DC = computeDeclContext(D.getCXXScopeSpec(), EnteringContext); + if (!DC) { + // If we could not compute the declaration context, it's because the + // declaration context is dependent but does not refer to a class, + // class template, or class template partial specialization. Complain + // and return early, to avoid the coming semantic disaster. + Diag(D.getIdentifierLoc(), + diag::err_template_qualified_declarator_no_match) + << (NestedNameSpecifier*)D.getCXXScopeSpec().getScopeRep() + << D.getCXXScopeSpec().getRange(); + return 0; + } + bool IsDependentContext = DC->isDependentContext(); + + if (!IsDependentContext && + RequireCompleteDeclContext(D.getCXXScopeSpec(), DC)) + return 0; + + if (isa(DC) && !cast(DC)->hasDefinition()) { + Diag(D.getIdentifierLoc(), + diag::err_member_def_undefined_record) + << Name << DC << D.getCXXScopeSpec().getRange(); + D.setInvalidType(); + } else if (!D.getDeclSpec().isFriendSpecified()) { + if (diagnoseQualifiedDeclaration(D.getCXXScopeSpec(), DC, + Name, D.getIdentifierLoc())) { + if (DC->isRecord()) + return 0; + + D.setInvalidType(); + } + } + + // Check whether we need to rebuild the type of the given + // declaration in the current instantiation. + if (EnteringContext && IsDependentContext && + TemplateParamLists.size() != 0) { + ContextRAII SavedContext(*this, DC); + if (RebuildDeclaratorInCurrentInstantiation(*this, D, Name)) + D.setInvalidType(); + } + } + + if (DiagnoseClassNameShadow(DC, NameInfo)) + // If this is a typedef, we'll end up spewing multiple diagnostics. + // Just return early; it's safer. + if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) + return 0; + + NamedDecl *New; + + TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); + QualType R = TInfo->getType(); + + if (DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo, + UPPC_DeclarationType)) + D.setInvalidType(); + + LookupResult Previous(*this, NameInfo, LookupOrdinaryName, + ForRedeclaration); + + // See if this is a redefinition of a variable in the same scope. + if (!D.getCXXScopeSpec().isSet()) { + bool IsLinkageLookup = false; + + // If the declaration we're planning to build will be a function + // or object with linkage, then look for another declaration with + // linkage (C99 6.2.2p4-5 and C++ [basic.link]p6). + if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) + /* Do nothing*/; + else if (R->isFunctionType()) { + if (CurContext->isFunctionOrMethod() || + D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static) + IsLinkageLookup = true; + } else if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_extern) + IsLinkageLookup = true; + else if (CurContext->getRedeclContext()->isTranslationUnit() && + D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static) + IsLinkageLookup = true; + + if (IsLinkageLookup) + Previous.clear(LookupRedeclarationWithLinkage); + + LookupName(Previous, S, /* CreateBuiltins = */ IsLinkageLookup); + } else { // Something like "int foo::x;" + LookupQualifiedName(Previous, DC); + + // C++ [dcl.meaning]p1: + // When the declarator-id is qualified, the declaration shall refer to a + // previously declared member of the class or namespace to which the + // qualifier refers (or, in the case of a namespace, of an element of the + // inline namespace set of that namespace (7.3.1)) or to a specialization + // thereof; [...] + // + // Note that we already checked the context above, and that we do not have + // enough information to make sure that Previous contains the declaration + // we want to match. For example, given: + // + // class X { + // void f(); + // void f(float); + // }; + // + // void X::f(int) { } // ill-formed + // + // In this case, Previous will point to the overload set + // containing the two f's declared in X, but neither of them + // matches. + + // C++ [dcl.meaning]p1: + // [...] the member shall not merely have been introduced by a + // using-declaration in the scope of the class or namespace nominated by + // the nested-name-specifier of the declarator-id. + RemoveUsingDecls(Previous); + } + + if (Previous.isSingleResult() && + Previous.getFoundDecl()->isTemplateParameter()) { + // Maybe we will complain about the shadowed template parameter. + if (!D.isInvalidType()) + DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), + Previous.getFoundDecl()); + + // Just pretend that we didn't see the previous declaration. + Previous.clear(); + } + + // In C++, the previous declaration we find might be a tag type + // (class or enum). In this case, the new declaration will hide the + // tag type. Note that this does does not apply if we're declaring a + // typedef (C++ [dcl.typedef]p4). + if (Previous.isSingleTagDecl() && + D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef) + Previous.clear(); + + bool AddToScope = true; + if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) { + if (TemplateParamLists.size()) { + Diag(D.getIdentifierLoc(), diag::err_template_typedef); + return 0; + } + + New = ActOnTypedefDeclarator(S, D, DC, TInfo, Previous); + } else if (R->isFunctionType()) { + New = ActOnFunctionDeclarator(S, D, DC, TInfo, Previous, + move(TemplateParamLists), + AddToScope); + } else { + New = ActOnVariableDeclarator(S, D, DC, TInfo, Previous, + move(TemplateParamLists)); + } + + if (New == 0) + return 0; + + // If this has an identifier and is not an invalid redeclaration or + // function template specialization, add it to the scope stack. + if (New->getDeclName() && AddToScope && + !(D.isRedeclaration() && New->isInvalidDecl())) + PushOnScopeChains(New, S); + + return New; +} + +/// TryToFixInvalidVariablyModifiedType - Helper method to turn variable array +/// types into constant array types in certain situations which would otherwise +/// be errors (for GCC compatibility). +static QualType TryToFixInvalidVariablyModifiedType(QualType T, + ASTContext &Context, + 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, + Oversized); + if (FixedType.isNull()) return FixedType; + FixedType = Context.getPointerType(FixedType); + return Qs.apply(Context, FixedType); + } + if (const ParenType* PTy = dyn_cast(Ty)) { + QualType Inner = PTy->getInnerType(); + QualType FixedType = + TryToFixInvalidVariablyModifiedType(Inner, Context, SizeIsNegative, + Oversized); + if (FixedType.isNull()) return FixedType; + FixedType = Context.getParenType(FixedType); + return Qs.apply(Context, FixedType); + } + + const VariableArrayType* VLATy = dyn_cast(T); + if (!VLATy) + return QualType(); + // FIXME: We should probably handle this case + if (VLATy->getElementType()->isVariablyModifiedType()) + return QualType(); + + llvm::APSInt Res; + if (!VLATy->getSizeExpr() || + !VLATy->getSizeExpr()->EvaluateAsInt(Res, Context)) + return QualType(); + + // Check whether the array size is negative. + if (Res.isSigned() && Res.isNegative()) { + 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 +/// that it can be found later for redeclarations +void +Sema::RegisterLocallyScopedExternCDecl(NamedDecl *ND, + const LookupResult &Previous, + Scope *S) { + assert(ND->getLexicalDeclContext()->isFunctionOrMethod() && + "Decl is not a locally-scoped decl!"); + // Note that we have a locally-scoped external with this name. + LocallyScopedExternalDecls[ND->getDeclName()] = ND; + + if (!Previous.isSingleResult()) + return; + + NamedDecl *PrevDecl = Previous.getFoundDecl(); + + // If there was a previous declaration of this variable, it may be + // in our identifier chain. Update the identifier chain with the new + // declaration. + if (S && IdResolver.ReplaceDecl(PrevDecl, ND)) { + // The previous declaration was found on the identifer resolver + // chain, so remove it from its scope. + + if (S->isDeclScope(PrevDecl)) { + // Special case for redeclarations in the SAME scope. + // Because this declaration is going to be added to the identifier chain + // later, we should temporarily take it OFF the chain. + IdResolver.RemoveDecl(ND); + + } else { + // Find the scope for the original declaration. + while (S && !S->isDeclScope(PrevDecl)) + S = S->getParent(); + } + + if (S) + S->RemoveDecl(PrevDecl); + } +} + +llvm::DenseMap::iterator +Sema::findLocallyScopedExternalDecl(DeclarationName Name) { + if (ExternalSource) { + // Load locally-scoped external decls from the external source. + SmallVector Decls; + ExternalSource->ReadLocallyScopedExternalDecls(Decls); + for (unsigned I = 0, N = Decls.size(); I != N; ++I) { + llvm::DenseMap::iterator Pos + = LocallyScopedExternalDecls.find(Decls[I]->getDeclName()); + if (Pos == LocallyScopedExternalDecls.end()) + LocallyScopedExternalDecls[Decls[I]->getDeclName()] = Decls[I]; + } + } + + return LocallyScopedExternalDecls.find(Name); +} + +/// \brief Diagnose function specifiers on a declaration of an identifier that +/// does not identify a function. +void Sema::DiagnoseFunctionSpecifiers(Declarator& D) { + // FIXME: We should probably indicate the identifier in question to avoid + // confusion for constructs like "inline int a(), b;" + if (D.getDeclSpec().isInlineSpecified()) + Diag(D.getDeclSpec().getInlineSpecLoc(), + diag::err_inline_non_function); + + if (D.getDeclSpec().isVirtualSpecified()) + Diag(D.getDeclSpec().getVirtualSpecLoc(), + diag::err_virtual_non_function); + + if (D.getDeclSpec().isExplicitSpecified()) + Diag(D.getDeclSpec().getExplicitSpecLoc(), + diag::err_explicit_non_function); +} + +NamedDecl* +Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, + TypeSourceInfo *TInfo, LookupResult &Previous) { + // Typedef declarators cannot be qualified (C++ [dcl.meaning]p1). + if (D.getCXXScopeSpec().isSet()) { + Diag(D.getIdentifierLoc(), diag::err_qualified_typedef_declarator) + << D.getCXXScopeSpec().getRange(); + D.setInvalidType(); + // Pretend we didn't see the scope specifier. + DC = CurContext; + Previous.clear(); + } + + if (getLangOpts().CPlusPlus) { + // Check that there are no default arguments (C++ only). + CheckExtraCXXDefaultArguments(D); + } + + DiagnoseFunctionSpecifiers(D); + + if (D.getDeclSpec().isThreadSpecified()) + Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread); + if (D.getDeclSpec().isConstexprSpecified()) + Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_invalid_constexpr) + << 1; + + if (D.getName().Kind != UnqualifiedId::IK_Identifier) { + Diag(D.getName().StartLocation, diag::err_typedef_not_identifier) + << D.getName().getSourceRange(); + return 0; + } + + TypedefDecl *NewTD = ParseTypedefDecl(S, D, TInfo->getType(), TInfo); + if (!NewTD) return 0; + + // Handle attributes prior to checking for duplicates in MergeVarDecl + ProcessDeclAttributes(S, NewTD, D); + + CheckTypedefForVariablyModifiedType(S, NewTD); + + bool Redeclaration = D.isRedeclaration(); + NamedDecl *ND = ActOnTypedefNameDecl(S, DC, NewTD, Previous, Redeclaration); + D.setRedeclaration(Redeclaration); + return ND; +} + +void +Sema::CheckTypedefForVariablyModifiedType(Scope *S, TypedefNameDecl *NewTD) { + // 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()) { + getCurFunction()->setHasBranchProtectedScope(); + + if (S->getFnParent() == 0) { + bool SizeIsNegative; + llvm::APSInt Oversized; + QualType FixedTy = + TryToFixInvalidVariablyModifiedType(T, Context, SizeIsNegative, + Oversized); + if (!FixedTy.isNull()) { + Diag(NewTD->getLocation(), diag::warn_illegal_constant_array_size); + NewTD->setTypeSourceInfo(Context.getTrivialTypeSourceInfo(FixedTy)); + } else { + if (SizeIsNegative) + Diag(NewTD->getLocation(), diag::err_typecheck_negative_array_size); + else if (T->isVariableArrayType()) + Diag(NewTD->getLocation(), diag::err_vla_decl_in_file_scope); + else if (Oversized.getBoolValue()) + Diag(NewTD->getLocation(), diag::err_array_too_large) + << Oversized.toString(10); + else + Diag(NewTD->getLocation(), diag::err_vm_decl_in_file_scope); + NewTD->setInvalidDecl(); + } + } + } +} + + +/// ActOnTypedefNameDecl - Perform semantic checking for a declaration which +/// declares a typedef-name, either using the 'typedef' type specifier or via +/// a C++0x [dcl.typedef]p2 alias-declaration: 'using T = A;'. +NamedDecl* +Sema::ActOnTypedefNameDecl(Scope *S, DeclContext *DC, TypedefNameDecl *NewTD, + LookupResult &Previous, bool &Redeclaration) { + // Merge the decl with the existing one if appropriate. If the decl is + // in an outer scope, it isn't the same thing. + FilterLookupForScope(Previous, DC, S, /*ConsiderLinkage*/ false, + /*ExplicitInstantiationOrSpecialization=*/false); + if (!Previous.empty()) { + Redeclaration = true; + MergeTypedefNameDecl(NewTD, Previous); + } + + // If this is the C FILE type, notify the AST context. + if (IdentifierInfo *II = NewTD->getIdentifier()) + if (!NewTD->isInvalidDecl() && + NewTD->getDeclContext()->getRedeclContext()->isTranslationUnit()) { + if (II->isStr("FILE")) + Context.setFILEDecl(NewTD); + else if (II->isStr("jmp_buf")) + Context.setjmp_bufDecl(NewTD); + else if (II->isStr("sigjmp_buf")) + Context.setsigjmp_bufDecl(NewTD); + else if (II->isStr("ucontext_t")) + Context.setucontext_tDecl(NewTD); + else if (II->isStr("__builtin_va_list")) + Context.setBuiltinVaListType(Context.getTypedefType(NewTD)); + } + + return NewTD; +} + +/// \brief Determines whether the given declaration is an out-of-scope +/// previous declaration. +/// +/// This routine should be invoked when name lookup has found a +/// previous declaration (PrevDecl) that is not in the scope where a +/// new declaration by the same name is being introduced. If the new +/// declaration occurs in a local scope, previous declarations with +/// linkage may still be considered previous declarations (C99 +/// 6.2.2p4-5, C++ [basic.link]p6). +/// +/// \param PrevDecl the previous declaration found by name +/// lookup +/// +/// \param DC the context in which the new declaration is being +/// declared. +/// +/// \returns true if PrevDecl is an out-of-scope previous declaration +/// for a new delcaration with the same name. +static bool +isOutOfScopePreviousDeclaration(NamedDecl *PrevDecl, DeclContext *DC, + ASTContext &Context) { + if (!PrevDecl) + return false; + + if (!PrevDecl->hasLinkage()) + return false; + + if (Context.getLangOpts().CPlusPlus) { + // C++ [basic.link]p6: + // If there is a visible declaration of an entity with linkage + // having the same name and type, ignoring entities declared + // 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->getRedeclContext(); + if (!OuterContext->isFunctionOrMethod()) + // This rule only applies to block-scope declarations. + 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; +} + +static void SetNestedNameSpecifier(DeclaratorDecl *DD, Declarator &D) { + CXXScopeSpec &SS = D.getCXXScopeSpec(); + if (!SS.isSet()) return; + DD->setQualifierInfo(SS.getWithLocInContext(DD->getASTContext())); +} + +bool Sema::inferObjCARCLifetime(ValueDecl *decl) { + QualType type = decl->getType(); + Qualifiers::ObjCLifetime lifetime = type.getObjCLifetime(); + if (lifetime == Qualifiers::OCL_Autoreleasing) { + // Various kinds of declaration aren't allowed to be __autoreleasing. + unsigned kind = -1U; + if (VarDecl *var = dyn_cast(decl)) { + if (var->hasAttr()) + kind = 0; // __block + else if (!var->hasLocalStorage()) + kind = 1; // global + } else if (isa(decl)) { + kind = 3; // ivar + } else if (isa(decl)) { + kind = 2; // field + } + + if (kind != -1U) { + Diag(decl->getLocation(), diag::err_arc_autoreleasing_var) + << kind; + } + } else if (lifetime == Qualifiers::OCL_None) { + // Try to infer lifetime. + if (!type->isObjCLifetimeType()) + return false; + + lifetime = type->getObjCARCImplicitLifetime(); + type = Context.getLifetimeQualifiedType(type, lifetime); + decl->setType(type); + } + + if (VarDecl *var = dyn_cast(decl)) { + // Thread-local variables cannot have lifetime. + if (lifetime && lifetime != Qualifiers::OCL_ExplicitNone && + var->isThreadSpecified()) { + Diag(var->getLocation(), diag::err_arc_thread_ownership) + << var->getType(); + return true; + } + } + + return false; +} + +NamedDecl* +Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, + TypeSourceInfo *TInfo, LookupResult &Previous, + MultiTemplateParamsArg TemplateParamLists) { + QualType R = TInfo->getType(); + DeclarationName Name = GetNameForDeclarator(D).getName(); + + // Check that there are no default arguments (C++ only). + if (getLangOpts().CPlusPlus) + CheckExtraCXXDefaultArguments(D); + + DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpec(); + assert(SCSpec != DeclSpec::SCS_typedef && + "Parser allowed 'typedef' as storage class VarDecl."); + 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 = SC_None; + } + SCSpec = D.getDeclSpec().getStorageClassSpecAsWritten(); + VarDecl::StorageClass SCAsWritten + = StorageClassSpecToVarDeclStorageClass(SCSpec); + + IdentifierInfo *II = Name.getAsIdentifierInfo(); + if (!II) { + Diag(D.getIdentifierLoc(), diag::err_bad_variable_name) + << Name; + return 0; + } + + DiagnoseFunctionSpecifiers(D); + + 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 == SC_Auto || SC == SC_Register) { + + // If this is a register variable with an asm label specified, then this + // is a GNU extension. + if (SC == SC_Register && D.getAsmLabel()) + Diag(D.getIdentifierLoc(), diag::err_unsupported_global_register); + else + Diag(D.getIdentifierLoc(), diag::err_typecheck_sclass_fscope); + D.setInvalidType(); + } + } + + if (getLangOpts().OpenCL) { + // Set up the special work-group-local storage class for variables in the + // OpenCL __local address space. + if (R.getAddressSpace() == LangAS::opencl_local) + SC = SC_OpenCLWorkGroupLocal; + } + + bool isExplicitSpecialization = false; + VarDecl *NewVD; + if (!getLangOpts().CPlusPlus) { + NewVD = VarDecl::Create(Context, DC, D.getLocStart(), + D.getIdentifierLoc(), II, + R, TInfo, SC, SCAsWritten); + + if (D.isInvalidType()) + NewVD->setInvalidDecl(); + } else { + if (DC->isRecord() && !CurContext->isRecord()) { + // This is an out-of-line definition of a static data member. + if (SC == SC_Static) { + Diag(D.getDeclSpec().getStorageClassSpecLoc(), + diag::err_static_out_of_line) + << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc()); + } else if (SC == SC_None) + SC = SC_Static; + } + if (SC == SC_Static && CurContext->isRecord()) { + if (const CXXRecordDecl *RD = dyn_cast(DC)) { + if (RD->isLocalClass()) + Diag(D.getIdentifierLoc(), + diag::err_static_data_member_not_allowed_in_local_class) + << Name << RD->getDeclName(); + + // C++98 [class.union]p1: If a union contains a static data member, + // the program is ill-formed. C++11 drops this restriction. + if (RD->isUnion()) + Diag(D.getIdentifierLoc(), + getLangOpts().CPlusPlus0x + ? diag::warn_cxx98_compat_static_data_member_in_union + : diag::ext_static_data_member_in_union) << Name; + // We conservatively disallow static data members in anonymous structs. + else if (!RD->getDeclName()) + Diag(D.getIdentifierLoc(), + diag::err_static_data_member_not_allowed_in_anon_struct) + << Name << RD->isUnion(); + } + } + + // Match up the template parameter lists with the scope specifier, then + // determine whether we have a template or a template specialization. + isExplicitSpecialization = false; + bool Invalid = false; + if (TemplateParameterList *TemplateParams + = MatchTemplateParametersToScopeSpecifier( + D.getDeclSpec().getLocStart(), + D.getIdentifierLoc(), + D.getCXXScopeSpec(), + TemplateParamLists.get(), + TemplateParamLists.size(), + /*never a friend*/ false, + isExplicitSpecialization, + Invalid)) { + if (TemplateParams->size() > 0) { + // There is no such thing as a variable template. + Diag(D.getIdentifierLoc(), diag::err_template_variable) + << II + << SourceRange(TemplateParams->getTemplateLoc(), + TemplateParams->getRAngleLoc()); + return 0; + } else { + // There is an extraneous 'template<>' for this variable. Complain + // about it, but allow the declaration of the variable. + Diag(TemplateParams->getTemplateLoc(), + diag::err_template_variable_noparams) + << II + << SourceRange(TemplateParams->getTemplateLoc(), + TemplateParams->getRAngleLoc()); + } + } + + NewVD = VarDecl::Create(Context, DC, D.getLocStart(), + D.getIdentifierLoc(), II, + R, TInfo, SC, SCAsWritten); + + // If this decl has an auto type in need of deduction, make a note of the + // Decl so we can diagnose uses of it in its own initializer. + if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto && + R->getContainedAutoType()) + ParsingInitForAutoVars.insert(NewVD); + + if (D.isInvalidType() || Invalid) + NewVD->setInvalidDecl(); + + SetNestedNameSpecifier(NewVD, D); + + if (TemplateParamLists.size() > 0 && D.getCXXScopeSpec().isSet()) { + NewVD->setTemplateParameterListsInfo(Context, + TemplateParamLists.size(), + TemplateParamLists.release()); + } + + if (D.getDeclSpec().isConstexprSpecified()) + NewVD->setConstexpr(true); + } + + // Set the lexical context. If the declarator has a C++ scope specifier, the + // lexical context will be different from the semantic context. + NewVD->setLexicalDeclContext(CurContext); + + if (D.getDeclSpec().isThreadSpecified()) { + if (NewVD->hasLocalStorage()) + Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_thread_non_global); + else if (!Context.getTargetInfo().isTLSSupported()) + Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_thread_unsupported); + else + NewVD->setThreadSpecified(true); + } + + if (D.getDeclSpec().isModulePrivateSpecified()) { + if (isExplicitSpecialization) + Diag(NewVD->getLocation(), diag::err_module_private_specialization) + << 2 + << FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc()); + else if (NewVD->hasLocalStorage()) + Diag(NewVD->getLocation(), diag::err_module_private_local) + << 0 << NewVD->getDeclName() + << SourceRange(D.getDeclSpec().getModulePrivateSpecLoc()) + << FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc()); + else + NewVD->setModulePrivate(); + } + + // Handle attributes prior to checking for duplicates in MergeVarDecl + ProcessDeclAttributes(S, NewVD, D); + + // In auto-retain/release, infer strong retension for variables of + // retainable type. + if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(NewVD)) + NewVD->setInvalidDecl(); + + // Handle GNU asm-label extension (encoded as an attribute). + if (Expr *E = (Expr*)D.getAsmLabel()) { + // The parser guarantees this is a string. + StringLiteral *SE = cast(E); + StringRef Label = SE->getString(); + if (S->getFnParent() != 0) { + switch (SC) { + case SC_None: + case SC_Auto: + Diag(E->getExprLoc(), diag::warn_asm_label_on_auto_decl) << Label; + break; + case SC_Register: + if (!Context.getTargetInfo().isValidGCCRegisterName(Label)) + Diag(E->getExprLoc(), diag::err_asm_unknown_register_name) << Label; + break; + case SC_Static: + case SC_Extern: + case SC_PrivateExtern: + case SC_OpenCLWorkGroupLocal: + break; + } + } + + NewVD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0), + Context, Label)); + } else if (!ExtnameUndeclaredIdentifiers.empty()) { + llvm::DenseMap::iterator I = + ExtnameUndeclaredIdentifiers.find(NewVD->getIdentifier()); + if (I != ExtnameUndeclaredIdentifiers.end()) { + NewVD->addAttr(I->second); + ExtnameUndeclaredIdentifiers.erase(I); + } + } + + // Diagnose shadowed variables before filtering for scope. + if (!D.getCXXScopeSpec().isSet()) + CheckShadow(S, NewVD, Previous); + + // Don't consider existing declarations that are in a different + // scope and are out-of-semantic-context declarations (if the new + // declaration has linkage). + FilterLookupForScope(Previous, DC, S, NewVD->hasLinkage(), + isExplicitSpecialization); + + if (!getLangOpts().CPlusPlus) { + D.setRedeclaration(CheckVariableDeclaration(NewVD, Previous)); + } else { + // Merge the decl with the existing one if appropriate. + if (!Previous.empty()) { + if (Previous.isSingleResult() && + isa(Previous.getFoundDecl()) && + D.getCXXScopeSpec().isSet()) { + // The user tried to define a non-static data member + // out-of-line (C++ [dcl.meaning]p1). + Diag(NewVD->getLocation(), diag::err_nonstatic_member_out_of_line) + << D.getCXXScopeSpec().getRange(); + Previous.clear(); + NewVD->setInvalidDecl(); + } + } else if (D.getCXXScopeSpec().isSet()) { + // No previous declaration in the qualifying scope. + Diag(D.getIdentifierLoc(), diag::err_no_member) + << Name << computeDeclContext(D.getCXXScopeSpec(), true) + << D.getCXXScopeSpec().getRange(); + NewVD->setInvalidDecl(); + } + + D.setRedeclaration(CheckVariableDeclaration(NewVD, Previous)); + + // This is an explicit specialization of a static data member. Check it. + if (isExplicitSpecialization && !NewVD->isInvalidDecl() && + CheckMemberSpecialization(NewVD, Previous)) + 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()) && + Def != NewVD && D.hasAttributes()) { + Diag(NewVD->getLocation(), diag::warn_attribute_precede_definition); + Diag(Def->getLocation(), diag::note_previous_definition); + } + } + + // If this is a locally-scoped extern C variable, update the map of + // such variables. + if (CurContext->isFunctionOrMethod() && NewVD->isExternC() && + !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; +} + +/// \brief Diagnose variable or built-in function shadowing. Implements +/// -Wshadow. +/// +/// This method is called whenever a VarDecl is added to a "useful" +/// scope. +/// +/// \param S the scope in which the shadowing name is being declared +/// \param R the lookup of the name +/// +void Sema::CheckShadow(Scope *S, VarDecl *D, const LookupResult& R) { + // Return if warning is ignored. + if (Diags.getDiagnosticLevel(diag::warn_decl_shadow, R.getNameLoc()) == + DiagnosticsEngine::Ignored) + return; + + // Don't diagnose declarations at file scope. + if (D->hasGlobalStorage()) + return; + + DeclContext *NewDC = D->getDeclContext(); + + // Only diagnose if we're shadowing an unambiguous field or variable. + if (R.getResultKind() != LookupResult::Found) + return; + + NamedDecl* ShadowedDecl = R.getFoundDecl(); + if (!isa(ShadowedDecl) && !isa(ShadowedDecl)) + return; + + // Fields are not shadowed by variables in C++ static methods. + if (isa(ShadowedDecl)) + if (CXXMethodDecl *MD = dyn_cast(NewDC)) + if (MD->isStatic()) + return; + + if (VarDecl *shadowedVar = dyn_cast(ShadowedDecl)) + if (shadowedVar->isExternC()) { + // For shadowing external vars, make sure that we point to the global + // declaration, not a locally scoped extern declaration. + for (VarDecl::redecl_iterator + I = shadowedVar->redecls_begin(), E = shadowedVar->redecls_end(); + I != E; ++I) + if (I->isFileVarDecl()) { + ShadowedDecl = *I; + break; + } + } + + DeclContext *OldDC = ShadowedDecl->getDeclContext(); + + // Only warn about certain kinds of shadowing for class members. + if (NewDC && NewDC->isRecord()) { + // In particular, don't warn about shadowing non-class members. + if (!OldDC->isRecord()) + return; + + // TODO: should we warn about static data members shadowing + // static data members from base classes? + + // TODO: don't diagnose for inaccessible shadowed members. + // This is hard to do perfectly because we might friend the + // shadowing context, but that's just a false negative. + } + + // Determine what kind of declaration we're shadowing. + unsigned Kind; + if (isa(OldDC)) { + if (isa(ShadowedDecl)) + Kind = 3; // field + else + Kind = 2; // static data member + } else if (OldDC->isFileContext()) + Kind = 1; // global + else + Kind = 0; // local + + DeclarationName Name = R.getLookupName(); + + // Emit warning and note. + Diag(R.getNameLoc(), diag::warn_decl_shadow) << Name << Kind << OldDC; + Diag(ShadowedDecl->getLocation(), diag::note_previous_declaration); +} + +/// \brief Check -Wshadow without the advantage of a previous lookup. +void Sema::CheckShadow(Scope *S, VarDecl *D) { + if (Diags.getDiagnosticLevel(diag::warn_decl_shadow, D->getLocation()) == + DiagnosticsEngine::Ignored) + return; + + LookupResult R(*this, D->getDeclName(), D->getLocation(), + Sema::LookupOrdinaryName, Sema::ForRedeclaration); + LookupName(R, S); + CheckShadow(S, D, R); +} + +/// \brief Perform semantic checking on a newly-created variable +/// declaration. +/// +/// This routine performs all of the type-checking required for a +/// variable declaration once it has been built. It is used both to +/// check variables after they have been parsed and their declarators +/// have been translated into a declaration, and to check variables +/// that have been instantiated from a template. +/// +/// Sets NewVD->isInvalidDecl() if an error was encountered. +/// +/// Returns true if the variable declaration is a redeclaration. +bool Sema::CheckVariableDeclaration(VarDecl *NewVD, + LookupResult &Previous) { + // If the decl is already known invalid, don't check it. + if (NewVD->isInvalidDecl()) + return false; + + QualType T = NewVD->getType(); + + if (T->isObjCObjectType()) { + Diag(NewVD->getLocation(), diag::err_statically_allocated_object) + << FixItHint::CreateInsertion(NewVD->getLocation(), "*"); + T = Context.getObjCObjectPointerType(T); + NewVD->setType(T); + } + + // Emit an error if an address space was applied to decl with local storage. + // This includes arrays of objects with address space qualifiers, but not + // automatic variables that point to other address spaces. + // ISO/IEC TR 18037 S5.1.2 + if (NewVD->hasLocalStorage() && T.getAddressSpace() != 0) { + Diag(NewVD->getLocation(), diag::err_as_qualified_auto_decl); + NewVD->setInvalidDecl(); + return false; + } + + if (NewVD->hasLocalStorage() && T.isObjCGCWeak() + && !NewVD->hasAttr()) { + if (getLangOpts().getGC() != LangOptions::NonGC) + Diag(NewVD->getLocation(), diag::warn_gc_attribute_weak_on_local); + else + Diag(NewVD->getLocation(), diag::warn_attribute_weak_on_local); + } + + bool isVM = T->isVariablyModifiedType(); + if (isVM || NewVD->hasAttr() || + NewVD->hasAttr()) + getCurFunction()->setHasBranchProtectedScope(); + + if ((isVM && NewVD->hasLinkage()) || + (T->isVariableArrayType() && NewVD->hasGlobalStorage())) { + bool SizeIsNegative; + llvm::APSInt Oversized; + QualType FixedTy = + TryToFixInvalidVariablyModifiedType(T, Context, SizeIsNegative, + Oversized); + + if (FixedTy.isNull() && T->isVariableArrayType()) { + const VariableArrayType *VAT = Context.getAsVariableArrayType(T); + // FIXME: This won't give the correct result for + // int a[10][n]; + SourceRange SizeRange = VAT->getSizeExpr()->getSourceRange(); + + if (NewVD->isFileVarDecl()) + Diag(NewVD->getLocation(), diag::err_vla_decl_in_file_scope) + << SizeRange; + else if (NewVD->getStorageClass() == SC_Static) + Diag(NewVD->getLocation(), diag::err_vla_decl_has_static_storage) + << SizeRange; + else + Diag(NewVD->getLocation(), diag::err_vla_decl_has_extern_linkage) + << SizeRange; + NewVD->setInvalidDecl(); + return false; + } + + if (FixedTy.isNull()) { + if (NewVD->isFileVarDecl()) + Diag(NewVD->getLocation(), diag::err_vm_decl_in_file_scope); + else + Diag(NewVD->getLocation(), diag::err_vm_decl_has_extern_linkage); + NewVD->setInvalidDecl(); + return false; + } + + Diag(NewVD->getLocation(), diag::warn_illegal_constant_array_size); + NewVD->setType(FixedTy); + } + + if (Previous.empty() && NewVD->isExternC()) { + // Since we did not find anything by this name and we're declaring + // an extern "C" variable, look for a non-visible extern "C" + // declaration with the same name. + llvm::DenseMap::iterator Pos + = findLocallyScopedExternalDecl(NewVD->getDeclName()); + if (Pos != LocallyScopedExternalDecls.end()) + Previous.addDecl(Pos->second); + } + + if (T->isVoidType() && !NewVD->hasExternalStorage()) { + Diag(NewVD->getLocation(), diag::err_typecheck_decl_incomplete_type) + << T; + NewVD->setInvalidDecl(); + return false; + } + + if (!NewVD->hasLocalStorage() && NewVD->hasAttr()) { + Diag(NewVD->getLocation(), diag::err_block_on_nonlocal); + NewVD->setInvalidDecl(); + return false; + } + + if (isVM && NewVD->hasAttr()) { + Diag(NewVD->getLocation(), diag::err_block_on_vm); + NewVD->setInvalidDecl(); + return false; + } + + if (NewVD->isConstexpr() && !T->isDependentType() && + RequireLiteralType(NewVD->getLocation(), T, + PDiag(diag::err_constexpr_var_non_literal))) { + NewVD->setInvalidDecl(); + return false; + } + + if (!Previous.empty()) { + MergeVarDecl(NewVD, Previous); + return true; + } + return false; +} + +/// \brief Data used with FindOverriddenMethod +struct FindOverriddenMethodData { + Sema *S; + CXXMethodDecl *Method; +}; + +/// \brief Member lookup function that determines whether a given C++ +/// method overrides a method in a base class, to be used with +/// CXXRecordDecl::lookupInBases(). +static bool FindOverriddenMethod(const CXXBaseSpecifier *Specifier, + CXXBasePath &Path, + void *UserData) { + RecordDecl *BaseRecord = Specifier->getType()->getAs()->getDecl(); + + FindOverriddenMethodData *Data + = reinterpret_cast(UserData); + + DeclarationName Name = Data->Method->getDeclName(); + + // FIXME: Do we care about other names here too? + if (Name.getNameKind() == DeclarationName::CXXDestructorName) { + // We really want to find the base class destructor here. + QualType T = Data->S->Context.getTypeDeclType(BaseRecord); + CanQualType CT = Data->S->Context.getCanonicalType(T); + + Name = Data->S->Context.DeclarationNames.getCXXDestructorName(CT); + } + + for (Path.Decls = BaseRecord->lookup(Name); + Path.Decls.first != Path.Decls.second; + ++Path.Decls.first) { + NamedDecl *D = *Path.Decls.first; + if (CXXMethodDecl *MD = dyn_cast(D)) { + if (MD->isVirtual() && !Data->S->IsOverload(Data->Method, MD, false)) + return true; + } + } + + return false; +} + +static bool hasDelayedExceptionSpec(CXXMethodDecl *Method) { + const FunctionProtoType *Proto =Method->getType()->getAs(); + return Proto && Proto->getExceptionSpecType() == EST_Delayed; +} + +/// AddOverriddenMethods - See if a method overrides any in the base classes, +/// and if so, check that it's a valid override and remember it. +bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) { + // Look for virtual methods in base classes that this method might override. + CXXBasePaths Paths; + FindOverriddenMethodData Data; + Data.Method = MD; + Data.S = this; + bool AddedAny = false; + if (DC->lookupInBases(&FindOverriddenMethod, &Data, Paths)) { + for (CXXBasePaths::decl_iterator I = Paths.found_decls_begin(), + E = Paths.found_decls_end(); I != E; ++I) { + if (CXXMethodDecl *OldMD = dyn_cast(*I)) { + MD->addOverriddenMethod(OldMD->getCanonicalDecl()); + if (!CheckOverridingFunctionReturnType(MD, OldMD) && + (hasDelayedExceptionSpec(MD) || + !CheckOverridingFunctionExceptionSpec(MD, OldMD)) && + !CheckIfOverriddenFunctionIsMarkedFinal(MD, OldMD)) { + AddedAny = true; + } + } + } + } + + return AddedAny; +} + +namespace { + // Struct for holding all of the extra arguments needed by + // DiagnoseInvalidRedeclaration to call Sema::ActOnFunctionDeclarator. + struct ActOnFDArgs { + Scope *S; + Declarator &D; + MultiTemplateParamsArg TemplateParamLists; + bool AddToScope; + }; +} + +namespace { + +// Callback to only accept typo corrections that have a non-zero edit distance. +// Also only accept corrections that have the same parent decl. +class DifferentNameValidatorCCC : public CorrectionCandidateCallback { + public: + DifferentNameValidatorCCC(CXXRecordDecl *Parent) + : ExpectedParent(Parent ? Parent->getCanonicalDecl() : 0) {} + + virtual bool ValidateCandidate(const TypoCorrection &candidate) { + if (candidate.getEditDistance() == 0) + return false; + + if (CXXMethodDecl *MD = candidate.getCorrectionDeclAs()) { + CXXRecordDecl *Parent = MD->getParent(); + return Parent && Parent->getCanonicalDecl() == ExpectedParent; + } + + return !ExpectedParent; + } + + private: + CXXRecordDecl *ExpectedParent; +}; + +} + +/// \brief Generate diagnostics for an invalid function redeclaration. +/// +/// This routine handles generating the diagnostic messages for an invalid +/// function redeclaration, including finding possible similar declarations +/// or performing typo correction if there are no previous declarations with +/// the same name. +/// +/// Returns a NamedDecl iff typo correction was performed and substituting in +/// the new declaration name does not cause new errors. +static NamedDecl* DiagnoseInvalidRedeclaration( + Sema &SemaRef, LookupResult &Previous, FunctionDecl *NewFD, + ActOnFDArgs &ExtraArgs) { + NamedDecl *Result = NULL; + DeclarationName Name = NewFD->getDeclName(); + DeclContext *NewDC = NewFD->getDeclContext(); + LookupResult Prev(SemaRef, Name, NewFD->getLocation(), + Sema::LookupOrdinaryName, Sema::ForRedeclaration); + llvm::SmallVector MismatchedParams; + llvm::SmallVector, 1> NearMatches; + TypoCorrection Correction; + bool isFriendDecl = (SemaRef.getLangOpts().CPlusPlus && + ExtraArgs.D.getDeclSpec().isFriendSpecified()); + unsigned DiagMsg = isFriendDecl ? diag::err_no_matching_local_friend + : diag::err_member_def_does_not_match; + + NewFD->setInvalidDecl(); + SemaRef.LookupQualifiedName(Prev, NewDC); + assert(!Prev.isAmbiguous() && + "Cannot have an ambiguity in previous-declaration lookup"); + CXXMethodDecl *MD = dyn_cast(NewFD); + DifferentNameValidatorCCC Validator(MD ? MD->getParent() : 0); + if (!Prev.empty()) { + for (LookupResult::iterator Func = Prev.begin(), FuncEnd = Prev.end(); + Func != FuncEnd; ++Func) { + FunctionDecl *FD = dyn_cast(*Func); + if (FD && + hasSimilarParameters(SemaRef.Context, FD, NewFD, MismatchedParams)) { + // Add 1 to the index so that 0 can mean the mismatch didn't + // involve a parameter + unsigned ParamNum = + MismatchedParams.empty() ? 0 : MismatchedParams.front() + 1; + NearMatches.push_back(std::make_pair(FD, ParamNum)); + } + } + // If the qualified name lookup yielded nothing, try typo correction + } else if ((Correction = SemaRef.CorrectTypo(Prev.getLookupNameInfo(), + Prev.getLookupKind(), 0, 0, + Validator, NewDC))) { + // Trap errors. + Sema::SFINAETrap Trap(SemaRef); + + // Set up everything for the call to ActOnFunctionDeclarator + ExtraArgs.D.SetIdentifier(Correction.getCorrectionAsIdentifierInfo(), + ExtraArgs.D.getIdentifierLoc()); + Previous.clear(); + Previous.setLookupName(Correction.getCorrection()); + for (TypoCorrection::decl_iterator CDecl = Correction.begin(), + CDeclEnd = Correction.end(); + CDecl != CDeclEnd; ++CDecl) { + FunctionDecl *FD = dyn_cast(*CDecl); + if (FD && hasSimilarParameters(SemaRef.Context, FD, NewFD, + MismatchedParams)) { + Previous.addDecl(FD); + } + } + bool wasRedeclaration = ExtraArgs.D.isRedeclaration(); + // TODO: Refactor ActOnFunctionDeclarator so that we can call only the + // pieces need to verify the typo-corrected C++ declaraction and hopefully + // eliminate the need for the parameter pack ExtraArgs. + Result = SemaRef.ActOnFunctionDeclarator( + ExtraArgs.S, ExtraArgs.D, + Correction.getCorrectionDecl()->getDeclContext(), + NewFD->getTypeSourceInfo(), Previous, ExtraArgs.TemplateParamLists, + ExtraArgs.AddToScope); + if (Trap.hasErrorOccurred()) { + // Pretend the typo correction never occurred + ExtraArgs.D.SetIdentifier(Name.getAsIdentifierInfo(), + ExtraArgs.D.getIdentifierLoc()); + ExtraArgs.D.setRedeclaration(wasRedeclaration); + Previous.clear(); + Previous.setLookupName(Name); + Result = NULL; + } else { + for (LookupResult::iterator Func = Previous.begin(), + FuncEnd = Previous.end(); + Func != FuncEnd; ++Func) { + if (FunctionDecl *FD = dyn_cast(*Func)) + NearMatches.push_back(std::make_pair(FD, 0)); + } + } + if (NearMatches.empty()) { + // Ignore the correction if it didn't yield any close FunctionDecl matches + Correction = TypoCorrection(); + } else { + DiagMsg = isFriendDecl ? diag::err_no_matching_local_friend_suggest + : diag::err_member_def_does_not_match_suggest; + } + } + + if (Correction) + SemaRef.Diag(NewFD->getLocation(), DiagMsg) + << Name << NewDC << Correction.getQuoted(SemaRef.getLangOpts()) + << FixItHint::CreateReplacement( + NewFD->getLocation(), + Correction.getAsString(SemaRef.getLangOpts())); + else + SemaRef.Diag(NewFD->getLocation(), DiagMsg) + << Name << NewDC << NewFD->getLocation(); + + bool NewFDisConst = false; + if (CXXMethodDecl *NewMD = dyn_cast(NewFD)) + NewFDisConst = NewMD->getTypeQualifiers() & Qualifiers::Const; + + for (llvm::SmallVector, 1>::iterator + NearMatch = NearMatches.begin(), NearMatchEnd = NearMatches.end(); + NearMatch != NearMatchEnd; ++NearMatch) { + FunctionDecl *FD = NearMatch->first; + bool FDisConst = false; + if (CXXMethodDecl *MD = dyn_cast(FD)) + FDisConst = MD->getTypeQualifiers() & Qualifiers::Const; + + if (unsigned Idx = NearMatch->second) { + ParmVarDecl *FDParam = FD->getParamDecl(Idx-1); + SourceLocation Loc = FDParam->getTypeSpecStartLoc(); + if (Loc.isInvalid()) Loc = FD->getLocation(); + SemaRef.Diag(Loc, diag::note_member_def_close_param_match) + << Idx << FDParam->getType() << NewFD->getParamDecl(Idx-1)->getType(); + } else if (Correction) { + SemaRef.Diag(FD->getLocation(), diag::note_previous_decl) + << Correction.getQuoted(SemaRef.getLangOpts()); + } else if (FDisConst != NewFDisConst) { + SemaRef.Diag(FD->getLocation(), diag::note_member_def_close_const_match) + << NewFDisConst << FD->getSourceRange().getEnd(); + } else + SemaRef.Diag(FD->getLocation(), diag::note_member_def_close_match); + } + return Result; +} + +static FunctionDecl::StorageClass getFunctionStorageClass(Sema &SemaRef, + Declarator &D) { + switch (D.getDeclSpec().getStorageClassSpec()) { + default: llvm_unreachable("Unknown storage class!"); + case DeclSpec::SCS_auto: + case DeclSpec::SCS_register: + case DeclSpec::SCS_mutable: + SemaRef.Diag(D.getDeclSpec().getStorageClassSpecLoc(), + diag::err_typecheck_sclass_func); + D.setInvalidType(); + break; + case DeclSpec::SCS_unspecified: break; + case DeclSpec::SCS_extern: return SC_Extern; + case DeclSpec::SCS_static: { + if (SemaRef.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 + // other than extern + // See also (C++ [dcl.stc]p4). + SemaRef.Diag(D.getDeclSpec().getStorageClassSpecLoc(), + diag::err_static_block_func); + break; + } else + return SC_Static; + } + case DeclSpec::SCS_private_extern: return SC_PrivateExtern; + } + + // No explicit storage class has already been returned + return SC_None; +} + +static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, + DeclContext *DC, QualType &R, + TypeSourceInfo *TInfo, + FunctionDecl::StorageClass SC, + bool &IsVirtualOkay) { + DeclarationNameInfo NameInfo = SemaRef.GetNameForDeclarator(D); + DeclarationName Name = NameInfo.getName(); + + FunctionDecl *NewFD = 0; + bool isInline = D.getDeclSpec().isInlineSpecified(); + DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpecAsWritten(); + FunctionDecl::StorageClass SCAsWritten + = StorageClassSpecToFunctionDeclStorageClass(SCSpec); + + if (!SemaRef.getLangOpts().CPlusPlus) { + // Determine whether the function was written with a + // prototype. This true when: + // - there is a prototype in the declarator, or + // - the type R of the function is some kind of typedef or other reference + // to a type name (which eventually refers to a function type). + bool HasPrototype = + (D.isFunctionDeclarator() && D.getFunctionTypeInfo().hasPrototype) || + (!isa(R.getTypePtr()) && R->isFunctionProtoType()); + + NewFD = FunctionDecl::Create(SemaRef.Context, DC, + D.getLocStart(), NameInfo, R, + TInfo, SC, SCAsWritten, isInline, + HasPrototype); + if (D.isInvalidType()) + NewFD->setInvalidDecl(); + + // Set the lexical context. + NewFD->setLexicalDeclContext(SemaRef.CurContext); + + return NewFD; + } + + bool isExplicit = D.getDeclSpec().isExplicitSpecified(); + bool isConstexpr = D.getDeclSpec().isConstexprSpecified(); + + // Check that the return type is not an abstract class type. + // For record types, this is done by the AbstractClassUsageDiagnoser once + // the class has been completely parsed. + if (!DC->isRecord() && + SemaRef.RequireNonAbstractType(D.getIdentifierLoc(), + R->getAs()->getResultType(), + diag::err_abstract_type_in_decl, + SemaRef.AbstractReturnType)) + D.setInvalidType(); + + if (Name.getNameKind() == DeclarationName::CXXConstructorName) { + // This is a C++ constructor declaration. + assert(DC->isRecord() && + "Constructors can only be declared in a member context"); + + R = SemaRef.CheckConstructorDeclarator(D, R, SC); + return CXXConstructorDecl::Create(SemaRef.Context, cast(DC), + D.getLocStart(), NameInfo, + R, TInfo, isExplicit, isInline, + /*isImplicitlyDeclared=*/false, + isConstexpr); + + } else if (Name.getNameKind() == DeclarationName::CXXDestructorName) { + // This is a C++ destructor declaration. + if (DC->isRecord()) { + R = SemaRef.CheckDestructorDeclarator(D, R, SC); + CXXRecordDecl *Record = cast(DC); + CXXDestructorDecl *NewDD = CXXDestructorDecl::Create( + SemaRef.Context, Record, + D.getLocStart(), + NameInfo, R, TInfo, isInline, + /*isImplicitlyDeclared=*/false); + + // If the class is complete, then we now create the implicit exception + // specification. If the class is incomplete or dependent, we can't do + // it yet. + if (SemaRef.getLangOpts().CPlusPlus0x && !Record->isDependentType() && + Record->getDefinition() && !Record->isBeingDefined() && + R->getAs()->getExceptionSpecType() == EST_None) { + SemaRef.AdjustDestructorExceptionSpec(Record, NewDD); + } + + IsVirtualOkay = true; + return NewDD; + + } else { + SemaRef.Diag(D.getIdentifierLoc(), diag::err_destructor_not_member); + D.setInvalidType(); + + // Create a FunctionDecl to satisfy the function definition parsing + // code path. + return FunctionDecl::Create(SemaRef.Context, DC, + D.getLocStart(), + D.getIdentifierLoc(), Name, R, TInfo, + SC, SCAsWritten, isInline, + /*hasPrototype=*/true, isConstexpr); + } + + } else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName) { + if (!DC->isRecord()) { + SemaRef.Diag(D.getIdentifierLoc(), + diag::err_conv_function_not_member); + return 0; + } + + SemaRef.CheckConversionDeclarator(D, R, SC); + IsVirtualOkay = true; + return CXXConversionDecl::Create(SemaRef.Context, cast(DC), + D.getLocStart(), NameInfo, + R, TInfo, isInline, isExplicit, + isConstexpr, SourceLocation()); + + } else if (DC->isRecord()) { + // If the name of the function is the same as the name of the record, + // then this must be an invalid constructor that has a return type. + // (The parser checks for a return type and makes the declarator a + // constructor if it has no return type). + if (Name.getAsIdentifierInfo() && + Name.getAsIdentifierInfo() == cast(DC)->getIdentifier()){ + SemaRef.Diag(D.getIdentifierLoc(), diag::err_constructor_return_type) + << SourceRange(D.getDeclSpec().getTypeSpecTypeLoc()) + << SourceRange(D.getIdentifierLoc()); + return 0; + } + + bool isStatic = SC == SC_Static; + + // [class.free]p1: + // Any allocation function for a class T is a static member + // (even if not explicitly declared static). + if (Name.getCXXOverloadedOperator() == OO_New || + Name.getCXXOverloadedOperator() == OO_Array_New) + isStatic = true; + + // [class.free]p6 Any deallocation function for a class X is a static member + // (even if not explicitly declared static). + if (Name.getCXXOverloadedOperator() == OO_Delete || + Name.getCXXOverloadedOperator() == OO_Array_Delete) + isStatic = true; + + IsVirtualOkay = !isStatic; + + // This is a C++ method declaration. + return CXXMethodDecl::Create(SemaRef.Context, cast(DC), + D.getLocStart(), NameInfo, R, + TInfo, isStatic, SCAsWritten, isInline, + isConstexpr, SourceLocation()); + + } else { + // Determine whether the function was written with a + // prototype. This true when: + // - we're in C++ (where every function has a prototype), + return FunctionDecl::Create(SemaRef.Context, DC, + D.getLocStart(), + NameInfo, R, TInfo, SC, SCAsWritten, isInline, + true/*HasPrototype*/, isConstexpr); + } +} + +NamedDecl* +Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, + TypeSourceInfo *TInfo, LookupResult &Previous, + MultiTemplateParamsArg TemplateParamLists, + bool &AddToScope) { + QualType R = TInfo->getType(); + + assert(R.getTypePtr()->isFunctionType()); + + // TODO: consider using NameInfo for diagnostic. + DeclarationNameInfo NameInfo = GetNameForDeclarator(D); + DeclarationName Name = NameInfo.getName(); + FunctionDecl::StorageClass SC = getFunctionStorageClass(*this, D); + + if (D.getDeclSpec().isThreadSpecified()) + Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread); + + // Do not allow returning a objc interface by-value. + if (R->getAs()->getResultType()->isObjCObjectType()) { + Diag(D.getIdentifierLoc(), + diag::err_object_cannot_be_passed_returned_by_value) << 0 + << R->getAs()->getResultType() + << FixItHint::CreateInsertion(D.getIdentifierLoc(), "*"); + + QualType T = R->getAs()->getResultType(); + T = Context.getObjCObjectPointerType(T); + if (const FunctionProtoType *FPT = dyn_cast(R)) { + FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); + R = Context.getFunctionType(T, FPT->arg_type_begin(), + FPT->getNumArgs(), EPI); + } + else if (isa(R)) + R = Context.getFunctionNoProtoType(T); + } + + bool isFriend = false; + FunctionTemplateDecl *FunctionTemplate = 0; + bool isExplicitSpecialization = false; + bool isFunctionTemplateSpecialization = false; + bool isDependentClassScopeExplicitSpecialization = false; + bool isVirtualOkay = false; + + FunctionDecl *NewFD = CreateNewFunctionDecl(*this, D, DC, R, TInfo, SC, + isVirtualOkay); + if (!NewFD) return 0; + + if (OriginalLexicalContext && OriginalLexicalContext->isObjCContainer()) + NewFD->setTopLevelDeclInObjCContainer(); + + if (getLangOpts().CPlusPlus) { + bool isInline = D.getDeclSpec().isInlineSpecified(); + bool isVirtual = D.getDeclSpec().isVirtualSpecified(); + bool isExplicit = D.getDeclSpec().isExplicitSpecified(); + bool isConstexpr = D.getDeclSpec().isConstexprSpecified(); + isFriend = D.getDeclSpec().isFriendSpecified(); + if (isFriend && !isInline && D.isFunctionDefinition()) { + // C++ [class.friend]p5 + // A function can be defined in a friend declaration of a + // class . . . . Such a function is implicitly inline. + NewFD->setImplicitlyInline(); + } + + SetNestedNameSpecifier(NewFD, D); + isExplicitSpecialization = false; + isFunctionTemplateSpecialization = false; + if (D.isInvalidType()) + NewFD->setInvalidDecl(); + + // Set the lexical context. If the declarator has a C++ + // scope specifier, or is the object of a friend declaration, the + // lexical context will be different from the semantic context. + NewFD->setLexicalDeclContext(CurContext); + + // Match up the template parameter lists with the scope specifier, then + // determine whether we have a template or a template specialization. + bool Invalid = false; + if (TemplateParameterList *TemplateParams + = MatchTemplateParametersToScopeSpecifier( + D.getDeclSpec().getLocStart(), + D.getIdentifierLoc(), + D.getCXXScopeSpec(), + TemplateParamLists.get(), + TemplateParamLists.size(), + isFriend, + isExplicitSpecialization, + Invalid)) { + if (TemplateParams->size() > 0) { + // This is a function template + + // Check that we can declare a template here. + if (CheckTemplateDeclScope(S, TemplateParams)) + return 0; + + // A destructor cannot be a template. + if (Name.getNameKind() == DeclarationName::CXXDestructorName) { + Diag(NewFD->getLocation(), diag::err_destructor_template); + return 0; + } + + // If we're adding a template to a dependent context, we may need to + // rebuilding some of the types used within the template parameter list, + // now that we know what the current instantiation is. + if (DC->isDependentContext()) { + ContextRAII SavedContext(*this, DC); + if (RebuildTemplateParamsInCurrentInstantiation(TemplateParams)) + Invalid = true; + } + + + FunctionTemplate = FunctionTemplateDecl::Create(Context, DC, + NewFD->getLocation(), + Name, TemplateParams, + NewFD); + FunctionTemplate->setLexicalDeclContext(CurContext); + NewFD->setDescribedFunctionTemplate(FunctionTemplate); + + // For source fidelity, store the other template param lists. + if (TemplateParamLists.size() > 1) { + NewFD->setTemplateParameterListsInfo(Context, + TemplateParamLists.size() - 1, + TemplateParamLists.release()); + } + } else { + // This is a function template specialization. + isFunctionTemplateSpecialization = true; + // For source fidelity, store all the template param lists. + NewFD->setTemplateParameterListsInfo(Context, + TemplateParamLists.size(), + TemplateParamLists.release()); + + // C++0x [temp.expl.spec]p20 forbids "template<> friend void foo(int);". + if (isFriend) { + // We want to remove the "template<>", found here. + SourceRange RemoveRange = TemplateParams->getSourceRange(); + + // If we remove the template<> and the name is not a + // template-id, we're actually silently creating a problem: + // the friend declaration will refer to an untemplated decl, + // and clearly the user wants a template specialization. So + // we need to insert '<>' after the name. + SourceLocation InsertLoc; + if (D.getName().getKind() != UnqualifiedId::IK_TemplateId) { + InsertLoc = D.getName().getSourceRange().getEnd(); + InsertLoc = PP.getLocForEndOfToken(InsertLoc); + } + + Diag(D.getIdentifierLoc(), diag::err_template_spec_decl_friend) + << Name << RemoveRange + << FixItHint::CreateRemoval(RemoveRange) + << FixItHint::CreateInsertion(InsertLoc, "<>"); + } + } + } + else { + // All template param lists were matched against the scope specifier: + // this is NOT (an explicit specialization of) a template. + if (TemplateParamLists.size() > 0) + // For source fidelity, store all the template param lists. + NewFD->setTemplateParameterListsInfo(Context, + TemplateParamLists.size(), + TemplateParamLists.release()); + } + + if (Invalid) { + NewFD->setInvalidDecl(); + if (FunctionTemplate) + FunctionTemplate->setInvalidDecl(); + } + + // If we see "T var();" at block scope, where T is a class type, it is + // probably an attempt to initialize a variable, not a function declaration. + // We don't catch this case earlier, since there is no ambiguity here. + if (!FunctionTemplate && D.getFunctionDefinitionKind() == FDK_Declaration && + CurContext->isFunctionOrMethod() && + D.getNumTypeObjects() == 1 && D.isFunctionDeclarator() && + D.getDeclSpec().getStorageClassSpecAsWritten() + == DeclSpec::SCS_unspecified) { + QualType T = R->getAs()->getResultType(); + DeclaratorChunk &C = D.getTypeObject(0); + if (!T->isVoidType() && C.Fun.NumArgs == 0 && !C.Fun.isVariadic && + !C.Fun.TrailingReturnType && + C.Fun.getExceptionSpecType() == EST_None) { + SourceRange ParenRange(C.Loc, C.EndLoc); + Diag(C.Loc, diag::warn_empty_parens_are_function_decl) << ParenRange; + + // If the declaration looks like: + // T var1, + // f(); + // and name lookup finds a function named 'f', then the ',' was + // probably intended to be a ';'. + if (!D.isFirstDeclarator() && D.getIdentifier()) { + FullSourceLoc Comma(D.getCommaLoc(), SourceMgr); + FullSourceLoc Name(D.getIdentifierLoc(), SourceMgr); + if (Comma.getFileID() != Name.getFileID() || + Comma.getSpellingLineNumber() != Name.getSpellingLineNumber()) { + LookupResult Result(*this, D.getIdentifier(), SourceLocation(), + LookupOrdinaryName); + if (LookupName(Result, S)) + Diag(D.getCommaLoc(), diag::note_empty_parens_function_call) + << FixItHint::CreateReplacement(D.getCommaLoc(), ";") << NewFD; + } + } + const CXXRecordDecl *RD = T->getAsCXXRecordDecl(); + // Empty parens mean value-initialization, and no parens mean default + // initialization. These are equivalent if the default constructor is + // user-provided, or if zero-initialization is a no-op. + if (RD && RD->hasDefinition() && + (RD->isEmpty() || RD->hasUserProvidedDefaultConstructor())) + Diag(C.Loc, diag::note_empty_parens_default_ctor) + << FixItHint::CreateRemoval(ParenRange); + else if (const char *Init = getFixItZeroInitializerForType(T)) + Diag(C.Loc, diag::note_empty_parens_zero_initialize) + << FixItHint::CreateReplacement(ParenRange, Init); + else if (LangOpts.CPlusPlus0x) + Diag(C.Loc, diag::note_empty_parens_zero_initialize) + << FixItHint::CreateReplacement(ParenRange, "{}"); + } + } + + // C++ [dcl.fct.spec]p5: + // The virtual specifier shall only be used in declarations of + // nonstatic class member functions that appear within a + // member-specification of a class declaration; see 10.3. + // + if (isVirtual && !NewFD->isInvalidDecl()) { + if (!isVirtualOkay) { + Diag(D.getDeclSpec().getVirtualSpecLoc(), + diag::err_virtual_non_function); + } else if (!CurContext->isRecord()) { + // 'virtual' was specified outside of the class. + Diag(D.getDeclSpec().getVirtualSpecLoc(), + diag::err_virtual_out_of_class) + << FixItHint::CreateRemoval(D.getDeclSpec().getVirtualSpecLoc()); + } else if (NewFD->getDescribedFunctionTemplate()) { + // C++ [temp.mem]p3: + // A member function template shall not be virtual. + Diag(D.getDeclSpec().getVirtualSpecLoc(), + diag::err_virtual_member_function_template) + << FixItHint::CreateRemoval(D.getDeclSpec().getVirtualSpecLoc()); + } else { + // Okay: Add virtual to the method. + NewFD->setVirtualAsWritten(true); + } + } + + // C++ [dcl.fct.spec]p3: + // The inline specifier shall not appear on a block scope function + // declaration. + if (isInline && !NewFD->isInvalidDecl()) { + 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 and 12.3.2. + if (isExplicit && !NewFD->isInvalidDecl()) { + if (!CurContext->isRecord()) { + // 'explicit' was specified outside of the class. + Diag(D.getDeclSpec().getExplicitSpecLoc(), + diag::err_explicit_out_of_class) + << FixItHint::CreateRemoval(D.getDeclSpec().getExplicitSpecLoc()); + } else if (!isa(NewFD) && + !isa(NewFD)) { + // 'explicit' was specified on a function that wasn't a constructor + // or conversion function. + Diag(D.getDeclSpec().getExplicitSpecLoc(), + diag::err_explicit_non_ctor_or_conv_function) + << FixItHint::CreateRemoval(D.getDeclSpec().getExplicitSpecLoc()); + } + } + + if (isConstexpr) { + // C++0x [dcl.constexpr]p2: constexpr functions and constexpr constructors + // are implicitly inline. + NewFD->setImplicitlyInline(); + + // C++0x [dcl.constexpr]p3: functions declared constexpr are required to + // be either constructors or to return a literal type. Therefore, + // destructors cannot be declared constexpr. + if (isa(NewFD)) + Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_constexpr_dtor); + } + + // If __module_private__ was specified, mark the function accordingly. + if (D.getDeclSpec().isModulePrivateSpecified()) { + if (isFunctionTemplateSpecialization) { + SourceLocation ModulePrivateLoc + = D.getDeclSpec().getModulePrivateSpecLoc(); + Diag(ModulePrivateLoc, diag::err_module_private_specialization) + << 0 + << FixItHint::CreateRemoval(ModulePrivateLoc); + } else { + NewFD->setModulePrivate(); + if (FunctionTemplate) + FunctionTemplate->setModulePrivate(); + } + } + + if (isFriend) { + // For now, claim that the objects have no previous declaration. + if (FunctionTemplate) { + FunctionTemplate->setObjectOfFriendDecl(false); + FunctionTemplate->setAccess(AS_public); + } + NewFD->setObjectOfFriendDecl(false); + NewFD->setAccess(AS_public); + } + + // If a function is defined as defaulted or deleted, mark it as such now. + switch (D.getFunctionDefinitionKind()) { + case FDK_Declaration: + case FDK_Definition: + break; + + case FDK_Defaulted: + NewFD->setDefaulted(); + break; + + case FDK_Deleted: + NewFD->setDeletedAsWritten(); + break; + } + + if (isa(NewFD) && DC == CurContext && + D.isFunctionDefinition()) { + // C++ [class.mfct]p2: + // A member function may be defined (8.4) in its class definition, in + // which case it is an inline member function (7.1.2) + NewFD->setImplicitlyInline(); + } + + if (SC == SC_Static && isa(NewFD) && + !CurContext->isRecord()) { + // C++ [class.static]p1: + // A data or function member of a class may be declared static + // in a class definition, in which case it is a static member of + // the class. + + // Complain about the 'static' specifier if it's on an out-of-line + // member function definition. + Diag(D.getDeclSpec().getStorageClassSpecLoc(), + diag::err_static_out_of_line) + << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc()); + } + } + + // Filter out previous declarations that don't match the scope. + FilterLookupForScope(Previous, DC, S, NewFD->hasLinkage(), + isExplicitSpecialization || + isFunctionTemplateSpecialization); + + // Handle GNU asm-label extension (encoded as an attribute). + if (Expr *E = (Expr*) D.getAsmLabel()) { + // The parser guarantees this is a string. + StringLiteral *SE = cast(E); + NewFD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0), Context, + SE->getString())); + } else if (!ExtnameUndeclaredIdentifiers.empty()) { + llvm::DenseMap::iterator I = + ExtnameUndeclaredIdentifiers.find(NewFD->getIdentifier()); + if (I != ExtnameUndeclaredIdentifiers.end()) { + NewFD->addAttr(I->second); + ExtnameUndeclaredIdentifiers.erase(I); + } + } + + // Copy the parameter declarations from the declarator D to the function + // declaration NewFD, if they are available. First scavenge them into Params. + SmallVector Params; + if (D.isFunctionDeclarator()) { + DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); + + // Check for C99 6.7.5.3p10 - foo(void) is a non-varargs + // function that takes no arguments, not a function that takes a + // single void argument. + // We let through "const void" here because Sema::GetTypeForDeclarator + // already checks for that case. + if (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 && + FTI.ArgInfo[0].Param && + cast(FTI.ArgInfo[0].Param)->getType()->isVoidType()) { + // Empty arg list, don't push any params. + 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. + if (getLangOpts().CPlusPlus && + Param->getType().getUnqualifiedType() != Context.VoidTy) { + bool IsTypeAlias = false; + if (const TypedefType *TT = Param->getType()->getAs()) + IsTypeAlias = isa(TT->getDecl()); + else if (const TemplateSpecializationType *TST = + Param->getType()->getAs()) + IsTypeAlias = TST->isTypeAlias(); + Diag(Param->getLocation(), diag::err_param_typedef_of_void) + << IsTypeAlias; + } + } else if (FTI.NumArgs > 0 && FTI.ArgInfo[0].Param != 0) { + for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) { + ParmVarDecl *Param = cast(FTI.ArgInfo[i].Param); + assert(Param->getDeclContext() != NewFD && "Was set before ?"); + Param->setDeclContext(NewFD); + Params.push_back(Param); + + if (Param->isInvalidDecl()) + NewFD->setInvalidDecl(); + } + } + + } else if (const FunctionProtoType *FT = R->getAs()) { + // When we're declaring a function with a typedef, typeof, etc as in the + // following example, we'll need to synthesize (unnamed) + // parameters for use in the declaration. + // + // @code + // typedef void fn(int); + // fn f; + // @endcode + + // Synthesize a parameter for each argument type. + for (FunctionProtoType::arg_type_iterator AI = FT->arg_type_begin(), + AE = FT->arg_type_end(); AI != AE; ++AI) { + ParmVarDecl *Param = + BuildParmVarDeclForTypedef(NewFD, D.getIdentifierLoc(), *AI); + Param->setScopeInfo(0, Params.size()); + Params.push_back(Param); + } + } else { + assert(R->isFunctionNoProtoType() && NewFD->getNumParams() == 0 && + "Should not need args for typedef of non-prototype fn"); + } + + // Finally, we know we have the right number of parameters, install them. + NewFD->setParams(Params); + + // Find all anonymous symbols defined during the declaration of this function + // and add to NewFD. This lets us track decls such 'enum Y' in: + // + // void f(enum Y {AA} x) {} + // + // which would otherwise incorrectly end up in the translation unit scope. + NewFD->setDeclsInPrototypeScope(DeclsInPrototypeScope); + DeclsInPrototypeScope.clear(); + + // Process the non-inheritable attributes on this declaration. + ProcessDeclAttributes(S, NewFD, D, + /*NonInheritable=*/true, /*Inheritable=*/false); + + // Functions returning a variably modified type violate C99 6.7.5.2p2 + // because all functions have linkage. + if (!NewFD->isInvalidDecl() && + NewFD->getResultType()->isVariablyModifiedType()) { + Diag(NewFD->getLocation(), diag::err_vm_func_decl); + NewFD->setInvalidDecl(); + } + + if (!getLangOpts().CPlusPlus) { + // Perform semantic checking on the function declaration. + bool isExplicitSpecialization=false; + if (!NewFD->isInvalidDecl()) { + if (NewFD->isMain()) + CheckMain(NewFD, D.getDeclSpec()); + D.setRedeclaration(CheckFunctionDeclaration(S, NewFD, Previous, + isExplicitSpecialization)); + } + assert((NewFD->isInvalidDecl() || !D.isRedeclaration() || + Previous.getResultKind() != LookupResult::FoundOverloaded) && + "previous declaration set still overloaded"); + } else { + // If the declarator is a template-id, translate the parser's template + // argument list into our AST format. + bool HasExplicitTemplateArgs = false; + TemplateArgumentListInfo TemplateArgs; + if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) { + TemplateIdAnnotation *TemplateId = D.getName().TemplateId; + TemplateArgs.setLAngleLoc(TemplateId->LAngleLoc); + TemplateArgs.setRAngleLoc(TemplateId->RAngleLoc); + ASTTemplateArgsPtr TemplateArgsPtr(*this, + TemplateId->getTemplateArgs(), + TemplateId->NumArgs); + translateTemplateArguments(TemplateArgsPtr, + TemplateArgs); + TemplateArgsPtr.release(); + + HasExplicitTemplateArgs = true; + + if (NewFD->isInvalidDecl()) { + HasExplicitTemplateArgs = false; + } else if (FunctionTemplate) { + // Function template with explicit template arguments. + Diag(D.getIdentifierLoc(), diag::err_function_template_partial_spec) + << SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc); + + HasExplicitTemplateArgs = false; + } else if (!isFunctionTemplateSpecialization && + !D.getDeclSpec().isFriendSpecified()) { + // We have encountered something that the user meant to be a + // specialization (because it has explicitly-specified template + // arguments) but that was not introduced with a "template<>" (or had + // too few of them). + Diag(D.getIdentifierLoc(), diag::err_template_spec_needs_header) + << SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc) + << FixItHint::CreateInsertion( + D.getDeclSpec().getLocStart(), + "template<> "); + isFunctionTemplateSpecialization = true; + } else { + // "friend void foo<>(int);" is an implicit specialization decl. + isFunctionTemplateSpecialization = true; + } + } else if (isFriend && isFunctionTemplateSpecialization) { + // This combination is only possible in a recovery case; the user + // wrote something like: + // template <> friend void foo(int); + // which we're recovering from as if the user had written: + // friend void foo<>(int); + // Go ahead and fake up a template id. + HasExplicitTemplateArgs = true; + TemplateArgs.setLAngleLoc(D.getIdentifierLoc()); + TemplateArgs.setRAngleLoc(D.getIdentifierLoc()); + } + + // If it's a friend (and only if it's a friend), it's possible + // that either the specialized function type or the specialized + // template is dependent, and therefore matching will fail. In + // this case, don't check the specialization yet. + bool InstantiationDependent = false; + if (isFunctionTemplateSpecialization && isFriend && + (NewFD->getType()->isDependentType() || DC->isDependentContext() || + TemplateSpecializationType::anyDependentTemplateArguments( + TemplateArgs.getArgumentArray(), TemplateArgs.size(), + InstantiationDependent))) { + assert(HasExplicitTemplateArgs && + "friend function specialization without template args"); + if (CheckDependentFunctionTemplateSpecialization(NewFD, TemplateArgs, + Previous)) + NewFD->setInvalidDecl(); + } else if (isFunctionTemplateSpecialization) { + if (CurContext->isDependentContext() && CurContext->isRecord() + && !isFriend) { + isDependentClassScopeExplicitSpecialization = true; + Diag(NewFD->getLocation(), getLangOpts().MicrosoftExt ? + diag::ext_function_specialization_in_class : + diag::err_function_specialization_in_class) + << NewFD->getDeclName(); + } else if (CheckFunctionTemplateSpecialization(NewFD, + (HasExplicitTemplateArgs ? &TemplateArgs : 0), + Previous)) + NewFD->setInvalidDecl(); + + // C++ [dcl.stc]p1: + // A storage-class-specifier shall not be specified in an explicit + // specialization (14.7.3) + if (SC != SC_None) { + if (SC != NewFD->getStorageClass()) + Diag(NewFD->getLocation(), + diag::err_explicit_specialization_inconsistent_storage_class) + << SC + << FixItHint::CreateRemoval( + D.getDeclSpec().getStorageClassSpecLoc()); + + else + Diag(NewFD->getLocation(), + diag::ext_explicit_specialization_storage_class) + << FixItHint::CreateRemoval( + D.getDeclSpec().getStorageClassSpecLoc()); + } + + } else if (isExplicitSpecialization && isa(NewFD)) { + if (CheckMemberSpecialization(NewFD, Previous)) + NewFD->setInvalidDecl(); + } + + // Perform semantic checking on the function declaration. + if (!isDependentClassScopeExplicitSpecialization) { + if (NewFD->isInvalidDecl()) { + // If this is a class member, mark the class invalid immediately. + // This avoids some consistency errors later. + if (CXXMethodDecl* methodDecl = dyn_cast(NewFD)) + methodDecl->getParent()->setInvalidDecl(); + } else { + if (NewFD->isMain()) + CheckMain(NewFD, D.getDeclSpec()); + D.setRedeclaration(CheckFunctionDeclaration(S, NewFD, Previous, + isExplicitSpecialization)); + } + } + + assert((NewFD->isInvalidDecl() || !D.isRedeclaration() || + Previous.getResultKind() != LookupResult::FoundOverloaded) && + "previous declaration set still overloaded"); + + NamedDecl *PrincipalDecl = (FunctionTemplate + ? cast(FunctionTemplate) + : NewFD); + + if (isFriend && D.isRedeclaration()) { + AccessSpecifier Access = AS_public; + if (!NewFD->isInvalidDecl()) + Access = NewFD->getPreviousDecl()->getAccess(); + + NewFD->setAccess(Access); + if (FunctionTemplate) FunctionTemplate->setAccess(Access); + + PrincipalDecl->setObjectOfFriendDecl(true); + } + + if (NewFD->isOverloadedOperator() && !DC->isRecord() && + PrincipalDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary)) + PrincipalDecl->setNonMemberOperator(); + + // If we have a function template, check the template parameter + // list. This will check and merge default template arguments. + if (FunctionTemplate) { + FunctionTemplateDecl *PrevTemplate = + FunctionTemplate->getPreviousDecl(); + CheckTemplateParameterList(FunctionTemplate->getTemplateParameters(), + PrevTemplate ? PrevTemplate->getTemplateParameters() : 0, + D.getDeclSpec().isFriendSpecified() + ? (D.isFunctionDefinition() + ? TPC_FriendFunctionTemplateDefinition + : TPC_FriendFunctionTemplate) + : (D.getCXXScopeSpec().isSet() && + DC && DC->isRecord() && + DC->isDependentContext()) + ? TPC_ClassTemplateMember + : TPC_FunctionTemplate); + } + + if (NewFD->isInvalidDecl()) { + // Ignore all the rest of this. + } else if (!D.isRedeclaration()) { + struct ActOnFDArgs ExtraArgs = { S, D, TemplateParamLists, + AddToScope }; + // Fake up an access specifier if it's supposed to be a class member. + if (isa(NewFD->getDeclContext())) + NewFD->setAccess(AS_public); + + // Qualified decls generally require a previous declaration. + if (D.getCXXScopeSpec().isSet()) { + // ...with the major exception of templated-scope or + // dependent-scope friend declarations. + + // TODO: we currently also suppress this check in dependent + // contexts because (1) the parameter depth will be off when + // matching friend templates and (2) we might actually be + // selecting a friend based on a dependent factor. But there + // are situations where these conditions don't apply and we + // can actually do this check immediately. + if (isFriend && + (TemplateParamLists.size() || + D.getCXXScopeSpec().getScopeRep()->isDependent() || + CurContext->isDependentContext())) { + // ignore these + } else { + // 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, + // C++ [namespace.memdef]p2). For example: + // + // class X { + // void f() const; + // }; + // + // void X::f() { } // ill-formed + // + // Complain about this problem, and attempt to suggest close + // matches (e.g., those that differ only in cv-qualifiers and + // whether the parameter types are references). + + if (NamedDecl *Result = DiagnoseInvalidRedeclaration(*this, Previous, + NewFD, + ExtraArgs)) { + AddToScope = ExtraArgs.AddToScope; + return Result; + } + } + + // Unqualified local friend declarations are required to resolve + // to something. + } else if (isFriend && cast(CurContext)->isLocalClass()) { + if (NamedDecl *Result = DiagnoseInvalidRedeclaration(*this, Previous, + NewFD, + ExtraArgs)) { + AddToScope = ExtraArgs.AddToScope; + return Result; + } + } + + } else if (!D.isFunctionDefinition() && D.getCXXScopeSpec().isSet() && + !isFriend && !isFunctionTemplateSpecialization && + !isExplicitSpecialization) { + // An out-of-line member function declaration must also be a + // 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. We also allow these declarations as an + // extension for compatibility with old SWIG code which likes to + // generate them. + Diag(NewFD->getLocation(), diag::ext_out_of_line_declaration) + << D.getCXXScopeSpec().getRange(); + } + } + + + // Handle attributes. We need to have merged decls when handling attributes + // (for example to check for conflicts, etc). + // FIXME: This needs to happen before we merge declarations. Then, + // let attribute merging cope with attribute conflicts. + ProcessDeclAttributes(S, NewFD, D, + /*NonInheritable=*/false, /*Inheritable=*/true); + + // attributes declared post-definition are currently ignored + // FIXME: This should happen during attribute merging + if (D.isRedeclaration() && Previous.isSingleResult()) { + const FunctionDecl *Def; + FunctionDecl *PrevFD = dyn_cast(Previous.getFoundDecl()); + if (PrevFD && PrevFD->isDefined(Def) && D.hasAttributes()) { + Diag(NewFD->getLocation(), diag::warn_attribute_precede_definition); + Diag(Def->getLocation(), diag::note_previous_definition); + } + } + + AddKnownFunctionAttributes(NewFD); + + 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(); + FunctionProtoType::ExtProtoInfo EPI; + EPI.Variadic = true; + EPI.ExtInfo = FT->getExtInfo(); + + QualType R = Context.getFunctionType(FT->getResultType(), 0, 0, EPI); + 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 there's a #pragma clang arc_cf_code_audited in scope, consider + // marking the function. + AddCFAuditedAttribute(NewFD); + + // If this is a locally-scoped extern C function, update the + // map of such names. + if (CurContext->isFunctionOrMethod() && NewFD->isExternC() + && !NewFD->isInvalidDecl()) + RegisterLocallyScopedExternCDecl(NewFD, Previous, S); + + // Set this FunctionDecl's range up to the right paren. + NewFD->setRangeEnd(D.getSourceRange().getEnd()); + + if (getLangOpts().CPlusPlus) { + if (FunctionTemplate) { + if (NewFD->isInvalidDecl()) + FunctionTemplate->setInvalidDecl(); + return FunctionTemplate; + } + } + + MarkUnusedFileScopedDecl(NewFD); + + if (getLangOpts().CUDA) + if (IdentifierInfo *II = NewFD->getIdentifier()) + if (!NewFD->isInvalidDecl() && + NewFD->getDeclContext()->getRedeclContext()->isTranslationUnit()) { + if (II->isStr("cudaConfigureCall")) { + if (!R->getAs()->getResultType()->isScalarType()) + Diag(NewFD->getLocation(), diag::err_config_scalar_return); + + Context.setcudaConfigureCallDecl(NewFD); + } + } + + // Here we have an function template explicit specialization at class scope. + // The actually specialization will be postponed to template instatiation + // time via the ClassScopeFunctionSpecializationDecl node. + if (isDependentClassScopeExplicitSpecialization) { + ClassScopeFunctionSpecializationDecl *NewSpec = + ClassScopeFunctionSpecializationDecl::Create( + Context, CurContext, SourceLocation(), + cast(NewFD)); + CurContext->addDecl(NewSpec); + AddToScope = false; + } + + return NewFD; +} + +/// \brief Perform semantic checking of a new function declaration. +/// +/// Performs semantic analysis of the new function declaration +/// NewFD. This routine performs all semantic checking that does not +/// require the actual declarator involved in the declaration, and is +/// used both for the declaration of functions as they are parsed +/// (called via ActOnDeclarator) and for the declaration of functions +/// that have been instantiated via C++ template instantiation (called +/// via InstantiateDecl). +/// +/// \param IsExplicitSpecialiation whether this new function declaration is +/// an explicit specialization of the previous declaration. +/// +/// This sets NewFD->isInvalidDecl() to true if there was an error. +/// +/// Returns true if the function declaration is a redeclaration. +bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, + LookupResult &Previous, + bool IsExplicitSpecialization) { + assert(!NewFD->getResultType()->isVariablyModifiedType() + && "Variably modified return types are not handled here"); + + // Check for a previous declaration of this name. + if (Previous.empty() && NewFD->isExternC()) { + // Since we did not find anything by this name and we're declaring + // an extern "C" function, look for a non-visible extern "C" + // declaration with the same name. + llvm::DenseMap::iterator Pos + = findLocallyScopedExternalDecl(NewFD->getDeclName()); + if (Pos != LocallyScopedExternalDecls.end()) + Previous.addDecl(Pos->second); + } + + bool Redeclaration = false; + + // Merge or overload the declaration with an existing declaration of + // the same name, if appropriate. + if (!Previous.empty()) { + // Determine whether NewFD is an overload of PrevDecl or + // a declaration that requires merging. If it's an overload, + // there's no more work to do here; we'll just add the new + // function to the scope. + + NamedDecl *OldDecl = 0; + if (!AllowOverloadingOfFunction(Previous, Context)) { + Redeclaration = true; + OldDecl = Previous.getFoundDecl(); + } else { + switch (CheckOverload(S, NewFD, Previous, OldDecl, + /*NewIsUsingDecl*/ false)) { + case Ovl_Match: + Redeclaration = true; + break; + + case Ovl_NonFunction: + Redeclaration = true; + break; + + case Ovl_Overload: + Redeclaration = false; + break; + } + + if (!getLangOpts().CPlusPlus && !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) + << Redeclaration << NewFD; + NamedDecl *OverloadedDecl = 0; + if (Redeclaration) + OverloadedDecl = OldDecl; + else if (!Previous.empty()) + OverloadedDecl = Previous.getRepresentativeDecl(); + if (OverloadedDecl) + Diag(OverloadedDecl->getLocation(), + diag::note_attribute_overloadable_prev_overload); + NewFD->addAttr(::new (Context) OverloadableAttr(SourceLocation(), + Context)); + } + } + + if (Redeclaration) { + // NewFD and OldDecl represent declarations that need to be + // merged. + if (MergeFunctionDecl(NewFD, OldDecl, S)) { + NewFD->setInvalidDecl(); + return Redeclaration; + } + + Previous.clear(); + Previous.addDecl(OldDecl); + + if (FunctionTemplateDecl *OldTemplateDecl + = dyn_cast(OldDecl)) { + NewFD->setPreviousDeclaration(OldTemplateDecl->getTemplatedDecl()); + FunctionTemplateDecl *NewTemplateDecl + = NewFD->getDescribedFunctionTemplate(); + assert(NewTemplateDecl && "Template/non-template mismatch"); + if (CXXMethodDecl *Method + = dyn_cast(NewTemplateDecl->getTemplatedDecl())) { + Method->setAccess(OldTemplateDecl->getAccess()); + NewTemplateDecl->setAccess(OldTemplateDecl->getAccess()); + } + + // If this is an explicit specialization of a member that is a function + // template, mark it as a member specialization. + if (IsExplicitSpecialization && + NewTemplateDecl->getInstantiatedFromMemberTemplate()) { + NewTemplateDecl->setMemberSpecialization(); + assert(OldTemplateDecl->isMemberSpecialization()); + } + + } else { + if (isa(NewFD)) // Set access for out-of-line definitions + NewFD->setAccess(OldDecl->getAccess()); + NewFD->setPreviousDeclaration(cast(OldDecl)); + } + } + } + + // Semantic checking for this function declaration (in isolation). + if (getLangOpts().CPlusPlus) { + // C++-specific checks. + if (CXXConstructorDecl *Constructor = dyn_cast(NewFD)) { + CheckConstructor(Constructor); + } else if (CXXDestructorDecl *Destructor = + dyn_cast(NewFD)) { + CXXRecordDecl *Record = Destructor->getParent(); + QualType ClassType = Context.getTypeDeclType(Record); + + // FIXME: Shouldn't we be able to perform this check even when the class + // type is dependent? Both gcc and edg can handle that. + if (!ClassType->isDependentType()) { + DeclarationName Name + = Context.DeclarationNames.getCXXDestructorName( + Context.getCanonicalType(ClassType)); + if (NewFD->getDeclName() != Name) { + Diag(NewFD->getLocation(), diag::err_destructor_name); + NewFD->setInvalidDecl(); + return Redeclaration; + } + } + } else if (CXXConversionDecl *Conversion + = dyn_cast(NewFD)) { + ActOnConversionDeclarator(Conversion); + } + + // Find any virtual functions that this function overrides. + if (CXXMethodDecl *Method = dyn_cast(NewFD)) { + if (!Method->isFunctionTemplateSpecialization() && + !Method->getDescribedFunctionTemplate()) { + if (AddOverriddenMethods(Method->getParent(), Method)) { + // If the function was marked as "static", we have a problem. + if (NewFD->getStorageClass() == SC_Static) { + Diag(NewFD->getLocation(), diag::err_static_overrides_virtual) + << NewFD->getDeclName(); + for (CXXMethodDecl::method_iterator + Overridden = Method->begin_overridden_methods(), + OverriddenEnd = Method->end_overridden_methods(); + Overridden != OverriddenEnd; + ++Overridden) { + Diag((*Overridden)->getLocation(), + diag::note_overridden_virtual_function); + } + } + } + } + + if (Method->isStatic()) + checkThisInStaticMemberFunctionType(Method); + } + + // Extra checking for C++ overloaded operators (C++ [over.oper]). + if (NewFD->isOverloadedOperator() && + CheckOverloadedOperatorDeclaration(NewFD)) { + NewFD->setInvalidDecl(); + return Redeclaration; + } + + // Extra checking for C++0x literal operators (C++0x [over.literal]). + if (NewFD->getLiteralIdentifier() && + CheckLiteralOperatorDeclaration(NewFD)) { + NewFD->setInvalidDecl(); + return Redeclaration; + } + + // In C++, check default arguments now that we have merged decls. Unless + // the lexical context is the class, because in this case this is done + // during delayed parsing anyway. + if (!CurContext->isRecord()) + CheckCXXDefaultArguments(NewFD); + + // If this function declares a builtin function, check the type of this + // declaration against the expected type for the builtin. + if (unsigned BuiltinID = NewFD->getBuiltinID()) { + ASTContext::GetBuiltinTypeError Error; + QualType T = Context.GetBuiltinType(BuiltinID, Error); + if (!T.isNull() && !Context.hasSameType(T, NewFD->getType())) { + // The type of this function differs from the type of the builtin, + // so forget about the builtin entirely. + Context.BuiltinInfo.ForgetBuiltin(BuiltinID, Context.Idents); + } + } + + // If this function is declared as being extern "C", then check to see if + // the function returns a UDT (class, struct, or union type) that is not C + // compatible, and if it does, warn the user. + if (NewFD->isExternC()) { + QualType R = NewFD->getResultType(); + if (!R.isPODType(Context) && + !R->isVoidType()) + Diag( NewFD->getLocation(), diag::warn_return_value_udt ) + << NewFD << R; + } + } + return Redeclaration; +} + +void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) { + // C++11 [basic.start.main]p3: A program that declares main to be inline, + // static or constexpr is ill-formed. + // C99 6.7.4p4: In a hosted environment, the inline function specifier + // shall not appear in a declaration of main. + // static main is not an error under C99, but we should warn about it. + if (FD->getStorageClass() == SC_Static) + Diag(DS.getStorageClassSpecLoc(), getLangOpts().CPlusPlus + ? diag::err_static_main : diag::warn_static_main) + << FixItHint::CreateRemoval(DS.getStorageClassSpecLoc()); + if (FD->isInlineSpecified()) + Diag(DS.getInlineSpecLoc(), diag::err_inline_main) + << FixItHint::CreateRemoval(DS.getInlineSpecLoc()); + if (FD->isConstexpr()) { + Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_main) + << FixItHint::CreateRemoval(DS.getConstexprSpecLoc()); + FD->setConstexpr(false); + } + + QualType T = FD->getType(); + assert(T->isFunctionType() && "function decl is not of function type"); + const FunctionType* FT = T->castAs(); + + // All the standards say that main() should should return 'int'. + if (Context.hasSameUnqualifiedType(FT->getResultType(), Context.IntTy)) { + // In C and C++, main magically returns 0 if you fall off the end; + // set the flag which tells us that. + // This is C++ [basic.start.main]p5 and C99 5.1.2.2.3. + FD->setHasImplicitReturnZero(true); + + // In C with GNU extensions we allow main() to have non-integer return + // type, but we should warn about the extension, and we disable the + // implicit-return-zero rule. + } else if (getLangOpts().GNUMode && !getLangOpts().CPlusPlus) { + Diag(FD->getTypeSpecStartLoc(), diag::ext_main_returns_nonint); + + // Otherwise, this is just a flat-out error. + } else { + Diag(FD->getTypeSpecStartLoc(), diag::err_main_returns_nonint); + FD->setInvalidDecl(true); + } + + // Treat protoless main() as nullary. + if (isa(FT)) return; + + const FunctionProtoType* FTP = cast(FT); + unsigned nparams = FTP->getNumArgs(); + assert(FD->getNumParams() == nparams); + + bool HasExtraParameters = (nparams > 3); + + // Darwin passes an undocumented fourth argument of type char**. If + // other platforms start sprouting these, the logic below will start + // getting shifty. + if (nparams == 4 && Context.getTargetInfo().getTriple().isOSDarwin()) + HasExtraParameters = false; + + if (HasExtraParameters) { + Diag(FD->getLocation(), diag::err_main_surplus_args) << nparams; + FD->setInvalidDecl(true); + nparams = 3; + } + + // FIXME: a lot of the following diagnostics would be improved + // if we had some location information about types. + + QualType CharPP = + Context.getPointerType(Context.getPointerType(Context.CharTy)); + QualType Expected[] = { Context.IntTy, CharPP, CharPP, CharPP }; + + for (unsigned i = 0; i < nparams; ++i) { + QualType AT = FTP->getArgType(i); + + bool mismatch = true; + + if (Context.hasSameUnqualifiedType(AT, Expected[i])) + mismatch = false; + else if (Expected[i] == CharPP) { + // As an extension, the following forms are okay: + // char const ** + // char const * const * + // char * const * + + QualifierCollector qs; + const PointerType* PT; + if ((PT = qs.strip(AT)->getAs()) && + (PT = qs.strip(PT->getPointeeType())->getAs()) && + (QualType(qs.strip(PT->getPointeeType()), 0) == Context.CharTy)) { + qs.removeConst(); + mismatch = !qs.empty(); + } + } + + if (mismatch) { + Diag(FD->getLocation(), diag::err_main_arg_wrong) << i << Expected[i]; + // TODO: suggest replacing given type with expected type + FD->setInvalidDecl(true); + } + } + + if (nparams == 1 && !FD->isInvalidDecl()) { + Diag(FD->getLocation(), diag::warn_main_one_arg); + } + + if (!FD->isInvalidDecl() && FD->getDescribedFunctionTemplate()) { + Diag(FD->getLocation(), diag::err_main_template_decl); + FD->setInvalidDecl(); + } +} + +bool Sema::CheckForConstantInitializer(Expr *Init, QualType DclT) { + // FIXME: Need strict checking. In C89, we need to check for + // any assignment, increment, decrement, function-calls, or + // commas outside of a sizeof. In C99, it's the same list, + // except that the aforementioned are allowed in unevaluated + // expressions. Everything else falls under the + // "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, false)) + return false; + Diag(Init->getExprLoc(), diag::err_init_element_not_constant) + << Init->getSourceRange(); + return true; +} + +namespace { + // Visits an initialization expression to see if OrigDecl is evaluated in + // its own initialization and throws a warning if it does. + class SelfReferenceChecker + : public EvaluatedExprVisitor { + Sema &S; + Decl *OrigDecl; + bool isRecordType; + bool isPODType; + + public: + typedef EvaluatedExprVisitor Inherited; + + SelfReferenceChecker(Sema &S, Decl *OrigDecl) : Inherited(S.Context), + S(S), OrigDecl(OrigDecl) { + isPODType = false; + isRecordType = false; + if (ValueDecl *VD = dyn_cast(OrigDecl)) { + isPODType = VD->getType().isPODType(S.Context); + isRecordType = VD->getType()->isRecordType(); + } + } + + void VisitExpr(Expr *E) { + if (isa(*E)) return; + if (isRecordType) { + Expr *expr = E; + if (MemberExpr *ME = dyn_cast(E)) { + ValueDecl *VD = ME->getMemberDecl(); + if (isa(VD) || isa(VD)) return; + expr = ME->getBase(); + } + if (DeclRefExpr *DRE = dyn_cast(expr)) { + HandleDeclRefExpr(DRE); + return; + } + } + Inherited::VisitExpr(E); + } + + void VisitMemberExpr(MemberExpr *E) { + if (E->getType()->canDecayToPointerType()) return; + ValueDecl *VD = E->getMemberDecl(); + if (isa(VD) || isa(VD)) + if (DeclRefExpr *DRE + = dyn_cast(E->getBase()->IgnoreParenImpCasts())) { + HandleDeclRefExpr(DRE); + return; + } + Inherited::VisitMemberExpr(E); + } + + void VisitImplicitCastExpr(ImplicitCastExpr *E) { + if ((!isRecordType &&E->getCastKind() == CK_LValueToRValue) || + (isRecordType && E->getCastKind() == CK_NoOp)) { + Expr* SubExpr = E->getSubExpr()->IgnoreParenImpCasts(); + if (MemberExpr *ME = dyn_cast(SubExpr)) + SubExpr = ME->getBase()->IgnoreParenImpCasts(); + if (DeclRefExpr *DRE = dyn_cast(SubExpr)) { + HandleDeclRefExpr(DRE); + return; + } + } + Inherited::VisitImplicitCastExpr(E); + } + + void VisitUnaryOperator(UnaryOperator *E) { + // For POD record types, addresses of its own members are well-defined. + if (isRecordType && isPODType) return; + Inherited::VisitUnaryOperator(E); + } + + void HandleDeclRefExpr(DeclRefExpr *DRE) { + Decl* ReferenceDecl = DRE->getDecl(); + if (OrigDecl != ReferenceDecl) return; + LookupResult Result(S, DRE->getNameInfo(), Sema::LookupOrdinaryName, + Sema::NotForRedeclaration); + S.DiagRuntimeBehavior(DRE->getLocStart(), DRE, + S.PDiag(diag::warn_uninit_self_reference_in_init) + << Result.getLookupName() + << OrigDecl->getLocation() + << DRE->getSourceRange()); + } + }; +} + +/// CheckSelfReference - Warns if OrigDecl is used in expression E. +void Sema::CheckSelfReference(Decl* OrigDecl, Expr *E) { + SelfReferenceChecker(*this, OrigDecl).VisitExpr(E); +} + +/// 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(Decl *RealDecl, Expr *Init, + bool DirectInit, bool TypeMayContainAuto) { + // If there is no declaration, there was an error parsing it. Just ignore + // the initializer. + if (RealDecl == 0 || RealDecl->isInvalidDecl()) + return; + + if (CXXMethodDecl *Method = dyn_cast(RealDecl)) { + // With declarators parsed the way they are, the parser cannot + // distinguish between a normal initializer and a pure-specifier. + // Thus this grotesque test. + IntegerLiteral *IL; + if ((IL = dyn_cast(Init)) && IL->getValue() == 0 && + Context.getCanonicalType(IL->getType()) == Context.IntTy) + CheckPureMethod(Method, Init->getSourceRange()); + else { + Diag(Method->getLocation(), diag::err_member_function_initialization) + << Method->getDeclName() << Init->getSourceRange(); + Method->setInvalidDecl(); + } + return; + } + + VarDecl *VDecl = dyn_cast(RealDecl); + if (!VDecl) { + assert(!isa(RealDecl) && "field init shouldn't get here"); + Diag(RealDecl->getLocation(), diag::err_illegal_initializer); + RealDecl->setInvalidDecl(); + return; + } + + // Check for self-references within variable initializers. + // Variables declared within a function/method body are handled + // by a dataflow analysis. + if (!VDecl->hasLocalStorage() && !VDecl->isStaticLocal()) + CheckSelfReference(RealDecl, Init); + + ParenListExpr *CXXDirectInit = dyn_cast(Init); + + // C++11 [decl.spec.auto]p6. Deduce the type which 'auto' stands in for. + if (TypeMayContainAuto && VDecl->getType()->getContainedAutoType()) { + Expr *DeduceInit = Init; + // Initializer could be a C++ direct-initializer. Deduction only works if it + // contains exactly one expression. + if (CXXDirectInit) { + if (CXXDirectInit->getNumExprs() == 0) { + // It isn't possible to write this directly, but it is possible to + // end up in this situation with "auto x(some_pack...);" + Diag(CXXDirectInit->getLocStart(), + diag::err_auto_var_init_no_expression) + << VDecl->getDeclName() << VDecl->getType() + << VDecl->getSourceRange(); + RealDecl->setInvalidDecl(); + return; + } else if (CXXDirectInit->getNumExprs() > 1) { + Diag(CXXDirectInit->getExpr(1)->getLocStart(), + diag::err_auto_var_init_multiple_expressions) + << VDecl->getDeclName() << VDecl->getType() + << VDecl->getSourceRange(); + RealDecl->setInvalidDecl(); + return; + } else { + DeduceInit = CXXDirectInit->getExpr(0); + } + } + TypeSourceInfo *DeducedType = 0; + if (DeduceAutoType(VDecl->getTypeSourceInfo(), DeduceInit, DeducedType) == + DAR_Failed) + DiagnoseAutoDeductionFailure(VDecl, DeduceInit); + if (!DeducedType) { + RealDecl->setInvalidDecl(); + return; + } + VDecl->setTypeSourceInfo(DeducedType); + VDecl->setType(DeducedType->getType()); + VDecl->ClearLinkageCache(); + + // In ARC, infer lifetime. + if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(VDecl)) + VDecl->setInvalidDecl(); + + // If this is a redeclaration, check that the type we just deduced matches + // the previously declared type. + if (VarDecl *Old = VDecl->getPreviousDecl()) + MergeVarDeclTypes(VDecl, Old); + } + + if (VDecl->isLocalVarDecl() && VDecl->hasExternalStorage()) { + // C99 6.7.8p5. C++ has no such restriction, but that is a defect. + Diag(VDecl->getLocation(), diag::err_block_extern_cant_init); + VDecl->setInvalidDecl(); + return; + } + + if (!VDecl->getType()->isDependentType()) { + // 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. + QualType BaseDeclType = VDecl->getType(); + if (const ArrayType *Array = Context.getAsIncompleteArrayType(BaseDeclType)) + BaseDeclType = Array->getElementType(); + if (RequireCompleteType(VDecl->getLocation(), BaseDeclType, + diag::err_typecheck_decl_incomplete_type)) { + RealDecl->setInvalidDecl(); + return; + } + + // The variable can not have an abstract class type. + if (RequireNonAbstractType(VDecl->getLocation(), VDecl->getType(), + diag::err_abstract_type_in_decl, + AbstractVariableType)) + VDecl->setInvalidDecl(); + } + + const VarDecl *Def; + if ((Def = VDecl->getDefinition()) && Def != VDecl) { + Diag(VDecl->getLocation(), diag::err_redefinition) + << VDecl->getDeclName(); + Diag(Def->getLocation(), diag::note_previous_definition); + VDecl->setInvalidDecl(); + return; + } + + const VarDecl* PrevInit = 0; + if (getLangOpts().CPlusPlus) { + // 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. + if (VDecl->isStaticDataMember() && VDecl->getAnyInitializer(PrevInit)) { + Diag(VDecl->getLocation(), diag::err_redefinition) + << VDecl->getDeclName(); + Diag(PrevInit->getLocation(), diag::note_previous_definition); + return; + } + + if (VDecl->hasLocalStorage()) + getCurFunction()->setHasBranchProtectedScope(); + + if (DiagnoseUnexpandedParameterPack(Init, UPPC_Initializer)) { + VDecl->setInvalidDecl(); + return; + } + } + + // OpenCL 1.1 6.5.2: "Variables allocated in the __local address space inside + // a kernel function cannot be initialized." + if (VDecl->getStorageClass() == SC_OpenCLWorkGroupLocal) { + Diag(VDecl->getLocation(), diag::err_local_cant_init); + VDecl->setInvalidDecl(); + return; + } + + // Get the decls type and save a reference for later, since + // CheckInitializerTypes may change it. + QualType DclT = VDecl->getType(), SavT = DclT; + + // Top-level message sends default to 'id' when we're in a debugger + // and we are assigning it to a variable of 'id' type. + if (getLangOpts().DebuggerCastResultToId && DclT->isObjCIdType()) + if (Init->getType() == Context.UnknownAnyTy && isa(Init)) { + ExprResult Result = forceUnknownAnyToType(Init, Context.getObjCIdType()); + if (Result.isInvalid()) { + VDecl->setInvalidDecl(); + return; + } + Init = Result.take(); + } + + // Perform the initialization. + if (!VDecl->isInvalidDecl()) { + InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl); + InitializationKind Kind + = DirectInit ? + CXXDirectInit ? InitializationKind::CreateDirect(VDecl->getLocation(), + Init->getLocStart(), + Init->getLocEnd()) + : InitializationKind::CreateDirectList( + VDecl->getLocation()) + : InitializationKind::CreateCopy(VDecl->getLocation(), + Init->getLocStart()); + + Expr **Args = &Init; + unsigned NumArgs = 1; + if (CXXDirectInit) { + Args = CXXDirectInit->getExprs(); + NumArgs = CXXDirectInit->getNumExprs(); + } + InitializationSequence InitSeq(*this, Entity, Kind, Args, NumArgs); + ExprResult Result = InitSeq.Perform(*this, Entity, Kind, + MultiExprArg(*this, Args,NumArgs), + &DclT); + if (Result.isInvalid()) { + VDecl->setInvalidDecl(); + return; + } + + Init = Result.takeAs(); + } + + // If the type changed, it means we had an incomplete type that was + // completed by the initializer. For example: + // int ary[] = { 1, 3, 5 }; + // "ary" transitions from an IncompleteArrayType to a ConstantArrayType. + if (!VDecl->isInvalidDecl() && (DclT != SavT)) + VDecl->setType(DclT); + + // Check any implicit conversions within the expression. + CheckImplicitConversions(Init, VDecl->getLocation()); + + if (!VDecl->isInvalidDecl()) + checkUnsafeAssigns(VDecl->getLocation(), VDecl->getType(), Init); + + Init = MaybeCreateExprWithCleanups(Init); + // Attach the initializer to the decl. + VDecl->setInit(Init); + + if (VDecl->isLocalVarDecl()) { + // C99 6.7.8p4: All the expressions in an initializer for an object that has + // static storage duration shall be constant expressions or string literals. + // C++ does not have this restriction. + if (!getLangOpts().CPlusPlus && !VDecl->isInvalidDecl() && + VDecl->getStorageClass() == SC_Static) + CheckForConstantInitializer(Init, DclT); + } else if (VDecl->isStaticDataMember() && + VDecl->getLexicalDeclContext()->isRecord()) { + // This is an in-class initialization for a static data member, e.g., + // + // struct S { + // static const int value = 17; + // }; + + // C++ [class.mem]p4: + // A member-declarator can contain a constant-initializer only + // if it declares a static member (9.4) of const integral or + // const enumeration type, see 9.4.2. + // + // C++11 [class.static.data]p3: + // If a non-volatile const static data member is of integral or + // enumeration type, its declaration in the class definition can + // specify a brace-or-equal-initializer in which every initalizer-clause + // that is an assignment-expression is a constant expression. A static + // data member of literal type can be declared in the class definition + // with the constexpr specifier; if so, its declaration shall specify a + // brace-or-equal-initializer in which every initializer-clause that is + // an assignment-expression is a constant expression. + + // Do nothing on dependent types. + if (DclT->isDependentType()) { + + // Allow any 'static constexpr' members, whether or not they are of literal + // type. We separately check that every constexpr variable is of literal + // type. + } else if (VDecl->isConstexpr()) { + + // Require constness. + } else if (!DclT.isConstQualified()) { + Diag(VDecl->getLocation(), diag::err_in_class_initializer_non_const) + << Init->getSourceRange(); + VDecl->setInvalidDecl(); + + // We allow integer constant expressions in all cases. + } else if (DclT->isIntegralOrEnumerationType()) { + // Check whether the expression is a constant expression. + SourceLocation Loc; + if (getLangOpts().CPlusPlus0x && DclT.isVolatileQualified()) + // In C++11, a non-constexpr const static data member with an + // in-class initializer cannot be volatile. + Diag(VDecl->getLocation(), diag::err_in_class_initializer_volatile); + else if (Init->isValueDependent()) + ; // Nothing to check. + else if (Init->isIntegerConstantExpr(Context, &Loc)) + ; // Ok, it's an ICE! + else if (Init->isEvaluatable(Context)) { + // If we can constant fold the initializer through heroics, accept it, + // but report this as a use of an extension for -pedantic. + Diag(Loc, diag::ext_in_class_initializer_non_constant) + << Init->getSourceRange(); + } else { + // Otherwise, this is some crazy unknown case. Report the issue at the + // location provided by the isIntegerConstantExpr failed check. + Diag(Loc, diag::err_in_class_initializer_non_constant) + << Init->getSourceRange(); + VDecl->setInvalidDecl(); + } + + // We allow foldable floating-point constants as an extension. + } else if (DclT->isFloatingType()) { // also permits complex, which is ok + Diag(VDecl->getLocation(), diag::ext_in_class_initializer_float_type) + << DclT << Init->getSourceRange(); + if (getLangOpts().CPlusPlus0x) + Diag(VDecl->getLocation(), + diag::note_in_class_initializer_float_type_constexpr) + << FixItHint::CreateInsertion(VDecl->getLocStart(), "constexpr "); + + if (!Init->isValueDependent() && !Init->isEvaluatable(Context)) { + Diag(Init->getExprLoc(), diag::err_in_class_initializer_non_constant) + << Init->getSourceRange(); + VDecl->setInvalidDecl(); + } + + // Suggest adding 'constexpr' in C++11 for literal types. + } else if (getLangOpts().CPlusPlus0x && DclT->isLiteralType()) { + Diag(VDecl->getLocation(), diag::err_in_class_initializer_literal_type) + << DclT << Init->getSourceRange() + << FixItHint::CreateInsertion(VDecl->getLocStart(), "constexpr "); + VDecl->setConstexpr(true); + + } else { + Diag(VDecl->getLocation(), diag::err_in_class_initializer_bad_type) + << DclT << Init->getSourceRange(); + VDecl->setInvalidDecl(); + } + } else if (VDecl->isFileVarDecl()) { + if (VDecl->getStorageClassAsWritten() == SC_Extern && + (!getLangOpts().CPlusPlus || + !Context.getBaseElementType(VDecl->getType()).isConstQualified())) + Diag(VDecl->getLocation(), diag::warn_extern_init); + + // C99 6.7.8p4. All file scoped initializers need to be constant. + if (!getLangOpts().CPlusPlus && !VDecl->isInvalidDecl()) + CheckForConstantInitializer(Init, DclT); + } + + // We will represent direct-initialization similarly to copy-initialization: + // int x(1); -as-> int x = 1; + // ClassType x(a,b,c); -as-> ClassType x = ClassType(a,b,c); + // + // Clients that want to distinguish between the two forms, can check for + // direct initializer using VarDecl::getInitStyle(). + // A major benefit is that clients that don't particularly care about which + // exactly form was it (like the CodeGen) can handle both cases without + // special case code. + + // C++ 8.5p11: + // The form of initialization (using parentheses or '=') is generally + // insignificant, but does matter when the entity being initialized has a + // class type. + if (CXXDirectInit) { + assert(DirectInit && "Call-style initializer must be direct init."); + VDecl->setInitStyle(VarDecl::CallInit); + } else if (DirectInit) { + // This must be list-initialization. No other way is direct-initialization. + VDecl->setInitStyle(VarDecl::ListInit); + } + + CheckCompleteVariableDeclaration(VDecl); +} + +/// 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(Decl *D) { + // Our main concern here is re-establishing invariants like "a + // variable's type is either dependent or complete". + if (!D || D->isInvalidDecl()) return; + + VarDecl *VD = dyn_cast(D); + if (!VD) return; + + // Auto types are meaningless if we can't make sense of the initializer. + if (ParsingInitForAutoVars.count(D)) { + D->setInvalidDecl(); + return; + } + + QualType Ty = VD->getType(); + if (Ty->isDependentType()) return; + + // Require a complete type. + if (RequireCompleteType(VD->getLocation(), + Context.getBaseElementType(Ty), + diag::err_typecheck_decl_incomplete_type)) { + VD->setInvalidDecl(); + return; + } + + // Require an abstract type. + if (RequireNonAbstractType(VD->getLocation(), Ty, + diag::err_abstract_type_in_decl, + AbstractVariableType)) { + VD->setInvalidDecl(); + return; + } + + // Don't bother complaining about constructors or destructors, + // though. +} + +void Sema::ActOnUninitializedDecl(Decl *RealDecl, + bool TypeMayContainAuto) { + // If there is no declaration, there was an error parsing it. Just ignore it. + if (RealDecl == 0) + return; + + if (VarDecl *Var = dyn_cast(RealDecl)) { + QualType Type = Var->getType(); + + // C++11 [dcl.spec.auto]p3 + if (TypeMayContainAuto && Type->getContainedAutoType()) { + Diag(Var->getLocation(), diag::err_auto_var_requires_init) + << Var->getDeclName() << Type; + Var->setInvalidDecl(); + return; + } + + // C++11 [class.static.data]p3: A static data member can be declared with + // the constexpr specifier; if so, its declaration shall specify + // a brace-or-equal-initializer. + // C++11 [dcl.constexpr]p1: The constexpr specifier shall be applied only to + // the definition of a variable [...] or the declaration of a static data + // member. + if (Var->isConstexpr() && !Var->isThisDeclarationADefinition()) { + if (Var->isStaticDataMember()) + Diag(Var->getLocation(), + diag::err_constexpr_static_mem_var_requires_init) + << Var->getDeclName(); + else + Diag(Var->getLocation(), diag::err_invalid_constexpr_var_decl); + Var->setInvalidDecl(); + return; + } + + switch (Var->isThisDeclarationADefinition()) { + case VarDecl::Definition: + if (!Var->isStaticDataMember() || !Var->getAnyInitializer()) + break; + + // We have an out-of-line definition of a static data member + // that has an in-class initializer, so we type-check this like + // a declaration. + // + // Fall through + + case VarDecl::DeclarationOnly: + // It's only a declaration. + + // Block scope. C99 6.7p7: If an identifier for an object is + // declared with no linkage (C99 6.2.2p6), the type for the + // object shall be complete. + if (!Type->isDependentType() && Var->isLocalVarDecl() && + !Var->getLinkage() && !Var->isInvalidDecl() && + RequireCompleteType(Var->getLocation(), Type, + diag::err_typecheck_decl_incomplete_type)) + Var->setInvalidDecl(); + + // Make sure that the type is not abstract. + if (!Type->isDependentType() && !Var->isInvalidDecl() && + RequireNonAbstractType(Var->getLocation(), Type, + diag::err_abstract_type_in_decl, + AbstractVariableType)) + Var->setInvalidDecl(); + return; + + case VarDecl::TentativeDefinition: + // File scope. C99 6.9.2p2: A declaration of an identifier for an + // object that has file scope without an initializer, and without a + // storage-class specifier or with the storage-class specifier "static", + // constitutes a tentative definition. Note: A tentative definition with + // external linkage is valid (C99 6.2.2p5). + if (!Var->isInvalidDecl()) { + if (const IncompleteArrayType *ArrayT + = Context.getAsIncompleteArrayType(Type)) { + if (RequireCompleteType(Var->getLocation(), + ArrayT->getElementType(), + diag::err_illegal_decl_array_incomplete_type)) + Var->setInvalidDecl(); + } 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. + // NOTE: code such as the following + // static struct s; + // struct s { int a; }; + // is accepted by gcc. Hence here we issue a warning instead of + // an error and we do not invalidate the static declaration. + // NOTE: to avoid multiple warnings, only check the first declaration. + if (Var->getPreviousDecl() == 0) + RequireCompleteType(Var->getLocation(), Type, + diag::ext_typecheck_decl_incomplete_type); + } + } + + // Record the tentative definition; we're done. + if (!Var->isInvalidDecl()) + TentativeDefinitions.push_back(Var); + return; + } + + // Provide a specific diagnostic for uninitialized variable + // definitions with incomplete array type. + if (Type->isIncompleteArrayType()) { + Diag(Var->getLocation(), + diag::err_typecheck_incomplete_array_needs_initializer); + 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. + if (Type->isDependentType()) + return; + + if (Var->isInvalidDecl()) + return; + + if (RequireCompleteType(Var->getLocation(), + Context.getBaseElementType(Type), + diag::err_typecheck_decl_incomplete_type)) { + Var->setInvalidDecl(); + return; + } + + // The variable can not have an abstract class type. + if (RequireNonAbstractType(Var->getLocation(), Type, + diag::err_abstract_type_in_decl, + AbstractVariableType)) { + Var->setInvalidDecl(); + return; + } + + // Check for jumps past the implicit initializer. C++0x + // clarifies that this applies to a "variable with automatic + // storage duration", not a "local variable". + // C++11 [stmt.dcl]p3 + // A program that jumps from a point where a variable with automatic + // storage duration is not in scope to a point where it is in scope is + // ill-formed unless the variable has scalar type, class type with a + // trivial default constructor and a trivial destructor, a cv-qualified + // version of one of these types, or an array of one of the preceding + // types and is declared without an initializer. + if (getLangOpts().CPlusPlus && Var->hasLocalStorage()) { + if (const RecordType *Record + = Context.getBaseElementType(Type)->getAs()) { + CXXRecordDecl *CXXRecord = cast(Record->getDecl()); + // Mark the function for further checking even if the looser rules of + // C++11 do not require such checks, so that we can diagnose + // incompatibilities with C++98. + if (!CXXRecord->isPOD()) + getCurFunction()->setHasBranchProtectedScope(); + } + } + + // C++03 [dcl.init]p9: + // If no initializer is specified for an object, and the + // object is of (possibly cv-qualified) non-POD class type (or + // array thereof), the object shall be default-initialized; if + // the object is of const-qualified type, the underlying class + // type shall have a user-declared default + // constructor. Otherwise, if no initializer is specified for + // a non- static object, the object and its subobjects, if + // any, have an indeterminate initial value); if the object + // or any of its subobjects are of const-qualified type, the + // program is ill-formed. + // C++0x [dcl.init]p11: + // If no initializer is specified for an object, the object is + // default-initialized; [...]. + InitializedEntity Entity = InitializedEntity::InitializeVariable(Var); + InitializationKind Kind + = InitializationKind::CreateDefault(Var->getLocation()); + + InitializationSequence InitSeq(*this, Entity, Kind, 0, 0); + ExprResult Init = InitSeq.Perform(*this, Entity, Kind, + MultiExprArg(*this, 0, 0)); + if (Init.isInvalid()) + Var->setInvalidDecl(); + else if (Init.get()) { + Var->setInit(MaybeCreateExprWithCleanups(Init.get())); + // This is important for template substitution. + Var->setInitStyle(VarDecl::CallInit); + } + + CheckCompleteVariableDeclaration(Var); + } +} + +void Sema::ActOnCXXForRangeDecl(Decl *D) { + VarDecl *VD = dyn_cast(D); + if (!VD) { + Diag(D->getLocation(), diag::err_for_range_decl_must_be_var); + D->setInvalidDecl(); + return; + } + + VD->setCXXForRangeDecl(true); + + // for-range-declaration cannot be given a storage class specifier. + int Error = -1; + switch (VD->getStorageClassAsWritten()) { + case SC_None: + break; + case SC_Extern: + Error = 0; + break; + case SC_Static: + Error = 1; + break; + case SC_PrivateExtern: + Error = 2; + break; + case SC_Auto: + Error = 3; + break; + case SC_Register: + Error = 4; + break; + case SC_OpenCLWorkGroupLocal: + llvm_unreachable("Unexpected storage class"); + } + if (VD->isConstexpr()) + Error = 5; + if (Error != -1) { + Diag(VD->getOuterLocStart(), diag::err_for_range_storage_class) + << VD->getDeclName() << Error; + D->setInvalidDecl(); + } +} + +void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { + if (var->isInvalidDecl()) return; + + // In ARC, don't allow jumps past the implicit initialization of a + // local retaining variable. + if (getLangOpts().ObjCAutoRefCount && + var->hasLocalStorage()) { + switch (var->getType().getObjCLifetime()) { + case Qualifiers::OCL_None: + case Qualifiers::OCL_ExplicitNone: + case Qualifiers::OCL_Autoreleasing: + break; + + case Qualifiers::OCL_Weak: + case Qualifiers::OCL_Strong: + getCurFunction()->setHasBranchProtectedScope(); + break; + } + } + + // All the following checks are C++ only. + if (!getLangOpts().CPlusPlus) return; + + QualType baseType = Context.getBaseElementType(var->getType()); + if (baseType->isDependentType()) return; + + // __block variables might require us to capture a copy-initializer. + if (var->hasAttr()) { + // It's currently invalid to ever have a __block variable with an + // array type; should we diagnose that here? + + // Regardless, we don't want to ignore array nesting when + // constructing this copy. + QualType type = var->getType(); + + if (type->isStructureOrClassType()) { + SourceLocation poi = var->getLocation(); + Expr *varRef =new (Context) DeclRefExpr(var, false, type, VK_LValue, poi); + ExprResult result = + PerformCopyInitialization( + InitializedEntity::InitializeBlock(poi, type, false), + poi, Owned(varRef)); + if (!result.isInvalid()) { + result = MaybeCreateExprWithCleanups(result); + Expr *init = result.takeAs(); + Context.setBlockVarCopyInits(var, init); + } + } + } + + Expr *Init = var->getInit(); + bool IsGlobal = var->hasGlobalStorage() && !var->isStaticLocal(); + + if (!var->getDeclContext()->isDependentContext() && Init) { + if (IsGlobal && !var->isConstexpr() && + getDiagnostics().getDiagnosticLevel(diag::warn_global_constructor, + var->getLocation()) + != DiagnosticsEngine::Ignored && + !Init->isConstantInitializer(Context, baseType->isReferenceType())) + Diag(var->getLocation(), diag::warn_global_constructor) + << Init->getSourceRange(); + + if (var->isConstexpr()) { + llvm::SmallVector Notes; + if (!var->evaluateValue(Notes) || !var->isInitICE()) { + SourceLocation DiagLoc = var->getLocation(); + // If the note doesn't add any useful information other than a source + // location, fold it into the primary diagnostic. + if (Notes.size() == 1 && Notes[0].second.getDiagID() == + diag::note_invalid_subexpr_in_const_expr) { + DiagLoc = Notes[0].first; + Notes.clear(); + } + Diag(DiagLoc, diag::err_constexpr_var_requires_const_init) + << var << Init->getSourceRange(); + for (unsigned I = 0, N = Notes.size(); I != N; ++I) + Diag(Notes[I].first, Notes[I].second); + } + } else if (var->isUsableInConstantExpressions(Context)) { + // Check whether the initializer of a const variable of integral or + // enumeration type is an ICE now, since we can't tell whether it was + // initialized by a constant expression if we check later. + var->checkInitIsICE(); + } + } + + // Require the destructor. + if (const RecordType *recordType = baseType->getAs()) + FinalizeVarWithDestructor(var, recordType); +} + +/// FinalizeDeclaration - called by ParseDeclarationAfterDeclarator to perform +/// any semantic actions necessary after any initializer has been attached. +void +Sema::FinalizeDeclaration(Decl *ThisDecl) { + // Note that we are no longer parsing the initializer for this declaration. + ParsingInitForAutoVars.erase(ThisDecl); +} + +Sema::DeclGroupPtrTy +Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, + Decl **Group, unsigned NumDecls) { + SmallVector Decls; + + if (DS.isTypeSpecOwned()) + Decls.push_back(DS.getRepAsDecl()); + + for (unsigned i = 0; i != NumDecls; ++i) + if (Decl *D = Group[i]) + Decls.push_back(D); + + return BuildDeclaratorGroup(Decls.data(), Decls.size(), + DS.getTypeSpecType() == DeclSpec::TST_auto); +} + +/// BuildDeclaratorGroup - convert a list of declarations into a declaration +/// group, performing any necessary semantic checking. +Sema::DeclGroupPtrTy +Sema::BuildDeclaratorGroup(Decl **Group, unsigned NumDecls, + bool TypeMayContainAuto) { + // C++0x [dcl.spec.auto]p7: + // If the type deduced for the template parameter U is not the same in each + // deduction, the program is ill-formed. + // FIXME: When initializer-list support is added, a distinction is needed + // between the deduced type U and the deduced type which 'auto' stands for. + // auto a = 0, b = { 1, 2, 3 }; + // is legal because the deduced type U is 'int' in both cases. + if (TypeMayContainAuto && NumDecls > 1) { + QualType Deduced; + CanQualType DeducedCanon; + VarDecl *DeducedDecl = 0; + for (unsigned i = 0; i != NumDecls; ++i) { + if (VarDecl *D = dyn_cast(Group[i])) { + AutoType *AT = D->getType()->getContainedAutoType(); + // Don't reissue diagnostics when instantiating a template. + if (AT && D->isInvalidDecl()) + break; + if (AT && AT->isDeduced()) { + QualType U = AT->getDeducedType(); + CanQualType UCanon = Context.getCanonicalType(U); + if (Deduced.isNull()) { + Deduced = U; + DeducedCanon = UCanon; + DeducedDecl = D; + } else if (DeducedCanon != UCanon) { + Diag(D->getTypeSourceInfo()->getTypeLoc().getBeginLoc(), + diag::err_auto_different_deductions) + << Deduced << DeducedDecl->getDeclName() + << U << D->getDeclName() + << DeducedDecl->getInit()->getSourceRange() + << D->getInit()->getSourceRange(); + D->setInvalidDecl(); + break; + } + } + } + } + } + + return DeclGroupPtrTy::make(DeclGroupRef::Create(Context, Group, NumDecls)); +} + + +/// ActOnParamDeclarator - Called from Parser::ParseFunctionDeclarator() +/// to introduce parameters into function prototype scope. +Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { + const DeclSpec &DS = D.getDeclSpec(); + + // Verify C99 6.7.5.3p2: The only SCS allowed is 'register'. + // C++03 [dcl.stc]p2 also permits 'auto'. + VarDecl::StorageClass StorageClass = SC_None; + VarDecl::StorageClass StorageClassAsWritten = SC_None; + if (DS.getStorageClassSpec() == DeclSpec::SCS_register) { + StorageClass = SC_Register; + StorageClassAsWritten = SC_Register; + } else if (getLangOpts().CPlusPlus && + DS.getStorageClassSpec() == DeclSpec::SCS_auto) { + StorageClass = SC_Auto; + StorageClassAsWritten = SC_Auto; + } else if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified) { + Diag(DS.getStorageClassSpecLoc(), + diag::err_invalid_storage_class_in_func_decl); + D.getMutableDeclSpec().ClearStorageClassSpecs(); + } + + if (D.getDeclSpec().isThreadSpecified()) + Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread); + if (D.getDeclSpec().isConstexprSpecified()) + Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_invalid_constexpr) + << 0; + + DiagnoseFunctionSpecifiers(D); + + TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); + QualType parmDeclType = TInfo->getType(); + + if (getLangOpts().CPlusPlus) { + // Check that there are no default arguments inside the type of this + // parameter. + CheckExtraCXXDefaultArguments(D); + + // Parameter declarators cannot be qualified (C++ [dcl.meaning]p1). + if (D.getCXXScopeSpec().isSet()) { + Diag(D.getIdentifierLoc(), diag::err_qualified_param_declarator) + << D.getCXXScopeSpec().getRange(); + D.getCXXScopeSpec().clear(); + } + } + + // Ensure we have a valid name + IdentifierInfo *II = 0; + if (D.hasName()) { + II = D.getIdentifier(); + if (!II) { + Diag(D.getIdentifierLoc(), diag::err_bad_parameter_name) + << GetNameForDeclarator(D).getName().getAsString(); + D.setInvalidType(true); + } + } + + // Check for redeclaration of parameters, e.g. int foo(int x, int x); + if (II) { + LookupResult R(*this, II, D.getIdentifierLoc(), LookupOrdinaryName, + ForRedeclaration); + LookupName(R, S); + if (R.isSingleResult()) { + NamedDecl *PrevDecl = R.getFoundDecl(); + if (PrevDecl->isTemplateParameter()) { + // Maybe we will complain about the shadowed template parameter. + DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl); + // Just pretend that we didn't see the previous declaration. + PrevDecl = 0; + } else if (S->isDeclScope(PrevDecl)) { + Diag(D.getIdentifierLoc(), diag::err_param_redefinition) << II; + Diag(PrevDecl->getLocation(), diag::note_previous_declaration); + + // Recover by removing the name + II = 0; + D.SetIdentifier(0, D.getIdentifierLoc()); + D.setInvalidType(true); + } + } + } + + // Temporarily put parameter variables in the translation unit, not + // the enclosing context. This prevents them from accidentally + // looking like class members in C++. + ParmVarDecl *New = CheckParameter(Context.getTranslationUnitDecl(), + D.getLocStart(), + D.getIdentifierLoc(), II, + parmDeclType, TInfo, + StorageClass, StorageClassAsWritten); + + if (D.isInvalidType()) + New->setInvalidDecl(); + + assert(S->isFunctionPrototypeScope()); + assert(S->getFunctionPrototypeDepth() >= 1); + New->setScopeInfo(S->getFunctionPrototypeDepth() - 1, + S->getNextFunctionPrototypeIndex()); + + // Add the parameter declaration into this scope. + S->AddDecl(New); + if (II) + IdResolver.AddDecl(New); + + ProcessDeclAttributes(S, New, D); + + if (D.getDeclSpec().isModulePrivateSpecified()) + Diag(New->getLocation(), diag::err_module_private_local) + << 1 << New->getDeclName() + << SourceRange(D.getDeclSpec().getModulePrivateSpecLoc()) + << FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc()); + + if (New->hasAttr()) { + Diag(New->getLocation(), diag::err_block_on_nonlocal); + } + return New; +} + +/// \brief Synthesizes a variable for a parameter arising from a +/// typedef. +ParmVarDecl *Sema::BuildParmVarDeclForTypedef(DeclContext *DC, + SourceLocation Loc, + QualType T) { + /* FIXME: setting StartLoc == Loc. + Would it be worth to modify callers so as to provide proper source + location for the unnamed parameters, embedding the parameter's type? */ + ParmVarDecl *Param = ParmVarDecl::Create(Context, DC, Loc, Loc, 0, + T, Context.getTrivialTypeSourceInfo(T, Loc), + SC_None, SC_None, 0); + Param->setImplicit(); + return Param; +} + +void Sema::DiagnoseUnusedParameters(ParmVarDecl * const *Param, + ParmVarDecl * const *ParamEnd) { + // 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)->isReferenced() && (*Param)->getDeclName() && + !(*Param)->hasAttr()) { + Diag((*Param)->getLocation(), diag::warn_unused_parameter) + << (*Param)->getDeclName(); + } + } +} + +void Sema::DiagnoseSizeOfParametersAndReturnValue(ParmVarDecl * const *Param, + ParmVarDecl * const *ParamEnd, + QualType ReturnTy, + NamedDecl *D) { + if (LangOpts.NumLargeByValueCopy == 0) // No check. + return; + + // Warn if the return value is pass-by-value and larger than the specified + // threshold. + if (!ReturnTy->isDependentType() && ReturnTy.isPODType(Context)) { + unsigned Size = Context.getTypeSizeInChars(ReturnTy).getQuantity(); + if (Size > LangOpts.NumLargeByValueCopy) + Diag(D->getLocation(), diag::warn_return_value_size) + << D->getDeclName() << Size; + } + + // Warn if any parameter is pass-by-value and larger than the specified + // threshold. + for (; Param != ParamEnd; ++Param) { + QualType T = (*Param)->getType(); + if (T->isDependentType() || !T.isPODType(Context)) + continue; + unsigned Size = Context.getTypeSizeInChars(T).getQuantity(); + if (Size > LangOpts.NumLargeByValueCopy) + Diag((*Param)->getLocation(), diag::warn_parameter_size) + << (*Param)->getDeclName() << Size; + } +} + +ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc, + SourceLocation NameLoc, IdentifierInfo *Name, + QualType T, TypeSourceInfo *TSInfo, + VarDecl::StorageClass StorageClass, + VarDecl::StorageClass StorageClassAsWritten) { + // In ARC, infer a lifetime qualifier for appropriate parameter types. + if (getLangOpts().ObjCAutoRefCount && + T.getObjCLifetime() == Qualifiers::OCL_None && + T->isObjCLifetimeType()) { + + Qualifiers::ObjCLifetime lifetime; + + // Special cases for arrays: + // - if it's const, use __unsafe_unretained + // - otherwise, it's an error + if (T->isArrayType()) { + if (!T.isConstQualified()) { + DelayedDiagnostics.add( + sema::DelayedDiagnostic::makeForbiddenType( + NameLoc, diag::err_arc_array_param_no_ownership, T, false)); + } + lifetime = Qualifiers::OCL_ExplicitNone; + } else { + lifetime = T->getObjCARCImplicitLifetime(); + } + T = Context.getLifetimeQualifiedType(T, lifetime); + } + + ParmVarDecl *New = ParmVarDecl::Create(Context, DC, StartLoc, NameLoc, Name, + Context.getAdjustedParameterType(T), + TSInfo, + StorageClass, StorageClassAsWritten, + 0); + + // Parameters can not be abstract class types. + // For record types, this is done by the AbstractClassUsageDiagnoser once + // the class has been completely parsed. + if (!CurContext->isRecord() && + RequireNonAbstractType(NameLoc, T, diag::err_abstract_type_in_decl, + AbstractParamType)) + New->setInvalidDecl(); + + // Parameter declarators cannot be interface types. All ObjC objects are + // passed by reference. + if (T->isObjCObjectType()) { + Diag(NameLoc, + diag::err_object_cannot_be_passed_returned_by_value) << 1 << T + << FixItHint::CreateInsertion(NameLoc, "*"); + T = Context.getObjCObjectPointerType(T); + New->setType(T); + } + + // ISO/IEC TR 18037 S6.7.3: "The type of an object with automatic storage + // duration shall not be qualified by an address-space qualifier." + // Since all parameters have automatic store duration, they can not have + // an address space. + if (T.getAddressSpace() != 0) { + Diag(NameLoc, diag::err_arg_with_address_space); + New->setInvalidDecl(); + } + + return New; +} + +void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D, + SourceLocation LocAfterDecls) { + DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); + + // Verify 6.9.1p6: 'every identifier in the identifier list shall be declared' + // for a K&R function. + if (!FTI.hasPrototype) { + for (int i = FTI.NumArgs; i != 0; /* decrement in loop */) { + --i; + if (FTI.ArgInfo[i].Param == 0) { + SmallString<256> Code; + llvm::raw_svector_ostream(Code) << " int " + << FTI.ArgInfo[i].Ident->getName() + << ";\n"; + Diag(FTI.ArgInfo[i].IdentLoc, diag::ext_param_not_declared) + << FTI.ArgInfo[i].Ident + << FixItHint::CreateInsertion(LocAfterDecls, Code.str()); + + // Implicitly declare the argument as type 'int' for lack of a better + // type. + AttributeFactory attrs; + DeclSpec DS(attrs); + const char* PrevSpec; // unused + unsigned DiagID; // unused + DS.SetTypeSpecType(DeclSpec::TST_int, FTI.ArgInfo[i].IdentLoc, + PrevSpec, DiagID); + Declarator ParamD(DS, Declarator::KNRTypeListContext); + ParamD.SetIdentifier(FTI.ArgInfo[i].Ident, FTI.ArgInfo[i].IdentLoc); + FTI.ArgInfo[i].Param = ActOnParamDeclarator(S, ParamD); + } + } + } +} + +Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) { + assert(getCurFunctionDecl() == 0 && "Function parsing confused"); + assert(D.isFunctionDeclarator() && "Not a function declarator!"); + Scope *ParentScope = FnBodyScope->getParent(); + + D.setFunctionDefinitionKind(FDK_Definition); + Decl *DP = HandleDeclarator(ParentScope, D, + MultiTemplateParamsArg(*this)); + return ActOnStartOfFunctionDef(FnBodyScope, DP); +} + +static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD) { + // Don't warn about invalid declarations. + if (FD->isInvalidDecl()) + return false; + + // Or declarations that aren't global. + if (!FD->isGlobal()) + return false; + + // Don't warn about C++ member functions. + if (isa(FD)) + return false; + + // Don't warn about 'main'. + if (FD->isMain()) + return false; + + // Don't warn about inline functions. + if (FD->isInlined()) + return false; + + // Don't warn about function templates. + if (FD->getDescribedFunctionTemplate()) + return false; + + // Don't warn about function template specializations. + if (FD->isFunctionTemplateSpecialization()) + return false; + + bool MissingPrototype = true; + for (const FunctionDecl *Prev = FD->getPreviousDecl(); + Prev; Prev = Prev->getPreviousDecl()) { + // Ignore any declarations that occur in function or method + // scope, because they aren't visible from the header. + if (Prev->getDeclContext()->isFunctionOrMethod()) + continue; + + MissingPrototype = !Prev->getType()->isFunctionProtoType(); + break; + } + + return MissingPrototype; +} + +void Sema::CheckForFunctionRedefinition(FunctionDecl *FD) { + // Don't complain if we're in GNU89 mode and the previous definition + // was an extern inline function. + const FunctionDecl *Definition; + if (FD->isDefined(Definition) && + !canRedefineFunction(Definition, getLangOpts())) { + if (getLangOpts().GNUMode && Definition->isInlineSpecified() && + Definition->getStorageClass() == SC_Extern) + Diag(FD->getLocation(), diag::err_redefinition_extern_inline) + << FD->getDeclName() << getLangOpts().CPlusPlus; + else + Diag(FD->getLocation(), diag::err_redefinition) << FD->getDeclName(); + Diag(Definition->getLocation(), diag::note_previous_definition); + } +} + +Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) { + // Clear the last template instantiation error context. + LastTemplateInstantiationErrorContext = ActiveTemplateInstantiation(); + + if (!D) + return D; + FunctionDecl *FD = 0; + + if (FunctionTemplateDecl *FunTmpl = dyn_cast(D)) + FD = FunTmpl->getTemplatedDecl(); + else + FD = cast(D); + + // Enter a new function scope + PushFunctionScope(); + + // See if this is a redefinition. + if (!FD->isLateTemplateParsed()) + CheckForFunctionRedefinition(FD); + + // Builtin functions cannot be defined. + if (unsigned BuiltinID = FD->getBuiltinID()) { + if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) { + Diag(FD->getLocation(), diag::err_builtin_definition) << FD; + FD->setInvalidDecl(); + } + } + + // The return type of a function definition must be complete + // (C99 6.9.1p3, C++ [dcl.fct]p6). + QualType ResultType = FD->getResultType(); + if (!ResultType->isDependentType() && !ResultType->isVoidType() && + !FD->isInvalidDecl() && + RequireCompleteType(FD->getLocation(), ResultType, + diag::err_func_def_incomplete_result)) + FD->setInvalidDecl(); + + // GNU warning -Wmissing-prototypes: + // Warn if a global function is defined without a previous + // prototype declaration. This warning is issued even if the + // definition itself provides a prototype. The aim is to detect + // global functions that fail to be declared in header files. + if (ShouldWarnAboutMissingPrototype(FD)) + Diag(FD->getLocation(), diag::warn_missing_prototype) << FD; + + if (FnBodyScope) + PushDeclContext(FnBodyScope, FD); + + // Check the validity of our function parameters + CheckParmsForFunctionDef(FD->param_begin(), FD->param_end(), + /*CheckParameterNames=*/true); + + // Introduce our parameters into the function scope + for (unsigned p = 0, NumParams = FD->getNumParams(); p < NumParams; ++p) { + ParmVarDecl *Param = FD->getParamDecl(p); + Param->setOwningFunction(FD); + + // If this has an identifier, add it to the scope stack. + if (Param->getIdentifier() && FnBodyScope) { + CheckShadow(FnBodyScope, Param); + + PushOnScopeChains(Param, FnBodyScope); + } + } + + // If we had any tags defined in the function prototype, + // introduce them into the function scope. + if (FnBodyScope) { + for (llvm::ArrayRef::iterator I = FD->getDeclsInPrototypeScope().begin(), + E = FD->getDeclsInPrototypeScope().end(); I != E; ++I) { + NamedDecl *D = *I; + + // Some of these decls (like enums) may have been pinned to the translation unit + // for lack of a real context earlier. If so, remove from the translation unit + // and reattach to the current context. + if (D->getLexicalDeclContext() == Context.getTranslationUnitDecl()) { + // Is the decl actually in the context? + for (DeclContext::decl_iterator DI = Context.getTranslationUnitDecl()->decls_begin(), + DE = Context.getTranslationUnitDecl()->decls_end(); DI != DE; ++DI) { + if (*DI == D) { + Context.getTranslationUnitDecl()->removeDecl(D); + break; + } + } + // Either way, reassign the lexical decl context to our FunctionDecl. + D->setLexicalDeclContext(CurContext); + } + + // If the decl has a non-null name, make accessible in the current scope. + if (!D->getName().empty()) + PushOnScopeChains(D, FnBodyScope, /*AddToContext=*/false); + + // Similarly, dive into enums and fish their constants out, making them + // accessible in this scope. + if (EnumDecl *ED = dyn_cast(D)) { + for (EnumDecl::enumerator_iterator EI = ED->enumerator_begin(), + EE = ED->enumerator_end(); EI != EE; ++EI) + PushOnScopeChains(*EI, FnBodyScope, /*AddToContext=*/false); + } + } + } + + // Ensure that the function's exception specification is instantiated. + if (const FunctionProtoType *FPT = FD->getType()->getAs()) + ResolveExceptionSpec(D->getLocation(), FPT); + + // Checking attributes of current function definition + // dllimport attribute. + DLLImportAttr *DA = FD->getAttr(); + if (DA && (!FD->getAttr())) { + // dllimport attribute cannot be directly applied to definition. + // Microsoft accepts dllimport for functions defined within class scope. + if (!DA->isInherited() && + !(LangOpts.MicrosoftExt && FD->getLexicalDeclContext()->isRecord())) { + Diag(FD->getLocation(), + diag::err_attribute_can_be_applied_only_to_symbol_declaration) + << "dllimport"; + FD->setInvalidDecl(); + return FD; + } + + // Visual C++ appears to not think this is an issue, so only issue + // a warning when Microsoft extensions are disabled. + if (!LangOpts.MicrosoftExt) { + // If a symbol previously declared dllimport is later defined, the + // attribute is ignored in subsequent references, and a warning is + // emitted. + Diag(FD->getLocation(), + diag::warn_redeclaration_without_attribute_prev_attribute_ignored) + << FD->getName() << "dllimport"; + } + } + return FD; +} + +/// \brief Given the set of return statements within a function body, +/// compute the variables that are subject to the named return value +/// optimization. +/// +/// Each of the variables that is subject to the named return value +/// optimization will be marked as NRVO variables in the AST, and any +/// return statement that has a marked NRVO variable as its NRVO candidate can +/// use the named return value optimization. +/// +/// This function applies a very simplistic algorithm for NRVO: if every return +/// statement in the function has the same NRVO candidate, that candidate is +/// the NRVO variable. +/// +/// 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. +void Sema::computeNRVO(Stmt *Body, FunctionScopeInfo *Scope) { + ReturnStmt **Returns = Scope->Returns.data(); + + const VarDecl *NRVOCandidate = 0; + for (unsigned I = 0, E = Scope->Returns.size(); I != E; ++I) { + if (!Returns[I]->getNRVOCandidate()) + return; + + if (!NRVOCandidate) + NRVOCandidate = Returns[I]->getNRVOCandidate(); + else if (NRVOCandidate != Returns[I]->getNRVOCandidate()) + return; + } + + if (NRVOCandidate) + const_cast(NRVOCandidate)->setNRVOVariable(true); +} + +Decl *Sema::ActOnFinishFunctionBody(Decl *D, Stmt *BodyArg) { + return ActOnFinishFunctionBody(D, move(BodyArg), false); +} + +Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, + bool IsInstantiation) { + FunctionDecl *FD = 0; + FunctionTemplateDecl *FunTmpl = dyn_cast_or_null(dcl); + if (FunTmpl) + FD = FunTmpl->getTemplatedDecl(); + else + FD = dyn_cast_or_null(dcl); + + sema::AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy(); + sema::AnalysisBasedWarnings::Policy *ActivePolicy = 0; + + if (FD) { + FD->setBody(Body); + + // If the function implicitly returns zero (like 'main') or is naked, + // don't complain about missing return statements. + if (FD->hasImplicitReturnZero() || FD->hasAttr()) + WP.disableCheckFallThrough(); + + // MSVC permits the use of pure specifier (=0) on function definition, + // defined at class scope, warn about this non standard construct. + if (getLangOpts().MicrosoftExt && FD->isPure()) + Diag(FD->getLocation(), diag::warn_pure_function_definition); + + if (!FD->isInvalidDecl()) { + DiagnoseUnusedParameters(FD->param_begin(), FD->param_end()); + DiagnoseSizeOfParametersAndReturnValue(FD->param_begin(), FD->param_end(), + FD->getResultType(), FD); + + // If this is a constructor, we need a vtable. + if (CXXConstructorDecl *Constructor = dyn_cast(FD)) + MarkVTableUsed(FD->getLocation(), Constructor->getParent()); + + computeNRVO(Body, getCurFunction()); + } + + assert((FD == getCurFunctionDecl() || getCurLambda()->CallOperator == FD) && + "Function parsing confused"); + } else if (ObjCMethodDecl *MD = dyn_cast_or_null(dcl)) { + assert(MD == getCurMethodDecl() && "Method parsing confused"); + MD->setBody(Body); + if (Body) + MD->setEndLoc(Body->getLocEnd()); + if (!MD->isInvalidDecl()) { + DiagnoseUnusedParameters(MD->param_begin(), MD->param_end()); + DiagnoseSizeOfParametersAndReturnValue(MD->param_begin(), MD->param_end(), + MD->getResultType(), MD); + + if (Body) + computeNRVO(Body, getCurFunction()); + } + if (ObjCShouldCallSuperDealloc) { + Diag(MD->getLocEnd(), diag::warn_objc_missing_super_dealloc); + ObjCShouldCallSuperDealloc = false; + } + if (ObjCShouldCallSuperFinalize) { + Diag(MD->getLocEnd(), diag::warn_objc_missing_super_finalize); + ObjCShouldCallSuperFinalize = false; + } + } else { + return 0; + } + + assert(!ObjCShouldCallSuperDealloc && "This should only be set for " + "ObjC methods, which should have been handled in the block above."); + assert(!ObjCShouldCallSuperFinalize && "This should only be set for " + "ObjC methods, which should have been handled in the block above."); + + // Verify and clean out per-function state. + if (Body) { + // C++ constructors that have function-try-blocks can't have return + // statements in the handlers of that block. (C++ [except.handle]p14) + // Verify this. + if (FD && isa(FD) && isa(Body)) + DiagnoseReturnInConstructorExceptionHandler(cast(Body)); + + // Verify that gotos and switch cases don't jump into scopes illegally. + if (getCurFunction()->NeedsScopeChecking() && + !dcl->isInvalidDecl() && + !hasAnyUnrecoverableErrorsInThisFunction()) + DiagnoseInvalidJumps(Body); + + 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 + // deletion in some later function. + if (PP.getDiagnostics().hasErrorOccurred() || + PP.getDiagnostics().getSuppressAllDiagnostics()) { + DiscardCleanupsInEvaluationContext(); + } else if (!isa(dcl)) { + // Since the body is valid, issue any analysis-based warnings that are + // enabled. + ActivePolicy = &WP; + } + + if (!IsInstantiation && FD && FD->isConstexpr() && !FD->isInvalidDecl() && + (!CheckConstexprFunctionDecl(FD) || + !CheckConstexprFunctionBody(FD, Body))) + FD->setInvalidDecl(); + + assert(ExprCleanupObjects.empty() && "Leftover temporaries in function"); + assert(!ExprNeedsCleanups && "Unaccounted cleanups in function"); + assert(MaybeODRUseExprs.empty() && + "Leftover expressions for odr-use checking"); + } + + if (!IsInstantiation) + PopDeclContext(); + + PopFunctionScopeInfo(ActivePolicy, dcl); + + // 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 + // deletion in some later function. + if (getDiagnostics().hasErrorOccurred()) { + DiscardCleanupsInEvaluationContext(); + } + + return dcl; +} + + +/// When we finish delayed parsing of an attribute, we must attach it to the +/// relevant Decl. +void Sema::ActOnFinishDelayedAttribute(Scope *S, Decl *D, + ParsedAttributes &Attrs) { + // Always attach attributes to the underlying decl. + if (TemplateDecl *TD = dyn_cast(D)) + D = TD->getTemplatedDecl(); + ProcessDeclAttributeList(S, D, Attrs.getList()); + + if (CXXMethodDecl *Method = dyn_cast_or_null(D)) + if (Method->isStatic()) + checkThisInStaticMemberFunctionAttributes(Method); +} + + +/// ImplicitlyDefineFunction - An undeclared identifier was used in a function +/// call, forming a call to an implicitly defined function (per C99 6.5.1p2). +NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, + IdentifierInfo &II, Scope *S) { + // Before we produce a declaration for an implicitly defined + // function, see whether there was a locally-scoped declaration of + // this name as a function or variable. If so, use that + // (non-visible) declaration, and complain about it. + llvm::DenseMap::iterator Pos + = findLocallyScopedExternalDecl(&II); + if (Pos != LocallyScopedExternalDecls.end()) { + Diag(Loc, diag::warn_use_out_of_scope_declaration) << Pos->second; + Diag(Pos->second->getLocation(), diag::note_previous_declaration); + return Pos->second; + } + + // Extension in C99. Legal in C90, but warn about it. + unsigned diag_id; + if (II.getName().startswith("__builtin_")) + diag_id = diag::warn_builtin_unknown; + else if (getLangOpts().C99) + diag_id = diag::ext_implicit_function_decl; + else + diag_id = diag::warn_implicit_function_decl; + Diag(Loc, diag_id) << &II; + + // Because typo correction is expensive, only do it if the implicit + // function declaration is going to be treated as an error. + if (Diags.getDiagnosticLevel(diag_id, Loc) >= DiagnosticsEngine::Error) { + TypoCorrection Corrected; + DeclFilterCCC Validator; + if (S && (Corrected = CorrectTypo(DeclarationNameInfo(&II, Loc), + LookupOrdinaryName, S, 0, Validator))) { + std::string CorrectedStr = Corrected.getAsString(getLangOpts()); + std::string CorrectedQuotedStr = Corrected.getQuoted(getLangOpts()); + FunctionDecl *Func = Corrected.getCorrectionDeclAs(); + + Diag(Loc, diag::note_function_suggestion) << CorrectedQuotedStr + << FixItHint::CreateReplacement(Loc, CorrectedStr); + + if (Func->getLocation().isValid() + && !II.getName().startswith("__builtin_")) + Diag(Func->getLocation(), diag::note_previous_decl) + << CorrectedQuotedStr; + } + } + + // Set a Declarator for the implicit definition: int foo(); + const char *Dummy; + AttributeFactory attrFactory; + DeclSpec DS(attrFactory); + unsigned DiagID; + bool Error = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, Dummy, DiagID); + (void)Error; // Silence warning. + assert(!Error && "Error setting up implicit decl!"); + Declarator D(DS, Declarator::BlockContext); + D.AddTypeInfo(DeclaratorChunk::getFunction(false, false, SourceLocation(), 0, + 0, 0, true, SourceLocation(), + SourceLocation(), SourceLocation(), + SourceLocation(), + EST_None, SourceLocation(), + 0, 0, 0, 0, Loc, Loc, D), + DS.getAttributes(), + SourceLocation()); + D.SetIdentifier(&II, Loc); + + // Insert this function into translation-unit scope. + + DeclContext *PrevDC = CurContext; + CurContext = Context.getTranslationUnitDecl(); + + FunctionDecl *FD = dyn_cast(ActOnDeclarator(TUScope, D)); + FD->setImplicit(); + + CurContext = PrevDC; + + AddKnownFunctionAttributes(FD); + + return FD; +} + +/// \brief Adds any function attributes that we know a priori based on +/// the declaration of this function. +/// +/// These attributes can apply both to implicitly-declared builtins +/// (like __builtin___printf_chk) or to library-declared functions +/// like NSLog or printf. +/// +/// We need to check for duplicate attributes both here and where user-written +/// attributes are applied to declarations. +void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { + if (FD->isInvalidDecl()) + return; + + // If this is a built-in function, map its builtin attributes to + // actual attributes. + if (unsigned BuiltinID = FD->getBuiltinID()) { + // Handle printf-formatting attributes. + unsigned FormatIdx; + bool HasVAListArg; + if (Context.BuiltinInfo.isPrintfLike(BuiltinID, FormatIdx, HasVAListArg)) { + if (!FD->getAttr()) { + const char *fmt = "printf"; + unsigned int NumParams = FD->getNumParams(); + if (FormatIdx < NumParams && // NumParams may be 0 (e.g. vfprintf) + FD->getParamDecl(FormatIdx)->getType()->isObjCObjectPointerType()) + fmt = "NSString"; + FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context, + fmt, 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 + // IRgen to use LLVM intrinsics for such functions. + if (!getLangOpts().MathErrno && + Context.BuiltinInfo.isConstWithoutErrno(BuiltinID)) { + if (!FD->getAttr()) + FD->addAttr(::new (Context) ConstAttr(FD->getLocation(), Context)); + } + + if (Context.BuiltinInfo.isReturnsTwice(BuiltinID) && + !FD->getAttr()) + FD->addAttr(::new (Context) ReturnsTwiceAttr(FD->getLocation(), Context)); + if (Context.BuiltinInfo.isNoThrow(BuiltinID) && !FD->getAttr()) + FD->addAttr(::new (Context) NoThrowAttr(FD->getLocation(), Context)); + if (Context.BuiltinInfo.isConst(BuiltinID) && !FD->getAttr()) + FD->addAttr(::new (Context) ConstAttr(FD->getLocation(), Context)); + } + + IdentifierInfo *Name = FD->getIdentifier(); + if (!Name) + return; + if ((!getLangOpts().CPlusPlus && + FD->getDeclContext()->isTranslationUnit()) || + (isa(FD->getDeclContext()) && + cast(FD->getDeclContext())->getLanguage() == + LinkageSpecDecl::lang_c)) { + // Okay: this could be a libc/libm/Objective-C function we know + // about. + } else + return; + + 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(FD->getLocation(), Context, + "printf", 2, + Name->isStr("vasprintf") ? 0 : 3)); + } +} + +TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T, + TypeSourceInfo *TInfo) { + assert(D.getIdentifier() && "Wrong callback for declspec without declarator"); + assert(!T.isNull() && "GetTypeForDeclarator() returned null type"); + + if (!TInfo) { + assert(D.isInvalidType() && "no declarator info for valid type"); + TInfo = Context.getTrivialTypeSourceInfo(T); + } + + // Scope manipulation handled by caller. + TypedefDecl *NewTD = TypedefDecl::Create(Context, CurContext, + D.getLocStart(), + D.getIdentifierLoc(), + D.getIdentifier(), + TInfo); + + // Bail out immediately if we have an invalid declaration. + if (D.isInvalidType()) { + NewTD->setInvalidDecl(); + return NewTD; + } + + if (D.getDeclSpec().isModulePrivateSpecified()) { + if (CurContext->isFunctionOrMethod()) + Diag(NewTD->getLocation(), diag::err_module_private_local) + << 2 << NewTD->getDeclName() + << SourceRange(D.getDeclSpec().getModulePrivateSpecLoc()) + << FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc()); + else + NewTD->setModulePrivate(); + } + + // C++ [dcl.typedef]p8: + // If the typedef declaration defines an unnamed class (or + // enum), the first typedef-name declared by the declaration + // to be that class type (or enum type) is used to denote the + // class type (or enum type) for linkage purposes only. + // We need to check whether the type was declared in the declaration. + switch (D.getDeclSpec().getTypeSpecType()) { + case TST_enum: + case TST_struct: + case TST_union: + case TST_class: { + TagDecl *tagFromDeclSpec = cast(D.getDeclSpec().getRepAsDecl()); + + // Do nothing if the tag is not anonymous or already has an + // associated typedef (from an earlier typedef in this decl group). + if (tagFromDeclSpec->getIdentifier()) break; + if (tagFromDeclSpec->getTypedefNameForAnonDecl()) break; + + // A well-formed anonymous tag must always be a TUK_Definition. + assert(tagFromDeclSpec->isThisDeclarationADefinition()); + + // The type must match the tag exactly; no qualifiers allowed. + if (!Context.hasSameType(T, Context.getTagDeclType(tagFromDeclSpec))) + break; + + // Otherwise, set this is the anon-decl typedef for the tag. + tagFromDeclSpec->setTypedefNameForAnonDecl(NewTD); + break; + } + + default: + break; + } + + return NewTD; +} + + +/// \brief Check that this is a valid underlying type for an enum declaration. +bool Sema::CheckEnumUnderlyingType(TypeSourceInfo *TI) { + SourceLocation UnderlyingLoc = TI->getTypeLoc().getBeginLoc(); + QualType T = TI->getType(); + + if (T->isDependentType() || T->isIntegralType(Context)) + return false; + + Diag(UnderlyingLoc, diag::err_enum_invalid_underlying) << T; + return true; +} + +/// Check whether this is a valid redeclaration of a previous enumeration. +/// \return true if the redeclaration was invalid. +bool Sema::CheckEnumRedeclaration(SourceLocation EnumLoc, bool IsScoped, + QualType EnumUnderlyingTy, + const EnumDecl *Prev) { + bool IsFixed = !EnumUnderlyingTy.isNull(); + + if (IsScoped != Prev->isScoped()) { + Diag(EnumLoc, diag::err_enum_redeclare_scoped_mismatch) + << Prev->isScoped(); + Diag(Prev->getLocation(), diag::note_previous_use); + return true; + } + + if (IsFixed && Prev->isFixed()) { + if (!EnumUnderlyingTy->isDependentType() && + !Prev->getIntegerType()->isDependentType() && + !Context.hasSameUnqualifiedType(EnumUnderlyingTy, + Prev->getIntegerType())) { + Diag(EnumLoc, diag::err_enum_redeclare_type_mismatch) + << EnumUnderlyingTy << Prev->getIntegerType(); + Diag(Prev->getLocation(), diag::note_previous_use); + return true; + } + } else if (IsFixed != Prev->isFixed()) { + Diag(EnumLoc, diag::err_enum_redeclare_fixed_mismatch) + << Prev->isFixed(); + Diag(Prev->getLocation(), diag::note_previous_use); + return true; + } + + return false; +} + +/// \brief Determine whether a tag with a given kind is acceptable +/// as a redeclaration of the given tag declaration. +/// +/// \returns true if the new tag kind is acceptable, false otherwise. +bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous, + TagTypeKind NewTag, bool isDefinition, + SourceLocation NewTagLoc, + const IdentifierInfo &Name) { + // C++ [dcl.type.elab]p3: + // The class-key or enum keyword present in the + // elaborated-type-specifier shall agree in kind with the + // declaration to which the name in the elaborated-type-specifier + // refers. This rule also applies to the form of + // elaborated-type-specifier that declares a class-name or + // friend class since it can be construed as referring to the + // definition of the class. Thus, in any + // elaborated-type-specifier, the enum keyword shall be used to + // refer to an enumeration (7.2), the union class-key shall be + // used to refer to a union (clause 9), and either the class or + // struct class-key shall be used to refer to a class (clause 9) + // declared using the class or struct class-key. + TagTypeKind OldTag = Previous->getTagKind(); + if (!isDefinition || (NewTag != TTK_Class && NewTag != TTK_Struct)) + if (OldTag == NewTag) + return true; + + if ((OldTag == TTK_Struct || OldTag == TTK_Class) && + (NewTag == TTK_Struct || NewTag == TTK_Class)) { + // Warn about the struct/class tag mismatch. + bool isTemplate = false; + if (const CXXRecordDecl *Record = dyn_cast(Previous)) + isTemplate = Record->getDescribedClassTemplate(); + + if (!ActiveTemplateInstantiations.empty()) { + // In a template instantiation, do not offer fix-its for tag mismatches + // since they usually mess up the template instead of fixing the problem. + Diag(NewTagLoc, diag::warn_struct_class_tag_mismatch) + << (NewTag == TTK_Class) << isTemplate << &Name; + return true; + } + + if (isDefinition) { + // On definitions, check previous tags and issue a fix-it for each + // one that doesn't match the current tag. + if (Previous->getDefinition()) { + // Don't suggest fix-its for redefinitions. + return true; + } + + bool previousMismatch = false; + for (TagDecl::redecl_iterator I(Previous->redecls_begin()), + E(Previous->redecls_end()); I != E; ++I) { + if (I->getTagKind() != NewTag) { + if (!previousMismatch) { + previousMismatch = true; + Diag(NewTagLoc, diag::warn_struct_class_previous_tag_mismatch) + << (NewTag == TTK_Class) << isTemplate << &Name; + } + Diag(I->getInnerLocStart(), diag::note_struct_class_suggestion) + << (NewTag == TTK_Class) + << FixItHint::CreateReplacement(I->getInnerLocStart(), + NewTag == TTK_Class? + "class" : "struct"); + } + } + return true; + } + + // Check for a previous definition. If current tag and definition + // are same type, do nothing. If no definition, but disagree with + // with previous tag type, give a warning, but no fix-it. + const TagDecl *Redecl = Previous->getDefinition() ? + Previous->getDefinition() : Previous; + if (Redecl->getTagKind() == NewTag) { + return true; + } + + Diag(NewTagLoc, diag::warn_struct_class_tag_mismatch) + << (NewTag == TTK_Class) + << isTemplate << &Name; + Diag(Redecl->getLocation(), diag::note_previous_use); + + // If there is a previous defintion, suggest a fix-it. + if (Previous->getDefinition()) { + Diag(NewTagLoc, diag::note_struct_class_suggestion) + << (Redecl->getTagKind() == TTK_Class) + << FixItHint::CreateReplacement(SourceRange(NewTagLoc), + Redecl->getTagKind() == TTK_Class? "class" : "struct"); + } + + return true; + } + return false; +} + +/// ActOnTag - This is invoked when we see 'struct foo' or 'struct {'. In the +/// 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. +Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, + SourceLocation KWLoc, CXXScopeSpec &SS, + IdentifierInfo *Name, SourceLocation NameLoc, + AttributeList *Attr, AccessSpecifier AS, + SourceLocation ModulePrivateLoc, + MultiTemplateParamsArg TemplateParameterLists, + bool &OwnedDecl, bool &IsDependent, + SourceLocation ScopedEnumKWLoc, + bool ScopedEnumUsesClassTag, + TypeResult UnderlyingType) { + // If this is not a definition, it must have a name. + IdentifierInfo *OrigName = Name; + assert((Name != 0 || TUK == TUK_Definition) && + "Nameless record must be a definition!"); + assert(TemplateParameterLists.size() == 0 || TUK != TUK_Reference); + + OwnedDecl = false; + TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec); + bool ScopedEnum = ScopedEnumKWLoc.isValid(); + + // FIXME: Check explicit specializations more carefully. + bool isExplicitSpecialization = false; + bool Invalid = false; + + // We only need to do this matching if we have template parameters + // or a scope specifier, which also conveniently avoids this work + // for non-C++ cases. + if (TemplateParameterLists.size() > 0 || + (SS.isNotEmpty() && TUK != TUK_Reference)) { + if (TemplateParameterList *TemplateParams + = MatchTemplateParametersToScopeSpecifier(KWLoc, NameLoc, SS, + TemplateParameterLists.get(), + TemplateParameterLists.size(), + TUK == TUK_Friend, + isExplicitSpecialization, + Invalid)) { + if (TemplateParams->size() > 0) { + // This is a declaration or definition of a class template (which may + // be a member of another template). + + if (Invalid) + return 0; + + OwnedDecl = false; + DeclResult Result = CheckClassTemplate(S, TagSpec, TUK, KWLoc, + SS, Name, NameLoc, Attr, + TemplateParams, AS, + ModulePrivateLoc, + TemplateParameterLists.size() - 1, + (TemplateParameterList**) TemplateParameterLists.release()); + return Result.get(); + } else { + // The "template<>" header is extraneous. + Diag(TemplateParams->getTemplateLoc(), diag::err_template_tag_noparams) + << TypeWithKeyword::getTagTypeKindName(Kind) << Name; + isExplicitSpecialization = true; + } + } + } + + // Figure out the underlying type if this a enum declaration. We need to do + // this early, because it's needed to detect if this is an incompatible + // redeclaration. + llvm::PointerUnion EnumUnderlying; + + if (Kind == TTK_Enum) { + if (UnderlyingType.isInvalid() || (!UnderlyingType.get() && ScopedEnum)) + // No underlying type explicitly specified, or we failed to parse the + // type, default to int. + EnumUnderlying = Context.IntTy.getTypePtr(); + else if (UnderlyingType.get()) { + // C++0x 7.2p2: The type-specifier-seq of an enum-base shall name an + // integral type; any cv-qualification is ignored. + TypeSourceInfo *TI = 0; + GetTypeFromParser(UnderlyingType.get(), &TI); + EnumUnderlying = TI; + + if (CheckEnumUnderlyingType(TI)) + // Recover by falling back to int. + EnumUnderlying = Context.IntTy.getTypePtr(); + + if (DiagnoseUnexpandedParameterPack(TI->getTypeLoc().getBeginLoc(), TI, + UPPC_FixedUnderlyingType)) + EnumUnderlying = Context.IntTy.getTypePtr(); + + } else if (getLangOpts().MicrosoftMode) + // Microsoft enums are always of int type. + EnumUnderlying = Context.IntTy.getTypePtr(); + } + + DeclContext *SearchDC = CurContext; + DeclContext *DC = CurContext; + bool isStdBadAlloc = false; + + RedeclarationKind Redecl = ForRedeclaration; + if (TUK == TUK_Friend || TUK == TUK_Reference) + Redecl = NotForRedeclaration; + + LookupResult Previous(*this, Name, NameLoc, LookupTagName, Redecl); + + if (Name && SS.isNotEmpty()) { + // We have a nested-name tag ('struct foo::bar'). + + // Check for invalid 'foo::'. + if (SS.isInvalid()) { + Name = 0; + goto CreateNewDecl; + } + + // If this is a friend or a reference to a class in a dependent + // context, don't try to make a decl for it. + if (TUK == TUK_Friend || TUK == TUK_Reference) { + DC = computeDeclContext(SS, false); + if (!DC) { + IsDependent = true; + return 0; + } + } else { + DC = computeDeclContext(SS, true); + if (!DC) { + Diag(SS.getRange().getBegin(), diag::err_dependent_nested_name_spec) + << SS.getRange(); + return 0; + } + } + + if (RequireCompleteDeclContext(SS, DC)) + return 0; + + SearchDC = DC; + // Look-up name inside 'foo::'. + LookupQualifiedName(Previous, DC); + + if (Previous.isAmbiguous()) + return 0; + + if (Previous.empty()) { + // Name lookup did not find anything. However, if the + // nested-name-specifier refers to the current instantiation, + // and that current instantiation has any dependent base + // classes, we might find something at instantiation time: treat + // this as a dependent elaborated-type-specifier. + // But this only makes any sense for reference-like lookups. + if (Previous.wasNotFoundInCurrentInstantiation() && + (TUK == TUK_Reference || TUK == TUK_Friend)) { + IsDependent = true; + return 0; + } + + // A tag 'foo::bar' must already exist. + Diag(NameLoc, diag::err_not_tag_in_scope) + << Kind << Name << DC << SS.getRange(); + Name = 0; + Invalid = true; + goto CreateNewDecl; + } + } else if (Name) { + // If this is a named struct, check to see if there was a previous forward + // declaration or definition. + // FIXME: We're looking into outer scopes here, even when we + // shouldn't be. Doing so can result in ambiguities that we + // shouldn't be diagnosing. + LookupName(Previous, S); + + if (Previous.isAmbiguous() && + (TUK == TUK_Definition || TUK == TUK_Declaration)) { + LookupResult::Filter F = Previous.makeFilter(); + while (F.hasNext()) { + NamedDecl *ND = F.next(); + if (ND->getDeclContext()->getRedeclContext() != SearchDC) + F.erase(); + } + F.done(); + } + + // Note: there used to be some attempt at recovery here. + if (Previous.isAmbiguous()) + return 0; + + if (!getLangOpts().CPlusPlus && TUK != TUK_Reference) { + // FIXME: This makes sure that we ignore the contexts associated + // with C structs, unions, and enums when looking for a matching + // tag declaration or definition. See the similar lookup tweak + // in Sema::LookupName; is there a better way to deal with this? + while (isa(SearchDC) || isa(SearchDC)) + SearchDC = SearchDC->getParent(); + } + } else if (S->isFunctionPrototypeScope()) { + // If this is an enum declaration in function prototype scope, set its + // initial context to the translation unit. + // FIXME: [citation needed] + SearchDC = Context.getTranslationUnitDecl(); + } + + if (Previous.isSingleResult() && + Previous.getFoundDecl()->isTemplateParameter()) { + // Maybe we will complain about the shadowed template parameter. + DiagnoseTemplateParameterShadow(NameLoc, Previous.getFoundDecl()); + // Just pretend that we didn't see the previous declaration. + Previous.clear(); + } + + if (getLangOpts().CPlusPlus && Name && DC && StdNamespace && + DC->Equals(getStdNamespace()) && Name->isStr("bad_alloc")) { + // This is a declaration of or a reference to "std::bad_alloc". + isStdBadAlloc = true; + + if (Previous.empty() && StdBadAlloc) { + // 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(getStdBadAlloc()); + } + } + + // If we didn't find a previous declaration, and this is a reference + // (or friend reference), move to the correct scope. In C++, we + // also need to do a redeclaration lookup there, just in case + // there's a shadow friend decl. + if (Name && Previous.empty() && + (TUK == TUK_Reference || TUK == TUK_Friend)) { + if (Invalid) goto CreateNewDecl; + assert(SS.isEmpty()); + + if (TUK == TUK_Reference) { + // C++ [basic.scope.pdecl]p5: + // -- for an elaborated-type-specifier of the form + // + // class-key identifier + // + // if the elaborated-type-specifier is used in the + // decl-specifier-seq or parameter-declaration-clause of a + // function defined in namespace scope, the identifier is + // declared as a class-name in the namespace that contains + // the declaration; otherwise, except as a friend + // declaration, the identifier is declared in the smallest + // non-class, non-function-prototype scope that contains the + // declaration. + // + // C99 6.7.2.3p8 has a similar (but not identical!) provision for + // C structs and unions. + // + // It is an error in C++ to declare (rather than define) an enum + // type, including via an elaborated type specifier. We'll + // diagnose that later; for now, declare the enum in the same + // scope as we would have picked for any other tag type. + // + // GNU C also supports this behavior as part of its incomplete + // enum types extension, while GNU C++ does not. + // + // Find the context where we'll be declaring the tag. + // FIXME: We would like to maintain the current DeclContext as the + // lexical context, + while (!SearchDC->isFileContext() && !SearchDC->isFunctionOrMethod()) + SearchDC = SearchDC->getParent(); + + // Find the scope where we'll be declaring the tag. + while (S->isClassScope() || + (getLangOpts().CPlusPlus && + S->isFunctionPrototypeScope()) || + ((S->getFlags() & Scope::DeclScope) == 0) || + (S->getEntity() && + ((DeclContext *)S->getEntity())->isTransparentContext())) + S = S->getParent(); + } else { + assert(TUK == TUK_Friend); + // C++ [namespace.memdef]p3: + // If a friend declaration in a non-local class first declares a + // class or function, the friend class or function is a member of + // the innermost enclosing namespace. + SearchDC = SearchDC->getEnclosingNamespaceContext(); + } + + // In C++, we need to do a redeclaration lookup to properly + // diagnose some problems. + if (getLangOpts().CPlusPlus) { + Previous.setRedeclarationKind(ForRedeclaration); + LookupQualifiedName(Previous, SearchDC); + } + } + + if (!Previous.empty()) { + NamedDecl *PrevDecl = (*Previous.begin())->getUnderlyingDecl(); + + // It's okay to have a tag decl in the same scope as a typedef + // which hides a tag decl in the same scope. Finding this + // insanity with a redeclaration lookup can only actually happen + // in C++. + // + // This is also okay for elaborated-type-specifiers, which is + // technically forbidden by the current standard but which is + // okay according to the likely resolution of an open issue; + // see http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#407 + if (getLangOpts().CPlusPlus) { + if (TypedefNameDecl *TD = dyn_cast(PrevDecl)) { + if (const TagType *TT = TD->getUnderlyingType()->getAs()) { + TagDecl *Tag = TT->getDecl(); + if (Tag->getDeclName() == Name && + Tag->getDeclContext()->getRedeclContext() + ->Equals(TD->getDeclContext()->getRedeclContext())) { + PrevDecl = Tag; + Previous.clear(); + Previous.addDecl(Tag); + Previous.resolveKind(); + } + } + } + } + + if (TagDecl *PrevTagDecl = dyn_cast(PrevDecl)) { + // If this is a use of a previous tag, or if the tag is already declared + // in the same scope (so that the definition/declaration completes or + // rementions the tag), reuse the decl. + if (TUK == TUK_Reference || TUK == TUK_Friend || + isDeclInScope(PrevDecl, SearchDC, S, isExplicitSpecialization)) { + // Make sure that this wasn't declared as an enum and now used as a + // struct or something similar. + if (!isAcceptableTagRedeclaration(PrevTagDecl, Kind, + TUK == TUK_Definition, KWLoc, + *Name)) { + bool SafeToContinue + = (PrevTagDecl->getTagKind() != TTK_Enum && + Kind != TTK_Enum); + if (SafeToContinue) + Diag(KWLoc, diag::err_use_with_wrong_tag) + << Name + << FixItHint::CreateReplacement(SourceRange(KWLoc), + PrevTagDecl->getKindName()); + else + Diag(KWLoc, diag::err_use_with_wrong_tag) << Name; + Diag(PrevTagDecl->getLocation(), diag::note_previous_use); + + if (SafeToContinue) + Kind = PrevTagDecl->getTagKind(); + else { + // Recover by making this an anonymous redefinition. + Name = 0; + Previous.clear(); + Invalid = true; + } + } + + if (Kind == TTK_Enum && PrevTagDecl->getTagKind() == TTK_Enum) { + const EnumDecl *PrevEnum = cast(PrevTagDecl); + + // If this is an elaborated-type-specifier for a scoped enumeration, + // the 'class' keyword is not necessary and not permitted. + if (TUK == TUK_Reference || TUK == TUK_Friend) { + if (ScopedEnum) + Diag(ScopedEnumKWLoc, diag::err_enum_class_reference) + << PrevEnum->isScoped() + << FixItHint::CreateRemoval(ScopedEnumKWLoc); + return PrevTagDecl; + } + + QualType EnumUnderlyingTy; + if (TypeSourceInfo *TI = EnumUnderlying.dyn_cast()) + EnumUnderlyingTy = TI->getType(); + else if (const Type *T = EnumUnderlying.dyn_cast()) + EnumUnderlyingTy = QualType(T, 0); + + // All conflicts with previous declarations are recovered by + // returning the previous declaration, unless this is a definition, + // in which case we want the caller to bail out. + if (CheckEnumRedeclaration(NameLoc.isValid() ? NameLoc : KWLoc, + ScopedEnum, EnumUnderlyingTy, PrevEnum)) + return TUK == TUK_Declaration ? PrevTagDecl : 0; + } + + if (!Invalid) { + // If this is a use, just return the declaration we found. + + // FIXME: In the future, return a variant or some other clue + // for the consumer of this Decl to know it doesn't own it. + // For our current ASTs this shouldn't be a problem, but will + // need to be changed with DeclGroups. + if ((TUK == TUK_Reference && (!PrevTagDecl->getFriendObjectKind() || + getLangOpts().MicrosoftExt)) || TUK == TUK_Friend) + return PrevTagDecl; + + // Diagnose attempts to redefine a tag. + if (TUK == TUK_Definition) { + if (TagDecl *Def = PrevTagDecl->getDefinition()) { + // If we're defining a specialization and the previous definition + // is from an implicit instantiation, don't emit an error + // here; we'll catch this in the general case below. + bool IsExplicitSpecializationAfterInstantiation = false; + if (isExplicitSpecialization) { + if (CXXRecordDecl *RD = dyn_cast(Def)) + IsExplicitSpecializationAfterInstantiation = + RD->getTemplateSpecializationKind() != + TSK_ExplicitSpecialization; + else if (EnumDecl *ED = dyn_cast(Def)) + IsExplicitSpecializationAfterInstantiation = + ED->getTemplateSpecializationKind() != + TSK_ExplicitSpecialization; + } + + if (!IsExplicitSpecializationAfterInstantiation) { + // A redeclaration in function prototype scope in C isn't + // visible elsewhere, so merely issue a warning. + if (!getLangOpts().CPlusPlus && S->containedInPrototypeScope()) + Diag(NameLoc, diag::warn_redefinition_in_param_list) << Name; + else + Diag(NameLoc, diag::err_redefinition) << Name; + Diag(Def->getLocation(), diag::note_previous_definition); + // If this is a redefinition, recover by making this + // struct be anonymous, which will make any later + // references get the previous definition. + Name = 0; + Previous.clear(); + Invalid = true; + } + } else { + // If the type is currently being defined, complain + // about a nested redefinition. + const TagType *Tag + = cast(Context.getTagDeclType(PrevTagDecl)); + if (Tag->isBeingDefined()) { + Diag(NameLoc, diag::err_nested_redefinition) << Name; + Diag(PrevTagDecl->getLocation(), + diag::note_previous_definition); + Name = 0; + Previous.clear(); + Invalid = true; + } + } + + // Okay, this is definition of a previously declared or referenced + // tag PrevDecl. We're going to create a new Decl for it. + } + } + // If we get here we have (another) forward declaration or we + // have a definition. Just create a new decl. + + } else { + // If we get here, this is a definition of a new tag type in a nested + // scope, e.g. "struct foo; void bar() { struct foo; }", just create a + // new decl/type. We set PrevDecl to NULL so that the entities + // have distinct types. + Previous.clear(); + } + // If we get here, we're going to create a new Decl. If PrevDecl + // is non-NULL, it's a definition of the tag declared by + // PrevDecl. If it's NULL, we have a new definition. + + + // Otherwise, PrevDecl is not a tag, but was found with tag + // lookup. This is only actually possible in C++, where a few + // things like templates still live in the tag namespace. + } else { + // Use a better diagnostic if an elaborated-type-specifier + // found the wrong kind of type on the first + // (non-redeclaration) lookup. + if ((TUK == TUK_Reference || TUK == TUK_Friend) && + !Previous.isForRedeclaration()) { + unsigned Kind = 0; + if (isa(PrevDecl)) Kind = 1; + else if (isa(PrevDecl)) Kind = 2; + else if (isa(PrevDecl)) Kind = 3; + Diag(NameLoc, diag::err_tag_reference_non_tag) << Kind; + Diag(PrevDecl->getLocation(), diag::note_declared_at); + Invalid = true; + + // Otherwise, only diagnose if the declaration is in scope. + } else if (!isDeclInScope(PrevDecl, SearchDC, S, + isExplicitSpecialization)) { + // do nothing + + // Diagnose implicit declarations introduced by elaborated types. + } else if (TUK == TUK_Reference || TUK == TUK_Friend) { + unsigned Kind = 0; + if (isa(PrevDecl)) Kind = 1; + else if (isa(PrevDecl)) Kind = 2; + else if (isa(PrevDecl)) Kind = 3; + Diag(NameLoc, diag::err_tag_reference_conflict) << Kind; + Diag(PrevDecl->getLocation(), diag::note_previous_decl) << PrevDecl; + Invalid = true; + + // Otherwise it's a declaration. Call out a particularly common + // case here. + } else if (TypedefNameDecl *TND = dyn_cast(PrevDecl)) { + unsigned Kind = 0; + if (isa(PrevDecl)) Kind = 1; + Diag(NameLoc, diag::err_tag_definition_of_typedef) + << Name << Kind << TND->getUnderlyingType(); + Diag(PrevDecl->getLocation(), diag::note_previous_decl) << PrevDecl; + Invalid = true; + + // Otherwise, diagnose. + } else { + // The tag name clashes with something else in the target scope, + // issue an error and recover by making this tag be anonymous. + Diag(NameLoc, diag::err_redefinition_different_kind) << Name; + Diag(PrevDecl->getLocation(), diag::note_previous_definition); + Name = 0; + Invalid = true; + } + + // The existing declaration isn't relevant to us; we're in a + // new scope, so clear out the previous declaration. + Previous.clear(); + } + } + +CreateNewDecl: + + TagDecl *PrevDecl = 0; + if (Previous.isSingleResult()) + PrevDecl = cast(Previous.getFoundDecl()); + + // If there is an identifier, use the location of the identifier as the + // location of the decl, otherwise use the location of the struct/union + // keyword. + SourceLocation Loc = NameLoc.isValid() ? NameLoc : KWLoc; + + // Otherwise, create a new declaration. If there is a previous + // declaration of the same entity, the two will be linked via + // PrevDecl. + TagDecl *New; + + bool IsForwardReference = false; + if (Kind == TTK_Enum) { + // FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.: + // enum X { A, B, C } D; D should chain to X. + New = EnumDecl::Create(Context, SearchDC, KWLoc, Loc, Name, + cast_or_null(PrevDecl), ScopedEnum, + ScopedEnumUsesClassTag, !EnumUnderlying.isNull()); + // If this is an undefined enum, warn. + if (TUK != TUK_Definition && !Invalid) { + TagDecl *Def; + if (getLangOpts().CPlusPlus0x && cast(New)->isFixed()) { + // C++0x: 7.2p2: opaque-enum-declaration. + // Conflicts are diagnosed above. Do nothing. + } + else if (PrevDecl && (Def = cast(PrevDecl)->getDefinition())) { + Diag(Loc, diag::ext_forward_ref_enum_def) + << New; + Diag(Def->getLocation(), diag::note_previous_definition); + } else { + unsigned DiagID = diag::ext_forward_ref_enum; + if (getLangOpts().MicrosoftMode) + DiagID = diag::ext_ms_forward_ref_enum; + else if (getLangOpts().CPlusPlus) + DiagID = diag::err_forward_ref_enum; + Diag(Loc, DiagID); + + // If this is a forward-declared reference to an enumeration, make a + // note of it; we won't actually be introducing the declaration into + // the declaration context. + if (TUK == TUK_Reference) + IsForwardReference = true; + } + } + + if (EnumUnderlying) { + EnumDecl *ED = cast(New); + if (TypeSourceInfo *TI = EnumUnderlying.dyn_cast()) + ED->setIntegerTypeSourceInfo(TI); + else + ED->setIntegerType(QualType(EnumUnderlying.get(), 0)); + ED->setPromotionType(ED->getIntegerType()); + } + + } else { + // struct/union/class + + // FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.: + // struct X { int A; } D; D should chain to X. + if (getLangOpts().CPlusPlus) { + // FIXME: Look for a way to use RecordDecl for simple structs. + New = CXXRecordDecl::Create(Context, Kind, SearchDC, KWLoc, Loc, Name, + cast_or_null(PrevDecl)); + + if (isStdBadAlloc && (!StdBadAlloc || getStdBadAlloc()->isImplicit())) + StdBadAlloc = cast(New); + } else + New = RecordDecl::Create(Context, Kind, SearchDC, KWLoc, Loc, Name, + cast_or_null(PrevDecl)); + } + + // Maybe add qualifier info. + if (SS.isNotEmpty()) { + if (SS.isSet()) { + // If this is either a declaration or a definition, check the + // nested-name-specifier against the current context. We don't do this + // for explicit specializations, because they have similar checking + // (with more specific diagnostics) in the call to + // CheckMemberSpecialization, below. + if (!isExplicitSpecialization && + (TUK == TUK_Definition || TUK == TUK_Declaration) && + diagnoseQualifiedDeclaration(SS, DC, OrigName, NameLoc)) + Invalid = true; + + New->setQualifierInfo(SS.getWithLocInContext(Context)); + if (TemplateParameterLists.size() > 0) { + New->setTemplateParameterListsInfo(Context, + TemplateParameterLists.size(), + (TemplateParameterList**) TemplateParameterLists.release()); + } + } + else + Invalid = true; + } + + if (RecordDecl *RD = dyn_cast(New)) { + // Add alignment attributes if necessary; these attributes are checked when + // the ASTContext lays out the structure. + // + // It is important for implementing the correct semantics that this + // happen here (in act on tag decl). The #pragma pack stack is + // maintained as a result of parser callbacks which can occur at + // many points during the parsing of a struct declaration (because + // the #pragma tokens are effectively skipped over during the + // parsing of the struct). + AddAlignmentAttributesForRecord(RD); + + AddMsStructLayoutForRecord(RD); + } + + if (ModulePrivateLoc.isValid()) { + if (isExplicitSpecialization) + Diag(New->getLocation(), diag::err_module_private_specialization) + << 2 + << FixItHint::CreateRemoval(ModulePrivateLoc); + // __module_private__ does not apply to local classes. However, we only + // diagnose this as an error when the declaration specifiers are + // freestanding. Here, we just ignore the __module_private__. + else if (!SearchDC->isFunctionOrMethod()) + New->setModulePrivate(); + } + + // If this is a specialization of a member class (of a class template), + // check the specialization. + if (isExplicitSpecialization && CheckMemberSpecialization(New, Previous)) + Invalid = true; + + if (Invalid) + New->setInvalidDecl(); + + if (Attr) + ProcessDeclAttributeList(S, New, Attr); + + // If we're declaring or defining a tag in function prototype scope + // in C, note that this type can only be used within the function. + if (Name && S->isFunctionPrototypeScope() && !getLangOpts().CPlusPlus) + Diag(Loc, diag::warn_decl_in_param_list) << Context.getTagDeclType(New); + + // Set the lexical context. If the tag has a C++ scope specifier, the + // lexical context will be different from the semantic context. + New->setLexicalDeclContext(CurContext); + + // Mark this as a friend decl if applicable. + // In Microsoft mode, a friend declaration also acts as a forward + // declaration so we always pass true to setObjectOfFriendDecl to make + // the tag name visible. + if (TUK == TUK_Friend) + New->setObjectOfFriendDecl(/* PreviouslyDeclared = */ !Previous.empty() || + getLangOpts().MicrosoftExt); + + // Set the access specifier. + if (!Invalid && SearchDC->isRecord()) + SetMemberAccessSpecifier(New, PrevDecl, AS); + + if (TUK == TUK_Definition) + New->startDefinition(); + + // If this has an identifier, add it to the scope stack. + if (TUK == TUK_Friend) { + // We might be replacing an existing declaration in the lookup tables; + // if so, borrow its access specifier. + if (PrevDecl) + New->setAccess(PrevDecl->getAccess()); + + DeclContext *DC = New->getDeclContext()->getRedeclContext(); + DC->makeDeclVisibleInContext(New); + if (Name) // can be null along some error paths + if (Scope *EnclosingScope = getScopeForDeclContext(S, DC)) + PushOnScopeChains(New, EnclosingScope, /* AddToContext = */ false); + } else if (Name) { + S = getNonFieldDeclScope(S); + PushOnScopeChains(New, S, !IsForwardReference); + if (IsForwardReference) + SearchDC->makeDeclVisibleInContext(New); + + } else { + CurContext->addDecl(New); + } + + // If this is the C FILE type, notify the AST context. + if (IdentifierInfo *II = New->getIdentifier()) + if (!New->isInvalidDecl() && + New->getDeclContext()->getRedeclContext()->isTranslationUnit() && + II->isStr("FILE")) + Context.setFILEDecl(New); + + // If we were in function prototype scope (and not in C++ mode), add this + // tag to the list of decls to inject into the function definition scope. + if (S->isFunctionPrototypeScope() && !getLangOpts().CPlusPlus && + InFunctionDeclarator && Name) + DeclsInPrototypeScope.push_back(New); + + OwnedDecl = true; + return New; +} + +void Sema::ActOnTagStartDefinition(Scope *S, Decl *TagD) { + AdjustDeclIfTemplate(TagD); + TagDecl *Tag = cast(TagD); + + // Enter the tag context. + PushDeclContext(S, Tag); +} + +Decl *Sema::ActOnObjCContainerStartDefinition(Decl *IDecl) { + assert(isa(IDecl) && + "ActOnObjCContainerStartDefinition - Not ObjCContainerDecl"); + DeclContext *OCD = cast(IDecl); + assert(getContainingDC(OCD) == CurContext && + "The next DeclContext should be lexically contained in the current one."); + CurContext = OCD; + return IDecl; +} + +void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD, + SourceLocation FinalLoc, + SourceLocation LBraceLoc) { + AdjustDeclIfTemplate(TagD); + CXXRecordDecl *Record = cast(TagD); + + FieldCollector->StartClass(); + + if (!Record->getIdentifier()) + return; + + if (FinalLoc.isValid()) + Record->addAttr(new (Context) FinalAttr(FinalLoc, Context)); + + // C++ [class]p2: + // [...] The class-name is also inserted into the scope of the + // class itself; this is known as the injected-class-name. For + // purposes of access checking, the injected-class-name is treated + // as if it were a public member name. + CXXRecordDecl *InjectedClassName + = CXXRecordDecl::Create(Context, Record->getTagKind(), CurContext, + Record->getLocStart(), Record->getLocation(), + Record->getIdentifier(), + /*PrevDecl=*/0, + /*DelayTypeCreation=*/true); + Context.getTypeDeclType(InjectedClassName, Record); + InjectedClassName->setImplicit(); + InjectedClassName->setAccess(AS_public); + if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) + InjectedClassName->setDescribedClassTemplate(Template); + PushOnScopeChains(InjectedClassName, S); + assert(InjectedClassName->isInjectedClassName() && + "Broken injected-class-name"); +} + +void Sema::ActOnTagFinishDefinition(Scope *S, Decl *TagD, + SourceLocation RBraceLoc) { + AdjustDeclIfTemplate(TagD); + TagDecl *Tag = cast(TagD); + Tag->setRBraceLoc(RBraceLoc); + + // Make sure we "complete" the definition even it is invalid. + if (Tag->isBeingDefined()) { + assert(Tag->isInvalidDecl() && "We should already have completed it"); + if (RecordDecl *RD = dyn_cast(Tag)) + RD->completeDefinition(); + } + + if (isa(Tag)) + FieldCollector->FinishClass(); + + // Exit this scope of this tag's definition. + PopDeclContext(); + + // Notify the consumer that we've defined a tag. + Consumer.HandleTagDeclDefinition(Tag); +} + +void Sema::ActOnObjCContainerFinishDefinition() { + // Exit this scope of this interface definition. + PopDeclContext(); +} + +void Sema::ActOnObjCTemporaryExitContainerContext(DeclContext *DC) { + assert(DC == CurContext && "Mismatch of container contexts"); + OriginalLexicalContext = DC; + ActOnObjCContainerFinishDefinition(); +} + +void Sema::ActOnObjCReenterContainerContext(DeclContext *DC) { + ActOnObjCContainerStartDefinition(cast(DC)); + OriginalLexicalContext = 0; +} + +void Sema::ActOnTagDefinitionError(Scope *S, Decl *TagD) { + AdjustDeclIfTemplate(TagD); + TagDecl *Tag = cast(TagD); + Tag->setInvalidDecl(); + + // Make sure we "complete" the definition even it is invalid. + if (Tag->isBeingDefined()) { + if (RecordDecl *RD = dyn_cast(Tag)) + RD->completeDefinition(); + } + + // We're undoing ActOnTagStartDefinition here, not + // ActOnStartCXXMemberDeclarations, so we don't have to mess with + // the FieldCollector. + + PopDeclContext(); +} + +// Note that FieldName may be null for anonymous bitfields. +ExprResult Sema::VerifyBitField(SourceLocation FieldLoc, + IdentifierInfo *FieldName, + QualType FieldTy, Expr *BitWidth, + bool *ZeroWidth) { + // Default to true; that shouldn't confuse checks for emptiness + if (ZeroWidth) + *ZeroWidth = true; + + // C99 6.7.2.1p4 - verify the field type. + // C++ 9.6p3: A bit-field shall have integral or enumeration type. + if (!FieldTy->isDependentType() && !FieldTy->isIntegralOrEnumerationType()) { + // Handle incomplete types with specific error. + if (RequireCompleteType(FieldLoc, FieldTy, diag::err_field_incomplete)) + return ExprError(); + if (FieldName) + return Diag(FieldLoc, diag::err_not_integral_type_bitfield) + << FieldName << FieldTy << BitWidth->getSourceRange(); + return Diag(FieldLoc, diag::err_not_integral_type_anon_bitfield) + << FieldTy << BitWidth->getSourceRange(); + } else if (DiagnoseUnexpandedParameterPack(const_cast(BitWidth), + UPPC_BitFieldWidth)) + return ExprError(); + + // If the bit-width is type- or value-dependent, don't try to check + // it now. + if (BitWidth->isValueDependent() || BitWidth->isTypeDependent()) + return Owned(BitWidth); + + llvm::APSInt Value; + ExprResult ICE = VerifyIntegerConstantExpression(BitWidth, &Value); + if (ICE.isInvalid()) + return ICE; + BitWidth = ICE.take(); + + if (Value != 0 && ZeroWidth) + *ZeroWidth = false; + + // Zero-width bitfield is ok for anonymous field. + if (Value == 0 && FieldName) + return Diag(FieldLoc, diag::err_bitfield_has_zero_width) << FieldName; + + if (Value.isSigned() && Value.isNegative()) { + if (FieldName) + return Diag(FieldLoc, diag::err_bitfield_has_negative_width) + << FieldName << Value.toString(10); + return Diag(FieldLoc, diag::err_anon_bitfield_has_negative_width) + << Value.toString(10); + } + + if (!FieldTy->isDependentType()) { + uint64_t TypeSize = Context.getTypeSize(FieldTy); + if (Value.getZExtValue() > TypeSize) { + if (!getLangOpts().CPlusPlus) { + if (FieldName) + return Diag(FieldLoc, diag::err_bitfield_width_exceeds_type_size) + << FieldName << (unsigned)Value.getZExtValue() + << (unsigned)TypeSize; + + return Diag(FieldLoc, diag::err_anon_bitfield_width_exceeds_type_size) + << (unsigned)Value.getZExtValue() << (unsigned)TypeSize; + } + + if (FieldName) + Diag(FieldLoc, diag::warn_bitfield_width_exceeds_type_size) + << FieldName << (unsigned)Value.getZExtValue() + << (unsigned)TypeSize; + else + Diag(FieldLoc, diag::warn_anon_bitfield_width_exceeds_type_size) + << (unsigned)Value.getZExtValue() << (unsigned)TypeSize; + } + } + + return Owned(BitWidth); +} + +/// ActOnField - Each field of a C struct/union is passed into this in order +/// to create a FieldDecl object for it. +Decl *Sema::ActOnField(Scope *S, Decl *TagD, SourceLocation DeclStart, + Declarator &D, Expr *BitfieldWidth) { + FieldDecl *Res = HandleField(S, cast_or_null(TagD), + DeclStart, D, static_cast(BitfieldWidth), + /*HasInit=*/false, AS_public); + return Res; +} + +/// HandleField - Analyze a field of a C struct or a C++ data member. +/// +FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record, + SourceLocation DeclStart, + Declarator &D, Expr *BitWidth, bool HasInit, + AccessSpecifier AS) { + IdentifierInfo *II = D.getIdentifier(); + SourceLocation Loc = DeclStart; + if (II) Loc = D.getIdentifierLoc(); + + TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); + QualType T = TInfo->getType(); + if (getLangOpts().CPlusPlus) { + CheckExtraCXXDefaultArguments(D); + + if (DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo, + UPPC_DataMemberType)) { + D.setInvalidType(); + T = Context.IntTy; + TInfo = Context.getTrivialTypeSourceInfo(T, Loc); + } + } + + DiagnoseFunctionSpecifiers(D); + + if (D.getDeclSpec().isThreadSpecified()) + Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread); + if (D.getDeclSpec().isConstexprSpecified()) + Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_invalid_constexpr) + << 2; + + // Check to see if this name was declared as a member previously + NamedDecl *PrevDecl = 0; + LookupResult Previous(*this, II, Loc, LookupMemberName, ForRedeclaration); + LookupName(Previous, S); + switch (Previous.getResultKind()) { + case LookupResult::Found: + case LookupResult::FoundUnresolvedValue: + PrevDecl = Previous.getAsSingle(); + break; + + case LookupResult::FoundOverloaded: + PrevDecl = Previous.getRepresentativeDecl(); + break; + + case LookupResult::NotFound: + case LookupResult::NotFoundInCurrentInstantiation: + case LookupResult::Ambiguous: + break; + } + Previous.suppressDiagnostics(); + + if (PrevDecl && PrevDecl->isTemplateParameter()) { + // Maybe we will complain about the shadowed template parameter. + DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl); + // Just pretend that we didn't see the previous declaration. + PrevDecl = 0; + } + + if (PrevDecl && !isDeclInScope(PrevDecl, Record, S)) + PrevDecl = 0; + + bool Mutable + = (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_mutable); + SourceLocation TSSL = D.getLocStart(); + FieldDecl *NewFD + = CheckFieldDecl(II, T, TInfo, Record, Loc, Mutable, BitWidth, HasInit, + TSSL, AS, PrevDecl, &D); + + if (NewFD->isInvalidDecl()) + Record->setInvalidDecl(); + + if (D.getDeclSpec().isModulePrivateSpecified()) + NewFD->setModulePrivate(); + + if (NewFD->isInvalidDecl() && PrevDecl) { + // Don't introduce NewFD into scope; there's already something + // with the same name in the same scope. + } else if (II) { + PushOnScopeChains(NewFD, S); + } else + Record->addDecl(NewFD); + + return NewFD; +} + +/// \brief Build a new FieldDecl and check its well-formedness. +/// +/// This routine builds a new FieldDecl given the fields name, type, +/// record, etc. \p PrevDecl should refer to any previous declaration +/// with the same name and in the same scope as the field to be +/// created. +/// +/// \returns a new FieldDecl. +/// +/// \todo The Declarator argument is a hack. It will be removed once +FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, + TypeSourceInfo *TInfo, + RecordDecl *Record, SourceLocation Loc, + bool Mutable, Expr *BitWidth, bool HasInit, + SourceLocation TSSL, + AccessSpecifier AS, NamedDecl *PrevDecl, + Declarator *D) { + IdentifierInfo *II = Name.getAsIdentifierInfo(); + bool InvalidDecl = false; + if (D) InvalidDecl = D->isInvalidType(); + + // If we receive a broken type, recover by assuming 'int' and + // marking this declaration as invalid. + if (T.isNull()) { + InvalidDecl = true; + T = Context.IntTy; + } + + QualType EltTy = Context.getBaseElementType(T); + if (!EltTy->isDependentType()) { + if (RequireCompleteType(Loc, EltTy, diag::err_field_incomplete)) { + // Fields of incomplete type force their record to be invalid. + Record->setInvalidDecl(); + InvalidDecl = true; + } else { + NamedDecl *Def; + EltTy->isIncompleteType(&Def); + if (Def && Def->isInvalidDecl()) { + 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, + 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; + } + } + + // Fields can not have abstract class types + if (!InvalidDecl && RequireNonAbstractType(Loc, T, + diag::err_abstract_type_in_decl, + AbstractFieldType)) + InvalidDecl = true; + + bool ZeroWidth = false; + // If this is declared as a bit-field, check the bit-field. + if (!InvalidDecl && BitWidth) { + BitWidth = VerifyBitField(Loc, II, T, BitWidth, &ZeroWidth).take(); + if (!BitWidth) { + InvalidDecl = true; + BitWidth = 0; + ZeroWidth = false; + } + } + + // Check that 'mutable' is consistent with the type of the declaration. + if (!InvalidDecl && Mutable) { + unsigned DiagID = 0; + if (T->isReferenceType()) + DiagID = diag::err_mutable_reference; + else if (T.isConstQualified()) + DiagID = diag::err_mutable_const; + + if (DiagID) { + SourceLocation ErrLoc = Loc; + if (D && D->getDeclSpec().getStorageClassSpecLoc().isValid()) + ErrLoc = D->getDeclSpec().getStorageClassSpecLoc(); + Diag(ErrLoc, DiagID); + Mutable = false; + InvalidDecl = true; + } + } + + FieldDecl *NewFD = FieldDecl::Create(Context, Record, TSSL, Loc, II, T, TInfo, + BitWidth, Mutable, HasInit); + if (InvalidDecl) + NewFD->setInvalidDecl(); + + if (PrevDecl && !isa(PrevDecl)) { + Diag(Loc, diag::err_duplicate_member) << II; + Diag(PrevDecl->getLocation(), diag::note_previous_declaration); + NewFD->setInvalidDecl(); + } + + if (!InvalidDecl && getLangOpts().CPlusPlus) { + if (Record->isUnion()) { + if (const RecordType *RT = EltTy->getAs()) { + CXXRecordDecl* RDecl = cast(RT->getDecl()); + if (RDecl->getDefinition()) { + // C++ [class.union]p1: An object of a class with a non-trivial + // constructor, a non-trivial copy constructor, a non-trivial + // destructor, or a non-trivial copy assignment operator + // cannot be a member of a union, nor can an array of such + // objects. + if (CheckNontrivialField(NewFD)) + NewFD->setInvalidDecl(); + } + } + + // C++ [class.union]p1: If a union contains a member of reference type, + // the program is ill-formed. + if (EltTy->isReferenceType()) { + Diag(NewFD->getLocation(), diag::err_union_member_of_reference_type) + << NewFD->getDeclName() << EltTy; + NewFD->setInvalidDecl(); + } + } + } + + // FIXME: We need to pass in the attributes given an AST + // representation, not a parser representation. + if (D) + // FIXME: What to pass instead of TUScope? + ProcessDeclAttributes(TUScope, NewFD, *D); + + // In auto-retain/release, infer strong retension for fields of + // retainable type. + if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(NewFD)) + NewFD->setInvalidDecl(); + + if (T.isObjCGCWeak()) + Diag(Loc, diag::warn_attribute_weak_on_field); + + NewFD->setAccess(AS); + return NewFD; +} + +bool Sema::CheckNontrivialField(FieldDecl *FD) { + assert(FD); + assert(getLangOpts().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->hasTrivialDefaultConstructor()) + member = CXXDefaultConstructor; + else if (!RDecl->hasTrivialCopyAssignment()) + member = CXXCopyAssignment; + else if (!RDecl->hasTrivialDestructor()) + member = CXXDestructor; + + if (member != CXXInvalid) { + if (!getLangOpts().CPlusPlus0x && + getLangOpts().ObjCAutoRefCount && RDecl->hasObjectMember()) { + // Objective-C++ ARC: it is an error to have a non-trivial field of + // a union. However, system headers in Objective-C programs + // occasionally have Objective-C lifetime objects within unions, + // and rather than cause the program to fail, we make those + // members unavailable. + SourceLocation Loc = FD->getLocation(); + if (getSourceManager().isInSystemHeader(Loc)) { + if (!FD->hasAttr()) + FD->addAttr(new (Context) UnavailableAttr(Loc, Context, + "this system field has retaining ownership")); + return false; + } + } + + Diag(FD->getLocation(), getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_nontrivial_union_or_anon_struct_member : + diag::err_illegal_union_or_anon_struct_member) + << (int)FD->getParent()->isUnion() << FD->getDeclName() << member; + DiagnoseNontrivial(RT, member); + return !getLangOpts().CPlusPlus0x; + } + } + } + + return false; +} + +/// If the given constructor is user-provided, produce a diagnostic explaining +/// that it makes the class non-trivial. +static bool DiagnoseNontrivialUserProvidedCtor(Sema &S, QualType QT, + CXXConstructorDecl *CD, + Sema::CXXSpecialMember CSM) { + if (!CD->isUserProvided()) + return false; + + SourceLocation CtorLoc = CD->getLocation(); + S.Diag(CtorLoc, diag::note_nontrivial_user_defined) << QT << CSM; + return true; +} + +/// DiagnoseNontrivial - Given that a class has a non-trivial +/// special member, figure out why. +void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) { + QualType QT(T, 0U); + CXXRecordDecl* RD = cast(T->getDecl()); + + // Check whether the member was user-declared. + switch (member) { + case CXXInvalid: + break; + + case CXXDefaultConstructor: + if (RD->hasUserDeclaredConstructor()) { + typedef CXXRecordDecl::ctor_iterator ctor_iter; + for (ctor_iter CI = RD->ctor_begin(), CE = RD->ctor_end(); CI != CE; ++CI) + if (DiagnoseNontrivialUserProvidedCtor(*this, QT, *CI, member)) + return; + + // No user-provided constructors; look for constructor templates. + typedef CXXRecordDecl::specific_decl_iterator + tmpl_iter; + for (tmpl_iter TI(RD->decls_begin()), TE(RD->decls_end()); + TI != TE; ++TI) { + CXXConstructorDecl *CD = + dyn_cast(TI->getTemplatedDecl()); + if (CD && DiagnoseNontrivialUserProvidedCtor(*this, QT, CD, member)) + return; + } + } + break; + + case CXXCopyConstructor: + if (RD->hasUserDeclaredCopyConstructor()) { + SourceLocation CtorLoc = + RD->getCopyConstructor(0)->getLocation(); + Diag(CtorLoc, diag::note_nontrivial_user_defined) << QT << member; + return; + } + break; + + case CXXMoveConstructor: + if (RD->hasUserDeclaredMoveConstructor()) { + SourceLocation CtorLoc = RD->getMoveConstructor()->getLocation(); + Diag(CtorLoc, diag::note_nontrivial_user_defined) << QT << member; + return; + } + break; + + case CXXCopyAssignment: + if (RD->hasUserDeclaredCopyAssignment()) { + // FIXME: this should use the location of the copy + // assignment, not the type. + SourceLocation TyLoc = RD->getLocStart(); + Diag(TyLoc, diag::note_nontrivial_user_defined) << QT << member; + return; + } + break; + + case CXXMoveAssignment: + if (RD->hasUserDeclaredMoveAssignment()) { + SourceLocation AssignLoc = RD->getMoveAssignmentOperator()->getLocation(); + Diag(AssignLoc, diag::note_nontrivial_user_defined) << QT << member; + return; + } + break; + + case CXXDestructor: + if (RD->hasUserDeclaredDestructor()) { + SourceLocation DtorLoc = LookupDestructor(RD)->getLocation(); + Diag(DtorLoc, diag::note_nontrivial_user_defined) << QT << member; + return; + } + break; + } + + typedef CXXRecordDecl::base_class_iterator base_iter; + + // Virtual bases and members inhibit trivial copying/construction, + // but not trivial destruction. + if (member != CXXDestructor) { + // Check for virtual bases. vbases includes indirect virtual bases, + // so we just iterate through the direct bases. + for (base_iter bi = RD->bases_begin(), be = RD->bases_end(); bi != be; ++bi) + if (bi->isVirtual()) { + SourceLocation BaseLoc = bi->getLocStart(); + Diag(BaseLoc, diag::note_nontrivial_has_virtual) << QT << 1; + return; + } + + // Check for virtual methods. + typedef CXXRecordDecl::method_iterator meth_iter; + for (meth_iter mi = RD->method_begin(), me = RD->method_end(); mi != me; + ++mi) { + if (mi->isVirtual()) { + SourceLocation MLoc = mi->getLocStart(); + Diag(MLoc, diag::note_nontrivial_has_virtual) << QT << 0; + return; + } + } + } + + bool (CXXRecordDecl::*hasTrivial)() const; + switch (member) { + case CXXDefaultConstructor: + hasTrivial = &CXXRecordDecl::hasTrivialDefaultConstructor; break; + case CXXCopyConstructor: + hasTrivial = &CXXRecordDecl::hasTrivialCopyConstructor; break; + case CXXCopyAssignment: + hasTrivial = &CXXRecordDecl::hasTrivialCopyAssignment; break; + case CXXDestructor: + hasTrivial = &CXXRecordDecl::hasTrivialDestructor; break; + default: + llvm_unreachable("unexpected special member"); + } + + // Check for nontrivial bases (and recurse). + for (base_iter bi = RD->bases_begin(), be = RD->bases_end(); bi != be; ++bi) { + const RecordType *BaseRT = bi->getType()->getAs(); + assert(BaseRT && "Don't know how to handle dependent bases"); + CXXRecordDecl *BaseRecTy = cast(BaseRT->getDecl()); + if (!(BaseRecTy->*hasTrivial)()) { + SourceLocation BaseLoc = bi->getLocStart(); + Diag(BaseLoc, diag::note_nontrivial_has_nontrivial) << QT << 1 << member; + DiagnoseNontrivial(BaseRT, member); + return; + } + } + + // Check for nontrivial members (and recurse). + typedef RecordDecl::field_iterator field_iter; + for (field_iter fi = RD->field_begin(), fe = RD->field_end(); fi != fe; + ++fi) { + QualType EltTy = Context.getBaseElementType((*fi)->getType()); + if (const RecordType *EltRT = EltTy->getAs()) { + CXXRecordDecl* EltRD = cast(EltRT->getDecl()); + + if (!(EltRD->*hasTrivial)()) { + SourceLocation FLoc = (*fi)->getLocation(); + Diag(FLoc, diag::note_nontrivial_has_nontrivial) << QT << 0 << member; + DiagnoseNontrivial(EltRT, member); + return; + } + } + + if (EltTy->isObjCLifetimeType()) { + switch (EltTy.getObjCLifetime()) { + case Qualifiers::OCL_None: + case Qualifiers::OCL_ExplicitNone: + break; + + case Qualifiers::OCL_Autoreleasing: + case Qualifiers::OCL_Weak: + case Qualifiers::OCL_Strong: + Diag((*fi)->getLocation(), diag::note_nontrivial_objc_ownership) + << QT << EltTy.getObjCLifetime(); + return; + } + } + } + + llvm_unreachable("found no explanation for non-trivial member"); +} + +/// TranslateIvarVisibility - Translate visibility from a token ID to an +/// AST enum value. +static ObjCIvarDecl::AccessControl +TranslateIvarVisibility(tok::ObjCKeywordKind ivarVisibility) { + switch (ivarVisibility) { + default: llvm_unreachable("Unknown visitibility kind"); + case tok::objc_private: return ObjCIvarDecl::Private; + case tok::objc_public: return ObjCIvarDecl::Public; + case tok::objc_protected: return ObjCIvarDecl::Protected; + case tok::objc_package: return ObjCIvarDecl::Package; + } +} + +/// ActOnIvar - Each ivar field of an objective-c class is passed into this +/// in order to create an IvarDecl object for it. +Decl *Sema::ActOnIvar(Scope *S, + SourceLocation DeclStart, + Declarator &D, Expr *BitfieldWidth, + tok::ObjCKeywordKind Visibility) { + + IdentifierInfo *II = D.getIdentifier(); + Expr *BitWidth = (Expr*)BitfieldWidth; + SourceLocation Loc = DeclStart; + if (II) Loc = D.getIdentifierLoc(); + + // FIXME: Unnamed fields can be handled in various different ways, for + // example, unnamed unions inject all members into the struct namespace! + + TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); + QualType T = TInfo->getType(); + + if (BitWidth) { + // 6.7.2.1p3, 6.7.2.1p4 + BitWidth = VerifyBitField(Loc, II, T, BitWidth).take(); + if (!BitWidth) + D.setInvalidType(); + } else { + // Not a bitfield. + + // validate II. + + } + if (T->isReferenceType()) { + Diag(Loc, diag::err_ivar_reference_type); + D.setInvalidType(); + } + // C99 6.7.2.1p8: A member of a structure or union may have any type other + // than a variably modified type. + else if (T->isVariablyModifiedType()) { + Diag(Loc, diag::err_typecheck_ivar_variable_size); + D.setInvalidType(); + } + + // Get the visibility (access control) for this ivar. + ObjCIvarDecl::AccessControl ac = + Visibility != tok::objc_not_keyword ? TranslateIvarVisibility(Visibility) + : ObjCIvarDecl::None; + // Must set ivar's DeclContext to its enclosing interface. + ObjCContainerDecl *EnclosingDecl = cast(CurContext); + if (!EnclosingDecl || EnclosingDecl->isInvalidDecl()) + return 0; + 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!"); + } + else + EnclosingContext = EnclosingDecl; + } else { + if (ObjCCategoryDecl *CDecl = + dyn_cast(EnclosingDecl)) { + if (!LangOpts.ObjCNonFragileABI2 || !CDecl->IsClassExtension()) { + Diag(Loc, diag::err_misplaced_ivar) << CDecl->IsClassExtension(); + return 0; + } + } + EnclosingContext = EnclosingDecl; + } + + // Construct the decl. + ObjCIvarDecl *NewID = ObjCIvarDecl::Create(Context, EnclosingContext, + DeclStart, Loc, II, T, + TInfo, ac, (Expr *)BitfieldWidth); + + if (II) { + NamedDecl *PrevDecl = LookupSingleName(S, II, Loc, LookupMemberName, + ForRedeclaration); + if (PrevDecl && isDeclInScope(PrevDecl, EnclosingContext, S) + && !isa(PrevDecl)) { + Diag(Loc, diag::err_duplicate_member) << II; + Diag(PrevDecl->getLocation(), diag::note_previous_declaration); + NewID->setInvalidDecl(); + } + } + + // Process attributes attached to the ivar. + ProcessDeclAttributes(S, NewID, D); + + if (D.isInvalidType()) + NewID->setInvalidDecl(); + + // In ARC, infer 'retaining' for ivars of retainable type. + if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(NewID)) + NewID->setInvalidDecl(); + + if (D.getDeclSpec().isModulePrivateSpecified()) + NewID->setModulePrivate(); + + if (II) { + // FIXME: When interfaces are DeclContexts, we'll need to add + // these to the interface. + S->AddDecl(NewID); + IdResolver.AddDecl(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, + SmallVectorImpl &AllIvarDecls) { + if (!LangOpts.ObjCNonFragileABI2 || AllIvarDecls.empty()) + return; + + Decl *ivarDecl = AllIvarDecls[AllIvarDecls.size()-1]; + ObjCIvarDecl *Ivar = cast(ivarDecl); + + if (!Ivar->isBitField() || Ivar->getBitWidthValue(Context) == 0) + return; + ObjCInterfaceDecl *ID = dyn_cast(CurContext); + if (!ID) { + if (ObjCCategoryDecl *CD = dyn_cast(CurContext)) { + 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.IntTy), 0); + Expr * BW = IntegerLiteral::Create(Context, Zero, Context.IntTy, DeclLoc); + + Ivar = ObjCIvarDecl::Create(Context, cast(CurContext), + DeclLoc, DeclLoc, 0, + Context.CharTy, + Context.getTrivialTypeSourceInfo(Context.CharTy, + DeclLoc), + ObjCIvarDecl::Private, BW, + true); + AllIvarDecls.push_back(Ivar); +} + +void Sema::ActOnFields(Scope* S, + SourceLocation RecLoc, Decl *EnclosingDecl, + llvm::ArrayRef Fields, + SourceLocation LBrac, SourceLocation RBrac, + AttributeList *Attr) { + assert(EnclosingDecl && "missing record or interface decl"); + + // If the decl this is being inserted into is invalid, then it may be a + // redeclaration or some other bogus case. Don't try to add fields to it. + if (EnclosingDecl->isInvalidDecl()) + return; + + RecordDecl *Record = dyn_cast(EnclosingDecl); + + // Start counting up the number of named members; make sure to include + // members of anonymous structs and unions in the total. + unsigned NumNamedMembers = 0; + if (Record) { + for (RecordDecl::decl_iterator i = Record->decls_begin(), + e = Record->decls_end(); i != e; i++) { + if (IndirectFieldDecl *IFD = dyn_cast(*i)) + if (IFD->getDeclName()) + ++NumNamedMembers; + } + } + + // Verify that all the fields are okay. + SmallVector RecFields; + + bool ARCErrReported = false; + for (llvm::ArrayRef::iterator i = Fields.begin(), end = Fields.end(); + i != end; ++i) { + FieldDecl *FD = cast(*i); + + // Get the type for the field. + const Type *FDTy = FD->getType().getTypePtr(); + + if (!FD->isAnonymousStructOrUnion()) { + // Remember all fields written by the user. + RecFields.push_back(FD); + } + + // If the field is already invalid for some reason, don't emit more + // diagnostics about it. + if (FD->isInvalidDecl()) { + EnclosingDecl->setInvalidDecl(); + continue; + } + + // C99 6.7.2.1p2: + // A structure or union shall not contain a member with + // incomplete or function type (hence, a structure shall not + // contain an instance of itself, but may contain a pointer to + // an instance of itself), except that the last member of a + // structure with more than one named member may have incomplete + // array type; such a structure (and any union containing, + // possibly recursively, a member that is such a structure) + // shall not be a member of a structure or an element of an + // array. + if (FDTy->isFunctionType()) { + // Field declared as a function. + Diag(FD->getLocation(), diag::err_field_declared_as_function) + << FD->getDeclName(); + FD->setInvalidDecl(); + EnclosingDecl->setInvalidDecl(); + continue; + } else if (FDTy->isIncompleteArrayType() && Record && + ((i + 1 == Fields.end() && !Record->isUnion()) || + ((getLangOpts().MicrosoftExt || + getLangOpts().CPlusPlus) && + (i + 1 == Fields.end() || Record->isUnion())))) { + // Flexible array member. + // Microsoft and g++ is more permissive regarding flexible array. + // It will accept flexible array in union and also + // as the sole element of a struct/class. + if (getLangOpts().MicrosoftExt) { + if (Record->isUnion()) + Diag(FD->getLocation(), diag::ext_flexible_array_union_ms) + << FD->getDeclName(); + else if (Fields.size() == 1) + Diag(FD->getLocation(), diag::ext_flexible_array_empty_aggregate_ms) + << FD->getDeclName() << Record->getTagKind(); + } else if (getLangOpts().CPlusPlus) { + if (Record->isUnion()) + Diag(FD->getLocation(), diag::ext_flexible_array_union_gnu) + << FD->getDeclName(); + else if (Fields.size() == 1) + Diag(FD->getLocation(), diag::ext_flexible_array_empty_aggregate_gnu) + << FD->getDeclName() << Record->getTagKind(); + } else if (!getLangOpts().C99) { + if (Record->isUnion()) + Diag(FD->getLocation(), diag::ext_flexible_array_union_gnu) + << FD->getDeclName(); + else + Diag(FD->getLocation(), diag::ext_c99_flexible_array_member) + << FD->getDeclName() << Record->getTagKind(); + } else if (NumNamedMembers < 1) { + Diag(FD->getLocation(), diag::err_flexible_array_empty_struct) + << FD->getDeclName(); + FD->setInvalidDecl(); + EnclosingDecl->setInvalidDecl(); + continue; + } + if (!FD->getType()->isDependentType() && + !Context.getBaseElementType(FD->getType()).isPODType(Context)) { + Diag(FD->getLocation(), diag::err_flexible_array_has_nonpod_type) + << FD->getDeclName() << FD->getType(); + FD->setInvalidDecl(); + EnclosingDecl->setInvalidDecl(); + continue; + } + // Okay, we have a legal flexible array member at the end of the struct. + if (Record) + Record->setHasFlexibleArrayMember(true); + } else if (!FDTy->isDependentType() && + RequireCompleteType(FD->getLocation(), FD->getType(), + diag::err_field_incomplete)) { + // Incomplete type + FD->setInvalidDecl(); + EnclosingDecl->setInvalidDecl(); + continue; + } else if (const RecordType *FDTTy = FDTy->getAs()) { + if (FDTTy->getDecl()->hasFlexibleArrayMember()) { + // If this is a member of a union, then entire union becomes "flexible". + if (Record && Record->isUnion()) { + Record->setHasFlexibleArrayMember(true); + } else { + // If this is a struct/class and this is not the last element, reject + // it. Note that GCC supports variable sized arrays in the middle of + // structures. + if (i + 1 != Fields.end()) + Diag(FD->getLocation(), diag::ext_variable_sized_type_in_struct) + << FD->getDeclName() << FD->getType(); + else { + // We support flexible arrays at the end of structs in + // other structs as an extension. + Diag(FD->getLocation(), diag::ext_flexible_array_in_struct) + << FD->getDeclName(); + if (Record) + Record->setHasFlexibleArrayMember(true); + } + } + } + if (Record && FDTTy->getDecl()->hasObjectMember()) + Record->setHasObjectMember(true); + } else if (FDTy->isObjCObjectType()) { + /// A field cannot be an Objective-c object + Diag(FD->getLocation(), diag::err_statically_allocated_object) + << FixItHint::CreateInsertion(FD->getLocation(), "*"); + QualType T = Context.getObjCObjectPointerType(FD->getType()); + FD->setType(T); + } + else if (!getLangOpts().CPlusPlus) { + if (getLangOpts().ObjCAutoRefCount && Record && !ARCErrReported) { + // It's an error in ARC if a field has lifetime. + // We don't want to report this in a system header, though, + // so we just make the field unavailable. + // FIXME: that's really not sufficient; we need to make the type + // itself invalid to, say, initialize or copy. + QualType T = FD->getType(); + Qualifiers::ObjCLifetime lifetime = T.getObjCLifetime(); + if (lifetime && lifetime != Qualifiers::OCL_ExplicitNone) { + SourceLocation loc = FD->getLocation(); + if (getSourceManager().isInSystemHeader(loc)) { + if (!FD->hasAttr()) { + FD->addAttr(new (Context) UnavailableAttr(loc, Context, + "this system field has retaining ownership")); + } + } else { + Diag(FD->getLocation(), diag::err_arc_objc_object_in_struct) + << T->isBlockPointerType(); + } + ARCErrReported = true; + } + } + else if (getLangOpts().ObjC1 && + getLangOpts().getGC() != LangOptions::NonGC && + Record && !Record->hasObjectMember()) { + if (FD->getType()->isObjCObjectPointerType() || + FD->getType().isObjCGCStrong()) + Record->setHasObjectMember(true); + else if (Context.getAsArrayType(FD->getType())) { + QualType BaseType = Context.getBaseElementType(FD->getType()); + if (BaseType->isRecordType() && + BaseType->getAs()->getDecl()->hasObjectMember()) + Record->setHasObjectMember(true); + else if (BaseType->isObjCObjectPointerType() || + BaseType.isObjCGCStrong()) + Record->setHasObjectMember(true); + } + } + } + // Keep track of the number of named members. + if (FD->getIdentifier()) + ++NumNamedMembers; + } + + // Okay, we successfully defined 'Record'. + if (Record) { + bool Completed = false; + if (CXXRecordDecl *CXXRecord = dyn_cast(Record)) { + if (!CXXRecord->isInvalidDecl()) { + // Set access bits correctly on the directly-declared conversions. + UnresolvedSetImpl *Convs = CXXRecord->getConversionFunctions(); + for (UnresolvedSetIterator I = Convs->begin(), E = Convs->end(); + I != E; ++I) + Convs->setAccess(I, (*I)->getAccess()); + + if (!CXXRecord->isDependentType()) { + // Objective-C Automatic Reference Counting: + // If a class has a non-static data member of Objective-C pointer + // type (or array thereof), it is a non-POD type and its + // default constructor (if any), copy constructor, copy assignment + // operator, and destructor are non-trivial. + // + // This rule is also handled by CXXRecordDecl::completeDefinition(). + // However, here we check whether this particular class is only + // non-POD because of the presence of an Objective-C pointer member. + // If so, objects of this type cannot be shared between code compiled + // with instant objects and code compiled with manual retain/release. + if (getLangOpts().ObjCAutoRefCount && + CXXRecord->hasObjectMember() && + CXXRecord->getLinkage() == ExternalLinkage) { + if (CXXRecord->isPOD()) { + Diag(CXXRecord->getLocation(), + diag::warn_arc_non_pod_class_with_object_member) + << CXXRecord; + } else { + // FIXME: Fix-Its would be nice here, but finding a good location + // for them is going to be tricky. + if (CXXRecord->hasTrivialCopyConstructor()) + Diag(CXXRecord->getLocation(), + diag::warn_arc_trivial_member_function_with_object_member) + << CXXRecord << 0; + if (CXXRecord->hasTrivialCopyAssignment()) + Diag(CXXRecord->getLocation(), + diag::warn_arc_trivial_member_function_with_object_member) + << CXXRecord << 1; + if (CXXRecord->hasTrivialDestructor()) + Diag(CXXRecord->getLocation(), + diag::warn_arc_trivial_member_function_with_object_member) + << CXXRecord << 2; + } + } + + // Adjust user-defined destructor exception spec. + if (getLangOpts().CPlusPlus0x && + CXXRecord->hasUserDeclaredDestructor()) + AdjustDestructorExceptionSpec(CXXRecord,CXXRecord->getDestructor()); + + // Add any implicitly-declared members to this class. + AddImplicitlyDeclaredMembersToClass(CXXRecord); + + // If we have virtual base classes, we may end up finding multiple + // final overriders for a given virtual function. Check for this + // problem now. + if (CXXRecord->getNumVBases()) { + CXXFinalOverriderMap FinalOverriders; + CXXRecord->getFinalOverriders(FinalOverriders); + + for (CXXFinalOverriderMap::iterator M = FinalOverriders.begin(), + MEnd = FinalOverriders.end(); + M != MEnd; ++M) { + for (OverridingMethods::iterator SO = M->second.begin(), + SOEnd = M->second.end(); + SO != SOEnd; ++SO) { + assert(SO->second.size() > 0 && + "Virtual function without overridding functions?"); + if (SO->second.size() == 1) + continue; + + // C++ [class.virtual]p2: + // In a derived class, if a virtual member function of a base + // class subobject has more than one final overrider the + // program is ill-formed. + Diag(Record->getLocation(), diag::err_multiple_final_overriders) + << (NamedDecl *)M->first << Record; + Diag(M->first->getLocation(), + diag::note_overridden_virtual_function); + for (OverridingMethods::overriding_iterator + OM = SO->second.begin(), + OMEnd = SO->second.end(); + OM != OMEnd; ++OM) + Diag(OM->Method->getLocation(), diag::note_final_overrider) + << (NamedDecl *)M->first << OM->Method->getParent(); + + Record->setInvalidDecl(); + } + } + CXXRecord->completeDefinition(&FinalOverriders); + Completed = true; + } + } + } + } + + if (!Completed) + Record->completeDefinition(); + + } else { + ObjCIvarDecl **ClsFields = + reinterpret_cast(RecFields.data()); + if (ObjCInterfaceDecl *ID = dyn_cast(EnclosingDecl)) { + ID->setEndOfDefinitionLoc(RBrac); + // Add ivar's to class's DeclContext. + for (unsigned i = 0, e = RecFields.size(); i != e; ++i) { + ClsFields[i]->setLexicalDeclContext(ID); + ID->addDecl(ClsFields[i]); + } + // Must enforce the rule that ivars in the base classes may not be + // duplicates. + if (ID->getSuperClass()) + DiagnoseDuplicateIvars(ID, ID->getSuperClass()); + } else if (ObjCImplementationDecl *IMPDecl = + dyn_cast(EnclosingDecl)) { + assert(IMPDecl && "ActOnFields - missing ObjCImplementationDecl"); + for (unsigned I = 0, N = RecFields.size(); I != N; ++I) + // Ivar declared in @implementation never belongs to the implementation. + // Only it is in implementation's lexical context. + ClsFields[I]->setLexicalDeclContext(IMPDecl); + CheckImplementationIvars(IMPDecl, ClsFields, RecFields.size(), RBrac); + IMPDecl->setIvarLBraceLoc(LBrac); + IMPDecl->setIvarRBraceLoc(RBrac); + } else if (ObjCCategoryDecl *CDecl = + dyn_cast(EnclosingDecl)) { + // case of ivars in class extension; all other cases have been + // reported as errors elsewhere. + // FIXME. Class extension does not have a LocEnd field. + // CDecl->setLocEnd(RBrac); + // Add ivar's to class extension's DeclContext. + // Diagnose redeclaration of private ivars. + ObjCInterfaceDecl *IDecl = CDecl->getClassInterface(); + for (unsigned i = 0, e = RecFields.size(); i != e; ++i) { + if (IDecl) { + if (const ObjCIvarDecl *ClsIvar = + IDecl->getIvarDecl(ClsFields[i]->getIdentifier())) { + Diag(ClsFields[i]->getLocation(), + diag::err_duplicate_ivar_declaration); + Diag(ClsIvar->getLocation(), diag::note_previous_definition); + continue; + } + for (const ObjCCategoryDecl *ClsExtDecl = + IDecl->getFirstClassExtension(); + ClsExtDecl; ClsExtDecl = ClsExtDecl->getNextClassExtension()) { + if (const ObjCIvarDecl *ClsExtIvar = + ClsExtDecl->getIvarDecl(ClsFields[i]->getIdentifier())) { + Diag(ClsFields[i]->getLocation(), + diag::err_duplicate_ivar_declaration); + Diag(ClsExtIvar->getLocation(), diag::note_previous_definition); + continue; + } + } + } + ClsFields[i]->setLexicalDeclContext(CDecl); + CDecl->addDecl(ClsFields[i]); + } + CDecl->setIvarLBraceLoc(LBrac); + CDecl->setIvarRBraceLoc(RBrac); + } + } + + 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 +/// the given type T. +static bool isRepresentableIntegerValue(ASTContext &Context, + llvm::APSInt &Value, + QualType T) { + assert(T->isIntegralType(Context) && "Integral type required!"); + unsigned BitWidth = Context.getIntWidth(T); + + if (Value.isUnsigned() || Value.isNonNegative()) { + if (T->isSignedIntegerOrEnumerationType()) + --BitWidth; + return Value.getActiveBits() <= BitWidth; + } + return Value.getMinSignedBits() <= BitWidth; +} + +// \brief Given an integral type, return the next larger integral type +// (or a NULL type of no such type exists). +static QualType getNextLargerIntegralType(ASTContext &Context, QualType T) { + // FIXME: Int128/UInt128 support, which also needs to be introduced into + // enum checking below. + assert(T->isIntegralType(Context) && "Integral type required!"); + const unsigned NumTypes = 4; + QualType SignedIntegralTypes[NumTypes] = { + Context.ShortTy, Context.IntTy, Context.LongTy, Context.LongLongTy + }; + QualType UnsignedIntegralTypes[NumTypes] = { + Context.UnsignedShortTy, Context.UnsignedIntTy, Context.UnsignedLongTy, + Context.UnsignedLongLongTy + }; + + unsigned BitWidth = Context.getTypeSize(T); + QualType *Types = T->isSignedIntegerOrEnumerationType()? SignedIntegralTypes + : UnsignedIntegralTypes; + for (unsigned I = 0; I != NumTypes; ++I) + if (Context.getTypeSize(Types[I]) > BitWidth) + return Types[I]; + + return QualType(); +} + +EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, + EnumConstantDecl *LastEnumConst, + SourceLocation IdLoc, + IdentifierInfo *Id, + Expr *Val) { + unsigned IntWidth = Context.getTargetInfo().getIntWidth(); + llvm::APSInt EnumVal(IntWidth); + QualType EltTy; + + if (Val && DiagnoseUnexpandedParameterPack(Val, UPPC_EnumeratorValue)) + Val = 0; + + if (Val) + Val = DefaultLvalueConversion(Val).take(); + + if (Val) { + if (Enum->isDependentType() || Val->isTypeDependent()) + EltTy = Context.DependentTy; + else { + SourceLocation ExpLoc; + if (getLangOpts().CPlusPlus0x && Enum->isFixed() && + !getLangOpts().MicrosoftMode) { + // C++11 [dcl.enum]p5: If the underlying type is fixed, [...] the + // constant-expression in the enumerator-definition shall be a converted + // constant expression of the underlying type. + EltTy = Enum->getIntegerType(); + ExprResult Converted = + CheckConvertedConstantExpression(Val, EltTy, EnumVal, + CCEK_Enumerator); + if (Converted.isInvalid()) + Val = 0; + else + Val = Converted.take(); + } else if (!Val->isValueDependent() && + !(Val = VerifyIntegerConstantExpression(Val, + &EnumVal).take())) { + // C99 6.7.2.2p2: Make sure we have an integer constant expression. + } else { + if (Enum->isFixed()) { + EltTy = Enum->getIntegerType(); + + // In Obj-C and Microsoft mode, require the enumeration value to be + // representable in the underlying type of the enumeration. In C++11, + // we perform a non-narrowing conversion as part of converted constant + // expression checking. + if (!isRepresentableIntegerValue(Context, EnumVal, EltTy)) { + if (getLangOpts().MicrosoftMode) { + Diag(IdLoc, diag::ext_enumerator_too_large) << EltTy; + Val = ImpCastExprToType(Val, EltTy, CK_IntegralCast).take(); + } else + Diag(IdLoc, diag::err_enumerator_too_large) << EltTy; + } else + Val = ImpCastExprToType(Val, EltTy, CK_IntegralCast).take(); + } else if (getLangOpts().CPlusPlus) { + // C++11 [dcl.enum]p5: + // If the underlying type is not fixed, the type of each enumerator + // is the type of its initializing value: + // - If an initializer is specified for an enumerator, the + // initializing value has the same type as the expression. + EltTy = Val->getType(); + } else { + // C99 6.7.2.2p2: + // The expression that defines the value of an enumeration constant + // shall be an integer constant expression that has a value + // representable as an int. + + // Complain if the value is not representable in an int. + if (!isRepresentableIntegerValue(Context, EnumVal, Context.IntTy)) + Diag(IdLoc, diag::ext_enum_value_not_int) + << EnumVal.toString(10) << Val->getSourceRange() + << (EnumVal.isUnsigned() || EnumVal.isNonNegative()); + else if (!Context.hasSameType(Val->getType(), Context.IntTy)) { + // Force the type of the expression to 'int'. + Val = ImpCastExprToType(Val, Context.IntTy, CK_IntegralCast).take(); + } + EltTy = Val->getType(); + } + } + } + } + + if (!Val) { + if (Enum->isDependentType()) + EltTy = Context.DependentTy; + else if (!LastEnumConst) { + // C++0x [dcl.enum]p5: + // If the underlying type is not fixed, the type of each enumerator + // is the type of its initializing value: + // - If no initializer is specified for the first enumerator, the + // initializing value has an unspecified integral type. + // + // GCC uses 'int' for its unspecified integral type, as does + // C99 6.7.2.2p3. + if (Enum->isFixed()) { + EltTy = Enum->getIntegerType(); + } + else { + EltTy = Context.IntTy; + } + } else { + // Assign the last value + 1. + EnumVal = LastEnumConst->getInitVal(); + ++EnumVal; + EltTy = LastEnumConst->getType(); + + // Check for overflow on increment. + if (EnumVal < LastEnumConst->getInitVal()) { + // C++0x [dcl.enum]p5: + // If the underlying type is not fixed, the type of each enumerator + // is the type of its initializing value: + // + // - Otherwise the type of the initializing value is the same as + // the type of the initializing value of the preceding enumerator + // unless the incremented value is not representable in that type, + // in which case the type is an unspecified integral type + // sufficient to contain the incremented value. If no such type + // exists, the program is ill-formed. + QualType T = getNextLargerIntegralType(Context, EltTy); + if (T.isNull() || Enum->isFixed()) { + // There is no integral type larger enough to represent this + // value. Complain, then allow the value to wrap around. + EnumVal = LastEnumConst->getInitVal(); + EnumVal = EnumVal.zext(EnumVal.getBitWidth() * 2); + ++EnumVal; + if (Enum->isFixed()) + // When the underlying type is fixed, this is ill-formed. + Diag(IdLoc, diag::err_enumerator_wrapped) + << EnumVal.toString(10) + << EltTy; + else + Diag(IdLoc, diag::warn_enumerator_too_large) + << EnumVal.toString(10); + } else { + EltTy = T; + } + + // Retrieve the last enumerator's value, extent that type to the + // type that is supposed to be large enough to represent the incremented + // value, then increment. + EnumVal = LastEnumConst->getInitVal(); + EnumVal.setIsSigned(EltTy->isSignedIntegerOrEnumerationType()); + EnumVal = EnumVal.zextOrTrunc(Context.getIntWidth(EltTy)); + ++EnumVal; + + // If we're not in C++, diagnose the overflow of enumerator values, + // which in C99 means that the enumerator value is not representable in + // an int (C99 6.7.2.2p2). However, we support GCC's extension that + // permits enumerator values that are representable in some larger + // integral type. + if (!getLangOpts().CPlusPlus && !T.isNull()) + Diag(IdLoc, diag::warn_enum_value_overflow); + } else if (!getLangOpts().CPlusPlus && + !isRepresentableIntegerValue(Context, EnumVal, EltTy)) { + // Enforce C99 6.7.2.2p2 even when we compute the next value. + Diag(IdLoc, diag::ext_enum_value_not_int) + << EnumVal.toString(10) << 1; + } + } + } + + if (!EltTy->isDependentType()) { + // Make the enumerator value match the signedness and size of the + // enumerator's type. + EnumVal = EnumVal.extOrTrunc(Context.getIntWidth(EltTy)); + EnumVal.setIsSigned(EltTy->isSignedIntegerOrEnumerationType()); + } + + return EnumConstantDecl::Create(Context, Enum, IdLoc, Id, EltTy, + Val, EnumVal); +} + + +Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst, + SourceLocation IdLoc, IdentifierInfo *Id, + AttributeList *Attr, + SourceLocation EqualLoc, Expr *Val) { + EnumDecl *TheEnumDecl = cast(theEnumDecl); + EnumConstantDecl *LastEnumConst = + cast_or_null(lastEnumConst); + + // The scope passed in may not be a decl scope. Zip up the scope tree until + // we find one that is. + S = getNonFieldDeclScope(S); + + // Verify that there isn't already something declared with this name in this + // scope. + NamedDecl *PrevDecl = LookupSingleName(S, Id, IdLoc, LookupOrdinaryName, + ForRedeclaration); + if (PrevDecl && PrevDecl->isTemplateParameter()) { + // Maybe we will complain about the shadowed template parameter. + DiagnoseTemplateParameterShadow(IdLoc, PrevDecl); + // Just pretend that we didn't see the previous declaration. + PrevDecl = 0; + } + + if (PrevDecl) { + // When in C++, we may get a TagDecl with the same name; in this case the + // enum constant will 'hide' the tag. + assert((getLangOpts().CPlusPlus || !isa(PrevDecl)) && + "Received TagDecl when not in C++!"); + if (!isa(PrevDecl) && isDeclInScope(PrevDecl, CurContext, S)) { + if (isa(PrevDecl)) + Diag(IdLoc, diag::err_redefinition_of_enumerator) << Id; + else + Diag(IdLoc, diag::err_redefinition) << Id; + Diag(PrevDecl->getLocation(), diag::note_previous_definition); + return 0; + } + } + + // C++ [class.mem]p13: + // If T is the name of a class, then each of the following shall have a + // name different from T: + // - every enumerator of every member of class T that is an enumerated + // type + if (CXXRecordDecl *Record + = dyn_cast( + TheEnumDecl->getDeclContext()->getRedeclContext())) + if (Record->getIdentifier() && Record->getIdentifier() == Id) + Diag(IdLoc, diag::err_member_name_of_class) << Id; + + EnumConstantDecl *New = + CheckEnumConstant(TheEnumDecl, LastEnumConst, IdLoc, Id, Val); + + if (New) { + // Process attributes. + if (Attr) ProcessDeclAttributeList(S, New, Attr); + + // Register this decl in the current scope stack. + New->setAccess(TheEnumDecl->getAccess()); + PushOnScopeChains(New, S); + } + + return New; +} + +void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, + SourceLocation RBraceLoc, Decl *EnumDeclX, + Decl **Elements, unsigned NumElements, + Scope *S, AttributeList *Attr) { + EnumDecl *Enum = cast(EnumDeclX); + QualType EnumType = Context.getTypeDeclType(Enum); + + if (Attr) + ProcessDeclAttributeList(S, Enum, Attr); + + if (Enum->isDependentType()) { + for (unsigned i = 0; i != NumElements; ++i) { + EnumConstantDecl *ECD = + cast_or_null(Elements[i]); + if (!ECD) continue; + + ECD->setType(EnumType); + } + + Enum->completeDefinition(Context.DependentTy, Context.DependentTy, 0, 0); + return; + } + + // TODO: If the result value doesn't fit in an int, it must be a long or long + // long value. ISO C does not support this, but GCC does as an extension, + // emit a warning. + unsigned IntWidth = Context.getTargetInfo().getIntWidth(); + unsigned CharWidth = Context.getTargetInfo().getCharWidth(); + unsigned ShortWidth = Context.getTargetInfo().getShortWidth(); + + // Verify that all the values are okay, compute the size of the values, and + // reverse the list. + unsigned NumNegativeBits = 0; + unsigned NumPositiveBits = 0; + + // Keep track of whether all elements have type int. + bool AllElementsInt = true; + + for (unsigned i = 0; i != NumElements; ++i) { + EnumConstantDecl *ECD = + cast_or_null(Elements[i]); + if (!ECD) continue; // Already issued a diagnostic. + + const llvm::APSInt &InitVal = ECD->getInitVal(); + + // Keep track of the size of positive and negative values. + if (InitVal.isUnsigned() || InitVal.isNonNegative()) + NumPositiveBits = std::max(NumPositiveBits, + (unsigned)InitVal.getActiveBits()); + else + NumNegativeBits = std::max(NumNegativeBits, + (unsigned)InitVal.getMinSignedBits()); + + // Keep track of whether every enum element has type int (very commmon). + if (AllElementsInt) + AllElementsInt = ECD->getType() == Context.IntTy; + } + + // Figure out the type that should be used for this enum. + QualType BestType; + unsigned BestWidth; + + // C++0x N3000 [conv.prom]p3: + // An rvalue of an unscoped enumeration type whose underlying + // type is not fixed can be converted to an rvalue of the first + // of the following types that can represent all the values of + // the enumeration: int, unsigned int, long int, unsigned long + // int, long long int, or unsigned long long int. + // C99 6.4.4.3p2: + // An identifier declared as an enumeration constant has type int. + // The C99 rule is modified by a gcc extension + QualType BestPromotionType; + + bool Packed = Enum->getAttr() ? true : false; + // -fshort-enums is the equivalent to specifying the packed attribute on all + // enum definitions. + if (LangOpts.ShortEnums) + Packed = true; + + if (Enum->isFixed()) { + BestType = Enum->getIntegerType(); + if (BestType->isPromotableIntegerType()) + BestPromotionType = Context.getPromotedIntegerType(BestType); + else + BestPromotionType = BestType; + // We don't need to set BestWidth, because BestType is going to be the type + // of the enumerators, but we do anyway because otherwise some compilers + // warn that it might be used uninitialized. + BestWidth = CharWidth; + } + else if (NumNegativeBits) { + // If there is a negative value, figure out the smallest integer type (of + // int/long/longlong) that fits. + // If it's packed, check also if it fits a char or a short. + if (Packed && NumNegativeBits <= CharWidth && NumPositiveBits < CharWidth) { + BestType = Context.SignedCharTy; + BestWidth = CharWidth; + } else if (Packed && NumNegativeBits <= ShortWidth && + NumPositiveBits < ShortWidth) { + BestType = Context.ShortTy; + BestWidth = ShortWidth; + } else if (NumNegativeBits <= IntWidth && NumPositiveBits < IntWidth) { + BestType = Context.IntTy; + BestWidth = IntWidth; + } else { + BestWidth = Context.getTargetInfo().getLongWidth(); + + if (NumNegativeBits <= BestWidth && NumPositiveBits < BestWidth) { + BestType = Context.LongTy; + } else { + BestWidth = Context.getTargetInfo().getLongLongWidth(); + + if (NumNegativeBits > BestWidth || NumPositiveBits >= BestWidth) + Diag(Enum->getLocation(), diag::warn_enum_too_large); + BestType = Context.LongLongTy; + } + } + BestPromotionType = (BestWidth <= IntWidth ? Context.IntTy : BestType); + } else { + // If there is no negative value, figure out the smallest type that fits + // all of the enumerator values. + // If it's packed, check also if it fits a char or a short. + if (Packed && NumPositiveBits <= CharWidth) { + BestType = Context.UnsignedCharTy; + BestPromotionType = Context.IntTy; + BestWidth = CharWidth; + } else if (Packed && NumPositiveBits <= ShortWidth) { + BestType = Context.UnsignedShortTy; + BestPromotionType = Context.IntTy; + BestWidth = ShortWidth; + } else if (NumPositiveBits <= IntWidth) { + BestType = Context.UnsignedIntTy; + BestWidth = IntWidth; + BestPromotionType + = (NumPositiveBits == BestWidth || !getLangOpts().CPlusPlus) + ? Context.UnsignedIntTy : Context.IntTy; + } else if (NumPositiveBits <= + (BestWidth = Context.getTargetInfo().getLongWidth())) { + BestType = Context.UnsignedLongTy; + BestPromotionType + = (NumPositiveBits == BestWidth || !getLangOpts().CPlusPlus) + ? Context.UnsignedLongTy : Context.LongTy; + } else { + BestWidth = Context.getTargetInfo().getLongLongWidth(); + assert(NumPositiveBits <= BestWidth && + "How could an initializer get larger than ULL?"); + BestType = Context.UnsignedLongLongTy; + BestPromotionType + = (NumPositiveBits == BestWidth || !getLangOpts().CPlusPlus) + ? Context.UnsignedLongLongTy : Context.LongLongTy; + } + } + + // 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]); + if (!ECD) continue; // Already issued a diagnostic. + + // Standard C says the enumerators have int type, but we allow, as an + // extension, the enumerators to be larger than int size. If each + // enumerator value fits in an int, type it as an int, otherwise type it the + // same as the enumerator decl itself. This means that in "enum { X = 1U }" + // that X has type 'int', not 'unsigned'. + + // Determine whether the value fits into an int. + llvm::APSInt InitVal = ECD->getInitVal(); + + // If it fits into an integer type, force it. Otherwise force it to match + // the enum decl type. + QualType NewTy; + unsigned NewWidth; + bool NewSign; + if (!getLangOpts().CPlusPlus && + !Enum->isFixed() && + isRepresentableIntegerValue(Context, InitVal, Context.IntTy)) { + NewTy = Context.IntTy; + NewWidth = IntWidth; + NewSign = true; + } else if (ECD->getType() == BestType) { + // Already the right type! + if (getLangOpts().CPlusPlus) + // C++ [dcl.enum]p4: Following the closing brace of an + // enum-specifier, each enumerator has the type of its + // enumeration. + ECD->setType(EnumType); + continue; + } else { + NewTy = BestType; + NewWidth = BestWidth; + NewSign = BestType->isSignedIntegerOrEnumerationType(); + } + + // Adjust the APSInt value. + InitVal = InitVal.extOrTrunc(NewWidth); + InitVal.setIsSigned(NewSign); + ECD->setInitVal(InitVal); + + // Adjust the Expr initializer and type. + if (ECD->getInitExpr() && + !Context.hasSameType(NewTy, ECD->getInitExpr()->getType())) + ECD->setInitExpr(ImplicitCastExpr::Create(Context, NewTy, + CK_IntegralCast, + ECD->getInitExpr(), + /*base paths*/ 0, + VK_RValue)); + if (getLangOpts().CPlusPlus) + // C++ [dcl.enum]p4: Following the closing brace of an + // enum-specifier, each enumerator has the type of its + // enumeration. + ECD->setType(EnumType); + else + ECD->setType(NewTy); + } + + Enum->completeDefinition(BestType, BestPromotionType, + NumPositiveBits, NumNegativeBits); + + // If we're declaring a function, ensure this decl isn't forgotten about - + // it needs to go into the function scope. + if (InFunctionDeclarator) + DeclsInPrototypeScope.push_back(Enum); + +} + +Decl *Sema::ActOnFileScopeAsmDecl(Expr *expr, + SourceLocation StartLoc, + SourceLocation EndLoc) { + StringLiteral *AsmString = cast(expr); + + FileScopeAsmDecl *New = FileScopeAsmDecl::Create(Context, CurContext, + AsmString, StartLoc, + EndLoc); + CurContext->addDecl(New); + return New; +} + +DeclResult Sema::ActOnModuleImport(SourceLocation AtLoc, + SourceLocation ImportLoc, + ModuleIdPath Path) { + Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path, + Module::AllVisible, + /*IsIncludeDirective=*/false); + if (!Mod) + return true; + + llvm::SmallVector IdentifierLocs; + Module *ModCheck = Mod; + for (unsigned I = 0, N = Path.size(); I != N; ++I) { + // If we've run out of module parents, just drop the remaining identifiers. + // We need the length to be consistent. + if (!ModCheck) + break; + ModCheck = ModCheck->Parent; + + IdentifierLocs.push_back(Path[I].second); + } + + ImportDecl *Import = ImportDecl::Create(Context, + Context.getTranslationUnitDecl(), + AtLoc.isValid()? AtLoc : ImportLoc, + Mod, IdentifierLocs); + Context.getTranslationUnitDecl()->addDecl(Import); + return Import; +} + +void Sema::ActOnPragmaRedefineExtname(IdentifierInfo* Name, + IdentifierInfo* AliasName, + SourceLocation PragmaLoc, + SourceLocation NameLoc, + SourceLocation AliasNameLoc) { + Decl *PrevDecl = LookupSingleName(TUScope, Name, NameLoc, + LookupOrdinaryName); + AsmLabelAttr *Attr = + ::new (Context) AsmLabelAttr(AliasNameLoc, Context, AliasName->getName()); + + if (PrevDecl) + PrevDecl->addAttr(Attr); + else + (void)ExtnameUndeclaredIdentifiers.insert( + std::pair(Name, Attr)); +} + +void Sema::ActOnPragmaWeakID(IdentifierInfo* Name, + SourceLocation PragmaLoc, + SourceLocation NameLoc) { + Decl *PrevDecl = LookupSingleName(TUScope, Name, NameLoc, LookupOrdinaryName); + + if (PrevDecl) { + PrevDecl->addAttr(::new (Context) WeakAttr(PragmaLoc, Context)); + } else { + (void)WeakUndeclaredIdentifiers.insert( + std::pair + (Name, WeakInfo((IdentifierInfo*)0, NameLoc))); + } +} + +void Sema::ActOnPragmaWeakAlias(IdentifierInfo* Name, + IdentifierInfo* AliasName, + SourceLocation PragmaLoc, + SourceLocation NameLoc, + SourceLocation AliasNameLoc) { + Decl *PrevDecl = LookupSingleName(TUScope, AliasName, AliasNameLoc, + LookupOrdinaryName); + WeakInfo W = WeakInfo(Name, NameLoc); + + if (PrevDecl) { + if (!PrevDecl->hasAttr()) + if (NamedDecl *ND = dyn_cast(PrevDecl)) + DeclApplyPragmaWeak(TUScope, ND, W); + } else { + (void)WeakUndeclaredIdentifiers.insert( + std::pair(AliasName, W)); + } +} + +Decl *Sema::getObjCDeclContext() const { + return (dyn_cast_or_null(CurContext)); +} + +AvailabilityResult Sema::getCurContextAvailability() const { + const Decl *D = cast(getCurLexicalContext()); + // A category implicitly has the availability of the interface. + if (const ObjCCategoryDecl *CatD = dyn_cast(D)) + D = CatD->getClassInterface(); + + return D->getAvailability(); +} diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp new file mode 100644 index 0000000..5c6ddd2 --- /dev/null +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -0,0 +1,4171 @@ +//===--- SemaDeclAttr.cpp - Declaration Attribute Handling ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements decl-related attribute processing. +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/SemaInternal.h" +#include "TargetAttributesSema.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/Expr.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Basic/TargetInfo.h" +#include "clang/Sema/DeclSpec.h" +#include "clang/Sema/DelayedDiagnostic.h" +#include "clang/Sema/Lookup.h" +#include "llvm/ADT/StringExtras.h" +using namespace clang; +using namespace sema; + +/// These constants match the enumerated choices of +/// warn_attribute_wrong_decl_type and err_attribute_wrong_decl_type. +enum AttributeDeclKind { + ExpectedFunction, + ExpectedUnion, + ExpectedVariableOrFunction, + ExpectedFunctionOrMethod, + ExpectedParameter, + ExpectedFunctionMethodOrBlock, + ExpectedFunctionMethodOrParameter, + ExpectedClass, + ExpectedVariable, + ExpectedMethod, + ExpectedVariableFunctionOrLabel, + ExpectedFieldOrGlobalVar, + ExpectedStruct +}; + +//===----------------------------------------------------------------------===// +// Helper functions +//===----------------------------------------------------------------------===// + +static const FunctionType *getFunctionType(const Decl *D, + bool blocksToo = true) { + QualType Ty; + if (const ValueDecl *decl = dyn_cast(D)) + Ty = decl->getType(); + else if (const FieldDecl *decl = dyn_cast(D)) + Ty = decl->getType(); + else if (const TypedefNameDecl* decl = dyn_cast(D)) + Ty = decl->getUnderlyingType(); + else + return 0; + + if (Ty->isFunctionPointerType()) + Ty = Ty->getAs()->getPointeeType(); + else if (blocksToo && Ty->isBlockPointerType()) + Ty = Ty->getAs()->getPointeeType(); + + return Ty->getAs(); +} + +// FIXME: We should provide an abstraction around a method or function +// to provide the following bits of information. + +/// isFunction - Return true if the given decl has function +/// type (function or function-typed variable). +static bool isFunction(const Decl *D) { + return getFunctionType(D, false) != NULL; +} + +/// isFunctionOrMethod - Return true if the given decl has function +/// type (function or function-typed variable) or an Objective-C +/// method. +static bool isFunctionOrMethod(const Decl *D) { + return isFunction(D)|| isa(D); +} + +/// isFunctionOrMethodOrBlock - Return true if the given decl has function +/// type (function or function-typed variable) or an Objective-C +/// method or a block. +static bool isFunctionOrMethodOrBlock(const Decl *D) { + if (isFunctionOrMethod(D)) + return true; + // check for block is more involved. + if (const VarDecl *V = dyn_cast(D)) { + QualType Ty = V->getType(); + return Ty->isBlockPointerType(); + } + return isa(D); +} + +/// Return true if the given decl has a declarator that should have +/// been processed by Sema::GetTypeForDeclarator. +static bool hasDeclarator(const Decl *D) { + // In some sense, TypedefDecl really *ought* to be a DeclaratorDecl. + return isa(D) || isa(D) || isa(D) || + isa(D); +} + +/// hasFunctionProto - Return true if the given decl has a argument +/// information. This decl should have already passed +/// isFunctionOrMethod or isFunctionOrMethodOrBlock. +static bool hasFunctionProto(const Decl *D) { + if (const FunctionType *FnTy = getFunctionType(D)) + return isa(FnTy); + else { + assert(isa(D) || isa(D)); + return true; + } +} + +/// getFunctionOrMethodNumArgs - Return number of function or method +/// arguments. It is an error to call this on a K&R function (use +/// hasFunctionProto first). +static unsigned getFunctionOrMethodNumArgs(const Decl *D) { + if (const FunctionType *FnTy = getFunctionType(D)) + return cast(FnTy)->getNumArgs(); + if (const BlockDecl *BD = dyn_cast(D)) + return BD->getNumParams(); + return cast(D)->param_size(); +} + +static QualType getFunctionOrMethodArgType(const Decl *D, unsigned Idx) { + if (const FunctionType *FnTy = getFunctionType(D)) + return cast(FnTy)->getArgType(Idx); + if (const BlockDecl *BD = dyn_cast(D)) + return BD->getParamDecl(Idx)->getType(); + + return cast(D)->param_begin()[Idx]->getType(); +} + +static QualType getFunctionOrMethodResultType(const Decl *D) { + if (const FunctionType *FnTy = getFunctionType(D)) + return cast(FnTy)->getResultType(); + return cast(D)->getResultType(); +} + +static bool isFunctionOrMethodVariadic(const Decl *D) { + if (const FunctionType *FnTy = getFunctionType(D)) { + const FunctionProtoType *proto = cast(FnTy); + return proto->isVariadic(); + } else if (const BlockDecl *BD = dyn_cast(D)) + return BD->isVariadic(); + else { + return cast(D)->isVariadic(); + } +} + +static bool isInstanceMethod(const Decl *D) { + if (const CXXMethodDecl *MethodDecl = dyn_cast(D)) + return MethodDecl->isInstance(); + return false; +} + +static inline bool isNSStringType(QualType T, ASTContext &Ctx) { + const ObjCObjectPointerType *PT = T->getAs(); + if (!PT) + return false; + + ObjCInterfaceDecl *Cls = PT->getObjectType()->getInterface(); + if (!Cls) + return false; + + IdentifierInfo* ClsName = Cls->getIdentifier(); + + // FIXME: Should we walk the chain of classes? + return ClsName == &Ctx.Idents.get("NSString") || + ClsName == &Ctx.Idents.get("NSMutableString"); +} + +static inline bool isCFStringType(QualType T, ASTContext &Ctx) { + const PointerType *PT = T->getAs(); + if (!PT) + return false; + + const RecordType *RT = PT->getPointeeType()->getAs(); + if (!RT) + return false; + + const RecordDecl *RD = RT->getDecl(); + if (RD->getTagKind() != TTK_Struct) + return false; + + return RD->getIdentifier() == &Ctx.Idents.get("__CFString"); +} + +/// \brief Check if the attribute has exactly as many args as Num. May +/// output an error. +static bool checkAttributeNumArgs(Sema &S, const AttributeList &Attr, + unsigned int Num) { + if (Attr.getNumArgs() != Num) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << Num; + return false; + } + + return true; +} + + +/// \brief Check if the attribute has at least as many args as Num. May +/// output an error. +static bool checkAttributeAtLeastNumArgs(Sema &S, const AttributeList &Attr, + unsigned int Num) { + if (Attr.getNumArgs() < Num) { + S.Diag(Attr.getLoc(), diag::err_attribute_too_few_arguments) << Num; + return false; + } + + return true; +} + +/// +/// \brief Check if passed in Decl is a field or potentially shared global var +/// \return true if the Decl is a field or potentially shared global variable +/// +static bool mayBeSharedVariable(const Decl *D) { + if (isa(D)) + return true; + if (const VarDecl *vd = dyn_cast(D)) + return (vd->hasGlobalStorage() && !(vd->isThreadSpecified())); + + return false; +} + +/// \brief Check if the passed-in expression is of type int or bool. +static bool isIntOrBool(Expr *Exp) { + QualType QT = Exp->getType(); + return QT->isBooleanType() || QT->isIntegerType(); +} + +/// +/// \brief Check if passed in Decl is a pointer type. +/// Note that this function may produce an error message. +/// \return true if the Decl is a pointer type; false otherwise +/// +static bool checkIsPointer(Sema &S, const Decl *D, const AttributeList &Attr) { + if (const ValueDecl *vd = dyn_cast(D)) { + QualType QT = vd->getType(); + if (QT->isAnyPointerType()) + return true; + S.Diag(Attr.getLoc(), diag::warn_pointer_attribute_wrong_type) + << Attr.getName()->getName() << QT; + } else { + S.Diag(Attr.getLoc(), diag::err_attribute_can_be_applied_only_to_value_decl) + << Attr.getName(); + } + return false; +} + +/// \brief Checks that the passed in QualType either is of RecordType or points +/// to RecordType. Returns the relevant RecordType, null if it does not exit. +static const RecordType *getRecordType(QualType QT) { + if (const RecordType *RT = QT->getAs()) + return RT; + + // Now check if we point to record type. + if (const PointerType *PT = QT->getAs()) + return PT->getPointeeType()->getAs(); + + return 0; +} + +/// \brief Thread Safety Analysis: Checks that the passed in RecordType +/// resolves to a lockable object. May flag an error. +static void checkForLockableRecord(Sema &S, Decl *D, const AttributeList &Attr, + QualType Ty) { + const RecordType *RT = getRecordType(Ty); + + // Warn if could not get record type for this argument. + if (!RT) { + S.Diag(Attr.getLoc(), diag::warn_attribute_argument_not_class) + << Attr.getName() << Ty.getAsString(); + return; + } + // Don't check for lockable if the class hasn't been defined yet. + if (RT->isIncompleteType()) + return; + // Warn if the type is not lockable. + if (!RT->getDecl()->getAttr()) { + S.Diag(Attr.getLoc(), diag::warn_attribute_argument_not_lockable) + << Attr.getName() << Ty.getAsString(); + return; + } +} + +/// \brief Thread Safety Analysis: Checks that all attribute arguments, starting +/// from Sidx, resolve to a lockable object. May flag an error. +/// \param Sidx The attribute argument index to start checking with. +/// \param ParamIdxOk Whether an argument can be indexing into a function +/// parameter list. +static bool checkAttrArgsAreLockableObjs(Sema &S, Decl *D, + const AttributeList &Attr, + SmallVectorImpl &Args, + int Sidx = 0, + bool ParamIdxOk = false) { + for(unsigned Idx = Sidx; Idx < Attr.getNumArgs(); ++Idx) { + Expr *ArgExp = Attr.getArg(Idx); + + if (ArgExp->isTypeDependent()) { + // FIXME -- need to processs this again on template instantiation + Args.push_back(ArgExp); + continue; + } + + QualType ArgTy = ArgExp->getType(); + + // First see if we can just cast to record type, or point to record type. + const RecordType *RT = getRecordType(ArgTy); + + // Now check if we index into a record type function param. + if(!RT && ParamIdxOk) { + FunctionDecl *FD = dyn_cast(D); + IntegerLiteral *IL = dyn_cast(ArgExp); + if(FD && IL) { + unsigned int NumParams = FD->getNumParams(); + llvm::APInt ArgValue = IL->getValue(); + uint64_t ParamIdxFromOne = ArgValue.getZExtValue(); + uint64_t ParamIdxFromZero = ParamIdxFromOne - 1; + if(!ArgValue.isStrictlyPositive() || ParamIdxFromOne > NumParams) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_range) + << Attr.getName() << Idx + 1 << NumParams; + return false; + } + ArgTy = FD->getParamDecl(ParamIdxFromZero)->getType(); + } + } + + checkForLockableRecord(S, D, Attr, ArgTy); + + Args.push_back(ArgExp); + } + return true; +} + +//===----------------------------------------------------------------------===// +// Attribute Implementations +//===----------------------------------------------------------------------===// + +// FIXME: All this manual attribute parsing code is gross. At the +// least add some helper functions to check most argument patterns (# +// and types of args). + +static void handleGuardedVarAttr(Sema &S, Decl *D, const AttributeList &Attr, + bool pointer = false) { + assert(!Attr.isInvalid()); + + if (!checkAttributeNumArgs(S, Attr, 0)) + return; + + // D must be either a member field or global (potentially shared) variable. + if (!mayBeSharedVariable(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFieldOrGlobalVar; + return; + } + + if (pointer && !checkIsPointer(S, D, Attr)) + return; + + if (pointer) + D->addAttr(::new (S.Context) PtGuardedVarAttr(Attr.getRange(), S.Context)); + else + D->addAttr(::new (S.Context) GuardedVarAttr(Attr.getRange(), S.Context)); +} + +static void handleGuardedByAttr(Sema &S, Decl *D, const AttributeList &Attr, + bool pointer = false) { + assert(!Attr.isInvalid()); + + if (!checkAttributeNumArgs(S, Attr, 1)) + return; + + Expr *Arg = Attr.getArg(0); + + // D must be either a member field or global (potentially shared) variable. + if (!mayBeSharedVariable(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFieldOrGlobalVar; + return; + } + + if (pointer && !checkIsPointer(S, D, Attr)) + return; + + if (!Arg->isTypeDependent()) { + checkForLockableRecord(S, D, Attr, Arg->getType()); + } + + if (pointer) + D->addAttr(::new (S.Context) PtGuardedByAttr(Attr.getRange(), + S.Context, Arg)); + else + D->addAttr(::new (S.Context) GuardedByAttr(Attr.getRange(), S.Context, Arg)); +} + + +static void handleLockableAttr(Sema &S, Decl *D, const AttributeList &Attr, + bool scoped = false) { + assert(!Attr.isInvalid()); + + if (!checkAttributeNumArgs(S, Attr, 0)) + return; + + // FIXME: Lockable structs for C code. + if (!isa(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedClass; + return; + } + + if (scoped) + D->addAttr(::new (S.Context) ScopedLockableAttr(Attr.getRange(), S.Context)); + else + D->addAttr(::new (S.Context) LockableAttr(Attr.getRange(), S.Context)); +} + +static void handleNoThreadSafetyAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + assert(!Attr.isInvalid()); + + if (!checkAttributeNumArgs(S, Attr, 0)) + return; + + if (!isa(D) && !isa(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunctionOrMethod; + return; + } + + D->addAttr(::new (S.Context) NoThreadSafetyAnalysisAttr(Attr.getRange(), + S.Context)); +} + +static void handleNoAddressSafetyAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + assert(!Attr.isInvalid()); + + if (!checkAttributeNumArgs(S, Attr, 0)) + return; + + if (!isa(D) && !isa(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunctionOrMethod; + return; + } + + D->addAttr(::new (S.Context) NoAddressSafetyAnalysisAttr(Attr.getRange(), + S.Context)); +} + +static void handleAcquireOrderAttr(Sema &S, Decl *D, const AttributeList &Attr, + bool before) { + assert(!Attr.isInvalid()); + + if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) + return; + + // D must be either a member field or global (potentially shared) variable. + ValueDecl *VD = dyn_cast(D); + if (!VD || !mayBeSharedVariable(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFieldOrGlobalVar; + return; + } + + // Check that this attribute only applies to lockable types + QualType QT = VD->getType(); + if (!QT->isDependentType()) { + const RecordType *RT = getRecordType(QT); + if (!RT || !RT->getDecl()->getAttr()) { + S.Diag(Attr.getLoc(), diag::warn_attribute_decl_not_lockable) + << Attr.getName(); + return; + } + } + + SmallVector Args; + // check that all arguments are lockable objects + if (!checkAttrArgsAreLockableObjs(S, D, Attr, Args)) + return; + + unsigned Size = Args.size(); + assert(Size == Attr.getNumArgs()); + Expr **StartArg = Size == 0 ? 0 : &Args[0]; + + if (before) + D->addAttr(::new (S.Context) AcquiredBeforeAttr(Attr.getRange(), S.Context, + StartArg, Size)); + else + D->addAttr(::new (S.Context) AcquiredAfterAttr(Attr.getRange(), S.Context, + StartArg, Size)); +} + +static void handleLockFunAttr(Sema &S, Decl *D, const AttributeList &Attr, + bool exclusive = false) { + assert(!Attr.isInvalid()); + + // zero or more arguments ok + + // check that the attribute is applied to a function + if (!isa(D) && !isa(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunctionOrMethod; + return; + } + + // check that all arguments are lockable objects + SmallVector Args; + if (!checkAttrArgsAreLockableObjs(S, D, Attr, Args, 0, /*ParamIdxOk=*/true)) + return; + + unsigned Size = Args.size(); + assert(Size == Attr.getNumArgs()); + Expr **StartArg = Size == 0 ? 0 : &Args[0]; + + if (exclusive) + D->addAttr(::new (S.Context) ExclusiveLockFunctionAttr(Attr.getRange(), + S.Context, StartArg, + Size)); + else + D->addAttr(::new (S.Context) SharedLockFunctionAttr(Attr.getRange(), + S.Context, StartArg, + Size)); +} + +static void handleTrylockFunAttr(Sema &S, Decl *D, const AttributeList &Attr, + bool exclusive = false) { + assert(!Attr.isInvalid()); + + if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) + return; + + + if (!isa(D) && !isa(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunctionOrMethod; + return; + } + + if (!isIntOrBool(Attr.getArg(0))) { + S.Diag(Attr.getLoc(), diag::err_attribute_first_argument_not_int_or_bool) + << Attr.getName(); + return; + } + + SmallVector Args; + // check that all arguments are lockable objects + if (!checkAttrArgsAreLockableObjs(S, D, Attr, Args, 1)) + return; + + unsigned Size = Args.size(); + Expr **StartArg = Size == 0 ? 0 : &Args[0]; + + if (exclusive) + D->addAttr(::new (S.Context) ExclusiveTrylockFunctionAttr(Attr.getRange(), + S.Context, + Attr.getArg(0), + StartArg, Size)); + else + D->addAttr(::new (S.Context) SharedTrylockFunctionAttr(Attr.getRange(), + S.Context, + Attr.getArg(0), + StartArg, Size)); +} + +static void handleLocksRequiredAttr(Sema &S, Decl *D, const AttributeList &Attr, + bool exclusive = false) { + assert(!Attr.isInvalid()); + + if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) + return; + + if (!isa(D) && !isa(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunctionOrMethod; + return; + } + + // check that all arguments are lockable objects + SmallVector Args; + if (!checkAttrArgsAreLockableObjs(S, D, Attr, Args)) + return; + + unsigned Size = Args.size(); + assert(Size == Attr.getNumArgs()); + Expr **StartArg = Size == 0 ? 0 : &Args[0]; + + if (exclusive) + D->addAttr(::new (S.Context) ExclusiveLocksRequiredAttr(Attr.getRange(), + S.Context, StartArg, + Size)); + else + D->addAttr(::new (S.Context) SharedLocksRequiredAttr(Attr.getRange(), + S.Context, StartArg, + Size)); +} + +static void handleUnlockFunAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + assert(!Attr.isInvalid()); + + // zero or more arguments ok + + if (!isa(D) && !isa(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunctionOrMethod; + return; + } + + // check that all arguments are lockable objects + SmallVector Args; + if (!checkAttrArgsAreLockableObjs(S, D, Attr, Args, 0, /*ParamIdxOk=*/true)) + return; + + unsigned Size = Args.size(); + assert(Size == Attr.getNumArgs()); + Expr **StartArg = Size == 0 ? 0 : &Args[0]; + + D->addAttr(::new (S.Context) UnlockFunctionAttr(Attr.getRange(), S.Context, + StartArg, Size)); +} + +static void handleLockReturnedAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + assert(!Attr.isInvalid()); + + if (!checkAttributeNumArgs(S, Attr, 1)) + return; + Expr *Arg = Attr.getArg(0); + + if (!isa(D) && !isa(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunctionOrMethod; + return; + } + + if (Arg->isTypeDependent()) + return; + + // check that the argument is lockable object + checkForLockableRecord(S, D, Attr, Arg->getType()); + + D->addAttr(::new (S.Context) LockReturnedAttr(Attr.getRange(), S.Context, Arg)); +} + +static void handleLocksExcludedAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + assert(!Attr.isInvalid()); + + if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) + return; + + if (!isa(D) && !isa(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunctionOrMethod; + return; + } + + // check that all arguments are lockable objects + SmallVector Args; + if (!checkAttrArgsAreLockableObjs(S, D, Attr, Args)) + return; + + unsigned Size = Args.size(); + assert(Size == Attr.getNumArgs()); + Expr **StartArg = Size == 0 ? 0 : &Args[0]; + + D->addAttr(::new (S.Context) LocksExcludedAttr(Attr.getRange(), S.Context, + StartArg, Size)); +} + + +static void handleExtVectorTypeAttr(Sema &S, Scope *scope, Decl *D, + const AttributeList &Attr) { + TypedefNameDecl *tDecl = dyn_cast(D); + if (tDecl == 0) { + S.Diag(Attr.getLoc(), diag::err_typecheck_ext_vector_not_typedef); + return; + } + + QualType curType = tDecl->getUnderlyingType(); + + Expr *sizeExpr; + + // Special case where the argument is a template id. + if (Attr.getParameterName()) { + CXXScopeSpec SS; + SourceLocation TemplateKWLoc; + UnqualifiedId id; + id.setIdentifier(Attr.getParameterName(), Attr.getLoc()); + + ExprResult Size = S.ActOnIdExpression(scope, SS, TemplateKWLoc, id, + false, false); + if (Size.isInvalid()) + return; + + sizeExpr = Size.get(); + } else { + // check the attribute arguments. + if (!checkAttributeNumArgs(S, Attr, 1)) + return; + + sizeExpr = Attr.getArg(0); + } + + // Instantiate/Install the vector type, and let Sema build the type for us. + // This will run the reguired checks. + QualType T = S.BuildExtVectorType(curType, sizeExpr, Attr.getLoc()); + if (!T.isNull()) { + // FIXME: preserve the old source info. + tDecl->setTypeSourceInfo(S.Context.getTrivialTypeSourceInfo(T)); + + // Remember this typedef decl, we will need it later for diagnostics. + S.ExtVectorDecls.push_back(tDecl); + } +} + +static void handlePackedAttr(Sema &S, Decl *D, const AttributeList &Attr) { + // check the attribute arguments. + if (!checkAttributeNumArgs(S, Attr, 0)) + return; + + if (TagDecl *TD = dyn_cast(D)) + TD->addAttr(::new (S.Context) PackedAttr(Attr.getRange(), 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. + if (!FD->getType()->isIncompleteType() && + S.Context.getTypeAlign(FD->getType()) <= 8) + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored_for_field_of_type) + << Attr.getName() << FD->getType(); + else + FD->addAttr(::new (S.Context) PackedAttr(Attr.getRange(), S.Context)); + } else + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); +} + +static void handleMsStructAttr(Sema &S, Decl *D, const AttributeList &Attr) { + if (TagDecl *TD = dyn_cast(D)) + TD->addAttr(::new (S.Context) MsStructAttr(Attr.getRange(), S.Context)); + else + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); +} + +static void handleIBAction(Sema &S, Decl *D, const AttributeList &Attr) { + // check the attribute arguments. + if (!checkAttributeNumArgs(S, Attr, 0)) + return; + + // The IBAction attributes only apply to instance methods. + if (ObjCMethodDecl *MD = dyn_cast(D)) + if (MD->isInstanceMethod()) { + D->addAttr(::new (S.Context) IBActionAttr(Attr.getRange(), S.Context)); + return; + } + + S.Diag(Attr.getLoc(), diag::warn_attribute_ibaction) << Attr.getName(); +} + +static bool checkIBOutletCommon(Sema &S, Decl *D, const AttributeList &Attr) { + // The IBOutlet/IBOutletCollection attributes only apply to instance + // variables or properties of Objective-C classes. The outlet must also + // have an object reference type. + if (const ObjCIvarDecl *VD = dyn_cast(D)) { + if (!VD->getType()->getAs()) { + S.Diag(Attr.getLoc(), diag::warn_iboutlet_object_type) + << Attr.getName() << VD->getType() << 0; + return false; + } + } + else if (const ObjCPropertyDecl *PD = dyn_cast(D)) { + if (!PD->getType()->getAs()) { + S.Diag(Attr.getLoc(), diag::warn_iboutlet_object_type) + << Attr.getName() << PD->getType() << 1; + return false; + } + } + else { + S.Diag(Attr.getLoc(), diag::warn_attribute_iboutlet) << Attr.getName(); + return false; + } + + return true; +} + +static void handleIBOutlet(Sema &S, Decl *D, const AttributeList &Attr) { + // check the attribute arguments. + if (!checkAttributeNumArgs(S, Attr, 0)) + return; + + if (!checkIBOutletCommon(S, D, Attr)) + return; + + D->addAttr(::new (S.Context) IBOutletAttr(Attr.getRange(), S.Context)); +} + +static void handleIBOutletCollection(Sema &S, Decl *D, + const AttributeList &Attr) { + + // The iboutletcollection attribute can have zero or one arguments. + if (Attr.getParameterName() && Attr.getNumArgs() > 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + return; + } + + if (!checkIBOutletCommon(S, D, Attr)) + return; + + IdentifierInfo *II = Attr.getParameterName(); + if (!II) + II = &S.Context.Idents.get("NSObject"); + + 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->isObjCObjectType()) { + S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << II; + return; + } + D->addAttr(::new (S.Context) IBOutletCollectionAttr(Attr.getRange(),S.Context, + QT, Attr.getParameterLoc())); +} + +static void possibleTransparentUnionPointerType(QualType &T) { + if (const RecordType *UT = T->getAsUnionType()) + if (UT && UT->getDecl()->hasAttr()) { + RecordDecl *UD = UT->getDecl(); + for (RecordDecl::field_iterator it = UD->field_begin(), + itend = UD->field_end(); it != itend; ++it) { + QualType QT = it->getType(); + if (QT->isAnyPointerType() || QT->isBlockPointerType()) { + T = QT; + return; + } + } + } +} + +static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) { + // GCC ignores the nonnull attribute on K&R style function prototypes, so we + // ignore it as well + if (!isFunctionOrMethod(D) || !hasFunctionProto(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunction; + return; + } + + // In C++ the implicit 'this' function parameter also counts, and they are + // counted from one. + bool HasImplicitThisParam = isInstanceMethod(D); + unsigned NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam; + + // The nonnull attribute only applies to pointers. + SmallVector NonNullArgs; + + for (AttributeList::arg_iterator I=Attr.arg_begin(), + E=Attr.arg_end(); I!=E; ++I) { + + + // The argument must be an integer constant expression. + Expr *Ex = *I; + llvm::APSInt ArgNum(32); + if (Ex->isTypeDependent() || Ex->isValueDependent() || + !Ex->isIntegerConstantExpr(ArgNum, S.Context)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) + << "nonnull" << Ex->getSourceRange(); + return; + } + + unsigned x = (unsigned) ArgNum.getZExtValue(); + + if (x < 1 || x > NumArgs) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds) + << "nonnull" << I.getArgNum() << Ex->getSourceRange(); + return; + } + + --x; + if (HasImplicitThisParam) { + if (x == 0) { + S.Diag(Attr.getLoc(), + diag::err_attribute_invalid_implicit_this_argument) + << "nonnull" << Ex->getSourceRange(); + return; + } + --x; + } + + // Is the function argument a pointer type? + QualType T = getFunctionOrMethodArgType(D, x).getNonReferenceType(); + possibleTransparentUnionPointerType(T); + + if (!T->isAnyPointerType() && !T->isBlockPointerType()) { + // FIXME: Should also highlight argument in decl. + S.Diag(Attr.getLoc(), diag::warn_nonnull_pointers_only) + << "nonnull" << Ex->getSourceRange(); + continue; + } + + NonNullArgs.push_back(x); + } + + // If no arguments were specified to __attribute__((nonnull)) then all pointer + // arguments have a nonnull attribute. + if (NonNullArgs.empty()) { + for (unsigned I = 0, E = getFunctionOrMethodNumArgs(D); I != E; ++I) { + QualType T = getFunctionOrMethodArgType(D, I).getNonReferenceType(); + possibleTransparentUnionPointerType(T); + if (T->isAnyPointerType() || T->isBlockPointerType()) + NonNullArgs.push_back(I); + } + + // No pointer arguments? + if (NonNullArgs.empty()) { + // Warn the trivial case only if attribute is not coming from a + // macro instantiation. + if (Attr.getLoc().isFileID()) + S.Diag(Attr.getLoc(), diag::warn_attribute_nonnull_no_pointers); + return; + } + } + + unsigned* start = &NonNullArgs[0]; + unsigned size = NonNullArgs.size(); + llvm::array_pod_sort(start, start + size); + D->addAttr(::new (S.Context) NonNullAttr(Attr.getRange(), S.Context, start, + size)); +} + +static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) { + // 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() << ExpectedFunction; + return; + } + + // In C++ the implicit 'this' function parameter also counts, and they are + // counted from one. + bool HasImplicitThisParam = isInstanceMethod(D); + unsigned NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam; + + StringRef Module = AL.getParameterName()->getName(); + + // Normalize the argument, __foo__ becomes foo. + if (Module.startswith("__") && Module.endswith("__")) + Module = Module.substr(2, Module.size() - 4); + + SmallVector OwnershipArgs; + + for (AttributeList::arg_iterator I = AL.arg_begin(), E = AL.arg_end(); I != E; + ++I) { + + Expr *IdxExpr = *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; + if (HasImplicitThisParam) { + if (x == 0) { + S.Diag(AL.getLoc(), diag::err_attribute_invalid_implicit_this_argument) + << "ownership" << IdxExpr->getSourceRange(); + return; + } + --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 = 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; + } + } // 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)); +} + +/// Whether this declaration has internal linkage for the purposes of +/// things that want to complain about things not have internal linkage. +static bool hasEffectivelyInternalLinkage(NamedDecl *D) { + switch (D->getLinkage()) { + case NoLinkage: + case InternalLinkage: + return true; + + // Template instantiations that go from external to unique-external + // shouldn't get diagnosed. + case UniqueExternalLinkage: + return true; + + case ExternalLinkage: + return false; + } + llvm_unreachable("unknown linkage kind!"); +} + +static void handleWeakRefAttr(Sema &S, Decl *D, const AttributeList &Attr) { + // Check the attribute arguments. + if (Attr.getNumArgs() > 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + return; + } + + if (!isa(D) && !isa(D)) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) + << Attr.getName() << ExpectedVariableOrFunction; + return; + } + + NamedDecl *nd = cast(D); + + // gcc rejects + // class c { + // static int a __attribute__((weakref ("v2"))); + // static int b() __attribute__((weakref ("f3"))); + // }; + // and ignores the attributes of + // void f(void) { + // static int a __attribute__((weakref ("v2"))); + // } + // we reject them + const DeclContext *Ctx = D->getDeclContext()->getRedeclContext(); + if (!Ctx->isFileContext()) { + S.Diag(Attr.getLoc(), diag::err_attribute_weakref_not_global_context) << + nd->getNameAsString(); + return; + } + + // The GCC manual says + // + // At present, a declaration to which `weakref' is attached can only + // be `static'. + // + // It also says + // + // Without a TARGET, + // given as an argument to `weakref' or to `alias', `weakref' is + // equivalent to `weak'. + // + // gcc 4.4.1 will accept + // int a7 __attribute__((weakref)); + // as + // int a7 __attribute__((weak)); + // This looks like a bug in gcc. We reject that for now. We should revisit + // it if this behaviour is actually used. + + if (!hasEffectivelyInternalLinkage(nd)) { + S.Diag(Attr.getLoc(), diag::err_attribute_weakref_not_static); + return; + } + + // GCC rejects + // static ((alias ("y"), weakref)). + // Should we? How to check that weakref is before or after alias? + + if (Attr.getNumArgs() == 1) { + Expr *Arg = Attr.getArg(0); + Arg = Arg->IgnoreParenCasts(); + StringLiteral *Str = dyn_cast(Arg); + + if (!Str || !Str->isAscii()) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) + << "weakref" << 1; + return; + } + // GCC will accept anything as the argument of weakref. Should we + // check for an existing decl? + D->addAttr(::new (S.Context) AliasAttr(Attr.getRange(), S.Context, + Str->getString())); + } + + D->addAttr(::new (S.Context) WeakRefAttr(Attr.getRange(), S.Context)); +} + +static void handleAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) { + // check the attribute arguments. + if (Attr.getNumArgs() != 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + return; + } + + Expr *Arg = Attr.getArg(0); + Arg = Arg->IgnoreParenCasts(); + StringLiteral *Str = dyn_cast(Arg); + + if (!Str || !Str->isAscii()) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) + << "alias" << 1; + return; + } + + if (S.Context.getTargetInfo().getTriple().isOSDarwin()) { + S.Diag(Attr.getLoc(), diag::err_alias_not_supported_on_darwin); + return; + } + + // FIXME: check if target symbol exists in current file + + D->addAttr(::new (S.Context) AliasAttr(Attr.getRange(), S.Context, + Str->getString())); +} + +static void handleNakedAttr(Sema &S, Decl *D, const AttributeList &Attr) { + // Check the attribute arguments. + if (!checkAttributeNumArgs(S, Attr, 0)) + return; + + if (!isa(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunction; + return; + } + + D->addAttr(::new (S.Context) NakedAttr(Attr.getRange(), S.Context)); +} + +static void handleAlwaysInlineAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + // Check the attribute arguments. + if (Attr.hasParameterOrArguments()) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + if (!isa(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunction; + return; + } + + D->addAttr(::new (S.Context) AlwaysInlineAttr(Attr.getRange(), S.Context)); +} + +static void handleMallocAttr(Sema &S, Decl *D, const AttributeList &Attr) { + // Check the attribute arguments. + if (Attr.hasParameterOrArguments()) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + if (const FunctionDecl *FD = dyn_cast(D)) { + QualType RetTy = FD->getResultType(); + if (RetTy->isAnyPointerType() || RetTy->isBlockPointerType()) { + D->addAttr(::new (S.Context) MallocAttr(Attr.getRange(), S.Context)); + return; + } + } + + S.Diag(Attr.getLoc(), diag::warn_attribute_malloc_pointer_only); +} + +static void handleMayAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) { + // check the attribute arguments. + if (!checkAttributeNumArgs(S, Attr, 0)) + return; + + D->addAttr(::new (S.Context) MayAliasAttr(Attr.getRange(), S.Context)); +} + +static void handleNoCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) { + assert(!Attr.isInvalid()); + if (isa(D)) + D->addAttr(::new (S.Context) NoCommonAttr(Attr.getRange(), S.Context)); + else + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedVariable; +} + +static void handleCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) { + assert(!Attr.isInvalid()); + if (isa(D)) + D->addAttr(::new (S.Context) CommonAttr(Attr.getRange(), S.Context)); + else + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedVariable; +} + +static void handleNoReturnAttr(Sema &S, Decl *D, const AttributeList &attr) { + if (hasDeclarator(D)) return; + + if (S.CheckNoReturnAttr(attr)) return; + + if (!isa(D)) { + S.Diag(attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << attr.getName() << ExpectedFunctionOrMethod; + return; + } + + D->addAttr(::new (S.Context) NoReturnAttr(attr.getRange(), S.Context)); +} + +bool Sema::CheckNoReturnAttr(const AttributeList &attr) { + if (attr.hasParameterOrArguments()) { + Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + attr.setInvalid(); + return true; + } + + return false; +} + +static void handleAnalyzerNoReturnAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + + // The checking path for 'noreturn' and 'analyzer_noreturn' are different + // because 'analyzer_noreturn' does not impact the type. + + if(!checkAttributeNumArgs(S, Attr, 0)) + 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() << ExpectedFunctionMethodOrBlock; + return; + } + } + + D->addAttr(::new (S.Context) AnalyzerNoReturnAttr(Attr.getRange(), S.Context)); +} + +// PS3 PPU-specific. +static void handleVecReturnAttr(Sema &S, Decl *D, const AttributeList &Attr) { +/* + 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() << ExpectedClass; + return; + } + + if (D->getAttr()) { + S.Diag(Attr.getLoc(), diag::err_repeat_attribute) << "vecreturn"; + return; + } + + RecordDecl *record = cast(D); + int count = 0; + + if (!isa(record)) { + S.Diag(Attr.getLoc(), diag::err_attribute_vecreturn_only_vector_member); + return; + } + + if (!cast(record)->isPOD()) { + S.Diag(Attr.getLoc(), diag::err_attribute_vecreturn_only_pod_record); + return; + } + + for (RecordDecl::field_iterator iter = record->field_begin(); + iter != record->field_end(); iter++) { + if ((count == 1) || !iter->getType()->isVectorType()) { + S.Diag(Attr.getLoc(), diag::err_attribute_vecreturn_only_vector_member); + return; + } + count++; + } + + D->addAttr(::new (S.Context) VecReturnAttr(Attr.getRange(), S.Context)); +} + +static void handleDependencyAttr(Sema &S, Decl *D, const AttributeList &Attr) { + if (!isFunctionOrMethod(D) && !isa(D)) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunctionMethodOrParameter; + return; + } + // FIXME: Actually store the attribute on the declaration +} + +static void handleUnusedAttr(Sema &S, Decl *D, const AttributeList &Attr) { + // check the attribute arguments. + if (Attr.hasParameterOrArguments()) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + if (!isa(D) && !isa(D) && !isFunctionOrMethod(D) && + !isa(D) && !isa(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedVariableFunctionOrLabel; + return; + } + + D->addAttr(::new (S.Context) UnusedAttr(Attr.getRange(), S.Context)); +} + +static void handleReturnsTwiceAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + // check the attribute arguments. + if (Attr.hasParameterOrArguments()) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + if (!isa(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunction; + return; + } + + D->addAttr(::new (S.Context) ReturnsTwiceAttr(Attr.getRange(), S.Context)); +} + +static void handleUsedAttr(Sema &S, Decl *D, const AttributeList &Attr) { + // check the attribute arguments. + if (Attr.hasParameterOrArguments()) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + if (const VarDecl *VD = dyn_cast(D)) { + if (VD->hasLocalStorage() || VD->hasExternalStorage()) { + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "used"; + return; + } + } else if (!isFunctionOrMethod(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedVariableOrFunction; + return; + } + + D->addAttr(::new (S.Context) UsedAttr(Attr.getRange(), S.Context)); +} + +static void handleConstructorAttr(Sema &S, Decl *D, const AttributeList &Attr) { + // check the attribute arguments. + if (Attr.getNumArgs() > 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1; + return; + } + + int priority = 65535; // FIXME: Do not hardcode such constants. + if (Attr.getNumArgs() > 0) { + Expr *E = Attr.getArg(0); + llvm::APSInt Idx(32); + if (E->isTypeDependent() || E->isValueDependent() || + !E->isIntegerConstantExpr(Idx, S.Context)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) + << "constructor" << 1 << E->getSourceRange(); + return; + } + priority = Idx.getZExtValue(); + } + + if (!isa(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunction; + return; + } + + D->addAttr(::new (S.Context) ConstructorAttr(Attr.getRange(), S.Context, + priority)); +} + +static void handleDestructorAttr(Sema &S, Decl *D, const AttributeList &Attr) { + // check the attribute arguments. + if (Attr.getNumArgs() > 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1; + return; + } + + int priority = 65535; // FIXME: Do not hardcode such constants. + if (Attr.getNumArgs() > 0) { + Expr *E = Attr.getArg(0); + llvm::APSInt Idx(32); + if (E->isTypeDependent() || E->isValueDependent() || + !E->isIntegerConstantExpr(Idx, S.Context)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) + << "destructor" << 1 << E->getSourceRange(); + return; + } + priority = Idx.getZExtValue(); + } + + if (!isa(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunction; + return; + } + + D->addAttr(::new (S.Context) DestructorAttr(Attr.getRange(), S.Context, + priority)); +} + +static void handleDeprecatedAttr(Sema &S, Decl *D, const AttributeList &Attr) { + unsigned NumArgs = Attr.getNumArgs(); + if (NumArgs > 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1; + return; + } + + // Handle the case where deprecated attribute has a text message. + StringRef Str; + if (NumArgs == 1) { + StringLiteral *SE = dyn_cast(Attr.getArg(0)); + if (!SE) { + S.Diag(Attr.getArg(0)->getLocStart(), diag::err_attribute_not_string) + << "deprecated"; + return; + } + Str = SE->getString(); + } + + D->addAttr(::new (S.Context) DeprecatedAttr(Attr.getRange(), S.Context, Str)); +} + +static void handleUnavailableAttr(Sema &S, Decl *D, const AttributeList &Attr) { + unsigned NumArgs = Attr.getNumArgs(); + if (NumArgs > 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1; + return; + } + + // Handle the case where unavailable attribute has a text message. + StringRef Str; + if (NumArgs == 1) { + StringLiteral *SE = dyn_cast(Attr.getArg(0)); + if (!SE) { + S.Diag(Attr.getArg(0)->getLocStart(), + diag::err_attribute_not_string) << "unavailable"; + return; + } + Str = SE->getString(); + } + D->addAttr(::new (S.Context) UnavailableAttr(Attr.getRange(), S.Context, Str)); +} + +static void handleArcWeakrefUnavailableAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + unsigned NumArgs = Attr.getNumArgs(); + if (NumArgs > 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 0; + return; + } + + D->addAttr(::new (S.Context) ArcWeakrefUnavailableAttr( + Attr.getRange(), S.Context)); +} + +static void handleObjCRootClassAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + if (!isa(D)) { + S.Diag(Attr.getLoc(), diag::err_attribute_requires_objc_interface); + return; + } + + unsigned NumArgs = Attr.getNumArgs(); + if (NumArgs > 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 0; + return; + } + + D->addAttr(::new (S.Context) ObjCRootClassAttr(Attr.getRange(), S.Context)); +} + +static void handleObjCRequiresPropertyDefsAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + if (!isa(D)) { + S.Diag(Attr.getLoc(), diag::err_suppress_autosynthesis); + return; + } + + unsigned NumArgs = Attr.getNumArgs(); + if (NumArgs > 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 0; + return; + } + + D->addAttr(::new (S.Context) ObjCRequiresPropertyDefsAttr( + Attr.getRange(), S.Context)); +} + +static void handleAvailabilityAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + IdentifierInfo *Platform = Attr.getParameterName(); + SourceLocation PlatformLoc = Attr.getParameterLoc(); + + StringRef PlatformName + = AvailabilityAttr::getPrettyPlatformName(Platform->getName()); + if (PlatformName.empty()) { + S.Diag(PlatformLoc, diag::warn_availability_unknown_platform) + << Platform; + + PlatformName = Platform->getName(); + } + + AvailabilityChange Introduced = Attr.getAvailabilityIntroduced(); + AvailabilityChange Deprecated = Attr.getAvailabilityDeprecated(); + AvailabilityChange Obsoleted = Attr.getAvailabilityObsoleted(); + bool IsUnavailable = Attr.getUnavailableLoc().isValid(); + + // Ensure that Introduced <= Deprecated <= Obsoleted (although not all + // of these steps are needed). + if (Introduced.isValid() && Deprecated.isValid() && + !(Introduced.Version <= Deprecated.Version)) { + S.Diag(Introduced.KeywordLoc, diag::warn_availability_version_ordering) + << 1 << PlatformName << Deprecated.Version.getAsString() + << 0 << Introduced.Version.getAsString(); + return; + } + + if (Introduced.isValid() && Obsoleted.isValid() && + !(Introduced.Version <= Obsoleted.Version)) { + S.Diag(Introduced.KeywordLoc, diag::warn_availability_version_ordering) + << 2 << PlatformName << Obsoleted.Version.getAsString() + << 0 << Introduced.Version.getAsString(); + return; + } + + if (Deprecated.isValid() && Obsoleted.isValid() && + !(Deprecated.Version <= Obsoleted.Version)) { + S.Diag(Deprecated.KeywordLoc, diag::warn_availability_version_ordering) + << 2 << PlatformName << Obsoleted.Version.getAsString() + << 1 << Deprecated.Version.getAsString(); + return; + } + + StringRef Str; + const StringLiteral *SE = + dyn_cast_or_null(Attr.getMessageExpr()); + if (SE) + Str = SE->getString(); + + D->addAttr(::new (S.Context) AvailabilityAttr(Attr.getRange(), S.Context, + Platform, + Introduced.Version, + Deprecated.Version, + Obsoleted.Version, + IsUnavailable, + Str)); +} + +static void handleVisibilityAttr(Sema &S, Decl *D, const AttributeList &Attr) { + // check the attribute arguments. + if(!checkAttributeNumArgs(S, Attr, 1)) + return; + + Expr *Arg = Attr.getArg(0); + Arg = Arg->IgnoreParenCasts(); + StringLiteral *Str = dyn_cast(Arg); + + if (!Str || !Str->isAscii()) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) + << "visibility" << 1; + return; + } + + StringRef TypeStr = Str->getString(); + VisibilityAttr::VisibilityType type; + + if (TypeStr == "default") + type = VisibilityAttr::Default; + else if (TypeStr == "hidden") + type = VisibilityAttr::Hidden; + else if (TypeStr == "internal") + type = VisibilityAttr::Hidden; // FIXME + else if (TypeStr == "protected") { + // Complain about attempts to use protected visibility on targets + // (like Darwin) that don't support it. + if (!S.Context.getTargetInfo().hasProtectedVisibility()) { + S.Diag(Attr.getLoc(), diag::warn_attribute_protected_visibility); + type = VisibilityAttr::Default; + } else { + type = VisibilityAttr::Protected; + } + } else { + S.Diag(Attr.getLoc(), diag::warn_attribute_unknown_visibility) << TypeStr; + return; + } + + D->addAttr(::new (S.Context) VisibilityAttr(Attr.getRange(), S.Context, type)); +} + +static void handleObjCMethodFamilyAttr(Sema &S, Decl *decl, + const AttributeList &Attr) { + ObjCMethodDecl *method = dyn_cast(decl); + if (!method) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) + << ExpectedMethod; + return; + } + + if (Attr.getNumArgs() != 0 || !Attr.getParameterName()) { + if (!Attr.getParameterName() && Attr.getNumArgs() == 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) + << "objc_method_family" << 1; + } else { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + } + Attr.setInvalid(); + return; + } + + StringRef param = Attr.getParameterName()->getName(); + ObjCMethodFamilyAttr::FamilyKind family; + if (param == "none") + family = ObjCMethodFamilyAttr::OMF_None; + else if (param == "alloc") + family = ObjCMethodFamilyAttr::OMF_alloc; + else if (param == "copy") + family = ObjCMethodFamilyAttr::OMF_copy; + else if (param == "init") + family = ObjCMethodFamilyAttr::OMF_init; + else if (param == "mutableCopy") + family = ObjCMethodFamilyAttr::OMF_mutableCopy; + else if (param == "new") + family = ObjCMethodFamilyAttr::OMF_new; + else { + // Just warn and ignore it. This is future-proof against new + // families being used in system headers. + S.Diag(Attr.getParameterLoc(), diag::warn_unknown_method_family); + return; + } + + if (family == ObjCMethodFamilyAttr::OMF_init && + !method->getResultType()->isObjCObjectPointerType()) { + S.Diag(method->getLocation(), diag::err_init_method_bad_return_type) + << method->getResultType(); + // Ignore the attribute. + return; + } + + method->addAttr(new (S.Context) ObjCMethodFamilyAttr(Attr.getRange(), + S.Context, family)); +} + +static void handleObjCExceptionAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + if (!checkAttributeNumArgs(S, Attr, 0)) + return; + + ObjCInterfaceDecl *OCI = dyn_cast(D); + if (OCI == 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_requires_objc_interface); + return; + } + + D->addAttr(::new (S.Context) ObjCExceptionAttr(Attr.getRange(), S.Context)); +} + +static void handleObjCNSObject(Sema &S, Decl *D, const AttributeList &Attr) { + if (Attr.getNumArgs() != 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + return; + } + if (TypedefNameDecl *TD = dyn_cast(D)) { + QualType T = TD->getUnderlyingType(); + if (!T->isPointerType() || + !T->getAs()->getPointeeType()->isRecordType()) { + S.Diag(TD->getLocation(), diag::err_nsobject_attribute); + return; + } + } + else if (!isa(D)) { + // It is okay to include this attribute on properties, e.g.: + // + // @property (retain, nonatomic) struct Bork *Q __attribute__((NSObject)); + // + // In this case it follows tradition and suppresses an error in the above + // case. + S.Diag(D->getLocation(), diag::warn_nsobject_attribute); + } + D->addAttr(::new (S.Context) ObjCNSObjectAttr(Attr.getRange(), S.Context)); +} + +static void +handleOverloadableAttr(Sema &S, Decl *D, const AttributeList &Attr) { + if (Attr.getNumArgs() != 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + return; + } + + if (!isa(D)) { + S.Diag(Attr.getLoc(), diag::err_attribute_overloadable_not_function); + return; + } + + D->addAttr(::new (S.Context) OverloadableAttr(Attr.getRange(), S.Context)); +} + +static void handleBlocksAttr(Sema &S, Decl *D, const AttributeList &Attr) { + if (!Attr.getParameterName()) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) + << "blocks" << 1; + return; + } + + if (Attr.getNumArgs() != 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + return; + } + + BlocksAttr::BlockType type; + if (Attr.getParameterName()->isStr("byref")) + type = BlocksAttr::ByRef; + else { + S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported) + << "blocks" << Attr.getParameterName(); + return; + } + + D->addAttr(::new (S.Context) BlocksAttr(Attr.getRange(), S.Context, type)); +} + +static void handleSentinelAttr(Sema &S, Decl *D, const AttributeList &Attr) { + // check the attribute arguments. + if (Attr.getNumArgs() > 2) { + S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 2; + return; + } + + unsigned sentinel = 0; + if (Attr.getNumArgs() > 0) { + Expr *E = Attr.getArg(0); + llvm::APSInt Idx(32); + if (E->isTypeDependent() || E->isValueDependent() || + !E->isIntegerConstantExpr(Idx, S.Context)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) + << "sentinel" << 1 << E->getSourceRange(); + return; + } + + if (Idx.isSigned() && Idx.isNegative()) { + S.Diag(Attr.getLoc(), diag::err_attribute_sentinel_less_than_zero) + << E->getSourceRange(); + return; + } + + sentinel = Idx.getZExtValue(); + } + + unsigned nullPos = 0; + if (Attr.getNumArgs() > 1) { + Expr *E = Attr.getArg(1); + llvm::APSInt Idx(32); + if (E->isTypeDependent() || E->isValueDependent() || + !E->isIntegerConstantExpr(Idx, S.Context)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) + << "sentinel" << 2 << E->getSourceRange(); + return; + } + nullPos = Idx.getZExtValue(); + + if ((Idx.isSigned() && Idx.isNegative()) || nullPos > 1) { + // FIXME: This error message could be improved, it would be nice + // to say what the bounds actually are. + S.Diag(Attr.getLoc(), diag::err_attribute_sentinel_not_zero_or_one) + << E->getSourceRange(); + return; + } + } + + if (FunctionDecl *FD = dyn_cast(D)) { + const FunctionType *FT = FD->getType()->castAs(); + if (isa(FT)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_named_arguments); + return; + } + + if (!cast(FT)->isVariadic()) { + S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0; + return; + } + } else if (ObjCMethodDecl *MD = dyn_cast(D)) { + if (!MD->isVariadic()) { + S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0; + return; + } + } else if (BlockDecl *BD = dyn_cast(D)) { + if (!BD->isVariadic()) { + S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 1; + return; + } + } else if (const VarDecl *V = dyn_cast(D)) { + QualType Ty = V->getType(); + if (Ty->isBlockPointerType() || Ty->isFunctionPointerType()) { + const FunctionType *FT = Ty->isFunctionPointerType() ? getFunctionType(D) + : Ty->getAs()->getPointeeType()->getAs(); + if (!cast(FT)->isVariadic()) { + int m = Ty->isFunctionPointerType() ? 0 : 1; + S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << m; + return; + } + } else { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunctionMethodOrBlock; + return; + } + } else { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunctionMethodOrBlock; + return; + } + D->addAttr(::new (S.Context) SentinelAttr(Attr.getRange(), S.Context, sentinel, + nullPos)); +} + +static void handleWarnUnusedResult(Sema &S, Decl *D, const AttributeList &Attr) { + // check the attribute arguments. + if (!checkAttributeNumArgs(S, Attr, 0)) + return; + + if (!isFunction(D) && !isa(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunctionOrMethod; + return; + } + + if (isFunction(D) && getFunctionType(D)->getResultType()->isVoidType()) { + S.Diag(Attr.getLoc(), diag::warn_attribute_void_function_method) + << Attr.getName() << 0; + return; + } + if (const ObjCMethodDecl *MD = dyn_cast(D)) + if (MD->getResultType()->isVoidType()) { + S.Diag(Attr.getLoc(), diag::warn_attribute_void_function_method) + << Attr.getName() << 1; + return; + } + + D->addAttr(::new (S.Context) WarnUnusedResultAttr(Attr.getRange(), S.Context)); +} + +static void handleWeakAttr(Sema &S, Decl *D, const AttributeList &Attr) { + // check the attribute arguments. + if (Attr.hasParameterOrArguments()) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + if (!isa(D) && !isa(D)) { + if (isa(D)) { + D->addAttr(::new (S.Context) WeakAttr(Attr.getRange(), S.Context)); + return; + } + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedVariableOrFunction; + return; + } + + NamedDecl *nd = cast(D); + + // 'weak' only applies to declarations with external linkage. + if (hasEffectivelyInternalLinkage(nd)) { + S.Diag(Attr.getLoc(), diag::err_attribute_weak_static); + return; + } + + nd->addAttr(::new (S.Context) WeakAttr(Attr.getRange(), S.Context)); +} + +static void handleWeakImportAttr(Sema &S, Decl *D, const AttributeList &Attr) { + // check the attribute arguments. + if (!checkAttributeNumArgs(S, Attr, 0)) + return; + + + // weak_import only applies to variable & function declarations. + bool isDef = false; + if (!D->canBeWeakImported(isDef)) { + if (isDef) + S.Diag(Attr.getLoc(), + diag::warn_attribute_weak_import_invalid_on_definition) + << "weak_import" << 2 /*variable and function*/; + else if (isa(D) || isa(D) || + (S.Context.getTargetInfo().getTriple().isOSDarwin() && + (isa(D) || isa(D)))) { + // Nothing to warn about here. + } else + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedVariableOrFunction; + + return; + } + + D->addAttr(::new (S.Context) WeakImportAttr(Attr.getRange(), S.Context)); +} + +static void handleReqdWorkGroupSize(Sema &S, Decl *D, + const AttributeList &Attr) { + // Attribute has 3 arguments. + if (!checkAttributeNumArgs(S, Attr, 3)) + return; + + unsigned WGSize[3]; + for (unsigned i = 0; i < 3; ++i) { + Expr *E = Attr.getArg(i); + llvm::APSInt ArgNum(32); + if (E->isTypeDependent() || E->isValueDependent() || + !E->isIntegerConstantExpr(ArgNum, S.Context)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) + << "reqd_work_group_size" << E->getSourceRange(); + return; + } + WGSize[i] = (unsigned) ArgNum.getZExtValue(); + } + D->addAttr(::new (S.Context) ReqdWorkGroupSizeAttr(Attr.getRange(), S.Context, + WGSize[0], WGSize[1], + WGSize[2])); +} + +static void handleSectionAttr(Sema &S, Decl *D, const AttributeList &Attr) { + // Attribute has no arguments. + if (!checkAttributeNumArgs(S, Attr, 1)) + return; + + // Make sure that there is a string literal as the sections's single + // argument. + Expr *ArgExpr = Attr.getArg(0); + StringLiteral *SE = dyn_cast(ArgExpr); + if (!SE) { + S.Diag(ArgExpr->getLocStart(), diag::err_attribute_not_string) << "section"; + return; + } + + // If the target wants to validate the section specifier, make it happen. + std::string Error = S.Context.getTargetInfo().isValidSectionSpecifier(SE->getString()); + if (!Error.empty()) { + S.Diag(SE->getLocStart(), diag::err_attribute_section_invalid_for_target) + << Error; + return; + } + + // This attribute cannot be applied to local variables. + if (isa(D) && cast(D)->hasLocalStorage()) { + S.Diag(SE->getLocStart(), diag::err_attribute_section_local_variable); + return; + } + + D->addAttr(::new (S.Context) SectionAttr(Attr.getRange(), S.Context, + SE->getString())); +} + + +static void handleNothrowAttr(Sema &S, Decl *D, const AttributeList &Attr) { + // check the attribute arguments. + if (Attr.hasParameterOrArguments()) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + if (NoThrowAttr *Existing = D->getAttr()) { + if (Existing->getLocation().isInvalid()) + Existing->setRange(Attr.getRange()); + } else { + D->addAttr(::new (S.Context) NoThrowAttr(Attr.getRange(), S.Context)); + } +} + +static void handleConstAttr(Sema &S, Decl *D, const AttributeList &Attr) { + // check the attribute arguments. + if (Attr.hasParameterOrArguments()) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + if (ConstAttr *Existing = D->getAttr()) { + if (Existing->getLocation().isInvalid()) + Existing->setRange(Attr.getRange()); + } else { + D->addAttr(::new (S.Context) ConstAttr(Attr.getRange(), S.Context)); + } +} + +static void handlePureAttr(Sema &S, Decl *D, const AttributeList &Attr) { + // check the attribute arguments. + if (!checkAttributeNumArgs(S, Attr, 0)) + return; + + D->addAttr(::new (S.Context) PureAttr(Attr.getRange(), S.Context)); +} + +static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) { + if (!Attr.getParameterName()) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + return; + } + + if (Attr.getNumArgs() != 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + return; + } + + VarDecl *VD = dyn_cast(D); + + if (!VD || !VD->hasLocalStorage()) { + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "cleanup"; + return; + } + + // Look up the function + // FIXME: Lookup probably isn't looking in the right place + NamedDecl *CleanupDecl + = S.LookupSingleName(S.TUScope, Attr.getParameterName(), + Attr.getParameterLoc(), Sema::LookupOrdinaryName); + if (!CleanupDecl) { + S.Diag(Attr.getParameterLoc(), diag::err_attribute_cleanup_arg_not_found) << + Attr.getParameterName(); + return; + } + + FunctionDecl *FD = dyn_cast(CleanupDecl); + if (!FD) { + S.Diag(Attr.getParameterLoc(), + diag::err_attribute_cleanup_arg_not_function) + << Attr.getParameterName(); + return; + } + + if (FD->getNumParams() != 1) { + S.Diag(Attr.getParameterLoc(), + diag::err_attribute_cleanup_func_must_take_one_arg) + << Attr.getParameterName(); + return; + } + + // We're currently more strict than GCC about what function types we accept. + // If this ever proves to be a problem it should be easy to fix. + QualType Ty = S.Context.getPointerType(VD->getType()); + QualType ParamTy = FD->getParamDecl(0)->getType(); + if (S.CheckAssignmentConstraints(FD->getParamDecl(0)->getLocation(), + ParamTy, Ty) != Sema::Compatible) { + S.Diag(Attr.getParameterLoc(), + diag::err_attribute_cleanup_func_arg_incompatible_type) << + Attr.getParameterName() << ParamTy << Ty; + return; + } + + D->addAttr(::new (S.Context) CleanupAttr(Attr.getRange(), S.Context, FD)); + S.MarkFunctionReferenced(Attr.getParameterLoc(), FD); +} + +/// Handle __attribute__((format_arg((idx)))) attribute based on +/// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html +static void handleFormatArgAttr(Sema &S, Decl *D, const AttributeList &Attr) { + if (!checkAttributeNumArgs(S, Attr, 1)) + return; + + if (!isFunctionOrMethod(D) || !hasFunctionProto(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunction; + return; + } + + // In C++ the implicit 'this' function parameter also counts, and they are + // counted from one. + bool HasImplicitThisParam = isInstanceMethod(D); + unsigned NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam; + unsigned FirstIdx = 1; + + // checks for the 2nd argument + Expr *IdxExpr = Attr.getArg(0); + llvm::APSInt Idx(32); + if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() || + !IdxExpr->isIntegerConstantExpr(Idx, S.Context)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) + << "format" << 2 << IdxExpr->getSourceRange(); + return; + } + + if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds) + << "format" << 2 << IdxExpr->getSourceRange(); + return; + } + + unsigned ArgIdx = Idx.getZExtValue() - 1; + + if (HasImplicitThisParam) { + if (ArgIdx == 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_invalid_implicit_this_argument) + << "format_arg" << IdxExpr->getSourceRange(); + return; + } + ArgIdx--; + } + + // make sure the format string is really a string + QualType Ty = getFunctionOrMethodArgType(D, ArgIdx); + + bool not_nsstring_type = !isNSStringType(Ty, S.Context); + if (not_nsstring_type && + !isCFStringType(Ty, S.Context) && + (!Ty->isPointerType() || + !Ty->getAs()->getPointeeType()->isCharType())) { + // FIXME: Should highlight the actual expression that has the wrong type. + S.Diag(Attr.getLoc(), diag::err_format_attribute_not) + << (not_nsstring_type ? "a string type" : "an NSString") + << IdxExpr->getSourceRange(); + return; + } + Ty = getFunctionOrMethodResultType(D); + if (!isNSStringType(Ty, S.Context) && + !isCFStringType(Ty, S.Context) && + (!Ty->isPointerType() || + !Ty->getAs()->getPointeeType()->isCharType())) { + // FIXME: Should highlight the actual expression that has the wrong type. + S.Diag(Attr.getLoc(), diag::err_format_attribute_result_not) + << (not_nsstring_type ? "string type" : "NSString") + << IdxExpr->getSourceRange(); + return; + } + + D->addAttr(::new (S.Context) FormatArgAttr(Attr.getRange(), S.Context, + Idx.getZExtValue())); +} + +enum FormatAttrKind { + CFStringFormat, + NSStringFormat, + StrftimeFormat, + SupportedFormat, + IgnoredFormat, + InvalidFormat +}; + +/// getFormatAttrKind - Map from format attribute names to supported format +/// types. +static FormatAttrKind getFormatAttrKind(StringRef Format) { + // Check for formats that get handled specially. + if (Format == "NSString") + return NSStringFormat; + if (Format == "CFString") + return CFStringFormat; + if (Format == "strftime") + return StrftimeFormat; + + // Otherwise, check for supported formats. + if (Format == "scanf" || Format == "printf" || Format == "printf0" || + Format == "strfmon" || Format == "cmn_err" || Format == "vcmn_err" || + Format == "zcmn_err" || + Format == "kprintf") // OpenBSD. + return SupportedFormat; + + if (Format == "gcc_diag" || Format == "gcc_cdiag" || + Format == "gcc_cxxdiag" || Format == "gcc_tdiag") + return IgnoredFormat; + + return InvalidFormat; +} + +/// Handle __attribute__((init_priority(priority))) attributes based on +/// http://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html +static void handleInitPriorityAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + if (!S.getLangOpts().CPlusPlus) { + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); + return; + } + + if (!isa(D) || S.getCurFunctionOrMethodDecl()) { + S.Diag(Attr.getLoc(), diag::err_init_priority_object_attr); + Attr.setInvalid(); + return; + } + QualType T = dyn_cast(D)->getType(); + if (S.Context.getAsArrayType(T)) + T = S.Context.getBaseElementType(T); + if (!T->getAs()) { + S.Diag(Attr.getLoc(), diag::err_init_priority_object_attr); + Attr.setInvalid(); + return; + } + + if (Attr.getNumArgs() != 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + Attr.setInvalid(); + return; + } + Expr *priorityExpr = Attr.getArg(0); + + llvm::APSInt priority(32); + if (priorityExpr->isTypeDependent() || priorityExpr->isValueDependent() || + !priorityExpr->isIntegerConstantExpr(priority, S.Context)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) + << "init_priority" << priorityExpr->getSourceRange(); + Attr.setInvalid(); + return; + } + unsigned prioritynum = priority.getZExtValue(); + if (prioritynum < 101 || prioritynum > 65535) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_outof_range) + << priorityExpr->getSourceRange(); + Attr.setInvalid(); + return; + } + D->addAttr(::new (S.Context) InitPriorityAttr(Attr.getRange(), S.Context, + prioritynum)); +} + +/// Handle __attribute__((format(type,idx,firstarg))) attributes based on +/// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html +static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) { + + if (!Attr.getParameterName()) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) + << "format" << 1; + return; + } + + if (Attr.getNumArgs() != 2) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 3; + return; + } + + if (!isFunctionOrMethodOrBlock(D) || !hasFunctionProto(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunction; + return; + } + + // In C++ the implicit 'this' function parameter also counts, and they are + // counted from one. + bool HasImplicitThisParam = isInstanceMethod(D); + unsigned NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam; + unsigned FirstIdx = 1; + + StringRef Format = Attr.getParameterName()->getName(); + + // Normalize the argument, __foo__ becomes foo. + if (Format.startswith("__") && Format.endswith("__")) + Format = Format.substr(2, Format.size() - 4); + + // Check for supported formats. + FormatAttrKind Kind = getFormatAttrKind(Format); + + if (Kind == IgnoredFormat) + return; + + if (Kind == InvalidFormat) { + S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported) + << "format" << Attr.getParameterName()->getName(); + return; + } + + // checks for the 2nd argument + Expr *IdxExpr = Attr.getArg(0); + llvm::APSInt Idx(32); + if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() || + !IdxExpr->isIntegerConstantExpr(Idx, S.Context)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) + << "format" << 2 << IdxExpr->getSourceRange(); + return; + } + + if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds) + << "format" << 2 << IdxExpr->getSourceRange(); + return; + } + + // FIXME: Do we need to bounds check? + unsigned ArgIdx = Idx.getZExtValue() - 1; + + if (HasImplicitThisParam) { + if (ArgIdx == 0) { + S.Diag(Attr.getLoc(), + diag::err_format_attribute_implicit_this_format_string) + << IdxExpr->getSourceRange(); + return; + } + ArgIdx--; + } + + // make sure the format string is really a string + QualType Ty = getFunctionOrMethodArgType(D, ArgIdx); + + if (Kind == CFStringFormat) { + if (!isCFStringType(Ty, S.Context)) { + S.Diag(Attr.getLoc(), diag::err_format_attribute_not) + << "a CFString" << IdxExpr->getSourceRange(); + return; + } + } else if (Kind == NSStringFormat) { + // FIXME: do we need to check if the type is NSString*? What are the + // semantics? + if (!isNSStringType(Ty, S.Context)) { + // FIXME: Should highlight the actual expression that has the wrong type. + S.Diag(Attr.getLoc(), diag::err_format_attribute_not) + << "an NSString" << IdxExpr->getSourceRange(); + return; + } + } else if (!Ty->isPointerType() || + !Ty->getAs()->getPointeeType()->isCharType()) { + // FIXME: Should highlight the actual expression that has the wrong type. + S.Diag(Attr.getLoc(), diag::err_format_attribute_not) + << "a string type" << IdxExpr->getSourceRange(); + return; + } + + // check the 3rd argument + Expr *FirstArgExpr = Attr.getArg(1); + llvm::APSInt FirstArg(32); + if (FirstArgExpr->isTypeDependent() || FirstArgExpr->isValueDependent() || + !FirstArgExpr->isIntegerConstantExpr(FirstArg, S.Context)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) + << "format" << 3 << FirstArgExpr->getSourceRange(); + return; + } + + // check if the function is variadic if the 3rd argument non-zero + if (FirstArg != 0) { + if (isFunctionOrMethodVariadic(D)) { + ++NumArgs; // +1 for ... + } else { + S.Diag(D->getLocation(), diag::err_format_attribute_requires_variadic); + return; + } + } + + // strftime requires FirstArg to be 0 because it doesn't read from any + // variable the input is just the current time + the format string. + if (Kind == StrftimeFormat) { + if (FirstArg != 0) { + S.Diag(Attr.getLoc(), diag::err_format_strftime_third_parameter) + << FirstArgExpr->getSourceRange(); + return; + } + // if 0 it disables parameter checking (to use with e.g. va_list) + } else if (FirstArg != 0 && FirstArg != NumArgs) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds) + << "format" << 3 << FirstArgExpr->getSourceRange(); + return; + } + + // Check whether we already have an equivalent format attribute. + for (specific_attr_iterator + i = D->specific_attr_begin(), + e = D->specific_attr_end(); + i != e ; ++i) { + FormatAttr *f = *i; + if (f->getType() == Format && + f->getFormatIdx() == (int)Idx.getZExtValue() && + f->getFirstArg() == (int)FirstArg.getZExtValue()) { + // If we don't have a valid location for this attribute, adopt the + // location. + if (f->getLocation().isInvalid()) + f->setRange(Attr.getRange()); + return; + } + } + + D->addAttr(::new (S.Context) FormatAttr(Attr.getRange(), S.Context, Format, + Idx.getZExtValue(), + FirstArg.getZExtValue())); +} + +static void handleTransparentUnionAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + // check the attribute arguments. + if (!checkAttributeNumArgs(S, Attr, 0)) + return; + + + // Try to find the underlying union declaration. + RecordDecl *RD = 0; + TypedefNameDecl *TD = dyn_cast(D); + if (TD && TD->getUnderlyingType()->isUnionType()) + RD = TD->getUnderlyingType()->getAsUnionType()->getDecl(); + else + RD = dyn_cast(D); + + if (!RD || !RD->isUnion()) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedUnion; + return; + } + + if (!RD->isCompleteDefinition()) { + S.Diag(Attr.getLoc(), + diag::warn_transparent_union_attribute_not_definition); + return; + } + + RecordDecl::field_iterator Field = RD->field_begin(), + FieldEnd = RD->field_end(); + if (Field == FieldEnd) { + S.Diag(Attr.getLoc(), diag::warn_transparent_union_attribute_zero_fields); + return; + } + + FieldDecl *FirstField = *Field; + QualType FirstType = FirstField->getType(); + if (FirstType->hasFloatingRepresentation() || FirstType->isVectorType()) { + S.Diag(FirstField->getLocation(), + diag::warn_transparent_union_attribute_floating) + << FirstType->isVectorType() << FirstType; + return; + } + + uint64_t FirstSize = S.Context.getTypeSize(FirstType); + uint64_t FirstAlign = S.Context.getTypeAlign(FirstType); + for (; Field != FieldEnd; ++Field) { + QualType FieldType = Field->getType(); + if (S.Context.getTypeSize(FieldType) != FirstSize || + S.Context.getTypeAlign(FieldType) != FirstAlign) { + // Warn if we drop the attribute. + bool isSize = S.Context.getTypeSize(FieldType) != FirstSize; + unsigned FieldBits = isSize? S.Context.getTypeSize(FieldType) + : S.Context.getTypeAlign(FieldType); + S.Diag(Field->getLocation(), + diag::warn_transparent_union_attribute_field_size_align) + << isSize << Field->getDeclName() << FieldBits; + unsigned FirstBits = isSize? FirstSize : FirstAlign; + S.Diag(FirstField->getLocation(), + diag::note_transparent_union_first_field_size_align) + << isSize << FirstBits; + return; + } + } + + RD->addAttr(::new (S.Context) TransparentUnionAttr(Attr.getRange(), S.Context)); +} + +static void handleAnnotateAttr(Sema &S, Decl *D, const AttributeList &Attr) { + // check the attribute arguments. + if (!checkAttributeNumArgs(S, Attr, 1)) + return; + + Expr *ArgExpr = Attr.getArg(0); + StringLiteral *SE = dyn_cast(ArgExpr); + + // Make sure that there is a string literal as the annotation's single + // argument. + if (!SE) { + S.Diag(ArgExpr->getLocStart(), diag::err_attribute_not_string) <<"annotate"; + return; + } + + // Don't duplicate annotations that are already set. + for (specific_attr_iterator + i = D->specific_attr_begin(), + e = D->specific_attr_end(); i != e; ++i) { + if ((*i)->getAnnotation() == SE->getString()) + return; + } + D->addAttr(::new (S.Context) AnnotateAttr(Attr.getRange(), S.Context, + SE->getString())); +} + +static void handleAlignedAttr(Sema &S, Decl *D, const AttributeList &Attr) { + // check the attribute arguments. + if (Attr.getNumArgs() > 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + return; + } + + //FIXME: The C++0x version of this attribute has more limited applicabilty + // than GNU's, and should error out when it is used to specify a + // weaker alignment, rather than being silently ignored. + + if (Attr.getNumArgs() == 0) { + D->addAttr(::new (S.Context) AlignedAttr(Attr.getRange(), S.Context, true, 0)); + return; + } + + S.AddAlignedAttr(Attr.getRange(), D, Attr.getArg(0)); +} + +void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E) { + // FIXME: Handle pack-expansions here. + if (DiagnoseUnexpandedParameterPack(E)) + return; + + if (E->isTypeDependent() || E->isValueDependent()) { + // Save dependent expressions in the AST to be instantiated. + D->addAttr(::new (Context) AlignedAttr(AttrRange, Context, true, E)); + return; + } + + SourceLocation AttrLoc = AttrRange.getBegin(); + // FIXME: Cache the number on the Attr object? + llvm::APSInt Alignment(32); + ExprResult ICE = + VerifyIntegerConstantExpression(E, &Alignment, + PDiag(diag::err_attribute_argument_not_int) << "aligned", + /*AllowFold*/ false); + if (ICE.isInvalid()) + return; + if (!llvm::isPowerOf2_64(Alignment.getZExtValue())) { + Diag(AttrLoc, diag::err_attribute_aligned_not_power_of_two) + << E->getSourceRange(); + return; + } + + D->addAttr(::new (Context) AlignedAttr(AttrRange, Context, true, ICE.take())); +} + +void Sema::AddAlignedAttr(SourceRange AttrRange, 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(AttrRange, Context, false, TS)); + return; +} + +/// handleModeAttr - This attribute modifies the width of a decl with primitive +/// type. +/// +/// Despite what would be logical, the mode attribute is a decl attribute, not a +/// type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make 'G' be +/// HImode, not an intermediate pointer. +static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) { + // This attribute isn't documented, but glibc uses it. It changes + // the width of an int or unsigned int to the specified size. + + // Check that there aren't any arguments + if (!checkAttributeNumArgs(S, Attr, 0)) + return; + + + IdentifierInfo *Name = Attr.getParameterName(); + if (!Name) { + S.Diag(Attr.getLoc(), diag::err_attribute_missing_parameter_name); + return; + } + + StringRef Str = Attr.getParameterName()->getName(); + + // Normalize the attribute name, __foo__ becomes foo. + if (Str.startswith("__") && Str.endswith("__")) + Str = Str.substr(2, Str.size() - 4); + + unsigned DestWidth = 0; + bool IntegerMode = true; + bool ComplexMode = false; + switch (Str.size()) { + case 2: + switch (Str[0]) { + case 'Q': DestWidth = 8; break; + case 'H': DestWidth = 16; break; + case 'S': DestWidth = 32; break; + case 'D': DestWidth = 64; break; + case 'X': DestWidth = 96; break; + case 'T': DestWidth = 128; break; + } + if (Str[1] == 'F') { + IntegerMode = false; + } else if (Str[1] == 'C') { + IntegerMode = false; + ComplexMode = true; + } else if (Str[1] != 'I') { + DestWidth = 0; + } + break; + case 4: + // FIXME: glibc uses 'word' to define register_t; this is narrower than a + // pointer on PIC16 and other embedded platforms. + if (Str == "word") + DestWidth = S.Context.getTargetInfo().getPointerWidth(0); + else if (Str == "byte") + DestWidth = S.Context.getTargetInfo().getCharWidth(); + break; + case 7: + if (Str == "pointer") + DestWidth = S.Context.getTargetInfo().getPointerWidth(0); + break; + } + + QualType OldTy; + if (TypedefNameDecl *TD = dyn_cast(D)) + OldTy = TD->getUnderlyingType(); + else if (ValueDecl *VD = dyn_cast(D)) + OldTy = VD->getType(); + else { + S.Diag(D->getLocation(), diag::err_attr_wrong_decl) + << "mode" << Attr.getRange(); + return; + } + + if (!OldTy->getAs() && !OldTy->isComplexType()) + S.Diag(Attr.getLoc(), diag::err_mode_not_primitive); + else if (IntegerMode) { + if (!OldTy->isIntegralOrEnumerationType()) + S.Diag(Attr.getLoc(), diag::err_mode_wrong_type); + } else if (ComplexMode) { + if (!OldTy->isComplexType()) + S.Diag(Attr.getLoc(), diag::err_mode_wrong_type); + } else { + if (!OldTy->isFloatingType()) + S.Diag(Attr.getLoc(), diag::err_mode_wrong_type); + } + + // FIXME: Sync this with InitializePredefinedMacros; we need to match int8_t + // and friends, at least with glibc. + // FIXME: Make sure 32/64-bit integers don't get defined to types of the wrong + // width on unusual platforms. + // FIXME: Make sure floating-point mappings are accurate + // FIXME: Support XF and TF types + QualType NewTy; + switch (DestWidth) { + case 0: + S.Diag(Attr.getLoc(), diag::err_unknown_machine_mode) << Name; + return; + default: + S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name; + return; + case 8: + if (!IntegerMode) { + S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name; + return; + } + if (OldTy->isSignedIntegerType()) + NewTy = S.Context.SignedCharTy; + else + NewTy = S.Context.UnsignedCharTy; + break; + case 16: + if (!IntegerMode) { + S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name; + return; + } + if (OldTy->isSignedIntegerType()) + NewTy = S.Context.ShortTy; + else + NewTy = S.Context.UnsignedShortTy; + break; + case 32: + if (!IntegerMode) + NewTy = S.Context.FloatTy; + else if (OldTy->isSignedIntegerType()) + NewTy = S.Context.IntTy; + else + NewTy = S.Context.UnsignedIntTy; + break; + case 64: + if (!IntegerMode) + NewTy = S.Context.DoubleTy; + else if (OldTy->isSignedIntegerType()) + if (S.Context.getTargetInfo().getLongWidth() == 64) + NewTy = S.Context.LongTy; + else + NewTy = S.Context.LongLongTy; + else + if (S.Context.getTargetInfo().getLongWidth() == 64) + NewTy = S.Context.UnsignedLongTy; + else + NewTy = S.Context.UnsignedLongLongTy; + break; + case 96: + NewTy = S.Context.LongDoubleTy; + break; + case 128: + if (!IntegerMode) { + S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name; + return; + } + if (OldTy->isSignedIntegerType()) + NewTy = S.Context.Int128Ty; + else + NewTy = S.Context.UnsignedInt128Ty; + break; + } + + if (ComplexMode) { + NewTy = S.Context.getComplexType(NewTy); + } + + // Install the new type. + if (TypedefNameDecl *TD = dyn_cast(D)) { + // FIXME: preserve existing source info. + TD->setTypeSourceInfo(S.Context.getTrivialTypeSourceInfo(NewTy)); + } else + cast(D)->setType(NewTy); +} + +static void handleNoDebugAttr(Sema &S, Decl *D, const AttributeList &Attr) { + // check the attribute arguments. + if (!checkAttributeNumArgs(S, Attr, 0)) + return; + + if (!isFunctionOrMethod(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunction; + return; + } + + D->addAttr(::new (S.Context) NoDebugAttr(Attr.getRange(), S.Context)); +} + +static void handleNoInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) { + // check the attribute arguments. + if (!checkAttributeNumArgs(S, Attr, 0)) + return; + + + if (!isa(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunction; + return; + } + + D->addAttr(::new (S.Context) NoInlineAttr(Attr.getRange(), S.Context)); +} + +static void handleNoInstrumentFunctionAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + // check the attribute arguments. + if (!checkAttributeNumArgs(S, Attr, 0)) + return; + + + if (!isa(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunction; + return; + } + + D->addAttr(::new (S.Context) NoInstrumentFunctionAttr(Attr.getRange(), + S.Context)); +} + +static void handleConstantAttr(Sema &S, Decl *D, const AttributeList &Attr) { + if (S.LangOpts.CUDA) { + // check the attribute arguments. + if (Attr.hasParameterOrArguments()) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + if (!isa(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedVariable; + return; + } + + D->addAttr(::new (S.Context) CUDAConstantAttr(Attr.getRange(), S.Context)); + } else { + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "constant"; + } +} + +static void handleDeviceAttr(Sema &S, Decl *D, const AttributeList &Attr) { + if (S.LangOpts.CUDA) { + // check the attribute arguments. + if (Attr.getNumArgs() != 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + if (!isa(D) && !isa(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedVariableOrFunction; + return; + } + + D->addAttr(::new (S.Context) CUDADeviceAttr(Attr.getRange(), S.Context)); + } else { + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "device"; + } +} + +static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) { + if (S.LangOpts.CUDA) { + // check the attribute arguments. + if (!checkAttributeNumArgs(S, Attr, 0)) + return; + + if (!isa(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunction; + return; + } + + FunctionDecl *FD = cast(D); + if (!FD->getResultType()->isVoidType()) { + TypeLoc TL = FD->getTypeSourceInfo()->getTypeLoc().IgnoreParens(); + if (FunctionTypeLoc* FTL = dyn_cast(&TL)) { + S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return) + << FD->getType() + << FixItHint::CreateReplacement(FTL->getResultLoc().getSourceRange(), + "void"); + } else { + S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return) + << FD->getType(); + } + return; + } + + D->addAttr(::new (S.Context) CUDAGlobalAttr(Attr.getRange(), S.Context)); + } else { + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "global"; + } +} + +static void handleHostAttr(Sema &S, Decl *D, const AttributeList &Attr) { + if (S.LangOpts.CUDA) { + // check the attribute arguments. + if (!checkAttributeNumArgs(S, Attr, 0)) + return; + + + if (!isa(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunction; + return; + } + + D->addAttr(::new (S.Context) CUDAHostAttr(Attr.getRange(), S.Context)); + } else { + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "host"; + } +} + +static void handleSharedAttr(Sema &S, Decl *D, const AttributeList &Attr) { + if (S.LangOpts.CUDA) { + // check the attribute arguments. + if (!checkAttributeNumArgs(S, Attr, 0)) + return; + + + if (!isa(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedVariable; + return; + } + + D->addAttr(::new (S.Context) CUDASharedAttr(Attr.getRange(), S.Context)); + } else { + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "shared"; + } +} + +static void handleGNUInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) { + // check the attribute arguments. + if (!checkAttributeNumArgs(S, Attr, 0)) + return; + + FunctionDecl *Fn = dyn_cast(D); + if (Fn == 0) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunction; + return; + } + + if (!Fn->isInlineSpecified()) { + S.Diag(Attr.getLoc(), diag::warn_gnu_inline_attribute_requires_inline); + return; + } + + D->addAttr(::new (S.Context) GNUInlineAttr(Attr.getRange(), S.Context)); +} + +static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &Attr) { + if (hasDeclarator(D)) return; + + // Diagnostic is emitted elsewhere: here we store the (valid) Attr + // in the Decl node for syntactic reasoning, e.g., pretty-printing. + CallingConv CC; + if (S.CheckCallingConvAttr(Attr, CC)) + return; + + if (!isa(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunctionOrMethod; + return; + } + + switch (Attr.getKind()) { + case AttributeList::AT_fastcall: + D->addAttr(::new (S.Context) FastCallAttr(Attr.getRange(), S.Context)); + return; + case AttributeList::AT_stdcall: + D->addAttr(::new (S.Context) StdCallAttr(Attr.getRange(), S.Context)); + return; + case AttributeList::AT_thiscall: + D->addAttr(::new (S.Context) ThisCallAttr(Attr.getRange(), S.Context)); + return; + case AttributeList::AT_cdecl: + D->addAttr(::new (S.Context) CDeclAttr(Attr.getRange(), S.Context)); + return; + case AttributeList::AT_pascal: + D->addAttr(::new (S.Context) PascalAttr(Attr.getRange(), S.Context)); + return; + case AttributeList::AT_pcs: { + Expr *Arg = Attr.getArg(0); + StringLiteral *Str = dyn_cast(Arg); + if (!Str || !Str->isAscii()) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) + << "pcs" << 1; + Attr.setInvalid(); + return; + } + + StringRef StrRef = Str->getString(); + PcsAttr::PCSType PCS; + if (StrRef == "aapcs") + PCS = PcsAttr::AAPCS; + else if (StrRef == "aapcs-vfp") + PCS = PcsAttr::AAPCS_VFP; + else { + S.Diag(Attr.getLoc(), diag::err_invalid_pcs); + Attr.setInvalid(); + return; + } + + D->addAttr(::new (S.Context) PcsAttr(Attr.getRange(), S.Context, PCS)); + } + default: + llvm_unreachable("unexpected attribute kind"); + } +} + +static void handleOpenCLKernelAttr(Sema &S, Decl *D, const AttributeList &Attr){ + assert(!Attr.isInvalid()); + D->addAttr(::new (S.Context) OpenCLKernelAttr(Attr.getRange(), S.Context)); +} + +bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC) { + if (attr.isInvalid()) + return true; + + if ((attr.getNumArgs() != 0 && + !(attr.getKind() == AttributeList::AT_pcs && attr.getNumArgs() == 1)) || + attr.getParameterName()) { + Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + attr.setInvalid(); + return true; + } + + // TODO: diagnose uses of these conventions on the wrong target. Or, better + // move to TargetAttributesSema one day. + switch (attr.getKind()) { + case AttributeList::AT_cdecl: CC = CC_C; break; + case AttributeList::AT_fastcall: CC = CC_X86FastCall; break; + case AttributeList::AT_stdcall: CC = CC_X86StdCall; break; + case AttributeList::AT_thiscall: CC = CC_X86ThisCall; break; + case AttributeList::AT_pascal: CC = CC_X86Pascal; break; + case AttributeList::AT_pcs: { + Expr *Arg = attr.getArg(0); + StringLiteral *Str = dyn_cast(Arg); + if (!Str || !Str->isAscii()) { + Diag(attr.getLoc(), diag::err_attribute_argument_n_not_string) + << "pcs" << 1; + attr.setInvalid(); + return true; + } + + StringRef StrRef = Str->getString(); + if (StrRef == "aapcs") { + CC = CC_AAPCS; + break; + } else if (StrRef == "aapcs-vfp") { + CC = CC_AAPCS_VFP; + break; + } + // FALLS THROUGH + } + default: llvm_unreachable("unexpected attribute kind"); + } + + return false; +} + +static void handleRegparmAttr(Sema &S, Decl *D, const AttributeList &Attr) { + if (hasDeclarator(D)) return; + + unsigned numParams; + if (S.CheckRegparmAttr(Attr, numParams)) + return; + + if (!isa(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunctionOrMethod; + return; + } + + D->addAttr(::new (S.Context) RegparmAttr(Attr.getRange(), S.Context, numParams)); +} + +/// Checks a regparm attribute, returning true if it is ill-formed and +/// otherwise setting numParams to the appropriate value. +bool Sema::CheckRegparmAttr(const AttributeList &Attr, unsigned &numParams) { + if (Attr.isInvalid()) + return true; + + if (Attr.getNumArgs() != 1) { + Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + Attr.setInvalid(); + return true; + } + + Expr *NumParamsExpr = Attr.getArg(0); + llvm::APSInt NumParams(32); + if (NumParamsExpr->isTypeDependent() || NumParamsExpr->isValueDependent() || + !NumParamsExpr->isIntegerConstantExpr(NumParams, Context)) { + Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) + << "regparm" << NumParamsExpr->getSourceRange(); + Attr.setInvalid(); + return true; + } + + if (Context.getTargetInfo().getRegParmMax() == 0) { + Diag(Attr.getLoc(), diag::err_attribute_regparm_wrong_platform) + << NumParamsExpr->getSourceRange(); + Attr.setInvalid(); + return true; + } + + numParams = NumParams.getZExtValue(); + if (numParams > Context.getTargetInfo().getRegParmMax()) { + Diag(Attr.getLoc(), diag::err_attribute_regparm_invalid_number) + << Context.getTargetInfo().getRegParmMax() << NumParamsExpr->getSourceRange(); + Attr.setInvalid(); + return true; + } + + return false; +} + +static void handleLaunchBoundsAttr(Sema &S, Decl *D, const AttributeList &Attr){ + if (S.LangOpts.CUDA) { + // check the attribute arguments. + if (Attr.getNumArgs() != 1 && Attr.getNumArgs() != 2) { + // FIXME: 0 is not okay. + S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 2; + return; + } + + if (!isFunctionOrMethod(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunctionOrMethod; + return; + } + + Expr *MaxThreadsExpr = Attr.getArg(0); + llvm::APSInt MaxThreads(32); + if (MaxThreadsExpr->isTypeDependent() || + MaxThreadsExpr->isValueDependent() || + !MaxThreadsExpr->isIntegerConstantExpr(MaxThreads, S.Context)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) + << "launch_bounds" << 1 << MaxThreadsExpr->getSourceRange(); + return; + } + + llvm::APSInt MinBlocks(32); + if (Attr.getNumArgs() > 1) { + Expr *MinBlocksExpr = Attr.getArg(1); + if (MinBlocksExpr->isTypeDependent() || + MinBlocksExpr->isValueDependent() || + !MinBlocksExpr->isIntegerConstantExpr(MinBlocks, S.Context)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) + << "launch_bounds" << 2 << MinBlocksExpr->getSourceRange(); + return; + } + } + + D->addAttr(::new (S.Context) CUDALaunchBoundsAttr(Attr.getRange(), S.Context, + MaxThreads.getZExtValue(), + MinBlocks.getZExtValue())); + } else { + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "launch_bounds"; + } +} + +//===----------------------------------------------------------------------===// +// Checker-specific attribute handlers. +//===----------------------------------------------------------------------===// + +static bool isValidSubjectOfNSAttribute(Sema &S, QualType type) { + return type->isDependentType() || + type->isObjCObjectPointerType() || + S.Context.isObjCNSObjectType(type); +} +static bool isValidSubjectOfCFAttribute(Sema &S, QualType type) { + return type->isDependentType() || + type->isPointerType() || + isValidSubjectOfNSAttribute(S, type); +} + +static void handleNSConsumedAttr(Sema &S, Decl *D, const AttributeList &Attr) { + ParmVarDecl *param = dyn_cast(D); + if (!param) { + S.Diag(D->getLocStart(), diag::warn_attribute_wrong_decl_type) + << Attr.getRange() << Attr.getName() << ExpectedParameter; + return; + } + + bool typeOK, cf; + if (Attr.getKind() == AttributeList::AT_ns_consumed) { + typeOK = isValidSubjectOfNSAttribute(S, param->getType()); + cf = false; + } else { + typeOK = isValidSubjectOfCFAttribute(S, param->getType()); + cf = true; + } + + if (!typeOK) { + S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_parameter_type) + << Attr.getRange() << Attr.getName() << cf; + return; + } + + if (cf) + param->addAttr(::new (S.Context) CFConsumedAttr(Attr.getRange(), S.Context)); + else + param->addAttr(::new (S.Context) NSConsumedAttr(Attr.getRange(), S.Context)); +} + +static void handleNSConsumesSelfAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + if (!isa(D)) { + S.Diag(D->getLocStart(), diag::warn_attribute_wrong_decl_type) + << Attr.getRange() << Attr.getName() << ExpectedMethod; + return; + } + + D->addAttr(::new (S.Context) NSConsumesSelfAttr(Attr.getRange(), S.Context)); +} + +static void handleNSReturnsRetainedAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + + QualType returnType; + + if (ObjCMethodDecl *MD = dyn_cast(D)) + returnType = MD->getResultType(); + else if (ObjCPropertyDecl *PD = dyn_cast(D)) + returnType = PD->getType(); + else if (S.getLangOpts().ObjCAutoRefCount && hasDeclarator(D) && + (Attr.getKind() == AttributeList::AT_ns_returns_retained)) + return; // ignore: was handled as a type attribute + else if (FunctionDecl *FD = dyn_cast(D)) + returnType = FD->getResultType(); + else { + S.Diag(D->getLocStart(), diag::warn_attribute_wrong_decl_type) + << Attr.getRange() << Attr.getName() + << ExpectedFunctionOrMethod; + return; + } + + bool typeOK; + bool cf; + switch (Attr.getKind()) { + default: llvm_unreachable("invalid ownership attribute"); + case AttributeList::AT_ns_returns_autoreleased: + case AttributeList::AT_ns_returns_retained: + case AttributeList::AT_ns_returns_not_retained: + typeOK = isValidSubjectOfNSAttribute(S, returnType); + cf = false; + break; + + case AttributeList::AT_cf_returns_retained: + case AttributeList::AT_cf_returns_not_retained: + typeOK = isValidSubjectOfCFAttribute(S, returnType); + cf = true; + break; + } + + if (!typeOK) { + S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_return_type) + << Attr.getRange() << Attr.getName() << isa(D) << cf; + return; + } + + switch (Attr.getKind()) { + default: + llvm_unreachable("invalid ownership attribute"); + case AttributeList::AT_ns_returns_autoreleased: + D->addAttr(::new (S.Context) NSReturnsAutoreleasedAttr(Attr.getRange(), + S.Context)); + return; + case AttributeList::AT_cf_returns_not_retained: + D->addAttr(::new (S.Context) CFReturnsNotRetainedAttr(Attr.getRange(), + S.Context)); + return; + case AttributeList::AT_ns_returns_not_retained: + D->addAttr(::new (S.Context) NSReturnsNotRetainedAttr(Attr.getRange(), + S.Context)); + return; + case AttributeList::AT_cf_returns_retained: + D->addAttr(::new (S.Context) CFReturnsRetainedAttr(Attr.getRange(), + S.Context)); + return; + case AttributeList::AT_ns_returns_retained: + D->addAttr(::new (S.Context) NSReturnsRetainedAttr(Attr.getRange(), + S.Context)); + return; + }; +} + +static void handleObjCReturnsInnerPointerAttr(Sema &S, Decl *D, + const AttributeList &attr) { + SourceLocation loc = attr.getLoc(); + + ObjCMethodDecl *method = dyn_cast(D); + + if (!isa(method)) { + S.Diag(method->getLocStart(), diag::err_attribute_wrong_decl_type) + << SourceRange(loc, loc) << attr.getName() << ExpectedMethod; + return; + } + + // Check that the method returns a normal pointer. + QualType resultType = method->getResultType(); + + if (!resultType->isReferenceType() && + (!resultType->isPointerType() || resultType->isObjCRetainableType())) { + S.Diag(method->getLocStart(), diag::warn_ns_attribute_wrong_return_type) + << SourceRange(loc) + << attr.getName() << /*method*/ 1 << /*non-retainable pointer*/ 2; + + // Drop the attribute. + return; + } + + method->addAttr( + ::new (S.Context) ObjCReturnsInnerPointerAttr(attr.getRange(), S.Context)); +} + +/// Handle cf_audited_transfer and cf_unknown_transfer. +static void handleCFTransferAttr(Sema &S, Decl *D, const AttributeList &A) { + if (!isa(D)) { + S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type) + << A.getRange() << A.getName() << ExpectedFunction; + return; + } + + bool IsAudited = (A.getKind() == AttributeList::AT_cf_audited_transfer); + + // Check whether there's a conflicting attribute already present. + Attr *Existing; + if (IsAudited) { + Existing = D->getAttr(); + } else { + Existing = D->getAttr(); + } + if (Existing) { + S.Diag(D->getLocStart(), diag::err_attributes_are_not_compatible) + << A.getName() + << (IsAudited ? "cf_unknown_transfer" : "cf_audited_transfer") + << A.getRange() << Existing->getRange(); + return; + } + + // All clear; add the attribute. + if (IsAudited) { + D->addAttr( + ::new (S.Context) CFAuditedTransferAttr(A.getRange(), S.Context)); + } else { + D->addAttr( + ::new (S.Context) CFUnknownTransferAttr(A.getRange(), S.Context)); + } +} + +static void handleNSBridgedAttr(Sema &S, Scope *Sc, Decl *D, + const AttributeList &Attr) { + RecordDecl *RD = dyn_cast(D); + if (!RD || RD->isUnion()) { + S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type) + << Attr.getRange() << Attr.getName() << ExpectedStruct; + } + + IdentifierInfo *ParmName = Attr.getParameterName(); + + // In Objective-C, verify that the type names an Objective-C type. + // We don't want to check this outside of ObjC because people sometimes + // do crazy C declarations of Objective-C types. + if (ParmName && S.getLangOpts().ObjC1) { + // Check for an existing type with this name. + LookupResult R(S, DeclarationName(ParmName), Attr.getParameterLoc(), + Sema::LookupOrdinaryName); + if (S.LookupName(R, Sc)) { + NamedDecl *Target = R.getFoundDecl(); + if (Target && !isa(Target)) { + S.Diag(D->getLocStart(), diag::err_ns_bridged_not_interface); + S.Diag(Target->getLocStart(), diag::note_declared_at); + } + } + } + + D->addAttr(::new (S.Context) NSBridgedAttr(Attr.getRange(), S.Context, + ParmName)); +} + +static void handleObjCOwnershipAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + if (hasDeclarator(D)) return; + + S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type) + << Attr.getRange() << Attr.getName() << ExpectedVariable; +} + +static void handleObjCPreciseLifetimeAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + if (!isa(D) && !isa(D)) { + S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type) + << Attr.getRange() << Attr.getName() << ExpectedVariable; + return; + } + + ValueDecl *vd = cast(D); + QualType type = vd->getType(); + + if (!type->isDependentType() && + !type->isObjCLifetimeType()) { + S.Diag(Attr.getLoc(), diag::err_objc_precise_lifetime_bad_type) + << type; + return; + } + + Qualifiers::ObjCLifetime lifetime = type.getObjCLifetime(); + + // If we have no lifetime yet, check the lifetime we're presumably + // going to infer. + if (lifetime == Qualifiers::OCL_None && !type->isDependentType()) + lifetime = type->getObjCARCImplicitLifetime(); + + switch (lifetime) { + case Qualifiers::OCL_None: + assert(type->isDependentType() && + "didn't infer lifetime for non-dependent type?"); + break; + + case Qualifiers::OCL_Weak: // meaningful + case Qualifiers::OCL_Strong: // meaningful + break; + + case Qualifiers::OCL_ExplicitNone: + case Qualifiers::OCL_Autoreleasing: + S.Diag(Attr.getLoc(), diag::warn_objc_precise_lifetime_meaningless) + << (lifetime == Qualifiers::OCL_Autoreleasing); + break; + } + + D->addAttr(::new (S.Context) + ObjCPreciseLifetimeAttr(Attr.getRange(), S.Context)); +} + +static bool isKnownDeclSpecAttr(const AttributeList &Attr) { + switch (Attr.getKind()) { + default: + return false; + case AttributeList::AT_dllimport: + case AttributeList::AT_dllexport: + case AttributeList::AT_uuid: + case AttributeList::AT_deprecated: + case AttributeList::AT_noreturn: + case AttributeList::AT_nothrow: + case AttributeList::AT_naked: + case AttributeList::AT_noinline: + return true; + } +} + +//===----------------------------------------------------------------------===// +// Microsoft specific attribute handlers. +//===----------------------------------------------------------------------===// + +static void handleUuidAttr(Sema &S, Decl *D, const AttributeList &Attr) { + if (S.LangOpts.MicrosoftExt || S.LangOpts.Borland) { + // check the attribute arguments. + if (!checkAttributeNumArgs(S, Attr, 1)) + return; + + Expr *Arg = Attr.getArg(0); + StringLiteral *Str = dyn_cast(Arg); + if (!Str || !Str->isAscii()) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) + << "uuid" << 1; + return; + } + + StringRef StrRef = Str->getString(); + + bool IsCurly = StrRef.size() > 1 && StrRef.front() == '{' && + StrRef.back() == '}'; + + // Validate GUID length. + if (IsCurly && StrRef.size() != 38) { + S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid); + return; + } + if (!IsCurly && StrRef.size() != 36) { + S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid); + return; + } + + // GUID format is "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" or + // "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}" + StringRef::iterator I = StrRef.begin(); + if (IsCurly) // Skip the optional '{' + ++I; + + for (int i = 0; i < 36; ++i) { + if (i == 8 || i == 13 || i == 18 || i == 23) { + if (*I != '-') { + S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid); + return; + } + } else if (!isxdigit(*I)) { + S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid); + return; + } + I++; + } + + D->addAttr(::new (S.Context) UuidAttr(Attr.getRange(), S.Context, + Str->getString())); + } else + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "uuid"; +} + +//===----------------------------------------------------------------------===// +// Top Level Sema Entry Points +//===----------------------------------------------------------------------===// + +static void ProcessNonInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, + const AttributeList &Attr) { + switch (Attr.getKind()) { + case AttributeList::AT_device: handleDeviceAttr (S, D, Attr); break; + case AttributeList::AT_host: handleHostAttr (S, D, Attr); break; + case AttributeList::AT_overloadable:handleOverloadableAttr(S, D, Attr); break; + default: + break; + } +} + +static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, + const AttributeList &Attr) { + switch (Attr.getKind()) { + case AttributeList::AT_ibaction: handleIBAction(S, D, Attr); break; + case AttributeList::AT_iboutlet: handleIBOutlet(S, D, Attr); break; + case AttributeList::AT_iboutletcollection: + handleIBOutletCollection(S, D, Attr); break; + case AttributeList::AT_address_space: + case AttributeList::AT_opencl_image_access: + case AttributeList::AT_objc_gc: + case AttributeList::AT_vector_size: + case AttributeList::AT_neon_vector_type: + case AttributeList::AT_neon_polyvector_type: + // Ignore these, these are type attributes, handled by + // ProcessTypeAttributes. + break; + case AttributeList::AT_device: + case AttributeList::AT_host: + case AttributeList::AT_overloadable: + // Ignore, this is a non-inheritable attribute, handled + // by ProcessNonInheritableDeclAttr. + break; + case AttributeList::AT_alias: handleAliasAttr (S, D, Attr); break; + case AttributeList::AT_aligned: handleAlignedAttr (S, D, Attr); break; + case AttributeList::AT_always_inline: + handleAlwaysInlineAttr (S, D, Attr); break; + case AttributeList::AT_analyzer_noreturn: + handleAnalyzerNoReturnAttr (S, D, Attr); break; + case AttributeList::AT_annotate: handleAnnotateAttr (S, D, Attr); break; + case AttributeList::AT_availability:handleAvailabilityAttr(S, D, Attr); break; + case AttributeList::AT_carries_dependency: + handleDependencyAttr (S, D, Attr); break; + case AttributeList::AT_common: handleCommonAttr (S, D, Attr); break; + case AttributeList::AT_constant: handleConstantAttr (S, D, Attr); break; + case AttributeList::AT_constructor: handleConstructorAttr (S, D, Attr); break; + case AttributeList::AT_deprecated: handleDeprecatedAttr (S, D, Attr); break; + case AttributeList::AT_destructor: handleDestructorAttr (S, D, Attr); break; + case AttributeList::AT_ext_vector_type: + handleExtVectorTypeAttr(S, scope, D, Attr); + break; + case AttributeList::AT_format: handleFormatAttr (S, D, Attr); break; + case AttributeList::AT_format_arg: handleFormatArgAttr (S, D, Attr); break; + case AttributeList::AT_global: handleGlobalAttr (S, D, Attr); break; + case AttributeList::AT_gnu_inline: handleGNUInlineAttr (S, D, Attr); break; + case AttributeList::AT_launch_bounds: + handleLaunchBoundsAttr(S, D, Attr); + break; + case AttributeList::AT_mode: handleModeAttr (S, D, Attr); break; + case AttributeList::AT_malloc: handleMallocAttr (S, D, Attr); break; + case AttributeList::AT_may_alias: handleMayAliasAttr (S, D, Attr); break; + case AttributeList::AT_nocommon: handleNoCommonAttr (S, D, Attr); break; + case AttributeList::AT_nonnull: handleNonNullAttr (S, D, Attr); break; + case AttributeList::AT_ownership_returns: + case AttributeList::AT_ownership_takes: + case AttributeList::AT_ownership_holds: + handleOwnershipAttr (S, D, Attr); break; + case AttributeList::AT_naked: handleNakedAttr (S, D, Attr); break; + case AttributeList::AT_noreturn: handleNoReturnAttr (S, D, Attr); break; + case AttributeList::AT_nothrow: handleNothrowAttr (S, D, Attr); break; + case AttributeList::AT_shared: handleSharedAttr (S, D, Attr); break; + case AttributeList::AT_vecreturn: handleVecReturnAttr (S, D, Attr); break; + + case AttributeList::AT_objc_ownership: + handleObjCOwnershipAttr(S, D, Attr); break; + case AttributeList::AT_objc_precise_lifetime: + handleObjCPreciseLifetimeAttr(S, D, Attr); break; + + case AttributeList::AT_objc_returns_inner_pointer: + handleObjCReturnsInnerPointerAttr(S, D, Attr); break; + + case AttributeList::AT_ns_bridged: + handleNSBridgedAttr(S, scope, D, Attr); break; + + case AttributeList::AT_cf_audited_transfer: + case AttributeList::AT_cf_unknown_transfer: + handleCFTransferAttr(S, D, Attr); break; + + // Checker-specific. + case AttributeList::AT_cf_consumed: + case AttributeList::AT_ns_consumed: handleNSConsumedAttr (S, D, Attr); break; + case AttributeList::AT_ns_consumes_self: + handleNSConsumesSelfAttr(S, D, Attr); break; + + case AttributeList::AT_ns_returns_autoreleased: + case AttributeList::AT_ns_returns_not_retained: + case AttributeList::AT_cf_returns_not_retained: + case AttributeList::AT_ns_returns_retained: + case AttributeList::AT_cf_returns_retained: + handleNSReturnsRetainedAttr(S, D, Attr); break; + + case AttributeList::AT_reqd_work_group_size: + handleReqdWorkGroupSize(S, D, Attr); break; + + case AttributeList::AT_init_priority: + handleInitPriorityAttr(S, D, Attr); break; + + case AttributeList::AT_packed: handlePackedAttr (S, D, Attr); break; + case AttributeList::AT_ms_struct: handleMsStructAttr (S, D, Attr); break; + case AttributeList::AT_section: handleSectionAttr (S, D, Attr); break; + case AttributeList::AT_unavailable: handleUnavailableAttr (S, D, Attr); break; + case AttributeList::AT_objc_arc_weak_reference_unavailable: + handleArcWeakrefUnavailableAttr (S, D, Attr); + break; + case AttributeList::AT_objc_root_class: + handleObjCRootClassAttr(S, D, Attr); + break; + case AttributeList::AT_objc_requires_property_definitions: + handleObjCRequiresPropertyDefsAttr (S, D, Attr); + break; + case AttributeList::AT_unused: handleUnusedAttr (S, D, Attr); break; + case AttributeList::AT_returns_twice: + handleReturnsTwiceAttr(S, D, Attr); + break; + case AttributeList::AT_used: handleUsedAttr (S, D, Attr); break; + case AttributeList::AT_visibility: handleVisibilityAttr (S, D, Attr); break; + case AttributeList::AT_warn_unused_result: handleWarnUnusedResult(S, D, Attr); + break; + case AttributeList::AT_weak: handleWeakAttr (S, D, Attr); break; + case AttributeList::AT_weakref: handleWeakRefAttr (S, D, Attr); break; + case AttributeList::AT_weak_import: handleWeakImportAttr (S, D, Attr); break; + case AttributeList::AT_transparent_union: + handleTransparentUnionAttr(S, D, Attr); + break; + case AttributeList::AT_objc_exception: + handleObjCExceptionAttr(S, D, Attr); + break; + case AttributeList::AT_objc_method_family: + handleObjCMethodFamilyAttr(S, D, Attr); + break; + case AttributeList::AT_NSObject: handleObjCNSObject (S, D, Attr); break; + case AttributeList::AT_blocks: handleBlocksAttr (S, D, Attr); break; + case AttributeList::AT_sentinel: handleSentinelAttr (S, D, Attr); break; + case AttributeList::AT_const: handleConstAttr (S, D, Attr); break; + case AttributeList::AT_pure: handlePureAttr (S, D, Attr); break; + case AttributeList::AT_cleanup: handleCleanupAttr (S, D, Attr); break; + case AttributeList::AT_nodebug: handleNoDebugAttr (S, D, Attr); break; + case AttributeList::AT_noinline: handleNoInlineAttr (S, D, Attr); break; + case AttributeList::AT_regparm: handleRegparmAttr (S, D, Attr); break; + case AttributeList::IgnoredAttribute: + // Just ignore + break; + case AttributeList::AT_no_instrument_function: // Interacts with -pg. + handleNoInstrumentFunctionAttr(S, D, Attr); + break; + case AttributeList::AT_stdcall: + case AttributeList::AT_cdecl: + case AttributeList::AT_fastcall: + case AttributeList::AT_thiscall: + case AttributeList::AT_pascal: + case AttributeList::AT_pcs: + handleCallConvAttr(S, D, Attr); + break; + case AttributeList::AT_opencl_kernel_function: + handleOpenCLKernelAttr(S, D, Attr); + break; + case AttributeList::AT_uuid: + handleUuidAttr(S, D, Attr); + break; + + // Thread safety attributes: + case AttributeList::AT_guarded_var: + handleGuardedVarAttr(S, D, Attr); + break; + case AttributeList::AT_pt_guarded_var: + handleGuardedVarAttr(S, D, Attr, /*pointer = */true); + break; + case AttributeList::AT_scoped_lockable: + handleLockableAttr(S, D, Attr, /*scoped = */true); + break; + case AttributeList::AT_no_address_safety_analysis: + handleNoAddressSafetyAttr(S, D, Attr); + break; + case AttributeList::AT_no_thread_safety_analysis: + handleNoThreadSafetyAttr(S, D, Attr); + break; + case AttributeList::AT_lockable: + handleLockableAttr(S, D, Attr); + break; + case AttributeList::AT_guarded_by: + handleGuardedByAttr(S, D, Attr); + break; + case AttributeList::AT_pt_guarded_by: + handleGuardedByAttr(S, D, Attr, /*pointer = */true); + break; + case AttributeList::AT_exclusive_lock_function: + handleLockFunAttr(S, D, Attr, /*exclusive = */true); + break; + case AttributeList::AT_exclusive_locks_required: + handleLocksRequiredAttr(S, D, Attr, /*exclusive = */true); + break; + case AttributeList::AT_exclusive_trylock_function: + handleTrylockFunAttr(S, D, Attr, /*exclusive = */true); + break; + case AttributeList::AT_lock_returned: + handleLockReturnedAttr(S, D, Attr); + break; + case AttributeList::AT_locks_excluded: + handleLocksExcludedAttr(S, D, Attr); + break; + case AttributeList::AT_shared_lock_function: + handleLockFunAttr(S, D, Attr); + break; + case AttributeList::AT_shared_locks_required: + handleLocksRequiredAttr(S, D, Attr); + break; + case AttributeList::AT_shared_trylock_function: + handleTrylockFunAttr(S, D, Attr); + break; + case AttributeList::AT_unlock_function: + handleUnlockFunAttr(S, D, Attr); + break; + case AttributeList::AT_acquired_before: + handleAcquireOrderAttr(S, D, Attr, /*before = */true); + break; + case AttributeList::AT_acquired_after: + handleAcquireOrderAttr(S, D, Attr, /*before = */false); + break; + + default: + // Ask target about the attribute. + const TargetAttributesSema &TargetAttrs = S.getTargetAttributesSema(); + if (!TargetAttrs.ProcessDeclAttribute(scope, D, Attr, S)) + S.Diag(Attr.getLoc(), diag::warn_unknown_attribute_ignored) + << Attr.getName(); + break; + } +} + +/// ProcessDeclAttribute - Apply the specific attribute to the specified decl if +/// the attribute applies to decls. If the attribute is a type attribute, just +/// silently ignore it if a GNU attribute. FIXME: Applying a C++0x attribute to +/// the wrong thing is illegal (C++0x [dcl.attr.grammar]/4). +static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, + const AttributeList &Attr, + bool NonInheritable, bool Inheritable) { + if (Attr.isInvalid()) + return; + + if (Attr.isDeclspecAttribute() && !isKnownDeclSpecAttr(Attr)) + // FIXME: Try to deal with other __declspec attributes! + return; + + if (NonInheritable) + ProcessNonInheritableDeclAttr(S, scope, D, Attr); + + if (Inheritable) + ProcessInheritableDeclAttr(S, scope, D, Attr); +} + +/// ProcessDeclAttributeList - Apply all the decl attributes in the specified +/// attribute list to the specified decl, ignoring any type attributes. +void Sema::ProcessDeclAttributeList(Scope *S, Decl *D, + const AttributeList *AttrList, + bool NonInheritable, bool Inheritable) { + for (const AttributeList* l = AttrList; l; l = l->getNext()) { + ProcessDeclAttribute(*this, S, D, *l, NonInheritable, Inheritable); + } + + // GCC accepts + // static int a9 __attribute__((weakref)); + // but that looks really pointless. We reject it. + if (Inheritable && D->hasAttr() && !D->hasAttr()) { + Diag(AttrList->getLoc(), diag::err_attribute_weakref_without_alias) << + dyn_cast(D)->getNameAsString(); + return; + } +} + +// Annotation attributes are the only attributes allowed after an access +// specifier. +bool Sema::ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl, + const AttributeList *AttrList) { + for (const AttributeList* l = AttrList; l; l = l->getNext()) { + if (l->getKind() == AttributeList::AT_annotate) { + handleAnnotateAttr(*this, ASDecl, *l); + } else { + Diag(l->getLoc(), diag::err_only_annotate_after_access_spec); + return true; + } + } + + return false; +} + +/// checkUnusedDeclAttributes - Check a list of attributes to see if it +/// contains any decl attributes that we should warn about. +static void checkUnusedDeclAttributes(Sema &S, const AttributeList *A) { + for ( ; A; A = A->getNext()) { + // Only warn if the attribute is an unignored, non-type attribute. + if (A->isUsedAsTypeAttr()) continue; + if (A->getKind() == AttributeList::IgnoredAttribute) continue; + + if (A->getKind() == AttributeList::UnknownAttribute) { + S.Diag(A->getLoc(), diag::warn_unknown_attribute_ignored) + << A->getName() << A->getRange(); + } else { + S.Diag(A->getLoc(), diag::warn_attribute_not_on_decl) + << A->getName() << A->getRange(); + } + } +} + +/// checkUnusedDeclAttributes - Given a declarator which is not being +/// used to build a declaration, complain about any decl attributes +/// which might be lying around on it. +void Sema::checkUnusedDeclAttributes(Declarator &D) { + ::checkUnusedDeclAttributes(*this, D.getDeclSpec().getAttributes().getList()); + ::checkUnusedDeclAttributes(*this, D.getAttributes()); + for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) + ::checkUnusedDeclAttributes(*this, D.getTypeObject(i).getAttrs()); +} + +/// DeclClonePragmaWeak - clone existing decl (maybe definition), +/// #pragma weak needs a non-definition decl and source may not have one +NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II, + SourceLocation Loc) { + assert(isa(ND) || isa(ND)); + NamedDecl *NewD = 0; + if (FunctionDecl *FD = dyn_cast(ND)) { + FunctionDecl *NewFD; + // FIXME: Missing call to CheckFunctionDeclaration(). + // FIXME: Mangling? + // FIXME: Is the qualifier info correct? + // FIXME: Is the DeclContext correct? + NewFD = FunctionDecl::Create(FD->getASTContext(), FD->getDeclContext(), + Loc, Loc, DeclarationName(II), + FD->getType(), FD->getTypeSourceInfo(), + SC_None, SC_None, + false/*isInlineSpecified*/, + FD->hasPrototype(), + false/*isConstexprSpecified*/); + NewD = NewFD; + + if (FD->getQualifier()) + NewFD->setQualifierInfo(FD->getQualifierLoc()); + + // Fake up parameter variables; they are declared as if this were + // a typedef. + QualType FDTy = FD->getType(); + if (const FunctionProtoType *FT = FDTy->getAs()) { + SmallVector Params; + for (FunctionProtoType::arg_type_iterator AI = FT->arg_type_begin(), + AE = FT->arg_type_end(); AI != AE; ++AI) { + ParmVarDecl *Param = BuildParmVarDeclForTypedef(NewFD, Loc, *AI); + Param->setScopeInfo(0, Params.size()); + Params.push_back(Param); + } + NewFD->setParams(Params); + } + } else if (VarDecl *VD = dyn_cast(ND)) { + NewD = VarDecl::Create(VD->getASTContext(), VD->getDeclContext(), + VD->getInnerLocStart(), VD->getLocation(), II, + VD->getType(), VD->getTypeSourceInfo(), + VD->getStorageClass(), + VD->getStorageClassAsWritten()); + if (VD->getQualifier()) { + VarDecl *NewVD = cast(NewD); + NewVD->setQualifierInfo(VD->getQualifierLoc()); + } + } + return NewD; +} + +/// DeclApplyPragmaWeak - A declaration (maybe definition) needs #pragma weak +/// applied to it, possibly with an alias. +void Sema::DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W) { + if (W.getUsed()) return; // only do this once + W.setUsed(true); + if (W.getAlias()) { // clone decl, impersonate __attribute(weak,alias(...)) + IdentifierInfo *NDId = ND->getIdentifier(); + NamedDecl *NewD = DeclClonePragmaWeak(ND, W.getAlias(), W.getLocation()); + 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. + DeclContext *SavedContext = CurContext; + CurContext = Context.getTranslationUnitDecl(); + PushOnScopeChains(NewD, S); + CurContext = SavedContext; + } else { // just add weak to existing + ND->addAttr(::new (Context) WeakAttr(W.getLocation(), Context)); + } +} + +/// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in +/// it, apply them to D. This is a bit tricky because PD can have attributes +/// specified in many different places, and we need to find and apply them all. +void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD, + bool NonInheritable, bool Inheritable) { + // It's valid to "forward-declare" #pragma weak, in which case we + // have to do this. + if (Inheritable) { + LoadExternalWeakUndeclaredIdentifiers(); + if (!WeakUndeclaredIdentifiers.empty()) { + if (NamedDecl *ND = dyn_cast(D)) { + if (IdentifierInfo *Id = ND->getIdentifier()) { + llvm::DenseMap::iterator I + = WeakUndeclaredIdentifiers.find(Id); + if (I != WeakUndeclaredIdentifiers.end() && ND->hasLinkage()) { + WeakInfo W = I->second; + DeclApplyPragmaWeak(S, ND, W); + WeakUndeclaredIdentifiers[Id] = W; + } + } + } + } + } + + // Apply decl attributes from the DeclSpec if present. + if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes().getList()) + ProcessDeclAttributeList(S, D, Attrs, NonInheritable, Inheritable); + + // Walk the declarator structure, applying decl attributes that were in a type + // position to the decl itself. This handles cases like: + // int *__attr__(x)** D; + // when X is a decl attribute. + for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i) + if (const AttributeList *Attrs = PD.getTypeObject(i).getAttrs()) + ProcessDeclAttributeList(S, D, Attrs, NonInheritable, Inheritable); + + // Finally, apply any attributes on the decl itself. + if (const AttributeList *Attrs = PD.getAttributes()) + ProcessDeclAttributeList(S, D, Attrs, NonInheritable, Inheritable); +} + +/// Is the given declaration allowed to use a forbidden type? +static bool isForbiddenTypeAllowed(Sema &S, Decl *decl) { + // Private ivars are always okay. Unfortunately, people don't + // always properly make their ivars private, even in system headers. + // Plus we need to make fields okay, too. + // Function declarations in sys headers will be marked unavailable. + if (!isa(decl) && !isa(decl) && + !isa(decl)) + return false; + + // Require it to be declared in a system header. + return S.Context.getSourceManager().isInSystemHeader(decl->getLocation()); +} + +/// Handle a delayed forbidden-type diagnostic. +static void handleDelayedForbiddenType(Sema &S, DelayedDiagnostic &diag, + Decl *decl) { + if (decl && isForbiddenTypeAllowed(S, decl)) { + decl->addAttr(new (S.Context) UnavailableAttr(diag.Loc, S.Context, + "this system declaration uses an unsupported type")); + return; + } + if (S.getLangOpts().ObjCAutoRefCount) + if (const FunctionDecl *FD = dyn_cast(decl)) { + // FIXME. we may want to supress diagnostics for all + // kind of forbidden type messages on unavailable functions. + if (FD->hasAttr() && + diag.getForbiddenTypeDiagnostic() == + diag::err_arc_array_param_no_ownership) { + diag.Triggered = true; + return; + } + } + + S.Diag(diag.Loc, diag.getForbiddenTypeDiagnostic()) + << diag.getForbiddenTypeOperand() << diag.getForbiddenTypeArgument(); + diag.Triggered = true; +} + +// This duplicates a vector push_back but hides the need to know the +// size of the type. +void Sema::DelayedDiagnostics::add(const DelayedDiagnostic &diag) { + assert(StackSize <= StackCapacity); + + // Grow the stack if necessary. + if (StackSize == StackCapacity) { + unsigned newCapacity = 2 * StackCapacity + 2; + char *newBuffer = new char[newCapacity * sizeof(DelayedDiagnostic)]; + const char *oldBuffer = (const char*) Stack; + + if (StackCapacity) + memcpy(newBuffer, oldBuffer, StackCapacity * sizeof(DelayedDiagnostic)); + + delete[] oldBuffer; + Stack = reinterpret_cast(newBuffer); + StackCapacity = newCapacity; + } + + assert(StackSize < StackCapacity); + new (&Stack[StackSize++]) DelayedDiagnostic(diag); +} + +void Sema::DelayedDiagnostics::popParsingDecl(Sema &S, ParsingDeclState state, + Decl *decl) { + DelayedDiagnostics &DD = S.DelayedDiagnostics; + + // Check the invariants. + assert(DD.StackSize >= state.SavedStackSize); + assert(state.SavedStackSize >= DD.ActiveStackBase); + assert(DD.ParsingDepth > 0); + + // Drop the parsing depth. + DD.ParsingDepth--; + + // If there are no active diagnostics, we're done. + if (DD.StackSize == DD.ActiveStackBase) + return; + + // We only want to actually emit delayed diagnostics when we + // successfully parsed a decl. + if (decl) { + // We emit all the active diagnostics, not just those starting + // from the saved state. The idea is this: we get one push for a + // decl spec and another for each declarator; in a decl group like: + // deprecated_typedef foo, *bar, baz(); + // only the declarator pops will be passed decls. This is correct; + // we really do need to consider delayed diagnostics from the decl spec + // for each of the different declarations. + for (unsigned i = DD.ActiveStackBase, e = DD.StackSize; i != e; ++i) { + DelayedDiagnostic &diag = DD.Stack[i]; + if (diag.Triggered) + continue; + + switch (diag.Kind) { + case DelayedDiagnostic::Deprecation: + // Don't bother giving deprecation diagnostics if the decl is invalid. + if (!decl->isInvalidDecl()) + S.HandleDelayedDeprecationCheck(diag, decl); + break; + + case DelayedDiagnostic::Access: + S.HandleDelayedAccessCheck(diag, decl); + break; + + case DelayedDiagnostic::ForbiddenType: + handleDelayedForbiddenType(S, diag, decl); + break; + } + } + } + + // Destroy all the delayed diagnostics we're about to pop off. + for (unsigned i = state.SavedStackSize, e = DD.StackSize; i != e; ++i) + DD.Stack[i].Destroy(); + + DD.StackSize = state.SavedStackSize; +} + +static bool isDeclDeprecated(Decl *D) { + do { + if (D->isDeprecated()) + return true; + // A category implicitly has the availability of the interface. + if (const ObjCCategoryDecl *CatD = dyn_cast(D)) + return CatD->getClassInterface()->isDeprecated(); + } while ((D = cast_or_null(D->getDeclContext()))); + return false; +} + +void Sema::HandleDelayedDeprecationCheck(DelayedDiagnostic &DD, + Decl *Ctx) { + if (isDeclDeprecated(Ctx)) + return; + + DD.Triggered = true; + if (!DD.getDeprecationMessage().empty()) + Diag(DD.Loc, diag::warn_deprecated_message) + << DD.getDeprecationDecl()->getDeclName() + << DD.getDeprecationMessage(); + else if (DD.getUnknownObjCClass()) { + Diag(DD.Loc, diag::warn_deprecated_fwdclass_message) + << DD.getDeprecationDecl()->getDeclName(); + Diag(DD.getUnknownObjCClass()->getLocation(), diag::note_forward_class); + } + else + Diag(DD.Loc, diag::warn_deprecated) + << DD.getDeprecationDecl()->getDeclName(); +} + +void Sema::EmitDeprecationWarning(NamedDecl *D, StringRef Message, + SourceLocation Loc, + const ObjCInterfaceDecl *UnknownObjCClass) { + // Delay if we're currently parsing a declaration. + if (DelayedDiagnostics.shouldDelayDiagnostics()) { + DelayedDiagnostics.add(DelayedDiagnostic::makeDeprecation(Loc, D, + UnknownObjCClass, + Message)); + return; + } + + // Otherwise, don't warn if our current context is deprecated. + if (isDeclDeprecated(cast(getCurLexicalContext()))) + return; + if (!Message.empty()) + Diag(Loc, diag::warn_deprecated_message) << D->getDeclName() + << Message; + else { + if (!UnknownObjCClass) + Diag(Loc, diag::warn_deprecated) << D->getDeclName(); + else { + Diag(Loc, diag::warn_deprecated_fwdclass_message) << D->getDeclName(); + Diag(UnknownObjCClass->getLocation(), diag::note_forward_class); + } + } +} diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp new file mode 100644 index 0000000..c861072 --- /dev/null +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -0,0 +1,11340 @@ +//===------ SemaDeclCXX.cpp - Semantic Analysis for C++ Declarations ------===// +// +// 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 C++ declarations. +// +//===----------------------------------------------------------------------===// + +#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/Sema/ScopeInfo.h" +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/ASTMutationListener.h" +#include "clang/AST/CharUnits.h" +#include "clang/AST/CXXInheritance.h" +#include "clang/AST/DeclVisitor.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/RecordLayout.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/StmtVisitor.h" +#include "clang/AST/TypeLoc.h" +#include "clang/AST/TypeOrdering.h" +#include "clang/Sema/DeclSpec.h" +#include "clang/Sema/ParsedTemplate.h" +#include "clang/Basic/PartialDiagnostic.h" +#include "clang/Lex/Preprocessor.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/STLExtras.h" +#include +#include + +using namespace clang; + +//===----------------------------------------------------------------------===// +// CheckDefaultArgumentVisitor +//===----------------------------------------------------------------------===// + +namespace { + /// CheckDefaultArgumentVisitor - C++ [dcl.fct.default] Traverses + /// the default argument of a parameter to determine whether it + /// contains any ill-formed subexpressions. For example, this will + /// diagnose the use of local variables or parameters within the + /// default argument expression. + class CheckDefaultArgumentVisitor + : public StmtVisitor { + Expr *DefaultArg; + Sema *S; + + public: + CheckDefaultArgumentVisitor(Expr *defarg, Sema *s) + : DefaultArg(defarg), S(s) {} + + bool VisitExpr(Expr *Node); + bool VisitDeclRefExpr(DeclRefExpr *DRE); + bool VisitCXXThisExpr(CXXThisExpr *ThisE); + bool VisitLambdaExpr(LambdaExpr *Lambda); + }; + + /// VisitExpr - Visit all of the children of this expression. + bool CheckDefaultArgumentVisitor::VisitExpr(Expr *Node) { + bool IsInvalid = false; + for (Stmt::child_range I = Node->children(); I; ++I) + IsInvalid |= Visit(*I); + return IsInvalid; + } + + /// VisitDeclRefExpr - Visit a reference to a declaration, to + /// determine whether this declaration can be used in the default + /// argument expression. + bool CheckDefaultArgumentVisitor::VisitDeclRefExpr(DeclRefExpr *DRE) { + NamedDecl *Decl = DRE->getDecl(); + if (ParmVarDecl *Param = dyn_cast(Decl)) { + // C++ [dcl.fct.default]p9 + // Default arguments are evaluated each time the function is + // called. The order of evaluation of function arguments is + // unspecified. Consequently, parameters of a function shall not + // be used in default argument expressions, even if they are not + // evaluated. Parameters of a function declared before a default + // argument expression are in scope and can hide namespace and + // class member names. + return S->Diag(DRE->getLocStart(), + diag::err_param_default_argument_references_param) + << Param->getDeclName() << DefaultArg->getSourceRange(); + } else if (VarDecl *VDecl = dyn_cast(Decl)) { + // C++ [dcl.fct.default]p7 + // Local variables shall not be used in default argument + // expressions. + if (VDecl->isLocalVarDecl()) + return S->Diag(DRE->getLocStart(), + diag::err_param_default_argument_references_local) + << VDecl->getDeclName() << DefaultArg->getSourceRange(); + } + + return false; + } + + /// VisitCXXThisExpr - Visit a C++ "this" expression. + bool CheckDefaultArgumentVisitor::VisitCXXThisExpr(CXXThisExpr *ThisE) { + // C++ [dcl.fct.default]p8: + // The keyword this shall not be used in a default argument of a + // member function. + return S->Diag(ThisE->getLocStart(), + diag::err_param_default_argument_references_this) + << ThisE->getSourceRange(); + } + + bool CheckDefaultArgumentVisitor::VisitLambdaExpr(LambdaExpr *Lambda) { + // C++11 [expr.lambda.prim]p13: + // A lambda-expression appearing in a default argument shall not + // implicitly or explicitly capture any entity. + if (Lambda->capture_begin() == Lambda->capture_end()) + return false; + + return S->Diag(Lambda->getLocStart(), + diag::err_lambda_capture_default_arg); + } +} + +void Sema::ImplicitExceptionSpecification::CalledDecl(SourceLocation CallLoc, + CXXMethodDecl *Method) { + // If we have an MSAny or unknown spec already, don't bother. + if (!Method || ComputedEST == EST_MSAny || ComputedEST == EST_Delayed) + return; + + const FunctionProtoType *Proto + = Method->getType()->getAs(); + Proto = Self->ResolveExceptionSpec(CallLoc, Proto); + if (!Proto) + return; + + ExceptionSpecificationType EST = Proto->getExceptionSpecType(); + + // If this function can throw any exceptions, make a note of that. + if (EST == EST_Delayed || EST == EST_MSAny || EST == EST_None) { + ClearExceptions(); + ComputedEST = EST; + return; + } + + // FIXME: If the call to this decl is using any of its default arguments, we + // need to search them for potentially-throwing calls. + + // If this function has a basic noexcept, it doesn't affect the outcome. + if (EST == EST_BasicNoexcept) + return; + + // If we have a throw-all spec at this point, ignore the function. + if (ComputedEST == EST_None) + return; + + // If we're still at noexcept(true) and there's a nothrow() callee, + // change to that specification. + if (EST == EST_DynamicNone) { + if (ComputedEST == EST_BasicNoexcept) + ComputedEST = EST_DynamicNone; + return; + } + + // Check out noexcept specs. + if (EST == EST_ComputedNoexcept) { + FunctionProtoType::NoexceptResult NR = + Proto->getNoexceptSpec(Self->Context); + assert(NR != FunctionProtoType::NR_NoNoexcept && + "Must have noexcept result for EST_ComputedNoexcept."); + assert(NR != FunctionProtoType::NR_Dependent && + "Should not generate implicit declarations for dependent cases, " + "and don't know how to handle them anyway."); + + // noexcept(false) -> no spec on the new function + if (NR == FunctionProtoType::NR_Throw) { + ClearExceptions(); + ComputedEST = EST_None; + } + // noexcept(true) won't change anything either. + return; + } + + assert(EST == EST_Dynamic && "EST case not considered earlier."); + assert(ComputedEST != EST_None && + "Shouldn't collect exceptions when throw-all is guaranteed."); + ComputedEST = EST_Dynamic; + // Record the exceptions in this function's exception specification. + for (FunctionProtoType::exception_iterator E = Proto->exception_begin(), + EEnd = Proto->exception_end(); + E != EEnd; ++E) + if (ExceptionsSeen.insert(Self->Context.getCanonicalType(*E))) + Exceptions.push_back(*E); +} + +void Sema::ImplicitExceptionSpecification::CalledExpr(Expr *E) { + if (!E || ComputedEST == EST_MSAny || ComputedEST == EST_Delayed) + return; + + // FIXME: + // + // C++0x [except.spec]p14: + // [An] implicit exception-specification specifies the type-id T if and + // only if T is allowed by the exception-specification of a function directly + // invoked by f's implicit definition; f shall allow all exceptions if any + // function it directly invokes allows all exceptions, and f shall allow no + // exceptions if every function it directly invokes allows no exceptions. + // + // Note in particular that if an implicit exception-specification is generated + // for a function containing a throw-expression, that specification can still + // be noexcept(true). + // + // Note also that 'directly invoked' is not defined in the standard, and there + // is no indication that we should only consider potentially-evaluated calls. + // + // Ultimately we should implement the intent of the standard: the exception + // specification should be the set of exceptions which can be thrown by the + // implicit definition. For now, we assume that any non-nothrow expression can + // throw any exception. + + if (Self->canThrow(E)) + ComputedEST = EST_None; +} + +bool +Sema::SetParamDefaultArgument(ParmVarDecl *Param, Expr *Arg, + SourceLocation EqualLoc) { + if (RequireCompleteType(Param->getLocation(), Param->getType(), + diag::err_typecheck_decl_incomplete_type)) { + Param->setInvalidDecl(); + return true; + } + + // C++ [dcl.fct.default]p5 + // A default argument expression is implicitly converted (clause + // 4) to the parameter type. The default argument expression has + // the same semantic constraints as the initializer expression in + // a declaration of a variable of the parameter type, using the + // copy-initialization semantics (8.5). + InitializedEntity Entity = InitializedEntity::InitializeParameter(Context, + Param); + InitializationKind Kind = InitializationKind::CreateCopy(Param->getLocation(), + EqualLoc); + InitializationSequence InitSeq(*this, Entity, Kind, &Arg, 1); + ExprResult Result = InitSeq.Perform(*this, Entity, Kind, + MultiExprArg(*this, &Arg, 1)); + if (Result.isInvalid()) + return true; + Arg = Result.takeAs(); + + CheckImplicitConversions(Arg, EqualLoc); + Arg = MaybeCreateExprWithCleanups(Arg); + + // Okay: add the default argument to the parameter + Param->setDefaultArg(Arg); + + // We have already instantiated this parameter; provide each of the + // instantiations with the uninstantiated default argument. + UnparsedDefaultArgInstantiationsMap::iterator InstPos + = UnparsedDefaultArgInstantiations.find(Param); + if (InstPos != UnparsedDefaultArgInstantiations.end()) { + for (unsigned I = 0, N = InstPos->second.size(); I != N; ++I) + InstPos->second[I]->setUninstantiatedDefaultArg(Arg); + + // We're done tracking this parameter's instantiations. + UnparsedDefaultArgInstantiations.erase(InstPos); + } + + return false; +} + +/// ActOnParamDefaultArgument - Check whether the default argument +/// provided for a function parameter is well-formed. If so, attach it +/// to the parameter declaration. +void +Sema::ActOnParamDefaultArgument(Decl *param, SourceLocation EqualLoc, + Expr *DefaultArg) { + if (!param || !DefaultArg) + return; + + ParmVarDecl *Param = cast(param); + UnparsedDefaultArgLocs.erase(Param); + + // Default arguments are only permitted in C++ + if (!getLangOpts().CPlusPlus) { + Diag(EqualLoc, diag::err_param_default_argument) + << DefaultArg->getSourceRange(); + Param->setInvalidDecl(); + return; + } + + // Check for unexpanded parameter packs. + if (DiagnoseUnexpandedParameterPack(DefaultArg, UPPC_DefaultArgument)) { + Param->setInvalidDecl(); + return; + } + + // Check that the default argument is well-formed + CheckDefaultArgumentVisitor DefaultArgChecker(DefaultArg, this); + if (DefaultArgChecker.Visit(DefaultArg)) { + Param->setInvalidDecl(); + return; + } + + 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(Decl *param, + SourceLocation EqualLoc, + SourceLocation ArgLoc) { + if (!param) + return; + + ParmVarDecl *Param = cast(param); + if (Param) + Param->setUnparsedDefaultArg(); + + UnparsedDefaultArgLocs[Param] = ArgLoc; +} + +/// ActOnParamDefaultArgumentError - Parsing or semantic analysis of +/// the default argument for the parameter param failed. +void Sema::ActOnParamDefaultArgumentError(Decl *param) { + if (!param) + return; + + ParmVarDecl *Param = cast(param); + + Param->setInvalidDecl(); + + UnparsedDefaultArgLocs.erase(Param); +} + +/// CheckExtraCXXDefaultArguments - Check for any extra default +/// arguments in the declarator, which is not a function declaration +/// or definition and therefore is not permitted to have default +/// arguments. This routine should be invoked for every declarator +/// that is not a function declaration or definition. +void Sema::CheckExtraCXXDefaultArguments(Declarator &D) { + // C++ [dcl.fct.default]p3 + // A default argument expression shall be specified only in the + // parameter-declaration-clause of a function declaration or in a + // template-parameter (14.1). It shall not be specified for a + // parameter pack. If it is specified in a + // parameter-declaration-clause, it shall not occur within a + // declarator or abstract-declarator of a parameter-declaration. + for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) { + DeclaratorChunk &chunk = D.getTypeObject(i); + if (chunk.Kind == DeclaratorChunk::Function) { + for (unsigned argIdx = 0, e = chunk.Fun.NumArgs; argIdx != e; ++argIdx) { + ParmVarDecl *Param = + 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) + << SourceRange((*Toks)[1].getLocation(), Toks->back().getLocation()); + delete Toks; + chunk.Fun.ArgInfo[argIdx].DefaultArgTokens = 0; + } else if (Param->getDefaultArg()) { + Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc) + << Param->getDefaultArg()->getSourceRange(); + Param->setDefaultArg(0); + } + } + } + } +} + +// MergeCXXFunctionDecl - Merge two declarations of the same C++ +// function, once we already know that they have the same +// type. Subroutine of MergeFunctionDecl. Returns true if there was an +// error, false otherwise. +bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, + Scope *S) { + bool Invalid = false; + + // C++ [dcl.fct.default]p4: + // For non-template functions, default arguments can be added in + // later declarations of a function in the same + // scope. Declarations in different scopes have completely + // distinct sets of default arguments. That is, declarations in + // inner scopes do not acquire default arguments from + // declarations in outer scopes, and vice versa. In a given + // function declaration, all parameters subsequent to a + // parameter with a default argument shall have default + // arguments supplied in this or previous declarations. A + // default argument shall not be redefined by a later + // declaration (not even to the same value). + // + // C++ [dcl.fct.default]p6: + // Except for member functions of class templates, the default arguments + // in a member function definition that appears outside of the class + // definition are added to the set of default arguments provided by the + // member function declaration in the class definition. + for (unsigned p = 0, NumParams = Old->getNumParams(); p < NumParams; ++p) { + ParmVarDecl *OldParam = Old->getParamDecl(p); + ParmVarDecl *NewParam = New->getParamDecl(p); + + bool OldParamHasDfl = OldParam->hasDefaultArg(); + bool NewParamHasDfl = NewParam->hasDefaultArg(); + + NamedDecl *ND = Old; + if (S && !isDeclInScope(ND, New->getDeclContext(), S)) + // Ignore default parameters of old decl if they are not in + // the same scope. + OldParamHasDfl = false; + + if (OldParamHasDfl && NewParamHasDfl) { + + unsigned DiagDefaultParamID = + diag::err_param_default_argument_redefinition; + + // MSVC accepts that default parameters be redefined for member functions + // of template class. The new default parameter's value is ignored. + Invalid = true; + if (getLangOpts().MicrosoftExt) { + CXXMethodDecl* MD = dyn_cast(New); + if (MD && MD->getParent()->getDescribedClassTemplate()) { + // Merge the old default argument into the new parameter. + NewParam->setHasInheritedDefaultArg(); + if (OldParam->hasUninstantiatedDefaultArg()) + NewParam->setUninstantiatedDefaultArg( + OldParam->getUninstantiatedDefaultArg()); + else + NewParam->setDefaultArg(OldParam->getInit()); + DiagDefaultParamID = diag::warn_param_default_argument_redefinition; + Invalid = false; + } + } + + // FIXME: If we knew where the '=' was, we could easily provide a fix-it + // hint here. Alternatively, we could walk the type-source information + // for NewParam to find the last source location in the type... but it + // isn't worth the effort right now. This is the kind of test case that + // is hard to get right: + // int f(int); + // void g(int (*fp)(int) = f); + // void g(int (*fp)(int) = &f); + Diag(NewParam->getLocation(), DiagDefaultParamID) + << NewParam->getDefaultArgRange(); + + // Look for the function declaration where the default argument was + // actually written, which may be a declaration prior to Old. + for (FunctionDecl *Older = Old->getPreviousDecl(); + Older; Older = Older->getPreviousDecl()) { + if (!Older->getParamDecl(p)->hasDefaultArg()) + break; + + OldParam = Older->getParamDecl(p); + } + + Diag(OldParam->getLocation(), diag::note_previous_definition) + << OldParam->getDefaultArgRange(); + } else if (OldParamHasDfl) { + // Merge the old default argument into the new parameter. + // It's important to use getInit() here; getDefaultArg() + // strips off any top-level ExprWithCleanups. + NewParam->setHasInheritedDefaultArg(); + if (OldParam->hasUninstantiatedDefaultArg()) + NewParam->setUninstantiatedDefaultArg( + OldParam->getUninstantiatedDefaultArg()); + else + NewParam->setDefaultArg(OldParam->getInit()); + } else if (NewParamHasDfl) { + if (New->getDescribedFunctionTemplate()) { + // Paragraph 4, quoted above, only applies to non-template functions. + Diag(NewParam->getLocation(), + diag::err_param_default_argument_template_redecl) + << NewParam->getDefaultArgRange(); + Diag(Old->getLocation(), diag::note_template_prev_declaration) + << false; + } else if (New->getTemplateSpecializationKind() + != TSK_ImplicitInstantiation && + New->getTemplateSpecializationKind() != TSK_Undeclared) { + // C++ [temp.expr.spec]p21: + // Default function arguments shall not be specified in a declaration + // or a definition for one of the following explicit specializations: + // - the explicit specialization of a function template; + // - the explicit specialization of a member function template; + // - the explicit specialization of a member function of a class + // template where the class template specialization to which the + // member function specialization belongs is implicitly + // instantiated. + Diag(NewParam->getLocation(), diag::err_template_spec_default_arg) + << (New->getTemplateSpecializationKind() ==TSK_ExplicitSpecialization) + << New->getDeclName() + << NewParam->getDefaultArgRange(); + } else if (New->getDeclContext()->isDependentContext()) { + // C++ [dcl.fct.default]p6 (DR217): + // Default arguments for a member function of a class template shall + // be specified on the initial declaration of the member function + // within the class template. + // + // Reading the tea leaves a bit in DR217 and its reference to DR205 + // leads me to the conclusion that one cannot add default function + // arguments for an out-of-line definition of a member function of a + // dependent type. + int WhichKind = 2; + if (CXXRecordDecl *Record + = dyn_cast(New->getDeclContext())) { + if (Record->getDescribedClassTemplate()) + WhichKind = 0; + else if (isa(Record)) + WhichKind = 1; + else + WhichKind = 2; + } + + Diag(NewParam->getLocation(), + diag::err_param_default_argument_member_template_redecl) + << WhichKind + << NewParam->getDefaultArgRange(); + } else if (CXXConstructorDecl *Ctor = dyn_cast(New)) { + CXXSpecialMember NewSM = getSpecialMember(Ctor), + OldSM = getSpecialMember(cast(Old)); + if (NewSM != OldSM) { + Diag(NewParam->getLocation(),diag::warn_default_arg_makes_ctor_special) + << NewParam->getDefaultArgRange() << NewSM; + Diag(Old->getLocation(), diag::note_previous_declaration_special) + << OldSM; + } + } + } + } + + // C++11 [dcl.constexpr]p1: If any declaration of a function or function + // template has a constexpr specifier then all its declarations shall + // contain the constexpr specifier. + if (New->isConstexpr() != Old->isConstexpr()) { + Diag(New->getLocation(), diag::err_constexpr_redecl_mismatch) + << New << New->isConstexpr(); + Diag(Old->getLocation(), diag::note_previous_declaration); + Invalid = true; + } + + if (CheckEquivalentExceptionSpec(Old, New)) + Invalid = true; + + return Invalid; +} + +/// \brief Merge the exception specifications of two variable declarations. +/// +/// This is called when there's a redeclaration of a VarDecl. The function +/// checks if the redeclaration might have an exception specification and +/// validates compatibility and merges the specs if necessary. +void Sema::MergeVarDeclExceptionSpecs(VarDecl *New, VarDecl *Old) { + // Shortcut if exceptions are disabled. + if (!getLangOpts().CXXExceptions) + return; + + assert(Context.hasSameType(New->getType(), Old->getType()) && + "Should only be called if types are otherwise the same."); + + QualType NewType = New->getType(); + QualType OldType = Old->getType(); + + // We're only interested in pointers and references to functions, as well + // as pointers to member functions. + if (const ReferenceType *R = NewType->getAs()) { + NewType = R->getPointeeType(); + OldType = OldType->getAs()->getPointeeType(); + } else if (const PointerType *P = NewType->getAs()) { + NewType = P->getPointeeType(); + OldType = OldType->getAs()->getPointeeType(); + } else if (const MemberPointerType *M = NewType->getAs()) { + NewType = M->getPointeeType(); + OldType = OldType->getAs()->getPointeeType(); + } + + if (!NewType->isFunctionProtoType()) + return; + + // There's lots of special cases for functions. For function pointers, system + // libraries are hopefully not as broken so that we don't need these + // workarounds. + if (CheckEquivalentExceptionSpec( + OldType->getAs(), Old->getLocation(), + NewType->getAs(), New->getLocation())) { + New->setInvalidDecl(); + } +} + +/// CheckCXXDefaultArguments - Verify that the default arguments for a +/// function declaration are well-formed according to C++ +/// [dcl.fct.default]. +void Sema::CheckCXXDefaultArguments(FunctionDecl *FD) { + unsigned NumParams = FD->getNumParams(); + unsigned p; + + bool IsLambda = FD->getOverloadedOperator() == OO_Call && + isa(FD) && + cast(FD)->getParent()->isLambda(); + + // Find first parameter with a default argument + for (p = 0; p < NumParams; ++p) { + ParmVarDecl *Param = FD->getParamDecl(p); + if (Param->hasDefaultArg()) { + // C++11 [expr.prim.lambda]p5: + // [...] Default arguments (8.3.6) shall not be specified in the + // parameter-declaration-clause of a lambda-declarator. + // + // FIXME: Core issue 974 strikes this sentence, we only provide an + // extension warning. + if (IsLambda) + Diag(Param->getLocation(), diag::ext_lambda_default_arguments) + << Param->getDefaultArgRange(); + break; + } + } + + // C++ [dcl.fct.default]p4: + // In a given function declaration, all parameters + // subsequent to a parameter with a default argument shall + // have default arguments supplied in this or previous + // declarations. A default argument shall not be redefined + // by a later declaration (not even to the same value). + unsigned LastMissingDefaultArg = 0; + for (; p < NumParams; ++p) { + ParmVarDecl *Param = FD->getParamDecl(p); + if (!Param->hasDefaultArg()) { + if (Param->isInvalidDecl()) + /* We already complained about this parameter. */; + else if (Param->getIdentifier()) + Diag(Param->getLocation(), + diag::err_param_default_argument_missing_name) + << Param->getIdentifier(); + else + Diag(Param->getLocation(), + diag::err_param_default_argument_missing); + + LastMissingDefaultArg = p; + } + } + + if (LastMissingDefaultArg > 0) { + // Some default arguments were missing. Clear out all of the + // default arguments up to (and including) the last missing + // default argument, so that we leave the function parameters + // in a semantically valid state. + for (p = 0; p <= LastMissingDefaultArg; ++p) { + ParmVarDecl *Param = FD->getParamDecl(p); + if (Param->hasDefaultArg()) { + Param->setDefaultArg(0); + } + } + } +} + +// CheckConstexprParameterTypes - Check whether a function's parameter types +// are all literal types. If so, return true. If not, produce a suitable +// diagnostic and return false. +static bool CheckConstexprParameterTypes(Sema &SemaRef, + const FunctionDecl *FD) { + unsigned ArgIndex = 0; + const FunctionProtoType *FT = FD->getType()->getAs(); + for (FunctionProtoType::arg_type_iterator i = FT->arg_type_begin(), + e = FT->arg_type_end(); i != e; ++i, ++ArgIndex) { + const ParmVarDecl *PD = FD->getParamDecl(ArgIndex); + SourceLocation ParamLoc = PD->getLocation(); + if (!(*i)->isDependentType() && + SemaRef.RequireLiteralType(ParamLoc, *i, + SemaRef.PDiag(diag::err_constexpr_non_literal_param) + << ArgIndex+1 << PD->getSourceRange() + << isa(FD))) + return false; + } + return true; +} + +// CheckConstexprFunctionDecl - Check whether a function declaration satisfies +// the requirements of a constexpr function definition or a constexpr +// constructor definition. If so, return true. If not, produce appropriate +// diagnostics and return false. +// +// This implements C++11 [dcl.constexpr]p3,4, as amended by DR1360. +bool Sema::CheckConstexprFunctionDecl(const FunctionDecl *NewFD) { + const CXXMethodDecl *MD = dyn_cast(NewFD); + if (MD && MD->isInstance()) { + // C++11 [dcl.constexpr]p4: + // The definition of a constexpr constructor shall satisfy the following + // constraints: + // - the class shall not have any virtual base classes; + const CXXRecordDecl *RD = MD->getParent(); + if (RD->getNumVBases()) { + Diag(NewFD->getLocation(), diag::err_constexpr_virtual_base) + << isa(NewFD) << RD->isStruct() + << RD->getNumVBases(); + for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(), + E = RD->vbases_end(); I != E; ++I) + Diag(I->getLocStart(), + diag::note_constexpr_virtual_base_here) << I->getSourceRange(); + return false; + } + } + + if (!isa(NewFD)) { + // C++11 [dcl.constexpr]p3: + // The definition of a constexpr function shall satisfy the following + // constraints: + // - it shall not be virtual; + const CXXMethodDecl *Method = dyn_cast(NewFD); + if (Method && Method->isVirtual()) { + Diag(NewFD->getLocation(), diag::err_constexpr_virtual); + + // If it's not obvious why this function is virtual, find an overridden + // function which uses the 'virtual' keyword. + const CXXMethodDecl *WrittenVirtual = Method; + while (!WrittenVirtual->isVirtualAsWritten()) + WrittenVirtual = *WrittenVirtual->begin_overridden_methods(); + if (WrittenVirtual != Method) + Diag(WrittenVirtual->getLocation(), + diag::note_overridden_virtual_function); + return false; + } + + // - its return type shall be a literal type; + QualType RT = NewFD->getResultType(); + if (!RT->isDependentType() && + RequireLiteralType(NewFD->getLocation(), RT, + PDiag(diag::err_constexpr_non_literal_return))) + return false; + } + + // - each of its parameter types shall be a literal type; + if (!CheckConstexprParameterTypes(*this, NewFD)) + return false; + + return true; +} + +/// Check the given declaration statement is legal within a constexpr function +/// body. C++0x [dcl.constexpr]p3,p4. +/// +/// \return true if the body is OK, false if we have diagnosed a problem. +static bool CheckConstexprDeclStmt(Sema &SemaRef, const FunctionDecl *Dcl, + DeclStmt *DS) { + // C++0x [dcl.constexpr]p3 and p4: + // The definition of a constexpr function(p3) or constructor(p4) [...] shall + // contain only + for (DeclStmt::decl_iterator DclIt = DS->decl_begin(), + DclEnd = DS->decl_end(); DclIt != DclEnd; ++DclIt) { + switch ((*DclIt)->getKind()) { + case Decl::StaticAssert: + case Decl::Using: + case Decl::UsingShadow: + case Decl::UsingDirective: + case Decl::UnresolvedUsingTypename: + // - static_assert-declarations + // - using-declarations, + // - using-directives, + continue; + + case Decl::Typedef: + case Decl::TypeAlias: { + // - typedef declarations and alias-declarations that do not define + // classes or enumerations, + TypedefNameDecl *TN = cast(*DclIt); + if (TN->getUnderlyingType()->isVariablyModifiedType()) { + // Don't allow variably-modified types in constexpr functions. + TypeLoc TL = TN->getTypeSourceInfo()->getTypeLoc(); + SemaRef.Diag(TL.getBeginLoc(), diag::err_constexpr_vla) + << TL.getSourceRange() << TL.getType() + << isa(Dcl); + return false; + } + continue; + } + + case Decl::Enum: + case Decl::CXXRecord: + // As an extension, we allow the declaration (but not the definition) of + // classes and enumerations in all declarations, not just in typedef and + // alias declarations. + if (cast(*DclIt)->isThisDeclarationADefinition()) { + SemaRef.Diag(DS->getLocStart(), diag::err_constexpr_type_definition) + << isa(Dcl); + return false; + } + continue; + + case Decl::Var: + SemaRef.Diag(DS->getLocStart(), diag::err_constexpr_var_declaration) + << isa(Dcl); + return false; + + default: + SemaRef.Diag(DS->getLocStart(), diag::err_constexpr_body_invalid_stmt) + << isa(Dcl); + return false; + } + } + + return true; +} + +/// Check that the given field is initialized within a constexpr constructor. +/// +/// \param Dcl The constexpr constructor being checked. +/// \param Field The field being checked. This may be a member of an anonymous +/// struct or union nested within the class being checked. +/// \param Inits All declarations, including anonymous struct/union members and +/// indirect members, for which any initialization was provided. +/// \param Diagnosed Set to true if an error is produced. +static void CheckConstexprCtorInitializer(Sema &SemaRef, + const FunctionDecl *Dcl, + FieldDecl *Field, + llvm::SmallSet &Inits, + bool &Diagnosed) { + if (Field->isUnnamedBitfield()) + return; + + if (Field->isAnonymousStructOrUnion() && + Field->getType()->getAsCXXRecordDecl()->isEmpty()) + return; + + if (!Inits.count(Field)) { + if (!Diagnosed) { + SemaRef.Diag(Dcl->getLocation(), diag::err_constexpr_ctor_missing_init); + Diagnosed = true; + } + SemaRef.Diag(Field->getLocation(), diag::note_constexpr_ctor_missing_init); + } else if (Field->isAnonymousStructOrUnion()) { + const RecordDecl *RD = Field->getType()->castAs()->getDecl(); + for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); + I != E; ++I) + // If an anonymous union contains an anonymous struct of which any member + // is initialized, all members must be initialized. + if (!RD->isUnion() || Inits.count(*I)) + CheckConstexprCtorInitializer(SemaRef, Dcl, *I, Inits, Diagnosed); + } +} + +/// Check the body for the given constexpr function declaration only contains +/// the permitted types of statement. C++11 [dcl.constexpr]p3,p4. +/// +/// \return true if the body is OK, false if we have diagnosed a problem. +bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) { + if (isa(Body)) { + // C++11 [dcl.constexpr]p3: + // The definition of a constexpr function shall satisfy the following + // constraints: [...] + // - its function-body shall be = delete, = default, or a + // compound-statement + // + // C++11 [dcl.constexpr]p4: + // In the definition of a constexpr constructor, [...] + // - its function-body shall not be a function-try-block; + Diag(Body->getLocStart(), diag::err_constexpr_function_try_block) + << isa(Dcl); + return false; + } + + // - its function-body shall be [...] a compound-statement that contains only + CompoundStmt *CompBody = cast(Body); + + llvm::SmallVector ReturnStmts; + for (CompoundStmt::body_iterator BodyIt = CompBody->body_begin(), + BodyEnd = CompBody->body_end(); BodyIt != BodyEnd; ++BodyIt) { + switch ((*BodyIt)->getStmtClass()) { + case Stmt::NullStmtClass: + // - null statements, + continue; + + case Stmt::DeclStmtClass: + // - static_assert-declarations + // - using-declarations, + // - using-directives, + // - typedef declarations and alias-declarations that do not define + // classes or enumerations, + if (!CheckConstexprDeclStmt(*this, Dcl, cast(*BodyIt))) + return false; + continue; + + case Stmt::ReturnStmtClass: + // - and exactly one return statement; + if (isa(Dcl)) + break; + + ReturnStmts.push_back((*BodyIt)->getLocStart()); + continue; + + default: + break; + } + + Diag((*BodyIt)->getLocStart(), diag::err_constexpr_body_invalid_stmt) + << isa(Dcl); + return false; + } + + if (const CXXConstructorDecl *Constructor + = dyn_cast(Dcl)) { + const CXXRecordDecl *RD = Constructor->getParent(); + // DR1359: + // - every non-variant non-static data member and base class sub-object + // shall be initialized; + // - if the class is a non-empty union, or for each non-empty anonymous + // union member of a non-union class, exactly one non-static data member + // shall be initialized; + if (RD->isUnion()) { + if (Constructor->getNumCtorInitializers() == 0 && !RD->isEmpty()) { + Diag(Dcl->getLocation(), diag::err_constexpr_union_ctor_no_init); + return false; + } + } else if (!Constructor->isDependentContext() && + !Constructor->isDelegatingConstructor()) { + assert(RD->getNumVBases() == 0 && "constexpr ctor with virtual bases"); + + // Skip detailed checking if we have enough initializers, and we would + // allow at most one initializer per member. + bool AnyAnonStructUnionMembers = false; + unsigned Fields = 0; + for (CXXRecordDecl::field_iterator I = RD->field_begin(), + E = RD->field_end(); I != E; ++I, ++Fields) { + if ((*I)->isAnonymousStructOrUnion()) { + AnyAnonStructUnionMembers = true; + break; + } + } + if (AnyAnonStructUnionMembers || + Constructor->getNumCtorInitializers() != RD->getNumBases() + Fields) { + // Check initialization of non-static data members. Base classes are + // always initialized so do not need to be checked. Dependent bases + // might not have initializers in the member initializer list. + llvm::SmallSet Inits; + for (CXXConstructorDecl::init_const_iterator + I = Constructor->init_begin(), E = Constructor->init_end(); + I != E; ++I) { + if (FieldDecl *FD = (*I)->getMember()) + Inits.insert(FD); + else if (IndirectFieldDecl *ID = (*I)->getIndirectMember()) + Inits.insert(ID->chain_begin(), ID->chain_end()); + } + + bool Diagnosed = false; + for (CXXRecordDecl::field_iterator I = RD->field_begin(), + E = RD->field_end(); I != E; ++I) + CheckConstexprCtorInitializer(*this, Dcl, *I, Inits, Diagnosed); + if (Diagnosed) + return false; + } + } + } else { + if (ReturnStmts.empty()) { + Diag(Dcl->getLocation(), diag::err_constexpr_body_no_return); + return false; + } + if (ReturnStmts.size() > 1) { + Diag(ReturnStmts.back(), diag::err_constexpr_body_multiple_return); + for (unsigned I = 0; I < ReturnStmts.size() - 1; ++I) + Diag(ReturnStmts[I], diag::note_constexpr_body_previous_return); + return false; + } + } + + // C++11 [dcl.constexpr]p5: + // if no function argument values exist such that the function invocation + // substitution would produce a constant expression, the program is + // ill-formed; no diagnostic required. + // C++11 [dcl.constexpr]p3: + // - every constructor call and implicit conversion used in initializing the + // return value shall be one of those allowed in a constant expression. + // C++11 [dcl.constexpr]p4: + // - every constructor involved in initializing non-static data members and + // base class sub-objects shall be a constexpr constructor. + llvm::SmallVector Diags; + if (!Expr::isPotentialConstantExpr(Dcl, Diags)) { + Diag(Dcl->getLocation(), diag::err_constexpr_function_never_constant_expr) + << isa(Dcl); + for (size_t I = 0, N = Diags.size(); I != N; ++I) + Diag(Diags[I].first, Diags[I].second); + return false; + } + + return true; +} + +/// isCurrentClassName - Determine whether the identifier II is the +/// name of the class type currently being defined. In the case of +/// nested classes, this will only return true if II is the name of +/// the innermost class. +bool Sema::isCurrentClassName(const IdentifierInfo &II, Scope *, + const CXXScopeSpec *SS) { + assert(getLangOpts().CPlusPlus && "No class names in C!"); + + CXXRecordDecl *CurDecl; + if (SS && SS->isSet() && !SS->isInvalid()) { + DeclContext *DC = computeDeclContext(*SS, true); + CurDecl = dyn_cast_or_null(DC); + } else + CurDecl = dyn_cast_or_null(CurContext); + + if (CurDecl && CurDecl->getIdentifier()) + return &II == CurDecl->getIdentifier(); + else + return false; +} + +/// \brief Check the validity of a C++ base class specifier. +/// +/// \returns a new CXXBaseSpecifier if well-formed, emits diagnostics +/// and returns NULL otherwise. +CXXBaseSpecifier * +Sema::CheckBaseSpecifier(CXXRecordDecl *Class, + SourceRange SpecifierRange, + bool Virtual, AccessSpecifier Access, + TypeSourceInfo *TInfo, + SourceLocation EllipsisLoc) { + QualType BaseType = TInfo->getType(); + + // C++ [class.union]p1: + // A union shall not have base classes. + if (Class->isUnion()) { + Diag(Class->getLocation(), diag::err_base_clause_on_union) + << SpecifierRange; + return 0; + } + + if (EllipsisLoc.isValid() && + !TInfo->getType()->containsUnexpandedParameterPack()) { + Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) + << TInfo->getTypeLoc().getSourceRange(); + EllipsisLoc = SourceLocation(); + } + + if (BaseType->isDependentType()) + return new (Context) CXXBaseSpecifier(SpecifierRange, Virtual, + Class->getTagKind() == TTK_Class, + Access, TInfo, EllipsisLoc); + + SourceLocation BaseLoc = TInfo->getTypeLoc().getBeginLoc(); + + // Base specifiers must be record types. + if (!BaseType->isRecordType()) { + Diag(BaseLoc, diag::err_base_must_be_class) << SpecifierRange; + return 0; + } + + // C++ [class.union]p1: + // A union shall not be used as a base class. + if (BaseType->isUnionType()) { + Diag(BaseLoc, diag::err_union_as_base_class) << SpecifierRange; + return 0; + } + + // C++ [class.derived]p2: + // The class-name in a base-specifier shall not be an incompletely + // defined class. + if (RequireCompleteType(BaseLoc, BaseType, + PDiag(diag::err_incomplete_base_class) + << 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(); + assert(BaseDecl && "Record type has no declaration"); + BaseDecl = BaseDecl->getDefinition(); + assert(BaseDecl && "Base type is not incomplete, but has no definition"); + CXXRecordDecl * CXXBaseDecl = cast(BaseDecl); + assert(CXXBaseDecl && "Base type is not a C++ type"); + + // C++ [class]p3: + // If a class is marked final and it appears as a base-type-specifier in + // base-clause, the program is ill-formed. + if (CXXBaseDecl->hasAttr()) { + Diag(BaseLoc, diag::err_class_marked_final_used_as_base) + << CXXBaseDecl->getDeclName(); + Diag(CXXBaseDecl->getLocation(), diag::note_previous_decl) + << CXXBaseDecl->getDeclName(); + return 0; + } + + if (BaseDecl->isInvalidDecl()) + Class->setInvalidDecl(); + + // Create the base specifier. + return new (Context) CXXBaseSpecifier(SpecifierRange, Virtual, + Class->getTagKind() == TTK_Class, + Access, TInfo, EllipsisLoc); +} + +/// ActOnBaseSpecifier - Parsed a base specifier. A base specifier is +/// one entry in the base class list of a class specifier, for +/// example: +/// class foo : public bar, virtual private baz { +/// 'public bar' and 'virtual private baz' are each base-specifiers. +BaseResult +Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange, + bool Virtual, AccessSpecifier Access, + ParsedType basetype, SourceLocation BaseLoc, + SourceLocation EllipsisLoc) { + if (!classdecl) + return true; + + AdjustDeclIfTemplate(classdecl); + CXXRecordDecl *Class = dyn_cast(classdecl); + if (!Class) + return true; + + TypeSourceInfo *TInfo = 0; + GetTypeFromParser(basetype, &TInfo); + + if (EllipsisLoc.isInvalid() && + DiagnoseUnexpandedParameterPack(SpecifierRange.getBegin(), TInfo, + UPPC_BaseType)) + return true; + + if (CXXBaseSpecifier *BaseSpec = CheckBaseSpecifier(Class, SpecifierRange, + Virtual, Access, TInfo, + EllipsisLoc)) + return BaseSpec; + + return true; +} + +/// \brief Performs the actual work of attaching the given base class +/// specifiers to a C++ class. +bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases, + unsigned NumBases) { + if (NumBases == 0) + return false; + + // Used to keep track of which base types we have already seen, so + // that we can properly diagnose redundant direct base types. Note + // that the key is always the unqualified canonical type of the base + // class. + std::map KnownBaseTypes; + + // Copy non-redundant base specifiers into permanent storage. + unsigned NumGoodBases = 0; + bool Invalid = false; + for (unsigned idx = 0; idx < NumBases; ++idx) { + QualType NewBaseType + = Context.getCanonicalType(Bases[idx]->getType()); + NewBaseType = NewBaseType.getLocalUnqualifiedType(); + + CXXBaseSpecifier *&KnownBase = KnownBaseTypes[NewBaseType]; + if (KnownBase) { + // C++ [class.mi]p3: + // A class shall not be specified as a direct base class of a + // derived class more than once. + Diag(Bases[idx]->getLocStart(), + diag::err_duplicate_base_class) + << KnownBase->getType() + << Bases[idx]->getSourceRange(); + + // Delete the duplicate base class specifier; we're going to + // overwrite its pointer later. + Context.Deallocate(Bases[idx]); + + Invalid = true; + } else { + // Okay, add this new base class. + KnownBase = Bases[idx]; + Bases[NumGoodBases++] = Bases[idx]; + if (const RecordType *Record = NewBaseType->getAs()) + if (const CXXRecordDecl *RD = cast(Record->getDecl())) + if (RD->hasAttr()) + Class->addAttr(::new (Context) WeakAttr(SourceRange(), Context)); + } + } + + // Attach the remaining base class specifiers to the derived class. + Class->setBases(Bases, NumGoodBases); + + // Delete the remaining (good) base class specifiers, since their + // data has been copied into the CXXRecordDecl. + for (unsigned idx = 0; idx < NumGoodBases; ++idx) + Context.Deallocate(Bases[idx]); + + return Invalid; +} + +/// ActOnBaseSpecifiers - Attach the given base specifiers to the +/// class, after checking whether there are any duplicate base +/// classes. +void Sema::ActOnBaseSpecifiers(Decl *ClassDecl, CXXBaseSpecifier **Bases, + unsigned NumBases) { + if (!ClassDecl || !Bases || !NumBases) + return; + + AdjustDeclIfTemplate(ClassDecl); + AttachBaseSpecifiers(cast(ClassDecl), + (CXXBaseSpecifier**)(Bases), NumBases); +} + +static CXXRecordDecl *GetClassForType(QualType T) { + if (const RecordType *RT = T->getAs()) + return cast(RT->getDecl()); + else if (const InjectedClassNameType *ICT = T->getAs()) + return ICT->getDecl(); + else + return 0; +} + +/// \brief Determine whether the type \p Derived is a C++ class that is +/// derived from the type \p Base. +bool Sema::IsDerivedFrom(QualType Derived, QualType Base) { + if (!getLangOpts().CPlusPlus) + return false; + + CXXRecordDecl *DerivedRD = GetClassForType(Derived); + if (!DerivedRD) + return false; + + CXXRecordDecl *BaseRD = GetClassForType(Base); + if (!BaseRD) + return false; + + // FIXME: instantiate DerivedRD if necessary. We need a PoI for this. + return DerivedRD->hasDefinition() && DerivedRD->isDerivedFrom(BaseRD); +} + +/// \brief Determine whether the type \p Derived is a C++ class that is +/// derived from the type \p Base. +bool Sema::IsDerivedFrom(QualType Derived, QualType Base, CXXBasePaths &Paths) { + if (!getLangOpts().CPlusPlus) + return false; + + CXXRecordDecl *DerivedRD = GetClassForType(Derived); + if (!DerivedRD) + return false; + + CXXRecordDecl *BaseRD = GetClassForType(Base); + if (!BaseRD) + return false; + + return DerivedRD->isDerivedFrom(BaseRD, Paths); +} + +void Sema::BuildBasePathArray(const CXXBasePaths &Paths, + CXXCastPath &BasePathArray) { + assert(BasePathArray.empty() && "Base path array must be empty!"); + assert(Paths.isRecordingPaths() && "Must record paths!"); + + const CXXBasePath &Path = Paths.front(); + + // We first go backward and check if we have a virtual base. + // FIXME: It would be better if CXXBasePath had the base specifier for + // the nearest virtual base. + unsigned Start = 0; + for (unsigned I = Path.size(); I != 0; --I) { + if (Path[I - 1].Base->isVirtual()) { + Start = I - 1; + break; + } + } + + // Now add all bases. + for (unsigned I = Start, E = Path.size(); I != E; ++I) + BasePathArray.push_back(const_cast(Path[I].Base)); +} + +/// \brief Determine whether the given base path includes a virtual +/// base class. +bool Sema::BasePathInvolvesVirtualBase(const CXXCastPath &BasePath) { + for (CXXCastPath::const_iterator B = BasePath.begin(), + BEnd = BasePath.end(); + B != BEnd; ++B) + if ((*B)->isVirtual()) + return true; + + return false; +} + +/// CheckDerivedToBaseConversion - Check whether the Derived-to-Base +/// conversion (where Derived and Base are class types) is +/// well-formed, meaning that the conversion is unambiguous (and +/// that all of the base classes are accessible). Returns true +/// and emits a diagnostic if the code is ill-formed, returns false +/// otherwise. Loc is the location where this routine should point to +/// if there is an error, and Range is the source range to highlight +/// if there is an error. +bool +Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, + unsigned InaccessibleBaseID, + unsigned AmbigiousBaseConvID, + SourceLocation Loc, SourceRange Range, + DeclarationName Name, + 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 + // explore multiple paths to determine if there is an ambiguity. + CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, + /*DetectVirtual=*/false); + bool DerivationOkay = IsDerivedFrom(Derived, Base, Paths); + assert(DerivationOkay && + "Can only be used with a derived-to-base conversion"); + (void)DerivationOkay; + + if (!Paths.isAmbiguous(Context.getCanonicalType(Base).getUnqualifiedType())) { + if (InaccessibleBaseID) { + // Check that the base class can be accessed. + switch (CheckBaseClassAccess(Loc, Base, Derived, Paths.front(), + InaccessibleBaseID)) { + case AR_inaccessible: + return true; + case AR_accessible: + case AR_dependent: + case AR_delayed: + break; + } + } + + // Build a base path if necessary. + if (BasePath) + BuildBasePathArray(Paths, *BasePath); + return false; + } + + // We know that the derived-to-base conversion is ambiguous, and + // we're going to produce a diagnostic. Perform the derived-to-base + // search just one more time to compute all of the possible paths so + // that we can print them out. This is more expensive than any of + // the previous derived-to-base checks we've done, but at this point + // performance isn't as much of an issue. + Paths.clear(); + Paths.setRecordingPaths(true); + bool StillOkay = IsDerivedFrom(Derived, Base, Paths); + assert(StillOkay && "Can only be used with a derived-to-base conversion"); + (void)StillOkay; + + // Build up a textual representation of the ambiguous paths, e.g., + // D -> B -> A, that will be used to illustrate the ambiguous + // conversions in the diagnostic. We only print one of the paths + // to each base class subobject. + std::string PathDisplayStr = getAmbiguousPathsDisplayString(Paths); + + Diag(Loc, AmbigiousBaseConvID) + << Derived << Base << PathDisplayStr << Range << Name; + return true; +} + +bool +Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, + SourceLocation Loc, SourceRange Range, + CXXCastPath *BasePath, + bool IgnoreAccess) { + return CheckDerivedToBaseConversion(Derived, Base, + IgnoreAccess ? 0 + : diag::err_upcast_to_inaccessible_base, + diag::err_ambiguous_derived_to_base_conv, + Loc, Range, DeclarationName(), + BasePath); +} + + +/// @brief Builds a string representing ambiguous paths from a +/// specific derived class to different subobjects of the same base +/// class. +/// +/// This function builds a string that can be used in error messages +/// to show the different paths that one can take through the +/// inheritance hierarchy to go from the derived class to different +/// subobjects of a base class. The result looks something like this: +/// @code +/// struct D -> struct B -> struct A +/// struct D -> struct C -> struct A +/// @endcode +std::string Sema::getAmbiguousPathsDisplayString(CXXBasePaths &Paths) { + std::string PathDisplayStr; + std::set DisplayedPaths; + for (CXXBasePaths::paths_iterator Path = Paths.begin(); + Path != Paths.end(); ++Path) { + if (DisplayedPaths.insert(Path->back().SubobjectNumber).second) { + // We haven't displayed a path to this particular base + // class subobject yet. + PathDisplayStr += "\n "; + PathDisplayStr += Context.getTypeDeclType(Paths.getOrigin()).getAsString(); + for (CXXBasePath::const_iterator Element = Path->begin(); + Element != Path->end(); ++Element) + PathDisplayStr += " -> " + Element->Base->getType().getAsString(); + } + } + + return PathDisplayStr; +} + +//===----------------------------------------------------------------------===// +// C++ class member Handling +//===----------------------------------------------------------------------===// + +/// ActOnAccessSpecifier - Parsed an access specifier followed by a colon. +bool Sema::ActOnAccessSpecifier(AccessSpecifier Access, + SourceLocation ASLoc, + SourceLocation ColonLoc, + AttributeList *Attrs) { + assert(Access != AS_none && "Invalid kind for syntactic access specifier!"); + AccessSpecDecl *ASDecl = AccessSpecDecl::Create(Context, Access, CurContext, + ASLoc, ColonLoc); + CurContext->addHiddenDecl(ASDecl); + return ProcessAccessDeclAttributeList(ASDecl, Attrs); +} + +/// CheckOverrideControl - Check C++0x override control semantics. +void Sema::CheckOverrideControl(const Decl *D) { + const CXXMethodDecl *MD = dyn_cast(D); + if (!MD || !MD->isVirtual()) + return; + + if (MD->isDependentContext()) + return; + + // C++0x [class.virtual]p3: + // If a virtual function is marked with the virt-specifier override and does + // not override a member function of a base class, + // the program is ill-formed. + bool HasOverriddenMethods = + MD->begin_overridden_methods() != MD->end_overridden_methods(); + if (MD->hasAttr() && !HasOverriddenMethods) { + Diag(MD->getLocation(), + diag::err_function_marked_override_not_overriding) + << MD->getDeclName(); + return; + } +} + +/// CheckIfOverriddenFunctionIsMarkedFinal - Checks whether a virtual member +/// function overrides a virtual member function marked 'final', according to +/// C++0x [class.virtual]p3. +bool Sema::CheckIfOverriddenFunctionIsMarkedFinal(const CXXMethodDecl *New, + const CXXMethodDecl *Old) { + if (!Old->hasAttr()) + return false; + + Diag(New->getLocation(), diag::err_final_function_overridden) + << New->getDeclName(); + Diag(Old->getLocation(), diag::note_overridden_virtual_function); + return true; +} + +/// 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, 'InitExpr' specifies the initializer if +/// one has been parsed, and 'HasDeferredInit' is true if an initializer is +/// present but parsing it has been deferred. +Decl * +Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, + MultiTemplateParamsArg TemplateParameterLists, + Expr *BW, const VirtSpecifiers &VS, + bool HasDeferredInit) { + const DeclSpec &DS = D.getDeclSpec(); + DeclarationNameInfo NameInfo = GetNameForDeclarator(D); + DeclarationName Name = NameInfo.getName(); + SourceLocation Loc = NameInfo.getLoc(); + + // For anonymous bitfields, the location should point to the type. + if (Loc.isInvalid()) + Loc = D.getLocStart(); + + Expr *BitWidth = static_cast(BW); + + assert(isa(CurContext)); + assert(!DS.isFriendSpecified()); + + bool isFunc = D.isDeclarationOfFunction(); + + // C++ 9.2p6: A member shall not be declared to have automatic storage + // duration (auto, register) or with the extern storage-class-specifier. + // C++ 7.1.1p8: The mutable specifier can be applied only to names of class + // data members and cannot be applied to names declared const or static, + // and cannot be applied to reference members. + switch (DS.getStorageClassSpec()) { + case DeclSpec::SCS_unspecified: + case DeclSpec::SCS_typedef: + case DeclSpec::SCS_static: + // FALL THROUGH. + break; + case DeclSpec::SCS_mutable: + if (isFunc) { + if (DS.getStorageClassSpecLoc().isValid()) + Diag(DS.getStorageClassSpecLoc(), diag::err_mutable_function); + else + Diag(DS.getThreadSpecLoc(), diag::err_mutable_function); + + // FIXME: It would be nicer if the keyword was ignored only for this + // declarator. Otherwise we could get follow-up errors. + D.getMutableDeclSpec().ClearStorageClassSpecs(); + } + break; + default: + if (DS.getStorageClassSpecLoc().isValid()) + Diag(DS.getStorageClassSpecLoc(), + diag::err_storageclass_invalid_for_member); + else + Diag(DS.getThreadSpecLoc(), diag::err_storageclass_invalid_for_member); + D.getMutableDeclSpec().ClearStorageClassSpecs(); + } + + bool isInstField = ((DS.getStorageClassSpec() == DeclSpec::SCS_unspecified || + DS.getStorageClassSpec() == DeclSpec::SCS_mutable) && + !isFunc); + + Decl *Member; + if (isInstField) { + CXXScopeSpec &SS = D.getCXXScopeSpec(); + + // Data members must have identifiers for names. + if (Name.getNameKind() != DeclarationName::Identifier) { + Diag(Loc, diag::err_bad_variable_name) + << Name; + return 0; + } + + IdentifierInfo *II = Name.getAsIdentifierInfo(); + + // Member field could not be with "template" keyword. + // So TemplateParameterLists should be empty in this case. + if (TemplateParameterLists.size()) { + TemplateParameterList* TemplateParams = TemplateParameterLists.get()[0]; + if (TemplateParams->size()) { + // There is no such thing as a member field template. + Diag(D.getIdentifierLoc(), diag::err_template_member) + << II + << SourceRange(TemplateParams->getTemplateLoc(), + TemplateParams->getRAngleLoc()); + } else { + // There is an extraneous 'template<>' for this member. + Diag(TemplateParams->getTemplateLoc(), + diag::err_template_member_noparams) + << II + << SourceRange(TemplateParams->getTemplateLoc(), + TemplateParams->getRAngleLoc()); + } + return 0; + } + + if (SS.isSet() && !SS.isInvalid()) { + // The user provided a superfluous scope specifier inside a class + // definition: + // + // class X { + // int X::member; + // }; + if (DeclContext *DC = computeDeclContext(SS, false)) + diagnoseQualifiedDeclaration(SS, DC, Name, D.getIdentifierLoc()); + else + Diag(D.getIdentifierLoc(), diag::err_member_qualification) + << Name << SS.getRange(); + + SS.clear(); + } + + Member = HandleField(S, cast(CurContext), Loc, D, BitWidth, + HasDeferredInit, AS); + assert(Member && "HandleField never returns null"); + } else { + assert(!HasDeferredInit); + + Member = HandleDeclarator(S, D, move(TemplateParameterLists)); + if (!Member) { + return 0; + } + + // Non-instance-fields can't have a bitfield. + if (BitWidth) { + if (Member->isInvalidDecl()) { + // don't emit another diagnostic. + } else if (isa(Member)) { + // C++ 9.6p3: A bit-field shall not be a static member. + // "static member 'A' cannot be a bit-field" + Diag(Loc, diag::err_static_not_bitfield) + << Name << BitWidth->getSourceRange(); + } else if (isa(Member)) { + // "typedef member 'x' cannot be a bit-field" + Diag(Loc, diag::err_typedef_not_bitfield) + << Name << BitWidth->getSourceRange(); + } else { + // A function typedef ("typedef int f(); f a;"). + // C++ 9.6p3: A bit-field shall have integral or enumeration type. + Diag(Loc, diag::err_not_integral_type_bitfield) + << Name << cast(Member)->getType() + << BitWidth->getSourceRange(); + } + + BitWidth = 0; + Member->setInvalidDecl(); + } + + Member->setAccess(AS); + + // If we have declared a member function template, set the access of the + // templated declaration as well. + if (FunctionTemplateDecl *FunTmpl = dyn_cast(Member)) + FunTmpl->getTemplatedDecl()->setAccess(AS); + } + + if (VS.isOverrideSpecified()) { + CXXMethodDecl *MD = dyn_cast(Member); + if (!MD || !MD->isVirtual()) { + Diag(Member->getLocStart(), + diag::override_keyword_only_allowed_on_virtual_member_functions) + << "override" << FixItHint::CreateRemoval(VS.getOverrideLoc()); + } else + MD->addAttr(new (Context) OverrideAttr(VS.getOverrideLoc(), Context)); + } + if (VS.isFinalSpecified()) { + CXXMethodDecl *MD = dyn_cast(Member); + if (!MD || !MD->isVirtual()) { + Diag(Member->getLocStart(), + diag::override_keyword_only_allowed_on_virtual_member_functions) + << "final" << FixItHint::CreateRemoval(VS.getFinalLoc()); + } else + MD->addAttr(new (Context) FinalAttr(VS.getFinalLoc(), Context)); + } + + if (VS.getLastLocation().isValid()) { + // Update the end location of a method that has a virt-specifiers. + if (CXXMethodDecl *MD = dyn_cast_or_null(Member)) + MD->setRangeEnd(VS.getLastLocation()); + } + + CheckOverrideControl(Member); + + assert((Name || isInstField) && "No identifier for non-field ?"); + + if (isInstField) + FieldCollector->Add(cast(Member)); + return Member; +} + +/// ActOnCXXInClassMemberInitializer - This is invoked after parsing an +/// in-class initializer for a non-static C++ class member, and after +/// instantiating an in-class initializer in a class template. Such actions +/// are deferred until the class is complete. +void +Sema::ActOnCXXInClassMemberInitializer(Decl *D, SourceLocation EqualLoc, + Expr *InitExpr) { + FieldDecl *FD = cast(D); + + if (!InitExpr) { + FD->setInvalidDecl(); + FD->removeInClassInitializer(); + return; + } + + if (DiagnoseUnexpandedParameterPack(InitExpr, UPPC_Initializer)) { + FD->setInvalidDecl(); + FD->removeInClassInitializer(); + return; + } + + ExprResult Init = InitExpr; + if (!FD->getType()->isDependentType() && !InitExpr->isTypeDependent()) { + if (isa(InitExpr) && isStdInitializerList(FD->getType(), 0)) { + Diag(FD->getLocation(), diag::warn_dangling_std_initializer_list) + << /*at end of ctor*/1 << InitExpr->getSourceRange(); + } + Expr **Inits = &InitExpr; + unsigned NumInits = 1; + InitializedEntity Entity = InitializedEntity::InitializeMember(FD); + InitializationKind Kind = EqualLoc.isInvalid() + ? InitializationKind::CreateDirectList(InitExpr->getLocStart()) + : InitializationKind::CreateCopy(InitExpr->getLocStart(), EqualLoc); + InitializationSequence Seq(*this, Entity, Kind, Inits, NumInits); + Init = Seq.Perform(*this, Entity, Kind, MultiExprArg(Inits, NumInits)); + if (Init.isInvalid()) { + FD->setInvalidDecl(); + return; + } + + CheckImplicitConversions(Init.get(), EqualLoc); + } + + // C++0x [class.base.init]p7: + // The initialization of each base and member constitutes a + // full-expression. + Init = MaybeCreateExprWithCleanups(Init); + if (Init.isInvalid()) { + FD->setInvalidDecl(); + return; + } + + InitExpr = Init.release(); + + FD->setInClassInitializer(InitExpr); +} + +/// \brief Find the direct and/or virtual base specifiers that +/// correspond to the given base type, for use in base initialization +/// within a constructor. +static bool FindBaseInitializer(Sema &SemaRef, + CXXRecordDecl *ClassDecl, + QualType BaseType, + const CXXBaseSpecifier *&DirectBaseSpec, + const CXXBaseSpecifier *&VirtualBaseSpec) { + // First, check for a direct base class. + DirectBaseSpec = 0; + for (CXXRecordDecl::base_class_const_iterator Base + = ClassDecl->bases_begin(); + Base != ClassDecl->bases_end(); ++Base) { + if (SemaRef.Context.hasSameUnqualifiedType(BaseType, Base->getType())) { + // We found a direct base of this type. That's what we're + // initializing. + DirectBaseSpec = &*Base; + break; + } + } + + // Check for a virtual base class. + // FIXME: We might be able to short-circuit this if we know in advance that + // there are no virtual bases. + VirtualBaseSpec = 0; + if (!DirectBaseSpec || !DirectBaseSpec->isVirtual()) { + // We haven't found a base yet; search the class hierarchy for a + // virtual base class. + CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, + /*DetectVirtual=*/false); + if (SemaRef.IsDerivedFrom(SemaRef.Context.getTypeDeclType(ClassDecl), + BaseType, Paths)) { + for (CXXBasePaths::paths_iterator Path = Paths.begin(); + Path != Paths.end(); ++Path) { + if (Path->back().Base->isVirtual()) { + VirtualBaseSpec = Path->back().Base; + break; + } + } + } + } + + return DirectBaseSpec || VirtualBaseSpec; +} + +/// \brief Handle a C++ member initializer using braced-init-list syntax. +MemInitResult +Sema::ActOnMemInitializer(Decl *ConstructorD, + Scope *S, + CXXScopeSpec &SS, + IdentifierInfo *MemberOrBase, + ParsedType TemplateTypeTy, + const DeclSpec &DS, + SourceLocation IdLoc, + Expr *InitList, + SourceLocation EllipsisLoc) { + return BuildMemInitializer(ConstructorD, S, SS, MemberOrBase, TemplateTypeTy, + DS, IdLoc, InitList, + EllipsisLoc); +} + +/// \brief Handle a C++ member initializer using parentheses syntax. +MemInitResult +Sema::ActOnMemInitializer(Decl *ConstructorD, + Scope *S, + CXXScopeSpec &SS, + IdentifierInfo *MemberOrBase, + ParsedType TemplateTypeTy, + const DeclSpec &DS, + SourceLocation IdLoc, + SourceLocation LParenLoc, + Expr **Args, unsigned NumArgs, + SourceLocation RParenLoc, + SourceLocation EllipsisLoc) { + Expr *List = new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs, + RParenLoc); + return BuildMemInitializer(ConstructorD, S, SS, MemberOrBase, TemplateTypeTy, + DS, IdLoc, List, EllipsisLoc); +} + +namespace { + +// Callback to only accept typo corrections that can be a valid C++ member +// intializer: either a non-static field member or a base class. +class MemInitializerValidatorCCC : public CorrectionCandidateCallback { + public: + explicit MemInitializerValidatorCCC(CXXRecordDecl *ClassDecl) + : ClassDecl(ClassDecl) {} + + virtual bool ValidateCandidate(const TypoCorrection &candidate) { + if (NamedDecl *ND = candidate.getCorrectionDecl()) { + if (FieldDecl *Member = dyn_cast(ND)) + return Member->getDeclContext()->getRedeclContext()->Equals(ClassDecl); + else + return isa(ND); + } + return false; + } + + private: + CXXRecordDecl *ClassDecl; +}; + +} + +/// \brief Handle a C++ member initializer. +MemInitResult +Sema::BuildMemInitializer(Decl *ConstructorD, + Scope *S, + CXXScopeSpec &SS, + IdentifierInfo *MemberOrBase, + ParsedType TemplateTypeTy, + const DeclSpec &DS, + SourceLocation IdLoc, + Expr *Init, + SourceLocation EllipsisLoc) { + if (!ConstructorD) + return true; + + AdjustDeclIfTemplate(ConstructorD); + + CXXConstructorDecl *Constructor + = 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 + // have more member initializers coming; we'll diagnose it just + // once in ActOnMemInitializers. + return true; + } + + CXXRecordDecl *ClassDecl = Constructor->getParent(); + + // C++ [class.base.init]p2: + // Names in a mem-initializer-id are looked up in the scope of the + // constructor's class and, if not found in that scope, are looked + // up in the scope containing the constructor's definition. + // [Note: if the constructor's class contains a member with the + // same name as a direct or virtual base class of the class, a + // mem-initializer-id naming the member or base class and composed + // of a single identifier refers to the class member. A + // mem-initializer-id for the hidden base class may be specified + // using a qualified name. ] + if (!SS.getScopeRep() && !TemplateTypeTy) { + // Look for a member, first. + DeclContext::lookup_result Result + = ClassDecl->lookup(MemberOrBase); + if (Result.first != Result.second) { + ValueDecl *Member; + if ((Member = dyn_cast(*Result.first)) || + (Member = dyn_cast(*Result.first))) { + if (EllipsisLoc.isValid()) + Diag(EllipsisLoc, diag::err_pack_expansion_member_init) + << MemberOrBase + << SourceRange(IdLoc, Init->getSourceRange().getEnd()); + + return BuildMemberInitializer(Member, Init, IdLoc); + } + } + } + // It didn't name a member, so see if it names a class. + QualType BaseType; + TypeSourceInfo *TInfo = 0; + + if (TemplateTypeTy) { + BaseType = GetTypeFromParser(TemplateTypeTy, &TInfo); + } else if (DS.getTypeSpecType() == TST_decltype) { + BaseType = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc()); + } else { + LookupResult R(*this, MemberOrBase, IdLoc, LookupOrdinaryName); + LookupParsedName(R, S, &SS); + + TypeDecl *TyD = R.getAsSingle(); + if (!TyD) { + if (R.isAmbiguous()) return true; + + // We don't want access-control diagnostics here. + R.suppressDiagnostics(); + + if (SS.isSet() && isDependentScopeSpecifier(SS)) { + bool NotUnknownSpecialization = false; + DeclContext *DC = computeDeclContext(SS, false); + if (CXXRecordDecl *Record = dyn_cast_or_null(DC)) + NotUnknownSpecialization = !Record->hasAnyDependentBases(); + + if (!NotUnknownSpecialization) { + // When the scope specifier can refer to a member of an unknown + // specialization, we take it as a type name. + BaseType = CheckTypenameType(ETK_None, SourceLocation(), + SS.getWithLocInContext(Context), + *MemberOrBase, IdLoc); + if (BaseType.isNull()) + return true; + + R.clear(); + R.setLookupName(MemberOrBase); + } + } + + // If no results were found, try to correct typos. + TypoCorrection Corr; + MemInitializerValidatorCCC Validator(ClassDecl); + if (R.empty() && BaseType.isNull() && + (Corr = CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S, &SS, + Validator, ClassDecl))) { + std::string CorrectedStr(Corr.getAsString(getLangOpts())); + std::string CorrectedQuotedStr(Corr.getQuoted(getLangOpts())); + if (FieldDecl *Member = Corr.getCorrectionDeclAs()) { + // We have found a non-static data member with a similar + // name to what was typed; complain and initialize that + // member. + Diag(R.getNameLoc(), diag::err_mem_init_not_member_or_class_suggest) + << MemberOrBase << true << CorrectedQuotedStr + << FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr); + Diag(Member->getLocation(), diag::note_previous_decl) + << CorrectedQuotedStr; + + return BuildMemberInitializer(Member, Init, IdLoc); + } else if (TypeDecl *Type = Corr.getCorrectionDeclAs()) { + const CXXBaseSpecifier *DirectBaseSpec; + const CXXBaseSpecifier *VirtualBaseSpec; + if (FindBaseInitializer(*this, ClassDecl, + Context.getTypeDeclType(Type), + DirectBaseSpec, VirtualBaseSpec)) { + // We have found a direct or virtual base class with a + // similar name to what was typed; complain and initialize + // that base class. + Diag(R.getNameLoc(), diag::err_mem_init_not_member_or_class_suggest) + << MemberOrBase << false << CorrectedQuotedStr + << FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr); + + const CXXBaseSpecifier *BaseSpec = DirectBaseSpec? DirectBaseSpec + : VirtualBaseSpec; + Diag(BaseSpec->getLocStart(), + diag::note_base_class_specified_here) + << BaseSpec->getType() + << BaseSpec->getSourceRange(); + + TyD = Type; + } + } + } + + if (!TyD && BaseType.isNull()) { + Diag(IdLoc, diag::err_mem_init_not_member_or_class) + << MemberOrBase << SourceRange(IdLoc,Init->getSourceRange().getEnd()); + return true; + } + } + + if (BaseType.isNull()) { + BaseType = Context.getTypeDeclType(TyD); + if (SS.isSet()) { + NestedNameSpecifier *Qualifier = + static_cast(SS.getScopeRep()); + + // FIXME: preserve source range information + BaseType = Context.getElaboratedType(ETK_None, Qualifier, BaseType); + } + } + } + + if (!TInfo) + TInfo = Context.getTrivialTypeSourceInfo(BaseType, IdLoc); + + return BuildBaseInitializer(BaseType, TInfo, Init, ClassDecl, EllipsisLoc); +} + +/// Checks a member initializer expression for cases where reference (or +/// pointer) members are bound to by-value parameters (or their addresses). +static void CheckForDanglingReferenceOrPointer(Sema &S, ValueDecl *Member, + Expr *Init, + SourceLocation IdLoc) { + QualType MemberTy = Member->getType(); + + // We only handle pointers and references currently. + // FIXME: Would this be relevant for ObjC object pointers? Or block pointers? + if (!MemberTy->isReferenceType() && !MemberTy->isPointerType()) + return; + + const bool IsPointer = MemberTy->isPointerType(); + if (IsPointer) { + if (const UnaryOperator *Op + = dyn_cast(Init->IgnoreParenImpCasts())) { + // The only case we're worried about with pointers requires taking the + // address. + if (Op->getOpcode() != UO_AddrOf) + return; + + Init = Op->getSubExpr(); + } else { + // We only handle address-of expression initializers for pointers. + return; + } + } + + if (isa(Init->IgnoreParens())) { + // Taking the address of a temporary will be diagnosed as a hard error. + if (IsPointer) + return; + + S.Diag(Init->getExprLoc(), diag::warn_bind_ref_member_to_temporary) + << Member << Init->getSourceRange(); + } else if (const DeclRefExpr *DRE + = dyn_cast(Init->IgnoreParens())) { + // We only warn when referring to a non-reference parameter declaration. + const ParmVarDecl *Parameter = dyn_cast(DRE->getDecl()); + if (!Parameter || Parameter->getType()->isReferenceType()) + return; + + S.Diag(Init->getExprLoc(), + IsPointer ? diag::warn_init_ptr_member_to_parameter_addr + : diag::warn_bind_ref_member_to_parameter) + << Member << Parameter << Init->getSourceRange(); + } else { + // Other initializers are fine. + return; + } + + S.Diag(Member->getLocation(), diag::note_ref_or_ptr_member_declared_here) + << (unsigned)IsPointer; +} + +/// Checks an initializer expression for use of uninitialized fields, such as +/// containing the field that is being initialized. Returns true if there is an +/// uninitialized field was used an updates the SourceLocation parameter; false +/// otherwise. +static bool InitExprContainsUninitializedFields(const Stmt *S, + const ValueDecl *LhsField, + SourceLocation *L) { + assert(isa(LhsField) || isa(LhsField)); + + if (isa(S)) { + // Do not descend into function calls or constructors, as the use + // of an uninitialized field may be valid. One would have to inspect + // the contents of the function/ctor to determine if it is safe or not. + // i.e. Pass-by-value is never safe, but pass-by-reference and pointers + // may be safe, depending on what the function/ctor does. + return false; + } + if (const MemberExpr *ME = dyn_cast(S)) { + const NamedDecl *RhsField = ME->getMemberDecl(); + + if (const VarDecl *VD = dyn_cast(RhsField)) { + // The member expression points to a static data member. + assert(VD->isStaticDataMember() && + "Member points to non-static data member!"); + (void)VD; + return false; + } + + if (isa(RhsField)) { + // The member expression points to an enum. + return false; + } + + if (RhsField == LhsField) { + // Initializing a field with itself. Throw a warning. + // But wait; there are exceptions! + // Exception #1: The field may not belong to this record. + // e.g. Foo(const Foo& rhs) : A(rhs.A) {} + const Expr *base = ME->getBase(); + if (base != NULL && !isa(base->IgnoreParenCasts())) { + // Even though the field matches, it does not belong to this record. + return false; + } + // None of the exceptions triggered; return true to indicate an + // uninitialized field was used. + *L = ME->getMemberLoc(); + return true; + } + } else if (isa(S)) { + // sizeof/alignof doesn't reference contents, do not warn. + return false; + } else if (const UnaryOperator *UOE = dyn_cast(S)) { + // address-of doesn't reference contents (the pointer may be dereferenced + // in the same expression but it would be rare; and weird). + if (UOE->getOpcode() == UO_AddrOf) + return false; + } + for (Stmt::const_child_range it = S->children(); it; ++it) { + if (!*it) { + // An expression such as 'member(arg ?: "")' may trigger this. + continue; + } + if (InitExprContainsUninitializedFields(*it, LhsField, L)) + return true; + } + return false; +} + +MemInitResult +Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init, + SourceLocation IdLoc) { + FieldDecl *DirectMember = dyn_cast(Member); + IndirectFieldDecl *IndirectMember = dyn_cast(Member); + assert((DirectMember || IndirectMember) && + "Member must be a FieldDecl or IndirectFieldDecl"); + + if (DiagnoseUnexpandedParameterPack(Init, UPPC_Initializer)) + return true; + + if (Member->isInvalidDecl()) + return true; + + // Diagnose value-uses of fields to initialize themselves, e.g. + // foo(foo) + // where foo is not also a parameter to the constructor. + // TODO: implement -Wuninitialized and fold this into that framework. + Expr **Args; + unsigned NumArgs; + if (ParenListExpr *ParenList = dyn_cast(Init)) { + Args = ParenList->getExprs(); + NumArgs = ParenList->getNumExprs(); + } else { + InitListExpr *InitList = cast(Init); + Args = InitList->getInits(); + NumArgs = InitList->getNumInits(); + } + for (unsigned i = 0; i < NumArgs; ++i) { + SourceLocation L; + if (InitExprContainsUninitializedFields(Args[i], Member, &L)) { + // FIXME: Return true in the case when other fields are used before being + // uninitialized. For example, let this field be the i'th field. When + // initializing the i'th field, throw a warning if any of the >= i'th + // fields are used, as they are not yet initialized. + // Right now we are only handling the case where the i'th field uses + // itself in its initializer. + Diag(L, diag::warn_field_is_uninit); + } + } + + SourceRange InitRange = Init->getSourceRange(); + + if (Member->getType()->isDependentType() || Init->isTypeDependent()) { + // Can't check initialization for a member of dependent type or when + // any of the arguments are type-dependent expressions. + DiscardCleanupsInEvaluationContext(); + } else { + bool InitList = false; + if (isa(Init)) { + InitList = true; + Args = &Init; + NumArgs = 1; + + if (isStdInitializerList(Member->getType(), 0)) { + Diag(IdLoc, diag::warn_dangling_std_initializer_list) + << /*at end of ctor*/1 << InitRange; + } + } + + // Initialize the member. + InitializedEntity MemberEntity = + DirectMember ? InitializedEntity::InitializeMember(DirectMember, 0) + : InitializedEntity::InitializeMember(IndirectMember, 0); + InitializationKind Kind = + InitList ? InitializationKind::CreateDirectList(IdLoc) + : InitializationKind::CreateDirect(IdLoc, InitRange.getBegin(), + InitRange.getEnd()); + + InitializationSequence InitSeq(*this, MemberEntity, Kind, Args, NumArgs); + ExprResult MemberInit = InitSeq.Perform(*this, MemberEntity, Kind, + MultiExprArg(*this, Args, NumArgs), + 0); + if (MemberInit.isInvalid()) + return true; + + CheckImplicitConversions(MemberInit.get(), + InitRange.getBegin()); + + // C++0x [class.base.init]p7: + // The initialization of each base and member constitutes a + // full-expression. + MemberInit = MaybeCreateExprWithCleanups(MemberInit); + if (MemberInit.isInvalid()) + return true; + + // If we are in a dependent context, template instantiation will + // perform this type-checking again. Just save the arguments that we + // received. + // FIXME: This isn't quite ideal, since our ASTs don't capture all + // of the information that we have about the member + // initializer. However, deconstructing the ASTs is a dicey process, + // and this approach is far more likely to get the corner cases right. + if (CurContext->isDependentContext()) { + // The existing Init will do fine. + } else { + Init = MemberInit.get(); + CheckForDanglingReferenceOrPointer(*this, Member, Init, IdLoc); + } + } + + if (DirectMember) { + return new (Context) CXXCtorInitializer(Context, DirectMember, IdLoc, + InitRange.getBegin(), Init, + InitRange.getEnd()); + } else { + return new (Context) CXXCtorInitializer(Context, IndirectMember, IdLoc, + InitRange.getBegin(), Init, + InitRange.getEnd()); + } +} + +MemInitResult +Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init, + CXXRecordDecl *ClassDecl) { + SourceLocation NameLoc = TInfo->getTypeLoc().getLocalSourceRange().getBegin(); + if (!LangOpts.CPlusPlus0x) + return Diag(NameLoc, diag::err_delegating_ctor) + << TInfo->getTypeLoc().getLocalSourceRange(); + Diag(NameLoc, diag::warn_cxx98_compat_delegating_ctor); + + bool InitList = true; + Expr **Args = &Init; + unsigned NumArgs = 1; + if (ParenListExpr *ParenList = dyn_cast(Init)) { + InitList = false; + Args = ParenList->getExprs(); + NumArgs = ParenList->getNumExprs(); + } + + SourceRange InitRange = Init->getSourceRange(); + // Initialize the object. + InitializedEntity DelegationEntity = InitializedEntity::InitializeDelegation( + QualType(ClassDecl->getTypeForDecl(), 0)); + InitializationKind Kind = + InitList ? InitializationKind::CreateDirectList(NameLoc) + : InitializationKind::CreateDirect(NameLoc, InitRange.getBegin(), + InitRange.getEnd()); + InitializationSequence InitSeq(*this, DelegationEntity, Kind, Args, NumArgs); + ExprResult DelegationInit = InitSeq.Perform(*this, DelegationEntity, Kind, + MultiExprArg(*this, Args,NumArgs), + 0); + if (DelegationInit.isInvalid()) + return true; + + assert(cast(DelegationInit.get())->getConstructor() && + "Delegating constructor with no target?"); + + CheckImplicitConversions(DelegationInit.get(), InitRange.getBegin()); + + // C++0x [class.base.init]p7: + // The initialization of each base and member constitutes a + // full-expression. + DelegationInit = MaybeCreateExprWithCleanups(DelegationInit); + if (DelegationInit.isInvalid()) + return true; + + return new (Context) CXXCtorInitializer(Context, TInfo, InitRange.getBegin(), + DelegationInit.takeAs(), + InitRange.getEnd()); +} + +MemInitResult +Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, + Expr *Init, CXXRecordDecl *ClassDecl, + SourceLocation EllipsisLoc) { + SourceLocation BaseLoc + = BaseTInfo->getTypeLoc().getLocalSourceRange().getBegin(); + + if (!BaseType->isDependentType() && !BaseType->isRecordType()) + return Diag(BaseLoc, diag::err_base_init_does_not_name_class) + << BaseType << BaseTInfo->getTypeLoc().getLocalSourceRange(); + + // C++ [class.base.init]p2: + // [...] Unless the mem-initializer-id names a nonstatic data + // member of the constructor's class or a direct or virtual base + // of that class, the mem-initializer is ill-formed. A + // mem-initializer-list can initialize a base class using any + // name that denotes that base class type. + bool Dependent = BaseType->isDependentType() || Init->isTypeDependent(); + + SourceRange InitRange = Init->getSourceRange(); + if (EllipsisLoc.isValid()) { + // This is a pack expansion. + if (!BaseType->containsUnexpandedParameterPack()) { + Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) + << SourceRange(BaseLoc, InitRange.getEnd()); + + EllipsisLoc = SourceLocation(); + } + } else { + // Check for any unexpanded parameter packs. + if (DiagnoseUnexpandedParameterPack(BaseLoc, BaseTInfo, UPPC_Initializer)) + return true; + + if (DiagnoseUnexpandedParameterPack(Init, UPPC_Initializer)) + return true; + } + + // Check for direct and virtual base classes. + const CXXBaseSpecifier *DirectBaseSpec = 0; + const CXXBaseSpecifier *VirtualBaseSpec = 0; + if (!Dependent) { + if (Context.hasSameUnqualifiedType(QualType(ClassDecl->getTypeForDecl(),0), + BaseType)) + return BuildDelegatingInitializer(BaseTInfo, Init, ClassDecl); + + FindBaseInitializer(*this, ClassDecl, BaseType, DirectBaseSpec, + VirtualBaseSpec); + + // C++ [base.class.init]p2: + // Unless the mem-initializer-id names a nonstatic data member of the + // constructor's class or a direct or virtual base of that class, the + // mem-initializer is ill-formed. + if (!DirectBaseSpec && !VirtualBaseSpec) { + // If the class has any dependent bases, then it's possible that + // one of those types will resolve to the same type as + // BaseType. Therefore, just treat this as a dependent base + // class initialization. FIXME: Should we try to check the + // initialization anyway? It seems odd. + if (ClassDecl->hasAnyDependentBases()) + Dependent = true; + else + return Diag(BaseLoc, diag::err_not_direct_base_or_virtual) + << BaseType << Context.getTypeDeclType(ClassDecl) + << BaseTInfo->getTypeLoc().getLocalSourceRange(); + } + } + + if (Dependent) { + DiscardCleanupsInEvaluationContext(); + + return new (Context) CXXCtorInitializer(Context, BaseTInfo, + /*IsVirtual=*/false, + InitRange.getBegin(), Init, + InitRange.getEnd(), EllipsisLoc); + } + + // C++ [base.class.init]p2: + // If a mem-initializer-id is ambiguous because it designates both + // a direct non-virtual base class and an inherited virtual base + // class, the mem-initializer is ill-formed. + if (DirectBaseSpec && VirtualBaseSpec) + return Diag(BaseLoc, diag::err_base_init_direct_and_virtual) + << BaseType << BaseTInfo->getTypeLoc().getLocalSourceRange(); + + CXXBaseSpecifier *BaseSpec = const_cast(DirectBaseSpec); + if (!BaseSpec) + BaseSpec = const_cast(VirtualBaseSpec); + + // Initialize the base. + bool InitList = true; + Expr **Args = &Init; + unsigned NumArgs = 1; + if (ParenListExpr *ParenList = dyn_cast(Init)) { + InitList = false; + Args = ParenList->getExprs(); + NumArgs = ParenList->getNumExprs(); + } + + InitializedEntity BaseEntity = + InitializedEntity::InitializeBase(Context, BaseSpec, VirtualBaseSpec); + InitializationKind Kind = + InitList ? InitializationKind::CreateDirectList(BaseLoc) + : InitializationKind::CreateDirect(BaseLoc, InitRange.getBegin(), + InitRange.getEnd()); + InitializationSequence InitSeq(*this, BaseEntity, Kind, Args, NumArgs); + ExprResult BaseInit = InitSeq.Perform(*this, BaseEntity, Kind, + MultiExprArg(*this, Args, NumArgs), + 0); + if (BaseInit.isInvalid()) + return true; + + CheckImplicitConversions(BaseInit.get(), InitRange.getBegin()); + + // C++0x [class.base.init]p7: + // The initialization of each base and member constitutes a + // full-expression. + BaseInit = MaybeCreateExprWithCleanups(BaseInit); + if (BaseInit.isInvalid()) + return true; + + // If we are in a dependent context, template instantiation will + // perform this type-checking again. Just save the arguments that we + // received in a ParenListExpr. + // FIXME: This isn't quite ideal, since our ASTs don't capture all + // of the information that we have about the base + // initializer. However, deconstructing the ASTs is a dicey process, + // and this approach is far more likely to get the corner cases right. + if (CurContext->isDependentContext()) + BaseInit = Owned(Init); + + return new (Context) CXXCtorInitializer(Context, BaseTInfo, + BaseSpec->isVirtual(), + InitRange.getBegin(), + BaseInit.takeAs(), + InitRange.getEnd(), EllipsisLoc); +} + +// Create a static_cast\(expr). +static Expr *CastForMoving(Sema &SemaRef, Expr *E) { + QualType ExprType = E->getType(); + QualType TargetType = SemaRef.Context.getRValueReferenceType(ExprType); + SourceLocation ExprLoc = E->getLocStart(); + TypeSourceInfo *TargetLoc = SemaRef.Context.getTrivialTypeSourceInfo( + TargetType, ExprLoc); + + return SemaRef.BuildCXXNamedCast(ExprLoc, tok::kw_static_cast, TargetLoc, E, + SourceRange(ExprLoc, ExprLoc), + E->getSourceRange()).take(); +} + +/// ImplicitInitializerKind - How an implicit base or member initializer should +/// initialize its base or member. +enum ImplicitInitializerKind { + IIK_Default, + IIK_Copy, + IIK_Move +}; + +static bool +BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, + ImplicitInitializerKind ImplicitInitKind, + CXXBaseSpecifier *BaseSpec, + bool IsInheritedVirtualBase, + CXXCtorInitializer *&CXXBaseInit) { + InitializedEntity InitEntity + = InitializedEntity::InitializeBase(SemaRef.Context, BaseSpec, + IsInheritedVirtualBase); + + ExprResult BaseInit; + + switch (ImplicitInitKind) { + case IIK_Default: { + InitializationKind InitKind + = InitializationKind::CreateDefault(Constructor->getLocation()); + InitializationSequence InitSeq(SemaRef, InitEntity, InitKind, 0, 0); + BaseInit = InitSeq.Perform(SemaRef, InitEntity, InitKind, + MultiExprArg(SemaRef, 0, 0)); + break; + } + + case IIK_Move: + case IIK_Copy: { + bool Moving = ImplicitInitKind == IIK_Move; + ParmVarDecl *Param = Constructor->getParamDecl(0); + QualType ParamType = Param->getType().getNonReferenceType(); + + Expr *CopyCtorArg = + DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(), + SourceLocation(), Param, false, + Constructor->getLocation(), ParamType, + VK_LValue, 0); + + SemaRef.MarkDeclRefReferenced(cast(CopyCtorArg)); + + // Cast to the base class to avoid ambiguities. + QualType ArgTy = + SemaRef.Context.getQualifiedType(BaseSpec->getType().getUnqualifiedType(), + ParamType.getQualifiers()); + + if (Moving) { + CopyCtorArg = CastForMoving(SemaRef, CopyCtorArg); + } + + CXXCastPath BasePath; + BasePath.push_back(BaseSpec); + CopyCtorArg = SemaRef.ImpCastExprToType(CopyCtorArg, ArgTy, + CK_UncheckedDerivedToBase, + Moving ? VK_XValue : VK_LValue, + &BasePath).take(); + + InitializationKind InitKind + = InitializationKind::CreateDirect(Constructor->getLocation(), + SourceLocation(), SourceLocation()); + InitializationSequence InitSeq(SemaRef, InitEntity, InitKind, + &CopyCtorArg, 1); + BaseInit = InitSeq.Perform(SemaRef, InitEntity, InitKind, + MultiExprArg(&CopyCtorArg, 1)); + break; + } + } + + BaseInit = SemaRef.MaybeCreateExprWithCleanups(BaseInit); + if (BaseInit.isInvalid()) + return true; + + CXXBaseInit = + new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context, + SemaRef.Context.getTrivialTypeSourceInfo(BaseSpec->getType(), + SourceLocation()), + BaseSpec->isVirtual(), + SourceLocation(), + BaseInit.takeAs(), + SourceLocation(), + SourceLocation()); + + return false; +} + +static bool RefersToRValueRef(Expr *MemRef) { + ValueDecl *Referenced = cast(MemRef)->getMemberDecl(); + return Referenced->getType()->isRValueReferenceType(); +} + +static bool +BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, + ImplicitInitializerKind ImplicitInitKind, + FieldDecl *Field, IndirectFieldDecl *Indirect, + CXXCtorInitializer *&CXXMemberInit) { + if (Field->isInvalidDecl()) + return true; + + SourceLocation Loc = Constructor->getLocation(); + + if (ImplicitInitKind == IIK_Copy || ImplicitInitKind == IIK_Move) { + bool Moving = ImplicitInitKind == IIK_Move; + ParmVarDecl *Param = Constructor->getParamDecl(0); + QualType ParamType = Param->getType().getNonReferenceType(); + + // Suppress copying zero-width bitfields. + if (Field->isBitField() && Field->getBitWidthValue(SemaRef.Context) == 0) + return false; + + Expr *MemberExprBase = + DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(), + SourceLocation(), Param, false, + Loc, ParamType, VK_LValue, 0); + + SemaRef.MarkDeclRefReferenced(cast(MemberExprBase)); + + if (Moving) { + MemberExprBase = CastForMoving(SemaRef, MemberExprBase); + } + + // Build a reference to this field within the parameter. + CXXScopeSpec SS; + LookupResult MemberLookup(SemaRef, Field->getDeclName(), Loc, + Sema::LookupMemberName); + MemberLookup.addDecl(Indirect ? cast(Indirect) + : cast(Field), AS_public); + MemberLookup.resolveKind(); + ExprResult CtorArg + = SemaRef.BuildMemberReferenceExpr(MemberExprBase, + ParamType, Loc, + /*IsArrow=*/false, + SS, + /*TemplateKWLoc=*/SourceLocation(), + /*FirstQualifierInScope=*/0, + MemberLookup, + /*TemplateArgs=*/0); + if (CtorArg.isInvalid()) + return true; + + // C++11 [class.copy]p15: + // - if a member m has rvalue reference type T&&, it is direct-initialized + // with static_cast(x.m); + if (RefersToRValueRef(CtorArg.get())) { + CtorArg = CastForMoving(SemaRef, CtorArg.take()); + } + + // When the field we are copying is an array, create index variables for + // each dimension of the array. We use these index variables to subscript + // the source array, and other clients (e.g., CodeGen) will perform the + // necessary iteration with these index variables. + SmallVector IndexVariables; + QualType BaseType = Field->getType(); + QualType SizeType = SemaRef.Context.getSizeType(); + bool InitializingArray = false; + while (const ConstantArrayType *Array + = SemaRef.Context.getAsConstantArrayType(BaseType)) { + InitializingArray = true; + // Create the iteration variable for this array index. + IdentifierInfo *IterationVarName = 0; + { + SmallString<8> Str; + llvm::raw_svector_ostream OS(Str); + OS << "__i" << IndexVariables.size(); + IterationVarName = &SemaRef.Context.Idents.get(OS.str()); + } + VarDecl *IterationVar + = VarDecl::Create(SemaRef.Context, SemaRef.CurContext, Loc, Loc, + IterationVarName, SizeType, + SemaRef.Context.getTrivialTypeSourceInfo(SizeType, Loc), + SC_None, SC_None); + IndexVariables.push_back(IterationVar); + + // Create a reference to the iteration variable. + ExprResult IterationVarRef + = SemaRef.BuildDeclRefExpr(IterationVar, SizeType, VK_LValue, Loc); + assert(!IterationVarRef.isInvalid() && + "Reference to invented variable cannot fail!"); + IterationVarRef = SemaRef.DefaultLvalueConversion(IterationVarRef.take()); + assert(!IterationVarRef.isInvalid() && + "Conversion of invented variable cannot fail!"); + + // Subscript the array with this iteration variable. + CtorArg = SemaRef.CreateBuiltinArraySubscriptExpr(CtorArg.take(), Loc, + IterationVarRef.take(), + Loc); + if (CtorArg.isInvalid()) + return true; + + BaseType = Array->getElementType(); + } + + // The array subscript expression is an lvalue, which is wrong for moving. + if (Moving && InitializingArray) + CtorArg = CastForMoving(SemaRef, CtorArg.take()); + + // Construct the entity that we will be initializing. For an array, this + // will be first element in the array, which may require several levels + // of array-subscript entities. + SmallVector Entities; + Entities.reserve(1 + IndexVariables.size()); + if (Indirect) + Entities.push_back(InitializedEntity::InitializeMember(Indirect)); + else + Entities.push_back(InitializedEntity::InitializeMember(Field)); + for (unsigned I = 0, N = IndexVariables.size(); I != N; ++I) + Entities.push_back(InitializedEntity::InitializeElement(SemaRef.Context, + 0, + Entities.back())); + + // Direct-initialize to use the copy constructor. + InitializationKind InitKind = + InitializationKind::CreateDirect(Loc, SourceLocation(), SourceLocation()); + + Expr *CtorArgE = CtorArg.takeAs(); + InitializationSequence InitSeq(SemaRef, Entities.back(), InitKind, + &CtorArgE, 1); + + ExprResult MemberInit + = InitSeq.Perform(SemaRef, Entities.back(), InitKind, + MultiExprArg(&CtorArgE, 1)); + MemberInit = SemaRef.MaybeCreateExprWithCleanups(MemberInit); + if (MemberInit.isInvalid()) + return true; + + if (Indirect) { + assert(IndexVariables.size() == 0 && + "Indirect field improperly initialized"); + CXXMemberInit + = new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context, Indirect, + Loc, Loc, + MemberInit.takeAs(), + Loc); + } else + CXXMemberInit = CXXCtorInitializer::Create(SemaRef.Context, Field, Loc, + Loc, MemberInit.takeAs(), + Loc, + IndexVariables.data(), + IndexVariables.size()); + return false; + } + + assert(ImplicitInitKind == IIK_Default && "Unhandled implicit init kind!"); + + QualType FieldBaseElementType = + SemaRef.Context.getBaseElementType(Field->getType()); + + if (FieldBaseElementType->isRecordType()) { + InitializedEntity InitEntity + = Indirect? InitializedEntity::InitializeMember(Indirect) + : InitializedEntity::InitializeMember(Field); + InitializationKind InitKind = + InitializationKind::CreateDefault(Loc); + + InitializationSequence InitSeq(SemaRef, InitEntity, InitKind, 0, 0); + ExprResult MemberInit = + InitSeq.Perform(SemaRef, InitEntity, InitKind, MultiExprArg()); + + MemberInit = SemaRef.MaybeCreateExprWithCleanups(MemberInit); + if (MemberInit.isInvalid()) + return true; + + if (Indirect) + CXXMemberInit = new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context, + Indirect, Loc, + Loc, + MemberInit.get(), + Loc); + else + CXXMemberInit = new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context, + Field, Loc, Loc, + MemberInit.get(), + Loc); + return false; + } + + if (!Field->getParent()->isUnion()) { + if (FieldBaseElementType->isReferenceType()) { + SemaRef.Diag(Constructor->getLocation(), + diag::err_uninitialized_member_in_ctor) + << (int)Constructor->isImplicit() + << SemaRef.Context.getTagDeclType(Constructor->getParent()) + << 0 << Field->getDeclName(); + SemaRef.Diag(Field->getLocation(), diag::note_declared_at); + return true; + } + + if (FieldBaseElementType.isConstQualified()) { + SemaRef.Diag(Constructor->getLocation(), + diag::err_uninitialized_member_in_ctor) + << (int)Constructor->isImplicit() + << SemaRef.Context.getTagDeclType(Constructor->getParent()) + << 1 << Field->getDeclName(); + SemaRef.Diag(Field->getLocation(), diag::note_declared_at); + return true; + } + } + + if (SemaRef.getLangOpts().ObjCAutoRefCount && + FieldBaseElementType->isObjCRetainableType() && + FieldBaseElementType.getObjCLifetime() != Qualifiers::OCL_None && + FieldBaseElementType.getObjCLifetime() != Qualifiers::OCL_ExplicitNone) { + // Instant objects: + // Default-initialize Objective-C pointers to NULL. + CXXMemberInit + = new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context, Field, + Loc, Loc, + new (SemaRef.Context) ImplicitValueInitExpr(Field->getType()), + Loc); + return false; + } + + // Nothing to initialize. + CXXMemberInit = 0; + return false; +} + +namespace { +struct BaseAndFieldInfo { + Sema &S; + CXXConstructorDecl *Ctor; + bool AnyErrorsInInits; + ImplicitInitializerKind IIK; + llvm::DenseMap AllBaseFields; + SmallVector AllToInit; + + BaseAndFieldInfo(Sema &S, CXXConstructorDecl *Ctor, bool ErrorsInInits) + : S(S), Ctor(Ctor), AnyErrorsInInits(ErrorsInInits) { + bool Generated = Ctor->isImplicit() || Ctor->isDefaulted(); + if (Generated && Ctor->isCopyConstructor()) + IIK = IIK_Copy; + else if (Generated && Ctor->isMoveConstructor()) + IIK = IIK_Move; + else + IIK = IIK_Default; + } + + bool isImplicitCopyOrMove() const { + switch (IIK) { + case IIK_Copy: + case IIK_Move: + return true; + + case IIK_Default: + return false; + } + + llvm_unreachable("Invalid ImplicitInitializerKind!"); + } +}; +} + +/// \brief Determine whether the given indirect field declaration is somewhere +/// within an anonymous union. +static bool isWithinAnonymousUnion(IndirectFieldDecl *F) { + for (IndirectFieldDecl::chain_iterator C = F->chain_begin(), + CEnd = F->chain_end(); + C != CEnd; ++C) + if (CXXRecordDecl *Record = dyn_cast((*C)->getDeclContext())) + if (Record->isUnion()) + return true; + + return false; +} + +/// \brief Determine whether the given type is an incomplete or zero-lenfgth +/// array type. +static bool isIncompleteOrZeroLengthArrayType(ASTContext &Context, QualType T) { + if (T->isIncompleteArrayType()) + return true; + + while (const ConstantArrayType *ArrayT = Context.getAsConstantArrayType(T)) { + if (!ArrayT->getSize()) + return true; + + T = ArrayT->getElementType(); + } + + return false; +} + +static bool CollectFieldInitializer(Sema &SemaRef, BaseAndFieldInfo &Info, + FieldDecl *Field, + IndirectFieldDecl *Indirect = 0) { + + // Overwhelmingly common case: we have a direct initializer for this field. + if (CXXCtorInitializer *Init = Info.AllBaseFields.lookup(Field)) { + Info.AllToInit.push_back(Init); + return false; + } + + // C++0x [class.base.init]p8: if the entity is a non-static data member that + // has a brace-or-equal-initializer, the entity is initialized as specified + // in [dcl.init]. + if (Field->hasInClassInitializer() && !Info.isImplicitCopyOrMove()) { + CXXCtorInitializer *Init; + if (Indirect) + Init = new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context, Indirect, + SourceLocation(), + SourceLocation(), 0, + SourceLocation()); + else + Init = new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context, Field, + SourceLocation(), + SourceLocation(), 0, + SourceLocation()); + Info.AllToInit.push_back(Init); + return false; + } + + // Don't build an implicit initializer for union members if none was + // explicitly specified. + if (Field->getParent()->isUnion() || + (Indirect && isWithinAnonymousUnion(Indirect))) + return false; + + // Don't initialize incomplete or zero-length arrays. + if (isIncompleteOrZeroLengthArrayType(SemaRef.Context, Field->getType())) + return false; + + // Don't try to build an implicit initializer if there were semantic + // errors in any of the initializers (and therefore we might be + // missing some that the user actually wrote). + if (Info.AnyErrorsInInits || Field->isInvalidDecl()) + return false; + + CXXCtorInitializer *Init = 0; + if (BuildImplicitMemberInitializer(Info.S, Info.Ctor, Info.IIK, Field, + Indirect, Init)) + return true; + + if (Init) + Info.AllToInit.push_back(Init); + + return false; +} + +bool +Sema::SetDelegatingInitializer(CXXConstructorDecl *Constructor, + CXXCtorInitializer *Initializer) { + assert(Initializer->isDelegatingInitializer()); + Constructor->setNumCtorInitializers(1); + CXXCtorInitializer **initializer = + new (Context) CXXCtorInitializer*[1]; + memcpy(initializer, &Initializer, sizeof (CXXCtorInitializer*)); + Constructor->setCtorInitializers(initializer); + + if (CXXDestructorDecl *Dtor = LookupDestructor(Constructor->getParent())) { + MarkFunctionReferenced(Initializer->getSourceLocation(), Dtor); + DiagnoseUseOfDecl(Dtor, Initializer->getSourceLocation()); + } + + DelegatingCtorDecls.push_back(Constructor); + + return false; +} + +bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, + CXXCtorInitializer **Initializers, + unsigned NumInitializers, + bool AnyErrors) { + if (Constructor->isDependentContext()) { + // Just store the initializers as written, they will be checked during + // instantiation. + if (NumInitializers > 0) { + Constructor->setNumCtorInitializers(NumInitializers); + CXXCtorInitializer **baseOrMemberInitializers = + new (Context) CXXCtorInitializer*[NumInitializers]; + memcpy(baseOrMemberInitializers, Initializers, + NumInitializers * sizeof(CXXCtorInitializer*)); + Constructor->setCtorInitializers(baseOrMemberInitializers); + } + + return false; + } + + BaseAndFieldInfo Info(*this, Constructor, AnyErrors); + + // We need to build the initializer AST according to order of construction + // and not what user specified in the Initializers list. + CXXRecordDecl *ClassDecl = Constructor->getParent()->getDefinition(); + if (!ClassDecl) + return true; + + bool HadError = false; + + for (unsigned i = 0; i < NumInitializers; i++) { + CXXCtorInitializer *Member = Initializers[i]; + + if (Member->isBaseInitializer()) + Info.AllBaseFields[Member->getBaseClass()->getAs()] = Member; + else + Info.AllBaseFields[Member->getAnyMember()] = Member; + } + + // Keep track of the direct virtual bases. + llvm::SmallPtrSet DirectVBases; + for (CXXRecordDecl::base_class_iterator I = ClassDecl->bases_begin(), + E = ClassDecl->bases_end(); I != E; ++I) { + if (I->isVirtual()) + DirectVBases.insert(I); + } + + // Push virtual bases before others. + for (CXXRecordDecl::base_class_iterator VBase = ClassDecl->vbases_begin(), + E = ClassDecl->vbases_end(); VBase != E; ++VBase) { + + if (CXXCtorInitializer *Value + = Info.AllBaseFields.lookup(VBase->getType()->getAs())) { + Info.AllToInit.push_back(Value); + } else if (!AnyErrors) { + bool IsInheritedVirtualBase = !DirectVBases.count(VBase); + CXXCtorInitializer *CXXBaseInit; + if (BuildImplicitBaseInitializer(*this, Constructor, Info.IIK, + VBase, IsInheritedVirtualBase, + CXXBaseInit)) { + HadError = true; + continue; + } + + Info.AllToInit.push_back(CXXBaseInit); + } + } + + // Non-virtual bases. + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), + E = ClassDecl->bases_end(); Base != E; ++Base) { + // Virtuals are in the virtual base list and already constructed. + if (Base->isVirtual()) + continue; + + if (CXXCtorInitializer *Value + = Info.AllBaseFields.lookup(Base->getType()->getAs())) { + Info.AllToInit.push_back(Value); + } else if (!AnyErrors) { + CXXCtorInitializer *CXXBaseInit; + if (BuildImplicitBaseInitializer(*this, Constructor, Info.IIK, + Base, /*IsInheritedVirtualBase=*/false, + CXXBaseInit)) { + HadError = true; + continue; + } + + Info.AllToInit.push_back(CXXBaseInit); + } + } + + // Fields. + for (DeclContext::decl_iterator Mem = ClassDecl->decls_begin(), + MemEnd = ClassDecl->decls_end(); + Mem != MemEnd; ++Mem) { + if (FieldDecl *F = dyn_cast(*Mem)) { + // C++ [class.bit]p2: + // A declaration for a bit-field that omits the identifier declares an + // unnamed bit-field. Unnamed bit-fields are not members and cannot be + // initialized. + if (F->isUnnamedBitfield()) + continue; + + // If we're not generating the implicit copy/move constructor, then we'll + // handle anonymous struct/union fields based on their individual + // indirect fields. + if (F->isAnonymousStructOrUnion() && Info.IIK == IIK_Default) + continue; + + if (CollectFieldInitializer(*this, Info, F)) + HadError = true; + continue; + } + + // Beyond this point, we only consider default initialization. + if (Info.IIK != IIK_Default) + continue; + + if (IndirectFieldDecl *F = dyn_cast(*Mem)) { + if (F->getType()->isIncompleteArrayType()) { + assert(ClassDecl->hasFlexibleArrayMember() && + "Incomplete array type is not valid"); + continue; + } + + // Initialize each field of an anonymous struct individually. + if (CollectFieldInitializer(*this, Info, F->getAnonField(), F)) + HadError = true; + + continue; + } + } + + NumInitializers = Info.AllToInit.size(); + if (NumInitializers > 0) { + Constructor->setNumCtorInitializers(NumInitializers); + CXXCtorInitializer **baseOrMemberInitializers = + new (Context) CXXCtorInitializer*[NumInitializers]; + memcpy(baseOrMemberInitializers, Info.AllToInit.data(), + NumInitializers * sizeof(CXXCtorInitializer*)); + Constructor->setCtorInitializers(baseOrMemberInitializers); + + // Constructors implicitly reference the base and member + // destructors. + MarkBaseAndMemberDestructorsReferenced(Constructor->getLocation(), + Constructor->getParent()); + } + + return HadError; +} + +static void *GetKeyForTopLevelField(FieldDecl *Field) { + // For anonymous unions, use the class declaration as the key. + if (const RecordType *RT = Field->getType()->getAs()) { + if (RT->getDecl()->isAnonymousStructOrUnion()) + return static_cast(RT->getDecl()); + } + return static_cast(Field); +} + +static void *GetKeyForBase(ASTContext &Context, QualType BaseType) { + return const_cast(Context.getCanonicalType(BaseType).getTypePtr()); +} + +static void *GetKeyForMember(ASTContext &Context, + CXXCtorInitializer *Member) { + if (!Member->isAnyMemberInitializer()) + return GetKeyForBase(Context, QualType(Member->getBaseClass(), 0)); + + // For fields injected into the class via declaration of an anonymous union, + // use its anonymous union class declaration as the unique key. + FieldDecl *Field = Member->getAnyMember(); + + // If the field is a member of an anonymous struct or union, our key + // is the anonymous record decl that's a direct child of the class. + RecordDecl *RD = Field->getParent(); + if (RD->isAnonymousStructOrUnion()) { + while (true) { + RecordDecl *Parent = cast(RD->getDeclContext()); + if (Parent->isAnonymousStructOrUnion()) + RD = Parent; + else + break; + } + + return static_cast(RD); + } + + return static_cast(Field); +} + +static void +DiagnoseBaseOrMemInitializerOrder(Sema &SemaRef, + const CXXConstructorDecl *Constructor, + CXXCtorInitializer **Inits, + unsigned NumInits) { + if (Constructor->getDeclContext()->isDependentContext()) + return; + + // Don't check initializers order unless the warning is enabled at the + // location of at least one initializer. + bool ShouldCheckOrder = false; + for (unsigned InitIndex = 0; InitIndex != NumInits; ++InitIndex) { + CXXCtorInitializer *Init = Inits[InitIndex]; + if (SemaRef.Diags.getDiagnosticLevel(diag::warn_initializer_out_of_order, + Init->getSourceLocation()) + != DiagnosticsEngine::Ignored) { + ShouldCheckOrder = true; + break; + } + } + if (!ShouldCheckOrder) + return; + + // Build the list of bases and members in the order that they'll + // actually be initialized. The explicit initializers should be in + // this same order but may be missing things. + SmallVector IdealInitKeys; + + const CXXRecordDecl *ClassDecl = Constructor->getParent(); + + // 1. Virtual bases. + for (CXXRecordDecl::base_class_const_iterator VBase = + ClassDecl->vbases_begin(), + E = ClassDecl->vbases_end(); VBase != E; ++VBase) + IdealInitKeys.push_back(GetKeyForBase(SemaRef.Context, VBase->getType())); + + // 2. Non-virtual bases. + for (CXXRecordDecl::base_class_const_iterator Base = ClassDecl->bases_begin(), + E = ClassDecl->bases_end(); Base != E; ++Base) { + if (Base->isVirtual()) + continue; + IdealInitKeys.push_back(GetKeyForBase(SemaRef.Context, Base->getType())); + } + + // 3. Direct fields. + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), + E = ClassDecl->field_end(); Field != E; ++Field) { + if (Field->isUnnamedBitfield()) + continue; + + IdealInitKeys.push_back(GetKeyForTopLevelField(*Field)); + } + + unsigned NumIdealInits = IdealInitKeys.size(); + unsigned IdealIndex = 0; + + CXXCtorInitializer *PrevInit = 0; + for (unsigned InitIndex = 0; InitIndex != NumInits; ++InitIndex) { + CXXCtorInitializer *Init = Inits[InitIndex]; + void *InitKey = GetKeyForMember(SemaRef.Context, Init); + + // Scan forward to try to find this initializer in the idealized + // initializers list. + for (; IdealIndex != NumIdealInits; ++IdealIndex) + if (InitKey == IdealInitKeys[IdealIndex]) + break; + + // If we didn't find this initializer, it must be because we + // scanned past it on a previous iteration. That can only + // happen if we're out of order; emit a warning. + if (IdealIndex == NumIdealInits && PrevInit) { + Sema::SemaDiagnosticBuilder D = + SemaRef.Diag(PrevInit->getSourceLocation(), + diag::warn_initializer_out_of_order); + + if (PrevInit->isAnyMemberInitializer()) + D << 0 << PrevInit->getAnyMember()->getDeclName(); + else + D << 1 << PrevInit->getTypeSourceInfo()->getType(); + + if (Init->isAnyMemberInitializer()) + D << 0 << Init->getAnyMember()->getDeclName(); + else + D << 1 << Init->getTypeSourceInfo()->getType(); + + // Move back to the initializer's location in the ideal list. + for (IdealIndex = 0; IdealIndex != NumIdealInits; ++IdealIndex) + if (InitKey == IdealInitKeys[IdealIndex]) + break; + + assert(IdealIndex != NumIdealInits && + "initializer not found in initializer list"); + } + + PrevInit = Init; + } +} + +namespace { +bool CheckRedundantInit(Sema &S, + CXXCtorInitializer *Init, + CXXCtorInitializer *&PrevInit) { + if (!PrevInit) { + PrevInit = Init; + return false; + } + + if (FieldDecl *Field = Init->getMember()) + S.Diag(Init->getSourceLocation(), + diag::err_multiple_mem_initialization) + << Field->getDeclName() + << Init->getSourceRange(); + else { + const Type *BaseClass = Init->getBaseClass(); + assert(BaseClass && "neither field nor base"); + S.Diag(Init->getSourceLocation(), + diag::err_multiple_base_initialization) + << QualType(BaseClass, 0) + << Init->getSourceRange(); + } + S.Diag(PrevInit->getSourceLocation(), diag::note_previous_initializer) + << 0 << PrevInit->getSourceRange(); + + return true; +} + +typedef std::pair UnionEntry; +typedef llvm::DenseMap RedundantUnionMap; + +bool CheckRedundantUnionInit(Sema &S, + CXXCtorInitializer *Init, + RedundantUnionMap &Unions) { + FieldDecl *Field = Init->getAnyMember(); + RecordDecl *Parent = Field->getParent(); + NamedDecl *Child = Field; + + while (Parent->isAnonymousStructOrUnion() || Parent->isUnion()) { + if (Parent->isUnion()) { + UnionEntry &En = Unions[Parent]; + if (En.first && En.first != Child) { + S.Diag(Init->getSourceLocation(), + diag::err_multiple_mem_union_initialization) + << Field->getDeclName() + << Init->getSourceRange(); + S.Diag(En.second->getSourceLocation(), diag::note_previous_initializer) + << 0 << En.second->getSourceRange(); + return true; + } + if (!En.first) { + En.first = Child; + En.second = Init; + } + if (!Parent->isAnonymousStructOrUnion()) + return false; + } + + Child = Parent; + Parent = cast(Parent->getDeclContext()); + } + + return false; +} +} + +/// ActOnMemInitializers - Handle the member initializers for a constructor. +void Sema::ActOnMemInitializers(Decl *ConstructorDecl, + SourceLocation ColonLoc, + CXXCtorInitializer **meminits, + unsigned NumMemInits, + bool AnyErrors) { + if (!ConstructorDecl) + return; + + AdjustDeclIfTemplate(ConstructorDecl); + + CXXConstructorDecl *Constructor + = dyn_cast(ConstructorDecl); + + if (!Constructor) { + Diag(ColonLoc, diag::err_only_constructors_take_base_inits); + return; + } + + CXXCtorInitializer **MemInits = + reinterpret_cast(meminits); + + // Mapping for the duplicate initializers check. + // For member initializers, this is keyed with a FieldDecl*. + // For base initializers, this is keyed with a Type*. + llvm::DenseMap Members; + + // Mapping for the inconsistent anonymous-union initializers check. + RedundantUnionMap MemberUnions; + + bool HadError = false; + for (unsigned i = 0; i < NumMemInits; i++) { + CXXCtorInitializer *Init = MemInits[i]; + + // Set the source order index. + Init->setSourceOrder(i); + + if (Init->isAnyMemberInitializer()) { + FieldDecl *Field = Init->getAnyMember(); + if (CheckRedundantInit(*this, Init, Members[Field]) || + CheckRedundantUnionInit(*this, Init, MemberUnions)) + HadError = true; + } else if (Init->isBaseInitializer()) { + void *Key = GetKeyForBase(Context, QualType(Init->getBaseClass(), 0)); + if (CheckRedundantInit(*this, Init, Members[Key])) + HadError = true; + } else { + assert(Init->isDelegatingInitializer()); + // This must be the only initializer + if (i != 0 || NumMemInits > 1) { + Diag(MemInits[0]->getSourceLocation(), + diag::err_delegating_initializer_alone) + << MemInits[0]->getSourceRange(); + HadError = true; + // We will treat this as being the only initializer. + } + SetDelegatingInitializer(Constructor, MemInits[i]); + // Return immediately as the initializer is set. + return; + } + } + + if (HadError) + return; + + DiagnoseBaseOrMemInitializerOrder(*this, Constructor, MemInits, NumMemInits); + + SetCtorInitializers(Constructor, MemInits, NumMemInits, AnyErrors); +} + +void +Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location, + CXXRecordDecl *ClassDecl) { + // Ignore dependent contexts. Also ignore unions, since their members never + // have destructors implicitly called. + if (ClassDecl->isDependentContext() || ClassDecl->isUnion()) + return; + + // FIXME: all the access-control diagnostics are positioned on the + // field/base declaration. That's probably good; that said, the + // user might reasonably want to know why the destructor is being + // emitted, and we currently don't say. + + // Non-static data members. + for (CXXRecordDecl::field_iterator I = ClassDecl->field_begin(), + E = ClassDecl->field_end(); I != E; ++I) { + FieldDecl *Field = *I; + if (Field->isInvalidDecl()) + continue; + + // Don't destroy incomplete or zero-length arrays. + if (isIncompleteOrZeroLengthArrayType(Context, Field->getType())) + continue; + + QualType FieldType = Context.getBaseElementType(Field->getType()); + + const RecordType* RT = FieldType->getAs(); + if (!RT) + continue; + + CXXRecordDecl *FieldClassDecl = cast(RT->getDecl()); + if (FieldClassDecl->isInvalidDecl()) + continue; + if (FieldClassDecl->hasIrrelevantDestructor()) + continue; + // The destructor for an implicit anonymous union member is never invoked. + if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion()) + continue; + + CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl); + assert(Dtor && "No dtor found for FieldClassDecl!"); + CheckDestructorAccess(Field->getLocation(), Dtor, + PDiag(diag::err_access_dtor_field) + << Field->getDeclName() + << FieldType); + + MarkFunctionReferenced(Location, const_cast(Dtor)); + DiagnoseUseOfDecl(Dtor, Location); + } + + llvm::SmallPtrSet DirectVirtualBases; + + // Bases. + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), + E = ClassDecl->bases_end(); Base != E; ++Base) { + // Bases are always records in a well-formed non-dependent class. + const RecordType *RT = Base->getType()->getAs(); + + // Remember direct virtual bases. + if (Base->isVirtual()) + DirectVirtualBases.insert(RT); + + CXXRecordDecl *BaseClassDecl = cast(RT->getDecl()); + // If our base class is invalid, we probably can't get its dtor anyway. + if (BaseClassDecl->isInvalidDecl()) + continue; + if (BaseClassDecl->hasIrrelevantDestructor()) + continue; + + CXXDestructorDecl *Dtor = LookupDestructor(BaseClassDecl); + assert(Dtor && "No dtor found for BaseClassDecl!"); + + // FIXME: caret should be on the start of the class name + CheckDestructorAccess(Base->getLocStart(), Dtor, + PDiag(diag::err_access_dtor_base) + << Base->getType() + << Base->getSourceRange(), + Context.getTypeDeclType(ClassDecl)); + + MarkFunctionReferenced(Location, const_cast(Dtor)); + DiagnoseUseOfDecl(Dtor, Location); + } + + // Virtual bases. + for (CXXRecordDecl::base_class_iterator VBase = ClassDecl->vbases_begin(), + E = ClassDecl->vbases_end(); VBase != E; ++VBase) { + + // Bases are always records in a well-formed non-dependent class. + const RecordType *RT = VBase->getType()->castAs(); + + // Ignore direct virtual bases. + if (DirectVirtualBases.count(RT)) + continue; + + CXXRecordDecl *BaseClassDecl = cast(RT->getDecl()); + // If our base class is invalid, we probably can't get its dtor anyway. + if (BaseClassDecl->isInvalidDecl()) + continue; + if (BaseClassDecl->hasIrrelevantDestructor()) + continue; + + CXXDestructorDecl *Dtor = LookupDestructor(BaseClassDecl); + assert(Dtor && "No dtor found for BaseClassDecl!"); + CheckDestructorAccess(ClassDecl->getLocation(), Dtor, + PDiag(diag::err_access_dtor_vbase) + << VBase->getType(), + Context.getTypeDeclType(ClassDecl)); + + MarkFunctionReferenced(Location, const_cast(Dtor)); + DiagnoseUseOfDecl(Dtor, Location); + } +} + +void Sema::ActOnDefaultCtorInitializers(Decl *CDtorDecl) { + if (!CDtorDecl) + return; + + if (CXXConstructorDecl *Constructor + = dyn_cast(CDtorDecl)) + SetCtorInitializers(Constructor, 0, 0, /*AnyErrors=*/false); +} + +bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T, + unsigned DiagID, AbstractDiagSelID SelID) { + if (SelID == -1) + return RequireNonAbstractType(Loc, T, PDiag(DiagID)); + else + return RequireNonAbstractType(Loc, T, PDiag(DiagID) << SelID); +} + +bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T, + const PartialDiagnostic &PD) { + if (!getLangOpts().CPlusPlus) + return false; + + if (const ArrayType *AT = Context.getAsArrayType(T)) + return RequireNonAbstractType(Loc, AT->getElementType(), PD); + + if (const PointerType *PT = T->getAs()) { + // Find the innermost pointer type. + while (const PointerType *T = PT->getPointeeType()->getAs()) + PT = T; + + if (const ArrayType *AT = Context.getAsArrayType(PT->getPointeeType())) + return RequireNonAbstractType(Loc, AT->getElementType(), PD); + } + + const RecordType *RT = T->getAs(); + if (!RT) + return false; + + const CXXRecordDecl *RD = cast(RT->getDecl()); + + // 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); + + 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; + + CXXFinalOverriderMap FinalOverriders; + RD->getFinalOverriders(FinalOverriders); + + // Keep a set of seen pure methods so we won't diagnose the same method + // more than once. + llvm::SmallPtrSet SeenPureMethods; + + for (CXXFinalOverriderMap::iterator M = FinalOverriders.begin(), + MEnd = FinalOverriders.end(); + M != MEnd; + ++M) { + for (OverridingMethods::iterator SO = M->second.begin(), + SOEnd = M->second.end(); + SO != SOEnd; ++SO) { + // C++ [class.abstract]p4: + // A class is abstract if it contains or inherits at least one + // pure virtual function for which the final overrider is pure + // virtual. + + // + if (SO->second.size() != 1) + continue; + + if (!SO->second.front().Method->isPure()) + continue; + + if (!SeenPureMethods.insert(SO->second.front().Method)) + continue; + + Diag(SO->second.front().Method->getLocation(), + diag::note_pure_virtual_function) + << SO->second.front().Method->getDeclName() << RD->getDeclName(); + } + } + + if (!PureVirtualClassDiagSet) + PureVirtualClassDiagSet.reset(new RecordDeclSetTy); + PureVirtualClassDiagSet->insert(RD); +} + +namespace { +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; + } + + void CheckType(const NamedDecl *D, TypeLoc TL, Sema::AbstractDiagSelID Sel); +}; + +struct CheckAbstractUsage { + AbstractUsageInfo &Info; + const NamedDecl *Ctx; + + 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" + } + } + + void Check(FunctionProtoTypeLoc TL, Sema::AbstractDiagSelID Sel) { + Visit(TL.getResultLoc(), Sema::AbstractReturnType); + for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { + if (!TL.getArg(I)) + continue; + + TypeSourceInfo *TSI = TL.getArg(I)->getTypeSourceInfo(); + if (TSI) Visit(TSI->getTypeLoc(), Sema::AbstractParamType); + } + } + + void Check(ArrayTypeLoc TL, Sema::AbstractDiagSelID Sel) { + Visit(TL.getElementLoc(), Sema::AbstractArrayType); + } + + 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? + } + } + + // 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) + CheckPolymorphic(AtomicTypeLoc) + + /// 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; + + // 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(); + } +}; + +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->doesThisDeclarationHaveABody()) + 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 +/// completing, introducing implicitly-declared members, checking for +/// abstract types, etc. +void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { + if (!Record) + return; + + 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 + // type, since they will never get initializers. + if (!Record->isInvalidDecl() && !Record->isDependentType() && + !Record->isAggregate() && !Record->hasUserDeclaredConstructor() && + !Record->isLambda()) { + bool Complained = false; + for (RecordDecl::field_iterator F = Record->field_begin(), + FEnd = Record->field_end(); + F != FEnd; ++F) { + if (F->hasInClassInitializer() || F->isUnnamedBitfield()) + continue; + + if (F->getType()->isReferenceType() || + (F->getType().isConstQualified() && F->getType()->isScalarType())) { + if (!Complained) { + Diag(Record->getLocation(), diag::warn_no_constructor_for_refconst) + << Record->getTagKind() << Record; + Complained = true; + } + + Diag(F->getLocation(), diag::note_refconst_member_not_initialized) + << F->getType()->isReferenceType() + << F->getDeclName(); + } + } + } + + if (Record->isDynamicClass() && !Record->isDependentType()) + DynamicClasses.push_back(Record); + + if (Record->getIdentifier()) { + // C++ [class.mem]p13: + // If T is the name of a class, then each of the following shall have a + // name different from T: + // - every member of every anonymous union that is a member of class T. + // + // C++ [class.mem]p14: + // In addition, if class T has a user-declared constructor (12.1), every + // non-static data member of class T shall have a name different from T. + for (DeclContext::lookup_result R = Record->lookup(Record->getDeclName()); + R.first != R.second; ++R.first) { + NamedDecl *D = *R.first; + if ((isa(D) && Record->hasUserDeclaredConstructor()) || + isa(D)) { + Diag(D->getLocation(), diag::err_member_name_of_class) + << D->getDeclName(); + break; + } + } + } + + // Warn if the class has virtual methods but non-virtual public destructor. + if (Record->isPolymorphic() && !Record->isDependentType()) { + CXXDestructorDecl *dtor = Record->getDestructor(); + if (!dtor || (!dtor->isVirtual() && dtor->getAccess() == AS_public)) + Diag(dtor ? dtor->getLocation() : Record->getLocation(), + diag::warn_non_virtual_dtor) << Context.getRecordType(Record); + } + + // See if a method overloads virtual methods in a base + /// class without overriding any. + if (!Record->isDependentType()) { + for (CXXRecordDecl::method_iterator M = Record->method_begin(), + MEnd = Record->method_end(); + M != MEnd; ++M) { + if (!(*M)->isStatic()) + DiagnoseHiddenVirtualMethods(Record, *M); + } + } + + // C++0x [dcl.constexpr]p8: A constexpr specifier for a non-static member + // function that is not a constructor declares that member function to be + // const. [...] The class of which that function is a member shall be + // a literal type. + // + // If the class has virtual bases, any constexpr members will already have + // been diagnosed by the checks performed on the member declaration, so + // suppress this (less useful) diagnostic. + if (LangOpts.CPlusPlus0x && !Record->isDependentType() && + !Record->isLiteral() && !Record->getNumVBases()) { + for (CXXRecordDecl::method_iterator M = Record->method_begin(), + MEnd = Record->method_end(); + M != MEnd; ++M) { + if (M->isConstexpr() && M->isInstance() && !isa(*M)) { + switch (Record->getTemplateSpecializationKind()) { + case TSK_ImplicitInstantiation: + case TSK_ExplicitInstantiationDeclaration: + case TSK_ExplicitInstantiationDefinition: + // If a template instantiates to a non-literal type, but its members + // instantiate to constexpr functions, the template is technically + // ill-formed, but we allow it for sanity. + continue; + + case TSK_Undeclared: + case TSK_ExplicitSpecialization: + RequireLiteralType((*M)->getLocation(), Context.getRecordType(Record), + PDiag(diag::err_constexpr_method_non_literal)); + break; + } + + // Only produce one error per class. + break; + } + } + } + + // Declare inherited constructors. We do this eagerly here because: + // - The standard requires an eager diagnostic for conflicting inherited + // constructors from different classes. + // - The lazy declaration of the other implicit constructors is so as to not + // waste space and performance on classes that are not meant to be + // instantiated (e.g. meta-functions). This doesn't apply to classes that + // have inherited constructors. + DeclareInheritedConstructors(Record); + + if (!Record->isDependentType()) + CheckExplicitlyDefaultedMethods(Record); +} + +void Sema::CheckExplicitlyDefaultedMethods(CXXRecordDecl *Record) { + for (CXXRecordDecl::method_iterator MI = Record->method_begin(), + ME = Record->method_end(); + MI != ME; ++MI) { + if (!MI->isInvalidDecl() && MI->isExplicitlyDefaulted()) { + switch (getSpecialMember(*MI)) { + case CXXDefaultConstructor: + CheckExplicitlyDefaultedDefaultConstructor( + cast(*MI)); + break; + + case CXXDestructor: + CheckExplicitlyDefaultedDestructor(cast(*MI)); + break; + + case CXXCopyConstructor: + CheckExplicitlyDefaultedCopyConstructor(cast(*MI)); + break; + + case CXXCopyAssignment: + CheckExplicitlyDefaultedCopyAssignment(*MI); + break; + + case CXXMoveConstructor: + CheckExplicitlyDefaultedMoveConstructor(cast(*MI)); + break; + + case CXXMoveAssignment: + CheckExplicitlyDefaultedMoveAssignment(*MI); + break; + + case CXXInvalid: + llvm_unreachable("non-special member explicitly defaulted!"); + } + } + } + +} + +void Sema::CheckExplicitlyDefaultedDefaultConstructor(CXXConstructorDecl *CD) { + assert(CD->isExplicitlyDefaulted() && CD->isDefaultConstructor()); + + // Whether this was the first-declared instance of the constructor. + // This affects whether we implicitly add an exception spec (and, eventually, + // constexpr). It is also ill-formed to explicitly default a constructor such + // that it would be deleted. (C++0x [decl.fct.def.default]) + bool First = CD == CD->getCanonicalDecl(); + + bool HadError = false; + if (CD->getNumParams() != 0) { + Diag(CD->getLocation(), diag::err_defaulted_default_ctor_params) + << CD->getSourceRange(); + HadError = true; + } + + ImplicitExceptionSpecification Spec + = ComputeDefaultedDefaultCtorExceptionSpec(CD->getParent()); + FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI(); + if (EPI.ExceptionSpecType == EST_Delayed) { + // Exception specification depends on some deferred part of the class. We'll + // try again when the class's definition has been fully processed. + return; + } + const FunctionProtoType *CtorType = CD->getType()->getAs(), + *ExceptionType = Context.getFunctionType( + Context.VoidTy, 0, 0, EPI)->getAs(); + + // C++11 [dcl.fct.def.default]p2: + // An explicitly-defaulted function may be declared constexpr only if it + // would have been implicitly declared as constexpr, + // Do not apply this rule to templates, since core issue 1358 makes such + // functions always instantiate to constexpr functions. + if (CD->isConstexpr() && + CD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) { + if (!CD->getParent()->defaultedDefaultConstructorIsConstexpr()) { + Diag(CD->getLocStart(), diag::err_incorrect_defaulted_constexpr) + << CXXDefaultConstructor; + HadError = true; + } + } + // and may have an explicit exception-specification only if it is compatible + // with the exception-specification on the implicit declaration. + if (CtorType->hasExceptionSpec()) { + if (CheckEquivalentExceptionSpec( + PDiag(diag::err_incorrect_defaulted_exception_spec) + << CXXDefaultConstructor, + PDiag(), + ExceptionType, SourceLocation(), + CtorType, CD->getLocation())) { + HadError = true; + } + } + + // If a function is explicitly defaulted on its first declaration, + if (First) { + // -- it is implicitly considered to be constexpr if the implicit + // definition would be, + CD->setConstexpr(CD->getParent()->defaultedDefaultConstructorIsConstexpr()); + + // -- it is implicitly considered to have the same + // exception-specification as if it had been implicitly declared + // + // FIXME: a compatible, but different, explicit exception specification + // will be silently overridden. We should issue a warning if this happens. + EPI.ExtInfo = CtorType->getExtInfo(); + + // Such a function is also trivial if the implicitly-declared function + // would have been. + CD->setTrivial(CD->getParent()->hasTrivialDefaultConstructor()); + } + + if (HadError) { + CD->setInvalidDecl(); + return; + } + + if (ShouldDeleteSpecialMember(CD, CXXDefaultConstructor)) { + if (First) { + CD->setDeletedAsWritten(); + } else { + Diag(CD->getLocation(), diag::err_out_of_line_default_deletes) + << CXXDefaultConstructor; + CD->setInvalidDecl(); + } + } +} + +void Sema::CheckExplicitlyDefaultedCopyConstructor(CXXConstructorDecl *CD) { + assert(CD->isExplicitlyDefaulted() && CD->isCopyConstructor()); + + // Whether this was the first-declared instance of the constructor. + bool First = CD == CD->getCanonicalDecl(); + + bool HadError = false; + if (CD->getNumParams() != 1) { + Diag(CD->getLocation(), diag::err_defaulted_copy_ctor_params) + << CD->getSourceRange(); + HadError = true; + } + + ImplicitExceptionSpecification Spec(*this); + bool Const; + llvm::tie(Spec, Const) = + ComputeDefaultedCopyCtorExceptionSpecAndConst(CD->getParent()); + + FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI(); + const FunctionProtoType *CtorType = CD->getType()->getAs(), + *ExceptionType = Context.getFunctionType( + Context.VoidTy, 0, 0, EPI)->getAs(); + + // Check for parameter type matching. + // This is a copy ctor so we know it's a cv-qualified reference to T. + QualType ArgType = CtorType->getArgType(0); + if (ArgType->getPointeeType().isVolatileQualified()) { + Diag(CD->getLocation(), diag::err_defaulted_copy_ctor_volatile_param); + HadError = true; + } + if (ArgType->getPointeeType().isConstQualified() && !Const) { + Diag(CD->getLocation(), diag::err_defaulted_copy_ctor_const_param); + HadError = true; + } + + // C++11 [dcl.fct.def.default]p2: + // An explicitly-defaulted function may be declared constexpr only if it + // would have been implicitly declared as constexpr, + // Do not apply this rule to templates, since core issue 1358 makes such + // functions always instantiate to constexpr functions. + if (CD->isConstexpr() && + CD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) { + if (!CD->getParent()->defaultedCopyConstructorIsConstexpr()) { + Diag(CD->getLocStart(), diag::err_incorrect_defaulted_constexpr) + << CXXCopyConstructor; + HadError = true; + } + } + // and may have an explicit exception-specification only if it is compatible + // with the exception-specification on the implicit declaration. + if (CtorType->hasExceptionSpec()) { + if (CheckEquivalentExceptionSpec( + PDiag(diag::err_incorrect_defaulted_exception_spec) + << CXXCopyConstructor, + PDiag(), + ExceptionType, SourceLocation(), + CtorType, CD->getLocation())) { + HadError = true; + } + } + + // If a function is explicitly defaulted on its first declaration, + if (First) { + // -- it is implicitly considered to be constexpr if the implicit + // definition would be, + CD->setConstexpr(CD->getParent()->defaultedCopyConstructorIsConstexpr()); + + // -- it is implicitly considered to have the same + // exception-specification as if it had been implicitly declared, and + // + // FIXME: a compatible, but different, explicit exception specification + // will be silently overridden. We should issue a warning if this happens. + EPI.ExtInfo = CtorType->getExtInfo(); + + // -- [...] it shall have the same parameter type as if it had been + // implicitly declared. + CD->setType(Context.getFunctionType(Context.VoidTy, &ArgType, 1, EPI)); + + // Such a function is also trivial if the implicitly-declared function + // would have been. + CD->setTrivial(CD->getParent()->hasTrivialCopyConstructor()); + } + + if (HadError) { + CD->setInvalidDecl(); + return; + } + + if (ShouldDeleteSpecialMember(CD, CXXCopyConstructor)) { + if (First) { + CD->setDeletedAsWritten(); + } else { + Diag(CD->getLocation(), diag::err_out_of_line_default_deletes) + << CXXCopyConstructor; + CD->setInvalidDecl(); + } + } +} + +void Sema::CheckExplicitlyDefaultedCopyAssignment(CXXMethodDecl *MD) { + assert(MD->isExplicitlyDefaulted()); + + // Whether this was the first-declared instance of the operator + bool First = MD == MD->getCanonicalDecl(); + + bool HadError = false; + if (MD->getNumParams() != 1) { + Diag(MD->getLocation(), diag::err_defaulted_copy_assign_params) + << MD->getSourceRange(); + HadError = true; + } + + QualType ReturnType = + MD->getType()->getAs()->getResultType(); + if (!ReturnType->isLValueReferenceType() || + !Context.hasSameType( + Context.getCanonicalType(ReturnType->getPointeeType()), + Context.getCanonicalType(Context.getTypeDeclType(MD->getParent())))) { + Diag(MD->getLocation(), diag::err_defaulted_copy_assign_return_type); + HadError = true; + } + + ImplicitExceptionSpecification Spec(*this); + bool Const; + llvm::tie(Spec, Const) = + ComputeDefaultedCopyCtorExceptionSpecAndConst(MD->getParent()); + + FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI(); + const FunctionProtoType *OperType = MD->getType()->getAs(), + *ExceptionType = Context.getFunctionType( + Context.VoidTy, 0, 0, EPI)->getAs(); + + QualType ArgType = OperType->getArgType(0); + if (!ArgType->isLValueReferenceType()) { + Diag(MD->getLocation(), diag::err_defaulted_copy_assign_not_ref); + HadError = true; + } else { + if (ArgType->getPointeeType().isVolatileQualified()) { + Diag(MD->getLocation(), diag::err_defaulted_copy_assign_volatile_param); + HadError = true; + } + if (ArgType->getPointeeType().isConstQualified() && !Const) { + Diag(MD->getLocation(), diag::err_defaulted_copy_assign_const_param); + HadError = true; + } + } + + if (OperType->getTypeQuals()) { + Diag(MD->getLocation(), diag::err_defaulted_copy_assign_quals); + HadError = true; + } + + if (OperType->hasExceptionSpec()) { + if (CheckEquivalentExceptionSpec( + PDiag(diag::err_incorrect_defaulted_exception_spec) + << CXXCopyAssignment, + PDiag(), + ExceptionType, SourceLocation(), + OperType, MD->getLocation())) { + HadError = true; + } + } + if (First) { + // We set the declaration to have the computed exception spec here. + // We duplicate the one parameter type. + EPI.RefQualifier = OperType->getRefQualifier(); + EPI.ExtInfo = OperType->getExtInfo(); + MD->setType(Context.getFunctionType(ReturnType, &ArgType, 1, EPI)); + + // Such a function is also trivial if the implicitly-declared function + // would have been. + MD->setTrivial(MD->getParent()->hasTrivialCopyAssignment()); + } + + if (HadError) { + MD->setInvalidDecl(); + return; + } + + if (ShouldDeleteSpecialMember(MD, CXXCopyAssignment)) { + if (First) { + MD->setDeletedAsWritten(); + } else { + Diag(MD->getLocation(), diag::err_out_of_line_default_deletes) + << CXXCopyAssignment; + MD->setInvalidDecl(); + } + } +} + +void Sema::CheckExplicitlyDefaultedMoveConstructor(CXXConstructorDecl *CD) { + assert(CD->isExplicitlyDefaulted() && CD->isMoveConstructor()); + + // Whether this was the first-declared instance of the constructor. + bool First = CD == CD->getCanonicalDecl(); + + bool HadError = false; + if (CD->getNumParams() != 1) { + Diag(CD->getLocation(), diag::err_defaulted_move_ctor_params) + << CD->getSourceRange(); + HadError = true; + } + + ImplicitExceptionSpecification Spec( + ComputeDefaultedMoveCtorExceptionSpec(CD->getParent())); + + FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI(); + const FunctionProtoType *CtorType = CD->getType()->getAs(), + *ExceptionType = Context.getFunctionType( + Context.VoidTy, 0, 0, EPI)->getAs(); + + // Check for parameter type matching. + // This is a move ctor so we know it's a cv-qualified rvalue reference to T. + QualType ArgType = CtorType->getArgType(0); + if (ArgType->getPointeeType().isVolatileQualified()) { + Diag(CD->getLocation(), diag::err_defaulted_move_ctor_volatile_param); + HadError = true; + } + if (ArgType->getPointeeType().isConstQualified()) { + Diag(CD->getLocation(), diag::err_defaulted_move_ctor_const_param); + HadError = true; + } + + // C++11 [dcl.fct.def.default]p2: + // An explicitly-defaulted function may be declared constexpr only if it + // would have been implicitly declared as constexpr, + // Do not apply this rule to templates, since core issue 1358 makes such + // functions always instantiate to constexpr functions. + if (CD->isConstexpr() && + CD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) { + if (!CD->getParent()->defaultedMoveConstructorIsConstexpr()) { + Diag(CD->getLocStart(), diag::err_incorrect_defaulted_constexpr) + << CXXMoveConstructor; + HadError = true; + } + } + // and may have an explicit exception-specification only if it is compatible + // with the exception-specification on the implicit declaration. + if (CtorType->hasExceptionSpec()) { + if (CheckEquivalentExceptionSpec( + PDiag(diag::err_incorrect_defaulted_exception_spec) + << CXXMoveConstructor, + PDiag(), + ExceptionType, SourceLocation(), + CtorType, CD->getLocation())) { + HadError = true; + } + } + + // If a function is explicitly defaulted on its first declaration, + if (First) { + // -- it is implicitly considered to be constexpr if the implicit + // definition would be, + CD->setConstexpr(CD->getParent()->defaultedMoveConstructorIsConstexpr()); + + // -- it is implicitly considered to have the same + // exception-specification as if it had been implicitly declared, and + // + // FIXME: a compatible, but different, explicit exception specification + // will be silently overridden. We should issue a warning if this happens. + EPI.ExtInfo = CtorType->getExtInfo(); + + // -- [...] it shall have the same parameter type as if it had been + // implicitly declared. + CD->setType(Context.getFunctionType(Context.VoidTy, &ArgType, 1, EPI)); + + // Such a function is also trivial if the implicitly-declared function + // would have been. + CD->setTrivial(CD->getParent()->hasTrivialMoveConstructor()); + } + + if (HadError) { + CD->setInvalidDecl(); + return; + } + + if (ShouldDeleteSpecialMember(CD, CXXMoveConstructor)) { + if (First) { + CD->setDeletedAsWritten(); + } else { + Diag(CD->getLocation(), diag::err_out_of_line_default_deletes) + << CXXMoveConstructor; + CD->setInvalidDecl(); + } + } +} + +void Sema::CheckExplicitlyDefaultedMoveAssignment(CXXMethodDecl *MD) { + assert(MD->isExplicitlyDefaulted()); + + // Whether this was the first-declared instance of the operator + bool First = MD == MD->getCanonicalDecl(); + + bool HadError = false; + if (MD->getNumParams() != 1) { + Diag(MD->getLocation(), diag::err_defaulted_move_assign_params) + << MD->getSourceRange(); + HadError = true; + } + + QualType ReturnType = + MD->getType()->getAs()->getResultType(); + if (!ReturnType->isLValueReferenceType() || + !Context.hasSameType( + Context.getCanonicalType(ReturnType->getPointeeType()), + Context.getCanonicalType(Context.getTypeDeclType(MD->getParent())))) { + Diag(MD->getLocation(), diag::err_defaulted_move_assign_return_type); + HadError = true; + } + + ImplicitExceptionSpecification Spec( + ComputeDefaultedMoveCtorExceptionSpec(MD->getParent())); + + FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI(); + const FunctionProtoType *OperType = MD->getType()->getAs(), + *ExceptionType = Context.getFunctionType( + Context.VoidTy, 0, 0, EPI)->getAs(); + + QualType ArgType = OperType->getArgType(0); + if (!ArgType->isRValueReferenceType()) { + Diag(MD->getLocation(), diag::err_defaulted_move_assign_not_ref); + HadError = true; + } else { + if (ArgType->getPointeeType().isVolatileQualified()) { + Diag(MD->getLocation(), diag::err_defaulted_move_assign_volatile_param); + HadError = true; + } + if (ArgType->getPointeeType().isConstQualified()) { + Diag(MD->getLocation(), diag::err_defaulted_move_assign_const_param); + HadError = true; + } + } + + if (OperType->getTypeQuals()) { + Diag(MD->getLocation(), diag::err_defaulted_move_assign_quals); + HadError = true; + } + + if (OperType->hasExceptionSpec()) { + if (CheckEquivalentExceptionSpec( + PDiag(diag::err_incorrect_defaulted_exception_spec) + << CXXMoveAssignment, + PDiag(), + ExceptionType, SourceLocation(), + OperType, MD->getLocation())) { + HadError = true; + } + } + if (First) { + // We set the declaration to have the computed exception spec here. + // We duplicate the one parameter type. + EPI.RefQualifier = OperType->getRefQualifier(); + EPI.ExtInfo = OperType->getExtInfo(); + MD->setType(Context.getFunctionType(ReturnType, &ArgType, 1, EPI)); + + // Such a function is also trivial if the implicitly-declared function + // would have been. + MD->setTrivial(MD->getParent()->hasTrivialMoveAssignment()); + } + + if (HadError) { + MD->setInvalidDecl(); + return; + } + + if (ShouldDeleteSpecialMember(MD, CXXMoveAssignment)) { + if (First) { + MD->setDeletedAsWritten(); + } else { + Diag(MD->getLocation(), diag::err_out_of_line_default_deletes) + << CXXMoveAssignment; + MD->setInvalidDecl(); + } + } +} + +void Sema::CheckExplicitlyDefaultedDestructor(CXXDestructorDecl *DD) { + assert(DD->isExplicitlyDefaulted()); + + // Whether this was the first-declared instance of the destructor. + bool First = DD == DD->getCanonicalDecl(); + + ImplicitExceptionSpecification Spec + = ComputeDefaultedDtorExceptionSpec(DD->getParent()); + FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI(); + const FunctionProtoType *DtorType = DD->getType()->getAs(), + *ExceptionType = Context.getFunctionType( + Context.VoidTy, 0, 0, EPI)->getAs(); + + if (DtorType->hasExceptionSpec()) { + if (CheckEquivalentExceptionSpec( + PDiag(diag::err_incorrect_defaulted_exception_spec) + << CXXDestructor, + PDiag(), + ExceptionType, SourceLocation(), + DtorType, DD->getLocation())) { + DD->setInvalidDecl(); + return; + } + } + if (First) { + // We set the declaration to have the computed exception spec here. + // There are no parameters. + EPI.ExtInfo = DtorType->getExtInfo(); + DD->setType(Context.getFunctionType(Context.VoidTy, 0, 0, EPI)); + + // Such a function is also trivial if the implicitly-declared function + // would have been. + DD->setTrivial(DD->getParent()->hasTrivialDestructor()); + } + + if (ShouldDeleteSpecialMember(DD, CXXDestructor)) { + if (First) { + DD->setDeletedAsWritten(); + } else { + Diag(DD->getLocation(), diag::err_out_of_line_default_deletes) + << CXXDestructor; + DD->setInvalidDecl(); + } + } +} + +namespace { +struct SpecialMemberDeletionInfo { + Sema &S; + CXXMethodDecl *MD; + Sema::CXXSpecialMember CSM; + bool Diagnose; + + // Properties of the special member, computed for convenience. + bool IsConstructor, IsAssignment, IsMove, ConstArg, VolatileArg; + SourceLocation Loc; + + bool AllFieldsAreConst; + + SpecialMemberDeletionInfo(Sema &S, CXXMethodDecl *MD, + Sema::CXXSpecialMember CSM, bool Diagnose) + : S(S), MD(MD), CSM(CSM), Diagnose(Diagnose), + IsConstructor(false), IsAssignment(false), IsMove(false), + ConstArg(false), VolatileArg(false), Loc(MD->getLocation()), + AllFieldsAreConst(true) { + switch (CSM) { + case Sema::CXXDefaultConstructor: + case Sema::CXXCopyConstructor: + IsConstructor = true; + break; + case Sema::CXXMoveConstructor: + IsConstructor = true; + IsMove = true; + break; + case Sema::CXXCopyAssignment: + IsAssignment = true; + break; + case Sema::CXXMoveAssignment: + IsAssignment = true; + IsMove = true; + break; + case Sema::CXXDestructor: + break; + case Sema::CXXInvalid: + llvm_unreachable("invalid special member kind"); + } + + if (MD->getNumParams()) { + ConstArg = MD->getParamDecl(0)->getType().isConstQualified(); + VolatileArg = MD->getParamDecl(0)->getType().isVolatileQualified(); + } + } + + bool inUnion() const { return MD->getParent()->isUnion(); } + + /// Look up the corresponding special member in the given class. + Sema::SpecialMemberOverloadResult *lookupIn(CXXRecordDecl *Class) { + unsigned TQ = MD->getTypeQualifiers(); + return S.LookupSpecialMember(Class, CSM, ConstArg, VolatileArg, + MD->getRefQualifier() == RQ_RValue, + TQ & Qualifiers::Const, + TQ & Qualifiers::Volatile); + } + + typedef llvm::PointerUnion Subobject; + + bool shouldDeleteForBase(CXXBaseSpecifier *Base); + bool shouldDeleteForField(FieldDecl *FD); + bool shouldDeleteForAllConstMembers(); + + bool shouldDeleteForClassSubobject(CXXRecordDecl *Class, Subobject Subobj); + bool shouldDeleteForSubobjectCall(Subobject Subobj, + Sema::SpecialMemberOverloadResult *SMOR, + bool IsDtorCallInCtor); + + bool isAccessible(Subobject Subobj, CXXMethodDecl *D); +}; +} + +/// Is the given special member inaccessible when used on the given +/// sub-object. +bool SpecialMemberDeletionInfo::isAccessible(Subobject Subobj, + CXXMethodDecl *target) { + /// If we're operating on a base class, the object type is the + /// type of this special member. + QualType objectTy; + AccessSpecifier access = target->getAccess();; + if (CXXBaseSpecifier *base = Subobj.dyn_cast()) { + objectTy = S.Context.getTypeDeclType(MD->getParent()); + access = CXXRecordDecl::MergeAccess(base->getAccessSpecifier(), access); + + // If we're operating on a field, the object type is the type of the field. + } else { + objectTy = S.Context.getTypeDeclType(target->getParent()); + } + + return S.isSpecialMemberAccessibleForDeletion(target, access, objectTy); +} + +/// Check whether we should delete a special member due to the implicit +/// definition containing a call to a special member of a subobject. +bool SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall( + Subobject Subobj, Sema::SpecialMemberOverloadResult *SMOR, + bool IsDtorCallInCtor) { + CXXMethodDecl *Decl = SMOR->getMethod(); + FieldDecl *Field = Subobj.dyn_cast(); + + int DiagKind = -1; + + if (SMOR->getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted) + DiagKind = !Decl ? 0 : 1; + else if (SMOR->getKind() == Sema::SpecialMemberOverloadResult::Ambiguous) + DiagKind = 2; + else if (!isAccessible(Subobj, Decl)) + DiagKind = 3; + else if (!IsDtorCallInCtor && Field && Field->getParent()->isUnion() && + !Decl->isTrivial()) { + // A member of a union must have a trivial corresponding special member. + // As a weird special case, a destructor call from a union's constructor + // must be accessible and non-deleted, but need not be trivial. Such a + // destructor is never actually called, but is semantically checked as + // if it were. + DiagKind = 4; + } + + if (DiagKind == -1) + return false; + + if (Diagnose) { + if (Field) { + S.Diag(Field->getLocation(), + diag::note_deleted_special_member_class_subobject) + << CSM << MD->getParent() << /*IsField*/true + << Field << DiagKind << IsDtorCallInCtor; + } else { + CXXBaseSpecifier *Base = Subobj.get(); + S.Diag(Base->getLocStart(), + diag::note_deleted_special_member_class_subobject) + << CSM << MD->getParent() << /*IsField*/false + << Base->getType() << DiagKind << IsDtorCallInCtor; + } + + if (DiagKind == 1) + S.NoteDeletedFunction(Decl); + // FIXME: Explain inaccessibility if DiagKind == 3. + } + + return true; +} + +/// Check whether we should delete a special member function due to having a +/// direct or virtual base class or static data member of class type M. +bool SpecialMemberDeletionInfo::shouldDeleteForClassSubobject( + CXXRecordDecl *Class, Subobject Subobj) { + FieldDecl *Field = Subobj.dyn_cast(); + + // C++11 [class.ctor]p5: + // -- any direct or virtual base class, or non-static data member with no + // brace-or-equal-initializer, has class type M (or array thereof) and + // either M has no default constructor or overload resolution as applied + // to M's default constructor results in an ambiguity or in a function + // that is deleted or inaccessible + // C++11 [class.copy]p11, C++11 [class.copy]p23: + // -- a direct or virtual base class B that cannot be copied/moved because + // overload resolution, as applied to B's corresponding special member, + // results in an ambiguity or a function that is deleted or inaccessible + // from the defaulted special member + // C++11 [class.dtor]p5: + // -- any direct or virtual base class [...] has a type with a destructor + // that is deleted or inaccessible + if (!(CSM == Sema::CXXDefaultConstructor && + Field && Field->hasInClassInitializer()) && + shouldDeleteForSubobjectCall(Subobj, lookupIn(Class), false)) + return true; + + // C++11 [class.ctor]p5, C++11 [class.copy]p11: + // -- any direct or virtual base class or non-static data member has a + // type with a destructor that is deleted or inaccessible + if (IsConstructor) { + Sema::SpecialMemberOverloadResult *SMOR = + S.LookupSpecialMember(Class, Sema::CXXDestructor, + false, false, false, false, false); + if (shouldDeleteForSubobjectCall(Subobj, SMOR, true)) + return true; + } + + return false; +} + +/// Check whether we should delete a special member function due to the class +/// having a particular direct or virtual base class. +bool SpecialMemberDeletionInfo::shouldDeleteForBase(CXXBaseSpecifier *Base) { + CXXRecordDecl *BaseClass = Base->getType()->getAsCXXRecordDecl(); + return shouldDeleteForClassSubobject(BaseClass, Base); +} + +/// Check whether we should delete a special member function due to the class +/// having a particular non-static data member. +bool SpecialMemberDeletionInfo::shouldDeleteForField(FieldDecl *FD) { + QualType FieldType = S.Context.getBaseElementType(FD->getType()); + CXXRecordDecl *FieldRecord = FieldType->getAsCXXRecordDecl(); + + if (CSM == Sema::CXXDefaultConstructor) { + // For a default constructor, all references must be initialized in-class + // and, if a union, it must have a non-const member. + if (FieldType->isReferenceType() && !FD->hasInClassInitializer()) { + if (Diagnose) + S.Diag(FD->getLocation(), diag::note_deleted_default_ctor_uninit_field) + << MD->getParent() << FD << FieldType << /*Reference*/0; + return true; + } + // C++11 [class.ctor]p5: any non-variant non-static data member of + // const-qualified type (or array thereof) with no + // brace-or-equal-initializer does not have a user-provided default + // constructor. + if (!inUnion() && FieldType.isConstQualified() && + !FD->hasInClassInitializer() && + (!FieldRecord || !FieldRecord->hasUserProvidedDefaultConstructor())) { + if (Diagnose) + S.Diag(FD->getLocation(), diag::note_deleted_default_ctor_uninit_field) + << MD->getParent() << FD << FieldType << /*Const*/1; + return true; + } + + if (inUnion() && !FieldType.isConstQualified()) + AllFieldsAreConst = false; + } else if (CSM == Sema::CXXCopyConstructor) { + // For a copy constructor, data members must not be of rvalue reference + // type. + if (FieldType->isRValueReferenceType()) { + if (Diagnose) + S.Diag(FD->getLocation(), diag::note_deleted_copy_ctor_rvalue_reference) + << MD->getParent() << FD << FieldType; + return true; + } + } else if (IsAssignment) { + // For an assignment operator, data members must not be of reference type. + if (FieldType->isReferenceType()) { + if (Diagnose) + S.Diag(FD->getLocation(), diag::note_deleted_assign_field) + << IsMove << MD->getParent() << FD << FieldType << /*Reference*/0; + return true; + } + if (!FieldRecord && FieldType.isConstQualified()) { + // C++11 [class.copy]p23: + // -- a non-static data member of const non-class type (or array thereof) + if (Diagnose) + S.Diag(FD->getLocation(), diag::note_deleted_assign_field) + << IsMove << MD->getParent() << FD << FieldType << /*Const*/1; + return true; + } + } + + if (FieldRecord) { + // Some additional restrictions exist on the variant members. + if (!inUnion() && FieldRecord->isUnion() && + FieldRecord->isAnonymousStructOrUnion()) { + bool AllVariantFieldsAreConst = true; + + // FIXME: Handle anonymous unions declared within anonymous unions. + for (CXXRecordDecl::field_iterator UI = FieldRecord->field_begin(), + UE = FieldRecord->field_end(); + UI != UE; ++UI) { + QualType UnionFieldType = S.Context.getBaseElementType(UI->getType()); + + if (!UnionFieldType.isConstQualified()) + AllVariantFieldsAreConst = false; + + CXXRecordDecl *UnionFieldRecord = UnionFieldType->getAsCXXRecordDecl(); + if (UnionFieldRecord && + shouldDeleteForClassSubobject(UnionFieldRecord, *UI)) + return true; + } + + // At least one member in each anonymous union must be non-const + if (CSM == Sema::CXXDefaultConstructor && AllVariantFieldsAreConst && + FieldRecord->field_begin() != FieldRecord->field_end()) { + if (Diagnose) + S.Diag(FieldRecord->getLocation(), + diag::note_deleted_default_ctor_all_const) + << MD->getParent() << /*anonymous union*/1; + return true; + } + + // Don't check the implicit member of the anonymous union type. + // This is technically non-conformant, but sanity demands it. + return false; + } + + if (shouldDeleteForClassSubobject(FieldRecord, FD)) + return true; + } + + return false; +} + +/// C++11 [class.ctor] p5: +/// A defaulted default constructor for a class X is defined as deleted if +/// X is a union and all of its variant members are of const-qualified type. +bool SpecialMemberDeletionInfo::shouldDeleteForAllConstMembers() { + // This is a silly definition, because it gives an empty union a deleted + // default constructor. Don't do that. + if (CSM == Sema::CXXDefaultConstructor && inUnion() && AllFieldsAreConst && + (MD->getParent()->field_begin() != MD->getParent()->field_end())) { + if (Diagnose) + S.Diag(MD->getParent()->getLocation(), + diag::note_deleted_default_ctor_all_const) + << MD->getParent() << /*not anonymous union*/0; + return true; + } + return false; +} + +/// Determine whether a defaulted special member function should be defined as +/// deleted, as specified in C++11 [class.ctor]p5, C++11 [class.copy]p11, +/// C++11 [class.copy]p23, and C++11 [class.dtor]p5. +bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, + bool Diagnose) { + assert(!MD->isInvalidDecl()); + CXXRecordDecl *RD = MD->getParent(); + assert(!RD->isDependentType() && "do deletion after instantiation"); + if (!LangOpts.CPlusPlus0x || RD->isInvalidDecl()) + return false; + + // C++11 [expr.lambda.prim]p19: + // The closure type associated with a lambda-expression has a + // deleted (8.4.3) default constructor and a deleted copy + // assignment operator. + if (RD->isLambda() && + (CSM == CXXDefaultConstructor || CSM == CXXCopyAssignment)) { + if (Diagnose) + Diag(RD->getLocation(), diag::note_lambda_decl); + return true; + } + + // For an anonymous struct or union, the copy and assignment special members + // will never be used, so skip the check. For an anonymous union declared at + // namespace scope, the constructor and destructor are used. + if (CSM != CXXDefaultConstructor && CSM != CXXDestructor && + RD->isAnonymousStructOrUnion()) + return false; + + // C++11 [class.copy]p7, p18: + // If the class definition declares a move constructor or move assignment + // operator, an implicitly declared copy constructor or copy assignment + // operator is defined as deleted. + if (MD->isImplicit() && + (CSM == CXXCopyConstructor || CSM == CXXCopyAssignment)) { + CXXMethodDecl *UserDeclaredMove = 0; + + // In Microsoft mode, a user-declared move only causes the deletion of the + // corresponding copy operation, not both copy operations. + if (RD->hasUserDeclaredMoveConstructor() && + (!getLangOpts().MicrosoftMode || CSM == CXXCopyConstructor)) { + if (!Diagnose) return true; + UserDeclaredMove = RD->getMoveConstructor(); + assert(UserDeclaredMove); + } else if (RD->hasUserDeclaredMoveAssignment() && + (!getLangOpts().MicrosoftMode || CSM == CXXCopyAssignment)) { + if (!Diagnose) return true; + UserDeclaredMove = RD->getMoveAssignmentOperator(); + assert(UserDeclaredMove); + } + + if (UserDeclaredMove) { + Diag(UserDeclaredMove->getLocation(), + diag::note_deleted_copy_user_declared_move) + << (CSM == CXXCopyAssignment) << RD + << UserDeclaredMove->isMoveAssignmentOperator(); + return true; + } + } + + // Do access control from the special member function + ContextRAII MethodContext(*this, MD); + + // C++11 [class.dtor]p5: + // -- for a virtual destructor, lookup of the non-array deallocation function + // results in an ambiguity or in a function that is deleted or inaccessible + if (CSM == CXXDestructor && MD->isVirtual()) { + FunctionDecl *OperatorDelete = 0; + DeclarationName Name = + Context.DeclarationNames.getCXXOperatorName(OO_Delete); + if (FindDeallocationFunction(MD->getLocation(), MD->getParent(), Name, + OperatorDelete, false)) { + if (Diagnose) + Diag(RD->getLocation(), diag::note_deleted_dtor_no_operator_delete); + return true; + } + } + + SpecialMemberDeletionInfo SMI(*this, MD, CSM, Diagnose); + + for (CXXRecordDecl::base_class_iterator BI = RD->bases_begin(), + BE = RD->bases_end(); BI != BE; ++BI) + if (!BI->isVirtual() && + SMI.shouldDeleteForBase(BI)) + return true; + + for (CXXRecordDecl::base_class_iterator BI = RD->vbases_begin(), + BE = RD->vbases_end(); BI != BE; ++BI) + if (SMI.shouldDeleteForBase(BI)) + return true; + + for (CXXRecordDecl::field_iterator FI = RD->field_begin(), + FE = RD->field_end(); FI != FE; ++FI) + if (!FI->isInvalidDecl() && !FI->isUnnamedBitfield() && + SMI.shouldDeleteForField(*FI)) + return true; + + if (SMI.shouldDeleteForAllConstMembers()) + return true; + + return false; +} + +/// \brief Data used with FindHiddenVirtualMethod +namespace { + struct FindHiddenVirtualMethodData { + Sema *S; + CXXMethodDecl *Method; + llvm::SmallPtrSet OverridenAndUsingBaseMethods; + SmallVector OverloadedMethods; + }; +} + +/// \brief Member lookup function that determines whether a given C++ +/// method overloads virtual methods in a base class without overriding any, +/// to be used with CXXRecordDecl::lookupInBases(). +static bool FindHiddenVirtualMethod(const CXXBaseSpecifier *Specifier, + CXXBasePath &Path, + void *UserData) { + RecordDecl *BaseRecord = Specifier->getType()->getAs()->getDecl(); + + FindHiddenVirtualMethodData &Data + = *static_cast(UserData); + + DeclarationName Name = Data.Method->getDeclName(); + assert(Name.getNameKind() == DeclarationName::Identifier); + + bool foundSameNameMethod = false; + SmallVector overloadedMethods; + for (Path.Decls = BaseRecord->lookup(Name); + Path.Decls.first != Path.Decls.second; + ++Path.Decls.first) { + NamedDecl *D = *Path.Decls.first; + if (CXXMethodDecl *MD = dyn_cast(D)) { + MD = MD->getCanonicalDecl(); + foundSameNameMethod = true; + // Interested only in hidden virtual methods. + if (!MD->isVirtual()) + continue; + // If the method we are checking overrides a method from its base + // don't warn about the other overloaded methods. + if (!Data.S->IsOverload(Data.Method, MD, false)) + return true; + // Collect the overload only if its hidden. + if (!Data.OverridenAndUsingBaseMethods.count(MD)) + overloadedMethods.push_back(MD); + } + } + + if (foundSameNameMethod) + Data.OverloadedMethods.append(overloadedMethods.begin(), + overloadedMethods.end()); + return foundSameNameMethod; +} + +/// \brief See if a method overloads virtual methods in a base class without +/// overriding any. +void Sema::DiagnoseHiddenVirtualMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) { + if (Diags.getDiagnosticLevel(diag::warn_overloaded_virtual, + MD->getLocation()) == DiagnosticsEngine::Ignored) + return; + if (MD->getDeclName().getNameKind() != DeclarationName::Identifier) + return; + + CXXBasePaths Paths(/*FindAmbiguities=*/true, // true to look in all bases. + /*bool RecordPaths=*/false, + /*bool DetectVirtual=*/false); + FindHiddenVirtualMethodData Data; + Data.Method = MD; + Data.S = this; + + // Keep the base methods that were overriden or introduced in the subclass + // by 'using' in a set. A base method not in this set is hidden. + for (DeclContext::lookup_result res = DC->lookup(MD->getDeclName()); + res.first != res.second; ++res.first) { + if (CXXMethodDecl *MD = dyn_cast(*res.first)) + for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(), + E = MD->end_overridden_methods(); + I != E; ++I) + Data.OverridenAndUsingBaseMethods.insert((*I)->getCanonicalDecl()); + if (UsingShadowDecl *shad = dyn_cast(*res.first)) + if (CXXMethodDecl *MD = dyn_cast(shad->getTargetDecl())) + Data.OverridenAndUsingBaseMethods.insert(MD->getCanonicalDecl()); + } + + if (DC->lookupInBases(&FindHiddenVirtualMethod, &Data, Paths) && + !Data.OverloadedMethods.empty()) { + Diag(MD->getLocation(), diag::warn_overloaded_virtual) + << MD << (Data.OverloadedMethods.size() > 1); + + for (unsigned i = 0, e = Data.OverloadedMethods.size(); i != e; ++i) { + CXXMethodDecl *overloadedMD = Data.OverloadedMethods[i]; + Diag(overloadedMD->getLocation(), + diag::note_hidden_overloaded_virtual_declared_here) << overloadedMD; + } + } +} + +void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, + Decl *TagDecl, + SourceLocation LBrac, + SourceLocation RBrac, + AttributeList *AttrList) { + if (!TagDecl) + return; + + AdjustDeclIfTemplate(TagDecl); + + ActOnFields(S, RLoc, TagDecl, llvm::makeArrayRef( + // strict aliasing violation! + reinterpret_cast(FieldCollector->getCurFields()), + FieldCollector->getCurNumFields()), LBrac, RBrac, AttrList); + + CheckCompletedCXXClass( + dyn_cast_or_null(TagDecl)); +} + +/// AddImplicitlyDeclaredMembersToClass - Adds any implicitly-declared +/// special functions, such as the default constructor, copy +/// constructor, or destructor, to the given C++ class (C++ +/// [special]p1). This routine can only be executed just before the +/// definition of the class is complete. +void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { + if (!ClassDecl->hasUserDeclaredConstructor()) + ++ASTContext::NumImplicitDefaultConstructors; + + if (!ClassDecl->hasUserDeclaredCopyConstructor()) + ++ASTContext::NumImplicitCopyConstructors; + + if (getLangOpts().CPlusPlus0x && ClassDecl->needsImplicitMoveConstructor()) + ++ASTContext::NumImplicitMoveConstructors; + + if (!ClassDecl->hasUserDeclaredCopyAssignment()) { + ++ASTContext::NumImplicitCopyAssignmentOperators; + + // If we have a dynamic class, then the copy assignment operator may be + // virtual, so we have to declare it immediately. This ensures that, e.g., + // it shows up in the right place in the vtable and that we diagnose + // problems with the implicit exception specification. + if (ClassDecl->isDynamicClass()) + DeclareImplicitCopyAssignment(ClassDecl); + } + + if (getLangOpts().CPlusPlus0x && ClassDecl->needsImplicitMoveAssignment()) { + ++ASTContext::NumImplicitMoveAssignmentOperators; + + // Likewise for the move assignment operator. + if (ClassDecl->isDynamicClass()) + DeclareImplicitMoveAssignment(ClassDecl); + } + + if (!ClassDecl->hasUserDeclaredDestructor()) { + ++ASTContext::NumImplicitDestructors; + + // If we have a dynamic class, then the destructor may be virtual, so we + // have to declare the destructor immediately. This ensures that, e.g., it + // shows up in the right place in the vtable and that we diagnose problems + // with the implicit exception specification. + if (ClassDecl->isDynamicClass()) + DeclareImplicitDestructor(ClassDecl); + } +} + +void Sema::ActOnReenterDeclaratorTemplateScope(Scope *S, DeclaratorDecl *D) { + if (!D) + return; + + int NumParamList = D->getNumTemplateParameterLists(); + for (int i = 0; i < NumParamList; i++) { + TemplateParameterList* Params = D->getTemplateParameterList(i); + for (TemplateParameterList::iterator Param = Params->begin(), + ParamEnd = Params->end(); + Param != ParamEnd; ++Param) { + NamedDecl *Named = cast(*Param); + if (Named->getDeclName()) { + S->AddDecl(Named); + IdResolver.AddDecl(Named); + } + } + } +} + +void Sema::ActOnReenterTemplateScope(Scope *S, Decl *D) { + if (!D) + return; + + TemplateParameterList *Params = 0; + if (TemplateDecl *Template = dyn_cast(D)) + Params = Template->getTemplateParameters(); + else if (ClassTemplatePartialSpecializationDecl *PartialSpec + = dyn_cast(D)) + Params = PartialSpec->getTemplateParameters(); + else + return; + + for (TemplateParameterList::iterator Param = Params->begin(), + ParamEnd = Params->end(); + Param != ParamEnd; ++Param) { + NamedDecl *Named = cast(*Param); + if (Named->getDeclName()) { + S->AddDecl(Named); + IdResolver.AddDecl(Named); + } + } +} + +void Sema::ActOnStartDelayedMemberDeclarations(Scope *S, Decl *RecordD) { + if (!RecordD) return; + AdjustDeclIfTemplate(RecordD); + CXXRecordDecl *Record = cast(RecordD); + PushDeclContext(S, Record); +} + +void Sema::ActOnFinishDelayedMemberDeclarations(Scope *S, Decl *RecordD) { + if (!RecordD) return; + PopDeclContext(); +} + +/// ActOnStartDelayedCXXMethodDeclaration - We have completed +/// parsing a top-level (non-nested) C++ class, and we are now +/// parsing those parts of the given Method declaration that could +/// not be parsed earlier (C++ [class.mem]p2), such as default +/// arguments. This action should enter the scope of the given +/// Method declaration as if we had just parsed the qualified method +/// name. However, it should not bring the parameters into scope; +/// that will be performed by ActOnDelayedCXXMethodParameter. +void Sema::ActOnStartDelayedCXXMethodDeclaration(Scope *S, Decl *MethodD) { +} + +/// ActOnDelayedCXXMethodParameter - We've already started a delayed +/// C++ method declaration. We're (re-)introducing the given +/// function parameter into scope for use in parsing later parts of +/// the method declaration. For example, we could see an +/// ActOnParamDefaultArgument event for this parameter. +void Sema::ActOnDelayedCXXMethodParameter(Scope *S, Decl *ParamD) { + if (!ParamD) + return; + + 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(Param); + if (Param->getDeclName()) + IdResolver.AddDecl(Param); +} + +/// ActOnFinishDelayedCXXMethodDeclaration - We have finished +/// processing the delayed method declaration for Method. The method +/// declaration is now considered finished. There may be a separate +/// ActOnStartOfFunctionDef action later (not necessarily +/// immediately!) for this method, if it was also defined inside the +/// class body. +void Sema::ActOnFinishDelayedCXXMethodDeclaration(Scope *S, Decl *MethodD) { + if (!MethodD) + return; + + AdjustDeclIfTemplate(MethodD); + + FunctionDecl *Method = cast(MethodD); + + // Now that we have our default arguments, check the constructor + // again. It could produce additional diagnostics or affect whether + // the class has implicitly-declared destructors, among other + // things. + if (CXXConstructorDecl *Constructor = dyn_cast(Method)) + CheckConstructor(Constructor); + + // Check the default arguments, which we may have added. + if (!Method->isInvalidDecl()) + CheckCXXDefaultArguments(Method); +} + +/// CheckConstructorDeclarator - Called by ActOnDeclarator to check +/// the well-formedness of the constructor declarator @p D with type @p +/// R. If there are any errors in the declarator, this routine will +/// emit diagnostics and set the invalid bit to true. In any case, the type +/// will be updated to reflect a well-formed type for the constructor and +/// returned. +QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R, + StorageClass &SC) { + bool isVirtual = D.getDeclSpec().isVirtualSpecified(); + + // C++ [class.ctor]p3: + // A constructor shall not be virtual (10.3) or static (9.4). A + // constructor can be invoked for a const, volatile or const + // volatile object. A constructor shall not be declared const, + // volatile, or const volatile (9.3.2). + if (isVirtual) { + if (!D.isInvalidType()) + Diag(D.getIdentifierLoc(), diag::err_constructor_cannot_be) + << "virtual" << SourceRange(D.getDeclSpec().getVirtualSpecLoc()) + << SourceRange(D.getIdentifierLoc()); + D.setInvalidType(); + } + 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 = SC_None; + } + + DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); + if (FTI.TypeQuals != 0) { + if (FTI.TypeQuals & Qualifiers::Const) + Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor) + << "const" << SourceRange(D.getIdentifierLoc()); + if (FTI.TypeQuals & Qualifiers::Volatile) + Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor) + << "volatile" << SourceRange(D.getIdentifierLoc()); + if (FTI.TypeQuals & Qualifiers::Restrict) + Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor) + << "restrict" << SourceRange(D.getIdentifierLoc()); + D.setInvalidType(); + } + + // C++0x [class.ctor]p4: + // A constructor shall not be declared with a ref-qualifier. + if (FTI.hasRefQualifier()) { + Diag(FTI.getRefQualifierLoc(), diag::err_ref_qualifier_constructor) + << FTI.RefQualifierIsLValueRef + << FixItHint::CreateRemoval(FTI.getRefQualifierLoc()); + D.setInvalidType(); + } + + // Rebuild the function type "R" without any type qualifiers (in + // case any of the errors above fired) and with "void" as the + // return type, since constructors don't have return types. + const FunctionProtoType *Proto = R->getAs(); + if (Proto->getResultType() == Context.VoidTy && !D.isInvalidType()) + return R; + + FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo(); + EPI.TypeQuals = 0; + EPI.RefQualifier = RQ_None; + + return Context.getFunctionType(Context.VoidTy, Proto->arg_type_begin(), + Proto->getNumArgs(), EPI); +} + +/// CheckConstructor - Checks a fully-formed constructor for +/// well-formedness, issuing any diagnostics required. Returns true if +/// the constructor declarator is invalid. +void Sema::CheckConstructor(CXXConstructorDecl *Constructor) { + CXXRecordDecl *ClassDecl + = dyn_cast(Constructor->getDeclContext()); + if (!ClassDecl) + return Constructor->setInvalidDecl(); + + // C++ [class.copy]p3: + // A declaration of a constructor for a class X is ill-formed if + // its first parameter is of type (optionally cv-qualified) X and + // either there are no other parameters or else all other + // parameters have default arguments. + if (!Constructor->isInvalidDecl() && + ((Constructor->getNumParams() == 1) || + (Constructor->getNumParams() > 1 && + Constructor->getParamDecl(1)->hasDefaultArg())) && + Constructor->getTemplateSpecializationKind() + != TSK_ImplicitInstantiation) { + QualType ParamType = Constructor->getParamDecl(0)->getType(); + QualType ClassTy = Context.getTagDeclType(ClassDecl); + if (Context.getCanonicalType(ParamType).getUnqualifiedType() == ClassTy) { + SourceLocation ParamLoc = Constructor->getParamDecl(0)->getLocation(); + const char *ConstRef + = Constructor->getParamDecl(0)->getIdentifier() ? "const &" + : " const &"; + Diag(ParamLoc, diag::err_constructor_byvalue_arg) + << FixItHint::CreateInsertion(ParamLoc, ConstRef); + + // FIXME: Rather that making the constructor invalid, we should endeavor + // to fix the type. + Constructor->setInvalidDecl(); + } + } +} + +/// 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(); + + if (Destructor->isVirtual()) { + SourceLocation Loc; + + if (!Destructor->isImplicit()) + Loc = Destructor->getLocation(); + else + Loc = RD->getLocation(); + + // If we have a virtual destructor, look up the deallocation function + FunctionDecl *OperatorDelete = 0; + DeclarationName Name = + Context.DeclarationNames.getCXXOperatorName(OO_Delete); + if (FindDeallocationFunction(Loc, RD, Name, OperatorDelete)) + return true; + + MarkFunctionReferenced(Loc, OperatorDelete); + + Destructor->setOperatorDelete(OperatorDelete); + } + + return false; +} + +static inline bool +FTIHasSingleVoidArgument(DeclaratorChunk::FunctionTypeInfo &FTI) { + return (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 && + FTI.ArgInfo[0].Param && + cast(FTI.ArgInfo[0].Param)->getType()->isVoidType()); +} + +/// CheckDestructorDeclarator - Called by ActOnDeclarator to check +/// the well-formednes of the destructor declarator @p D with type @p +/// R. If there are any errors in the declarator, this routine will +/// emit diagnostics and set the declarator to invalid. Even if this happens, +/// will be updated to reflect a well-formed type for the destructor and +/// returned. +QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R, + 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 + // be used as the identifier in the declarator for a destructor + // declaration. + QualType DeclaratorType = GetTypeFromParser(D.getName().DestructorName); + if (const TypedefType *TT = DeclaratorType->getAs()) + Diag(D.getIdentifierLoc(), diag::err_destructor_typedef_name) + << DeclaratorType << isa(TT->getDecl()); + else if (const TemplateSpecializationType *TST = + DeclaratorType->getAs()) + if (TST->isTypeAlias()) + Diag(D.getIdentifierLoc(), diag::err_destructor_typedef_name) + << DeclaratorType << 1; + + // C++ [class.dtor]p2: + // A destructor is used to destroy objects of its class type. A + // destructor takes no parameters, and no return type can be + // specified for it (not even void). The address of a destructor + // shall not be taken. A destructor shall not be static. A + // 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 == 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 = SC_None; + } + if (D.getDeclSpec().hasTypeSpecifier() && !D.isInvalidType()) { + // Destructors don't have return types, but the parser will + // happily parse something like: + // + // class X { + // float ~X(); + // }; + // + // The return type will be eliminated later. + Diag(D.getIdentifierLoc(), diag::err_destructor_return_type) + << SourceRange(D.getDeclSpec().getTypeSpecTypeLoc()) + << SourceRange(D.getIdentifierLoc()); + } + + DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); + if (FTI.TypeQuals != 0 && !D.isInvalidType()) { + if (FTI.TypeQuals & Qualifiers::Const) + Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor) + << "const" << SourceRange(D.getIdentifierLoc()); + if (FTI.TypeQuals & Qualifiers::Volatile) + Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor) + << "volatile" << SourceRange(D.getIdentifierLoc()); + if (FTI.TypeQuals & Qualifiers::Restrict) + Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor) + << "restrict" << SourceRange(D.getIdentifierLoc()); + D.setInvalidType(); + } + + // C++0x [class.dtor]p2: + // A destructor shall not be declared with a ref-qualifier. + if (FTI.hasRefQualifier()) { + Diag(FTI.getRefQualifierLoc(), diag::err_ref_qualifier_destructor) + << FTI.RefQualifierIsLValueRef + << FixItHint::CreateRemoval(FTI.getRefQualifierLoc()); + D.setInvalidType(); + } + + // Make sure we don't have any parameters. + if (FTI.NumArgs > 0 && !FTIHasSingleVoidArgument(FTI)) { + Diag(D.getIdentifierLoc(), diag::err_destructor_with_params); + + // Delete the parameters. + FTI.freeArgs(); + D.setInvalidType(); + } + + // Make sure the destructor isn't variadic. + if (FTI.isVariadic) { + Diag(D.getIdentifierLoc(), diag::err_destructor_variadic); + D.setInvalidType(); + } + + // Rebuild the function type "R" without any type qualifiers or + // parameters (in case any of the errors above fired) and with + // "void" as the return type, since destructors don't have return + // types. + if (!D.isInvalidType()) + return R; + + const FunctionProtoType *Proto = R->getAs(); + FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo(); + EPI.Variadic = false; + EPI.TypeQuals = 0; + EPI.RefQualifier = RQ_None; + return Context.getFunctionType(Context.VoidTy, 0, 0, EPI); +} + +/// CheckConversionDeclarator - Called by ActOnDeclarator to check the +/// well-formednes of the conversion function declarator @p D with +/// type @p R. If there are any errors in the declarator, this routine +/// will emit diagnostics and return true. Otherwise, it will return +/// 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, + 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 == 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 = SC_None; + } + + QualType ConvType = GetTypeFromParser(D.getName().ConversionFunctionId); + + if (D.getDeclSpec().hasTypeSpecifier() && !D.isInvalidType()) { + // Conversion functions don't have return types, but the parser will + // happily parse something like: + // + // class X { + // float operator bool(); + // }; + // + // The return type will be changed later anyway. + Diag(D.getIdentifierLoc(), diag::err_conv_function_return_type) + << SourceRange(D.getDeclSpec().getTypeSpecTypeLoc()) + << SourceRange(D.getIdentifierLoc()); + D.setInvalidType(); + } + + const FunctionProtoType *Proto = R->getAs(); + + // Make sure we don't have any parameters. + if (Proto->getNumArgs() > 0) { + Diag(D.getIdentifierLoc(), diag::err_conv_function_with_params); + + // Delete the parameters. + D.getFunctionTypeInfo().freeArgs(); + D.setInvalidType(); + } else if (Proto->isVariadic()) { + Diag(D.getIdentifierLoc(), diag::err_conv_function_variadic); + D.setInvalidType(); + } + + // Diagnose "&operator bool()" and other such nonsense. This + // is actually a gcc extension which we don't support. + if (Proto->getResultType() != ConvType) { + Diag(D.getIdentifierLoc(), diag::err_conv_function_with_complex_decl) + << Proto->getResultType(); + D.setInvalidType(); + ConvType = Proto->getResultType(); + } + + // C++ [class.conv.fct]p4: + // The conversion-type-id shall not represent a function type nor + // an array type. + if (ConvType->isArrayType()) { + Diag(D.getIdentifierLoc(), diag::err_conv_function_to_array); + ConvType = Context.getPointerType(ConvType); + D.setInvalidType(); + } else if (ConvType->isFunctionType()) { + Diag(D.getIdentifierLoc(), diag::err_conv_function_to_function); + ConvType = Context.getPointerType(ConvType); + D.setInvalidType(); + } + + // Rebuild the function type "R" without any parameters (in case any + // of the errors above fired) and with the conversion type as the + // return type. + if (D.isInvalidType()) + R = Context.getFunctionType(ConvType, 0, 0, Proto->getExtProtoInfo()); + + // C++0x explicit conversion operators. + if (D.getDeclSpec().isExplicitSpecified()) + Diag(D.getDeclSpec().getExplicitSpecLoc(), + getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_explicit_conversion_functions : + diag::ext_explicit_conversion_functions) + << SourceRange(D.getDeclSpec().getExplicitSpecLoc()); +} + +/// ActOnConversionDeclarator - Called by ActOnDeclarator to complete +/// the declaration of the given C++ conversion function. This routine +/// is responsible for recording the conversion function in the C++ +/// class, if possible. +Decl *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) { + assert(Conversion && "Expected to receive a conversion function declaration"); + + CXXRecordDecl *ClassDecl = cast(Conversion->getDeclContext()); + + // Make sure we aren't redeclaring the conversion function. + QualType ConvType = Context.getCanonicalType(Conversion->getConversionType()); + + // C++ [class.conv.fct]p1: + // [...] A conversion function is never used to convert a + // (possibly cv-qualified) object to the (possibly cv-qualified) + // same object type (or a reference to it), to a (possibly + // cv-qualified) base class of that type (or a reference to it), + // or to (possibly cv-qualified) void. + // FIXME: Suppress this warning if the conversion function ends up being a + // virtual function that overrides a virtual function in a base class. + QualType ClassType + = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl)); + if (const ReferenceType *ConvTypeRef = ConvType->getAs()) + ConvType = ConvTypeRef->getPointeeType(); + if (Conversion->getTemplateSpecializationKind() != TSK_Undeclared && + Conversion->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) + /* Suppress diagnostics for instantiations. */; + else if (ConvType->isRecordType()) { + ConvType = Context.getCanonicalType(ConvType).getUnqualifiedType(); + if (ConvType == ClassType) + Diag(Conversion->getLocation(), diag::warn_conv_to_self_not_used) + << ClassType; + else if (IsDerivedFrom(ClassType, ConvType)) + Diag(Conversion->getLocation(), diag::warn_conv_to_base_not_used) + << ClassType << ConvType; + } else if (ConvType->isVoidType()) { + Diag(Conversion->getLocation(), diag::warn_conv_to_void_not_used) + << ClassType << ConvType; + } + + if (FunctionTemplateDecl *ConversionTemplate + = Conversion->getDescribedFunctionTemplate()) + return ConversionTemplate; + + return Conversion; +} + +//===----------------------------------------------------------------------===// +// Namespace Handling +//===----------------------------------------------------------------------===// + + + +/// ActOnStartNamespaceDef - This is called at the start of a namespace +/// definition. +Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, + SourceLocation InlineLoc, + SourceLocation NamespaceLoc, + SourceLocation IdentLoc, + IdentifierInfo *II, + SourceLocation LBrace, + AttributeList *AttrList) { + SourceLocation StartLoc = InlineLoc.isValid() ? InlineLoc : NamespaceLoc; + // For anonymous namespace, take the location of the left brace. + SourceLocation Loc = II ? IdentLoc : LBrace; + bool IsInline = InlineLoc.isValid(); + bool IsInvalid = false; + bool IsStd = false; + bool AddToKnown = false; + Scope *DeclRegionScope = NamespcScope->getParent(); + + NamespaceDecl *PrevNS = 0; + if (II) { + // C++ [namespace.def]p2: + // The identifier in an original-namespace-definition shall not + // have been previously defined in the declarative region in + // which the original-namespace-definition appears. The + // identifier in an original-namespace-definition is the name of + // the namespace. Subsequently in that declarative region, it is + // treated as an original-namespace-name. + // + // Since namespace names are unique in their scope, and we don't + // look through using directives, just look for any ordinary names. + + const unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Member | + Decl::IDNS_Type | Decl::IDNS_Using | Decl::IDNS_Tag | + Decl::IDNS_Namespace; + NamedDecl *PrevDecl = 0; + for (DeclContext::lookup_result R + = CurContext->getRedeclContext()->lookup(II); + R.first != R.second; ++R.first) { + if ((*R.first)->getIdentifierNamespace() & IDNS) { + PrevDecl = *R.first; + break; + } + } + + PrevNS = dyn_cast_or_null(PrevDecl); + + if (PrevNS) { + // This is an extended namespace definition. + if (IsInline != PrevNS->isInline()) { + // inline-ness must match + if (PrevNS->isInline()) { + // The user probably just forgot the 'inline', so suggest that it + // be added back. + Diag(Loc, diag::warn_inline_namespace_reopened_noninline) + << FixItHint::CreateInsertion(NamespaceLoc, "inline "); + } else { + Diag(Loc, diag::err_inline_namespace_mismatch) + << IsInline; + } + Diag(PrevNS->getLocation(), diag::note_previous_definition); + + IsInline = PrevNS->isInline(); + } + } else if (PrevDecl) { + // This is an invalid name redefinition. + Diag(Loc, diag::err_redefinition_different_kind) + << II; + Diag(PrevDecl->getLocation(), diag::note_previous_definition); + IsInvalid = true; + // Continue on to push Namespc as current DeclContext and return it. + } else if (II->isStr("std") && + 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. + PrevNS = getStdNamespace(); + IsStd = true; + AddToKnown = !IsInline; + } else { + // We've seen this namespace for the first time. + AddToKnown = !IsInline; + } + } else { + // Anonymous namespaces. + + // Determine whether the parent already has an anonymous namespace. + DeclContext *Parent = CurContext->getRedeclContext(); + if (TranslationUnitDecl *TU = dyn_cast(Parent)) { + PrevNS = TU->getAnonymousNamespace(); + } else { + NamespaceDecl *ND = cast(Parent); + PrevNS = ND->getAnonymousNamespace(); + } + + if (PrevNS && IsInline != PrevNS->isInline()) { + // inline-ness must match + Diag(Loc, diag::err_inline_namespace_mismatch) + << IsInline; + Diag(PrevNS->getLocation(), diag::note_previous_definition); + + // Recover by ignoring the new namespace's inline status. + IsInline = PrevNS->isInline(); + } + } + + NamespaceDecl *Namespc = NamespaceDecl::Create(Context, CurContext, IsInline, + StartLoc, Loc, II, PrevNS); + if (IsInvalid) + Namespc->setInvalidDecl(); + + ProcessDeclAttributeList(DeclRegionScope, Namespc, AttrList); + + // FIXME: Should we be merging attributes? + if (const VisibilityAttr *Attr = Namespc->getAttr()) + PushNamespaceVisibilityAttr(Attr, Loc); + + if (IsStd) + StdNamespace = Namespc; + if (AddToKnown) + KnownNamespaces[Namespc] = false; + + if (II) { + PushOnScopeChains(Namespc, DeclRegionScope); + } else { + // Link the anonymous namespace into its parent. + DeclContext *Parent = CurContext->getRedeclContext(); + if (TranslationUnitDecl *TU = dyn_cast(Parent)) { + TU->setAnonymousNamespace(Namespc); + } else { + cast(Parent)->setAnonymousNamespace(Namespc); + } + + CurContext->addDecl(Namespc); + + // C++ [namespace.unnamed]p1. An unnamed-namespace-definition + // behaves as if it were replaced by + // namespace unique { /* empty body */ } + // using namespace unique; + // namespace unique { namespace-body } + // where all occurrences of 'unique' in a translation unit are + // replaced by the same identifier and this identifier differs + // from all other identifiers in the entire program. + + // We just create the namespace with an empty name and then add an + // implicit using declaration, just like the standard suggests. + // + // CodeGen enforces the "universally unique" aspect by giving all + // declarations semantically contained within an anonymous + // namespace internal linkage. + + if (!PrevNS) { + UsingDirectiveDecl* UD + = UsingDirectiveDecl::Create(Context, CurContext, + /* 'using' */ LBrace, + /* 'namespace' */ SourceLocation(), + /* qualifier */ NestedNameSpecifierLoc(), + /* identifier */ SourceLocation(), + Namespc, + /* Ancestor */ CurContext); + UD->setImplicit(); + CurContext->addDecl(UD); + } + } + + // Although we could have an invalid decl (i.e. the namespace name is a + // redefinition), push it as current DeclContext and try to continue parsing. + // FIXME: We should be able to push Namespc here, so that the each DeclContext + // for the namespace has the declarations that showed up in that particular + // namespace definition. + PushDeclContext(NamespcScope, Namespc); + return Namespc; +} + +/// getNamespaceDecl - Returns the namespace a decl represents. If the decl +/// is a namespace alias, returns the namespace it points to. +static inline NamespaceDecl *getNamespaceDecl(NamedDecl *D) { + if (NamespaceAliasDecl *AD = dyn_cast_or_null(D)) + return AD->getNamespace(); + return dyn_cast_or_null(D); +} + +/// ActOnFinishNamespaceDef - This callback is called after a namespace is +/// exited. Decl is the DeclTy returned by ActOnStartNamespaceDef. +void Sema::ActOnFinishNamespaceDef(Decl *Dcl, SourceLocation RBrace) { + NamespaceDecl *Namespc = dyn_cast_or_null(Dcl); + assert(Namespc && "Invalid parameter, expected NamespaceDecl"); + Namespc->setRBraceLoc(RBrace); + PopDeclContext(); + if (Namespc->hasAttr()) + PopPragmaVisibility(true, RBrace); +} + +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::getOrCreateStdNamespace() { + if (!StdNamespace) { + // The "std" namespace has not yet been defined, so build one implicitly. + StdNamespace = NamespaceDecl::Create(Context, + Context.getTranslationUnitDecl(), + /*Inline=*/false, + SourceLocation(), SourceLocation(), + &PP.getIdentifierTable().get("std"), + /*PrevDecl=*/0); + getStdNamespace()->setImplicit(true); + } + + return getStdNamespace(); +} + +bool Sema::isStdInitializerList(QualType Ty, QualType *Element) { + assert(getLangOpts().CPlusPlus && + "Looking for std::initializer_list outside of C++."); + + // We're looking for implicit instantiations of + // template class std::initializer_list. + + if (!StdNamespace) // If we haven't seen namespace std yet, this can't be it. + return false; + + ClassTemplateDecl *Template = 0; + const TemplateArgument *Arguments = 0; + + if (const RecordType *RT = Ty->getAs()) { + + ClassTemplateSpecializationDecl *Specialization = + dyn_cast(RT->getDecl()); + if (!Specialization) + return false; + + Template = Specialization->getSpecializedTemplate(); + Arguments = Specialization->getTemplateArgs().data(); + } else if (const TemplateSpecializationType *TST = + Ty->getAs()) { + Template = dyn_cast_or_null( + TST->getTemplateName().getAsTemplateDecl()); + Arguments = TST->getArgs(); + } + if (!Template) + return false; + + if (!StdInitializerList) { + // Haven't recognized std::initializer_list yet, maybe this is it. + CXXRecordDecl *TemplateClass = Template->getTemplatedDecl(); + if (TemplateClass->getIdentifier() != + &PP.getIdentifierTable().get("initializer_list") || + !getStdNamespace()->InEnclosingNamespaceSetOf( + TemplateClass->getDeclContext())) + return false; + // This is a template called std::initializer_list, but is it the right + // template? + TemplateParameterList *Params = Template->getTemplateParameters(); + if (Params->getMinRequiredArguments() != 1) + return false; + if (!isa(Params->getParam(0))) + return false; + + // It's the right template. + StdInitializerList = Template; + } + + if (Template != StdInitializerList) + return false; + + // This is an instance of std::initializer_list. Find the argument type. + if (Element) + *Element = Arguments[0].getAsType(); + return true; +} + +static ClassTemplateDecl *LookupStdInitializerList(Sema &S, SourceLocation Loc){ + NamespaceDecl *Std = S.getStdNamespace(); + if (!Std) { + S.Diag(Loc, diag::err_implied_std_initializer_list_not_found); + return 0; + } + + LookupResult Result(S, &S.PP.getIdentifierTable().get("initializer_list"), + Loc, Sema::LookupOrdinaryName); + if (!S.LookupQualifiedName(Result, Std)) { + S.Diag(Loc, diag::err_implied_std_initializer_list_not_found); + return 0; + } + ClassTemplateDecl *Template = Result.getAsSingle(); + if (!Template) { + Result.suppressDiagnostics(); + // We found something weird. Complain about the first thing we found. + NamedDecl *Found = *Result.begin(); + S.Diag(Found->getLocation(), diag::err_malformed_std_initializer_list); + return 0; + } + + // We found some template called std::initializer_list. Now verify that it's + // correct. + TemplateParameterList *Params = Template->getTemplateParameters(); + if (Params->getMinRequiredArguments() != 1 || + !isa(Params->getParam(0))) { + S.Diag(Template->getLocation(), diag::err_malformed_std_initializer_list); + return 0; + } + + return Template; +} + +QualType Sema::BuildStdInitializerList(QualType Element, SourceLocation Loc) { + if (!StdInitializerList) { + StdInitializerList = LookupStdInitializerList(*this, Loc); + if (!StdInitializerList) + return QualType(); + } + + TemplateArgumentListInfo Args(Loc, Loc); + Args.addArgument(TemplateArgumentLoc(TemplateArgument(Element), + Context.getTrivialTypeSourceInfo(Element, + Loc))); + return Context.getCanonicalType( + CheckTemplateIdType(TemplateName(StdInitializerList), Loc, Args)); +} + +bool Sema::isInitListConstructor(const CXXConstructorDecl* Ctor) { + // C++ [dcl.init.list]p2: + // A constructor is an initializer-list constructor if its first parameter + // is of type std::initializer_list or reference to possibly cv-qualified + // std::initializer_list for some type E, and either there are no other + // parameters or else all other parameters have default arguments. + if (Ctor->getNumParams() < 1 || + (Ctor->getNumParams() > 1 && !Ctor->getParamDecl(1)->hasDefaultArg())) + return false; + + QualType ArgType = Ctor->getParamDecl(0)->getType(); + if (const ReferenceType *RT = ArgType->getAs()) + ArgType = RT->getPointeeType().getUnqualifiedType(); + + return isStdInitializerList(ArgType, 0); +} + +/// \brief Determine whether a using statement is in a context where it will be +/// apply in all contexts. +static bool IsUsingDirectiveInToplevelContext(DeclContext *CurContext) { + switch (CurContext->getDeclKind()) { + case Decl::TranslationUnit: + return true; + case Decl::LinkageSpec: + return IsUsingDirectiveInToplevelContext(CurContext->getParent()); + default: + return false; + } +} + +namespace { + +// Callback to only accept typo corrections that are namespaces. +class NamespaceValidatorCCC : public CorrectionCandidateCallback { + public: + virtual bool ValidateCandidate(const TypoCorrection &candidate) { + if (NamedDecl *ND = candidate.getCorrectionDecl()) { + return isa(ND) || isa(ND); + } + return false; + } +}; + +} + +static bool TryNamespaceTypoCorrection(Sema &S, LookupResult &R, Scope *Sc, + CXXScopeSpec &SS, + SourceLocation IdentLoc, + IdentifierInfo *Ident) { + NamespaceValidatorCCC Validator; + R.clear(); + if (TypoCorrection Corrected = S.CorrectTypo(R.getLookupNameInfo(), + R.getLookupKind(), Sc, &SS, + Validator)) { + std::string CorrectedStr(Corrected.getAsString(S.getLangOpts())); + std::string CorrectedQuotedStr(Corrected.getQuoted(S.getLangOpts())); + if (DeclContext *DC = S.computeDeclContext(SS, false)) + S.Diag(IdentLoc, diag::err_using_directive_member_suggest) + << Ident << DC << CorrectedQuotedStr << SS.getRange() + << FixItHint::CreateReplacement(IdentLoc, CorrectedStr); + else + S.Diag(IdentLoc, diag::err_using_directive_suggest) + << Ident << CorrectedQuotedStr + << FixItHint::CreateReplacement(IdentLoc, CorrectedStr); + + S.Diag(Corrected.getCorrectionDecl()->getLocation(), + diag::note_namespace_defined_here) << CorrectedQuotedStr; + + R.addDecl(Corrected.getCorrectionDecl()); + return true; + } + return false; +} + +Decl *Sema::ActOnUsingDirective(Scope *S, + SourceLocation UsingLoc, + SourceLocation NamespcLoc, + CXXScopeSpec &SS, + SourceLocation IdentLoc, + IdentifierInfo *NamespcName, + AttributeList *AttrList) { + assert(!SS.isInvalid() && "Invalid CXXScopeSpec."); + assert(NamespcName && "Invalid NamespcName."); + assert(IdentLoc.isValid() && "Invalid NamespceName location."); + + // This can only happen along a recovery path. + while (S->getFlags() & Scope::TemplateParamScope) + S = S->getParent(); + assert(S->getFlags() & Scope::DeclScope && "Invalid Scope."); + + UsingDirectiveDecl *UDir = 0; + NestedNameSpecifier *Qualifier = 0; + if (SS.isSet()) + Qualifier = static_cast(SS.getScopeRep()); + + // Lookup namespace name. + LookupResult R(*this, NamespcName, IdentLoc, LookupNamespaceName); + LookupParsedName(R, S, &SS); + if (R.isAmbiguous()) + return 0; + + if (R.empty()) { + R.clear(); + // Allow "using namespace std;" or "using namespace ::std;" even if + // "std" hasn't been defined yet, for GCC compatibility. + if ((!Qualifier || Qualifier->getKind() == NestedNameSpecifier::Global) && + NamespcName->isStr("std")) { + Diag(IdentLoc, diag::ext_using_undefined_std); + R.addDecl(getOrCreateStdNamespace()); + R.resolveKind(); + } + // Otherwise, attempt typo correction. + else TryNamespaceTypoCorrection(*this, R, S, SS, IdentLoc, NamespcName); + } + + if (!R.empty()) { + NamedDecl *Named = R.getFoundDecl(); + assert((isa(Named) || isa(Named)) + && "expected namespace decl"); + // C++ [namespace.udir]p1: + // A using-directive specifies that the names in the nominated + // namespace can be used in the scope in which the + // using-directive appears after the using-directive. During + // unqualified name lookup (3.4.1), the names appear as if they + // were declared in the nearest enclosing namespace which + // contains both the using-directive and the nominated + // namespace. [Note: in this context, "contains" means "contains + // directly or indirectly". ] + + // Find enclosing context containing both using-directive and + // nominated namespace. + NamespaceDecl *NS = getNamespaceDecl(Named); + DeclContext *CommonAncestor = cast(NS); + while (CommonAncestor && !CommonAncestor->Encloses(CurContext)) + CommonAncestor = CommonAncestor->getParent(); + + UDir = UsingDirectiveDecl::Create(Context, CurContext, UsingLoc, NamespcLoc, + SS.getWithLocInContext(Context), + IdentLoc, Named, CommonAncestor); + + if (IsUsingDirectiveInToplevelContext(CurContext) && + !SourceMgr.isFromMainFile(SourceMgr.getExpansionLoc(IdentLoc))) { + Diag(IdentLoc, diag::warn_using_directive_in_header); + } + + PushUsingDirective(S, UDir); + } else { + Diag(IdentLoc, diag::err_expected_namespace_name) << SS.getRange(); + } + + // FIXME: We ignore attributes for now. + return UDir; +} + +void Sema::PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir) { + // If the scope has an associated entity and the using directive is at + // namespace or translation unit scope, add the UsingDirectiveDecl into + // its lookup structure so qualified name lookup can find it. + DeclContext *Ctx = static_cast(S->getEntity()); + if (Ctx && !Ctx->isFunctionOrMethod()) + Ctx->addDecl(UDir); + else + // Otherwise, it is at block sope. The using-directives will affect lookup + // only to the end of the scope. + S->PushUsingDirective(UDir); +} + + +Decl *Sema::ActOnUsingDeclaration(Scope *S, + AccessSpecifier AS, + bool HasUsingKeyword, + SourceLocation UsingLoc, + CXXScopeSpec &SS, + UnqualifiedId &Name, + AttributeList *AttrList, + bool IsTypeName, + SourceLocation TypenameLoc) { + assert(S->getFlags() & Scope::DeclScope && "Invalid Scope."); + + switch (Name.getKind()) { + case UnqualifiedId::IK_ImplicitSelfParam: + case UnqualifiedId::IK_Identifier: + case UnqualifiedId::IK_OperatorFunctionId: + case UnqualifiedId::IK_LiteralOperatorId: + case UnqualifiedId::IK_ConversionFunctionId: + break; + + case UnqualifiedId::IK_ConstructorName: + case UnqualifiedId::IK_ConstructorTemplateId: + // C++11 inheriting constructors. + Diag(Name.getLocStart(), + getLangOpts().CPlusPlus0x ? + // FIXME: Produce warn_cxx98_compat_using_decl_constructor + // instead once inheriting constructors work. + diag::err_using_decl_constructor_unsupported : + diag::err_using_decl_constructor) + << SS.getRange(); + + if (getLangOpts().CPlusPlus0x) break; + + return 0; + + case UnqualifiedId::IK_DestructorName: + Diag(Name.getLocStart(), diag::err_using_decl_destructor) + << SS.getRange(); + return 0; + + case UnqualifiedId::IK_TemplateId: + Diag(Name.getLocStart(), diag::err_using_decl_template_id) + << SourceRange(Name.TemplateId->LAngleLoc, Name.TemplateId->RAngleLoc); + return 0; + } + + DeclarationNameInfo TargetNameInfo = GetNameFromUnqualifiedId(Name); + DeclarationName TargetName = TargetNameInfo.getName(); + if (!TargetName) + return 0; + + // Warn about using declarations. + // TODO: store that the declaration was written without 'using' and + // talk about access decls instead of using decls in the + // diagnostics. + if (!HasUsingKeyword) { + UsingLoc = Name.getLocStart(); + + Diag(UsingLoc, diag::warn_access_decl_deprecated) + << FixItHint::CreateInsertion(SS.getRange().getBegin(), "using "); + } + + if (DiagnoseUnexpandedParameterPack(SS, UPPC_UsingDeclaration) || + DiagnoseUnexpandedParameterPack(TargetNameInfo, UPPC_UsingDeclaration)) + return 0; + + NamedDecl *UD = BuildUsingDeclaration(S, AS, UsingLoc, SS, + TargetNameInfo, AttrList, + /* IsInstantiation */ false, + IsTypeName, TypenameLoc); + if (UD) + PushOnScopeChains(UD, S, /*AddToContext*/ false); + + return UD; +} + +/// \brief Determine whether a using declaration considers the given +/// declarations as "equivalent", e.g., if they are redeclarations of +/// the same entity or are both typedefs of the same type. +static bool +IsEquivalentForUsingDecl(ASTContext &Context, NamedDecl *D1, NamedDecl *D2, + bool &SuppressRedeclaration) { + if (D1->getCanonicalDecl() == D2->getCanonicalDecl()) { + SuppressRedeclaration = false; + return true; + } + + if (TypedefNameDecl *TD1 = dyn_cast(D1)) + if (TypedefNameDecl *TD2 = dyn_cast(D2)) { + SuppressRedeclaration = true; + return Context.hasSameType(TD1->getUnderlyingType(), + TD2->getUnderlyingType()); + } + + return false; +} + + +/// Determines whether to create a using shadow decl for a particular +/// decl, given the set of decls existing prior to this using lookup. +bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, + const LookupResult &Previous) { + // Diagnose finding a decl which is not from a base class of the + // current class. We do this now because there are cases where this + // function will silently decide not to build a shadow decl, which + // will pre-empt further diagnostics. + // + // We don't need to do this in C++0x because we do the check once on + // the qualifier. + // + // FIXME: diagnose the following if we care enough: + // struct A { int foo; }; + // struct B : A { using A::foo; }; + // template struct C : A {}; + // template struct D : C { using B::foo; } // <--- + // This is invalid (during instantiation) in C++03 because B::foo + // resolves to the using decl in B, which is not a base class of D. + // We can't diagnose it immediately because C is an unknown + // specialization. The UsingShadowDecl in D then points directly + // to A::foo, which will look well-formed when we instantiate. + // The right solution is to not collapse the shadow-decl chain. + if (!getLangOpts().CPlusPlus0x && CurContext->isRecord()) { + DeclContext *OrigDC = Orig->getDeclContext(); + + // Handle enums and anonymous structs. + if (isa(OrigDC)) OrigDC = OrigDC->getParent(); + CXXRecordDecl *OrigRec = cast(OrigDC); + while (OrigRec->isAnonymousStructOrUnion()) + OrigRec = cast(OrigRec->getDeclContext()); + + if (cast(CurContext)->isProvablyNotDerivedFrom(OrigRec)) { + if (OrigDC == CurContext) { + Diag(Using->getLocation(), + diag::err_using_decl_nested_name_specifier_is_current_class) + << Using->getQualifierLoc().getSourceRange(); + Diag(Orig->getLocation(), diag::note_using_decl_target); + return true; + } + + Diag(Using->getQualifierLoc().getBeginLoc(), + diag::err_using_decl_nested_name_specifier_is_not_base_class) + << Using->getQualifier() + << cast(CurContext) + << Using->getQualifierLoc().getSourceRange(); + Diag(Orig->getLocation(), diag::note_using_decl_target); + return true; + } + } + + if (Previous.empty()) return false; + + NamedDecl *Target = Orig; + if (isa(Target)) + Target = cast(Target)->getTargetDecl(); + + // If the target happens to be one of the previous declarations, we + // don't have a conflict. + // + // FIXME: but we might be increasing its access, in which case we + // should redeclare it. + NamedDecl *NonTag = 0, *Tag = 0; + for (LookupResult::iterator I = Previous.begin(), E = Previous.end(); + I != E; ++I) { + NamedDecl *D = (*I)->getUnderlyingDecl(); + bool Result; + if (IsEquivalentForUsingDecl(Context, D, Target, Result)) + return Result; + + (isa(D) ? Tag : NonTag) = D; + } + + if (Target->isFunctionOrFunctionTemplate()) { + FunctionDecl *FD; + if (isa(Target)) + FD = cast(Target)->getTemplatedDecl(); + else + FD = cast(Target); + + NamedDecl *OldDecl = 0; + switch (CheckOverload(0, FD, Previous, OldDecl, /*IsForUsingDecl*/ true)) { + case Ovl_Overload: + return false; + + case Ovl_NonFunction: + Diag(Using->getLocation(), diag::err_using_decl_conflict); + break; + + // We found a decl with the exact signature. + case Ovl_Match: + // If we're in a record, we want to hide the target, so we + // return true (without a diagnostic) to tell the caller not to + // build a shadow decl. + if (CurContext->isRecord()) + return true; + + // If we're not in a record, this is an error. + Diag(Using->getLocation(), diag::err_using_decl_conflict); + break; + } + + Diag(Target->getLocation(), diag::note_using_decl_target); + Diag(OldDecl->getLocation(), diag::note_using_decl_conflict); + return true; + } + + // Target is not a function. + + if (isa(Target)) { + // No conflict between a tag and a non-tag. + if (!Tag) return false; + + Diag(Using->getLocation(), diag::err_using_decl_conflict); + Diag(Target->getLocation(), diag::note_using_decl_target); + Diag(Tag->getLocation(), diag::note_using_decl_conflict); + return true; + } + + // No conflict between a tag and a non-tag. + if (!NonTag) return false; + + Diag(Using->getLocation(), diag::err_using_decl_conflict); + Diag(Target->getLocation(), diag::note_using_decl_target); + Diag(NonTag->getLocation(), diag::note_using_decl_conflict); + return true; +} + +/// Builds a shadow declaration corresponding to a 'using' declaration. +UsingShadowDecl *Sema::BuildUsingShadowDecl(Scope *S, + UsingDecl *UD, + NamedDecl *Orig) { + + // If we resolved to another shadow declaration, just coalesce them. + NamedDecl *Target = Orig; + if (isa(Target)) { + Target = cast(Target)->getTargetDecl(); + assert(!isa(Target) && "nested shadow declaration"); + } + + UsingShadowDecl *Shadow + = UsingShadowDecl::Create(Context, CurContext, + UD->getLocation(), UD, Target); + UD->addShadowDecl(Shadow); + + Shadow->setAccess(UD->getAccess()); + if (Orig->isInvalidDecl() || UD->isInvalidDecl()) + Shadow->setInvalidDecl(); + + if (S) + PushOnScopeChains(Shadow, S); + else + CurContext->addDecl(Shadow); + + + return Shadow; +} + +/// Hides a using shadow declaration. This is required by the current +/// using-decl implementation when a resolvable using declaration in a +/// class is followed by a declaration which would hide or override +/// one or more of the using decl's targets; for example: +/// +/// struct Base { void foo(int); }; +/// struct Derived : Base { +/// using Base::foo; +/// void foo(int); +/// }; +/// +/// The governing language is C++03 [namespace.udecl]p12: +/// +/// When a using-declaration brings names from a base class into a +/// derived class scope, member functions in the derived class +/// override and/or hide member functions with the same name and +/// parameter types in a base class (rather than conflicting). +/// +/// There are two ways to implement this: +/// (1) optimistically create shadow decls when they're not hidden +/// by existing declarations, or +/// (2) don't create any shadow decls (or at least don't make them +/// visible) until we've fully parsed/instantiated the class. +/// The problem with (1) is that we might have to retroactively remove +/// a shadow decl, which requires several O(n) operations because the +/// decl structures are (very reasonably) not designed for removal. +/// (2) avoids this but is very fiddly and phase-dependent. +void Sema::HideUsingShadowDecl(Scope *S, UsingShadowDecl *Shadow) { + if (Shadow->getDeclName().getNameKind() == + DeclarationName::CXXConversionFunctionName) + cast(Shadow->getDeclContext())->removeConversion(Shadow); + + // Remove it from the DeclContext... + Shadow->getDeclContext()->removeDecl(Shadow); + + // ...and the scope, if applicable... + if (S) { + S->RemoveDecl(Shadow); + IdResolver.RemoveDecl(Shadow); + } + + // ...and the using decl. + Shadow->getUsingDecl()->removeShadowDecl(Shadow); + + // TODO: complain somehow if Shadow was used. It shouldn't + // be possible for this to happen, because...? +} + +/// Builds a using declaration. +/// +/// \param IsInstantiation - Whether this call arises from an +/// instantiation of an unresolved using declaration. We treat +/// the lookup differently for these declarations. +NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, + SourceLocation UsingLoc, + CXXScopeSpec &SS, + 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. + + if (SS.isEmpty()) { + Diag(IdentLoc, diag::err_using_requires_qualname); + return 0; + } + + // Do the redeclaration lookup in the current scope. + LookupResult Previous(*this, NameInfo, LookupUsingDeclName, + ForRedeclaration); + Previous.setHideTags(false); + if (S) { + LookupName(Previous, S); + + // It is really dumb that we have to do this. + LookupResult::Filter F = Previous.makeFilter(); + while (F.hasNext()) { + NamedDecl *D = F.next(); + if (!isDeclInScope(D, CurContext, S)) + F.erase(); + } + F.done(); + } else { + assert(IsInstantiation && "no scope in non-instantiation"); + assert(CurContext->isRecord() && "scope not record in instantiation"); + LookupQualifiedName(Previous, CurContext); + } + + // Check for invalid redeclarations. + if (CheckUsingDeclRedeclaration(UsingLoc, IsTypeName, SS, IdentLoc, Previous)) + return 0; + + // Check for bad qualifiers. + if (CheckUsingDeclQualifier(UsingLoc, SS, IdentLoc)) + return 0; + + DeclContext *LookupContext = computeDeclContext(SS); + NamedDecl *D; + NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context); + if (!LookupContext) { + if (IsTypeName) { + // FIXME: not all declaration name kinds are legal here + D = UnresolvedUsingTypenameDecl::Create(Context, CurContext, + UsingLoc, TypenameLoc, + QualifierLoc, + IdentLoc, NameInfo.getName()); + } else { + D = UnresolvedUsingValueDecl::Create(Context, CurContext, UsingLoc, + QualifierLoc, NameInfo); + } + } else { + D = UsingDecl::Create(Context, CurContext, UsingLoc, QualifierLoc, + NameInfo, IsTypeName); + } + D->setAccess(AS); + CurContext->addDecl(D); + + if (!LookupContext) return D; + UsingDecl *UD = cast(D); + + if (RequireCompleteDeclContext(SS, LookupContext)) { + UD->setInvalidDecl(); + return UD; + } + + // The normal rules do not apply to inheriting constructor declarations. + if (NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName) { + if (CheckInheritingConstructorUsingDecl(UD)) + UD->setInvalidDecl(); + return UD; + } + + // Otherwise, look up the target name. + + 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 + // even if hidden by ordinary names, *except* in a dependent context + // where it's important for the sanity of two-phase lookup. + if (!IsInstantiation) + R.setHideTags(false); + + // For the purposes of this lookup, we have a base object type + // equal to that of the current context. + if (CurContext->isRecord()) { + R.setBaseObjectType( + Context.getTypeDeclType(cast(CurContext))); + } + + LookupQualifiedName(R, LookupContext); + + if (R.empty()) { + Diag(IdentLoc, diag::err_no_member) + << NameInfo.getName() << LookupContext << SS.getRange(); + UD->setInvalidDecl(); + return UD; + } + + if (R.isAmbiguous()) { + UD->setInvalidDecl(); + return UD; + } + + if (IsTypeName) { + // If we asked for a typename and got a non-type decl, error out. + if (!R.getAsSingle()) { + Diag(IdentLoc, diag::err_using_typename_non_type); + for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) + Diag((*I)->getUnderlyingDecl()->getLocation(), + diag::note_using_decl_target); + UD->setInvalidDecl(); + return UD; + } + } else { + // If we asked for a non-typename and we got a type, error out, + // but only if this is an instantiation of an unresolved using + // decl. Otherwise just silently find the type name. + if (IsInstantiation && R.getAsSingle()) { + Diag(IdentLoc, diag::err_using_dependent_value_is_type); + Diag(R.getFoundDecl()->getLocation(), diag::note_using_decl_target); + UD->setInvalidDecl(); + return UD; + } + } + + // C++0x N2914 [namespace.udecl]p6: + // A using-declaration shall not name a namespace. + if (R.getAsSingle()) { + Diag(IdentLoc, diag::err_using_decl_can_not_refer_to_namespace) + << SS.getRange(); + UD->setInvalidDecl(); + return UD; + } + + for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { + if (!CheckUsingShadowDecl(UD, *I, Previous)) + BuildUsingShadowDecl(S, UD, *I); + } + + return UD; +} + +/// Additional checks for a using declaration referring to a constructor name. +bool Sema::CheckInheritingConstructorUsingDecl(UsingDecl *UD) { + assert(!UD->isTypeName() && "expecting a constructor name"); + + const Type *SourceType = UD->getQualifier()->getAsType(); + assert(SourceType && + "Using decl naming constructor doesn't have type in scope spec."); + CXXRecordDecl *TargetClass = cast(CurContext); + + // Check whether the named type is a direct base class. + CanQualType CanonicalSourceType = SourceType->getCanonicalTypeUnqualified(); + CXXRecordDecl::base_class_iterator BaseIt, BaseE; + for (BaseIt = TargetClass->bases_begin(), BaseE = TargetClass->bases_end(); + BaseIt != BaseE; ++BaseIt) { + CanQualType BaseType = BaseIt->getType()->getCanonicalTypeUnqualified(); + if (CanonicalSourceType == BaseType) + break; + if (BaseIt->getType()->isDependentType()) + break; + } + + if (BaseIt == BaseE) { + // Did not find SourceType in the bases. + Diag(UD->getUsingLocation(), + diag::err_using_decl_constructor_not_in_direct_base) + << UD->getNameInfo().getSourceRange() + << QualType(SourceType, 0) << TargetClass; + return true; + } + + if (!CurContext->isDependentContext()) + BaseIt->setInheritConstructors(); + + return false; +} + +/// Checks that the given using declaration is not an invalid +/// redeclaration. Note that this is checking only for the using decl +/// itself, not for any ill-formedness among the UsingShadowDecls. +bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc, + bool isTypeName, + const CXXScopeSpec &SS, + SourceLocation NameLoc, + const LookupResult &Prev) { + // C++03 [namespace.udecl]p8: + // C++0x [namespace.udecl]p10: + // A using-declaration is a declaration and can therefore be used + // repeatedly where (and only where) multiple declarations are + // allowed. + // + // That's in non-member contexts. + if (!CurContext->getRedeclContext()->isRecord()) + return false; + + NestedNameSpecifier *Qual + = static_cast(SS.getScopeRep()); + + for (LookupResult::iterator I = Prev.begin(), E = Prev.end(); I != E; ++I) { + NamedDecl *D = *I; + + bool DTypename; + NestedNameSpecifier *DQual; + if (UsingDecl *UD = dyn_cast(D)) { + DTypename = UD->isTypeName(); + DQual = UD->getQualifier(); + } else if (UnresolvedUsingValueDecl *UD + = dyn_cast(D)) { + DTypename = false; + DQual = UD->getQualifier(); + } else if (UnresolvedUsingTypenameDecl *UD + = dyn_cast(D)) { + DTypename = true; + DQual = UD->getQualifier(); + } else continue; + + // using decls differ if one says 'typename' and the other doesn't. + // FIXME: non-dependent using decls? + if (isTypeName != DTypename) continue; + + // using decls differ if they name different scopes (but note that + // template instantiation can cause this check to trigger when it + // didn't before instantiation). + if (Context.getCanonicalNestedNameSpecifier(Qual) != + Context.getCanonicalNestedNameSpecifier(DQual)) + continue; + + Diag(NameLoc, diag::err_using_decl_redeclaration) << SS.getRange(); + Diag(D->getLocation(), diag::note_using_decl) << 1; + return true; + } + + return false; +} + + +/// Checks that the given nested-name qualifier used in a using decl +/// in the current context is appropriately related to the current +/// scope. If an error is found, diagnoses it and returns true. +bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc, + const CXXScopeSpec &SS, + SourceLocation NameLoc) { + DeclContext *NamedContext = computeDeclContext(SS); + + if (!CurContext->isRecord()) { + // C++03 [namespace.udecl]p3: + // C++0x [namespace.udecl]p8: + // A using-declaration for a class member shall be a member-declaration. + + // If we weren't able to compute a valid scope, it must be a + // dependent class scope. + if (!NamedContext || NamedContext->isRecord()) { + Diag(NameLoc, diag::err_using_decl_can_not_refer_to_class_member) + << SS.getRange(); + return true; + } + + // Otherwise, everything is known to be fine. + return false; + } + + // The current scope is a record. + + // If the named context is dependent, we can't decide much. + if (!NamedContext) { + // FIXME: in C++0x, we can diagnose if we can prove that the + // nested-name-specifier does not refer to a base class, which is + // still possible in some cases. + + // Otherwise we have to conservatively report that things might be + // okay. + return false; + } + + if (!NamedContext->isRecord()) { + // Ideally this would point at the last name in the specifier, + // but we don't have that level of source info. + Diag(SS.getRange().getBegin(), + diag::err_using_decl_nested_name_specifier_is_not_class) + << (NestedNameSpecifier*) SS.getScopeRep() << SS.getRange(); + return true; + } + + if (!NamedContext->isDependentContext() && + RequireCompleteDeclContext(const_cast(SS), NamedContext)) + return true; + + if (getLangOpts().CPlusPlus0x) { + // C++0x [namespace.udecl]p3: + // In a using-declaration used as a member-declaration, the + // nested-name-specifier shall name a base class of the class + // being defined. + + if (cast(CurContext)->isProvablyNotDerivedFrom( + cast(NamedContext))) { + if (CurContext == NamedContext) { + Diag(NameLoc, + diag::err_using_decl_nested_name_specifier_is_current_class) + << SS.getRange(); + return true; + } + + Diag(SS.getRange().getBegin(), + diag::err_using_decl_nested_name_specifier_is_not_base_class) + << (NestedNameSpecifier*) SS.getScopeRep() + << cast(CurContext) + << SS.getRange(); + return true; + } + + return false; + } + + // C++03 [namespace.udecl]p4: + // A using-declaration used as a member-declaration shall refer + // to a member of a base class of the class being defined [etc.]. + + // Salient point: SS doesn't have to name a base class as long as + // lookup only finds members from base classes. Therefore we can + // diagnose here only if we can prove that that can't happen, + // i.e. if the class hierarchies provably don't intersect. + + // TODO: it would be nice if "definitely valid" results were cached + // in the UsingDecl and UsingShadowDecl so that these checks didn't + // need to be repeated. + + struct UserData { + llvm::SmallPtrSet Bases; + + static bool collect(const CXXRecordDecl *Base, void *OpaqueData) { + UserData *Data = reinterpret_cast(OpaqueData); + Data->Bases.insert(Base); + return true; + } + + bool hasDependentBases(const CXXRecordDecl *Class) { + return !Class->forallBases(collect, this); + } + + /// Returns true if the base is dependent or is one of the + /// accumulated base classes. + static bool doesNotContain(const CXXRecordDecl *Base, void *OpaqueData) { + UserData *Data = reinterpret_cast(OpaqueData); + return !Data->Bases.count(Base); + } + + bool mightShareBases(const CXXRecordDecl *Class) { + return Bases.count(Class) || !Class->forallBases(doesNotContain, this); + } + }; + + UserData Data; + + // Returns false if we find a dependent base. + if (Data.hasDependentBases(cast(CurContext))) + return false; + + // Returns false if the class has a dependent base or if it or one + // of its bases is present in the base set of the current context. + if (Data.mightShareBases(cast(NamedContext))) + return false; + + Diag(SS.getRange().getBegin(), + diag::err_using_decl_nested_name_specifier_is_not_base_class) + << (NestedNameSpecifier*) SS.getScopeRep() + << cast(CurContext) + << SS.getRange(); + + return true; +} + +Decl *Sema::ActOnAliasDeclaration(Scope *S, + AccessSpecifier AS, + MultiTemplateParamsArg TemplateParamLists, + SourceLocation UsingLoc, + UnqualifiedId &Name, + TypeResult Type) { + // Skip up to the relevant declaration scope. + while (S->getFlags() & Scope::TemplateParamScope) + S = S->getParent(); + assert((S->getFlags() & Scope::DeclScope) && + "got alias-declaration outside of declaration scope"); + + if (Type.isInvalid()) + return 0; + + bool Invalid = false; + DeclarationNameInfo NameInfo = GetNameFromUnqualifiedId(Name); + TypeSourceInfo *TInfo = 0; + GetTypeFromParser(Type.get(), &TInfo); + + if (DiagnoseClassNameShadow(CurContext, NameInfo)) + return 0; + + if (DiagnoseUnexpandedParameterPack(Name.StartLocation, TInfo, + UPPC_DeclarationType)) { + Invalid = true; + TInfo = Context.getTrivialTypeSourceInfo(Context.IntTy, + TInfo->getTypeLoc().getBeginLoc()); + } + + LookupResult Previous(*this, NameInfo, LookupOrdinaryName, ForRedeclaration); + LookupName(Previous, S); + + // Warn about shadowing the name of a template parameter. + if (Previous.isSingleResult() && + Previous.getFoundDecl()->isTemplateParameter()) { + DiagnoseTemplateParameterShadow(Name.StartLocation,Previous.getFoundDecl()); + Previous.clear(); + } + + assert(Name.Kind == UnqualifiedId::IK_Identifier && + "name in alias declaration must be an identifier"); + TypeAliasDecl *NewTD = TypeAliasDecl::Create(Context, CurContext, UsingLoc, + Name.StartLocation, + Name.Identifier, TInfo); + + NewTD->setAccess(AS); + + if (Invalid) + NewTD->setInvalidDecl(); + + CheckTypedefForVariablyModifiedType(S, NewTD); + Invalid |= NewTD->isInvalidDecl(); + + bool Redeclaration = false; + + NamedDecl *NewND; + if (TemplateParamLists.size()) { + TypeAliasTemplateDecl *OldDecl = 0; + TemplateParameterList *OldTemplateParams = 0; + + if (TemplateParamLists.size() != 1) { + Diag(UsingLoc, diag::err_alias_template_extra_headers) + << SourceRange(TemplateParamLists.get()[1]->getTemplateLoc(), + TemplateParamLists.get()[TemplateParamLists.size()-1]->getRAngleLoc()); + } + TemplateParameterList *TemplateParams = TemplateParamLists.get()[0]; + + // Only consider previous declarations in the same scope. + FilterLookupForScope(Previous, CurContext, S, /*ConsiderLinkage*/false, + /*ExplicitInstantiationOrSpecialization*/false); + if (!Previous.empty()) { + Redeclaration = true; + + OldDecl = Previous.getAsSingle(); + if (!OldDecl && !Invalid) { + Diag(UsingLoc, diag::err_redefinition_different_kind) + << Name.Identifier; + + NamedDecl *OldD = Previous.getRepresentativeDecl(); + if (OldD->getLocation().isValid()) + Diag(OldD->getLocation(), diag::note_previous_definition); + + Invalid = true; + } + + if (!Invalid && OldDecl && !OldDecl->isInvalidDecl()) { + if (TemplateParameterListsAreEqual(TemplateParams, + OldDecl->getTemplateParameters(), + /*Complain=*/true, + TPL_TemplateMatch)) + OldTemplateParams = OldDecl->getTemplateParameters(); + else + Invalid = true; + + TypeAliasDecl *OldTD = OldDecl->getTemplatedDecl(); + if (!Invalid && + !Context.hasSameType(OldTD->getUnderlyingType(), + NewTD->getUnderlyingType())) { + // FIXME: The C++0x standard does not clearly say this is ill-formed, + // but we can't reasonably accept it. + Diag(NewTD->getLocation(), diag::err_redefinition_different_typedef) + << 2 << NewTD->getUnderlyingType() << OldTD->getUnderlyingType(); + if (OldTD->getLocation().isValid()) + Diag(OldTD->getLocation(), diag::note_previous_definition); + Invalid = true; + } + } + } + + // Merge any previous default template arguments into our parameters, + // and check the parameter list. + if (CheckTemplateParameterList(TemplateParams, OldTemplateParams, + TPC_TypeAliasTemplate)) + return 0; + + TypeAliasTemplateDecl *NewDecl = + TypeAliasTemplateDecl::Create(Context, CurContext, UsingLoc, + Name.Identifier, TemplateParams, + NewTD); + + NewDecl->setAccess(AS); + + if (Invalid) + NewDecl->setInvalidDecl(); + else if (OldDecl) + NewDecl->setPreviousDeclaration(OldDecl); + + NewND = NewDecl; + } else { + ActOnTypedefNameDecl(S, CurContext, NewTD, Previous, Redeclaration); + NewND = NewTD; + } + + if (!Redeclaration) + PushOnScopeChains(NewND, S); + + return NewND; +} + +Decl *Sema::ActOnNamespaceAliasDef(Scope *S, + SourceLocation NamespaceLoc, + SourceLocation AliasLoc, + IdentifierInfo *Alias, + CXXScopeSpec &SS, + SourceLocation IdentLoc, + IdentifierInfo *Ident) { + + // Lookup the namespace name. + LookupResult R(*this, Ident, IdentLoc, LookupNamespaceName); + LookupParsedName(R, S, &SS); + + // Check if we have a previous declaration with the same name. + NamedDecl *PrevDecl + = LookupSingleName(S, Alias, AliasLoc, LookupOrdinaryName, + ForRedeclaration); + if (PrevDecl && !isDeclInScope(PrevDecl, CurContext, S)) + PrevDecl = 0; + + if (PrevDecl) { + if (NamespaceAliasDecl *AD = dyn_cast(PrevDecl)) { + // We already have an alias with the same name that points to the same + // namespace, so don't create a new one. + // FIXME: At some point, we'll want to create the (redundant) + // declaration to maintain better source information. + if (!R.isAmbiguous() && !R.empty() && + AD->getNamespace()->Equals(getNamespaceDecl(R.getFoundDecl()))) + 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 0; + } + + if (R.isAmbiguous()) + return 0; + + if (R.empty()) { + if (!TryNamespaceTypoCorrection(*this, R, S, SS, IdentLoc, Ident)) { + Diag(IdentLoc, diag::err_expected_namespace_name) << SS.getRange(); + return 0; + } + } + + NamespaceAliasDecl *AliasDecl = + NamespaceAliasDecl::Create(Context, CurContext, NamespaceLoc, AliasLoc, + Alias, SS.getWithLocInContext(Context), + IdentLoc, R.getFoundDecl()); + + PushOnScopeChains(AliasDecl, S); + return AliasDecl; +} + +namespace { + /// \brief Scoped object used to handle the state changes required in Sema + /// to implicitly define the body of a C++ member function; + class ImplicitlyDefinedFunctionScope { + Sema &S; + Sema::ContextRAII SavedContext; + + public: + ImplicitlyDefinedFunctionScope(Sema &S, CXXMethodDecl *Method) + : S(S), SavedContext(S, Method) + { + S.PushFunctionScope(); + S.PushExpressionEvaluationContext(Sema::PotentiallyEvaluated); + } + + ~ImplicitlyDefinedFunctionScope() { + S.PopExpressionEvaluationContext(); + S.PopFunctionScopeInfo(); + } + }; +} + +Sema::ImplicitExceptionSpecification +Sema::ComputeDefaultedDefaultCtorExceptionSpec(CXXRecordDecl *ClassDecl) { + // C++ [except.spec]p14: + // An implicitly declared special member function (Clause 12) shall have an + // exception-specification. [...] + ImplicitExceptionSpecification ExceptSpec(*this); + if (ClassDecl->isInvalidDecl()) + return ExceptSpec; + + // Direct base-class constructors. + for (CXXRecordDecl::base_class_iterator B = ClassDecl->bases_begin(), + BEnd = ClassDecl->bases_end(); + B != BEnd; ++B) { + if (B->isVirtual()) // Handled below. + continue; + + if (const RecordType *BaseType = B->getType()->getAs()) { + CXXRecordDecl *BaseClassDecl = cast(BaseType->getDecl()); + CXXConstructorDecl *Constructor = LookupDefaultConstructor(BaseClassDecl); + // If this is a deleted function, add it anyway. This might be conformant + // with the standard. This might not. I'm not sure. It might not matter. + if (Constructor) + ExceptSpec.CalledDecl(B->getLocStart(), Constructor); + } + } + + // Virtual base-class constructors. + for (CXXRecordDecl::base_class_iterator B = ClassDecl->vbases_begin(), + BEnd = ClassDecl->vbases_end(); + B != BEnd; ++B) { + if (const RecordType *BaseType = B->getType()->getAs()) { + CXXRecordDecl *BaseClassDecl = cast(BaseType->getDecl()); + CXXConstructorDecl *Constructor = LookupDefaultConstructor(BaseClassDecl); + // If this is a deleted function, add it anyway. This might be conformant + // with the standard. This might not. I'm not sure. It might not matter. + if (Constructor) + ExceptSpec.CalledDecl(B->getLocStart(), Constructor); + } + } + + // Field constructors. + for (RecordDecl::field_iterator F = ClassDecl->field_begin(), + FEnd = ClassDecl->field_end(); + F != FEnd; ++F) { + if (F->hasInClassInitializer()) { + if (Expr *E = F->getInClassInitializer()) + ExceptSpec.CalledExpr(E); + else if (!F->isInvalidDecl()) + ExceptSpec.SetDelayed(); + } else if (const RecordType *RecordTy + = Context.getBaseElementType(F->getType())->getAs()) { + CXXRecordDecl *FieldRecDecl = cast(RecordTy->getDecl()); + CXXConstructorDecl *Constructor = LookupDefaultConstructor(FieldRecDecl); + // If this is a deleted function, add it anyway. This might be conformant + // with the standard. This might not. I'm not sure. It might not matter. + // In particular, the problem is that this function never gets called. It + // might just be ill-formed because this function attempts to refer to + // a deleted function here. + if (Constructor) + ExceptSpec.CalledDecl(F->getLocation(), Constructor); + } + } + + return ExceptSpec; +} + +CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( + CXXRecordDecl *ClassDecl) { + // C++ [class.ctor]p5: + // A default constructor for a class X is a constructor of class X + // that can be called without an argument. If there is no + // user-declared constructor for class X, a default constructor is + // implicitly declared. An implicitly-declared default constructor + // is an inline public member of its class. + assert(!ClassDecl->hasUserDeclaredConstructor() && + "Should not build implicit default constructor!"); + + ImplicitExceptionSpecification Spec = + ComputeDefaultedDefaultCtorExceptionSpec(ClassDecl); + FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI(); + + // Create the actual constructor declaration. + CanQualType ClassType + = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl)); + SourceLocation ClassLoc = ClassDecl->getLocation(); + DeclarationName Name + = Context.DeclarationNames.getCXXConstructorName(ClassType); + DeclarationNameInfo NameInfo(Name, ClassLoc); + CXXConstructorDecl *DefaultCon = CXXConstructorDecl::Create( + Context, ClassDecl, ClassLoc, NameInfo, + Context.getFunctionType(Context.VoidTy, 0, 0, EPI), /*TInfo=*/0, + /*isExplicit=*/false, /*isInline=*/true, /*isImplicitlyDeclared=*/true, + /*isConstexpr=*/ClassDecl->defaultedDefaultConstructorIsConstexpr() && + getLangOpts().CPlusPlus0x); + DefaultCon->setAccess(AS_public); + DefaultCon->setDefaulted(); + DefaultCon->setImplicit(); + DefaultCon->setTrivial(ClassDecl->hasTrivialDefaultConstructor()); + + // Note that we have declared this constructor. + ++ASTContext::NumImplicitDefaultConstructorsDeclared; + + if (Scope *S = getScopeForContext(ClassDecl)) + PushOnScopeChains(DefaultCon, S, false); + ClassDecl->addDecl(DefaultCon); + + if (ShouldDeleteSpecialMember(DefaultCon, CXXDefaultConstructor)) + DefaultCon->setDeletedAsWritten(); + + return DefaultCon; +} + +void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, + CXXConstructorDecl *Constructor) { + assert((Constructor->isDefaulted() && Constructor->isDefaultConstructor() && + !Constructor->doesThisDeclarationHaveABody() && + !Constructor->isDeleted()) && + "DefineImplicitDefaultConstructor - call it for implicit default ctor"); + + CXXRecordDecl *ClassDecl = Constructor->getParent(); + assert(ClassDecl && "DefineImplicitDefaultConstructor - invalid constructor"); + + ImplicitlyDefinedFunctionScope Scope(*this, Constructor); + DiagnosticErrorTrap Trap(Diags); + if (SetCtorInitializers(Constructor, 0, 0, /*AnyErrors=*/false) || + Trap.hasErrorOccurred()) { + Diag(CurrentLocation, diag::note_member_synthesized_at) + << CXXDefaultConstructor << Context.getTagDeclType(ClassDecl); + Constructor->setInvalidDecl(); + return; + } + + SourceLocation Loc = Constructor->getLocation(); + Constructor->setBody(new (Context) CompoundStmt(Context, 0, 0, Loc, Loc)); + + Constructor->setUsed(); + MarkVTableUsed(CurrentLocation, ClassDecl); + + if (ASTMutationListener *L = getASTMutationListener()) { + L->CompletedImplicitDefinition(Constructor); + } +} + +/// Get any existing defaulted default constructor for the given class. Do not +/// implicitly define one if it does not exist. +static CXXConstructorDecl *getDefaultedDefaultConstructorUnsafe(Sema &Self, + CXXRecordDecl *D) { + ASTContext &Context = Self.Context; + QualType ClassType = Context.getTypeDeclType(D); + DeclarationName ConstructorName + = Context.DeclarationNames.getCXXConstructorName( + Context.getCanonicalType(ClassType.getUnqualifiedType())); + + DeclContext::lookup_const_iterator Con, ConEnd; + for (llvm::tie(Con, ConEnd) = D->lookup(ConstructorName); + Con != ConEnd; ++Con) { + // A function template cannot be defaulted. + if (isa(*Con)) + continue; + + CXXConstructorDecl *Constructor = cast(*Con); + if (Constructor->isDefaultConstructor()) + return Constructor->isDefaulted() ? Constructor : 0; + } + return 0; +} + +void Sema::ActOnFinishDelayedMemberInitializers(Decl *D) { + if (!D) return; + AdjustDeclIfTemplate(D); + + CXXRecordDecl *ClassDecl = cast(D); + CXXConstructorDecl *CtorDecl + = getDefaultedDefaultConstructorUnsafe(*this, ClassDecl); + + if (!CtorDecl) return; + + // Compute the exception specification for the default constructor. + const FunctionProtoType *CtorTy = + CtorDecl->getType()->castAs(); + if (CtorTy->getExceptionSpecType() == EST_Delayed) { + // FIXME: Don't do this unless the exception spec is needed. + ImplicitExceptionSpecification Spec = + ComputeDefaultedDefaultCtorExceptionSpec(ClassDecl); + FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI(); + assert(EPI.ExceptionSpecType != EST_Delayed); + + CtorDecl->setType(Context.getFunctionType(Context.VoidTy, 0, 0, EPI)); + } + + // If the default constructor is explicitly defaulted, checking the exception + // specification is deferred until now. + if (!CtorDecl->isInvalidDecl() && CtorDecl->isExplicitlyDefaulted() && + !ClassDecl->isDependentType()) + CheckExplicitlyDefaultedDefaultConstructor(CtorDecl); +} + +void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) { + // We start with an initial pass over the base classes to collect those that + // inherit constructors from. If there are none, we can forgo all further + // processing. + typedef SmallVector BasesVector; + BasesVector BasesToInheritFrom; + for (CXXRecordDecl::base_class_iterator BaseIt = ClassDecl->bases_begin(), + BaseE = ClassDecl->bases_end(); + BaseIt != BaseE; ++BaseIt) { + if (BaseIt->getInheritConstructors()) { + QualType Base = BaseIt->getType(); + if (Base->isDependentType()) { + // If we inherit constructors from anything that is dependent, just + // abort processing altogether. We'll get another chance for the + // instantiations. + return; + } + BasesToInheritFrom.push_back(Base->castAs()); + } + } + if (BasesToInheritFrom.empty()) + return; + + // Now collect the constructors that we already have in the current class. + // Those take precedence over inherited constructors. + // C++0x [class.inhctor]p3: [...] a constructor is implicitly declared [...] + // unless there is a user-declared constructor with the same signature in + // the class where the using-declaration appears. + llvm::SmallSet ExistingConstructors; + for (CXXRecordDecl::ctor_iterator CtorIt = ClassDecl->ctor_begin(), + CtorE = ClassDecl->ctor_end(); + CtorIt != CtorE; ++CtorIt) { + ExistingConstructors.insert( + Context.getCanonicalType(CtorIt->getType()).getTypePtr()); + } + + DeclarationName CreatedCtorName = + Context.DeclarationNames.getCXXConstructorName( + ClassDecl->getTypeForDecl()->getCanonicalTypeUnqualified()); + + // Now comes the true work. + // First, we keep a map from constructor types to the base that introduced + // them. Needed for finding conflicting constructors. We also keep the + // actually inserted declarations in there, for pretty diagnostics. + typedef std::pair ConstructorInfo; + typedef llvm::DenseMap ConstructorToSourceMap; + ConstructorToSourceMap InheritedConstructors; + for (BasesVector::iterator BaseIt = BasesToInheritFrom.begin(), + BaseE = BasesToInheritFrom.end(); + BaseIt != BaseE; ++BaseIt) { + const RecordType *Base = *BaseIt; + CanQualType CanonicalBase = Base->getCanonicalTypeUnqualified(); + CXXRecordDecl *BaseDecl = cast(Base->getDecl()); + for (CXXRecordDecl::ctor_iterator CtorIt = BaseDecl->ctor_begin(), + CtorE = BaseDecl->ctor_end(); + CtorIt != CtorE; ++CtorIt) { + // Find the using declaration for inheriting this base's constructors. + // FIXME: Don't perform name lookup just to obtain a source location! + DeclarationName Name = + Context.DeclarationNames.getCXXConstructorName(CanonicalBase); + LookupResult Result(*this, Name, SourceLocation(), LookupUsingDeclName); + LookupQualifiedName(Result, CurContext); + UsingDecl *UD = Result.getAsSingle(); + SourceLocation UsingLoc = UD ? UD->getLocation() : + ClassDecl->getLocation(); + + // C++0x [class.inhctor]p1: The candidate set of inherited constructors + // from the class X named in the using-declaration consists of actual + // constructors and notional constructors that result from the + // transformation of defaulted parameters as follows: + // - all non-template default constructors of X, and + // - for each non-template constructor of X that has at least one + // parameter with a default argument, the set of constructors that + // results from omitting any ellipsis parameter specification and + // successively omitting parameters with a default argument from the + // end of the parameter-type-list. + CXXConstructorDecl *BaseCtor = *CtorIt; + bool CanBeCopyOrMove = BaseCtor->isCopyOrMoveConstructor(); + const FunctionProtoType *BaseCtorType = + BaseCtor->getType()->getAs(); + + for (unsigned params = BaseCtor->getMinRequiredArguments(), + maxParams = BaseCtor->getNumParams(); + params <= maxParams; ++params) { + // Skip default constructors. They're never inherited. + if (params == 0) + continue; + // Skip copy and move constructors for the same reason. + if (CanBeCopyOrMove && params == 1) + continue; + + // Build up a function type for this particular constructor. + // FIXME: The working paper does not consider that the exception spec + // for the inheriting constructor might be larger than that of the + // source. This code doesn't yet, either. When it does, this code will + // need to be delayed until after exception specifications and in-class + // member initializers are attached. + const Type *NewCtorType; + if (params == maxParams) + NewCtorType = BaseCtorType; + else { + SmallVector Args; + for (unsigned i = 0; i < params; ++i) { + Args.push_back(BaseCtorType->getArgType(i)); + } + FunctionProtoType::ExtProtoInfo ExtInfo = + BaseCtorType->getExtProtoInfo(); + ExtInfo.Variadic = false; + NewCtorType = Context.getFunctionType(BaseCtorType->getResultType(), + Args.data(), params, ExtInfo) + .getTypePtr(); + } + const Type *CanonicalNewCtorType = + Context.getCanonicalType(NewCtorType); + + // Now that we have the type, first check if the class already has a + // constructor with this signature. + if (ExistingConstructors.count(CanonicalNewCtorType)) + continue; + + // Then we check if we have already declared an inherited constructor + // with this signature. + std::pair result = + InheritedConstructors.insert(std::make_pair( + CanonicalNewCtorType, + std::make_pair(CanonicalBase, (CXXConstructorDecl*)0))); + if (!result.second) { + // Already in the map. If it came from a different class, that's an + // error. Not if it's from the same. + CanQualType PreviousBase = result.first->second.first; + if (CanonicalBase != PreviousBase) { + const CXXConstructorDecl *PrevCtor = result.first->second.second; + const CXXConstructorDecl *PrevBaseCtor = + PrevCtor->getInheritedConstructor(); + assert(PrevBaseCtor && "Conflicting constructor was not inherited"); + + Diag(UsingLoc, diag::err_using_decl_constructor_conflict); + Diag(BaseCtor->getLocation(), + diag::note_using_decl_constructor_conflict_current_ctor); + Diag(PrevBaseCtor->getLocation(), + diag::note_using_decl_constructor_conflict_previous_ctor); + Diag(PrevCtor->getLocation(), + diag::note_using_decl_constructor_conflict_previous_using); + } + continue; + } + + // OK, we're there, now add the constructor. + // C++0x [class.inhctor]p8: [...] that would be performed by a + // user-written inline constructor [...] + DeclarationNameInfo DNI(CreatedCtorName, UsingLoc); + CXXConstructorDecl *NewCtor = CXXConstructorDecl::Create( + Context, ClassDecl, UsingLoc, DNI, QualType(NewCtorType, 0), + /*TInfo=*/0, BaseCtor->isExplicit(), /*Inline=*/true, + /*ImplicitlyDeclared=*/true, + // FIXME: Due to a defect in the standard, we treat inherited + // constructors as constexpr even if that makes them ill-formed. + /*Constexpr=*/BaseCtor->isConstexpr()); + NewCtor->setAccess(BaseCtor->getAccess()); + + // Build up the parameter decls and add them. + SmallVector ParamDecls; + for (unsigned i = 0; i < params; ++i) { + ParamDecls.push_back(ParmVarDecl::Create(Context, NewCtor, + UsingLoc, UsingLoc, + /*IdentifierInfo=*/0, + BaseCtorType->getArgType(i), + /*TInfo=*/0, SC_None, + SC_None, /*DefaultArg=*/0)); + } + NewCtor->setParams(ParamDecls); + NewCtor->setInheritedConstructor(BaseCtor); + + ClassDecl->addDecl(NewCtor); + result.first->second.second = NewCtor; + } + } + } +} + +Sema::ImplicitExceptionSpecification +Sema::ComputeDefaultedDtorExceptionSpec(CXXRecordDecl *ClassDecl) { + // C++ [except.spec]p14: + // An implicitly declared special member function (Clause 12) shall have + // an exception-specification. + ImplicitExceptionSpecification ExceptSpec(*this); + if (ClassDecl->isInvalidDecl()) + return ExceptSpec; + + // Direct base-class destructors. + for (CXXRecordDecl::base_class_iterator B = ClassDecl->bases_begin(), + BEnd = ClassDecl->bases_end(); + B != BEnd; ++B) { + if (B->isVirtual()) // Handled below. + continue; + + if (const RecordType *BaseType = B->getType()->getAs()) + ExceptSpec.CalledDecl(B->getLocStart(), + LookupDestructor(cast(BaseType->getDecl()))); + } + + // Virtual base-class destructors. + for (CXXRecordDecl::base_class_iterator B = ClassDecl->vbases_begin(), + BEnd = ClassDecl->vbases_end(); + B != BEnd; ++B) { + if (const RecordType *BaseType = B->getType()->getAs()) + ExceptSpec.CalledDecl(B->getLocStart(), + LookupDestructor(cast(BaseType->getDecl()))); + } + + // Field destructors. + for (RecordDecl::field_iterator F = ClassDecl->field_begin(), + FEnd = ClassDecl->field_end(); + F != FEnd; ++F) { + if (const RecordType *RecordTy + = Context.getBaseElementType(F->getType())->getAs()) + ExceptSpec.CalledDecl(F->getLocation(), + LookupDestructor(cast(RecordTy->getDecl()))); + } + + return ExceptSpec; +} + +CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) { + // C++ [class.dtor]p2: + // If a class has no user-declared destructor, a destructor is + // declared implicitly. An implicitly-declared destructor is an + // inline public member of its class. + + ImplicitExceptionSpecification Spec = + ComputeDefaultedDtorExceptionSpec(ClassDecl); + FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI(); + + // Create the actual destructor declaration. + QualType Ty = Context.getFunctionType(Context.VoidTy, 0, 0, EPI); + + CanQualType ClassType + = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl)); + SourceLocation ClassLoc = ClassDecl->getLocation(); + DeclarationName Name + = Context.DeclarationNames.getCXXDestructorName(ClassType); + DeclarationNameInfo NameInfo(Name, ClassLoc); + CXXDestructorDecl *Destructor + = CXXDestructorDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, Ty, 0, + /*isInline=*/true, + /*isImplicitlyDeclared=*/true); + Destructor->setAccess(AS_public); + Destructor->setDefaulted(); + Destructor->setImplicit(); + Destructor->setTrivial(ClassDecl->hasTrivialDestructor()); + + // Note that we have declared this destructor. + ++ASTContext::NumImplicitDestructorsDeclared; + + // Introduce this destructor into its scope. + if (Scope *S = getScopeForContext(ClassDecl)) + PushOnScopeChains(Destructor, S, false); + ClassDecl->addDecl(Destructor); + + // This could be uniqued if it ever proves significant. + Destructor->setTypeSourceInfo(Context.getTrivialTypeSourceInfo(Ty)); + + AddOverriddenMethods(ClassDecl, Destructor); + + if (ShouldDeleteSpecialMember(Destructor, CXXDestructor)) + Destructor->setDeletedAsWritten(); + + return Destructor; +} + +void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation, + CXXDestructorDecl *Destructor) { + assert((Destructor->isDefaulted() && + !Destructor->doesThisDeclarationHaveABody() && + !Destructor->isDeleted()) && + "DefineImplicitDestructor - call it for implicit default dtor"); + CXXRecordDecl *ClassDecl = Destructor->getParent(); + assert(ClassDecl && "DefineImplicitDestructor - invalid destructor"); + + if (Destructor->isInvalidDecl()) + return; + + ImplicitlyDefinedFunctionScope Scope(*this, Destructor); + + DiagnosticErrorTrap Trap(Diags); + MarkBaseAndMemberDestructorsReferenced(Destructor->getLocation(), + Destructor->getParent()); + + if (CheckDestructor(Destructor) || Trap.hasErrorOccurred()) { + Diag(CurrentLocation, diag::note_member_synthesized_at) + << CXXDestructor << Context.getTagDeclType(ClassDecl); + + Destructor->setInvalidDecl(); + return; + } + + SourceLocation Loc = Destructor->getLocation(); + Destructor->setBody(new (Context) CompoundStmt(Context, 0, 0, Loc, Loc)); + Destructor->setImplicitlyDefined(true); + Destructor->setUsed(); + MarkVTableUsed(CurrentLocation, ClassDecl); + + if (ASTMutationListener *L = getASTMutationListener()) { + L->CompletedImplicitDefinition(Destructor); + } +} + +/// \brief Perform any semantic analysis which needs to be delayed until all +/// pending class member declarations have been parsed. +void Sema::ActOnFinishCXXMemberDecls() { + // Now we have parsed all exception specifications, determine the implicit + // exception specifications for destructors. + for (unsigned i = 0, e = DelayedDestructorExceptionSpecs.size(); + i != e; ++i) { + CXXDestructorDecl *Dtor = DelayedDestructorExceptionSpecs[i]; + AdjustDestructorExceptionSpec(Dtor->getParent(), Dtor, true); + } + DelayedDestructorExceptionSpecs.clear(); + + // Perform any deferred checking of exception specifications for virtual + // destructors. + for (unsigned i = 0, e = DelayedDestructorExceptionSpecChecks.size(); + i != e; ++i) { + const CXXDestructorDecl *Dtor = + DelayedDestructorExceptionSpecChecks[i].first; + assert(!Dtor->getParent()->isDependentType() && + "Should not ever add destructors of templates into the list."); + CheckOverridingFunctionExceptionSpec(Dtor, + DelayedDestructorExceptionSpecChecks[i].second); + } + DelayedDestructorExceptionSpecChecks.clear(); +} + +void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *classDecl, + CXXDestructorDecl *destructor, + bool WasDelayed) { + // C++11 [class.dtor]p3: + // A declaration of a destructor that does not have an exception- + // specification is implicitly considered to have the same exception- + // specification as an implicit declaration. + const FunctionProtoType *dtorType = destructor->getType()-> + getAs(); + if (!WasDelayed && dtorType->hasExceptionSpec()) + return; + + ImplicitExceptionSpecification exceptSpec = + ComputeDefaultedDtorExceptionSpec(classDecl); + + // Replace the destructor's type, building off the existing one. Fortunately, + // the only thing of interest in the destructor type is its extended info. + // The return and arguments are fixed. + FunctionProtoType::ExtProtoInfo epi = dtorType->getExtProtoInfo(); + epi.ExceptionSpecType = exceptSpec.getExceptionSpecType(); + epi.NumExceptions = exceptSpec.size(); + epi.Exceptions = exceptSpec.data(); + QualType ty = Context.getFunctionType(Context.VoidTy, 0, 0, epi); + + destructor->setType(ty); + + // If we can't compute the exception specification for this destructor yet + // (because it depends on an exception specification which we have not parsed + // yet), make a note that we need to try again when the class is complete. + if (epi.ExceptionSpecType == EST_Delayed) { + assert(!WasDelayed && "couldn't compute destructor exception spec"); + DelayedDestructorExceptionSpecs.push_back(destructor); + } + + // FIXME: If the destructor has a body that could throw, and the newly created + // spec doesn't allow exceptions, we should emit a warning, because this + // change in behavior can break conforming C++03 programs at runtime. + // However, we don't have a body yet, so it needs to be done somewhere else. +} + +/// \brief Builds a statement that copies/moves the given entity from \p From to +/// \c To. +/// +/// This routine is used to copy/move the members of a class with an +/// implicitly-declared copy/move assignment operator. When the entities being +/// copied are arrays, this routine builds for loops to copy them. +/// +/// \param S The Sema object used for type-checking. +/// +/// \param Loc The location where the implicit copy/move is being generated. +/// +/// \param T The type of the expressions being copied/moved. Both expressions +/// must have this type. +/// +/// \param To The expression we are copying/moving to. +/// +/// \param From The expression we are copying/moving from. +/// +/// \param CopyingBaseSubobject Whether we're copying/moving a base subobject. +/// Otherwise, it's a non-static member subobject. +/// +/// \param Copying Whether we're copying or moving. +/// +/// \param Depth Internal parameter recording the depth of the recursion. +/// +/// \returns A statement or a loop that copies the expressions. +static StmtResult +BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, + Expr *To, Expr *From, + bool CopyingBaseSubobject, bool Copying, + unsigned Depth = 0) { + // C++0x [class.copy]p28: + // Each subobject is assigned in the manner appropriate to its type: + // + // - if the subobject is of class type, as if by a call to operator= with + // the subobject as the object expression and the corresponding + // subobject of x as a single function argument (as if by explicit + // qualification; that is, ignoring any possible virtual overriding + // functions in more derived classes); + if (const RecordType *RecordTy = T->getAs()) { + CXXRecordDecl *ClassDecl = cast(RecordTy->getDecl()); + + // Look for operator=. + DeclarationName Name + = S.Context.DeclarationNames.getCXXOperatorName(OO_Equal); + LookupResult OpLookup(S, Name, Loc, Sema::LookupOrdinaryName); + S.LookupQualifiedName(OpLookup, ClassDecl, false); + + // Filter out any result that isn't a copy/move-assignment operator. + LookupResult::Filter F = OpLookup.makeFilter(); + while (F.hasNext()) { + NamedDecl *D = F.next(); + if (CXXMethodDecl *Method = dyn_cast(D)) + if (Method->isCopyAssignmentOperator() || + (!Copying && Method->isMoveAssignmentOperator())) + continue; + + F.erase(); + } + F.done(); + + // Suppress the protected check (C++ [class.protected]) for each of the + // assignment operators we found. This strange dance is required when + // we're assigning via a base classes's copy-assignment operator. To + // ensure that we're getting the right base class subobject (without + // ambiguities), we need to cast "this" to that subobject type; to + // ensure that we don't go through the virtual call mechanism, we need + // to qualify the operator= name with the base class (see below). However, + // this means that if the base class has a protected copy assignment + // operator, the protected member access check will fail. So, we + // rewrite "protected" access to "public" access in this case, since we + // know by construction that we're calling from a derived class. + if (CopyingBaseSubobject) { + for (LookupResult::iterator L = OpLookup.begin(), LEnd = OpLookup.end(); + L != LEnd; ++L) { + if (L.getAccess() == AS_protected) + L.setAccess(AS_public); + } + } + + // Create the nested-name-specifier that will be used to qualify the + // reference to operator=; this is required to suppress the virtual + // call mechanism. + CXXScopeSpec SS; + const Type *CanonicalT = S.Context.getCanonicalType(T.getTypePtr()); + SS.MakeTrivial(S.Context, + NestedNameSpecifier::Create(S.Context, 0, false, + CanonicalT), + Loc); + + // Create the reference to operator=. + ExprResult OpEqualRef + = S.BuildMemberReferenceExpr(To, T, Loc, /*isArrow=*/false, SS, + /*TemplateKWLoc=*/SourceLocation(), + /*FirstQualifierInScope=*/0, + OpLookup, + /*TemplateArgs=*/0, + /*SuppressQualifierCheck=*/true); + if (OpEqualRef.isInvalid()) + return StmtError(); + + // Build the call to the assignment operator. + + ExprResult Call = S.BuildCallToMemberFunction(/*Scope=*/0, + OpEqualRef.takeAs(), + Loc, &From, 1, Loc); + if (Call.isInvalid()) + return StmtError(); + + return S.Owned(Call.takeAs()); + } + + // - if the subobject is of scalar type, the built-in assignment + // operator is used. + const ConstantArrayType *ArrayTy = S.Context.getAsConstantArrayType(T); + if (!ArrayTy) { + ExprResult Assignment = S.CreateBuiltinBinOp(Loc, BO_Assign, To, From); + if (Assignment.isInvalid()) + return StmtError(); + + return S.Owned(Assignment.takeAs()); + } + + // - if the subobject is an array, each element is assigned, in the + // manner appropriate to the element type; + + // Construct a loop over the array bounds, e.g., + // + // for (__SIZE_TYPE__ i0 = 0; i0 != array-size; ++i0) + // + // that will copy each of the array elements. + QualType SizeType = S.Context.getSizeType(); + + // Create the iteration variable. + IdentifierInfo *IterationVarName = 0; + { + SmallString<8> Str; + llvm::raw_svector_ostream OS(Str); + OS << "__i" << Depth; + IterationVarName = &S.Context.Idents.get(OS.str()); + } + VarDecl *IterationVar = VarDecl::Create(S.Context, S.CurContext, Loc, Loc, + IterationVarName, SizeType, + S.Context.getTrivialTypeSourceInfo(SizeType, Loc), + SC_None, SC_None); + + // Initialize the iteration variable to zero. + llvm::APInt Zero(S.Context.getTypeSize(SizeType), 0); + IterationVar->setInit(IntegerLiteral::Create(S.Context, Zero, SizeType, Loc)); + + // Create a reference to the iteration variable; we'll use this several + // times throughout. + Expr *IterationVarRef + = S.BuildDeclRefExpr(IterationVar, SizeType, VK_LValue, Loc).take(); + assert(IterationVarRef && "Reference to invented variable cannot fail!"); + Expr *IterationVarRefRVal = S.DefaultLvalueConversion(IterationVarRef).take(); + assert(IterationVarRefRVal && "Conversion of invented variable cannot fail!"); + + // Create the DeclStmt that holds the iteration variable. + Stmt *InitStmt = new (S.Context) DeclStmt(DeclGroupRef(IterationVar),Loc,Loc); + + // Create the comparison against the array bound. + llvm::APInt Upper + = ArrayTy->getSize().zextOrTrunc(S.Context.getTypeSize(SizeType)); + Expr *Comparison + = new (S.Context) BinaryOperator(IterationVarRefRVal, + IntegerLiteral::Create(S.Context, Upper, SizeType, Loc), + BO_NE, S.Context.BoolTy, + VK_RValue, OK_Ordinary, Loc); + + // Create the pre-increment of the iteration variable. + Expr *Increment + = new (S.Context) UnaryOperator(IterationVarRef, UO_PreInc, SizeType, + VK_LValue, OK_Ordinary, Loc); + + // Subscript the "from" and "to" expressions with the iteration variable. + From = AssertSuccess(S.CreateBuiltinArraySubscriptExpr(From, Loc, + IterationVarRefRVal, + Loc)); + To = AssertSuccess(S.CreateBuiltinArraySubscriptExpr(To, Loc, + IterationVarRefRVal, + Loc)); + if (!Copying) // Cast to rvalue + From = CastForMoving(S, From); + + // Build the copy/move for an individual element of the array. + StmtResult Copy = BuildSingleCopyAssign(S, Loc, ArrayTy->getElementType(), + To, From, CopyingBaseSubobject, + Copying, Depth + 1); + if (Copy.isInvalid()) + return StmtError(); + + // Construct the loop that copies all elements of this array. + return S.ActOnForStmt(Loc, Loc, InitStmt, + S.MakeFullExpr(Comparison), + 0, S.MakeFullExpr(Increment), + Loc, Copy.take()); +} + +std::pair +Sema::ComputeDefaultedCopyAssignmentExceptionSpecAndConst( + CXXRecordDecl *ClassDecl) { + if (ClassDecl->isInvalidDecl()) + return std::make_pair(ImplicitExceptionSpecification(*this), false); + + // C++ [class.copy]p10: + // If the class definition does not explicitly declare a copy + // assignment operator, one is declared implicitly. + // The implicitly-defined copy assignment operator for a class X + // will have the form + // + // X& X::operator=(const X&) + // + // if + bool HasConstCopyAssignment = true; + + // -- each direct base class B of X has a copy assignment operator + // whose parameter is of type const B&, const volatile B& or B, + // and + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), + BaseEnd = ClassDecl->bases_end(); + HasConstCopyAssignment && Base != BaseEnd; ++Base) { + // We'll handle this below + if (LangOpts.CPlusPlus0x && Base->isVirtual()) + continue; + + assert(!Base->getType()->isDependentType() && + "Cannot generate implicit members for class with dependent bases."); + CXXRecordDecl *BaseClassDecl = Base->getType()->getAsCXXRecordDecl(); + HasConstCopyAssignment &= + (bool)LookupCopyingAssignment(BaseClassDecl, Qualifiers::Const, + false, 0); + } + + // In C++11, the above citation has "or virtual" added + if (LangOpts.CPlusPlus0x) { + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(), + BaseEnd = ClassDecl->vbases_end(); + HasConstCopyAssignment && Base != BaseEnd; ++Base) { + assert(!Base->getType()->isDependentType() && + "Cannot generate implicit members for class with dependent bases."); + CXXRecordDecl *BaseClassDecl = Base->getType()->getAsCXXRecordDecl(); + HasConstCopyAssignment &= + (bool)LookupCopyingAssignment(BaseClassDecl, Qualifiers::Const, + false, 0); + } + } + + // -- for all the nonstatic data members of X that are of a class + // type M (or array thereof), each such class type has a copy + // assignment operator whose parameter is of type const M&, + // const volatile M& or M. + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), + FieldEnd = ClassDecl->field_end(); + HasConstCopyAssignment && Field != FieldEnd; + ++Field) { + QualType FieldType = Context.getBaseElementType((*Field)->getType()); + if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) { + HasConstCopyAssignment &= + (bool)LookupCopyingAssignment(FieldClassDecl, Qualifiers::Const, + false, 0); + } + } + + // Otherwise, the implicitly declared copy assignment operator will + // have the form + // + // X& X::operator=(X&) + + // C++ [except.spec]p14: + // An implicitly declared special member function (Clause 12) shall have an + // exception-specification. [...] + + // It is unspecified whether or not an implicit copy assignment operator + // attempts to deduplicate calls to assignment operators of virtual bases are + // made. As such, this exception specification is effectively unspecified. + // Based on a similar decision made for constness in C++0x, we're erring on + // the side of assuming such calls to be made regardless of whether they + // actually happen. + ImplicitExceptionSpecification ExceptSpec(*this); + unsigned ArgQuals = HasConstCopyAssignment ? Qualifiers::Const : 0; + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), + BaseEnd = ClassDecl->bases_end(); + Base != BaseEnd; ++Base) { + if (Base->isVirtual()) + continue; + + CXXRecordDecl *BaseClassDecl + = cast(Base->getType()->getAs()->getDecl()); + if (CXXMethodDecl *CopyAssign = LookupCopyingAssignment(BaseClassDecl, + ArgQuals, false, 0)) + ExceptSpec.CalledDecl(Base->getLocStart(), CopyAssign); + } + + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(), + BaseEnd = ClassDecl->vbases_end(); + Base != BaseEnd; ++Base) { + CXXRecordDecl *BaseClassDecl + = cast(Base->getType()->getAs()->getDecl()); + if (CXXMethodDecl *CopyAssign = LookupCopyingAssignment(BaseClassDecl, + ArgQuals, false, 0)) + ExceptSpec.CalledDecl(Base->getLocStart(), CopyAssign); + } + + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), + FieldEnd = ClassDecl->field_end(); + Field != FieldEnd; + ++Field) { + QualType FieldType = Context.getBaseElementType((*Field)->getType()); + if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) { + if (CXXMethodDecl *CopyAssign = + LookupCopyingAssignment(FieldClassDecl, ArgQuals, false, 0)) + ExceptSpec.CalledDecl(Field->getLocation(), CopyAssign); + } + } + + return std::make_pair(ExceptSpec, HasConstCopyAssignment); +} + +CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { + // Note: The following rules are largely analoguous to the copy + // constructor rules. Note that virtual bases are not taken into account + // for determining the argument type of the operator. Note also that + // operators taking an object instead of a reference are allowed. + + ImplicitExceptionSpecification Spec(*this); + bool Const; + llvm::tie(Spec, Const) = + ComputeDefaultedCopyAssignmentExceptionSpecAndConst(ClassDecl); + + QualType ArgType = Context.getTypeDeclType(ClassDecl); + QualType RetType = Context.getLValueReferenceType(ArgType); + if (Const) + ArgType = ArgType.withConst(); + ArgType = Context.getLValueReferenceType(ArgType); + + // An implicitly-declared copy assignment operator is an inline public + // member of its class. + FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI(); + DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal); + SourceLocation ClassLoc = ClassDecl->getLocation(); + DeclarationNameInfo NameInfo(Name, ClassLoc); + CXXMethodDecl *CopyAssignment + = CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, + Context.getFunctionType(RetType, &ArgType, 1, EPI), + /*TInfo=*/0, /*isStatic=*/false, + /*StorageClassAsWritten=*/SC_None, + /*isInline=*/true, /*isConstexpr=*/false, + SourceLocation()); + CopyAssignment->setAccess(AS_public); + CopyAssignment->setDefaulted(); + CopyAssignment->setImplicit(); + CopyAssignment->setTrivial(ClassDecl->hasTrivialCopyAssignment()); + + // Add the parameter to the operator. + ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyAssignment, + ClassLoc, ClassLoc, /*Id=*/0, + ArgType, /*TInfo=*/0, + SC_None, + SC_None, 0); + CopyAssignment->setParams(FromParam); + + // Note that we have added this copy-assignment operator. + ++ASTContext::NumImplicitCopyAssignmentOperatorsDeclared; + + if (Scope *S = getScopeForContext(ClassDecl)) + PushOnScopeChains(CopyAssignment, S, false); + ClassDecl->addDecl(CopyAssignment); + + // C++0x [class.copy]p19: + // .... If the class definition does not explicitly declare a copy + // assignment operator, there is no user-declared move constructor, and + // there is no user-declared move assignment operator, a copy assignment + // operator is implicitly declared as defaulted. + if (ShouldDeleteSpecialMember(CopyAssignment, CXXCopyAssignment)) + CopyAssignment->setDeletedAsWritten(); + + AddOverriddenMethods(ClassDecl, CopyAssignment); + return CopyAssignment; +} + +void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, + CXXMethodDecl *CopyAssignOperator) { + assert((CopyAssignOperator->isDefaulted() && + CopyAssignOperator->isOverloadedOperator() && + CopyAssignOperator->getOverloadedOperator() == OO_Equal && + !CopyAssignOperator->doesThisDeclarationHaveABody() && + !CopyAssignOperator->isDeleted()) && + "DefineImplicitCopyAssignment called for wrong function"); + + CXXRecordDecl *ClassDecl = CopyAssignOperator->getParent(); + + if (ClassDecl->isInvalidDecl() || CopyAssignOperator->isInvalidDecl()) { + CopyAssignOperator->setInvalidDecl(); + return; + } + + CopyAssignOperator->setUsed(); + + ImplicitlyDefinedFunctionScope Scope(*this, CopyAssignOperator); + DiagnosticErrorTrap Trap(Diags); + + // C++0x [class.copy]p30: + // The implicitly-defined or explicitly-defaulted copy assignment operator + // for a non-union class X performs memberwise copy assignment of its + // subobjects. The direct base classes of X are assigned first, in the + // order of their declaration in the base-specifier-list, and then the + // immediate non-static data members of X are assigned, in the order in + // which they were declared in the class definition. + + // The statements that form the synthesized function body. + ASTOwningVector Statements(*this); + + // The parameter for the "other" object, which we are copying from. + ParmVarDecl *Other = CopyAssignOperator->getParamDecl(0); + Qualifiers OtherQuals = Other->getType().getQualifiers(); + QualType OtherRefType = Other->getType(); + if (const LValueReferenceType *OtherRef + = OtherRefType->getAs()) { + OtherRefType = OtherRef->getPointeeType(); + OtherQuals = OtherRefType.getQualifiers(); + } + + // Our location for everything implicitly-generated. + SourceLocation Loc = CopyAssignOperator->getLocation(); + + // Construct a reference to the "other" object. We'll be using this + // throughout the generated ASTs. + Expr *OtherRef = BuildDeclRefExpr(Other, OtherRefType, VK_LValue, Loc).take(); + assert(OtherRef && "Reference to parameter cannot fail!"); + + // Construct the "this" pointer. We'll be using this throughout the generated + // ASTs. + Expr *This = ActOnCXXThis(Loc).takeAs(); + assert(This && "Reference to this cannot fail!"); + + // Assign base classes. + bool Invalid = false; + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), + E = ClassDecl->bases_end(); Base != E; ++Base) { + // Form the assignment: + // static_cast(this)->Base::operator=(static_cast(other)); + QualType BaseType = Base->getType().getUnqualifiedType(); + if (!BaseType->isRecordType()) { + Invalid = true; + 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; + From = ImpCastExprToType(From, Context.getQualifiedType(BaseType, OtherQuals), + CK_UncheckedDerivedToBase, + VK_LValue, &BasePath).take(); + + // Dereference "this". + ExprResult To = CreateBuiltinUnaryOp(Loc, UO_Deref, This); + + // Implicitly cast "this" to the appropriately-qualified base type. + To = ImpCastExprToType(To.take(), + Context.getCVRQualifiedType(BaseType, + CopyAssignOperator->getTypeQualifiers()), + CK_UncheckedDerivedToBase, + VK_LValue, &BasePath); + + // Build the copy. + StmtResult Copy = BuildSingleCopyAssign(*this, Loc, BaseType, + To.get(), From, + /*CopyingBaseSubobject=*/true, + /*Copying=*/true); + if (Copy.isInvalid()) { + Diag(CurrentLocation, diag::note_member_synthesized_at) + << CXXCopyAssignment << Context.getTagDeclType(ClassDecl); + CopyAssignOperator->setInvalidDecl(); + return; + } + + // Success! Record the copy. + Statements.push_back(Copy.takeAs()); + } + + // \brief Reference to the __builtin_memcpy function. + Expr *BuiltinMemCpyRef = 0; + // \brief Reference to the __builtin_objc_memmove_collectable function. + Expr *CollectableMemCpyRef = 0; + + // Assign non-static members. + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), + FieldEnd = ClassDecl->field_end(); + Field != FieldEnd; ++Field) { + if (Field->isUnnamedBitfield()) + continue; + + // Check for members of reference type; we can't copy those. + if (Field->getType()->isReferenceType()) { + Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign) + << Context.getTagDeclType(ClassDecl) << 0 << Field->getDeclName(); + Diag(Field->getLocation(), diag::note_declared_at); + Diag(CurrentLocation, diag::note_member_synthesized_at) + << CXXCopyAssignment << Context.getTagDeclType(ClassDecl); + Invalid = true; + continue; + } + + // Check for members of const-qualified, non-class type. + QualType BaseType = Context.getBaseElementType(Field->getType()); + if (!BaseType->getAs() && BaseType.isConstQualified()) { + Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign) + << Context.getTagDeclType(ClassDecl) << 1 << Field->getDeclName(); + Diag(Field->getLocation(), diag::note_declared_at); + Diag(CurrentLocation, diag::note_member_synthesized_at) + << CXXCopyAssignment << Context.getTagDeclType(ClassDecl); + Invalid = true; + continue; + } + + // Suppress assigning zero-width bitfields. + if (Field->isBitField() && Field->getBitWidthValue(Context) == 0) + continue; + + QualType FieldType = Field->getType().getNonReferenceType(); + if (FieldType->isIncompleteArrayType()) { + assert(ClassDecl->hasFlexibleArrayMember() && + "Incomplete array type is not valid"); + continue; + } + + // Build references to the field in the object we're copying from and to. + CXXScopeSpec SS; // Intentionally empty + LookupResult MemberLookup(*this, Field->getDeclName(), Loc, + LookupMemberName); + MemberLookup.addDecl(*Field); + MemberLookup.resolveKind(); + ExprResult From = BuildMemberReferenceExpr(OtherRef, OtherRefType, + Loc, /*IsArrow=*/false, + SS, SourceLocation(), 0, + MemberLookup, 0); + ExprResult To = BuildMemberReferenceExpr(This, This->getType(), + Loc, /*IsArrow=*/true, + SS, SourceLocation(), 0, + MemberLookup, 0); + assert(!From.isInvalid() && "Implicit field reference cannot fail"); + assert(!To.isInvalid() && "Implicit field reference cannot fail"); + + // If the field should be copied with __builtin_memcpy rather than via + // explicit assignments, do so. This optimization only applies for arrays + // of scalars and arrays of class type with trivial copy-assignment + // operators. + if (FieldType->isArrayType() && !FieldType.isVolatileQualified() + && BaseType.hasTrivialAssignment(Context, /*Copying=*/true)) { + // Compute the size of the memory buffer to be copied. + QualType SizeType = Context.getSizeType(); + llvm::APInt Size(Context.getTypeSize(SizeType), + Context.getTypeSizeInChars(BaseType).getQuantity()); + for (const ConstantArrayType *Array + = Context.getAsConstantArrayType(FieldType); + Array; + Array = Context.getAsConstantArrayType(Array->getElementType())) { + llvm::APInt ArraySize + = Array->getSize().zextOrTrunc(Size.getBitWidth()); + Size *= ArraySize; + } + + // Take the address of the field references for "from" and "to". + From = CreateBuiltinUnaryOp(Loc, UO_AddrOf, From.get()); + To = CreateBuiltinUnaryOp(Loc, UO_AddrOf, To.get()); + + bool NeedsCollectableMemCpy = + (BaseType->isRecordType() && + BaseType->getAs()->getDecl()->hasObjectMember()); + + if (NeedsCollectableMemCpy) { + if (!CollectableMemCpyRef) { + // Create a reference to the __builtin_objc_memmove_collectable function. + LookupResult R(*this, + &Context.Idents.get("__builtin_objc_memmove_collectable"), + Loc, LookupOrdinaryName); + LookupName(R, TUScope, true); + + FunctionDecl *CollectableMemCpy = R.getAsSingle(); + if (!CollectableMemCpy) { + // Something went horribly wrong earlier, and we will have + // complained about it. + Invalid = true; + continue; + } + + CollectableMemCpyRef = BuildDeclRefExpr(CollectableMemCpy, + CollectableMemCpy->getType(), + VK_LValue, Loc, 0).take(); + assert(CollectableMemCpyRef && "Builtin reference cannot fail"); + } + } + // Create a reference to the __builtin_memcpy builtin function. + else if (!BuiltinMemCpyRef) { + LookupResult R(*this, &Context.Idents.get("__builtin_memcpy"), Loc, + LookupOrdinaryName); + LookupName(R, TUScope, true); + + FunctionDecl *BuiltinMemCpy = R.getAsSingle(); + if (!BuiltinMemCpy) { + // Something went horribly wrong earlier, and we will have complained + // about it. + Invalid = true; + continue; + } + + BuiltinMemCpyRef = BuildDeclRefExpr(BuiltinMemCpy, + BuiltinMemCpy->getType(), + VK_LValue, Loc, 0).take(); + assert(BuiltinMemCpyRef && "Builtin reference cannot fail"); + } + + ASTOwningVector CallArgs(*this); + CallArgs.push_back(To.takeAs()); + CallArgs.push_back(From.takeAs()); + CallArgs.push_back(IntegerLiteral::Create(Context, Size, SizeType, Loc)); + ExprResult Call = ExprError(); + if (NeedsCollectableMemCpy) + Call = ActOnCallExpr(/*Scope=*/0, + CollectableMemCpyRef, + Loc, move_arg(CallArgs), + Loc); + else + Call = ActOnCallExpr(/*Scope=*/0, + BuiltinMemCpyRef, + Loc, move_arg(CallArgs), + Loc); + + assert(!Call.isInvalid() && "Call to __builtin_memcpy cannot fail!"); + Statements.push_back(Call.takeAs()); + continue; + } + + // Build the copy of this field. + StmtResult Copy = BuildSingleCopyAssign(*this, Loc, FieldType, + To.get(), From.get(), + /*CopyingBaseSubobject=*/false, + /*Copying=*/true); + if (Copy.isInvalid()) { + Diag(CurrentLocation, diag::note_member_synthesized_at) + << CXXCopyAssignment << Context.getTagDeclType(ClassDecl); + CopyAssignOperator->setInvalidDecl(); + return; + } + + // Success! Record the copy. + Statements.push_back(Copy.takeAs()); + } + + if (!Invalid) { + // Add a "return *this;" + ExprResult ThisObj = CreateBuiltinUnaryOp(Loc, UO_Deref, This); + + StmtResult Return = ActOnReturnStmt(Loc, ThisObj.get()); + if (Return.isInvalid()) + Invalid = true; + else { + Statements.push_back(Return.takeAs()); + + if (Trap.hasErrorOccurred()) { + Diag(CurrentLocation, diag::note_member_synthesized_at) + << CXXCopyAssignment << Context.getTagDeclType(ClassDecl); + Invalid = true; + } + } + } + + if (Invalid) { + CopyAssignOperator->setInvalidDecl(); + return; + } + + StmtResult Body; + { + CompoundScopeRAII CompoundScope(*this); + Body = ActOnCompoundStmt(Loc, Loc, move_arg(Statements), + /*isStmtExpr=*/false); + assert(!Body.isInvalid() && "Compound statement creation cannot fail"); + } + CopyAssignOperator->setBody(Body.takeAs()); + + if (ASTMutationListener *L = getASTMutationListener()) { + L->CompletedImplicitDefinition(CopyAssignOperator); + } +} + +Sema::ImplicitExceptionSpecification +Sema::ComputeDefaultedMoveAssignmentExceptionSpec(CXXRecordDecl *ClassDecl) { + ImplicitExceptionSpecification ExceptSpec(*this); + + if (ClassDecl->isInvalidDecl()) + return ExceptSpec; + + // C++0x [except.spec]p14: + // An implicitly declared special member function (Clause 12) shall have an + // exception-specification. [...] + + // It is unspecified whether or not an implicit move assignment operator + // attempts to deduplicate calls to assignment operators of virtual bases are + // made. As such, this exception specification is effectively unspecified. + // Based on a similar decision made for constness in C++0x, we're erring on + // the side of assuming such calls to be made regardless of whether they + // actually happen. + // Note that a move constructor is not implicitly declared when there are + // virtual bases, but it can still be user-declared and explicitly defaulted. + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), + BaseEnd = ClassDecl->bases_end(); + Base != BaseEnd; ++Base) { + if (Base->isVirtual()) + continue; + + CXXRecordDecl *BaseClassDecl + = cast(Base->getType()->getAs()->getDecl()); + if (CXXMethodDecl *MoveAssign = LookupMovingAssignment(BaseClassDecl, + false, 0)) + ExceptSpec.CalledDecl(Base->getLocStart(), MoveAssign); + } + + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(), + BaseEnd = ClassDecl->vbases_end(); + Base != BaseEnd; ++Base) { + CXXRecordDecl *BaseClassDecl + = cast(Base->getType()->getAs()->getDecl()); + if (CXXMethodDecl *MoveAssign = LookupMovingAssignment(BaseClassDecl, + false, 0)) + ExceptSpec.CalledDecl(Base->getLocStart(), MoveAssign); + } + + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), + FieldEnd = ClassDecl->field_end(); + Field != FieldEnd; + ++Field) { + QualType FieldType = Context.getBaseElementType((*Field)->getType()); + if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) { + if (CXXMethodDecl *MoveAssign = LookupMovingAssignment(FieldClassDecl, + false, 0)) + ExceptSpec.CalledDecl(Field->getLocation(), MoveAssign); + } + } + + return ExceptSpec; +} + +/// Determine whether the class type has any direct or indirect virtual base +/// classes which have a non-trivial move assignment operator. +static bool +hasVirtualBaseWithNonTrivialMoveAssignment(Sema &S, CXXRecordDecl *ClassDecl) { + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(), + BaseEnd = ClassDecl->vbases_end(); + Base != BaseEnd; ++Base) { + CXXRecordDecl *BaseClass = + cast(Base->getType()->getAs()->getDecl()); + + // Try to declare the move assignment. If it would be deleted, then the + // class does not have a non-trivial move assignment. + if (BaseClass->needsImplicitMoveAssignment()) + S.DeclareImplicitMoveAssignment(BaseClass); + + // If the class has both a trivial move assignment and a non-trivial move + // assignment, hasTrivialMoveAssignment() is false. + if (BaseClass->hasDeclaredMoveAssignment() && + !BaseClass->hasTrivialMoveAssignment()) + return true; + } + + return false; +} + +/// Determine whether the given type either has a move constructor or is +/// trivially copyable. +static bool +hasMoveOrIsTriviallyCopyable(Sema &S, QualType Type, bool IsConstructor) { + Type = S.Context.getBaseElementType(Type); + + // FIXME: Technically, non-trivially-copyable non-class types, such as + // reference types, are supposed to return false here, but that appears + // to be a standard defect. + CXXRecordDecl *ClassDecl = Type->getAsCXXRecordDecl(); + if (!ClassDecl) + return true; + + if (Type.isTriviallyCopyableType(S.Context)) + return true; + + if (IsConstructor) { + if (ClassDecl->needsImplicitMoveConstructor()) + S.DeclareImplicitMoveConstructor(ClassDecl); + return ClassDecl->hasDeclaredMoveConstructor(); + } + + if (ClassDecl->needsImplicitMoveAssignment()) + S.DeclareImplicitMoveAssignment(ClassDecl); + return ClassDecl->hasDeclaredMoveAssignment(); +} + +/// Determine whether all non-static data members and direct or virtual bases +/// of class \p ClassDecl have either a move operation, or are trivially +/// copyable. +static bool subobjectsHaveMoveOrTrivialCopy(Sema &S, CXXRecordDecl *ClassDecl, + bool IsConstructor) { + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), + BaseEnd = ClassDecl->bases_end(); + Base != BaseEnd; ++Base) { + if (Base->isVirtual()) + continue; + + if (!hasMoveOrIsTriviallyCopyable(S, Base->getType(), IsConstructor)) + return false; + } + + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(), + BaseEnd = ClassDecl->vbases_end(); + Base != BaseEnd; ++Base) { + if (!hasMoveOrIsTriviallyCopyable(S, Base->getType(), IsConstructor)) + return false; + } + + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), + FieldEnd = ClassDecl->field_end(); + Field != FieldEnd; ++Field) { + if (!hasMoveOrIsTriviallyCopyable(S, (*Field)->getType(), IsConstructor)) + return false; + } + + return true; +} + +CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) { + // C++11 [class.copy]p20: + // If the definition of a class X does not explicitly declare a move + // assignment operator, one will be implicitly declared as defaulted + // if and only if: + // + // - [first 4 bullets] + assert(ClassDecl->needsImplicitMoveAssignment()); + + // [Checked after we build the declaration] + // - the move assignment operator would not be implicitly defined as + // deleted, + + // [DR1402]: + // - X has no direct or indirect virtual base class with a non-trivial + // move assignment operator, and + // - each of X's non-static data members and direct or virtual base classes + // has a type that either has a move assignment operator or is trivially + // copyable. + if (hasVirtualBaseWithNonTrivialMoveAssignment(*this, ClassDecl) || + !subobjectsHaveMoveOrTrivialCopy(*this, ClassDecl,/*Constructor*/false)) { + ClassDecl->setFailedImplicitMoveAssignment(); + return 0; + } + + // Note: The following rules are largely analoguous to the move + // constructor rules. + + ImplicitExceptionSpecification Spec( + ComputeDefaultedMoveAssignmentExceptionSpec(ClassDecl)); + + QualType ArgType = Context.getTypeDeclType(ClassDecl); + QualType RetType = Context.getLValueReferenceType(ArgType); + ArgType = Context.getRValueReferenceType(ArgType); + + // An implicitly-declared move assignment operator is an inline public + // member of its class. + FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI(); + DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal); + SourceLocation ClassLoc = ClassDecl->getLocation(); + DeclarationNameInfo NameInfo(Name, ClassLoc); + CXXMethodDecl *MoveAssignment + = CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, + Context.getFunctionType(RetType, &ArgType, 1, EPI), + /*TInfo=*/0, /*isStatic=*/false, + /*StorageClassAsWritten=*/SC_None, + /*isInline=*/true, + /*isConstexpr=*/false, + SourceLocation()); + MoveAssignment->setAccess(AS_public); + MoveAssignment->setDefaulted(); + MoveAssignment->setImplicit(); + MoveAssignment->setTrivial(ClassDecl->hasTrivialMoveAssignment()); + + // Add the parameter to the operator. + ParmVarDecl *FromParam = ParmVarDecl::Create(Context, MoveAssignment, + ClassLoc, ClassLoc, /*Id=*/0, + ArgType, /*TInfo=*/0, + SC_None, + SC_None, 0); + MoveAssignment->setParams(FromParam); + + // Note that we have added this copy-assignment operator. + ++ASTContext::NumImplicitMoveAssignmentOperatorsDeclared; + + // C++0x [class.copy]p9: + // If the definition of a class X does not explicitly declare a move + // assignment operator, one will be implicitly declared as defaulted if and + // only if: + // [...] + // - the move assignment operator would not be implicitly defined as + // deleted. + if (ShouldDeleteSpecialMember(MoveAssignment, CXXMoveAssignment)) { + // Cache this result so that we don't try to generate this over and over + // on every lookup, leaking memory and wasting time. + ClassDecl->setFailedImplicitMoveAssignment(); + return 0; + } + + if (Scope *S = getScopeForContext(ClassDecl)) + PushOnScopeChains(MoveAssignment, S, false); + ClassDecl->addDecl(MoveAssignment); + + AddOverriddenMethods(ClassDecl, MoveAssignment); + return MoveAssignment; +} + +void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, + CXXMethodDecl *MoveAssignOperator) { + assert((MoveAssignOperator->isDefaulted() && + MoveAssignOperator->isOverloadedOperator() && + MoveAssignOperator->getOverloadedOperator() == OO_Equal && + !MoveAssignOperator->doesThisDeclarationHaveABody() && + !MoveAssignOperator->isDeleted()) && + "DefineImplicitMoveAssignment called for wrong function"); + + CXXRecordDecl *ClassDecl = MoveAssignOperator->getParent(); + + if (ClassDecl->isInvalidDecl() || MoveAssignOperator->isInvalidDecl()) { + MoveAssignOperator->setInvalidDecl(); + return; + } + + MoveAssignOperator->setUsed(); + + ImplicitlyDefinedFunctionScope Scope(*this, MoveAssignOperator); + DiagnosticErrorTrap Trap(Diags); + + // C++0x [class.copy]p28: + // The implicitly-defined or move assignment operator for a non-union class + // X performs memberwise move assignment of its subobjects. The direct base + // classes of X are assigned first, in the order of their declaration in the + // base-specifier-list, and then the immediate non-static data members of X + // are assigned, in the order in which they were declared in the class + // definition. + + // The statements that form the synthesized function body. + ASTOwningVector Statements(*this); + + // The parameter for the "other" object, which we are move from. + ParmVarDecl *Other = MoveAssignOperator->getParamDecl(0); + QualType OtherRefType = Other->getType()-> + getAs()->getPointeeType(); + assert(OtherRefType.getQualifiers() == 0 && + "Bad argument type of defaulted move assignment"); + + // Our location for everything implicitly-generated. + SourceLocation Loc = MoveAssignOperator->getLocation(); + + // Construct a reference to the "other" object. We'll be using this + // throughout the generated ASTs. + Expr *OtherRef = BuildDeclRefExpr(Other, OtherRefType, VK_LValue, Loc).take(); + assert(OtherRef && "Reference to parameter cannot fail!"); + // Cast to rvalue. + OtherRef = CastForMoving(*this, OtherRef); + + // Construct the "this" pointer. We'll be using this throughout the generated + // ASTs. + Expr *This = ActOnCXXThis(Loc).takeAs(); + assert(This && "Reference to this cannot fail!"); + + // Assign base classes. + bool Invalid = false; + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), + E = ClassDecl->bases_end(); Base != E; ++Base) { + // Form the assignment: + // static_cast(this)->Base::operator=(static_cast(other)); + QualType BaseType = Base->getType().getUnqualifiedType(); + if (!BaseType->isRecordType()) { + Invalid = true; + 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; + From = ImpCastExprToType(From, BaseType, CK_UncheckedDerivedToBase, + VK_XValue, &BasePath).take(); + + // Dereference "this". + ExprResult To = CreateBuiltinUnaryOp(Loc, UO_Deref, This); + + // Implicitly cast "this" to the appropriately-qualified base type. + To = ImpCastExprToType(To.take(), + Context.getCVRQualifiedType(BaseType, + MoveAssignOperator->getTypeQualifiers()), + CK_UncheckedDerivedToBase, + VK_LValue, &BasePath); + + // Build the move. + StmtResult Move = BuildSingleCopyAssign(*this, Loc, BaseType, + To.get(), From, + /*CopyingBaseSubobject=*/true, + /*Copying=*/false); + if (Move.isInvalid()) { + Diag(CurrentLocation, diag::note_member_synthesized_at) + << CXXMoveAssignment << Context.getTagDeclType(ClassDecl); + MoveAssignOperator->setInvalidDecl(); + return; + } + + // Success! Record the move. + Statements.push_back(Move.takeAs()); + } + + // \brief Reference to the __builtin_memcpy function. + Expr *BuiltinMemCpyRef = 0; + // \brief Reference to the __builtin_objc_memmove_collectable function. + Expr *CollectableMemCpyRef = 0; + + // Assign non-static members. + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), + FieldEnd = ClassDecl->field_end(); + Field != FieldEnd; ++Field) { + if (Field->isUnnamedBitfield()) + continue; + + // Check for members of reference type; we can't move those. + if (Field->getType()->isReferenceType()) { + Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign) + << Context.getTagDeclType(ClassDecl) << 0 << Field->getDeclName(); + Diag(Field->getLocation(), diag::note_declared_at); + Diag(CurrentLocation, diag::note_member_synthesized_at) + << CXXMoveAssignment << Context.getTagDeclType(ClassDecl); + Invalid = true; + continue; + } + + // Check for members of const-qualified, non-class type. + QualType BaseType = Context.getBaseElementType(Field->getType()); + if (!BaseType->getAs() && BaseType.isConstQualified()) { + Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign) + << Context.getTagDeclType(ClassDecl) << 1 << Field->getDeclName(); + Diag(Field->getLocation(), diag::note_declared_at); + Diag(CurrentLocation, diag::note_member_synthesized_at) + << CXXMoveAssignment << Context.getTagDeclType(ClassDecl); + Invalid = true; + continue; + } + + // Suppress assigning zero-width bitfields. + if (Field->isBitField() && Field->getBitWidthValue(Context) == 0) + continue; + + QualType FieldType = Field->getType().getNonReferenceType(); + if (FieldType->isIncompleteArrayType()) { + assert(ClassDecl->hasFlexibleArrayMember() && + "Incomplete array type is not valid"); + continue; + } + + // Build references to the field in the object we're copying from and to. + CXXScopeSpec SS; // Intentionally empty + LookupResult MemberLookup(*this, Field->getDeclName(), Loc, + LookupMemberName); + MemberLookup.addDecl(*Field); + MemberLookup.resolveKind(); + ExprResult From = BuildMemberReferenceExpr(OtherRef, OtherRefType, + Loc, /*IsArrow=*/false, + SS, SourceLocation(), 0, + MemberLookup, 0); + ExprResult To = BuildMemberReferenceExpr(This, This->getType(), + Loc, /*IsArrow=*/true, + SS, SourceLocation(), 0, + MemberLookup, 0); + assert(!From.isInvalid() && "Implicit field reference cannot fail"); + assert(!To.isInvalid() && "Implicit field reference cannot fail"); + + assert(!From.get()->isLValue() && // could be xvalue or prvalue + "Member reference with rvalue base must be rvalue except for reference " + "members, which aren't allowed for move assignment."); + + // If the field should be copied with __builtin_memcpy rather than via + // explicit assignments, do so. This optimization only applies for arrays + // of scalars and arrays of class type with trivial move-assignment + // operators. + if (FieldType->isArrayType() && !FieldType.isVolatileQualified() + && BaseType.hasTrivialAssignment(Context, /*Copying=*/false)) { + // Compute the size of the memory buffer to be copied. + QualType SizeType = Context.getSizeType(); + llvm::APInt Size(Context.getTypeSize(SizeType), + Context.getTypeSizeInChars(BaseType).getQuantity()); + for (const ConstantArrayType *Array + = Context.getAsConstantArrayType(FieldType); + Array; + Array = Context.getAsConstantArrayType(Array->getElementType())) { + llvm::APInt ArraySize + = Array->getSize().zextOrTrunc(Size.getBitWidth()); + Size *= ArraySize; + } + + // Take the address of the field references for "from" and "to". We + // directly construct UnaryOperators here because semantic analysis + // does not permit us to take the address of an xvalue. + From = new (Context) UnaryOperator(From.get(), UO_AddrOf, + Context.getPointerType(From.get()->getType()), + VK_RValue, OK_Ordinary, Loc); + To = new (Context) UnaryOperator(To.get(), UO_AddrOf, + Context.getPointerType(To.get()->getType()), + VK_RValue, OK_Ordinary, Loc); + + bool NeedsCollectableMemCpy = + (BaseType->isRecordType() && + BaseType->getAs()->getDecl()->hasObjectMember()); + + if (NeedsCollectableMemCpy) { + if (!CollectableMemCpyRef) { + // Create a reference to the __builtin_objc_memmove_collectable function. + LookupResult R(*this, + &Context.Idents.get("__builtin_objc_memmove_collectable"), + Loc, LookupOrdinaryName); + LookupName(R, TUScope, true); + + FunctionDecl *CollectableMemCpy = R.getAsSingle(); + if (!CollectableMemCpy) { + // Something went horribly wrong earlier, and we will have + // complained about it. + Invalid = true; + continue; + } + + CollectableMemCpyRef = BuildDeclRefExpr(CollectableMemCpy, + CollectableMemCpy->getType(), + VK_LValue, Loc, 0).take(); + assert(CollectableMemCpyRef && "Builtin reference cannot fail"); + } + } + // Create a reference to the __builtin_memcpy builtin function. + else if (!BuiltinMemCpyRef) { + LookupResult R(*this, &Context.Idents.get("__builtin_memcpy"), Loc, + LookupOrdinaryName); + LookupName(R, TUScope, true); + + FunctionDecl *BuiltinMemCpy = R.getAsSingle(); + if (!BuiltinMemCpy) { + // Something went horribly wrong earlier, and we will have complained + // about it. + Invalid = true; + continue; + } + + BuiltinMemCpyRef = BuildDeclRefExpr(BuiltinMemCpy, + BuiltinMemCpy->getType(), + VK_LValue, Loc, 0).take(); + assert(BuiltinMemCpyRef && "Builtin reference cannot fail"); + } + + ASTOwningVector CallArgs(*this); + CallArgs.push_back(To.takeAs()); + CallArgs.push_back(From.takeAs()); + CallArgs.push_back(IntegerLiteral::Create(Context, Size, SizeType, Loc)); + ExprResult Call = ExprError(); + if (NeedsCollectableMemCpy) + Call = ActOnCallExpr(/*Scope=*/0, + CollectableMemCpyRef, + Loc, move_arg(CallArgs), + Loc); + else + Call = ActOnCallExpr(/*Scope=*/0, + BuiltinMemCpyRef, + Loc, move_arg(CallArgs), + Loc); + + assert(!Call.isInvalid() && "Call to __builtin_memcpy cannot fail!"); + Statements.push_back(Call.takeAs()); + continue; + } + + // Build the move of this field. + StmtResult Move = BuildSingleCopyAssign(*this, Loc, FieldType, + To.get(), From.get(), + /*CopyingBaseSubobject=*/false, + /*Copying=*/false); + if (Move.isInvalid()) { + Diag(CurrentLocation, diag::note_member_synthesized_at) + << CXXMoveAssignment << Context.getTagDeclType(ClassDecl); + MoveAssignOperator->setInvalidDecl(); + return; + } + + // Success! Record the copy. + Statements.push_back(Move.takeAs()); + } + + if (!Invalid) { + // Add a "return *this;" + ExprResult ThisObj = CreateBuiltinUnaryOp(Loc, UO_Deref, This); + + StmtResult Return = ActOnReturnStmt(Loc, ThisObj.get()); + if (Return.isInvalid()) + Invalid = true; + else { + Statements.push_back(Return.takeAs()); + + if (Trap.hasErrorOccurred()) { + Diag(CurrentLocation, diag::note_member_synthesized_at) + << CXXMoveAssignment << Context.getTagDeclType(ClassDecl); + Invalid = true; + } + } + } + + if (Invalid) { + MoveAssignOperator->setInvalidDecl(); + return; + } + + StmtResult Body; + { + CompoundScopeRAII CompoundScope(*this); + Body = ActOnCompoundStmt(Loc, Loc, move_arg(Statements), + /*isStmtExpr=*/false); + assert(!Body.isInvalid() && "Compound statement creation cannot fail"); + } + MoveAssignOperator->setBody(Body.takeAs()); + + if (ASTMutationListener *L = getASTMutationListener()) { + L->CompletedImplicitDefinition(MoveAssignOperator); + } +} + +std::pair +Sema::ComputeDefaultedCopyCtorExceptionSpecAndConst(CXXRecordDecl *ClassDecl) { + if (ClassDecl->isInvalidDecl()) + return std::make_pair(ImplicitExceptionSpecification(*this), false); + + // C++ [class.copy]p5: + // The implicitly-declared copy constructor for a class X will + // have the form + // + // X::X(const X&) + // + // if + // FIXME: It ought to be possible to store this on the record. + bool HasConstCopyConstructor = true; + + // -- each direct or virtual base class B of X has a copy + // constructor whose first parameter is of type const B& or + // const volatile B&, and + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), + BaseEnd = ClassDecl->bases_end(); + HasConstCopyConstructor && Base != BaseEnd; + ++Base) { + // Virtual bases are handled below. + if (Base->isVirtual()) + continue; + + CXXRecordDecl *BaseClassDecl + = cast(Base->getType()->getAs()->getDecl()); + HasConstCopyConstructor &= + (bool)LookupCopyingConstructor(BaseClassDecl, Qualifiers::Const); + } + + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(), + BaseEnd = ClassDecl->vbases_end(); + HasConstCopyConstructor && Base != BaseEnd; + ++Base) { + CXXRecordDecl *BaseClassDecl + = cast(Base->getType()->getAs()->getDecl()); + HasConstCopyConstructor &= + (bool)LookupCopyingConstructor(BaseClassDecl, Qualifiers::Const); + } + + // -- for all the nonstatic data members of X that are of a + // class type M (or array thereof), each such class type + // has a copy constructor whose first parameter is of type + // const M& or const volatile M&. + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), + FieldEnd = ClassDecl->field_end(); + HasConstCopyConstructor && Field != FieldEnd; + ++Field) { + QualType FieldType = Context.getBaseElementType((*Field)->getType()); + if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) { + HasConstCopyConstructor &= + (bool)LookupCopyingConstructor(FieldClassDecl, Qualifiers::Const); + } + } + // Otherwise, the implicitly declared copy constructor will have + // the form + // + // X::X(X&) + + // C++ [except.spec]p14: + // An implicitly declared special member function (Clause 12) shall have an + // exception-specification. [...] + ImplicitExceptionSpecification ExceptSpec(*this); + unsigned Quals = HasConstCopyConstructor? Qualifiers::Const : 0; + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), + BaseEnd = ClassDecl->bases_end(); + Base != BaseEnd; + ++Base) { + // Virtual bases are handled below. + if (Base->isVirtual()) + continue; + + CXXRecordDecl *BaseClassDecl + = cast(Base->getType()->getAs()->getDecl()); + if (CXXConstructorDecl *CopyConstructor = + LookupCopyingConstructor(BaseClassDecl, Quals)) + ExceptSpec.CalledDecl(Base->getLocStart(), CopyConstructor); + } + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(), + BaseEnd = ClassDecl->vbases_end(); + Base != BaseEnd; + ++Base) { + CXXRecordDecl *BaseClassDecl + = cast(Base->getType()->getAs()->getDecl()); + if (CXXConstructorDecl *CopyConstructor = + LookupCopyingConstructor(BaseClassDecl, Quals)) + ExceptSpec.CalledDecl(Base->getLocStart(), CopyConstructor); + } + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), + FieldEnd = ClassDecl->field_end(); + Field != FieldEnd; + ++Field) { + QualType FieldType = Context.getBaseElementType((*Field)->getType()); + if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) { + if (CXXConstructorDecl *CopyConstructor = + LookupCopyingConstructor(FieldClassDecl, Quals)) + ExceptSpec.CalledDecl(Field->getLocation(), CopyConstructor); + } + } + + return std::make_pair(ExceptSpec, HasConstCopyConstructor); +} + +CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( + CXXRecordDecl *ClassDecl) { + // C++ [class.copy]p4: + // If the class definition does not explicitly declare a copy + // constructor, one is declared implicitly. + + ImplicitExceptionSpecification Spec(*this); + bool Const; + llvm::tie(Spec, Const) = + ComputeDefaultedCopyCtorExceptionSpecAndConst(ClassDecl); + + QualType ClassType = Context.getTypeDeclType(ClassDecl); + QualType ArgType = ClassType; + if (Const) + ArgType = ArgType.withConst(); + ArgType = Context.getLValueReferenceType(ArgType); + + FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI(); + + DeclarationName Name + = Context.DeclarationNames.getCXXConstructorName( + Context.getCanonicalType(ClassType)); + SourceLocation ClassLoc = ClassDecl->getLocation(); + DeclarationNameInfo NameInfo(Name, ClassLoc); + + // An implicitly-declared copy constructor is an inline public + // member of its class. + CXXConstructorDecl *CopyConstructor = CXXConstructorDecl::Create( + Context, ClassDecl, ClassLoc, NameInfo, + Context.getFunctionType(Context.VoidTy, &ArgType, 1, EPI), /*TInfo=*/0, + /*isExplicit=*/false, /*isInline=*/true, /*isImplicitlyDeclared=*/true, + /*isConstexpr=*/ClassDecl->defaultedCopyConstructorIsConstexpr() && + getLangOpts().CPlusPlus0x); + CopyConstructor->setAccess(AS_public); + CopyConstructor->setDefaulted(); + CopyConstructor->setTrivial(ClassDecl->hasTrivialCopyConstructor()); + + // Note that we have declared this constructor. + ++ASTContext::NumImplicitCopyConstructorsDeclared; + + // Add the parameter to the constructor. + ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyConstructor, + ClassLoc, ClassLoc, + /*IdentifierInfo=*/0, + ArgType, /*TInfo=*/0, + SC_None, + SC_None, 0); + CopyConstructor->setParams(FromParam); + + if (Scope *S = getScopeForContext(ClassDecl)) + PushOnScopeChains(CopyConstructor, S, false); + ClassDecl->addDecl(CopyConstructor); + + // C++11 [class.copy]p8: + // ... If the class definition does not explicitly declare a copy + // constructor, there is no user-declared move constructor, and there is no + // user-declared move assignment operator, a copy constructor is implicitly + // declared as defaulted. + if (ShouldDeleteSpecialMember(CopyConstructor, CXXCopyConstructor)) + CopyConstructor->setDeletedAsWritten(); + + return CopyConstructor; +} + +void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation, + CXXConstructorDecl *CopyConstructor) { + assert((CopyConstructor->isDefaulted() && + CopyConstructor->isCopyConstructor() && + !CopyConstructor->doesThisDeclarationHaveABody() && + !CopyConstructor->isDeleted()) && + "DefineImplicitCopyConstructor - call it for implicit copy ctor"); + + CXXRecordDecl *ClassDecl = CopyConstructor->getParent(); + assert(ClassDecl && "DefineImplicitCopyConstructor - invalid constructor"); + + ImplicitlyDefinedFunctionScope Scope(*this, CopyConstructor); + DiagnosticErrorTrap Trap(Diags); + + if (SetCtorInitializers(CopyConstructor, 0, 0, /*AnyErrors=*/false) || + Trap.hasErrorOccurred()) { + Diag(CurrentLocation, diag::note_member_synthesized_at) + << CXXCopyConstructor << Context.getTagDeclType(ClassDecl); + CopyConstructor->setInvalidDecl(); + } else { + Sema::CompoundScopeRAII CompoundScope(*this); + CopyConstructor->setBody(ActOnCompoundStmt(CopyConstructor->getLocation(), + CopyConstructor->getLocation(), + MultiStmtArg(*this, 0, 0), + /*isStmtExpr=*/false) + .takeAs()); + CopyConstructor->setImplicitlyDefined(true); + } + + CopyConstructor->setUsed(); + if (ASTMutationListener *L = getASTMutationListener()) { + L->CompletedImplicitDefinition(CopyConstructor); + } +} + +Sema::ImplicitExceptionSpecification +Sema::ComputeDefaultedMoveCtorExceptionSpec(CXXRecordDecl *ClassDecl) { + // C++ [except.spec]p14: + // An implicitly declared special member function (Clause 12) shall have an + // exception-specification. [...] + ImplicitExceptionSpecification ExceptSpec(*this); + if (ClassDecl->isInvalidDecl()) + return ExceptSpec; + + // Direct base-class constructors. + for (CXXRecordDecl::base_class_iterator B = ClassDecl->bases_begin(), + BEnd = ClassDecl->bases_end(); + B != BEnd; ++B) { + if (B->isVirtual()) // Handled below. + continue; + + if (const RecordType *BaseType = B->getType()->getAs()) { + CXXRecordDecl *BaseClassDecl = cast(BaseType->getDecl()); + CXXConstructorDecl *Constructor = LookupMovingConstructor(BaseClassDecl); + // If this is a deleted function, add it anyway. This might be conformant + // with the standard. This might not. I'm not sure. It might not matter. + if (Constructor) + ExceptSpec.CalledDecl(B->getLocStart(), Constructor); + } + } + + // Virtual base-class constructors. + for (CXXRecordDecl::base_class_iterator B = ClassDecl->vbases_begin(), + BEnd = ClassDecl->vbases_end(); + B != BEnd; ++B) { + if (const RecordType *BaseType = B->getType()->getAs()) { + CXXRecordDecl *BaseClassDecl = cast(BaseType->getDecl()); + CXXConstructorDecl *Constructor = LookupMovingConstructor(BaseClassDecl); + // If this is a deleted function, add it anyway. This might be conformant + // with the standard. This might not. I'm not sure. It might not matter. + if (Constructor) + ExceptSpec.CalledDecl(B->getLocStart(), Constructor); + } + } + + // Field constructors. + for (RecordDecl::field_iterator F = ClassDecl->field_begin(), + FEnd = ClassDecl->field_end(); + F != FEnd; ++F) { + if (const RecordType *RecordTy + = Context.getBaseElementType(F->getType())->getAs()) { + CXXRecordDecl *FieldRecDecl = cast(RecordTy->getDecl()); + CXXConstructorDecl *Constructor = LookupMovingConstructor(FieldRecDecl); + // If this is a deleted function, add it anyway. This might be conformant + // with the standard. This might not. I'm not sure. It might not matter. + // In particular, the problem is that this function never gets called. It + // might just be ill-formed because this function attempts to refer to + // a deleted function here. + if (Constructor) + ExceptSpec.CalledDecl(F->getLocation(), Constructor); + } + } + + return ExceptSpec; +} + +CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor( + CXXRecordDecl *ClassDecl) { + // C++11 [class.copy]p9: + // If the definition of a class X does not explicitly declare a move + // constructor, one will be implicitly declared as defaulted if and only if: + // + // - [first 4 bullets] + assert(ClassDecl->needsImplicitMoveConstructor()); + + // [Checked after we build the declaration] + // - the move assignment operator would not be implicitly defined as + // deleted, + + // [DR1402]: + // - each of X's non-static data members and direct or virtual base classes + // has a type that either has a move constructor or is trivially copyable. + if (!subobjectsHaveMoveOrTrivialCopy(*this, ClassDecl, /*Constructor*/true)) { + ClassDecl->setFailedImplicitMoveConstructor(); + return 0; + } + + ImplicitExceptionSpecification Spec( + ComputeDefaultedMoveCtorExceptionSpec(ClassDecl)); + + QualType ClassType = Context.getTypeDeclType(ClassDecl); + QualType ArgType = Context.getRValueReferenceType(ClassType); + + FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI(); + + DeclarationName Name + = Context.DeclarationNames.getCXXConstructorName( + Context.getCanonicalType(ClassType)); + SourceLocation ClassLoc = ClassDecl->getLocation(); + DeclarationNameInfo NameInfo(Name, ClassLoc); + + // C++0x [class.copy]p11: + // An implicitly-declared copy/move constructor is an inline public + // member of its class. + CXXConstructorDecl *MoveConstructor = CXXConstructorDecl::Create( + Context, ClassDecl, ClassLoc, NameInfo, + Context.getFunctionType(Context.VoidTy, &ArgType, 1, EPI), /*TInfo=*/0, + /*isExplicit=*/false, /*isInline=*/true, /*isImplicitlyDeclared=*/true, + /*isConstexpr=*/ClassDecl->defaultedMoveConstructorIsConstexpr() && + getLangOpts().CPlusPlus0x); + MoveConstructor->setAccess(AS_public); + MoveConstructor->setDefaulted(); + MoveConstructor->setTrivial(ClassDecl->hasTrivialMoveConstructor()); + + // Add the parameter to the constructor. + ParmVarDecl *FromParam = ParmVarDecl::Create(Context, MoveConstructor, + ClassLoc, ClassLoc, + /*IdentifierInfo=*/0, + ArgType, /*TInfo=*/0, + SC_None, + SC_None, 0); + MoveConstructor->setParams(FromParam); + + // C++0x [class.copy]p9: + // If the definition of a class X does not explicitly declare a move + // constructor, one will be implicitly declared as defaulted if and only if: + // [...] + // - the move constructor would not be implicitly defined as deleted. + if (ShouldDeleteSpecialMember(MoveConstructor, CXXMoveConstructor)) { + // Cache this result so that we don't try to generate this over and over + // on every lookup, leaking memory and wasting time. + ClassDecl->setFailedImplicitMoveConstructor(); + return 0; + } + + // Note that we have declared this constructor. + ++ASTContext::NumImplicitMoveConstructorsDeclared; + + if (Scope *S = getScopeForContext(ClassDecl)) + PushOnScopeChains(MoveConstructor, S, false); + ClassDecl->addDecl(MoveConstructor); + + return MoveConstructor; +} + +void Sema::DefineImplicitMoveConstructor(SourceLocation CurrentLocation, + CXXConstructorDecl *MoveConstructor) { + assert((MoveConstructor->isDefaulted() && + MoveConstructor->isMoveConstructor() && + !MoveConstructor->doesThisDeclarationHaveABody() && + !MoveConstructor->isDeleted()) && + "DefineImplicitMoveConstructor - call it for implicit move ctor"); + + CXXRecordDecl *ClassDecl = MoveConstructor->getParent(); + assert(ClassDecl && "DefineImplicitMoveConstructor - invalid constructor"); + + ImplicitlyDefinedFunctionScope Scope(*this, MoveConstructor); + DiagnosticErrorTrap Trap(Diags); + + if (SetCtorInitializers(MoveConstructor, 0, 0, /*AnyErrors=*/false) || + Trap.hasErrorOccurred()) { + Diag(CurrentLocation, diag::note_member_synthesized_at) + << CXXMoveConstructor << Context.getTagDeclType(ClassDecl); + MoveConstructor->setInvalidDecl(); + } else { + Sema::CompoundScopeRAII CompoundScope(*this); + MoveConstructor->setBody(ActOnCompoundStmt(MoveConstructor->getLocation(), + MoveConstructor->getLocation(), + MultiStmtArg(*this, 0, 0), + /*isStmtExpr=*/false) + .takeAs()); + MoveConstructor->setImplicitlyDefined(true); + } + + MoveConstructor->setUsed(); + + if (ASTMutationListener *L = getASTMutationListener()) { + L->CompletedImplicitDefinition(MoveConstructor); + } +} + +bool Sema::isImplicitlyDeleted(FunctionDecl *FD) { + return FD->isDeleted() && + (FD->isDefaulted() || FD->isImplicit()) && + isa(FD); +} + +/// \brief Mark the call operator of the given lambda closure type as "used". +static void markLambdaCallOperatorUsed(Sema &S, CXXRecordDecl *Lambda) { + CXXMethodDecl *CallOperator + = cast( + *Lambda->lookup( + S.Context.DeclarationNames.getCXXOperatorName(OO_Call)).first); + CallOperator->setReferenced(); + CallOperator->setUsed(); +} + +void Sema::DefineImplicitLambdaToFunctionPointerConversion( + SourceLocation CurrentLocation, + CXXConversionDecl *Conv) +{ + CXXRecordDecl *Lambda = Conv->getParent(); + + // Make sure that the lambda call operator is marked used. + markLambdaCallOperatorUsed(*this, Lambda); + + Conv->setUsed(); + + ImplicitlyDefinedFunctionScope Scope(*this, Conv); + DiagnosticErrorTrap Trap(Diags); + + // Return the address of the __invoke function. + DeclarationName InvokeName = &Context.Idents.get("__invoke"); + CXXMethodDecl *Invoke + = cast(*Lambda->lookup(InvokeName).first); + Expr *FunctionRef = BuildDeclRefExpr(Invoke, Invoke->getType(), + VK_LValue, Conv->getLocation()).take(); + assert(FunctionRef && "Can't refer to __invoke function?"); + Stmt *Return = ActOnReturnStmt(Conv->getLocation(), FunctionRef).take(); + Conv->setBody(new (Context) CompoundStmt(Context, &Return, 1, + Conv->getLocation(), + Conv->getLocation())); + + // Fill in the __invoke function with a dummy implementation. IR generation + // will fill in the actual details. + Invoke->setUsed(); + Invoke->setReferenced(); + Invoke->setBody(new (Context) CompoundStmt(Context, 0, 0, Conv->getLocation(), + Conv->getLocation())); + + if (ASTMutationListener *L = getASTMutationListener()) { + L->CompletedImplicitDefinition(Conv); + L->CompletedImplicitDefinition(Invoke); + } +} + +void Sema::DefineImplicitLambdaToBlockPointerConversion( + SourceLocation CurrentLocation, + CXXConversionDecl *Conv) +{ + Conv->setUsed(); + + ImplicitlyDefinedFunctionScope Scope(*this, Conv); + DiagnosticErrorTrap Trap(Diags); + + // Copy-initialize the lambda object as needed to capture it. + Expr *This = ActOnCXXThis(CurrentLocation).take(); + Expr *DerefThis =CreateBuiltinUnaryOp(CurrentLocation, UO_Deref, This).take(); + + ExprResult BuildBlock = BuildBlockForLambdaConversion(CurrentLocation, + Conv->getLocation(), + Conv, DerefThis); + + // If we're not under ARC, make sure we still get the _Block_copy/autorelease + // behavior. Note that only the general conversion function does this + // (since it's unusable otherwise); in the case where we inline the + // block literal, it has block literal lifetime semantics. + if (!BuildBlock.isInvalid() && !getLangOpts().ObjCAutoRefCount) + BuildBlock = ImplicitCastExpr::Create(Context, BuildBlock.get()->getType(), + CK_CopyAndAutoreleaseBlockObject, + BuildBlock.get(), 0, VK_RValue); + + if (BuildBlock.isInvalid()) { + Diag(CurrentLocation, diag::note_lambda_to_block_conv); + Conv->setInvalidDecl(); + return; + } + + // Create the return statement that returns the block from the conversion + // function. + StmtResult Return = ActOnReturnStmt(Conv->getLocation(), BuildBlock.get()); + if (Return.isInvalid()) { + Diag(CurrentLocation, diag::note_lambda_to_block_conv); + Conv->setInvalidDecl(); + return; + } + + // Set the body of the conversion function. + Stmt *ReturnS = Return.take(); + Conv->setBody(new (Context) CompoundStmt(Context, &ReturnS, 1, + Conv->getLocation(), + Conv->getLocation())); + + // We're done; notify the mutation listener, if any. + if (ASTMutationListener *L = getASTMutationListener()) { + L->CompletedImplicitDefinition(Conv); + } +} + +/// \brief Determine whether the given list arguments contains exactly one +/// "real" (non-default) argument. +static bool hasOneRealArgument(MultiExprArg Args) { + switch (Args.size()) { + case 0: + return false; + + default: + if (!Args.get()[1]->isDefaultArgument()) + return false; + + // fall through + case 1: + return !Args.get()[0]->isDefaultArgument(); + } + + return false; +} + +ExprResult +Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, + CXXConstructorDecl *Constructor, + MultiExprArg ExprArgs, + bool HadMultipleCandidates, + bool RequiresZeroInit, + unsigned ConstructKind, + SourceRange ParenRange) { + bool Elidable = false; + + // C++0x [class.copy]p34: + // When certain criteria are met, an implementation is allowed to + // omit the copy/move construction of a class object, even if the + // copy/move constructor and/or destructor for the object have + // side effects. [...] + // - when a temporary class object that has not been bound to a + // reference (12.2) would be copied/moved to a class object + // with the same cv-unqualified type, the copy/move operation + // can be omitted by constructing the temporary object + // directly into the target of the omitted copy/move + if (ConstructKind == CXXConstructExpr::CK_Complete && + Constructor->isCopyOrMoveConstructor() && hasOneRealArgument(ExprArgs)) { + Expr *SubExpr = ((Expr **)ExprArgs.get())[0]; + Elidable = SubExpr->isTemporaryObject(Context, Constructor->getParent()); + } + + return BuildCXXConstructExpr(ConstructLoc, DeclInitType, Constructor, + Elidable, move(ExprArgs), HadMultipleCandidates, + RequiresZeroInit, ConstructKind, ParenRange); +} + +/// BuildCXXConstructExpr - Creates a complete call to a constructor, +/// including handling of its default argument expressions. +ExprResult +Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, + CXXConstructorDecl *Constructor, bool Elidable, + MultiExprArg ExprArgs, + bool HadMultipleCandidates, + bool RequiresZeroInit, + unsigned ConstructKind, + SourceRange ParenRange) { + unsigned NumExprs = ExprArgs.size(); + Expr **Exprs = (Expr **)ExprArgs.release(); + + for (specific_attr_iterator + i = Constructor->specific_attr_begin(), + e = Constructor->specific_attr_end(); i != e; ++i) { + const NonNullAttr *NonNull = *i; + CheckNonNullArguments(NonNull, ExprArgs.get(), ConstructLoc); + } + + MarkFunctionReferenced(ConstructLoc, Constructor); + return Owned(CXXConstructExpr::Create(Context, DeclInitType, ConstructLoc, + Constructor, Elidable, Exprs, NumExprs, + HadMultipleCandidates, /*FIXME*/false, + RequiresZeroInit, + static_cast(ConstructKind), + ParenRange)); +} + +bool Sema::InitializeVarWithConstructor(VarDecl *VD, + CXXConstructorDecl *Constructor, + MultiExprArg Exprs, + bool HadMultipleCandidates) { + // FIXME: Provide the correct paren SourceRange when available. + ExprResult TempResult = + BuildCXXConstructExpr(VD->getLocation(), VD->getType(), Constructor, + move(Exprs), HadMultipleCandidates, false, + CXXConstructExpr::CK_Complete, SourceRange()); + if (TempResult.isInvalid()) + return true; + + Expr *Temp = TempResult.takeAs(); + CheckImplicitConversions(Temp, VD->getLocation()); + MarkFunctionReferenced(VD->getLocation(), Constructor); + Temp = MaybeCreateExprWithCleanups(Temp); + VD->setInit(Temp); + + return false; +} + +void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) { + if (VD->isInvalidDecl()) return; + + CXXRecordDecl *ClassDecl = cast(Record->getDecl()); + if (ClassDecl->isInvalidDecl()) return; + if (ClassDecl->hasIrrelevantDestructor()) return; + if (ClassDecl->isDependentContext()) return; + + CXXDestructorDecl *Destructor = LookupDestructor(ClassDecl); + MarkFunctionReferenced(VD->getLocation(), Destructor); + CheckDestructorAccess(VD->getLocation(), Destructor, + PDiag(diag::err_access_dtor_var) + << VD->getDeclName() + << VD->getType()); + DiagnoseUseOfDecl(Destructor, VD->getLocation()); + + if (!VD->hasGlobalStorage()) return; + + // Emit warning for non-trivial dtor in global scope (a real global, + // class-static, function-static). + Diag(VD->getLocation(), diag::warn_exit_time_destructor); + + // TODO: this should be re-enabled for static locals by !CXAAtExit + if (!VD->isStaticLocal()) + Diag(VD->getLocation(), diag::warn_global_destructor); +} + +/// \brief Given a constructor and the set of arguments provided for the +/// constructor, convert the arguments and add any required default arguments +/// to form a proper call to this constructor. +/// +/// \returns true if an error occurred, false otherwise. +bool +Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor, + MultiExprArg ArgsPtr, + SourceLocation Loc, + ASTOwningVector &ConvertedArgs, + bool AllowExplicit) { + // FIXME: This duplicates a lot of code from Sema::ConvertArgumentsForCall. + unsigned NumArgs = ArgsPtr.size(); + Expr **Args = (Expr **)ArgsPtr.get(); + + const FunctionProtoType *Proto + = Constructor->getType()->getAs(); + assert(Proto && "Constructor without a prototype?"); + unsigned NumArgsInProto = Proto->getNumArgs(); + + // If too few arguments are available, we'll fill in the rest with defaults. + if (NumArgs < NumArgsInProto) + ConvertedArgs.reserve(NumArgsInProto); + else + ConvertedArgs.reserve(NumArgs); + + VariadicCallType CallType = + Proto->isVariadic() ? VariadicConstructor : VariadicDoesNotApply; + SmallVector AllArgs; + bool Invalid = GatherArgumentsForCall(Loc, Constructor, + Proto, 0, Args, NumArgs, AllArgs, + CallType, AllowExplicit); + ConvertedArgs.append(AllArgs.begin(), AllArgs.end()); + + DiagnoseSentinelCalls(Constructor, Loc, AllArgs.data(), AllArgs.size()); + + // FIXME: Missing call to CheckFunctionCall or equivalent + + return Invalid; +} + +static inline bool +CheckOperatorNewDeleteDeclarationScope(Sema &SemaRef, + const FunctionDecl *FnDecl) { + const DeclContext *DC = FnDecl->getDeclContext()->getRedeclContext(); + if (isa(DC)) { + return SemaRef.Diag(FnDecl->getLocation(), + diag::err_operator_new_delete_declared_in_namespace) + << FnDecl->getDeclName(); + } + + if (isa(DC) && + FnDecl->getStorageClass() == SC_Static) { + return SemaRef.Diag(FnDecl->getLocation(), + diag::err_operator_new_delete_declared_static) + << FnDecl->getDeclName(); + } + + return false; +} + +static inline bool +CheckOperatorNewDeleteTypes(Sema &SemaRef, const FunctionDecl *FnDecl, + CanQualType ExpectedResultType, + CanQualType ExpectedFirstParamType, + unsigned DependentParamTypeDiag, + unsigned InvalidParamTypeDiag) { + QualType ResultType = + FnDecl->getType()->getAs()->getResultType(); + + // Check that the result type is not dependent. + if (ResultType->isDependentType()) + return SemaRef.Diag(FnDecl->getLocation(), + diag::err_operator_new_delete_dependent_result_type) + << FnDecl->getDeclName() << ExpectedResultType; + + // Check that the result type is what we expect. + if (SemaRef.Context.getCanonicalType(ResultType) != ExpectedResultType) + return SemaRef.Diag(FnDecl->getLocation(), + diag::err_operator_new_delete_invalid_result_type) + << FnDecl->getDeclName() << ExpectedResultType; + + // A function template must have at least 2 parameters. + if (FnDecl->getDescribedFunctionTemplate() && FnDecl->getNumParams() < 2) + return SemaRef.Diag(FnDecl->getLocation(), + diag::err_operator_new_delete_template_too_few_parameters) + << FnDecl->getDeclName(); + + // The function decl must have at least 1 parameter. + if (FnDecl->getNumParams() == 0) + return SemaRef.Diag(FnDecl->getLocation(), + diag::err_operator_new_delete_too_few_parameters) + << FnDecl->getDeclName(); + + // Check the the first parameter type is not dependent. + QualType FirstParamType = FnDecl->getParamDecl(0)->getType(); + if (FirstParamType->isDependentType()) + return SemaRef.Diag(FnDecl->getLocation(), DependentParamTypeDiag) + << FnDecl->getDeclName() << ExpectedFirstParamType; + + // Check that the first parameter type is what we expect. + if (SemaRef.Context.getCanonicalType(FirstParamType).getUnqualifiedType() != + ExpectedFirstParamType) + return SemaRef.Diag(FnDecl->getLocation(), InvalidParamTypeDiag) + << FnDecl->getDeclName() << ExpectedFirstParamType; + + return false; +} + +static bool +CheckOperatorNewDeclaration(Sema &SemaRef, const FunctionDecl *FnDecl) { + // C++ [basic.stc.dynamic.allocation]p1: + // A program is ill-formed if an allocation function is declared in a + // namespace scope other than global scope or declared static in global + // scope. + if (CheckOperatorNewDeleteDeclarationScope(SemaRef, FnDecl)) + return true; + + CanQualType SizeTy = + SemaRef.Context.getCanonicalType(SemaRef.Context.getSizeType()); + + // C++ [basic.stc.dynamic.allocation]p1: + // The return type shall be void*. The first parameter shall have type + // std::size_t. + if (CheckOperatorNewDeleteTypes(SemaRef, FnDecl, SemaRef.Context.VoidPtrTy, + SizeTy, + diag::err_operator_new_dependent_param_type, + diag::err_operator_new_param_type)) + return true; + + // C++ [basic.stc.dynamic.allocation]p1: + // The first parameter shall not have an associated default argument. + if (FnDecl->getParamDecl(0)->hasDefaultArg()) + return SemaRef.Diag(FnDecl->getLocation(), + diag::err_operator_new_default_arg) + << FnDecl->getDeclName() << FnDecl->getParamDecl(0)->getDefaultArgRange(); + + return false; +} + +static bool +CheckOperatorDeleteDeclaration(Sema &SemaRef, const FunctionDecl *FnDecl) { + // C++ [basic.stc.dynamic.deallocation]p1: + // A program is ill-formed if deallocation functions are declared in a + // namespace scope other than global scope or declared static in global + // scope. + if (CheckOperatorNewDeleteDeclarationScope(SemaRef, FnDecl)) + return true; + + // C++ [basic.stc.dynamic.deallocation]p2: + // Each deallocation function shall return void and its first parameter + // shall be void*. + if (CheckOperatorNewDeleteTypes(SemaRef, FnDecl, SemaRef.Context.VoidTy, + SemaRef.Context.VoidPtrTy, + diag::err_operator_delete_dependent_param_type, + diag::err_operator_delete_param_type)) + return true; + + return false; +} + +/// CheckOverloadedOperatorDeclaration - Check whether the declaration +/// of this overloaded operator is well-formed. If so, returns false; +/// otherwise, emits appropriate diagnostics and returns true. +bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) { + assert(FnDecl && FnDecl->isOverloadedOperator() && + "Expected an overloaded operator declaration"); + + OverloadedOperatorKind Op = FnDecl->getOverloadedOperator(); + + // C++ [over.oper]p5: + // The allocation and deallocation functions, operator new, + // operator new[], operator delete and operator delete[], are + // described completely in 3.7.3. The attributes and restrictions + // found in the rest of this subclause do not apply to them unless + // explicitly stated in 3.7.3. + if (Op == OO_Delete || Op == OO_Array_Delete) + return CheckOperatorDeleteDeclaration(*this, FnDecl); + + if (Op == OO_New || Op == OO_Array_New) + return CheckOperatorNewDeclaration(*this, FnDecl); + + // C++ [over.oper]p6: + // An operator function shall either be a non-static member + // function or be a non-member function and have at least one + // parameter whose type is a class, a reference to a class, an + // enumeration, or a reference to an enumeration. + if (CXXMethodDecl *MethodDecl = dyn_cast(FnDecl)) { + if (MethodDecl->isStatic()) + return Diag(FnDecl->getLocation(), + diag::err_operator_overload_static) << FnDecl->getDeclName(); + } else { + bool ClassOrEnumParam = false; + for (FunctionDecl::param_iterator Param = FnDecl->param_begin(), + ParamEnd = FnDecl->param_end(); + Param != ParamEnd; ++Param) { + QualType ParamType = (*Param)->getType().getNonReferenceType(); + if (ParamType->isDependentType() || ParamType->isRecordType() || + ParamType->isEnumeralType()) { + ClassOrEnumParam = true; + break; + } + } + + if (!ClassOrEnumParam) + return Diag(FnDecl->getLocation(), + diag::err_operator_overload_needs_class_or_enum) + << FnDecl->getDeclName(); + } + + // C++ [over.oper]p8: + // An operator function cannot have default arguments (8.3.6), + // except where explicitly stated below. + // + // Only the function-call operator allows default arguments + // (C++ [over.call]p1). + if (Op != OO_Call) { + for (FunctionDecl::param_iterator Param = FnDecl->param_begin(); + Param != FnDecl->param_end(); ++Param) { + if ((*Param)->hasDefaultArg()) + return Diag((*Param)->getLocation(), + diag::err_operator_overload_default_arg) + << FnDecl->getDeclName() << (*Param)->getDefaultArgRange(); + } + } + + static const bool OperatorUses[NUM_OVERLOADED_OPERATORS][3] = { + { false, false, false } +#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ + , { Unary, Binary, MemberOnly } +#include "clang/Basic/OperatorKinds.def" + }; + + bool CanBeUnaryOperator = OperatorUses[Op][0]; + bool CanBeBinaryOperator = OperatorUses[Op][1]; + bool MustBeMemberOperator = OperatorUses[Op][2]; + + // C++ [over.oper]p8: + // [...] Operator functions cannot have more or fewer parameters + // than the number required for the corresponding operator, as + // described in the rest of this subclause. + unsigned NumParams = FnDecl->getNumParams() + + (isa(FnDecl)? 1 : 0); + if (Op != OO_Call && + ((NumParams == 1 && !CanBeUnaryOperator) || + (NumParams == 2 && !CanBeBinaryOperator) || + (NumParams < 1) || (NumParams > 2))) { + // We have the wrong number of parameters. + unsigned ErrorKind; + if (CanBeUnaryOperator && CanBeBinaryOperator) { + ErrorKind = 2; // 2 -> unary or binary. + } else if (CanBeUnaryOperator) { + ErrorKind = 0; // 0 -> unary + } else { + assert(CanBeBinaryOperator && + "All non-call overloaded operators are unary or binary!"); + ErrorKind = 1; // 1 -> binary + } + + return Diag(FnDecl->getLocation(), diag::err_operator_overload_must_be) + << FnDecl->getDeclName() << NumParams << ErrorKind; + } + + // Overloaded operators other than operator() cannot be variadic. + if (Op != OO_Call && + FnDecl->getType()->getAs()->isVariadic()) { + return Diag(FnDecl->getLocation(), diag::err_operator_overload_variadic) + << FnDecl->getDeclName(); + } + + // Some operators must be non-static member functions. + if (MustBeMemberOperator && !isa(FnDecl)) { + return Diag(FnDecl->getLocation(), + diag::err_operator_overload_must_be_member) + << FnDecl->getDeclName(); + } + + // C++ [over.inc]p1: + // The user-defined function called operator++ implements the + // prefix and postfix ++ operator. If this function is a member + // function with no parameters, or a non-member function with one + // parameter of class or enumeration type, it defines the prefix + // increment operator ++ for objects of that type. If the function + // is a member function with one parameter (which shall be of type + // int) or a non-member function with two parameters (the second + // of which shall be of type int), it defines the postfix + // increment operator ++ for objects of that type. + if ((Op == OO_PlusPlus || Op == OO_MinusMinus) && NumParams == 2) { + ParmVarDecl *LastParam = FnDecl->getParamDecl(FnDecl->getNumParams() - 1); + bool ParamIsInt = false; + if (const BuiltinType *BT = LastParam->getType()->getAs()) + ParamIsInt = BT->getKind() == BuiltinType::Int; + + if (!ParamIsInt) + return Diag(LastParam->getLocation(), + diag::err_operator_overload_post_incdec_must_be_int) + << LastParam->getType() << (Op == OO_MinusMinus); + } + + return false; +} + +/// CheckLiteralOperatorDeclaration - Check whether the declaration +/// of this literal operator function is well-formed. If so, returns +/// false; otherwise, emits appropriate diagnostics and returns true. +bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) { + if (isa(FnDecl)) { + Diag(FnDecl->getLocation(), diag::err_literal_operator_outside_namespace) + << FnDecl->getDeclName(); + return true; + } + + if (FnDecl->isExternC()) { + Diag(FnDecl->getLocation(), diag::err_literal_operator_extern_c); + return true; + } + + bool Valid = false; + + // This might be the definition of a literal operator template. + FunctionTemplateDecl *TpDecl = FnDecl->getDescribedFunctionTemplate(); + // This might be a specialization of a literal operator template. + if (!TpDecl) + TpDecl = FnDecl->getPrimaryTemplate(); + + // template type operator "" name() is the only valid template + // signature, and the only valid signature with no parameters. + if (TpDecl) { + if (FnDecl->param_size() == 0) { + // Must have only one template parameter + TemplateParameterList *Params = TpDecl->getTemplateParameters(); + if (Params->size() == 1) { + NonTypeTemplateParmDecl *PmDecl = + cast(Params->getParam(0)); + + // The template parameter must be a char parameter pack. + if (PmDecl && PmDecl->isTemplateParameterPack() && + Context.hasSameType(PmDecl->getType(), Context.CharTy)) + Valid = true; + } + } + } else if (FnDecl->param_size()) { + // Check the first parameter + FunctionDecl::param_iterator Param = FnDecl->param_begin(); + + QualType T = (*Param)->getType().getUnqualifiedType(); + + // unsigned long long int, long double, and any character type are allowed + // as the only parameters. + if (Context.hasSameType(T, Context.UnsignedLongLongTy) || + Context.hasSameType(T, Context.LongDoubleTy) || + Context.hasSameType(T, Context.CharTy) || + Context.hasSameType(T, Context.WCharTy) || + Context.hasSameType(T, Context.Char16Ty) || + Context.hasSameType(T, Context.Char32Ty)) { + if (++Param == FnDecl->param_end()) + Valid = true; + goto FinishedParams; + } + + // Otherwise it must be a pointer to const; let's strip those qualifiers. + const PointerType *PT = T->getAs(); + if (!PT) + goto FinishedParams; + T = PT->getPointeeType(); + if (!T.isConstQualified() || T.isVolatileQualified()) + goto FinishedParams; + T = T.getUnqualifiedType(); + + // Move on to the second parameter; + ++Param; + + // If there is no second parameter, the first must be a const char * + if (Param == FnDecl->param_end()) { + if (Context.hasSameType(T, Context.CharTy)) + Valid = true; + goto FinishedParams; + } + + // const char *, const wchar_t*, const char16_t*, and const char32_t* + // are allowed as the first parameter to a two-parameter function + if (!(Context.hasSameType(T, Context.CharTy) || + Context.hasSameType(T, Context.WCharTy) || + Context.hasSameType(T, Context.Char16Ty) || + Context.hasSameType(T, Context.Char32Ty))) + goto FinishedParams; + + // The second and final parameter must be an std::size_t + T = (*Param)->getType().getUnqualifiedType(); + if (Context.hasSameType(T, Context.getSizeType()) && + ++Param == FnDecl->param_end()) + Valid = true; + } + + // FIXME: This diagnostic is absolutely terrible. +FinishedParams: + if (!Valid) { + Diag(FnDecl->getLocation(), diag::err_literal_operator_params) + << FnDecl->getDeclName(); + return true; + } + + // A parameter-declaration-clause containing a default argument is not + // equivalent to any of the permitted forms. + for (FunctionDecl::param_iterator Param = FnDecl->param_begin(), + ParamEnd = FnDecl->param_end(); + Param != ParamEnd; ++Param) { + if ((*Param)->hasDefaultArg()) { + Diag((*Param)->getDefaultArgRange().getBegin(), + diag::err_literal_operator_default_argument) + << (*Param)->getDefaultArgRange(); + break; + } + } + + StringRef LiteralName + = FnDecl->getDeclName().getCXXLiteralIdentifier()->getName(); + if (LiteralName[0] != '_') { + // C++11 [usrlit.suffix]p1: + // Literal suffix identifiers that do not start with an underscore + // are reserved for future standardization. + Diag(FnDecl->getLocation(), diag::warn_user_literal_reserved); + } + + return false; +} + +/// ActOnStartLinkageSpecification - Parsed the beginning of a C++ +/// linkage specification, including the language and (if present) +/// the '{'. ExternLoc is the location of the 'extern', LangLoc is +/// the location of the language string literal, which is provided +/// by Lang/StrSize. LBraceLoc, if valid, provides the location of +/// the '{' brace. Otherwise, this linkage specification does not +/// have any braces. +Decl *Sema::ActOnStartLinkageSpecification(Scope *S, SourceLocation ExternLoc, + SourceLocation LangLoc, + StringRef Lang, + SourceLocation LBraceLoc) { + LinkageSpecDecl::LanguageIDs Language; + if (Lang == "\"C\"") + Language = LinkageSpecDecl::lang_c; + else if (Lang == "\"C++\"") + Language = LinkageSpecDecl::lang_cxx; + else { + Diag(LangLoc, diag::err_bad_language); + return 0; + } + + // FIXME: Add all the various semantics of linkage specifications + + LinkageSpecDecl *D = LinkageSpecDecl::Create(Context, CurContext, + ExternLoc, LangLoc, Language); + CurContext->addDecl(D); + PushDeclContext(S, D); + return D; +} + +/// 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. +Decl *Sema::ActOnFinishLinkageSpecification(Scope *S, + Decl *LinkageSpec, + SourceLocation RBraceLoc) { + if (LinkageSpec) { + if (RBraceLoc.isValid()) { + LinkageSpecDecl* LSDecl = cast(LinkageSpec); + LSDecl->setRBraceLoc(RBraceLoc); + } + PopDeclContext(); + } + return LinkageSpec; +} + +/// \brief Perform semantic analysis for the variable declaration that +/// occurs within a C++ catch clause, returning the newly-created +/// variable. +VarDecl *Sema::BuildExceptionDeclaration(Scope *S, + TypeSourceInfo *TInfo, + SourceLocation StartLoc, + SourceLocation Loc, + IdentifierInfo *Name) { + bool Invalid = false; + QualType ExDeclType = TInfo->getType(); + + // Arrays and functions decay. + if (ExDeclType->isArrayType()) + ExDeclType = Context.getArrayDecayedType(ExDeclType); + else if (ExDeclType->isFunctionType()) + ExDeclType = Context.getPointerType(ExDeclType); + + // C++ 15.3p1: The exception-declaration shall not denote an incomplete type. + // The exception-declaration shall not denote a pointer or reference to an + // incomplete type, other than [cv] void*. + // N2844 forbids rvalue references. + if (!ExDeclType->isDependentType() && ExDeclType->isRValueReferenceType()) { + Diag(Loc, diag::err_catch_rvalue_ref); + Invalid = true; + } + + QualType BaseType = ExDeclType; + int Mode = 0; // 0 for direct type, 1 for pointer, 2 for reference + unsigned DK = diag::err_catch_incomplete; + if (const PointerType *Ptr = BaseType->getAs()) { + BaseType = Ptr->getPointeeType(); + Mode = 1; + DK = diag::err_catch_incomplete_ptr; + } else if (const ReferenceType *Ref = BaseType->getAs()) { + // For the purpose of error recovery, we treat rvalue refs like lvalue refs. + BaseType = Ref->getPointeeType(); + Mode = 2; + DK = diag::err_catch_incomplete_ref; + } + if (!Invalid && (Mode == 0 || !BaseType->isVoidType()) && + !BaseType->isDependentType() && RequireCompleteType(Loc, BaseType, DK)) + Invalid = true; + + if (!Invalid && !ExDeclType->isDependentType() && + RequireNonAbstractType(Loc, ExDeclType, + diag::err_abstract_type_in_decl, + 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 && getLangOpts().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 (!getLangOpts().ObjCNonFragileABI) + Diag(Loc, diag::warn_objc_pointer_cxx_catch_fragile); + } + } + + VarDecl *ExDecl = VarDecl::Create(Context, CurContext, StartLoc, Loc, Name, + ExDeclType, TInfo, SC_None, SC_None); + ExDecl->setExceptionVariable(true); + + // In ARC, infer 'retaining' for variables of retainable type. + if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(ExDecl)) + Invalid = true; + + if (!Invalid && !ExDeclType->isDependentType()) { + if (const RecordType *recordType = ExDeclType->getAs()) { + // C++ [except.handle]p16: + // The object declared in an exception-declaration or, if the + // exception-declaration does not specify a name, a temporary (12.2) is + // copy-initialized (8.5) from the exception object. [...] + // The object is destroyed when the handler exits, after the destruction + // of any automatic objects initialized within the handler. + // + // We just pretend to initialize the object with itself, then make sure + // it can be destroyed later. + QualType initType = ExDeclType; + + InitializedEntity entity = + InitializedEntity::InitializeVariable(ExDecl); + InitializationKind initKind = + InitializationKind::CreateCopy(Loc, SourceLocation()); + + Expr *opaqueValue = + new (Context) OpaqueValueExpr(Loc, initType, VK_LValue, OK_Ordinary); + InitializationSequence sequence(*this, entity, initKind, &opaqueValue, 1); + ExprResult result = sequence.Perform(*this, entity, initKind, + MultiExprArg(&opaqueValue, 1)); + if (result.isInvalid()) + Invalid = true; + else { + // If the constructor used was non-trivial, set this as the + // "initializer". + CXXConstructExpr *construct = cast(result.take()); + if (!construct->getConstructor()->isTrivial()) { + Expr *init = MaybeCreateExprWithCleanups(construct); + ExDecl->setInit(init); + } + + // And make sure it's destructable. + FinalizeVarWithDestructor(ExDecl, recordType); + } + } + } + + if (Invalid) + ExDecl->setInvalidDecl(); + + return ExDecl; +} + +/// ActOnExceptionDeclarator - Parsed the exception-declarator in a C++ catch +/// handler. +Decl *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) { + TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); + bool Invalid = D.isInvalidType(); + + // Check for unexpanded parameter packs. + if (TInfo && DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo, + UPPC_ExceptionType)) { + TInfo = Context.getTrivialTypeSourceInfo(Context.IntTy, + D.getIdentifierLoc()); + Invalid = true; + } + + IdentifierInfo *II = D.getIdentifier(); + if (NamedDecl *PrevDecl = LookupSingleName(S, II, D.getIdentifierLoc(), + LookupOrdinaryName, + ForRedeclaration)) { + // The scope should be freshly made just for us. There is just no way + // it contains any previous declaration. + assert(!S->isDeclScope(PrevDecl)); + if (PrevDecl->isTemplateParameter()) { + // Maybe we will complain about the shadowed template parameter. + DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl); + PrevDecl = 0; + } + } + + if (D.getCXXScopeSpec().isSet() && !Invalid) { + Diag(D.getIdentifierLoc(), diag::err_qualified_catch_declarator) + << D.getCXXScopeSpec().getRange(); + Invalid = true; + } + + VarDecl *ExDecl = BuildExceptionDeclaration(S, TInfo, + D.getLocStart(), + D.getIdentifierLoc(), + D.getIdentifier()); + if (Invalid) + ExDecl->setInvalidDecl(); + + // Add the exception declaration into this scope. + if (II) + PushOnScopeChains(ExDecl, S); + else + CurContext->addDecl(ExDecl); + + ProcessDeclAttributes(S, ExDecl, D); + return ExDecl; +} + +Decl *Sema::ActOnStaticAssertDeclaration(SourceLocation StaticAssertLoc, + Expr *AssertExpr, + Expr *AssertMessageExpr_, + SourceLocation RParenLoc) { + StringLiteral *AssertMessage = cast(AssertMessageExpr_); + + if (!AssertExpr->isTypeDependent() && !AssertExpr->isValueDependent()) { + // In a static_assert-declaration, the constant-expression shall be a + // constant expression that can be contextually converted to bool. + ExprResult Converted = PerformContextuallyConvertToBool(AssertExpr); + if (Converted.isInvalid()) + return 0; + + llvm::APSInt Cond; + if (VerifyIntegerConstantExpression(Converted.get(), &Cond, + PDiag(diag::err_static_assert_expression_is_not_constant), + /*AllowFold=*/false).isInvalid()) + return 0; + + if (!Cond) { + llvm::SmallString<256> MsgBuffer; + llvm::raw_svector_ostream Msg(MsgBuffer); + AssertMessage->printPretty(Msg, Context, 0, getPrintingPolicy()); + Diag(StaticAssertLoc, diag::err_static_assert_failed) + << Msg.str() << AssertExpr->getSourceRange(); + } + } + + if (DiagnoseUnexpandedParameterPack(AssertExpr, UPPC_StaticAssertExpression)) + return 0; + + Decl *Decl = StaticAssertDecl::Create(Context, CurContext, StaticAssertLoc, + AssertExpr, AssertMessage, RParenLoc); + + CurContext->addDecl(Decl); + return Decl; +} + +/// \brief Perform semantic analysis of the given friend type declaration. +/// +/// \returns A friend declaration that. +FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation Loc, + SourceLocation FriendLoc, + TypeSourceInfo *TSInfo) { + assert(TSInfo && "NULL TypeSourceInfo for friend type declaration"); + + QualType T = TSInfo->getType(); + SourceRange TypeRange = TSInfo->getTypeLoc().getLocalSourceRange(); + + // C++03 [class.friend]p2: + // An elaborated-type-specifier shall be used in a friend declaration + // for a class.* + // + // * The class-key of the elaborated-type-specifier is required. + if (!ActiveTemplateInstantiations.empty()) { + // Do not complain about the form of friend template types during + // template instantiation; we will already have complained when the + // template was declared. + } else if (!T->isElaboratedTypeSpecifier()) { + // If we evaluated the type to a record type, suggest putting + // a tag in front. + if (const RecordType *RT = T->getAs()) { + RecordDecl *RD = RT->getDecl(); + + std::string InsertionText = std::string(" ") + RD->getKindName(); + + Diag(TypeRange.getBegin(), + getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_unelaborated_friend_type : + diag::ext_unelaborated_friend_type) + << (unsigned) RD->getTagKind() + << T + << FixItHint::CreateInsertion(PP.getLocForEndOfToken(FriendLoc), + InsertionText); + } else { + Diag(FriendLoc, + getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_nonclass_type_friend : + diag::ext_nonclass_type_friend) + << T + << SourceRange(FriendLoc, TypeRange.getEnd()); + } + } else if (T->getAs()) { + Diag(FriendLoc, + getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_enum_friend : + diag::ext_enum_friend) + << T + << SourceRange(FriendLoc, TypeRange.getEnd()); + } + + // C++0x [class.friend]p3: + // If the type specifier in a friend declaration designates a (possibly + // cv-qualified) class type, that class is declared as a friend; otherwise, + // the friend declaration is ignored. + + // FIXME: C++0x has some syntactic restrictions on friend type declarations + // in [class.friend]p3 that we do not implement. + + return FriendDecl::Create(Context, CurContext, Loc, TSInfo, FriendLoc); +} + +/// Handle a friend tag declaration where the scope specifier was +/// templated. +Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, + unsigned TagSpec, SourceLocation TagLoc, + CXXScopeSpec &SS, + IdentifierInfo *Name, SourceLocation NameLoc, + AttributeList *Attr, + MultiTemplateParamsArg TempParamLists) { + TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec); + + bool isExplicitSpecialization = false; + bool Invalid = false; + + if (TemplateParameterList *TemplateParams + = MatchTemplateParametersToScopeSpecifier(TagLoc, NameLoc, SS, + TempParamLists.get(), + TempParamLists.size(), + /*friend*/ true, + isExplicitSpecialization, + Invalid)) { + if (TemplateParams->size() > 0) { + // This is a declaration of a class template. + if (Invalid) + return 0; + + return CheckClassTemplate(S, TagSpec, TUK_Friend, TagLoc, + SS, Name, NameLoc, Attr, + TemplateParams, AS_public, + /*ModulePrivateLoc=*/SourceLocation(), + TempParamLists.size() - 1, + (TemplateParameterList**) TempParamLists.release()).take(); + } else { + // The "template<>" header is extraneous. + Diag(TemplateParams->getTemplateLoc(), diag::err_template_tag_noparams) + << TypeWithKeyword::getTagTypeKindName(Kind) << Name; + isExplicitSpecialization = true; + } + } + + if (Invalid) return 0; + + bool isAllExplicitSpecializations = true; + for (unsigned I = TempParamLists.size(); I-- > 0; ) { + if (TempParamLists.get()[I]->size()) { + isAllExplicitSpecializations = false; + break; + } + } + + // FIXME: don't ignore attributes. + + // If it's explicit specializations all the way down, just forget + // about the template header and build an appropriate non-templated + // friend. TODO: for source fidelity, remember the headers. + if (isAllExplicitSpecializations) { + if (SS.isEmpty()) { + bool Owned = false; + bool IsDependent = false; + return ActOnTag(S, TagSpec, TUK_Friend, TagLoc, SS, Name, NameLoc, + Attr, AS_public, + /*ModulePrivateLoc=*/SourceLocation(), + MultiTemplateParamsArg(), Owned, IsDependent, + /*ScopedEnumKWLoc=*/SourceLocation(), + /*ScopedEnumUsesClassTag=*/false, + /*UnderlyingType=*/TypeResult()); + } + + NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context); + ElaboratedTypeKeyword Keyword + = TypeWithKeyword::getKeywordForTagTypeKind(Kind); + QualType T = CheckTypenameType(Keyword, TagLoc, QualifierLoc, + *Name, NameLoc); + if (T.isNull()) + return 0; + + TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T); + if (isa(T)) { + DependentNameTypeLoc TL = cast(TSI->getTypeLoc()); + TL.setElaboratedKeywordLoc(TagLoc); + TL.setQualifierLoc(QualifierLoc); + TL.setNameLoc(NameLoc); + } else { + ElaboratedTypeLoc TL = cast(TSI->getTypeLoc()); + TL.setElaboratedKeywordLoc(TagLoc); + TL.setQualifierLoc(QualifierLoc); + cast(TL.getNamedTypeLoc()).setNameLoc(NameLoc); + } + + FriendDecl *Friend = FriendDecl::Create(Context, CurContext, NameLoc, + TSI, FriendLoc); + Friend->setAccess(AS_public); + CurContext->addDecl(Friend); + return Friend; + } + + assert(SS.isNotEmpty() && "valid templated tag with no SS and no direct?"); + + + + // Handle the case of a templated-scope friend class. e.g. + // template class A::B; + // FIXME: we don't support these right now. + ElaboratedTypeKeyword ETK = TypeWithKeyword::getKeywordForTagTypeKind(Kind); + QualType T = Context.getDependentNameType(ETK, SS.getScopeRep(), Name); + TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T); + DependentNameTypeLoc TL = cast(TSI->getTypeLoc()); + TL.setElaboratedKeywordLoc(TagLoc); + TL.setQualifierLoc(SS.getWithLocInContext(Context)); + TL.setNameLoc(NameLoc); + + FriendDecl *Friend = FriendDecl::Create(Context, CurContext, NameLoc, + TSI, FriendLoc); + Friend->setAccess(AS_public); + Friend->setUnsupportedFriend(true); + CurContext->addDecl(Friend); + return Friend; +} + + +/// Handle a friend type declaration. This works in tandem with +/// ActOnTag. +/// +/// Notes on friend class templates: +/// +/// We generally treat friend class declarations as if they were +/// declaring a class. So, for example, the elaborated type specifier +/// in a friend declaration is required to obey the restrictions of a +/// class-head (i.e. no typedefs in the scope chain), template +/// parameters are required to match up with simple template-ids, &c. +/// However, unlike when declaring a template specialization, it's +/// okay to refer to a template specialization without an empty +/// template parameter declaration, e.g. +/// friend class A::B; +/// 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; +Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, + MultiTemplateParamsArg TempParams) { + SourceLocation Loc = DS.getLocStart(); + + assert(DS.isFriendSpecified()); + assert(DS.getStorageClassSpec() == DeclSpec::SCS_unspecified); + + // Try to convert the decl specifier to a type. This works for + // friend templates because ActOnTag never produces a ClassTemplateDecl + // for a TUK_Friend. + Declarator TheDeclarator(DS, Declarator::MemberContext); + TypeSourceInfo *TSI = GetTypeForDeclarator(TheDeclarator, S); + QualType T = TSI->getType(); + if (TheDeclarator.isInvalidType()) + return 0; + + if (DiagnoseUnexpandedParameterPack(Loc, TSI, UPPC_FriendDeclaration)) + 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 + // poorly written. + // + // The problem is with declarations like the following: + // template friend A::foo; + // where deciding whether a class C is a friend or not now hinges + // on whether there exists an instantiation of A that causes + // 'foo' to equal C. There are restrictions on class-heads + // (which we declare (by fiat) elaborated friend declarations to + // be) that makes this tractable. + // + // FIXME: handle "template <> friend class A;", which + // is possibly well-formed? Who even knows? + if (TempParams.size() && !T->isElaboratedTypeSpecifier()) { + Diag(Loc, diag::err_tagless_friend_type_template) + << DS.getSourceRange(); + return 0; + } + + // C++98 [class.friend]p1: A friend of a class is a function + // or class that is not a member of the class . . . + // This is fixed in DR77, which just barely didn't make the C++03 + // deadline. It's also a very silly restriction that seriously + // affects inner classes and which nobody else seems to implement; + // thus we never diagnose it, not even in -pedantic. + // + // But note that we could warn about it: it's always useless to + // friend one of your own members (it's not, however, worthless to + // friend a member of an arbitrary specialization of your template). + + Decl *D; + if (unsigned NumTempParamLists = TempParams.size()) + D = FriendTemplateDecl::Create(Context, CurContext, Loc, + NumTempParamLists, + TempParams.release(), + TSI, + DS.getFriendSpecLoc()); + else + D = CheckFriendTypeDecl(Loc, DS.getFriendSpecLoc(), TSI); + + if (!D) + return 0; + + D->setAccess(AS_public); + CurContext->addDecl(D); + + return D; +} + +Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, + MultiTemplateParamsArg TemplateParams) { + const DeclSpec &DS = D.getDeclSpec(); + + assert(DS.isFriendSpecified()); + assert(DS.getStorageClassSpec() == DeclSpec::SCS_unspecified); + + SourceLocation Loc = D.getIdentifierLoc(); + TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); + + // C++ [class.friend]p1 + // A friend of a class is a function or class.... + // Note that this sees through typedefs, which is intended. + // It *doesn't* see through dependent types, which is correct + // according to [temp.arg.type]p3: + // If a declaration acquires a function type through a + // type dependent on a template-parameter and this causes + // a declaration that does not use the syntactic form of a + // function declarator to have a function type, the program + // is ill-formed. + if (!TInfo->getType()->isFunctionType()) { + Diag(Loc, diag::err_unexpected_friend); + + // It might be worthwhile to try to recover by creating an + // appropriate declaration. + return 0; + } + + // C++ [namespace.memdef]p3 + // - If a friend declaration in a non-local class first declares a + // class or function, the friend class or function is a member + // of the innermost enclosing namespace. + // - The name of the friend is not found by simple name lookup + // until a matching declaration is provided in that namespace + // scope (either before or after the class declaration granting + // friendship). + // - If a friend function is called, its name may be found by the + // name lookup that considers functions from namespaces and + // classes associated with the types of the function arguments. + // - When looking for a prior declaration of a class or a function + // declared as a friend, scopes outside the innermost enclosing + // namespace scope are not considered. + + CXXScopeSpec &SS = D.getCXXScopeSpec(); + DeclarationNameInfo NameInfo = GetNameForDeclarator(D); + DeclarationName Name = NameInfo.getName(); + assert(Name); + + // Check for unexpanded parameter packs. + if (DiagnoseUnexpandedParameterPack(Loc, TInfo, UPPC_FriendDeclaration) || + DiagnoseUnexpandedParameterPack(NameInfo, UPPC_FriendDeclaration) || + DiagnoseUnexpandedParameterPack(SS, UPPC_FriendDeclaration)) + return 0; + + // The context we found the declaration in, or in which we should + // create the declaration. + DeclContext *DC; + Scope *DCScope = S; + LookupResult Previous(*this, NameInfo, LookupOrdinaryName, + ForRedeclaration); + + // FIXME: there are different rules in local classes + + // There are four cases here. + // - There's no scope specifier, in which case we just go to the + // appropriate scope and look for a function or function template + // there as appropriate. + // Recover from invalid scope qualifiers as if they just weren't there. + if (SS.isInvalid() || !SS.isSet()) { + // C++0x [namespace.memdef]p3: + // If the name in a friend declaration is neither qualified nor + // a template-id and the declaration is a function or an + // elaborated-type-specifier, the lookup to determine whether + // the entity has been previously declared shall not consider + // any scopes outside the innermost enclosing namespace. + // C++0x [class.friend]p11: + // If a friend declaration appears in a local class and the name + // specified is an unqualified name, a prior declaration is + // looked up without considering scopes that are outside the + // innermost enclosing non-class scope. For a friend function + // declaration, if there is no prior declaration, the program is + // ill-formed. + bool isLocal = cast(CurContext)->isLocalClass(); + bool isTemplateId = D.getName().getKind() == UnqualifiedId::IK_TemplateId; + + // Find the appropriate context according to the above. + DC = CurContext; + while (true) { + // Skip class contexts. If someone can cite chapter and verse + // for this behavior, that would be nice --- it's what GCC and + // EDG do, and it seems like a reasonable intent, but the spec + // really only says that checks for unqualified existing + // declarations should stop at the nearest enclosing namespace, + // not that they should only consider the nearest enclosing + // namespace. + while (DC->isRecord() || DC->isTransparentContext()) + DC = DC->getParent(); + + LookupQualifiedName(Previous, DC); + + // TODO: decide what we think about using declarations. + if (isLocal || !Previous.empty()) + break; + + if (isTemplateId) { + if (isa(DC)) break; + } else { + if (DC->isFileContext()) break; + } + DC = DC->getParent(); + } + + // C++ [class.friend]p1: A friend of a class is a function or + // class that is not a member of the class . . . + // C++11 changes this for both friend types and functions. + // Most C++ 98 compilers do seem to give an error here, so + // we do, too. + if (!Previous.empty() && DC->Equals(CurContext)) + Diag(DS.getFriendSpecLoc(), + getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_friend_is_member : + diag::err_friend_is_member); + + DCScope = getScopeForDeclContext(S, DC); + + // C++ [class.friend]p6: + // A function can be defined in a friend declaration of a class if and + // only if the class is a non-local class (9.8), the function name is + // unqualified, and the function has namespace scope. + if (isLocal && D.isFunctionDefinition()) { + Diag(NameInfo.getBeginLoc(), diag::err_friend_def_in_local_class); + } + + // - There's a non-dependent scope specifier, in which case we + // compute it and do a previous lookup there for a function + // or function template. + } else if (!SS.getScopeRep()->isDependent()) { + DC = computeDeclContext(SS); + if (!DC) return 0; + + if (RequireCompleteDeclContext(SS, DC)) return 0; + + LookupQualifiedName(Previous, DC); + + // Ignore things found implicitly in the wrong scope. + // TODO: better diagnostics for this case. Suggesting the right + // qualified scope would be nice... + LookupResult::Filter F = Previous.makeFilter(); + while (F.hasNext()) { + NamedDecl *D = F.next(); + if (!DC->InEnclosingNamespaceSetOf( + D->getDeclContext()->getRedeclContext())) + F.erase(); + } + F.done(); + + if (Previous.empty()) { + D.setInvalidType(); + Diag(Loc, diag::err_qualified_friend_not_found) + << Name << TInfo->getType(); + return 0; + } + + // C++ [class.friend]p1: A friend of a class is a function or + // class that is not a member of the class . . . + if (DC->Equals(CurContext)) + Diag(DS.getFriendSpecLoc(), + getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_friend_is_member : + diag::err_friend_is_member); + + if (D.isFunctionDefinition()) { + // C++ [class.friend]p6: + // A function can be defined in a friend declaration of a class if and + // only if the class is a non-local class (9.8), the function name is + // unqualified, and the function has namespace scope. + SemaDiagnosticBuilder DB + = Diag(SS.getRange().getBegin(), diag::err_qualified_friend_def); + + DB << SS.getScopeRep(); + if (DC->isFileContext()) + DB << FixItHint::CreateRemoval(SS.getRange()); + SS.clear(); + } + + // - There's a scope specifier that does not match any template + // parameter lists, in which case we use some arbitrary context, + // create a method or method template, and wait for instantiation. + // - There's a scope specifier that does match some template + // parameter lists, which we don't handle right now. + } else { + if (D.isFunctionDefinition()) { + // C++ [class.friend]p6: + // A function can be defined in a friend declaration of a class if and + // only if the class is a non-local class (9.8), the function name is + // unqualified, and the function has namespace scope. + Diag(SS.getRange().getBegin(), diag::err_qualified_friend_def) + << SS.getScopeRep(); + } + + DC = CurContext; + assert(isa(DC) && "friend declaration not in class?"); + } + + if (!DC->isRecord()) { + // This implies that it has to be an operator or function. + if (D.getName().getKind() == UnqualifiedId::IK_ConstructorName || + D.getName().getKind() == UnqualifiedId::IK_DestructorName || + D.getName().getKind() == UnqualifiedId::IK_ConversionFunctionId) { + Diag(Loc, diag::err_introducing_special_friend) << + (D.getName().getKind() == UnqualifiedId::IK_ConstructorName ? 0 : + D.getName().getKind() == UnqualifiedId::IK_DestructorName ? 1 : 2); + return 0; + } + } + + // FIXME: This is an egregious hack to cope with cases where the scope stack + // does not contain the declaration context, i.e., in an out-of-line + // definition of a class. + Scope FakeDCScope(S, Scope::DeclScope, Diags); + if (!DCScope) { + FakeDCScope.setEntity(DC); + DCScope = &FakeDCScope; + } + + bool AddToScope = true; + NamedDecl *ND = ActOnFunctionDeclarator(DCScope, D, DC, TInfo, Previous, + move(TemplateParams), AddToScope); + if (!ND) return 0; + + assert(ND->getDeclContext() == DC); + assert(ND->getLexicalDeclContext() == CurContext); + + // Add the function declaration to the appropriate lookup tables, + // adjusting the redeclarations list as necessary. We don't + // want to do this yet if the friending class is dependent. + // + // Also update the scope-based lookup if the target context's + // lookup context is in lexical scope. + if (!CurContext->isDependentContext()) { + DC = DC->getRedeclContext(); + DC->makeDeclVisibleInContext(ND); + if (Scope *EnclosingScope = getScopeForDeclContext(S, DC)) + PushOnScopeChains(ND, EnclosingScope, /*AddToContext=*/ false); + } + + FriendDecl *FrD = FriendDecl::Create(Context, CurContext, + D.getIdentifierLoc(), ND, + DS.getFriendSpecLoc()); + FrD->setAccess(AS_public); + CurContext->addDecl(FrD); + + if (ND->isInvalidDecl()) + FrD->setInvalidDecl(); + else { + FunctionDecl *FD; + if (FunctionTemplateDecl *FTD = dyn_cast(ND)) + FD = FTD->getTemplatedDecl(); + else + FD = cast(ND); + + // Mark templated-scope function declarations as unsupported. + if (FD->getNumTemplateParameterLists()) + FrD->setUnsupportedFriend(true); + } + + return ND; +} + +void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) { + AdjustDeclIfTemplate(Dcl); + + FunctionDecl *Fn = dyn_cast(Dcl); + if (!Fn) { + Diag(DelLoc, diag::err_deleted_non_function); + return; + } + if (const FunctionDecl *Prev = Fn->getPreviousDecl()) { + Diag(DelLoc, diag::err_deleted_decl_not_first); + Diag(Prev->getLocation(), diag::note_previous_declaration); + // If the declaration wasn't the first, we delete the function anyway for + // recovery. + } + Fn->setDeletedAsWritten(); + + CXXMethodDecl *MD = dyn_cast(Dcl); + if (!MD) + return; + + // A deleted special member function is trivial if the corresponding + // implicitly-declared function would have been. + switch (getSpecialMember(MD)) { + case CXXInvalid: + break; + case CXXDefaultConstructor: + MD->setTrivial(MD->getParent()->hasTrivialDefaultConstructor()); + break; + case CXXCopyConstructor: + MD->setTrivial(MD->getParent()->hasTrivialCopyConstructor()); + break; + case CXXMoveConstructor: + MD->setTrivial(MD->getParent()->hasTrivialMoveConstructor()); + break; + case CXXCopyAssignment: + MD->setTrivial(MD->getParent()->hasTrivialCopyAssignment()); + break; + case CXXMoveAssignment: + MD->setTrivial(MD->getParent()->hasTrivialMoveAssignment()); + break; + case CXXDestructor: + MD->setTrivial(MD->getParent()->hasTrivialDestructor()); + break; + } +} + +void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) { + CXXMethodDecl *MD = dyn_cast(Dcl); + + if (MD) { + if (MD->getParent()->isDependentType()) { + MD->setDefaulted(); + MD->setExplicitlyDefaulted(); + return; + } + + CXXSpecialMember Member = getSpecialMember(MD); + if (Member == CXXInvalid) { + Diag(DefaultLoc, diag::err_default_special_members); + return; + } + + MD->setDefaulted(); + MD->setExplicitlyDefaulted(); + + // If this definition appears within the record, do the checking when + // the record is complete. + const FunctionDecl *Primary = MD; + if (MD->getTemplatedKind() != FunctionDecl::TK_NonTemplate) + // Find the uninstantiated declaration that actually had the '= default' + // on it. + MD->getTemplateInstantiationPattern()->isDefined(Primary); + + if (Primary == Primary->getCanonicalDecl()) + return; + + switch (Member) { + case CXXDefaultConstructor: { + CXXConstructorDecl *CD = cast(MD); + CheckExplicitlyDefaultedDefaultConstructor(CD); + if (!CD->isInvalidDecl()) + DefineImplicitDefaultConstructor(DefaultLoc, CD); + break; + } + + case CXXCopyConstructor: { + CXXConstructorDecl *CD = cast(MD); + CheckExplicitlyDefaultedCopyConstructor(CD); + if (!CD->isInvalidDecl()) + DefineImplicitCopyConstructor(DefaultLoc, CD); + break; + } + + case CXXCopyAssignment: { + CheckExplicitlyDefaultedCopyAssignment(MD); + if (!MD->isInvalidDecl()) + DefineImplicitCopyAssignment(DefaultLoc, MD); + break; + } + + case CXXDestructor: { + CXXDestructorDecl *DD = cast(MD); + CheckExplicitlyDefaultedDestructor(DD); + if (!DD->isInvalidDecl()) + DefineImplicitDestructor(DefaultLoc, DD); + break; + } + + case CXXMoveConstructor: { + CXXConstructorDecl *CD = cast(MD); + CheckExplicitlyDefaultedMoveConstructor(CD); + if (!CD->isInvalidDecl()) + DefineImplicitMoveConstructor(DefaultLoc, CD); + break; + } + + case CXXMoveAssignment: { + CheckExplicitlyDefaultedMoveAssignment(MD); + if (!MD->isInvalidDecl()) + DefineImplicitMoveAssignment(DefaultLoc, MD); + break; + } + + case CXXInvalid: + llvm_unreachable("Invalid special member."); + } + } else { + Diag(DefaultLoc, diag::err_default_special_members); + } +} + +static void SearchForReturnInStmt(Sema &Self, Stmt *S) { + for (Stmt::child_range CI = S->children(); CI; ++CI) { + Stmt *SubStmt = *CI; + if (!SubStmt) + continue; + if (isa(SubStmt)) + Self.Diag(SubStmt->getLocStart(), + diag::err_return_in_constructor_handler); + if (!isa(SubStmt)) + SearchForReturnInStmt(Self, SubStmt); + } +} + +void Sema::DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock) { + for (unsigned I = 0, E = TryBlock->getNumHandlers(); I != E; ++I) { + CXXCatchStmt *Handler = TryBlock->getHandler(I); + SearchForReturnInStmt(*this, Handler); + } +} + +bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New, + const CXXMethodDecl *Old) { + QualType NewTy = New->getType()->getAs()->getResultType(); + QualType OldTy = Old->getType()->getAs()->getResultType(); + + if (Context.hasSameType(NewTy, OldTy) || + NewTy->isDependentType() || OldTy->isDependentType()) + return false; + + // Check if the return types are covariant + QualType NewClassTy, OldClassTy; + + /// Both types must be pointers or references to classes. + if (const PointerType *NewPT = NewTy->getAs()) { + if (const PointerType *OldPT = OldTy->getAs()) { + NewClassTy = NewPT->getPointeeType(); + OldClassTy = OldPT->getPointeeType(); + } + } else if (const ReferenceType *NewRT = NewTy->getAs()) { + if (const ReferenceType *OldRT = OldTy->getAs()) { + if (NewRT->getTypeClass() == OldRT->getTypeClass()) { + NewClassTy = NewRT->getPointeeType(); + OldClassTy = OldRT->getPointeeType(); + } + } + } + + // The return types aren't either both pointers or references to a class type. + if (NewClassTy.isNull()) { + Diag(New->getLocation(), + diag::err_different_return_type_for_overriding_virtual_function) + << New->getDeclName() << NewTy << OldTy; + Diag(Old->getLocation(), diag::note_overridden_virtual_function); + + return true; + } + + // C++ [class.virtual]p6: + // If the return type of D::f differs from the return type of B::f, the + // class type in the return type of D::f shall be complete at the point of + // declaration of D::f or shall be the class type D. + if (const RecordType *RT = NewClassTy->getAs()) { + if (!RT->isBeingDefined() && + RequireCompleteType(New->getLocation(), NewClassTy, + PDiag(diag::err_covariant_return_incomplete) + << New->getDeclName())) + return true; + } + + if (!Context.hasSameUnqualifiedType(NewClassTy, OldClassTy)) { + // Check if the new class derives from the old class. + if (!IsDerivedFrom(NewClassTy, OldClassTy)) { + Diag(New->getLocation(), + diag::err_covariant_return_not_derived) + << New->getDeclName() << NewTy << OldTy; + Diag(Old->getLocation(), diag::note_overridden_virtual_function); + return true; + } + + // Check if we the conversion from derived to base is valid. + if (CheckDerivedToBaseConversion(NewClassTy, OldClassTy, + diag::err_covariant_return_inaccessible_base, + diag::err_covariant_return_ambiguous_derived_to_base_conv, + // FIXME: Should this point to the return type? + New->getLocation(), SourceRange(), New->getDeclName(), 0)) { + // FIXME: this note won't trigger for delayed access control + // diagnostics, and it's impossible to get an undelayed error + // here from access control during the original parse because + // the ParsingDeclSpec/ParsingDeclarator are still in scope. + Diag(Old->getLocation(), diag::note_overridden_virtual_function); + return true; + } + } + + // The qualifiers of the return types must be the same. + if (NewTy.getLocalCVRQualifiers() != OldTy.getLocalCVRQualifiers()) { + Diag(New->getLocation(), + diag::err_covariant_return_type_different_qualifications) + << New->getDeclName() << NewTy << OldTy; + Diag(Old->getLocation(), diag::note_overridden_virtual_function); + return true; + }; + + + // The new class type must have the same or less qualifiers as the old type. + if (NewClassTy.isMoreQualifiedThan(OldClassTy)) { + Diag(New->getLocation(), + diag::err_covariant_return_type_class_type_more_qualified) + << New->getDeclName() << NewTy << OldTy; + Diag(Old->getLocation(), diag::note_overridden_virtual_function); + return true; + }; + + return false; +} + +/// \brief Mark the given method pure. +/// +/// \param Method the method to be marked pure. +/// +/// \param InitRange the source range that covers the "0" initializer. +bool Sema::CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange) { + SourceLocation EndLoc = InitRange.getEnd(); + if (EndLoc.isValid()) + Method->setRangeEnd(EndLoc); + + if (Method->isVirtual() || Method->getParent()->isDependentContext()) { + Method->setPure(); + return false; + } + + if (!Method->isInvalidDecl()) + Diag(Method->getLocation(), diag::err_non_virtual_pure) + << Method->getDeclName() << InitRange; + return true; +} + +/// \brief Determine whether the given declaration is a static data member. +static bool isStaticDataMember(Decl *D) { + VarDecl *Var = dyn_cast_or_null(D); + if (!Var) + return false; + + return Var->isStaticDataMember(); +} +/// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse +/// an initializer for the out-of-line declaration 'Dcl'. The scope +/// is a fresh scope pushed for just this purpose. +/// +/// 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, Decl *D) { + // If there is no declaration, there was an error parsing it. + if (D == 0 || D->isInvalidDecl()) return; + + // We should only get called for declarations with scope specifiers, like: + // int foo::bar; + assert(D->isOutOfLine()); + EnterDeclaratorContext(S, D->getDeclContext()); + + // If we are parsing the initializer for a static data member, push a + // new expression evaluation context that is associated with this static + // data member. + if (isStaticDataMember(D)) + PushExpressionEvaluationContext(PotentiallyEvaluated, D); +} + +/// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an +/// 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. + if (D == 0 || D->isInvalidDecl()) return; + + if (isStaticDataMember(D)) + PopExpressionEvaluationContext(); + + assert(D->isOutOfLine()); + ExitDeclaratorContext(S); +} + +/// ActOnCXXConditionDeclarationExpr - Parsed a condition declaration of a +/// C++ if/switch/while/for statement. +/// e.g: "if (int x = f()) {...}" +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 + // new class or enumeration. + assert(D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef && + "Parser allowed 'typedef' as storage class of condition decl."); + + Decl *Dcl = ActOnDeclarator(S, D); + if (!Dcl) + return true; + + if (isa(Dcl)) { // The declarator shall not specify a function. + Diag(Dcl->getLocation(), diag::err_invalid_use_of_function_type) + << D.getSourceRange(); + return true; + } + + return Dcl; +} + +void Sema::LoadExternalVTableUses() { + if (!ExternalSource) + return; + + SmallVector VTables; + ExternalSource->ReadUsedVTables(VTables); + SmallVector NewUses; + for (unsigned I = 0, N = VTables.size(); I != N; ++I) { + llvm::DenseMap::iterator Pos + = VTablesUsed.find(VTables[I].Record); + // Even if a definition wasn't required before, it may be required now. + if (Pos != VTablesUsed.end()) { + if (!Pos->second && VTables[I].DefinitionRequired) + Pos->second = true; + continue; + } + + VTablesUsed[VTables[I].Record] = VTables[I].DefinitionRequired; + NewUses.push_back(VTableUse(VTables[I].Record, VTables[I].Location)); + } + + VTableUses.insert(VTableUses.begin(), NewUses.begin(), NewUses.end()); +} + +void Sema::MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class, + bool DefinitionRequired) { + // Ignore any vtable uses in unevaluated operands or for classes that do + // not have a vtable. + if (!Class->isDynamicClass() || Class->isDependentContext() || + CurContext->isDependentContext() || + ExprEvalContexts.back().Context == Unevaluated) + return; + + // Try to insert this class into the map. + LoadExternalVTableUses(); + Class = cast(Class->getCanonicalDecl()); + std::pair::iterator, bool> + Pos = VTablesUsed.insert(std::make_pair(Class, DefinitionRequired)); + if (!Pos.second) { + // If we already had an entry, check to see if we are promoting this vtable + // to required a definition. If so, we need to reappend to the VTableUses + // list, since we may have already processed the first entry. + if (DefinitionRequired && !Pos.first->second) { + Pos.first->second = true; + } else { + // Otherwise, we can early exit. + return; + } + } + + // Local classes need to have their virtual members marked + // immediately. For all other classes, we mark their virtual members + // at the end of the translation unit. + if (Class->isLocalClass()) + MarkVirtualMembersReferenced(Loc, Class); + else + VTableUses.push_back(std::make_pair(Class, Loc)); +} + +bool Sema::DefineUsedVTables() { + LoadExternalVTableUses(); + if (VTableUses.empty()) + return false; + + // Note: The VTableUses vector could grow as a result of marking + // the members of a class as "used", so we check the size each + // time through the loop and prefer indices (with are stable) to + // iterators (which are not). + bool DefinedAnything = false; + for (unsigned I = 0; I != VTableUses.size(); ++I) { + CXXRecordDecl *Class = VTableUses[I].first->getDefinition(); + if (!Class) + continue; + + SourceLocation Loc = VTableUses[I].second; + + // If this class has a key function, but that key function is + // defined in another translation unit, we don't need to emit the + // vtable even though we're using it. + const CXXMethodDecl *KeyFunction = Context.getKeyFunction(Class); + if (KeyFunction && !KeyFunction->hasBody()) { + switch (KeyFunction->getTemplateSpecializationKind()) { + case TSK_Undeclared: + case TSK_ExplicitSpecialization: + case TSK_ExplicitInstantiationDeclaration: + // The key function is in another translation unit. + continue; + + case TSK_ExplicitInstantiationDefinition: + case TSK_ImplicitInstantiation: + // We will be instantiating the key function. + break; + } + } else if (!KeyFunction) { + // If we have a class with no key function that is the subject + // of an explicit instantiation declaration, suppress the + // vtable; it will live with the explicit instantiation + // definition. + bool IsExplicitInstantiationDeclaration + = Class->getTemplateSpecializationKind() + == TSK_ExplicitInstantiationDeclaration; + for (TagDecl::redecl_iterator R = Class->redecls_begin(), + REnd = Class->redecls_end(); + R != REnd; ++R) { + TemplateSpecializationKind TSK + = cast(*R)->getTemplateSpecializationKind(); + if (TSK == TSK_ExplicitInstantiationDeclaration) + IsExplicitInstantiationDeclaration = true; + else if (TSK == TSK_ExplicitInstantiationDefinition) { + IsExplicitInstantiationDeclaration = false; + break; + } + } + + if (IsExplicitInstantiationDeclaration) + continue; + } + + // Mark all of the virtual members of this class as referenced, so + // that we can build a vtable. Then, tell the AST consumer that a + // vtable for this class is required. + DefinedAnything = true; + MarkVirtualMembersReferenced(Loc, Class); + CXXRecordDecl *Canonical = cast(Class->getCanonicalDecl()); + Consumer.HandleVTable(Class, VTablesUsed[Canonical]); + + // Optionally warn if we're emitting a weak vtable. + if (Class->getLinkage() == ExternalLinkage && + Class->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) { + const FunctionDecl *KeyFunctionDef = 0; + if (!KeyFunction || + (KeyFunction->hasBody(KeyFunctionDef) && + KeyFunctionDef->isInlined())) + Diag(Class->getLocation(), Class->getTemplateSpecializationKind() == + TSK_ExplicitInstantiationDefinition + ? diag::warn_weak_template_vtable : diag::warn_weak_vtable) + << Class; + } + } + VTableUses.clear(); + + return DefinedAnything; +} + +void Sema::MarkVirtualMembersReferenced(SourceLocation Loc, + const CXXRecordDecl *RD) { + for (CXXRecordDecl::method_iterator i = RD->method_begin(), + e = RD->method_end(); i != e; ++i) { + CXXMethodDecl *MD = *i; + + // C++ [basic.def.odr]p2: + // [...] A virtual member function is used if it is not pure. [...] + if (MD->isVirtual() && !MD->isPure()) + MarkFunctionReferenced(Loc, MD); + } + + // Only classes that have virtual bases need a VTT. + if (RD->getNumVBases() == 0) + return; + + for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), + e = RD->bases_end(); i != e; ++i) { + const CXXRecordDecl *Base = + cast(i->getType()->getAs()->getDecl()); + if (Base->getNumVBases() == 0) + continue; + MarkVirtualMembersReferenced(Loc, Base); + } +} + +/// SetIvarInitializers - This routine builds initialization ASTs for the +/// Objective-C implementation whose ivars need be initialized. +void Sema::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) { + if (!getLangOpts().CPlusPlus) + return; + if (ObjCInterfaceDecl *OID = ObjCImplementation->getClassInterface()) { + SmallVector ivars; + CollectIvarsToConstructOrDestruct(OID, ivars); + if (ivars.empty()) + return; + SmallVector AllToInit; + for (unsigned i = 0; i < ivars.size(); i++) { + FieldDecl *Field = ivars[i]; + if (Field->isInvalidDecl()) + continue; + + CXXCtorInitializer *Member; + InitializedEntity InitEntity = InitializedEntity::InitializeMember(Field); + InitializationKind InitKind = + InitializationKind::CreateDefault(ObjCImplementation->getLocation()); + + InitializationSequence InitSeq(*this, InitEntity, InitKind, 0, 0); + ExprResult MemberInit = + InitSeq.Perform(*this, InitEntity, InitKind, MultiExprArg()); + MemberInit = MaybeCreateExprWithCleanups(MemberInit); + // 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()) + continue; + + Member = + new (Context) CXXCtorInitializer(Context, Field, SourceLocation(), + SourceLocation(), + MemberInit.takeAs(), + SourceLocation()); + AllToInit.push_back(Member); + + // Be sure that the destructor is accessible and is marked as referenced. + if (const RecordType *RecordTy + = Context.getBaseElementType(Field->getType()) + ->getAs()) { + CXXRecordDecl *RD = cast(RecordTy->getDecl()); + if (CXXDestructorDecl *Destructor = LookupDestructor(RD)) { + MarkFunctionReferenced(Field->getLocation(), Destructor); + CheckDestructorAccess(Field->getLocation(), Destructor, + PDiag(diag::err_access_dtor_ivar) + << Context.getBaseElementType(Field->getType())); + } + } + } + ObjCImplementation->setIvarInitializers(Context, + AllToInit.data(), AllToInit.size()); + } +} + +static +void DelegatingCycleHelper(CXXConstructorDecl* Ctor, + llvm::SmallSet &Valid, + llvm::SmallSet &Invalid, + llvm::SmallSet &Current, + Sema &S) { + llvm::SmallSet::iterator CI = Current.begin(), + CE = Current.end(); + if (Ctor->isInvalidDecl()) + return; + + const FunctionDecl *FNTarget = 0; + CXXConstructorDecl *Target; + + // We ignore the result here since if we don't have a body, Target will be + // null below. + (void)Ctor->getTargetConstructor()->hasBody(FNTarget); + Target += const_cast(cast_or_null(FNTarget)); + + CXXConstructorDecl *Canonical = Ctor->getCanonicalDecl(), + // Avoid dereferencing a null pointer here. + *TCanonical = Target ? Target->getCanonicalDecl() : 0; + + if (!Current.insert(Canonical)) + return; + + // We know that beyond here, we aren't chaining into a cycle. + if (!Target || !Target->isDelegatingConstructor() || + Target->isInvalidDecl() || Valid.count(TCanonical)) { + for (CI = Current.begin(), CE = Current.end(); CI != CE; ++CI) + Valid.insert(*CI); + Current.clear(); + // We've hit a cycle. + } else if (TCanonical == Canonical || Invalid.count(TCanonical) || + Current.count(TCanonical)) { + // If we haven't diagnosed this cycle yet, do so now. + if (!Invalid.count(TCanonical)) { + S.Diag((*Ctor->init_begin())->getSourceLocation(), + diag::warn_delegating_ctor_cycle) + << Ctor; + + // Don't add a note for a function delegating directo to itself. + if (TCanonical != Canonical) + S.Diag(Target->getLocation(), diag::note_it_delegates_to); + + CXXConstructorDecl *C = Target; + while (C->getCanonicalDecl() != Canonical) { + (void)C->getTargetConstructor()->hasBody(FNTarget); + assert(FNTarget && "Ctor cycle through bodiless function"); + + C + = const_cast(cast(FNTarget)); + S.Diag(C->getLocation(), diag::note_which_delegates_to); + } + } + + for (CI = Current.begin(), CE = Current.end(); CI != CE; ++CI) + Invalid.insert(*CI); + Current.clear(); + } else { + DelegatingCycleHelper(Target, Valid, Invalid, Current, S); + } +} + + +void Sema::CheckDelegatingCtorCycles() { + llvm::SmallSet Valid, Invalid, Current; + + llvm::SmallSet::iterator CI = Current.begin(), + CE = Current.end(); + + for (DelegatingCtorDeclsType::iterator + I = DelegatingCtorDecls.begin(ExternalSource), + E = DelegatingCtorDecls.end(); + I != E; ++I) { + DelegatingCycleHelper(*I, Valid, Invalid, Current, *this); + } + + for (CI = Invalid.begin(), CE = Invalid.end(); CI != CE; ++CI) + (*CI)->setInvalidDecl(); +} + +namespace { + /// \brief AST visitor that finds references to the 'this' expression. + class FindCXXThisExpr : public RecursiveASTVisitor { + Sema &S; + + public: + explicit FindCXXThisExpr(Sema &S) : S(S) { } + + bool VisitCXXThisExpr(CXXThisExpr *E) { + S.Diag(E->getLocation(), diag::err_this_static_member_func) + << E->isImplicit(); + return false; + } + }; +} + +bool Sema::checkThisInStaticMemberFunctionType(CXXMethodDecl *Method) { + TypeSourceInfo *TSInfo = Method->getTypeSourceInfo(); + if (!TSInfo) + return false; + + TypeLoc TL = TSInfo->getTypeLoc(); + FunctionProtoTypeLoc *ProtoTL = dyn_cast(&TL); + if (!ProtoTL) + return false; + + // C++11 [expr.prim.general]p3: + // [The expression this] shall not appear before the optional + // cv-qualifier-seq and it shall not appear within the declaration of a + // static member function (although its type and value category are defined + // within a static member function as they are within a non-static member + // function). [ Note: this is because declaration matching does not occur + // until the complete declarator is known. - end note ] + const FunctionProtoType *Proto = ProtoTL->getTypePtr(); + FindCXXThisExpr Finder(*this); + + // If the return type came after the cv-qualifier-seq, check it now. + if (Proto->hasTrailingReturn() && + !Finder.TraverseTypeLoc(ProtoTL->getResultLoc())) + return true; + + // Check the exception specification. + if (checkThisInStaticMemberFunctionExceptionSpec(Method)) + return true; + + return checkThisInStaticMemberFunctionAttributes(Method); +} + +bool Sema::checkThisInStaticMemberFunctionExceptionSpec(CXXMethodDecl *Method) { + TypeSourceInfo *TSInfo = Method->getTypeSourceInfo(); + if (!TSInfo) + return false; + + TypeLoc TL = TSInfo->getTypeLoc(); + FunctionProtoTypeLoc *ProtoTL = dyn_cast(&TL); + if (!ProtoTL) + return false; + + const FunctionProtoType *Proto = ProtoTL->getTypePtr(); + FindCXXThisExpr Finder(*this); + + switch (Proto->getExceptionSpecType()) { + case EST_Uninstantiated: + case EST_BasicNoexcept: + case EST_Delayed: + case EST_DynamicNone: + case EST_MSAny: + case EST_None: + break; + + case EST_ComputedNoexcept: + if (!Finder.TraverseStmt(Proto->getNoexceptExpr())) + return true; + + case EST_Dynamic: + for (FunctionProtoType::exception_iterator E = Proto->exception_begin(), + EEnd = Proto->exception_end(); + E != EEnd; ++E) { + if (!Finder.TraverseType(*E)) + return true; + } + break; + } + + return false; +} + +bool Sema::checkThisInStaticMemberFunctionAttributes(CXXMethodDecl *Method) { + FindCXXThisExpr Finder(*this); + + // Check attributes. + for (Decl::attr_iterator A = Method->attr_begin(), AEnd = Method->attr_end(); + A != AEnd; ++A) { + // FIXME: This should be emitted by tblgen. + Expr *Arg = 0; + ArrayRef Args; + if (GuardedByAttr *G = dyn_cast(*A)) + Arg = G->getArg(); + else if (PtGuardedByAttr *G = dyn_cast(*A)) + Arg = G->getArg(); + else if (AcquiredAfterAttr *AA = dyn_cast(*A)) + Args = ArrayRef(AA->args_begin(), AA->args_size()); + else if (AcquiredBeforeAttr *AB = dyn_cast(*A)) + Args = ArrayRef(AB->args_begin(), AB->args_size()); + else if (ExclusiveLockFunctionAttr *ELF + = dyn_cast(*A)) + Args = ArrayRef(ELF->args_begin(), ELF->args_size()); + else if (SharedLockFunctionAttr *SLF + = dyn_cast(*A)) + Args = ArrayRef(SLF->args_begin(), SLF->args_size()); + else if (ExclusiveTrylockFunctionAttr *ETLF + = dyn_cast(*A)) { + Arg = ETLF->getSuccessValue(); + Args = ArrayRef(ETLF->args_begin(), ETLF->args_size()); + } else if (SharedTrylockFunctionAttr *STLF + = dyn_cast(*A)) { + Arg = STLF->getSuccessValue(); + Args = ArrayRef(STLF->args_begin(), STLF->args_size()); + } else if (UnlockFunctionAttr *UF = dyn_cast(*A)) + Args = ArrayRef(UF->args_begin(), UF->args_size()); + else if (LockReturnedAttr *LR = dyn_cast(*A)) + Arg = LR->getArg(); + else if (LocksExcludedAttr *LE = dyn_cast(*A)) + Args = ArrayRef(LE->args_begin(), LE->args_size()); + else if (ExclusiveLocksRequiredAttr *ELR + = dyn_cast(*A)) + Args = ArrayRef(ELR->args_begin(), ELR->args_size()); + else if (SharedLocksRequiredAttr *SLR + = dyn_cast(*A)) + Args = ArrayRef(SLR->args_begin(), SLR->args_size()); + + if (Arg && !Finder.TraverseStmt(Arg)) + return true; + + for (unsigned I = 0, N = Args.size(); I != N; ++I) { + if (!Finder.TraverseStmt(Args[I])) + return true; + } + } + + return false; +} + +void +Sema::checkExceptionSpecification(ExceptionSpecificationType EST, + ArrayRef DynamicExceptions, + ArrayRef DynamicExceptionRanges, + Expr *NoexceptExpr, + llvm::SmallVectorImpl &Exceptions, + FunctionProtoType::ExtProtoInfo &EPI) { + Exceptions.clear(); + EPI.ExceptionSpecType = EST; + if (EST == EST_Dynamic) { + Exceptions.reserve(DynamicExceptions.size()); + for (unsigned ei = 0, ee = DynamicExceptions.size(); ei != ee; ++ei) { + // FIXME: Preserve type source info. + QualType ET = GetTypeFromParser(DynamicExceptions[ei]); + + SmallVector Unexpanded; + collectUnexpandedParameterPacks(ET, Unexpanded); + if (!Unexpanded.empty()) { + DiagnoseUnexpandedParameterPacks(DynamicExceptionRanges[ei].getBegin(), + UPPC_ExceptionType, + Unexpanded); + continue; + } + + // Check that the type is valid for an exception spec, and + // drop it if not. + if (!CheckSpecifiedExceptionType(ET, DynamicExceptionRanges[ei])) + Exceptions.push_back(ET); + } + EPI.NumExceptions = Exceptions.size(); + EPI.Exceptions = Exceptions.data(); + return; + } + + if (EST == EST_ComputedNoexcept) { + // If an error occurred, there's no expression here. + if (NoexceptExpr) { + assert((NoexceptExpr->isTypeDependent() || + NoexceptExpr->getType()->getCanonicalTypeUnqualified() == + Context.BoolTy) && + "Parser should have made sure that the expression is boolean"); + if (NoexceptExpr && DiagnoseUnexpandedParameterPack(NoexceptExpr)) { + EPI.ExceptionSpecType = EST_BasicNoexcept; + return; + } + + if (!NoexceptExpr->isValueDependent()) + NoexceptExpr = VerifyIntegerConstantExpression(NoexceptExpr, 0, + PDiag(diag::err_noexcept_needs_constant_expression), + /*AllowFold*/ false).take(); + EPI.NoexceptExpr = NoexceptExpr; + } + return; + } +} + +/// IdentifyCUDATarget - Determine the CUDA compilation target for this function +Sema::CUDAFunctionTarget Sema::IdentifyCUDATarget(const FunctionDecl *D) { + // Implicitly declared functions (e.g. copy constructors) are + // __host__ __device__ + if (D->isImplicit()) + return CFT_HostDevice; + + if (D->hasAttr()) + return CFT_Global; + + if (D->hasAttr()) { + if (D->hasAttr()) + return CFT_HostDevice; + else + return CFT_Device; + } + + return CFT_Host; +} + +bool Sema::CheckCUDATarget(CUDAFunctionTarget CallerTarget, + CUDAFunctionTarget CalleeTarget) { + // CUDA B.1.1 "The __device__ qualifier declares a function that is... + // Callable from the device only." + if (CallerTarget == CFT_Host && CalleeTarget == CFT_Device) + return true; + + // CUDA B.1.2 "The __global__ qualifier declares a function that is... + // Callable from the host only." + // CUDA B.1.3 "The __host__ qualifier declares a function that is... + // Callable from the host only." + if ((CallerTarget == CFT_Device || CallerTarget == CFT_Global) && + (CalleeTarget == CFT_Host || CalleeTarget == CFT_Global)) + return true; + + if (CallerTarget == CFT_HostDevice && CalleeTarget != CFT_HostDevice) + return true; + + return false; +} diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp new file mode 100644 index 0000000..a942d49 --- /dev/null +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -0,0 +1,3121 @@ +//===--- SemaDeclObjC.cpp - Semantic Analysis for ObjC Declarations -------===// +// +// 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 Objective C declarations. +// +//===----------------------------------------------------------------------===// + +#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/ASTConsumer.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprObjC.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/ASTMutationListener.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Sema/DeclSpec.h" +#include "clang/Lex/Preprocessor.h" +#include "llvm/ADT/DenseSet.h" + +using namespace clang; + +/// Check whether the given method, which must be in the 'init' +/// family, is a valid member of that family. +/// +/// \param receiverTypeIfCall - if null, check this as if declaring it; +/// if non-null, check this as if making a call to it with the given +/// receiver type +/// +/// \return true to indicate that there was an error and appropriate +/// actions were taken +bool Sema::checkInitMethod(ObjCMethodDecl *method, + QualType receiverTypeIfCall) { + if (method->isInvalidDecl()) return true; + + // This castAs is safe: methods that don't return an object + // pointer won't be inferred as inits and will reject an explicit + // objc_method_family(init). + + // We ignore protocols here. Should we? What about Class? + + const ObjCObjectType *result = method->getResultType() + ->castAs()->getObjectType(); + + if (result->isObjCId()) { + return false; + } else if (result->isObjCClass()) { + // fall through: always an error + } else { + ObjCInterfaceDecl *resultClass = result->getInterface(); + assert(resultClass && "unexpected object type!"); + + // It's okay for the result type to still be a forward declaration + // if we're checking an interface declaration. + if (!resultClass->hasDefinition()) { + if (receiverTypeIfCall.isNull() && + !isa(method->getDeclContext())) + return false; + + // Otherwise, we try to compare class types. + } else { + // If this method was declared in a protocol, we can't check + // anything unless we have a receiver type that's an interface. + const ObjCInterfaceDecl *receiverClass = 0; + if (isa(method->getDeclContext())) { + if (receiverTypeIfCall.isNull()) + return false; + + receiverClass = receiverTypeIfCall->castAs() + ->getInterfaceDecl(); + + // This can be null for calls to e.g. id. + if (!receiverClass) return false; + } else { + receiverClass = method->getClassInterface(); + assert(receiverClass && "method not associated with a class!"); + } + + // If either class is a subclass of the other, it's fine. + if (receiverClass->isSuperClassOf(resultClass) || + resultClass->isSuperClassOf(receiverClass)) + return false; + } + } + + SourceLocation loc = method->getLocation(); + + // If we're in a system header, and this is not a call, just make + // the method unusable. + if (receiverTypeIfCall.isNull() && getSourceManager().isInSystemHeader(loc)) { + method->addAttr(new (Context) UnavailableAttr(loc, Context, + "init method returns a type unrelated to its receiver type")); + return true; + } + + // Otherwise, it's an error. + Diag(loc, diag::err_arc_init_method_unrelated_result_type); + method->setInvalidDecl(); + return true; +} + +void Sema::CheckObjCMethodOverride(ObjCMethodDecl *NewMethod, + const ObjCMethodDecl *Overridden, + bool IsImplementation) { + if (Overridden->hasRelatedResultType() && + !NewMethod->hasRelatedResultType()) { + // This can only happen when the method follows a naming convention that + // implies a related result type, and the original (overridden) method has + // a suitable return type, but the new (overriding) method does not have + // a suitable return type. + QualType ResultType = NewMethod->getResultType(); + SourceRange ResultTypeRange; + if (const TypeSourceInfo *ResultTypeInfo + = NewMethod->getResultTypeSourceInfo()) + ResultTypeRange = ResultTypeInfo->getTypeLoc().getSourceRange(); + + // Figure out which class this method is part of, if any. + ObjCInterfaceDecl *CurrentClass + = dyn_cast(NewMethod->getDeclContext()); + if (!CurrentClass) { + DeclContext *DC = NewMethod->getDeclContext(); + if (ObjCCategoryDecl *Cat = dyn_cast(DC)) + CurrentClass = Cat->getClassInterface(); + else if (ObjCImplDecl *Impl = dyn_cast(DC)) + CurrentClass = Impl->getClassInterface(); + else if (ObjCCategoryImplDecl *CatImpl + = dyn_cast(DC)) + CurrentClass = CatImpl->getClassInterface(); + } + + if (CurrentClass) { + Diag(NewMethod->getLocation(), + diag::warn_related_result_type_compatibility_class) + << Context.getObjCInterfaceType(CurrentClass) + << ResultType + << ResultTypeRange; + } else { + Diag(NewMethod->getLocation(), + diag::warn_related_result_type_compatibility_protocol) + << ResultType + << ResultTypeRange; + } + + if (ObjCMethodFamily Family = Overridden->getMethodFamily()) + Diag(Overridden->getLocation(), + diag::note_related_result_type_overridden_family) + << Family; + else + Diag(Overridden->getLocation(), + diag::note_related_result_type_overridden); + } + if (getLangOpts().ObjCAutoRefCount) { + if ((NewMethod->hasAttr() != + Overridden->hasAttr())) { + Diag(NewMethod->getLocation(), + diag::err_nsreturns_retained_attribute_mismatch) << 1; + Diag(Overridden->getLocation(), diag::note_previous_decl) + << "method"; + } + if ((NewMethod->hasAttr() != + Overridden->hasAttr())) { + Diag(NewMethod->getLocation(), + diag::err_nsreturns_retained_attribute_mismatch) << 0; + Diag(Overridden->getLocation(), diag::note_previous_decl) + << "method"; + } + ObjCMethodDecl::param_const_iterator oi = Overridden->param_begin(); + for (ObjCMethodDecl::param_iterator + ni = NewMethod->param_begin(), ne = NewMethod->param_end(); + ni != ne; ++ni, ++oi) { + const ParmVarDecl *oldDecl = (*oi); + ParmVarDecl *newDecl = (*ni); + if (newDecl->hasAttr() != + oldDecl->hasAttr()) { + Diag(newDecl->getLocation(), + diag::err_nsconsumed_attribute_mismatch); + Diag(oldDecl->getLocation(), diag::note_previous_decl) + << "parameter"; + } + } + } +} + +/// \brief Check a method declaration for compatibility with the Objective-C +/// ARC conventions. +static bool CheckARCMethodDecl(Sema &S, ObjCMethodDecl *method) { + ObjCMethodFamily family = method->getMethodFamily(); + switch (family) { + case OMF_None: + case OMF_dealloc: + case OMF_finalize: + case OMF_retain: + case OMF_release: + case OMF_autorelease: + case OMF_retainCount: + case OMF_self: + case OMF_performSelector: + return false; + + case OMF_init: + // If the method doesn't obey the init rules, don't bother annotating it. + if (S.checkInitMethod(method, QualType())) + return true; + + method->addAttr(new (S.Context) NSConsumesSelfAttr(SourceLocation(), + S.Context)); + + // Don't add a second copy of this attribute, but otherwise don't + // let it be suppressed. + if (method->hasAttr()) + return false; + break; + + case OMF_alloc: + case OMF_copy: + case OMF_mutableCopy: + case OMF_new: + if (method->hasAttr() || + method->hasAttr() || + method->hasAttr()) + return false; + break; + } + + method->addAttr(new (S.Context) NSReturnsRetainedAttr(SourceLocation(), + S.Context)); + return false; +} + +static void DiagnoseObjCImplementedDeprecations(Sema &S, + NamedDecl *ND, + SourceLocation ImplLoc, + int select) { + if (ND && ND->isDeprecated()) { + S.Diag(ImplLoc, diag::warn_deprecated_def) << select; + if (select == 0) + S.Diag(ND->getLocation(), diag::note_method_declared_at) + << ND->getDeclName(); + else + S.Diag(ND->getLocation(), diag::note_previous_decl) << "class"; + } +} + +/// AddAnyMethodToGlobalPool - Add any method, instance or factory to global +/// pool. +void Sema::AddAnyMethodToGlobalPool(Decl *D) { + ObjCMethodDecl *MDecl = dyn_cast_or_null(D); + + // If we don't have a valid method decl, simply return. + if (!MDecl) + return; + if (MDecl->isInstanceMethod()) + AddInstanceMethodToGlobalPool(MDecl, true); + else + AddFactoryMethodToGlobalPool(MDecl, true); +} + +/// ActOnStartOfObjCMethodDef - This routine sets up parameters; invisible +/// and user declared, in the method definition's AST. +void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) { + assert(getCurMethodDecl() == 0 && "Method parsing confused"); + ObjCMethodDecl *MDecl = dyn_cast_or_null(D); + + // If we don't have a valid method decl, simply return. + if (!MDecl) + return; + + // Allow all of Sema to see that we are entering a method definition. + PushDeclContext(FnBodyScope, MDecl); + PushFunctionScope(); + + // Create Decl objects for each parameter, entrring them in the scope for + // binding to their use. + + // Insert the invisible arguments, self and _cmd! + MDecl->createImplicitParams(Context, MDecl->getClassInterface()); + + PushOnScopeChains(MDecl->getSelfDecl(), FnBodyScope); + PushOnScopeChains(MDecl->getCmdDecl(), FnBodyScope); + + // Introduce all of the other parameters into this scope. + for (ObjCMethodDecl::param_iterator PI = MDecl->param_begin(), + E = MDecl->param_end(); PI != E; ++PI) { + ParmVarDecl *Param = (*PI); + if (!Param->isInvalidDecl() && + RequireCompleteType(Param->getLocation(), Param->getType(), + diag::err_typecheck_decl_incomplete_type)) + Param->setInvalidDecl(); + if ((*PI)->getIdentifier()) + PushOnScopeChains(*PI, FnBodyScope); + } + + // In ARC, disallow definition of retain/release/autorelease/retainCount + if (getLangOpts().ObjCAutoRefCount) { + switch (MDecl->getMethodFamily()) { + case OMF_retain: + case OMF_retainCount: + case OMF_release: + case OMF_autorelease: + Diag(MDecl->getLocation(), diag::err_arc_illegal_method_def) + << MDecl->getSelector(); + break; + + case OMF_None: + case OMF_dealloc: + case OMF_finalize: + case OMF_alloc: + case OMF_init: + case OMF_mutableCopy: + case OMF_copy: + case OMF_new: + case OMF_self: + case OMF_performSelector: + break; + } + } + + // Warn on deprecated methods under -Wdeprecated-implementations, + // and prepare for warning on missing super calls. + if (ObjCInterfaceDecl *IC = MDecl->getClassInterface()) { + if (ObjCMethodDecl *IMD = + IC->lookupMethod(MDecl->getSelector(), MDecl->isInstanceMethod())) + DiagnoseObjCImplementedDeprecations(*this, + dyn_cast(IMD), + MDecl->getLocation(), 0); + + // If this is "dealloc" or "finalize", set some bit here. + // Then in ActOnSuperMessage() (SemaExprObjC), set it back to false. + // Finally, in ActOnFinishFunctionBody() (SemaDecl), warn if flag is set. + // Only do this if the current class actually has a superclass. + if (IC->getSuperClass()) { + ObjCShouldCallSuperDealloc = + !(Context.getLangOpts().ObjCAutoRefCount || + Context.getLangOpts().getGC() == LangOptions::GCOnly) && + MDecl->getMethodFamily() == OMF_dealloc; + ObjCShouldCallSuperFinalize = + Context.getLangOpts().getGC() != LangOptions::NonGC && + MDecl->getMethodFamily() == OMF_finalize; + } + } +} + +namespace { + +// Callback to only accept typo corrections that are Objective-C classes. +// If an ObjCInterfaceDecl* is given to the constructor, then the validation +// function will reject corrections to that class. +class ObjCInterfaceValidatorCCC : public CorrectionCandidateCallback { + public: + ObjCInterfaceValidatorCCC() : CurrentIDecl(0) {} + explicit ObjCInterfaceValidatorCCC(ObjCInterfaceDecl *IDecl) + : CurrentIDecl(IDecl) {} + + virtual bool ValidateCandidate(const TypoCorrection &candidate) { + ObjCInterfaceDecl *ID = candidate.getCorrectionDeclAs(); + return ID && !declaresSameEntity(ID, CurrentIDecl); + } + + private: + ObjCInterfaceDecl *CurrentIDecl; +}; + +} + +Decl *Sema:: +ActOnStartClassInterface(SourceLocation AtInterfaceLoc, + IdentifierInfo *ClassName, SourceLocation ClassLoc, + IdentifierInfo *SuperName, SourceLocation SuperLoc, + Decl * const *ProtoRefs, unsigned NumProtoRefs, + const SourceLocation *ProtoLocs, + SourceLocation EndProtoLoc, AttributeList *AttrList) { + assert(ClassName && "Missing class identifier"); + + // Check for another declaration kind with the same name. + NamedDecl *PrevDecl = LookupSingleName(TUScope, ClassName, ClassLoc, + LookupOrdinaryName, ForRedeclaration); + + if (PrevDecl && !isa(PrevDecl)) { + Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName; + Diag(PrevDecl->getLocation(), diag::note_previous_definition); + } + + // Create a declaration to describe this @interface. + ObjCInterfaceDecl* PrevIDecl = dyn_cast_or_null(PrevDecl); + ObjCInterfaceDecl *IDecl + = ObjCInterfaceDecl::Create(Context, CurContext, AtInterfaceLoc, ClassName, + PrevIDecl, ClassLoc); + + if (PrevIDecl) { + // Class already seen. Was it a definition? + if (ObjCInterfaceDecl *Def = PrevIDecl->getDefinition()) { + Diag(AtInterfaceLoc, diag::err_duplicate_class_def) + << PrevIDecl->getDeclName(); + Diag(Def->getLocation(), diag::note_previous_definition); + IDecl->setInvalidDecl(); + } + } + + if (AttrList) + ProcessDeclAttributeList(TUScope, IDecl, AttrList); + PushOnScopeChains(IDecl, TUScope); + + // Start the definition of this class. If we're in a redefinition case, there + // may already be a definition, so we'll end up adding to it. + if (!IDecl->hasDefinition()) + IDecl->startDefinition(); + + if (SuperName) { + // Check if a different kind of symbol declared in this scope. + PrevDecl = LookupSingleName(TUScope, SuperName, SuperLoc, + LookupOrdinaryName); + + if (!PrevDecl) { + // Try to correct for a typo in the superclass name without correcting + // to the class we're defining. + ObjCInterfaceValidatorCCC Validator(IDecl); + if (TypoCorrection Corrected = CorrectTypo( + DeclarationNameInfo(SuperName, SuperLoc), LookupOrdinaryName, TUScope, + NULL, Validator)) { + PrevDecl = Corrected.getCorrectionDeclAs(); + Diag(SuperLoc, diag::err_undef_superclass_suggest) + << SuperName << ClassName << PrevDecl->getDeclName(); + Diag(PrevDecl->getLocation(), diag::note_previous_decl) + << PrevDecl->getDeclName(); + } + } + + if (declaresSameEntity(PrevDecl, IDecl)) { + Diag(SuperLoc, diag::err_recursive_superclass) + << SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc); + IDecl->setEndOfDefinitionLoc(ClassLoc); + } else { + ObjCInterfaceDecl *SuperClassDecl = + dyn_cast_or_null(PrevDecl); + + // Diagnose classes that inherit from deprecated classes. + if (SuperClassDecl) + (void)DiagnoseUseOfDecl(SuperClassDecl, SuperLoc); + + if (PrevDecl && SuperClassDecl == 0) { + // The previous declaration was not a class decl. Check if we have a + // typedef. If we do, get the underlying class type. + if (const TypedefNameDecl *TDecl = + dyn_cast_or_null(PrevDecl)) { + QualType T = TDecl->getUnderlyingType(); + if (T->isObjCObjectType()) { + if (NamedDecl *IDecl = T->getAs()->getInterface()) + SuperClassDecl = dyn_cast(IDecl); + } + } + + // This handles the following case: + // + // typedef int SuperClass; + // @interface MyClass : SuperClass {} @end + // + if (!SuperClassDecl) { + Diag(SuperLoc, diag::err_redefinition_different_kind) << SuperName; + Diag(PrevDecl->getLocation(), diag::note_previous_definition); + } + } + + if (!dyn_cast_or_null(PrevDecl)) { + if (!SuperClassDecl) + Diag(SuperLoc, diag::err_undef_superclass) + << SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc); + else if (RequireCompleteType(SuperLoc, + Context.getObjCInterfaceType(SuperClassDecl), + PDiag(diag::err_forward_superclass) + << SuperClassDecl->getDeclName() + << ClassName + << SourceRange(AtInterfaceLoc, ClassLoc))) { + SuperClassDecl = 0; + } + } + IDecl->setSuperClass(SuperClassDecl); + IDecl->setSuperClassLoc(SuperLoc); + IDecl->setEndOfDefinitionLoc(SuperLoc); + } + } else { // we have a root class. + IDecl->setEndOfDefinitionLoc(ClassLoc); + } + + // Check then save referenced protocols. + if (NumProtoRefs) { + IDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs, + ProtoLocs, Context); + IDecl->setEndOfDefinitionLoc(EndProtoLoc); + } + + CheckObjCDeclScope(IDecl); + return ActOnObjCContainerStartDefinition(IDecl); +} + +/// ActOnCompatiblityAlias - this action is called after complete parsing of +/// @compatibility_alias declaration. It sets up the alias relationships. +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); + if (ADecl) { + if (isa(ADecl)) + Diag(AliasLocation, diag::warn_previous_alias_decl); + else + Diag(AliasLocation, diag::err_conflicting_aliasing_type) << AliasName; + Diag(ADecl->getLocation(), diag::note_previous_declaration); + return 0; + } + // Check for class declaration + NamedDecl *CDeclU = LookupSingleName(TUScope, ClassName, ClassLocation, + LookupOrdinaryName, ForRedeclaration); + if (const TypedefNameDecl *TDecl = + dyn_cast_or_null(CDeclU)) { + QualType T = TDecl->getUnderlyingType(); + if (T->isObjCObjectType()) { + if (NamedDecl *IDecl = T->getAs()->getInterface()) { + ClassName = IDecl->getIdentifier(); + CDeclU = LookupSingleName(TUScope, ClassName, ClassLocation, + LookupOrdinaryName, ForRedeclaration); + } + } + } + ObjCInterfaceDecl *CDecl = dyn_cast_or_null(CDeclU); + if (CDecl == 0) { + Diag(ClassLocation, diag::warn_undef_interface) << ClassName; + if (CDeclU) + Diag(CDeclU->getLocation(), diag::note_previous_declaration); + return 0; + } + + // Everything checked out, instantiate a new alias declaration AST. + ObjCCompatibleAliasDecl *AliasDecl = + ObjCCompatibleAliasDecl::Create(Context, CurContext, AtLoc, AliasName, CDecl); + + if (!CheckObjCDeclScope(AliasDecl)) + PushOnScopeChains(AliasDecl, TUScope); + + return AliasDecl; +} + +bool Sema::CheckForwardProtocolDeclarationForCircularDependency( + IdentifierInfo *PName, + SourceLocation &Ploc, SourceLocation PrevLoc, + const ObjCList &PList) { + + bool res = false; + for (ObjCList::iterator I = PList.begin(), + E = PList.end(); I != E; ++I) { + if (ObjCProtocolDecl *PDecl = LookupProtocol((*I)->getIdentifier(), + Ploc)) { + if (PDecl->getIdentifier() == PName) { + Diag(Ploc, diag::err_protocol_has_circular_dependency); + Diag(PrevLoc, diag::note_previous_definition); + res = true; + } + + if (!PDecl->hasDefinition()) + continue; + + if (CheckForwardProtocolDeclarationForCircularDependency(PName, Ploc, + PDecl->getLocation(), PDecl->getReferencedProtocols())) + res = true; + } + } + return res; +} + +Decl * +Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc, + IdentifierInfo *ProtocolName, + SourceLocation ProtocolLoc, + Decl * const *ProtoRefs, + unsigned NumProtoRefs, + const SourceLocation *ProtoLocs, + SourceLocation EndProtoLoc, + AttributeList *AttrList) { + bool err = false; + // FIXME: Deal with AttrList. + assert(ProtocolName && "Missing protocol identifier"); + ObjCProtocolDecl *PrevDecl = LookupProtocol(ProtocolName, ProtocolLoc, + ForRedeclaration); + ObjCProtocolDecl *PDecl = 0; + if (ObjCProtocolDecl *Def = PrevDecl? PrevDecl->getDefinition() : 0) { + // If we already have a definition, complain. + Diag(ProtocolLoc, diag::warn_duplicate_protocol_def) << ProtocolName; + Diag(Def->getLocation(), diag::note_previous_definition); + + // Create a new protocol that is completely distinct from previous + // declarations, and do not make this protocol available for name lookup. + // That way, we'll end up completely ignoring the duplicate. + // FIXME: Can we turn this into an error? + PDecl = ObjCProtocolDecl::Create(Context, CurContext, ProtocolName, + ProtocolLoc, AtProtoInterfaceLoc, + /*PrevDecl=*/0); + PDecl->startDefinition(); + } else { + if (PrevDecl) { + // Check for circular dependencies among protocol declarations. This can + // only happen if this protocol was forward-declared. + ObjCList PList; + PList.set((ObjCProtocolDecl *const*)ProtoRefs, NumProtoRefs, Context); + err = CheckForwardProtocolDeclarationForCircularDependency( + ProtocolName, ProtocolLoc, PrevDecl->getLocation(), PList); + } + + // Create the new declaration. + PDecl = ObjCProtocolDecl::Create(Context, CurContext, ProtocolName, + ProtocolLoc, AtProtoInterfaceLoc, + /*PrevDecl=*/PrevDecl); + + PushOnScopeChains(PDecl, TUScope); + PDecl->startDefinition(); + } + + if (AttrList) + ProcessDeclAttributeList(TUScope, PDecl, AttrList); + + // Merge attributes from previous declarations. + if (PrevDecl) + mergeDeclAttributes(PDecl, PrevDecl); + + if (!err && NumProtoRefs ) { + /// Check then save referenced protocols. + PDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs, + ProtoLocs, Context); + } + + CheckObjCDeclScope(PDecl); + return ActOnObjCContainerStartDefinition(PDecl); +} + +/// FindProtocolDeclaration - This routine looks up protocols and +/// issues an error if they are not declared. It returns list of +/// protocol declarations in its 'Protocols' argument. +void +Sema::FindProtocolDeclaration(bool WarnOnDeclarations, + const IdentifierLocPair *ProtocolId, + unsigned NumProtocols, + SmallVectorImpl &Protocols) { + for (unsigned i = 0; i != NumProtocols; ++i) { + ObjCProtocolDecl *PDecl = LookupProtocol(ProtocolId[i].first, + ProtocolId[i].second); + if (!PDecl) { + DeclFilterCCC Validator; + TypoCorrection Corrected = CorrectTypo( + DeclarationNameInfo(ProtocolId[i].first, ProtocolId[i].second), + LookupObjCProtocolName, TUScope, NULL, Validator); + if ((PDecl = Corrected.getCorrectionDeclAs())) { + Diag(ProtocolId[i].second, diag::err_undeclared_protocol_suggest) + << ProtocolId[i].first << Corrected.getCorrection(); + Diag(PDecl->getLocation(), diag::note_previous_decl) + << PDecl->getDeclName(); + } + } + + if (!PDecl) { + Diag(ProtocolId[i].second, diag::err_undeclared_protocol) + << ProtocolId[i].first; + continue; + } + + (void)DiagnoseUseOfDecl(PDecl, ProtocolId[i].second); + + // If this is a forward declaration and we are supposed to warn in this + // case, do it. + if (WarnOnDeclarations && !PDecl->hasDefinition()) + Diag(ProtocolId[i].second, diag::warn_undef_protocolref) + << ProtocolId[i].first; + Protocols.push_back(PDecl); + } +} + +/// DiagnoseClassExtensionDupMethods - Check for duplicate declaration of +/// a class method in its extension. +/// +void Sema::DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT, + ObjCInterfaceDecl *ID) { + if (!ID) + return; // Possibly due to previous error + + llvm::DenseMap MethodMap; + for (ObjCInterfaceDecl::method_iterator i = ID->meth_begin(), + e = ID->meth_end(); i != e; ++i) { + ObjCMethodDecl *MD = *i; + MethodMap[MD->getSelector()] = MD; + } + + if (MethodMap.empty()) + return; + for (ObjCCategoryDecl::method_iterator i = CAT->meth_begin(), + e = CAT->meth_end(); i != e; ++i) { + ObjCMethodDecl *Method = *i; + const ObjCMethodDecl *&PrevMethod = MethodMap[Method->getSelector()]; + if (PrevMethod && !MatchTwoMethodDeclarations(Method, PrevMethod)) { + Diag(Method->getLocation(), diag::err_duplicate_method_decl) + << Method->getDeclName(); + Diag(PrevMethod->getLocation(), diag::note_previous_declaration); + } + } +} + +/// ActOnForwardProtocolDeclaration - Handle @protocol foo; +Sema::DeclGroupPtrTy +Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc, + const IdentifierLocPair *IdentList, + unsigned NumElts, + AttributeList *attrList) { + SmallVector DeclsInGroup; + for (unsigned i = 0; i != NumElts; ++i) { + IdentifierInfo *Ident = IdentList[i].first; + ObjCProtocolDecl *PrevDecl = LookupProtocol(Ident, IdentList[i].second, + ForRedeclaration); + ObjCProtocolDecl *PDecl + = ObjCProtocolDecl::Create(Context, CurContext, Ident, + IdentList[i].second, AtProtocolLoc, + PrevDecl); + + PushOnScopeChains(PDecl, TUScope); + CheckObjCDeclScope(PDecl); + + if (attrList) + ProcessDeclAttributeList(TUScope, PDecl, attrList); + + if (PrevDecl) + mergeDeclAttributes(PDecl, PrevDecl); + + DeclsInGroup.push_back(PDecl); + } + + return BuildDeclaratorGroup(DeclsInGroup.data(), DeclsInGroup.size(), false); +} + +Decl *Sema:: +ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc, + IdentifierInfo *ClassName, SourceLocation ClassLoc, + IdentifierInfo *CategoryName, + SourceLocation CategoryLoc, + Decl * const *ProtoRefs, + unsigned NumProtoRefs, + const SourceLocation *ProtoLocs, + SourceLocation EndProtoLoc) { + ObjCCategoryDecl *CDecl; + ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc, true); + + /// Check that class of this category is already completely declared. + + if (!IDecl + || RequireCompleteType(ClassLoc, Context.getObjCInterfaceType(IDecl), + PDiag(diag::err_category_forward_interface) + << (CategoryName == 0))) { + // Create an invalid ObjCCategoryDecl to serve as context for + // the enclosing method declarations. We mark the decl invalid + // to make it clear that this isn't a valid AST. + CDecl = ObjCCategoryDecl::Create(Context, CurContext, AtInterfaceLoc, + ClassLoc, CategoryLoc, CategoryName,IDecl); + CDecl->setInvalidDecl(); + CurContext->addDecl(CDecl); + + if (!IDecl) + Diag(ClassLoc, diag::err_undef_interface) << ClassName; + return ActOnObjCContainerStartDefinition(CDecl); + } + + if (!CategoryName && IDecl->getImplementation()) { + Diag(ClassLoc, diag::err_class_extension_after_impl) << ClassName; + Diag(IDecl->getImplementation()->getLocation(), + diag::note_implementation_declared); + } + + if (CategoryName) { + /// Check for duplicate interface declaration for this category + ObjCCategoryDecl *CDeclChain; + for (CDeclChain = IDecl->getCategoryList(); CDeclChain; + CDeclChain = CDeclChain->getNextClassCategory()) { + if (CDeclChain->getIdentifier() == CategoryName) { + // Class extensions can be declared multiple times. + Diag(CategoryLoc, diag::warn_dup_category_def) + << ClassName << CategoryName; + Diag(CDeclChain->getLocation(), diag::note_previous_definition); + break; + } + } + } + + CDecl = ObjCCategoryDecl::Create(Context, CurContext, AtInterfaceLoc, + ClassLoc, CategoryLoc, CategoryName, IDecl); + // FIXME: PushOnScopeChains? + CurContext->addDecl(CDecl); + + if (NumProtoRefs) { + CDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs, + ProtoLocs, Context); + // Protocols in the class extension belong to the class. + if (CDecl->IsClassExtension()) + IDecl->mergeClassExtensionProtocolList((ObjCProtocolDecl**)ProtoRefs, + NumProtoRefs, Context); + } + + CheckObjCDeclScope(CDecl); + return ActOnObjCContainerStartDefinition(CDecl); +} + +/// ActOnStartCategoryImplementation - Perform semantic checks on the +/// category implementation declaration and build an ObjCCategoryImplDecl +/// object. +Decl *Sema::ActOnStartCategoryImplementation( + SourceLocation AtCatImplLoc, + IdentifierInfo *ClassName, SourceLocation ClassLoc, + IdentifierInfo *CatName, SourceLocation CatLoc) { + ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc, true); + ObjCCategoryDecl *CatIDecl = 0; + if (IDecl && IDecl->hasDefinition()) { + CatIDecl = IDecl->FindCategoryDeclaration(CatName); + if (!CatIDecl) { + // Category @implementation with no corresponding @interface. + // Create and install one. + CatIDecl = ObjCCategoryDecl::Create(Context, CurContext, AtCatImplLoc, + ClassLoc, CatLoc, + CatName, IDecl); + CatIDecl->setImplicit(); + } + } + + ObjCCategoryImplDecl *CDecl = + ObjCCategoryImplDecl::Create(Context, CurContext, CatName, IDecl, + ClassLoc, AtCatImplLoc, CatLoc); + /// Check that class of this category is already completely declared. + if (!IDecl) { + Diag(ClassLoc, diag::err_undef_interface) << ClassName; + CDecl->setInvalidDecl(); + } else if (RequireCompleteType(ClassLoc, Context.getObjCInterfaceType(IDecl), + diag::err_undef_interface)) { + CDecl->setInvalidDecl(); + } + + // FIXME: PushOnScopeChains? + CurContext->addDecl(CDecl); + + // If the interface is deprecated/unavailable, warn/error about it. + if (IDecl) + DiagnoseUseOfDecl(IDecl, ClassLoc); + + /// Check that CatName, category name, is not used in another implementation. + if (CatIDecl) { + if (CatIDecl->getImplementation()) { + Diag(ClassLoc, diag::err_dup_implementation_category) << ClassName + << CatName; + Diag(CatIDecl->getImplementation()->getLocation(), + diag::note_previous_definition); + } else { + CatIDecl->setImplementation(CDecl); + // Warn on implementating category of deprecated class under + // -Wdeprecated-implementations flag. + DiagnoseObjCImplementedDeprecations(*this, + dyn_cast(IDecl), + CDecl->getLocation(), 2); + } + } + + CheckObjCDeclScope(CDecl); + return ActOnObjCContainerStartDefinition(CDecl); +} + +Decl *Sema::ActOnStartClassImplementation( + SourceLocation AtClassImplLoc, + IdentifierInfo *ClassName, SourceLocation ClassLoc, + IdentifierInfo *SuperClassname, + SourceLocation SuperClassLoc) { + ObjCInterfaceDecl* IDecl = 0; + // Check for another declaration kind with the same name. + NamedDecl *PrevDecl + = LookupSingleName(TUScope, ClassName, ClassLoc, LookupOrdinaryName, + ForRedeclaration); + if (PrevDecl && !isa(PrevDecl)) { + Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName; + Diag(PrevDecl->getLocation(), diag::note_previous_definition); + } else if ((IDecl = dyn_cast_or_null(PrevDecl))) { + RequireCompleteType(ClassLoc, Context.getObjCInterfaceType(IDecl), + diag::warn_undef_interface); + } else { + // We did not find anything with the name ClassName; try to correct for + // typos in the class name. + ObjCInterfaceValidatorCCC Validator; + if (TypoCorrection Corrected = CorrectTypo( + DeclarationNameInfo(ClassName, ClassLoc), LookupOrdinaryName, TUScope, + NULL, Validator)) { + // Suggest the (potentially) correct interface name. However, put the + // fix-it hint itself in a separate note, since changing the name in + // the warning would make the fix-it change semantics.However, don't + // provide a code-modification hint or use the typo name for recovery, + // because this is just a warning. The program may actually be correct. + IDecl = Corrected.getCorrectionDeclAs(); + DeclarationName CorrectedName = Corrected.getCorrection(); + Diag(ClassLoc, diag::warn_undef_interface_suggest) + << ClassName << CorrectedName; + Diag(IDecl->getLocation(), diag::note_previous_decl) << CorrectedName + << FixItHint::CreateReplacement(ClassLoc, CorrectedName.getAsString()); + IDecl = 0; + } else { + Diag(ClassLoc, diag::warn_undef_interface) << ClassName; + } + } + + // Check that super class name is valid class name + ObjCInterfaceDecl* SDecl = 0; + if (SuperClassname) { + // Check if a different kind of symbol declared in this scope. + PrevDecl = LookupSingleName(TUScope, SuperClassname, SuperClassLoc, + LookupOrdinaryName); + if (PrevDecl && !isa(PrevDecl)) { + Diag(SuperClassLoc, diag::err_redefinition_different_kind) + << SuperClassname; + Diag(PrevDecl->getLocation(), diag::note_previous_definition); + } else { + SDecl = dyn_cast_or_null(PrevDecl); + if (SDecl && !SDecl->hasDefinition()) + SDecl = 0; + if (!SDecl) + Diag(SuperClassLoc, diag::err_undef_superclass) + << SuperClassname << ClassName; + else if (IDecl && !declaresSameEntity(IDecl->getSuperClass(), SDecl)) { + // This implementation and its interface do not have the same + // super class. + Diag(SuperClassLoc, diag::err_conflicting_super_class) + << SDecl->getDeclName(); + Diag(SDecl->getLocation(), diag::note_previous_definition); + } + } + } + + if (!IDecl) { + // Legacy case of @implementation with no corresponding @interface. + // Build, chain & install the interface decl into the identifier. + + // FIXME: Do we support attributes on the @implementation? If so we should + // copy them over. + IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtClassImplLoc, + ClassName, /*PrevDecl=*/0, ClassLoc, + true); + IDecl->startDefinition(); + if (SDecl) { + IDecl->setSuperClass(SDecl); + IDecl->setSuperClassLoc(SuperClassLoc); + IDecl->setEndOfDefinitionLoc(SuperClassLoc); + } else { + IDecl->setEndOfDefinitionLoc(ClassLoc); + } + + PushOnScopeChains(IDecl, TUScope); + } else { + // Mark the interface as being completed, even if it was just as + // @class ....; + // declaration; the user cannot reopen it. + if (!IDecl->hasDefinition()) + IDecl->startDefinition(); + } + + ObjCImplementationDecl* IMPDecl = + ObjCImplementationDecl::Create(Context, CurContext, IDecl, SDecl, + ClassLoc, AtClassImplLoc); + + if (CheckObjCDeclScope(IMPDecl)) + return ActOnObjCContainerStartDefinition(IMPDecl); + + // Check that there is no duplicate implementation of this class. + if (IDecl->getImplementation()) { + // FIXME: Don't leak everything! + Diag(ClassLoc, diag::err_dup_implementation_class) << ClassName; + Diag(IDecl->getImplementation()->getLocation(), + diag::note_previous_definition); + } else { // add it to the list. + IDecl->setImplementation(IMPDecl); + PushOnScopeChains(IMPDecl, TUScope); + // Warn on implementating deprecated class under + // -Wdeprecated-implementations flag. + DiagnoseObjCImplementedDeprecations(*this, + dyn_cast(IDecl), + IMPDecl->getLocation(), 1); + } + return ActOnObjCContainerStartDefinition(IMPDecl); +} + +Sema::DeclGroupPtrTy +Sema::ActOnFinishObjCImplementation(Decl *ObjCImpDecl, ArrayRef Decls) { + SmallVector DeclsInGroup; + DeclsInGroup.reserve(Decls.size() + 1); + + for (unsigned i = 0, e = Decls.size(); i != e; ++i) { + Decl *Dcl = Decls[i]; + if (!Dcl) + continue; + if (Dcl->getDeclContext()->isFileContext()) + Dcl->setTopLevelDeclInObjCContainer(); + DeclsInGroup.push_back(Dcl); + } + + DeclsInGroup.push_back(ObjCImpDecl); + + return BuildDeclaratorGroup(DeclsInGroup.data(), DeclsInGroup.size(), false); +} + +void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl, + ObjCIvarDecl **ivars, unsigned numIvars, + SourceLocation RBrace) { + assert(ImpDecl && "missing implementation decl"); + ObjCInterfaceDecl* IDecl = ImpDecl->getClassInterface(); + if (!IDecl) + return; + /// Check case of non-existing @interface decl. + /// (legacy objective-c @implementation decl without an @interface decl). + /// Add implementations's ivar to the synthesize class's ivar list. + if (IDecl->isImplicitInterfaceDecl()) { + IDecl->setEndOfDefinitionLoc(RBrace); + // Add ivar's to class's DeclContext. + for (unsigned i = 0, e = numIvars; i != e; ++i) { + ivars[i]->setLexicalDeclContext(ImpDecl); + IDecl->makeDeclVisibleInContext(ivars[i]); + ImpDecl->addDecl(ivars[i]); + } + + return; + } + // If implementation has empty ivar list, just return. + if (numIvars == 0) + return; + + assert(ivars && "missing @implementation ivars"); + if (LangOpts.ObjCNonFragileABI2) { + if (ImpDecl->getSuperClass()) + Diag(ImpDecl->getLocation(), diag::warn_on_superclass_use); + for (unsigned i = 0; i < numIvars; i++) { + ObjCIvarDecl* ImplIvar = ivars[i]; + if (const ObjCIvarDecl *ClsIvar = + IDecl->getIvarDecl(ImplIvar->getIdentifier())) { + Diag(ImplIvar->getLocation(), diag::err_duplicate_ivar_declaration); + Diag(ClsIvar->getLocation(), diag::note_previous_definition); + continue; + } + // Instance ivar to Implementation's DeclContext. + ImplIvar->setLexicalDeclContext(ImpDecl); + IDecl->makeDeclVisibleInContext(ImplIvar); + ImpDecl->addDecl(ImplIvar); + } + return; + } + // Check interface's Ivar list against those in the implementation. + // names and types must match. + // + unsigned j = 0; + ObjCInterfaceDecl::ivar_iterator + IVI = IDecl->ivar_begin(), IVE = IDecl->ivar_end(); + for (; numIvars > 0 && IVI != IVE; ++IVI) { + ObjCIvarDecl* ImplIvar = ivars[j++]; + ObjCIvarDecl* ClsIvar = *IVI; + assert (ImplIvar && "missing implementation ivar"); + assert (ClsIvar && "missing class ivar"); + + // First, make sure the types match. + if (!Context.hasSameType(ImplIvar->getType(), ClsIvar->getType())) { + Diag(ImplIvar->getLocation(), diag::err_conflicting_ivar_type) + << ImplIvar->getIdentifier() + << ImplIvar->getType() << ClsIvar->getType(); + Diag(ClsIvar->getLocation(), diag::note_previous_definition); + } else if (ImplIvar->isBitField() && ClsIvar->isBitField() && + ImplIvar->getBitWidthValue(Context) != + ClsIvar->getBitWidthValue(Context)) { + Diag(ImplIvar->getBitWidth()->getLocStart(), + diag::err_conflicting_ivar_bitwidth) << ImplIvar->getIdentifier(); + Diag(ClsIvar->getBitWidth()->getLocStart(), + diag::note_previous_definition); + } + // Make sure the names are identical. + if (ImplIvar->getIdentifier() != ClsIvar->getIdentifier()) { + Diag(ImplIvar->getLocation(), diag::err_conflicting_ivar_name) + << ImplIvar->getIdentifier() << ClsIvar->getIdentifier(); + Diag(ClsIvar->getLocation(), diag::note_previous_definition); + } + --numIvars; + } + + if (numIvars > 0) + Diag(ivars[j]->getLocation(), diag::err_inconsistant_ivar_count); + else if (IVI != IVE) + Diag((*IVI)->getLocation(), diag::err_inconsistant_ivar_count); +} + +void Sema::WarnUndefinedMethod(SourceLocation ImpLoc, ObjCMethodDecl *method, + bool &IncompleteImpl, unsigned DiagID) { + // No point warning no definition of method which is 'unavailable'. + if (method->hasAttr()) + return; + if (!IncompleteImpl) { + Diag(ImpLoc, diag::warn_incomplete_impl); + IncompleteImpl = true; + } + if (DiagID == diag::warn_unimplemented_protocol_method) + Diag(ImpLoc, DiagID) << method->getDeclName(); + else + Diag(method->getLocation(), DiagID) << method->getDeclName(); +} + +/// Determines if type B can be substituted for type A. Returns true if we can +/// guarantee that anything that the user will do to an object of type A can +/// also be done to an object of type B. This is trivially true if the two +/// types are the same, or if B is a subclass of A. It becomes more complex +/// in cases where protocols are involved. +/// +/// Object types in Objective-C describe the minimum requirements for an +/// object, rather than providing a complete description of a type. For +/// example, if A is a subclass of B, then B* may refer to an instance of A. +/// The principle of substitutability means that we may use an instance of A +/// anywhere that we may use an instance of B - it will implement all of the +/// ivars of B and all of the methods of B. +/// +/// This substitutability is important when type checking methods, because +/// the implementation may have stricter type definitions than the interface. +/// The interface specifies minimum requirements, but the implementation may +/// have more accurate ones. For example, a method may privately accept +/// instances of B, but only publish that it accepts instances of A. Any +/// object passed to it will be type checked against B, and so will implicitly +/// by a valid A*. Similarly, a method may return a subclass of the class that +/// it is declared as returning. +/// +/// This is most important when considering subclassing. A method in a +/// subclass must accept any object as an argument that its superclass's +/// implementation accepts. It may, however, accept a more general type +/// without breaking substitutability (i.e. you can still use the subclass +/// anywhere that you can use the superclass, but not vice versa). The +/// converse requirement applies to return types: the return type for a +/// subclass method must be a valid object of the kind that the superclass +/// advertises, but it may be specified more accurately. This avoids the need +/// for explicit down-casting by callers. +/// +/// Note: This is a stricter requirement than for assignment. +static bool isObjCTypeSubstitutable(ASTContext &Context, + const ObjCObjectPointerType *A, + const ObjCObjectPointerType *B, + bool rejectId) { + // Reject a protocol-unqualified id. + if (rejectId && B->isObjCIdType()) return false; + + // If B is a qualified id, then A must also be a qualified id and it must + // implement all of the protocols in B. It may not be a qualified class. + // For example, MyClass can be assigned to id, but MyClass is a + // stricter definition so it is not substitutable for id. + if (B->isObjCQualifiedIdType()) { + return A->isObjCQualifiedIdType() && + Context.ObjCQualifiedIdTypesAreCompatible(QualType(A, 0), + QualType(B,0), + false); + } + + /* + // id is a special type that bypasses type checking completely. We want a + // warning when it is used in one place but not another. + if (C.isObjCIdType(A) || C.isObjCIdType(B)) return false; + + + // If B is a qualified id, then A must also be a qualified id (which it isn't + // if we've got this far) + if (B->isObjCQualifiedIdType()) return false; + */ + + // Now we know that A and B are (potentially-qualified) class types. The + // normal rules for assignment apply. + return Context.canAssignObjCInterfaces(A, B); +} + +static SourceRange getTypeRange(TypeSourceInfo *TSI) { + return (TSI ? TSI->getTypeLoc().getSourceRange() : SourceRange()); +} + +static bool CheckMethodOverrideReturn(Sema &S, + ObjCMethodDecl *MethodImpl, + ObjCMethodDecl *MethodDecl, + bool IsProtocolMethodDecl, + bool IsOverridingMode, + bool Warn) { + if (IsProtocolMethodDecl && + (MethodDecl->getObjCDeclQualifier() != + MethodImpl->getObjCDeclQualifier())) { + if (Warn) { + S.Diag(MethodImpl->getLocation(), + (IsOverridingMode ? + diag::warn_conflicting_overriding_ret_type_modifiers + : diag::warn_conflicting_ret_type_modifiers)) + << MethodImpl->getDeclName() + << getTypeRange(MethodImpl->getResultTypeSourceInfo()); + S.Diag(MethodDecl->getLocation(), diag::note_previous_declaration) + << getTypeRange(MethodDecl->getResultTypeSourceInfo()); + } + else + return false; + } + + if (S.Context.hasSameUnqualifiedType(MethodImpl->getResultType(), + MethodDecl->getResultType())) + return true; + if (!Warn) + return false; + + unsigned DiagID = + IsOverridingMode ? diag::warn_conflicting_overriding_ret_types + : diag::warn_conflicting_ret_types; + + // Mismatches between ObjC pointers go into a different warning + // category, and sometimes they're even completely whitelisted. + if (const ObjCObjectPointerType *ImplPtrTy = + MethodImpl->getResultType()->getAs()) { + if (const ObjCObjectPointerType *IfacePtrTy = + MethodDecl->getResultType()->getAs()) { + // Allow non-matching return types as long as they don't violate + // the principle of substitutability. Specifically, we permit + // return types that are subclasses of the declared return type, + // or that are more-qualified versions of the declared type. + if (isObjCTypeSubstitutable(S.Context, IfacePtrTy, ImplPtrTy, false)) + return false; + + DiagID = + IsOverridingMode ? diag::warn_non_covariant_overriding_ret_types + : diag::warn_non_covariant_ret_types; + } + } + + S.Diag(MethodImpl->getLocation(), DiagID) + << MethodImpl->getDeclName() + << MethodDecl->getResultType() + << MethodImpl->getResultType() + << getTypeRange(MethodImpl->getResultTypeSourceInfo()); + S.Diag(MethodDecl->getLocation(), + IsOverridingMode ? diag::note_previous_declaration + : diag::note_previous_definition) + << getTypeRange(MethodDecl->getResultTypeSourceInfo()); + return false; +} + +static bool CheckMethodOverrideParam(Sema &S, + ObjCMethodDecl *MethodImpl, + ObjCMethodDecl *MethodDecl, + ParmVarDecl *ImplVar, + ParmVarDecl *IfaceVar, + bool IsProtocolMethodDecl, + bool IsOverridingMode, + bool Warn) { + if (IsProtocolMethodDecl && + (ImplVar->getObjCDeclQualifier() != + IfaceVar->getObjCDeclQualifier())) { + if (Warn) { + if (IsOverridingMode) + S.Diag(ImplVar->getLocation(), + diag::warn_conflicting_overriding_param_modifiers) + << getTypeRange(ImplVar->getTypeSourceInfo()) + << MethodImpl->getDeclName(); + else S.Diag(ImplVar->getLocation(), + diag::warn_conflicting_param_modifiers) + << getTypeRange(ImplVar->getTypeSourceInfo()) + << MethodImpl->getDeclName(); + S.Diag(IfaceVar->getLocation(), diag::note_previous_declaration) + << getTypeRange(IfaceVar->getTypeSourceInfo()); + } + else + return false; + } + + QualType ImplTy = ImplVar->getType(); + QualType IfaceTy = IfaceVar->getType(); + + if (S.Context.hasSameUnqualifiedType(ImplTy, IfaceTy)) + return true; + + if (!Warn) + return false; + unsigned DiagID = + IsOverridingMode ? diag::warn_conflicting_overriding_param_types + : diag::warn_conflicting_param_types; + + // Mismatches between ObjC pointers go into a different warning + // category, and sometimes they're even completely whitelisted. + if (const ObjCObjectPointerType *ImplPtrTy = + ImplTy->getAs()) { + if (const ObjCObjectPointerType *IfacePtrTy = + IfaceTy->getAs()) { + // Allow non-matching argument types as long as they don't + // violate the principle of substitutability. Specifically, the + // implementation must accept any objects that the superclass + // accepts, however it may also accept others. + if (isObjCTypeSubstitutable(S.Context, ImplPtrTy, IfacePtrTy, true)) + return false; + + DiagID = + IsOverridingMode ? diag::warn_non_contravariant_overriding_param_types + : diag::warn_non_contravariant_param_types; + } + } + + S.Diag(ImplVar->getLocation(), DiagID) + << getTypeRange(ImplVar->getTypeSourceInfo()) + << MethodImpl->getDeclName() << IfaceTy << ImplTy; + S.Diag(IfaceVar->getLocation(), + (IsOverridingMode ? diag::note_previous_declaration + : diag::note_previous_definition)) + << getTypeRange(IfaceVar->getTypeSourceInfo()); + return false; +} + +/// In ARC, check whether the conventional meanings of the two methods +/// match. If they don't, it's a hard error. +static bool checkMethodFamilyMismatch(Sema &S, ObjCMethodDecl *impl, + ObjCMethodDecl *decl) { + ObjCMethodFamily implFamily = impl->getMethodFamily(); + ObjCMethodFamily declFamily = decl->getMethodFamily(); + if (implFamily == declFamily) return false; + + // Since conventions are sorted by selector, the only possibility is + // that the types differ enough to cause one selector or the other + // to fall out of the family. + assert(implFamily == OMF_None || declFamily == OMF_None); + + // No further diagnostics required on invalid declarations. + if (impl->isInvalidDecl() || decl->isInvalidDecl()) return true; + + const ObjCMethodDecl *unmatched = impl; + ObjCMethodFamily family = declFamily; + unsigned errorID = diag::err_arc_lost_method_convention; + unsigned noteID = diag::note_arc_lost_method_convention; + if (declFamily == OMF_None) { + unmatched = decl; + family = implFamily; + errorID = diag::err_arc_gained_method_convention; + noteID = diag::note_arc_gained_method_convention; + } + + // Indexes into a %select clause in the diagnostic. + enum FamilySelector { + F_alloc, F_copy, F_mutableCopy = F_copy, F_init, F_new + }; + FamilySelector familySelector = FamilySelector(); + + switch (family) { + case OMF_None: llvm_unreachable("logic error, no method convention"); + case OMF_retain: + case OMF_release: + case OMF_autorelease: + case OMF_dealloc: + case OMF_finalize: + case OMF_retainCount: + case OMF_self: + case OMF_performSelector: + // Mismatches for these methods don't change ownership + // conventions, so we don't care. + return false; + + case OMF_init: familySelector = F_init; break; + case OMF_alloc: familySelector = F_alloc; break; + case OMF_copy: familySelector = F_copy; break; + case OMF_mutableCopy: familySelector = F_mutableCopy; break; + case OMF_new: familySelector = F_new; break; + } + + enum ReasonSelector { R_NonObjectReturn, R_UnrelatedReturn }; + ReasonSelector reasonSelector; + + // The only reason these methods don't fall within their families is + // due to unusual result types. + if (unmatched->getResultType()->isObjCObjectPointerType()) { + reasonSelector = R_UnrelatedReturn; + } else { + reasonSelector = R_NonObjectReturn; + } + + S.Diag(impl->getLocation(), errorID) << familySelector << reasonSelector; + S.Diag(decl->getLocation(), noteID) << familySelector << reasonSelector; + + return true; +} + +void Sema::WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethodDecl, + ObjCMethodDecl *MethodDecl, + bool IsProtocolMethodDecl) { + if (getLangOpts().ObjCAutoRefCount && + checkMethodFamilyMismatch(*this, ImpMethodDecl, MethodDecl)) + return; + + CheckMethodOverrideReturn(*this, ImpMethodDecl, MethodDecl, + IsProtocolMethodDecl, false, + true); + + for (ObjCMethodDecl::param_iterator IM = ImpMethodDecl->param_begin(), + IF = MethodDecl->param_begin(), EM = ImpMethodDecl->param_end(); + IM != EM; ++IM, ++IF) { + CheckMethodOverrideParam(*this, ImpMethodDecl, MethodDecl, *IM, *IF, + IsProtocolMethodDecl, false, true); + } + + if (ImpMethodDecl->isVariadic() != MethodDecl->isVariadic()) { + Diag(ImpMethodDecl->getLocation(), + diag::warn_conflicting_variadic); + Diag(MethodDecl->getLocation(), diag::note_previous_declaration); + } +} + +void Sema::CheckConflictingOverridingMethod(ObjCMethodDecl *Method, + ObjCMethodDecl *Overridden, + bool IsProtocolMethodDecl) { + + CheckMethodOverrideReturn(*this, Method, Overridden, + IsProtocolMethodDecl, true, + true); + + for (ObjCMethodDecl::param_iterator IM = Method->param_begin(), + IF = Overridden->param_begin(), EM = Method->param_end(); + IM != EM; ++IM, ++IF) { + CheckMethodOverrideParam(*this, Method, Overridden, *IM, *IF, + IsProtocolMethodDecl, true, true); + } + + if (Method->isVariadic() != Overridden->isVariadic()) { + Diag(Method->getLocation(), + diag::warn_conflicting_overriding_variadic); + Diag(Overridden->getLocation(), diag::note_previous_declaration); + } +} + +/// WarnExactTypedMethods - This routine issues a warning if method +/// implementation declaration matches exactly that of its declaration. +void Sema::WarnExactTypedMethods(ObjCMethodDecl *ImpMethodDecl, + ObjCMethodDecl *MethodDecl, + bool IsProtocolMethodDecl) { + // don't issue warning when protocol method is optional because primary + // class is not required to implement it and it is safe for protocol + // to implement it. + if (MethodDecl->getImplementationControl() == ObjCMethodDecl::Optional) + return; + // don't issue warning when primary class's method is + // depecated/unavailable. + if (MethodDecl->hasAttr() || + MethodDecl->hasAttr()) + return; + + bool match = CheckMethodOverrideReturn(*this, ImpMethodDecl, MethodDecl, + IsProtocolMethodDecl, false, false); + if (match) + for (ObjCMethodDecl::param_iterator IM = ImpMethodDecl->param_begin(), + IF = MethodDecl->param_begin(), EM = ImpMethodDecl->param_end(); + IM != EM; ++IM, ++IF) { + match = CheckMethodOverrideParam(*this, ImpMethodDecl, MethodDecl, + *IM, *IF, + IsProtocolMethodDecl, false, false); + if (!match) + break; + } + if (match) + match = (ImpMethodDecl->isVariadic() == MethodDecl->isVariadic()); + if (match) + match = !(MethodDecl->isClassMethod() && + MethodDecl->getSelector() == GetNullarySelector("load", Context)); + + if (match) { + Diag(ImpMethodDecl->getLocation(), + diag::warn_category_method_impl_match); + Diag(MethodDecl->getLocation(), diag::note_method_declared_at) + << MethodDecl->getDeclName(); + } +} + +/// FIXME: Type hierarchies in Objective-C can be deep. We could most likely +/// improve the efficiency of selector lookups and type checking by associating +/// with each protocol / interface / category the flattened instance tables. If +/// we used an immutable set to keep the table then it wouldn't add significant +/// memory cost and it would be handy for lookups. + +/// CheckProtocolMethodDefs - This routine checks unimplemented methods +/// Declared in protocol, and those referenced by it. +void Sema::CheckProtocolMethodDefs(SourceLocation ImpLoc, + ObjCProtocolDecl *PDecl, + bool& IncompleteImpl, + const llvm::DenseSet &InsMap, + const llvm::DenseSet &ClsMap, + ObjCContainerDecl *CDecl) { + ObjCCategoryDecl *C = dyn_cast(CDecl); + ObjCInterfaceDecl *IDecl = C ? C->getClassInterface() + : dyn_cast(CDecl); + assert (IDecl && "CheckProtocolMethodDefs - IDecl is null"); + + ObjCInterfaceDecl *Super = IDecl->getSuperClass(); + ObjCInterfaceDecl *NSIDecl = 0; + if (getLangOpts().NeXTRuntime) { + // check to see if class implements forwardInvocation method and objects + // of this class are derived from 'NSProxy' so that to forward requests + // from one object to another. + // Under such conditions, which means that every method possible is + // implemented in the class, we should not issue "Method definition not + // found" warnings. + // FIXME: Use a general GetUnarySelector method for this. + IdentifierInfo* II = &Context.Idents.get("forwardInvocation"); + Selector fISelector = Context.Selectors.getSelector(1, &II); + if (InsMap.count(fISelector)) + // Is IDecl derived from 'NSProxy'? If so, no instance methods + // need be implemented in the implementation. + NSIDecl = IDecl->lookupInheritedClass(&Context.Idents.get("NSProxy")); + } + + // If a method lookup fails locally we still need to look and see if + // the method was implemented by a base class or an inherited + // protocol. This lookup is slow, but occurs rarely in correct code + // and otherwise would terminate in a warning. + + // check unimplemented instance methods. + if (!NSIDecl) + for (ObjCProtocolDecl::instmeth_iterator I = PDecl->instmeth_begin(), + E = PDecl->instmeth_end(); I != E; ++I) { + ObjCMethodDecl *method = *I; + if (method->getImplementationControl() != ObjCMethodDecl::Optional && + !method->isSynthesized() && !InsMap.count(method->getSelector()) && + (!Super || + !Super->lookupInstanceMethod(method->getSelector()))) { + // If a method is not implemented in the category implementation but + // has been declared in its primary class, superclass, + // or in one of their protocols, no need to issue the warning. + // This is because method will be implemented in the primary class + // or one of its super class implementation. + + // Ugly, but necessary. Method declared in protcol might have + // have been synthesized due to a property declared in the class which + // uses the protocol. + if (ObjCMethodDecl *MethodInClass = + IDecl->lookupInstanceMethod(method->getSelector(), + true /*shallowCategoryLookup*/)) + if (C || MethodInClass->isSynthesized()) + continue; + unsigned DIAG = diag::warn_unimplemented_protocol_method; + if (Diags.getDiagnosticLevel(DIAG, ImpLoc) + != DiagnosticsEngine::Ignored) { + WarnUndefinedMethod(ImpLoc, method, IncompleteImpl, DIAG); + Diag(method->getLocation(), diag::note_method_declared_at) + << method->getDeclName(); + Diag(CDecl->getLocation(), diag::note_required_for_protocol_at) + << PDecl->getDeclName(); + } + } + } + // check unimplemented class methods + for (ObjCProtocolDecl::classmeth_iterator + I = PDecl->classmeth_begin(), E = PDecl->classmeth_end(); + I != E; ++I) { + ObjCMethodDecl *method = *I; + if (method->getImplementationControl() != ObjCMethodDecl::Optional && + !ClsMap.count(method->getSelector()) && + (!Super || !Super->lookupClassMethod(method->getSelector()))) { + // See above comment for instance method lookups. + if (C && IDecl->lookupClassMethod(method->getSelector(), + true /*shallowCategoryLookup*/)) + continue; + unsigned DIAG = diag::warn_unimplemented_protocol_method; + if (Diags.getDiagnosticLevel(DIAG, ImpLoc) != + DiagnosticsEngine::Ignored) { + WarnUndefinedMethod(ImpLoc, method, IncompleteImpl, DIAG); + Diag(method->getLocation(), diag::note_method_declared_at) + << method->getDeclName(); + Diag(IDecl->getLocation(), diag::note_required_for_protocol_at) << + PDecl->getDeclName(); + } + } + } + // Check on this protocols's referenced protocols, recursively. + for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(), + E = PDecl->protocol_end(); PI != E; ++PI) + CheckProtocolMethodDefs(ImpLoc, *PI, IncompleteImpl, InsMap, ClsMap, CDecl); +} + +/// MatchAllMethodDeclarations - Check methods declared in interface +/// or protocol against those declared in their implementations. +/// +void Sema::MatchAllMethodDeclarations(const llvm::DenseSet &InsMap, + const llvm::DenseSet &ClsMap, + llvm::DenseSet &InsMapSeen, + llvm::DenseSet &ClsMapSeen, + ObjCImplDecl* IMPDecl, + ObjCContainerDecl* CDecl, + bool &IncompleteImpl, + bool ImmediateClass, + bool WarnCategoryMethodImpl) { + // Check and see if instance methods in class interface have been + // implemented in the implementation class. If so, their types match. + for (ObjCInterfaceDecl::instmeth_iterator I = CDecl->instmeth_begin(), + E = CDecl->instmeth_end(); I != E; ++I) { + if (InsMapSeen.count((*I)->getSelector())) + continue; + InsMapSeen.insert((*I)->getSelector()); + if (!(*I)->isSynthesized() && + !InsMap.count((*I)->getSelector())) { + if (ImmediateClass) + WarnUndefinedMethod(IMPDecl->getLocation(), *I, IncompleteImpl, + diag::note_undef_method_impl); + continue; + } else { + ObjCMethodDecl *ImpMethodDecl = + IMPDecl->getInstanceMethod((*I)->getSelector()); + assert(CDecl->getInstanceMethod((*I)->getSelector()) && + "Expected to find the method through lookup as well"); + ObjCMethodDecl *MethodDecl = *I; + // ImpMethodDecl may be null as in a @dynamic property. + if (ImpMethodDecl) { + if (!WarnCategoryMethodImpl) + WarnConflictingTypedMethods(ImpMethodDecl, MethodDecl, + isa(CDecl)); + else if (!MethodDecl->isSynthesized()) + WarnExactTypedMethods(ImpMethodDecl, MethodDecl, + isa(CDecl)); + } + } + } + + // Check and see if class methods in class interface have been + // implemented in the implementation class. If so, their types match. + for (ObjCInterfaceDecl::classmeth_iterator + I = CDecl->classmeth_begin(), E = CDecl->classmeth_end(); I != E; ++I) { + if (ClsMapSeen.count((*I)->getSelector())) + continue; + ClsMapSeen.insert((*I)->getSelector()); + if (!ClsMap.count((*I)->getSelector())) { + if (ImmediateClass) + WarnUndefinedMethod(IMPDecl->getLocation(), *I, IncompleteImpl, + diag::note_undef_method_impl); + } else { + ObjCMethodDecl *ImpMethodDecl = + IMPDecl->getClassMethod((*I)->getSelector()); + assert(CDecl->getClassMethod((*I)->getSelector()) && + "Expected to find the method through lookup as well"); + ObjCMethodDecl *MethodDecl = *I; + if (!WarnCategoryMethodImpl) + WarnConflictingTypedMethods(ImpMethodDecl, MethodDecl, + isa(CDecl)); + else + WarnExactTypedMethods(ImpMethodDecl, MethodDecl, + isa(CDecl)); + } + } + + if (ObjCInterfaceDecl *I = dyn_cast (CDecl)) { + // Also methods in class extensions need be looked at next. + for (const ObjCCategoryDecl *ClsExtDecl = I->getFirstClassExtension(); + ClsExtDecl; ClsExtDecl = ClsExtDecl->getNextClassExtension()) + MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen, + IMPDecl, + const_cast(ClsExtDecl), + IncompleteImpl, false, + WarnCategoryMethodImpl); + + // Check for any implementation of a methods declared in protocol. + 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, + WarnCategoryMethodImpl); + + // FIXME. For now, we are not checking for extact match of methods + // in category implementation and its primary class's super class. + if (!WarnCategoryMethodImpl && I->getSuperClass()) + MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen, + IMPDecl, + I->getSuperClass(), IncompleteImpl, false); + } +} + +/// CheckCategoryVsClassMethodMatches - Checks that methods implemented in +/// category matches with those implemented in its primary class and +/// warns each time an exact match is found. +void Sema::CheckCategoryVsClassMethodMatches( + ObjCCategoryImplDecl *CatIMPDecl) { + llvm::DenseSet InsMap, ClsMap; + + for (ObjCImplementationDecl::instmeth_iterator + I = CatIMPDecl->instmeth_begin(), + E = CatIMPDecl->instmeth_end(); I!=E; ++I) + InsMap.insert((*I)->getSelector()); + + for (ObjCImplementationDecl::classmeth_iterator + I = CatIMPDecl->classmeth_begin(), + E = CatIMPDecl->classmeth_end(); I != E; ++I) + ClsMap.insert((*I)->getSelector()); + if (InsMap.empty() && ClsMap.empty()) + return; + + // Get category's primary class. + ObjCCategoryDecl *CatDecl = CatIMPDecl->getCategoryDecl(); + if (!CatDecl) + return; + ObjCInterfaceDecl *IDecl = CatDecl->getClassInterface(); + if (!IDecl) + return; + llvm::DenseSet InsMapSeen, ClsMapSeen; + bool IncompleteImpl = false; + MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen, + CatIMPDecl, IDecl, + IncompleteImpl, false, + true /*WarnCategoryMethodImpl*/); +} + +void Sema::ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl, + ObjCContainerDecl* CDecl, + bool IncompleteImpl) { + llvm::DenseSet InsMap; + // Check and see if instance methods in class interface have been + // implemented in the implementation class. + for (ObjCImplementationDecl::instmeth_iterator + I = IMPDecl->instmeth_begin(), E = IMPDecl->instmeth_end(); I!=E; ++I) + InsMap.insert((*I)->getSelector()); + + // Check and see if properties declared in the interface have either 1) + // an implementation or 2) there is a @synthesize/@dynamic implementation + // of the property in the @implementation. + if (const ObjCInterfaceDecl *IDecl = dyn_cast(CDecl)) + if (!(LangOpts.ObjCDefaultSynthProperties && LangOpts.ObjCNonFragileABI2) || + IDecl->isObjCRequiresPropertyDefs()) + DiagnoseUnimplementedProperties(S, IMPDecl, CDecl, InsMap); + + llvm::DenseSet ClsMap; + for (ObjCImplementationDecl::classmeth_iterator + I = IMPDecl->classmeth_begin(), + E = IMPDecl->classmeth_end(); I != E; ++I) + ClsMap.insert((*I)->getSelector()); + + // Check for type conflict of methods declared in a class/protocol and + // its implementation; if any. + llvm::DenseSet InsMapSeen, ClsMapSeen; + MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen, + IMPDecl, CDecl, + IncompleteImpl, true); + + // check all methods implemented in category against those declared + // in its primary class. + if (ObjCCategoryImplDecl *CatDecl = + dyn_cast(IMPDecl)) + CheckCategoryVsClassMethodMatches(CatDecl); + + // Check the protocol list for unimplemented methods in the @implementation + // class. + // Check and see if class methods in class interface have been + // implemented in the implementation class. + + if (ObjCInterfaceDecl *I = dyn_cast (CDecl)) { + 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) + for (const ObjCCategoryDecl *Categories = I->getFirstClassExtension(); + Categories; Categories = Categories->getNextClassExtension()) + ImplMethodsVsClassMethods(S, IMPDecl, + const_cast(Categories), + IncompleteImpl); + } else if (ObjCCategoryDecl *C = dyn_cast(CDecl)) { + // For extended class, unimplemented methods in its protocols will + // be reported in the primary class. + if (!C->IsClassExtension()) { + for (ObjCCategoryDecl::protocol_iterator PI = C->protocol_begin(), + E = C->protocol_end(); PI != E; ++PI) + CheckProtocolMethodDefs(IMPDecl->getLocation(), *PI, IncompleteImpl, + InsMap, ClsMap, CDecl); + // Report unimplemented properties in the category as well. + // When reporting on missing setter/getters, do not report when + // setter/getter is implemented in category's primary class + // implementation. + if (ObjCInterfaceDecl *ID = C->getClassInterface()) + if (ObjCImplDecl *IMP = ID->getImplementation()) { + for (ObjCImplementationDecl::instmeth_iterator + I = IMP->instmeth_begin(), E = IMP->instmeth_end(); I!=E; ++I) + InsMap.insert((*I)->getSelector()); + } + DiagnoseUnimplementedProperties(S, IMPDecl, CDecl, InsMap); + } + } else + llvm_unreachable("invalid ObjCContainerDecl type."); +} + +/// ActOnForwardClassDeclaration - +Sema::DeclGroupPtrTy +Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc, + IdentifierInfo **IdentList, + SourceLocation *IdentLocs, + unsigned NumElts) { + SmallVector DeclsInGroup; + for (unsigned i = 0; i != NumElts; ++i) { + // Check for another declaration kind with the same name. + NamedDecl *PrevDecl + = LookupSingleName(TUScope, IdentList[i], IdentLocs[i], + LookupOrdinaryName, ForRedeclaration); + if (PrevDecl && PrevDecl->isTemplateParameter()) { + // Maybe we will complain about the shadowed template parameter. + DiagnoseTemplateParameterShadow(AtClassLoc, PrevDecl); + // Just pretend that we didn't see the previous declaration. + PrevDecl = 0; + } + + if (PrevDecl && !isa(PrevDecl)) { + // GCC apparently allows the following idiom: + // + // typedef NSObject < XCElementTogglerP > XCElementToggler; + // @class XCElementToggler; + // + // Here we have chosen to ignore the forward class declaration + // with a warning. Since this is the implied behavior. + TypedefNameDecl *TDD = dyn_cast(PrevDecl); + if (!TDD || !TDD->getUnderlyingType()->isObjCObjectType()) { + Diag(AtClassLoc, diag::err_redefinition_different_kind) << IdentList[i]; + Diag(PrevDecl->getLocation(), diag::note_previous_definition); + } else { + // a forward class declaration matching a typedef name of a class refers + // to the underlying class. Just ignore the forward class with a warning + // as this will force the intended behavior which is to lookup the typedef + // name. + if (isa(TDD->getUnderlyingType())) { + Diag(AtClassLoc, diag::warn_forward_class_redefinition) << IdentList[i]; + Diag(PrevDecl->getLocation(), diag::note_previous_definition); + continue; + } + } + } + + // Create a declaration to describe this forward declaration. + ObjCInterfaceDecl *PrevIDecl + = dyn_cast_or_null(PrevDecl); + ObjCInterfaceDecl *IDecl + = ObjCInterfaceDecl::Create(Context, CurContext, AtClassLoc, + IdentList[i], PrevIDecl, IdentLocs[i]); + IDecl->setAtEndRange(IdentLocs[i]); + + PushOnScopeChains(IDecl, TUScope); + CheckObjCDeclScope(IDecl); + DeclsInGroup.push_back(IDecl); + } + + return BuildDeclaratorGroup(DeclsInGroup.data(), DeclsInGroup.size(), false); +} + +static bool tryMatchRecordTypes(ASTContext &Context, + Sema::MethodMatchStrategy strategy, + const Type *left, const Type *right); + +static bool matchTypes(ASTContext &Context, Sema::MethodMatchStrategy strategy, + QualType leftQT, QualType rightQT) { + const Type *left = + Context.getCanonicalType(leftQT).getUnqualifiedType().getTypePtr(); + const Type *right = + Context.getCanonicalType(rightQT).getUnqualifiedType().getTypePtr(); + + if (left == right) return true; + + // If we're doing a strict match, the types have to match exactly. + if (strategy == Sema::MMS_strict) return false; + + if (left->isIncompleteType() || right->isIncompleteType()) return false; + + // Otherwise, use this absurdly complicated algorithm to try to + // validate the basic, low-level compatibility of the two types. + + // As a minimum, require the sizes and alignments to match. + if (Context.getTypeInfo(left) != Context.getTypeInfo(right)) + return false; + + // Consider all the kinds of non-dependent canonical types: + // - functions and arrays aren't possible as return and parameter types + + // - vector types of equal size can be arbitrarily mixed + if (isa(left)) return isa(right); + if (isa(right)) return false; + + // - references should only match references of identical type + // - structs, unions, and Objective-C objects must match more-or-less + // exactly + // - everything else should be a scalar + if (!left->isScalarType() || !right->isScalarType()) + return tryMatchRecordTypes(Context, strategy, left, right); + + // Make scalars agree in kind, except count bools as chars, and group + // all non-member pointers together. + Type::ScalarTypeKind leftSK = left->getScalarTypeKind(); + Type::ScalarTypeKind rightSK = right->getScalarTypeKind(); + if (leftSK == Type::STK_Bool) leftSK = Type::STK_Integral; + if (rightSK == Type::STK_Bool) rightSK = Type::STK_Integral; + if (leftSK == Type::STK_CPointer || leftSK == Type::STK_BlockPointer) + leftSK = Type::STK_ObjCObjectPointer; + if (rightSK == Type::STK_CPointer || rightSK == Type::STK_BlockPointer) + rightSK = Type::STK_ObjCObjectPointer; + + // Note that data member pointers and function member pointers don't + // intermix because of the size differences. + + return (leftSK == rightSK); +} + +static bool tryMatchRecordTypes(ASTContext &Context, + Sema::MethodMatchStrategy strategy, + const Type *lt, const Type *rt) { + assert(lt && rt && lt != rt); + + if (!isa(lt) || !isa(rt)) return false; + RecordDecl *left = cast(lt)->getDecl(); + RecordDecl *right = cast(rt)->getDecl(); + + // Require union-hood to match. + if (left->isUnion() != right->isUnion()) return false; + + // Require an exact match if either is non-POD. + if ((isa(left) && !cast(left)->isPOD()) || + (isa(right) && !cast(right)->isPOD())) + return false; + + // Require size and alignment to match. + if (Context.getTypeInfo(lt) != Context.getTypeInfo(rt)) return false; + + // Require fields to match. + RecordDecl::field_iterator li = left->field_begin(), le = left->field_end(); + RecordDecl::field_iterator ri = right->field_begin(), re = right->field_end(); + for (; li != le && ri != re; ++li, ++ri) { + if (!matchTypes(Context, strategy, li->getType(), ri->getType())) + return false; + } + return (li == le && ri == re); +} + +/// MatchTwoMethodDeclarations - Checks that two methods have matching type and +/// returns true, or false, accordingly. +/// TODO: Handle protocol list; such as id in type comparisons +bool Sema::MatchTwoMethodDeclarations(const ObjCMethodDecl *left, + const ObjCMethodDecl *right, + MethodMatchStrategy strategy) { + if (!matchTypes(Context, strategy, + left->getResultType(), right->getResultType())) + return false; + + if (getLangOpts().ObjCAutoRefCount && + (left->hasAttr() + != right->hasAttr() || + left->hasAttr() + != right->hasAttr())) + return false; + + ObjCMethodDecl::param_const_iterator + li = left->param_begin(), le = left->param_end(), ri = right->param_begin(); + + for (; li != le; ++li, ++ri) { + assert(ri != right->param_end() && "Param mismatch"); + const ParmVarDecl *lparm = *li, *rparm = *ri; + + if (!matchTypes(Context, strategy, lparm->getType(), rparm->getType())) + return false; + + if (getLangOpts().ObjCAutoRefCount && + lparm->hasAttr() != rparm->hasAttr()) + return false; + } + return true; +} + +void Sema::addMethodToGlobalList(ObjCMethodList *List, ObjCMethodDecl *Method) { + // If the list is empty, make it a singleton list. + if (List->Method == 0) { + List->Method = Method; + List->Next = 0; + return; + } + + // We've seen a method with this name, see if we have already seen this type + // signature. + ObjCMethodList *Previous = List; + for (; List; Previous = List, List = List->Next) { + if (!MatchTwoMethodDeclarations(Method, List->Method)) + continue; + + ObjCMethodDecl *PrevObjCMethod = List->Method; + + // Propagate the 'defined' bit. + if (Method->isDefined()) + PrevObjCMethod->setDefined(true); + + // If a method is deprecated, push it in the global pool. + // This is used for better diagnostics. + if (Method->isDeprecated()) { + if (!PrevObjCMethod->isDeprecated()) + List->Method = Method; + } + // If new method is unavailable, push it into global pool + // unless previous one is deprecated. + if (Method->isUnavailable()) { + if (PrevObjCMethod->getAvailability() < AR_Deprecated) + List->Method = Method; + } + + return; + } + + // 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(); + Previous->Next = new (Mem) ObjCMethodList(Method, 0); +} + +/// \brief Read the contents of the method pool for a given selector from +/// external storage. +void Sema::ReadMethodPool(Selector Sel) { + assert(ExternalSource && "We need an external AST source"); + ExternalSource->ReadMethodPool(Sel); +} + +void Sema::AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl, + bool instance) { + // Ignore methods of invalid containers. + if (cast(Method->getDeclContext())->isInvalidDecl()) + return; + + if (ExternalSource) + ReadMethodPool(Method->getSelector()); + + GlobalMethodPool::iterator Pos = MethodPool.find(Method->getSelector()); + if (Pos == MethodPool.end()) + Pos = MethodPool.insert(std::make_pair(Method->getSelector(), + GlobalMethods())).first; + + Method->setDefined(impl); + + ObjCMethodList &Entry = instance ? Pos->second.first : Pos->second.second; + addMethodToGlobalList(&Entry, Method); +} + +/// Determines if this is an "acceptable" loose mismatch in the global +/// method pool. This exists mostly as a hack to get around certain +/// global mismatches which we can't afford to make warnings / errors. +/// Really, what we want is a way to take a method out of the global +/// method pool. +static bool isAcceptableMethodMismatch(ObjCMethodDecl *chosen, + ObjCMethodDecl *other) { + if (!chosen->isInstanceMethod()) + return false; + + Selector sel = chosen->getSelector(); + if (!sel.isUnarySelector() || sel.getNameForSlot(0) != "length") + return false; + + // Don't complain about mismatches for -length if the method we + // chose has an integral result type. + return (chosen->getResultType()->isIntegerType()); +} + +ObjCMethodDecl *Sema::LookupMethodInGlobalPool(Selector Sel, SourceRange R, + bool receiverIdOrClass, + bool warn, bool instance) { + if (ExternalSource) + ReadMethodPool(Sel); + + GlobalMethodPool::iterator Pos = MethodPool.find(Sel); + if (Pos == MethodPool.end()) + return 0; + + ObjCMethodList &MethList = instance ? Pos->second.first : Pos->second.second; + + if (warn && MethList.Method && MethList.Next) { + bool issueDiagnostic = false, issueError = false; + + // We support a warning which complains about *any* difference in + // method signature. + bool strictSelectorMatch = + (receiverIdOrClass && warn && + (Diags.getDiagnosticLevel(diag::warn_strict_multiple_method_decl, + R.getBegin()) != + DiagnosticsEngine::Ignored)); + if (strictSelectorMatch) + for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next) { + if (!MatchTwoMethodDeclarations(MethList.Method, Next->Method, + MMS_strict)) { + issueDiagnostic = true; + break; + } + } + + // If we didn't see any strict differences, we won't see any loose + // differences. In ARC, however, we also need to check for loose + // mismatches, because most of them are errors. + if (!strictSelectorMatch || + (issueDiagnostic && getLangOpts().ObjCAutoRefCount)) + for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next) { + // This checks if the methods differ in type mismatch. + if (!MatchTwoMethodDeclarations(MethList.Method, Next->Method, + MMS_loose) && + !isAcceptableMethodMismatch(MethList.Method, Next->Method)) { + issueDiagnostic = true; + if (getLangOpts().ObjCAutoRefCount) + issueError = true; + break; + } + } + + if (issueDiagnostic) { + if (issueError) + Diag(R.getBegin(), diag::err_arc_multiple_method_decl) << Sel << R; + else 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(), + issueError ? diag::note_possibility : 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::LookupImplementedMethodInGlobalPool(Selector Sel) { + GlobalMethodPool::iterator Pos = MethodPool.find(Sel); + if (Pos == MethodPool.end()) + return 0; + + GlobalMethods &Methods = Pos->second; + + 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 +/// identical selector names in current and its super classes and issues +/// a warning if any of their argument types are incompatible. +void Sema::CompareMethodParamsInBaseAndSuper(Decl *ClassDecl, + ObjCMethodDecl *Method, + bool IsInstance) { + ObjCInterfaceDecl *ID = dyn_cast(ClassDecl); + if (ID == 0) return; + + while (ObjCInterfaceDecl *SD = ID->getSuperClass()) { + ObjCMethodDecl *SuperMethodDecl = + SD->lookupMethod(Method->getSelector(), IsInstance); + if (SuperMethodDecl == 0) { + ID = SD; + continue; + } + ObjCMethodDecl::param_iterator ParamI = Method->param_begin(), + E = Method->param_end(); + ObjCMethodDecl::param_iterator PrevI = SuperMethodDecl->param_begin(); + for (; ParamI != E; ++ParamI, ++PrevI) { + // Number of parameters are the same and is guaranteed by selector match. + assert(PrevI != SuperMethodDecl->param_end() && "Param mismatch"); + QualType T1 = Context.getCanonicalType((*ParamI)->getType()); + QualType T2 = Context.getCanonicalType((*PrevI)->getType()); + // If type of argument of method in this class does not match its + // respective argument type in the super class method, issue warning; + if (!Context.typesAreCompatible(T1, T2)) { + Diag((*ParamI)->getLocation(), diag::ext_typecheck_base_super) + << T1 << T2; + Diag(SuperMethodDecl->getLocation(), diag::note_previous_declaration); + return; + } + } + ID = SD; + } +} + +/// DiagnoseDuplicateIvars - +/// Check for duplicate ivars in the entire class at the start of +/// @implementation. This becomes necesssary because class extension can +/// add ivars to a class in random order which will not be known until +/// class's @implementation is seen. +void Sema::DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID, + ObjCInterfaceDecl *SID) { + for (ObjCInterfaceDecl::ivar_iterator IVI = ID->ivar_begin(), + IVE = ID->ivar_end(); IVI != IVE; ++IVI) { + ObjCIvarDecl* Ivar = (*IVI); + if (Ivar->isInvalidDecl()) + continue; + if (IdentifierInfo *II = Ivar->getIdentifier()) { + ObjCIvarDecl* prevIvar = SID->lookupInstanceVariable(II); + if (prevIvar) { + Diag(Ivar->getLocation(), diag::err_duplicate_member) << II; + Diag(prevIvar->getLocation(), diag::note_previous_declaration); + Ivar->setInvalidDecl(); + } + } + } +} + +Sema::ObjCContainerKind Sema::getObjCContainerKind() const { + switch (CurContext->getDeclKind()) { + case Decl::ObjCInterface: + return Sema::OCK_Interface; + case Decl::ObjCProtocol: + return Sema::OCK_Protocol; + case Decl::ObjCCategory: + if (dyn_cast(CurContext)->IsClassExtension()) + return Sema::OCK_ClassExtension; + else + return Sema::OCK_Category; + case Decl::ObjCImplementation: + return Sema::OCK_Implementation; + case Decl::ObjCCategoryImpl: + return Sema::OCK_CategoryImplementation; + + default: + return Sema::OCK_None; + } +} + +// Note: For class/category implemenations, allMethods/allProperties is +// always null. +Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, + Decl **allMethods, unsigned allNum, + Decl **allProperties, unsigned pNum, + DeclGroupPtrTy *allTUVars, unsigned tuvNum) { + + if (getObjCContainerKind() == Sema::OCK_None) + return 0; + + assert(AtEnd.isValid() && "Invalid location for '@end'"); + + ObjCContainerDecl *OCD = dyn_cast(CurContext); + Decl *ClassDecl = cast(OCD); + + bool isInterfaceDeclKind = + isa(ClassDecl) || isa(ClassDecl) + || isa(ClassDecl); + bool checkIdenticalMethods = isa(ClassDecl); + + // FIXME: Remove these and use the ObjCContainerDecl/DeclContext. + llvm::DenseMap InsMap; + llvm::DenseMap ClsMap; + + for (unsigned i = 0; i < allNum; i++ ) { + ObjCMethodDecl *Method = + cast_or_null(allMethods[i]); + + if (!Method) continue; // Already issued a diagnostic. + if (Method->isInstanceMethod()) { + /// Check for instance method of the same name with incompatible types + const ObjCMethodDecl *&PrevMethod = InsMap[Method->getSelector()]; + bool match = PrevMethod ? MatchTwoMethodDeclarations(Method, PrevMethod) + : false; + if ((isInterfaceDeclKind && PrevMethod && !match) + || (checkIdenticalMethods && match)) { + Diag(Method->getLocation(), diag::err_duplicate_method_decl) + << Method->getDeclName(); + Diag(PrevMethod->getLocation(), diag::note_previous_declaration); + Method->setInvalidDecl(); + } else { + if (PrevMethod) { + Method->setAsRedeclaration(PrevMethod); + if (!Context.getSourceManager().isInSystemHeader( + Method->getLocation())) + Diag(Method->getLocation(), diag::warn_duplicate_method_decl) + << Method->getDeclName(); + Diag(PrevMethod->getLocation(), diag::note_previous_declaration); + } + InsMap[Method->getSelector()] = Method; + /// The following allows us to typecheck messages to "id". + AddInstanceMethodToGlobalPool(Method); + // verify that the instance method conforms to the same definition of + // parent methods if it shadows one. + CompareMethodParamsInBaseAndSuper(ClassDecl, Method, true); + } + } else { + /// Check for class method of the same name with incompatible types + const ObjCMethodDecl *&PrevMethod = ClsMap[Method->getSelector()]; + bool match = PrevMethod ? MatchTwoMethodDeclarations(Method, PrevMethod) + : false; + if ((isInterfaceDeclKind && PrevMethod && !match) + || (checkIdenticalMethods && match)) { + Diag(Method->getLocation(), diag::err_duplicate_method_decl) + << Method->getDeclName(); + Diag(PrevMethod->getLocation(), diag::note_previous_declaration); + Method->setInvalidDecl(); + } else { + if (PrevMethod) { + Method->setAsRedeclaration(PrevMethod); + if (!Context.getSourceManager().isInSystemHeader( + Method->getLocation())) + Diag(Method->getLocation(), diag::warn_duplicate_method_decl) + << Method->getDeclName(); + Diag(PrevMethod->getLocation(), diag::note_previous_declaration); + } + ClsMap[Method->getSelector()] = Method; + /// The following allows us to typecheck messages to "Class". + AddFactoryMethodToGlobalPool(Method); + // verify that the class method conforms to the same definition of + // parent methods if it shadows one. + CompareMethodParamsInBaseAndSuper(ClassDecl, Method, false); + } + } + } + if (ObjCInterfaceDecl *I = dyn_cast(ClassDecl)) { + // Compares properties declared in this class to those of its + // super class. + ComparePropertiesInBaseAndSuper(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, C); + if (C->IsClassExtension()) { + ObjCInterfaceDecl *CCPrimary = C->getClassInterface(); + DiagnoseClassExtensionDupMethods(C, CCPrimary); + } + } + if (ObjCContainerDecl *CDecl = dyn_cast(ClassDecl)) { + if (CDecl->getIdentifier()) + // ProcessPropertyDecl is responsible for diagnosing conflicts with any + // user-defined setter/getter. It also synthesizes setter/getter methods + // and adds them to the DeclContext and global method pools. + for (ObjCContainerDecl::prop_iterator I = CDecl->prop_begin(), + E = CDecl->prop_end(); + I != E; ++I) + ProcessPropertyDecl(*I, CDecl); + CDecl->setAtEndRange(AtEnd); + } + if (ObjCImplementationDecl *IC=dyn_cast(ClassDecl)) { + IC->setAtEndRange(AtEnd); + if (ObjCInterfaceDecl* IDecl = IC->getClassInterface()) { + // Any property declared in a class extension might have user + // declared setter or getter in current class extension or one + // of the other class extensions. Mark them as synthesized as + // property will be synthesized when property with same name is + // seen in the @implementation. + for (const ObjCCategoryDecl *ClsExtDecl = + IDecl->getFirstClassExtension(); + ClsExtDecl; ClsExtDecl = ClsExtDecl->getNextClassExtension()) { + for (ObjCContainerDecl::prop_iterator I = ClsExtDecl->prop_begin(), + E = ClsExtDecl->prop_end(); I != E; ++I) { + ObjCPropertyDecl *Property = (*I); + // Skip over properties declared @dynamic + if (const ObjCPropertyImplDecl *PIDecl + = IC->FindPropertyImplDecl(Property->getIdentifier())) + if (PIDecl->getPropertyImplementation() + == ObjCPropertyImplDecl::Dynamic) + continue; + + for (const ObjCCategoryDecl *CExtDecl = + IDecl->getFirstClassExtension(); + CExtDecl; CExtDecl = CExtDecl->getNextClassExtension()) { + if (ObjCMethodDecl *GetterMethod = + CExtDecl->getInstanceMethod(Property->getGetterName())) + GetterMethod->setSynthesized(true); + if (!Property->isReadOnly()) + if (ObjCMethodDecl *SetterMethod = + CExtDecl->getInstanceMethod(Property->getSetterName())) + SetterMethod->setSynthesized(true); + } + } + } + ImplMethodsVsClassMethods(S, IC, IDecl); + AtomicPropertySetterGetterRules(IC, IDecl); + DiagnoseOwningPropertyGetterSynthesis(IC); + + bool HasRootClassAttr = IDecl->hasAttr(); + if (IDecl->getSuperClass() == NULL) { + // This class has no superclass, so check that it has been marked with + // __attribute((objc_root_class)). + if (!HasRootClassAttr) { + SourceLocation DeclLoc(IDecl->getLocation()); + SourceLocation SuperClassLoc(PP.getLocForEndOfToken(DeclLoc)); + Diag(DeclLoc, diag::warn_objc_root_class_missing) + << IDecl->getIdentifier(); + // See if NSObject is in the current scope, and if it is, suggest + // adding " : NSObject " to the class declaration. + NamedDecl *IF = LookupSingleName(TUScope, + NSAPIObj->getNSClassId(NSAPI::ClassId_NSObject), + DeclLoc, LookupOrdinaryName); + ObjCInterfaceDecl *NSObjectDecl = dyn_cast_or_null(IF); + if (NSObjectDecl && NSObjectDecl->getDefinition()) { + Diag(SuperClassLoc, diag::note_objc_needs_superclass) + << FixItHint::CreateInsertion(SuperClassLoc, " : NSObject "); + } else { + Diag(SuperClassLoc, diag::note_objc_needs_superclass); + } + } + } else if (HasRootClassAttr) { + // Complain that only root classes may have this attribute. + Diag(IDecl->getLocation(), diag::err_objc_root_class_subclass); + } + + if (LangOpts.ObjCNonFragileABI2) { + while (IDecl->getSuperClass()) { + DiagnoseDuplicateIvars(IDecl, IDecl->getSuperClass()); + IDecl = IDecl->getSuperClass(); + } + } + } + SetIvarInitializers(IC); + } else if (ObjCCategoryImplDecl* CatImplClass = + dyn_cast(ClassDecl)) { + CatImplClass->setAtEndRange(AtEnd); + + // Find category interface decl and then check that all methods declared + // in this interface are implemented in the category @implementation. + if (ObjCInterfaceDecl* IDecl = CatImplClass->getClassInterface()) { + for (ObjCCategoryDecl *Categories = IDecl->getCategoryList(); + Categories; Categories = Categories->getNextClassCategory()) { + if (Categories->getIdentifier() == CatImplClass->getIdentifier()) { + ImplMethodsVsClassMethods(S, CatImplClass, Categories); + break; + } + } + } + } + if (isInterfaceDeclKind) { + // Reject invalid vardecls. + for (unsigned i = 0; i != tuvNum; i++) { + DeclGroupRef DG = allTUVars[i].getAsVal(); + for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) + if (VarDecl *VDecl = dyn_cast(*I)) { + if (!VDecl->hasExternalStorage()) + Diag(VDecl->getLocation(), diag::err_objc_var_decl_inclass); + } + } + } + ActOnObjCContainerFinishDefinition(); + + for (unsigned i = 0; i != tuvNum; i++) { + DeclGroupRef DG = allTUVars[i].getAsVal(); + for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) + (*I)->setTopLevelDeclInObjCContainer(); + Consumer.HandleTopLevelDeclInObjCContainer(DG); + } + + return ClassDecl; +} + + +/// CvtQTToAstBitMask - utility routine to produce an AST bitmask for +/// objective-c's type qualifier from the parser version of the same info. +static Decl::ObjCDeclQualifier +CvtQTToAstBitMask(ObjCDeclSpec::ObjCDeclQualifier PQTVal) { + return (Decl::ObjCDeclQualifier) (unsigned) PQTVal; +} + +static inline +bool containsInvalidMethodImplAttribute(ObjCMethodDecl *IMD, + const AttrVec &A) { + // If method is only declared in implementation (private method), + // No need to issue any diagnostics on method definition with attributes. + if (!IMD) + return false; + + // method declared in interface has no attribute. + // But implementation has attributes. This is invalid + if (!IMD->hasAttrs()) + return true; + + const AttrVec &D = IMD->getAttrs(); + if (D.size() != A.size()) + return true; + + // attributes on method declaration and definition must match exactly. + // Note that we have at most a couple of attributes on methods, so this + // n*n search is good enough. + for (AttrVec::const_iterator i = A.begin(), e = A.end(); i != e; ++i) { + bool match = false; + for (AttrVec::const_iterator i1 = D.begin(), e1 = D.end(); i1 != e1; ++i1) { + if ((*i)->getKind() == (*i1)->getKind()) { + match = true; + break; + } + } + if (!match) + return true; + } + return false; +} + +namespace { + /// \brief Describes the compatibility of a result type with its method. + enum ResultTypeCompatibilityKind { + RTC_Compatible, + RTC_Incompatible, + RTC_Unknown + }; +} + +/// \brief Check whether the declared result type of the given Objective-C +/// method declaration is compatible with the method's class. +/// +static ResultTypeCompatibilityKind +CheckRelatedResultTypeCompatibility(Sema &S, ObjCMethodDecl *Method, + ObjCInterfaceDecl *CurrentClass) { + QualType ResultType = Method->getResultType(); + + // If an Objective-C method inherits its related result type, then its + // declared result type must be compatible with its own class type. The + // declared result type is compatible if: + if (const ObjCObjectPointerType *ResultObjectType + = ResultType->getAs()) { + // - it is id or qualified id, or + if (ResultObjectType->isObjCIdType() || + ResultObjectType->isObjCQualifiedIdType()) + return RTC_Compatible; + + if (CurrentClass) { + if (ObjCInterfaceDecl *ResultClass + = ResultObjectType->getInterfaceDecl()) { + // - it is the same as the method's class type, or + if (declaresSameEntity(CurrentClass, ResultClass)) + return RTC_Compatible; + + // - it is a superclass of the method's class type + if (ResultClass->isSuperClassOf(CurrentClass)) + return RTC_Compatible; + } + } else { + // Any Objective-C pointer type might be acceptable for a protocol + // method; we just don't know. + return RTC_Unknown; + } + } + + return RTC_Incompatible; +} + +namespace { +/// A helper class for searching for methods which a particular method +/// overrides. +class OverrideSearch { +public: + Sema &S; + ObjCMethodDecl *Method; + llvm::SmallPtrSet Searched; + llvm::SmallPtrSet Overridden; + bool Recursive; + +public: + OverrideSearch(Sema &S, ObjCMethodDecl *method) : S(S), Method(method) { + Selector selector = method->getSelector(); + + // Bypass this search if we've never seen an instance/class method + // with this selector before. + Sema::GlobalMethodPool::iterator it = S.MethodPool.find(selector); + if (it == S.MethodPool.end()) { + if (!S.ExternalSource) return; + S.ReadMethodPool(selector); + + it = S.MethodPool.find(selector); + if (it == S.MethodPool.end()) + return; + } + ObjCMethodList &list = + method->isInstanceMethod() ? it->second.first : it->second.second; + if (!list.Method) return; + + ObjCContainerDecl *container + = cast(method->getDeclContext()); + + // Prevent the search from reaching this container again. This is + // important with categories, which override methods from the + // interface and each other. + Searched.insert(container); + searchFromContainer(container); + } + + typedef llvm::SmallPtrSet::iterator iterator; + iterator begin() const { return Overridden.begin(); } + iterator end() const { return Overridden.end(); } + +private: + void searchFromContainer(ObjCContainerDecl *container) { + if (container->isInvalidDecl()) return; + + switch (container->getDeclKind()) { +#define OBJCCONTAINER(type, base) \ + case Decl::type: \ + searchFrom(cast(container)); \ + break; +#define ABSTRACT_DECL(expansion) +#define DECL(type, base) \ + case Decl::type: +#include "clang/AST/DeclNodes.inc" + llvm_unreachable("not an ObjC container!"); + } + } + + void searchFrom(ObjCProtocolDecl *protocol) { + if (!protocol->hasDefinition()) + return; + + // A method in a protocol declaration overrides declarations from + // referenced ("parent") protocols. + search(protocol->getReferencedProtocols()); + } + + void searchFrom(ObjCCategoryDecl *category) { + // A method in a category declaration overrides declarations from + // the main class and from protocols the category references. + search(category->getClassInterface()); + search(category->getReferencedProtocols()); + } + + void searchFrom(ObjCCategoryImplDecl *impl) { + // A method in a category definition that has a category + // declaration overrides declarations from the category + // declaration. + if (ObjCCategoryDecl *category = impl->getCategoryDecl()) { + search(category); + + // Otherwise it overrides declarations from the class. + } else { + search(impl->getClassInterface()); + } + } + + void searchFrom(ObjCInterfaceDecl *iface) { + // A method in a class declaration overrides declarations from + if (!iface->hasDefinition()) + return; + + // - categories, + for (ObjCCategoryDecl *category = iface->getCategoryList(); + category; category = category->getNextClassCategory()) + search(category); + + // - the super class, and + if (ObjCInterfaceDecl *super = iface->getSuperClass()) + search(super); + + // - any referenced protocols. + search(iface->getReferencedProtocols()); + } + + void searchFrom(ObjCImplementationDecl *impl) { + // A method in a class implementation overrides declarations from + // the class interface. + search(impl->getClassInterface()); + } + + + void search(const ObjCProtocolList &protocols) { + for (ObjCProtocolList::iterator i = protocols.begin(), e = protocols.end(); + i != e; ++i) + search(*i); + } + + void search(ObjCContainerDecl *container) { + // Abort if we've already searched this container. + if (!Searched.insert(container)) return; + + // Check for a method in this container which matches this selector. + ObjCMethodDecl *meth = container->getMethod(Method->getSelector(), + Method->isInstanceMethod()); + + // If we find one, record it and bail out. + if (meth) { + Overridden.insert(meth); + return; + } + + // Otherwise, search for methods that a hypothetical method here + // would have overridden. + + // Note that we're now in a recursive case. + Recursive = true; + + searchFromContainer(container); + } +}; +} + +Decl *Sema::ActOnMethodDeclaration( + Scope *S, + SourceLocation MethodLoc, SourceLocation EndLoc, + tok::TokenKind MethodType, + ObjCDeclSpec &ReturnQT, ParsedType ReturnType, + ArrayRef SelectorLocs, + 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 MethodDeclKind, + bool isVariadic, bool MethodDefinition) { + // Make sure we can establish a context for the method. + if (!CurContext->isObjCContainer()) { + Diag(MethodLoc, diag::error_missing_method_context); + return 0; + } + ObjCContainerDecl *OCD = dyn_cast(CurContext); + Decl *ClassDecl = cast(OCD); + QualType resultDeclType; + + bool HasRelatedResultType = false; + TypeSourceInfo *ResultTInfo = 0; + if (ReturnType) { + resultDeclType = GetTypeFromParser(ReturnType, &ResultTInfo); + + // Methods cannot return interface types. All ObjC objects are + // passed by reference. + if (resultDeclType->isObjCObjectType()) { + Diag(MethodLoc, diag::err_object_cannot_be_passed_returned_by_value) + << 0 << resultDeclType; + return 0; + } + + HasRelatedResultType = (resultDeclType == Context.getObjCInstanceType()); + } else { // get the type for "id". + resultDeclType = Context.getObjCIdType(); + Diag(MethodLoc, diag::warn_missing_method_return_type) + << FixItHint::CreateInsertion(SelectorLocs.front(), "(id)"); + } + + ObjCMethodDecl* ObjCMethod = + ObjCMethodDecl::Create(Context, MethodLoc, EndLoc, Sel, + resultDeclType, + ResultTInfo, + CurContext, + MethodType == tok::minus, isVariadic, + /*isSynthesized=*/false, + /*isImplicitlyDeclared=*/false, /*isDefined=*/false, + MethodDeclKind == tok::objc_optional + ? ObjCMethodDecl::Optional + : ObjCMethodDecl::Required, + HasRelatedResultType); + + SmallVector Params; + + for (unsigned i = 0, e = Sel.getNumArgs(); i != e; ++i) { + QualType ArgType; + TypeSourceInfo *DI; + + if (ArgInfo[i].Type == 0) { + ArgType = Context.getObjCIdType(); + DI = 0; + } else { + ArgType = GetTypeFromParser(ArgInfo[i].Type, &DI); + // Perform the default array/function conversions (C99 6.7.5.3p[7,8]). + ArgType = Context.getAdjustedParameterType(ArgType); + } + + LookupResult R(*this, ArgInfo[i].Name, ArgInfo[i].NameLoc, + LookupOrdinaryName, ForRedeclaration); + LookupName(R, S); + if (R.isSingleResult()) { + NamedDecl *PrevDecl = R.getFoundDecl(); + if (S->isDeclScope(PrevDecl)) { + Diag(ArgInfo[i].NameLoc, + (MethodDefinition ? diag::warn_method_param_redefinition + : diag::warn_method_param_declaration)) + << ArgInfo[i].Name; + Diag(PrevDecl->getLocation(), + diag::note_previous_declaration); + } + } + + SourceLocation StartLoc = DI + ? DI->getTypeLoc().getBeginLoc() + : ArgInfo[i].NameLoc; + + ParmVarDecl* Param = CheckParameter(ObjCMethod, StartLoc, + ArgInfo[i].NameLoc, ArgInfo[i].Name, + ArgType, DI, SC_None, SC_None); + + Param->setObjCMethodScopeInfo(i); + + Param->setObjCDeclQualifier( + CvtQTToAstBitMask(ArgInfo[i].DeclSpec.getObjCDeclQualifier())); + + // Apply the attributes to the parameter. + ProcessDeclAttributeList(TUScope, Param, ArgInfo[i].ArgAttrs); + + if (Param->hasAttr()) { + Diag(Param->getLocation(), diag::err_block_on_nonlocal); + Param->setInvalidDecl(); + } + S->AddDecl(Param); + IdResolver.AddDecl(Param); + + Params.push_back(Param); + } + + for (unsigned i = 0, e = CNumArgs; i != e; ++i) { + ParmVarDecl *Param = cast(CParamInfo[i].Param); + QualType ArgType = Param->getType(); + if (ArgType.isNull()) + ArgType = Context.getObjCIdType(); + else + // Perform the default array/function conversions (C99 6.7.5.3p[7,8]). + ArgType = Context.getAdjustedParameterType(ArgType); + if (ArgType->isObjCObjectType()) { + Diag(Param->getLocation(), + diag::err_object_cannot_be_passed_returned_by_value) + << 1 << ArgType; + Param->setInvalidDecl(); + } + Param->setDeclContext(ObjCMethod); + + Params.push_back(Param); + } + + ObjCMethod->setMethodParams(Context, Params, SelectorLocs); + ObjCMethod->setObjCDeclQualifier( + CvtQTToAstBitMask(ReturnQT.getObjCDeclQualifier())); + + if (AttrList) + ProcessDeclAttributeList(TUScope, ObjCMethod, AttrList); + + // Add the method now. + const ObjCMethodDecl *PrevMethod = 0; + if (ObjCImplDecl *ImpDecl = dyn_cast(ClassDecl)) { + if (MethodType == tok::minus) { + PrevMethod = ImpDecl->getInstanceMethod(Sel); + ImpDecl->addInstanceMethod(ObjCMethod); + } else { + PrevMethod = ImpDecl->getClassMethod(Sel); + ImpDecl->addClassMethod(ObjCMethod); + } + + ObjCMethodDecl *IMD = 0; + if (ObjCInterfaceDecl *IDecl = ImpDecl->getClassInterface()) + IMD = IDecl->lookupMethod(ObjCMethod->getSelector(), + ObjCMethod->isInstanceMethod()); + if (ObjCMethod->hasAttrs() && + containsInvalidMethodImplAttribute(IMD, ObjCMethod->getAttrs())) { + SourceLocation MethodLoc = IMD->getLocation(); + if (!getSourceManager().isInSystemHeader(MethodLoc)) { + Diag(EndLoc, diag::warn_attribute_method_def); + Diag(MethodLoc, diag::note_method_declared_at) + << ObjCMethod->getDeclName(); + } + } + } else { + cast(ClassDecl)->addDecl(ObjCMethod); + } + + if (PrevMethod) { + // You can never have two method definitions with the same name. + Diag(ObjCMethod->getLocation(), diag::err_duplicate_method_decl) + << ObjCMethod->getDeclName(); + Diag(PrevMethod->getLocation(), diag::note_previous_declaration); + } + + // If this Objective-C method does not have a related result type, but we + // are allowed to infer related result types, try to do so based on the + // method family. + ObjCInterfaceDecl *CurrentClass = dyn_cast(ClassDecl); + if (!CurrentClass) { + if (ObjCCategoryDecl *Cat = dyn_cast(ClassDecl)) + CurrentClass = Cat->getClassInterface(); + else if (ObjCImplDecl *Impl = dyn_cast(ClassDecl)) + CurrentClass = Impl->getClassInterface(); + else if (ObjCCategoryImplDecl *CatImpl + = dyn_cast(ClassDecl)) + CurrentClass = CatImpl->getClassInterface(); + } + + ResultTypeCompatibilityKind RTC + = CheckRelatedResultTypeCompatibility(*this, ObjCMethod, CurrentClass); + + // Search for overridden methods and merge information down from them. + OverrideSearch overrides(*this, ObjCMethod); + for (OverrideSearch::iterator + i = overrides.begin(), e = overrides.end(); i != e; ++i) { + ObjCMethodDecl *overridden = *i; + + // Propagate down the 'related result type' bit from overridden methods. + if (RTC != RTC_Incompatible && overridden->hasRelatedResultType()) + ObjCMethod->SetRelatedResultType(); + + // Then merge the declarations. + mergeObjCMethodDecls(ObjCMethod, overridden); + + // Check for overriding methods + if (isa(ObjCMethod->getDeclContext()) || + isa(ObjCMethod->getDeclContext())) + CheckConflictingOverridingMethod(ObjCMethod, overridden, + isa(overridden->getDeclContext())); + } + + bool ARCError = false; + if (getLangOpts().ObjCAutoRefCount) + ARCError = CheckARCMethodDecl(*this, ObjCMethod); + + // Infer the related result type when possible. + if (!ARCError && RTC == RTC_Compatible && + !ObjCMethod->hasRelatedResultType() && + LangOpts.ObjCInferRelatedResultType) { + bool InferRelatedResultType = false; + switch (ObjCMethod->getMethodFamily()) { + case OMF_None: + case OMF_copy: + case OMF_dealloc: + case OMF_finalize: + case OMF_mutableCopy: + case OMF_release: + case OMF_retainCount: + case OMF_performSelector: + break; + + case OMF_alloc: + case OMF_new: + InferRelatedResultType = ObjCMethod->isClassMethod(); + break; + + case OMF_init: + case OMF_autorelease: + case OMF_retain: + case OMF_self: + InferRelatedResultType = ObjCMethod->isInstanceMethod(); + break; + } + + if (InferRelatedResultType) + ObjCMethod->SetRelatedResultType(); + } + + return ObjCMethod; +} + +bool Sema::CheckObjCDeclScope(Decl *D) { + // Following is also an error. But it is caused by a missing @end + // and diagnostic is issued elsewhere. + if (isa(CurContext->getRedeclContext())) + return false; + + // If we switched context to translation unit while we are still lexically in + // an objc container, it means the parser missed emitting an error. + if (isa(getCurLexicalContext()->getRedeclContext())) + return false; + + Diag(D->getLocation(), diag::err_objc_decls_may_only_appear_in_global_scope); + D->setInvalidDecl(); + + return true; +} + +/// Called whenever @defs(ClassName) is encountered in the source. Inserts the +/// instance variables of ClassName into Decls. +void Sema::ActOnDefs(Scope *S, Decl *TagD, SourceLocation DeclStart, + IdentifierInfo *ClassName, + SmallVectorImpl &Decls) { + // Check that ClassName is a valid class + ObjCInterfaceDecl *Class = getObjCInterfaceDecl(ClassName, DeclStart); + if (!Class) { + Diag(DeclStart, diag::err_undef_interface) << ClassName; + return; + } + if (LangOpts.ObjCNonFragileABI) { + Diag(DeclStart, diag::err_atdef_nonfragile_interface); + return; + } + + // Collect the instance variables + SmallVector Ivars; + Context.DeepCollectObjCIvars(Class, true, Ivars); + // For each ivar, create a fresh ObjCAtDefsFieldDecl. + for (unsigned i = 0; i < Ivars.size(); i++) { + const FieldDecl* ID = cast(Ivars[i]); + RecordDecl *Record = dyn_cast(TagD); + Decl *FD = ObjCAtDefsFieldDecl::Create(Context, Record, + /*FIXME: StartL=*/ID->getLocation(), + ID->getLocation(), + ID->getIdentifier(), ID->getType(), + ID->getBitWidth()); + Decls.push_back(FD); + } + + // Introduce all of these fields into the appropriate scope. + for (SmallVectorImpl::iterator D = Decls.begin(); + D != Decls.end(); ++D) { + FieldDecl *FD = cast(*D); + if (getLangOpts().CPlusPlus) + PushOnScopeChains(cast(FD), S); + else if (RecordDecl *Record = dyn_cast(TagD)) + Record->addDecl(FD); + } +} + +/// \brief Build a type-check a new Objective-C exception variable declaration. +VarDecl *Sema::BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType T, + SourceLocation StartLoc, + SourceLocation IdLoc, + IdentifierInfo *Id, + bool Invalid) { + // ISO/IEC TR 18037 S6.7.3: "The type of an object with automatic storage + // duration shall not be qualified by an address-space qualifier." + // Since all parameters have automatic store duration, they can not have + // an address space. + if (T.getAddressSpace() != 0) { + Diag(IdLoc, diag::err_arg_with_address_space); + Invalid = true; + } + + // An @catch parameter must be an unqualified object pointer type; + // FIXME: Recover from "NSObject foo" by inserting the * in "NSObject *foo"? + if (Invalid) { + // Don't do any further checking. + } else if (T->isDependentType()) { + // Okay: we don't know what this type will instantiate to. + } else if (!T->isObjCObjectPointerType()) { + Invalid = true; + Diag(IdLoc ,diag::err_catch_param_not_objc_type); + } else if (T->isObjCQualifiedIdType()) { + Invalid = true; + Diag(IdLoc, diag::err_illegal_qualifiers_on_catch_parm); + } + + VarDecl *New = VarDecl::Create(Context, CurContext, StartLoc, IdLoc, Id, + T, TInfo, SC_None, SC_None); + New->setExceptionVariable(true); + + // In ARC, infer 'retaining' for variables of retainable type. + if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(New)) + Invalid = true; + + if (Invalid) + New->setInvalidDecl(); + return New; +} + +Decl *Sema::ActOnObjCExceptionDecl(Scope *S, Declarator &D) { + const DeclSpec &DS = D.getDeclSpec(); + + // We allow the "register" storage class on exception variables because + // GCC did, but we drop it completely. Any other storage class is an error. + if (DS.getStorageClassSpec() == DeclSpec::SCS_register) { + Diag(DS.getStorageClassSpecLoc(), diag::warn_register_objc_catch_parm) + << FixItHint::CreateRemoval(SourceRange(DS.getStorageClassSpecLoc())); + } else if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified) { + Diag(DS.getStorageClassSpecLoc(), diag::err_storage_spec_on_catch_parm) + << DS.getStorageClassSpec(); + } + if (D.getDeclSpec().isThreadSpecified()) + Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread); + D.getMutableDeclSpec().ClearStorageClassSpecs(); + + DiagnoseFunctionSpecifiers(D); + + // Check that there are no default arguments inside the type of this + // exception object (C++ only). + if (getLangOpts().CPlusPlus) + CheckExtraCXXDefaultArguments(D); + + TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); + QualType ExceptionType = TInfo->getType(); + + VarDecl *New = BuildObjCExceptionDecl(TInfo, ExceptionType, + D.getSourceRange().getBegin(), + D.getIdentifierLoc(), + D.getIdentifier(), + D.isInvalidType()); + + // Parameter declarators cannot be qualified (C++ [dcl.meaning]p1). + if (D.getCXXScopeSpec().isSet()) { + Diag(D.getIdentifierLoc(), diag::err_qualified_objc_catch_parm) + << D.getCXXScopeSpec().getRange(); + New->setInvalidDecl(); + } + + // Add the parameter declaration into this scope. + S->AddDecl(New); + if (D.getIdentifier()) + IdResolver.AddDecl(New); + + ProcessDeclAttributes(S, New, D); + + if (New->hasAttr()) + Diag(New->getLocation(), diag::err_block_on_nonlocal); + return New; +} + +/// CollectIvarsToConstructOrDestruct - Collect those ivars which require +/// initialization. +void Sema::CollectIvarsToConstructOrDestruct(ObjCInterfaceDecl *OI, + SmallVectorImpl &Ivars) { + for (ObjCIvarDecl *Iv = OI->all_declared_ivar_begin(); Iv; + Iv= Iv->getNextIvar()) { + QualType QT = Context.getBaseElementType(Iv->getType()); + if (QT->isRecordType()) + Ivars.push_back(Iv); + } +} + +void Sema::DiagnoseUseOfUnimplementedSelectors() { + // Load referenced selectors from the external source. + if (ExternalSource) { + SmallVector, 4> Sels; + ExternalSource->ReadReferencedSelectors(Sels); + for (unsigned I = 0, N = Sels.size(); I != N; ++I) + ReferencedSelectors[Sels[I].first] = Sels[I].second; + } + + // Warning will be issued only when selector table is + // generated (which means there is at lease one implementation + // in the TU). This is to match gcc's behavior. + if (ReferencedSelectors.empty() || + !Context.AnyObjCImplementation()) + 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/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp new file mode 100644 index 0000000..14b2434 --- /dev/null +++ b/clang/lib/Sema/SemaExceptionSpec.cpp @@ -0,0 +1,1086 @@ +//===--- SemaExceptionSpec.cpp - C++ Exception Specifications ---*- 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 Sema routines for C++ exception specification testing. +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/SemaInternal.h" +#include "clang/AST/CXXInheritance.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/TypeLoc.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/SourceManager.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallString.h" + +namespace clang { + +static const FunctionProtoType *GetUnderlyingFunction(QualType T) +{ + if (const PointerType *PtrTy = T->getAs()) + T = PtrTy->getPointeeType(); + else if (const ReferenceType *RefTy = T->getAs()) + T = RefTy->getPointeeType(); + else if (const MemberPointerType *MPTy = T->getAs()) + T = MPTy->getPointeeType(); + return T->getAs(); +} + +/// CheckSpecifiedExceptionType - Check if the given type is valid in an +/// exception specification. Incomplete types, or pointers to incomplete types +/// other than void are not allowed. +bool Sema::CheckSpecifiedExceptionType(QualType T, const SourceRange &Range) { + + // This check (and the similar one below) deals with issue 437, that changes + // C++ 9.2p2 this way: + // Within the class member-specification, the class is regarded as complete + // within function bodies, default arguments, exception-specifications, and + // constructor ctor-initializers (including such things in nested classes). + if (T->isRecordType() && T->getAs()->isBeingDefined()) + return false; + + // C++ 15.4p2: A type denoted in an exception-specification shall not denote + // an incomplete type. + if (RequireCompleteType(Range.getBegin(), T, + PDiag(diag::err_incomplete_in_exception_spec) << /*direct*/0 << Range)) + return true; + + // C++ 15.4p2: A type denoted in an exception-specification shall not denote + // an incomplete type a pointer or reference to an incomplete type, other + // than (cv) void*. + int kind; + if (const PointerType* IT = T->getAs()) { + T = IT->getPointeeType(); + kind = 1; + } else if (const ReferenceType* IT = T->getAs()) { + T = IT->getPointeeType(); + kind = 2; + } else + return false; + + // Again as before + if (T->isRecordType() && T->getAs()->isBeingDefined()) + return false; + + if (!T->isVoidType() && RequireCompleteType(Range.getBegin(), T, + PDiag(diag::err_incomplete_in_exception_spec) << kind << Range)) + return true; + + return false; +} + +/// CheckDistantExceptionSpec - Check if the given type is a pointer or pointer +/// to member to a function with an exception specification. This means that +/// it is invalid to add another level of indirection. +bool Sema::CheckDistantExceptionSpec(QualType T) { + if (const PointerType *PT = T->getAs()) + T = PT->getPointeeType(); + else if (const MemberPointerType *PT = T->getAs()) + T = PT->getPointeeType(); + else + return false; + + const FunctionProtoType *FnT = T->getAs(); + if (!FnT) + return false; + + return FnT->hasExceptionSpec(); +} + +const FunctionProtoType * +Sema::ResolveExceptionSpec(SourceLocation Loc, const FunctionProtoType *FPT) { + // FIXME: If FD is a special member, we should delay computing its exception + // specification until this point. + if (FPT->getExceptionSpecType() != EST_Uninstantiated) + return FPT; + + FunctionDecl *SourceDecl = FPT->getExceptionSpecDecl(); + const FunctionProtoType *SourceFPT = + SourceDecl->getType()->castAs(); + + if (SourceFPT->getExceptionSpecType() != EST_Uninstantiated) + return SourceFPT; + + // Instantiate the exception specification now. + InstantiateExceptionSpec(Loc, SourceDecl); + + return SourceDecl->getType()->castAs(); +} + +bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { + OverloadedOperatorKind OO = New->getDeclName().getCXXOverloadedOperator(); + bool IsOperatorNew = OO == OO_New || OO == OO_Array_New; + bool MissingExceptionSpecification = false; + bool MissingEmptyExceptionSpecification = false; + unsigned DiagID = diag::err_mismatched_exception_spec; + if (getLangOpts().MicrosoftExt) + DiagID = diag::warn_mismatched_exception_spec; + + if (!CheckEquivalentExceptionSpec(PDiag(DiagID), + PDiag(diag::note_previous_declaration), + Old->getType()->getAs(), + Old->getLocation(), + New->getType()->getAs(), + New->getLocation(), + &MissingExceptionSpecification, + &MissingEmptyExceptionSpecification, + /*AllowNoexceptAllMatchWithNoSpec=*/true, + IsOperatorNew)) + return false; + + // The failure was something other than an empty exception + // specification; return an error. + if (!MissingExceptionSpecification && !MissingEmptyExceptionSpecification) + return true; + + const FunctionProtoType *NewProto + = New->getType()->getAs(); + + // The new function declaration is only missing an empty exception + // specification "throw()". If the throw() specification came from a + // function in a system header that has C linkage, just add an empty + // exception specification to the "new" declaration. This is an + // egregious workaround for glibc, which adds throw() specifications + // to many libc functions as an optimization. Unfortunately, that + // optimization isn't permitted by the C++ standard, so we're forced + // to work around it here. + if (MissingEmptyExceptionSpecification && NewProto && + (Old->getLocation().isInvalid() || + Context.getSourceManager().isInSystemHeader(Old->getLocation())) && + Old->isExternC()) { + FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo(); + EPI.ExceptionSpecType = EST_DynamicNone; + QualType NewType = Context.getFunctionType(NewProto->getResultType(), + NewProto->arg_type_begin(), + NewProto->getNumArgs(), + EPI); + New->setType(NewType); + return false; + } + + if (MissingExceptionSpecification && NewProto) { + const FunctionProtoType *OldProto + = Old->getType()->getAs(); + + FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo(); + EPI.ExceptionSpecType = OldProto->getExceptionSpecType(); + if (EPI.ExceptionSpecType == EST_Dynamic) { + EPI.NumExceptions = OldProto->getNumExceptions(); + EPI.Exceptions = OldProto->exception_begin(); + } else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) { + // FIXME: We can't just take the expression from the old prototype. It + // likely contains references to the old prototype's parameters. + } + + // Update the type of the function with the appropriate exception + // specification. + QualType NewType = Context.getFunctionType(NewProto->getResultType(), + NewProto->arg_type_begin(), + NewProto->getNumArgs(), + EPI); + New->setType(NewType); + + // If exceptions are disabled, suppress the warning about missing + // exception specifications for new and delete operators. + if (!getLangOpts().CXXExceptions) { + switch (New->getDeclName().getCXXOverloadedOperator()) { + case OO_New: + case OO_Array_New: + case OO_Delete: + case OO_Array_Delete: + if (New->getDeclContext()->isTranslationUnit()) + return false; + break; + + default: + break; + } + } + + // Warn about the lack of exception specification. + SmallString<128> ExceptionSpecString; + llvm::raw_svector_ostream OS(ExceptionSpecString); + switch (OldProto->getExceptionSpecType()) { + case EST_DynamicNone: + OS << "throw()"; + break; + + case EST_Dynamic: { + OS << "throw("; + bool OnFirstException = true; + for (FunctionProtoType::exception_iterator E = OldProto->exception_begin(), + EEnd = OldProto->exception_end(); + E != EEnd; + ++E) { + if (OnFirstException) + OnFirstException = false; + else + OS << ", "; + + OS << E->getAsString(getPrintingPolicy()); + } + OS << ")"; + break; + } + + case EST_BasicNoexcept: + OS << "noexcept"; + break; + + case EST_ComputedNoexcept: + OS << "noexcept("; + OldProto->getNoexceptExpr()->printPretty(OS, Context, 0, + getPrintingPolicy()); + OS << ")"; + break; + + default: + llvm_unreachable("This spec type is compatible with none."); + } + OS.flush(); + + SourceLocation FixItLoc; + if (TypeSourceInfo *TSInfo = New->getTypeSourceInfo()) { + TypeLoc TL = TSInfo->getTypeLoc().IgnoreParens(); + if (const FunctionTypeLoc *FTLoc = dyn_cast(&TL)) + FixItLoc = PP.getLocForEndOfToken(FTLoc->getLocalRangeEnd()); + } + + if (FixItLoc.isInvalid()) + Diag(New->getLocation(), diag::warn_missing_exception_specification) + << New << OS.str(); + else { + // FIXME: This will get more complicated with C++0x + // late-specified return types. + Diag(New->getLocation(), diag::warn_missing_exception_specification) + << New << OS.str() + << FixItHint::CreateInsertion(FixItLoc, " " + OS.str().str()); + } + + if (!Old->getLocation().isInvalid()) + Diag(Old->getLocation(), diag::note_previous_declaration); + + return false; + } + + Diag(New->getLocation(), DiagID); + Diag(Old->getLocation(), diag::note_previous_declaration); + return true; +} + +/// CheckEquivalentExceptionSpec - Check if the two types have equivalent +/// exception specifications. Exception specifications are equivalent if +/// they allow exactly the same set of exception types. It does not matter how +/// that is achieved. See C++ [except.spec]p2. +bool Sema::CheckEquivalentExceptionSpec( + const FunctionProtoType *Old, SourceLocation OldLoc, + const FunctionProtoType *New, SourceLocation NewLoc) { + unsigned DiagID = diag::err_mismatched_exception_spec; + if (getLangOpts().MicrosoftExt) + DiagID = diag::warn_mismatched_exception_spec; + return CheckEquivalentExceptionSpec( + PDiag(DiagID), + PDiag(diag::note_previous_declaration), + Old, OldLoc, New, NewLoc); +} + +/// CheckEquivalentExceptionSpec - Check if the two types have compatible +/// exception specifications. See C++ [except.spec]p3. +bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID, + const PartialDiagnostic & NoteID, + const FunctionProtoType *Old, + SourceLocation OldLoc, + const FunctionProtoType *New, + SourceLocation NewLoc, + bool *MissingExceptionSpecification, + bool*MissingEmptyExceptionSpecification, + bool AllowNoexceptAllMatchWithNoSpec, + bool IsOperatorNew) { + // Just completely ignore this under -fno-exceptions. + if (!getLangOpts().CXXExceptions) + return false; + + if (MissingExceptionSpecification) + *MissingExceptionSpecification = false; + + if (MissingEmptyExceptionSpecification) + *MissingEmptyExceptionSpecification = false; + + Old = ResolveExceptionSpec(NewLoc, Old); + if (!Old) + return false; + New = ResolveExceptionSpec(NewLoc, New); + if (!New) + return false; + + // C++0x [except.spec]p3: Two exception-specifications are compatible if: + // - both are non-throwing, regardless of their form, + // - both have the form noexcept(constant-expression) and the constant- + // expressions are equivalent, + // - both are dynamic-exception-specifications that have the same set of + // adjusted types. + // + // C++0x [except.spec]p12: An exception-specifcation is non-throwing if it is + // of the form throw(), noexcept, or noexcept(constant-expression) where the + // constant-expression yields true. + // + // C++0x [except.spec]p4: If any declaration of a function has an exception- + // specifier that is not a noexcept-specification allowing all exceptions, + // all declarations [...] of that function shall have a compatible + // exception-specification. + // + // That last point basically means that noexcept(false) matches no spec. + // It's considered when AllowNoexceptAllMatchWithNoSpec is true. + + ExceptionSpecificationType OldEST = Old->getExceptionSpecType(); + ExceptionSpecificationType NewEST = New->getExceptionSpecType(); + + assert(OldEST != EST_Delayed && NewEST != EST_Delayed && + OldEST != EST_Uninstantiated && NewEST != EST_Uninstantiated && + "Shouldn't see unknown exception specifications here"); + + // Shortcut the case where both have no spec. + if (OldEST == EST_None && NewEST == EST_None) + return false; + + FunctionProtoType::NoexceptResult OldNR = Old->getNoexceptSpec(Context); + FunctionProtoType::NoexceptResult NewNR = New->getNoexceptSpec(Context); + if (OldNR == FunctionProtoType::NR_BadNoexcept || + NewNR == FunctionProtoType::NR_BadNoexcept) + return false; + + // Dependent noexcept specifiers are compatible with each other, but nothing + // else. + // One noexcept is compatible with another if the argument is the same + if (OldNR == NewNR && + OldNR != FunctionProtoType::NR_NoNoexcept && + NewNR != FunctionProtoType::NR_NoNoexcept) + return false; + if (OldNR != NewNR && + OldNR != FunctionProtoType::NR_NoNoexcept && + NewNR != FunctionProtoType::NR_NoNoexcept) { + Diag(NewLoc, DiagID); + if (NoteID.getDiagID() != 0) + Diag(OldLoc, NoteID); + return true; + } + + // The MS extension throw(...) is compatible with itself. + if (OldEST == EST_MSAny && NewEST == EST_MSAny) + return false; + + // It's also compatible with no spec. + if ((OldEST == EST_None && NewEST == EST_MSAny) || + (OldEST == EST_MSAny && NewEST == EST_None)) + return false; + + // It's also compatible with noexcept(false). + if (OldEST == EST_MSAny && NewNR == FunctionProtoType::NR_Throw) + return false; + if (NewEST == EST_MSAny && OldNR == FunctionProtoType::NR_Throw) + return false; + + // As described above, noexcept(false) matches no spec only for functions. + if (AllowNoexceptAllMatchWithNoSpec) { + if (OldEST == EST_None && NewNR == FunctionProtoType::NR_Throw) + return false; + if (NewEST == EST_None && OldNR == FunctionProtoType::NR_Throw) + return false; + } + + // Any non-throwing specifications are compatible. + bool OldNonThrowing = OldNR == FunctionProtoType::NR_Nothrow || + OldEST == EST_DynamicNone; + bool NewNonThrowing = NewNR == FunctionProtoType::NR_Nothrow || + NewEST == EST_DynamicNone; + if (OldNonThrowing && NewNonThrowing) + return false; + + // As a special compatibility feature, under C++0x we accept no spec and + // throw(std::bad_alloc) as equivalent for operator new and operator new[]. + // This is because the implicit declaration changed, but old code would break. + if (getLangOpts().CPlusPlus0x && IsOperatorNew) { + const FunctionProtoType *WithExceptions = 0; + if (OldEST == EST_None && NewEST == EST_Dynamic) + WithExceptions = New; + else if (OldEST == EST_Dynamic && NewEST == EST_None) + WithExceptions = Old; + if (WithExceptions && WithExceptions->getNumExceptions() == 1) { + // One has no spec, the other throw(something). If that something is + // std::bad_alloc, all conditions are met. + QualType Exception = *WithExceptions->exception_begin(); + if (CXXRecordDecl *ExRecord = Exception->getAsCXXRecordDecl()) { + IdentifierInfo* Name = ExRecord->getIdentifier(); + if (Name && Name->getName() == "bad_alloc") { + // It's called bad_alloc, but is it in std? + DeclContext* DC = ExRecord->getDeclContext(); + DC = DC->getEnclosingNamespaceContext(); + if (NamespaceDecl* NS = dyn_cast(DC)) { + IdentifierInfo* NSName = NS->getIdentifier(); + DC = DC->getParent(); + if (NSName && NSName->getName() == "std" && + DC->getEnclosingNamespaceContext()->isTranslationUnit()) { + return false; + } + } + } + } + } + } + + // At this point, the only remaining valid case is two matching dynamic + // specifications. We return here unless both specifications are dynamic. + if (OldEST != EST_Dynamic || NewEST != EST_Dynamic) { + if (MissingExceptionSpecification && Old->hasExceptionSpec() && + !New->hasExceptionSpec()) { + // The old type has an exception specification of some sort, but + // the new type does not. + *MissingExceptionSpecification = true; + + if (MissingEmptyExceptionSpecification && OldNonThrowing) { + // The old type has a throw() or noexcept(true) exception specification + // and the new type has no exception specification, and the caller asked + // to handle this itself. + *MissingEmptyExceptionSpecification = true; + } + + return true; + } + + Diag(NewLoc, DiagID); + if (NoteID.getDiagID() != 0) + Diag(OldLoc, NoteID); + return true; + } + + assert(OldEST == EST_Dynamic && NewEST == EST_Dynamic && + "Exception compatibility logic error: non-dynamic spec slipped through."); + + bool Success = true; + // Both have a dynamic exception spec. Collect the first set, then compare + // to the second. + llvm::SmallPtrSet OldTypes, NewTypes; + for (FunctionProtoType::exception_iterator I = Old->exception_begin(), + E = Old->exception_end(); I != E; ++I) + OldTypes.insert(Context.getCanonicalType(*I).getUnqualifiedType()); + + for (FunctionProtoType::exception_iterator I = New->exception_begin(), + E = New->exception_end(); I != E && Success; ++I) { + CanQualType TypePtr = Context.getCanonicalType(*I).getUnqualifiedType(); + if(OldTypes.count(TypePtr)) + NewTypes.insert(TypePtr); + else + Success = false; + } + + Success = Success && OldTypes.size() == NewTypes.size(); + + if (Success) { + return false; + } + Diag(NewLoc, DiagID); + if (NoteID.getDiagID() != 0) + Diag(OldLoc, NoteID); + return true; +} + +/// CheckExceptionSpecSubset - Check whether the second function type's +/// exception specification is a subset (or equivalent) of the first function +/// type. This is used by override and pointer assignment checks. +bool Sema::CheckExceptionSpecSubset( + const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID, + const FunctionProtoType *Superset, SourceLocation SuperLoc, + const FunctionProtoType *Subset, SourceLocation SubLoc) { + + // Just auto-succeed under -fno-exceptions. + if (!getLangOpts().CXXExceptions) + return false; + + // FIXME: As usual, we could be more specific in our error messages, but + // that better waits until we've got types with source locations. + + if (!SubLoc.isValid()) + SubLoc = SuperLoc; + + // Resolve the exception specifications, if needed. + Superset = ResolveExceptionSpec(SuperLoc, Superset); + if (!Superset) + return false; + Subset = ResolveExceptionSpec(SubLoc, Subset); + if (!Subset) + return false; + + ExceptionSpecificationType SuperEST = Superset->getExceptionSpecType(); + + // If superset contains everything, we're done. + if (SuperEST == EST_None || SuperEST == EST_MSAny) + return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc); + + // If there are dependent noexcept specs, assume everything is fine. Unlike + // with the equivalency check, this is safe in this case, because we don't + // want to merge declarations. Checks after instantiation will catch any + // omissions we make here. + // We also shortcut checking if a noexcept expression was bad. + + FunctionProtoType::NoexceptResult SuperNR =Superset->getNoexceptSpec(Context); + if (SuperNR == FunctionProtoType::NR_BadNoexcept || + SuperNR == FunctionProtoType::NR_Dependent) + return false; + + // Another case of the superset containing everything. + if (SuperNR == FunctionProtoType::NR_Throw) + return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc); + + ExceptionSpecificationType SubEST = Subset->getExceptionSpecType(); + + assert(SuperEST != EST_Delayed && SubEST != EST_Delayed && + SuperEST != EST_Uninstantiated && SubEST != EST_Uninstantiated && + "Shouldn't see unknown exception specifications here"); + + // It does not. If the subset contains everything, we've failed. + if (SubEST == EST_None || SubEST == EST_MSAny) { + Diag(SubLoc, DiagID); + if (NoteID.getDiagID() != 0) + Diag(SuperLoc, NoteID); + return true; + } + + FunctionProtoType::NoexceptResult SubNR = Subset->getNoexceptSpec(Context); + if (SubNR == FunctionProtoType::NR_BadNoexcept || + SubNR == FunctionProtoType::NR_Dependent) + return false; + + // Another case of the subset containing everything. + if (SubNR == FunctionProtoType::NR_Throw) { + Diag(SubLoc, DiagID); + if (NoteID.getDiagID() != 0) + Diag(SuperLoc, NoteID); + return true; + } + + // If the subset contains nothing, we're done. + if (SubEST == EST_DynamicNone || SubNR == FunctionProtoType::NR_Nothrow) + return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc); + + // Otherwise, if the superset contains nothing, we've failed. + if (SuperEST == EST_DynamicNone || SuperNR == FunctionProtoType::NR_Nothrow) { + Diag(SubLoc, DiagID); + if (NoteID.getDiagID() != 0) + Diag(SuperLoc, NoteID); + return true; + } + + assert(SuperEST == EST_Dynamic && SubEST == EST_Dynamic && + "Exception spec subset: non-dynamic case slipped through."); + + // Neither contains everything or nothing. Do a proper comparison. + for (FunctionProtoType::exception_iterator SubI = Subset->exception_begin(), + SubE = Subset->exception_end(); SubI != SubE; ++SubI) { + // Take one type from the subset. + QualType CanonicalSubT = Context.getCanonicalType(*SubI); + // Unwrap pointers and references so that we can do checks within a class + // hierarchy. Don't unwrap member pointers; they don't have hierarchy + // conversions on the pointee. + bool SubIsPointer = false; + if (const ReferenceType *RefTy = CanonicalSubT->getAs()) + CanonicalSubT = RefTy->getPointeeType(); + if (const PointerType *PtrTy = CanonicalSubT->getAs()) { + CanonicalSubT = PtrTy->getPointeeType(); + SubIsPointer = true; + } + bool SubIsClass = CanonicalSubT->isRecordType(); + CanonicalSubT = CanonicalSubT.getLocalUnqualifiedType(); + + CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, + /*DetectVirtual=*/false); + + bool Contained = false; + // Make sure it's in the superset. + for (FunctionProtoType::exception_iterator SuperI = + Superset->exception_begin(), SuperE = Superset->exception_end(); + SuperI != SuperE; ++SuperI) { + QualType CanonicalSuperT = Context.getCanonicalType(*SuperI); + // SubT must be SuperT or derived from it, or pointer or reference to + // such types. + if (const ReferenceType *RefTy = CanonicalSuperT->getAs()) + CanonicalSuperT = RefTy->getPointeeType(); + if (SubIsPointer) { + if (const PointerType *PtrTy = CanonicalSuperT->getAs()) + CanonicalSuperT = PtrTy->getPointeeType(); + else { + continue; + } + } + CanonicalSuperT = CanonicalSuperT.getLocalUnqualifiedType(); + // If the types are the same, move on to the next type in the subset. + if (CanonicalSubT == CanonicalSuperT) { + Contained = true; + break; + } + + // Otherwise we need to check the inheritance. + if (!SubIsClass || !CanonicalSuperT->isRecordType()) + continue; + + Paths.clear(); + if (!IsDerivedFrom(CanonicalSubT, CanonicalSuperT, Paths)) + continue; + + if (Paths.isAmbiguous(Context.getCanonicalType(CanonicalSuperT))) + continue; + + // Do this check from a context without privileges. + switch (CheckBaseClassAccess(SourceLocation(), + CanonicalSuperT, CanonicalSubT, + Paths.front(), + /*Diagnostic*/ 0, + /*ForceCheck*/ true, + /*ForceUnprivileged*/ true)) { + case AR_accessible: break; + case AR_inaccessible: continue; + case AR_dependent: + llvm_unreachable("access check dependent for unprivileged context"); + case AR_delayed: + llvm_unreachable("access check delayed in non-declaration"); + } + + Contained = true; + break; + } + if (!Contained) { + Diag(SubLoc, DiagID); + if (NoteID.getDiagID() != 0) + Diag(SuperLoc, NoteID); + return true; + } + } + // We've run half the gauntlet. + return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc); +} + +static bool CheckSpecForTypesEquivalent(Sema &S, + const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID, + QualType Target, SourceLocation TargetLoc, + QualType Source, SourceLocation SourceLoc) +{ + const FunctionProtoType *TFunc = GetUnderlyingFunction(Target); + if (!TFunc) + return false; + const FunctionProtoType *SFunc = GetUnderlyingFunction(Source); + if (!SFunc) + return false; + + return S.CheckEquivalentExceptionSpec(DiagID, NoteID, TFunc, TargetLoc, + SFunc, SourceLoc); +} + +/// CheckParamExceptionSpec - Check if the parameter and return types of the +/// two functions have equivalent exception specs. This is part of the +/// assignment and override compatibility check. We do not check the parameters +/// of parameter function pointers recursively, as no sane programmer would +/// even be able to write such a function type. +bool Sema::CheckParamExceptionSpec(const PartialDiagnostic & NoteID, + const FunctionProtoType *Target, SourceLocation TargetLoc, + const FunctionProtoType *Source, SourceLocation SourceLoc) +{ + if (CheckSpecForTypesEquivalent(*this, + PDiag(diag::err_deep_exception_specs_differ) << 0, + PDiag(), + Target->getResultType(), TargetLoc, + Source->getResultType(), SourceLoc)) + return true; + + // We shouldn't even be testing this unless the arguments are otherwise + // compatible. + assert(Target->getNumArgs() == Source->getNumArgs() && + "Functions have different argument counts."); + for (unsigned i = 0, E = Target->getNumArgs(); i != E; ++i) { + if (CheckSpecForTypesEquivalent(*this, + PDiag(diag::err_deep_exception_specs_differ) << 1, + PDiag(), + Target->getArgType(i), TargetLoc, + Source->getArgType(i), SourceLoc)) + return true; + } + return false; +} + +bool Sema::CheckExceptionSpecCompatibility(Expr *From, QualType ToType) +{ + // First we check for applicability. + // Target type must be a function, function pointer or function reference. + const FunctionProtoType *ToFunc = GetUnderlyingFunction(ToType); + if (!ToFunc) + return false; + + // SourceType must be a function or function pointer. + const FunctionProtoType *FromFunc = GetUnderlyingFunction(From->getType()); + if (!FromFunc) + return false; + + // Now we've got the correct types on both sides, check their compatibility. + // This means that the source of the conversion can only throw a subset of + // the exceptions of the target, and any exception specs on arguments or + // return types must be equivalent. + return CheckExceptionSpecSubset(PDiag(diag::err_incompatible_exception_specs), + PDiag(), ToFunc, + From->getSourceRange().getBegin(), + FromFunc, SourceLocation()); +} + +bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New, + const CXXMethodDecl *Old) { + if (getLangOpts().CPlusPlus0x && isa(New)) { + // Don't check uninstantiated template destructors at all. We can only + // synthesize correct specs after the template is instantiated. + if (New->getParent()->isDependentType()) + return false; + if (New->getParent()->isBeingDefined()) { + // The destructor might be updated once the definition is finished. So + // remember it and check later. + DelayedDestructorExceptionSpecChecks.push_back(std::make_pair( + cast(New), cast(Old))); + return false; + } + } + unsigned DiagID = diag::err_override_exception_spec; + if (getLangOpts().MicrosoftExt) + DiagID = diag::warn_override_exception_spec; + return CheckExceptionSpecSubset(PDiag(DiagID), + PDiag(diag::note_overridden_virtual_function), + Old->getType()->getAs(), + Old->getLocation(), + New->getType()->getAs(), + New->getLocation()); +} + +static CanThrowResult canSubExprsThrow(Sema &S, const Expr *CE) { + Expr *E = const_cast(CE); + CanThrowResult R = CT_Cannot; + for (Expr::child_range I = E->children(); I && R != CT_Can; ++I) + R = mergeCanThrow(R, S.canThrow(cast(*I))); + return R; +} + +static CanThrowResult canCalleeThrow(Sema &S, const Expr *E, + const Decl *D, + bool NullThrows = true) { + if (!D) + return NullThrows ? CT_Can : CT_Cannot; + + // See if we can get a function type from the decl somehow. + const ValueDecl *VD = dyn_cast(D); + if (!VD) // If we have no clue what we're calling, assume the worst. + return CT_Can; + + // As an extension, we assume that __attribute__((nothrow)) functions don't + // throw. + if (isa(D) && D->hasAttr()) + return CT_Cannot; + + QualType T = VD->getType(); + const FunctionProtoType *FT; + if ((FT = T->getAs())) { + } else if (const PointerType *PT = T->getAs()) + FT = PT->getPointeeType()->getAs(); + else if (const ReferenceType *RT = T->getAs()) + FT = RT->getPointeeType()->getAs(); + else if (const MemberPointerType *MT = T->getAs()) + FT = MT->getPointeeType()->getAs(); + else if (const BlockPointerType *BT = T->getAs()) + FT = BT->getPointeeType()->getAs(); + + if (!FT) + return CT_Can; + + FT = S.ResolveExceptionSpec(E->getLocStart(), FT); + if (!FT) + return CT_Can; + + if (FT->getExceptionSpecType() == EST_Delayed) { + // FIXME: Try to resolve a delayed exception spec in ResolveExceptionSpec. + assert(isa(D) && + "only constructor exception specs can be unknown"); + S.Diag(E->getLocStart(), diag::err_exception_spec_unknown) + << E->getSourceRange(); + return CT_Can; + } + + return FT->isNothrow(S.Context) ? CT_Cannot : CT_Can; +} + +static CanThrowResult canDynamicCastThrow(const CXXDynamicCastExpr *DC) { + if (DC->isTypeDependent()) + return CT_Dependent; + + if (!DC->getTypeAsWritten()->isReferenceType()) + return CT_Cannot; + + if (DC->getSubExpr()->isTypeDependent()) + return CT_Dependent; + + return DC->getCastKind() == clang::CK_Dynamic? CT_Can : CT_Cannot; +} + +static CanThrowResult canTypeidThrow(Sema &S, const CXXTypeidExpr *DC) { + if (DC->isTypeOperand()) + return CT_Cannot; + + Expr *Op = DC->getExprOperand(); + if (Op->isTypeDependent()) + return CT_Dependent; + + const RecordType *RT = Op->getType()->getAs(); + if (!RT) + return CT_Cannot; + + if (!cast(RT->getDecl())->isPolymorphic()) + return CT_Cannot; + + if (Op->Classify(S.Context).isPRValue()) + return CT_Cannot; + + return CT_Can; +} + +CanThrowResult Sema::canThrow(const Expr *E) { + // C++ [expr.unary.noexcept]p3: + // [Can throw] if in a potentially-evaluated context the expression would + // contain: + switch (E->getStmtClass()) { + case Expr::CXXThrowExprClass: + // - a potentially evaluated throw-expression + return CT_Can; + + case Expr::CXXDynamicCastExprClass: { + // - a potentially evaluated dynamic_cast expression dynamic_cast(v), + // where T is a reference type, that requires a run-time check + CanThrowResult CT = canDynamicCastThrow(cast(E)); + if (CT == CT_Can) + return CT; + return mergeCanThrow(CT, canSubExprsThrow(*this, E)); + } + + case Expr::CXXTypeidExprClass: + // - a potentially evaluated typeid expression applied to a glvalue + // expression whose type is a polymorphic class type + return canTypeidThrow(*this, cast(E)); + + // - a potentially evaluated call to a function, member function, function + // pointer, or member function pointer that does not have a non-throwing + // exception-specification + case Expr::CallExprClass: + case Expr::CXXMemberCallExprClass: + case Expr::CXXOperatorCallExprClass: + case Expr::UserDefinedLiteralClass: { + const CallExpr *CE = cast(E); + CanThrowResult CT; + if (E->isTypeDependent()) + CT = CT_Dependent; + else if (isa(CE->getCallee()->IgnoreParens())) + CT = CT_Cannot; + else + CT = canCalleeThrow(*this, E, CE->getCalleeDecl()); + if (CT == CT_Can) + return CT; + return mergeCanThrow(CT, canSubExprsThrow(*this, E)); + } + + case Expr::CXXConstructExprClass: + case Expr::CXXTemporaryObjectExprClass: { + CanThrowResult CT = canCalleeThrow(*this, E, + cast(E)->getConstructor()); + if (CT == CT_Can) + return CT; + return mergeCanThrow(CT, canSubExprsThrow(*this, E)); + } + + case Expr::LambdaExprClass: { + const LambdaExpr *Lambda = cast(E); + CanThrowResult CT = CT_Cannot; + for (LambdaExpr::capture_init_iterator Cap = Lambda->capture_init_begin(), + CapEnd = Lambda->capture_init_end(); + Cap != CapEnd; ++Cap) + CT = mergeCanThrow(CT, canThrow(*Cap)); + return CT; + } + + case Expr::CXXNewExprClass: { + CanThrowResult CT; + if (E->isTypeDependent()) + CT = CT_Dependent; + else + CT = canCalleeThrow(*this, E, cast(E)->getOperatorNew()); + if (CT == CT_Can) + return CT; + return mergeCanThrow(CT, canSubExprsThrow(*this, E)); + } + + case Expr::CXXDeleteExprClass: { + CanThrowResult CT; + QualType DTy = cast(E)->getDestroyedType(); + if (DTy.isNull() || DTy->isDependentType()) { + CT = CT_Dependent; + } else { + CT = canCalleeThrow(*this, E, + cast(E)->getOperatorDelete()); + if (const RecordType *RT = DTy->getAs()) { + const CXXRecordDecl *RD = cast(RT->getDecl()); + CT = mergeCanThrow(CT, canCalleeThrow(*this, E, RD->getDestructor())); + } + if (CT == CT_Can) + return CT; + } + return mergeCanThrow(CT, canSubExprsThrow(*this, E)); + } + + case Expr::CXXBindTemporaryExprClass: { + // The bound temporary has to be destroyed again, which might throw. + CanThrowResult CT = canCalleeThrow(*this, E, + cast(E)->getTemporary()->getDestructor()); + if (CT == CT_Can) + return CT; + return mergeCanThrow(CT, canSubExprsThrow(*this, E)); + } + + // ObjC message sends are like function calls, but never have exception + // specs. + case Expr::ObjCMessageExprClass: + case Expr::ObjCPropertyRefExprClass: + case Expr::ObjCSubscriptRefExprClass: + return CT_Can; + + // All the ObjC literals that are implemented as calls are + // potentially throwing unless we decide to close off that + // possibility. + case Expr::ObjCArrayLiteralClass: + case Expr::ObjCDictionaryLiteralClass: + case Expr::ObjCNumericLiteralClass: + return CT_Can; + + // Many other things have subexpressions, so we have to test those. + // Some are simple: + case Expr::ConditionalOperatorClass: + case Expr::CompoundLiteralExprClass: + case Expr::CXXConstCastExprClass: + case Expr::CXXDefaultArgExprClass: + case Expr::CXXReinterpretCastExprClass: + case Expr::DesignatedInitExprClass: + case Expr::ExprWithCleanupsClass: + case Expr::ExtVectorElementExprClass: + case Expr::InitListExprClass: + case Expr::MemberExprClass: + case Expr::ObjCIsaExprClass: + case Expr::ObjCIvarRefExprClass: + case Expr::ParenExprClass: + case Expr::ParenListExprClass: + case Expr::ShuffleVectorExprClass: + case Expr::VAArgExprClass: + return canSubExprsThrow(*this, E); + + // Some might be dependent for other reasons. + case Expr::ArraySubscriptExprClass: + case Expr::BinaryOperatorClass: + case Expr::CompoundAssignOperatorClass: + case Expr::CStyleCastExprClass: + case Expr::CXXStaticCastExprClass: + case Expr::CXXFunctionalCastExprClass: + case Expr::ImplicitCastExprClass: + case Expr::MaterializeTemporaryExprClass: + case Expr::UnaryOperatorClass: { + CanThrowResult CT = E->isTypeDependent() ? CT_Dependent : CT_Cannot; + return mergeCanThrow(CT, canSubExprsThrow(*this, E)); + } + + // FIXME: We should handle StmtExpr, but that opens a MASSIVE can of worms. + case Expr::StmtExprClass: + return CT_Can; + + case Expr::ChooseExprClass: + if (E->isTypeDependent() || E->isValueDependent()) + return CT_Dependent; + return canThrow(cast(E)->getChosenSubExpr(Context)); + + case Expr::GenericSelectionExprClass: + if (cast(E)->isResultDependent()) + return CT_Dependent; + return canThrow(cast(E)->getResultExpr()); + + // Some expressions are always dependent. + case Expr::CXXDependentScopeMemberExprClass: + case Expr::CXXUnresolvedConstructExprClass: + case Expr::DependentScopeDeclRefExprClass: + return CT_Dependent; + + case Expr::AsTypeExprClass: + case Expr::BinaryConditionalOperatorClass: + case Expr::BlockExprClass: + case Expr::CUDAKernelCallExprClass: + case Expr::DeclRefExprClass: + case Expr::ObjCBridgedCastExprClass: + case Expr::ObjCIndirectCopyRestoreExprClass: + case Expr::ObjCProtocolExprClass: + case Expr::ObjCSelectorExprClass: + case Expr::OffsetOfExprClass: + case Expr::PackExpansionExprClass: + case Expr::PseudoObjectExprClass: + case Expr::SubstNonTypeTemplateParmExprClass: + case Expr::SubstNonTypeTemplateParmPackExprClass: + case Expr::UnaryExprOrTypeTraitExprClass: + case Expr::UnresolvedLookupExprClass: + case Expr::UnresolvedMemberExprClass: + // FIXME: Can any of the above throw? If so, when? + return CT_Cannot; + + case Expr::AddrLabelExprClass: + case Expr::ArrayTypeTraitExprClass: + case Expr::AtomicExprClass: + case Expr::BinaryTypeTraitExprClass: + case Expr::TypeTraitExprClass: + case Expr::CXXBoolLiteralExprClass: + case Expr::CXXNoexceptExprClass: + case Expr::CXXNullPtrLiteralExprClass: + case Expr::CXXPseudoDestructorExprClass: + case Expr::CXXScalarValueInitExprClass: + case Expr::CXXThisExprClass: + case Expr::CXXUuidofExprClass: + case Expr::CharacterLiteralClass: + case Expr::ExpressionTraitExprClass: + case Expr::FloatingLiteralClass: + case Expr::GNUNullExprClass: + case Expr::ImaginaryLiteralClass: + case Expr::ImplicitValueInitExprClass: + case Expr::IntegerLiteralClass: + case Expr::ObjCEncodeExprClass: + case Expr::ObjCStringLiteralClass: + case Expr::ObjCBoolLiteralExprClass: + case Expr::OpaqueValueExprClass: + case Expr::PredefinedExprClass: + case Expr::SizeOfPackExprClass: + case Expr::StringLiteralClass: + case Expr::UnaryTypeTraitExprClass: + // These expressions can never throw. + return CT_Cannot; + +#define STMT(CLASS, PARENT) case Expr::CLASS##Class: +#define STMT_RANGE(Base, First, Last) +#define LAST_STMT_RANGE(BASE, FIRST, LAST) +#define EXPR(CLASS, PARENT) +#define ABSTRACT_STMT(STMT) +#include "clang/AST/StmtNodes.inc" + case Expr::NoStmtClass: + llvm_unreachable("Invalid class for expression"); + } + llvm_unreachable("Bogus StmtClass"); +} + +} // end namespace clang diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp new file mode 100644 index 0000000..d2e0e6b --- /dev/null +++ b/clang/lib/Sema/SemaExpr.cpp @@ -0,0 +1,11280 @@ +//===--- SemaExpr.cpp - Semantic Analysis for Expressions -----------------===// +// +// 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 expressions. +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/DelayedDiagnostic.h" +#include "clang/Sema/Initialization.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/AnalysisBasedWarnings.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/ASTMutationListener.h" +#include "clang/AST/CXXInheritance.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/EvaluatedExprVisitor.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprObjC.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/TypeLoc.h" +#include "clang/Basic/PartialDiagnostic.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Basic/TargetInfo.h" +#include "clang/Lex/LiteralSupport.h" +#include "clang/Lex/Preprocessor.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/SemaFixItUtils.h" +#include "clang/Sema/Template.h" +#include "TreeTransform.h" +using namespace clang; +using namespace sema; + +/// \brief Determine whether the use of this declaration is valid, without +/// emitting diagnostics. +bool Sema::CanUseDecl(NamedDecl *D) { + // See if this is an auto-typed variable whose initializer we are parsing. + if (ParsingInitForAutoVars.count(D)) + return false; + + // See if this is a deleted function. + if (FunctionDecl *FD = dyn_cast(D)) { + if (FD->isDeleted()) + return false; + } + + // See if this function is unavailable. + if (D->getAvailability() == AR_Unavailable && + cast(CurContext)->getAvailability() != AR_Unavailable) + return false; + + return true; +} + +static AvailabilityResult DiagnoseAvailabilityOfDecl(Sema &S, + NamedDecl *D, SourceLocation Loc, + const ObjCInterfaceDecl *UnknownObjCClass) { + // See if this declaration is unavailable or deprecated. + std::string Message; + AvailabilityResult Result = D->getAvailability(&Message); + if (const EnumConstantDecl *ECD = dyn_cast(D)) + if (Result == AR_Available) { + const DeclContext *DC = ECD->getDeclContext(); + if (const EnumDecl *TheEnumDecl = dyn_cast(DC)) + Result = TheEnumDecl->getAvailability(&Message); + } + + switch (Result) { + case AR_Available: + case AR_NotYetIntroduced: + break; + + case AR_Deprecated: + S.EmitDeprecationWarning(D, Message, Loc, UnknownObjCClass); + break; + + case AR_Unavailable: + if (S.getCurContextAvailability() != AR_Unavailable) { + if (Message.empty()) { + if (!UnknownObjCClass) + S.Diag(Loc, diag::err_unavailable) << D->getDeclName(); + else + S.Diag(Loc, diag::warn_unavailable_fwdclass_message) + << D->getDeclName(); + } + else + S.Diag(Loc, diag::err_unavailable_message) + << D->getDeclName() << Message; + S.Diag(D->getLocation(), diag::note_unavailable_here) + << isa(D) << false; + } + break; + } + return Result; +} + +/// \brief Emit a note explaining that this function is deleted or unavailable. +void Sema::NoteDeletedFunction(FunctionDecl *Decl) { + CXXMethodDecl *Method = dyn_cast(Decl); + + if (Method && Method->isDeleted() && !Method->isDeletedAsWritten()) { + // If the method was explicitly defaulted, point at that declaration. + if (!Method->isImplicit()) + Diag(Decl->getLocation(), diag::note_implicitly_deleted); + + // Try to diagnose why this special member function was implicitly + // deleted. This might fail, if that reason no longer applies. + CXXSpecialMember CSM = getSpecialMember(Method); + if (CSM != CXXInvalid) + ShouldDeleteSpecialMember(Method, CSM, /*Diagnose=*/true); + + return; + } + + Diag(Decl->getLocation(), diag::note_unavailable_here) + << 1 << Decl->isDeleted(); +} + +/// \brief Determine whether the use of this declaration is valid, and +/// emit any corresponding diagnostics. +/// +/// This routine diagnoses various problems with referencing +/// declarations that can occur when using a declaration. For example, +/// it might warn if a deprecated or unavailable declaration is being +/// used, or produce an error (and return true) if a C++0x deleted +/// function is being used. +/// +/// \returns true if there was an error (this declaration cannot be +/// referenced), false otherwise. +/// +bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, + const ObjCInterfaceDecl *UnknownObjCClass) { + if (getLangOpts().CPlusPlus && isa(D)) { + // If there were any diagnostics suppressed by template argument deduction, + // emit them now. + llvm::DenseMap >::iterator + Pos = SuppressedDiagnostics.find(D->getCanonicalDecl()); + if (Pos != SuppressedDiagnostics.end()) { + SmallVectorImpl &Suppressed = Pos->second; + for (unsigned I = 0, N = Suppressed.size(); I != N; ++I) + Diag(Suppressed[I].first, Suppressed[I].second); + + // Clear out the list of suppressed diagnostics, so that we don't emit + // them again for this specialization. However, we don't obsolete this + // entry from the table, because we want to avoid ever emitting these + // diagnostics again. + Suppressed.clear(); + } + } + + // See if this is an auto-typed variable whose initializer we are parsing. + if (ParsingInitForAutoVars.count(D)) { + Diag(Loc, diag::err_auto_variable_cannot_appear_in_own_initializer) + << D->getDeclName(); + return true; + } + + // See if this is a deleted function. + if (FunctionDecl *FD = dyn_cast(D)) { + if (FD->isDeleted()) { + Diag(Loc, diag::err_deleted_function_use); + NoteDeletedFunction(FD); + return true; + } + } + DiagnoseAvailabilityOfDecl(*this, D, Loc, UnknownObjCClass); + + // Warn if this is used but marked unused. + if (D->hasAttr()) + Diag(Loc, diag::warn_used_but_marked_unused) << D->getDeclName(); + return false; +} + +/// \brief Retrieve the message suffix that should be added to a +/// diagnostic complaining about the given function being deleted or +/// unavailable. +std::string Sema::getDeletedOrUnavailableSuffix(const FunctionDecl *FD) { + // FIXME: C++0x implicitly-deleted special member functions could be + // detected here so that we could improve diagnostics to say, e.g., + // "base class 'A' had a deleted copy constructor". + if (FD->isDeleted()) + return std::string(); + + std::string Message; + if (FD->getAvailability(&Message)) + return ": " + Message; + + return std::string(); +} + +/// DiagnoseSentinelCalls - This routine checks whether a call or +/// message-send is to a declaration with the sentinel attribute, and +/// if so, it checks that the requirements of the sentinel are +/// satisfied. +void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc, + Expr **args, unsigned numArgs) { + const SentinelAttr *attr = D->getAttr(); + if (!attr) + return; + + // The number of formal parameters of the declaration. + unsigned numFormalParams; + + // The kind of declaration. This is also an index into a %select in + // the diagnostic. + enum CalleeType { CT_Function, CT_Method, CT_Block } calleeType; + + if (ObjCMethodDecl *MD = dyn_cast(D)) { + numFormalParams = MD->param_size(); + calleeType = CT_Method; + } else if (FunctionDecl *FD = dyn_cast(D)) { + numFormalParams = FD->param_size(); + calleeType = CT_Function; + } else if (isa(D)) { + QualType type = cast(D)->getType(); + const FunctionType *fn = 0; + if (const PointerType *ptr = type->getAs()) { + fn = ptr->getPointeeType()->getAs(); + if (!fn) return; + calleeType = CT_Function; + } else if (const BlockPointerType *ptr = type->getAs()) { + fn = ptr->getPointeeType()->castAs(); + calleeType = CT_Block; + } else { + return; + } + + if (const FunctionProtoType *proto = dyn_cast(fn)) { + numFormalParams = proto->getNumArgs(); + } else { + numFormalParams = 0; + } + } else { + return; + } + + // "nullPos" is the number of formal parameters at the end which + // effectively count as part of the variadic arguments. This is + // useful if you would prefer to not have *any* formal parameters, + // but the language forces you to have at least one. + unsigned nullPos = attr->getNullPos(); + assert((nullPos == 0 || nullPos == 1) && "invalid null position on sentinel"); + numFormalParams = (nullPos > numFormalParams ? 0 : numFormalParams - nullPos); + + // The number of arguments which should follow the sentinel. + unsigned numArgsAfterSentinel = attr->getSentinel(); + + // If there aren't enough arguments for all the formal parameters, + // the sentinel, and the args after the sentinel, complain. + if (numArgs < numFormalParams + numArgsAfterSentinel + 1) { + Diag(Loc, diag::warn_not_enough_argument) << D->getDeclName(); + Diag(D->getLocation(), diag::note_sentinel_here) << calleeType; + return; + } + + // Otherwise, find the sentinel expression. + Expr *sentinelExpr = args[numArgs - numArgsAfterSentinel - 1]; + if (!sentinelExpr) return; + if (sentinelExpr->isValueDependent()) return; + if (Context.isSentinelNullExpr(sentinelExpr)) return; + + // Pick a reasonable string to insert. Optimistically use 'nil' or + // 'NULL' if those are actually defined in the context. Only use + // 'nil' for ObjC methods, where it's much more likely that the + // variadic arguments form a list of object pointers. + SourceLocation MissingNilLoc + = PP.getLocForEndOfToken(sentinelExpr->getLocEnd()); + std::string NullValue; + if (calleeType == CT_Method && + PP.getIdentifierInfo("nil")->hasMacroDefinition()) + NullValue = "nil"; + else if (PP.getIdentifierInfo("NULL")->hasMacroDefinition()) + NullValue = "NULL"; + else + NullValue = "(void*) 0"; + + if (MissingNilLoc.isInvalid()) + Diag(Loc, diag::warn_missing_sentinel) << calleeType; + else + Diag(MissingNilLoc, diag::warn_missing_sentinel) + << calleeType + << FixItHint::CreateInsertion(MissingNilLoc, ", " + NullValue); + Diag(D->getLocation(), diag::note_sentinel_here) << calleeType; +} + +SourceRange Sema::getExprRange(Expr *E) const { + return E ? E->getSourceRange() : SourceRange(); +} + +//===----------------------------------------------------------------------===// +// Standard Promotions and Conversions +//===----------------------------------------------------------------------===// + +/// DefaultFunctionArrayConversion (C99 6.3.2.1p3, C99 6.3.2.1p4). +ExprResult Sema::DefaultFunctionArrayConversion(Expr *E) { + // Handle any placeholder expressions which made it here. + if (E->getType()->isPlaceholderType()) { + ExprResult result = CheckPlaceholderExpr(E); + if (result.isInvalid()) return ExprError(); + E = result.take(); + } + + QualType Ty = E->getType(); + assert(!Ty.isNull() && "DefaultFunctionArrayConversion - missing type"); + + if (Ty->isFunctionType()) + E = ImpCastExprToType(E, Context.getPointerType(Ty), + CK_FunctionToPointerDecay).take(); + 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 + // type 'array of type' is converted to an expression that has type 'pointer + // to type'...". In C99 this was changed to: C99 6.3.2.1p3: "an expression + // that has type 'array of type' ...". The relevant change is "an lvalue" + // (C90) to "an expression" (C99). + // + // C++ 4.2p1: + // 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". + // + if (getLangOpts().C99 || getLangOpts().CPlusPlus || E->isLValue()) + E = ImpCastExprToType(E, Context.getArrayDecayedType(Ty), + CK_ArrayToPointerDecay).take(); + } + return Owned(E); +} + +static void CheckForNullPointerDereference(Sema &S, Expr *E) { + // Check to see if we are dereferencing a null pointer. If so, + // and if not volatile-qualified, this is undefined behavior that the + // optimizer will delete, so warn about it. People sometimes try to use this + // to get a deterministic trap and are surprised by clang's behavior. This + // only handles the pattern "*null", which is a very syntactic check. + if (UnaryOperator *UO = dyn_cast(E->IgnoreParenCasts())) + if (UO->getOpcode() == UO_Deref && + UO->getSubExpr()->IgnoreParenCasts()-> + isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull) && + !UO->getType().isVolatileQualified()) { + S.DiagRuntimeBehavior(UO->getOperatorLoc(), UO, + S.PDiag(diag::warn_indirection_through_null) + << UO->getSubExpr()->getSourceRange()); + S.DiagRuntimeBehavior(UO->getOperatorLoc(), UO, + S.PDiag(diag::note_indirection_through_null)); + } +} + +ExprResult Sema::DefaultLvalueConversion(Expr *E) { + // Handle any placeholder expressions which made it here. + if (E->getType()->isPlaceholderType()) { + ExprResult result = CheckPlaceholderExpr(E); + if (result.isInvalid()) return ExprError(); + E = result.take(); + } + + // C++ [conv.lval]p1: + // A glvalue of a non-function, non-array type T can be + // converted to a prvalue. + if (!E->isGLValue()) return Owned(E); + + QualType T = E->getType(); + assert(!T.isNull() && "r-value conversion on typeless expression?"); + + // We don't want to throw lvalue-to-rvalue casts on top of + // expressions of certain types in C++. + if (getLangOpts().CPlusPlus && + (E->getType() == Context.OverloadTy || + T->isDependentType() || + T->isRecordType())) + return Owned(E); + + // The C standard is actually really unclear on this point, and + // DR106 tells us what the result should be but not why. It's + // generally best to say that void types just doesn't undergo + // lvalue-to-rvalue at all. Note that expressions of unqualified + // 'void' type are never l-values, but qualified void can be. + if (T->isVoidType()) + return Owned(E); + + CheckForNullPointerDereference(*this, E); + + // C++ [conv.lval]p1: + // [...] If T is a non-class type, the type of the prvalue is the + // cv-unqualified version of T. Otherwise, the type of the + // rvalue is T. + // + // C99 6.3.2.1p2: + // 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. + if (T.hasQualifiers()) + T = T.getUnqualifiedType(); + + UpdateMarkingForLValueToRValue(E); + + ExprResult Res = Owned(ImplicitCastExpr::Create(Context, T, CK_LValueToRValue, + E, 0, VK_RValue)); + + // C11 6.3.2.1p2: + // ... if the lvalue has atomic type, the value has the non-atomic version + // of the type of the lvalue ... + if (const AtomicType *Atomic = T->getAs()) { + T = Atomic->getValueType().getUnqualifiedType(); + Res = Owned(ImplicitCastExpr::Create(Context, T, CK_AtomicToNonAtomic, + Res.get(), 0, VK_RValue)); + } + + return Res; +} + +ExprResult Sema::DefaultFunctionArrayLvalueConversion(Expr *E) { + ExprResult Res = DefaultFunctionArrayConversion(E); + if (Res.isInvalid()) + return ExprError(); + Res = DefaultLvalueConversion(Res.take()); + if (Res.isInvalid()) + return ExprError(); + return move(Res); +} + + +/// UsualUnaryConversions - Performs various conversions that are common to most +/// operators (C99 6.3). The conversions of array and function types are +/// sometimes suppressed. For example, the array->pointer conversion doesn't +/// apply if the array is an argument to the sizeof or address (&) operators. +/// In these instances, this routine should *not* be called. +ExprResult Sema::UsualUnaryConversions(Expr *E) { + // First, convert to an r-value. + ExprResult Res = DefaultFunctionArrayLvalueConversion(E); + if (Res.isInvalid()) + return Owned(E); + E = Res.take(); + + QualType Ty = E->getType(); + assert(!Ty.isNull() && "UsualUnaryConversions - missing type"); + + // Half FP is a bit different: it's a storage-only type, meaning that any + // "use" of it should be promoted to float. + if (Ty->isHalfType()) + return ImpCastExprToType(Res.take(), Context.FloatTy, CK_FloatingCast); + + // Try to perform integral promotions if the object has a theoretically + // promotable type. + if (Ty->isIntegralOrUnscopedEnumerationType()) { + // C99 6.3.1.1p2: + // + // The following may be used in an expression wherever an int or + // unsigned int may be used: + // - an object or expression with an integer type whose integer + // conversion rank is less than or equal to the rank of int + // and unsigned int. + // - A bit-field of type _Bool, int, signed int, or unsigned int. + // + // If an int can represent all values of the original type, the + // value is converted to an int; otherwise, it is converted to an + // unsigned int. These are called the integer promotions. All + // other types are unchanged by the integer promotions. + + QualType PTy = Context.isPromotableBitField(E); + if (!PTy.isNull()) { + E = ImpCastExprToType(E, PTy, CK_IntegralCast).take(); + return Owned(E); + } + if (Ty->isPromotableIntegerType()) { + QualType PT = Context.getPromotedIntegerType(Ty); + E = ImpCastExprToType(E, PT, CK_IntegralCast).take(); + return Owned(E); + } + } + return Owned(E); +} + +/// DefaultArgumentPromotion (C99 6.5.2.2p6). Used for function calls that +/// do not have a prototype. Arguments that have type float are promoted to +/// double. All other argument types are converted by UsualUnaryConversions(). +ExprResult Sema::DefaultArgumentPromotion(Expr *E) { + QualType Ty = E->getType(); + assert(!Ty.isNull() && "DefaultArgumentPromotion - missing type"); + + ExprResult Res = UsualUnaryConversions(E); + if (Res.isInvalid()) + return Owned(E); + E = Res.take(); + + // If this is a 'float' (CVR qualified or typedef) promote to double. + if (Ty->isSpecificBuiltinType(BuiltinType::Float)) + E = ImpCastExprToType(E, Context.DoubleTy, CK_FloatingCast).take(); + + // C++ performs lvalue-to-rvalue conversion as a default argument + // promotion, even on class types, but note: + // C++11 [conv.lval]p2: + // When an lvalue-to-rvalue conversion occurs in an unevaluated + // operand or a subexpression thereof the value contained in the + // referenced object is not accessed. Otherwise, if the glvalue + // has a class type, the conversion copy-initializes a temporary + // of type T from the glvalue and the result of the conversion + // is a prvalue for the temporary. + // FIXME: add some way to gate this entire thing for correctness in + // potentially potentially evaluated contexts. + if (getLangOpts().CPlusPlus && E->isGLValue() && + ExprEvalContexts.back().Context != Unevaluated) { + ExprResult Temp = PerformCopyInitialization( + InitializedEntity::InitializeTemporary(E->getType()), + E->getExprLoc(), + Owned(E)); + if (Temp.isInvalid()) + return ExprError(); + E = Temp.get(); + } + + return Owned(E); +} + +/// DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but +/// will warn if the resulting type is not a POD type, and rejects ObjC +/// interfaces passed by value. +ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT, + FunctionDecl *FDecl) { + if (const BuiltinType *PlaceholderTy = E->getType()->getAsPlaceholderType()) { + // Strip the unbridged-cast placeholder expression off, if applicable. + if (PlaceholderTy->getKind() == BuiltinType::ARCUnbridgedCast && + (CT == VariadicMethod || + (FDecl && FDecl->hasAttr()))) { + E = stripARCUnbridgedCast(E); + + // Otherwise, do normal placeholder checking. + } else { + ExprResult ExprRes = CheckPlaceholderExpr(E); + if (ExprRes.isInvalid()) + return ExprError(); + E = ExprRes.take(); + } + } + + ExprResult ExprRes = DefaultArgumentPromotion(E); + if (ExprRes.isInvalid()) + return ExprError(); + E = ExprRes.take(); + + // Don't allow one to pass an Objective-C interface to a vararg. + if (E->getType()->isObjCObjectType() && + DiagRuntimeBehavior(E->getLocStart(), 0, + PDiag(diag::err_cannot_pass_objc_interface_to_vararg) + << E->getType() << CT)) + return ExprError(); + + // Complain about passing non-POD types through varargs. However, don't + // perform this check for incomplete types, which we can get here when we're + // in an unevaluated context. + if (!E->getType()->isIncompleteType() && !E->getType().isPODType(Context)) { + // C++0x [expr.call]p7: + // Passing a potentially-evaluated argument of class type (Clause 9) + // having a non-trivial copy constructor, a non-trivial move constructor, + // or a non-trivial destructor, with no corresponding parameter, + // is conditionally-supported with implementation-defined semantics. + bool TrivialEnough = false; + if (getLangOpts().CPlusPlus0x && !E->getType()->isDependentType()) { + if (CXXRecordDecl *Record = E->getType()->getAsCXXRecordDecl()) { + if (Record->hasTrivialCopyConstructor() && + Record->hasTrivialMoveConstructor() && + Record->hasTrivialDestructor()) { + DiagRuntimeBehavior(E->getLocStart(), 0, + PDiag(diag::warn_cxx98_compat_pass_non_pod_arg_to_vararg) + << E->getType() << CT); + TrivialEnough = true; + } + } + } + + if (!TrivialEnough && + getLangOpts().ObjCAutoRefCount && + E->getType()->isObjCLifetimeType()) + TrivialEnough = true; + + if (TrivialEnough) { + // Nothing to diagnose. This is okay. + } else if (DiagRuntimeBehavior(E->getLocStart(), 0, + PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg) + << getLangOpts().CPlusPlus0x << E->getType() + << CT)) { + // Turn this into a trap. + CXXScopeSpec SS; + SourceLocation TemplateKWLoc; + UnqualifiedId Name; + Name.setIdentifier(PP.getIdentifierInfo("__builtin_trap"), + E->getLocStart()); + ExprResult TrapFn = ActOnIdExpression(TUScope, SS, TemplateKWLoc, Name, + true, false); + if (TrapFn.isInvalid()) + return ExprError(); + + ExprResult Call = ActOnCallExpr(TUScope, TrapFn.get(), E->getLocStart(), + MultiExprArg(), E->getLocEnd()); + if (Call.isInvalid()) + return ExprError(); + + ExprResult Comma = ActOnBinOp(TUScope, E->getLocStart(), tok::comma, + Call.get(), E); + if (Comma.isInvalid()) + return ExprError(); + E = Comma.get(); + } + } + // c++ rules are enforced elsewhere. + if (!getLangOpts().CPlusPlus && + RequireCompleteType(E->getExprLoc(), E->getType(), + diag::err_call_incomplete_argument)) + return ExprError(); + + return Owned(E); +} + +/// \brief Converts an integer to complex float type. Helper function of +/// UsualArithmeticConversions() +/// +/// \return false if the integer expression is an integer type and is +/// successfully converted to the complex type. +static bool handleIntegerToComplexFloatConversion(Sema &S, ExprResult &IntExpr, + ExprResult &ComplexExpr, + QualType IntTy, + QualType ComplexTy, + bool SkipCast) { + if (IntTy->isComplexType() || IntTy->isRealFloatingType()) return true; + if (SkipCast) return false; + if (IntTy->isIntegerType()) { + QualType fpTy = cast(ComplexTy)->getElementType(); + IntExpr = S.ImpCastExprToType(IntExpr.take(), fpTy, CK_IntegralToFloating); + IntExpr = S.ImpCastExprToType(IntExpr.take(), ComplexTy, + CK_FloatingRealToComplex); + } else { + assert(IntTy->isComplexIntegerType()); + IntExpr = S.ImpCastExprToType(IntExpr.take(), ComplexTy, + CK_IntegralComplexToFloatingComplex); + } + return false; +} + +/// \brief Takes two complex float types and converts them to the same type. +/// Helper function of UsualArithmeticConversions() +static QualType +handleComplexFloatToComplexFloatConverstion(Sema &S, ExprResult &LHS, + ExprResult &RHS, QualType LHSType, + QualType RHSType, + bool IsCompAssign) { + int order = S.Context.getFloatingTypeOrder(LHSType, RHSType); + + if (order < 0) { + // _Complex float -> _Complex double + if (!IsCompAssign) + LHS = S.ImpCastExprToType(LHS.take(), RHSType, CK_FloatingComplexCast); + return RHSType; + } + if (order > 0) + // _Complex float -> _Complex double + RHS = S.ImpCastExprToType(RHS.take(), LHSType, CK_FloatingComplexCast); + return LHSType; +} + +/// \brief Converts otherExpr to complex float and promotes complexExpr if +/// necessary. Helper function of UsualArithmeticConversions() +static QualType handleOtherComplexFloatConversion(Sema &S, + ExprResult &ComplexExpr, + ExprResult &OtherExpr, + QualType ComplexTy, + QualType OtherTy, + bool ConvertComplexExpr, + bool ConvertOtherExpr) { + int order = S.Context.getFloatingTypeOrder(ComplexTy, OtherTy); + + // If just the complexExpr is complex, the otherExpr needs to be converted, + // and the complexExpr might need to be promoted. + if (order > 0) { // complexExpr is wider + // float -> _Complex double + if (ConvertOtherExpr) { + QualType fp = cast(ComplexTy)->getElementType(); + OtherExpr = S.ImpCastExprToType(OtherExpr.take(), fp, CK_FloatingCast); + OtherExpr = S.ImpCastExprToType(OtherExpr.take(), ComplexTy, + CK_FloatingRealToComplex); + } + return ComplexTy; + } + + // otherTy is at least as wide. Find its corresponding complex type. + QualType result = (order == 0 ? ComplexTy : + S.Context.getComplexType(OtherTy)); + + // double -> _Complex double + if (ConvertOtherExpr) + OtherExpr = S.ImpCastExprToType(OtherExpr.take(), result, + CK_FloatingRealToComplex); + + // _Complex float -> _Complex double + if (ConvertComplexExpr && order < 0) + ComplexExpr = S.ImpCastExprToType(ComplexExpr.take(), result, + CK_FloatingComplexCast); + + return result; +} + +/// \brief Handle arithmetic conversion with complex types. Helper function of +/// UsualArithmeticConversions() +static QualType handleComplexFloatConversion(Sema &S, ExprResult &LHS, + ExprResult &RHS, QualType LHSType, + QualType RHSType, + bool IsCompAssign) { + // if we have an integer operand, the result is the complex type. + if (!handleIntegerToComplexFloatConversion(S, RHS, LHS, RHSType, LHSType, + /*skipCast*/false)) + return LHSType; + if (!handleIntegerToComplexFloatConversion(S, LHS, RHS, LHSType, RHSType, + /*skipCast*/IsCompAssign)) + return RHSType; + + // This handles complex/complex, complex/float, or float/complex. + // When both operands are complex, the shorter operand is converted to the + // type of the longer, and that is the type of the result. This corresponds + // to what is done when combining two real floating-point operands. + // The fun begins when size promotion occur across type domains. + // From H&S 6.3.4: When one operand is complex and the other is a real + // floating-point type, the less precise type is converted, within it's + // real or complex domain, to the precision of the other type. For example, + // when combining a "long double" with a "double _Complex", the + // "double _Complex" is promoted to "long double _Complex". + + bool LHSComplexFloat = LHSType->isComplexType(); + bool RHSComplexFloat = RHSType->isComplexType(); + + // If both are complex, just cast to the more precise type. + if (LHSComplexFloat && RHSComplexFloat) + return handleComplexFloatToComplexFloatConverstion(S, LHS, RHS, + LHSType, RHSType, + IsCompAssign); + + // If only one operand is complex, promote it if necessary and convert the + // other operand to complex. + if (LHSComplexFloat) + return handleOtherComplexFloatConversion( + S, LHS, RHS, LHSType, RHSType, /*convertComplexExpr*/!IsCompAssign, + /*convertOtherExpr*/ true); + + assert(RHSComplexFloat); + return handleOtherComplexFloatConversion( + S, RHS, LHS, RHSType, LHSType, /*convertComplexExpr*/true, + /*convertOtherExpr*/ !IsCompAssign); +} + +/// \brief Hande arithmetic conversion from integer to float. Helper function +/// of UsualArithmeticConversions() +static QualType handleIntToFloatConversion(Sema &S, ExprResult &FloatExpr, + ExprResult &IntExpr, + QualType FloatTy, QualType IntTy, + bool ConvertFloat, bool ConvertInt) { + if (IntTy->isIntegerType()) { + if (ConvertInt) + // Convert intExpr to the lhs floating point type. + IntExpr = S.ImpCastExprToType(IntExpr.take(), FloatTy, + CK_IntegralToFloating); + return FloatTy; + } + + // Convert both sides to the appropriate complex float. + assert(IntTy->isComplexIntegerType()); + QualType result = S.Context.getComplexType(FloatTy); + + // _Complex int -> _Complex float + if (ConvertInt) + IntExpr = S.ImpCastExprToType(IntExpr.take(), result, + CK_IntegralComplexToFloatingComplex); + + // float -> _Complex float + if (ConvertFloat) + FloatExpr = S.ImpCastExprToType(FloatExpr.take(), result, + CK_FloatingRealToComplex); + + return result; +} + +/// \brief Handle arithmethic conversion with floating point types. Helper +/// function of UsualArithmeticConversions() +static QualType handleFloatConversion(Sema &S, ExprResult &LHS, + ExprResult &RHS, QualType LHSType, + QualType RHSType, bool IsCompAssign) { + bool LHSFloat = LHSType->isRealFloatingType(); + bool RHSFloat = RHSType->isRealFloatingType(); + + // If we have two real floating types, convert the smaller operand + // to the bigger result. + if (LHSFloat && RHSFloat) { + int order = S.Context.getFloatingTypeOrder(LHSType, RHSType); + if (order > 0) { + RHS = S.ImpCastExprToType(RHS.take(), LHSType, CK_FloatingCast); + return LHSType; + } + + assert(order < 0 && "illegal float comparison"); + if (!IsCompAssign) + LHS = S.ImpCastExprToType(LHS.take(), RHSType, CK_FloatingCast); + return RHSType; + } + + if (LHSFloat) + return handleIntToFloatConversion(S, LHS, RHS, LHSType, RHSType, + /*convertFloat=*/!IsCompAssign, + /*convertInt=*/ true); + assert(RHSFloat); + return handleIntToFloatConversion(S, RHS, LHS, RHSType, LHSType, + /*convertInt=*/ true, + /*convertFloat=*/!IsCompAssign); +} + +/// \brief Handle conversions with GCC complex int extension. Helper function +/// of UsualArithmeticConversions() +// FIXME: if the operands are (int, _Complex long), we currently +// don't promote the complex. Also, signedness? +static QualType handleComplexIntConversion(Sema &S, ExprResult &LHS, + ExprResult &RHS, QualType LHSType, + QualType RHSType, + bool IsCompAssign) { + const ComplexType *LHSComplexInt = LHSType->getAsComplexIntegerType(); + const ComplexType *RHSComplexInt = RHSType->getAsComplexIntegerType(); + + if (LHSComplexInt && RHSComplexInt) { + int order = S.Context.getIntegerTypeOrder(LHSComplexInt->getElementType(), + RHSComplexInt->getElementType()); + assert(order && "inequal types with equal element ordering"); + if (order > 0) { + // _Complex int -> _Complex long + RHS = S.ImpCastExprToType(RHS.take(), LHSType, CK_IntegralComplexCast); + return LHSType; + } + + if (!IsCompAssign) + LHS = S.ImpCastExprToType(LHS.take(), RHSType, CK_IntegralComplexCast); + return RHSType; + } + + if (LHSComplexInt) { + // int -> _Complex int + // FIXME: This needs to take integer ranks into account + RHS = S.ImpCastExprToType(RHS.take(), LHSComplexInt->getElementType(), + CK_IntegralCast); + RHS = S.ImpCastExprToType(RHS.take(), LHSType, CK_IntegralRealToComplex); + return LHSType; + } + + assert(RHSComplexInt); + // int -> _Complex int + // FIXME: This needs to take integer ranks into account + if (!IsCompAssign) { + LHS = S.ImpCastExprToType(LHS.take(), RHSComplexInt->getElementType(), + CK_IntegralCast); + LHS = S.ImpCastExprToType(LHS.take(), RHSType, CK_IntegralRealToComplex); + } + return RHSType; +} + +/// \brief Handle integer arithmetic conversions. Helper function of +/// UsualArithmeticConversions() +static QualType handleIntegerConversion(Sema &S, ExprResult &LHS, + ExprResult &RHS, QualType LHSType, + QualType RHSType, bool IsCompAssign) { + // The rules for this case are in C99 6.3.1.8 + int order = S.Context.getIntegerTypeOrder(LHSType, RHSType); + bool LHSSigned = LHSType->hasSignedIntegerRepresentation(); + bool RHSSigned = RHSType->hasSignedIntegerRepresentation(); + if (LHSSigned == RHSSigned) { + // Same signedness; use the higher-ranked type + if (order >= 0) { + RHS = S.ImpCastExprToType(RHS.take(), LHSType, CK_IntegralCast); + return LHSType; + } else if (!IsCompAssign) + LHS = S.ImpCastExprToType(LHS.take(), RHSType, CK_IntegralCast); + return RHSType; + } else if (order != (LHSSigned ? 1 : -1)) { + // The unsigned type has greater than or equal rank to the + // signed type, so use the unsigned type + if (RHSSigned) { + RHS = S.ImpCastExprToType(RHS.take(), LHSType, CK_IntegralCast); + return LHSType; + } else if (!IsCompAssign) + LHS = S.ImpCastExprToType(LHS.take(), RHSType, CK_IntegralCast); + return RHSType; + } else if (S.Context.getIntWidth(LHSType) != S.Context.getIntWidth(RHSType)) { + // The two types are different widths; if we are here, that + // means the signed type is larger than the unsigned type, so + // use the signed type. + if (LHSSigned) { + RHS = S.ImpCastExprToType(RHS.take(), LHSType, CK_IntegralCast); + return LHSType; + } else if (!IsCompAssign) + LHS = S.ImpCastExprToType(LHS.take(), RHSType, CK_IntegralCast); + return RHSType; + } else { + // The signed type is higher-ranked than the unsigned type, + // but isn't actually any bigger (like unsigned int and long + // on most 32-bit systems). Use the unsigned type corresponding + // to the signed type. + QualType result = + S.Context.getCorrespondingUnsignedType(LHSSigned ? LHSType : RHSType); + RHS = S.ImpCastExprToType(RHS.take(), result, CK_IntegralCast); + if (!IsCompAssign) + LHS = S.ImpCastExprToType(LHS.take(), result, CK_IntegralCast); + return result; + } +} + +/// UsualArithmeticConversions - Performs 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. +/// FIXME: verify the conversion rules for "complex int" are consistent with +/// GCC. +QualType Sema::UsualArithmeticConversions(ExprResult &LHS, ExprResult &RHS, + bool IsCompAssign) { + if (!IsCompAssign) { + LHS = UsualUnaryConversions(LHS.take()); + if (LHS.isInvalid()) + return QualType(); + } + + RHS = UsualUnaryConversions(RHS.take()); + if (RHS.isInvalid()) + return QualType(); + + // For conversion purposes, we ignore any qualifiers. + // For example, "const float" and "float" are equivalent. + QualType LHSType = + Context.getCanonicalType(LHS.get()->getType()).getUnqualifiedType(); + QualType RHSType = + Context.getCanonicalType(RHS.get()->getType()).getUnqualifiedType(); + + // If both types are identical, no conversion is needed. + if (LHSType == RHSType) + return LHSType; + + // If either side is a non-arithmetic type (e.g. a pointer), we are done. + // The caller can deal with this (e.g. pointer + int). + if (!LHSType->isArithmeticType() || !RHSType->isArithmeticType()) + return LHSType; + + // Apply unary and bitfield promotions to the LHS's type. + QualType LHSUnpromotedType = LHSType; + if (LHSType->isPromotableIntegerType()) + LHSType = Context.getPromotedIntegerType(LHSType); + QualType LHSBitfieldPromoteTy = Context.isPromotableBitField(LHS.get()); + if (!LHSBitfieldPromoteTy.isNull()) + LHSType = LHSBitfieldPromoteTy; + if (LHSType != LHSUnpromotedType && !IsCompAssign) + LHS = ImpCastExprToType(LHS.take(), LHSType, CK_IntegralCast); + + // If both types are identical, no conversion is needed. + if (LHSType == RHSType) + return LHSType; + + // At this point, we have two different arithmetic types. + + // Handle complex types first (C99 6.3.1.8p1). + if (LHSType->isComplexType() || RHSType->isComplexType()) + return handleComplexFloatConversion(*this, LHS, RHS, LHSType, RHSType, + IsCompAssign); + + // Now handle "real" floating types (i.e. float, double, long double). + if (LHSType->isRealFloatingType() || RHSType->isRealFloatingType()) + return handleFloatConversion(*this, LHS, RHS, LHSType, RHSType, + IsCompAssign); + + // Handle GCC complex int extension. + if (LHSType->isComplexIntegerType() || RHSType->isComplexIntegerType()) + return handleComplexIntConversion(*this, LHS, RHS, LHSType, RHSType, + IsCompAssign); + + // Finally, we have two differing integer types. + return handleIntegerConversion(*this, LHS, RHS, LHSType, RHSType, + IsCompAssign); +} + +//===----------------------------------------------------------------------===// +// Semantic Analysis for various Expression Types +//===----------------------------------------------------------------------===// + + +ExprResult +Sema::ActOnGenericSelectionExpr(SourceLocation KeyLoc, + SourceLocation DefaultLoc, + SourceLocation RParenLoc, + Expr *ControllingExpr, + MultiTypeArg ArgTypes, + MultiExprArg ArgExprs) { + unsigned NumAssocs = ArgTypes.size(); + assert(NumAssocs == ArgExprs.size()); + + ParsedType *ParsedTypes = ArgTypes.release(); + Expr **Exprs = ArgExprs.release(); + + TypeSourceInfo **Types = new TypeSourceInfo*[NumAssocs]; + for (unsigned i = 0; i < NumAssocs; ++i) { + if (ParsedTypes[i]) + (void) GetTypeFromParser(ParsedTypes[i], &Types[i]); + else + Types[i] = 0; + } + + ExprResult ER = CreateGenericSelectionExpr(KeyLoc, DefaultLoc, RParenLoc, + ControllingExpr, Types, Exprs, + NumAssocs); + delete [] Types; + return ER; +} + +ExprResult +Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc, + SourceLocation DefaultLoc, + SourceLocation RParenLoc, + Expr *ControllingExpr, + TypeSourceInfo **Types, + Expr **Exprs, + unsigned NumAssocs) { + bool TypeErrorFound = false, + IsResultDependent = ControllingExpr->isTypeDependent(), + ContainsUnexpandedParameterPack + = ControllingExpr->containsUnexpandedParameterPack(); + + for (unsigned i = 0; i < NumAssocs; ++i) { + if (Exprs[i]->containsUnexpandedParameterPack()) + ContainsUnexpandedParameterPack = true; + + if (Types[i]) { + if (Types[i]->getType()->containsUnexpandedParameterPack()) + ContainsUnexpandedParameterPack = true; + + if (Types[i]->getType()->isDependentType()) { + IsResultDependent = true; + } else { + // C11 6.5.1.1p2 "The type name in a generic association shall specify a + // complete object type other than a variably modified type." + unsigned D = 0; + if (Types[i]->getType()->isIncompleteType()) + D = diag::err_assoc_type_incomplete; + else if (!Types[i]->getType()->isObjectType()) + D = diag::err_assoc_type_nonobject; + else if (Types[i]->getType()->isVariablyModifiedType()) + D = diag::err_assoc_type_variably_modified; + + if (D != 0) { + Diag(Types[i]->getTypeLoc().getBeginLoc(), D) + << Types[i]->getTypeLoc().getSourceRange() + << Types[i]->getType(); + TypeErrorFound = true; + } + + // C11 6.5.1.1p2 "No two generic associations in the same generic + // selection shall specify compatible types." + for (unsigned j = i+1; j < NumAssocs; ++j) + if (Types[j] && !Types[j]->getType()->isDependentType() && + Context.typesAreCompatible(Types[i]->getType(), + Types[j]->getType())) { + Diag(Types[j]->getTypeLoc().getBeginLoc(), + diag::err_assoc_compatible_types) + << Types[j]->getTypeLoc().getSourceRange() + << Types[j]->getType() + << Types[i]->getType(); + Diag(Types[i]->getTypeLoc().getBeginLoc(), + diag::note_compat_assoc) + << Types[i]->getTypeLoc().getSourceRange() + << Types[i]->getType(); + TypeErrorFound = true; + } + } + } + } + if (TypeErrorFound) + return ExprError(); + + // If we determined that the generic selection is result-dependent, don't + // try to compute the result expression. + if (IsResultDependent) + return Owned(new (Context) GenericSelectionExpr( + Context, KeyLoc, ControllingExpr, + Types, Exprs, NumAssocs, DefaultLoc, + RParenLoc, ContainsUnexpandedParameterPack)); + + SmallVector CompatIndices; + unsigned DefaultIndex = -1U; + for (unsigned i = 0; i < NumAssocs; ++i) { + if (!Types[i]) + DefaultIndex = i; + else if (Context.typesAreCompatible(ControllingExpr->getType(), + Types[i]->getType())) + CompatIndices.push_back(i); + } + + // C11 6.5.1.1p2 "The controlling expression of a generic selection shall have + // type compatible with at most one of the types named in its generic + // association list." + if (CompatIndices.size() > 1) { + // We strip parens here because the controlling expression is typically + // parenthesized in macro definitions. + ControllingExpr = ControllingExpr->IgnoreParens(); + Diag(ControllingExpr->getLocStart(), diag::err_generic_sel_multi_match) + << ControllingExpr->getSourceRange() << ControllingExpr->getType() + << (unsigned) CompatIndices.size(); + for (SmallVector::iterator I = CompatIndices.begin(), + E = CompatIndices.end(); I != E; ++I) { + Diag(Types[*I]->getTypeLoc().getBeginLoc(), + diag::note_compat_assoc) + << Types[*I]->getTypeLoc().getSourceRange() + << Types[*I]->getType(); + } + return ExprError(); + } + + // C11 6.5.1.1p2 "If a generic selection has no default generic association, + // its controlling expression shall have type compatible with exactly one of + // the types named in its generic association list." + if (DefaultIndex == -1U && CompatIndices.size() == 0) { + // We strip parens here because the controlling expression is typically + // parenthesized in macro definitions. + ControllingExpr = ControllingExpr->IgnoreParens(); + Diag(ControllingExpr->getLocStart(), diag::err_generic_sel_no_match) + << ControllingExpr->getSourceRange() << ControllingExpr->getType(); + return ExprError(); + } + + // C11 6.5.1.1p3 "If a generic selection has a generic association with a + // type name that is compatible with the type of the controlling expression, + // then the result expression of the generic selection is the expression + // in that generic association. Otherwise, the result expression of the + // generic selection is the expression in the default generic association." + unsigned ResultIndex = + CompatIndices.size() ? CompatIndices[0] : DefaultIndex; + + return Owned(new (Context) GenericSelectionExpr( + Context, KeyLoc, ControllingExpr, + Types, Exprs, NumAssocs, DefaultLoc, + RParenLoc, ContainsUnexpandedParameterPack, + ResultIndex)); +} + +/// getUDSuffixLoc - Create a SourceLocation for a ud-suffix, given the +/// location of the token and the offset of the ud-suffix within it. +static SourceLocation getUDSuffixLoc(Sema &S, SourceLocation TokLoc, + unsigned Offset) { + return Lexer::AdvanceToTokenCharacter(TokLoc, Offset, S.getSourceManager(), + S.getLangOpts()); +} + +/// BuildCookedLiteralOperatorCall - A user-defined literal was found. Look up +/// the corresponding cooked (non-raw) literal operator, and build a call to it. +static ExprResult BuildCookedLiteralOperatorCall(Sema &S, Scope *Scope, + IdentifierInfo *UDSuffix, + SourceLocation UDSuffixLoc, + ArrayRef Args, + SourceLocation LitEndLoc) { + assert(Args.size() <= 2 && "too many arguments for literal operator"); + + QualType ArgTy[2]; + for (unsigned ArgIdx = 0; ArgIdx != Args.size(); ++ArgIdx) { + ArgTy[ArgIdx] = Args[ArgIdx]->getType(); + if (ArgTy[ArgIdx]->isArrayType()) + ArgTy[ArgIdx] = S.Context.getArrayDecayedType(ArgTy[ArgIdx]); + } + + DeclarationName OpName = + S.Context.DeclarationNames.getCXXLiteralOperatorName(UDSuffix); + DeclarationNameInfo OpNameInfo(OpName, UDSuffixLoc); + OpNameInfo.setCXXLiteralOperatorNameLoc(UDSuffixLoc); + + LookupResult R(S, OpName, UDSuffixLoc, Sema::LookupOrdinaryName); + if (S.LookupLiteralOperator(Scope, R, llvm::makeArrayRef(ArgTy, Args.size()), + /*AllowRawAndTemplate*/false) == Sema::LOLR_Error) + return ExprError(); + + return S.BuildLiteralOperatorCall(R, OpNameInfo, Args, LitEndLoc); +} + +/// ActOnStringLiteral - The specified tokens were lexed as pasted string +/// fragments (e.g. "foo" "bar" L"baz"). The result string has to handle string +/// concatenation ([C99 5.1.1.2, translation phase #6]), so it may come from +/// multiple tokens. However, the common case is that StringToks points to one +/// string. +/// +ExprResult +Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks, + Scope *UDLScope) { + assert(NumStringToks && "Must have at least one string!"); + + StringLiteralParser Literal(StringToks, NumStringToks, PP); + if (Literal.hadError) + return ExprError(); + + SmallVector StringTokLocs; + for (unsigned i = 0; i != NumStringToks; ++i) + StringTokLocs.push_back(StringToks[i].getLocation()); + + QualType StrTy = Context.CharTy; + if (Literal.isWide()) + StrTy = Context.getWCharType(); + else if (Literal.isUTF16()) + StrTy = Context.Char16Ty; + else if (Literal.isUTF32()) + StrTy = Context.Char32Ty; + else if (Literal.isPascal()) + StrTy = Context.UnsignedCharTy; + + StringLiteral::StringKind Kind = StringLiteral::Ascii; + if (Literal.isWide()) + Kind = StringLiteral::Wide; + else if (Literal.isUTF8()) + Kind = StringLiteral::UTF8; + else if (Literal.isUTF16()) + Kind = StringLiteral::UTF16; + else if (Literal.isUTF32()) + Kind = StringLiteral::UTF32; + + // A C++ string literal has a const-qualified element type (C++ 2.13.4p1). + if (getLangOpts().CPlusPlus || getLangOpts().ConstStrings) + StrTy.addConst(); + + // Get an array type for the string, according to C99 6.4.5. This includes + // the nul terminator character as well as the string length for pascal + // strings. + StrTy = Context.getConstantArrayType(StrTy, + llvm::APInt(32, Literal.GetNumStringChars()+1), + ArrayType::Normal, 0); + + // Pass &StringTokLocs[0], StringTokLocs.size() to factory! + StringLiteral *Lit = StringLiteral::Create(Context, Literal.GetString(), + Kind, Literal.Pascal, StrTy, + &StringTokLocs[0], + StringTokLocs.size()); + if (Literal.getUDSuffix().empty()) + return Owned(Lit); + + // We're building a user-defined literal. + IdentifierInfo *UDSuffix = &Context.Idents.get(Literal.getUDSuffix()); + SourceLocation UDSuffixLoc = + getUDSuffixLoc(*this, StringTokLocs[Literal.getUDSuffixToken()], + Literal.getUDSuffixOffset()); + + // Make sure we're allowed user-defined literals here. + if (!UDLScope) + return ExprError(Diag(UDSuffixLoc, diag::err_invalid_string_udl)); + + // C++11 [lex.ext]p5: The literal L is treated as a call of the form + // operator "" X (str, len) + QualType SizeType = Context.getSizeType(); + llvm::APInt Len(Context.getIntWidth(SizeType), Literal.GetNumStringChars()); + IntegerLiteral *LenArg = IntegerLiteral::Create(Context, Len, SizeType, + StringTokLocs[0]); + Expr *Args[] = { Lit, LenArg }; + return BuildCookedLiteralOperatorCall(*this, UDLScope, UDSuffix, UDSuffixLoc, + Args, StringTokLocs.back()); +} + +ExprResult +Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, + SourceLocation Loc, + const CXXScopeSpec *SS) { + DeclarationNameInfo NameInfo(D->getDeclName(), Loc); + return BuildDeclRefExpr(D, Ty, VK, NameInfo, SS); +} + +/// BuildDeclRefExpr - Build an expression that references a +/// declaration that does not require a closure capture. +ExprResult +Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, + const DeclarationNameInfo &NameInfo, + const CXXScopeSpec *SS) { + if (getLangOpts().CUDA) + if (const FunctionDecl *Caller = dyn_cast(CurContext)) + if (const FunctionDecl *Callee = dyn_cast(D)) { + CUDAFunctionTarget CallerTarget = IdentifyCUDATarget(Caller), + CalleeTarget = IdentifyCUDATarget(Callee); + if (CheckCUDATarget(CallerTarget, CalleeTarget)) { + Diag(NameInfo.getLoc(), diag::err_ref_bad_target) + << CalleeTarget << D->getIdentifier() << CallerTarget; + Diag(D->getLocation(), diag::note_previous_decl) + << D->getIdentifier(); + return ExprError(); + } + } + + bool refersToEnclosingScope = + (CurContext != D->getDeclContext() && + D->getDeclContext()->isFunctionOrMethod()); + + DeclRefExpr *E = DeclRefExpr::Create(Context, + SS ? SS->getWithLocInContext(Context) + : NestedNameSpecifierLoc(), + SourceLocation(), + D, refersToEnclosingScope, + NameInfo, Ty, VK); + + MarkDeclRefReferenced(E); + + // Just in case we're building an illegal pointer-to-member. + FieldDecl *FD = dyn_cast(D); + if (FD && FD->isBitField()) + E->setObjectKind(OK_BitField); + + return Owned(E); +} + +/// 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 +/// DecomposeTemplateName. +/// +/// This actually loses a lot of source location information for +/// non-standard name kinds; we should consider preserving that in +/// some way. +void +Sema::DecomposeUnqualifiedId(const UnqualifiedId &Id, + TemplateArgumentListInfo &Buffer, + DeclarationNameInfo &NameInfo, + const TemplateArgumentListInfo *&TemplateArgs) { + if (Id.getKind() == UnqualifiedId::IK_TemplateId) { + Buffer.setLAngleLoc(Id.TemplateId->LAngleLoc); + Buffer.setRAngleLoc(Id.TemplateId->RAngleLoc); + + ASTTemplateArgsPtr TemplateArgsPtr(*this, + Id.TemplateId->getTemplateArgs(), + Id.TemplateId->NumArgs); + translateTemplateArguments(TemplateArgsPtr, Buffer); + TemplateArgsPtr.release(); + + TemplateName TName = Id.TemplateId->Template.get(); + SourceLocation TNameLoc = Id.TemplateId->TemplateNameLoc; + NameInfo = Context.getNameForTemplate(TName, TNameLoc); + TemplateArgs = &Buffer; + } else { + NameInfo = GetNameFromUnqualifiedId(Id); + TemplateArgs = 0; + } +} + +/// Diagnose an empty lookup. +/// +/// \return false if new lookup candidates were found +bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, + CorrectionCandidateCallback &CCC, + TemplateArgumentListInfo *ExplicitTemplateArgs, + llvm::ArrayRef Args) { + DeclarationName Name = R.getLookupName(); + + unsigned diagnostic = diag::err_undeclared_var_use; + unsigned diagnostic_suggest = diag::err_undeclared_var_use_suggest; + if (Name.getNameKind() == DeclarationName::CXXOperatorName || + Name.getNameKind() == DeclarationName::CXXLiteralOperatorName || + Name.getNameKind() == DeclarationName::CXXConversionFunctionName) { + diagnostic = diag::err_undeclared_use; + diagnostic_suggest = diag::err_undeclared_use_suggest; + } + + // If the original lookup was an unqualified lookup, fake an + // unqualified lookup. This is useful when (for example) the + // original lookup would not have found something because it was a + // dependent name. + DeclContext *DC = SS.isEmpty() ? CurContext : 0; + while (DC) { + if (isa(DC)) { + LookupQualifiedName(R, DC); + + if (!R.empty()) { + // Don't give errors about ambiguities in this lookup. + R.suppressDiagnostics(); + + // During a default argument instantiation the CurContext points + // to a CXXMethodDecl; but we can't apply a this-> fixit inside a + // function parameter list, hence add an explicit check. + bool isDefaultArgument = !ActiveTemplateInstantiations.empty() && + ActiveTemplateInstantiations.back().Kind == + ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation; + CXXMethodDecl *CurMethod = dyn_cast(CurContext); + bool isInstance = CurMethod && + CurMethod->isInstance() && + DC == CurMethod->getParent() && !isDefaultArgument; + + + // Give a code modification hint to insert 'this->'. + // TODO: fixit for inserting 'Base::' in the other cases. + // Actually quite difficult! + if (isInstance) { + UnresolvedLookupExpr *ULE = cast( + CallsUndergoingInstantiation.back()->getCallee()); + CXXMethodDecl *DepMethod = cast_or_null( + CurMethod->getInstantiatedFromMemberFunction()); + if (DepMethod) { + if (getLangOpts().MicrosoftMode) + diagnostic = diag::warn_found_via_dependent_bases_lookup; + Diag(R.getNameLoc(), diagnostic) << Name + << FixItHint::CreateInsertion(R.getNameLoc(), "this->"); + QualType DepThisType = DepMethod->getThisType(Context); + CheckCXXThisCapture(R.getNameLoc()); + CXXThisExpr *DepThis = new (Context) CXXThisExpr( + R.getNameLoc(), DepThisType, false); + TemplateArgumentListInfo TList; + if (ULE->hasExplicitTemplateArgs()) + ULE->copyTemplateArgumentsInto(TList); + + CXXScopeSpec SS; + SS.Adopt(ULE->getQualifierLoc()); + CXXDependentScopeMemberExpr *DepExpr = + CXXDependentScopeMemberExpr::Create( + Context, DepThis, DepThisType, true, SourceLocation(), + SS.getWithLocInContext(Context), + ULE->getTemplateKeywordLoc(), 0, + R.getLookupNameInfo(), + ULE->hasExplicitTemplateArgs() ? &TList : 0); + 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 { + if (getLangOpts().MicrosoftMode) + diagnostic = diag::warn_found_via_dependent_bases_lookup; + Diag(R.getNameLoc(), diagnostic) << Name; + } + + // Do we really want to note all of these? + for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) + Diag((*I)->getLocation(), diag::note_dependent_var_use); + + // Return true if we are inside a default argument instantiation + // and the found name refers to an instance member function, otherwise + // the function calling DiagnoseEmptyLookup will try to create an + // implicit member call and this is wrong for default argument. + if (isDefaultArgument && ((*R.begin())->isCXXInstanceMember())) { + Diag(R.getNameLoc(), diag::err_member_call_without_object); + return true; + } + + // Tell the callee to try to recover. + return false; + } + + R.clear(); + } + + // In Microsoft mode, if we are performing lookup from within a friend + // function definition declared at class scope then we must set + // DC to the lexical parent to be able to search into the parent + // class. + if (getLangOpts().MicrosoftMode && isa(DC) && + cast(DC)->getFriendObjectKind() && + DC->getLexicalParent()->isRecord()) + DC = DC->getLexicalParent(); + else + DC = DC->getParent(); + } + + // We didn't find anything, so try to correct for a typo. + TypoCorrection Corrected; + if (S && (Corrected = CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), + S, &SS, CCC))) { + std::string CorrectedStr(Corrected.getAsString(getLangOpts())); + std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOpts())); + R.setLookupName(Corrected.getCorrection()); + + if (NamedDecl *ND = Corrected.getCorrectionDecl()) { + if (Corrected.isOverloaded()) { + OverloadCandidateSet OCS(R.getNameLoc()); + OverloadCandidateSet::iterator Best; + for (TypoCorrection::decl_iterator CD = Corrected.begin(), + CDEnd = Corrected.end(); + CD != CDEnd; ++CD) { + if (FunctionTemplateDecl *FTD = + dyn_cast(*CD)) + AddTemplateOverloadCandidate( + FTD, DeclAccessPair::make(FTD, AS_none), ExplicitTemplateArgs, + Args, OCS); + else if (FunctionDecl *FD = dyn_cast(*CD)) + if (!ExplicitTemplateArgs || ExplicitTemplateArgs->size() == 0) + AddOverloadCandidate(FD, DeclAccessPair::make(FD, AS_none), + Args, OCS); + } + switch (OCS.BestViableFunction(*this, R.getNameLoc(), Best)) { + case OR_Success: + ND = Best->Function; + break; + default: + break; + } + } + R.addDecl(ND); + if (isa(ND) || isa(ND)) { + if (SS.isEmpty()) + Diag(R.getNameLoc(), diagnostic_suggest) << Name << CorrectedQuotedStr + << FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr); + else + Diag(R.getNameLoc(), diag::err_no_member_suggest) + << Name << computeDeclContext(SS, false) << CorrectedQuotedStr + << SS.getRange() + << FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr); + if (ND) + Diag(ND->getLocation(), diag::note_previous_decl) + << CorrectedQuotedStr; + + // Tell the callee to try to recover. + return false; + } + + if (isa(ND) || isa(ND)) { + // FIXME: If we ended up with a typo for a type name or + // Objective-C class name, we're in trouble because the parser + // is in the wrong place to recover. Suggest the typo + // correction, but don't make it a fix-it since we're not going + // to recover well anyway. + if (SS.isEmpty()) + Diag(R.getNameLoc(), diagnostic_suggest) + << Name << CorrectedQuotedStr; + else + Diag(R.getNameLoc(), diag::err_no_member_suggest) + << Name << computeDeclContext(SS, false) << CorrectedQuotedStr + << SS.getRange(); + + // Don't try to recover; it won't work. + return true; + } + } else { + // FIXME: We found a keyword. Suggest it, but don't provide a fix-it + // because we aren't able to recover. + if (SS.isEmpty()) + Diag(R.getNameLoc(), diagnostic_suggest) << Name << CorrectedQuotedStr; + else + Diag(R.getNameLoc(), diag::err_no_member_suggest) + << Name << computeDeclContext(SS, false) << CorrectedQuotedStr + << SS.getRange(); + return true; + } + } + R.clear(); + + // Emit a special diagnostic for failed member lookups. + // FIXME: computing the declaration context might fail here (?) + if (!SS.isEmpty()) { + Diag(R.getNameLoc(), diag::err_no_member) + << Name << computeDeclContext(SS, false) + << SS.getRange(); + return true; + } + + // Give up, we can't recover. + Diag(R.getNameLoc(), diagnostic) << Name; + return true; +} + +ExprResult Sema::ActOnIdExpression(Scope *S, + CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, + UnqualifiedId &Id, + bool HasTrailingLParen, + bool IsAddressOfOperand, + CorrectionCandidateCallback *CCC) { + assert(!(IsAddressOfOperand && HasTrailingLParen) && + "cannot be direct & operand and have a trailing lparen"); + + if (SS.isInvalid()) + return ExprError(); + + TemplateArgumentListInfo TemplateArgsBuffer; + + // Decompose the UnqualifiedId into the following data. + DeclarationNameInfo NameInfo; + const TemplateArgumentListInfo *TemplateArgs; + DecomposeUnqualifiedId(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: + // -- an identifier that was declared with a dependent type, + // (note: handled after lookup) + // -- a template-id that is dependent, + // (note: handled in BuildTemplateIdExpr) + // -- a conversion-function-id that specifies a dependent type, + // -- a nested-name-specifier that contains a class-name that + // names a dependent type. + // Determine whether this is a member of an unknown specialization; + // we need to handle these differently. + bool DependentID = false; + if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName && + Name.getCXXNameType()->isDependentType()) { + DependentID = true; + } else if (SS.isSet()) { + if (DeclContext *DC = computeDeclContext(SS, false)) { + if (RequireCompleteDeclContext(SS, DC)) + return ExprError(); + } else { + DependentID = true; + } + } + + if (DependentID) + return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo, + IsAddressOfOperand, TemplateArgs); + + // Perform the required lookup. + LookupResult R(*this, NameInfo, + (Id.getKind() == UnqualifiedId::IK_ImplicitSelfParam) + ? LookupObjCImplicitSelfParam : 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 + // lookup to determine that it was a template name in the first place. If + // this becomes a performance hit, we can work harder to preserve those + // results until we get here but it's likely not worth it. + bool MemberOfUnknownSpecialization; + LookupTemplateName(R, S, SS, QualType(), /*EnteringContext=*/false, + MemberOfUnknownSpecialization); + + if (MemberOfUnknownSpecialization || + (R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation)) + return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo, + IsAddressOfOperand, TemplateArgs); + } else { + bool IvarLookupFollowUp = II && !SS.isSet() && getCurMethodDecl(); + LookupParsedName(R, S, &SS, !IvarLookupFollowUp); + + // If the result might be in a dependent base class, this is a dependent + // id-expression. + if (R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation) + return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo, + IsAddressOfOperand, TemplateArgs); + + // If this reference is in an Objective-C method, then we need to do + // some special Objective-C lookup, too. + if (IvarLookupFollowUp) { + ExprResult E(LookupInObjCMethod(R, S, II, true)); + if (E.isInvalid()) + return ExprError(); + + if (Expr *Ex = E.takeAs()) + return Owned(Ex); + } + } + + if (R.isAmbiguous()) + return ExprError(); + + // Determine whether this name might be a candidate for + // argument-dependent lookup. + bool ADL = UseArgumentDependentLookup(SS, R, HasTrailingLParen); + + if (R.empty() && !ADL) { + // Otherwise, this could be an implicitly declared function reference (legal + // in C90, extension in C99, forbidden in C++). + if (HasTrailingLParen && II && !getLangOpts().CPlusPlus) { + NamedDecl *D = ImplicitlyDefineFunction(NameLoc, *II, S); + if (D) R.addDecl(D); + } + + // If this name wasn't predeclared and if this is not a function + // call, diagnose the problem. + if (R.empty()) { + + // In Microsoft mode, if we are inside a template class member function + // and we can't resolve an identifier then assume the identifier is type + // dependent. The goal is to postpone name lookup to instantiation time + // to be able to search into type dependent base classes. + if (getLangOpts().MicrosoftMode && CurContext->isDependentContext() && + isa(CurContext)) + return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo, + IsAddressOfOperand, TemplateArgs); + + CorrectionCandidateCallback DefaultValidator; + if (DiagnoseEmptyLookup(S, SS, R, CCC ? *CCC : DefaultValidator)) + return ExprError(); + + assert(!R.empty() && + "DiagnoseEmptyLookup returned false but added no results"); + + // If we found an Objective-C instance variable, let + // LookupInObjCMethod build the appropriate expression to + // reference the ivar. + if (ObjCIvarDecl *Ivar = R.getAsSingle()) { + R.clear(); + ExprResult E(LookupInObjCMethod(R, S, Ivar->getIdentifier())); + // In a hopelessly buggy code, Objective-C instance variable + // lookup fails and no expression will be built to reference it. + if (!E.isInvalid() && !E.get()) + return ExprError(); + return move(E); + } + } + } + + // This is guaranteed from this point on. + assert(!R.empty() || ADL); + + // Check whether this might be a C++ implicit instance member access. + // 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 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()) || + isa(R.getFoundDecl()); + + if (MightBeImplicitMember) + return BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc, + R, TemplateArgs); + } + + if (TemplateArgs || TemplateKWLoc.isValid()) + return BuildTemplateIdExpr(SS, TemplateKWLoc, R, ADL, TemplateArgs); + + return BuildDeclarationNameExpr(SS, R, ADL); +} + +/// BuildQualifiedDeclarationNameExpr - Build a C++ qualified +/// declaration name, generally during template instantiation. +/// There's a large number of things which don't need to be done along +/// this path. +ExprResult +Sema::BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS, + const DeclarationNameInfo &NameInfo) { + DeclContext *DC; + if (!(DC = computeDeclContext(SS, false)) || DC->isDependentContext()) + return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(), + NameInfo, /*TemplateArgs=*/0); + + if (RequireCompleteDeclContext(SS, DC)) + return ExprError(); + + LookupResult R(*this, NameInfo, LookupOrdinaryName); + LookupQualifiedName(R, DC); + + if (R.isAmbiguous()) + return ExprError(); + + if (R.empty()) { + Diag(NameInfo.getLoc(), diag::err_no_member) + << NameInfo.getName() << DC << SS.getRange(); + return ExprError(); + } + + return BuildDeclarationNameExpr(SS, R, /*ADL*/ false); +} + +/// LookupInObjCMethod - The parser has read a name in, and Sema has +/// detected that we're currently inside an ObjC method. Perform some +/// additional lookup. +/// +/// Ideally, most of this would be done by lookup, but there's +/// actually quite a lot of extra work involved. +/// +/// Returns a null sentinel to indicate trivial success. +ExprResult +Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S, + IdentifierInfo *II, bool AllowBuiltinCreation) { + SourceLocation Loc = Lookup.getNameLoc(); + ObjCMethodDecl *CurMethod = getCurMethodDecl(); + + // There are two cases to handle here. 1) scoped lookup could have failed, + // in which case we should look for an ivar. 2) scoped lookup could have + // found a decl, but that decl is outside the current instance method (i.e. + // a global variable). In these two cases, we do a lookup for an ivar with + // this name, if the lookup sucedes, we replace it our current decl. + + // If we're in a class method, we don't normally want to look for + // ivars. But if we don't find anything else, and there's an + // ivar, that's an error. + bool IsClassMethod = CurMethod->isClassMethod(); + + bool LookForIvars; + if (Lookup.empty()) + LookForIvars = true; + else if (IsClassMethod) + LookForIvars = false; + else + LookForIvars = (Lookup.isSingleResult() && + Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod()); + ObjCInterfaceDecl *IFace = 0; + if (LookForIvars) { + IFace = CurMethod->getClassInterface(); + ObjCInterfaceDecl *ClassDeclared; + ObjCIvarDecl *IV = 0; + if (IFace && (IV = IFace->lookupInstanceVariable(II, ClassDeclared))) { + // Diagnose using an ivar in a class method. + if (IsClassMethod) + return ExprError(Diag(Loc, diag::error_ivar_use_in_class_method) + << IV->getDeclName()); + + // If we're referencing an invalid decl, just return this as a silent + // error node. The error diagnostic was already emitted on the decl. + if (IV->isInvalidDecl()) + return ExprError(); + + // Check if referencing a field with __attribute__((deprecated)). + if (DiagnoseUseOfDecl(IV, Loc)) + return ExprError(); + + // Diagnose the use of an ivar outside of the declaring class. + if (IV->getAccessControl() == ObjCIvarDecl::Private && + !declaresSameEntity(ClassDeclared, IFace) && + !getLangOpts().DebuggerSupport) + Diag(Loc, diag::error_private_ivar_access) << IV->getDeclName(); + + // FIXME: This should use a new expr for a direct reference, don't + // turn this into Self->ivar, just return a BareIVarExpr or something. + IdentifierInfo &II = Context.Idents.get("self"); + UnqualifiedId SelfName; + SelfName.setIdentifier(&II, SourceLocation()); + SelfName.setKind(UnqualifiedId::IK_ImplicitSelfParam); + CXXScopeSpec SelfScopeSpec; + SourceLocation TemplateKWLoc; + ExprResult SelfExpr = ActOnIdExpression(S, SelfScopeSpec, TemplateKWLoc, + SelfName, false, false); + if (SelfExpr.isInvalid()) + return ExprError(); + + SelfExpr = DefaultLvalueConversion(SelfExpr.take()); + if (SelfExpr.isInvalid()) + return ExprError(); + + MarkAnyDeclReferenced(Loc, IV); + return Owned(new (Context) + ObjCIvarRefExpr(IV, IV->getType(), Loc, + SelfExpr.take(), true, true)); + } + } else if (CurMethod->isInstanceMethod()) { + // We should warn if a local variable hides an ivar. + if (ObjCInterfaceDecl *IFace = CurMethod->getClassInterface()) { + ObjCInterfaceDecl *ClassDeclared; + if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) { + if (IV->getAccessControl() != ObjCIvarDecl::Private || + declaresSameEntity(IFace, ClassDeclared)) + Diag(Loc, diag::warn_ivar_use_hidden) << IV->getDeclName(); + } + } + } else if (Lookup.isSingleResult() && + Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod()) { + // If accessing a stand-alone ivar in a class method, this is an error. + if (const ObjCIvarDecl *IV = dyn_cast(Lookup.getFoundDecl())) + return ExprError(Diag(Loc, diag::error_ivar_use_in_class_method) + << IV->getDeclName()); + } + + if (Lookup.empty() && II && AllowBuiltinCreation) { + // FIXME. Consolidate this with similar code in LookupName. + if (unsigned BuiltinID = II->getBuiltinID()) { + if (!(getLangOpts().CPlusPlus && + Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))) { + NamedDecl *D = LazilyCreateBuiltin((IdentifierInfo *)II, BuiltinID, + S, Lookup.isForRedeclaration(), + Lookup.getNameLoc()); + if (D) Lookup.addDecl(D); + } + } + } + // Sentinel value saying that we didn't do anything special. + return Owned((Expr*) 0); +} + +/// \brief Cast a base object to a member's actual type. +/// +/// Logically this happens in three phases: +/// +/// * First we cast from the base type to the naming class. +/// The naming class is the class into which we were looking +/// when we found the member; it's the qualifier type if a +/// qualifier was provided, and otherwise it's the base type. +/// +/// * Next we cast from the naming class to the declaring class. +/// If the member we found was brought into a class's scope by +/// a using declaration, this is that class; otherwise it's +/// the class declaring the member. +/// +/// * Finally we cast from the declaring class to the "true" +/// declaring class of the member. This conversion does not +/// obey access control. +ExprResult +Sema::PerformObjectMemberConversion(Expr *From, + NestedNameSpecifier *Qualifier, + NamedDecl *FoundDecl, + NamedDecl *Member) { + CXXRecordDecl *RD = dyn_cast(Member->getDeclContext()); + if (!RD) + return Owned(From); + + QualType DestRecordType; + QualType DestType; + QualType FromRecordType; + QualType FromType = From->getType(); + bool PointerConversions = false; + if (isa(Member)) { + DestRecordType = Context.getCanonicalType(Context.getTypeDeclType(RD)); + + if (FromType->getAs()) { + DestType = Context.getPointerType(DestRecordType); + FromRecordType = FromType->getPointeeType(); + PointerConversions = true; + } else { + DestType = DestRecordType; + FromRecordType = FromType; + } + } else if (CXXMethodDecl *Method = dyn_cast(Member)) { + if (Method->isStatic()) + return Owned(From); + + DestType = Method->getThisType(Context); + DestRecordType = DestType->getPointeeType(); + + if (FromType->getAs()) { + FromRecordType = FromType->getPointeeType(); + PointerConversions = true; + } else { + FromRecordType = FromType; + DestType = DestRecordType; + } + } else { + // No conversion necessary. + return Owned(From); + } + + if (DestType->isDependentType() || FromType->isDependentType()) + return Owned(From); + + // If the unqualified types are the same, no conversion is necessary. + if (Context.hasSameUnqualifiedType(FromRecordType, DestRecordType)) + return Owned(From); + + SourceRange FromRange = From->getSourceRange(); + SourceLocation FromLoc = FromRange.getBegin(); + + ExprValueKind VK = From->getValueKind(); + + // C++ [class.member.lookup]p8: + // [...] Ambiguities can often be resolved by qualifying a name with its + // class name. + // + // If the member was a qualified name and the qualified referred to a + // specific base subobject type, we'll cast to that intermediate type + // first and then to the object in which the member is declared. That allows + // one to resolve ambiguities in, e.g., a diamond-shaped hierarchy such as: + // + // class Base { public: int x; }; + // class Derived1 : public Base { }; + // class Derived2 : public Base { }; + // class VeryDerived : public Derived1, public Derived2 { void f(); }; + // + // void VeryDerived::f() { + // x = 17; // error: ambiguous base subobjects + // Derived1::x = 17; // okay, pick the Base subobject of Derived1 + // } + if (Qualifier) { + QualType QType = QualType(Qualifier->getAsType(), 0); + assert(!QType.isNull() && "lookup done with dependent qualifier?"); + assert(QType->isRecordType() && "lookup done with non-record type"); + + QualType QRecordType = QualType(QType->getAs(), 0); + + // In C++98, the qualifier type doesn't actually have to be a base + // type of the object type, in which case we just ignore it. + // Otherwise build the appropriate casts. + if (IsDerivedFrom(FromRecordType, QRecordType)) { + CXXCastPath BasePath; + if (CheckDerivedToBaseConversion(FromRecordType, QRecordType, + FromLoc, FromRange, &BasePath)) + return ExprError(); + + if (PointerConversions) + QType = Context.getPointerType(QType); + From = ImpCastExprToType(From, QType, CK_UncheckedDerivedToBase, + VK, &BasePath).take(); + + FromType = QType; + FromRecordType = QRecordType; + + // If the qualifier type was the same as the destination type, + // we're done. + if (Context.hasSameUnqualifiedType(FromRecordType, DestRecordType)) + return Owned(From); + } + } + + bool IgnoreAccess = false; + + // If we actually found the member through a using declaration, cast + // down to the using declaration's type. + // + // Pointer equality is fine here because only one declaration of a + // class ever has member declarations. + if (FoundDecl->getDeclContext() != Member->getDeclContext()) { + assert(isa(FoundDecl)); + QualType URecordType = Context.getTypeDeclType( + cast(FoundDecl->getDeclContext())); + + // We only need to do this if the naming-class to declaring-class + // conversion is non-trivial. + if (!Context.hasSameUnqualifiedType(FromRecordType, URecordType)) { + assert(IsDerivedFrom(FromRecordType, URecordType)); + CXXCastPath BasePath; + if (CheckDerivedToBaseConversion(FromRecordType, URecordType, + FromLoc, FromRange, &BasePath)) + return ExprError(); + + QualType UType = URecordType; + if (PointerConversions) + UType = Context.getPointerType(UType); + From = ImpCastExprToType(From, UType, CK_UncheckedDerivedToBase, + VK, &BasePath).take(); + FromType = UType; + FromRecordType = URecordType; + } + + // We don't do access control for the conversion from the + // declaring class to the true declaring class. + IgnoreAccess = true; + } + + CXXCastPath BasePath; + if (CheckDerivedToBaseConversion(FromRecordType, DestRecordType, + FromLoc, FromRange, &BasePath, + IgnoreAccess)) + return ExprError(); + + return ImpCastExprToType(From, DestType, CK_UncheckedDerivedToBase, + VK, &BasePath); +} + +bool Sema::UseArgumentDependentLookup(const CXXScopeSpec &SS, + const LookupResult &R, + bool HasTrailingLParen) { + // Only when used directly as the postfix-expression of a call. + if (!HasTrailingLParen) + return false; + + // Never if a scope specifier was provided. + if (SS.isSet()) + return false; + + // Only in C++ or ObjC++. + if (!getLangOpts().CPlusPlus) + return false; + + // Turn off ADL when we find certain kinds of declarations during + // normal lookup: + for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { + NamedDecl *D = *I; + + // C++0x [basic.lookup.argdep]p3: + // -- a declaration of a class member + // Since using decls preserve this property, we check this on the + // original decl. + if (D->isCXXClassMember()) + return false; + + // C++0x [basic.lookup.argdep]p3: + // -- a block-scope function declaration that is not a + // using-declaration + // NOTE: we also trigger this for function templates (in fact, we + // don't check the decl type at all, since all other decl types + // turn off ADL anyway). + if (isa(D)) + D = cast(D)->getTargetDecl(); + else if (D->getDeclContext()->isFunctionOrMethod()) + return false; + + // C++0x [basic.lookup.argdep]p3: + // -- a declaration that is neither a function or a function + // template + // And also for builtin functions. + if (isa(D)) { + FunctionDecl *FDecl = cast(D); + + // But also builtin functions. + if (FDecl->getBuiltinID() && FDecl->isImplicit()) + return false; + } else if (!isa(D)) + return false; + } + + return true; +} + + +/// Diagnoses obvious problems with the use of the given declaration +/// as an expression. This is only actually called for lookups that +/// were not overloaded, and it doesn't promise that the declaration +/// will in fact be used. +static bool CheckDeclInExpr(Sema &S, SourceLocation Loc, NamedDecl *D) { + if (isa(D)) { + S.Diag(Loc, diag::err_unexpected_typedef) << D->getDeclName(); + return true; + } + + if (isa(D)) { + S.Diag(Loc, diag::err_unexpected_interface) << D->getDeclName(); + return true; + } + + if (isa(D)) { + S.Diag(Loc, diag::err_unexpected_namespace) << D->getDeclName(); + return true; + } + + return false; +} + +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.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 + // functions and function templates. + if (R.isSingleResult() && + CheckDeclInExpr(*this, R.getNameLoc(), R.getFoundDecl())) + return ExprError(); + + // Otherwise, just build an unresolved lookup expression. Suppress + // any lookup-related diagnostics; we'll hash these out later, when + // we've picked a target. + R.suppressDiagnostics(); + + UnresolvedLookupExpr *ULE + = UnresolvedLookupExpr::Create(Context, R.getNamingClass(), + SS.getWithLocInContext(Context), + R.getLookupNameInfo(), + NeedsADL, R.isOverloadedResult(), + R.begin(), R.end()); + + return Owned(ULE); +} + +/// \brief Complete semantic analysis for a reference to the given declaration. +ExprResult +Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, + 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(); + + if (TemplateDecl *Template = dyn_cast(D)) { + // Specifically diagnose references to class templates that are missing + // a template argument list. + Diag(Loc, diag::err_template_decl_ref) + << Template << SS.getRange(); + Diag(Template->getLocation(), diag::note_template_decl_here); + return ExprError(); + } + + // Make sure that we're referring to a value. + ValueDecl *VD = dyn_cast(D); + if (!VD) { + Diag(Loc, diag::err_ref_non_value) + << D << SS.getRange(); + Diag(D->getLocation(), diag::note_declared_at); + return ExprError(); + } + + // Check whether this declaration can be used. Note that we suppress + // this check when we're going to perform argument-dependent lookup + // on this function name, because this might not be the function + // that overload resolution actually selects. + if (DiagnoseUseOfDecl(VD, Loc)) + return ExprError(); + + // Only create DeclRefExpr's for valid Decl's. + if (VD->isInvalidDecl()) + return ExprError(); + + // Handle members of anonymous structs and unions. If we got here, + // and the reference is to a class member indirect field, then this + // must be the subject of a pointer-to-member expression. + if (IndirectFieldDecl *indirectField = dyn_cast(VD)) + if (!indirectField->isCXXClassMember()) + return BuildAnonymousStructUnionMemberReference(SS, NameInfo.getLoc(), + indirectField); + + { + QualType type = VD->getType(); + ExprValueKind valueKind = VK_RValue; + + switch (D->getKind()) { + // Ignore all the non-ValueDecl kinds. +#define ABSTRACT_DECL(kind) +#define VALUE(type, base) +#define DECL(type, base) \ + case Decl::type: +#include "clang/AST/DeclNodes.inc" + llvm_unreachable("invalid value decl kind"); + + // These shouldn't make it here. + case Decl::ObjCAtDefsField: + case Decl::ObjCIvar: + llvm_unreachable("forming non-member reference to ivar?"); + + // Enum constants are always r-values and never references. + // Unresolved using declarations are dependent. + case Decl::EnumConstant: + case Decl::UnresolvedUsingValue: + valueKind = VK_RValue; + break; + + // Fields and indirect fields that got here must be for + // pointer-to-member expressions; we just call them l-values for + // internal consistency, because this subexpression doesn't really + // exist in the high-level semantics. + case Decl::Field: + case Decl::IndirectField: + assert(getLangOpts().CPlusPlus && + "building reference to field in C?"); + + // These can't have reference type in well-formed programs, but + // for internal consistency we do this anyway. + type = type.getNonReferenceType(); + valueKind = VK_LValue; + break; + + // Non-type template parameters are either l-values or r-values + // depending on the type. + case Decl::NonTypeTemplateParm: { + if (const ReferenceType *reftype = type->getAs()) { + type = reftype->getPointeeType(); + valueKind = VK_LValue; // even if the parameter is an r-value reference + break; + } + + // For non-references, we need to strip qualifiers just in case + // the template parameter was declared as 'const int' or whatever. + valueKind = VK_RValue; + type = type.getUnqualifiedType(); + break; + } + + case Decl::Var: + // In C, "extern void blah;" is valid and is an r-value. + if (!getLangOpts().CPlusPlus && + !type.hasQualifiers() && + type->isVoidType()) { + valueKind = VK_RValue; + break; + } + // fallthrough + + case Decl::ImplicitParam: + case Decl::ParmVar: { + // These are always l-values. + valueKind = VK_LValue; + type = type.getNonReferenceType(); + + // FIXME: Does the addition of const really only apply in + // potentially-evaluated contexts? Since the variable isn't actually + // captured in an unevaluated context, it seems that the answer is no. + if (ExprEvalContexts.back().Context != Sema::Unevaluated) { + QualType CapturedType = getCapturedDeclRefType(cast(VD), Loc); + if (!CapturedType.isNull()) + type = CapturedType; + } + + break; + } + + case Decl::Function: { + const FunctionType *fty = type->castAs(); + + // If we're referring to a function with an __unknown_anytype + // result type, make the entire expression __unknown_anytype. + if (fty->getResultType() == Context.UnknownAnyTy) { + type = Context.UnknownAnyTy; + valueKind = VK_RValue; + break; + } + + // Functions are l-values in C++. + if (getLangOpts().CPlusPlus) { + valueKind = VK_LValue; + break; + } + + // C99 DR 316 says that, if a function type comes from a + // function definition (without a prototype), that type is only + // used for checking compatibility. Therefore, when referencing + // the function, we pretend that we don't have the full function + // type. + if (!cast(VD)->hasPrototype() && + isa(fty)) + type = Context.getFunctionNoProtoType(fty->getResultType(), + fty->getExtInfo()); + + // Functions are r-values in C. + valueKind = VK_RValue; + break; + } + + case Decl::CXXMethod: + // If we're referring to a method with an __unknown_anytype + // result type, make the entire expression __unknown_anytype. + // This should only be possible with a type written directly. + if (const FunctionProtoType *proto + = dyn_cast(VD->getType())) + if (proto->getResultType() == Context.UnknownAnyTy) { + type = Context.UnknownAnyTy; + valueKind = VK_RValue; + break; + } + + // C++ methods are l-values if static, r-values if non-static. + if (cast(VD)->isStatic()) { + valueKind = VK_LValue; + break; + } + // fallthrough + + case Decl::CXXConversion: + case Decl::CXXDestructor: + case Decl::CXXConstructor: + valueKind = VK_RValue; + break; + } + + return BuildDeclRefExpr(VD, type, valueKind, NameInfo, &SS); + } +} + +ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) { + PredefinedExpr::IdentType IT; + + switch (Kind) { + default: llvm_unreachable("Unknown simple primary expr!"); + case tok::kw___func__: IT = PredefinedExpr::Func; break; // [C99 6.4.2.2] + case tok::kw___FUNCTION__: IT = PredefinedExpr::Function; break; + case tok::kw___PRETTY_FUNCTION__: IT = PredefinedExpr::PrettyFunction; break; + } + + // Pre-defined identifiers are of type char[x], where x is the length of the + // string. + + Decl *currentDecl = getCurFunctionOrMethodDecl(); + if (!currentDecl && getCurBlock()) + currentDecl = getCurBlock()->TheDecl; + if (!currentDecl) { + Diag(Loc, diag::ext_predef_outside_function); + currentDecl = Context.getTranslationUnitDecl(); + } + + QualType ResTy; + if (cast(currentDecl)->isDependentContext()) { + ResTy = Context.DependentTy; + } else { + unsigned Length = PredefinedExpr::ComputeName(IT, currentDecl).length(); + + llvm::APInt LengthI(32, Length + 1); + ResTy = Context.CharTy.withConst(); + ResTy = Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal, 0); + } + return Owned(new (Context) PredefinedExpr(Loc, ResTy, IT)); +} + +ExprResult Sema::ActOnCharacterConstant(const Token &Tok, Scope *UDLScope) { + SmallString<16> CharBuffer; + bool Invalid = false; + StringRef ThisTok = PP.getSpelling(Tok, CharBuffer, &Invalid); + if (Invalid) + return ExprError(); + + CharLiteralParser Literal(ThisTok.begin(), ThisTok.end(), Tok.getLocation(), + PP, Tok.getKind()); + if (Literal.hadError()) + return ExprError(); + + QualType Ty; + if (Literal.isWide()) + Ty = Context.WCharTy; // L'x' -> wchar_t in C and C++. + else if (Literal.isUTF16()) + Ty = Context.Char16Ty; // u'x' -> char16_t in C11 and C++11. + else if (Literal.isUTF32()) + Ty = Context.Char32Ty; // U'x' -> char32_t in C11 and C++11. + else if (!getLangOpts().CPlusPlus || Literal.isMultiChar()) + Ty = Context.IntTy; // 'x' -> int in C, 'wxyz' -> int in C++. + else + Ty = Context.CharTy; // 'x' -> char in C++ + + CharacterLiteral::CharacterKind Kind = CharacterLiteral::Ascii; + if (Literal.isWide()) + Kind = CharacterLiteral::Wide; + else if (Literal.isUTF16()) + Kind = CharacterLiteral::UTF16; + else if (Literal.isUTF32()) + Kind = CharacterLiteral::UTF32; + + Expr *Lit = new (Context) CharacterLiteral(Literal.getValue(), Kind, Ty, + Tok.getLocation()); + + if (Literal.getUDSuffix().empty()) + return Owned(Lit); + + // We're building a user-defined literal. + IdentifierInfo *UDSuffix = &Context.Idents.get(Literal.getUDSuffix()); + SourceLocation UDSuffixLoc = + getUDSuffixLoc(*this, Tok.getLocation(), Literal.getUDSuffixOffset()); + + // Make sure we're allowed user-defined literals here. + if (!UDLScope) + return ExprError(Diag(UDSuffixLoc, diag::err_invalid_character_udl)); + + // C++11 [lex.ext]p6: The literal L is treated as a call of the form + // operator "" X (ch) + return BuildCookedLiteralOperatorCall(*this, UDLScope, UDSuffix, UDSuffixLoc, + llvm::makeArrayRef(&Lit, 1), + Tok.getLocation()); +} + +ExprResult Sema::ActOnIntegerConstant(SourceLocation Loc, uint64_t Val) { + unsigned IntSize = Context.getTargetInfo().getIntWidth(); + return Owned(IntegerLiteral::Create(Context, llvm::APInt(IntSize, Val), + Context.IntTy, Loc)); +} + +static Expr *BuildFloatingLiteral(Sema &S, NumericLiteralParser &Literal, + QualType Ty, SourceLocation Loc) { + const llvm::fltSemantics &Format = S.Context.getFloatTypeSemantics(Ty); + + using llvm::APFloat; + APFloat Val(Format); + + APFloat::opStatus result = Literal.GetFloatValue(Val); + + // Overflow is always an error, but underflow is only an error if + // we underflowed to zero (APFloat reports denormals as underflow). + if ((result & APFloat::opOverflow) || + ((result & APFloat::opUnderflow) && Val.isZero())) { + unsigned diagnostic; + SmallString<20> buffer; + if (result & APFloat::opOverflow) { + diagnostic = diag::warn_float_overflow; + APFloat::getLargest(Format).toString(buffer); + } else { + diagnostic = diag::warn_float_underflow; + APFloat::getSmallest(Format).toString(buffer); + } + + S.Diag(Loc, diagnostic) + << Ty + << StringRef(buffer.data(), buffer.size()); + } + + bool isExact = (result == APFloat::opOK); + return FloatingLiteral::Create(S.Context, Val, isExact, Ty, Loc); +} + +ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { + // Fast path for a single digit (which is quite common). A single digit + // cannot have a trigraph, escaped newline, radix prefix, or suffix. + if (Tok.getLength() == 1) { + const char Val = PP.getSpellingOfSingleCharacterNumericConstant(Tok); + return ActOnIntegerConstant(Tok.getLocation(), Val-'0'); + } + + SmallString<512> IntegerBuffer; + // Add padding so that NumericLiteralParser can overread by one character. + IntegerBuffer.resize(Tok.getLength()+1); + const char *ThisTokBegin = &IntegerBuffer[0]; + + // Get the spelling of the token, which eliminates trigraphs, etc. + bool Invalid = false; + unsigned ActualLength = PP.getSpelling(Tok, ThisTokBegin, &Invalid); + if (Invalid) + return ExprError(); + + NumericLiteralParser Literal(ThisTokBegin, ThisTokBegin+ActualLength, + Tok.getLocation(), PP); + if (Literal.hadError) + return ExprError(); + + if (Literal.hasUDSuffix()) { + // We're building a user-defined literal. + IdentifierInfo *UDSuffix = &Context.Idents.get(Literal.getUDSuffix()); + SourceLocation UDSuffixLoc = + getUDSuffixLoc(*this, Tok.getLocation(), Literal.getUDSuffixOffset()); + + // Make sure we're allowed user-defined literals here. + if (!UDLScope) + return ExprError(Diag(UDSuffixLoc, diag::err_invalid_numeric_udl)); + + QualType CookedTy; + if (Literal.isFloatingLiteral()) { + // C++11 [lex.ext]p4: If S contains a literal operator with parameter type + // long double, the literal is treated as a call of the form + // operator "" X (f L) + CookedTy = Context.LongDoubleTy; + } else { + // C++11 [lex.ext]p3: If S contains a literal operator with parameter type + // unsigned long long, the literal is treated as a call of the form + // operator "" X (n ULL) + CookedTy = Context.UnsignedLongLongTy; + } + + DeclarationName OpName = + Context.DeclarationNames.getCXXLiteralOperatorName(UDSuffix); + DeclarationNameInfo OpNameInfo(OpName, UDSuffixLoc); + OpNameInfo.setCXXLiteralOperatorNameLoc(UDSuffixLoc); + + // Perform literal operator lookup to determine if we're building a raw + // literal or a cooked one. + LookupResult R(*this, OpName, UDSuffixLoc, LookupOrdinaryName); + switch (LookupLiteralOperator(UDLScope, R, llvm::makeArrayRef(&CookedTy, 1), + /*AllowRawAndTemplate*/true)) { + case LOLR_Error: + return ExprError(); + + case LOLR_Cooked: { + Expr *Lit; + if (Literal.isFloatingLiteral()) { + Lit = BuildFloatingLiteral(*this, Literal, CookedTy, Tok.getLocation()); + } else { + llvm::APInt ResultVal(Context.getTargetInfo().getLongLongWidth(), 0); + if (Literal.GetIntegerValue(ResultVal)) + Diag(Tok.getLocation(), diag::warn_integer_too_large); + Lit = IntegerLiteral::Create(Context, ResultVal, CookedTy, + Tok.getLocation()); + } + return BuildLiteralOperatorCall(R, OpNameInfo, + llvm::makeArrayRef(&Lit, 1), + Tok.getLocation()); + } + + case LOLR_Raw: { + // C++11 [lit.ext]p3, p4: If S contains a raw literal operator, the + // literal is treated as a call of the form + // operator "" X ("n") + SourceLocation TokLoc = Tok.getLocation(); + unsigned Length = Literal.getUDSuffixOffset(); + QualType StrTy = Context.getConstantArrayType( + Context.CharTy, llvm::APInt(32, Length + 1), + ArrayType::Normal, 0); + Expr *Lit = StringLiteral::Create( + Context, StringRef(ThisTokBegin, Length), StringLiteral::Ascii, + /*Pascal*/false, StrTy, &TokLoc, 1); + return BuildLiteralOperatorCall(R, OpNameInfo, + llvm::makeArrayRef(&Lit, 1), TokLoc); + } + + case LOLR_Template: + // C++11 [lit.ext]p3, p4: Otherwise (S contains a literal operator + // template), L is treated as a call fo the form + // operator "" X <'c1', 'c2', ... 'ck'>() + // where n is the source character sequence c1 c2 ... ck. + TemplateArgumentListInfo ExplicitArgs; + unsigned CharBits = Context.getIntWidth(Context.CharTy); + bool CharIsUnsigned = Context.CharTy->isUnsignedIntegerType(); + llvm::APSInt Value(CharBits, CharIsUnsigned); + for (unsigned I = 0, N = Literal.getUDSuffixOffset(); I != N; ++I) { + Value = ThisTokBegin[I]; + TemplateArgument Arg(Value, Context.CharTy); + TemplateArgumentLocInfo ArgInfo; + ExplicitArgs.addArgument(TemplateArgumentLoc(Arg, ArgInfo)); + } + return BuildLiteralOperatorCall(R, OpNameInfo, ArrayRef(), + Tok.getLocation(), &ExplicitArgs); + } + + llvm_unreachable("unexpected literal operator lookup result"); + } + + Expr *Res; + + if (Literal.isFloatingLiteral()) { + QualType Ty; + if (Literal.isFloat) + Ty = Context.FloatTy; + else if (!Literal.isLong) + Ty = Context.DoubleTy; + else + Ty = Context.LongDoubleTy; + + Res = BuildFloatingLiteral(*this, Literal, Ty, Tok.getLocation()); + + if (Ty == Context.DoubleTy) { + if (getLangOpts().SinglePrecisionConstants) { + Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).take(); + } else if (getLangOpts().OpenCL && !getOpenCLOptions().cl_khr_fp64) { + Diag(Tok.getLocation(), diag::warn_double_const_requires_fp64); + Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).take(); + } + } + } else if (!Literal.isIntegerLiteral()) { + return ExprError(); + } else { + QualType Ty; + + // long long is a C99 feature. + if (!getLangOpts().C99 && Literal.isLongLong) + Diag(Tok.getLocation(), + getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_longlong : diag::ext_longlong); + + // Get the value in the widest-possible width. + llvm::APInt ResultVal(Context.getTargetInfo().getIntMaxTWidth(), 0); + + if (Literal.GetIntegerValue(ResultVal)) { + // If this value didn't fit into uintmax_t, warn and force to ull. + Diag(Tok.getLocation(), diag::warn_integer_too_large); + Ty = Context.UnsignedLongLongTy; + assert(Context.getTypeSize(Ty) == ResultVal.getBitWidth() && + "long long is not intmax_t?"); + } else { + // If this value fits into a ULL, try to figure out what else it fits into + // according to the rules of C99 6.4.4.1p5. + + // Octal, Hexadecimal, and integers with a U suffix are allowed to + // be an unsigned int. + bool AllowUnsigned = Literal.isUnsigned || Literal.getRadix() != 10; + + // Check from smallest to largest, picking the smallest type we can. + unsigned Width = 0; + if (!Literal.isLong && !Literal.isLongLong) { + // Are int/unsigned possibilities? + unsigned IntSize = Context.getTargetInfo().getIntWidth(); + + // Does it fit in a unsigned int? + if (ResultVal.isIntN(IntSize)) { + // Does it fit in a signed int? + if (!Literal.isUnsigned && ResultVal[IntSize-1] == 0) + Ty = Context.IntTy; + else if (AllowUnsigned) + Ty = Context.UnsignedIntTy; + Width = IntSize; + } + } + + // Are long/unsigned long possibilities? + if (Ty.isNull() && !Literal.isLongLong) { + unsigned LongSize = Context.getTargetInfo().getLongWidth(); + + // Does it fit in a unsigned long? + if (ResultVal.isIntN(LongSize)) { + // Does it fit in a signed long? + if (!Literal.isUnsigned && ResultVal[LongSize-1] == 0) + Ty = Context.LongTy; + else if (AllowUnsigned) + Ty = Context.UnsignedLongTy; + Width = LongSize; + } + } + + // Finally, check long long if needed. + if (Ty.isNull()) { + unsigned LongLongSize = Context.getTargetInfo().getLongLongWidth(); + + // Does it fit in a unsigned long long? + if (ResultVal.isIntN(LongLongSize)) { + // Does it fit in a signed long long? + // To be compatible with MSVC, hex integer literals ending with the + // LL or i64 suffix are always signed in Microsoft mode. + if (!Literal.isUnsigned && (ResultVal[LongLongSize-1] == 0 || + (getLangOpts().MicrosoftExt && Literal.isLongLong))) + Ty = Context.LongLongTy; + else if (AllowUnsigned) + Ty = Context.UnsignedLongLongTy; + Width = LongLongSize; + } + } + + // If we still couldn't decide a type, we probably have something that + // does not fit in a signed long long, but has no U suffix. + if (Ty.isNull()) { + Diag(Tok.getLocation(), diag::warn_integer_too_large_for_signed); + Ty = Context.UnsignedLongLongTy; + Width = Context.getTargetInfo().getLongLongWidth(); + } + + if (ResultVal.getBitWidth() != Width) + ResultVal = ResultVal.trunc(Width); + } + Res = IntegerLiteral::Create(Context, ResultVal, Ty, Tok.getLocation()); + } + + // If this is an imaginary literal, create the ImaginaryLiteral wrapper. + if (Literal.isImaginary) + Res = new (Context) ImaginaryLiteral(Res, + Context.getComplexType(Res->getType())); + + return Owned(Res); +} + +ExprResult Sema::ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *E) { + assert((E != 0) && "ActOnParenExpr() missing expr"); + return Owned(new (Context) ParenExpr(L, R, E)); +} + +static bool CheckVecStepTraitOperandType(Sema &S, QualType T, + SourceLocation Loc, + SourceRange ArgRange) { + // [OpenCL 1.1 6.11.12] "The vec_step built-in function takes a built-in + // scalar or vector data type argument..." + // Every built-in scalar type (OpenCL 1.1 6.1.1) is either an arithmetic + // type (C99 6.2.5p18) or void. + if (!(T->isArithmeticType() || T->isVoidType() || T->isVectorType())) { + S.Diag(Loc, diag::err_vecstep_non_scalar_vector_type) + << T << ArgRange; + return true; + } + + assert((T->isVoidType() || !T->isIncompleteType()) && + "Scalar types should always be complete"); + return false; +} + +static bool CheckExtensionTraitOperandType(Sema &S, QualType T, + SourceLocation Loc, + SourceRange ArgRange, + UnaryExprOrTypeTrait TraitKind) { + // C99 6.5.3.4p1: + if (T->isFunctionType()) { + // alignof(function) is allowed as an extension. + if (TraitKind == UETT_SizeOf) + S.Diag(Loc, diag::ext_sizeof_function_type) << ArgRange; + return false; + } + + // Allow sizeof(void)/alignof(void) as an extension. + if (T->isVoidType()) { + S.Diag(Loc, diag::ext_sizeof_void_type) << TraitKind << ArgRange; + return false; + } + + return true; +} + +static bool CheckObjCTraitOperandConstraints(Sema &S, QualType T, + SourceLocation Loc, + SourceRange ArgRange, + UnaryExprOrTypeTrait TraitKind) { + // Reject sizeof(interface) and sizeof(interface) in 64-bit mode. + if (S.LangOpts.ObjCNonFragileABI && T->isObjCObjectType()) { + S.Diag(Loc, diag::err_sizeof_nonfragile_interface) + << T << (TraitKind == UETT_SizeOf) + << ArgRange; + return true; + } + + return false; +} + +/// \brief Check the constrains on expression operands to unary type expression +/// and type traits. +/// +/// Completes any types necessary and validates the constraints on the operand +/// expression. The logic mostly mirrors the type-based overload, but may modify +/// the expression as it completes the type for that expression through template +/// instantiation, etc. +bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *E, + UnaryExprOrTypeTrait ExprKind) { + QualType ExprTy = E->getType(); + + // C++ [expr.sizeof]p2: "When applied to a reference or a reference type, + // the result is the size of the referenced type." + // C++ [expr.alignof]p3: "When alignof is applied to a reference type, the + // result shall be the alignment of the referenced type." + if (const ReferenceType *Ref = ExprTy->getAs()) + ExprTy = Ref->getPointeeType(); + + if (ExprKind == UETT_VecStep) + return CheckVecStepTraitOperandType(*this, ExprTy, E->getExprLoc(), + E->getSourceRange()); + + // Whitelist some types as extensions + if (!CheckExtensionTraitOperandType(*this, ExprTy, E->getExprLoc(), + E->getSourceRange(), ExprKind)) + return false; + + if (RequireCompleteExprType(E, + PDiag(diag::err_sizeof_alignof_incomplete_type) + << ExprKind << E->getSourceRange(), + std::make_pair(SourceLocation(), PDiag(0)))) + return true; + + // Completeing the expression's type may have changed it. + ExprTy = E->getType(); + if (const ReferenceType *Ref = ExprTy->getAs()) + ExprTy = Ref->getPointeeType(); + + if (CheckObjCTraitOperandConstraints(*this, ExprTy, E->getExprLoc(), + E->getSourceRange(), ExprKind)) + return true; + + if (ExprKind == UETT_SizeOf) { + if (DeclRefExpr *DeclRef = dyn_cast(E->IgnoreParens())) { + if (ParmVarDecl *PVD = dyn_cast(DeclRef->getFoundDecl())) { + QualType OType = PVD->getOriginalType(); + QualType Type = PVD->getType(); + if (Type->isPointerType() && OType->isArrayType()) { + Diag(E->getExprLoc(), diag::warn_sizeof_array_param) + << Type << OType; + Diag(PVD->getLocation(), diag::note_declared_at); + } + } + } + } + + return false; +} + +/// \brief Check the constraints on operands to unary expression and type +/// traits. +/// +/// This will complete any types necessary, and validate the various constraints +/// on those operands. +/// +/// The UsualUnaryConversions() function is *not* called by this routine. +/// C99 6.3.2.1p[2-4] all state: +/// Except when it is the operand of the sizeof operator ... +/// +/// C++ [expr.sizeof]p4 +/// The lvalue-to-rvalue, array-to-pointer, and function-to-pointer +/// standard conversions are not applied to the operand of sizeof. +/// +/// This policy is followed for all of the unary trait expressions. +bool Sema::CheckUnaryExprOrTypeTraitOperand(QualType ExprType, + SourceLocation OpLoc, + SourceRange ExprRange, + UnaryExprOrTypeTrait ExprKind) { + if (ExprType->isDependentType()) + return false; + + // C++ [expr.sizeof]p2: "When applied to a reference or a reference type, + // the result is the size of the referenced type." + // C++ [expr.alignof]p3: "When alignof is applied to a reference type, the + // result shall be the alignment of the referenced type." + if (const ReferenceType *Ref = ExprType->getAs()) + ExprType = Ref->getPointeeType(); + + if (ExprKind == UETT_VecStep) + return CheckVecStepTraitOperandType(*this, ExprType, OpLoc, ExprRange); + + // Whitelist some types as extensions + if (!CheckExtensionTraitOperandType(*this, ExprType, OpLoc, ExprRange, + ExprKind)) + return false; + + if (RequireCompleteType(OpLoc, ExprType, + PDiag(diag::err_sizeof_alignof_incomplete_type) + << ExprKind << ExprRange)) + return true; + + if (CheckObjCTraitOperandConstraints(*this, ExprType, OpLoc, ExprRange, + ExprKind)) + return true; + + return false; +} + +static bool CheckAlignOfExpr(Sema &S, Expr *E) { + E = E->IgnoreParens(); + + // alignof decl is always ok. + if (isa(E)) + return false; + + // Cannot know anything else if the expression is dependent. + if (E->isTypeDependent()) + return false; + + if (E->getBitField()) { + S.Diag(E->getExprLoc(), diag::err_sizeof_alignof_bitfield) + << 1 << E->getSourceRange(); + return true; + } + + // Alignment of a field access is always okay, so long as it isn't a + // bit-field. + if (MemberExpr *ME = dyn_cast(E)) + if (isa(ME->getMemberDecl())) + return false; + + return S.CheckUnaryExprOrTypeTraitOperand(E, UETT_AlignOf); +} + +bool Sema::CheckVecStepExpr(Expr *E) { + E = E->IgnoreParens(); + + // Cannot know anything else if the expression is dependent. + if (E->isTypeDependent()) + return false; + + return CheckUnaryExprOrTypeTraitOperand(E, UETT_VecStep); +} + +/// \brief Build a sizeof or alignof expression given a type operand. +ExprResult +Sema::CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo, + SourceLocation OpLoc, + UnaryExprOrTypeTrait ExprKind, + SourceRange R) { + if (!TInfo) + return ExprError(); + + QualType T = TInfo->getType(); + + if (!T->isDependentType() && + CheckUnaryExprOrTypeTraitOperand(T, OpLoc, R, ExprKind)) + return ExprError(); + + // C99 6.5.3.4p4: the type (an unsigned integer type) is size_t. + return Owned(new (Context) UnaryExprOrTypeTraitExpr(ExprKind, TInfo, + Context.getSizeType(), + OpLoc, R.getEnd())); +} + +/// \brief Build a sizeof or alignof expression given an expression +/// operand. +ExprResult +Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc, + UnaryExprOrTypeTrait ExprKind) { + ExprResult PE = CheckPlaceholderExpr(E); + if (PE.isInvalid()) + return ExprError(); + + E = PE.get(); + + // Verify that the operand is valid. + bool isInvalid = false; + if (E->isTypeDependent()) { + // Delay type-checking for type-dependent expressions. + } else if (ExprKind == UETT_AlignOf) { + isInvalid = CheckAlignOfExpr(*this, E); + } else if (ExprKind == UETT_VecStep) { + isInvalid = CheckVecStepExpr(E); + } else if (E->getBitField()) { // C99 6.5.3.4p1. + Diag(E->getExprLoc(), diag::err_sizeof_alignof_bitfield) << 0; + isInvalid = true; + } else { + isInvalid = CheckUnaryExprOrTypeTraitOperand(E, UETT_SizeOf); + } + + if (isInvalid) + return ExprError(); + + if (ExprKind == UETT_SizeOf && E->getType()->isVariableArrayType()) { + PE = TranformToPotentiallyEvaluated(E); + if (PE.isInvalid()) return ExprError(); + E = PE.take(); + } + + // C99 6.5.3.4p4: the type (an unsigned integer type) is size_t. + return Owned(new (Context) UnaryExprOrTypeTraitExpr( + ExprKind, E, Context.getSizeType(), OpLoc, + E->getSourceRange().getEnd())); +} + +/// ActOnUnaryExprOrTypeTraitExpr - 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. +ExprResult +Sema::ActOnUnaryExprOrTypeTraitExpr(SourceLocation OpLoc, + UnaryExprOrTypeTrait ExprKind, bool IsType, + void *TyOrEx, const SourceRange &ArgRange) { + // If error parsing type, ignore. + if (TyOrEx == 0) return ExprError(); + + if (IsType) { + TypeSourceInfo *TInfo; + (void) GetTypeFromParser(ParsedType::getFromOpaquePtr(TyOrEx), &TInfo); + return CreateUnaryExprOrTypeTraitExpr(TInfo, OpLoc, ExprKind, ArgRange); + } + + Expr *ArgEx = (Expr *)TyOrEx; + ExprResult Result = CreateUnaryExprOrTypeTraitExpr(ArgEx, OpLoc, ExprKind); + return move(Result); +} + +static QualType CheckRealImagOperand(Sema &S, ExprResult &V, SourceLocation Loc, + bool IsReal) { + if (V.get()->isTypeDependent()) + return S.Context.DependentTy; + + // _Real and _Imag are only l-values for normal l-values. + if (V.get()->getObjectKind() != OK_Ordinary) { + V = S.DefaultLvalueConversion(V.take()); + if (V.isInvalid()) + return QualType(); + } + + // These operators return the element type of a complex type. + if (const ComplexType *CT = V.get()->getType()->getAs()) + return CT->getElementType(); + + // Otherwise they pass through real integer and floating point types here. + if (V.get()->getType()->isArithmeticType()) + return V.get()->getType(); + + // Test for placeholders. + ExprResult PR = S.CheckPlaceholderExpr(V.get()); + if (PR.isInvalid()) return QualType(); + if (PR.get() != V.get()) { + V = move(PR); + return CheckRealImagOperand(S, V, Loc, IsReal); + } + + // Reject anything else. + S.Diag(Loc, diag::err_realimag_invalid_type) << V.get()->getType() + << (IsReal ? "__real" : "__imag"); + return QualType(); +} + + + +ExprResult +Sema::ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc, + tok::TokenKind Kind, Expr *Input) { + UnaryOperatorKind Opc; + switch (Kind) { + default: llvm_unreachable("Unknown unary op!"); + case tok::plusplus: Opc = UO_PostInc; break; + case tok::minusminus: Opc = UO_PostDec; break; + } + + // Since this might is a postfix expression, get rid of ParenListExprs. + ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Input); + if (Result.isInvalid()) return ExprError(); + Input = Result.take(); + + return BuildUnaryOp(S, OpLoc, Opc, Input); +} + +ExprResult +Sema::ActOnArraySubscriptExpr(Scope *S, Expr *Base, SourceLocation LLoc, + Expr *Idx, SourceLocation RLoc) { + // Since this might be a postfix expression, get rid of ParenListExprs. + ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Base); + if (Result.isInvalid()) return ExprError(); + Base = Result.take(); + + Expr *LHSExp = Base, *RHSExp = Idx; + + if (getLangOpts().CPlusPlus && + (LHSExp->isTypeDependent() || RHSExp->isTypeDependent())) { + return Owned(new (Context) ArraySubscriptExpr(LHSExp, RHSExp, + Context.DependentTy, + VK_LValue, OK_Ordinary, + RLoc)); + } + + if (getLangOpts().CPlusPlus && + (LHSExp->getType()->isRecordType() || + LHSExp->getType()->isEnumeralType() || + RHSExp->getType()->isRecordType() || + RHSExp->getType()->isEnumeralType()) && + !LHSExp->getType()->isObjCObjectPointerType()) { + return CreateOverloadedArraySubscriptExpr(LLoc, RLoc, Base, Idx); + } + + return CreateBuiltinArraySubscriptExpr(Base, LLoc, Idx, RLoc); +} + + +ExprResult +Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, + Expr *Idx, SourceLocation RLoc) { + Expr *LHSExp = Base; + Expr *RHSExp = Idx; + + // Perform default conversions. + if (!LHSExp->getType()->getAs()) { + ExprResult Result = DefaultFunctionArrayLvalueConversion(LHSExp); + if (Result.isInvalid()) + return ExprError(); + LHSExp = Result.take(); + } + ExprResult Result = DefaultFunctionArrayLvalueConversion(RHSExp); + if (Result.isInvalid()) + return ExprError(); + RHSExp = Result.take(); + + QualType LHSTy = LHSExp->getType(), RHSTy = RHSExp->getType(); + ExprValueKind VK = VK_LValue; + ExprObjectKind OK = OK_Ordinary; + + // C99 6.5.2.1p2: the expression e1[e2] is by definition precisely equivalent + // to the expression *((e1)+(e2)). This means the array "Base" may actually be + // in the subscript position. As a result, we need to derive the array base + // and index from the expression types. + Expr *BaseExpr, *IndexExpr; + QualType ResultType; + if (LHSTy->isDependentType() || RHSTy->isDependentType()) { + BaseExpr = LHSExp; + IndexExpr = RHSExp; + ResultType = Context.DependentTy; + } else if (const PointerType *PTy = LHSTy->getAs()) { + BaseExpr = LHSExp; + IndexExpr = RHSExp; + ResultType = PTy->getPointeeType(); + } else if (const ObjCObjectPointerType *PTy = + LHSTy->getAs()) { + BaseExpr = LHSExp; + IndexExpr = RHSExp; + Result = BuildObjCSubscriptExpression(RLoc, BaseExpr, IndexExpr, 0, 0); + if (!Result.isInvalid()) + return Owned(Result.take()); + ResultType = PTy->getPointeeType(); + } else if (const PointerType *PTy = RHSTy->getAs()) { + // Handle the uncommon case of "123[Ptr]". + BaseExpr = RHSExp; + IndexExpr = LHSExp; + ResultType = PTy->getPointeeType(); + } else if (const ObjCObjectPointerType *PTy = + RHSTy->getAs()) { + // Handle the uncommon case of "123[Ptr]". + BaseExpr = RHSExp; + IndexExpr = LHSExp; + ResultType = PTy->getPointeeType(); + } else if (const VectorType *VTy = LHSTy->getAs()) { + BaseExpr = LHSExp; // vectors: V[123] + IndexExpr = RHSExp; + VK = LHSExp->getValueKind(); + if (VK != VK_RValue) + OK = OK_VectorComponent; + + // FIXME: need to deal with const... + ResultType = VTy->getElementType(); + } else if (LHSTy->isArrayType()) { + // If we see an array that wasn't promoted by + // DefaultFunctionArrayLvalueConversion, it must be an array that + // wasn't promoted because of the C90 rule that doesn't + // allow promoting non-lvalue arrays. Warn, then + // force the promotion here. + Diag(LHSExp->getLocStart(), diag::ext_subscript_non_lvalue) << + LHSExp->getSourceRange(); + LHSExp = ImpCastExprToType(LHSExp, Context.getArrayDecayedType(LHSTy), + CK_ArrayToPointerDecay).take(); + LHSTy = LHSExp->getType(); + + BaseExpr = LHSExp; + IndexExpr = RHSExp; + ResultType = LHSTy->getAs()->getPointeeType(); + } else if (RHSTy->isArrayType()) { + // Same as previous, except for 123[f().a] case + Diag(RHSExp->getLocStart(), diag::ext_subscript_non_lvalue) << + RHSExp->getSourceRange(); + RHSExp = ImpCastExprToType(RHSExp, Context.getArrayDecayedType(RHSTy), + CK_ArrayToPointerDecay).take(); + RHSTy = RHSExp->getType(); + + BaseExpr = RHSExp; + IndexExpr = LHSExp; + ResultType = RHSTy->getAs()->getPointeeType(); + } else { + return ExprError(Diag(LLoc, diag::err_typecheck_subscript_value) + << LHSExp->getSourceRange() << RHSExp->getSourceRange()); + } + // C99 6.5.2.1p1 + if (!IndexExpr->getType()->isIntegerType() && !IndexExpr->isTypeDependent()) + return ExprError(Diag(LLoc, diag::err_typecheck_subscript_not_integer) + << IndexExpr->getSourceRange()); + + if ((IndexExpr->getType()->isSpecificBuiltinType(BuiltinType::Char_S) || + IndexExpr->getType()->isSpecificBuiltinType(BuiltinType::Char_U)) + && !IndexExpr->isTypeDependent()) + Diag(LLoc, diag::warn_subscript_is_char) << IndexExpr->getSourceRange(); + + // C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly, + // C++ [expr.sub]p1: The type "T" shall be a completely-defined object + // type. Note that Functions are not objects, and that (in C99 parlance) + // incomplete types are not object types. + if (ResultType->isFunctionType()) { + Diag(BaseExpr->getLocStart(), diag::err_subscript_function_type) + << ResultType << BaseExpr->getSourceRange(); + return ExprError(); + } + + if (ResultType->isVoidType() && !getLangOpts().CPlusPlus) { + // GNU extension: subscripting on pointer to void + Diag(LLoc, diag::ext_gnu_subscript_void_type) + << BaseExpr->getSourceRange(); + + // C forbids expressions of unqualified void type from being l-values. + // See IsCForbiddenLValueType. + if (!ResultType.hasQualifiers()) VK = VK_RValue; + } else if (!ResultType->isDependentType() && + RequireCompleteType(LLoc, ResultType, + PDiag(diag::err_subscript_incomplete_type) + << BaseExpr->getSourceRange())) + return ExprError(); + + // Diagnose bad cases where we step over interface counts. + if (ResultType->isObjCObjectType() && LangOpts.ObjCNonFragileABI) { + Diag(LLoc, diag::err_subscript_nonfragile_interface) + << ResultType << BaseExpr->getSourceRange(); + return ExprError(); + } + + assert(VK == VK_RValue || LangOpts.CPlusPlus || + !ResultType.isCForbiddenLValueType()); + + return Owned(new (Context) ArraySubscriptExpr(LHSExp, RHSExp, + ResultType, VK, OK, RLoc)); +} + +ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, + FunctionDecl *FD, + ParmVarDecl *Param) { + if (Param->hasUnparsedDefaultArg()) { + Diag(CallLoc, + diag::err_use_of_default_argument_to_function_declared_later) << + FD << cast(FD->getDeclContext())->getDeclName(); + Diag(UnparsedDefaultArgLocs[Param], + diag::note_default_argument_declared_here); + return ExprError(); + } + + if (Param->hasUninstantiatedDefaultArg()) { + Expr *UninstExpr = Param->getUninstantiatedDefaultArg(); + + // Instantiate the expression. + MultiLevelTemplateArgumentList ArgList + = getTemplateInstantiationArgs(FD, 0, /*RelativeToPrimary=*/true); + + std::pair Innermost + = ArgList.getInnermost(); + InstantiatingTemplate Inst(*this, CallLoc, Param, Innermost.first, + Innermost.second); + + ExprResult Result; + { + // C++ [dcl.fct.default]p5: + // The names in the [default argument] expression are bound, and + // the semantic constraints are checked, at the point where the + // default argument expression appears. + ContextRAII SavedContext(*this, FD); + LocalInstantiationScope Local(*this); + Result = SubstExpr(UninstExpr, ArgList); + } + if (Result.isInvalid()) + return ExprError(); + + // Check the expression as an initializer for the parameter. + InitializedEntity Entity + = InitializedEntity::InitializeParameter(Context, Param); + InitializationKind Kind + = InitializationKind::CreateCopy(Param->getLocation(), + /*FIXME:EqualLoc*/UninstExpr->getLocStart()); + Expr *ResultE = Result.takeAs(); + + InitializationSequence InitSeq(*this, Entity, Kind, &ResultE, 1); + Result = InitSeq.Perform(*this, Entity, Kind, + MultiExprArg(*this, &ResultE, 1)); + if (Result.isInvalid()) + return ExprError(); + + // Build the default argument expression. + return Owned(CXXDefaultArgExpr::Create(Context, CallLoc, Param, + Result.takeAs())); + } + + // If the default expression creates temporaries, we need to + // push them to the current stack of expression temporaries so they'll + // be properly destroyed. + // FIXME: We should really be rebuilding the default argument with new + // bound temporaries; see the comment in PR5810. + // We don't need to do that with block decls, though, because + // blocks in default argument expression can never capture anything. + if (isa(Param->getInit())) { + // Set the "needs cleanups" bit regardless of whether there are + // any explicit objects. + ExprNeedsCleanups = true; + + // Append all the objects to the cleanup list. Right now, this + // should always be a no-op, because blocks in default argument + // expressions should never be able to capture anything. + assert(!cast(Param->getInit())->getNumObjects() && + "default argument expression has capturing blocks?"); + } + + // We already type-checked the argument, so we know it works. + // Just mark all of the declarations in this potentially-evaluated expression + // as being "referenced". + MarkDeclarationsReferencedInExpr(Param->getDefaultArg(), + /*SkipLocalVariables=*/true); + return Owned(CXXDefaultArgExpr::Create(Context, CallLoc, Param)); +} + +/// ConvertArgumentsForCall - Converts the arguments specified in +/// Args/NumArgs to the parameter types of the function FDecl with +/// function prototype Proto. Call is the call expression itself, and +/// Fn is the function expression. For a C++ member function, this +/// routine does not attempt to convert the object argument. Returns +/// true if the call is ill-formed. +bool +Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, + FunctionDecl *FDecl, + const FunctionProtoType *Proto, + Expr **Args, unsigned NumArgs, + SourceLocation RParenLoc, + bool IsExecConfig) { + // Bail out early if calling a builtin with custom typechecking. + // We don't need to do this in the + if (FDecl) + if (unsigned ID = FDecl->getBuiltinID()) + if (Context.BuiltinInfo.hasCustomTypechecking(ID)) + return false; + + // C99 6.5.2.2p7 - the arguments are implicitly converted, as if by + // assignment, to the types of the corresponding parameter, ... + unsigned NumArgsInProto = Proto->getNumArgs(); + bool Invalid = false; + unsigned MinArgs = FDecl ? FDecl->getMinRequiredArguments() : NumArgsInProto; + unsigned FnKind = Fn->getType()->isBlockPointerType() + ? 1 /* block */ + : (IsExecConfig ? 3 /* kernel function (exec config) */ + : 0 /* function */); + + // If too few arguments are available (and we don't have default + // arguments for the remaining parameters), don't make the call. + if (NumArgs < NumArgsInProto) { + if (NumArgs < MinArgs) { + Diag(RParenLoc, MinArgs == NumArgsInProto + ? diag::err_typecheck_call_too_few_args + : diag::err_typecheck_call_too_few_args_at_least) + << FnKind + << MinArgs << NumArgs << Fn->getSourceRange(); + + // Emit the location of the prototype. + if (FDecl && !FDecl->getBuiltinID() && !IsExecConfig) + Diag(FDecl->getLocStart(), diag::note_callee_decl) + << FDecl; + + return true; + } + Call->setNumArgs(Context, NumArgsInProto); + } + + // If too many are passed and not variadic, error on the extras and drop + // them. + if (NumArgs > NumArgsInProto) { + if (!Proto->isVariadic()) { + Diag(Args[NumArgsInProto]->getLocStart(), + MinArgs == NumArgsInProto + ? diag::err_typecheck_call_too_many_args + : diag::err_typecheck_call_too_many_args_at_most) + << FnKind + << NumArgsInProto << NumArgs << Fn->getSourceRange() + << SourceRange(Args[NumArgsInProto]->getLocStart(), + Args[NumArgs-1]->getLocEnd()); + + // Emit the location of the prototype. + if (FDecl && !FDecl->getBuiltinID() && !IsExecConfig) + Diag(FDecl->getLocStart(), diag::note_callee_decl) + << FDecl; + + // This deletes the extra arguments. + Call->setNumArgs(Context, NumArgsInProto); + return true; + } + } + SmallVector AllArgs; + VariadicCallType CallType = + Proto->isVariadic() ? VariadicFunction : VariadicDoesNotApply; + if (Fn->getType()->isBlockPointerType()) + CallType = VariadicBlock; // Block + else if (isa(Fn)) + CallType = VariadicMethod; + Invalid = GatherArgumentsForCall(Call->getLocStart(), FDecl, + Proto, 0, Args, NumArgs, AllArgs, CallType); + if (Invalid) + return true; + unsigned TotalNumArgs = AllArgs.size(); + for (unsigned i = 0; i < TotalNumArgs; ++i) + Call->setArg(i, AllArgs[i]); + + return false; +} + +bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, + FunctionDecl *FDecl, + const FunctionProtoType *Proto, + unsigned FirstProtoArg, + Expr **Args, unsigned NumArgs, + SmallVector &AllArgs, + VariadicCallType CallType, + bool AllowExplicit) { + unsigned NumArgsInProto = Proto->getNumArgs(); + unsigned NumArgsToCheck = NumArgs; + bool Invalid = false; + if (NumArgs != NumArgsInProto) + // Use default arguments for missing arguments + NumArgsToCheck = NumArgsInProto; + unsigned ArgIx = 0; + // Continue to check argument types (even if we have too few/many args). + for (unsigned i = FirstProtoArg; i != NumArgsToCheck; i++) { + QualType ProtoArgType = Proto->getArgType(i); + + Expr *Arg; + ParmVarDecl *Param; + if (ArgIx < NumArgs) { + Arg = Args[ArgIx++]; + + if (RequireCompleteType(Arg->getLocStart(), + ProtoArgType, + PDiag(diag::err_call_incomplete_argument) + << Arg->getSourceRange())) + return true; + + // Pass the argument + Param = 0; + if (FDecl && i < FDecl->getNumParams()) + Param = FDecl->getParamDecl(i); + + // Strip the unbridged-cast placeholder expression off, if applicable. + if (Arg->getType() == Context.ARCUnbridgedCastTy && + FDecl && FDecl->hasAttr() && + (!Param || !Param->hasAttr())) + Arg = stripARCUnbridgedCast(Arg); + + InitializedEntity Entity = + Param? InitializedEntity::InitializeParameter(Context, Param) + : InitializedEntity::InitializeParameter(Context, ProtoArgType, + Proto->isArgConsumed(i)); + ExprResult ArgE = PerformCopyInitialization(Entity, + SourceLocation(), + Owned(Arg), + /*TopLevelOfInitList=*/false, + AllowExplicit); + if (ArgE.isInvalid()) + return true; + + Arg = ArgE.takeAs(); + } else { + Param = FDecl->getParamDecl(i); + + ExprResult ArgExpr = + BuildCXXDefaultArgExpr(CallLoc, FDecl, Param); + if (ArgExpr.isInvalid()) + return true; + + Arg = ArgExpr.takeAs(); + } + + // Check for array bounds violations for each argument to the call. This + // check only triggers warnings when the argument isn't a more complex Expr + // with its own checking, such as a BinaryOperator. + CheckArrayAccess(Arg); + + // Check for violations of C99 static array rules (C99 6.7.5.3p7). + CheckStaticArrayArgument(CallLoc, Param, Arg); + + AllArgs.push_back(Arg); + } + + // If this is a variadic call, handle args passed through "...". + if (CallType != VariadicDoesNotApply) { + + // Assume that extern "C" functions with variadic arguments that + // return __unknown_anytype aren't *really* variadic. + if (Proto->getResultType() == Context.UnknownAnyTy && + FDecl && FDecl->isExternC()) { + for (unsigned i = ArgIx; i != NumArgs; ++i) { + ExprResult arg; + if (isa(Args[i]->IgnoreParens())) + arg = DefaultFunctionArrayLvalueConversion(Args[i]); + else + arg = DefaultVariadicArgumentPromotion(Args[i], CallType, FDecl); + Invalid |= arg.isInvalid(); + AllArgs.push_back(arg.take()); + } + + // Otherwise do argument promotion, (C99 6.5.2.2p7). + } else { + for (unsigned i = ArgIx; i != NumArgs; ++i) { + ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], CallType, + FDecl); + Invalid |= Arg.isInvalid(); + AllArgs.push_back(Arg.take()); + } + } + + // Check for array bounds violations. + for (unsigned i = ArgIx; i != NumArgs; ++i) + CheckArrayAccess(Args[i]); + } + return Invalid; +} + +static void DiagnoseCalleeStaticArrayParam(Sema &S, ParmVarDecl *PVD) { + TypeLoc TL = PVD->getTypeSourceInfo()->getTypeLoc(); + if (ArrayTypeLoc *ATL = dyn_cast(&TL)) + S.Diag(PVD->getLocation(), diag::note_callee_static_array) + << ATL->getLocalSourceRange(); +} + +/// CheckStaticArrayArgument - If the given argument corresponds to a static +/// array parameter, check that it is non-null, and that if it is formed by +/// array-to-pointer decay, the underlying array is sufficiently large. +/// +/// C99 6.7.5.3p7: If the keyword static also appears within the [ and ] of the +/// array type derivation, then for each call to the function, the value of the +/// corresponding actual argument shall provide access to the first element of +/// an array with at least as many elements as specified by the size expression. +void +Sema::CheckStaticArrayArgument(SourceLocation CallLoc, + ParmVarDecl *Param, + const Expr *ArgExpr) { + // Static array parameters are not supported in C++. + if (!Param || getLangOpts().CPlusPlus) + return; + + QualType OrigTy = Param->getOriginalType(); + + const ArrayType *AT = Context.getAsArrayType(OrigTy); + if (!AT || AT->getSizeModifier() != ArrayType::Static) + return; + + if (ArgExpr->isNullPointerConstant(Context, + Expr::NPC_NeverValueDependent)) { + Diag(CallLoc, diag::warn_null_arg) << ArgExpr->getSourceRange(); + DiagnoseCalleeStaticArrayParam(*this, Param); + return; + } + + const ConstantArrayType *CAT = dyn_cast(AT); + if (!CAT) + return; + + const ConstantArrayType *ArgCAT = + Context.getAsConstantArrayType(ArgExpr->IgnoreParenImpCasts()->getType()); + if (!ArgCAT) + return; + + if (ArgCAT->getSize().ult(CAT->getSize())) { + Diag(CallLoc, diag::warn_static_array_too_small) + << ArgExpr->getSourceRange() + << (unsigned) ArgCAT->getSize().getZExtValue() + << (unsigned) CAT->getSize().getZExtValue(); + DiagnoseCalleeStaticArrayParam(*this, Param); + } +} + +/// Given a function expression of unknown-any type, try to rebuild it +/// to have a function type. +static ExprResult rebuildUnknownAnyFunction(Sema &S, Expr *fn); + +/// ActOnCallExpr - Handle a call to Fn with the specified array of arguments. +/// This provides the location of the left/right parens and a list of comma +/// locations. +ExprResult +Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, + MultiExprArg ArgExprs, SourceLocation RParenLoc, + Expr *ExecConfig, bool IsExecConfig) { + unsigned NumArgs = ArgExprs.size(); + + // Since this might be a postfix expression, get rid of ParenListExprs. + ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Fn); + if (Result.isInvalid()) return ExprError(); + Fn = Result.take(); + + Expr **Args = ArgExprs.release(); + + if (getLangOpts().CPlusPlus) { + // If this is a pseudo-destructor expression, build the call immediately. + if (isa(Fn)) { + if (NumArgs > 0) { + // Pseudo-destructor calls should not have any arguments. + Diag(Fn->getLocStart(), diag::err_pseudo_dtor_call_with_args) + << FixItHint::CreateRemoval( + SourceRange(Args[0]->getLocStart(), + Args[NumArgs-1]->getLocEnd())); + } + + return Owned(new (Context) CallExpr(Context, Fn, 0, 0, Context.VoidTy, + VK_RValue, RParenLoc)); + } + + // Determine whether this is a dependent call inside a C++ template, + // in which case we won't do any semantic analysis now. + // FIXME: Will need to cache the results of name lookup (including ADL) in + // Fn. + bool Dependent = false; + if (Fn->isTypeDependent()) + Dependent = true; + else if (Expr::hasAnyTypeDependentArguments( + llvm::makeArrayRef(Args, NumArgs))) + Dependent = true; + + if (Dependent) { + if (ExecConfig) { + return Owned(new (Context) CUDAKernelCallExpr( + Context, Fn, cast(ExecConfig), Args, NumArgs, + Context.DependentTy, VK_RValue, RParenLoc)); + } else { + return Owned(new (Context) CallExpr(Context, Fn, Args, NumArgs, + Context.DependentTy, VK_RValue, + RParenLoc)); + } + } + + // Determine whether this is a call to an object (C++ [over.call.object]). + if (Fn->getType()->isRecordType()) + return Owned(BuildCallToObjectOfClassType(S, Fn, LParenLoc, Args, NumArgs, + RParenLoc)); + + if (Fn->getType() == Context.UnknownAnyTy) { + ExprResult result = rebuildUnknownAnyFunction(*this, Fn); + if (result.isInvalid()) return ExprError(); + Fn = result.take(); + } + + if (Fn->getType() == Context.BoundMemberTy) { + return BuildCallToMemberFunction(S, Fn, LParenLoc, Args, NumArgs, + RParenLoc); + } + } + + // Check for overloaded calls. This can happen even in C due to extensions. + if (Fn->getType() == Context.OverloadTy) { + OverloadExpr::FindResult find = OverloadExpr::find(Fn); + + // We aren't supposed to apply this logic for if there's an '&' involved. + if (!find.HasFormOfMemberPointer) { + OverloadExpr *ovl = find.Expression; + if (isa(ovl)) { + UnresolvedLookupExpr *ULE = cast(ovl); + return BuildOverloadedCallExpr(S, Fn, ULE, LParenLoc, Args, NumArgs, + RParenLoc, ExecConfig); + } else { + return BuildCallToMemberFunction(S, Fn, LParenLoc, Args, NumArgs, + RParenLoc); + } + } + } + + // If we're directly calling a function, get the appropriate declaration. + if (Fn->getType() == Context.UnknownAnyTy) { + ExprResult result = rebuildUnknownAnyFunction(*this, Fn); + if (result.isInvalid()) return ExprError(); + Fn = result.take(); + } + + Expr *NakedFn = Fn->IgnoreParens(); + + NamedDecl *NDecl = 0; + if (UnaryOperator *UnOp = dyn_cast(NakedFn)) + if (UnOp->getOpcode() == UO_AddrOf) + NakedFn = UnOp->getSubExpr()->IgnoreParens(); + + if (isa(NakedFn)) + NDecl = cast(NakedFn)->getDecl(); + else if (isa(NakedFn)) + NDecl = cast(NakedFn)->getMemberDecl(); + + return BuildResolvedCallExpr(Fn, NDecl, LParenLoc, Args, NumArgs, RParenLoc, + ExecConfig, IsExecConfig); +} + +ExprResult +Sema::ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc, + MultiExprArg ExecConfig, SourceLocation GGGLoc) { + FunctionDecl *ConfigDecl = Context.getcudaConfigureCallDecl(); + if (!ConfigDecl) + return ExprError(Diag(LLLLoc, diag::err_undeclared_var_use) + << "cudaConfigureCall"); + QualType ConfigQTy = ConfigDecl->getType(); + + DeclRefExpr *ConfigDR = new (Context) DeclRefExpr( + ConfigDecl, false, ConfigQTy, VK_LValue, LLLLoc); + MarkFunctionReferenced(LLLLoc, ConfigDecl); + + return ActOnCallExpr(S, ConfigDR, LLLLoc, ExecConfig, GGGLoc, 0, + /*IsExecConfig=*/true); +} + +/// ActOnAsTypeExpr - create a new asType (bitcast) from the arguments. +/// +/// __builtin_astype( value, dst type ) +/// +ExprResult Sema::ActOnAsTypeExpr(Expr *E, ParsedType ParsedDestTy, + SourceLocation BuiltinLoc, + SourceLocation RParenLoc) { + ExprValueKind VK = VK_RValue; + ExprObjectKind OK = OK_Ordinary; + QualType DstTy = GetTypeFromParser(ParsedDestTy); + QualType SrcTy = E->getType(); + if (Context.getTypeSize(DstTy) != Context.getTypeSize(SrcTy)) + return ExprError(Diag(BuiltinLoc, + diag::err_invalid_astype_of_different_size) + << DstTy + << SrcTy + << E->getSourceRange()); + return Owned(new (Context) AsTypeExpr(E, DstTy, VK, OK, BuiltinLoc, + RParenLoc)); +} + +/// BuildResolvedCallExpr - Build a call to a resolved expression, +/// i.e. an expression not of \p OverloadTy. The expression should +/// unary-convert to an expression of function-pointer or +/// block-pointer type. +/// +/// \param NDecl the declaration being called, if available +ExprResult +Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, + SourceLocation LParenLoc, + Expr **Args, unsigned NumArgs, + SourceLocation RParenLoc, + Expr *Config, bool IsExecConfig) { + FunctionDecl *FDecl = dyn_cast_or_null(NDecl); + + // Promote the function operand. + ExprResult Result = UsualUnaryConversions(Fn); + if (Result.isInvalid()) + return ExprError(); + Fn = Result.take(); + + // Make the call expr early, before semantic checks. This guarantees cleanup + // of arguments and function on error. + CallExpr *TheCall; + if (Config) { + TheCall = new (Context) CUDAKernelCallExpr(Context, Fn, + cast(Config), + Args, NumArgs, + Context.BoolTy, + VK_RValue, + RParenLoc); + } else { + TheCall = new (Context) CallExpr(Context, Fn, + Args, NumArgs, + Context.BoolTy, + VK_RValue, + RParenLoc); + } + + unsigned BuiltinID = (FDecl ? FDecl->getBuiltinID() : 0); + + // Bail out early if calling a builtin with custom typechecking. + if (BuiltinID && Context.BuiltinInfo.hasCustomTypechecking(BuiltinID)) + return CheckBuiltinFunctionCall(BuiltinID, TheCall); + + retry: + const FunctionType *FuncT; + if (const PointerType *PT = Fn->getType()->getAs()) { + // C99 6.5.2.2p1 - "The expression that denotes the called function shall + // have type pointer to function". + FuncT = PT->getPointeeType()->getAs(); + if (FuncT == 0) + return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function) + << Fn->getType() << Fn->getSourceRange()); + } else if (const BlockPointerType *BPT = + Fn->getType()->getAs()) { + FuncT = BPT->getPointeeType()->castAs(); + } else { + // Handle calls to expressions of unknown-any type. + if (Fn->getType() == Context.UnknownAnyTy) { + ExprResult rewrite = rebuildUnknownAnyFunction(*this, Fn); + if (rewrite.isInvalid()) return ExprError(); + Fn = rewrite.take(); + TheCall->setCallee(Fn); + goto retry; + } + + return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function) + << Fn->getType() << Fn->getSourceRange()); + } + + if (getLangOpts().CUDA) { + if (Config) { + // CUDA: Kernel calls must be to global functions + if (FDecl && !FDecl->hasAttr()) + return ExprError(Diag(LParenLoc,diag::err_kern_call_not_global_function) + << FDecl->getName() << Fn->getSourceRange()); + + // CUDA: Kernel function must have 'void' return type + if (!FuncT->getResultType()->isVoidType()) + return ExprError(Diag(LParenLoc, diag::err_kern_type_not_void_return) + << Fn->getType() << Fn->getSourceRange()); + } else { + // CUDA: Calls to global functions must be configured + if (FDecl && FDecl->hasAttr()) + return ExprError(Diag(LParenLoc, diag::err_global_call_not_config) + << FDecl->getName() << Fn->getSourceRange()); + } + } + + // Check for a valid return type + if (CheckCallReturnType(FuncT->getResultType(), + Fn->getLocStart(), TheCall, + FDecl)) + return ExprError(); + + // We know the result type of the call, set it. + TheCall->setType(FuncT->getCallResultType(Context)); + TheCall->setValueKind(Expr::getValueKindForType(FuncT->getResultType())); + + if (const FunctionProtoType *Proto = dyn_cast(FuncT)) { + if (ConvertArgumentsForCall(TheCall, Fn, FDecl, Proto, Args, NumArgs, + RParenLoc, IsExecConfig)) + return ExprError(); + } else { + assert(isa(FuncT) && "Unknown FunctionType!"); + + if (FDecl) { + // Check if we have too few/too many template arguments, based + // on our knowledge of the function definition. + const FunctionDecl *Def = 0; + if (FDecl->hasBody(Def) && NumArgs != Def->param_size()) { + const FunctionProtoType *Proto + = Def->getType()->getAs(); + if (!Proto || !(Proto->isVariadic() && NumArgs >= Def->param_size())) + Diag(RParenLoc, diag::warn_call_wrong_number_of_arguments) + << (NumArgs > Def->param_size()) << FDecl << Fn->getSourceRange(); + } + + // If the function we're calling isn't a function prototype, but we have + // a function prototype from a prior declaratiom, use that prototype. + if (!FDecl->hasPrototype()) + Proto = FDecl->getType()->getAs(); + } + + // Promote the arguments (C99 6.5.2.2p6). + for (unsigned i = 0; i != NumArgs; i++) { + Expr *Arg = Args[i]; + + if (Proto && i < Proto->getNumArgs()) { + InitializedEntity Entity + = InitializedEntity::InitializeParameter(Context, + Proto->getArgType(i), + Proto->isArgConsumed(i)); + ExprResult ArgE = PerformCopyInitialization(Entity, + SourceLocation(), + Owned(Arg)); + if (ArgE.isInvalid()) + return true; + + Arg = ArgE.takeAs(); + + } else { + ExprResult ArgE = DefaultArgumentPromotion(Arg); + + if (ArgE.isInvalid()) + return true; + + Arg = ArgE.takeAs(); + } + + if (RequireCompleteType(Arg->getLocStart(), + Arg->getType(), + PDiag(diag::err_call_incomplete_argument) + << Arg->getSourceRange())) + return ExprError(); + + TheCall->setArg(i, Arg); + } + } + + if (CXXMethodDecl *Method = dyn_cast_or_null(FDecl)) + if (!Method->isStatic()) + return ExprError(Diag(LParenLoc, diag::err_member_call_without_object) + << Fn->getSourceRange()); + + // Check for sentinels + if (NDecl) + DiagnoseSentinelCalls(NDecl, LParenLoc, Args, NumArgs); + + // Do special checking on direct calls to functions. + if (FDecl) { + if (CheckFunctionCall(FDecl, TheCall)) + return ExprError(); + + if (BuiltinID) + return CheckBuiltinFunctionCall(BuiltinID, TheCall); + } else if (NDecl) { + if (CheckBlockCall(NDecl, TheCall)) + return ExprError(); + } + + return MaybeBindToTemporary(TheCall); +} + +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"); + + TypeSourceInfo *TInfo; + QualType literalType = GetTypeFromParser(Ty, &TInfo); + if (!TInfo) + TInfo = Context.getTrivialTypeSourceInfo(literalType); + + return BuildCompoundLiteralExpr(LParenLoc, TInfo, RParenLoc, InitExpr); +} + +ExprResult +Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo, + SourceLocation RParenLoc, Expr *LiteralExpr) { + QualType literalType = TInfo->getType(); + + if (literalType->isArrayType()) { + if (RequireCompleteType(LParenLoc, Context.getBaseElementType(literalType), + PDiag(diag::err_illegal_decl_array_incomplete_type) + << SourceRange(LParenLoc, + LiteralExpr->getSourceRange().getEnd()))) + return ExprError(); + if (literalType->isVariableArrayType()) + return ExprError(Diag(LParenLoc, diag::err_variable_object_no_init) + << SourceRange(LParenLoc, LiteralExpr->getSourceRange().getEnd())); + } else if (!literalType->isDependentType() && + RequireCompleteType(LParenLoc, literalType, + PDiag(diag::err_typecheck_decl_incomplete_type) + << SourceRange(LParenLoc, + LiteralExpr->getSourceRange().getEnd()))) + return ExprError(); + + InitializedEntity Entity + = InitializedEntity::InitializeTemporary(literalType); + InitializationKind Kind + = InitializationKind::CreateCStyleCast(LParenLoc, + SourceRange(LParenLoc, RParenLoc), + /*InitList=*/true); + InitializationSequence InitSeq(*this, Entity, Kind, &LiteralExpr, 1); + ExprResult Result = InitSeq.Perform(*this, Entity, Kind, + MultiExprArg(*this, &LiteralExpr, 1), + &literalType); + if (Result.isInvalid()) + return ExprError(); + LiteralExpr = Result.get(); + + bool isFileScope = getCurFunctionOrMethodDecl() == 0; + if (isFileScope) { // 6.5.2.5p3 + if (CheckForConstantInitializer(LiteralExpr, literalType)) + return ExprError(); + } + + // In C, compound literals are l-values for some reason. + ExprValueKind VK = getLangOpts().CPlusPlus ? VK_RValue : VK_LValue; + + return MaybeBindToTemporary( + new (Context) CompoundLiteralExpr(LParenLoc, TInfo, literalType, + VK, LiteralExpr, isFileScope)); +} + +ExprResult +Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg InitArgList, + SourceLocation RBraceLoc) { + unsigned NumInit = InitArgList.size(); + Expr **InitList = InitArgList.release(); + + // Immediately handle non-overload placeholders. Overloads can be + // resolved contextually, but everything else here can't. + for (unsigned I = 0; I != NumInit; ++I) { + if (InitList[I]->getType()->isNonOverloadPlaceholderType()) { + ExprResult result = CheckPlaceholderExpr(InitList[I]); + + // Ignore failures; dropping the entire initializer list because + // of one failure would be terrible for indexing/etc. + if (result.isInvalid()) continue; + + InitList[I] = result.take(); + } + } + + // Semantic analysis for initializers is done by ActOnDeclarator() and + // CheckInitializer() - it requires knowledge of the object being intialized. + + InitListExpr *E = new (Context) InitListExpr(Context, LBraceLoc, InitList, + NumInit, RBraceLoc); + E->setType(Context.VoidTy); // FIXME: just a place holder for now. + return Owned(E); +} + +/// Do an explicit extend of the given block pointer if we're in ARC. +static void maybeExtendBlockObject(Sema &S, ExprResult &E) { + assert(E.get()->getType()->isBlockPointerType()); + assert(E.get()->isRValue()); + + // Only do this in an r-value context. + if (!S.getLangOpts().ObjCAutoRefCount) return; + + E = ImplicitCastExpr::Create(S.Context, E.get()->getType(), + CK_ARCExtendBlockObject, E.get(), + /*base path*/ 0, VK_RValue); + S.ExprNeedsCleanups = true; +} + +/// Prepare a conversion of the given expression to an ObjC object +/// pointer type. +CastKind Sema::PrepareCastToObjCObjectPointer(ExprResult &E) { + QualType type = E.get()->getType(); + if (type->isObjCObjectPointerType()) { + return CK_BitCast; + } else if (type->isBlockPointerType()) { + maybeExtendBlockObject(*this, E); + return CK_BlockPointerToObjCPointerCast; + } else { + assert(type->isPointerType()); + return CK_CPointerToObjCPointerCast; + } +} + +/// Prepares for a scalar cast, performing all the necessary stages +/// except the final cast and returning the kind required. +CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) { + // Both Src and Dest are scalar types, i.e. arithmetic or pointer. + // Also, callers should have filtered out the invalid cases with + // pointers. Everything else should be possible. + + QualType SrcTy = Src.get()->getType(); + if (const AtomicType *SrcAtomicTy = SrcTy->getAs()) + SrcTy = SrcAtomicTy->getValueType(); + if (const AtomicType *DestAtomicTy = DestTy->getAs()) + DestTy = DestAtomicTy->getValueType(); + + if (Context.hasSameUnqualifiedType(SrcTy, DestTy)) + return CK_NoOp; + + switch (Type::ScalarTypeKind SrcKind = SrcTy->getScalarTypeKind()) { + case Type::STK_MemberPointer: + llvm_unreachable("member pointer type in C"); + + case Type::STK_CPointer: + case Type::STK_BlockPointer: + case Type::STK_ObjCObjectPointer: + switch (DestTy->getScalarTypeKind()) { + case Type::STK_CPointer: + return CK_BitCast; + case Type::STK_BlockPointer: + return (SrcKind == Type::STK_BlockPointer + ? CK_BitCast : CK_AnyPointerToBlockPointerCast); + case Type::STK_ObjCObjectPointer: + if (SrcKind == Type::STK_ObjCObjectPointer) + return CK_BitCast; + if (SrcKind == Type::STK_CPointer) + return CK_CPointerToObjCPointerCast; + maybeExtendBlockObject(*this, Src); + return CK_BlockPointerToObjCPointerCast; + case Type::STK_Bool: + return CK_PointerToBoolean; + case Type::STK_Integral: + return CK_PointerToIntegral; + case Type::STK_Floating: + case Type::STK_FloatingComplex: + case Type::STK_IntegralComplex: + case Type::STK_MemberPointer: + llvm_unreachable("illegal cast from pointer"); + } + llvm_unreachable("Should have returned before this"); + + case Type::STK_Bool: // casting from bool is like casting from an integer + case Type::STK_Integral: + switch (DestTy->getScalarTypeKind()) { + case Type::STK_CPointer: + case Type::STK_ObjCObjectPointer: + case Type::STK_BlockPointer: + if (Src.get()->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNull)) + return CK_NullToPointer; + return CK_IntegralToPointer; + case Type::STK_Bool: + return CK_IntegralToBoolean; + case Type::STK_Integral: + return CK_IntegralCast; + case Type::STK_Floating: + return CK_IntegralToFloating; + case Type::STK_IntegralComplex: + Src = ImpCastExprToType(Src.take(), + DestTy->castAs()->getElementType(), + CK_IntegralCast); + return CK_IntegralRealToComplex; + case Type::STK_FloatingComplex: + Src = ImpCastExprToType(Src.take(), + DestTy->castAs()->getElementType(), + CK_IntegralToFloating); + return CK_FloatingRealToComplex; + case Type::STK_MemberPointer: + llvm_unreachable("member pointer type in C"); + } + llvm_unreachable("Should have returned before this"); + + case Type::STK_Floating: + switch (DestTy->getScalarTypeKind()) { + case Type::STK_Floating: + return CK_FloatingCast; + case Type::STK_Bool: + return CK_FloatingToBoolean; + case Type::STK_Integral: + return CK_FloatingToIntegral; + case Type::STK_FloatingComplex: + Src = ImpCastExprToType(Src.take(), + DestTy->castAs()->getElementType(), + CK_FloatingCast); + return CK_FloatingRealToComplex; + case Type::STK_IntegralComplex: + Src = ImpCastExprToType(Src.take(), + DestTy->castAs()->getElementType(), + CK_FloatingToIntegral); + return CK_IntegralRealToComplex; + case Type::STK_CPointer: + case Type::STK_ObjCObjectPointer: + case Type::STK_BlockPointer: + llvm_unreachable("valid float->pointer cast?"); + case Type::STK_MemberPointer: + llvm_unreachable("member pointer type in C"); + } + llvm_unreachable("Should have returned before this"); + + case Type::STK_FloatingComplex: + switch (DestTy->getScalarTypeKind()) { + case Type::STK_FloatingComplex: + return CK_FloatingComplexCast; + case Type::STK_IntegralComplex: + return CK_FloatingComplexToIntegralComplex; + case Type::STK_Floating: { + QualType ET = SrcTy->castAs()->getElementType(); + if (Context.hasSameType(ET, DestTy)) + return CK_FloatingComplexToReal; + Src = ImpCastExprToType(Src.take(), ET, CK_FloatingComplexToReal); + return CK_FloatingCast; + } + case Type::STK_Bool: + return CK_FloatingComplexToBoolean; + case Type::STK_Integral: + Src = ImpCastExprToType(Src.take(), + SrcTy->castAs()->getElementType(), + CK_FloatingComplexToReal); + return CK_FloatingToIntegral; + case Type::STK_CPointer: + case Type::STK_ObjCObjectPointer: + case Type::STK_BlockPointer: + llvm_unreachable("valid complex float->pointer cast?"); + case Type::STK_MemberPointer: + llvm_unreachable("member pointer type in C"); + } + llvm_unreachable("Should have returned before this"); + + case Type::STK_IntegralComplex: + switch (DestTy->getScalarTypeKind()) { + case Type::STK_FloatingComplex: + return CK_IntegralComplexToFloatingComplex; + case Type::STK_IntegralComplex: + return CK_IntegralComplexCast; + case Type::STK_Integral: { + QualType ET = SrcTy->castAs()->getElementType(); + if (Context.hasSameType(ET, DestTy)) + return CK_IntegralComplexToReal; + Src = ImpCastExprToType(Src.take(), ET, CK_IntegralComplexToReal); + return CK_IntegralCast; + } + case Type::STK_Bool: + return CK_IntegralComplexToBoolean; + case Type::STK_Floating: + Src = ImpCastExprToType(Src.take(), + SrcTy->castAs()->getElementType(), + CK_IntegralComplexToReal); + return CK_IntegralToFloating; + case Type::STK_CPointer: + case Type::STK_ObjCObjectPointer: + case Type::STK_BlockPointer: + llvm_unreachable("valid complex int->pointer cast?"); + case Type::STK_MemberPointer: + llvm_unreachable("member pointer type in C"); + } + llvm_unreachable("Should have returned before this"); + } + + llvm_unreachable("Unhandled scalar cast"); +} + +bool Sema::CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty, + CastKind &Kind) { + assert(VectorTy->isVectorType() && "Not a vector type!"); + + if (Ty->isVectorType() || Ty->isIntegerType()) { + if (Context.getTypeSize(VectorTy) != Context.getTypeSize(Ty)) + return Diag(R.getBegin(), + Ty->isVectorType() ? + diag::err_invalid_conversion_between_vectors : + diag::err_invalid_conversion_between_vector_and_integer) + << VectorTy << Ty << R; + } else + return Diag(R.getBegin(), + diag::err_invalid_conversion_between_vector_and_scalar) + << VectorTy << Ty << R; + + Kind = CK_BitCast; + return false; +} + +ExprResult Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, + Expr *CastExpr, CastKind &Kind) { + assert(DestTy->isExtVectorType() && "Not an extended vector type!"); + + QualType SrcTy = CastExpr->getType(); + + // If SrcTy is a VectorType, the total size must match to explicitly cast to + // an ExtVectorType. + // In OpenCL, casts between vectors of different types are not allowed. + // (See OpenCL 6.2). + if (SrcTy->isVectorType()) { + if (Context.getTypeSize(DestTy) != Context.getTypeSize(SrcTy) + || (getLangOpts().OpenCL && + (DestTy.getCanonicalType() != SrcTy.getCanonicalType()))) { + Diag(R.getBegin(),diag::err_invalid_conversion_between_ext_vectors) + << DestTy << SrcTy << R; + return ExprError(); + } + Kind = CK_BitCast; + return Owned(CastExpr); + } + + // All non-pointer scalars can be cast to ExtVector type. The appropriate + // conversion will take place first from scalar to elt type, and then + // splat from elt type to vector. + if (SrcTy->isPointerType()) + return Diag(R.getBegin(), + diag::err_invalid_conversion_between_vector_and_scalar) + << DestTy << SrcTy << R; + + QualType DestElemTy = DestTy->getAs()->getElementType(); + ExprResult CastExprRes = Owned(CastExpr); + CastKind CK = PrepareScalarCast(CastExprRes, DestElemTy); + if (CastExprRes.isInvalid()) + return ExprError(); + CastExpr = ImpCastExprToType(CastExprRes.take(), DestElemTy, CK).take(); + + Kind = CK_VectorSplat; + return Owned(CastExpr); +} + +ExprResult +Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc, + Declarator &D, ParsedType &Ty, + SourceLocation RParenLoc, Expr *CastExpr) { + assert(!D.isInvalidType() && (CastExpr != 0) && + "ActOnCastExpr(): missing type or expr"); + + TypeSourceInfo *castTInfo = GetTypeForDeclaratorCast(D, CastExpr->getType()); + if (D.isInvalidType()) + return ExprError(); + + if (getLangOpts().CPlusPlus) { + // Check that there are no default arguments (C++ only). + CheckExtraCXXDefaultArguments(D); + } + + checkUnusedDeclAttributes(D); + + QualType castType = castTInfo->getType(); + Ty = CreateParsedType(castType, castTInfo); + + bool isVectorLiteral = false; + + // Check for an altivec or OpenCL literal, + // i.e. all the elements are integer constants. + ParenExpr *PE = dyn_cast(CastExpr); + ParenListExpr *PLE = dyn_cast(CastExpr); + if ((getLangOpts().AltiVec || getLangOpts().OpenCL) + && castType->isVectorType() && (PE || PLE)) { + if (PLE && PLE->getNumExprs() == 0) { + Diag(PLE->getExprLoc(), diag::err_altivec_empty_initializer); + return ExprError(); + } + if (PE || PLE->getNumExprs() == 1) { + Expr *E = (PE ? PE->getSubExpr() : PLE->getExpr(0)); + if (!E->getType()->isVectorType()) + isVectorLiteral = true; + } + else + isVectorLiteral = true; + } + + // If this is a vector initializer, '(' type ')' '(' init, ..., init ')' + // then handle it as such. + if (isVectorLiteral) + return BuildVectorLiteral(LParenLoc, RParenLoc, CastExpr, castTInfo); + + // If the Expr being casted is a ParenListExpr, handle it specially. + // This is not an AltiVec-style cast, so turn the ParenListExpr into a + // sequence of BinOp comma operators. + if (isa(CastExpr)) { + ExprResult Result = MaybeConvertParenListExprToParenExpr(S, CastExpr); + if (Result.isInvalid()) return ExprError(); + CastExpr = Result.take(); + } + + return BuildCStyleCastExpr(LParenLoc, castTInfo, RParenLoc, CastExpr); +} + +ExprResult Sema::BuildVectorLiteral(SourceLocation LParenLoc, + SourceLocation RParenLoc, Expr *E, + TypeSourceInfo *TInfo) { + assert((isa(E) || isa(E)) && + "Expected paren or paren list expression"); + + Expr **exprs; + unsigned numExprs; + Expr *subExpr; + if (ParenListExpr *PE = dyn_cast(E)) { + exprs = PE->getExprs(); + numExprs = PE->getNumExprs(); + } else { + subExpr = cast(E)->getSubExpr(); + exprs = &subExpr; + numExprs = 1; + } + + QualType Ty = TInfo->getType(); + assert(Ty->isVectorType() && "Expected vector type"); + + SmallVector initExprs; + const VectorType *VTy = Ty->getAs(); + unsigned numElems = Ty->getAs()->getNumElements(); + + // '(...)' form of vector initialization in AltiVec: the number of + // initializers must be one or must match the size of the vector. + // If a single value is specified in the initializer then it will be + // replicated to all the components of the vector + if (VTy->getVectorKind() == VectorType::AltiVecVector) { + // The number of initializers must be one or must match the size of the + // vector. If a single value is specified in the initializer then it will + // be replicated to all the components of the vector + if (numExprs == 1) { + QualType ElemTy = Ty->getAs()->getElementType(); + ExprResult Literal = DefaultLvalueConversion(exprs[0]); + if (Literal.isInvalid()) + return ExprError(); + Literal = ImpCastExprToType(Literal.take(), ElemTy, + PrepareScalarCast(Literal, ElemTy)); + return BuildCStyleCastExpr(LParenLoc, TInfo, RParenLoc, Literal.take()); + } + else if (numExprs < numElems) { + Diag(E->getExprLoc(), + diag::err_incorrect_number_of_vector_initializers); + return ExprError(); + } + else + initExprs.append(exprs, exprs + numExprs); + } + else { + // For OpenCL, when the number of initializers is a single value, + // it will be replicated to all components of the vector. + if (getLangOpts().OpenCL && + VTy->getVectorKind() == VectorType::GenericVector && + numExprs == 1) { + QualType ElemTy = Ty->getAs()->getElementType(); + ExprResult Literal = DefaultLvalueConversion(exprs[0]); + if (Literal.isInvalid()) + return ExprError(); + Literal = ImpCastExprToType(Literal.take(), ElemTy, + PrepareScalarCast(Literal, ElemTy)); + return BuildCStyleCastExpr(LParenLoc, TInfo, RParenLoc, Literal.take()); + } + + initExprs.append(exprs, exprs + numExprs); + } + // FIXME: This means that pretty-printing the final AST will produce curly + // braces instead of the original commas. + InitListExpr *initE = new (Context) InitListExpr(Context, LParenLoc, + &initExprs[0], + initExprs.size(), RParenLoc); + initE->setType(Ty); + return BuildCompoundLiteralExpr(LParenLoc, TInfo, RParenLoc, initE); +} + +/// This is not an AltiVec-style cast or or C++ direct-initialization, so turn +/// the ParenListExpr into a sequence of comma binary operators. +ExprResult +Sema::MaybeConvertParenListExprToParenExpr(Scope *S, Expr *OrigExpr) { + ParenListExpr *E = dyn_cast(OrigExpr); + if (!E) + return Owned(OrigExpr); + + ExprResult Result(E->getExpr(0)); + + for (unsigned i = 1, e = E->getNumExprs(); i != e && !Result.isInvalid(); ++i) + Result = ActOnBinOp(S, E->getExprLoc(), tok::comma, Result.get(), + E->getExpr(i)); + + if (Result.isInvalid()) return ExprError(); + + return ActOnParenExpr(E->getLParenLoc(), E->getRParenLoc(), Result.get()); +} + +ExprResult Sema::ActOnParenListExpr(SourceLocation L, + SourceLocation R, + MultiExprArg Val) { + unsigned nexprs = Val.size(); + Expr **exprs = reinterpret_cast(Val.release()); + assert((exprs != 0) && "ActOnParenOrParenListExpr() missing expr list"); + Expr *expr = new (Context) ParenListExpr(Context, L, exprs, nexprs, R); + return Owned(expr); +} + +/// \brief Emit a specialized diagnostic when one expression is a null pointer +/// constant and the other is not a pointer. Returns true if a diagnostic is +/// emitted. +bool Sema::DiagnoseConditionalForNull(Expr *LHSExpr, Expr *RHSExpr, + SourceLocation QuestionLoc) { + Expr *NullExpr = LHSExpr; + Expr *NonPointerExpr = RHSExpr; + Expr::NullPointerConstantKind NullKind = + NullExpr->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNotNull); + + if (NullKind == Expr::NPCK_NotNull) { + NullExpr = RHSExpr; + NonPointerExpr = LHSExpr; + NullKind = + NullExpr->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNotNull); + } + + if (NullKind == Expr::NPCK_NotNull) + return false; + + if (NullKind == Expr::NPCK_ZeroInteger) { + // In this case, check to make sure that we got here from a "NULL" + // string in the source code. + NullExpr = NullExpr->IgnoreParenImpCasts(); + SourceLocation loc = NullExpr->getExprLoc(); + if (!findMacroSpelling(loc, "NULL")) + return false; + } + + int DiagType = (NullKind == Expr::NPCK_CXX0X_nullptr); + Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands_null) + << NonPointerExpr->getType() << DiagType + << NonPointerExpr->getSourceRange(); + return true; +} + +/// \brief Return false if the condition expression is valid, true otherwise. +static bool checkCondition(Sema &S, Expr *Cond) { + QualType CondTy = Cond->getType(); + + // C99 6.5.15p2 + if (CondTy->isScalarType()) return false; + + // OpenCL: Sec 6.3.i says the condition is allowed to be a vector or scalar. + if (S.getLangOpts().OpenCL && CondTy->isVectorType()) + return false; + + // Emit the proper error message. + S.Diag(Cond->getLocStart(), S.getLangOpts().OpenCL ? + diag::err_typecheck_cond_expect_scalar : + diag::err_typecheck_cond_expect_scalar_or_vector) + << CondTy; + return true; +} + +/// \brief Return false if the two expressions can be converted to a vector, +/// true otherwise +static bool checkConditionalConvertScalarsToVectors(Sema &S, ExprResult &LHS, + ExprResult &RHS, + QualType CondTy) { + // Both operands should be of scalar type. + if (!LHS.get()->getType()->isScalarType()) { + S.Diag(LHS.get()->getLocStart(), diag::err_typecheck_cond_expect_scalar) + << CondTy; + return true; + } + if (!RHS.get()->getType()->isScalarType()) { + S.Diag(RHS.get()->getLocStart(), diag::err_typecheck_cond_expect_scalar) + << CondTy; + return true; + } + + // Implicity convert these scalars to the type of the condition. + LHS = S.ImpCastExprToType(LHS.take(), CondTy, CK_IntegralCast); + RHS = S.ImpCastExprToType(RHS.take(), CondTy, CK_IntegralCast); + return false; +} + +/// \brief Handle when one or both operands are void type. +static QualType checkConditionalVoidType(Sema &S, ExprResult &LHS, + ExprResult &RHS) { + Expr *LHSExpr = LHS.get(); + Expr *RHSExpr = RHS.get(); + + if (!LHSExpr->getType()->isVoidType()) + S.Diag(RHSExpr->getLocStart(), diag::ext_typecheck_cond_one_void) + << RHSExpr->getSourceRange(); + if (!RHSExpr->getType()->isVoidType()) + S.Diag(LHSExpr->getLocStart(), diag::ext_typecheck_cond_one_void) + << LHSExpr->getSourceRange(); + LHS = S.ImpCastExprToType(LHS.take(), S.Context.VoidTy, CK_ToVoid); + RHS = S.ImpCastExprToType(RHS.take(), S.Context.VoidTy, CK_ToVoid); + return S.Context.VoidTy; +} + +/// \brief Return false if the NullExpr can be promoted to PointerTy, +/// true otherwise. +static bool checkConditionalNullPointer(Sema &S, ExprResult &NullExpr, + QualType PointerTy) { + if ((!PointerTy->isAnyPointerType() && !PointerTy->isBlockPointerType()) || + !NullExpr.get()->isNullPointerConstant(S.Context, + Expr::NPC_ValueDependentIsNull)) + return true; + + NullExpr = S.ImpCastExprToType(NullExpr.take(), PointerTy, CK_NullToPointer); + return false; +} + +/// \brief Checks compatibility between two pointers and return the resulting +/// type. +static QualType checkConditionalPointerCompatibility(Sema &S, ExprResult &LHS, + ExprResult &RHS, + SourceLocation Loc) { + QualType LHSTy = LHS.get()->getType(); + QualType RHSTy = RHS.get()->getType(); + + if (S.Context.hasSameType(LHSTy, RHSTy)) { + // Two identical pointers types are always compatible. + return LHSTy; + } + + QualType lhptee, rhptee; + + // Get the pointee types. + if (const BlockPointerType *LHSBTy = LHSTy->getAs()) { + lhptee = LHSBTy->getPointeeType(); + rhptee = RHSTy->castAs()->getPointeeType(); + } else { + lhptee = LHSTy->castAs()->getPointeeType(); + rhptee = RHSTy->castAs()->getPointeeType(); + } + + // C99 6.5.15p6: If both operands are pointers to compatible types or to + // differently qualified versions of compatible types, the result type is + // a pointer to an appropriately qualified version of the composite + // type. + + // Only CVR-qualifiers exist in the standard, and the differently-qualified + // clause doesn't make sense for our extensions. E.g. address space 2 should + // be incompatible with address space 3: they may live on different devices or + // anything. + Qualifiers lhQual = lhptee.getQualifiers(); + Qualifiers rhQual = rhptee.getQualifiers(); + + unsigned MergedCVRQual = lhQual.getCVRQualifiers() | rhQual.getCVRQualifiers(); + lhQual.removeCVRQualifiers(); + rhQual.removeCVRQualifiers(); + + lhptee = S.Context.getQualifiedType(lhptee.getUnqualifiedType(), lhQual); + rhptee = S.Context.getQualifiedType(rhptee.getUnqualifiedType(), rhQual); + + QualType CompositeTy = S.Context.mergeTypes(lhptee, rhptee); + + if (CompositeTy.isNull()) { + S.Diag(Loc, diag::warn_typecheck_cond_incompatible_pointers) + << LHSTy << RHSTy << LHS.get()->getSourceRange() + << RHS.get()->getSourceRange(); + // In this situation, we assume void* type. No especially good + // reason, but this is what gcc does, and we do have to pick + // to get a consistent AST. + QualType incompatTy = S.Context.getPointerType(S.Context.VoidTy); + LHS = S.ImpCastExprToType(LHS.take(), incompatTy, CK_BitCast); + RHS = S.ImpCastExprToType(RHS.take(), incompatTy, CK_BitCast); + return incompatTy; + } + + // The pointer types are compatible. + QualType ResultTy = CompositeTy.withCVRQualifiers(MergedCVRQual); + ResultTy = S.Context.getPointerType(ResultTy); + + LHS = S.ImpCastExprToType(LHS.take(), ResultTy, CK_BitCast); + RHS = S.ImpCastExprToType(RHS.take(), ResultTy, CK_BitCast); + return ResultTy; +} + +/// \brief Return the resulting type when the operands are both block pointers. +static QualType checkConditionalBlockPointerCompatibility(Sema &S, + ExprResult &LHS, + ExprResult &RHS, + SourceLocation Loc) { + QualType LHSTy = LHS.get()->getType(); + QualType RHSTy = RHS.get()->getType(); + + if (!LHSTy->isBlockPointerType() || !RHSTy->isBlockPointerType()) { + if (LHSTy->isVoidPointerType() || RHSTy->isVoidPointerType()) { + QualType destType = S.Context.getPointerType(S.Context.VoidTy); + LHS = S.ImpCastExprToType(LHS.take(), destType, CK_BitCast); + RHS = S.ImpCastExprToType(RHS.take(), destType, CK_BitCast); + return destType; + } + S.Diag(Loc, diag::err_typecheck_cond_incompatible_operands) + << LHSTy << RHSTy << LHS.get()->getSourceRange() + << RHS.get()->getSourceRange(); + return QualType(); + } + + // We have 2 block pointer types. + return checkConditionalPointerCompatibility(S, LHS, RHS, Loc); +} + +/// \brief Return the resulting type when the operands are both pointers. +static QualType +checkConditionalObjectPointersCompatibility(Sema &S, ExprResult &LHS, + ExprResult &RHS, + SourceLocation Loc) { + // get the pointer types + QualType LHSTy = LHS.get()->getType(); + QualType RHSTy = RHS.get()->getType(); + + // get the "pointed to" types + QualType lhptee = LHSTy->getAs()->getPointeeType(); + QualType rhptee = RHSTy->getAs()->getPointeeType(); + + // ignore qualifiers on void (C99 6.5.15p3, clause 6) + if (lhptee->isVoidType() && rhptee->isIncompleteOrObjectType()) { + // Figure out necessary qualifiers (C99 6.5.15p6) + QualType destPointee + = S.Context.getQualifiedType(lhptee, rhptee.getQualifiers()); + QualType destType = S.Context.getPointerType(destPointee); + // Add qualifiers if necessary. + LHS = S.ImpCastExprToType(LHS.take(), destType, CK_NoOp); + // Promote to void*. + RHS = S.ImpCastExprToType(RHS.take(), destType, CK_BitCast); + return destType; + } + if (rhptee->isVoidType() && lhptee->isIncompleteOrObjectType()) { + QualType destPointee + = S.Context.getQualifiedType(rhptee, lhptee.getQualifiers()); + QualType destType = S.Context.getPointerType(destPointee); + // Add qualifiers if necessary. + RHS = S.ImpCastExprToType(RHS.take(), destType, CK_NoOp); + // Promote to void*. + LHS = S.ImpCastExprToType(LHS.take(), destType, CK_BitCast); + return destType; + } + + return checkConditionalPointerCompatibility(S, LHS, RHS, Loc); +} + +/// \brief Return false if the first expression is not an integer and the second +/// expression is not a pointer, true otherwise. +static bool checkPointerIntegerMismatch(Sema &S, ExprResult &Int, + Expr* PointerExpr, SourceLocation Loc, + bool IsIntFirstExpr) { + if (!PointerExpr->getType()->isPointerType() || + !Int.get()->getType()->isIntegerType()) + return false; + + Expr *Expr1 = IsIntFirstExpr ? Int.get() : PointerExpr; + Expr *Expr2 = IsIntFirstExpr ? PointerExpr : Int.get(); + + S.Diag(Loc, diag::warn_typecheck_cond_pointer_integer_mismatch) + << Expr1->getType() << Expr2->getType() + << Expr1->getSourceRange() << Expr2->getSourceRange(); + Int = S.ImpCastExprToType(Int.take(), PointerExpr->getType(), + CK_IntegralToPointer); + return true; +} + +/// Note that LHS is not null here, even if this is the gnu "x ?: y" extension. +/// In that case, LHS = cond. +/// C99 6.5.15 +QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, + ExprResult &RHS, ExprValueKind &VK, + ExprObjectKind &OK, + SourceLocation QuestionLoc) { + + ExprResult LHSResult = CheckPlaceholderExpr(LHS.get()); + if (!LHSResult.isUsable()) return QualType(); + LHS = move(LHSResult); + + ExprResult RHSResult = CheckPlaceholderExpr(RHS.get()); + if (!RHSResult.isUsable()) return QualType(); + RHS = move(RHSResult); + + // C++ is sufficiently different to merit its own checker. + if (getLangOpts().CPlusPlus) + return CXXCheckConditionalOperands(Cond, LHS, RHS, VK, OK, QuestionLoc); + + VK = VK_RValue; + OK = OK_Ordinary; + + Cond = UsualUnaryConversions(Cond.take()); + if (Cond.isInvalid()) + return QualType(); + LHS = UsualUnaryConversions(LHS.take()); + if (LHS.isInvalid()) + return QualType(); + RHS = UsualUnaryConversions(RHS.take()); + if (RHS.isInvalid()) + return QualType(); + + QualType CondTy = Cond.get()->getType(); + QualType LHSTy = LHS.get()->getType(); + QualType RHSTy = RHS.get()->getType(); + + // first, check the condition. + if (checkCondition(*this, Cond.get())) + return QualType(); + + // Now check the two expressions. + if (LHSTy->isVectorType() || RHSTy->isVectorType()) + return CheckVectorOperands(LHS, RHS, QuestionLoc, /*isCompAssign*/false); + + // OpenCL: If the condition is a vector, and both operands are scalar, + // attempt to implicity convert them to the vector type to act like the + // built in select. + if (getLangOpts().OpenCL && CondTy->isVectorType()) + if (checkConditionalConvertScalarsToVectors(*this, LHS, RHS, CondTy)) + return QualType(); + + // If both operands have arithmetic type, do the usual arithmetic conversions + // to find a common type: C99 6.5.15p3,5. + if (LHSTy->isArithmeticType() && RHSTy->isArithmeticType()) { + UsualArithmeticConversions(LHS, RHS); + if (LHS.isInvalid() || RHS.isInvalid()) + return QualType(); + return LHS.get()->getType(); + } + + // If both operands are the same structure or union type, the result is that + // type. + if (const RecordType *LHSRT = LHSTy->getAs()) { // C99 6.5.15p3 + if (const RecordType *RHSRT = RHSTy->getAs()) + if (LHSRT->getDecl() == RHSRT->getDecl()) + // "If both the operands have structure or union type, the result has + // that type." This implies that CV qualifiers are dropped. + return LHSTy.getUnqualifiedType(); + // FIXME: Type of conditional expression must be complete in C mode. + } + + // C99 6.5.15p5: "If both operands have void type, the result has void type." + // The following || allows only one side to be void (a GCC-ism). + if (LHSTy->isVoidType() || RHSTy->isVoidType()) { + return checkConditionalVoidType(*this, LHS, RHS); + } + + // C99 6.5.15p6 - "if one operand is a null pointer constant, the result has + // the type of the other operand." + if (!checkConditionalNullPointer(*this, RHS, LHSTy)) return LHSTy; + if (!checkConditionalNullPointer(*this, LHS, RHSTy)) return RHSTy; + + // All objective-c pointer type analysis is done here. + QualType compositeType = FindCompositeObjCPointerType(LHS, RHS, + QuestionLoc); + if (LHS.isInvalid() || RHS.isInvalid()) + return QualType(); + if (!compositeType.isNull()) + return compositeType; + + + // Handle block pointer types. + if (LHSTy->isBlockPointerType() || RHSTy->isBlockPointerType()) + return checkConditionalBlockPointerCompatibility(*this, LHS, RHS, + QuestionLoc); + + // Check constraints for C object pointers types (C99 6.5.15p3,6). + if (LHSTy->isPointerType() && RHSTy->isPointerType()) + return checkConditionalObjectPointersCompatibility(*this, LHS, RHS, + QuestionLoc); + + // GCC compatibility: soften pointer/integer mismatch. Note that + // null pointers have been filtered out by this point. + if (checkPointerIntegerMismatch(*this, LHS, RHS.get(), QuestionLoc, + /*isIntFirstExpr=*/true)) + return RHSTy; + if (checkPointerIntegerMismatch(*this, RHS, LHS.get(), QuestionLoc, + /*isIntFirstExpr=*/false)) + return LHSTy; + + // Emit a better diagnostic if one of the expressions is a null pointer + // constant and the other is not a pointer type. In this case, the user most + // likely forgot to take the address of the other expression. + if (DiagnoseConditionalForNull(LHS.get(), RHS.get(), QuestionLoc)) + return QualType(); + + // Otherwise, the operands are not compatible. + Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands) + << LHSTy << RHSTy << LHS.get()->getSourceRange() + << RHS.get()->getSourceRange(); + return QualType(); +} + +/// FindCompositeObjCPointerType - Helper method to find composite type of +/// two objective-c pointer types of the two input expressions. +QualType Sema::FindCompositeObjCPointerType(ExprResult &LHS, ExprResult &RHS, + SourceLocation QuestionLoc) { + QualType LHSTy = LHS.get()->getType(); + QualType RHSTy = RHS.get()->getType(); + + // Handle things like Class and struct objc_class*. Here we case the result + // to the pseudo-builtin, because that will be implicitly cast back to the + // redefinition type if an attempt is made to access its fields. + if (LHSTy->isObjCClassType() && + (Context.hasSameType(RHSTy, Context.getObjCClassRedefinitionType()))) { + RHS = ImpCastExprToType(RHS.take(), LHSTy, CK_CPointerToObjCPointerCast); + return LHSTy; + } + if (RHSTy->isObjCClassType() && + (Context.hasSameType(LHSTy, Context.getObjCClassRedefinitionType()))) { + LHS = ImpCastExprToType(LHS.take(), RHSTy, CK_CPointerToObjCPointerCast); + return RHSTy; + } + // And the same for struct objc_object* / id + if (LHSTy->isObjCIdType() && + (Context.hasSameType(RHSTy, Context.getObjCIdRedefinitionType()))) { + RHS = ImpCastExprToType(RHS.take(), LHSTy, CK_CPointerToObjCPointerCast); + return LHSTy; + } + if (RHSTy->isObjCIdType() && + (Context.hasSameType(LHSTy, Context.getObjCIdRedefinitionType()))) { + LHS = ImpCastExprToType(LHS.take(), RHSTy, CK_CPointerToObjCPointerCast); + return RHSTy; + } + // And the same for struct objc_selector* / SEL + if (Context.isObjCSelType(LHSTy) && + (Context.hasSameType(RHSTy, Context.getObjCSelRedefinitionType()))) { + RHS = ImpCastExprToType(RHS.take(), LHSTy, CK_BitCast); + return LHSTy; + } + if (Context.isObjCSelType(RHSTy) && + (Context.hasSameType(LHSTy, Context.getObjCSelRedefinitionType()))) { + LHS = ImpCastExprToType(LHS.take(), RHSTy, CK_BitCast); + return RHSTy; + } + // Check constraints for Objective-C object pointers types. + if (LHSTy->isObjCObjectPointerType() && RHSTy->isObjCObjectPointerType()) { + + if (Context.getCanonicalType(LHSTy) == Context.getCanonicalType(RHSTy)) { + // Two identical object pointer types are always compatible. + return LHSTy; + } + const ObjCObjectPointerType *LHSOPT = LHSTy->castAs(); + const ObjCObjectPointerType *RHSOPT = RHSTy->castAs(); + QualType compositeType = LHSTy; + + // If both operands are interfaces and either operand can be + // assigned to the other, use that type as the composite + // type. This allows + // xxx ? (A*) a : (B*) b + // where B is a subclass of A. + // + // Additionally, as for assignment, if either type is 'id' + // allow silent coercion. Finally, if the types are + // incompatible then make sure to use 'id' as the composite + // type so the result is acceptable for sending messages to. + + // FIXME: Consider unifying with 'areComparableObjCPointerTypes'. + // It could return the composite type. + if (Context.canAssignObjCInterfaces(LHSOPT, RHSOPT)) { + compositeType = RHSOPT->isObjCBuiltinType() ? RHSTy : LHSTy; + } else if (Context.canAssignObjCInterfaces(RHSOPT, LHSOPT)) { + compositeType = LHSOPT->isObjCBuiltinType() ? LHSTy : RHSTy; + } else if ((LHSTy->isObjCQualifiedIdType() || + RHSTy->isObjCQualifiedIdType()) && + Context.ObjCQualifiedIdTypesAreCompatible(LHSTy, RHSTy, true)) { + // Need to handle "id" explicitly. + // GCC allows qualified id and any Objective-C type to devolve to + // id. Currently localizing to here until clear this should be + // part of ObjCQualifiedIdTypesAreCompatible. + compositeType = Context.getObjCIdType(); + } else if (LHSTy->isObjCIdType() || RHSTy->isObjCIdType()) { + compositeType = Context.getObjCIdType(); + } else if (!(compositeType = + Context.areCommonBaseCompatible(LHSOPT, RHSOPT)).isNull()) + ; + else { + Diag(QuestionLoc, diag::ext_typecheck_cond_incompatible_operands) + << LHSTy << RHSTy + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + QualType incompatTy = Context.getObjCIdType(); + LHS = ImpCastExprToType(LHS.take(), incompatTy, CK_BitCast); + RHS = ImpCastExprToType(RHS.take(), incompatTy, CK_BitCast); + return incompatTy; + } + // The object pointer types are compatible. + LHS = ImpCastExprToType(LHS.take(), compositeType, CK_BitCast); + RHS = ImpCastExprToType(RHS.take(), compositeType, CK_BitCast); + return compositeType; + } + // Check Objective-C object pointer types and 'void *' + if (LHSTy->isVoidPointerType() && RHSTy->isObjCObjectPointerType()) { + if (getLangOpts().ObjCAutoRefCount) { + // ARC forbids the implicit conversion of object pointers to 'void *', + // so these types are not compatible. + Diag(QuestionLoc, diag::err_cond_voidptr_arc) << LHSTy << RHSTy + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + LHS = RHS = true; + return QualType(); + } + QualType lhptee = LHSTy->getAs()->getPointeeType(); + QualType rhptee = RHSTy->getAs()->getPointeeType(); + QualType destPointee + = Context.getQualifiedType(lhptee, rhptee.getQualifiers()); + QualType destType = Context.getPointerType(destPointee); + // Add qualifiers if necessary. + LHS = ImpCastExprToType(LHS.take(), destType, CK_NoOp); + // Promote to void*. + RHS = ImpCastExprToType(RHS.take(), destType, CK_BitCast); + return destType; + } + if (LHSTy->isObjCObjectPointerType() && RHSTy->isVoidPointerType()) { + if (getLangOpts().ObjCAutoRefCount) { + // ARC forbids the implicit conversion of object pointers to 'void *', + // so these types are not compatible. + Diag(QuestionLoc, diag::err_cond_voidptr_arc) << LHSTy << RHSTy + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + LHS = RHS = true; + return QualType(); + } + QualType lhptee = LHSTy->getAs()->getPointeeType(); + QualType rhptee = RHSTy->getAs()->getPointeeType(); + QualType destPointee + = Context.getQualifiedType(rhptee, lhptee.getQualifiers()); + QualType destType = Context.getPointerType(destPointee); + // Add qualifiers if necessary. + RHS = ImpCastExprToType(RHS.take(), destType, CK_NoOp); + // Promote to void*. + LHS = ImpCastExprToType(LHS.take(), destType, CK_BitCast); + return destType; + } + return QualType(); +} + +/// SuggestParentheses - Emit a note with a fixit hint that wraps +/// ParenRange in parentheses. +static void SuggestParentheses(Sema &Self, SourceLocation Loc, + const PartialDiagnostic &Note, + SourceRange ParenRange) { + SourceLocation EndLoc = Self.PP.getLocForEndOfToken(ParenRange.getEnd()); + if (ParenRange.getBegin().isFileID() && ParenRange.getEnd().isFileID() && + EndLoc.isValid()) { + Self.Diag(Loc, Note) + << FixItHint::CreateInsertion(ParenRange.getBegin(), "(") + << FixItHint::CreateInsertion(EndLoc, ")"); + } else { + // We can't display the parentheses, so just show the bare note. + Self.Diag(Loc, Note) << ParenRange; + } +} + +static bool IsArithmeticOp(BinaryOperatorKind Opc) { + return Opc >= BO_Mul && Opc <= BO_Shr; +} + +/// IsArithmeticBinaryExpr - Returns true if E is an arithmetic binary +/// expression, either using a built-in or overloaded operator, +/// and sets *OpCode to the opcode and *RHSExprs to the right-hand side +/// expression. +static bool IsArithmeticBinaryExpr(Expr *E, BinaryOperatorKind *Opcode, + Expr **RHSExprs) { + // Don't strip parenthesis: we should not warn if E is in parenthesis. + E = E->IgnoreImpCasts(); + E = E->IgnoreConversionOperator(); + E = E->IgnoreImpCasts(); + + // Built-in binary operator. + if (BinaryOperator *OP = dyn_cast(E)) { + if (IsArithmeticOp(OP->getOpcode())) { + *Opcode = OP->getOpcode(); + *RHSExprs = OP->getRHS(); + return true; + } + } + + // Overloaded operator. + if (CXXOperatorCallExpr *Call = dyn_cast(E)) { + if (Call->getNumArgs() != 2) + return false; + + // Make sure this is really a binary operator that is safe to pass into + // BinaryOperator::getOverloadedOpcode(), e.g. it's not a subscript op. + OverloadedOperatorKind OO = Call->getOperator(); + if (OO < OO_Plus || OO > OO_Arrow) + return false; + + BinaryOperatorKind OpKind = BinaryOperator::getOverloadedOpcode(OO); + if (IsArithmeticOp(OpKind)) { + *Opcode = OpKind; + *RHSExprs = Call->getArg(1); + return true; + } + } + + return false; +} + +static bool IsLogicOp(BinaryOperatorKind Opc) { + return (Opc >= BO_LT && Opc <= BO_NE) || (Opc >= BO_LAnd && Opc <= BO_LOr); +} + +/// ExprLooksBoolean - Returns true if E looks boolean, i.e. it has boolean type +/// or is a logical expression such as (x==y) which has int type, but is +/// commonly interpreted as boolean. +static bool ExprLooksBoolean(Expr *E) { + E = E->IgnoreParenImpCasts(); + + if (E->getType()->isBooleanType()) + return true; + if (BinaryOperator *OP = dyn_cast(E)) + return IsLogicOp(OP->getOpcode()); + if (UnaryOperator *OP = dyn_cast(E)) + return OP->getOpcode() == UO_LNot; + + return false; +} + +/// DiagnoseConditionalPrecedence - Emit a warning when a conditional operator +/// and binary operator are mixed in a way that suggests the programmer assumed +/// the conditional operator has higher precedence, for example: +/// "int x = a + someBinaryCondition ? 1 : 2". +static void DiagnoseConditionalPrecedence(Sema &Self, + SourceLocation OpLoc, + Expr *Condition, + Expr *LHSExpr, + Expr *RHSExpr) { + BinaryOperatorKind CondOpcode; + Expr *CondRHS; + + if (!IsArithmeticBinaryExpr(Condition, &CondOpcode, &CondRHS)) + return; + if (!ExprLooksBoolean(CondRHS)) + return; + + // The condition is an arithmetic binary expression, with a right- + // hand side that looks boolean, so warn. + + Self.Diag(OpLoc, diag::warn_precedence_conditional) + << Condition->getSourceRange() + << BinaryOperator::getOpcodeStr(CondOpcode); + + SuggestParentheses(Self, OpLoc, + Self.PDiag(diag::note_precedence_conditional_silence) + << BinaryOperator::getOpcodeStr(CondOpcode), + SourceRange(Condition->getLocStart(), Condition->getLocEnd())); + + SuggestParentheses(Self, OpLoc, + Self.PDiag(diag::note_precedence_conditional_first), + SourceRange(CondRHS->getLocStart(), RHSExpr->getLocEnd())); +} + +/// ActOnConditionalOp - Parse a ?: operation. Note that 'LHS' may be null +/// in the case of a the GNU conditional expr extension. +ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc, + SourceLocation ColonLoc, + Expr *CondExpr, Expr *LHSExpr, + Expr *RHSExpr) { + // If this is the gnu "x ?: y" extension, analyze the types as though the LHS + // was the condition. + OpaqueValueExpr *opaqueValue = 0; + Expr *commonExpr = 0; + if (LHSExpr == 0) { + commonExpr = CondExpr; + + // We usually want to apply unary conversions *before* saving, except + // in the special case of a C++ l-value conditional. + if (!(getLangOpts().CPlusPlus + && !commonExpr->isTypeDependent() + && commonExpr->getValueKind() == RHSExpr->getValueKind() + && commonExpr->isGLValue() + && commonExpr->isOrdinaryOrBitFieldObject() + && RHSExpr->isOrdinaryOrBitFieldObject() + && Context.hasSameType(commonExpr->getType(), RHSExpr->getType()))) { + ExprResult commonRes = UsualUnaryConversions(commonExpr); + if (commonRes.isInvalid()) + return ExprError(); + commonExpr = commonRes.take(); + } + + opaqueValue = new (Context) OpaqueValueExpr(commonExpr->getExprLoc(), + commonExpr->getType(), + commonExpr->getValueKind(), + commonExpr->getObjectKind(), + commonExpr); + LHSExpr = CondExpr = opaqueValue; + } + + ExprValueKind VK = VK_RValue; + ExprObjectKind OK = OK_Ordinary; + ExprResult Cond = Owned(CondExpr), LHS = Owned(LHSExpr), RHS = Owned(RHSExpr); + QualType result = CheckConditionalOperands(Cond, LHS, RHS, + VK, OK, QuestionLoc); + if (result.isNull() || Cond.isInvalid() || LHS.isInvalid() || + RHS.isInvalid()) + return ExprError(); + + DiagnoseConditionalPrecedence(*this, QuestionLoc, Cond.get(), LHS.get(), + RHS.get()); + + if (!commonExpr) + return Owned(new (Context) ConditionalOperator(Cond.take(), QuestionLoc, + LHS.take(), ColonLoc, + RHS.take(), result, VK, OK)); + + return Owned(new (Context) + BinaryConditionalOperator(commonExpr, opaqueValue, Cond.take(), LHS.take(), + RHS.take(), QuestionLoc, ColonLoc, result, VK, + OK)); +} + +// checkPointerTypesForAssignment - This is a very tricky routine (despite +// being closely modeled after the C99 spec:-). The odd characteristic of this +// routine is it effectively iqnores the qualifiers on the top level pointee. +// This circumvents the usual type rules specified in 6.2.7p1 & 6.7.5.[1-3]. +// FIXME: add a couple examples in this comment. +static Sema::AssignConvertType +checkPointerTypesForAssignment(Sema &S, QualType LHSType, QualType RHSType) { + assert(LHSType.isCanonical() && "LHS not canonicalized!"); + assert(RHSType.isCanonical() && "RHS not canonicalized!"); + + // get the "pointed to" type (ignoring qualifiers at the top level) + const Type *lhptee, *rhptee; + Qualifiers lhq, rhq; + llvm::tie(lhptee, lhq) = cast(LHSType)->getPointeeType().split(); + llvm::tie(rhptee, rhq) = cast(RHSType)->getPointeeType().split(); + + Sema::AssignConvertType ConvTy = Sema::Compatible; + + // C99 6.5.16.1p1: This following citation is common to constraints + // 3 & 4 (below). ...and the type *pointed to* by the left has all the + // qualifiers of the type *pointed to* by the right; + Qualifiers lq; + + // As a special case, 'non-__weak A *' -> 'non-__weak const *' is okay. + if (lhq.getObjCLifetime() != rhq.getObjCLifetime() && + lhq.compatiblyIncludesObjCLifetime(rhq)) { + // Ignore lifetime for further calculation. + lhq.removeObjCLifetime(); + rhq.removeObjCLifetime(); + } + + if (!lhq.compatiblyIncludes(rhq)) { + // Treat address-space mismatches as fatal. TODO: address subspaces + if (lhq.getAddressSpace() != rhq.getAddressSpace()) + ConvTy = Sema::IncompatiblePointerDiscardsQualifiers; + + // It's okay to add or remove GC or lifetime qualifiers when converting to + // and from void*. + else if (lhq.withoutObjCGCAttr().withoutObjCLifetime() + .compatiblyIncludes( + rhq.withoutObjCGCAttr().withoutObjCLifetime()) + && (lhptee->isVoidType() || rhptee->isVoidType())) + ; // keep old + + // Treat lifetime mismatches as fatal. + else if (lhq.getObjCLifetime() != rhq.getObjCLifetime()) + ConvTy = Sema::IncompatiblePointerDiscardsQualifiers; + + // For GCC compatibility, other qualifier mismatches are treated + // as still compatible in C. + else ConvTy = Sema::CompatiblePointerDiscardsQualifiers; + } + + // C99 6.5.16.1p1 (constraint 4): If one operand is a pointer to an object or + // incomplete type and the other is a pointer to a qualified or unqualified + // version of void... + if (lhptee->isVoidType()) { + if (rhptee->isIncompleteOrObjectType()) + return ConvTy; + + // As an extension, we allow cast to/from void* to function pointer. + assert(rhptee->isFunctionType()); + return Sema::FunctionVoidPointer; + } + + if (rhptee->isVoidType()) { + if (lhptee->isIncompleteOrObjectType()) + return ConvTy; + + // As an extension, we allow cast to/from void* to function pointer. + assert(lhptee->isFunctionType()); + return Sema::FunctionVoidPointer; + } + + // C99 6.5.16.1p1 (constraint 3): both operands are pointers to qualified or + // unqualified versions of compatible types, ... + QualType ltrans = QualType(lhptee, 0), rtrans = QualType(rhptee, 0); + if (!S.Context.typesAreCompatible(ltrans, rtrans)) { + // Check if the pointee types are compatible ignoring the sign. + // We explicitly check for char so that we catch "char" vs + // "unsigned char" on systems where "char" is unsigned. + if (lhptee->isCharType()) + ltrans = S.Context.UnsignedCharTy; + else if (lhptee->hasSignedIntegerRepresentation()) + ltrans = S.Context.getCorrespondingUnsignedType(ltrans); + + if (rhptee->isCharType()) + rtrans = S.Context.UnsignedCharTy; + else if (rhptee->hasSignedIntegerRepresentation()) + rtrans = S.Context.getCorrespondingUnsignedType(rtrans); + + if (ltrans == rtrans) { + // Types are compatible ignoring the sign. Qualifier incompatibility + // takes priority over sign incompatibility because the sign + // warning can be disabled. + if (ConvTy != Sema::Compatible) + return ConvTy; + + return Sema::IncompatiblePointerSign; + } + + // If we are a multi-level pointer, it's possible that our issue is simply + // one of qualification - e.g. char ** -> const char ** is not allowed. If + // the eventual target type is the same and the pointers have the same + // level of indirection, this must be the issue. + if (isa(lhptee) && isa(rhptee)) { + do { + lhptee = cast(lhptee)->getPointeeType().getTypePtr(); + rhptee = cast(rhptee)->getPointeeType().getTypePtr(); + } while (isa(lhptee) && isa(rhptee)); + + if (lhptee == rhptee) + return Sema::IncompatibleNestedPointerQualifiers; + } + + // General pointer incompatibility takes priority over qualifiers. + return Sema::IncompatiblePointer; + } + if (!S.getLangOpts().CPlusPlus && + S.IsNoReturnConversion(ltrans, rtrans, ltrans)) + return Sema::IncompatiblePointer; + return ConvTy; +} + +/// checkBlockPointerTypesForAssignment - This routine determines whether two +/// block pointer types are compatible or whether a block and normal pointer +/// are compatible. It is more restrict than comparing two function pointer +// types. +static Sema::AssignConvertType +checkBlockPointerTypesForAssignment(Sema &S, QualType LHSType, + QualType RHSType) { + assert(LHSType.isCanonical() && "LHS not canonicalized!"); + assert(RHSType.isCanonical() && "RHS not canonicalized!"); + + QualType lhptee, rhptee; + + // get the "pointed to" type (ignoring qualifiers at the top level) + lhptee = cast(LHSType)->getPointeeType(); + rhptee = cast(RHSType)->getPointeeType(); + + // In C++, the types have to match exactly. + if (S.getLangOpts().CPlusPlus) + return Sema::IncompatibleBlockPointer; + + Sema::AssignConvertType ConvTy = Sema::Compatible; + + // For blocks we enforce that qualifiers are identical. + if (lhptee.getLocalQualifiers() != rhptee.getLocalQualifiers()) + ConvTy = Sema::CompatiblePointerDiscardsQualifiers; + + if (!S.Context.typesAreBlockPointerCompatible(LHSType, RHSType)) + return Sema::IncompatibleBlockPointer; + + return ConvTy; +} + +/// checkObjCPointerTypesForAssignment - Compares two objective-c pointer types +/// for assignment compatibility. +static Sema::AssignConvertType +checkObjCPointerTypesForAssignment(Sema &S, QualType LHSType, + QualType RHSType) { + assert(LHSType.isCanonical() && "LHS was not canonicalized!"); + assert(RHSType.isCanonical() && "RHS was not canonicalized!"); + + if (LHSType->isObjCBuiltinType()) { + // Class is not compatible with ObjC object pointers. + if (LHSType->isObjCClassType() && !RHSType->isObjCBuiltinType() && + !RHSType->isObjCQualifiedClassType()) + return Sema::IncompatiblePointer; + return Sema::Compatible; + } + if (RHSType->isObjCBuiltinType()) { + if (RHSType->isObjCClassType() && !LHSType->isObjCBuiltinType() && + !LHSType->isObjCQualifiedClassType()) + return Sema::IncompatiblePointer; + return Sema::Compatible; + } + QualType lhptee = LHSType->getAs()->getPointeeType(); + QualType rhptee = RHSType->getAs()->getPointeeType(); + + if (!lhptee.isAtLeastAsQualifiedAs(rhptee) && + // make an exception for id

+ !LHSType->isObjCQualifiedIdType()) + return Sema::CompatiblePointerDiscardsQualifiers; + + if (S.Context.typesAreCompatible(LHSType, RHSType)) + return Sema::Compatible; + if (LHSType->isObjCQualifiedIdType() || RHSType->isObjCQualifiedIdType()) + return Sema::IncompatibleObjCQualifiedId; + return Sema::IncompatiblePointer; +} + +Sema::AssignConvertType +Sema::CheckAssignmentConstraints(SourceLocation Loc, + QualType LHSType, QualType RHSType) { + // Fake up an opaque expression. We don't actually care about what + // cast operations are required, so if CheckAssignmentConstraints + // adds casts to this they'll be wasted, but fortunately that doesn't + // usually happen on valid code. + OpaqueValueExpr RHSExpr(Loc, RHSType, VK_RValue); + ExprResult RHSPtr = &RHSExpr; + CastKind K = CK_Invalid; + + return CheckAssignmentConstraints(LHSType, RHSPtr, K); +} + +/// CheckAssignmentConstraints (C99 6.5.16) - This routine currently +/// has code to accommodate several GCC extensions when type checking +/// pointers. Here are some objectionable examples that GCC considers warnings: +/// +/// int a, *pint; +/// short *pshort; +/// struct foo *pfoo; +/// +/// pint = pshort; // warning: assignment from incompatible pointer type +/// a = pint; // warning: assignment makes integer from pointer without a cast +/// pint = a; // warning: assignment makes pointer from integer without a cast +/// pint = pfoo; // warning: assignment from incompatible pointer type +/// +/// As a result, the code for dealing with pointers is more complex than the +/// C99 spec dictates. +/// +/// Sets 'Kind' for any result kind except Incompatible. +Sema::AssignConvertType +Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS, + CastKind &Kind) { + QualType RHSType = RHS.get()->getType(); + QualType OrigLHSType = LHSType; + + // Get canonical types. We're not formatting these types, just comparing + // them. + LHSType = Context.getCanonicalType(LHSType).getUnqualifiedType(); + RHSType = Context.getCanonicalType(RHSType).getUnqualifiedType(); + + + // Common case: no conversion required. + if (LHSType == RHSType) { + Kind = CK_NoOp; + return Compatible; + } + + if (const AtomicType *AtomicTy = dyn_cast(LHSType)) { + if (AtomicTy->getValueType() == RHSType) { + Kind = CK_NonAtomicToAtomic; + return Compatible; + } + } + + if (const AtomicType *AtomicTy = dyn_cast(RHSType)) { + if (AtomicTy->getValueType() == LHSType) { + Kind = CK_AtomicToNonAtomic; + return Compatible; + } + } + + + // If the left-hand side is a reference type, then we are in a + // (rare!) case where we've allowed the use of references in C, + // e.g., as a parameter type in a built-in function. In this case, + // just make sure that the type referenced is compatible with the + // right-hand side type. The caller is responsible for adjusting + // LHSType so that the resulting expression does not have reference + // type. + if (const ReferenceType *LHSTypeRef = LHSType->getAs()) { + if (Context.typesAreCompatible(LHSTypeRef->getPointeeType(), RHSType)) { + Kind = CK_LValueBitCast; + return Compatible; + } + return Incompatible; + } + + // Allow scalar to ExtVector assignments, and assignments of an ExtVector type + // to the same ExtVector type. + if (LHSType->isExtVectorType()) { + if (RHSType->isExtVectorType()) + return Incompatible; + if (RHSType->isArithmeticType()) { + // CK_VectorSplat does T -> vector T, so first cast to the + // element type. + QualType elType = cast(LHSType)->getElementType(); + if (elType != RHSType) { + Kind = PrepareScalarCast(RHS, elType); + RHS = ImpCastExprToType(RHS.take(), elType, Kind); + } + Kind = CK_VectorSplat; + return Compatible; + } + } + + // Conversions to or from vector type. + if (LHSType->isVectorType() || RHSType->isVectorType()) { + if (LHSType->isVectorType() && RHSType->isVectorType()) { + // Allow assignments of an AltiVec vector type to an equivalent GCC + // vector type and vice versa + if (Context.areCompatibleVectorTypes(LHSType, RHSType)) { + Kind = CK_BitCast; + return Compatible; + } + + // 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 (getLangOpts().LaxVectorConversions && + (Context.getTypeSize(LHSType) == Context.getTypeSize(RHSType))) { + Kind = CK_BitCast; + return IncompatibleVectors; + } + } + return Incompatible; + } + + // Arithmetic conversions. + if (LHSType->isArithmeticType() && RHSType->isArithmeticType() && + !(getLangOpts().CPlusPlus && LHSType->isEnumeralType())) { + Kind = PrepareScalarCast(RHS, LHSType); + return Compatible; + } + + // Conversions to normal pointers. + if (const PointerType *LHSPointer = dyn_cast(LHSType)) { + // U* -> T* + if (isa(RHSType)) { + Kind = CK_BitCast; + return checkPointerTypesForAssignment(*this, LHSType, RHSType); + } + + // int -> T* + if (RHSType->isIntegerType()) { + Kind = CK_IntegralToPointer; // FIXME: null? + return IntToPointer; + } + + // C pointers are not compatible with ObjC object pointers, + // with two exceptions: + if (isa(RHSType)) { + // - conversions to void* + if (LHSPointer->getPointeeType()->isVoidType()) { + Kind = CK_BitCast; + return Compatible; + } + + // - conversions from 'Class' to the redefinition type + if (RHSType->isObjCClassType() && + Context.hasSameType(LHSType, + Context.getObjCClassRedefinitionType())) { + Kind = CK_BitCast; + return Compatible; + } + + Kind = CK_BitCast; + return IncompatiblePointer; + } + + // U^ -> void* + if (RHSType->getAs()) { + if (LHSPointer->getPointeeType()->isVoidType()) { + Kind = CK_BitCast; + return Compatible; + } + } + + return Incompatible; + } + + // Conversions to block pointers. + if (isa(LHSType)) { + // U^ -> T^ + if (RHSType->isBlockPointerType()) { + Kind = CK_BitCast; + return checkBlockPointerTypesForAssignment(*this, LHSType, RHSType); + } + + // int or null -> T^ + if (RHSType->isIntegerType()) { + Kind = CK_IntegralToPointer; // FIXME: null + return IntToBlockPointer; + } + + // id -> T^ + if (getLangOpts().ObjC1 && RHSType->isObjCIdType()) { + Kind = CK_AnyPointerToBlockPointerCast; + return Compatible; + } + + // void* -> T^ + if (const PointerType *RHSPT = RHSType->getAs()) + if (RHSPT->getPointeeType()->isVoidType()) { + Kind = CK_AnyPointerToBlockPointerCast; + return Compatible; + } + + return Incompatible; + } + + // Conversions to Objective-C pointers. + if (isa(LHSType)) { + // A* -> B* + if (RHSType->isObjCObjectPointerType()) { + Kind = CK_BitCast; + Sema::AssignConvertType result = + checkObjCPointerTypesForAssignment(*this, LHSType, RHSType); + if (getLangOpts().ObjCAutoRefCount && + result == Compatible && + !CheckObjCARCUnavailableWeakConversion(OrigLHSType, RHSType)) + result = IncompatibleObjCWeakRef; + return result; + } + + // int or null -> A* + if (RHSType->isIntegerType()) { + Kind = CK_IntegralToPointer; // FIXME: null + return IntToPointer; + } + + // In general, C pointers are not compatible with ObjC object pointers, + // with two exceptions: + if (isa(RHSType)) { + Kind = CK_CPointerToObjCPointerCast; + + // - conversions from 'void*' + if (RHSType->isVoidPointerType()) { + return Compatible; + } + + // - conversions to 'Class' from its redefinition type + if (LHSType->isObjCClassType() && + Context.hasSameType(RHSType, + Context.getObjCClassRedefinitionType())) { + return Compatible; + } + + return IncompatiblePointer; + } + + // T^ -> A* + if (RHSType->isBlockPointerType()) { + maybeExtendBlockObject(*this, RHS); + Kind = CK_BlockPointerToObjCPointerCast; + return Compatible; + } + + return Incompatible; + } + + // Conversions from pointers that are not covered by the above. + if (isa(RHSType)) { + // T* -> _Bool + if (LHSType == Context.BoolTy) { + Kind = CK_PointerToBoolean; + return Compatible; + } + + // T* -> int + if (LHSType->isIntegerType()) { + Kind = CK_PointerToIntegral; + return PointerToInt; + } + + return Incompatible; + } + + // Conversions from Objective-C pointers that are not covered by the above. + if (isa(RHSType)) { + // T* -> _Bool + if (LHSType == Context.BoolTy) { + Kind = CK_PointerToBoolean; + return Compatible; + } + + // T* -> int + if (LHSType->isIntegerType()) { + Kind = CK_PointerToIntegral; + return PointerToInt; + } + + return Incompatible; + } + + // struct A -> struct B + if (isa(LHSType) && isa(RHSType)) { + if (Context.typesAreCompatible(LHSType, RHSType)) { + Kind = CK_NoOp; + return Compatible; + } + } + + return Incompatible; +} + +/// \brief Constructs a transparent union from an expression that is +/// used to initialize the transparent union. +static void ConstructTransparentUnion(Sema &S, ASTContext &C, + ExprResult &EResult, QualType UnionType, + FieldDecl *Field) { + // Build an initializer list that designates the appropriate member + // of the transparent union. + Expr *E = EResult.take(); + InitListExpr *Initializer = new (C) InitListExpr(C, SourceLocation(), + &E, 1, + SourceLocation()); + Initializer->setType(UnionType); + Initializer->setInitializedFieldInUnion(Field); + + // Build a compound literal constructing a value of the transparent + // union type from this initializer list. + TypeSourceInfo *unionTInfo = C.getTrivialTypeSourceInfo(UnionType); + EResult = S.Owned( + new (C) CompoundLiteralExpr(SourceLocation(), unionTInfo, UnionType, + VK_RValue, Initializer, false)); +} + +Sema::AssignConvertType +Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType, + ExprResult &RHS) { + QualType RHSType = RHS.get()->getType(); + + // If the ArgType is a Union type, we want to handle a potential + // transparent_union GCC extension. + const RecordType *UT = ArgType->getAsUnionType(); + if (!UT || !UT->getDecl()->hasAttr()) + return Incompatible; + + // The field to initialize within the transparent union. + RecordDecl *UD = UT->getDecl(); + FieldDecl *InitField = 0; + // It's compatible if the expression matches any of the fields. + for (RecordDecl::field_iterator it = UD->field_begin(), + itend = UD->field_end(); + it != itend; ++it) { + if (it->getType()->isPointerType()) { + // If the transparent union contains a pointer type, we allow: + // 1) void pointer + // 2) null pointer constant + if (RHSType->isPointerType()) + if (RHSType->castAs()->getPointeeType()->isVoidType()) { + RHS = ImpCastExprToType(RHS.take(), it->getType(), CK_BitCast); + InitField = *it; + break; + } + + if (RHS.get()->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNull)) { + RHS = ImpCastExprToType(RHS.take(), it->getType(), + CK_NullToPointer); + InitField = *it; + break; + } + } + + CastKind Kind = CK_Invalid; + if (CheckAssignmentConstraints(it->getType(), RHS, Kind) + == Compatible) { + RHS = ImpCastExprToType(RHS.take(), it->getType(), Kind); + InitField = *it; + break; + } + } + + if (!InitField) + return Incompatible; + + ConstructTransparentUnion(*this, Context, RHS, ArgType, InitField); + return Compatible; +} + +Sema::AssignConvertType +Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS, + bool Diagnose) { + if (getLangOpts().CPlusPlus) { + if (!LHSType->isRecordType() && !LHSType->isAtomicType()) { + // C++ 5.17p3: If the left operand is not of class type, the + // expression is implicitly converted (C++ 4) to the + // cv-unqualified type of the left operand. + ExprResult Res; + if (Diagnose) { + Res = PerformImplicitConversion(RHS.get(), LHSType.getUnqualifiedType(), + AA_Assigning); + } else { + ImplicitConversionSequence ICS = + TryImplicitConversion(RHS.get(), LHSType.getUnqualifiedType(), + /*SuppressUserConversions=*/false, + /*AllowExplicit=*/false, + /*InOverloadResolution=*/false, + /*CStyle=*/false, + /*AllowObjCWritebackConversion=*/false); + if (ICS.isFailure()) + return Incompatible; + Res = PerformImplicitConversion(RHS.get(), LHSType.getUnqualifiedType(), + ICS, AA_Assigning); + } + if (Res.isInvalid()) + return Incompatible; + Sema::AssignConvertType result = Compatible; + if (getLangOpts().ObjCAutoRefCount && + !CheckObjCARCUnavailableWeakConversion(LHSType, + RHS.get()->getType())) + result = IncompatibleObjCWeakRef; + RHS = move(Res); + return result; + } + + // FIXME: Currently, we fall through and treat C++ classes like C + // structures. + // FIXME: We also fall through for atomics; not sure what should + // happen there, though. + } + + // C99 6.5.16.1p1: the left operand is a pointer and the right is + // a null pointer constant. + if ((LHSType->isPointerType() || + LHSType->isObjCObjectPointerType() || + LHSType->isBlockPointerType()) + && RHS.get()->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNull)) { + RHS = ImpCastExprToType(RHS.take(), LHSType, CK_NullToPointer); + 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 suppress this implicit conversion (&, sizeof). + // + // Suppress this for references: C++ 8.5.3p5. + if (!LHSType->isReferenceType()) { + RHS = DefaultFunctionArrayLvalueConversion(RHS.take()); + if (RHS.isInvalid()) + return Incompatible; + } + + CastKind Kind = CK_Invalid; + Sema::AssignConvertType result = + CheckAssignmentConstraints(LHSType, RHS, Kind); + + // C99 6.5.16.1p2: The value of the right operand is converted to the + // type of the assignment expression. + // CheckAssignmentConstraints allows the left-hand side to be a reference, + // so that we can use references in built-in functions even in C. + // The getNonReferenceType() call makes sure that the resulting expression + // does not have reference type. + if (result != Incompatible && RHS.get()->getType() != LHSType) + RHS = ImpCastExprToType(RHS.take(), + LHSType.getNonLValueExprType(Context), Kind); + return result; +} + +QualType Sema::InvalidOperands(SourceLocation Loc, ExprResult &LHS, + ExprResult &RHS) { + Diag(Loc, diag::err_typecheck_invalid_operands) + << LHS.get()->getType() << RHS.get()->getType() + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + return QualType(); +} + +QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS, + SourceLocation Loc, bool IsCompAssign) { + if (!IsCompAssign) { + LHS = DefaultFunctionArrayLvalueConversion(LHS.take()); + if (LHS.isInvalid()) + return QualType(); + } + RHS = DefaultFunctionArrayLvalueConversion(RHS.take()); + if (RHS.isInvalid()) + return QualType(); + + // For conversion purposes, we ignore any qualifiers. + // For example, "const float" and "float" are equivalent. + QualType LHSType = + Context.getCanonicalType(LHS.get()->getType()).getUnqualifiedType(); + QualType RHSType = + Context.getCanonicalType(RHS.get()->getType()).getUnqualifiedType(); + + // If the vector types are identical, return. + if (LHSType == RHSType) + return LHSType; + + // Handle the case of equivalent AltiVec and GCC vector types + if (LHSType->isVectorType() && RHSType->isVectorType() && + Context.areCompatibleVectorTypes(LHSType, RHSType)) { + if (LHSType->isExtVectorType()) { + RHS = ImpCastExprToType(RHS.take(), LHSType, CK_BitCast); + return LHSType; + } + + if (!IsCompAssign) + LHS = ImpCastExprToType(LHS.take(), RHSType, CK_BitCast); + return RHSType; + } + + if (getLangOpts().LaxVectorConversions && + 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. + // FIXME: Should we really be allowing this? + RHS = ImpCastExprToType(RHS.take(), LHSType, CK_BitCast); + return LHSType; + } + + // 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; + if (RHSType->isExtVectorType() && !IsCompAssign) { + swapped = true; + std::swap(RHS, LHS); + std::swap(RHSType, LHSType); + } + + // Handle the case of an ext vector and scalar. + if (const ExtVectorType *LV = LHSType->getAs()) { + QualType EltTy = LV->getElementType(); + if (EltTy->isIntegralType(Context) && RHSType->isIntegralType(Context)) { + int order = Context.getIntegerTypeOrder(EltTy, RHSType); + if (order > 0) + RHS = ImpCastExprToType(RHS.take(), EltTy, CK_IntegralCast); + if (order >= 0) { + RHS = ImpCastExprToType(RHS.take(), LHSType, CK_VectorSplat); + if (swapped) std::swap(RHS, LHS); + return LHSType; + } + } + if (EltTy->isRealFloatingType() && RHSType->isScalarType() && + RHSType->isRealFloatingType()) { + int order = Context.getFloatingTypeOrder(EltTy, RHSType); + if (order > 0) + RHS = ImpCastExprToType(RHS.take(), EltTy, CK_FloatingCast); + if (order >= 0) { + RHS = ImpCastExprToType(RHS.take(), LHSType, CK_VectorSplat); + if (swapped) std::swap(RHS, LHS); + return LHSType; + } + } + } + + // Vectors of different size or scalar and non-ext-vector are errors. + if (swapped) std::swap(RHS, LHS); + Diag(Loc, diag::err_typecheck_vector_not_convertable) + << LHS.get()->getType() << RHS.get()->getType() + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + return QualType(); +} + +// checkArithmeticNull - Detect when a NULL constant is used improperly in an +// expression. These are mainly cases where the null pointer is used as an +// integer instead of a pointer. +static void checkArithmeticNull(Sema &S, ExprResult &LHS, ExprResult &RHS, + SourceLocation Loc, bool IsCompare) { + // The canonical way to check for a GNU null is with isNullPointerConstant, + // but we use a bit of a hack here for speed; this is a relatively + // hot path, and isNullPointerConstant is slow. + bool LHSNull = isa(LHS.get()->IgnoreParenImpCasts()); + bool RHSNull = isa(RHS.get()->IgnoreParenImpCasts()); + + QualType NonNullType = LHSNull ? RHS.get()->getType() : LHS.get()->getType(); + + // Avoid analyzing cases where the result will either be invalid (and + // diagnosed as such) or entirely valid and not something to warn about. + if ((!LHSNull && !RHSNull) || NonNullType->isBlockPointerType() || + NonNullType->isMemberPointerType() || NonNullType->isFunctionType()) + return; + + // Comparison operations would not make sense with a null pointer no matter + // what the other expression is. + if (!IsCompare) { + S.Diag(Loc, diag::warn_null_in_arithmetic_operation) + << (LHSNull ? LHS.get()->getSourceRange() : SourceRange()) + << (RHSNull ? RHS.get()->getSourceRange() : SourceRange()); + return; + } + + // The rest of the operations only make sense with a null pointer + // if the other expression is a pointer. + if (LHSNull == RHSNull || NonNullType->isAnyPointerType() || + NonNullType->canDecayToPointerType()) + return; + + S.Diag(Loc, diag::warn_null_in_comparison_operation) + << LHSNull /* LHS is NULL */ << NonNullType + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); +} + +QualType Sema::CheckMultiplyDivideOperands(ExprResult &LHS, ExprResult &RHS, + SourceLocation Loc, + bool IsCompAssign, bool IsDiv) { + checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/false); + + if (LHS.get()->getType()->isVectorType() || + RHS.get()->getType()->isVectorType()) + return CheckVectorOperands(LHS, RHS, Loc, IsCompAssign); + + QualType compType = UsualArithmeticConversions(LHS, RHS, IsCompAssign); + if (LHS.isInvalid() || RHS.isInvalid()) + return QualType(); + + + if (!LHS.get()->getType()->isArithmeticType() || + !RHS.get()->getType()->isArithmeticType()) { + if (IsCompAssign && + LHS.get()->getType()->isAtomicType() && + RHS.get()->getType()->isArithmeticType()) + return compType; + return InvalidOperands(Loc, LHS, RHS); + } + + // Check for division by zero. + if (IsDiv && + RHS.get()->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNotNull)) + DiagRuntimeBehavior(Loc, RHS.get(), PDiag(diag::warn_division_by_zero) + << RHS.get()->getSourceRange()); + + return compType; +} + +QualType Sema::CheckRemainderOperands( + ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, bool IsCompAssign) { + checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/false); + + if (LHS.get()->getType()->isVectorType() || + RHS.get()->getType()->isVectorType()) { + if (LHS.get()->getType()->hasIntegerRepresentation() && + RHS.get()->getType()->hasIntegerRepresentation()) + return CheckVectorOperands(LHS, RHS, Loc, IsCompAssign); + return InvalidOperands(Loc, LHS, RHS); + } + + QualType compType = UsualArithmeticConversions(LHS, RHS, IsCompAssign); + if (LHS.isInvalid() || RHS.isInvalid()) + return QualType(); + + if (!LHS.get()->getType()->isIntegerType() || + !RHS.get()->getType()->isIntegerType()) + return InvalidOperands(Loc, LHS, RHS); + + // Check for remainder by zero. + if (RHS.get()->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNotNull)) + DiagRuntimeBehavior(Loc, RHS.get(), PDiag(diag::warn_remainder_by_zero) + << RHS.get()->getSourceRange()); + + return compType; +} + +/// \brief Diagnose invalid arithmetic on two void pointers. +static void diagnoseArithmeticOnTwoVoidPointers(Sema &S, SourceLocation Loc, + Expr *LHSExpr, Expr *RHSExpr) { + S.Diag(Loc, S.getLangOpts().CPlusPlus + ? diag::err_typecheck_pointer_arith_void_type + : diag::ext_gnu_void_ptr) + << 1 /* two pointers */ << LHSExpr->getSourceRange() + << RHSExpr->getSourceRange(); +} + +/// \brief Diagnose invalid arithmetic on a void pointer. +static void diagnoseArithmeticOnVoidPointer(Sema &S, SourceLocation Loc, + Expr *Pointer) { + S.Diag(Loc, S.getLangOpts().CPlusPlus + ? diag::err_typecheck_pointer_arith_void_type + : diag::ext_gnu_void_ptr) + << 0 /* one pointer */ << Pointer->getSourceRange(); +} + +/// \brief Diagnose invalid arithmetic on two function pointers. +static void diagnoseArithmeticOnTwoFunctionPointers(Sema &S, SourceLocation Loc, + Expr *LHS, Expr *RHS) { + assert(LHS->getType()->isAnyPointerType()); + assert(RHS->getType()->isAnyPointerType()); + S.Diag(Loc, S.getLangOpts().CPlusPlus + ? diag::err_typecheck_pointer_arith_function_type + : diag::ext_gnu_ptr_func_arith) + << 1 /* two pointers */ << LHS->getType()->getPointeeType() + // We only show the second type if it differs from the first. + << (unsigned)!S.Context.hasSameUnqualifiedType(LHS->getType(), + RHS->getType()) + << RHS->getType()->getPointeeType() + << LHS->getSourceRange() << RHS->getSourceRange(); +} + +/// \brief Diagnose invalid arithmetic on a function pointer. +static void diagnoseArithmeticOnFunctionPointer(Sema &S, SourceLocation Loc, + Expr *Pointer) { + assert(Pointer->getType()->isAnyPointerType()); + S.Diag(Loc, S.getLangOpts().CPlusPlus + ? diag::err_typecheck_pointer_arith_function_type + : diag::ext_gnu_ptr_func_arith) + << 0 /* one pointer */ << Pointer->getType()->getPointeeType() + << 0 /* one pointer, so only one type */ + << Pointer->getSourceRange(); +} + +/// \brief Emit error if Operand is incomplete pointer type +/// +/// \returns True if pointer has incomplete type +static bool checkArithmeticIncompletePointerType(Sema &S, SourceLocation Loc, + Expr *Operand) { + if ((Operand->getType()->isPointerType() && + !Operand->getType()->isDependentType()) || + Operand->getType()->isObjCObjectPointerType()) { + QualType PointeeTy = Operand->getType()->getPointeeType(); + if (S.RequireCompleteType( + Loc, PointeeTy, + S.PDiag(diag::err_typecheck_arithmetic_incomplete_type) + << PointeeTy << Operand->getSourceRange())) + return true; + } + return false; +} + +/// \brief Check the validity of an arithmetic pointer operand. +/// +/// If the operand has pointer type, this code will check for pointer types +/// which are invalid in arithmetic operations. These will be diagnosed +/// appropriately, including whether or not the use is supported as an +/// extension. +/// +/// \returns True when the operand is valid to use (even if as an extension). +static bool checkArithmeticOpPointerOperand(Sema &S, SourceLocation Loc, + Expr *Operand) { + if (!Operand->getType()->isAnyPointerType()) return true; + + QualType PointeeTy = Operand->getType()->getPointeeType(); + if (PointeeTy->isVoidType()) { + diagnoseArithmeticOnVoidPointer(S, Loc, Operand); + return !S.getLangOpts().CPlusPlus; + } + if (PointeeTy->isFunctionType()) { + diagnoseArithmeticOnFunctionPointer(S, Loc, Operand); + return !S.getLangOpts().CPlusPlus; + } + + if (checkArithmeticIncompletePointerType(S, Loc, Operand)) return false; + + return true; +} + +/// \brief Check the validity of a binary arithmetic operation w.r.t. pointer +/// operands. +/// +/// This routine will diagnose any invalid arithmetic on pointer operands much +/// like \see checkArithmeticOpPointerOperand. However, it has special logic +/// for emitting a single diagnostic even for operations where both LHS and RHS +/// are (potentially problematic) pointers. +/// +/// \returns True when the operand is valid to use (even if as an extension). +static bool checkArithmeticBinOpPointerOperands(Sema &S, SourceLocation Loc, + Expr *LHSExpr, Expr *RHSExpr) { + bool isLHSPointer = LHSExpr->getType()->isAnyPointerType(); + bool isRHSPointer = RHSExpr->getType()->isAnyPointerType(); + if (!isLHSPointer && !isRHSPointer) return true; + + QualType LHSPointeeTy, RHSPointeeTy; + if (isLHSPointer) LHSPointeeTy = LHSExpr->getType()->getPointeeType(); + if (isRHSPointer) RHSPointeeTy = RHSExpr->getType()->getPointeeType(); + + // Check for arithmetic on pointers to incomplete types. + bool isLHSVoidPtr = isLHSPointer && LHSPointeeTy->isVoidType(); + bool isRHSVoidPtr = isRHSPointer && RHSPointeeTy->isVoidType(); + if (isLHSVoidPtr || isRHSVoidPtr) { + if (!isRHSVoidPtr) diagnoseArithmeticOnVoidPointer(S, Loc, LHSExpr); + else if (!isLHSVoidPtr) diagnoseArithmeticOnVoidPointer(S, Loc, RHSExpr); + else diagnoseArithmeticOnTwoVoidPointers(S, Loc, LHSExpr, RHSExpr); + + return !S.getLangOpts().CPlusPlus; + } + + bool isLHSFuncPtr = isLHSPointer && LHSPointeeTy->isFunctionType(); + bool isRHSFuncPtr = isRHSPointer && RHSPointeeTy->isFunctionType(); + if (isLHSFuncPtr || isRHSFuncPtr) { + if (!isRHSFuncPtr) diagnoseArithmeticOnFunctionPointer(S, Loc, LHSExpr); + else if (!isLHSFuncPtr) diagnoseArithmeticOnFunctionPointer(S, Loc, + RHSExpr); + else diagnoseArithmeticOnTwoFunctionPointers(S, Loc, LHSExpr, RHSExpr); + + return !S.getLangOpts().CPlusPlus; + } + + if (checkArithmeticIncompletePointerType(S, Loc, LHSExpr)) return false; + if (checkArithmeticIncompletePointerType(S, Loc, RHSExpr)) return false; + + return true; +} + +/// \brief Check bad cases where we step over interface counts. +static bool checkArithmethicPointerOnNonFragileABI(Sema &S, + SourceLocation OpLoc, + Expr *Op) { + assert(Op->getType()->isAnyPointerType()); + QualType PointeeTy = Op->getType()->getPointeeType(); + if (!PointeeTy->isObjCObjectType() || !S.LangOpts.ObjCNonFragileABI) + return true; + + S.Diag(OpLoc, diag::err_arithmetic_nonfragile_interface) + << PointeeTy << Op->getSourceRange(); + return false; +} + +/// diagnoseStringPlusInt - Emit a warning when adding an integer to a string +/// literal. +static void diagnoseStringPlusInt(Sema &Self, SourceLocation OpLoc, + Expr *LHSExpr, Expr *RHSExpr) { + StringLiteral* StrExpr = dyn_cast(LHSExpr->IgnoreImpCasts()); + Expr* IndexExpr = RHSExpr; + if (!StrExpr) { + StrExpr = dyn_cast(RHSExpr->IgnoreImpCasts()); + IndexExpr = LHSExpr; + } + + bool IsStringPlusInt = StrExpr && + IndexExpr->getType()->isIntegralOrUnscopedEnumerationType(); + if (!IsStringPlusInt) + return; + + llvm::APSInt index; + if (IndexExpr->EvaluateAsInt(index, Self.getASTContext())) { + unsigned StrLenWithNull = StrExpr->getLength() + 1; + if (index.isNonNegative() && + index <= llvm::APSInt(llvm::APInt(index.getBitWidth(), StrLenWithNull), + index.isUnsigned())) + return; + } + + SourceRange DiagRange(LHSExpr->getLocStart(), RHSExpr->getLocEnd()); + Self.Diag(OpLoc, diag::warn_string_plus_int) + << DiagRange << IndexExpr->IgnoreImpCasts()->getType(); + + // Only print a fixit for "str" + int, not for int + "str". + if (IndexExpr == RHSExpr) { + SourceLocation EndLoc = Self.PP.getLocForEndOfToken(RHSExpr->getLocEnd()); + Self.Diag(OpLoc, diag::note_string_plus_int_silence) + << FixItHint::CreateInsertion(LHSExpr->getLocStart(), "&") + << FixItHint::CreateReplacement(SourceRange(OpLoc), "[") + << FixItHint::CreateInsertion(EndLoc, "]"); + } else + Self.Diag(OpLoc, diag::note_string_plus_int_silence); +} + +/// \brief Emit error when two pointers are incompatible. +static void diagnosePointerIncompatibility(Sema &S, SourceLocation Loc, + Expr *LHSExpr, Expr *RHSExpr) { + assert(LHSExpr->getType()->isAnyPointerType()); + assert(RHSExpr->getType()->isAnyPointerType()); + S.Diag(Loc, diag::err_typecheck_sub_ptr_compatible) + << LHSExpr->getType() << RHSExpr->getType() << LHSExpr->getSourceRange() + << RHSExpr->getSourceRange(); +} + +QualType Sema::CheckAdditionOperands( // C99 6.5.6 + ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, unsigned Opc, + QualType* CompLHSTy) { + checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/false); + + if (LHS.get()->getType()->isVectorType() || + RHS.get()->getType()->isVectorType()) { + QualType compType = CheckVectorOperands(LHS, RHS, Loc, CompLHSTy); + if (CompLHSTy) *CompLHSTy = compType; + return compType; + } + + QualType compType = UsualArithmeticConversions(LHS, RHS, CompLHSTy); + if (LHS.isInvalid() || RHS.isInvalid()) + return QualType(); + + // Diagnose "string literal" '+' int. + if (Opc == BO_Add) + diagnoseStringPlusInt(*this, Loc, LHS.get(), RHS.get()); + + // handle the common case first (both operands are arithmetic). + if (LHS.get()->getType()->isArithmeticType() && + RHS.get()->getType()->isArithmeticType()) { + if (CompLHSTy) *CompLHSTy = compType; + return compType; + } + + if (LHS.get()->getType()->isAtomicType() && + RHS.get()->getType()->isArithmeticType()) { + *CompLHSTy = LHS.get()->getType(); + return compType; + } + + // Put any potential pointer into PExp + Expr* PExp = LHS.get(), *IExp = RHS.get(); + if (IExp->getType()->isAnyPointerType()) + std::swap(PExp, IExp); + + if (!PExp->getType()->isAnyPointerType()) + return InvalidOperands(Loc, LHS, RHS); + + if (!IExp->getType()->isIntegerType()) + return InvalidOperands(Loc, LHS, RHS); + + if (!checkArithmeticOpPointerOperand(*this, Loc, PExp)) + return QualType(); + + // Diagnose bad cases where we step over interface counts. + if (!checkArithmethicPointerOnNonFragileABI(*this, Loc, PExp)) + return QualType(); + + // Check array bounds for pointer arithemtic + CheckArrayAccess(PExp, IExp); + + if (CompLHSTy) { + QualType LHSTy = Context.isPromotableBitField(LHS.get()); + if (LHSTy.isNull()) { + LHSTy = LHS.get()->getType(); + if (LHSTy->isPromotableIntegerType()) + LHSTy = Context.getPromotedIntegerType(LHSTy); + } + *CompLHSTy = LHSTy; + } + + return PExp->getType(); +} + +// C99 6.5.6 +QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS, + SourceLocation Loc, + QualType* CompLHSTy) { + checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/false); + + if (LHS.get()->getType()->isVectorType() || + RHS.get()->getType()->isVectorType()) { + QualType compType = CheckVectorOperands(LHS, RHS, Loc, CompLHSTy); + if (CompLHSTy) *CompLHSTy = compType; + return compType; + } + + QualType compType = UsualArithmeticConversions(LHS, RHS, CompLHSTy); + if (LHS.isInvalid() || RHS.isInvalid()) + return QualType(); + + // Enforce type constraints: C99 6.5.6p3. + + // Handle the common case first (both operands are arithmetic). + if (LHS.get()->getType()->isArithmeticType() && + RHS.get()->getType()->isArithmeticType()) { + if (CompLHSTy) *CompLHSTy = compType; + return compType; + } + + if (LHS.get()->getType()->isAtomicType() && + RHS.get()->getType()->isArithmeticType()) { + *CompLHSTy = LHS.get()->getType(); + return compType; + } + + // Either ptr - int or ptr - ptr. + if (LHS.get()->getType()->isAnyPointerType()) { + QualType lpointee = LHS.get()->getType()->getPointeeType(); + + // Diagnose bad cases where we step over interface counts. + if (!checkArithmethicPointerOnNonFragileABI(*this, Loc, LHS.get())) + return QualType(); + + // The result type of a pointer-int computation is the pointer type. + if (RHS.get()->getType()->isIntegerType()) { + if (!checkArithmeticOpPointerOperand(*this, Loc, LHS.get())) + return QualType(); + + // Check array bounds for pointer arithemtic + CheckArrayAccess(LHS.get(), RHS.get(), /*ArraySubscriptExpr*/0, + /*AllowOnePastEnd*/true, /*IndexNegated*/true); + + if (CompLHSTy) *CompLHSTy = LHS.get()->getType(); + return LHS.get()->getType(); + } + + // Handle pointer-pointer subtractions. + if (const PointerType *RHSPTy + = RHS.get()->getType()->getAs()) { + QualType rpointee = RHSPTy->getPointeeType(); + + if (getLangOpts().CPlusPlus) { + // Pointee types must be the same: C++ [expr.add] + if (!Context.hasSameUnqualifiedType(lpointee, rpointee)) { + diagnosePointerIncompatibility(*this, Loc, LHS.get(), RHS.get()); + } + } else { + // Pointee types must be compatible C99 6.5.6p3 + if (!Context.typesAreCompatible( + Context.getCanonicalType(lpointee).getUnqualifiedType(), + Context.getCanonicalType(rpointee).getUnqualifiedType())) { + diagnosePointerIncompatibility(*this, Loc, LHS.get(), RHS.get()); + return QualType(); + } + } + + if (!checkArithmeticBinOpPointerOperands(*this, Loc, + LHS.get(), RHS.get())) + return QualType(); + + if (CompLHSTy) *CompLHSTy = LHS.get()->getType(); + return Context.getPointerDiffType(); + } + } + + return InvalidOperands(Loc, LHS, RHS); +} + +static bool isScopedEnumerationType(QualType T) { + if (const EnumType *ET = dyn_cast(T)) + return ET->getDecl()->isScoped(); + return false; +} + +static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS, + SourceLocation Loc, unsigned Opc, + QualType LHSType) { + llvm::APSInt Right; + // Check right/shifter operand + if (RHS.get()->isValueDependent() || + !RHS.get()->isIntegerConstantExpr(Right, S.Context)) + return; + + if (Right.isNegative()) { + S.DiagRuntimeBehavior(Loc, RHS.get(), + S.PDiag(diag::warn_shift_negative) + << RHS.get()->getSourceRange()); + return; + } + llvm::APInt LeftBits(Right.getBitWidth(), + S.Context.getTypeSize(LHS.get()->getType())); + if (Right.uge(LeftBits)) { + S.DiagRuntimeBehavior(Loc, RHS.get(), + S.PDiag(diag::warn_shift_gt_typewidth) + << RHS.get()->getSourceRange()); + return; + } + if (Opc != BO_Shl) + return; + + // When left shifting an ICE which is signed, we can check for overflow which + // according to C++ has undefined behavior ([expr.shift] 5.8/2). Unsigned + // integers have defined behavior modulo one more than the maximum value + // representable in the result type, so never warn for those. + llvm::APSInt Left; + if (LHS.get()->isValueDependent() || + !LHS.get()->isIntegerConstantExpr(Left, S.Context) || + LHSType->hasUnsignedIntegerRepresentation()) + return; + llvm::APInt ResultBits = + static_cast(Right) + Left.getMinSignedBits(); + if (LeftBits.uge(ResultBits)) + return; + llvm::APSInt Result = Left.extend(ResultBits.getLimitedValue()); + Result = Result.shl(Right); + + // Print the bit representation of the signed integer as an unsigned + // hexadecimal number. + SmallString<40> HexResult; + Result.toString(HexResult, 16, /*Signed =*/false, /*Literal =*/true); + + // If we are only missing a sign bit, this is less likely to result in actual + // bugs -- if the result is cast back to an unsigned type, it will have the + // expected value. Thus we place this behind a different warning that can be + // turned off separately if needed. + if (LeftBits == ResultBits - 1) { + S.Diag(Loc, diag::warn_shift_result_sets_sign_bit) + << HexResult.str() << LHSType + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + return; + } + + S.Diag(Loc, diag::warn_shift_result_gt_typewidth) + << HexResult.str() << Result.getMinSignedBits() << LHSType + << Left.getBitWidth() << LHS.get()->getSourceRange() + << RHS.get()->getSourceRange(); +} + +// C99 6.5.7 +QualType Sema::CheckShiftOperands(ExprResult &LHS, ExprResult &RHS, + SourceLocation Loc, unsigned Opc, + bool IsCompAssign) { + checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/false); + + // C99 6.5.7p2: Each of the operands shall have integer type. + if (!LHS.get()->getType()->hasIntegerRepresentation() || + !RHS.get()->getType()->hasIntegerRepresentation()) + return InvalidOperands(Loc, LHS, RHS); + + // C++0x: Don't allow scoped enums. FIXME: Use something better than + // hasIntegerRepresentation() above instead of this. + if (isScopedEnumerationType(LHS.get()->getType()) || + isScopedEnumerationType(RHS.get()->getType())) { + return InvalidOperands(Loc, LHS, RHS); + } + + // Vector shifts promote their scalar inputs to vector type. + if (LHS.get()->getType()->isVectorType() || + RHS.get()->getType()->isVectorType()) + return CheckVectorOperands(LHS, RHS, Loc, IsCompAssign); + + // Shifts don't perform usual arithmetic conversions, they just do integer + // promotions on each operand. C99 6.5.7p3 + + // For the LHS, do usual unary conversions, but then reset them away + // if this is a compound assignment. + ExprResult OldLHS = LHS; + LHS = UsualUnaryConversions(LHS.take()); + if (LHS.isInvalid()) + return QualType(); + QualType LHSType = LHS.get()->getType(); + if (IsCompAssign) LHS = OldLHS; + + // The RHS is simpler. + RHS = UsualUnaryConversions(RHS.take()); + if (RHS.isInvalid()) + return QualType(); + + // Sanity-check shift operands + DiagnoseBadShiftValues(*this, LHS, RHS, Loc, Opc, LHSType); + + // "The type of the result is that of the promoted left operand." + return LHSType; +} + +static bool IsWithinTemplateSpecialization(Decl *D) { + if (DeclContext *DC = D->getDeclContext()) { + if (isa(DC)) + return true; + if (FunctionDecl *FD = dyn_cast(DC)) + return FD->isFunctionTemplateSpecialization(); + } + return false; +} + +/// If two different enums are compared, raise a warning. +static void checkEnumComparison(Sema &S, SourceLocation Loc, ExprResult &LHS, + ExprResult &RHS) { + QualType LHSStrippedType = LHS.get()->IgnoreParenImpCasts()->getType(); + QualType RHSStrippedType = RHS.get()->IgnoreParenImpCasts()->getType(); + + const EnumType *LHSEnumType = LHSStrippedType->getAs(); + if (!LHSEnumType) + return; + const EnumType *RHSEnumType = RHSStrippedType->getAs(); + if (!RHSEnumType) + return; + + // Ignore anonymous enums. + if (!LHSEnumType->getDecl()->getIdentifier()) + return; + if (!RHSEnumType->getDecl()->getIdentifier()) + return; + + if (S.Context.hasSameUnqualifiedType(LHSStrippedType, RHSStrippedType)) + return; + + S.Diag(Loc, diag::warn_comparison_of_mixed_enum_types) + << LHSStrippedType << RHSStrippedType + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); +} + +/// \brief Diagnose bad pointer comparisons. +static void diagnoseDistinctPointerComparison(Sema &S, SourceLocation Loc, + ExprResult &LHS, ExprResult &RHS, + bool IsError) { + S.Diag(Loc, IsError ? diag::err_typecheck_comparison_of_distinct_pointers + : diag::ext_typecheck_comparison_of_distinct_pointers) + << LHS.get()->getType() << RHS.get()->getType() + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); +} + +/// \brief Returns false if the pointers are converted to a composite type, +/// true otherwise. +static bool convertPointersToCompositeType(Sema &S, SourceLocation Loc, + ExprResult &LHS, ExprResult &RHS) { + // C++ [expr.rel]p2: + // [...] Pointer conversions (4.10) and qualification + // conversions (4.4) are performed on pointer operands (or on + // a pointer operand and a null pointer constant) to bring + // them to their composite pointer type. [...] + // + // C++ [expr.eq]p1 uses the same notion for (in)equality + // comparisons of pointers. + + // C++ [expr.eq]p2: + // In addition, pointers to members can be compared, or a pointer to + // member and a null pointer constant. Pointer to member conversions + // (4.11) and qualification conversions (4.4) are performed to bring + // them to a common type. If one operand is a null pointer constant, + // the common type is the type of the other operand. Otherwise, the + // common type is a pointer to member type similar (4.4) to the type + // of one of the operands, with a cv-qualification signature (4.4) + // that is the union of the cv-qualification signatures of the operand + // types. + + QualType LHSType = LHS.get()->getType(); + QualType RHSType = RHS.get()->getType(); + assert((LHSType->isPointerType() && RHSType->isPointerType()) || + (LHSType->isMemberPointerType() && RHSType->isMemberPointerType())); + + bool NonStandardCompositeType = false; + bool *BoolPtr = S.isSFINAEContext() ? 0 : &NonStandardCompositeType; + QualType T = S.FindCompositePointerType(Loc, LHS, RHS, BoolPtr); + if (T.isNull()) { + diagnoseDistinctPointerComparison(S, Loc, LHS, RHS, /*isError*/true); + return true; + } + + if (NonStandardCompositeType) + S.Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers_nonstandard) + << LHSType << RHSType << T << LHS.get()->getSourceRange() + << RHS.get()->getSourceRange(); + + LHS = S.ImpCastExprToType(LHS.take(), T, CK_BitCast); + RHS = S.ImpCastExprToType(RHS.take(), T, CK_BitCast); + return false; +} + +static void diagnoseFunctionPointerToVoidComparison(Sema &S, SourceLocation Loc, + ExprResult &LHS, + ExprResult &RHS, + bool IsError) { + S.Diag(Loc, IsError ? diag::err_typecheck_comparison_of_fptr_to_void + : diag::ext_typecheck_comparison_of_fptr_to_void) + << LHS.get()->getType() << RHS.get()->getType() + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); +} + +// C99 6.5.8, C++ [expr.rel] +QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, + SourceLocation Loc, unsigned OpaqueOpc, + bool IsRelational) { + checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/true); + + BinaryOperatorKind Opc = (BinaryOperatorKind) OpaqueOpc; + + // Handle vector comparisons separately. + if (LHS.get()->getType()->isVectorType() || + RHS.get()->getType()->isVectorType()) + return CheckVectorCompareOperands(LHS, RHS, Loc, IsRelational); + + QualType LHSType = LHS.get()->getType(); + QualType RHSType = RHS.get()->getType(); + + Expr *LHSStripped = LHS.get()->IgnoreParenImpCasts(); + Expr *RHSStripped = RHS.get()->IgnoreParenImpCasts(); + + checkEnumComparison(*this, Loc, LHS, RHS); + + if (!LHSType->hasFloatingRepresentation() && + !(LHSType->isBlockPointerType() && IsRelational) && + !LHS.get()->getLocStart().isMacroID() && + !RHS.get()->getLocStart().isMacroID()) { + // For non-floating point types, check for self-comparisons of the form + // x == x, x != x, x < x, etc. These always evaluate to a constant, and + // often indicate logic errors in the program. + // + // NOTE: Don't warn about comparison expressions resulting from macro + // expansion. Also don't warn about comparisons which are only self + // comparisons within a template specialization. The warnings should catch + // obvious cases in the definition of the template anyways. The idea is to + // warn when the typed comparison operator will always evaluate to the same + // result. + if (DeclRefExpr* DRL = dyn_cast(LHSStripped)) { + if (DeclRefExpr* DRR = dyn_cast(RHSStripped)) { + if (DRL->getDecl() == DRR->getDecl() && + !IsWithinTemplateSpecialization(DRL->getDecl())) { + DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always) + << 0 // self- + << (Opc == BO_EQ + || Opc == BO_LE + || Opc == BO_GE)); + } else if (LHSType->isArrayType() && RHSType->isArrayType() && + !DRL->getDecl()->getType()->isReferenceType() && + !DRR->getDecl()->getType()->isReferenceType()) { + // what is it always going to eval to? + char always_evals_to; + switch(Opc) { + case BO_EQ: // e.g. array1 == array2 + always_evals_to = 0; // false + break; + case BO_NE: // e.g. array1 != array2 + always_evals_to = 1; // true + break; + default: + // best we can say is 'a constant' + always_evals_to = 2; // e.g. array1 <= array2 + break; + } + DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always) + << 1 // array + << always_evals_to); + } + } + } + + if (isa(LHSStripped)) + LHSStripped = LHSStripped->IgnoreParenCasts(); + if (isa(RHSStripped)) + RHSStripped = RHSStripped->IgnoreParenCasts(); + + // Warn about comparisons against a string constant (unless the other + // operand is null), the user probably wants strcmp. + Expr *literalString = 0; + Expr *literalStringStripped = 0; + if ((isa(LHSStripped) || isa(LHSStripped)) && + !RHSStripped->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNull)) { + literalString = LHS.get(); + literalStringStripped = LHSStripped; + } else if ((isa(RHSStripped) || + isa(RHSStripped)) && + !LHSStripped->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNull)) { + literalString = RHS.get(); + literalStringStripped = RHSStripped; + } + + if (literalString) { + std::string resultComparison; + switch (Opc) { + 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: llvm_unreachable("Invalid comparison operator"); + } + + DiagRuntimeBehavior(Loc, 0, + PDiag(diag::warn_stringcompare) + << isa(literalStringStripped) + << literalString->getSourceRange()); + } + } + + // C99 6.5.8p3 / C99 6.5.9p4 + if (LHS.get()->getType()->isArithmeticType() && + RHS.get()->getType()->isArithmeticType()) { + UsualArithmeticConversions(LHS, RHS); + if (LHS.isInvalid() || RHS.isInvalid()) + return QualType(); + } + else { + LHS = UsualUnaryConversions(LHS.take()); + if (LHS.isInvalid()) + return QualType(); + + RHS = UsualUnaryConversions(RHS.take()); + if (RHS.isInvalid()) + return QualType(); + } + + LHSType = LHS.get()->getType(); + RHSType = RHS.get()->getType(); + + // The result of comparisons is 'bool' in C++, 'int' in C. + QualType ResultTy = Context.getLogicalOperationType(); + + if (IsRelational) { + if (LHSType->isRealType() && RHSType->isRealType()) + return ResultTy; + } else { + // Check for comparisons of floating point operands using != and ==. + if (LHSType->hasFloatingRepresentation()) + CheckFloatComparison(Loc, LHS.get(), RHS.get()); + + if (LHSType->isArithmeticType() && RHSType->isArithmeticType()) + return ResultTy; + } + + bool LHSIsNull = LHS.get()->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNull); + bool RHSIsNull = RHS.get()->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNull); + + // All of the following pointer-related warnings are GCC extensions, except + // when handling null pointer constants. + if (LHSType->isPointerType() && RHSType->isPointerType()) { // C99 6.5.8p2 + QualType LCanPointeeTy = + LHSType->castAs()->getPointeeType().getCanonicalType(); + QualType RCanPointeeTy = + RHSType->castAs()->getPointeeType().getCanonicalType(); + + if (getLangOpts().CPlusPlus) { + if (LCanPointeeTy == RCanPointeeTy) + return ResultTy; + if (!IsRelational && + (LCanPointeeTy->isVoidType() || RCanPointeeTy->isVoidType())) { + // Valid unless comparison between non-null pointer and function pointer + // This is a gcc extension compatibility comparison. + // In a SFINAE context, we treat this as a hard error to maintain + // conformance with the C++ standard. + if ((LCanPointeeTy->isFunctionType() || RCanPointeeTy->isFunctionType()) + && !LHSIsNull && !RHSIsNull) { + diagnoseFunctionPointerToVoidComparison( + *this, Loc, LHS, RHS, /*isError*/ isSFINAEContext()); + + if (isSFINAEContext()) + return QualType(); + + RHS = ImpCastExprToType(RHS.take(), LHSType, CK_BitCast); + return ResultTy; + } + } + + if (convertPointersToCompositeType(*this, Loc, LHS, RHS)) + return QualType(); + else + return ResultTy; + } + // C99 6.5.9p2 and C99 6.5.8p2 + if (Context.typesAreCompatible(LCanPointeeTy.getUnqualifiedType(), + RCanPointeeTy.getUnqualifiedType())) { + // Valid unless a relational comparison of function pointers + if (IsRelational && LCanPointeeTy->isFunctionType()) { + Diag(Loc, diag::ext_typecheck_ordered_comparison_of_function_pointers) + << LHSType << RHSType << LHS.get()->getSourceRange() + << RHS.get()->getSourceRange(); + } + } else if (!IsRelational && + (LCanPointeeTy->isVoidType() || RCanPointeeTy->isVoidType())) { + // Valid unless comparison between non-null pointer and function pointer + if ((LCanPointeeTy->isFunctionType() || RCanPointeeTy->isFunctionType()) + && !LHSIsNull && !RHSIsNull) + diagnoseFunctionPointerToVoidComparison(*this, Loc, LHS, RHS, + /*isError*/false); + } else { + // Invalid + diagnoseDistinctPointerComparison(*this, Loc, LHS, RHS, /*isError*/false); + } + if (LCanPointeeTy != RCanPointeeTy) { + if (LHSIsNull && !RHSIsNull) + LHS = ImpCastExprToType(LHS.take(), RHSType, CK_BitCast); + else + RHS = ImpCastExprToType(RHS.take(), LHSType, CK_BitCast); + } + return ResultTy; + } + + if (getLangOpts().CPlusPlus) { + // Comparison of nullptr_t with itself. + if (LHSType->isNullPtrType() && RHSType->isNullPtrType()) + return ResultTy; + + // Comparison of pointers with null pointer constants and equality + // comparisons of member pointers to null pointer constants. + if (RHSIsNull && + ((LHSType->isAnyPointerType() || LHSType->isNullPtrType()) || + (!IsRelational && + (LHSType->isMemberPointerType() || LHSType->isBlockPointerType())))) { + RHS = ImpCastExprToType(RHS.take(), LHSType, + LHSType->isMemberPointerType() + ? CK_NullToMemberPointer + : CK_NullToPointer); + return ResultTy; + } + if (LHSIsNull && + ((RHSType->isAnyPointerType() || RHSType->isNullPtrType()) || + (!IsRelational && + (RHSType->isMemberPointerType() || RHSType->isBlockPointerType())))) { + LHS = ImpCastExprToType(LHS.take(), RHSType, + RHSType->isMemberPointerType() + ? CK_NullToMemberPointer + : CK_NullToPointer); + return ResultTy; + } + + // Comparison of member pointers. + if (!IsRelational && + LHSType->isMemberPointerType() && RHSType->isMemberPointerType()) { + if (convertPointersToCompositeType(*this, Loc, LHS, RHS)) + return QualType(); + else + return ResultTy; + } + + // Handle scoped enumeration types specifically, since they don't promote + // to integers. + if (LHS.get()->getType()->isEnumeralType() && + Context.hasSameUnqualifiedType(LHS.get()->getType(), + RHS.get()->getType())) + return ResultTy; + } + + // Handle block pointer types. + if (!IsRelational && LHSType->isBlockPointerType() && + RHSType->isBlockPointerType()) { + QualType lpointee = LHSType->castAs()->getPointeeType(); + QualType rpointee = RHSType->castAs()->getPointeeType(); + + if (!LHSIsNull && !RHSIsNull && + !Context.typesAreCompatible(lpointee, rpointee)) { + Diag(Loc, diag::err_typecheck_comparison_of_distinct_blocks) + << LHSType << RHSType << LHS.get()->getSourceRange() + << RHS.get()->getSourceRange(); + } + RHS = ImpCastExprToType(RHS.take(), LHSType, CK_BitCast); + return ResultTy; + } + + // Allow block pointers to be compared with null pointer constants. + if (!IsRelational + && ((LHSType->isBlockPointerType() && RHSType->isPointerType()) + || (LHSType->isPointerType() && RHSType->isBlockPointerType()))) { + if (!LHSIsNull && !RHSIsNull) { + if (!((RHSType->isPointerType() && RHSType->castAs() + ->getPointeeType()->isVoidType()) + || (LHSType->isPointerType() && LHSType->castAs() + ->getPointeeType()->isVoidType()))) + Diag(Loc, diag::err_typecheck_comparison_of_distinct_blocks) + << LHSType << RHSType << LHS.get()->getSourceRange() + << RHS.get()->getSourceRange(); + } + if (LHSIsNull && !RHSIsNull) + LHS = ImpCastExprToType(LHS.take(), RHSType, + RHSType->isPointerType() ? CK_BitCast + : CK_AnyPointerToBlockPointerCast); + else + RHS = ImpCastExprToType(RHS.take(), LHSType, + LHSType->isPointerType() ? CK_BitCast + : CK_AnyPointerToBlockPointerCast); + return ResultTy; + } + + if (LHSType->isObjCObjectPointerType() || + RHSType->isObjCObjectPointerType()) { + const PointerType *LPT = LHSType->getAs(); + const PointerType *RPT = RHSType->getAs(); + if (LPT || RPT) { + bool LPtrToVoid = LPT ? LPT->getPointeeType()->isVoidType() : false; + bool RPtrToVoid = RPT ? RPT->getPointeeType()->isVoidType() : false; + + if (!LPtrToVoid && !RPtrToVoid && + !Context.typesAreCompatible(LHSType, RHSType)) { + diagnoseDistinctPointerComparison(*this, Loc, LHS, RHS, + /*isError*/false); + } + if (LHSIsNull && !RHSIsNull) + LHS = ImpCastExprToType(LHS.take(), RHSType, + RPT ? CK_BitCast :CK_CPointerToObjCPointerCast); + else + RHS = ImpCastExprToType(RHS.take(), LHSType, + LPT ? CK_BitCast :CK_CPointerToObjCPointerCast); + return ResultTy; + } + if (LHSType->isObjCObjectPointerType() && + RHSType->isObjCObjectPointerType()) { + if (!Context.areComparableObjCPointerTypes(LHSType, RHSType)) + diagnoseDistinctPointerComparison(*this, Loc, LHS, RHS, + /*isError*/false); + if (LHSIsNull && !RHSIsNull) + LHS = ImpCastExprToType(LHS.take(), RHSType, CK_BitCast); + else + RHS = ImpCastExprToType(RHS.take(), LHSType, CK_BitCast); + return ResultTy; + } + } + if ((LHSType->isAnyPointerType() && RHSType->isIntegerType()) || + (LHSType->isIntegerType() && RHSType->isAnyPointerType())) { + unsigned DiagID = 0; + bool isError = false; + if ((LHSIsNull && LHSType->isIntegerType()) || + (RHSIsNull && RHSType->isIntegerType())) { + if (IsRelational && !getLangOpts().CPlusPlus) + DiagID = diag::ext_typecheck_ordered_comparison_of_pointer_and_zero; + } else if (IsRelational && !getLangOpts().CPlusPlus) + DiagID = diag::ext_typecheck_ordered_comparison_of_pointer_integer; + else if (getLangOpts().CPlusPlus) { + DiagID = diag::err_typecheck_comparison_of_pointer_integer; + isError = true; + } else + DiagID = diag::ext_typecheck_comparison_of_pointer_integer; + + if (DiagID) { + Diag(Loc, DiagID) + << LHSType << RHSType << LHS.get()->getSourceRange() + << RHS.get()->getSourceRange(); + if (isError) + return QualType(); + } + + if (LHSType->isIntegerType()) + LHS = ImpCastExprToType(LHS.take(), RHSType, + LHSIsNull ? CK_NullToPointer : CK_IntegralToPointer); + else + RHS = ImpCastExprToType(RHS.take(), LHSType, + RHSIsNull ? CK_NullToPointer : CK_IntegralToPointer); + return ResultTy; + } + + // Handle block pointers. + if (!IsRelational && RHSIsNull + && LHSType->isBlockPointerType() && RHSType->isIntegerType()) { + RHS = ImpCastExprToType(RHS.take(), LHSType, CK_NullToPointer); + return ResultTy; + } + if (!IsRelational && LHSIsNull + && LHSType->isIntegerType() && RHSType->isBlockPointerType()) { + LHS = ImpCastExprToType(LHS.take(), RHSType, CK_NullToPointer); + return ResultTy; + } + + return InvalidOperands(Loc, LHS, RHS); +} + + +// Return a signed type that is of identical size and number of elements. +// For floating point vectors, return an integer type of identical size +// and number of elements. +QualType Sema::GetSignedVectorType(QualType V) { + const VectorType *VTy = V->getAs(); + unsigned TypeSize = Context.getTypeSize(VTy->getElementType()); + if (TypeSize == Context.getTypeSize(Context.CharTy)) + return Context.getExtVectorType(Context.CharTy, VTy->getNumElements()); + else if (TypeSize == Context.getTypeSize(Context.ShortTy)) + return Context.getExtVectorType(Context.ShortTy, VTy->getNumElements()); + else if (TypeSize == Context.getTypeSize(Context.IntTy)) + return Context.getExtVectorType(Context.IntTy, VTy->getNumElements()); + else if (TypeSize == Context.getTypeSize(Context.LongTy)) + return Context.getExtVectorType(Context.LongTy, VTy->getNumElements()); + assert(TypeSize == Context.getTypeSize(Context.LongLongTy) && + "Unhandled vector element size in vector compare"); + return Context.getExtVectorType(Context.LongLongTy, VTy->getNumElements()); +} + +/// CheckVectorCompareOperands - vector comparisons are a clang extension that +/// operates on extended vector types. Instead of producing an IntTy result, +/// like a scalar comparison, a vector comparison produces a vector of integer +/// types. +QualType Sema::CheckVectorCompareOperands(ExprResult &LHS, ExprResult &RHS, + SourceLocation Loc, + bool IsRelational) { + // Check to make sure we're operating on vectors of the same type and width, + // Allowing one side to be a scalar of element type. + QualType vType = CheckVectorOperands(LHS, RHS, Loc, /*isCompAssign*/false); + if (vType.isNull()) + return vType; + + QualType LHSType = LHS.get()->getType(); + + // If AltiVec, the comparison results in a numeric type, i.e. + // bool for C++, int for C + if (vType->getAs()->getVectorKind() == VectorType::AltiVecVector) + return Context.getLogicalOperationType(); + + // For non-floating point types, check for self-comparisons of the form + // x == x, x != x, x < x, etc. These always evaluate to a constant, and + // often indicate logic errors in the program. + if (!LHSType->hasFloatingRepresentation()) { + if (DeclRefExpr* DRL + = dyn_cast(LHS.get()->IgnoreParenImpCasts())) + if (DeclRefExpr* DRR + = dyn_cast(RHS.get()->IgnoreParenImpCasts())) + if (DRL->getDecl() == DRR->getDecl()) + DiagRuntimeBehavior(Loc, 0, + PDiag(diag::warn_comparison_always) + << 0 // self- + << 2 // "a constant" + ); + } + + // Check for comparisons of floating point operands using != and ==. + if (!IsRelational && LHSType->hasFloatingRepresentation()) { + assert (RHS.get()->getType()->hasFloatingRepresentation()); + CheckFloatComparison(Loc, LHS.get(), RHS.get()); + } + + // Return a signed type for the vector. + return GetSignedVectorType(LHSType); +} + +QualType Sema::CheckVectorLogicalOperands(ExprResult &LHS, ExprResult &RHS, + SourceLocation Loc) { + // Ensure that either both operands are of the same vector type, or + // one operand is of a vector type and the other is of its element type. + QualType vType = CheckVectorOperands(LHS, RHS, Loc, false); + if (vType.isNull() || vType->isFloatingType()) + return InvalidOperands(Loc, LHS, RHS); + + return GetSignedVectorType(LHS.get()->getType()); +} + +inline QualType Sema::CheckBitwiseOperands( + ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, bool IsCompAssign) { + checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/false); + + if (LHS.get()->getType()->isVectorType() || + RHS.get()->getType()->isVectorType()) { + if (LHS.get()->getType()->hasIntegerRepresentation() && + RHS.get()->getType()->hasIntegerRepresentation()) + return CheckVectorOperands(LHS, RHS, Loc, IsCompAssign); + + return InvalidOperands(Loc, LHS, RHS); + } + + ExprResult LHSResult = Owned(LHS), RHSResult = Owned(RHS); + QualType compType = UsualArithmeticConversions(LHSResult, RHSResult, + IsCompAssign); + if (LHSResult.isInvalid() || RHSResult.isInvalid()) + return QualType(); + LHS = LHSResult.take(); + RHS = RHSResult.take(); + + if (LHS.get()->getType()->isIntegralOrUnscopedEnumerationType() && + RHS.get()->getType()->isIntegralOrUnscopedEnumerationType()) + return compType; + return InvalidOperands(Loc, LHS, RHS); +} + +inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14] + ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, unsigned Opc) { + + // Check vector operands differently. + if (LHS.get()->getType()->isVectorType() || RHS.get()->getType()->isVectorType()) + return CheckVectorLogicalOperands(LHS, RHS, Loc); + + // Diagnose cases where the user write a logical and/or but probably meant a + // bitwise one. We do this when the LHS is a non-bool integer and the RHS + // is a constant. + if (LHS.get()->getType()->isIntegerType() && + !LHS.get()->getType()->isBooleanType() && + RHS.get()->getType()->isIntegerType() && !RHS.get()->isValueDependent() && + // Don't warn in macros or template instantiations. + !Loc.isMacroID() && ActiveTemplateInstantiations.empty()) { + // 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. + // Parens on the RHS are ignored. + llvm::APSInt Result; + if (RHS.get()->EvaluateAsInt(Result, Context)) + if ((getLangOpts().Bool && !RHS.get()->getType()->isBooleanType()) || + (Result != 0 && Result != 1)) { + Diag(Loc, diag::warn_logical_instead_of_bitwise) + << RHS.get()->getSourceRange() + << (Opc == BO_LAnd ? "&&" : "||"); + // Suggest replacing the logical operator with the bitwise version + Diag(Loc, diag::note_logical_instead_of_bitwise_change_operator) + << (Opc == BO_LAnd ? "&" : "|") + << FixItHint::CreateReplacement(SourceRange( + Loc, Lexer::getLocForEndOfToken(Loc, 0, getSourceManager(), + getLangOpts())), + Opc == BO_LAnd ? "&" : "|"); + if (Opc == BO_LAnd) + // Suggest replacing "Foo() && kNonZero" with "Foo()" + Diag(Loc, diag::note_logical_instead_of_bitwise_remove_constant) + << FixItHint::CreateRemoval( + SourceRange( + Lexer::getLocForEndOfToken(LHS.get()->getLocEnd(), + 0, getSourceManager(), + getLangOpts()), + RHS.get()->getLocEnd())); + } + } + + if (!Context.getLangOpts().CPlusPlus) { + LHS = UsualUnaryConversions(LHS.take()); + if (LHS.isInvalid()) + return QualType(); + + RHS = UsualUnaryConversions(RHS.take()); + if (RHS.isInvalid()) + return QualType(); + + if (!LHS.get()->getType()->isScalarType() || + !RHS.get()->getType()->isScalarType()) + return InvalidOperands(Loc, LHS, RHS); + + return Context.IntTy; + } + + // The following is safe because we only use this method for + // non-overloadable operands. + + // C++ [expr.log.and]p1 + // C++ [expr.log.or]p1 + // The operands are both contextually converted to type bool. + ExprResult LHSRes = PerformContextuallyConvertToBool(LHS.get()); + if (LHSRes.isInvalid()) + return InvalidOperands(Loc, LHS, RHS); + LHS = move(LHSRes); + + ExprResult RHSRes = PerformContextuallyConvertToBool(RHS.get()); + if (RHSRes.isInvalid()) + return InvalidOperands(Loc, LHS, RHS); + RHS = move(RHSRes); + + // C++ [expr.log.and]p2 + // C++ [expr.log.or]p2 + // The result is a bool. + return Context.BoolTy; +} + +/// IsReadonlyProperty - Verify that otherwise a valid l-value expression +/// is a read-only property; return true if so. A readonly property expression +/// depends on various declarations and thus must be treated specially. +/// +static bool IsReadonlyProperty(Expr *E, Sema &S) { + const ObjCPropertyRefExpr *PropExpr = dyn_cast(E); + if (!PropExpr) return false; + if (PropExpr->isImplicitProperty()) return false; + + ObjCPropertyDecl *PDecl = PropExpr->getExplicitProperty(); + QualType BaseType = PropExpr->isSuperReceiver() ? + PropExpr->getSuperReceiverType() : + PropExpr->getBase()->getType(); + + if (const ObjCObjectPointerType *OPT = + BaseType->getAsObjCInterfacePointerType()) + if (ObjCInterfaceDecl *IFace = OPT->getInterfaceDecl()) + if (S.isPropertyReadonly(PDecl, IFace)) + return true; + return false; +} + +static bool IsReadonlyMessage(Expr *E, Sema &S) { + const MemberExpr *ME = dyn_cast(E); + if (!ME) return false; + if (!isa(ME->getMemberDecl())) return false; + ObjCMessageExpr *Base = + dyn_cast(ME->getBase()->IgnoreParenImpCasts()); + if (!Base) return false; + return Base->getMethodDecl() != 0; +} + +/// Is the given expression (which must be 'const') a reference to a +/// variable which was originally non-const, but which has become +/// 'const' due to being captured within a block? +enum NonConstCaptureKind { NCCK_None, NCCK_Block, NCCK_Lambda }; +static NonConstCaptureKind isReferenceToNonConstCapture(Sema &S, Expr *E) { + assert(E->isLValue() && E->getType().isConstQualified()); + E = E->IgnoreParens(); + + // Must be a reference to a declaration from an enclosing scope. + DeclRefExpr *DRE = dyn_cast(E); + if (!DRE) return NCCK_None; + if (!DRE->refersToEnclosingLocal()) return NCCK_None; + + // The declaration must be a variable which is not declared 'const'. + VarDecl *var = dyn_cast(DRE->getDecl()); + if (!var) return NCCK_None; + if (var->getType().isConstQualified()) return NCCK_None; + assert(var->hasLocalStorage() && "capture added 'const' to non-local?"); + + // Decide whether the first capture was for a block or a lambda. + DeclContext *DC = S.CurContext; + while (DC->getParent() != var->getDeclContext()) + DC = DC->getParent(); + return (isa(DC) ? NCCK_Block : NCCK_Lambda); +} + +/// CheckForModifiableLvalue - Verify that E is a modifiable lvalue. If not, +/// emit an error and return true. If so, return false. +static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) { + assert(!E->hasPlaceholderType(BuiltinType::PseudoObject)); + SourceLocation OrigLoc = Loc; + Expr::isModifiableLvalueResult IsLV = E->isModifiableLvalue(S.Context, + &Loc); + if (IsLV == Expr::MLV_Valid && IsReadonlyProperty(E, S)) + IsLV = Expr::MLV_ReadonlyProperty; + else if (IsLV == Expr::MLV_ClassTemporary && IsReadonlyMessage(E, S)) + IsLV = Expr::MLV_InvalidMessageExpression; + if (IsLV == Expr::MLV_Valid) + return false; + + unsigned Diag = 0; + bool NeedType = false; + switch (IsLV) { // C99 6.5.16p2 + case Expr::MLV_ConstQualified: + Diag = diag::err_typecheck_assign_const; + + // Use a specialized diagnostic when we're assigning to an object + // from an enclosing function or block. + if (NonConstCaptureKind NCCK = isReferenceToNonConstCapture(S, E)) { + if (NCCK == NCCK_Block) + Diag = diag::err_block_decl_ref_not_modifiable_lvalue; + else + Diag = diag::err_lambda_decl_ref_not_modifiable_lvalue; + break; + } + + // In ARC, use some specialized diagnostics for occasions where we + // infer 'const'. These are always pseudo-strong variables. + if (S.getLangOpts().ObjCAutoRefCount) { + DeclRefExpr *declRef = dyn_cast(E->IgnoreParenCasts()); + if (declRef && isa(declRef->getDecl())) { + VarDecl *var = cast(declRef->getDecl()); + + // Use the normal diagnostic if it's pseudo-__strong but the + // user actually wrote 'const'. + if (var->isARCPseudoStrong() && + (!var->getTypeSourceInfo() || + !var->getTypeSourceInfo()->getType().isConstQualified())) { + // There are two pseudo-strong cases: + // - self + ObjCMethodDecl *method = S.getCurMethodDecl(); + if (method && var == method->getSelfDecl()) + Diag = method->isClassMethod() + ? diag::err_typecheck_arc_assign_self_class_method + : diag::err_typecheck_arc_assign_self; + + // - fast enumeration variables + else + Diag = diag::err_typecheck_arr_assign_enumeration; + + SourceRange Assign; + if (Loc != OrigLoc) + Assign = SourceRange(OrigLoc, OrigLoc); + S.Diag(Loc, Diag) << E->getSourceRange() << Assign; + // We need to preserve the AST regardless, so migration tool + // can do its job. + return false; + } + } + } + + break; + case Expr::MLV_ArrayType: + Diag = diag::err_typecheck_array_not_modifiable_lvalue; + NeedType = true; + break; + case Expr::MLV_NotObjectType: + Diag = diag::err_typecheck_non_object_not_modifiable_lvalue; + NeedType = true; + break; + case Expr::MLV_LValueCast: + Diag = diag::err_typecheck_lvalue_casts_not_supported; + break; + case Expr::MLV_Valid: + llvm_unreachable("did not take early return for MLV_Valid"); + case Expr::MLV_InvalidExpression: + case Expr::MLV_MemberFunction: + case Expr::MLV_ClassTemporary: + Diag = diag::err_typecheck_expression_not_modifiable_lvalue; + break; + case Expr::MLV_IncompleteType: + case Expr::MLV_IncompleteVoidType: + return S.RequireCompleteType(Loc, E->getType(), + S.PDiag(diag::err_typecheck_incomplete_type_not_modifiable_lvalue) + << E->getSourceRange()); + case Expr::MLV_DuplicateVectorComponents: + Diag = diag::err_typecheck_duplicate_vector_components_not_mlvalue; + break; + case Expr::MLV_ReadonlyProperty: + case Expr::MLV_NoSetterProperty: + llvm_unreachable("readonly properties should be processed differently"); + case Expr::MLV_InvalidMessageExpression: + Diag = diag::error_readonly_message_assignment; + break; + case Expr::MLV_SubObjCPropertySetting: + Diag = diag::error_no_subobject_property_setting; + break; + } + + SourceRange Assign; + if (Loc != OrigLoc) + Assign = SourceRange(OrigLoc, OrigLoc); + if (NeedType) + S.Diag(Loc, Diag) << E->getType() << E->getSourceRange() << Assign; + else + S.Diag(Loc, Diag) << E->getSourceRange() << Assign; + return true; +} + + + +// C99 6.5.16.1 +QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS, + SourceLocation Loc, + QualType CompoundType) { + assert(!LHSExpr->hasPlaceholderType(BuiltinType::PseudoObject)); + + // Verify that LHS is a modifiable lvalue, and emit error if not. + if (CheckForModifiableLvalue(LHSExpr, Loc, *this)) + return QualType(); + + QualType LHSType = LHSExpr->getType(); + QualType RHSType = CompoundType.isNull() ? RHS.get()->getType() : + CompoundType; + AssignConvertType ConvTy; + if (CompoundType.isNull()) { + QualType LHSTy(LHSType); + ConvTy = CheckSingleAssignmentConstraints(LHSTy, RHS); + if (RHS.isInvalid()) + return QualType(); + // Special case of NSObject attributes on c-style pointer types. + if (ConvTy == IncompatiblePointer && + ((Context.isObjCNSObjectType(LHSType) && + RHSType->isObjCObjectPointerType()) || + (Context.isObjCNSObjectType(RHSType) && + LHSType->isObjCObjectPointerType()))) + ConvTy = Compatible; + + if (ConvTy == Compatible && + LHSType->isObjCObjectType()) + Diag(Loc, diag::err_objc_object_assignment) + << LHSType; + + // If the RHS is a unary plus or minus, check to see if they = and + are + // right next to each other. If so, the user may have typo'd "x =+ 4" + // instead of "x += 4". + Expr *RHSCheck = RHS.get(); + if (ImplicitCastExpr *ICE = dyn_cast(RHSCheck)) + RHSCheck = ICE->getSubExpr(); + if (UnaryOperator *UO = dyn_cast(RHSCheck)) { + if ((UO->getOpcode() == UO_Plus || + UO->getOpcode() == UO_Minus) && + Loc.isFileID() && UO->getOperatorLoc().isFileID() && + // Only if the two operators are exactly adjacent. + Loc.getLocWithOffset(1) == UO->getOperatorLoc() && + // And there is a space or other character before the subexpr of the + // unary +/-. We don't want to warn on "x=-1". + Loc.getLocWithOffset(2) != UO->getSubExpr()->getLocStart() && + UO->getSubExpr()->getLocStart().isFileID()) { + Diag(Loc, diag::warn_not_compound_assign) + << (UO->getOpcode() == UO_Plus ? "+" : "-") + << SourceRange(UO->getOperatorLoc(), UO->getOperatorLoc()); + } + } + + if (ConvTy == Compatible) { + if (LHSType.getObjCLifetime() == Qualifiers::OCL_Strong) + checkRetainCycles(LHSExpr, RHS.get()); + else if (getLangOpts().ObjCAutoRefCount) + checkUnsafeExprAssigns(Loc, LHSExpr, RHS.get()); + } + } else { + // Compound assignment "x += y" + ConvTy = CheckAssignmentConstraints(Loc, LHSType, RHSType); + } + + if (DiagnoseAssignmentResult(ConvTy, Loc, LHSType, RHSType, + RHS.get(), AA_Assigning)) + return QualType(); + + CheckForNullPointerDereference(*this, LHSExpr); + + // C99 6.5.16p3: The type of an assignment expression is the type of the + // left operand unless the left operand has qualified type, in which case + // it is the unqualified version of the type of the left operand. + // C99 6.5.16.1p2: In simple assignment, the value of the right operand + // is converted to the type of the assignment expression (above). + // C++ 5.17p1: the type of the assignment expression is that of its left + // operand. + return (getLangOpts().CPlusPlus + ? LHSType : LHSType.getUnqualifiedType()); +} + +// C99 6.5.17 +static QualType CheckCommaOperands(Sema &S, ExprResult &LHS, ExprResult &RHS, + SourceLocation Loc) { + S.DiagnoseUnusedExprResult(LHS.get()); + + LHS = S.CheckPlaceholderExpr(LHS.take()); + RHS = S.CheckPlaceholderExpr(RHS.take()); + if (LHS.isInvalid() || RHS.isInvalid()) + return QualType(); + + // C's comma performs lvalue conversion (C99 6.3.2.1) on both its + // operands, but not unary promotions. + // C++'s comma does not do any conversions at all (C++ [expr.comma]p1). + + // So we treat the LHS as a ignored value, and in C++ we allow the + // containing site to determine what should be done with the RHS. + LHS = S.IgnoredValueConversions(LHS.take()); + if (LHS.isInvalid()) + return QualType(); + + if (!S.getLangOpts().CPlusPlus) { + RHS = S.DefaultFunctionArrayLvalueConversion(RHS.take()); + if (RHS.isInvalid()) + return QualType(); + if (!RHS.get()->getType()->isVoidType()) + S.RequireCompleteType(Loc, RHS.get()->getType(), + diag::err_incomplete_type); + } + + return RHS.get()->getType(); +} + +/// CheckIncrementDecrementOperand - unlike most "Check" methods, this routine +/// doesn't need to call UsualUnaryConversions or UsualArithmeticConversions. +static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op, + ExprValueKind &VK, + SourceLocation OpLoc, + bool IsInc, bool IsPrefix) { + if (Op->isTypeDependent()) + return S.Context.DependentTy; + + QualType ResType = Op->getType(); + // Atomic types can be used for increment / decrement where the non-atomic + // versions can, so ignore the _Atomic() specifier for the purpose of + // checking. + if (const AtomicType *ResAtomicType = ResType->getAs()) + ResType = ResAtomicType->getValueType(); + + assert(!ResType.isNull() && "no type for increment/decrement expression"); + + if (S.getLangOpts().CPlusPlus && ResType->isBooleanType()) { + // Decrement of bool is not allowed. + if (!IsInc) { + S.Diag(OpLoc, diag::err_decrement_bool) << Op->getSourceRange(); + return QualType(); + } + // Increment of bool sets it to true, but is deprecated. + S.Diag(OpLoc, diag::warn_increment_bool) << Op->getSourceRange(); + } else if (ResType->isRealType()) { + // OK! + } else if (ResType->isAnyPointerType()) { + // C99 6.5.2.4p2, 6.5.6p2 + if (!checkArithmeticOpPointerOperand(S, OpLoc, Op)) + return QualType(); + + // Diagnose bad cases where we step over interface counts. + else if (!checkArithmethicPointerOnNonFragileABI(S, OpLoc, Op)) + return QualType(); + } else if (ResType->isAnyComplexType()) { + // C99 does not support ++/-- on complex types, we allow as an extension. + S.Diag(OpLoc, diag::ext_integer_increment_complex) + << ResType << Op->getSourceRange(); + } else if (ResType->isPlaceholderType()) { + ExprResult PR = S.CheckPlaceholderExpr(Op); + if (PR.isInvalid()) return QualType(); + return CheckIncrementDecrementOperand(S, PR.take(), VK, OpLoc, + IsInc, IsPrefix); + } else if (S.getLangOpts().AltiVec && ResType->isVectorType()) { + // OK! ( C/C++ Language Extensions for CBEA(Version 2.6) 10.3 ) + } else { + S.Diag(OpLoc, diag::err_typecheck_illegal_increment_decrement) + << ResType << int(IsInc) << Op->getSourceRange(); + return QualType(); + } + // At this point, we know we have a real, complex or pointer type. + // Now make sure the operand is a modifiable lvalue. + if (CheckForModifiableLvalue(Op, OpLoc, S)) + return QualType(); + // In C++, a prefix increment is the same type as the operand. Otherwise + // (in C or with postfix), the increment is the unqualified type of the + // operand. + if (IsPrefix && S.getLangOpts().CPlusPlus) { + VK = VK_LValue; + return ResType; + } else { + VK = VK_RValue; + return ResType.getUnqualifiedType(); + } +} + + +/// getPrimaryDecl - Helper function for CheckAddressOfOperand(). +/// This routine allows us to typecheck complex/recursive expressions +/// where the declaration is needed for type checking. We only need to +/// handle cases when the expression references a function designator +/// or is an lvalue. Here are some examples: +/// - &(x) => x +/// - &*****f => f for f a function designator. +/// - &s.xx => s +/// - &s.zz[1].yy -> s, if zz is an array +/// - *(x + 1) -> x, if x is an array +/// - &"123"[2] -> 0 +/// - & __real__ x -> x +static ValueDecl *getPrimaryDecl(Expr *E) { + switch (E->getStmtClass()) { + case Stmt::DeclRefExprClass: + return cast(E)->getDecl(); + case Stmt::MemberExprClass: + // If this is an arrow operator, the address is an offset from + // the base's value, so the object the base refers to is + // irrelevant. + if (cast(E)->isArrow()) + return 0; + // Otherwise, the expression refers to a part of the base + return getPrimaryDecl(cast(E)->getBase()); + case Stmt::ArraySubscriptExprClass: { + // FIXME: This code shouldn't be necessary! We should catch the implicit + // promotion of register arrays earlier. + Expr* Base = cast(E)->getBase(); + if (ImplicitCastExpr* ICE = dyn_cast(Base)) { + if (ICE->getSubExpr()->getType()->isArrayType()) + return getPrimaryDecl(ICE->getSubExpr()); + } + return 0; + } + case Stmt::UnaryOperatorClass: { + UnaryOperator *UO = cast(E); + + switch(UO->getOpcode()) { + case UO_Real: + case UO_Imag: + case UO_Extension: + return getPrimaryDecl(UO->getSubExpr()); + default: + return 0; + } + } + case Stmt::ParenExprClass: + return getPrimaryDecl(cast(E)->getSubExpr()); + case Stmt::ImplicitCastExprClass: + // If the result of an implicit cast is an l-value, we care about + // the sub-expression; otherwise, the result here doesn't matter. + return getPrimaryDecl(cast(E)->getSubExpr()); + default: + return 0; + } +} + +namespace { + enum { + AO_Bit_Field = 0, + AO_Vector_Element = 1, + AO_Property_Expansion = 2, + AO_Register_Variable = 3, + AO_No_Error = 4 + }; +} +/// \brief Diagnose invalid operand for address of operations. +/// +/// \param Type The type of operand which cannot have its address taken. +static void diagnoseAddressOfInvalidType(Sema &S, SourceLocation Loc, + Expr *E, unsigned Type) { + S.Diag(Loc, diag::err_typecheck_address_of) << Type << E->getSourceRange(); +} + +/// CheckAddressOfOperand - The operand of & must be either a function +/// designator or an lvalue designating an object. If it is an lvalue, the +/// object cannot be declared with storage class register or be a bit field. +/// Note: The usual conversions are *not* applied to the operand of the & +/// 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. +static QualType CheckAddressOfOperand(Sema &S, ExprResult &OrigOp, + SourceLocation OpLoc) { + if (const BuiltinType *PTy = OrigOp.get()->getType()->getAsPlaceholderType()){ + if (PTy->getKind() == BuiltinType::Overload) { + if (!isa(OrigOp.get()->IgnoreParens())) { + S.Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof) + << OrigOp.get()->getSourceRange(); + return QualType(); + } + + return S.Context.OverloadTy; + } + + if (PTy->getKind() == BuiltinType::UnknownAny) + return S.Context.UnknownAnyTy; + + if (PTy->getKind() == BuiltinType::BoundMember) { + S.Diag(OpLoc, diag::err_invalid_form_pointer_member_function) + << OrigOp.get()->getSourceRange(); + return QualType(); + } + + OrigOp = S.CheckPlaceholderExpr(OrigOp.take()); + if (OrigOp.isInvalid()) return QualType(); + } + + if (OrigOp.get()->isTypeDependent()) + return S.Context.DependentTy; + + assert(!OrigOp.get()->getType()->isPlaceholderType()); + + // Make sure to ignore parentheses in subsequent checks + Expr *op = OrigOp.get()->IgnoreParens(); + + if (S.getLangOpts().C99) { + // Implement C99-only parts of addressof rules. + if (UnaryOperator* uOp = dyn_cast(op)) { + 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(); + } + // Technically, there should be a check for array subscript + // expressions here, but the result of one is always an lvalue anyway. + } + ValueDecl *dcl = getPrimaryDecl(op); + Expr::LValueClassification lval = op->ClassifyLValue(S.Context); + unsigned AddressOfError = AO_No_Error; + + if (lval == Expr::LV_ClassTemporary) { + bool sfinae = S.isSFINAEContext(); + S.Diag(OpLoc, sfinae ? diag::err_typecheck_addrof_class_temporary + : diag::ext_typecheck_addrof_class_temporary) + << op->getType() << op->getSourceRange(); + if (sfinae) + return QualType(); + } else if (isa(op)) { + return S.Context.getPointerType(op->getType()); + } 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)) { + S.Diag(OpLoc, diag::err_invalid_form_pointer_member_function) + << OrigOp.get()->getSourceRange(); + return QualType(); + } + DeclRefExpr *DRE = cast(op); + CXXMethodDecl *MD = cast(DRE->getDecl()); + + // The id-expression was parenthesized. + if (OrigOp.get() != DRE) { + S.Diag(OpLoc, diag::err_parens_pointer_member_function) + << OrigOp.get()->getSourceRange(); + + // The method was named without a qualifier. + } else if (!DRE->getQualifier()) { + S.Diag(OpLoc, diag::err_unqualified_pointer_member_function) + << op->getSourceRange(); + } + + return S.Context.getMemberPointerType(op->getType(), + S.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()) { + // Use a special diagnostic for loads from property references. + if (isa(op)) { + AddressOfError = AO_Property_Expansion; + } else { + // FIXME: emit more specific diag... + S.Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof) + << op->getSourceRange(); + return QualType(); + } + } + } else if (op->getObjectKind() == OK_BitField) { // C99 6.5.3.2p1 + // The operand cannot be a bit-field + AddressOfError = AO_Bit_Field; + } else if (op->getObjectKind() == OK_VectorComponent) { + // The operand cannot be an element of a vector + AddressOfError = AO_Vector_Element; + } 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)) { + // in C++ it is not error to take address of a register + // variable (c++03 7.1.1P3) + if (vd->getStorageClass() == SC_Register && + !S.getLangOpts().CPlusPlus) { + AddressOfError = AO_Register_Variable; + } + } else if (isa(dcl)) { + return S.Context.OverloadTy; + } else if (isa(dcl) || isa(dcl)) { + // Okay: we can take the address of a field. + // Could be a pointer to member, though, if there is an explicit + // scope qualifier for the class. + if (isa(op) && cast(op)->getQualifier()) { + DeclContext *Ctx = dcl->getDeclContext(); + if (Ctx && Ctx->isRecord()) { + if (dcl->getType()->isReferenceType()) { + S.Diag(OpLoc, + diag::err_cannot_form_pointer_to_member_of_reference_type) + << dcl->getDeclName() << dcl->getType(); + return QualType(); + } + + while (cast(Ctx)->isAnonymousStructOrUnion()) + Ctx = Ctx->getParent(); + return S.Context.getMemberPointerType(op->getType(), + S.Context.getTypeDeclType(cast(Ctx)).getTypePtr()); + } + } + } else if (!isa(dcl) && !isa(dcl)) + llvm_unreachable("Unknown/unexpected decl type"); + } + + if (AddressOfError != AO_No_Error) { + diagnoseAddressOfInvalidType(S, OpLoc, op, AddressOfError); + return QualType(); + } + + if (lval == Expr::LV_IncompleteVoidType) { + // Taking the address of a void variable is technically illegal, but we + // allow it in cases which are otherwise valid. + // Example: "extern void x; void* y = &x;". + S.Diag(OpLoc, diag::ext_typecheck_addrof_void) << op->getSourceRange(); + } + + // If the operand has type "type", the result has type "pointer to type". + if (op->getType()->isObjCObjectType()) + return S.Context.getObjCObjectPointerType(op->getType()); + return S.Context.getPointerType(op->getType()); +} + +/// CheckIndirectionOperand - Type check unary indirection (prefix '*'). +static QualType CheckIndirectionOperand(Sema &S, Expr *Op, ExprValueKind &VK, + SourceLocation OpLoc) { + if (Op->isTypeDependent()) + return S.Context.DependentTy; + + ExprResult ConvResult = S.UsualUnaryConversions(Op); + if (ConvResult.isInvalid()) + return QualType(); + Op = ConvResult.take(); + QualType OpTy = Op->getType(); + QualType Result; + + if (isa(Op)) { + QualType OpOrigType = Op->IgnoreParenCasts()->getType(); + S.CheckCompatibleReinterpretCast(OpOrigType, OpTy, /*IsDereference*/true, + Op->getSourceRange()); + } + + // Note that per both C89 and C99, indirection is always legal, even if OpTy + // is an incomplete type or void. It would be possible to warn about + // dereferencing a void pointer, but it's completely well-defined, and such a + // warning is unlikely to catch any mistakes. + if (const PointerType *PT = OpTy->getAs()) + Result = PT->getPointeeType(); + else if (const ObjCObjectPointerType *OPT = + OpTy->getAs()) + Result = OPT->getPointeeType(); + else { + ExprResult PR = S.CheckPlaceholderExpr(Op); + if (PR.isInvalid()) return QualType(); + if (PR.take() != Op) + return CheckIndirectionOperand(S, PR.take(), VK, OpLoc); + } + + if (Result.isNull()) { + S.Diag(OpLoc, diag::err_typecheck_indirection_requires_pointer) + << OpTy << Op->getSourceRange(); + return QualType(); + } + + // Dereferences are usually l-values... + VK = VK_LValue; + + // ...except that certain expressions are never l-values in C. + if (!S.getLangOpts().CPlusPlus && Result.isCForbiddenLValueType()) + VK = VK_RValue; + + return Result; +} + +static inline BinaryOperatorKind ConvertTokenKindToBinaryOpcode( + tok::TokenKind Kind) { + BinaryOperatorKind Opc; + switch (Kind) { + default: llvm_unreachable("Unknown binop!"); + 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 UnaryOperatorKind ConvertTokenKindToUnaryOpcode( + tok::TokenKind Kind) { + UnaryOperatorKind Opc; + switch (Kind) { + default: llvm_unreachable("Unknown unary op!"); + 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; +} + +/// DiagnoseSelfAssignment - Emits a warning if a value is assigned to itself. +/// This warning is only emitted for builtin assignment operations. It is also +/// suppressed in the event of macro expansions. +static void DiagnoseSelfAssignment(Sema &S, Expr *LHSExpr, Expr *RHSExpr, + SourceLocation OpLoc) { + if (!S.ActiveTemplateInstantiations.empty()) + return; + if (OpLoc.isInvalid() || OpLoc.isMacroID()) + return; + LHSExpr = LHSExpr->IgnoreParenImpCasts(); + RHSExpr = RHSExpr->IgnoreParenImpCasts(); + const DeclRefExpr *LHSDeclRef = dyn_cast(LHSExpr); + const DeclRefExpr *RHSDeclRef = dyn_cast(RHSExpr); + if (!LHSDeclRef || !RHSDeclRef || + LHSDeclRef->getLocation().isMacroID() || + RHSDeclRef->getLocation().isMacroID()) + return; + const ValueDecl *LHSDecl = + cast(LHSDeclRef->getDecl()->getCanonicalDecl()); + const ValueDecl *RHSDecl = + cast(RHSDeclRef->getDecl()->getCanonicalDecl()); + if (LHSDecl != RHSDecl) + return; + if (LHSDecl->getType().isVolatileQualified()) + return; + if (const ReferenceType *RefTy = LHSDecl->getType()->getAs()) + if (RefTy->getPointeeType().isVolatileQualified()) + return; + + S.Diag(OpLoc, diag::warn_self_assignment) + << LHSDeclRef->getType() + << LHSExpr->getSourceRange() << RHSExpr->getSourceRange(); +} + +/// 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. +ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, + BinaryOperatorKind Opc, + Expr *LHSExpr, Expr *RHSExpr) { + if (getLangOpts().CPlusPlus0x && isa(RHSExpr)) { + // The syntax only allows initializer lists on the RHS of assignment, + // so we don't need to worry about accepting invalid code for + // non-assignment operators. + // C++11 5.17p9: + // The meaning of x = {v} [...] is that of x = T(v) [...]. The meaning + // of x = {} is x = T(). + InitializationKind Kind = + InitializationKind::CreateDirectList(RHSExpr->getLocStart()); + InitializedEntity Entity = + InitializedEntity::InitializeTemporary(LHSExpr->getType()); + InitializationSequence InitSeq(*this, Entity, Kind, &RHSExpr, 1); + ExprResult Init = InitSeq.Perform(*this, Entity, Kind, + MultiExprArg(&RHSExpr, 1)); + if (Init.isInvalid()) + return Init; + RHSExpr = Init.take(); + } + + ExprResult LHS = Owned(LHSExpr), RHS = Owned(RHSExpr); + QualType ResultTy; // Result type of the binary operator. + // 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 + ExprValueKind VK = VK_RValue; + ExprObjectKind OK = OK_Ordinary; + + switch (Opc) { + case BO_Assign: + ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, QualType()); + if (getLangOpts().CPlusPlus && + LHS.get()->getObjectKind() != OK_ObjCProperty) { + VK = LHS.get()->getValueKind(); + OK = LHS.get()->getObjectKind(); + } + if (!ResultTy.isNull()) + DiagnoseSelfAssignment(*this, LHS.get(), RHS.get(), OpLoc); + break; + case BO_PtrMemD: + case BO_PtrMemI: + ResultTy = CheckPointerToMemberOperands(LHS, RHS, VK, OpLoc, + Opc == BO_PtrMemI); + break; + case BO_Mul: + case BO_Div: + ResultTy = CheckMultiplyDivideOperands(LHS, RHS, OpLoc, false, + Opc == BO_Div); + break; + case BO_Rem: + ResultTy = CheckRemainderOperands(LHS, RHS, OpLoc); + break; + case BO_Add: + ResultTy = CheckAdditionOperands(LHS, RHS, OpLoc, Opc); + break; + case BO_Sub: + ResultTy = CheckSubtractionOperands(LHS, RHS, OpLoc); + break; + case BO_Shl: + case BO_Shr: + ResultTy = CheckShiftOperands(LHS, RHS, OpLoc, Opc); + break; + case BO_LE: + case BO_LT: + case BO_GE: + case BO_GT: + ResultTy = CheckCompareOperands(LHS, RHS, OpLoc, Opc, true); + break; + case BO_EQ: + case BO_NE: + ResultTy = CheckCompareOperands(LHS, RHS, OpLoc, Opc, false); + break; + case BO_And: + case BO_Xor: + case BO_Or: + ResultTy = CheckBitwiseOperands(LHS, RHS, OpLoc); + break; + case BO_LAnd: + case BO_LOr: + ResultTy = CheckLogicalOperands(LHS, RHS, OpLoc, Opc); + break; + case BO_MulAssign: + case BO_DivAssign: + CompResultTy = CheckMultiplyDivideOperands(LHS, RHS, OpLoc, true, + Opc == BO_DivAssign); + CompLHSTy = CompResultTy; + if (!CompResultTy.isNull() && !LHS.isInvalid() && !RHS.isInvalid()) + ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, CompResultTy); + break; + case BO_RemAssign: + CompResultTy = CheckRemainderOperands(LHS, RHS, OpLoc, true); + CompLHSTy = CompResultTy; + if (!CompResultTy.isNull() && !LHS.isInvalid() && !RHS.isInvalid()) + ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, CompResultTy); + break; + case BO_AddAssign: + CompResultTy = CheckAdditionOperands(LHS, RHS, OpLoc, Opc, &CompLHSTy); + if (!CompResultTy.isNull() && !LHS.isInvalid() && !RHS.isInvalid()) + ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, CompResultTy); + break; + case BO_SubAssign: + CompResultTy = CheckSubtractionOperands(LHS, RHS, OpLoc, &CompLHSTy); + if (!CompResultTy.isNull() && !LHS.isInvalid() && !RHS.isInvalid()) + ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, CompResultTy); + break; + case BO_ShlAssign: + case BO_ShrAssign: + CompResultTy = CheckShiftOperands(LHS, RHS, OpLoc, Opc, true); + CompLHSTy = CompResultTy; + if (!CompResultTy.isNull() && !LHS.isInvalid() && !RHS.isInvalid()) + ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, CompResultTy); + break; + case BO_AndAssign: + case BO_XorAssign: + case BO_OrAssign: + CompResultTy = CheckBitwiseOperands(LHS, RHS, OpLoc, true); + CompLHSTy = CompResultTy; + if (!CompResultTy.isNull() && !LHS.isInvalid() && !RHS.isInvalid()) + ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, CompResultTy); + break; + case BO_Comma: + ResultTy = CheckCommaOperands(*this, LHS, RHS, OpLoc); + if (getLangOpts().CPlusPlus && !RHS.isInvalid()) { + VK = RHS.get()->getValueKind(); + OK = RHS.get()->getObjectKind(); + } + break; + } + if (ResultTy.isNull() || LHS.isInvalid() || RHS.isInvalid()) + return ExprError(); + + // Check for array bounds violations for both sides of the BinaryOperator + CheckArrayAccess(LHS.get()); + CheckArrayAccess(RHS.get()); + + if (CompResultTy.isNull()) + return Owned(new (Context) BinaryOperator(LHS.take(), RHS.take(), Opc, + ResultTy, VK, OK, OpLoc)); + if (getLangOpts().CPlusPlus && LHS.get()->getObjectKind() != + OK_ObjCProperty) { + VK = VK_LValue; + OK = LHS.get()->getObjectKind(); + } + return Owned(new (Context) CompoundAssignOperator(LHS.take(), RHS.take(), Opc, + ResultTy, VK, OK, CompLHSTy, + CompResultTy, OpLoc)); +} + +/// DiagnoseBitwisePrecedence - Emit a warning when bitwise and comparison +/// 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, BinaryOperatorKind Opc, + SourceLocation OpLoc, Expr *LHSExpr, + Expr *RHSExpr) { + typedef BinaryOperator BinOp; + BinOp::Opcode LHSopc = static_cast(-1), + RHSopc = static_cast(-1); + if (BinOp *BO = dyn_cast(LHSExpr)) + LHSopc = BO->getOpcode(); + if (BinOp *BO = dyn_cast(RHSExpr)) + RHSopc = BO->getOpcode(); + + // Subs are not binary operators. + if (LHSopc == -1 && RHSopc == -1) + return; + + // Bitwise operations are sometimes used as eager logical ops. + // Don't diagnose this. + if ((BinOp::isComparisonOp(LHSopc) || BinOp::isBitwiseOp(LHSopc)) && + (BinOp::isComparisonOp(RHSopc) || BinOp::isBitwiseOp(RHSopc))) + return; + + bool isLeftComp = BinOp::isComparisonOp(LHSopc); + bool isRightComp = BinOp::isComparisonOp(RHSopc); + if (!isLeftComp && !isRightComp) return; + + SourceRange DiagRange = isLeftComp ? SourceRange(LHSExpr->getLocStart(), + OpLoc) + : SourceRange(OpLoc, RHSExpr->getLocEnd()); + std::string OpStr = isLeftComp ? BinOp::getOpcodeStr(LHSopc) + : BinOp::getOpcodeStr(RHSopc); + SourceRange ParensRange = isLeftComp ? + SourceRange(cast(LHSExpr)->getRHS()->getLocStart(), + RHSExpr->getLocEnd()) + : SourceRange(LHSExpr->getLocStart(), + cast(RHSExpr)->getLHS()->getLocStart()); + + Self.Diag(OpLoc, diag::warn_precedence_bitwise_rel) + << DiagRange << BinOp::getOpcodeStr(Opc) << OpStr; + SuggestParentheses(Self, OpLoc, + Self.PDiag(diag::note_precedence_bitwise_silence) << OpStr, + RHSExpr->getSourceRange()); + SuggestParentheses(Self, OpLoc, + Self.PDiag(diag::note_precedence_bitwise_first) << BinOp::getOpcodeStr(Opc), + ParensRange); +} + +/// \brief It accepts a '&' expr that is inside a '|' one. +/// Emit a diagnostic together with a fixit hint that wraps the '&' expression +/// in parentheses. +static void +EmitDiagnosticForBitwiseAndInBitwiseOr(Sema &Self, SourceLocation OpLoc, + BinaryOperator *Bop) { + assert(Bop->getOpcode() == BO_And); + Self.Diag(Bop->getOperatorLoc(), diag::warn_bitwise_and_in_bitwise_or) + << Bop->getSourceRange() << OpLoc; + SuggestParentheses(Self, Bop->getOperatorLoc(), + Self.PDiag(diag::note_bitwise_and_in_bitwise_or_silence), + Bop->getSourceRange()); +} + +/// \brief It accepts a '&&' expr that is inside a '||' one. +/// Emit a diagnostic together with a fixit hint that wraps the '&&' expression +/// in parentheses. +static void +EmitDiagnosticForLogicalAndInLogicalOr(Sema &Self, SourceLocation OpLoc, + BinaryOperator *Bop) { + assert(Bop->getOpcode() == BO_LAnd); + Self.Diag(Bop->getOperatorLoc(), diag::warn_logical_and_in_logical_or) + << Bop->getSourceRange() << OpLoc; + SuggestParentheses(Self, Bop->getOperatorLoc(), + Self.PDiag(diag::note_logical_and_in_logical_or_silence), + Bop->getSourceRange()); +} + +/// \brief Returns true if the given expression can be evaluated as a constant +/// 'true'. +static bool EvaluatesAsTrue(Sema &S, Expr *E) { + bool Res; + return E->EvaluateAsBooleanCondition(Res, S.getASTContext()) && Res; +} + +/// \brief Returns true if the given expression can be evaluated as a constant +/// 'false'. +static bool EvaluatesAsFalse(Sema &S, Expr *E) { + bool Res; + return E->EvaluateAsBooleanCondition(Res, S.getASTContext()) && !Res; +} + +/// \brief Look for '&&' in the left hand of a '||' expr. +static void DiagnoseLogicalAndInLogicalOrLHS(Sema &S, SourceLocation OpLoc, + Expr *LHSExpr, Expr *RHSExpr) { + if (BinaryOperator *Bop = dyn_cast(LHSExpr)) { + if (Bop->getOpcode() == BO_LAnd) { + // If it's "a && b || 0" don't warn since the precedence doesn't matter. + if (EvaluatesAsFalse(S, RHSExpr)) + return; + // If it's "1 && a || b" don't warn since the precedence doesn't matter. + if (!EvaluatesAsTrue(S, Bop->getLHS())) + return EmitDiagnosticForLogicalAndInLogicalOr(S, OpLoc, Bop); + } else if (Bop->getOpcode() == BO_LOr) { + if (BinaryOperator *RBop = dyn_cast(Bop->getRHS())) { + // If it's "a || b && 1 || c" we didn't warn earlier for + // "a || b && 1", but warn now. + if (RBop->getOpcode() == BO_LAnd && EvaluatesAsTrue(S, RBop->getRHS())) + return EmitDiagnosticForLogicalAndInLogicalOr(S, OpLoc, RBop); + } + } + } +} + +/// \brief Look for '&&' in the right hand of a '||' expr. +static void DiagnoseLogicalAndInLogicalOrRHS(Sema &S, SourceLocation OpLoc, + Expr *LHSExpr, Expr *RHSExpr) { + if (BinaryOperator *Bop = dyn_cast(RHSExpr)) { + if (Bop->getOpcode() == BO_LAnd) { + // If it's "0 || a && b" don't warn since the precedence doesn't matter. + if (EvaluatesAsFalse(S, LHSExpr)) + return; + // If it's "a || b && 1" don't warn since the precedence doesn't matter. + if (!EvaluatesAsTrue(S, Bop->getRHS())) + return EmitDiagnosticForLogicalAndInLogicalOr(S, OpLoc, Bop); + } + } +} + +/// \brief Look for '&' in the left or right hand of a '|' expr. +static void DiagnoseBitwiseAndInBitwiseOr(Sema &S, SourceLocation OpLoc, + Expr *OrArg) { + if (BinaryOperator *Bop = dyn_cast(OrArg)) { + if (Bop->getOpcode() == BO_And) + return EmitDiagnosticForBitwiseAndInBitwiseOr(S, OpLoc, Bop); + } +} + +/// DiagnoseBinOpPrecedence - Emit warnings for expressions with tricky +/// precedence. +static void DiagnoseBinOpPrecedence(Sema &Self, BinaryOperatorKind Opc, + SourceLocation OpLoc, Expr *LHSExpr, + Expr *RHSExpr){ + // Diagnose "arg1 'bitwise' arg2 'eq' arg3". + if (BinaryOperator::isBitwiseOp(Opc)) + DiagnoseBitwisePrecedence(Self, Opc, OpLoc, LHSExpr, RHSExpr); + + // Diagnose "arg1 & arg2 | arg3" + if (Opc == BO_Or && !OpLoc.isMacroID()/* Don't warn in macros. */) { + DiagnoseBitwiseAndInBitwiseOr(Self, OpLoc, LHSExpr); + DiagnoseBitwiseAndInBitwiseOr(Self, OpLoc, RHSExpr); + } + + // Warn about arg1 || arg2 && arg3, as GCC 4.3+ does. + // We don't warn for 'assert(a || b && "bad")' since this is safe. + if (Opc == BO_LOr && !OpLoc.isMacroID()/* Don't warn in macros. */) { + DiagnoseLogicalAndInLogicalOrLHS(Self, OpLoc, LHSExpr, RHSExpr); + DiagnoseLogicalAndInLogicalOrRHS(Self, OpLoc, LHSExpr, RHSExpr); + } +} + +// Binary Operators. 'Tok' is the token for the operator. +ExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc, + tok::TokenKind Kind, + Expr *LHSExpr, Expr *RHSExpr) { + BinaryOperatorKind Opc = ConvertTokenKindToBinaryOpcode(Kind); + assert((LHSExpr != 0) && "ActOnBinOp(): missing left expression"); + assert((RHSExpr != 0) && "ActOnBinOp(): missing right expression"); + + // Emit warnings for tricky precedence issues, e.g. "bitfield & 0x4 == 0" + DiagnoseBinOpPrecedence(*this, Opc, TokLoc, LHSExpr, RHSExpr); + + return BuildBinOp(S, TokLoc, Opc, LHSExpr, RHSExpr); +} + +/// Build an overloaded binary operator expression in the given scope. +static ExprResult BuildOverloadedBinOp(Sema &S, Scope *Sc, SourceLocation OpLoc, + BinaryOperatorKind Opc, + Expr *LHS, Expr *RHS) { + // 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 + // the arguments. + UnresolvedSet<16> Functions; + OverloadedOperatorKind OverOp + = BinaryOperator::getOverloadedOperator(Opc); + if (Sc && OverOp != OO_None) + S.LookupOverloadedOperatorName(OverOp, Sc, LHS->getType(), + RHS->getType(), Functions); + + // Build the (potentially-overloaded, potentially-dependent) + // binary operation. + return S.CreateOverloadedBinOp(OpLoc, Opc, Functions, LHS, RHS); +} + +ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc, + BinaryOperatorKind Opc, + Expr *LHSExpr, Expr *RHSExpr) { + // We want to end up calling one of checkPseudoObjectAssignment + // (if the LHS is a pseudo-object), BuildOverloadedBinOp (if + // both expressions are overloadable or either is type-dependent), + // or CreateBuiltinBinOp (in any other case). We also want to get + // any placeholder types out of the way. + + // Handle pseudo-objects in the LHS. + if (const BuiltinType *pty = LHSExpr->getType()->getAsPlaceholderType()) { + // Assignments with a pseudo-object l-value need special analysis. + if (pty->getKind() == BuiltinType::PseudoObject && + BinaryOperator::isAssignmentOp(Opc)) + return checkPseudoObjectAssignment(S, OpLoc, Opc, LHSExpr, RHSExpr); + + // Don't resolve overloads if the other type is overloadable. + if (pty->getKind() == BuiltinType::Overload) { + // We can't actually test that if we still have a placeholder, + // though. Fortunately, none of the exceptions we see in that + // code below are valid when the LHS is an overload set. Note + // that an overload set can be dependently-typed, but it never + // instantiates to having an overloadable type. + ExprResult resolvedRHS = CheckPlaceholderExpr(RHSExpr); + if (resolvedRHS.isInvalid()) return ExprError(); + RHSExpr = resolvedRHS.take(); + + if (RHSExpr->isTypeDependent() || + RHSExpr->getType()->isOverloadableType()) + return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr); + } + + ExprResult LHS = CheckPlaceholderExpr(LHSExpr); + if (LHS.isInvalid()) return ExprError(); + LHSExpr = LHS.take(); + } + + // Handle pseudo-objects in the RHS. + if (const BuiltinType *pty = RHSExpr->getType()->getAsPlaceholderType()) { + // An overload in the RHS can potentially be resolved by the type + // being assigned to. + if (Opc == BO_Assign && pty->getKind() == BuiltinType::Overload) { + if (LHSExpr->isTypeDependent() || RHSExpr->isTypeDependent()) + return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr); + + if (LHSExpr->getType()->isOverloadableType()) + return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr); + + return CreateBuiltinBinOp(OpLoc, Opc, LHSExpr, RHSExpr); + } + + // Don't resolve overloads if the other type is overloadable. + if (pty->getKind() == BuiltinType::Overload && + LHSExpr->getType()->isOverloadableType()) + return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr); + + ExprResult resolvedRHS = CheckPlaceholderExpr(RHSExpr); + if (!resolvedRHS.isUsable()) return ExprError(); + RHSExpr = resolvedRHS.take(); + } + + if (getLangOpts().CPlusPlus) { + // If either expression is type-dependent, always build an + // overloaded op. + if (LHSExpr->isTypeDependent() || RHSExpr->isTypeDependent()) + return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr); + + // Otherwise, build an overloaded op if either expression has an + // overloadable type. + if (LHSExpr->getType()->isOverloadableType() || + RHSExpr->getType()->isOverloadableType()) + return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr); + } + + // Build a built-in binary operation. + return CreateBuiltinBinOp(OpLoc, Opc, LHSExpr, RHSExpr); +} + +ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, + UnaryOperatorKind Opc, + Expr *InputExpr) { + ExprResult Input = Owned(InputExpr); + ExprValueKind VK = VK_RValue; + ExprObjectKind OK = OK_Ordinary; + QualType resultType; + switch (Opc) { + case UO_PreInc: + case UO_PreDec: + case UO_PostInc: + case UO_PostDec: + resultType = CheckIncrementDecrementOperand(*this, Input.get(), VK, OpLoc, + Opc == UO_PreInc || + Opc == UO_PostInc, + Opc == UO_PreInc || + Opc == UO_PreDec); + break; + case UO_AddrOf: + resultType = CheckAddressOfOperand(*this, Input, OpLoc); + break; + case UO_Deref: { + Input = DefaultFunctionArrayLvalueConversion(Input.take()); + resultType = CheckIndirectionOperand(*this, Input.get(), VK, OpLoc); + break; + } + case UO_Plus: + case UO_Minus: + Input = UsualUnaryConversions(Input.take()); + if (Input.isInvalid()) return ExprError(); + resultType = Input.get()->getType(); + if (resultType->isDependentType()) + break; + if (resultType->isArithmeticType() || // C99 6.5.3.3p1 + resultType->isVectorType()) + break; + else if (getLangOpts().CPlusPlus && // C++ [expr.unary.op]p6-7 + resultType->isEnumeralType()) + break; + else if (getLangOpts().CPlusPlus && // C++ [expr.unary.op]p6 + Opc == UO_Plus && + resultType->isPointerType()) + break; + + return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) + << resultType << Input.get()->getSourceRange()); + + case UO_Not: // bitwise complement + Input = UsualUnaryConversions(Input.take()); + if (Input.isInvalid()) return ExprError(); + resultType = Input.get()->getType(); + if (resultType->isDependentType()) + break; + // C99 6.5.3.3p1. We allow complex int and float as a GCC extension. + if (resultType->isComplexType() || resultType->isComplexIntegerType()) + // C99 does not support '~' for complex conjugation. + Diag(OpLoc, diag::ext_integer_complement_complex) + << resultType << Input.get()->getSourceRange(); + else if (resultType->hasIntegerRepresentation()) + break; + else { + return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) + << resultType << Input.get()->getSourceRange()); + } + break; + + case UO_LNot: // logical negation + // Unlike +/-/~, integer promotions aren't done here (C99 6.5.3.3p5). + Input = DefaultFunctionArrayLvalueConversion(Input.take()); + if (Input.isInvalid()) return ExprError(); + resultType = Input.get()->getType(); + + // Though we still have to promote half FP to float... + if (resultType->isHalfType()) { + Input = ImpCastExprToType(Input.take(), Context.FloatTy, CK_FloatingCast).take(); + resultType = Context.FloatTy; + } + + if (resultType->isDependentType()) + break; + if (resultType->isScalarType()) { + // C99 6.5.3.3p1: ok, fallthrough; + if (Context.getLangOpts().CPlusPlus) { + // C++03 [expr.unary.op]p8, C++0x [expr.unary.op]p9: + // operand contextually converted to bool. + Input = ImpCastExprToType(Input.take(), Context.BoolTy, + ScalarTypeToBooleanCastKind(resultType)); + } + } else if (resultType->isExtVectorType()) { + // Vector logical not returns the signed variant of the operand type. + resultType = GetSignedVectorType(resultType); + break; + } else { + return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) + << resultType << Input.get()->getSourceRange()); + } + + // LNot always has type int. C99 6.5.3.3p5. + // In C++, it's bool. C++ 5.3.1p8 + resultType = Context.getLogicalOperationType(); + break; + case UO_Real: + case UO_Imag: + resultType = CheckRealImagOperand(*this, Input, OpLoc, Opc == UO_Real); + // _Real maps ordinary l-values into ordinary l-values. _Imag maps ordinary + // complex l-values to ordinary l-values and all other values to r-values. + if (Input.isInvalid()) return ExprError(); + if (Opc == UO_Real || Input.get()->getType()->isAnyComplexType()) { + if (Input.get()->getValueKind() != VK_RValue && + Input.get()->getObjectKind() == OK_Ordinary) + VK = Input.get()->getValueKind(); + } else if (!getLangOpts().CPlusPlus) { + // In C, a volatile scalar is read by __imag. In C++, it is not. + Input = DefaultLvalueConversion(Input.take()); + } + break; + case UO_Extension: + resultType = Input.get()->getType(); + VK = Input.get()->getValueKind(); + OK = Input.get()->getObjectKind(); + break; + } + if (resultType.isNull() || Input.isInvalid()) + return ExprError(); + + // Check for array bounds violations in the operand of the UnaryOperator, + // except for the '*' and '&' operators that have to be handled specially + // by CheckArrayAccess (as there are special cases like &array[arraysize] + // that are explicitly defined as valid by the standard). + if (Opc != UO_AddrOf && Opc != UO_Deref) + CheckArrayAccess(Input.get()); + + return Owned(new (Context) UnaryOperator(Input.take(), Opc, resultType, + VK, OK, OpLoc)); +} + +/// \brief Determine whether the given expression is a qualified member +/// access expression, of a form that could be turned into a pointer to member +/// with the address-of operator. +static bool isQualifiedMemberAccess(Expr *E) { + if (DeclRefExpr *DRE = dyn_cast(E)) { + if (!DRE->getQualifier()) + return false; + + ValueDecl *VD = DRE->getDecl(); + if (!VD->isCXXClassMember()) + return false; + + if (isa(VD) || isa(VD)) + return true; + if (CXXMethodDecl *Method = dyn_cast(VD)) + return Method->isInstance(); + + return false; + } + + if (UnresolvedLookupExpr *ULE = dyn_cast(E)) { + if (!ULE->getQualifier()) + return false; + + for (UnresolvedLookupExpr::decls_iterator D = ULE->decls_begin(), + DEnd = ULE->decls_end(); + D != DEnd; ++D) { + if (CXXMethodDecl *Method = dyn_cast(*D)) { + if (Method->isInstance()) + return true; + } else { + // Overload set does not contain methods. + break; + } + } + + return false; + } + + return false; +} + +ExprResult Sema::BuildUnaryOp(Scope *S, SourceLocation OpLoc, + UnaryOperatorKind Opc, Expr *Input) { + // First things first: handle placeholders so that the + // overloaded-operator check considers the right type. + if (const BuiltinType *pty = Input->getType()->getAsPlaceholderType()) { + // Increment and decrement of pseudo-object references. + if (pty->getKind() == BuiltinType::PseudoObject && + UnaryOperator::isIncrementDecrementOp(Opc)) + return checkPseudoObjectIncDec(S, OpLoc, Opc, Input); + + // extension is always a builtin operator. + if (Opc == UO_Extension) + return CreateBuiltinUnaryOp(OpLoc, Opc, Input); + + // & gets special logic for several kinds of placeholder. + // The builtin code knows what to do. + if (Opc == UO_AddrOf && + (pty->getKind() == BuiltinType::Overload || + pty->getKind() == BuiltinType::UnknownAny || + pty->getKind() == BuiltinType::BoundMember)) + return CreateBuiltinUnaryOp(OpLoc, Opc, Input); + + // Anything else needs to be handled now. + ExprResult Result = CheckPlaceholderExpr(Input); + if (Result.isInvalid()) return ExprError(); + Input = Result.take(); + } + + if (getLangOpts().CPlusPlus && Input->getType()->isOverloadableType() && + UnaryOperator::getOverloadedOperator(Opc) != OO_None && + !(Opc == UO_AddrOf && isQualifiedMemberAccess(Input))) { + // 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 + // the arguments. + UnresolvedSet<16> Functions; + OverloadedOperatorKind OverOp = UnaryOperator::getOverloadedOperator(Opc); + if (S && OverOp != OO_None) + LookupOverloadedOperatorName(OverOp, S, Input->getType(), QualType(), + Functions); + + return CreateOverloadedUnaryOp(OpLoc, Opc, Functions, Input); + } + + return CreateBuiltinUnaryOp(OpLoc, Opc, Input); +} + +// Unary Operators. 'Tok' is the token for the operator. +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". +ExprResult Sema::ActOnAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc, + LabelDecl *TheDecl) { + TheDecl->setUsed(); + // Create the AST node. The address of a label always has type 'void*'. + return Owned(new (Context) AddrLabelExpr(OpLoc, LabLoc, TheDecl, + Context.getPointerType(Context.VoidTy))); +} + +/// Given the last statement in a statement-expression, check whether +/// the result is a producing expression (like a call to an +/// ns_returns_retained function) and, if so, rebuild it to hoist the +/// release out of the full-expression. Otherwise, return null. +/// Cannot fail. +static Expr *maybeRebuildARCConsumingStmt(Stmt *Statement) { + // Should always be wrapped with one of these. + ExprWithCleanups *cleanups = dyn_cast(Statement); + if (!cleanups) return 0; + + ImplicitCastExpr *cast = dyn_cast(cleanups->getSubExpr()); + if (!cast || cast->getCastKind() != CK_ARCConsumeObject) + return 0; + + // Splice out the cast. This shouldn't modify any interesting + // features of the statement. + Expr *producer = cast->getSubExpr(); + assert(producer->getType() == cast->getType()); + assert(producer->getValueKind() == cast->getValueKind()); + cleanups->setSubExpr(producer); + return cleanups; +} + +void Sema::ActOnStartStmtExpr() { + PushExpressionEvaluationContext(ExprEvalContexts.back().Context); +} + +void Sema::ActOnStmtExprError() { + // Note that function is also called by TreeTransform when leaving a + // StmtExpr scope without rebuilding anything. + + DiscardCleanupsInEvaluationContext(); + PopExpressionEvaluationContext(); +} + +ExprResult +Sema::ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt, + SourceLocation RPLoc) { // "({..})" + assert(SubStmt && isa(SubStmt) && "Invalid action invocation!"); + CompoundStmt *Compound = cast(SubStmt); + + if (hasAnyUnrecoverableErrorsInThisFunction()) + DiscardCleanupsInEvaluationContext(); + assert(!ExprNeedsCleanups && "cleanups within StmtExpr not correctly bound!"); + PopExpressionEvaluationContext(); + + bool isFileScope + = (getCurFunctionOrMethodDecl() == 0) && (getCurBlock() == 0); + if (isFileScope) + return ExprError(Diag(LPLoc, diag::err_stmtexpr_file_scope)); + + // FIXME: there are a variety of strange constraints to enforce here, for + // example, it is not possible to goto into a stmt expression apparently. + // More semantic analysis is needed. + + // If there are sub stmts in the compound stmt, take the type of the last one + // as the type of the stmtexpr. + QualType Ty = Context.VoidTy; + bool StmtExprMayBindToTemp = false; + if (!Compound->body_empty()) { + Stmt *LastStmt = Compound->body_back(); + LabelStmt *LastLabelStmt = 0; + // If LastStmt is a label, skip down through into the body. + while (LabelStmt *Label = dyn_cast(LastStmt)) { + LastLabelStmt = Label; + LastStmt = Label->getSubStmt(); + } + + if (Expr *LastE = dyn_cast(LastStmt)) { + // Do function/array conversion on the last expression, but not + // lvalue-to-rvalue. However, initialize an unqualified type. + ExprResult LastExpr = DefaultFunctionArrayConversion(LastE); + if (LastExpr.isInvalid()) + return ExprError(); + Ty = LastExpr.get()->getType().getUnqualifiedType(); + + if (!Ty->isDependentType() && !LastExpr.get()->isTypeDependent()) { + // In ARC, if the final expression ends in a consume, splice + // the consume out and bind it later. In the alternate case + // (when dealing with a retainable type), the result + // initialization will create a produce. In both cases the + // result will be +1, and we'll need to balance that out with + // a bind. + if (Expr *rebuiltLastStmt + = maybeRebuildARCConsumingStmt(LastExpr.get())) { + LastExpr = rebuiltLastStmt; + } else { + LastExpr = PerformCopyInitialization( + InitializedEntity::InitializeResult(LPLoc, + Ty, + false), + SourceLocation(), + LastExpr); + } + + if (LastExpr.isInvalid()) + return ExprError(); + if (LastExpr.get() != 0) { + if (!LastLabelStmt) + Compound->setLastStmt(LastExpr.take()); + else + LastLabelStmt->setSubStmt(LastExpr.take()); + StmtExprMayBindToTemp = true; + } + } + } + } + + // FIXME: Check that expression type is complete/non-abstract; statement + // expressions are not lvalues. + Expr *ResStmtExpr = new (Context) StmtExpr(Compound, Ty, LPLoc, RPLoc); + if (StmtExprMayBindToTemp) + return MaybeBindToTemporary(ResStmtExpr); + return Owned(ResStmtExpr); +} + +ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc, + TypeSourceInfo *TInfo, + OffsetOfComponent *CompPtr, + unsigned NumComponents, + SourceLocation RParenLoc) { + QualType ArgTy = TInfo->getType(); + bool Dependent = ArgTy->isDependentType(); + SourceRange TypeRange = TInfo->getTypeLoc().getLocalSourceRange(); + + // 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(BuiltinLoc, diag::err_offsetof_record_type) + << ArgTy << TypeRange); + + // Type must be complete per C99 7.17p3 because a declaring a variable + // with an incomplete type would be ill-formed. + if (!Dependent + && RequireCompleteType(BuiltinLoc, ArgTy, + PDiag(diag::err_offsetof_incomplete_type) + << TypeRange)) + return ExprError(); + + // 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); + + bool DidWarnAboutNonPOD = false; + QualType CurrentType = ArgTy; + typedef OffsetOfExpr::OffsetOfNode OffsetOfNode; + SmallVector Comps; + SmallVector Exprs; + 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? + if (!CurrentType->isDependentType()) { + const ArrayType *AT = Context.getAsArrayType(CurrentType); + if(!AT) + return ExprError(Diag(OC.LocEnd, diag::err_offsetof_array_type) + << CurrentType); + CurrentType = AT->getElementType(); + } else + CurrentType = Context.DependentTy; + + ExprResult IdxRval = DefaultLvalueConversion(static_cast(OC.U.E)); + if (IdxRval.isInvalid()) + return ExprError(); + Expr *Idx = IdxRval.take(); + + // The expression must be an integral expression. + // FIXME: An integral constant expression? + if (!Idx->isTypeDependent() && !Idx->isValueDependent() && + !Idx->getType()->isIntegerType()) + return ExprError(Diag(Idx->getLocStart(), + diag::err_typecheck_subscript_not_integer) + << Idx->getSourceRange()); + + // Record this array index. + Comps.push_back(OffsetOfNode(OC.LocStart, Exprs.size(), OC.LocEnd)); + Exprs.push_back(Idx); + continue; + } + + // Offset of a field. + if (CurrentType->isDependentType()) { + // We have the offset of a field, but we can't look into the dependent + // type. Just record the identifier of the field. + Comps.push_back(OffsetOfNode(OC.LocStart, OC.U.IdentInfo, OC.LocEnd)); + CurrentType = Context.DependentTy; + continue; + } + + // We need to have a complete type to look into. + if (RequireCompleteType(OC.LocStart, CurrentType, + diag::err_offsetof_incomplete_type)) + return ExprError(); + + // Look for the designated field. + const RecordType *RC = CurrentType->getAs(); + if (!RC) + return ExprError(Diag(OC.LocEnd, diag::err_offsetof_record_type) + << CurrentType); + RecordDecl *RD = RC->getDecl(); + + // C++ [lib.support.types]p5: + // The macro offsetof accepts a restricted set of type arguments in this + // International Standard. type shall be a POD structure or a POD union + // (clause 9). + if (CXXRecordDecl *CRD = dyn_cast(RD)) { + if (!CRD->isPOD() && !DidWarnAboutNonPOD && + DiagRuntimeBehavior(BuiltinLoc, 0, + PDiag(diag::warn_offsetof_non_pod_type) + << SourceRange(CompPtr[0].LocStart, OC.LocEnd) + << CurrentType)) + DidWarnAboutNonPOD = true; + } + + // Look for the field. + LookupResult R(*this, OC.U.IdentInfo, OC.LocStart, LookupMemberName); + LookupQualifiedName(R, RD); + FieldDecl *MemberDecl = R.getAsSingle(); + IndirectFieldDecl *IndirectMemberDecl = 0; + if (!MemberDecl) { + if ((IndirectMemberDecl = R.getAsSingle())) + MemberDecl = IndirectMemberDecl->getAnonField(); + } + + 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->isBitField()) { + Diag(OC.LocEnd, diag::err_offsetof_bitfield) + << MemberDecl->getDeclName() + << SourceRange(BuiltinLoc, RParenLoc); + Diag(MemberDecl->getLocation(), diag::note_bitfield_decl); + return ExprError(); + } + + RecordDecl *Parent = MemberDecl->getParent(); + if (IndirectMemberDecl) + Parent = cast(IndirectMemberDecl->getDeclContext()); + + // 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(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 (IndirectMemberDecl) { + for (IndirectFieldDecl::chain_iterator FI = + IndirectMemberDecl->chain_begin(), + FEnd = IndirectMemberDecl->chain_end(); FI != FEnd; FI++) { + assert(isa(*FI)); + Comps.push_back(OffsetOfNode(OC.LocStart, + cast(*FI), OC.LocEnd)); + } + } else + Comps.push_back(OffsetOfNode(OC.LocStart, MemberDecl, OC.LocEnd)); + + CurrentType = MemberDecl->getType().getNonReferenceType(); + } + + return Owned(OffsetOfExpr::Create(Context, Context.getSizeType(), BuiltinLoc, + TInfo, Comps.data(), Comps.size(), + Exprs.data(), Exprs.size(), RParenLoc)); +} + +ExprResult Sema::ActOnBuiltinOffsetOf(Scope *S, + SourceLocation BuiltinLoc, + SourceLocation TypeLoc, + ParsedType ParsedArgTy, + OffsetOfComponent *CompPtr, + unsigned NumComponents, + SourceLocation RParenLoc) { + + TypeSourceInfo *ArgTInfo; + QualType ArgTy = GetTypeFromParser(ParsedArgTy, &ArgTInfo); + if (ArgTy.isNull()) + return ExprError(); + + if (!ArgTInfo) + ArgTInfo = Context.getTrivialTypeSourceInfo(ArgTy, TypeLoc); + + return BuildBuiltinOffsetOf(BuiltinLoc, ArgTInfo, CompPtr, NumComponents, + RParenLoc); +} + + +ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc, + Expr *CondExpr, + Expr *LHSExpr, Expr *RHSExpr, + SourceLocation RPLoc) { + assert((CondExpr && LHSExpr && RHSExpr) && "Missing type argument(s)"); + + ExprValueKind VK = VK_RValue; + ExprObjectKind OK = OK_Ordinary; + QualType resType; + bool ValueDependent = false; + if (CondExpr->isTypeDependent() || CondExpr->isValueDependent()) { + resType = Context.DependentTy; + ValueDependent = true; + } else { + // The conditional expression is required to be a constant expression. + llvm::APSInt condEval(32); + ExprResult CondICE = VerifyIntegerConstantExpression(CondExpr, &condEval, + PDiag(diag::err_typecheck_choose_expr_requires_constant), false); + if (CondICE.isInvalid()) + return ExprError(); + CondExpr = CondICE.take(); + + // If the condition is > zero, then the AST type is the same as the LSHExpr. + Expr *ActiveExpr = condEval.getZExtValue() ? LHSExpr : RHSExpr; + + resType = ActiveExpr->getType(); + ValueDependent = ActiveExpr->isValueDependent(); + VK = ActiveExpr->getValueKind(); + OK = ActiveExpr->getObjectKind(); + } + + return Owned(new (Context) ChooseExpr(BuiltinLoc, CondExpr, LHSExpr, RHSExpr, + resType, VK, OK, RPLoc, + resType->isDependentType(), + ValueDependent)); +} + +//===----------------------------------------------------------------------===// +// Clang Extensions. +//===----------------------------------------------------------------------===// + +/// ActOnBlockStart - This callback is invoked when a block literal is started. +void Sema::ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope) { + BlockDecl *Block = BlockDecl::Create(Context, CurContext, CaretLoc); + PushBlockScope(CurScope, Block); + CurContext->addDecl(Block); + if (CurScope) + PushDeclContext(CurScope, Block); + else + CurContext = Block; + + getCurBlock()->HasImplicitReturnType = true; + + // Enter a new evaluation context to insulate the block from any + // cleanups from the enclosing full-expression. + PushExpressionEvaluationContext(PotentiallyEvaluated); +} + +void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) { + assert(ParamInfo.getIdentifier()==0 && "block-id should have no identifier!"); + assert(ParamInfo.getContext() == Declarator::BlockLiteralContext); + BlockScopeInfo *CurBlock = getCurBlock(); + + TypeSourceInfo *Sig = GetTypeForDeclarator(ParamInfo, CurScope); + QualType T = Sig->getType(); + + // GetTypeForDeclarator always produces a function type for a block + // literal signature. Furthermore, it is always a FunctionProtoType + // unless the function was written with a typedef. + assert(T->isFunctionType() && + "GetTypeForDeclarator made a non-function block signature"); + + // Look for an explicit signature in that function type. + FunctionProtoTypeLoc ExplicitSignature; + + TypeLoc tmp = Sig->getTypeLoc().IgnoreParens(); + if (isa(tmp)) { + ExplicitSignature = cast(tmp); + + // Check whether that explicit signature was synthesized by + // GetTypeForDeclarator. If so, don't save that as part of the + // written signature. + if (ExplicitSignature.getLocalRangeBegin() == + ExplicitSignature.getLocalRangeEnd()) { + // This would be much cheaper if we stored TypeLocs instead of + // TypeSourceInfos. + TypeLoc Result = ExplicitSignature.getResultLoc(); + unsigned Size = Result.getFullDataSize(); + Sig = Context.CreateTypeSourceInfo(Result.getType(), Size); + Sig->getTypeLoc().initializeFullCopy(Result, Size); + + ExplicitSignature = FunctionProtoTypeLoc(); + } + } + + CurBlock->TheDecl->setSignatureAsWritten(Sig); + CurBlock->FunctionType = T; + + const FunctionType *Fn = T->getAs(); + QualType RetTy = Fn->getResultType(); + bool isVariadic = + (isa(Fn) && cast(Fn)->isVariadic()); + + CurBlock->TheDecl->setIsVariadic(isVariadic); + + // Don't allow returning a objc interface by value. + if (RetTy->isObjCObjectType()) { + Diag(ParamInfo.getLocStart(), + diag::err_object_cannot_be_passed_returned_by_value) << 0 << RetTy; + return; + } + + // Context.DependentTy is used as a placeholder for a missing block + // return type. TODO: what should we do with declarators like: + // ^ * { ... } + // If the answer is "apply template argument deduction".... + if (RetTy != Context.DependentTy) { + CurBlock->ReturnType = RetTy; + CurBlock->TheDecl->setBlockMissingReturnType(false); + CurBlock->HasImplicitReturnType = false; + } + + // Push block parameters from the declarator if we had them. + SmallVector Params; + if (ExplicitSignature) { + for (unsigned I = 0, E = ExplicitSignature.getNumArgs(); I != E; ++I) { + ParmVarDecl *Param = ExplicitSignature.getArg(I); + if (Param->getIdentifier() == 0 && + !Param->isImplicit() && + !Param->isInvalidDecl() && + !getLangOpts().CPlusPlus) + Diag(Param->getLocation(), diag::err_parameter_name_omitted); + Params.push_back(Param); + } + + // Fake up parameter variables if we have a typedef, like + // ^ fntype { ... } + } else if (const FunctionProtoType *Fn = T->getAs()) { + for (FunctionProtoType::arg_type_iterator + I = Fn->arg_type_begin(), E = Fn->arg_type_end(); I != E; ++I) { + ParmVarDecl *Param = + BuildParmVarDeclForTypedef(CurBlock->TheDecl, + ParamInfo.getLocStart(), + *I); + Params.push_back(Param); + } + } + + // Set the parameters on the block decl. + if (!Params.empty()) { + CurBlock->TheDecl->setParams(Params); + CheckParmsForFunctionDef(CurBlock->TheDecl->param_begin(), + CurBlock->TheDecl->param_end(), + /*CheckParameterNames=*/false); + } + + // Finally we can process decl attributes. + ProcessDeclAttributes(CurScope, CurBlock->TheDecl, ParamInfo); + + // Put the parameter variables in scope. We can bail out immediately + // if we don't have any. + if (Params.empty()) + return; + + for (BlockDecl::param_iterator AI = CurBlock->TheDecl->param_begin(), + E = CurBlock->TheDecl->param_end(); AI != E; ++AI) { + (*AI)->setOwningFunction(CurBlock->TheDecl); + + // If this has an identifier, add it to the scope stack. + if ((*AI)->getIdentifier()) { + CheckShadow(CurBlock->TheScope, *AI); + + PushOnScopeChains(*AI, CurBlock->TheScope); + } + } +} + +/// ActOnBlockError - If there is an error parsing a block, this callback +/// is invoked to pop the information about the block from the action impl. +void Sema::ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope) { + // Leave the expression-evaluation context. + DiscardCleanupsInEvaluationContext(); + PopExpressionEvaluationContext(); + + // Pop off CurBlock, handle nested blocks. + PopDeclContext(); + PopFunctionScopeInfo(); +} + +/// ActOnBlockStmtExpr - This is called when the body of a block statement +/// literal was successfully completed. ^(int x){...} +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); + + // Leave the expression-evaluation context. + if (hasAnyUnrecoverableErrorsInThisFunction()) + DiscardCleanupsInEvaluationContext(); + assert(!ExprNeedsCleanups && "cleanups within block not correctly bound!"); + PopExpressionEvaluationContext(); + + BlockScopeInfo *BSI = cast(FunctionScopes.back()); + + PopDeclContext(); + + QualType RetTy = Context.VoidTy; + if (!BSI->ReturnType.isNull()) + RetTy = BSI->ReturnType; + + bool NoReturn = BSI->TheDecl->getAttr(); + QualType BlockTy; + + // Set the captured variables on the block. + // FIXME: Share capture structure between BlockDecl and CapturingScopeInfo! + SmallVector Captures; + for (unsigned i = 0, e = BSI->Captures.size(); i != e; i++) { + CapturingScopeInfo::Capture &Cap = BSI->Captures[i]; + if (Cap.isThisCapture()) + continue; + BlockDecl::Capture NewCap(Cap.getVariable(), Cap.isBlockCapture(), + Cap.isNested(), Cap.getCopyExpr()); + Captures.push_back(NewCap); + } + BSI->TheDecl->setCaptures(Context, Captures.begin(), Captures.end(), + BSI->CXXThisCaptureIndex != 0); + + // If the user wrote a function type in some form, try to use that. + if (!BSI->FunctionType.isNull()) { + const FunctionType *FTy = BSI->FunctionType->getAs(); + + FunctionType::ExtInfo Ext = FTy->getExtInfo(); + if (NoReturn && !Ext.getNoReturn()) Ext = Ext.withNoReturn(true); + + // Turn protoless block types into nullary block types. + if (isa(FTy)) { + FunctionProtoType::ExtProtoInfo EPI; + EPI.ExtInfo = Ext; + BlockTy = Context.getFunctionType(RetTy, 0, 0, EPI); + + // Otherwise, if we don't need to change anything about the function type, + // preserve its sugar structure. + } else if (FTy->getResultType() == RetTy && + (!NoReturn || FTy->getNoReturnAttr())) { + BlockTy = BSI->FunctionType; + + // Otherwise, make the minimal modifications to the function type. + } else { + const FunctionProtoType *FPT = cast(FTy); + FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); + EPI.TypeQuals = 0; // FIXME: silently? + EPI.ExtInfo = Ext; + BlockTy = Context.getFunctionType(RetTy, + FPT->arg_type_begin(), + FPT->getNumArgs(), + EPI); + } + + // If we don't have a function type, just build one from nothing. + } else { + FunctionProtoType::ExtProtoInfo EPI; + EPI.ExtInfo = FunctionType::ExtInfo().withNoReturn(NoReturn); + BlockTy = Context.getFunctionType(RetTy, 0, 0, EPI); + } + + DiagnoseUnusedParameters(BSI->TheDecl->param_begin(), + BSI->TheDecl->param_end()); + BlockTy = Context.getBlockPointerType(BlockTy); + + // If needed, diagnose invalid gotos and switches in the block. + if (getCurFunction()->NeedsScopeChecking() && + !hasAnyUnrecoverableErrorsInThisFunction()) + DiagnoseInvalidJumps(cast(Body)); + + BSI->TheDecl->setBody(cast(Body)); + + computeNRVO(Body, getCurBlock()); + + BlockExpr *Result = new (Context) BlockExpr(BSI->TheDecl, BlockTy); + const AnalysisBasedWarnings::Policy &WP = AnalysisWarnings.getDefaultPolicy(); + PopFunctionScopeInfo(&WP, Result->getBlockDecl(), Result); + + // If the block isn't obviously global, i.e. it captures anything at + // all, then we need to do a few things in the surrounding context: + if (Result->getBlockDecl()->hasCaptures()) { + // First, this expression has a new cleanup object. + ExprCleanupObjects.push_back(Result->getBlockDecl()); + ExprNeedsCleanups = true; + + // It also gets a branch-protected scope if any of the captured + // variables needs destruction. + for (BlockDecl::capture_const_iterator + ci = Result->getBlockDecl()->capture_begin(), + ce = Result->getBlockDecl()->capture_end(); ci != ce; ++ci) { + const VarDecl *var = ci->getVariable(); + if (var->getType().isDestructedType() != QualType::DK_none) { + getCurFunction()->setHasBranchProtectedScope(); + break; + } + } + } + + return Owned(Result); +} + +ExprResult Sema::ActOnVAArg(SourceLocation BuiltinLoc, + Expr *E, ParsedType Ty, + SourceLocation RPLoc) { + TypeSourceInfo *TInfo; + GetTypeFromParser(Ty, &TInfo); + return BuildVAArgExpr(BuiltinLoc, E, TInfo, RPLoc); +} + +ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc, + Expr *E, TypeSourceInfo *TInfo, + SourceLocation RPLoc) { + Expr *OrigExpr = E; + + // Get the va_list type + QualType VaListType = Context.getBuiltinVaListType(); + if (VaListType->isArrayType()) { + // Deal with implicit array decay; for example, on x86-64, + // va_list is an array, but it's supposed to decay to + // a pointer for va_arg. + VaListType = Context.getArrayDecayedType(VaListType); + // Make sure the input expression also decays appropriately. + ExprResult Result = UsualUnaryConversions(E); + if (Result.isInvalid()) + return ExprError(); + E = Result.take(); + } else { + // Otherwise, the va_list argument must be an l-value because + // it is modified by va_arg. + if (!E->isTypeDependent() && + CheckForModifiableLvalue(E, BuiltinLoc, *this)) + return ExprError(); + } + + if (!E->isTypeDependent() && + !Context.hasSameType(VaListType, E->getType())) { + return ExprError(Diag(E->getLocStart(), + diag::err_first_argument_to_va_arg_not_of_type_va_list) + << OrigExpr->getType() << E->getSourceRange()); + } + + if (!TInfo->getType()->isDependentType()) { + if (RequireCompleteType(TInfo->getTypeLoc().getBeginLoc(), TInfo->getType(), + PDiag(diag::err_second_parameter_to_va_arg_incomplete) + << TInfo->getTypeLoc().getSourceRange())) + return ExprError(); + + if (RequireNonAbstractType(TInfo->getTypeLoc().getBeginLoc(), + TInfo->getType(), + PDiag(diag::err_second_parameter_to_va_arg_abstract) + << TInfo->getTypeLoc().getSourceRange())) + return ExprError(); + + if (!TInfo->getType().isPODType(Context)) { + Diag(TInfo->getTypeLoc().getBeginLoc(), + TInfo->getType()->isObjCLifetimeType() + ? diag::warn_second_parameter_to_va_arg_ownership_qualified + : diag::warn_second_parameter_to_va_arg_not_pod) + << TInfo->getType() + << TInfo->getTypeLoc().getSourceRange(); + } + + // Check for va_arg where arguments of the given type will be promoted + // (i.e. this va_arg is guaranteed to have undefined behavior). + QualType PromoteType; + if (TInfo->getType()->isPromotableIntegerType()) { + PromoteType = Context.getPromotedIntegerType(TInfo->getType()); + if (Context.typesAreCompatible(PromoteType, TInfo->getType())) + PromoteType = QualType(); + } + if (TInfo->getType()->isSpecificBuiltinType(BuiltinType::Float)) + PromoteType = Context.DoubleTy; + if (!PromoteType.isNull()) + Diag(TInfo->getTypeLoc().getBeginLoc(), + diag::warn_second_parameter_to_va_arg_never_compatible) + << TInfo->getType() + << PromoteType + << TInfo->getTypeLoc().getSourceRange(); + } + + QualType T = TInfo->getType().getNonLValueExprType(Context); + return Owned(new (Context) VAArgExpr(BuiltinLoc, E, TInfo, RPLoc, T)); +} + +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; + unsigned pw = Context.getTargetInfo().getPointerWidth(0); + if (pw == Context.getTargetInfo().getIntWidth()) + Ty = Context.IntTy; + else if (pw == Context.getTargetInfo().getLongWidth()) + Ty = Context.LongTy; + else if (pw == Context.getTargetInfo().getLongLongWidth()) + Ty = Context.LongLongTy; + else { + llvm_unreachable("I don't know size of pointer!"); + } + + return Owned(new (Context) GNUNullExpr(Ty, TokenLoc)); +} + +static void MakeObjCStringLiteralFixItHint(Sema& SemaRef, QualType DstType, + Expr *SrcExpr, FixItHint &Hint) { + if (!SemaRef.getLangOpts().ObjC1) + return; + + const ObjCObjectPointerType *PT = DstType->getAs(); + if (!PT) + return; + + // Check if the destination is of type 'id'. + if (!PT->isObjCIdType()) { + // Check if the destination is the 'NSString' interface. + const ObjCInterfaceDecl *ID = PT->getInterfaceDecl(); + if (!ID || !ID->getIdentifier()->isStr("NSString")) + return; + } + + // Ignore any parens, implicit casts (should only be + // array-to-pointer decays), and not-so-opaque values. The last is + // important for making this trigger for property assignments. + SrcExpr = SrcExpr->IgnoreParenImpCasts(); + if (OpaqueValueExpr *OV = dyn_cast(SrcExpr)) + if (OV->getSourceExpr()) + SrcExpr = OV->getSourceExpr()->IgnoreParenImpCasts(); + + StringLiteral *SL = dyn_cast(SrcExpr); + if (!SL || !SL->isAscii()) + return; + + Hint = FixItHint::CreateInsertion(SL->getLocStart(), "@"); +} + +bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, + SourceLocation Loc, + QualType DstType, QualType SrcType, + Expr *SrcExpr, AssignmentAction Action, + bool *Complained) { + if (Complained) + *Complained = false; + + // Decode the result (notice that AST's are still created for extensions). + bool CheckInferredResultType = false; + bool isInvalid = false; + unsigned DiagKind = 0; + FixItHint Hint; + ConversionFixItGenerator ConvHints; + bool MayHaveConvFixit = false; + bool MayHaveFunctionDiff = false; + + switch (ConvTy) { + case Compatible: return false; + case PointerToInt: + DiagKind = diag::ext_typecheck_convert_pointer_int; + ConvHints.tryToFixConversion(SrcExpr, SrcType, DstType, *this); + MayHaveConvFixit = true; + break; + case IntToPointer: + DiagKind = diag::ext_typecheck_convert_int_pointer; + ConvHints.tryToFixConversion(SrcExpr, SrcType, DstType, *this); + MayHaveConvFixit = true; + break; + case IncompatiblePointer: + MakeObjCStringLiteralFixItHint(*this, DstType, SrcExpr, Hint); + DiagKind = diag::ext_typecheck_convert_incompatible_pointer; + CheckInferredResultType = DstType->isObjCObjectPointerType() && + SrcType->isObjCObjectPointerType(); + if (Hint.isNull() && !CheckInferredResultType) { + ConvHints.tryToFixConversion(SrcExpr, SrcType, DstType, *this); + } + MayHaveConvFixit = true; + break; + case IncompatiblePointerSign: + DiagKind = diag::ext_typecheck_convert_incompatible_pointer_sign; + break; + case FunctionVoidPointer: + DiagKind = diag::ext_typecheck_convert_pointer_void_func; + break; + case IncompatiblePointerDiscardsQualifiers: { + // Perform array-to-pointer decay if necessary. + if (SrcType->isArrayType()) SrcType = Context.getArrayDecayedType(SrcType); + + Qualifiers lhq = SrcType->getPointeeType().getQualifiers(); + Qualifiers rhq = DstType->getPointeeType().getQualifiers(); + if (lhq.getAddressSpace() != rhq.getAddressSpace()) { + DiagKind = diag::err_typecheck_incompatible_address_space; + break; + + + } else if (lhq.getObjCLifetime() != rhq.getObjCLifetime()) { + DiagKind = diag::err_typecheck_incompatible_ownership; + break; + } + + llvm_unreachable("unknown error case for discarding qualifiers!"); + // fallthrough + } + case CompatiblePointerDiscardsQualifiers: + // If the qualifiers lost were because we were applying the + // (deprecated) C++ conversion from a string literal to a char* + // (or wchar_t*), then there was no error (C++ 4.2p2). FIXME: + // Ideally, this check would be performed in + // checkPointerTypesForAssignment. However, that would require a + // bit of refactoring (so that the second argument is an + // expression, rather than a type), which should be done as part + // of a larger effort to fix checkPointerTypesForAssignment for + // C++ semantics. + if (getLangOpts().CPlusPlus && + IsStringLiteralToNonConstPointerConversion(SrcExpr, DstType)) + return false; + DiagKind = diag::ext_typecheck_convert_discards_qualifiers; + break; + case IncompatibleNestedPointerQualifiers: + DiagKind = diag::ext_nested_pointer_qualifier_mismatch; + break; + case IntToBlockPointer: + DiagKind = diag::err_int_to_block_pointer; + break; + case IncompatibleBlockPointer: + DiagKind = diag::err_typecheck_convert_incompatible_block_pointer; + break; + case IncompatibleObjCQualifiedId: + // FIXME: Diagnose the problem in ObjCQualifiedIdTypesAreCompatible, since + // it can give a more specific diagnostic. + DiagKind = diag::warn_incompatible_qualified_id; + break; + case IncompatibleVectors: + DiagKind = diag::warn_incompatible_vectors; + break; + case IncompatibleObjCWeakRef: + DiagKind = diag::err_arc_weak_unavailable_assign; + break; + case Incompatible: + DiagKind = diag::err_typecheck_convert_incompatible; + ConvHints.tryToFixConversion(SrcExpr, SrcType, DstType, *this); + MayHaveConvFixit = true; + isInvalid = true; + MayHaveFunctionDiff = true; + break; + } + + QualType FirstType, SecondType; + switch (Action) { + case AA_Assigning: + case AA_Initializing: + // The destination type comes first. + FirstType = DstType; + SecondType = SrcType; + break; + + case AA_Returning: + case AA_Passing: + case AA_Converting: + case AA_Sending: + case AA_Casting: + // The source type comes first. + FirstType = SrcType; + SecondType = DstType; + break; + } + + PartialDiagnostic FDiag = PDiag(DiagKind); + FDiag << FirstType << SecondType << Action << SrcExpr->getSourceRange(); + + // If we can fix the conversion, suggest the FixIts. + assert(ConvHints.isNull() || Hint.isNull()); + if (!ConvHints.isNull()) { + for (std::vector::iterator HI = ConvHints.Hints.begin(), + HE = ConvHints.Hints.end(); HI != HE; ++HI) + FDiag << *HI; + } else { + FDiag << Hint; + } + if (MayHaveConvFixit) { FDiag << (unsigned) (ConvHints.Kind); } + + if (MayHaveFunctionDiff) + HandleFunctionTypeMismatch(FDiag, SecondType, FirstType); + + Diag(Loc, FDiag); + + if (SecondType == Context.OverloadTy) + NoteAllOverloadCandidates(OverloadExpr::find(SrcExpr).Expression, + FirstType); + + if (CheckInferredResultType) + EmitRelatedResultTypeNote(SrcExpr); + + if (Complained) + *Complained = true; + return isInvalid; +} + +ExprResult Sema::VerifyIntegerConstantExpression(Expr *E, + llvm::APSInt *Result) { + return VerifyIntegerConstantExpression(E, Result, + PDiag(diag::err_expr_not_ice) << LangOpts.CPlusPlus); +} + +ExprResult +Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, + const PartialDiagnostic &NotIceDiag, + bool AllowFold, + const PartialDiagnostic &FoldDiag) { + SourceLocation DiagLoc = E->getLocStart(); + + if (getLangOpts().CPlusPlus0x) { + // C++11 [expr.const]p5: + // If an expression of literal class type is used in a context where an + // integral constant expression is required, then that class type shall + // have a single non-explicit conversion function to an integral or + // unscoped enumeration type + ExprResult Converted; + if (NotIceDiag.getDiagID()) { + Converted = ConvertToIntegralOrEnumerationType( + DiagLoc, E, + PDiag(diag::err_ice_not_integral), + PDiag(diag::err_ice_incomplete_type), + PDiag(diag::err_ice_explicit_conversion), + PDiag(diag::note_ice_conversion_here), + PDiag(diag::err_ice_ambiguous_conversion), + PDiag(diag::note_ice_conversion_here), + PDiag(0), + /*AllowScopedEnumerations*/ false); + } else { + // The caller wants to silently enquire whether this is an ICE. Don't + // produce any diagnostics if it isn't. + Converted = ConvertToIntegralOrEnumerationType( + DiagLoc, E, PDiag(), PDiag(), PDiag(), PDiag(), + PDiag(), PDiag(), PDiag(), false); + } + if (Converted.isInvalid()) + return Converted; + E = Converted.take(); + if (!E->getType()->isIntegralOrUnscopedEnumerationType()) + return ExprError(); + } else if (!E->getType()->isIntegralOrUnscopedEnumerationType()) { + // An ICE must be of integral or unscoped enumeration type. + if (NotIceDiag.getDiagID()) + Diag(DiagLoc, NotIceDiag) << E->getSourceRange(); + return ExprError(); + } + + // Circumvent ICE checking in C++11 to avoid evaluating the expression twice + // in the non-ICE case. + if (!getLangOpts().CPlusPlus0x && E->isIntegerConstantExpr(Context)) { + if (Result) + *Result = E->EvaluateKnownConstInt(Context); + return Owned(E); + } + + Expr::EvalResult EvalResult; + llvm::SmallVector Notes; + EvalResult.Diag = &Notes; + + // Try to evaluate the expression, and produce diagnostics explaining why it's + // not a constant expression as a side-effect. + bool Folded = E->EvaluateAsRValue(EvalResult, Context) && + EvalResult.Val.isInt() && !EvalResult.HasSideEffects; + + // In C++11, we can rely on diagnostics being produced for any expression + // which is not a constant expression. If no diagnostics were produced, then + // this is a constant expression. + if (Folded && getLangOpts().CPlusPlus0x && Notes.empty()) { + if (Result) + *Result = EvalResult.Val.getInt(); + return Owned(E); + } + + // If our only note is the usual "invalid subexpression" note, just point + // the caret at its location rather than producing an essentially + // redundant note. + if (Notes.size() == 1 && Notes[0].second.getDiagID() == + diag::note_invalid_subexpr_in_const_expr) { + DiagLoc = Notes[0].first; + Notes.clear(); + } + + if (!Folded || !AllowFold) { + if (NotIceDiag.getDiagID()) { + Diag(DiagLoc, NotIceDiag) << E->getSourceRange(); + for (unsigned I = 0, N = Notes.size(); I != N; ++I) + Diag(Notes[I].first, Notes[I].second); + } + + return ExprError(); + } + + if (FoldDiag.getDiagID()) + Diag(DiagLoc, FoldDiag) << E->getSourceRange(); + else + Diag(DiagLoc, diag::ext_expr_not_ice) + << E->getSourceRange() << LangOpts.CPlusPlus; + for (unsigned I = 0, N = Notes.size(); I != N; ++I) + Diag(Notes[I].first, Notes[I].second); + + if (Result) + *Result = EvalResult.Val.getInt(); + return Owned(E); +} + +namespace { + // Handle the case where we conclude a expression which we speculatively + // considered to be unevaluated is actually evaluated. + class TransformToPE : public TreeTransform { + typedef TreeTransform BaseTransform; + + public: + TransformToPE(Sema &SemaRef) : BaseTransform(SemaRef) { } + + // Make sure we redo semantic analysis + bool AlwaysRebuild() { return true; } + + // Make sure we handle LabelStmts correctly. + // FIXME: This does the right thing, but maybe we need a more general + // fix to TreeTransform? + StmtResult TransformLabelStmt(LabelStmt *S) { + S->getDecl()->setStmt(0); + return BaseTransform::TransformLabelStmt(S); + } + + // We need to special-case DeclRefExprs referring to FieldDecls which + // are not part of a member pointer formation; normal TreeTransforming + // doesn't catch this case because of the way we represent them in the AST. + // FIXME: This is a bit ugly; is it really the best way to handle this + // case? + // + // Error on DeclRefExprs referring to FieldDecls. + ExprResult TransformDeclRefExpr(DeclRefExpr *E) { + if (isa(E->getDecl()) && + SemaRef.ExprEvalContexts.back().Context != Sema::Unevaluated) + return SemaRef.Diag(E->getLocation(), + diag::err_invalid_non_static_member_use) + << E->getDecl() << E->getSourceRange(); + + return BaseTransform::TransformDeclRefExpr(E); + } + + // Exception: filter out member pointer formation + ExprResult TransformUnaryOperator(UnaryOperator *E) { + if (E->getOpcode() == UO_AddrOf && E->getType()->isMemberPointerType()) + return E; + + return BaseTransform::TransformUnaryOperator(E); + } + + ExprResult TransformLambdaExpr(LambdaExpr *E) { + // Lambdas never need to be transformed. + return E; + } + }; +} + +ExprResult Sema::TranformToPotentiallyEvaluated(Expr *E) { + assert(ExprEvalContexts.back().Context == Unevaluated && + "Should only transform unevaluated expressions"); + ExprEvalContexts.back().Context = + ExprEvalContexts[ExprEvalContexts.size()-2].Context; + if (ExprEvalContexts.back().Context == Unevaluated) + return E; + return TransformToPE(*this).TransformExpr(E); +} + +void +Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, + Decl *LambdaContextDecl, + bool IsDecltype) { + ExprEvalContexts.push_back( + ExpressionEvaluationContextRecord(NewContext, + ExprCleanupObjects.size(), + ExprNeedsCleanups, + LambdaContextDecl, + IsDecltype)); + ExprNeedsCleanups = false; + if (!MaybeODRUseExprs.empty()) + std::swap(MaybeODRUseExprs, ExprEvalContexts.back().SavedMaybeODRUseExprs); +} + +void Sema::PopExpressionEvaluationContext() { + ExpressionEvaluationContextRecord& Rec = ExprEvalContexts.back(); + + if (!Rec.Lambdas.empty()) { + if (Rec.Context == Unevaluated) { + // C++11 [expr.prim.lambda]p2: + // A lambda-expression shall not appear in an unevaluated operand + // (Clause 5). + for (unsigned I = 0, N = Rec.Lambdas.size(); I != N; ++I) + Diag(Rec.Lambdas[I]->getLocStart(), + diag::err_lambda_unevaluated_operand); + } else { + // Mark the capture expressions odr-used. This was deferred + // during lambda expression creation. + for (unsigned I = 0, N = Rec.Lambdas.size(); I != N; ++I) { + LambdaExpr *Lambda = Rec.Lambdas[I]; + for (LambdaExpr::capture_init_iterator + C = Lambda->capture_init_begin(), + CEnd = Lambda->capture_init_end(); + C != CEnd; ++C) { + MarkDeclarationsReferencedInExpr(*C); + } + } + } + } + + // When are coming out of an unevaluated context, clear out any + // temporaries that we may have created as part of the evaluation of + // the expression in that context: they aren't relevant because they + // will never be constructed. + if (Rec.Context == Unevaluated || Rec.Context == ConstantEvaluated) { + ExprCleanupObjects.erase(ExprCleanupObjects.begin() + Rec.NumCleanupObjects, + ExprCleanupObjects.end()); + ExprNeedsCleanups = Rec.ParentNeedsCleanups; + CleanupVarDeclMarking(); + std::swap(MaybeODRUseExprs, Rec.SavedMaybeODRUseExprs); + // Otherwise, merge the contexts together. + } else { + ExprNeedsCleanups |= Rec.ParentNeedsCleanups; + MaybeODRUseExprs.insert(Rec.SavedMaybeODRUseExprs.begin(), + Rec.SavedMaybeODRUseExprs.end()); + } + + // Pop the current expression evaluation context off the stack. + ExprEvalContexts.pop_back(); +} + +void Sema::DiscardCleanupsInEvaluationContext() { + ExprCleanupObjects.erase( + ExprCleanupObjects.begin() + ExprEvalContexts.back().NumCleanupObjects, + ExprCleanupObjects.end()); + ExprNeedsCleanups = false; + MaybeODRUseExprs.clear(); +} + +ExprResult Sema::HandleExprEvaluationContextForTypeof(Expr *E) { + if (!E->getType()->isVariablyModifiedType()) + return E; + return TranformToPotentiallyEvaluated(E); +} + +static bool IsPotentiallyEvaluatedContext(Sema &SemaRef) { + // Do not mark anything as "used" within a dependent context; wait for + // an instantiation. + if (SemaRef.CurContext->isDependentContext()) + return false; + + switch (SemaRef.ExprEvalContexts.back().Context) { + case Sema::Unevaluated: + // We are in an expression that is not potentially evaluated; do nothing. + // (Depending on how you read the standard, we actually do need to do + // something here for null pointer constants, but the standard's + // definition of a null pointer constant is completely crazy.) + return false; + + case Sema::ConstantEvaluated: + case Sema::PotentiallyEvaluated: + // We are in a potentially evaluated expression (or a constant-expression + // in C++03); we need to do implicit template instantiation, implicitly + // define class members, and mark most declarations as used. + return true; + + case Sema::PotentiallyEvaluatedIfUsed: + // Referenced declarations will only be used if the construct in the + // containing expression is used. + return false; + } + llvm_unreachable("Invalid context"); +} + +/// \brief Mark a function referenced, and check whether it is odr-used +/// (C++ [basic.def.odr]p2, C99 6.9p3) +void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func) { + assert(Func && "No function?"); + + Func->setReferenced(); + + // Don't mark this function as used multiple times, unless it's a constexpr + // function which we need to instantiate. + if (Func->isUsed(false) && + !(Func->isConstexpr() && !Func->getBody() && + Func->isImplicitlyInstantiable())) + return; + + if (!IsPotentiallyEvaluatedContext(*this)) + return; + + // Note that this declaration has been used. + if (CXXConstructorDecl *Constructor = dyn_cast(Func)) { + if (Constructor->isDefaulted() && !Constructor->isDeleted()) { + if (Constructor->isDefaultConstructor()) { + if (Constructor->isTrivial()) + return; + if (!Constructor->isUsed(false)) + DefineImplicitDefaultConstructor(Loc, Constructor); + } else if (Constructor->isCopyConstructor()) { + if (!Constructor->isUsed(false)) + DefineImplicitCopyConstructor(Loc, Constructor); + } else if (Constructor->isMoveConstructor()) { + if (!Constructor->isUsed(false)) + DefineImplicitMoveConstructor(Loc, Constructor); + } + } + + MarkVTableUsed(Loc, Constructor->getParent()); + } else if (CXXDestructorDecl *Destructor = + dyn_cast(Func)) { + if (Destructor->isDefaulted() && !Destructor->isDeleted() && + !Destructor->isUsed(false)) + DefineImplicitDestructor(Loc, Destructor); + if (Destructor->isVirtual()) + MarkVTableUsed(Loc, Destructor->getParent()); + } else if (CXXMethodDecl *MethodDecl = dyn_cast(Func)) { + if (MethodDecl->isDefaulted() && !MethodDecl->isDeleted() && + MethodDecl->isOverloadedOperator() && + MethodDecl->getOverloadedOperator() == OO_Equal) { + if (!MethodDecl->isUsed(false)) { + if (MethodDecl->isCopyAssignmentOperator()) + DefineImplicitCopyAssignment(Loc, MethodDecl); + else + DefineImplicitMoveAssignment(Loc, MethodDecl); + } + } else if (isa(MethodDecl) && + MethodDecl->getParent()->isLambda()) { + CXXConversionDecl *Conversion = cast(MethodDecl); + if (Conversion->isLambdaToBlockPointerConversion()) + DefineImplicitLambdaToBlockPointerConversion(Loc, Conversion); + else + DefineImplicitLambdaToFunctionPointerConversion(Loc, Conversion); + } else if (MethodDecl->isVirtual()) + MarkVTableUsed(Loc, MethodDecl->getParent()); + } + + // Recursive functions should be marked when used from another function. + // FIXME: Is this really right? + if (CurContext == Func) return; + + // Instantiate the exception specification for any function which is + // used: CodeGen will need it. + const FunctionProtoType *FPT = Func->getType()->getAs(); + if (FPT && FPT->getExceptionSpecType() == EST_Uninstantiated) + InstantiateExceptionSpec(Loc, Func); + + // Implicit instantiation of function templates and member functions of + // class templates. + if (Func->isImplicitlyInstantiable()) { + bool AlreadyInstantiated = false; + SourceLocation PointOfInstantiation = Loc; + if (FunctionTemplateSpecializationInfo *SpecInfo + = Func->getTemplateSpecializationInfo()) { + if (SpecInfo->getPointOfInstantiation().isInvalid()) + SpecInfo->setPointOfInstantiation(Loc); + else if (SpecInfo->getTemplateSpecializationKind() + == TSK_ImplicitInstantiation) { + AlreadyInstantiated = true; + PointOfInstantiation = SpecInfo->getPointOfInstantiation(); + } + } else if (MemberSpecializationInfo *MSInfo + = Func->getMemberSpecializationInfo()) { + if (MSInfo->getPointOfInstantiation().isInvalid()) + MSInfo->setPointOfInstantiation(Loc); + else if (MSInfo->getTemplateSpecializationKind() + == TSK_ImplicitInstantiation) { + AlreadyInstantiated = true; + PointOfInstantiation = MSInfo->getPointOfInstantiation(); + } + } + + if (!AlreadyInstantiated || Func->isConstexpr()) { + if (isa(Func->getDeclContext()) && + cast(Func->getDeclContext())->isLocalClass()) + PendingLocalImplicitInstantiations.push_back( + std::make_pair(Func, PointOfInstantiation)); + else if (Func->isConstexpr()) + // Do not defer instantiations of constexpr functions, to avoid the + // expression evaluator needing to call back into Sema if it sees a + // call to such a function. + InstantiateFunctionDefinition(PointOfInstantiation, Func); + else { + PendingInstantiations.push_back(std::make_pair(Func, + PointOfInstantiation)); + // Notify the consumer that a function was implicitly instantiated. + Consumer.HandleCXXImplicitFunctionInstantiation(Func); + } + } + } else { + // Walk redefinitions, as some of them may be instantiable. + for (FunctionDecl::redecl_iterator i(Func->redecls_begin()), + e(Func->redecls_end()); i != e; ++i) { + if (!i->isUsed(false) && i->isImplicitlyInstantiable()) + MarkFunctionReferenced(Loc, *i); + } + } + + // Keep track of used but undefined functions. + if (!Func->isPure() && !Func->hasBody() && + Func->getLinkage() != ExternalLinkage) { + SourceLocation &old = UndefinedInternals[Func->getCanonicalDecl()]; + if (old.isInvalid()) old = Loc; + } + + Func->setUsed(true); +} + +static void +diagnoseUncapturableValueReference(Sema &S, SourceLocation loc, + VarDecl *var, DeclContext *DC) { + DeclContext *VarDC = var->getDeclContext(); + + // If the parameter still belongs to the translation unit, then + // we're actually just using one parameter in the declaration of + // the next. + if (isa(var) && + isa(VarDC)) + return; + + // For C code, don't diagnose about capture if we're not actually in code + // right now; it's impossible to write a non-constant expression outside of + // function context, so we'll get other (more useful) diagnostics later. + // + // For C++, things get a bit more nasty... it would be nice to suppress this + // diagnostic for certain cases like using a local variable in an array bound + // for a member of a local class, but the correct predicate is not obvious. + if (!S.getLangOpts().CPlusPlus && !S.CurContext->isFunctionOrMethod()) + return; + + if (isa(VarDC) && + cast(VarDC->getParent())->isLambda()) { + S.Diag(loc, diag::err_reference_to_local_var_in_enclosing_lambda) + << var->getIdentifier(); + } else if (FunctionDecl *fn = dyn_cast(VarDC)) { + S.Diag(loc, diag::err_reference_to_local_var_in_enclosing_function) + << var->getIdentifier() << fn->getDeclName(); + } else if (isa(VarDC)) { + S.Diag(loc, diag::err_reference_to_local_var_in_enclosing_block) + << var->getIdentifier(); + } else { + // FIXME: Is there any other context where a local variable can be + // declared? + S.Diag(loc, diag::err_reference_to_local_var_in_enclosing_context) + << var->getIdentifier(); + } + + S.Diag(var->getLocation(), diag::note_local_variable_declared_here) + << var->getIdentifier(); + + // FIXME: Add additional diagnostic info about class etc. which prevents + // capture. +} + +/// \brief Capture the given variable in the given lambda expression. +static ExprResult captureInLambda(Sema &S, LambdaScopeInfo *LSI, + VarDecl *Var, QualType FieldType, + QualType DeclRefType, + SourceLocation Loc) { + CXXRecordDecl *Lambda = LSI->Lambda; + + // Build the non-static data member. + FieldDecl *Field + = FieldDecl::Create(S.Context, Lambda, Loc, Loc, 0, FieldType, + S.Context.getTrivialTypeSourceInfo(FieldType, Loc), + 0, false, false); + Field->setImplicit(true); + Field->setAccess(AS_private); + Lambda->addDecl(Field); + + // C++11 [expr.prim.lambda]p21: + // When the lambda-expression is evaluated, the entities that + // are captured by copy are used to direct-initialize each + // corresponding non-static data member of the resulting closure + // object. (For array members, the array elements are + // direct-initialized in increasing subscript order.) These + // initializations are performed in the (unspecified) order in + // which the non-static data members are declared. + + // Introduce a new evaluation context for the initialization, so + // that temporaries introduced as part of the capture are retained + // to be re-"exported" from the lambda expression itself. + S.PushExpressionEvaluationContext(Sema::PotentiallyEvaluated); + + // C++ [expr.prim.labda]p12: + // An entity captured by a lambda-expression is odr-used (3.2) in + // the scope containing the lambda-expression. + Expr *Ref = new (S.Context) DeclRefExpr(Var, false, DeclRefType, + VK_LValue, Loc); + Var->setReferenced(true); + Var->setUsed(true); + + // When the field has array type, create index variables for each + // dimension of the array. We use these index variables to subscript + // the source array, and other clients (e.g., CodeGen) will perform + // the necessary iteration with these index variables. + SmallVector IndexVariables; + QualType BaseType = FieldType; + QualType SizeType = S.Context.getSizeType(); + LSI->ArrayIndexStarts.push_back(LSI->ArrayIndexVars.size()); + while (const ConstantArrayType *Array + = S.Context.getAsConstantArrayType(BaseType)) { + // Create the iteration variable for this array index. + IdentifierInfo *IterationVarName = 0; + { + SmallString<8> Str; + llvm::raw_svector_ostream OS(Str); + OS << "__i" << IndexVariables.size(); + IterationVarName = &S.Context.Idents.get(OS.str()); + } + VarDecl *IterationVar + = VarDecl::Create(S.Context, S.CurContext, Loc, Loc, + IterationVarName, SizeType, + S.Context.getTrivialTypeSourceInfo(SizeType, Loc), + SC_None, SC_None); + IndexVariables.push_back(IterationVar); + LSI->ArrayIndexVars.push_back(IterationVar); + + // Create a reference to the iteration variable. + ExprResult IterationVarRef + = S.BuildDeclRefExpr(IterationVar, SizeType, VK_LValue, Loc); + assert(!IterationVarRef.isInvalid() && + "Reference to invented variable cannot fail!"); + IterationVarRef = S.DefaultLvalueConversion(IterationVarRef.take()); + assert(!IterationVarRef.isInvalid() && + "Conversion of invented variable cannot fail!"); + + // Subscript the array with this iteration variable. + ExprResult Subscript = S.CreateBuiltinArraySubscriptExpr( + Ref, Loc, IterationVarRef.take(), Loc); + if (Subscript.isInvalid()) { + S.CleanupVarDeclMarking(); + S.DiscardCleanupsInEvaluationContext(); + S.PopExpressionEvaluationContext(); + return ExprError(); + } + + Ref = Subscript.take(); + BaseType = Array->getElementType(); + } + + // Construct the entity that we will be initializing. For an array, this + // will be first element in the array, which may require several levels + // of array-subscript entities. + SmallVector Entities; + Entities.reserve(1 + IndexVariables.size()); + Entities.push_back( + InitializedEntity::InitializeLambdaCapture(Var, Field, Loc)); + for (unsigned I = 0, N = IndexVariables.size(); I != N; ++I) + Entities.push_back(InitializedEntity::InitializeElement(S.Context, + 0, + Entities.back())); + + InitializationKind InitKind + = InitializationKind::CreateDirect(Loc, Loc, Loc); + InitializationSequence Init(S, Entities.back(), InitKind, &Ref, 1); + ExprResult Result(true); + if (!Init.Diagnose(S, Entities.back(), InitKind, &Ref, 1)) + Result = Init.Perform(S, Entities.back(), InitKind, + MultiExprArg(S, &Ref, 1)); + + // If this initialization requires any cleanups (e.g., due to a + // default argument to a copy constructor), note that for the + // lambda. + if (S.ExprNeedsCleanups) + LSI->ExprNeedsCleanups = true; + + // Exit the expression evaluation context used for the capture. + S.CleanupVarDeclMarking(); + S.DiscardCleanupsInEvaluationContext(); + S.PopExpressionEvaluationContext(); + return Result; +} + +bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation Loc, + TryCaptureKind Kind, SourceLocation EllipsisLoc, + bool BuildAndDiagnose, + QualType &CaptureType, + QualType &DeclRefType) { + bool Nested = false; + + DeclContext *DC = CurContext; + if (Var->getDeclContext() == DC) return true; + if (!Var->hasLocalStorage()) return true; + + bool HasBlocksAttr = Var->hasAttr(); + + // Walk up the stack to determine whether we can capture the variable, + // performing the "simple" checks that don't depend on type. We stop when + // we've either hit the declared scope of the variable or find an existing + // capture of that variable. + CaptureType = Var->getType(); + DeclRefType = CaptureType.getNonReferenceType(); + bool Explicit = (Kind != TryCapture_Implicit); + unsigned FunctionScopesIndex = FunctionScopes.size() - 1; + do { + // Only block literals and lambda expressions can capture; other + // scopes don't work. + DeclContext *ParentDC; + if (isa(DC)) + ParentDC = DC->getParent(); + else if (isa(DC) && + cast(DC)->getOverloadedOperator() == OO_Call && + cast(DC->getParent())->isLambda()) + ParentDC = DC->getParent()->getParent(); + else { + if (BuildAndDiagnose) + diagnoseUncapturableValueReference(*this, Loc, Var, DC); + return true; + } + + CapturingScopeInfo *CSI = + cast(FunctionScopes[FunctionScopesIndex]); + + // Check whether we've already captured it. + if (CSI->CaptureMap.count(Var)) { + // If we found a capture, any subcaptures are nested. + Nested = true; + + // Retrieve the capture type for this variable. + CaptureType = CSI->getCapture(Var).getCaptureType(); + + // Compute the type of an expression that refers to this variable. + DeclRefType = CaptureType.getNonReferenceType(); + + const CapturingScopeInfo::Capture &Cap = CSI->getCapture(Var); + if (Cap.isCopyCapture() && + !(isa(CSI) && cast(CSI)->Mutable)) + DeclRefType.addConst(); + break; + } + + bool IsBlock = isa(CSI); + bool IsLambda = !IsBlock; + + // Lambdas are not allowed to capture unnamed variables + // (e.g. anonymous unions). + // FIXME: The C++11 rule don't actually state this explicitly, but I'm + // assuming that's the intent. + if (IsLambda && !Var->getDeclName()) { + if (BuildAndDiagnose) { + Diag(Loc, diag::err_lambda_capture_anonymous_var); + Diag(Var->getLocation(), diag::note_declared_at); + } + return true; + } + + // Prohibit variably-modified types; they're difficult to deal with. + if (Var->getType()->isVariablyModifiedType()) { + if (BuildAndDiagnose) { + if (IsBlock) + Diag(Loc, diag::err_ref_vm_type); + else + Diag(Loc, diag::err_lambda_capture_vm_type) << Var->getDeclName(); + Diag(Var->getLocation(), diag::note_previous_decl) + << Var->getDeclName(); + } + return true; + } + + // Lambdas are not allowed to capture __block variables; they don't + // support the expected semantics. + if (IsLambda && HasBlocksAttr) { + if (BuildAndDiagnose) { + Diag(Loc, diag::err_lambda_capture_block) + << Var->getDeclName(); + Diag(Var->getLocation(), diag::note_previous_decl) + << Var->getDeclName(); + } + return true; + } + + if (CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_None && !Explicit) { + // No capture-default + if (BuildAndDiagnose) { + Diag(Loc, diag::err_lambda_impcap) << Var->getDeclName(); + Diag(Var->getLocation(), diag::note_previous_decl) + << Var->getDeclName(); + Diag(cast(CSI)->Lambda->getLocStart(), + diag::note_lambda_decl); + } + return true; + } + + FunctionScopesIndex--; + DC = ParentDC; + Explicit = false; + } while (!Var->getDeclContext()->Equals(DC)); + + // Walk back down the scope stack, computing the type of the capture at + // each step, checking type-specific requirements, and adding captures if + // requested. + for (unsigned I = ++FunctionScopesIndex, N = FunctionScopes.size(); I != N; + ++I) { + CapturingScopeInfo *CSI = cast(FunctionScopes[I]); + + // Compute the type of the capture and of a reference to the capture within + // this scope. + if (isa(CSI)) { + Expr *CopyExpr = 0; + bool ByRef = false; + + // Blocks are not allowed to capture arrays. + if (CaptureType->isArrayType()) { + if (BuildAndDiagnose) { + Diag(Loc, diag::err_ref_array_type); + Diag(Var->getLocation(), diag::note_previous_decl) + << Var->getDeclName(); + } + return true; + } + + // Forbid the block-capture of autoreleasing variables. + if (CaptureType.getObjCLifetime() == Qualifiers::OCL_Autoreleasing) { + if (BuildAndDiagnose) { + Diag(Loc, diag::err_arc_autoreleasing_capture) + << /*block*/ 0; + Diag(Var->getLocation(), diag::note_previous_decl) + << Var->getDeclName(); + } + return true; + } + + if (HasBlocksAttr || CaptureType->isReferenceType()) { + // Block capture by reference does not change the capture or + // declaration reference types. + ByRef = true; + } else { + // Block capture by copy introduces 'const'. + CaptureType = CaptureType.getNonReferenceType().withConst(); + DeclRefType = CaptureType; + + if (getLangOpts().CPlusPlus && BuildAndDiagnose) { + if (const RecordType *Record = DeclRefType->getAs()) { + // The capture logic needs the destructor, so make sure we mark it. + // Usually this is unnecessary because most local variables have + // their destructors marked at declaration time, but parameters are + // an exception because it's technically only the call site that + // actually requires the destructor. + if (isa(Var)) + FinalizeVarWithDestructor(Var, Record); + + // According to the blocks spec, the capture of a variable from + // the stack requires a const copy constructor. This is not true + // of the copy/move done to move a __block variable to the heap. + Expr *DeclRef = new (Context) DeclRefExpr(Var, false, + DeclRefType.withConst(), + VK_LValue, Loc); + ExprResult Result + = PerformCopyInitialization( + InitializedEntity::InitializeBlock(Var->getLocation(), + CaptureType, false), + Loc, Owned(DeclRef)); + + // Build a full-expression copy expression if initialization + // succeeded and used a non-trivial constructor. Recover from + // errors by pretending that the copy isn't necessary. + if (!Result.isInvalid() && + !cast(Result.get())->getConstructor() + ->isTrivial()) { + Result = MaybeCreateExprWithCleanups(Result); + CopyExpr = Result.take(); + } + } + } + } + + // Actually capture the variable. + if (BuildAndDiagnose) + CSI->addCapture(Var, HasBlocksAttr, ByRef, Nested, Loc, + SourceLocation(), CaptureType, CopyExpr); + Nested = true; + continue; + } + + LambdaScopeInfo *LSI = cast(CSI); + + // Determine whether we are capturing by reference or by value. + bool ByRef = false; + if (I == N - 1 && Kind != TryCapture_Implicit) { + ByRef = (Kind == TryCapture_ExplicitByRef); + } else { + ByRef = (LSI->ImpCaptureStyle == LambdaScopeInfo::ImpCap_LambdaByref); + } + + // Compute the type of the field that will capture this variable. + if (ByRef) { + // C++11 [expr.prim.lambda]p15: + // An entity is captured by reference if it is implicitly or + // explicitly captured but not captured by copy. It is + // unspecified whether additional unnamed non-static data + // members are declared in the closure type for entities + // captured by reference. + // + // FIXME: It is not clear whether we want to build an lvalue reference + // to the DeclRefType or to CaptureType.getNonReferenceType(). GCC appears + // to do the former, while EDG does the latter. Core issue 1249 will + // clarify, but for now we follow GCC because it's a more permissive and + // easily defensible position. + CaptureType = Context.getLValueReferenceType(DeclRefType); + } else { + // C++11 [expr.prim.lambda]p14: + // For each entity captured by copy, an unnamed non-static + // data member is declared in the closure type. The + // declaration order of these members is unspecified. The type + // of such a data member is the type of the corresponding + // captured entity if the entity is not a reference to an + // object, or the referenced type otherwise. [Note: If the + // captured entity is a reference to a function, the + // corresponding data member is also a reference to a + // function. - end note ] + if (const ReferenceType *RefType = CaptureType->getAs()){ + if (!RefType->getPointeeType()->isFunctionType()) + CaptureType = RefType->getPointeeType(); + } + + // Forbid the lambda copy-capture of autoreleasing variables. + if (CaptureType.getObjCLifetime() == Qualifiers::OCL_Autoreleasing) { + if (BuildAndDiagnose) { + Diag(Loc, diag::err_arc_autoreleasing_capture) << /*lambda*/ 1; + Diag(Var->getLocation(), diag::note_previous_decl) + << Var->getDeclName(); + } + return true; + } + } + + // Capture this variable in the lambda. + Expr *CopyExpr = 0; + if (BuildAndDiagnose) { + ExprResult Result = captureInLambda(*this, LSI, Var, CaptureType, + DeclRefType, Loc); + if (!Result.isInvalid()) + CopyExpr = Result.take(); + } + + // Compute the type of a reference to this captured variable. + if (ByRef) + DeclRefType = CaptureType.getNonReferenceType(); + else { + // C++ [expr.prim.lambda]p5: + // The closure type for a lambda-expression has a public inline + // function call operator [...]. This function call operator is + // declared const (9.3.1) if and only if the lambda-expression’s + // parameter-declaration-clause is not followed by mutable. + DeclRefType = CaptureType.getNonReferenceType(); + if (!LSI->Mutable && !CaptureType->isReferenceType()) + DeclRefType.addConst(); + } + + // Add the capture. + if (BuildAndDiagnose) + CSI->addCapture(Var, /*IsBlock=*/false, ByRef, Nested, Loc, + EllipsisLoc, CaptureType, CopyExpr); + Nested = true; + } + + return false; +} + +bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation Loc, + TryCaptureKind Kind, SourceLocation EllipsisLoc) { + QualType CaptureType; + QualType DeclRefType; + return tryCaptureVariable(Var, Loc, Kind, EllipsisLoc, + /*BuildAndDiagnose=*/true, CaptureType, + DeclRefType); +} + +QualType Sema::getCapturedDeclRefType(VarDecl *Var, SourceLocation Loc) { + QualType CaptureType; + QualType DeclRefType; + + // Determine whether we can capture this variable. + if (tryCaptureVariable(Var, Loc, TryCapture_Implicit, SourceLocation(), + /*BuildAndDiagnose=*/false, CaptureType, DeclRefType)) + return QualType(); + + return DeclRefType; +} + +static void MarkVarDeclODRUsed(Sema &SemaRef, VarDecl *Var, + SourceLocation Loc) { + // Keep track of used but undefined variables. + // FIXME: We shouldn't suppress this warning for static data members. + if (Var->hasDefinition(SemaRef.Context) == VarDecl::DeclarationOnly && + Var->getLinkage() != ExternalLinkage && + !(Var->isStaticDataMember() && Var->hasInit())) { + SourceLocation &old = SemaRef.UndefinedInternals[Var->getCanonicalDecl()]; + if (old.isInvalid()) old = Loc; + } + + SemaRef.tryCaptureVariable(Var, Loc); + + Var->setUsed(true); +} + +void Sema::UpdateMarkingForLValueToRValue(Expr *E) { + // Per C++11 [basic.def.odr], a variable is odr-used "unless it is + // an object that satisfies the requirements for appearing in a + // constant expression (5.19) and the lvalue-to-rvalue conversion (4.1) + // is immediately applied." This function handles the lvalue-to-rvalue + // conversion part. + MaybeODRUseExprs.erase(E->IgnoreParens()); +} + +ExprResult Sema::ActOnConstantExpression(ExprResult Res) { + if (!Res.isUsable()) + return Res; + + // If a constant-expression is a reference to a variable where we delay + // deciding whether it is an odr-use, just assume we will apply the + // lvalue-to-rvalue conversion. In the one case where this doesn't happen + // (a non-type template argument), we have special handling anyway. + UpdateMarkingForLValueToRValue(Res.get()); + return Res; +} + +void Sema::CleanupVarDeclMarking() { + for (llvm::SmallPtrSetIterator i = MaybeODRUseExprs.begin(), + e = MaybeODRUseExprs.end(); + i != e; ++i) { + VarDecl *Var; + SourceLocation Loc; + if (DeclRefExpr *DRE = dyn_cast(*i)) { + Var = cast(DRE->getDecl()); + Loc = DRE->getLocation(); + } else if (MemberExpr *ME = dyn_cast(*i)) { + Var = cast(ME->getMemberDecl()); + Loc = ME->getMemberLoc(); + } else { + llvm_unreachable("Unexpcted expression"); + } + + MarkVarDeclODRUsed(*this, Var, Loc); + } + + MaybeODRUseExprs.clear(); +} + +// Mark a VarDecl referenced, and perform the necessary handling to compute +// odr-uses. +static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc, + VarDecl *Var, Expr *E) { + Var->setReferenced(); + + if (!IsPotentiallyEvaluatedContext(SemaRef)) + return; + + // Implicit instantiation of static data members of class templates. + if (Var->isStaticDataMember() && Var->getInstantiatedFromStaticDataMember()) { + MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo(); + assert(MSInfo && "Missing member specialization information?"); + bool AlreadyInstantiated = !MSInfo->getPointOfInstantiation().isInvalid(); + if (MSInfo->getTemplateSpecializationKind() == TSK_ImplicitInstantiation && + (!AlreadyInstantiated || + Var->isUsableInConstantExpressions(SemaRef.Context))) { + if (!AlreadyInstantiated) { + // This is a modification of an existing AST node. Notify listeners. + if (ASTMutationListener *L = SemaRef.getASTMutationListener()) + L->StaticDataMemberInstantiated(Var); + MSInfo->setPointOfInstantiation(Loc); + } + SourceLocation PointOfInstantiation = MSInfo->getPointOfInstantiation(); + if (Var->isUsableInConstantExpressions(SemaRef.Context)) + // Do not defer instantiations of variables which could be used in a + // constant expression. + SemaRef.InstantiateStaticDataMemberDefinition(PointOfInstantiation,Var); + else + SemaRef.PendingInstantiations.push_back( + std::make_pair(Var, PointOfInstantiation)); + } + } + + // Per C++11 [basic.def.odr], a variable is odr-used "unless it is + // an object that satisfies the requirements for appearing in a + // constant expression (5.19) and the lvalue-to-rvalue conversion (4.1) + // is immediately applied." We check the first part here, and + // Sema::UpdateMarkingForLValueToRValue deals with the second part. + // Note that we use the C++11 definition everywhere because nothing in + // C++03 depends on whether we get the C++03 version correct. This does not + // apply to references, since they are not objects. + const VarDecl *DefVD; + if (E && !isa(Var) && !Var->getType()->isReferenceType() && + Var->isUsableInConstantExpressions(SemaRef.Context) && + Var->getAnyInitializer(DefVD) && DefVD->checkInitIsICE()) + SemaRef.MaybeODRUseExprs.insert(E); + else + MarkVarDeclODRUsed(SemaRef, Var, Loc); +} + +/// \brief Mark a variable referenced, and check whether it is odr-used +/// (C++ [basic.def.odr]p2, C99 6.9p3). Note that this should not be +/// used directly for normal expressions referring to VarDecl. +void Sema::MarkVariableReferenced(SourceLocation Loc, VarDecl *Var) { + DoMarkVarDeclReferenced(*this, Loc, Var, 0); +} + +static void MarkExprReferenced(Sema &SemaRef, SourceLocation Loc, + Decl *D, Expr *E) { + if (VarDecl *Var = dyn_cast(D)) { + DoMarkVarDeclReferenced(SemaRef, Loc, Var, E); + return; + } + + SemaRef.MarkAnyDeclReferenced(Loc, D); +} + +/// \brief Perform reference-marking and odr-use handling for a DeclRefExpr. +void Sema::MarkDeclRefReferenced(DeclRefExpr *E) { + MarkExprReferenced(*this, E->getLocation(), E->getDecl(), E); +} + +/// \brief Perform reference-marking and odr-use handling for a MemberExpr. +void Sema::MarkMemberReferenced(MemberExpr *E) { + MarkExprReferenced(*this, E->getMemberLoc(), E->getMemberDecl(), E); +} + +/// \brief Perform marking for a reference to an arbitrary declaration. It +/// marks the declaration referenced, and performs odr-use checking for functions +/// and variables. This method should not be used when building an normal +/// expression which refers to a variable. +void Sema::MarkAnyDeclReferenced(SourceLocation Loc, Decl *D) { + if (VarDecl *VD = dyn_cast(D)) + MarkVariableReferenced(Loc, VD); + else if (FunctionDecl *FD = dyn_cast(D)) + MarkFunctionReferenced(Loc, FD); + else + D->setReferenced(); +} + +namespace { + // Mark all of the declarations referenced + // FIXME: Not fully implemented yet! We need to have a better understanding + // of when we're entering + class MarkReferencedDecls : public RecursiveASTVisitor { + Sema &S; + SourceLocation Loc; + + public: + typedef RecursiveASTVisitor Inherited; + + MarkReferencedDecls(Sema &S, SourceLocation Loc) : S(S), Loc(Loc) { } + + bool TraverseTemplateArgument(const TemplateArgument &Arg); + bool TraverseRecordType(RecordType *T); + }; +} + +bool MarkReferencedDecls::TraverseTemplateArgument( + const TemplateArgument &Arg) { + if (Arg.getKind() == TemplateArgument::Declaration) { + if (Decl *D = Arg.getAsDecl()) + S.MarkAnyDeclReferenced(Loc, D); + } + + return Inherited::TraverseTemplateArgument(Arg); +} + +bool MarkReferencedDecls::TraverseRecordType(RecordType *T) { + if (ClassTemplateSpecializationDecl *Spec + = dyn_cast(T->getDecl())) { + const TemplateArgumentList &Args = Spec->getTemplateArgs(); + return TraverseTemplateArguments(Args.data(), Args.size()); + } + + return true; +} + +void Sema::MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T) { + MarkReferencedDecls Marker(*this, Loc); + Marker.TraverseType(Context.getCanonicalType(T)); +} + +namespace { + /// \brief Helper class that marks all of the declarations referenced by + /// potentially-evaluated subexpressions as "referenced". + class EvaluatedExprMarker : public EvaluatedExprVisitor { + Sema &S; + bool SkipLocalVariables; + + public: + typedef EvaluatedExprVisitor Inherited; + + EvaluatedExprMarker(Sema &S, bool SkipLocalVariables) + : Inherited(S.Context), S(S), SkipLocalVariables(SkipLocalVariables) { } + + void VisitDeclRefExpr(DeclRefExpr *E) { + // If we were asked not to visit local variables, don't. + if (SkipLocalVariables) { + if (VarDecl *VD = dyn_cast(E->getDecl())) + if (VD->hasLocalStorage()) + return; + } + + S.MarkDeclRefReferenced(E); + } + + void VisitMemberExpr(MemberExpr *E) { + S.MarkMemberReferenced(E); + Inherited::VisitMemberExpr(E); + } + + void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { + S.MarkFunctionReferenced(E->getLocStart(), + const_cast(E->getTemporary()->getDestructor())); + Visit(E->getSubExpr()); + } + + void VisitCXXNewExpr(CXXNewExpr *E) { + if (E->getOperatorNew()) + S.MarkFunctionReferenced(E->getLocStart(), E->getOperatorNew()); + if (E->getOperatorDelete()) + S.MarkFunctionReferenced(E->getLocStart(), E->getOperatorDelete()); + Inherited::VisitCXXNewExpr(E); + } + + void VisitCXXDeleteExpr(CXXDeleteExpr *E) { + if (E->getOperatorDelete()) + S.MarkFunctionReferenced(E->getLocStart(), E->getOperatorDelete()); + QualType Destroyed = S.Context.getBaseElementType(E->getDestroyedType()); + if (const RecordType *DestroyedRec = Destroyed->getAs()) { + CXXRecordDecl *Record = cast(DestroyedRec->getDecl()); + S.MarkFunctionReferenced(E->getLocStart(), + S.LookupDestructor(Record)); + } + + Inherited::VisitCXXDeleteExpr(E); + } + + void VisitCXXConstructExpr(CXXConstructExpr *E) { + S.MarkFunctionReferenced(E->getLocStart(), E->getConstructor()); + Inherited::VisitCXXConstructExpr(E); + } + + void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { + Visit(E->getExpr()); + } + + void VisitImplicitCastExpr(ImplicitCastExpr *E) { + Inherited::VisitImplicitCastExpr(E); + + if (E->getCastKind() == CK_LValueToRValue) + S.UpdateMarkingForLValueToRValue(E->getSubExpr()); + } + }; +} + +/// \brief Mark any declarations that appear within this expression or any +/// potentially-evaluated subexpressions as "referenced". +/// +/// \param SkipLocalVariables If true, don't mark local variables as +/// 'referenced'. +void Sema::MarkDeclarationsReferencedInExpr(Expr *E, + bool SkipLocalVariables) { + EvaluatedExprMarker(*this, SkipLocalVariables).Visit(E); +} + +/// \brief Emit a diagnostic that describes an effect on the run-time behavior +/// of the program being compiled. +/// +/// This routine emits the given diagnostic when the code currently being +/// type-checked is "potentially evaluated", meaning that there is a +/// possibility that the code will actually be executable. Code in sizeof() +/// expressions, code used only during overload resolution, etc., are not +/// potentially evaluated. This routine will suppress such diagnostics or, +/// in the absolutely nutty case of potentially potentially evaluated +/// expressions (C++ typeid), queue the diagnostic to potentially emit it +/// later. +/// +/// This routine should be used for all diagnostics that describe the run-time +/// behavior of a program, such as passing a non-POD value through an ellipsis. +/// Failure to do so will likely result in spurious diagnostics or failures +/// during overload resolution or within sizeof/alignof/typeof/typeid. +bool Sema::DiagRuntimeBehavior(SourceLocation Loc, const Stmt *Statement, + const PartialDiagnostic &PD) { + switch (ExprEvalContexts.back().Context) { + case Unevaluated: + // The argument will never be evaluated, so don't complain. + break; + + case ConstantEvaluated: + // Relevant diagnostics should be produced by constant evaluation. + break; + + case PotentiallyEvaluated: + case PotentiallyEvaluatedIfUsed: + if (Statement && getCurFunctionOrMethodDecl()) { + FunctionScopes.back()->PossiblyUnreachableDiags. + push_back(sema::PossiblyUnreachableDiag(PD, Loc, Statement)); + } + else + Diag(Loc, PD); + + return true; + } + + return false; +} + +bool Sema::CheckCallReturnType(QualType ReturnType, SourceLocation Loc, + CallExpr *CE, FunctionDecl *FD) { + if (ReturnType->isVoidType() || !ReturnType->isIncompleteType()) + return false; + + // If we're inside a decltype's expression, don't check for a valid return + // type or construct temporaries until we know whether this is the last call. + if (ExprEvalContexts.back().IsDecltype) { + ExprEvalContexts.back().DelayedDecltypeCalls.push_back(CE); + return false; + } + + PartialDiagnostic Note = + FD ? PDiag(diag::note_function_with_incomplete_return_type_declared_here) + << FD->getDeclName() : PDiag(); + SourceLocation NoteLoc = FD ? FD->getLocation() : SourceLocation(); + + if (RequireCompleteType(Loc, ReturnType, + FD ? + PDiag(diag::err_call_function_incomplete_return) + << CE->getSourceRange() << FD->getDeclName() : + PDiag(diag::err_call_incomplete_return) + << CE->getSourceRange(), + std::make_pair(NoteLoc, Note))) + return true; + + return false; +} + +// Diagnose the s/=/==/ and s/\|=/!=/ typos. Note that adding parentheses +// will prevent this condition from triggering, which is what we want. +void Sema::DiagnoseAssignmentAsCondition(Expr *E) { + SourceLocation Loc; + + unsigned diagnostic = diag::warn_condition_is_assignment; + bool IsOrAssign = false; + + if (BinaryOperator *Op = dyn_cast(E)) { + if (Op->getOpcode() != BO_Assign && Op->getOpcode() != BO_OrAssign) + return; + + IsOrAssign = Op->getOpcode() == BO_OrAssign; + + // Greylist some idioms by putting them into a warning subcategory. + if (ObjCMessageExpr *ME + = dyn_cast(Op->getRHS()->IgnoreParenCasts())) { + Selector Sel = ME->getSelector(); + + // self = [ init...] + if (isSelfExpr(Op->getLHS()) && Sel.getNameForSlot(0).startswith("init")) + diagnostic = diag::warn_condition_is_idiomatic_assignment; + + // = [ nextObject] + else if (Sel.isUnarySelector() && Sel.getNameForSlot(0) == "nextObject") + diagnostic = diag::warn_condition_is_idiomatic_assignment; + } + + Loc = Op->getOperatorLoc(); + } else if (CXXOperatorCallExpr *Op = dyn_cast(E)) { + if (Op->getOperator() != OO_Equal && Op->getOperator() != OO_PipeEqual) + return; + + IsOrAssign = Op->getOperator() == OO_PipeEqual; + Loc = Op->getOperatorLoc(); + } else { + // Not an assignment. + return; + } + + Diag(Loc, diagnostic) << E->getSourceRange(); + + SourceLocation Open = E->getLocStart(); + SourceLocation Close = PP.getLocForEndOfToken(E->getSourceRange().getEnd()); + Diag(Loc, diag::note_condition_assign_silence) + << FixItHint::CreateInsertion(Open, "(") + << FixItHint::CreateInsertion(Close, ")"); + + if (IsOrAssign) + Diag(Loc, diag::note_condition_or_assign_to_comparison) + << FixItHint::CreateReplacement(Loc, "!="); + else + Diag(Loc, diag::note_condition_assign_to_comparison) + << FixItHint::CreateReplacement(Loc, "=="); +} + +/// \brief Redundant parentheses over an equality comparison can indicate +/// that the user intended an assignment used as condition. +void Sema::DiagnoseEqualityWithExtraParens(ParenExpr *ParenE) { + // Don't warn if the parens came from a macro. + SourceLocation parenLoc = ParenE->getLocStart(); + if (parenLoc.isInvalid() || parenLoc.isMacroID()) + return; + // Don't warn for dependent expressions. + if (ParenE->isTypeDependent()) + return; + + Expr *E = ParenE->IgnoreParens(); + + if (BinaryOperator *opE = dyn_cast(E)) + if (opE->getOpcode() == BO_EQ && + opE->getLHS()->IgnoreParenImpCasts()->isModifiableLvalue(Context) + == Expr::MLV_Valid) { + SourceLocation Loc = opE->getOperatorLoc(); + + Diag(Loc, diag::warn_equality_with_extra_parens) << E->getSourceRange(); + SourceRange ParenERange = ParenE->getSourceRange(); + Diag(Loc, diag::note_equality_comparison_silence) + << FixItHint::CreateRemoval(ParenERange.getBegin()) + << FixItHint::CreateRemoval(ParenERange.getEnd()); + Diag(Loc, diag::note_equality_comparison_to_assign) + << FixItHint::CreateReplacement(Loc, "="); + } +} + +ExprResult Sema::CheckBooleanCondition(Expr *E, SourceLocation Loc) { + DiagnoseAssignmentAsCondition(E); + if (ParenExpr *parenE = dyn_cast(E)) + DiagnoseEqualityWithExtraParens(parenE); + + ExprResult result = CheckPlaceholderExpr(E); + if (result.isInvalid()) return ExprError(); + E = result.take(); + + if (!E->isTypeDependent()) { + if (getLangOpts().CPlusPlus) + return CheckCXXBooleanCondition(E); // C++ 6.4p4 + + ExprResult ERes = DefaultFunctionArrayLvalueConversion(E); + if (ERes.isInvalid()) + return ExprError(); + E = ERes.take(); + + QualType T = E->getType(); + if (!T->isScalarType()) { // C99 6.8.4.1p1 + Diag(Loc, diag::err_typecheck_statement_requires_scalar) + << T << E->getSourceRange(); + return ExprError(); + } + } + + return Owned(E); +} + +ExprResult Sema::ActOnBooleanCondition(Scope *S, SourceLocation Loc, + Expr *SubExpr) { + if (!SubExpr) + return ExprError(); + + return CheckBooleanCondition(SubExpr, Loc); +} + +namespace { + /// A visitor for rebuilding a call to an __unknown_any expression + /// to have an appropriate type. + struct RebuildUnknownAnyFunction + : StmtVisitor { + + Sema &S; + + RebuildUnknownAnyFunction(Sema &S) : S(S) {} + + ExprResult VisitStmt(Stmt *S) { + llvm_unreachable("unexpected statement!"); + } + + ExprResult VisitExpr(Expr *E) { + S.Diag(E->getExprLoc(), diag::err_unsupported_unknown_any_call) + << E->getSourceRange(); + return ExprError(); + } + + /// Rebuild an expression which simply semantically wraps another + /// expression which it shares the type and value kind of. + template ExprResult rebuildSugarExpr(T *E) { + ExprResult SubResult = Visit(E->getSubExpr()); + if (SubResult.isInvalid()) return ExprError(); + + Expr *SubExpr = SubResult.take(); + E->setSubExpr(SubExpr); + E->setType(SubExpr->getType()); + E->setValueKind(SubExpr->getValueKind()); + assert(E->getObjectKind() == OK_Ordinary); + return E; + } + + ExprResult VisitParenExpr(ParenExpr *E) { + return rebuildSugarExpr(E); + } + + ExprResult VisitUnaryExtension(UnaryOperator *E) { + return rebuildSugarExpr(E); + } + + ExprResult VisitUnaryAddrOf(UnaryOperator *E) { + ExprResult SubResult = Visit(E->getSubExpr()); + if (SubResult.isInvalid()) return ExprError(); + + Expr *SubExpr = SubResult.take(); + E->setSubExpr(SubExpr); + E->setType(S.Context.getPointerType(SubExpr->getType())); + assert(E->getValueKind() == VK_RValue); + assert(E->getObjectKind() == OK_Ordinary); + return E; + } + + ExprResult resolveDecl(Expr *E, ValueDecl *VD) { + if (!isa(VD)) return VisitExpr(E); + + E->setType(VD->getType()); + + assert(E->getValueKind() == VK_RValue); + if (S.getLangOpts().CPlusPlus && + !(isa(VD) && + cast(VD)->isInstance())) + E->setValueKind(VK_LValue); + + return E; + } + + ExprResult VisitMemberExpr(MemberExpr *E) { + return resolveDecl(E, E->getMemberDecl()); + } + + ExprResult VisitDeclRefExpr(DeclRefExpr *E) { + return resolveDecl(E, E->getDecl()); + } + }; +} + +/// Given a function expression of unknown-any type, try to rebuild it +/// to have a function type. +static ExprResult rebuildUnknownAnyFunction(Sema &S, Expr *FunctionExpr) { + ExprResult Result = RebuildUnknownAnyFunction(S).Visit(FunctionExpr); + if (Result.isInvalid()) return ExprError(); + return S.DefaultFunctionArrayConversion(Result.take()); +} + +namespace { + /// A visitor for rebuilding an expression of type __unknown_anytype + /// into one which resolves the type directly on the referring + /// expression. Strict preservation of the original source + /// structure is not a goal. + struct RebuildUnknownAnyExpr + : StmtVisitor { + + Sema &S; + + /// The current destination type. + QualType DestType; + + RebuildUnknownAnyExpr(Sema &S, QualType CastType) + : S(S), DestType(CastType) {} + + ExprResult VisitStmt(Stmt *S) { + llvm_unreachable("unexpected statement!"); + } + + ExprResult VisitExpr(Expr *E) { + S.Diag(E->getExprLoc(), diag::err_unsupported_unknown_any_expr) + << E->getSourceRange(); + return ExprError(); + } + + ExprResult VisitCallExpr(CallExpr *E); + ExprResult VisitObjCMessageExpr(ObjCMessageExpr *E); + + /// Rebuild an expression which simply semantically wraps another + /// expression which it shares the type and value kind of. + template ExprResult rebuildSugarExpr(T *E) { + ExprResult SubResult = Visit(E->getSubExpr()); + if (SubResult.isInvalid()) return ExprError(); + Expr *SubExpr = SubResult.take(); + E->setSubExpr(SubExpr); + E->setType(SubExpr->getType()); + E->setValueKind(SubExpr->getValueKind()); + assert(E->getObjectKind() == OK_Ordinary); + return E; + } + + ExprResult VisitParenExpr(ParenExpr *E) { + return rebuildSugarExpr(E); + } + + ExprResult VisitUnaryExtension(UnaryOperator *E) { + return rebuildSugarExpr(E); + } + + ExprResult VisitUnaryAddrOf(UnaryOperator *E) { + const PointerType *Ptr = DestType->getAs(); + if (!Ptr) { + S.Diag(E->getOperatorLoc(), diag::err_unknown_any_addrof) + << E->getSourceRange(); + return ExprError(); + } + assert(E->getValueKind() == VK_RValue); + assert(E->getObjectKind() == OK_Ordinary); + E->setType(DestType); + + // Build the sub-expression as if it were an object of the pointee type. + DestType = Ptr->getPointeeType(); + ExprResult SubResult = Visit(E->getSubExpr()); + if (SubResult.isInvalid()) return ExprError(); + E->setSubExpr(SubResult.take()); + return E; + } + + ExprResult VisitImplicitCastExpr(ImplicitCastExpr *E); + + ExprResult resolveDecl(Expr *E, ValueDecl *VD); + + ExprResult VisitMemberExpr(MemberExpr *E) { + return resolveDecl(E, E->getMemberDecl()); + } + + ExprResult VisitDeclRefExpr(DeclRefExpr *E) { + return resolveDecl(E, E->getDecl()); + } + }; +} + +/// Rebuilds a call expression which yielded __unknown_anytype. +ExprResult RebuildUnknownAnyExpr::VisitCallExpr(CallExpr *E) { + Expr *CalleeExpr = E->getCallee(); + + enum FnKind { + FK_MemberFunction, + FK_FunctionPointer, + FK_BlockPointer + }; + + FnKind Kind; + QualType CalleeType = CalleeExpr->getType(); + if (CalleeType == S.Context.BoundMemberTy) { + assert(isa(E) || isa(E)); + Kind = FK_MemberFunction; + CalleeType = Expr::findBoundMemberType(CalleeExpr); + } else if (const PointerType *Ptr = CalleeType->getAs()) { + CalleeType = Ptr->getPointeeType(); + Kind = FK_FunctionPointer; + } else { + CalleeType = CalleeType->castAs()->getPointeeType(); + Kind = FK_BlockPointer; + } + const FunctionType *FnType = CalleeType->castAs(); + + // Verify that this is a legal result type of a function. + if (DestType->isArrayType() || DestType->isFunctionType()) { + unsigned diagID = diag::err_func_returning_array_function; + if (Kind == FK_BlockPointer) + diagID = diag::err_block_returning_array_function; + + S.Diag(E->getExprLoc(), diagID) + << DestType->isFunctionType() << DestType; + return ExprError(); + } + + // Otherwise, go ahead and set DestType as the call's result. + E->setType(DestType.getNonLValueExprType(S.Context)); + E->setValueKind(Expr::getValueKindForType(DestType)); + assert(E->getObjectKind() == OK_Ordinary); + + // Rebuild the function type, replacing the result type with DestType. + if (const FunctionProtoType *Proto = dyn_cast(FnType)) + DestType = S.Context.getFunctionType(DestType, + Proto->arg_type_begin(), + Proto->getNumArgs(), + Proto->getExtProtoInfo()); + else + DestType = S.Context.getFunctionNoProtoType(DestType, + FnType->getExtInfo()); + + // Rebuild the appropriate pointer-to-function type. + switch (Kind) { + case FK_MemberFunction: + // Nothing to do. + break; + + case FK_FunctionPointer: + DestType = S.Context.getPointerType(DestType); + break; + + case FK_BlockPointer: + DestType = S.Context.getBlockPointerType(DestType); + break; + } + + // Finally, we can recurse. + ExprResult CalleeResult = Visit(CalleeExpr); + if (!CalleeResult.isUsable()) return ExprError(); + E->setCallee(CalleeResult.take()); + + // Bind a temporary if necessary. + return S.MaybeBindToTemporary(E); +} + +ExprResult RebuildUnknownAnyExpr::VisitObjCMessageExpr(ObjCMessageExpr *E) { + // Verify that this is a legal result type of a call. + if (DestType->isArrayType() || DestType->isFunctionType()) { + S.Diag(E->getExprLoc(), diag::err_func_returning_array_function) + << DestType->isFunctionType() << DestType; + return ExprError(); + } + + // Rewrite the method result type if available. + if (ObjCMethodDecl *Method = E->getMethodDecl()) { + assert(Method->getResultType() == S.Context.UnknownAnyTy); + Method->setResultType(DestType); + } + + // Change the type of the message. + E->setType(DestType.getNonReferenceType()); + E->setValueKind(Expr::getValueKindForType(DestType)); + + return S.MaybeBindToTemporary(E); +} + +ExprResult RebuildUnknownAnyExpr::VisitImplicitCastExpr(ImplicitCastExpr *E) { + // The only case we should ever see here is a function-to-pointer decay. + if (E->getCastKind() == CK_FunctionToPointerDecay) { + assert(E->getValueKind() == VK_RValue); + assert(E->getObjectKind() == OK_Ordinary); + + E->setType(DestType); + + // Rebuild the sub-expression as the pointee (function) type. + DestType = DestType->castAs()->getPointeeType(); + + ExprResult Result = Visit(E->getSubExpr()); + if (!Result.isUsable()) return ExprError(); + + E->setSubExpr(Result.take()); + return S.Owned(E); + } else if (E->getCastKind() == CK_LValueToRValue) { + assert(E->getValueKind() == VK_RValue); + assert(E->getObjectKind() == OK_Ordinary); + + assert(isa(E->getType())); + + E->setType(DestType); + + // The sub-expression has to be a lvalue reference, so rebuild it as such. + DestType = S.Context.getLValueReferenceType(DestType); + + ExprResult Result = Visit(E->getSubExpr()); + if (!Result.isUsable()) return ExprError(); + + E->setSubExpr(Result.take()); + return S.Owned(E); + } else { + llvm_unreachable("Unhandled cast type!"); + } +} + +ExprResult RebuildUnknownAnyExpr::resolveDecl(Expr *E, ValueDecl *VD) { + ExprValueKind ValueKind = VK_LValue; + QualType Type = DestType; + + // We know how to make this work for certain kinds of decls: + + // - functions + if (FunctionDecl *FD = dyn_cast(VD)) { + if (const PointerType *Ptr = Type->getAs()) { + DestType = Ptr->getPointeeType(); + ExprResult Result = resolveDecl(E, VD); + if (Result.isInvalid()) return ExprError(); + return S.ImpCastExprToType(Result.take(), Type, + CK_FunctionToPointerDecay, VK_RValue); + } + + if (!Type->isFunctionType()) { + S.Diag(E->getExprLoc(), diag::err_unknown_any_function) + << VD << E->getSourceRange(); + return ExprError(); + } + + if (CXXMethodDecl *MD = dyn_cast(FD)) + if (MD->isInstance()) { + ValueKind = VK_RValue; + Type = S.Context.BoundMemberTy; + } + + // Function references aren't l-values in C. + if (!S.getLangOpts().CPlusPlus) + ValueKind = VK_RValue; + + // - variables + } else if (isa(VD)) { + if (const ReferenceType *RefTy = Type->getAs()) { + Type = RefTy->getPointeeType(); + } else if (Type->isFunctionType()) { + S.Diag(E->getExprLoc(), diag::err_unknown_any_var_function_type) + << VD << E->getSourceRange(); + return ExprError(); + } + + // - nothing else + } else { + S.Diag(E->getExprLoc(), diag::err_unsupported_unknown_any_decl) + << VD << E->getSourceRange(); + return ExprError(); + } + + VD->setType(DestType); + E->setType(Type); + E->setValueKind(ValueKind); + return S.Owned(E); +} + +/// Check a cast of an unknown-any type. We intentionally only +/// trigger this for C-style casts. +ExprResult Sema::checkUnknownAnyCast(SourceRange TypeRange, QualType CastType, + Expr *CastExpr, CastKind &CastKind, + ExprValueKind &VK, CXXCastPath &Path) { + // Rewrite the casted expression from scratch. + ExprResult result = RebuildUnknownAnyExpr(*this, CastType).Visit(CastExpr); + if (!result.isUsable()) return ExprError(); + + CastExpr = result.take(); + VK = CastExpr->getValueKind(); + CastKind = CK_NoOp; + + return CastExpr; +} + +ExprResult Sema::forceUnknownAnyToType(Expr *E, QualType ToType) { + return RebuildUnknownAnyExpr(*this, ToType).Visit(E); +} + +static ExprResult diagnoseUnknownAnyExpr(Sema &S, Expr *E) { + Expr *orig = E; + unsigned diagID = diag::err_uncasted_use_of_unknown_any; + while (true) { + E = E->IgnoreParenImpCasts(); + if (CallExpr *call = dyn_cast(E)) { + E = call->getCallee(); + diagID = diag::err_uncasted_call_of_unknown_any; + } else { + break; + } + } + + SourceLocation loc; + NamedDecl *d; + if (DeclRefExpr *ref = dyn_cast(E)) { + loc = ref->getLocation(); + d = ref->getDecl(); + } else if (MemberExpr *mem = dyn_cast(E)) { + loc = mem->getMemberLoc(); + d = mem->getMemberDecl(); + } else if (ObjCMessageExpr *msg = dyn_cast(E)) { + diagID = diag::err_uncasted_call_of_unknown_any; + loc = msg->getSelectorStartLoc(); + d = msg->getMethodDecl(); + if (!d) { + S.Diag(loc, diag::err_uncasted_send_to_unknown_any_method) + << static_cast(msg->isClassMessage()) << msg->getSelector() + << orig->getSourceRange(); + return ExprError(); + } + } else { + S.Diag(E->getExprLoc(), diag::err_unsupported_unknown_any_expr) + << E->getSourceRange(); + return ExprError(); + } + + S.Diag(loc, diagID) << d << orig->getSourceRange(); + + // Never recoverable. + return ExprError(); +} + +/// Check for operands with placeholder types and complain if found. +/// Returns true if there was an error and no recovery was possible. +ExprResult Sema::CheckPlaceholderExpr(Expr *E) { + const BuiltinType *placeholderType = E->getType()->getAsPlaceholderType(); + if (!placeholderType) return Owned(E); + + switch (placeholderType->getKind()) { + + // Overloaded expressions. + case BuiltinType::Overload: { + // Try to resolve a single function template specialization. + // This is obligatory. + ExprResult result = Owned(E); + if (ResolveAndFixSingleFunctionTemplateSpecialization(result, false)) { + return result; + + // If that failed, try to recover with a call. + } else { + tryToRecoverWithCall(result, PDiag(diag::err_ovl_unresolvable), + /*complain*/ true); + return result; + } + } + + // Bound member functions. + case BuiltinType::BoundMember: { + ExprResult result = Owned(E); + tryToRecoverWithCall(result, PDiag(diag::err_bound_member_function), + /*complain*/ true); + return result; + } + + // ARC unbridged casts. + case BuiltinType::ARCUnbridgedCast: { + Expr *realCast = stripARCUnbridgedCast(E); + diagnoseARCUnbridgedCast(realCast); + return Owned(realCast); + } + + // Expressions of unknown type. + case BuiltinType::UnknownAny: + return diagnoseUnknownAnyExpr(*this, E); + + // Pseudo-objects. + case BuiltinType::PseudoObject: + return checkPseudoObjectRValue(E); + + // Everything else should be impossible. +#define BUILTIN_TYPE(Id, SingletonId) \ + case BuiltinType::Id: +#define PLACEHOLDER_TYPE(Id, SingletonId) +#include "clang/AST/BuiltinTypes.def" + break; + } + + llvm_unreachable("invalid placeholder type!"); +} + +bool Sema::CheckCaseExpression(Expr *E) { + if (E->isTypeDependent()) + return true; + if (E->isValueDependent() || E->isIntegerConstantExpr(Context)) + return E->getType()->isIntegralOrEnumerationType(); + return false; +} + +/// ActOnObjCBoolLiteral - Parse {__objc_yes,__objc_no} literals. +ExprResult +Sema::ActOnObjCBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind) { + assert((Kind == tok::kw___objc_yes || Kind == tok::kw___objc_no) && + "Unknown Objective-C Boolean value!"); + return Owned(new (Context) ObjCBoolLiteralExpr(Kind == tok::kw___objc_yes, + Context.ObjCBuiltinBoolTy, OpLoc)); +} diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp new file mode 100644 index 0000000..af86cb2 --- /dev/null +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -0,0 +1,5362 @@ +//===--- SemaExprCXX.cpp - Semantic Analysis for Expressions --------------===// +// +// 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 C++ expressions. +// +//===----------------------------------------------------------------------===// + +#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/ScopeInfo.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/TemplateDeduction.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/CharUnits.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 "TypeLocBuilder.h" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/ErrorHandling.h" +using namespace clang; +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 + // wording is rather unclear about which scopes we search for the + // destructor name; see core issues 399 and 555. Issue 399 in + // particular shows where the current description of destructor name + // lookup is completely out of line with existing practice, e.g., + // this appears to be ill-formed: + // + // namespace N { + // template struct S { + // ~S(); + // }; + // } + // + // void f(N::S* s) { + // s->N::S::~S(); + // } + // + // See also PR6358 and PR6359. + // For this reason, we're currently only doing the C++03 version of this + // code; the C++0x version has to wait until we get a proper spec. + QualType SearchType; + DeclContext *LookupCtx = 0; + bool isDependent = false; + bool LookInScope = false; + + // If we have an object type, it's because we are in a + // pseudo-destructor-expression or a member access expression, and + // we know what type we're looking for. + if (ObjectTypePtr) + SearchType = GetTypeFromParser(ObjectTypePtr); + + if (SS.isSet()) { + NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep(); + + bool AlreadySearched = false; + bool LookAtPrefix = true; + // C++ [basic.lookup.qual]p6: + // If a pseudo-destructor-name (5.2.4) contains a nested-name-specifier, + // the type-names are looked up as types in the scope designated by the + // nested-name-specifier. In a qualified-id of the form: + // + // ::[opt] nested-name-specifier ~ class-name + // + // where the nested-name-specifier designates a namespace scope, and in + // a qualified-id of the form: + // + // ::opt nested-name-specifier class-name :: ~ class-name + // + // the class-names are looked up as types in the scope designated by + // the nested-name-specifier. + // + // Here, we check the first case (completely) and determine whether the + // code below is permitted to look at the prefix of the + // nested-name-specifier. + DeclContext *DC = computeDeclContext(SS, EnteringContext); + if (DC && DC->isFileContext()) { + AlreadySearched = true; + LookupCtx = DC; + isDependent = false; + } else if (DC && isa(DC)) + LookAtPrefix = false; + + // The second case from the C++03 rules quoted further above. + NestedNameSpecifier *Prefix = 0; + if (AlreadySearched) { + // Nothing left to do. + } else if (LookAtPrefix && (Prefix = NNS->getPrefix())) { + CXXScopeSpec PrefixSS; + PrefixSS.Adopt(NestedNameSpecifierLoc(Prefix, SS.location_data())); + LookupCtx = computeDeclContext(PrefixSS, EnteringContext); + isDependent = isDependentScopeSpecifier(PrefixSS); + } else if (ObjectTypePtr) { + LookupCtx = computeDeclContext(SearchType); + isDependent = SearchType->isDependentType(); + } else { + LookupCtx = computeDeclContext(SS, EnteringContext); + isDependent = LookupCtx && LookupCtx->isDependentContext(); + } + + LookInScope = false; + } else if (ObjectTypePtr) { + // C++ [basic.lookup.classref]p3: + // If the unqualified-id is ~type-name, the type-name is looked up + // in the context of the entire postfix-expression. If the type T + // of the object expression is of a class type C, the type-name is + // also looked up in the scope of class C. At least one of the + // lookups shall find a name that refers to (possibly + // cv-qualified) T. + LookupCtx = computeDeclContext(SearchType); + isDependent = SearchType->isDependentType(); + assert((isDependent || !SearchType->isIncompleteType()) && + "Caller should have completed object type"); + + LookInScope = true; + } else { + // Perform lookup into the current scope (only). + LookInScope = true; + } + + TypeDecl *NonMatchingTypeDecl = 0; + LookupResult Found(*this, &II, NameLoc, LookupOrdinaryName); + for (unsigned Step = 0; Step != 2; ++Step) { + // Look for the name first in the computed lookup context (if we + // have one) and, if that fails to find a match, in the scope (if + // we're allowed to look there). + Found.clear(); + if (Step == 0 && LookupCtx) + LookupQualifiedName(Found, LookupCtx); + else if (Step == 1 && LookInScope && S) + LookupName(Found, S); + else + continue; + + // FIXME: Should we be suppressing ambiguities here? + if (Found.isAmbiguous()) + return ParsedType(); + + if (TypeDecl *Type = Found.getAsSingle()) { + QualType T = Context.getTypeDeclType(Type); + + if (SearchType.isNull() || SearchType->isDependentType() || + Context.hasSameUnqualifiedType(T, SearchType)) { + // We found our type! + + return ParsedType::make(T); + } + + if (!SearchType.isNull()) + NonMatchingTypeDecl = Type; + } + + // If the name that we found is a class template name, and it is + // the same name as the template name in the last part of the + // nested-name-specifier (if present) or the object type, then + // this is the destructor for that class. + // FIXME: This is a workaround until we get real drafting for core + // issue 399, for which there isn't even an obvious direction. + if (ClassTemplateDecl *Template = Found.getAsSingle()) { + QualType MemberOfType; + if (SS.isSet()) { + if (DeclContext *Ctx = computeDeclContext(SS, EnteringContext)) { + // Figure out the type of the context, if it has one. + if (CXXRecordDecl *Record = dyn_cast(Ctx)) + MemberOfType = Context.getTypeDeclType(Record); + } + } + if (MemberOfType.isNull()) + MemberOfType = SearchType; + + if (MemberOfType.isNull()) + continue; + + // We're referring into a class template specialization. If the + // class template we found is the same as the template being + // specialized, we found what we are looking for. + if (const RecordType *Record = MemberOfType->getAs()) { + if (ClassTemplateSpecializationDecl *Spec + = dyn_cast(Record->getDecl())) { + if (Spec->getSpecializedTemplate()->getCanonicalDecl() == + Template->getCanonicalDecl()) + return ParsedType::make(MemberOfType); + } + + continue; + } + + // We're referring to an unresolved class template + // specialization. Determine whether we class template we found + // is the same as the template being specialized or, if we don't + // know which template is being specialized, that it at least + // has the same name. + if (const TemplateSpecializationType *SpecType + = MemberOfType->getAs()) { + TemplateName SpecName = SpecType->getTemplateName(); + + // The class template we found is the same template being + // specialized. + if (TemplateDecl *SpecTemplate = SpecName.getAsTemplateDecl()) { + if (SpecTemplate->getCanonicalDecl() == Template->getCanonicalDecl()) + return ParsedType::make(MemberOfType); + + continue; + } + + // The class template we found has the same name as the + // (dependent) template name being specialized. + if (DependentTemplateName *DepTemplate + = SpecName.getAsDependentTemplateName()) { + if (DepTemplate->isIdentifier() && + DepTemplate->getIdentifier() == Template->getIdentifier()) + return ParsedType::make(MemberOfType); + + continue; + } + } + } + } + + if (isDependent) { + // We didn't find our type, but that's okay: it's dependent + // anyway. + + // FIXME: What if we have no nested-name-specifier? + QualType T = CheckTypenameType(ETK_None, SourceLocation(), + SS.getWithLocInContext(Context), + II, NameLoc); + return ParsedType::make(T); + } + + if (NonMatchingTypeDecl) { + QualType T = Context.getTypeDeclType(NonMatchingTypeDecl); + Diag(NameLoc, diag::err_destructor_expr_type_mismatch) + << T << SearchType; + Diag(NonMatchingTypeDecl->getLocation(), diag::note_destructor_type_here) + << T; + } else if (ObjectTypePtr) + Diag(NameLoc, diag::err_ident_in_dtor_not_a_type) + << &II; + else + Diag(NameLoc, diag::err_destructor_class_name); + + return ParsedType(); +} + +ParsedType Sema::getDestructorType(const DeclSpec& DS, ParsedType ObjectType) { + if (DS.getTypeSpecType() == DeclSpec::TST_error || !ObjectType) + return ParsedType(); + assert(DS.getTypeSpecType() == DeclSpec::TST_decltype + && "only get destructor types from declspecs"); + QualType T = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc()); + QualType SearchType = GetTypeFromParser(ObjectType); + if (SearchType->isDependentType() || Context.hasSameUnqualifiedType(SearchType, T)) { + return ParsedType::make(T); + } + + Diag(DS.getTypeSpecTypeLoc(), diag::err_destructor_expr_type_mismatch) + << T << SearchType; + return ParsedType(); +} + +/// \brief Build a C++ typeid expression with a type operand. +ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType, + SourceLocation TypeidLoc, + TypeSourceInfo *Operand, + SourceLocation RParenLoc) { + // C++ [expr.typeid]p4: + // The top-level cv-qualifiers of the lvalue expression or the type-id + // that is the operand of typeid are always ignored. + // If the type of the type-id is a class type or a reference to a class + // type, the class shall be completely-defined. + Qualifiers Quals; + QualType T + = Context.getUnqualifiedArrayType(Operand->getType().getNonReferenceType(), + Quals); + if (T->getAs() && + RequireCompleteType(TypeidLoc, T, diag::err_incomplete_typeid)) + return ExprError(); + + return Owned(new (Context) CXXTypeidExpr(TypeInfoType.withConst(), + Operand, + SourceRange(TypeidLoc, RParenLoc))); +} + +/// \brief Build a C++ typeid expression with an expression operand. +ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType, + SourceLocation TypeidLoc, + Expr *E, + SourceLocation RParenLoc) { + if (E && !E->isTypeDependent()) { + if (E->getType()->isPlaceholderType()) { + ExprResult result = CheckPlaceholderExpr(E); + if (result.isInvalid()) return ExprError(); + E = result.take(); + } + + QualType T = E->getType(); + if (const RecordType *RecordT = T->getAs()) { + CXXRecordDecl *RecordD = cast(RecordT->getDecl()); + // C++ [expr.typeid]p3: + // [...] If the type of the expression is a class type, the class + // shall be completely-defined. + if (RequireCompleteType(TypeidLoc, T, diag::err_incomplete_typeid)) + return ExprError(); + + // C++ [expr.typeid]p3: + // 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->Classify(Context).isGLValue()) { + // The subexpression is potentially evaluated; switch the context + // and recheck the subexpression. + ExprResult Result = TranformToPotentiallyEvaluated(E); + if (Result.isInvalid()) return ExprError(); + E = Result.take(); + + // We require a vtable to query the type at run time. + MarkVTableUsed(TypeidLoc, RecordD); + } + } + + // C++ [expr.typeid]p4: + // [...] If the type of the type-id is a reference to a possibly + // cv-qualified type, the result of the typeid expression refers to a + // std::type_info object representing the cv-unqualified referenced + // type. + Qualifiers Quals; + QualType UnqualT = Context.getUnqualifiedArrayType(T, Quals); + if (!Context.hasSameType(T, UnqualT)) { + T = UnqualT; + E = ImpCastExprToType(E, UnqualT, CK_NoOp, E->getValueKind()).take(); + } + } + + return Owned(new (Context) CXXTypeidExpr(TypeInfoType.withConst(), + E, + SourceRange(TypeidLoc, RParenLoc))); +} + +/// ActOnCXXTypeidOfType - Parse typeid( type-id ) or typeid (expression); +ExprResult +Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc, + bool isType, void *TyOrExpr, SourceLocation RParenLoc) { + // Find the std::type_info type. + if (!getStdNamespace()) + return ExprError(Diag(OpLoc, diag::err_need_header_before_typeid)); + + if (!CXXTypeInfoDecl) { + IdentifierInfo *TypeInfoII = &PP.getIdentifierTable().get("type_info"); + LookupResult R(*this, TypeInfoII, SourceLocation(), LookupTagName); + LookupQualifiedName(R, getStdNamespace()); + CXXTypeInfoDecl = R.getAsSingle(); + if (!CXXTypeInfoDecl) + return ExprError(Diag(OpLoc, diag::err_need_header_before_typeid)); + } + + QualType TypeInfoType = Context.getTypeDeclType(CXXTypeInfoDecl); + + if (isType) { + // The operand is a type; handle it as such. + TypeSourceInfo *TInfo = 0; + QualType T = GetTypeFromParser(ParsedType::getFromOpaquePtr(TyOrExpr), + &TInfo); + if (T.isNull()) + return ExprError(); + + if (!TInfo) + TInfo = Context.getTrivialTypeSourceInfo(T, OpLoc); + + return BuildCXXTypeId(TypeInfoType, OpLoc, TInfo, RParenLoc); + } + + // The operand is an expression. + return BuildCXXTypeId(TypeInfoType, OpLoc, (Expr*)TyOrExpr, RParenLoc); +} + +/// Retrieve the UuidAttr associated with QT. +static UuidAttr *GetUuidAttrOfType(QualType QT) { + // Optionally remove one level of pointer, reference or array indirection. + const Type *Ty = QT.getTypePtr();; + if (QT->isPointerType() || QT->isReferenceType()) + Ty = QT->getPointeeType().getTypePtr(); + else if (QT->isArrayType()) + Ty = cast(QT)->getElementType().getTypePtr(); + + // Loop all record redeclaration looking for an uuid attribute. + CXXRecordDecl *RD = Ty->getAsCXXRecordDecl(); + for (CXXRecordDecl::redecl_iterator I = RD->redecls_begin(), + E = RD->redecls_end(); I != E; ++I) { + if (UuidAttr *Uuid = I->getAttr()) + return Uuid; + } + + return 0; +} + +/// \brief Build a Microsoft __uuidof expression with a type operand. +ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType, + SourceLocation TypeidLoc, + TypeSourceInfo *Operand, + SourceLocation RParenLoc) { + if (!Operand->getType()->isDependentType()) { + if (!GetUuidAttrOfType(Operand->getType())) + return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid)); + } + + // FIXME: add __uuidof semantic analysis for type operand. + return Owned(new (Context) CXXUuidofExpr(TypeInfoType.withConst(), + Operand, + SourceRange(TypeidLoc, RParenLoc))); +} + +/// \brief Build a Microsoft __uuidof expression with an expression operand. +ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType, + SourceLocation TypeidLoc, + Expr *E, + SourceLocation RParenLoc) { + if (!E->getType()->isDependentType()) { + if (!GetUuidAttrOfType(E->getType()) && + !E->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) + return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid)); + } + // FIXME: add __uuidof semantic analysis for type operand. + return Owned(new (Context) CXXUuidofExpr(TypeInfoType.withConst(), + E, + SourceRange(TypeidLoc, RParenLoc))); +} + +/// ActOnCXXUuidof - Parse __uuidof( type-id ) or __uuidof (expression); +ExprResult +Sema::ActOnCXXUuidof(SourceLocation OpLoc, SourceLocation LParenLoc, + bool isType, void *TyOrExpr, SourceLocation RParenLoc) { + // If MSVCGuidDecl has not been cached, do the lookup. + if (!MSVCGuidDecl) { + IdentifierInfo *GuidII = &PP.getIdentifierTable().get("_GUID"); + LookupResult R(*this, GuidII, SourceLocation(), LookupTagName); + LookupQualifiedName(R, Context.getTranslationUnitDecl()); + MSVCGuidDecl = R.getAsSingle(); + if (!MSVCGuidDecl) + return ExprError(Diag(OpLoc, diag::err_need_header_before_ms_uuidof)); + } + + QualType GuidType = Context.getTypeDeclType(MSVCGuidDecl); + + if (isType) { + // The operand is a type; handle it as such. + TypeSourceInfo *TInfo = 0; + QualType T = GetTypeFromParser(ParsedType::getFromOpaquePtr(TyOrExpr), + &TInfo); + if (T.isNull()) + return ExprError(); + + if (!TInfo) + TInfo = Context.getTrivialTypeSourceInfo(T, OpLoc); + + return BuildCXXUuidof(GuidType, OpLoc, TInfo, RParenLoc); + } + + // The operand is an expression. + return BuildCXXUuidof(GuidType, OpLoc, (Expr*)TyOrExpr, RParenLoc); +} + +/// ActOnCXXBoolLiteral - Parse {true,false} literals. +ExprResult +Sema::ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind) { + assert((Kind == tok::kw_true || Kind == tok::kw_false) && + "Unknown C++ Boolean value!"); + return Owned(new (Context) CXXBoolLiteralExpr(Kind == tok::kw_true, + Context.BoolTy, OpLoc)); +} + +/// ActOnCXXNullPtrLiteral - Parse 'nullptr'. +ExprResult +Sema::ActOnCXXNullPtrLiteral(SourceLocation Loc) { + return Owned(new (Context) CXXNullPtrLiteralExpr(Context.NullPtrTy, Loc)); +} + +/// ActOnCXXThrow - Parse throw expressions. +ExprResult +Sema::ActOnCXXThrow(Scope *S, SourceLocation OpLoc, Expr *Ex) { + bool IsThrownVarInScope = false; + if (Ex) { + // C++0x [class.copymove]p31: + // When certain criteria are met, an implementation is allowed to omit the + // copy/move construction of a class object [...] + // + // - in a throw-expression, when the operand is the name of a + // non-volatile automatic object (other than a function or catch- + // clause parameter) whose scope does not extend beyond the end of the + // innermost enclosing try-block (if there is one), the copy/move + // operation from the operand to the exception object (15.1) can be + // omitted by constructing the automatic object directly into the + // exception object + if (DeclRefExpr *DRE = dyn_cast(Ex->IgnoreParens())) + if (VarDecl *Var = dyn_cast(DRE->getDecl())) { + if (Var->hasLocalStorage() && !Var->getType().isVolatileQualified()) { + for( ; S; S = S->getParent()) { + if (S->isDeclScope(Var)) { + IsThrownVarInScope = true; + break; + } + + if (S->getFlags() & + (Scope::FnScope | Scope::ClassScope | Scope::BlockScope | + Scope::FunctionPrototypeScope | Scope::ObjCMethodScope | + Scope::TryScope)) + break; + } + } + } + } + + return BuildCXXThrow(OpLoc, Ex, IsThrownVarInScope); +} + +ExprResult Sema::BuildCXXThrow(SourceLocation OpLoc, Expr *Ex, + bool IsThrownVarInScope) { + // Don't report an error if 'throw' is used in system headers. + if (!getLangOpts().CXXExceptions && + !getSourceManager().isInSystemHeader(OpLoc)) + Diag(OpLoc, diag::err_exceptions_disabled) << "throw"; + + if (Ex && !Ex->isTypeDependent()) { + ExprResult ExRes = CheckCXXThrowOperand(OpLoc, Ex, IsThrownVarInScope); + if (ExRes.isInvalid()) + return ExprError(); + Ex = ExRes.take(); + } + + return Owned(new (Context) CXXThrowExpr(Ex, Context.VoidTy, OpLoc, + IsThrownVarInScope)); +} + +/// CheckCXXThrowOperand - Validate the operand of a throw. +ExprResult Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *E, + bool IsThrownVarInScope) { + // C++ [except.throw]p3: + // A throw-expression initializes a temporary object, called the exception + // object, the type of which is determined by removing any top-level + // cv-qualifiers from the static type of the operand of throw and adjusting + // the type from "array of T" or "function returning T" to "pointer to T" + // or "pointer to function returning T", [...] + if (E->getType().hasQualifiers()) + E = ImpCastExprToType(E, E->getType().getUnqualifiedType(), CK_NoOp, + E->getValueKind()).take(); + + ExprResult Res = DefaultFunctionArrayConversion(E); + if (Res.isInvalid()) + return ExprError(); + E = Res.take(); + + // If the type of the exception would be an incomplete type or a pointer + // to an incomplete type other than (cv) void the program is ill-formed. + QualType Ty = E->getType(); + bool isPointer = false; + if (const PointerType* Ptr = Ty->getAs()) { + Ty = Ptr->getPointeeType(); + isPointer = true; + } + if (!isPointer || !Ty->isVoidType()) { + if (RequireCompleteType(ThrowLoc, Ty, + PDiag(isPointer ? diag::err_throw_incomplete_ptr + : diag::err_throw_incomplete) + << E->getSourceRange())) + return ExprError(); + + if (RequireNonAbstractType(ThrowLoc, E->getType(), + PDiag(diag::err_throw_abstract_type) + << E->getSourceRange())) + return ExprError(); + } + + // Initialize the exception result. This implicitly weeds out + // abstract types or types with inaccessible copy constructors. + + // C++0x [class.copymove]p31: + // When certain criteria are met, an implementation is allowed to omit the + // copy/move construction of a class object [...] + // + // - in a throw-expression, when the operand is the name of a + // non-volatile automatic object (other than a function or catch-clause + // parameter) whose scope does not extend beyond the end of the + // innermost enclosing try-block (if there is one), the copy/move + // operation from the operand to the exception object (15.1) can be + // omitted by constructing the automatic object directly into the + // exception object + const VarDecl *NRVOVariable = 0; + if (IsThrownVarInScope) + NRVOVariable = getCopyElisionCandidate(QualType(), E, false); + + InitializedEntity Entity = + InitializedEntity::InitializeException(ThrowLoc, E->getType(), + /*NRVO=*/NRVOVariable != 0); + Res = PerformMoveOrCopyInitialization(Entity, NRVOVariable, + QualType(), E, + IsThrownVarInScope); + if (Res.isInvalid()) + return ExprError(); + E = Res.take(); + + // If the exception has class type, we need additional handling. + const RecordType *RecordTy = Ty->getAs(); + if (!RecordTy) + return Owned(E); + CXXRecordDecl *RD = cast(RecordTy->getDecl()); + + // If we are throwing a polymorphic class type or pointer thereof, + // exception handling will make use of the vtable. + MarkVTableUsed(ThrowLoc, RD); + + // If a pointer is thrown, the referenced object will not be destroyed. + if (isPointer) + return Owned(E); + + // If the class has a destructor, we must be able to call it. + if (RD->hasIrrelevantDestructor()) + return Owned(E); + + CXXDestructorDecl *Destructor = LookupDestructor(RD); + if (!Destructor) + return Owned(E); + + MarkFunctionReferenced(E->getExprLoc(), Destructor); + CheckDestructorAccess(E->getExprLoc(), Destructor, + PDiag(diag::err_access_dtor_exception) << Ty); + DiagnoseUseOfDecl(Destructor, E->getExprLoc()); + return Owned(E); +} + +QualType Sema::getCurrentThisType() { + DeclContext *DC = getFunctionLevelDeclContext(); + QualType ThisTy = CXXThisTypeOverride; + if (CXXMethodDecl *method = dyn_cast(DC)) { + if (method && method->isInstance()) + ThisTy = method->getThisType(Context); + } + + return ThisTy; +} + +Sema::CXXThisScopeRAII::CXXThisScopeRAII(Sema &S, + Decl *ContextDecl, + unsigned CXXThisTypeQuals, + bool Enabled) + : S(S), OldCXXThisTypeOverride(S.CXXThisTypeOverride), Enabled(false) +{ + if (!Enabled || !ContextDecl) + return; + + CXXRecordDecl *Record = 0; + if (ClassTemplateDecl *Template = dyn_cast(ContextDecl)) + Record = Template->getTemplatedDecl(); + else + Record = cast(ContextDecl); + + S.CXXThisTypeOverride + = S.Context.getPointerType( + S.Context.getRecordType(Record).withCVRQualifiers(CXXThisTypeQuals)); + + this->Enabled = true; +} + + +Sema::CXXThisScopeRAII::~CXXThisScopeRAII() { + if (Enabled) { + S.CXXThisTypeOverride = OldCXXThisTypeOverride; + } +} + +void Sema::CheckCXXThisCapture(SourceLocation Loc, bool Explicit) { + // We don't need to capture this in an unevaluated context. + if (ExprEvalContexts.back().Context == Unevaluated && !Explicit) + return; + + // Otherwise, check that we can capture 'this'. + unsigned NumClosures = 0; + for (unsigned idx = FunctionScopes.size() - 1; idx != 0; idx--) { + if (CapturingScopeInfo *CSI = + dyn_cast(FunctionScopes[idx])) { + if (CSI->CXXThisCaptureIndex != 0) { + // 'this' is already being captured; there isn't anything more to do. + break; + } + + if (CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_LambdaByref || + CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_LambdaByval || + CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_Block || + Explicit) { + // This closure can capture 'this'; continue looking upwards. + NumClosures++; + Explicit = false; + continue; + } + // This context can't implicitly capture 'this'; fail out. + Diag(Loc, diag::err_this_capture) << Explicit; + return; + } + break; + } + + // Mark that we're implicitly capturing 'this' in all the scopes we skipped. + // FIXME: We need to delay this marking in PotentiallyPotentiallyEvaluated + // contexts. + for (unsigned idx = FunctionScopes.size() - 1; + NumClosures; --idx, --NumClosures) { + CapturingScopeInfo *CSI = cast(FunctionScopes[idx]); + Expr *ThisExpr = 0; + QualType ThisTy = getCurrentThisType(); + if (LambdaScopeInfo *LSI = dyn_cast(CSI)) { + // For lambda expressions, build a field and an initializing expression. + CXXRecordDecl *Lambda = LSI->Lambda; + FieldDecl *Field + = FieldDecl::Create(Context, Lambda, Loc, Loc, 0, ThisTy, + Context.getTrivialTypeSourceInfo(ThisTy, Loc), + 0, false, false); + Field->setImplicit(true); + Field->setAccess(AS_private); + Lambda->addDecl(Field); + ThisExpr = new (Context) CXXThisExpr(Loc, ThisTy, /*isImplicit=*/true); + } + bool isNested = NumClosures > 1; + CSI->addThisCapture(isNested, Loc, ThisTy, ThisExpr); + } +} + +ExprResult Sema::ActOnCXXThis(SourceLocation Loc) { + /// 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. + + QualType ThisTy = getCurrentThisType(); + if (ThisTy.isNull()) return Diag(Loc, diag::err_invalid_this_use); + + CheckCXXThisCapture(Loc); + return Owned(new (Context) CXXThisExpr(Loc, ThisTy, /*isImplicit=*/false)); +} + +bool Sema::isThisOutsideMemberFunctionBody(QualType BaseType) { + // If we're outside the body of a member function, then we'll have a specified + // type for 'this'. + if (CXXThisTypeOverride.isNull()) + return false; + + // Determine whether we're looking into a class that's currently being + // defined. + CXXRecordDecl *Class = BaseType->getAsCXXRecordDecl(); + return Class && Class->isBeingDefined(); +} + +ExprResult +Sema::ActOnCXXTypeConstructExpr(ParsedType TypeRep, + SourceLocation LParenLoc, + MultiExprArg exprs, + SourceLocation RParenLoc) { + if (!TypeRep) + return ExprError(); + + TypeSourceInfo *TInfo; + QualType Ty = GetTypeFromParser(TypeRep, &TInfo); + if (!TInfo) + TInfo = Context.getTrivialTypeSourceInfo(Ty, SourceLocation()); + + return BuildCXXTypeConstructExpr(TInfo, LParenLoc, exprs, RParenLoc); +} + +/// ActOnCXXTypeConstructExpr - Parse construction of a specified type. +/// Can be interpreted either as function-style casting ("int(x)") +/// or class type construction ("ClassType(x,y,z)") +/// or creation of a value-initialized type ("int()"). +ExprResult +Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, + SourceLocation LParenLoc, + MultiExprArg exprs, + SourceLocation RParenLoc) { + QualType Ty = TInfo->getType(); + unsigned NumExprs = exprs.size(); + Expr **Exprs = (Expr**)exprs.get(); + SourceLocation TyBeginLoc = TInfo->getTypeLoc().getBeginLoc(); + + if (Ty->isDependentType() || + CallExpr::hasAnyTypeDependentArguments( + llvm::makeArrayRef(Exprs, NumExprs))) { + exprs.release(); + + return Owned(CXXUnresolvedConstructExpr::Create(Context, TInfo, + LParenLoc, + Exprs, NumExprs, + RParenLoc)); + } + + bool ListInitialization = LParenLoc.isInvalid(); + assert((!ListInitialization || (NumExprs == 1 && isa(Exprs[0]))) + && "List initialization must have initializer list as expression."); + SourceRange FullRange = SourceRange(TyBeginLoc, + ListInitialization ? Exprs[0]->getSourceRange().getEnd() : RParenLoc); + + // C++ [expr.type.conv]p1: + // If the expression list is a single expression, the type conversion + // expression is equivalent (in definedness, and if defined in meaning) to the + // corresponding cast expression. + if (NumExprs == 1 && !ListInitialization) { + Expr *Arg = Exprs[0]; + exprs.release(); + return BuildCXXFunctionalCastExpr(TInfo, LParenLoc, Arg, RParenLoc); + } + + QualType ElemTy = Ty; + if (Ty->isArrayType()) { + if (!ListInitialization) + return ExprError(Diag(TyBeginLoc, + diag::err_value_init_for_array_type) << FullRange); + ElemTy = Context.getBaseElementType(Ty); + } + + if (!Ty->isVoidType() && + RequireCompleteType(TyBeginLoc, ElemTy, + PDiag(diag::err_invalid_incomplete_type_use) + << FullRange)) + return ExprError(); + + if (RequireNonAbstractType(TyBeginLoc, Ty, + diag::err_allocation_of_abstract_type)) + return ExprError(); + + InitializedEntity Entity = InitializedEntity::InitializeTemporary(TInfo); + InitializationKind Kind + = NumExprs ? ListInitialization + ? InitializationKind::CreateDirectList(TyBeginLoc) + : InitializationKind::CreateDirect(TyBeginLoc, + LParenLoc, RParenLoc) + : InitializationKind::CreateValue(TyBeginLoc, + LParenLoc, RParenLoc); + InitializationSequence InitSeq(*this, Entity, Kind, Exprs, NumExprs); + ExprResult Result = InitSeq.Perform(*this, Entity, Kind, move(exprs)); + + if (!Result.isInvalid() && ListInitialization && + isa(Result.get())) { + // If the list-initialization doesn't involve a constructor call, we'll get + // the initializer-list (with corrected type) back, but that's not what we + // want, since it will be treated as an initializer list in further + // processing. Explicitly insert a cast here. + InitListExpr *List = cast(Result.take()); + Result = Owned(CXXFunctionalCastExpr::Create(Context, List->getType(), + Expr::getValueKindForType(TInfo->getType()), + TInfo, TyBeginLoc, CK_NoOp, + List, /*Path=*/0, RParenLoc)); + } + + // FIXME: Improve AST representation? + return move(Result); +} + +/// doesUsualArrayDeleteWantSize - Answers whether the usual +/// operator delete[] for the given type has a size_t parameter. +static bool doesUsualArrayDeleteWantSize(Sema &S, SourceLocation loc, + QualType allocType) { + const RecordType *record = + allocType->getBaseElementTypeUnsafe()->getAs(); + if (!record) return false; + + // Try to find an operator delete[] in class scope. + + DeclarationName deleteName = + S.Context.DeclarationNames.getCXXOperatorName(OO_Array_Delete); + LookupResult ops(S, deleteName, loc, Sema::LookupOrdinaryName); + S.LookupQualifiedName(ops, record->getDecl()); + + // We're just doing this for information. + ops.suppressDiagnostics(); + + // Very likely: there's no operator delete[]. + if (ops.empty()) return false; + + // If it's ambiguous, it should be illegal to call operator delete[] + // on this thing, so it doesn't matter if we allocate extra space or not. + if (ops.isAmbiguous()) return false; + + LookupResult::Filter filter = ops.makeFilter(); + while (filter.hasNext()) { + NamedDecl *del = filter.next()->getUnderlyingDecl(); + + // C++0x [basic.stc.dynamic.deallocation]p2: + // A template instance is never a usual deallocation function, + // regardless of its signature. + if (isa(del)) { + filter.erase(); + continue; + } + + // C++0x [basic.stc.dynamic.deallocation]p2: + // If class T does not declare [an operator delete[] with one + // parameter] but does declare a member deallocation function + // named operator delete[] with exactly two parameters, the + // second of which has type std::size_t, then this function + // is a usual deallocation function. + if (!cast(del)->isUsualDeallocationFunction()) { + filter.erase(); + continue; + } + } + filter.done(); + + if (!ops.isSingleResult()) return false; + + const FunctionDecl *del = cast(ops.getFoundDecl()); + return (del->getNumParams() == 2); +} + +/// \brief Parsed a C++ 'new' expression (C++ 5.3.4). + +/// E.g.: +/// @code new (memory) int[size][4] @endcode +/// or +/// @code ::new Foo(23, "hello") @endcode +/// +/// \param StartLoc The first location of the expression. +/// \param UseGlobal True if 'new' was prefixed with '::'. +/// \param PlacementLParen Opening paren of the placement arguments. +/// \param PlacementArgs Placement new arguments. +/// \param PlacementRParen Closing paren of the placement arguments. +/// \param TypeIdParens If the type is in parens, the source range. +/// \param D The type to be allocated, as well as array dimensions. +/// \param ConstructorLParen Opening paren of the constructor args, empty if +/// initializer-list syntax is used. +/// \param ConstructorArgs Constructor/initialization arguments. +/// \param ConstructorRParen Closing paren of the constructor args. +ExprResult +Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, + SourceLocation PlacementLParen, MultiExprArg PlacementArgs, + SourceLocation PlacementRParen, SourceRange TypeIdParens, + Declarator &D, Expr *Initializer) { + bool TypeContainsAuto = D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto; + + Expr *ArraySize = 0; + // If the specified type is an array, unwrap it and save the expression. + if (D.getNumTypeObjects() > 0 && + D.getTypeObject(0).Kind == DeclaratorChunk::Array) { + DeclaratorChunk &Chunk = D.getTypeObject(0); + if (TypeContainsAuto) + return ExprError(Diag(Chunk.Loc, diag::err_new_array_of_auto) + << D.getSourceRange()); + if (Chunk.Arr.hasStatic) + return ExprError(Diag(Chunk.Loc, diag::err_static_illegal_in_new) + << D.getSourceRange()); + if (!Chunk.Arr.NumElts) + return ExprError(Diag(Chunk.Loc, diag::err_array_new_needs_size) + << D.getSourceRange()); + + ArraySize = static_cast(Chunk.Arr.NumElts); + D.DropFirstTypeObject(); + } + + // Every dimension shall be of constant size. + if (ArraySize) { + for (unsigned I = 0, N = D.getNumTypeObjects(); I < N; ++I) { + if (D.getTypeObject(I).Kind != DeclaratorChunk::Array) + break; + + DeclaratorChunk::ArrayTypeInfo &Array = D.getTypeObject(I).Arr; + if (Expr *NumElts = (Expr *)Array.NumElts) { + if (!NumElts->isTypeDependent() && !NumElts->isValueDependent()) { + Array.NumElts = VerifyIntegerConstantExpression(NumElts, 0, + PDiag(diag::err_new_array_nonconst)).take(); + if (!Array.NumElts) + return ExprError(); + } + } + } + } + + TypeSourceInfo *TInfo = GetTypeForDeclarator(D, /*Scope=*/0); + QualType AllocType = TInfo->getType(); + if (D.isInvalidType()) + return ExprError(); + + SourceRange DirectInitRange; + if (ParenListExpr *List = dyn_cast_or_null(Initializer)) + DirectInitRange = List->getSourceRange(); + + return BuildCXXNew(StartLoc, UseGlobal, + PlacementLParen, + move(PlacementArgs), + PlacementRParen, + TypeIdParens, + AllocType, + TInfo, + ArraySize, + DirectInitRange, + Initializer, + TypeContainsAuto); +} + +static bool isLegalArrayNewInitializer(CXXNewExpr::InitializationStyle Style, + Expr *Init) { + if (!Init) + return true; + if (ParenListExpr *PLE = dyn_cast(Init)) + return PLE->getNumExprs() == 0; + if (isa(Init)) + return true; + else if (CXXConstructExpr *CCE = dyn_cast(Init)) + return !CCE->isListInitialization() && + CCE->getConstructor()->isDefaultConstructor(); + else if (Style == CXXNewExpr::ListInit) { + assert(isa(Init) && + "Shouldn't create list CXXConstructExprs for arrays."); + return true; + } + return false; +} + +ExprResult +Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, + SourceLocation PlacementLParen, + MultiExprArg PlacementArgs, + SourceLocation PlacementRParen, + SourceRange TypeIdParens, + QualType AllocType, + TypeSourceInfo *AllocTypeInfo, + Expr *ArraySize, + SourceRange DirectInitRange, + Expr *Initializer, + bool TypeMayContainAuto) { + SourceRange TypeRange = AllocTypeInfo->getTypeLoc().getSourceRange(); + + CXXNewExpr::InitializationStyle initStyle; + if (DirectInitRange.isValid()) { + assert(Initializer && "Have parens but no initializer."); + initStyle = CXXNewExpr::CallInit; + } else if (Initializer && isa(Initializer)) + initStyle = CXXNewExpr::ListInit; + else { + // In template instantiation, the initializer could be a CXXDefaultArgExpr + // unwrapped from a CXXConstructExpr that was implicitly built. There is no + // particularly sane way we can handle this (especially since it can even + // occur for array new), so we throw the initializer away and have it be + // rebuilt. + if (Initializer && isa(Initializer)) + Initializer = 0; + assert((!Initializer || isa(Initializer) || + isa(Initializer)) && + "Initializer expression that cannot have been implicitly created."); + initStyle = CXXNewExpr::NoInit; + } + + Expr **Inits = &Initializer; + unsigned NumInits = Initializer ? 1 : 0; + if (initStyle == CXXNewExpr::CallInit) { + if (ParenListExpr *List = dyn_cast(Initializer)) { + Inits = List->getExprs(); + NumInits = List->getNumExprs(); + } else if (CXXConstructExpr *CCE = dyn_cast(Initializer)){ + if (!isa(CCE)) { + // Can happen in template instantiation. Since this is just an implicit + // construction, we just take it apart and rebuild it. + Inits = CCE->getArgs(); + NumInits = CCE->getNumArgs(); + } + } + } + + // C++0x [decl.spec.auto]p6. Deduce the type which 'auto' stands in for. + if (TypeMayContainAuto && AllocType->getContainedAutoType()) { + if (initStyle == CXXNewExpr::NoInit || NumInits == 0) + return ExprError(Diag(StartLoc, diag::err_auto_new_requires_ctor_arg) + << AllocType << TypeRange); + if (initStyle == CXXNewExpr::ListInit) + return ExprError(Diag(Inits[0]->getLocStart(), + diag::err_auto_new_requires_parens) + << AllocType << TypeRange); + if (NumInits > 1) { + Expr *FirstBad = Inits[1]; + return ExprError(Diag(FirstBad->getLocStart(), + diag::err_auto_new_ctor_multiple_expressions) + << AllocType << TypeRange); + } + Expr *Deduce = Inits[0]; + TypeSourceInfo *DeducedType = 0; + if (DeduceAutoType(AllocTypeInfo, Deduce, DeducedType) == + DAR_Failed) + return ExprError(Diag(StartLoc, diag::err_auto_new_deduction_failure) + << AllocType << Deduce->getType() + << TypeRange << Deduce->getSourceRange()); + if (!DeducedType) + return ExprError(); + + AllocTypeInfo = DeducedType; + AllocType = AllocTypeInfo->getType(); + } + + // Per C++0x [expr.new]p5, the type being constructed may be a + // typedef of an array type. + if (!ArraySize) { + if (const ConstantArrayType *Array + = Context.getAsConstantArrayType(AllocType)) { + ArraySize = IntegerLiteral::Create(Context, Array->getSize(), + Context.getSizeType(), + TypeRange.getEnd()); + AllocType = Array->getElementType(); + } + } + + if (CheckAllocatedType(AllocType, TypeRange.getBegin(), TypeRange)) + return ExprError(); + + if (initStyle == CXXNewExpr::ListInit && isStdInitializerList(AllocType, 0)) { + Diag(AllocTypeInfo->getTypeLoc().getBeginLoc(), + diag::warn_dangling_std_initializer_list) + << /*at end of FE*/0 << Inits[0]->getSourceRange(); + } + + // In ARC, infer 'retaining' for the allocated + if (getLangOpts().ObjCAutoRefCount && + AllocType.getObjCLifetime() == Qualifiers::OCL_None && + AllocType->isObjCLifetimeType()) { + AllocType = Context.getLifetimeQualifiedType(AllocType, + AllocType->getObjCARCImplicitLifetime()); + } + + QualType ResultType = Context.getPointerType(AllocType); + + // C++98 5.3.4p6: "The expression in a direct-new-declarator shall have + // integral or enumeration type with a non-negative value." + // C++11 [expr.new]p6: The expression [...] shall be of integral or unscoped + // enumeration type, or a class type for which a single non-explicit + // conversion function to integral or unscoped enumeration type exists. + if (ArraySize && !ArraySize->isTypeDependent()) { + ExprResult ConvertedSize = ConvertToIntegralOrEnumerationType( + StartLoc, ArraySize, + PDiag(diag::err_array_size_not_integral) << getLangOpts().CPlusPlus0x, + PDiag(diag::err_array_size_incomplete_type) + << ArraySize->getSourceRange(), + PDiag(diag::err_array_size_explicit_conversion), + PDiag(diag::note_array_size_conversion), + PDiag(diag::err_array_size_ambiguous_conversion), + PDiag(diag::note_array_size_conversion), + PDiag(getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_array_size_conversion : + diag::ext_array_size_conversion), + /*AllowScopedEnumerations*/ false); + if (ConvertedSize.isInvalid()) + return ExprError(); + + ArraySize = ConvertedSize.take(); + QualType SizeType = ArraySize->getType(); + if (!SizeType->isIntegralOrUnscopedEnumerationType()) + return ExprError(); + + // C++98 [expr.new]p7: + // The expression in a direct-new-declarator shall have integral type + // with a non-negative value. + // + // Let's see if this is a constant < 0. If so, we reject it out of + // hand. Otherwise, if it's not a constant, we must have an unparenthesized + // array type. + // + // Note: such a construct has well-defined semantics in C++11: it throws + // std::bad_array_new_length. + if (!ArraySize->isValueDependent()) { + llvm::APSInt Value; + // We've already performed any required implicit conversion to integer or + // unscoped enumeration type. + if (ArraySize->isIntegerConstantExpr(Value, Context)) { + if (Value < llvm::APSInt( + llvm::APInt::getNullValue(Value.getBitWidth()), + Value.isUnsigned())) { + if (getLangOpts().CPlusPlus0x) + Diag(ArraySize->getLocStart(), + diag::warn_typecheck_negative_array_new_size) + << ArraySize->getSourceRange(); + else + return ExprError(Diag(ArraySize->getLocStart(), + diag::err_typecheck_negative_array_size) + << ArraySize->getSourceRange()); + } else if (!AllocType->isDependentType()) { + unsigned ActiveSizeBits = + ConstantArrayType::getNumAddressingBits(Context, AllocType, Value); + if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) { + if (getLangOpts().CPlusPlus0x) + Diag(ArraySize->getLocStart(), + diag::warn_array_new_too_large) + << Value.toString(10) + << ArraySize->getSourceRange(); + else + return ExprError(Diag(ArraySize->getLocStart(), + diag::err_array_too_large) + << Value.toString(10) + << ArraySize->getSourceRange()); + } + } + } 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) + << ArraySize->getSourceRange() + << FixItHint::CreateRemoval(TypeIdParens.getBegin()) + << FixItHint::CreateRemoval(TypeIdParens.getEnd()); + + TypeIdParens = SourceRange(); + } + } + + // ARC: warn about ABI issues. + if (getLangOpts().ObjCAutoRefCount) { + QualType BaseAllocType = Context.getBaseElementType(AllocType); + if (BaseAllocType.hasStrongOrWeakObjCLifetime()) + Diag(StartLoc, diag::warn_err_new_delete_object_array) + << 0 << BaseAllocType; + } + + // Note that we do *not* convert the argument in any way. It can + // be signed, larger than size_t, whatever. + } + + FunctionDecl *OperatorNew = 0; + FunctionDecl *OperatorDelete = 0; + Expr **PlaceArgs = (Expr**)PlacementArgs.get(); + unsigned NumPlaceArgs = PlacementArgs.size(); + + if (!AllocType->isDependentType() && + !Expr::hasAnyTypeDependentArguments( + llvm::makeArrayRef(PlaceArgs, NumPlaceArgs)) && + FindAllocationFunctions(StartLoc, + SourceRange(PlacementLParen, PlacementRParen), + UseGlobal, AllocType, ArraySize, PlaceArgs, + NumPlaceArgs, OperatorNew, OperatorDelete)) + return ExprError(); + + // If this is an array allocation, compute whether the usual array + // deallocation function for the type has a size_t parameter. + bool UsualArrayDeleteWantsSize = false; + if (ArraySize && !AllocType->isDependentType()) + UsualArrayDeleteWantsSize + = doesUsualArrayDeleteWantSize(*this, StartLoc, AllocType); + + SmallVector AllPlaceArgs; + if (OperatorNew) { + // Add default arguments, if any. + const FunctionProtoType *Proto = + OperatorNew->getType()->getAs(); + VariadicCallType CallType = + Proto->isVariadic() ? VariadicFunction : VariadicDoesNotApply; + + if (GatherArgumentsForCall(PlacementLParen, OperatorNew, + Proto, 1, PlaceArgs, NumPlaceArgs, + AllPlaceArgs, CallType)) + return ExprError(); + + NumPlaceArgs = AllPlaceArgs.size(); + if (NumPlaceArgs > 0) + PlaceArgs = &AllPlaceArgs[0]; + + DiagnoseSentinelCalls(OperatorNew, PlacementLParen, + PlaceArgs, NumPlaceArgs); + + // FIXME: Missing call to CheckFunctionCall or equivalent + } + + // Warn if the type is over-aligned and is being allocated by global operator + // new. + if (NumPlaceArgs == 0 && OperatorNew && + (OperatorNew->isImplicit() || + getSourceManager().isInSystemHeader(OperatorNew->getLocStart()))) { + if (unsigned Align = Context.getPreferredTypeAlign(AllocType.getTypePtr())){ + unsigned SuitableAlign = Context.getTargetInfo().getSuitableAlign(); + if (Align > SuitableAlign) + Diag(StartLoc, diag::warn_overaligned_type) + << AllocType + << unsigned(Align / Context.getCharWidth()) + << unsigned(SuitableAlign / Context.getCharWidth()); + } + } + + QualType InitType = AllocType; + // Array 'new' can't have any initializers except empty parentheses. + // Initializer lists are also allowed, in C++11. Rely on the parser for the + // dialect distinction. + if (ResultType->isArrayType() || ArraySize) { + if (!isLegalArrayNewInitializer(initStyle, Initializer)) { + SourceRange InitRange(Inits[0]->getLocStart(), + Inits[NumInits - 1]->getLocEnd()); + Diag(StartLoc, diag::err_new_array_init_args) << InitRange; + return ExprError(); + } + if (InitListExpr *ILE = dyn_cast_or_null(Initializer)) { + // We do the initialization typechecking against the array type + // corresponding to the number of initializers + 1 (to also check + // default-initialization). + unsigned NumElements = ILE->getNumInits() + 1; + InitType = Context.getConstantArrayType(AllocType, + llvm::APInt(Context.getTypeSize(Context.getSizeType()), NumElements), + ArrayType::Normal, 0); + } + } + + if (!AllocType->isDependentType() && + !Expr::hasAnyTypeDependentArguments( + llvm::makeArrayRef(Inits, NumInits))) { + // C++11 [expr.new]p15: + // A new-expression that creates an object of type T initializes that + // object as follows: + InitializationKind Kind + // - If the new-initializer is omitted, the object is default- + // initialized (8.5); if no initialization is performed, + // the object has indeterminate value + = initStyle == CXXNewExpr::NoInit + ? InitializationKind::CreateDefault(TypeRange.getBegin()) + // - Otherwise, the new-initializer is interpreted according to the + // initialization rules of 8.5 for direct-initialization. + : initStyle == CXXNewExpr::ListInit + ? InitializationKind::CreateDirectList(TypeRange.getBegin()) + : InitializationKind::CreateDirect(TypeRange.getBegin(), + DirectInitRange.getBegin(), + DirectInitRange.getEnd()); + + InitializedEntity Entity + = InitializedEntity::InitializeNew(StartLoc, InitType); + InitializationSequence InitSeq(*this, Entity, Kind, Inits, NumInits); + ExprResult FullInit = InitSeq.Perform(*this, Entity, Kind, + MultiExprArg(Inits, NumInits)); + if (FullInit.isInvalid()) + return ExprError(); + + // FullInit is our initializer; strip off CXXBindTemporaryExprs, because + // we don't want the initialized object to be destructed. + if (CXXBindTemporaryExpr *Binder = + dyn_cast_or_null(FullInit.get())) + FullInit = Owned(Binder->getSubExpr()); + + Initializer = FullInit.take(); + } + + // Mark the new and delete operators as referenced. + if (OperatorNew) + MarkFunctionReferenced(StartLoc, OperatorNew); + if (OperatorDelete) + MarkFunctionReferenced(StartLoc, OperatorDelete); + + // C++0x [expr.new]p17: + // If the new expression creates an array of objects of class type, + // access and ambiguity control are done for the destructor. + QualType BaseAllocType = Context.getBaseElementType(AllocType); + if (ArraySize && !BaseAllocType->isDependentType()) { + if (const RecordType *BaseRecordType = BaseAllocType->getAs()) { + if (CXXDestructorDecl *dtor = LookupDestructor( + cast(BaseRecordType->getDecl()))) { + MarkFunctionReferenced(StartLoc, dtor); + CheckDestructorAccess(StartLoc, dtor, + PDiag(diag::err_access_dtor) + << BaseAllocType); + DiagnoseUseOfDecl(dtor, StartLoc); + } + } + } + + PlacementArgs.release(); + + return Owned(new (Context) CXXNewExpr(Context, UseGlobal, OperatorNew, + OperatorDelete, + UsualArrayDeleteWantsSize, + PlaceArgs, NumPlaceArgs, TypeIdParens, + ArraySize, initStyle, Initializer, + ResultType, AllocTypeInfo, + StartLoc, DirectInitRange)); +} + +/// \brief Checks that a type is suitable as the allocated type +/// in a new-expression. +bool Sema::CheckAllocatedType(QualType AllocType, SourceLocation Loc, + SourceRange R) { + // C++ 5.3.4p1: "[The] type shall be a complete object type, but not an + // abstract class type or array thereof. + if (AllocType->isFunctionType()) + return Diag(Loc, diag::err_bad_new_type) + << AllocType << 0 << R; + else if (AllocType->isReferenceType()) + return Diag(Loc, diag::err_bad_new_type) + << AllocType << 1 << R; + else if (!AllocType->isDependentType() && + RequireCompleteType(Loc, AllocType, + PDiag(diag::err_new_incomplete_type) + << R)) + return true; + else if (RequireNonAbstractType(Loc, AllocType, + diag::err_allocation_of_abstract_type)) + return true; + else if (AllocType->isVariablyModifiedType()) + return Diag(Loc, diag::err_variably_modified_new_type) + << AllocType; + else if (unsigned AddressSpace = AllocType.getAddressSpace()) + return Diag(Loc, diag::err_address_space_qualified_new) + << AllocType.getUnqualifiedType() << AddressSpace; + else if (getLangOpts().ObjCAutoRefCount) { + if (const ArrayType *AT = Context.getAsArrayType(AllocType)) { + QualType BaseAllocType = Context.getBaseElementType(AT); + if (BaseAllocType.getObjCLifetime() == Qualifiers::OCL_None && + BaseAllocType->isObjCLifetimeType()) + return Diag(Loc, diag::err_arc_new_array_without_ownership) + << BaseAllocType; + } + } + + return false; +} + +/// \brief Determine whether the given function is a non-placement +/// deallocation function. +static bool isNonPlacementDeallocationFunction(FunctionDecl *FD) { + if (FD->isInvalidDecl()) + return false; + + if (CXXMethodDecl *Method = dyn_cast(FD)) + return Method->isUsualDeallocationFunction(); + + return ((FD->getOverloadedOperator() == OO_Delete || + FD->getOverloadedOperator() == OO_Array_Delete) && + FD->getNumParams() == 1); +} + +/// FindAllocationFunctions - Finds the overloads of operator new and delete +/// that are appropriate for the allocation. +bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, + bool UseGlobal, QualType AllocType, + bool IsArray, Expr **PlaceArgs, + unsigned NumPlaceArgs, + FunctionDecl *&OperatorNew, + FunctionDecl *&OperatorDelete) { + // --- Choosing an allocation function --- + // C++ 5.3.4p8 - 14 & 18 + // 1) If UseGlobal is true, only look in the global scope. Else, also look + // in the scope of the allocated class. + // 2) If an array size is given, look for operator new[], else look for + // operator new. + // 3) The first argument is always size_t. Append the arguments from the + // placement form. + + SmallVector AllocArgs(1 + NumPlaceArgs); + // 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(Context, llvm::APInt::getNullValue( + Context.getTargetInfo().getPointerWidth(0)), + Context.getSizeType(), + SourceLocation()); + AllocArgs[0] = &Size; + std::copy(PlaceArgs, PlaceArgs + NumPlaceArgs, AllocArgs.begin() + 1); + + // C++ [expr.new]p8: + // If the allocated type is a non-array type, the allocation + // function's name is operator new and the deallocation function's + // name is operator delete. If the allocated type is an array + // type, the allocation function's name is operator new[] and the + // deallocation function's name is operator delete[]. + DeclarationName NewName = Context.DeclarationNames.getCXXOperatorName( + IsArray ? OO_Array_New : OO_New); + DeclarationName DeleteName = Context.DeclarationNames.getCXXOperatorName( + IsArray ? OO_Array_Delete : OO_Delete); + + QualType AllocElemType = Context.getBaseElementType(AllocType); + + if (AllocElemType->isRecordType() && !UseGlobal) { + CXXRecordDecl *Record + = cast(AllocElemType->getAs()->getDecl()); + if (FindAllocationOverload(StartLoc, Range, NewName, &AllocArgs[0], + AllocArgs.size(), Record, /*AllowMissing=*/true, + OperatorNew)) + return true; + } + if (!OperatorNew) { + // Didn't find a member overload. Look for a global one. + DeclareGlobalNewDelete(); + DeclContext *TUDecl = Context.getTranslationUnitDecl(); + if (FindAllocationOverload(StartLoc, Range, NewName, &AllocArgs[0], + AllocArgs.size(), TUDecl, /*AllowMissing=*/false, + OperatorNew)) + return true; + } + + // We don't need an operator delete if we're running under + // -fno-exceptions. + if (!getLangOpts().Exceptions) { + OperatorDelete = 0; + return false; + } + + // FindAllocationOverload can change the passed in arguments, so we need to + // copy them back. + if (NumPlaceArgs > 0) + std::copy(&AllocArgs[1], AllocArgs.end(), PlaceArgs); + + // C++ [expr.new]p19: + // + // If the new-expression begins with a unary :: operator, the + // deallocation function's name is looked up in the global + // scope. Otherwise, if the allocated type is a class type T or an + // array thereof, the deallocation function's name is looked up in + // the scope of T. If this lookup fails to find the name, or if + // 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 (AllocElemType->isRecordType() && !UseGlobal) { + CXXRecordDecl *RD + = cast(AllocElemType->getAs()->getDecl()); + LookupQualifiedName(FoundDelete, RD); + } + if (FoundDelete.isAmbiguous()) + return true; // FIXME: clean up expressions? + + if (FoundDelete.empty()) { + DeclareGlobalNewDelete(); + LookupQualifiedName(FoundDelete, Context.getTranslationUnitDecl()); + } + + FoundDelete.suppressDiagnostics(); + + SmallVector, 2> Matches; + + // Whether we're looking for a placement operator delete is dictated + // by whether we selected a placement operator new, not by whether + // we had explicit placement arguments. This matters for things like + // struct A { void *operator new(size_t, int = 0); ... }; + // A *a = new A() + bool isPlacementNew = (NumPlaceArgs > 0 || OperatorNew->param_size() != 1); + + if (isPlacementNew) { + // C++ [expr.new]p20: + // A declaration of a placement deallocation function matches the + // declaration of a placement allocation function if it has the + // same number of parameters and, after parameter transformations + // (8.3.5), all parameter types except the first are + // identical. [...] + // + // To perform this comparison, we compute the function type that + // the deallocation function should have, and use that type both + // for template argument deduction and for comparison purposes. + // + // FIXME: this comparison should ignore CC and the like. + QualType ExpectedFunctionType; + { + const FunctionProtoType *Proto + = OperatorNew->getType()->getAs(); + + SmallVector ArgTypes; + ArgTypes.push_back(Context.VoidPtrTy); + for (unsigned I = 1, N = Proto->getNumArgs(); I < N; ++I) + ArgTypes.push_back(Proto->getArgType(I)); + + FunctionProtoType::ExtProtoInfo EPI; + EPI.Variadic = Proto->isVariadic(); + + ExpectedFunctionType + = Context.getFunctionType(Context.VoidTy, ArgTypes.data(), + ArgTypes.size(), EPI); + } + + for (LookupResult::iterator D = FoundDelete.begin(), + DEnd = FoundDelete.end(); + D != DEnd; ++D) { + FunctionDecl *Fn = 0; + if (FunctionTemplateDecl *FnTmpl + = dyn_cast((*D)->getUnderlyingDecl())) { + // Perform template argument deduction to try to match the + // expected function type. + TemplateDeductionInfo Info(Context, StartLoc); + if (DeduceTemplateArguments(FnTmpl, 0, ExpectedFunctionType, Fn, Info)) + continue; + } else + Fn = cast((*D)->getUnderlyingDecl()); + + if (Context.hasSameType(Fn->getType(), ExpectedFunctionType)) + Matches.push_back(std::make_pair(D.getPair(), Fn)); + } + } else { + // C++ [expr.new]p20: + // [...] Any non-placement deallocation function matches a + // non-placement allocation function. [...] + for (LookupResult::iterator D = FoundDelete.begin(), + DEnd = FoundDelete.end(); + D != DEnd; ++D) { + if (FunctionDecl *Fn = dyn_cast((*D)->getUnderlyingDecl())) + if (isNonPlacementDeallocationFunction(Fn)) + Matches.push_back(std::make_pair(D.getPair(), Fn)); + } + } + + // C++ [expr.new]p20: + // [...] If the lookup finds a single matching deallocation + // function, that function will be called; otherwise, no + // deallocation function will be called. + if (Matches.size() == 1) { + OperatorDelete = Matches[0].second; + + // C++0x [expr.new]p20: + // If the lookup finds the two-parameter form of a usual + // deallocation function (3.7.4.2) and that function, considered + // as a placement deallocation function, would have been + // selected as a match for the allocation function, the program + // is ill-formed. + if (NumPlaceArgs && getLangOpts().CPlusPlus0x && + isNonPlacementDeallocationFunction(OperatorDelete)) { + Diag(StartLoc, diag::err_placement_new_non_placement_delete) + << SourceRange(PlaceArgs[0]->getLocStart(), + PlaceArgs[NumPlaceArgs - 1]->getLocEnd()); + Diag(OperatorDelete->getLocation(), diag::note_previous_decl) + << DeleteName; + } else { + CheckAllocationAccess(StartLoc, Range, FoundDelete.getNamingClass(), + Matches[0].first); + } + } + + return false; +} + +/// FindAllocationOverload - Find an fitting overload for the allocation +/// function in the specified scope. +bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range, + DeclarationName Name, Expr** Args, + unsigned NumArgs, DeclContext *Ctx, + bool AllowMissing, FunctionDecl *&Operator, + bool Diagnose) { + LookupResult R(*this, Name, StartLoc, LookupOrdinaryName); + LookupQualifiedName(R, Ctx); + if (R.empty()) { + if (AllowMissing || !Diagnose) + return false; + return Diag(StartLoc, diag::err_ovl_no_viable_function_in_call) + << Name << Range; + } + + if (R.isAmbiguous()) + return true; + + R.suppressDiagnostics(); + + OverloadCandidateSet Candidates(StartLoc); + for (LookupResult::iterator Alloc = R.begin(), AllocEnd = R.end(); + Alloc != AllocEnd; ++Alloc) { + // Even member operator new/delete are implicitly treated as + // static, so don't use AddMemberCandidate. + NamedDecl *D = (*Alloc)->getUnderlyingDecl(); + + if (FunctionTemplateDecl *FnTemplate = dyn_cast(D)) { + AddTemplateOverloadCandidate(FnTemplate, Alloc.getPair(), + /*ExplicitTemplateArgs=*/0, + llvm::makeArrayRef(Args, NumArgs), + Candidates, + /*SuppressUserConversions=*/false); + continue; + } + + FunctionDecl *Fn = cast(D); + AddOverloadCandidate(Fn, Alloc.getPair(), + llvm::makeArrayRef(Args, NumArgs), Candidates, + /*SuppressUserConversions=*/false); + } + + // Do the resolution. + OverloadCandidateSet::iterator Best; + switch (Candidates.BestViableFunction(*this, StartLoc, Best)) { + case OR_Success: { + // Got one! + FunctionDecl *FnDecl = Best->Function; + MarkFunctionReferenced(StartLoc, FnDecl); + // The first argument is size_t, and the first parameter must be size_t, + // too. This is checked on declaration and can be assumed. (It can't be + // asserted on, though, since invalid decls are left in there.) + // Watch out for variadic allocator function. + unsigned NumArgsInFnDecl = FnDecl->getNumParams(); + for (unsigned i = 0; (i < NumArgs && i < NumArgsInFnDecl); ++i) { + InitializedEntity Entity = InitializedEntity::InitializeParameter(Context, + FnDecl->getParamDecl(i)); + + if (!Diagnose && !CanPerformCopyInitialization(Entity, Owned(Args[i]))) + return true; + + ExprResult Result + = PerformCopyInitialization(Entity, SourceLocation(), Owned(Args[i])); + if (Result.isInvalid()) + return true; + + Args[i] = Result.takeAs(); + } + + Operator = FnDecl; + + if (CheckAllocationAccess(StartLoc, Range, R.getNamingClass(), + Best->FoundDecl, Diagnose) == AR_inaccessible) + return true; + + return false; + } + + case OR_No_Viable_Function: + if (Diagnose) { + Diag(StartLoc, diag::err_ovl_no_viable_function_in_call) + << Name << Range; + Candidates.NoteCandidates(*this, OCD_AllCandidates, + llvm::makeArrayRef(Args, NumArgs)); + } + return true; + + case OR_Ambiguous: + if (Diagnose) { + Diag(StartLoc, diag::err_ovl_ambiguous_call) + << Name << Range; + Candidates.NoteCandidates(*this, OCD_ViableCandidates, + llvm::makeArrayRef(Args, NumArgs)); + } + return true; + + case OR_Deleted: { + if (Diagnose) { + Diag(StartLoc, diag::err_ovl_deleted_call) + << Best->Function->isDeleted() + << Name + << getDeletedOrUnavailableSuffix(Best->Function) + << Range; + Candidates.NoteCandidates(*this, OCD_AllCandidates, + llvm::makeArrayRef(Args, NumArgs)); + } + return true; + } + } + llvm_unreachable("Unreachable, bad result from BestViableFunction"); +} + + +/// DeclareGlobalNewDelete - Declare the global forms of operator new and +/// delete. These are: +/// @code +/// // C++03: +/// void* operator new(std::size_t) throw(std::bad_alloc); +/// void* operator new[](std::size_t) throw(std::bad_alloc); +/// void operator delete(void *) throw(); +/// void operator delete[](void *) throw(); +/// // C++0x: +/// void* operator new(std::size_t); +/// void* operator new[](std::size_t); +/// void operator delete(void *); +/// void operator delete[](void *); +/// @endcode +/// C++0x operator delete is implicitly noexcept. +/// Note that the placement and nothrow forms of new are *not* implicitly +/// declared. Their use requires including \. +void Sema::DeclareGlobalNewDelete() { + if (GlobalNewDeleteDeclared) + return; + + // C++ [basic.std.dynamic]p2: + // [...] The following allocation and deallocation functions (18.4) are + // implicitly declared in global scope in each translation unit of a + // program + // + // C++03: + // void* operator new(std::size_t) throw(std::bad_alloc); + // void* operator new[](std::size_t) throw(std::bad_alloc); + // void operator delete(void*) throw(); + // void operator delete[](void*) throw(); + // C++0x: + // void* operator new(std::size_t); + // void* operator new[](std::size_t); + // void operator delete(void*); + // void operator delete[](void*); + // + // These implicit declarations introduce only the function names operator + // new, operator new[], operator delete, operator delete[]. + // + // Here, we need to refer to std::bad_alloc, so we will implicitly declare + // "std" or "bad_alloc" as necessary to form the exception specification. + // However, we do not make these implicit declarations visible to name + // lookup. + // Note that the C++0x versions of operator delete are deallocation functions, + // and thus are implicitly noexcept. + if (!StdBadAlloc && !getLangOpts().CPlusPlus0x) { + // The "std::bad_alloc" class has not yet been declared, so build it + // implicitly. + StdBadAlloc = CXXRecordDecl::Create(Context, TTK_Class, + getOrCreateStdNamespace(), + SourceLocation(), SourceLocation(), + &PP.getIdentifierTable().get("bad_alloc"), + 0); + getStdBadAlloc()->setImplicit(true); + } + + GlobalNewDeleteDeclared = true; + + QualType VoidPtr = Context.getPointerType(Context.VoidTy); + QualType SizeT = Context.getSizeType(); + bool AssumeSaneOperatorNew = getLangOpts().AssumeSaneOperatorNew; + + DeclareGlobalAllocationFunction( + Context.DeclarationNames.getCXXOperatorName(OO_New), + VoidPtr, SizeT, AssumeSaneOperatorNew); + DeclareGlobalAllocationFunction( + Context.DeclarationNames.getCXXOperatorName(OO_Array_New), + VoidPtr, SizeT, AssumeSaneOperatorNew); + DeclareGlobalAllocationFunction( + Context.DeclarationNames.getCXXOperatorName(OO_Delete), + Context.VoidTy, VoidPtr); + DeclareGlobalAllocationFunction( + Context.DeclarationNames.getCXXOperatorName(OO_Array_Delete), + Context.VoidTy, VoidPtr); +} + +/// DeclareGlobalAllocationFunction - Declares a single implicit global +/// allocation function if it doesn't already exist. +void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, + QualType Return, QualType Argument, + bool AddMallocAttr) { + DeclContext *GlobalCtx = Context.getTranslationUnitDecl(); + + // Check if this function is already declared. + { + DeclContext::lookup_iterator Alloc, AllocEnd; + for (llvm::tie(Alloc, AllocEnd) = GlobalCtx->lookup(Name); + Alloc != AllocEnd; ++Alloc) { + // Only look at non-template functions, as it is the predefined, + // non-templated allocation function we are trying to declare here. + if (FunctionDecl *Func = dyn_cast(*Alloc)) { + QualType InitialParamType = + Context.getCanonicalType( + Func->getParamDecl(0)->getType().getUnqualifiedType()); + // FIXME: Do we need to check for default arguments here? + if (Func->getNumParams() == 1 && InitialParamType == Argument) { + if(AddMallocAttr && !Func->hasAttr()) + Func->addAttr(::new (Context) MallocAttr(SourceLocation(), Context)); + return; + } + } + } + } + + QualType BadAllocType; + bool HasBadAllocExceptionSpec + = (Name.getCXXOverloadedOperator() == OO_New || + Name.getCXXOverloadedOperator() == OO_Array_New); + if (HasBadAllocExceptionSpec && !getLangOpts().CPlusPlus0x) { + assert(StdBadAlloc && "Must have std::bad_alloc declared"); + BadAllocType = Context.getTypeDeclType(getStdBadAlloc()); + } + + FunctionProtoType::ExtProtoInfo EPI; + if (HasBadAllocExceptionSpec) { + if (!getLangOpts().CPlusPlus0x) { + EPI.ExceptionSpecType = EST_Dynamic; + EPI.NumExceptions = 1; + EPI.Exceptions = &BadAllocType; + } + } else { + EPI.ExceptionSpecType = getLangOpts().CPlusPlus0x ? + EST_BasicNoexcept : EST_DynamicNone; + } + + QualType FnType = Context.getFunctionType(Return, &Argument, 1, EPI); + FunctionDecl *Alloc = + FunctionDecl::Create(Context, GlobalCtx, SourceLocation(), + SourceLocation(), Name, + FnType, /*TInfo=*/0, SC_None, + SC_None, false, true); + Alloc->setImplicit(); + + if (AddMallocAttr) + Alloc->addAttr(::new (Context) MallocAttr(SourceLocation(), Context)); + + ParmVarDecl *Param = ParmVarDecl::Create(Context, Alloc, SourceLocation(), + SourceLocation(), 0, + Argument, /*TInfo=*/0, + SC_None, SC_None, 0); + Alloc->setParams(Param); + + // 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. + Context.getTranslationUnitDecl()->addDecl(Alloc); +} + +bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, + DeclarationName Name, + FunctionDecl* &Operator, bool Diagnose) { + LookupResult Found(*this, Name, StartLoc, LookupOrdinaryName); + // Try to find operator delete/operator delete[] in class scope. + LookupQualifiedName(Found, RD); + + if (Found.isAmbiguous()) + return true; + + Found.suppressDiagnostics(); + + SmallVector Matches; + for (LookupResult::iterator F = Found.begin(), FEnd = Found.end(); + F != FEnd; ++F) { + 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()); + + if (Operator->isDeleted()) { + if (Diagnose) { + Diag(StartLoc, diag::err_deleted_function_use); + NoteDeletedFunction(Operator); + } + return true; + } + + if (CheckAllocationAccess(StartLoc, SourceRange(), Found.getNamingClass(), + Matches[0], Diagnose) == AR_inaccessible) + return true; + + return false; + + // We found multiple suitable operators; complain about the ambiguity. + } else if (!Matches.empty()) { + if (Diagnose) { + Diag(StartLoc, diag::err_ambiguous_suitable_delete_member_function_found) + << Name << RD; + + for (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 + // none of them were suitable. + if (!Found.empty()) { + if (Diagnose) { + Diag(StartLoc, diag::err_no_suitable_delete_member_function_found) + << Name << RD; + + for (LookupResult::iterator F = Found.begin(), FEnd = Found.end(); + F != FEnd; ++F) + Diag((*F)->getUnderlyingDecl()->getLocation(), + diag::note_member_declared_here) << Name; + } + return true; + } + + // Look for a global declaration. + DeclareGlobalNewDelete(); + DeclContext *TUDecl = Context.getTranslationUnitDecl(); + + CXXNullPtrLiteralExpr Null(Context.VoidPtrTy, SourceLocation()); + Expr* DeallocArgs[1]; + DeallocArgs[0] = &Null; + if (FindAllocationOverload(StartLoc, SourceRange(), Name, + DeallocArgs, 1, TUDecl, !Diagnose, + Operator, Diagnose)) + return true; + + assert(Operator && "Did not find a deallocation function!"); + return false; +} + +/// ActOnCXXDelete - Parsed a C++ 'delete' expression (C++ 5.3.5), as in: +/// @code ::delete ptr; @endcode +/// or +/// @code delete [] ptr; @endcode +ExprResult +Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, + bool ArrayForm, Expr *ExE) { + // 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. + // + // DR599 amends "pointer type" to "pointer to object type" in both cases. + + ExprResult Ex = Owned(ExE); + FunctionDecl *OperatorDelete = 0; + bool ArrayFormAsWritten = ArrayForm; + bool UsualArrayDeleteWantsSize = false; + + if (!Ex.get()->isTypeDependent()) { + // Perform lvalue-to-rvalue cast, if needed. + Ex = DefaultLvalueConversion(Ex.take()); + + QualType Type = Ex.get()->getType(); + + if (const RecordType *Record = Type->getAs()) { + if (RequireCompleteType(StartLoc, Type, + PDiag(diag::err_delete_incomplete_class_type))) + return ExprError(); + + SmallVector ObjectPtrConversions; + + CXXRecordDecl *RD = cast(Record->getDecl()); + const UnresolvedSetImpl *Conversions = RD->getVisibleConversionFunctions(); + for (UnresolvedSetImpl::iterator I = Conversions->begin(), + E = Conversions->end(); I != E; ++I) { + NamedDecl *D = I.getDecl(); + if (isa(D)) + D = cast(D)->getTargetDecl(); + + // Skip over templated conversion functions; they aren't considered. + if (isa(D)) + continue; + + CXXConversionDecl *Conv = cast(D); + + QualType ConvType = Conv->getConversionType().getNonReferenceType(); + if (const PointerType *ConvPtrType = ConvType->getAs()) + 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. + ExprResult Res = + PerformImplicitConversion(Ex.get(), + ObjectPtrConversions.front()->getConversionType(), + AA_Converting); + if (Res.isUsable()) { + Ex = move(Res); + Type = Ex.get()->getType(); + } + } + else if (ObjectPtrConversions.size() > 1) { + Diag(StartLoc, diag::err_ambiguous_delete_operand) + << Type << Ex.get()->getSourceRange(); + for (unsigned i= 0; i < ObjectPtrConversions.size(); i++) + NoteOverloadCandidate(ObjectPtrConversions[i]); + return ExprError(); + } + } + + if (!Type->isPointerType()) + return ExprError(Diag(StartLoc, diag::err_delete_operand) + << Type << Ex.get()->getSourceRange()); + + QualType Pointee = Type->getAs()->getPointeeType(); + QualType PointeeElem = Context.getBaseElementType(Pointee); + + if (unsigned AddressSpace = Pointee.getAddressSpace()) + return Diag(Ex.get()->getLocStart(), + diag::err_address_space_qualified_delete) + << Pointee.getUnqualifiedType() << AddressSpace; + + CXXRecordDecl *PointeeRD = 0; + if (Pointee->isVoidType() && !isSFINAEContext()) { + // The C++ standard bans deleting a pointer to a non-object type, which + // effectively bans deletion of "void*". However, most compilers support + // this, so we treat it as a warning unless we're in a SFINAE context. + Diag(StartLoc, diag::ext_delete_void_ptr_operand) + << Type << Ex.get()->getSourceRange(); + } else if (Pointee->isFunctionType() || Pointee->isVoidType()) { + return ExprError(Diag(StartLoc, diag::err_delete_operand) + << Type << Ex.get()->getSourceRange()); + } else if (!Pointee->isDependentType()) { + if (!RequireCompleteType(StartLoc, Pointee, + PDiag(diag::warn_delete_incomplete) + << Ex.get()->getSourceRange())) { + if (const RecordType *RT = PointeeElem->getAs()) + PointeeRD = cast(RT->getDecl()); + } + } + + // C++ [expr.delete]p2: + // [Note: a pointer to a const type can be the operand of a + // delete-expression; it is not necessary to cast away the constness + // (5.2.11) of the pointer expression before it is used as the operand + // of the delete-expression. ] + if (!Context.hasSameType(Ex.get()->getType(), Context.VoidPtrTy)) + Ex = Owned(ImplicitCastExpr::Create(Context, Context.VoidPtrTy, + CK_BitCast, Ex.take(), 0, VK_RValue)); + + if (Pointee->isArrayType() && !ArrayForm) { + Diag(StartLoc, diag::warn_delete_array_type) + << Type << Ex.get()->getSourceRange() + << FixItHint::CreateInsertion(PP.getLocForEndOfToken(StartLoc), "[]"); + ArrayForm = true; + } + + DeclarationName DeleteName = Context.DeclarationNames.getCXXOperatorName( + ArrayForm ? OO_Array_Delete : OO_Delete); + + if (PointeeRD) { + if (!UseGlobal && + FindDeallocationFunction(StartLoc, PointeeRD, DeleteName, + OperatorDelete)) + return ExprError(); + + // If we're allocating an array of records, check whether the + // usual operator delete[] has a size_t parameter. + if (ArrayForm) { + // If the user specifically asked to use the global allocator, + // we'll need to do the lookup into the class. + if (UseGlobal) + UsualArrayDeleteWantsSize = + doesUsualArrayDeleteWantSize(*this, StartLoc, PointeeElem); + + // Otherwise, the usual operator delete[] should be the + // function we just found. + else if (isa(OperatorDelete)) + UsualArrayDeleteWantsSize = (OperatorDelete->getNumParams() == 2); + } + + if (!PointeeRD->hasIrrelevantDestructor()) + if (CXXDestructorDecl *Dtor = LookupDestructor(PointeeRD)) { + MarkFunctionReferenced(StartLoc, + const_cast(Dtor)); + DiagnoseUseOfDecl(Dtor, StartLoc); + } + + // C++ [expr.delete]p3: + // In the first alternative (delete object), if the static type of the + // object to be deleted is different from its dynamic type, the static + // type shall be a base class of the dynamic type of the object to be + // deleted and the static type shall have a virtual destructor or the + // behavior is undefined. + // + // Note: a final class cannot be derived from, no issue there + if (PointeeRD->isPolymorphic() && !PointeeRD->hasAttr()) { + CXXDestructorDecl *dtor = PointeeRD->getDestructor(); + if (dtor && !dtor->isVirtual()) { + if (PointeeRD->isAbstract()) { + // If the class is abstract, we warn by default, because we're + // sure the code has undefined behavior. + Diag(StartLoc, diag::warn_delete_abstract_non_virtual_dtor) + << PointeeElem; + } else if (!ArrayForm) { + // Otherwise, if this is not an array delete, it's a bit suspect, + // but not necessarily wrong. + Diag(StartLoc, diag::warn_delete_non_virtual_dtor) << PointeeElem; + } + } + } + + } else if (getLangOpts().ObjCAutoRefCount && + PointeeElem->isObjCLifetimeType() && + (PointeeElem.getObjCLifetime() == Qualifiers::OCL_Strong || + PointeeElem.getObjCLifetime() == Qualifiers::OCL_Weak) && + ArrayForm) { + Diag(StartLoc, diag::warn_err_new_delete_object_array) + << 1 << PointeeElem; + } + + if (!OperatorDelete) { + // Look for a global declaration. + DeclareGlobalNewDelete(); + DeclContext *TUDecl = Context.getTranslationUnitDecl(); + Expr *Arg = Ex.get(); + if (FindAllocationOverload(StartLoc, SourceRange(), DeleteName, + &Arg, 1, TUDecl, /*AllowMissing=*/false, + OperatorDelete)) + return ExprError(); + } + + MarkFunctionReferenced(StartLoc, OperatorDelete); + + // Check access and ambiguity of operator delete and destructor. + if (PointeeRD) { + if (CXXDestructorDecl *Dtor = LookupDestructor(PointeeRD)) { + CheckDestructorAccess(Ex.get()->getExprLoc(), Dtor, + PDiag(diag::err_access_dtor) << PointeeElem); + } + } + + } + + return Owned(new (Context) CXXDeleteExpr(Context.VoidTy, UseGlobal, ArrayForm, + ArrayFormAsWritten, + UsualArrayDeleteWantsSize, + OperatorDelete, Ex.take(), StartLoc)); +} + +/// \brief Check the use of the given variable as a C++ condition in an if, +/// while, do-while, or switch statement. +ExprResult Sema::CheckConditionVariable(VarDecl *ConditionVar, + SourceLocation StmtLoc, + bool ConvertToBoolean) { + QualType T = ConditionVar->getType(); + + // C++ [stmt.select]p2: + // The declarator shall not specify a function or an array. + if (T->isFunctionType()) + return ExprError(Diag(ConditionVar->getLocation(), + diag::err_invalid_use_of_function_type) + << ConditionVar->getSourceRange()); + else if (T->isArrayType()) + return ExprError(Diag(ConditionVar->getLocation(), + diag::err_invalid_use_of_array_type) + << ConditionVar->getSourceRange()); + + ExprResult Condition = + Owned(DeclRefExpr::Create(Context, NestedNameSpecifierLoc(), + SourceLocation(), + ConditionVar, + /*enclosing*/ false, + ConditionVar->getLocation(), + ConditionVar->getType().getNonReferenceType(), + VK_LValue)); + + MarkDeclRefReferenced(cast(Condition.get())); + + if (ConvertToBoolean) { + Condition = CheckBooleanCondition(Condition.take(), StmtLoc); + if (Condition.isInvalid()) + return ExprError(); + } + + return move(Condition); +} + +/// CheckCXXBooleanCondition - Returns true if a conversion to bool is invalid. +ExprResult Sema::CheckCXXBooleanCondition(Expr *CondExpr) { + // C++ 6.4p4: + // The value of a condition that is an initialized declaration in a statement + // other than a switch statement is the value of the declared variable + // implicitly converted to type bool. If that conversion is ill-formed, the + // program is ill-formed. + // The value of a condition that is an expression is the value of the + // expression, implicitly converted to bool. + // + return PerformContextuallyConvertToBool(CondExpr); +} + +/// Helper function to determine whether this is the (deprecated) C++ +/// conversion from a string literal to a pointer to non-const char or +/// non-const wchar_t (for narrow and wide string literals, +/// respectively). +bool +Sema::IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType) { + // Look inside the implicit cast, if it exists. + if (ImplicitCastExpr *Cast = dyn_cast(From)) + From = Cast->getSubExpr(); + + // A string literal (2.13.4) that is not a wide string literal can + // be converted to an rvalue of type "pointer to char"; a wide + // string literal can be converted to an rvalue of type "pointer + // to wchar_t" (C++ 4.2p2). + if (StringLiteral *StrLit = dyn_cast(From->IgnoreParens())) + if (const PointerType *ToPtrType = ToType->getAs()) + if (const BuiltinType *ToPointeeType + = ToPtrType->getPointeeType()->getAs()) { + // This conversion is considered only when there is an + // explicit appropriate pointer target type (C++ 4.2p2). + if (!ToPtrType->getPointeeType().hasQualifiers()) { + switch (StrLit->getKind()) { + case StringLiteral::UTF8: + case StringLiteral::UTF16: + case StringLiteral::UTF32: + // We don't allow UTF literals to be implicitly converted + break; + case StringLiteral::Ascii: + return (ToPointeeType->getKind() == BuiltinType::Char_U || + ToPointeeType->getKind() == BuiltinType::Char_S); + case StringLiteral::Wide: + return ToPointeeType->isWideCharType(); + } + } + } + + return false; +} + +static ExprResult BuildCXXCastArgument(Sema &S, + SourceLocation CastLoc, + QualType Ty, + CastKind Kind, + CXXMethodDecl *Method, + DeclAccessPair FoundDecl, + bool HadMultipleCandidates, + Expr *From) { + switch (Kind) { + default: llvm_unreachable("Unhandled cast kind!"); + case CK_ConstructorConversion: { + CXXConstructorDecl *Constructor = cast(Method); + ASTOwningVector ConstructorArgs(S); + + if (S.CompleteConstructorCall(Constructor, + MultiExprArg(&From, 1), + CastLoc, ConstructorArgs)) + return ExprError(); + + S.CheckConstructorAccess(CastLoc, Constructor, + InitializedEntity::InitializeTemporary(Ty), + Constructor->getAccess()); + + ExprResult Result + = S.BuildCXXConstructExpr(CastLoc, Ty, cast(Method), + move_arg(ConstructorArgs), + HadMultipleCandidates, /*ZeroInit*/ false, + CXXConstructExpr::CK_Complete, SourceRange()); + if (Result.isInvalid()) + return ExprError(); + + return S.MaybeBindToTemporary(Result.takeAs()); + } + + case CK_UserDefinedConversion: { + assert(!From->getType()->isPointerType() && "Arg can't have pointer type!"); + + // Create an implicit call expr that calls it. + CXXConversionDecl *Conv = cast(Method); + ExprResult Result = S.BuildCXXMemberCallExpr(From, FoundDecl, Conv, + HadMultipleCandidates); + if (Result.isInvalid()) + return ExprError(); + // Record usage of conversion in an implicit cast. + Result = S.Owned(ImplicitCastExpr::Create(S.Context, + Result.get()->getType(), + CK_UserDefinedConversion, + Result.get(), 0, + Result.get()->getValueKind())); + + S.CheckMemberOperatorAccess(CastLoc, From, /*arg*/ 0, FoundDecl); + + return S.MaybeBindToTemporary(Result.get()); + } + } +} + +/// PerformImplicitConversion - Perform an implicit conversion of the +/// expression From to the type ToType using the pre-computed implicit +/// conversion sequence ICS. Returns the converted +/// expression. Action is the kind of conversion we're performing, +/// used in the error message. +ExprResult +Sema::PerformImplicitConversion(Expr *From, QualType ToType, + const ImplicitConversionSequence &ICS, + AssignmentAction Action, + CheckedConversionKind CCK) { + switch (ICS.getKind()) { + case ImplicitConversionSequence::StandardConversion: { + ExprResult Res = PerformImplicitConversion(From, ToType, ICS.Standard, + Action, CCK); + if (Res.isInvalid()) + return ExprError(); + From = Res.take(); + break; + } + + case ImplicitConversionSequence::UserDefinedConversion: { + + FunctionDecl *FD = ICS.UserDefined.ConversionFunction; + CastKind CastKind; + QualType BeforeToType; + assert(FD && "FIXME: aggregate initialization from init list"); + if (const CXXConversionDecl *Conv = dyn_cast(FD)) { + CastKind = CK_UserDefinedConversion; + + // If the user-defined conversion is specified by a conversion function, + // the initial standard conversion sequence converts the source type to + // the implicit object parameter of the conversion function. + BeforeToType = Context.getTagDeclType(Conv->getParent()); + } else { + const CXXConstructorDecl *Ctor = cast(FD); + 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 + // initial standard conversion sequence converts the source type to the + // type required by the argument of the constructor + BeforeToType = Ctor->getParamDecl(0)->getType().getNonReferenceType(); + } + } + // Watch out for elipsis conversion. + if (!ICS.UserDefined.EllipsisConversion) { + ExprResult Res = + PerformImplicitConversion(From, BeforeToType, + ICS.UserDefined.Before, AA_Converting, + CCK); + if (Res.isInvalid()) + return ExprError(); + From = Res.take(); + } + + ExprResult CastArg + = BuildCXXCastArgument(*this, + From->getLocStart(), + ToType.getNonReferenceType(), + CastKind, cast(FD), + ICS.UserDefined.FoundConversionFunction, + ICS.UserDefined.HadMultipleCandidates, + From); + + if (CastArg.isInvalid()) + return ExprError(); + + From = CastArg.take(); + + return PerformImplicitConversion(From, ToType, ICS.UserDefined.After, + AA_Converting, CCK); + } + + case ImplicitConversionSequence::AmbiguousConversion: + ICS.DiagnoseAmbiguousConversion(*this, From->getExprLoc(), + PDiag(diag::err_typecheck_ambiguous_condition) + << From->getSourceRange()); + return ExprError(); + + case ImplicitConversionSequence::EllipsisConversion: + llvm_unreachable("Cannot perform an ellipsis conversion"); + + case ImplicitConversionSequence::BadConversion: + return ExprError(); + } + + // Everything went well. + return Owned(From); +} + +/// PerformImplicitConversion - Perform an implicit conversion of the +/// expression From to the type ToType by following the standard +/// conversion sequence SCS. Returns the converted +/// expression. Flavor is the context in which we're performing this +/// conversion, for use in error messages. +ExprResult +Sema::PerformImplicitConversion(Expr *From, QualType ToType, + const StandardConversionSequence& SCS, + AssignmentAction Action, + CheckedConversionKind CCK) { + bool CStyle = (CCK == CCK_CStyleCast || CCK == CCK_FunctionalCast); + + // Overall FIXME: we are recomputing too many types here and doing far too + // much extra work. What this means is that we need to keep track of more + // information that is computed when we try the implicit conversion initially, + // so that we don't need to recompute anything here. + QualType FromType = From->getType(); + + if (SCS.CopyConstructor) { + // FIXME: When can ToType be a reference type? + assert(!ToType->isReferenceType()); + if (SCS.Second == ICK_Derived_To_Base) { + ASTOwningVector ConstructorArgs(*this); + if (CompleteConstructorCall(cast(SCS.CopyConstructor), + MultiExprArg(*this, &From, 1), + /*FIXME:ConstructLoc*/SourceLocation(), + ConstructorArgs)) + return ExprError(); + return BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(), + ToType, SCS.CopyConstructor, + move_arg(ConstructorArgs), + /*HadMultipleCandidates*/ false, + /*ZeroInit*/ false, + CXXConstructExpr::CK_Complete, + SourceRange()); + } + return BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(), + ToType, SCS.CopyConstructor, + MultiExprArg(*this, &From, 1), + /*HadMultipleCandidates*/ false, + /*ZeroInit*/ false, + CXXConstructExpr::CK_Complete, + SourceRange()); + } + + // Resolve overloaded function references. + if (Context.hasSameType(FromType, Context.OverloadTy)) { + DeclAccessPair Found; + FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(From, ToType, + true, Found); + if (!Fn) + return ExprError(); + + if (DiagnoseUseOfDecl(Fn, From->getLocStart())) + return ExprError(); + + From = FixOverloadedFunctionReference(From, Found, Fn); + FromType = From->getType(); + } + + // Perform the first implicit conversion. + switch (SCS.First) { + case ICK_Identity: + // Nothing to do. + break; + + case ICK_Lvalue_To_Rvalue: { + assert(From->getObjectKind() != OK_ObjCProperty); + FromType = FromType.getUnqualifiedType(); + ExprResult FromRes = DefaultLvalueConversion(From); + assert(!FromRes.isInvalid() && "Can't perform deduced conversion?!"); + From = FromRes.take(); + break; + } + + case ICK_Array_To_Pointer: + FromType = Context.getArrayDecayedType(FromType); + From = ImpCastExprToType(From, FromType, CK_ArrayToPointerDecay, + VK_RValue, /*BasePath=*/0, CCK).take(); + break; + + case ICK_Function_To_Pointer: + FromType = Context.getPointerType(FromType); + From = ImpCastExprToType(From, FromType, CK_FunctionToPointerDecay, + VK_RValue, /*BasePath=*/0, CCK).take(); + break; + + default: + llvm_unreachable("Improper first standard conversion"); + } + + // Perform the second implicit conversion + switch (SCS.Second) { + case ICK_Identity: + // If both sides are functions (or pointers/references to them), there could + // be incompatible exception declarations. + if (CheckExceptionSpecCompatibility(From, ToType)) + return ExprError(); + // Nothing else to do. + break; + + case ICK_NoReturn_Adjustment: + // If both sides are functions (or pointers/references to them), there could + // be incompatible exception declarations. + if (CheckExceptionSpecCompatibility(From, ToType)) + return ExprError(); + + From = ImpCastExprToType(From, ToType, CK_NoOp, + VK_RValue, /*BasePath=*/0, CCK).take(); + break; + + case ICK_Integral_Promotion: + case ICK_Integral_Conversion: + From = ImpCastExprToType(From, ToType, CK_IntegralCast, + VK_RValue, /*BasePath=*/0, CCK).take(); + break; + + case ICK_Floating_Promotion: + case ICK_Floating_Conversion: + From = ImpCastExprToType(From, ToType, CK_FloatingCast, + VK_RValue, /*BasePath=*/0, CCK).take(); + break; + + case ICK_Complex_Promotion: + case ICK_Complex_Conversion: { + QualType FromEl = From->getType()->getAs()->getElementType(); + QualType ToEl = ToType->getAs()->getElementType(); + CastKind CK; + if (FromEl->isRealFloatingType()) { + if (ToEl->isRealFloatingType()) + CK = CK_FloatingComplexCast; + else + CK = CK_FloatingComplexToIntegralComplex; + } else if (ToEl->isRealFloatingType()) { + CK = CK_IntegralComplexToFloatingComplex; + } else { + CK = CK_IntegralComplexCast; + } + From = ImpCastExprToType(From, ToType, CK, + VK_RValue, /*BasePath=*/0, CCK).take(); + break; + } + + case ICK_Floating_Integral: + if (ToType->isRealFloatingType()) + From = ImpCastExprToType(From, ToType, CK_IntegralToFloating, + VK_RValue, /*BasePath=*/0, CCK).take(); + else + From = ImpCastExprToType(From, ToType, CK_FloatingToIntegral, + VK_RValue, /*BasePath=*/0, CCK).take(); + break; + + case ICK_Compatible_Conversion: + From = ImpCastExprToType(From, ToType, CK_NoOp, + VK_RValue, /*BasePath=*/0, CCK).take(); + break; + + case ICK_Writeback_Conversion: + case ICK_Pointer_Conversion: { + if (SCS.IncompatibleObjC && Action != AA_Casting) { + // Diagnose incompatible Objective-C conversions + if (Action == AA_Initializing || Action == AA_Assigning) + Diag(From->getLocStart(), + diag::ext_typecheck_convert_incompatible_pointer) + << ToType << From->getType() << Action + << From->getSourceRange() << 0; + else + Diag(From->getLocStart(), + diag::ext_typecheck_convert_incompatible_pointer) + << From->getType() << ToType << Action + << From->getSourceRange() << 0; + + if (From->getType()->isObjCObjectPointerType() && + ToType->isObjCObjectPointerType()) + EmitRelatedResultTypeNote(From); + } + else if (getLangOpts().ObjCAutoRefCount && + !CheckObjCARCUnavailableWeakConversion(ToType, + From->getType())) { + if (Action == AA_Initializing) + Diag(From->getLocStart(), + diag::err_arc_weak_unavailable_assign); + else + Diag(From->getLocStart(), + diag::err_arc_convesion_of_weak_unavailable) + << (Action == AA_Casting) << From->getType() << ToType + << From->getSourceRange(); + } + + CastKind Kind = CK_Invalid; + CXXCastPath BasePath; + if (CheckPointerConversion(From, ToType, Kind, BasePath, CStyle)) + return ExprError(); + + // Make sure we extend blocks if necessary. + // FIXME: doing this here is really ugly. + if (Kind == CK_BlockPointerToObjCPointerCast) { + ExprResult E = From; + (void) PrepareCastToObjCObjectPointer(E); + From = E.take(); + } + + From = ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath, CCK) + .take(); + break; + } + + case ICK_Pointer_Member: { + CastKind Kind = CK_Invalid; + CXXCastPath BasePath; + if (CheckMemberPointerConversion(From, ToType, Kind, BasePath, CStyle)) + return ExprError(); + if (CheckExceptionSpecCompatibility(From, ToType)) + return ExprError(); + From = ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath, CCK) + .take(); + break; + } + + case ICK_Boolean_Conversion: + // Perform half-to-boolean conversion via float. + if (From->getType()->isHalfType()) { + From = ImpCastExprToType(From, Context.FloatTy, CK_FloatingCast).take(); + FromType = Context.FloatTy; + } + + From = ImpCastExprToType(From, Context.BoolTy, + ScalarTypeToBooleanCastKind(FromType), + VK_RValue, /*BasePath=*/0, CCK).take(); + break; + + case ICK_Derived_To_Base: { + CXXCastPath BasePath; + if (CheckDerivedToBaseConversion(From->getType(), + ToType.getNonReferenceType(), + From->getLocStart(), + From->getSourceRange(), + &BasePath, + CStyle)) + return ExprError(); + + From = ImpCastExprToType(From, ToType.getNonReferenceType(), + CK_DerivedToBase, From->getValueKind(), + &BasePath, CCK).take(); + break; + } + + case ICK_Vector_Conversion: + From = ImpCastExprToType(From, ToType, CK_BitCast, + VK_RValue, /*BasePath=*/0, CCK).take(); + break; + + case ICK_Vector_Splat: + From = ImpCastExprToType(From, ToType, CK_VectorSplat, + VK_RValue, /*BasePath=*/0, CCK).take(); + break; + + case ICK_Complex_Real: + // Case 1. x -> _Complex y + if (const ComplexType *ToComplex = ToType->getAs()) { + QualType ElType = ToComplex->getElementType(); + bool isFloatingComplex = ElType->isRealFloatingType(); + + // x -> y + if (Context.hasSameUnqualifiedType(ElType, From->getType())) { + // do nothing + } else if (From->getType()->isRealFloatingType()) { + From = ImpCastExprToType(From, ElType, + isFloatingComplex ? CK_FloatingCast : CK_FloatingToIntegral).take(); + } else { + assert(From->getType()->isIntegerType()); + From = ImpCastExprToType(From, ElType, + isFloatingComplex ? CK_IntegralToFloating : CK_IntegralCast).take(); + } + // y -> _Complex y + From = ImpCastExprToType(From, ToType, + isFloatingComplex ? CK_FloatingRealToComplex + : CK_IntegralRealToComplex).take(); + + // Case 2. _Complex x -> y + } else { + const ComplexType *FromComplex = From->getType()->getAs(); + assert(FromComplex); + + QualType ElType = FromComplex->getElementType(); + bool isFloatingComplex = ElType->isRealFloatingType(); + + // _Complex x -> x + From = ImpCastExprToType(From, ElType, + isFloatingComplex ? CK_FloatingComplexToReal + : CK_IntegralComplexToReal, + VK_RValue, /*BasePath=*/0, CCK).take(); + + // x -> y + if (Context.hasSameUnqualifiedType(ElType, ToType)) { + // do nothing + } else if (ToType->isRealFloatingType()) { + From = ImpCastExprToType(From, ToType, + isFloatingComplex ? CK_FloatingCast : CK_IntegralToFloating, + VK_RValue, /*BasePath=*/0, CCK).take(); + } else { + assert(ToType->isIntegerType()); + From = ImpCastExprToType(From, ToType, + isFloatingComplex ? CK_FloatingToIntegral : CK_IntegralCast, + VK_RValue, /*BasePath=*/0, CCK).take(); + } + } + break; + + case ICK_Block_Pointer_Conversion: { + From = ImpCastExprToType(From, ToType.getUnqualifiedType(), CK_BitCast, + VK_RValue, /*BasePath=*/0, CCK).take(); + break; + } + + case ICK_TransparentUnionConversion: { + ExprResult FromRes = Owned(From); + Sema::AssignConvertType ConvTy = + CheckTransparentUnionArgumentConstraints(ToType, FromRes); + if (FromRes.isInvalid()) + return ExprError(); + From = FromRes.take(); + assert ((ConvTy == Sema::Compatible) && + "Improper transparent union conversion"); + (void)ConvTy; + break; + } + + case ICK_Lvalue_To_Rvalue: + case ICK_Array_To_Pointer: + case ICK_Function_To_Pointer: + case ICK_Qualification: + case ICK_Num_Conversion_Kinds: + llvm_unreachable("Improper second standard conversion"); + } + + switch (SCS.Third) { + case ICK_Identity: + // Nothing to do. + break; + + case ICK_Qualification: { + // The qualification keeps the category of the inner expression, unless the + // target type isn't a reference. + ExprValueKind VK = ToType->isReferenceType() ? + From->getValueKind() : VK_RValue; + From = ImpCastExprToType(From, ToType.getNonLValueExprType(Context), + CK_NoOp, VK, /*BasePath=*/0, CCK).take(); + + if (SCS.DeprecatedStringLiteralToCharPtr && + !getLangOpts().WritableStrings) + Diag(From->getLocStart(), diag::warn_deprecated_string_literal_conversion) + << ToType.getNonReferenceType(); + + break; + } + + default: + llvm_unreachable("Improper third standard conversion"); + } + + // If this conversion sequence involved a scalar -> atomic conversion, perform + // that conversion now. + if (const AtomicType *ToAtomic = ToType->getAs()) + if (Context.hasSameType(ToAtomic->getValueType(), From->getType())) + From = ImpCastExprToType(From, ToType, CK_NonAtomicToAtomic, VK_RValue, 0, + CCK).take(); + + return Owned(From); +} + +ExprResult Sema::ActOnUnaryTypeTrait(UnaryTypeTrait UTT, + SourceLocation KWLoc, + ParsedType Ty, + SourceLocation RParen) { + TypeSourceInfo *TSInfo; + QualType T = GetTypeFromParser(Ty, &TSInfo); + + if (!TSInfo) + TSInfo = Context.getTrivialTypeSourceInfo(T); + return BuildUnaryTypeTrait(UTT, KWLoc, TSInfo, RParen); +} + +/// \brief Check the completeness of a type in a unary type trait. +/// +/// If the particular type trait requires a complete type, tries to complete +/// it. If completing the type fails, a diagnostic is emitted and false +/// returned. If completing the type succeeds or no completion was required, +/// returns true. +static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, + UnaryTypeTrait UTT, + SourceLocation Loc, + QualType ArgTy) { + // C++0x [meta.unary.prop]p3: + // For all of the class templates X declared in this Clause, instantiating + // that template with a template argument that is a class template + // specialization may result in the implicit instantiation of the template + // argument if and only if the semantics of X require that the argument + // must be a complete type. + // We apply this rule to all the type trait expressions used to implement + // these class templates. We also try to follow any GCC documented behavior + // in these expressions to ensure portability of standard libraries. + switch (UTT) { + // is_complete_type somewhat obviously cannot require a complete type. + case UTT_IsCompleteType: + // Fall-through + + // These traits are modeled on the type predicates in C++0x + // [meta.unary.cat] and [meta.unary.comp]. They are not specified as + // requiring a complete type, as whether or not they return true cannot be + // impacted by the completeness of the type. + case UTT_IsVoid: + case UTT_IsIntegral: + case UTT_IsFloatingPoint: + case UTT_IsArray: + case UTT_IsPointer: + case UTT_IsLvalueReference: + case UTT_IsRvalueReference: + case UTT_IsMemberFunctionPointer: + case UTT_IsMemberObjectPointer: + case UTT_IsEnum: + case UTT_IsUnion: + case UTT_IsClass: + case UTT_IsFunction: + case UTT_IsReference: + case UTT_IsArithmetic: + case UTT_IsFundamental: + case UTT_IsObject: + case UTT_IsScalar: + case UTT_IsCompound: + case UTT_IsMemberPointer: + // Fall-through + + // These traits are modeled on type predicates in C++0x [meta.unary.prop] + // which requires some of its traits to have the complete type. However, + // the completeness of the type cannot impact these traits' semantics, and + // so they don't require it. This matches the comments on these traits in + // Table 49. + case UTT_IsConst: + case UTT_IsVolatile: + case UTT_IsSigned: + case UTT_IsUnsigned: + return true; + + // C++0x [meta.unary.prop] Table 49 requires the following traits to be + // applied to a complete type. + case UTT_IsTrivial: + case UTT_IsTriviallyCopyable: + case UTT_IsStandardLayout: + case UTT_IsPOD: + case UTT_IsLiteral: + case UTT_IsEmpty: + case UTT_IsPolymorphic: + case UTT_IsAbstract: + // Fall-through + + // These traits require a complete type. + case UTT_IsFinal: + + // These trait expressions are designed to help implement predicates in + // [meta.unary.prop] despite not being named the same. They are specified + // by both GCC and the Embarcadero C++ compiler, and require the complete + // type due to the overarching C++0x type predicates being implemented + // requiring the complete type. + case UTT_HasNothrowAssign: + case UTT_HasNothrowConstructor: + case UTT_HasNothrowCopy: + case UTT_HasTrivialAssign: + case UTT_HasTrivialDefaultConstructor: + case UTT_HasTrivialCopy: + case UTT_HasTrivialDestructor: + case UTT_HasVirtualDestructor: + // Arrays of unknown bound are expressly allowed. + QualType ElTy = ArgTy; + if (ArgTy->isIncompleteArrayType()) + ElTy = S.Context.getAsArrayType(ArgTy)->getElementType(); + + // The void type is expressly allowed. + if (ElTy->isVoidType()) + return true; + + return !S.RequireCompleteType( + Loc, ElTy, diag::err_incomplete_type_used_in_type_trait_expr); + } + llvm_unreachable("Type trait not handled by switch"); +} + +static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, + SourceLocation KeyLoc, QualType T) { + assert(!T->isDependentType() && "Cannot evaluate traits of dependent type"); + + ASTContext &C = Self.Context; + switch(UTT) { + // Type trait expressions corresponding to the primary type category + // predicates in C++0x [meta.unary.cat]. + case UTT_IsVoid: + return T->isVoidType(); + case UTT_IsIntegral: + return T->isIntegralType(C); + case UTT_IsFloatingPoint: + return T->isFloatingType(); + case UTT_IsArray: + return T->isArrayType(); + case UTT_IsPointer: + return T->isPointerType(); + case UTT_IsLvalueReference: + return T->isLValueReferenceType(); + case UTT_IsRvalueReference: + return T->isRValueReferenceType(); + case UTT_IsMemberFunctionPointer: + return T->isMemberFunctionPointerType(); + case UTT_IsMemberObjectPointer: + return T->isMemberDataPointerType(); + case UTT_IsEnum: + return T->isEnumeralType(); + case UTT_IsUnion: + return T->isUnionType(); + case UTT_IsClass: + return T->isClassType() || T->isStructureType(); + case UTT_IsFunction: + return T->isFunctionType(); + + // Type trait expressions which correspond to the convenient composition + // predicates in C++0x [meta.unary.comp]. + case UTT_IsReference: + return T->isReferenceType(); + case UTT_IsArithmetic: + return T->isArithmeticType() && !T->isEnumeralType(); + case UTT_IsFundamental: + return T->isFundamentalType(); + case UTT_IsObject: + return T->isObjectType(); + case UTT_IsScalar: + // Note: semantic analysis depends on Objective-C lifetime types to be + // considered scalar types. However, such types do not actually behave + // like scalar types at run time (since they may require retain/release + // operations), so we report them as non-scalar. + if (T->isObjCLifetimeType()) { + switch (T.getObjCLifetime()) { + case Qualifiers::OCL_None: + case Qualifiers::OCL_ExplicitNone: + return true; + + case Qualifiers::OCL_Strong: + case Qualifiers::OCL_Weak: + case Qualifiers::OCL_Autoreleasing: + return false; + } + } + + return T->isScalarType(); + case UTT_IsCompound: + return T->isCompoundType(); + case UTT_IsMemberPointer: + return T->isMemberPointerType(); + + // Type trait expressions which correspond to the type property predicates + // in C++0x [meta.unary.prop]. + case UTT_IsConst: + return T.isConstQualified(); + case UTT_IsVolatile: + return T.isVolatileQualified(); + case UTT_IsTrivial: + return T.isTrivialType(Self.Context); + case UTT_IsTriviallyCopyable: + return T.isTriviallyCopyableType(Self.Context); + case UTT_IsStandardLayout: + return T->isStandardLayoutType(); + case UTT_IsPOD: + return T.isPODType(Self.Context); + case UTT_IsLiteral: + return T->isLiteralType(); + case UTT_IsEmpty: + if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) + return !RD->isUnion() && RD->isEmpty(); + return false; + case UTT_IsPolymorphic: + if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) + return RD->isPolymorphic(); + return false; + case UTT_IsAbstract: + if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) + return RD->isAbstract(); + return false; + case UTT_IsFinal: + if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) + return RD->hasAttr(); + return false; + case UTT_IsSigned: + return T->isSignedIntegerType(); + case UTT_IsUnsigned: + return T->isUnsignedIntegerType(); + + // Type trait expressions which query classes regarding their construction, + // destruction, and copying. Rather than being based directly on the + // related type predicates in the standard, they are specified by both + // GCC[1] and the Embarcadero C++ compiler[2], and Clang implements those + // specifications. + // + // 1: http://gcc.gnu/.org/onlinedocs/gcc/Type-Traits.html + // 2: http://docwiki.embarcadero.com/RADStudio/XE/en/Type_Trait_Functions_(C%2B%2B0x)_Index + case UTT_HasTrivialDefaultConstructor: + // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: + // If __is_pod (type) is true then the trait is true, else if type is + // a cv class or union type (or array thereof) with a trivial default + // constructor ([class.ctor]) then the trait is true, else it is false. + if (T.isPODType(Self.Context)) + return true; + if (const RecordType *RT = + C.getBaseElementType(T)->getAs()) + return cast(RT->getDecl())->hasTrivialDefaultConstructor(); + return false; + case UTT_HasTrivialCopy: + // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: + // If __is_pod (type) is true or type is a reference type then + // the trait is true, else if type is a cv class or union type + // with a trivial copy constructor ([class.copy]) then the trait + // is true, else it is false. + if (T.isPODType(Self.Context) || T->isReferenceType()) + return true; + if (const RecordType *RT = T->getAs()) + return cast(RT->getDecl())->hasTrivialCopyConstructor(); + return false; + case UTT_HasTrivialAssign: + // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: + // If type is const qualified or is a reference type then the + // trait is false. Otherwise if __is_pod (type) is true then the + // trait is true, else if type is a cv class or union type with + // a trivial copy assignment ([class.copy]) then the trait is + // true, else it is false. + // Note: the const and reference restrictions are interesting, + // given that const and reference members don't prevent a class + // from having a trivial copy assignment operator (but do cause + // errors if the copy assignment operator is actually used, q.v. + // [class.copy]p12). + + if (C.getBaseElementType(T).isConstQualified()) + return false; + if (T.isPODType(Self.Context)) + return true; + if (const RecordType *RT = T->getAs()) + return cast(RT->getDecl())->hasTrivialCopyAssignment(); + return false; + case UTT_HasTrivialDestructor: + // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: + // If __is_pod (type) is true or type is a reference type + // then the trait is true, else if type is a cv class or union + // type (or array thereof) with a trivial destructor + // ([class.dtor]) then the trait is true, else it is + // false. + if (T.isPODType(Self.Context) || T->isReferenceType()) + return true; + + // Objective-C++ ARC: autorelease types don't require destruction. + if (T->isObjCLifetimeType() && + T.getObjCLifetime() == Qualifiers::OCL_Autoreleasing) + return true; + + if (const RecordType *RT = + C.getBaseElementType(T)->getAs()) + return cast(RT->getDecl())->hasTrivialDestructor(); + return false; + // TODO: Propagate nothrowness for implicitly declared special members. + case UTT_HasNothrowAssign: + // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: + // If type is const qualified or is a reference type then the + // trait is false. Otherwise if __has_trivial_assign (type) + // is true then the trait is true, else if type is a cv class + // or union type with copy assignment operators that are known + // not to throw an exception then the trait is true, else it is + // false. + if (C.getBaseElementType(T).isConstQualified()) + return false; + if (T->isReferenceType()) + return false; + if (T.isPODType(Self.Context) || T->isObjCLifetimeType()) + return true; + if (const RecordType *RT = T->getAs()) { + CXXRecordDecl* RD = cast(RT->getDecl()); + if (RD->hasTrivialCopyAssignment()) + return true; + + bool FoundAssign = false; + DeclarationName Name = C.DeclarationNames.getCXXOperatorName(OO_Equal); + LookupResult Res(Self, DeclarationNameInfo(Name, KeyLoc), + Sema::LookupOrdinaryName); + if (Self.LookupQualifiedName(Res, RD)) { + Res.suppressDiagnostics(); + for (LookupResult::iterator Op = Res.begin(), OpEnd = Res.end(); + Op != OpEnd; ++Op) { + if (isa(*Op)) + continue; + + CXXMethodDecl *Operator = cast(*Op); + if (Operator->isCopyAssignmentOperator()) { + FoundAssign = true; + const FunctionProtoType *CPT + = Operator->getType()->getAs(); + CPT = Self.ResolveExceptionSpec(KeyLoc, CPT); + if (!CPT) + return false; + if (CPT->getExceptionSpecType() == EST_Delayed) + return false; + if (!CPT->isNothrow(Self.Context)) + return false; + } + } + } + + return FoundAssign; + } + return false; + case UTT_HasNothrowCopy: + // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: + // If __has_trivial_copy (type) is true then the trait is true, else + // if type is a cv class or union type with copy constructors that are + // known not to throw an exception then the trait is true, else it is + // false. + if (T.isPODType(C) || T->isReferenceType() || T->isObjCLifetimeType()) + return true; + if (const RecordType *RT = T->getAs()) { + CXXRecordDecl *RD = cast(RT->getDecl()); + if (RD->hasTrivialCopyConstructor()) + return true; + + bool FoundConstructor = false; + unsigned FoundTQs; + DeclContext::lookup_const_iterator Con, ConEnd; + for (llvm::tie(Con, ConEnd) = Self.LookupConstructors(RD); + Con != ConEnd; ++Con) { + // A template constructor is never a copy constructor. + // FIXME: However, it may actually be selected at the actual overload + // resolution point. + if (isa(*Con)) + continue; + CXXConstructorDecl *Constructor = cast(*Con); + if (Constructor->isCopyConstructor(FoundTQs)) { + FoundConstructor = true; + const FunctionProtoType *CPT + = Constructor->getType()->getAs(); + CPT = Self.ResolveExceptionSpec(KeyLoc, CPT); + if (!CPT) + return false; + if (CPT->getExceptionSpecType() == EST_Delayed) + return false; + // FIXME: check whether evaluating default arguments can throw. + // For now, we'll be conservative and assume that they can throw. + if (!CPT->isNothrow(Self.Context) || CPT->getNumArgs() > 1) + return false; + } + } + + return FoundConstructor; + } + return false; + case UTT_HasNothrowConstructor: + // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: + // If __has_trivial_constructor (type) is true then the trait is + // true, else if type is a cv class or union type (or array + // thereof) with a default constructor that is known not to + // throw an exception then the trait is true, else it is false. + if (T.isPODType(C) || T->isObjCLifetimeType()) + return true; + if (const RecordType *RT = C.getBaseElementType(T)->getAs()) { + CXXRecordDecl *RD = cast(RT->getDecl()); + if (RD->hasTrivialDefaultConstructor()) + return true; + + DeclContext::lookup_const_iterator Con, ConEnd; + for (llvm::tie(Con, ConEnd) = Self.LookupConstructors(RD); + Con != ConEnd; ++Con) { + // FIXME: In C++0x, a constructor template can be a default constructor. + if (isa(*Con)) + continue; + CXXConstructorDecl *Constructor = cast(*Con); + if (Constructor->isDefaultConstructor()) { + const FunctionProtoType *CPT + = Constructor->getType()->getAs(); + CPT = Self.ResolveExceptionSpec(KeyLoc, CPT); + if (!CPT) + return false; + if (CPT->getExceptionSpecType() == EST_Delayed) + return false; + // TODO: check whether evaluating default arguments can throw. + // For now, we'll be conservative and assume that they can throw. + return CPT->isNothrow(Self.Context) && CPT->getNumArgs() == 0; + } + } + } + return false; + case UTT_HasVirtualDestructor: + // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: + // If type is a class type with a virtual destructor ([class.dtor]) + // then the trait is true, else it is false. + if (const RecordType *Record = T->getAs()) { + CXXRecordDecl *RD = cast(Record->getDecl()); + if (CXXDestructorDecl *Destructor = Self.LookupDestructor(RD)) + return Destructor->isVirtual(); + } + return false; + + // These type trait expressions are modeled on the specifications for the + // Embarcadero C++0x type trait functions: + // http://docwiki.embarcadero.com/RADStudio/XE/en/Type_Trait_Functions_(C%2B%2B0x)_Index + case UTT_IsCompleteType: + // http://docwiki.embarcadero.com/RADStudio/XE/en/Is_complete_type_(typename_T_): + // Returns True if and only if T is a complete type at the point of the + // function call. + return !T->isIncompleteType(); + } + llvm_unreachable("Type trait not covered by switch"); +} + +ExprResult Sema::BuildUnaryTypeTrait(UnaryTypeTrait UTT, + SourceLocation KWLoc, + TypeSourceInfo *TSInfo, + SourceLocation RParen) { + QualType T = TSInfo->getType(); + if (!CheckUnaryTypeTraitTypeCompleteness(*this, UTT, KWLoc, T)) + return ExprError(); + + bool Value = false; + if (!T->isDependentType()) + Value = EvaluateUnaryTypeTrait(*this, UTT, KWLoc, T); + + return Owned(new (Context) UnaryTypeTraitExpr(KWLoc, UTT, TSInfo, Value, + RParen, Context.BoolTy)); +} + +ExprResult Sema::ActOnBinaryTypeTrait(BinaryTypeTrait BTT, + SourceLocation KWLoc, + ParsedType LhsTy, + ParsedType RhsTy, + SourceLocation RParen) { + TypeSourceInfo *LhsTSInfo; + QualType LhsT = GetTypeFromParser(LhsTy, &LhsTSInfo); + if (!LhsTSInfo) + LhsTSInfo = Context.getTrivialTypeSourceInfo(LhsT); + + TypeSourceInfo *RhsTSInfo; + QualType RhsT = GetTypeFromParser(RhsTy, &RhsTSInfo); + if (!RhsTSInfo) + RhsTSInfo = Context.getTrivialTypeSourceInfo(RhsT); + + return BuildBinaryTypeTrait(BTT, KWLoc, LhsTSInfo, RhsTSInfo, RParen); +} + +static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc, + ArrayRef Args, + SourceLocation RParenLoc) { + switch (Kind) { + case clang::TT_IsTriviallyConstructible: { + // C++11 [meta.unary.prop]: + // is_trivially_constructible is defined as: + // + // is_constructible::value is true and the variable + // definition for is_constructible, as defined below, is known to call no + // operation that is not trivial. + // + // The predicate condition for a template specialization + // is_constructible shall be satisfied if and only if the + // following variable definition would be well-formed for some invented + // variable t: + // + // T t(create()...); + if (Args.empty()) { + S.Diag(KWLoc, diag::err_type_trait_arity) + << 1 << 1 << 1 << (int)Args.size(); + return false; + } + + bool SawVoid = false; + for (unsigned I = 0, N = Args.size(); I != N; ++I) { + if (Args[I]->getType()->isVoidType()) { + SawVoid = true; + continue; + } + + if (!Args[I]->getType()->isIncompleteType() && + S.RequireCompleteType(KWLoc, Args[I]->getType(), + diag::err_incomplete_type_used_in_type_trait_expr)) + return false; + } + + // If any argument was 'void', of course it won't type-check. + if (SawVoid) + return false; + + llvm::SmallVector OpaqueArgExprs; + llvm::SmallVector ArgExprs; + ArgExprs.reserve(Args.size() - 1); + for (unsigned I = 1, N = Args.size(); I != N; ++I) { + QualType T = Args[I]->getType(); + if (T->isObjectType() || T->isFunctionType()) + T = S.Context.getRValueReferenceType(T); + OpaqueArgExprs.push_back( + OpaqueValueExpr(Args[I]->getTypeLoc().getLocStart(), + T.getNonLValueExprType(S.Context), + Expr::getValueKindForType(T))); + ArgExprs.push_back(&OpaqueArgExprs.back()); + } + + // Perform the initialization in an unevaluated context within a SFINAE + // trap at translation unit scope. + EnterExpressionEvaluationContext Unevaluated(S, Sema::Unevaluated); + Sema::SFINAETrap SFINAE(S, /*AccessCheckingSFINAE=*/true); + Sema::ContextRAII TUContext(S, S.Context.getTranslationUnitDecl()); + InitializedEntity To(InitializedEntity::InitializeTemporary(Args[0])); + InitializationKind InitKind(InitializationKind::CreateDirect(KWLoc, KWLoc, + RParenLoc)); + InitializationSequence Init(S, To, InitKind, + ArgExprs.begin(), ArgExprs.size()); + if (Init.Failed()) + return false; + + ExprResult Result = Init.Perform(S, To, InitKind, + MultiExprArg(ArgExprs.data(), + ArgExprs.size())); + if (Result.isInvalid() || SFINAE.hasErrorOccurred()) + return false; + + // The initialization succeeded; not make sure there are no non-trivial + // calls. + return !Result.get()->hasNonTrivialCall(S.Context); + } + } + + return false; +} + +ExprResult Sema::BuildTypeTrait(TypeTrait Kind, SourceLocation KWLoc, + ArrayRef Args, + SourceLocation RParenLoc) { + bool Dependent = false; + for (unsigned I = 0, N = Args.size(); I != N; ++I) { + if (Args[I]->getType()->isDependentType()) { + Dependent = true; + break; + } + } + + bool Value = false; + if (!Dependent) + Value = evaluateTypeTrait(*this, Kind, KWLoc, Args, RParenLoc); + + return TypeTraitExpr::Create(Context, Context.BoolTy, KWLoc, Kind, + Args, RParenLoc, Value); +} + +ExprResult Sema::ActOnTypeTrait(TypeTrait Kind, SourceLocation KWLoc, + ArrayRef Args, + SourceLocation RParenLoc) { + llvm::SmallVector ConvertedArgs; + ConvertedArgs.reserve(Args.size()); + + for (unsigned I = 0, N = Args.size(); I != N; ++I) { + TypeSourceInfo *TInfo; + QualType T = GetTypeFromParser(Args[I], &TInfo); + if (!TInfo) + TInfo = Context.getTrivialTypeSourceInfo(T, KWLoc); + + ConvertedArgs.push_back(TInfo); + } + + return BuildTypeTrait(Kind, KWLoc, ConvertedArgs, RParenLoc); +} + +static bool EvaluateBinaryTypeTrait(Sema &Self, BinaryTypeTrait BTT, + QualType LhsT, QualType RhsT, + SourceLocation KeyLoc) { + assert(!LhsT->isDependentType() && !RhsT->isDependentType() && + "Cannot evaluate traits of dependent types"); + + switch(BTT) { + case BTT_IsBaseOf: { + // C++0x [meta.rel]p2 + // Base is a base class of Derived without regard to cv-qualifiers or + // Base and Derived are not unions and name the same class type without + // regard to cv-qualifiers. + + const RecordType *lhsRecord = LhsT->getAs(); + if (!lhsRecord) return false; + + const RecordType *rhsRecord = RhsT->getAs(); + if (!rhsRecord) return false; + + assert(Self.Context.hasSameUnqualifiedType(LhsT, RhsT) + == (lhsRecord == rhsRecord)); + + if (lhsRecord == rhsRecord) + return !lhsRecord->getDecl()->isUnion(); + + // C++0x [meta.rel]p2: + // If Base and Derived are class types and are different types + // (ignoring possible cv-qualifiers) then Derived shall be a + // complete type. + if (Self.RequireCompleteType(KeyLoc, RhsT, + diag::err_incomplete_type_used_in_type_trait_expr)) + return false; + + return cast(rhsRecord->getDecl()) + ->isDerivedFrom(cast(lhsRecord->getDecl())); + } + case BTT_IsSame: + return Self.Context.hasSameType(LhsT, RhsT); + case BTT_TypeCompatible: + return Self.Context.typesAreCompatible(LhsT.getUnqualifiedType(), + RhsT.getUnqualifiedType()); + case BTT_IsConvertible: + case BTT_IsConvertibleTo: { + // C++0x [meta.rel]p4: + // Given the following function prototype: + // + // template + // typename add_rvalue_reference::type create(); + // + // the predicate condition for a template specialization + // is_convertible shall be satisfied if and only if + // the return expression in the following code would be + // well-formed, including any implicit conversions to the return + // type of the function: + // + // To test() { + // return create(); + // } + // + // Access checking is performed as if in a context unrelated to To and + // From. Only the validity of the immediate context of the expression + // of the return-statement (including conversions to the return type) + // is considered. + // + // We model the initialization as a copy-initialization of a temporary + // of the appropriate type, which for this expression is identical to the + // return statement (since NRVO doesn't apply). + if (LhsT->isObjectType() || LhsT->isFunctionType()) + LhsT = Self.Context.getRValueReferenceType(LhsT); + + InitializedEntity To(InitializedEntity::InitializeTemporary(RhsT)); + OpaqueValueExpr From(KeyLoc, LhsT.getNonLValueExprType(Self.Context), + Expr::getValueKindForType(LhsT)); + Expr *FromPtr = &From; + InitializationKind Kind(InitializationKind::CreateCopy(KeyLoc, + SourceLocation())); + + // Perform the initialization in an unevaluated context within a SFINAE + // trap at translation unit scope. + EnterExpressionEvaluationContext Unevaluated(Self, Sema::Unevaluated); + Sema::SFINAETrap SFINAE(Self, /*AccessCheckingSFINAE=*/true); + Sema::ContextRAII TUContext(Self, Self.Context.getTranslationUnitDecl()); + InitializationSequence Init(Self, To, Kind, &FromPtr, 1); + if (Init.Failed()) + return false; + + ExprResult Result = Init.Perform(Self, To, Kind, MultiExprArg(&FromPtr, 1)); + return !Result.isInvalid() && !SFINAE.hasErrorOccurred(); + } + + case BTT_IsTriviallyAssignable: { + // C++11 [meta.unary.prop]p3: + // is_trivially_assignable is defined as: + // is_assignable::value is true and the assignment, as defined by + // is_assignable, is known to call no operation that is not trivial + // + // is_assignable is defined as: + // The expression declval() = declval() is well-formed when + // treated as an unevaluated operand (Clause 5). + // + // For both, T and U shall be complete types, (possibly cv-qualified) + // void, or arrays of unknown bound. + if (!LhsT->isVoidType() && !LhsT->isIncompleteArrayType() && + Self.RequireCompleteType(KeyLoc, LhsT, + diag::err_incomplete_type_used_in_type_trait_expr)) + return false; + if (!RhsT->isVoidType() && !RhsT->isIncompleteArrayType() && + Self.RequireCompleteType(KeyLoc, RhsT, + diag::err_incomplete_type_used_in_type_trait_expr)) + return false; + + // cv void is never assignable. + if (LhsT->isVoidType() || RhsT->isVoidType()) + return false; + + // Build expressions that emulate the effect of declval() and + // declval(). + if (LhsT->isObjectType() || LhsT->isFunctionType()) + LhsT = Self.Context.getRValueReferenceType(LhsT); + if (RhsT->isObjectType() || RhsT->isFunctionType()) + RhsT = Self.Context.getRValueReferenceType(RhsT); + OpaqueValueExpr Lhs(KeyLoc, LhsT.getNonLValueExprType(Self.Context), + Expr::getValueKindForType(LhsT)); + OpaqueValueExpr Rhs(KeyLoc, RhsT.getNonLValueExprType(Self.Context), + Expr::getValueKindForType(RhsT)); + + // Attempt the assignment in an unevaluated context within a SFINAE + // trap at translation unit scope. + EnterExpressionEvaluationContext Unevaluated(Self, Sema::Unevaluated); + Sema::SFINAETrap SFINAE(Self, /*AccessCheckingSFINAE=*/true); + Sema::ContextRAII TUContext(Self, Self.Context.getTranslationUnitDecl()); + ExprResult Result = Self.BuildBinOp(/*S=*/0, KeyLoc, BO_Assign, &Lhs, &Rhs); + if (Result.isInvalid() || SFINAE.hasErrorOccurred()) + return false; + + return !Result.get()->hasNonTrivialCall(Self.Context); + } + } + llvm_unreachable("Unknown type trait or not implemented"); +} + +ExprResult Sema::BuildBinaryTypeTrait(BinaryTypeTrait BTT, + SourceLocation KWLoc, + TypeSourceInfo *LhsTSInfo, + TypeSourceInfo *RhsTSInfo, + SourceLocation RParen) { + QualType LhsT = LhsTSInfo->getType(); + QualType RhsT = RhsTSInfo->getType(); + + if (BTT == BTT_TypeCompatible) { + if (getLangOpts().CPlusPlus) { + Diag(KWLoc, diag::err_types_compatible_p_in_cplusplus) + << SourceRange(KWLoc, RParen); + return ExprError(); + } + } + + bool Value = false; + if (!LhsT->isDependentType() && !RhsT->isDependentType()) + Value = EvaluateBinaryTypeTrait(*this, BTT, LhsT, RhsT, KWLoc); + + // Select trait result type. + QualType ResultType; + switch (BTT) { + case BTT_IsBaseOf: ResultType = Context.BoolTy; break; + case BTT_IsConvertible: ResultType = Context.BoolTy; break; + case BTT_IsSame: ResultType = Context.BoolTy; break; + case BTT_TypeCompatible: ResultType = Context.IntTy; break; + case BTT_IsConvertibleTo: ResultType = Context.BoolTy; break; + case BTT_IsTriviallyAssignable: ResultType = Context.BoolTy; + } + + return Owned(new (Context) BinaryTypeTraitExpr(KWLoc, BTT, LhsTSInfo, + RhsTSInfo, Value, RParen, + ResultType)); +} + +ExprResult Sema::ActOnArrayTypeTrait(ArrayTypeTrait ATT, + SourceLocation KWLoc, + ParsedType Ty, + Expr* DimExpr, + SourceLocation RParen) { + TypeSourceInfo *TSInfo; + QualType T = GetTypeFromParser(Ty, &TSInfo); + if (!TSInfo) + TSInfo = Context.getTrivialTypeSourceInfo(T); + + return BuildArrayTypeTrait(ATT, KWLoc, TSInfo, DimExpr, RParen); +} + +static uint64_t EvaluateArrayTypeTrait(Sema &Self, ArrayTypeTrait ATT, + QualType T, Expr *DimExpr, + SourceLocation KeyLoc) { + assert(!T->isDependentType() && "Cannot evaluate traits of dependent type"); + + switch(ATT) { + case ATT_ArrayRank: + if (T->isArrayType()) { + unsigned Dim = 0; + while (const ArrayType *AT = Self.Context.getAsArrayType(T)) { + ++Dim; + T = AT->getElementType(); + } + return Dim; + } + return 0; + + case ATT_ArrayExtent: { + llvm::APSInt Value; + uint64_t Dim; + if (Self.VerifyIntegerConstantExpression(DimExpr, &Value, + Self.PDiag(diag::err_dimension_expr_not_constant_integer), + false).isInvalid()) + return 0; + if (Value.isSigned() && Value.isNegative()) { + Self.Diag(KeyLoc, diag::err_dimension_expr_not_constant_integer) + << DimExpr->getSourceRange(); + return 0; + } + Dim = Value.getLimitedValue(); + + if (T->isArrayType()) { + unsigned D = 0; + bool Matched = false; + while (const ArrayType *AT = Self.Context.getAsArrayType(T)) { + if (Dim == D) { + Matched = true; + break; + } + ++D; + T = AT->getElementType(); + } + + if (Matched && T->isArrayType()) { + if (const ConstantArrayType *CAT = Self.Context.getAsConstantArrayType(T)) + return CAT->getSize().getLimitedValue(); + } + } + return 0; + } + } + llvm_unreachable("Unknown type trait or not implemented"); +} + +ExprResult Sema::BuildArrayTypeTrait(ArrayTypeTrait ATT, + SourceLocation KWLoc, + TypeSourceInfo *TSInfo, + Expr* DimExpr, + SourceLocation RParen) { + QualType T = TSInfo->getType(); + + // FIXME: This should likely be tracked as an APInt to remove any host + // assumptions about the width of size_t on the target. + uint64_t Value = 0; + if (!T->isDependentType()) + Value = EvaluateArrayTypeTrait(*this, ATT, T, DimExpr, KWLoc); + + // While the specification for these traits from the Embarcadero C++ + // compiler's documentation says the return type is 'unsigned int', Clang + // returns 'size_t'. On Windows, the primary platform for the Embarcadero + // compiler, there is no difference. On several other platforms this is an + // important distinction. + return Owned(new (Context) ArrayTypeTraitExpr(KWLoc, ATT, TSInfo, Value, + DimExpr, RParen, + Context.getSizeType())); +} + +ExprResult Sema::ActOnExpressionTrait(ExpressionTrait ET, + SourceLocation KWLoc, + Expr *Queried, + SourceLocation RParen) { + // If error parsing the expression, ignore. + if (!Queried) + return ExprError(); + + ExprResult Result = BuildExpressionTrait(ET, KWLoc, Queried, RParen); + + return move(Result); +} + +static bool EvaluateExpressionTrait(ExpressionTrait ET, Expr *E) { + switch (ET) { + case ET_IsLValueExpr: return E->isLValue(); + case ET_IsRValueExpr: return E->isRValue(); + } + llvm_unreachable("Expression trait not covered by switch"); +} + +ExprResult Sema::BuildExpressionTrait(ExpressionTrait ET, + SourceLocation KWLoc, + Expr *Queried, + SourceLocation RParen) { + if (Queried->isTypeDependent()) { + // Delay type-checking for type-dependent expressions. + } else if (Queried->getType()->isPlaceholderType()) { + ExprResult PE = CheckPlaceholderExpr(Queried); + if (PE.isInvalid()) return ExprError(); + return BuildExpressionTrait(ET, KWLoc, PE.take(), RParen); + } + + bool Value = EvaluateExpressionTrait(ET, Queried); + + return Owned(new (Context) ExpressionTraitExpr(KWLoc, ET, Queried, Value, + RParen, Context.BoolTy)); +} + +QualType Sema::CheckPointerToMemberOperands(ExprResult &LHS, ExprResult &RHS, + ExprValueKind &VK, + SourceLocation Loc, + bool isIndirect) { + assert(!LHS.get()->getType()->isPlaceholderType() && + !RHS.get()->getType()->isPlaceholderType() && + "placeholders should have been weeded out by now"); + + // The LHS undergoes lvalue conversions if this is ->*. + if (isIndirect) { + LHS = DefaultLvalueConversion(LHS.take()); + if (LHS.isInvalid()) return QualType(); + } + + // The RHS always undergoes lvalue conversions. + RHS = DefaultLvalueConversion(RHS.take()); + if (RHS.isInvalid()) return QualType(); + + const char *OpSpelling = isIndirect ? "->*" : ".*"; + // C++ 5.5p2 + // The binary operator .* [p3: ->*] binds its second operand, which shall + // be of type "pointer to member of T" (where T is a completely-defined + // class type) [...] + QualType RHSType = RHS.get()->getType(); + const MemberPointerType *MemPtr = RHSType->getAs(); + if (!MemPtr) { + Diag(Loc, diag::err_bad_memptr_rhs) + << OpSpelling << RHSType << RHS.get()->getSourceRange(); + return QualType(); + } + + QualType Class(MemPtr->getClass(), 0); + + // Note: C++ [expr.mptr.oper]p2-3 says that the class type into which the + // member pointer points must be completely-defined. However, there is no + // reason for this semantic distinction, and the rule is not enforced by + // other compilers. Therefore, we do not check this property, as it is + // likely to be considered a defect. + + // C++ 5.5p2 + // [...] to its first operand, which shall be of class T or of a class of + // which T is an unambiguous and accessible base class. [p3: a pointer to + // such a class] + QualType LHSType = LHS.get()->getType(); + if (isIndirect) { + if (const PointerType *Ptr = LHSType->getAs()) + LHSType = Ptr->getPointeeType(); + else { + Diag(Loc, diag::err_bad_memptr_lhs) + << OpSpelling << 1 << LHSType + << FixItHint::CreateReplacement(SourceRange(Loc), ".*"); + return QualType(); + } + } + + if (!Context.hasSameUnqualifiedType(Class, LHSType)) { + // If we want to check the hierarchy, we need a complete type. + if (RequireCompleteType(Loc, LHSType, PDiag(diag::err_bad_memptr_lhs) + << OpSpelling << (int)isIndirect)) { + return QualType(); + } + CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, + /*DetectVirtual=*/false); + // FIXME: Would it be useful to print full ambiguity paths, or is that + // overkill? + if (!IsDerivedFrom(LHSType, Class, Paths) || + Paths.isAmbiguous(Context.getCanonicalType(Class))) { + Diag(Loc, diag::err_bad_memptr_lhs) << OpSpelling + << (int)isIndirect << LHS.get()->getType(); + return QualType(); + } + // Cast LHS to type of use. + QualType UseType = isIndirect ? Context.getPointerType(Class) : Class; + ExprValueKind VK = isIndirect ? VK_RValue : LHS.get()->getValueKind(); + + CXXCastPath BasePath; + BuildBasePathArray(Paths, BasePath); + LHS = ImpCastExprToType(LHS.take(), UseType, CK_DerivedToBase, VK, + &BasePath); + } + + if (isa(RHS.get()->IgnoreParens())) { + // Diagnose use of pointer-to-member type which when used as + // the functional cast in a pointer-to-member expression. + Diag(Loc, diag::err_pointer_to_member_type) << isIndirect; + return QualType(); + } + + // C++ 5.5p2 + // The result is an object or a function of the type specified by the + // second operand. + // The cv qualifiers are the union of those in the pointer and the left side, + // in accordance with 5.5p5 and 5.2.5. + QualType Result = MemPtr->getPointeeType(); + Result = Context.getCVRQualifiedType(Result, LHSType.getCVRQualifiers()); + + // C++0x [expr.mptr.oper]p6: + // In a .* expression whose object expression is an rvalue, the program is + // ill-formed if the second operand is a pointer to member function with + // ref-qualifier &. In a ->* expression or in a .* expression whose object + // expression is an lvalue, the program is ill-formed if the second operand + // is a pointer to member function with ref-qualifier &&. + if (const FunctionProtoType *Proto = Result->getAs()) { + switch (Proto->getRefQualifier()) { + case RQ_None: + // Do nothing + break; + + case RQ_LValue: + if (!isIndirect && !LHS.get()->Classify(Context).isLValue()) + Diag(Loc, diag::err_pointer_to_member_oper_value_classify) + << RHSType << 1 << LHS.get()->getSourceRange(); + break; + + case RQ_RValue: + if (isIndirect || !LHS.get()->Classify(Context).isRValue()) + Diag(Loc, diag::err_pointer_to_member_oper_value_classify) + << RHSType << 0 << LHS.get()->getSourceRange(); + break; + } + } + + // C++ [expr.mptr.oper]p6: + // The result of a .* expression whose second operand is a pointer + // to a data member is of the same value category as its + // first operand. The result of a .* expression whose second + // operand is a pointer to a member function is a prvalue. The + // result of an ->* expression is an lvalue if its second operand + // is a pointer to data member and a prvalue otherwise. + if (Result->isFunctionType()) { + VK = VK_RValue; + return Context.BoundMemberTy; + } else if (isIndirect) { + VK = VK_LValue; + } else { + VK = LHS.get()->getValueKind(); + } + + return Result; +} + +/// \brief Try to convert a type to another according to C++0x 5.16p3. +/// +/// This is part of the parameter validation for the ? operator. If either +/// value operand is a class type, the two operands are attempted to be +/// converted to each other. This function does the conversion in one direction. +/// It returns true if the program is ill-formed and has already been diagnosed +/// as such. +static bool TryClassUnification(Sema &Self, Expr *From, Expr *To, + SourceLocation QuestionLoc, + bool &HaveConversion, + QualType &ToType) { + HaveConversion = false; + ToType = To->getType(); + + InitializationKind Kind = InitializationKind::CreateCopy(To->getLocStart(), + SourceLocation()); + // C++0x 5.16p3 + // The process for determining whether an operand expression E1 of type T1 + // can be converted to match an operand expression E2 of type T2 is defined + // as follows: + // -- If E2 is an lvalue: + bool ToIsLvalue = To->isLValue(); + if (ToIsLvalue) { + // E1 can be converted to match E2 if E1 can be implicitly converted to + // type "lvalue reference to T2", subject to the constraint that in the + // conversion the reference must bind directly to E1. + QualType T = Self.Context.getLValueReferenceType(ToType); + InitializedEntity Entity = InitializedEntity::InitializeTemporary(T); + + InitializationSequence InitSeq(Self, Entity, Kind, &From, 1); + if (InitSeq.isDirectReferenceBinding()) { + ToType = T; + HaveConversion = true; + return false; + } + + if (InitSeq.isAmbiguous()) + return InitSeq.Diagnose(Self, Entity, Kind, &From, 1); + } + + // -- If E2 is an rvalue, or if the conversion above cannot be done: + // -- if E1 and E2 have class type, and the underlying class types are + // the same or one is a base class of the other: + QualType FTy = From->getType(); + QualType TTy = To->getType(); + const RecordType *FRec = FTy->getAs(); + const RecordType *TRec = TTy->getAs(); + bool FDerivedFromT = FRec && TRec && FRec != TRec && + Self.IsDerivedFrom(FTy, TTy); + if (FRec && TRec && + (FRec == TRec || FDerivedFromT || Self.IsDerivedFrom(TTy, FTy))) { + // E1 can be converted to match E2 if the class of T2 is the + // same type as, or a base class of, the class of T1, and + // [cv2 > cv1]. + if (FRec == TRec || FDerivedFromT) { + if (TTy.isAtLeastAsQualifiedAs(FTy)) { + InitializedEntity Entity = InitializedEntity::InitializeTemporary(TTy); + InitializationSequence InitSeq(Self, Entity, Kind, &From, 1); + if (InitSeq) { + HaveConversion = true; + return false; + } + + if (InitSeq.isAmbiguous()) + return InitSeq.Diagnose(Self, Entity, Kind, &From, 1); + } + } + + return false; + } + + // -- Otherwise: E1 can be converted to match E2 if E1 can be + // implicitly converted to the type that expression E2 would have + // if E2 were converted to an rvalue (or the type it has, if E2 is + // an rvalue). + // + // This actually refers very narrowly to the lvalue-to-rvalue conversion, not + // to the array-to-pointer or function-to-pointer conversions. + if (!TTy->getAs()) + TTy = TTy.getUnqualifiedType(); + + InitializedEntity Entity = InitializedEntity::InitializeTemporary(TTy); + InitializationSequence InitSeq(Self, Entity, Kind, &From, 1); + HaveConversion = !InitSeq.Failed(); + ToType = TTy; + if (InitSeq.isAmbiguous()) + return InitSeq.Diagnose(Self, Entity, Kind, &From, 1); + + return false; +} + +/// \brief Try to find a common type for two according to C++0x 5.16p5. +/// +/// This is part of the parameter validation for the ? operator. If either +/// value operand is a class type, overload resolution is used to find a +/// conversion to a common type. +static bool FindConditionalOverload(Sema &Self, ExprResult &LHS, ExprResult &RHS, + SourceLocation QuestionLoc) { + Expr *Args[2] = { LHS.get(), RHS.get() }; + OverloadCandidateSet CandidateSet(QuestionLoc); + Self.AddBuiltinOperatorCandidates(OO_Conditional, QuestionLoc, Args, 2, + CandidateSet); + + OverloadCandidateSet::iterator Best; + switch (CandidateSet.BestViableFunction(Self, QuestionLoc, Best)) { + case OR_Success: { + // We found a match. Perform the conversions on the arguments and move on. + ExprResult LHSRes = + Self.PerformImplicitConversion(LHS.get(), Best->BuiltinTypes.ParamTypes[0], + Best->Conversions[0], Sema::AA_Converting); + if (LHSRes.isInvalid()) + break; + LHS = move(LHSRes); + + ExprResult RHSRes = + Self.PerformImplicitConversion(RHS.get(), Best->BuiltinTypes.ParamTypes[1], + Best->Conversions[1], Sema::AA_Converting); + if (RHSRes.isInvalid()) + break; + RHS = move(RHSRes); + if (Best->Function) + Self.MarkFunctionReferenced(QuestionLoc, Best->Function); + return false; + } + + case OR_No_Viable_Function: + + // Emit a better diagnostic if one of the expressions is a null pointer + // constant and the other is a pointer type. In this case, the user most + // likely forgot to take the address of the other expression. + if (Self.DiagnoseConditionalForNull(LHS.get(), RHS.get(), QuestionLoc)) + return true; + + Self.Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands) + << LHS.get()->getType() << RHS.get()->getType() + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + return true; + + case OR_Ambiguous: + Self.Diag(QuestionLoc, diag::err_conditional_ambiguous_ovl) + << LHS.get()->getType() << RHS.get()->getType() + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + // FIXME: Print the possible common types by printing the return types of + // the viable candidates. + break; + + case OR_Deleted: + llvm_unreachable("Conditional operator has only built-in overloads"); + } + return true; +} + +/// \brief Perform an "extended" implicit conversion as returned by +/// TryClassUnification. +static bool ConvertForConditional(Sema &Self, ExprResult &E, QualType T) { + InitializedEntity Entity = InitializedEntity::InitializeTemporary(T); + InitializationKind Kind = InitializationKind::CreateCopy(E.get()->getLocStart(), + SourceLocation()); + Expr *Arg = E.take(); + InitializationSequence InitSeq(Self, Entity, Kind, &Arg, 1); + ExprResult Result = InitSeq.Perform(Self, Entity, Kind, MultiExprArg(&Arg, 1)); + if (Result.isInvalid()) + return true; + + E = Result; + return false; +} + +/// \brief Check the operands of ?: under C++ semantics. +/// +/// See C++ [expr.cond]. Note that LHS is never null, even for the GNU x ?: y +/// extension. In this case, LHS == Cond. (But they're not aliases.) +QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, ExprResult &RHS, + ExprValueKind &VK, ExprObjectKind &OK, + SourceLocation QuestionLoc) { + // FIXME: Handle C99's complex types, vector types, block pointers and Obj-C++ + // interface pointers. + + // C++0x 5.16p1 + // The first expression is contextually converted to bool. + if (!Cond.get()->isTypeDependent()) { + ExprResult CondRes = CheckCXXBooleanCondition(Cond.take()); + if (CondRes.isInvalid()) + return QualType(); + Cond = move(CondRes); + } + + // Assume r-value. + VK = VK_RValue; + OK = OK_Ordinary; + + // Either of the arguments dependent? + if (LHS.get()->isTypeDependent() || RHS.get()->isTypeDependent()) + return Context.DependentTy; + + // C++0x 5.16p2 + // If either the second or the third operand has type (cv) void, ... + QualType LTy = LHS.get()->getType(); + QualType RTy = RHS.get()->getType(); + bool LVoid = LTy->isVoidType(); + bool RVoid = RTy->isVoidType(); + if (LVoid || RVoid) { + // ... then the [l2r] conversions are performed on the second and third + // operands ... + LHS = DefaultFunctionArrayLvalueConversion(LHS.take()); + RHS = DefaultFunctionArrayLvalueConversion(RHS.take()); + if (LHS.isInvalid() || RHS.isInvalid()) + return QualType(); + LTy = LHS.get()->getType(); + RTy = RHS.get()->getType(); + + // ... and one of the following shall hold: + // -- The second or the third operand (but not both) is a throw- + // expression; the result is of the type of the other and is an rvalue. + bool LThrow = isa(LHS.get()); + bool RThrow = isa(RHS.get()); + if (LThrow && !RThrow) + return RTy; + if (RThrow && !LThrow) + return LTy; + + // -- Both the second and third operands have type void; the result is of + // type void and is an rvalue. + if (LVoid && RVoid) + return Context.VoidTy; + + // Neither holds, error. + Diag(QuestionLoc, diag::err_conditional_void_nonvoid) + << (LVoid ? RTy : LTy) << (LVoid ? 0 : 1) + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + return QualType(); + } + + // Neither is void. + + // C++0x 5.16p3 + // Otherwise, if the second and third operand have different types, and + // either has (cv) class type, and attempt is made to convert each of those + // operands to the other. + if (!Context.hasSameType(LTy, RTy) && + (LTy->isRecordType() || RTy->isRecordType())) { + ImplicitConversionSequence ICSLeftToRight, ICSRightToLeft; + // These return true if a single direction is already ambiguous. + QualType L2RType, R2LType; + bool HaveL2R, HaveR2L; + if (TryClassUnification(*this, LHS.get(), RHS.get(), QuestionLoc, HaveL2R, L2RType)) + return QualType(); + if (TryClassUnification(*this, RHS.get(), LHS.get(), QuestionLoc, HaveR2L, R2LType)) + return QualType(); + + // If both can be converted, [...] the program is ill-formed. + if (HaveL2R && HaveR2L) { + Diag(QuestionLoc, diag::err_conditional_ambiguous) + << LTy << RTy << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + return QualType(); + } + + // If exactly one conversion is possible, that conversion is applied to + // the chosen operand and the converted operands are used in place of the + // original operands for the remainder of this section. + if (HaveL2R) { + if (ConvertForConditional(*this, LHS, L2RType) || LHS.isInvalid()) + return QualType(); + LTy = LHS.get()->getType(); + } else if (HaveR2L) { + if (ConvertForConditional(*this, RHS, R2LType) || RHS.isInvalid()) + return QualType(); + RTy = RHS.get()->getType(); + } + } + + // C++0x 5.16p4 + // If the second and third operands are glvalues of the same value + // category and have the same type, the result is of that type and + // value category and it is a bit-field if the second or the third + // operand is a bit-field, or if both are bit-fields. + // We only extend this to bitfields, not to the crazy other kinds of + // l-values. + bool Same = Context.hasSameType(LTy, RTy); + if (Same && + LHS.get()->isGLValue() && + LHS.get()->getValueKind() == RHS.get()->getValueKind() && + LHS.get()->isOrdinaryOrBitFieldObject() && + RHS.get()->isOrdinaryOrBitFieldObject()) { + VK = LHS.get()->getValueKind(); + if (LHS.get()->getObjectKind() == OK_BitField || + RHS.get()->getObjectKind() == OK_BitField) + OK = OK_BitField; + return LTy; + } + + // C++0x 5.16p5 + // Otherwise, the result is an rvalue. If the second and third operands + // do not have the same type, and either has (cv) class type, ... + if (!Same && (LTy->isRecordType() || RTy->isRecordType())) { + // ... overload resolution is used to determine the conversions (if any) + // to be applied to the operands. If the overload resolution fails, the + // program is ill-formed. + if (FindConditionalOverload(*this, LHS, RHS, QuestionLoc)) + return QualType(); + } + + // C++0x 5.16p6 + // LValue-to-rvalue, array-to-pointer, and function-to-pointer standard + // conversions are performed on the second and third operands. + LHS = DefaultFunctionArrayLvalueConversion(LHS.take()); + RHS = DefaultFunctionArrayLvalueConversion(RHS.take()); + if (LHS.isInvalid() || RHS.isInvalid()) + return QualType(); + LTy = LHS.get()->getType(); + RTy = RHS.get()->getType(); + + // After those conversions, one of the following shall hold: + // -- The second and third operands have the same type; the result + // is of that type. If the operands have class type, the result + // is a prvalue temporary of the result type, which is + // copy-initialized from either the second operand or the third + // operand depending on the value of the first operand. + if (Context.getCanonicalType(LTy) == Context.getCanonicalType(RTy)) { + if (LTy->isRecordType()) { + // The operands have class type. Make a temporary copy. + InitializedEntity Entity = InitializedEntity::InitializeTemporary(LTy); + ExprResult LHSCopy = PerformCopyInitialization(Entity, + SourceLocation(), + LHS); + if (LHSCopy.isInvalid()) + return QualType(); + + ExprResult RHSCopy = PerformCopyInitialization(Entity, + SourceLocation(), + RHS); + if (RHSCopy.isInvalid()) + return QualType(); + + LHS = LHSCopy; + RHS = RHSCopy; + } + + return LTy; + } + + // Extension: conditional operator involving vector types. + if (LTy->isVectorType() || RTy->isVectorType()) + return CheckVectorOperands(LHS, RHS, QuestionLoc, /*isCompAssign*/false); + + // -- The second and third operands have arithmetic or enumeration type; + // the usual arithmetic conversions are performed to bring them to a + // common type, and the result is of that type. + if (LTy->isArithmeticType() && RTy->isArithmeticType()) { + UsualArithmeticConversions(LHS, RHS); + if (LHS.isInvalid() || RHS.isInvalid()) + return QualType(); + return LHS.get()->getType(); + } + + // -- The second and third operands have pointer type, or one has pointer + // type and the other is a null pointer constant; pointer conversions + // and qualification conversions are performed to bring them to their + // composite pointer type. The result is of the composite pointer type. + // -- The second and third operands have pointer to member type, or one has + // pointer to member type and the other is a null pointer constant; + // pointer to member conversions and qualification conversions are + // performed to bring them to a common type, whose cv-qualification + // shall match the cv-qualification of either the second or the third + // operand. The result is of the common type. + bool NonStandardCompositeType = false; + QualType Composite = FindCompositePointerType(QuestionLoc, LHS, RHS, + isSFINAEContext()? 0 : &NonStandardCompositeType); + if (!Composite.isNull()) { + if (NonStandardCompositeType) + Diag(QuestionLoc, + diag::ext_typecheck_cond_incompatible_operands_nonstandard) + << LTy << RTy << Composite + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + + return Composite; + } + + // Similarly, attempt to find composite type of two objective-c pointers. + Composite = FindCompositeObjCPointerType(LHS, RHS, QuestionLoc); + if (!Composite.isNull()) + return Composite; + + // Check if we are using a null with a non-pointer type. + if (DiagnoseConditionalForNull(LHS.get(), RHS.get(), QuestionLoc)) + return QualType(); + + Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands) + << LHS.get()->getType() << RHS.get()->getType() + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + return QualType(); +} + +/// \brief Find a merged pointer type and convert the two expressions to it. +/// +/// This finds the composite pointer type (or member pointer type) for @p E1 +/// and @p E2 according to C++0x 5.9p2. It converts both expressions to this +/// type and returns it. +/// It does not emit diagnostics. +/// +/// \param Loc The location of the operator requiring these two expressions to +/// be converted to the composite pointer type. +/// +/// If \p NonStandardCompositeType is non-NULL, then we are permitted to find +/// a non-standard (but still sane) composite type to which both expressions +/// can be converted. When such a type is chosen, \c *NonStandardCompositeType +/// will be set true. +QualType Sema::FindCompositePointerType(SourceLocation Loc, + Expr *&E1, Expr *&E2, + bool *NonStandardCompositeType) { + if (NonStandardCompositeType) + *NonStandardCompositeType = false; + + assert(getLangOpts().CPlusPlus && "This function assumes C++"); + QualType T1 = E1->getType(), T2 = E2->getType(); + + if (!T1->isAnyPointerType() && !T1->isMemberPointerType() && + !T2->isAnyPointerType() && !T2->isMemberPointerType()) + return QualType(); + + // C++0x 5.9p2 + // Pointer conversions and qualification conversions are performed on + // pointer operands to bring them to their composite pointer type. If + // one operand is a null pointer constant, the composite pointer type is + // the type of the other operand. + if (E1->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { + if (T2->isMemberPointerType()) + E1 = ImpCastExprToType(E1, T2, CK_NullToMemberPointer).take(); + else + E1 = ImpCastExprToType(E1, T2, CK_NullToPointer).take(); + return T2; + } + if (E2->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { + if (T1->isMemberPointerType()) + E2 = ImpCastExprToType(E2, T1, CK_NullToMemberPointer).take(); + else + E2 = ImpCastExprToType(E2, T1, CK_NullToPointer).take(); + return T1; + } + + // Now both have to be pointers or member pointers. + if ((!T1->isPointerType() && !T1->isMemberPointerType()) || + (!T2->isPointerType() && !T2->isMemberPointerType())) + return QualType(); + + // Otherwise, of one of the operands has type "pointer to cv1 void," then + // the other has type "pointer to cv2 T" and the composite pointer type is + // "pointer to cv12 void," where cv12 is the union of cv1 and cv2. + // Otherwise, the composite pointer type is a pointer type similar to the + // type of one of the operands, with a cv-qualification signature that is + // the union of the cv-qualification signatures of the operand types. + // In practice, the first part here is redundant; it's subsumed by the second. + // What we do here is, we build the two possible composite types, and try the + // conversions in both directions. If only one works, or if the two composite + // types are the same, we have succeeded. + // FIXME: extended qualifiers? + typedef SmallVector QualifierVector; + QualifierVector QualifierUnion; + typedef SmallVector, 4> + ContainingClassVector; + ContainingClassVector MemberOfClass; + QualType Composite1 = Context.getCanonicalType(T1), + Composite2 = Context.getCanonicalType(T2); + unsigned NeedConstBefore = 0; + do { + const PointerType *Ptr1, *Ptr2; + if ((Ptr1 = Composite1->getAs()) && + (Ptr2 = Composite2->getAs())) { + Composite1 = Ptr1->getPointeeType(); + Composite2 = Ptr2->getPointeeType(); + + // If we're allowed to create a non-standard composite type, keep track + // of where we need to fill in additional 'const' qualifiers. + if (NonStandardCompositeType && + Composite1.getCVRQualifiers() != Composite2.getCVRQualifiers()) + NeedConstBefore = QualifierUnion.size(); + + QualifierUnion.push_back( + Composite1.getCVRQualifiers() | Composite2.getCVRQualifiers()); + MemberOfClass.push_back(std::make_pair((const Type *)0, (const Type *)0)); + continue; + } + + const MemberPointerType *MemPtr1, *MemPtr2; + if ((MemPtr1 = Composite1->getAs()) && + (MemPtr2 = Composite2->getAs())) { + Composite1 = MemPtr1->getPointeeType(); + Composite2 = MemPtr2->getPointeeType(); + + // If we're allowed to create a non-standard composite type, keep track + // of where we need to fill in additional 'const' qualifiers. + if (NonStandardCompositeType && + Composite1.getCVRQualifiers() != Composite2.getCVRQualifiers()) + NeedConstBefore = QualifierUnion.size(); + + QualifierUnion.push_back( + Composite1.getCVRQualifiers() | Composite2.getCVRQualifiers()); + MemberOfClass.push_back(std::make_pair(MemPtr1->getClass(), + MemPtr2->getClass())); + continue; + } + + // FIXME: block pointer types? + + // Cannot unwrap any more types. + break; + } while (true); + + if (NeedConstBefore && NonStandardCompositeType) { + // Extension: Add 'const' to qualifiers that come before the first qualifier + // mismatch, so that our (non-standard!) composite type meets the + // requirements of C++ [conv.qual]p4 bullet 3. + for (unsigned I = 0; I != NeedConstBefore; ++I) { + if ((QualifierUnion[I] & Qualifiers::Const) == 0) { + QualifierUnion[I] = QualifierUnion[I] | Qualifiers::Const; + *NonStandardCompositeType = true; + } + } + } + + // Rewrap the composites as pointers or member pointers with the union CVRs. + ContainingClassVector::reverse_iterator MOC + = MemberOfClass.rbegin(); + for (QualifierVector::reverse_iterator + I = QualifierUnion.rbegin(), + E = QualifierUnion.rend(); + I != E; (void)++I, ++MOC) { + Qualifiers Quals = Qualifiers::fromCVRMask(*I); + if (MOC->first && MOC->second) { + // Rebuild member pointer type + Composite1 = Context.getMemberPointerType( + Context.getQualifiedType(Composite1, Quals), + MOC->first); + Composite2 = Context.getMemberPointerType( + Context.getQualifiedType(Composite2, Quals), + MOC->second); + } else { + // Rebuild pointer type + Composite1 + = Context.getPointerType(Context.getQualifiedType(Composite1, Quals)); + Composite2 + = Context.getPointerType(Context.getQualifiedType(Composite2, Quals)); + } + } + + // Try to convert to the first composite pointer type. + InitializedEntity Entity1 + = InitializedEntity::InitializeTemporary(Composite1); + InitializationKind Kind + = InitializationKind::CreateCopy(Loc, SourceLocation()); + InitializationSequence E1ToC1(*this, Entity1, Kind, &E1, 1); + InitializationSequence E2ToC1(*this, Entity1, Kind, &E2, 1); + + if (E1ToC1 && E2ToC1) { + // Conversion to Composite1 is viable. + if (!Context.hasSameType(Composite1, Composite2)) { + // Composite2 is a different type from Composite1. Check whether + // Composite2 is also viable. + InitializedEntity Entity2 + = InitializedEntity::InitializeTemporary(Composite2); + InitializationSequence E1ToC2(*this, Entity2, Kind, &E1, 1); + InitializationSequence E2ToC2(*this, Entity2, Kind, &E2, 1); + if (E1ToC2 && E2ToC2) { + // Both Composite1 and Composite2 are viable and are different; + // this is an ambiguity. + return QualType(); + } + } + + // Convert E1 to Composite1 + ExprResult E1Result + = E1ToC1.Perform(*this, Entity1, Kind, MultiExprArg(*this,&E1,1)); + if (E1Result.isInvalid()) + return QualType(); + E1 = E1Result.takeAs(); + + // Convert E2 to Composite1 + ExprResult E2Result + = E2ToC1.Perform(*this, Entity1, Kind, MultiExprArg(*this,&E2,1)); + if (E2Result.isInvalid()) + return QualType(); + E2 = E2Result.takeAs(); + + return Composite1; + } + + // Check whether Composite2 is viable. + InitializedEntity Entity2 + = InitializedEntity::InitializeTemporary(Composite2); + InitializationSequence E1ToC2(*this, Entity2, Kind, &E1, 1); + InitializationSequence E2ToC2(*this, Entity2, Kind, &E2, 1); + if (!E1ToC2 || !E2ToC2) + return QualType(); + + // Convert E1 to Composite2 + ExprResult E1Result + = E1ToC2.Perform(*this, Entity2, Kind, MultiExprArg(*this, &E1, 1)); + if (E1Result.isInvalid()) + return QualType(); + E1 = E1Result.takeAs(); + + // Convert E2 to Composite2 + ExprResult E2Result + = E2ToC2.Perform(*this, Entity2, Kind, MultiExprArg(*this, &E2, 1)); + if (E2Result.isInvalid()) + return QualType(); + E2 = E2Result.takeAs(); + + return Composite2; +} + +ExprResult Sema::MaybeBindToTemporary(Expr *E) { + if (!E) + return ExprError(); + + assert(!isa(E) && "Double-bound temporary?"); + + // If the result is a glvalue, we shouldn't bind it. + if (!E->isRValue()) + return Owned(E); + + // In ARC, calls that return a retainable type can return retained, + // in which case we have to insert a consuming cast. + if (getLangOpts().ObjCAutoRefCount && + E->getType()->isObjCRetainableType()) { + + bool ReturnsRetained; + + // For actual calls, we compute this by examining the type of the + // called value. + if (CallExpr *Call = dyn_cast(E)) { + Expr *Callee = Call->getCallee()->IgnoreParens(); + QualType T = Callee->getType(); + + if (T == Context.BoundMemberTy) { + // Handle pointer-to-members. + if (BinaryOperator *BinOp = dyn_cast(Callee)) + T = BinOp->getRHS()->getType(); + else if (MemberExpr *Mem = dyn_cast(Callee)) + T = Mem->getMemberDecl()->getType(); + } + + if (const PointerType *Ptr = T->getAs()) + T = Ptr->getPointeeType(); + else if (const BlockPointerType *Ptr = T->getAs()) + T = Ptr->getPointeeType(); + else if (const MemberPointerType *MemPtr = T->getAs()) + T = MemPtr->getPointeeType(); + + const FunctionType *FTy = T->getAs(); + assert(FTy && "call to value not of function type?"); + ReturnsRetained = FTy->getExtInfo().getProducesResult(); + + // ActOnStmtExpr arranges things so that StmtExprs of retainable + // type always produce a +1 object. + } else if (isa(E)) { + ReturnsRetained = true; + + // We hit this case with the lambda conversion-to-block optimization; + // we don't want any extra casts here. + } else if (isa(E) && + isa(cast(E)->getSubExpr())) { + return Owned(E); + + // For message sends and property references, we try to find an + // actual method. FIXME: we should infer retention by selector in + // cases where we don't have an actual method. + } else { + ObjCMethodDecl *D = 0; + if (ObjCMessageExpr *Send = dyn_cast(E)) { + D = Send->getMethodDecl(); + } else if (ObjCNumericLiteral *NumLit = dyn_cast(E)) { + D = NumLit->getObjCNumericLiteralMethod(); + } else if (ObjCArrayLiteral *ArrayLit = dyn_cast(E)) { + D = ArrayLit->getArrayWithObjectsMethod(); + } else if (ObjCDictionaryLiteral *DictLit + = dyn_cast(E)) { + D = DictLit->getDictWithObjectsMethod(); + } + + ReturnsRetained = (D && D->hasAttr()); + + // Don't do reclaims on performSelector calls; despite their + // return type, the invoked method doesn't necessarily actually + // return an object. + if (!ReturnsRetained && + D && D->getMethodFamily() == OMF_performSelector) + return Owned(E); + } + + // Don't reclaim an object of Class type. + if (!ReturnsRetained && E->getType()->isObjCARCImplicitlyUnretainedType()) + return Owned(E); + + ExprNeedsCleanups = true; + + CastKind ck = (ReturnsRetained ? CK_ARCConsumeObject + : CK_ARCReclaimReturnedObject); + return Owned(ImplicitCastExpr::Create(Context, E->getType(), ck, E, 0, + VK_RValue)); + } + + if (!getLangOpts().CPlusPlus) + return Owned(E); + + // Search for the base element type (cf. ASTContext::getBaseElementType) with + // a fast path for the common case that the type is directly a RecordType. + const Type *T = Context.getCanonicalType(E->getType().getTypePtr()); + const RecordType *RT = 0; + while (!RT) { + switch (T->getTypeClass()) { + case Type::Record: + RT = cast(T); + break; + case Type::ConstantArray: + case Type::IncompleteArray: + case Type::VariableArray: + case Type::DependentSizedArray: + T = cast(T)->getElementType().getTypePtr(); + break; + default: + return Owned(E); + } + } + + // That should be enough to guarantee that this type is complete, if we're + // not processing a decltype expression. + CXXRecordDecl *RD = cast(RT->getDecl()); + if (RD->isInvalidDecl() || RD->isDependentContext()) + return Owned(E); + + bool IsDecltype = ExprEvalContexts.back().IsDecltype; + CXXDestructorDecl *Destructor = IsDecltype ? 0 : LookupDestructor(RD); + + if (Destructor) { + MarkFunctionReferenced(E->getExprLoc(), Destructor); + CheckDestructorAccess(E->getExprLoc(), Destructor, + PDiag(diag::err_access_dtor_temp) + << E->getType()); + DiagnoseUseOfDecl(Destructor, E->getExprLoc()); + + // If destructor is trivial, we can avoid the extra copy. + if (Destructor->isTrivial()) + return Owned(E); + + // We need a cleanup, but we don't need to remember the temporary. + ExprNeedsCleanups = true; + } + + CXXTemporary *Temp = CXXTemporary::Create(Context, Destructor); + CXXBindTemporaryExpr *Bind = CXXBindTemporaryExpr::Create(Context, Temp, E); + + if (IsDecltype) + ExprEvalContexts.back().DelayedDecltypeBinds.push_back(Bind); + + return Owned(Bind); +} + +ExprResult +Sema::MaybeCreateExprWithCleanups(ExprResult SubExpr) { + if (SubExpr.isInvalid()) + return ExprError(); + + return Owned(MaybeCreateExprWithCleanups(SubExpr.take())); +} + +Expr *Sema::MaybeCreateExprWithCleanups(Expr *SubExpr) { + assert(SubExpr && "sub expression can't be null!"); + + CleanupVarDeclMarking(); + + unsigned FirstCleanup = ExprEvalContexts.back().NumCleanupObjects; + assert(ExprCleanupObjects.size() >= FirstCleanup); + assert(ExprNeedsCleanups || ExprCleanupObjects.size() == FirstCleanup); + if (!ExprNeedsCleanups) + return SubExpr; + + ArrayRef Cleanups + = llvm::makeArrayRef(ExprCleanupObjects.begin() + FirstCleanup, + ExprCleanupObjects.size() - FirstCleanup); + + Expr *E = ExprWithCleanups::Create(Context, SubExpr, Cleanups); + DiscardCleanupsInEvaluationContext(); + + return E; +} + +Stmt *Sema::MaybeCreateStmtWithCleanups(Stmt *SubStmt) { + assert(SubStmt && "sub statement can't be null!"); + + CleanupVarDeclMarking(); + + if (!ExprNeedsCleanups) + return SubStmt; + + // FIXME: In order to attach the temporaries, wrap the statement into + // a StmtExpr; currently this is only used for asm statements. + // This is hacky, either create a new CXXStmtWithTemporaries statement or + // a new AsmStmtWithTemporaries. + CompoundStmt *CompStmt = new (Context) CompoundStmt(Context, &SubStmt, 1, + SourceLocation(), + SourceLocation()); + Expr *E = new (Context) StmtExpr(CompStmt, Context.VoidTy, SourceLocation(), + SourceLocation()); + return MaybeCreateExprWithCleanups(E); +} + +/// Process the expression contained within a decltype. For such expressions, +/// certain semantic checks on temporaries are delayed until this point, and +/// are omitted for the 'topmost' call in the decltype expression. If the +/// topmost call bound a temporary, strip that temporary off the expression. +ExprResult Sema::ActOnDecltypeExpression(Expr *E) { + ExpressionEvaluationContextRecord &Rec = ExprEvalContexts.back(); + assert(Rec.IsDecltype && "not in a decltype expression"); + + // C++11 [expr.call]p11: + // If a function call is a prvalue of object type, + // -- if the function call is either + // -- the operand of a decltype-specifier, or + // -- the right operand of a comma operator that is the operand of a + // decltype-specifier, + // a temporary object is not introduced for the prvalue. + + // Recursively rebuild ParenExprs and comma expressions to strip out the + // outermost CXXBindTemporaryExpr, if any. + if (ParenExpr *PE = dyn_cast(E)) { + ExprResult SubExpr = ActOnDecltypeExpression(PE->getSubExpr()); + if (SubExpr.isInvalid()) + return ExprError(); + if (SubExpr.get() == PE->getSubExpr()) + return Owned(E); + return ActOnParenExpr(PE->getLParen(), PE->getRParen(), SubExpr.take()); + } + if (BinaryOperator *BO = dyn_cast(E)) { + if (BO->getOpcode() == BO_Comma) { + ExprResult RHS = ActOnDecltypeExpression(BO->getRHS()); + if (RHS.isInvalid()) + return ExprError(); + if (RHS.get() == BO->getRHS()) + return Owned(E); + return Owned(new (Context) BinaryOperator(BO->getLHS(), RHS.take(), + BO_Comma, BO->getType(), + BO->getValueKind(), + BO->getObjectKind(), + BO->getOperatorLoc())); + } + } + + CXXBindTemporaryExpr *TopBind = dyn_cast(E); + if (TopBind) + E = TopBind->getSubExpr(); + + // Disable the special decltype handling now. + Rec.IsDecltype = false; + + // Perform the semantic checks we delayed until this point. + CallExpr *TopCall = dyn_cast(E); + for (unsigned I = 0, N = Rec.DelayedDecltypeCalls.size(); I != N; ++I) { + CallExpr *Call = Rec.DelayedDecltypeCalls[I]; + if (Call == TopCall) + continue; + + if (CheckCallReturnType(Call->getCallReturnType(), + Call->getLocStart(), + Call, Call->getDirectCallee())) + return ExprError(); + } + + // Now all relevant types are complete, check the destructors are accessible + // and non-deleted, and annotate them on the temporaries. + for (unsigned I = 0, N = Rec.DelayedDecltypeBinds.size(); I != N; ++I) { + CXXBindTemporaryExpr *Bind = Rec.DelayedDecltypeBinds[I]; + if (Bind == TopBind) + continue; + + CXXTemporary *Temp = Bind->getTemporary(); + + CXXRecordDecl *RD = + Bind->getType()->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); + CXXDestructorDecl *Destructor = LookupDestructor(RD); + Temp->setDestructor(Destructor); + + MarkFunctionReferenced(E->getExprLoc(), Destructor); + CheckDestructorAccess(E->getExprLoc(), Destructor, + PDiag(diag::err_access_dtor_temp) + << E->getType()); + DiagnoseUseOfDecl(Destructor, E->getExprLoc()); + + // We need a cleanup, but we don't need to remember the temporary. + ExprNeedsCleanups = true; + } + + // Possibly strip off the top CXXBindTemporaryExpr. + return Owned(E); +} + +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. + ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Base); + if (Result.isInvalid()) return ExprError(); + Base = Result.get(); + + Result = CheckPlaceholderExpr(Base); + if (Result.isInvalid()) return ExprError(); + Base = Result.take(); + + QualType BaseType = Base->getType(); + MayBePseudoDestructor = false; + if (BaseType->isDependentType()) { + // If we have a pointer to a dependent type and are using the -> operator, + // the object type is the type that the pointer points to. We might still + // have enough information about that type to do something useful. + if (OpKind == tok::arrow) + if (const PointerType *Ptr = BaseType->getAs()) + BaseType = Ptr->getPointeeType(); + + ObjectType = ParsedType::make(BaseType); + MayBePseudoDestructor = true; + return Owned(Base); + } + + // C++ [over.match.oper]p8: + // [...] When operator->returns, the operator-> is applied to the value + // returned, with the original second operand. + if (OpKind == tok::arrow) { + // The set of types we've considered so far. + llvm::SmallPtrSet CTypes; + SmallVector Locations; + CTypes.insert(Context.getCanonicalType(BaseType)); + + while (BaseType->isRecordType()) { + Result = BuildOverloadedArrowExpr(S, Base, OpLoc); + if (Result.isInvalid()) + return ExprError(); + Base = Result.get(); + if (CXXOperatorCallExpr *OpCall = dyn_cast(Base)) + Locations.push_back(OpCall->getDirectCallee()->getLocation()); + BaseType = Base->getType(); + CanQualType CBaseType = Context.getCanonicalType(BaseType); + if (!CTypes.insert(CBaseType)) { + Diag(OpLoc, diag::err_operator_arrow_circular); + for (unsigned i = 0; i < Locations.size(); i++) + Diag(Locations[i], diag::note_declared_at); + return ExprError(); + } + } + + if (BaseType->isPointerType() || BaseType->isObjCObjectPointerType()) + BaseType = BaseType->getPointeeType(); + } + + // Objective-C properties allow "." access on Objective-C pointer types, + // so adjust the base type to the object type itself. + if (BaseType->isObjCObjectPointerType()) + BaseType = BaseType->getPointeeType(); + + // C++ [basic.lookup.classref]p2: + // [...] If the type of the object expression is of pointer to scalar + // type, the unqualified-id is looked up in the context of the complete + // postfix-expression. + // + // This also indicates that we could be parsing a pseudo-destructor-name. + // Note that Objective-C class and object types can be pseudo-destructor + // expressions or normal member (ivar or property) access expressions. + if (BaseType->isObjCObjectOrInterfaceType()) { + MayBePseudoDestructor = true; + } else if (!BaseType->isRecordType()) { + ObjectType = ParsedType(); + MayBePseudoDestructor = true; + return Owned(Base); + } + + // The object type must be complete (or dependent), or + // C++11 [expr.prim.general]p3: + // Unlike the object expression in other contexts, *this is not required to + // be of complete type for purposes of class member access (5.2.5) outside + // the member function body. + if (!BaseType->isDependentType() && + !isThisOutsideMemberFunctionBody(BaseType) && + RequireCompleteType(OpLoc, BaseType, + PDiag(diag::err_incomplete_member_access))) + return ExprError(); + + // C++ [basic.lookup.classref]p2: + // If the id-expression in a class member access (5.2.5) is an + // 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 = ParsedType::make(BaseType); + return move(Base); +} + +ExprResult Sema::DiagnoseDtorReference(SourceLocation NameLoc, + Expr *MemExpr) { + SourceLocation ExpectedLParenLoc = PP.getLocForEndOfToken(NameLoc); + Diag(MemExpr->getLocStart(), diag::err_dtor_expr_without_call) + << isa(MemExpr) + << FixItHint::CreateInsertion(ExpectedLParenLoc, "()"); + + return ActOnCallExpr(/*Scope*/ 0, + MemExpr, + /*LPLoc*/ ExpectedLParenLoc, + MultiExprArg(), + /*RPLoc*/ ExpectedLParenLoc); +} + +static bool CheckArrow(Sema& S, QualType& ObjectType, Expr *&Base, + tok::TokenKind& OpKind, SourceLocation OpLoc) { + if (Base->hasPlaceholderType()) { + ExprResult result = S.CheckPlaceholderExpr(Base); + if (result.isInvalid()) return true; + Base = result.take(); + } + ObjectType = Base->getType(); + + // 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. + // Note that this is rather different from the normal handling for the + // arrow operator. + if (OpKind == tok::arrow) { + if (const PointerType *Ptr = ObjectType->getAs()) { + ObjectType = Ptr->getPointeeType(); + } else if (!Base->isTypeDependent()) { + // The user wrote "p->" when she probably meant "p."; fix it. + S.Diag(OpLoc, diag::err_typecheck_member_reference_suggestion) + << ObjectType << true + << FixItHint::CreateReplacement(OpLoc, "."); + if (S.isSFINAEContext()) + return true; + + OpKind = tok::period; + } + } + + return false; +} + +ExprResult Sema::BuildPseudoDestructorExpr(Expr *Base, + SourceLocation OpLoc, + tok::TokenKind OpKind, + const CXXScopeSpec &SS, + TypeSourceInfo *ScopeTypeInfo, + SourceLocation CCLoc, + SourceLocation TildeLoc, + PseudoDestructorTypeStorage Destructed, + bool HasTrailingLParen) { + TypeSourceInfo *DestructedTypeInfo = Destructed.getTypeSourceInfo(); + + QualType ObjectType; + if (CheckArrow(*this, ObjectType, Base, OpKind, OpLoc)) + return ExprError(); + + if (!ObjectType->isDependentType() && !ObjectType->isScalarType()) { + if (getLangOpts().MicrosoftMode && ObjectType->isVoidType()) + Diag(OpLoc, diag::ext_pseudo_dtor_on_void) << Base->getSourceRange(); + else + Diag(OpLoc, diag::err_pseudo_dtor_base_not_scalar) + << ObjectType << Base->getSourceRange(); + return ExprError(); + } + + // C++ [expr.pseudo]p2: + // [...] The cv-unqualified versions of the object type and of the type + // designated by the pseudo-destructor-name shall be the same type. + if (DestructedTypeInfo) { + QualType DestructedType = DestructedTypeInfo->getType(); + SourceLocation DestructedTypeStart + = DestructedTypeInfo->getTypeLoc().getLocalSourceRange().getBegin(); + if (!DestructedType->isDependentType() && !ObjectType->isDependentType()) { + if (!Context.hasSameUnqualifiedType(DestructedType, ObjectType)) { + Diag(DestructedTypeStart, diag::err_pseudo_dtor_type_mismatch) + << ObjectType << DestructedType << Base->getSourceRange() + << DestructedTypeInfo->getTypeLoc().getLocalSourceRange(); + + // Recover by setting the destructed type to the object type. + DestructedType = ObjectType; + DestructedTypeInfo = Context.getTrivialTypeSourceInfo(ObjectType, + DestructedTypeStart); + Destructed = PseudoDestructorTypeStorage(DestructedTypeInfo); + } else if (DestructedType.getObjCLifetime() != + ObjectType.getObjCLifetime()) { + + if (DestructedType.getObjCLifetime() == Qualifiers::OCL_None) { + // Okay: just pretend that the user provided the correctly-qualified + // type. + } else { + Diag(DestructedTypeStart, diag::err_arc_pseudo_dtor_inconstant_quals) + << ObjectType << DestructedType << Base->getSourceRange() + << DestructedTypeInfo->getTypeLoc().getLocalSourceRange(); + } + + // Recover by setting the destructed type to the object type. + DestructedType = ObjectType; + DestructedTypeInfo = Context.getTrivialTypeSourceInfo(ObjectType, + DestructedTypeStart); + Destructed = PseudoDestructorTypeStorage(DestructedTypeInfo); + } + } + } + + // C++ [expr.pseudo]p2: + // [...] Furthermore, the two type-names in a pseudo-destructor-name of the + // form + // + // ::[opt] nested-name-specifier[opt] type-name :: ~ type-name + // + // shall designate the same scalar type. + if (ScopeTypeInfo) { + QualType ScopeType = ScopeTypeInfo->getType(); + if (!ScopeType->isDependentType() && !ObjectType->isDependentType() && + !Context.hasSameUnqualifiedType(ScopeType, ObjectType)) { + + Diag(ScopeTypeInfo->getTypeLoc().getLocalSourceRange().getBegin(), + diag::err_pseudo_dtor_type_mismatch) + << ObjectType << ScopeType << Base->getSourceRange() + << ScopeTypeInfo->getTypeLoc().getLocalSourceRange(); + + ScopeType = QualType(); + ScopeTypeInfo = 0; + } + } + + Expr *Result + = new (Context) CXXPseudoDestructorExpr(Context, Base, + OpKind == tok::arrow, OpLoc, + SS.getWithLocInContext(Context), + ScopeTypeInfo, + CCLoc, + TildeLoc, + Destructed); + + if (HasTrailingLParen) + return Owned(Result); + + return DiagnoseDtorReference(Destructed.getLocation(), Result); +} + +ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, + SourceLocation OpLoc, + tok::TokenKind OpKind, + CXXScopeSpec &SS, + UnqualifiedId &FirstTypeName, + SourceLocation CCLoc, + SourceLocation TildeLoc, + UnqualifiedId &SecondTypeName, + bool HasTrailingLParen) { + assert((FirstTypeName.getKind() == UnqualifiedId::IK_TemplateId || + FirstTypeName.getKind() == UnqualifiedId::IK_Identifier) && + "Invalid first type name in pseudo-destructor"); + assert((SecondTypeName.getKind() == UnqualifiedId::IK_TemplateId || + SecondTypeName.getKind() == UnqualifiedId::IK_Identifier) && + "Invalid second type name in pseudo-destructor"); + + QualType ObjectType; + if (CheckArrow(*this, ObjectType, Base, OpKind, OpLoc)) + return ExprError(); + + // Compute the object type that we should use for name lookup purposes. Only + // record types and dependent types matter. + ParsedType ObjectTypePtrForLookup; + if (!SS.isSet()) { + if (ObjectType->isRecordType()) + ObjectTypePtrForLookup = ParsedType::make(ObjectType); + else if (ObjectType->isDependentType()) + ObjectTypePtrForLookup = ParsedType::make(Context.DependentTy); + } + + // Convert the name of the type being destructed (following the ~) into a + // type (with source-location information). + QualType DestructedType; + TypeSourceInfo *DestructedTypeInfo = 0; + PseudoDestructorTypeStorage Destructed; + if (SecondTypeName.getKind() == UnqualifiedId::IK_Identifier) { + ParsedType T = getTypeName(*SecondTypeName.Identifier, + SecondTypeName.StartLocation, + S, &SS, true, false, ObjectTypePtrForLookup); + if (!T && + ((SS.isSet() && !computeDeclContext(SS, false)) || + (!SS.isSet() && ObjectType->isDependentType()))) { + // The name of the type being destroyed is a dependent name, and we + // couldn't find anything useful in scope. Just store the identifier and + // it's location, and we'll perform (qualified) name lookup again at + // template instantiation time. + Destructed = PseudoDestructorTypeStorage(SecondTypeName.Identifier, + SecondTypeName.StartLocation); + } else if (!T) { + Diag(SecondTypeName.StartLocation, + diag::err_pseudo_dtor_destructor_non_type) + << SecondTypeName.Identifier << ObjectType; + if (isSFINAEContext()) + return ExprError(); + + // Recover by assuming we had the right type all along. + DestructedType = ObjectType; + } else + DestructedType = GetTypeFromParser(T, &DestructedTypeInfo); + } else { + // Resolve the template-id to a type. + TemplateIdAnnotation *TemplateId = SecondTypeName.TemplateId; + ASTTemplateArgsPtr TemplateArgsPtr(*this, + TemplateId->getTemplateArgs(), + TemplateId->NumArgs); + TypeResult T = ActOnTemplateIdType(TemplateId->SS, + TemplateId->TemplateKWLoc, + TemplateId->Template, + TemplateId->TemplateNameLoc, + TemplateId->LAngleLoc, + TemplateArgsPtr, + TemplateId->RAngleLoc); + if (T.isInvalid() || !T.get()) { + // Recover by assuming we had the right type all along. + DestructedType = ObjectType; + } else + DestructedType = GetTypeFromParser(T.get(), &DestructedTypeInfo); + } + + // If we've performed some kind of recovery, (re-)build the type source + // information. + if (!DestructedType.isNull()) { + if (!DestructedTypeInfo) + DestructedTypeInfo = Context.getTrivialTypeSourceInfo(DestructedType, + SecondTypeName.StartLocation); + Destructed = PseudoDestructorTypeStorage(DestructedTypeInfo); + } + + // Convert the name of the scope type (the type prior to '::') into a type. + TypeSourceInfo *ScopeTypeInfo = 0; + QualType ScopeType; + if (FirstTypeName.getKind() == UnqualifiedId::IK_TemplateId || + FirstTypeName.Identifier) { + if (FirstTypeName.getKind() == UnqualifiedId::IK_Identifier) { + ParsedType T = getTypeName(*FirstTypeName.Identifier, + FirstTypeName.StartLocation, + S, &SS, true, false, ObjectTypePtrForLookup); + if (!T) { + Diag(FirstTypeName.StartLocation, + diag::err_pseudo_dtor_destructor_non_type) + << FirstTypeName.Identifier << ObjectType; + + if (isSFINAEContext()) + return ExprError(); + + // Just drop this type. It's unnecessary anyway. + ScopeType = QualType(); + } else + ScopeType = GetTypeFromParser(T, &ScopeTypeInfo); + } else { + // Resolve the template-id to a type. + TemplateIdAnnotation *TemplateId = FirstTypeName.TemplateId; + ASTTemplateArgsPtr TemplateArgsPtr(*this, + TemplateId->getTemplateArgs(), + TemplateId->NumArgs); + TypeResult T = ActOnTemplateIdType(TemplateId->SS, + TemplateId->TemplateKWLoc, + TemplateId->Template, + TemplateId->TemplateNameLoc, + TemplateId->LAngleLoc, + TemplateArgsPtr, + TemplateId->RAngleLoc); + if (T.isInvalid() || !T.get()) { + // Recover by dropping this type. + ScopeType = QualType(); + } else + ScopeType = GetTypeFromParser(T.get(), &ScopeTypeInfo); + } + } + + if (!ScopeType.isNull() && !ScopeTypeInfo) + ScopeTypeInfo = Context.getTrivialTypeSourceInfo(ScopeType, + FirstTypeName.StartLocation); + + + return BuildPseudoDestructorExpr(Base, OpLoc, OpKind, SS, + ScopeTypeInfo, CCLoc, TildeLoc, + Destructed, HasTrailingLParen); +} + +ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, + SourceLocation OpLoc, + tok::TokenKind OpKind, + SourceLocation TildeLoc, + const DeclSpec& DS, + bool HasTrailingLParen) { + QualType ObjectType; + if (CheckArrow(*this, ObjectType, Base, OpKind, OpLoc)) + return ExprError(); + + QualType T = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc()); + + TypeLocBuilder TLB; + DecltypeTypeLoc DecltypeTL = TLB.push(T); + DecltypeTL.setNameLoc(DS.getTypeSpecTypeLoc()); + TypeSourceInfo *DestructedTypeInfo = TLB.getTypeSourceInfo(Context, T); + PseudoDestructorTypeStorage Destructed(DestructedTypeInfo); + + return BuildPseudoDestructorExpr(Base, OpLoc, OpKind, CXXScopeSpec(), + 0, SourceLocation(), TildeLoc, + Destructed, HasTrailingLParen); +} + +ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl, + CXXConversionDecl *Method, + bool HadMultipleCandidates) { + if (Method->getParent()->isLambda() && + Method->getConversionType()->isBlockPointerType()) { + // This is a lambda coversion to block pointer; check if the argument + // is a LambdaExpr. + Expr *SubE = E; + CastExpr *CE = dyn_cast(SubE); + if (CE && CE->getCastKind() == CK_NoOp) + SubE = CE->getSubExpr(); + SubE = SubE->IgnoreParens(); + if (CXXBindTemporaryExpr *BE = dyn_cast(SubE)) + SubE = BE->getSubExpr(); + if (isa(SubE)) { + // For the conversion to block pointer on a lambda expression, we + // construct a special BlockLiteral instead; this doesn't really make + // a difference in ARC, but outside of ARC the resulting block literal + // follows the normal lifetime rules for block literals instead of being + // autoreleased. + DiagnosticErrorTrap Trap(Diags); + ExprResult Exp = BuildBlockForLambdaConversion(E->getExprLoc(), + E->getExprLoc(), + Method, E); + if (Exp.isInvalid()) + Diag(E->getExprLoc(), diag::note_lambda_to_block_conv); + return Exp; + } + } + + + ExprResult Exp = PerformObjectArgumentInitialization(E, /*Qualifier=*/0, + FoundDecl, Method); + if (Exp.isInvalid()) + return true; + + MemberExpr *ME = + new (Context) MemberExpr(Exp.take(), /*IsArrow=*/false, Method, + SourceLocation(), Context.BoundMemberTy, + VK_RValue, OK_Ordinary); + if (HadMultipleCandidates) + ME->setHadMultipleCandidates(true); + + QualType ResultType = Method->getResultType(); + ExprValueKind VK = Expr::getValueKindForType(ResultType); + ResultType = ResultType.getNonLValueExprType(Context); + + MarkFunctionReferenced(Exp.get()->getLocStart(), Method); + CXXMemberCallExpr *CE = + new (Context) CXXMemberCallExpr(Context, ME, 0, 0, ResultType, VK, + Exp.get()->getLocEnd()); + return CE; +} + +ExprResult Sema::BuildCXXNoexceptExpr(SourceLocation KeyLoc, Expr *Operand, + SourceLocation RParen) { + CanThrowResult CanThrow = canThrow(Operand); + return Owned(new (Context) CXXNoexceptExpr(Context.BoolTy, Operand, + CanThrow, KeyLoc, RParen)); +} + +ExprResult Sema::ActOnNoexceptExpr(SourceLocation KeyLoc, SourceLocation, + Expr *Operand, SourceLocation RParen) { + return BuildCXXNoexceptExpr(KeyLoc, Operand, RParen); +} + +/// Perform the conversions required for an expression used in a +/// context that ignores the result. +ExprResult Sema::IgnoredValueConversions(Expr *E) { + if (E->hasPlaceholderType()) { + ExprResult result = CheckPlaceholderExpr(E); + if (result.isInvalid()) return Owned(E); + E = result.take(); + } + + // C99 6.3.2.1: + // [Except in specific positions,] an lvalue that does not have + // array type is converted to the value stored in the + // designated object (and is no longer an lvalue). + if (E->isRValue()) { + // In C, function designators (i.e. expressions of function type) + // are r-values, but we still want to do function-to-pointer decay + // on them. This is both technically correct and convenient for + // some clients. + if (!getLangOpts().CPlusPlus && E->getType()->isFunctionType()) + return DefaultFunctionArrayConversion(E); + + return Owned(E); + } + + // Otherwise, this rule does not apply in C++, at least not for the moment. + if (getLangOpts().CPlusPlus) return Owned(E); + + // GCC seems to also exclude expressions of incomplete enum type. + if (const EnumType *T = E->getType()->getAs()) { + if (!T->getDecl()->isComplete()) { + // FIXME: stupid workaround for a codegen bug! + E = ImpCastExprToType(E, Context.VoidTy, CK_ToVoid).take(); + return Owned(E); + } + } + + ExprResult Res = DefaultFunctionArrayLvalueConversion(E); + if (Res.isInvalid()) + return Owned(E); + E = Res.take(); + + if (!E->getType()->isVoidType()) + RequireCompleteType(E->getExprLoc(), E->getType(), + diag::err_incomplete_type); + return Owned(E); +} + +ExprResult Sema::ActOnFinishFullExpr(Expr *FE) { + ExprResult FullExpr = Owned(FE); + + if (!FullExpr.get()) + return ExprError(); + + if (DiagnoseUnexpandedParameterPack(FullExpr.get())) + return ExprError(); + + // Top-level message sends default to 'id' when we're in a debugger. + if (getLangOpts().DebuggerCastResultToId && + FullExpr.get()->getType() == Context.UnknownAnyTy && + isa(FullExpr.get())) { + FullExpr = forceUnknownAnyToType(FullExpr.take(), Context.getObjCIdType()); + if (FullExpr.isInvalid()) + return ExprError(); + } + + FullExpr = CheckPlaceholderExpr(FullExpr.take()); + if (FullExpr.isInvalid()) + return ExprError(); + + FullExpr = IgnoredValueConversions(FullExpr.take()); + if (FullExpr.isInvalid()) + return ExprError(); + + CheckImplicitConversions(FullExpr.get(), FullExpr.get()->getExprLoc()); + return MaybeCreateExprWithCleanups(FullExpr); +} + +StmtResult Sema::ActOnFinishFullStmt(Stmt *FullStmt) { + if (!FullStmt) return StmtError(); + + return MaybeCreateStmtWithCleanups(FullStmt); +} + +Sema::IfExistsResult +Sema::CheckMicrosoftIfExistsSymbol(Scope *S, + CXXScopeSpec &SS, + const DeclarationNameInfo &TargetNameInfo) { + DeclarationName TargetName = TargetNameInfo.getName(); + if (!TargetName) + return IER_DoesNotExist; + + // If the name itself is dependent, then the result is dependent. + if (TargetName.isDependentName()) + return IER_Dependent; + + // Do the redeclaration lookup in the current scope. + LookupResult R(*this, TargetNameInfo, Sema::LookupAnyName, + Sema::NotForRedeclaration); + LookupParsedName(R, S, &SS); + R.suppressDiagnostics(); + + switch (R.getResultKind()) { + case LookupResult::Found: + case LookupResult::FoundOverloaded: + case LookupResult::FoundUnresolvedValue: + case LookupResult::Ambiguous: + return IER_Exists; + + case LookupResult::NotFound: + return IER_DoesNotExist; + + case LookupResult::NotFoundInCurrentInstantiation: + return IER_Dependent; + } + + llvm_unreachable("Invalid LookupResult Kind!"); +} + +Sema::IfExistsResult +Sema::CheckMicrosoftIfExistsSymbol(Scope *S, SourceLocation KeywordLoc, + bool IsIfExists, CXXScopeSpec &SS, + UnqualifiedId &Name) { + DeclarationNameInfo TargetNameInfo = GetNameFromUnqualifiedId(Name); + + // Check for unexpanded parameter packs. + SmallVector Unexpanded; + collectUnexpandedParameterPacks(SS, Unexpanded); + collectUnexpandedParameterPacks(TargetNameInfo, Unexpanded); + if (!Unexpanded.empty()) { + DiagnoseUnexpandedParameterPacks(KeywordLoc, + IsIfExists? UPPC_IfExists + : UPPC_IfNotExists, + Unexpanded); + return IER_Error; + } + + return CheckMicrosoftIfExistsSymbol(S, SS, TargetNameInfo); +} diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp new file mode 100644 index 0000000..6c84caa --- /dev/null +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -0,0 +1,1618 @@ +//===--- SemaExprMember.cpp - Semantic Analysis for Expressions -----------===// +// +// 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 member access expressions. +// +//===----------------------------------------------------------------------===// +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/Scope.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprObjC.h" +#include "clang/Lex/Preprocessor.h" + +using namespace clang; +using namespace sema; + +/// Determines if the given class is provably not derived from all of +/// the prospective base classes. +static bool IsProvablyNotDerivedFrom(Sema &SemaRef, + CXXRecordDecl *Record, + const llvm::SmallPtrSet &Bases) { + if (Bases.count(Record->getCanonicalDecl())) + return false; + + RecordDecl *RD = Record->getDefinition(); + if (!RD) return false; + Record = cast(RD); + + for (CXXRecordDecl::base_class_iterator I = Record->bases_begin(), + E = Record->bases_end(); I != E; ++I) { + CanQualType BaseT = SemaRef.Context.getCanonicalType((*I).getType()); + CanQual BaseRT = BaseT->getAs(); + if (!BaseRT) return false; + + CXXRecordDecl *BaseRecord = cast(BaseRT->getDecl()); + if (!IsProvablyNotDerivedFrom(SemaRef, BaseRecord, Bases)) + return false; + } + + return true; +} + +enum IMAKind { + /// The reference is definitely not an instance member access. + IMA_Static, + + /// The reference may be an implicit instance member access. + IMA_Mixed, + + /// The reference may be to an instance member, but it might be invalid if + /// so, because the context is not an instance method. + IMA_Mixed_StaticContext, + + /// The reference may be to an instance member, but it is invalid if + /// so, because the context is from an unrelated class. + IMA_Mixed_Unrelated, + + /// The reference is definitely an implicit instance member access. + IMA_Instance, + + /// The reference may be to an unresolved using declaration. + IMA_Unresolved, + + /// The reference may be to an unresolved using declaration and the + /// context is not an instance method. + IMA_Unresolved_StaticContext, + + // The reference refers to a field which is not a member of the containing + // class, which is allowed because we're in C++11 mode and the context is + // unevaluated. + IMA_Field_Uneval_Context, + + /// All possible referrents are instance members and the current + /// context is not an instance method. + IMA_Error_StaticContext, + + /// All possible referrents are instance members of an unrelated + /// class. + IMA_Error_Unrelated +}; + +/// The given lookup names class member(s) and is not being used for +/// an address-of-member expression. Classify the type of access +/// according to whether it's possible that this reference names an +/// instance member. This is best-effort in dependent contexts; it is okay to +/// conservatively answer "yes", in which case some errors will simply +/// not be caught until template-instantiation. +static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, + Scope *CurScope, + const LookupResult &R) { + assert(!R.empty() && (*R.begin())->isCXXClassMember()); + + DeclContext *DC = SemaRef.getFunctionLevelDeclContext(); + + bool isStaticContext = SemaRef.CXXThisTypeOverride.isNull() && + (!isa(DC) || cast(DC)->isStatic()); + + if (R.isUnresolvableResult()) + return isStaticContext ? IMA_Unresolved_StaticContext : IMA_Unresolved; + + // Collect all the declaring classes of instance members we find. + bool hasNonInstance = false; + bool isField = false; + llvm::SmallPtrSet Classes; + for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { + NamedDecl *D = *I; + + if (D->isCXXInstanceMember()) { + if (dyn_cast(D)) + isField = true; + + CXXRecordDecl *R = cast(D->getDeclContext()); + Classes.insert(R->getCanonicalDecl()); + } + else + hasNonInstance = true; + } + + // If we didn't find any instance members, it can't be an implicit + // member reference. + if (Classes.empty()) + return IMA_Static; + + bool IsCXX11UnevaluatedField = false; + if (SemaRef.getLangOpts().CPlusPlus0x && isField) { + // C++11 [expr.prim.general]p12: + // An id-expression that denotes a non-static data member or non-static + // member function of a class can only be used: + // (...) + // - if that id-expression denotes a non-static data member and it + // appears in an unevaluated operand. + const Sema::ExpressionEvaluationContextRecord& record + = SemaRef.ExprEvalContexts.back(); + if (record.Context == Sema::Unevaluated) + IsCXX11UnevaluatedField = true; + } + + // If the current context is not an instance method, it can't be + // an implicit member reference. + if (isStaticContext) { + if (hasNonInstance) + return IMA_Mixed_StaticContext; + + return IsCXX11UnevaluatedField ? IMA_Field_Uneval_Context + : IMA_Error_StaticContext; + } + + CXXRecordDecl *contextClass; + if (CXXMethodDecl *MD = dyn_cast(DC)) + contextClass = MD->getParent()->getCanonicalDecl(); + else + contextClass = cast(DC); + + // [class.mfct.non-static]p3: + // ...is used in the body of a non-static member function of class X, + // if name lookup (3.4.1) resolves the name in the id-expression to a + // non-static non-type member of some class C [...] + // ...if C is not X or a base class of X, the class member access expression + // is ill-formed. + if (R.getNamingClass() && + contextClass->getCanonicalDecl() != + R.getNamingClass()->getCanonicalDecl() && + contextClass->isProvablyNotDerivedFrom(R.getNamingClass())) + return hasNonInstance ? IMA_Mixed_Unrelated : + IsCXX11UnevaluatedField ? IMA_Field_Uneval_Context : + IMA_Error_Unrelated; + + // If we can prove that the current context is unrelated to all the + // declaring classes, it can't be an implicit member reference (in + // which case it's an error if any of those members are selected). + if (IsProvablyNotDerivedFrom(SemaRef, contextClass, Classes)) + return hasNonInstance ? IMA_Mixed_Unrelated : + IsCXX11UnevaluatedField ? IMA_Field_Uneval_Context : + IMA_Error_Unrelated; + + return (hasNonInstance ? IMA_Mixed : IMA_Instance); +} + +/// Diagnose a reference to a field with no object available. +static void diagnoseInstanceReference(Sema &SemaRef, + const CXXScopeSpec &SS, + NamedDecl *Rep, + const DeclarationNameInfo &nameInfo) { + SourceLocation Loc = nameInfo.getLoc(); + SourceRange Range(Loc); + if (SS.isSet()) Range.setBegin(SS.getRange().getBegin()); + + DeclContext *FunctionLevelDC = SemaRef.getFunctionLevelDeclContext(); + CXXMethodDecl *Method = dyn_cast(FunctionLevelDC); + CXXRecordDecl *ContextClass = Method ? Method->getParent() : 0; + CXXRecordDecl *RepClass = dyn_cast(Rep->getDeclContext()); + + bool InStaticMethod = Method && Method->isStatic(); + bool IsField = isa(Rep) || isa(Rep); + + if (IsField && InStaticMethod) + // "invalid use of member 'x' in static member function" + SemaRef.Diag(Loc, diag::err_invalid_member_use_in_static_method) + << Range << nameInfo.getName(); + else if (ContextClass && RepClass && SS.isEmpty() && !InStaticMethod && + !RepClass->Equals(ContextClass) && RepClass->Encloses(ContextClass)) + // Unqualified lookup in a non-static member function found a member of an + // enclosing class. + SemaRef.Diag(Loc, diag::err_nested_non_static_member_use) + << IsField << RepClass << nameInfo.getName() << ContextClass << Range; + else if (IsField) + SemaRef.Diag(Loc, diag::err_invalid_non_static_member_use) + << nameInfo.getName() << Range; + else + SemaRef.Diag(Loc, diag::err_member_call_without_object) + << Range; +} + +/// Builds an expression which might be an implicit member expression. +ExprResult +Sema::BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, + LookupResult &R, + const TemplateArgumentListInfo *TemplateArgs) { + switch (ClassifyImplicitMemberAccess(*this, CurScope, R)) { + case IMA_Instance: + return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, true); + + case IMA_Mixed: + case IMA_Mixed_Unrelated: + case IMA_Unresolved: + return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, false); + + case IMA_Field_Uneval_Context: + Diag(R.getNameLoc(), diag::warn_cxx98_compat_non_static_member_use) + << R.getLookupNameInfo().getName(); + // Fall through. + case IMA_Static: + case IMA_Mixed_StaticContext: + case IMA_Unresolved_StaticContext: + if (TemplateArgs || TemplateKWLoc.isValid()) + return BuildTemplateIdExpr(SS, TemplateKWLoc, R, false, TemplateArgs); + return BuildDeclarationNameExpr(SS, R, false); + + case IMA_Error_StaticContext: + case IMA_Error_Unrelated: + diagnoseInstanceReference(*this, SS, R.getRepresentativeDecl(), + R.getLookupNameInfo()); + return ExprError(); + } + + llvm_unreachable("unexpected instance member access kind"); +} + +/// Check an ext-vector component access expression. +/// +/// VK should be set in advance to the value kind of the base +/// expression. +static QualType +CheckExtVectorComponent(Sema &S, QualType baseType, ExprValueKind &VK, + SourceLocation OpLoc, const IdentifierInfo *CompName, + SourceLocation CompLoc) { + // FIXME: Share logic with ExtVectorElementExpr::containsDuplicateElements, + // see FIXME there. + // + // FIXME: This logic can be greatly simplified by splitting it along + // halving/not halving and reworking the component checking. + const ExtVectorType *vecType = baseType->getAs(); + + // The vector accessor can't exceed the number of elements. + const char *compStr = CompName->getNameStart(); + + // This flag determines whether or not the component is one of the four + // special names that indicate a subset of exactly half the elements are + // to be selected. + bool HalvingSwizzle = false; + + // This flag determines whether or not CompName has an 's' char prefix, + // indicating that it is a string of hex values to be used as vector indices. + bool HexSwizzle = *compStr == 's' || *compStr == 'S'; + + bool HasRepeated = false; + bool HasIndex[16] = {}; + + int Idx; + + // Check that we've found one of the special components, or that the component + // names must come from the same set. + if (!strcmp(compStr, "hi") || !strcmp(compStr, "lo") || + !strcmp(compStr, "even") || !strcmp(compStr, "odd")) { + HalvingSwizzle = true; + } else if (!HexSwizzle && + (Idx = vecType->getPointAccessorIdx(*compStr)) != -1) { + do { + if (HasIndex[Idx]) HasRepeated = true; + HasIndex[Idx] = true; + compStr++; + } while (*compStr && (Idx = vecType->getPointAccessorIdx(*compStr)) != -1); + } else { + if (HexSwizzle) compStr++; + while ((Idx = vecType->getNumericAccessorIdx(*compStr)) != -1) { + if (HasIndex[Idx]) HasRepeated = true; + HasIndex[Idx] = true; + compStr++; + } + } + + if (!HalvingSwizzle && *compStr) { + // 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. + S.Diag(OpLoc, diag::err_ext_vector_component_name_illegal) + << StringRef(compStr, 1) << SourceRange(CompLoc); + return QualType(); + } + + // Ensure no component accessor exceeds the width of the vector type it + // operates on. + if (!HalvingSwizzle) { + compStr = CompName->getNameStart(); + + if (HexSwizzle) + compStr++; + + while (*compStr) { + if (!vecType->isAccessorWithinNumElements(*compStr++)) { + S.Diag(OpLoc, diag::err_ext_vector_component_exceeds_length) + << baseType << SourceRange(CompLoc); + return QualType(); + } + } + } + + // The component accessor looks fine - now we need to compute the actual type. + // The vector type is implied by the component accessor. For example, + // vec4.b is a float, vec4.xy is a vec2, vec4.rgb is a vec3, etc. + // vec4.s0 is a float, vec4.s23 is a vec3, etc. + // vec4.hi, vec4.lo, vec4.e, and vec4.o all return vec2. + unsigned CompSize = HalvingSwizzle ? (vecType->getNumElements() + 1) / 2 + : CompName->getLength(); + if (HexSwizzle) + CompSize--; + + if (CompSize == 1) + return vecType->getElementType(); + + if (HasRepeated) VK = VK_RValue; + + QualType VT = S.Context.getExtVectorType(vecType->getElementType(), CompSize); + // Now look up the TypeDefDecl from the vector type. Without this, + // diagostics look bad. We want extended vector types to appear built-in. + for (Sema::ExtVectorDeclsType::iterator + I = S.ExtVectorDecls.begin(S.ExternalSource), + E = S.ExtVectorDecls.end(); + I != E; ++I) { + if ((*I)->getUnderlyingType() == VT) + return S.Context.getTypedefType(*I); + } + + return VT; // should never get here (a typedef type should always be found). +} + +static Decl *FindGetterSetterNameDeclFromProtocolList(const ObjCProtocolDecl*PDecl, + IdentifierInfo *Member, + const Selector &Sel, + ASTContext &Context) { + if (Member) + if (ObjCPropertyDecl *PD = PDecl->FindPropertyDeclaration(Member)) + return PD; + if (ObjCMethodDecl *OMD = PDecl->getInstanceMethod(Sel)) + return OMD; + + for (ObjCProtocolDecl::protocol_iterator I = PDecl->protocol_begin(), + E = PDecl->protocol_end(); I != E; ++I) { + if (Decl *D = FindGetterSetterNameDeclFromProtocolList(*I, Member, Sel, + Context)) + return D; + } + return 0; +} + +static Decl *FindGetterSetterNameDecl(const ObjCObjectPointerType *QIdTy, + IdentifierInfo *Member, + const Selector &Sel, + ASTContext &Context) { + // Check protocols on qualified interfaces. + Decl *GDecl = 0; + for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(), + E = QIdTy->qual_end(); I != E; ++I) { + if (Member) + if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(Member)) { + GDecl = PD; + break; + } + // Also must look for a getter or setter name which uses property syntax. + if (ObjCMethodDecl *OMD = (*I)->getInstanceMethod(Sel)) { + GDecl = OMD; + break; + } + } + if (!GDecl) { + for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(), + E = QIdTy->qual_end(); I != E; ++I) { + // Search in the protocol-qualifier list of current protocol. + GDecl = FindGetterSetterNameDeclFromProtocolList(*I, Member, Sel, + Context); + if (GDecl) + return GDecl; + } + } + return GDecl; +} + +ExprResult +Sema::ActOnDependentMemberExpr(Expr *BaseExpr, QualType BaseType, + bool IsArrow, SourceLocation OpLoc, + const CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, + NamedDecl *FirstQualifierInScope, + const DeclarationNameInfo &NameInfo, + const TemplateArgumentListInfo *TemplateArgs) { + // Even in dependent contexts, try to diagnose base expressions with + // obviously wrong types, e.g.: + // + // T* t; + // t.f; + // + // In Obj-C++, however, the above expression is valid, since it could be + // accessing the 'f' property if T is an Obj-C interface. The extra check + // allows this, while still reporting an error if T is a struct pointer. + if (!IsArrow) { + const PointerType *PT = BaseType->getAs(); + if (PT && (!getLangOpts().ObjC1 || + PT->getPointeeType()->isRecordType())) { + assert(BaseExpr && "cannot happen with implicit member accesses"); + Diag(NameInfo.getLoc(), diag::err_typecheck_member_reference_struct_union) + << BaseType << BaseExpr->getSourceRange(); + return ExprError(); + } + } + + 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, + SS.getWithLocInContext(Context), + TemplateKWLoc, + FirstQualifierInScope, + NameInfo, TemplateArgs)); +} + +/// We know that the given qualified member reference points only to +/// declarations which do not belong to the static type of the base +/// expression. Diagnose the problem. +static void DiagnoseQualifiedMemberReference(Sema &SemaRef, + Expr *BaseExpr, + QualType BaseType, + const CXXScopeSpec &SS, + NamedDecl *rep, + const DeclarationNameInfo &nameInfo) { + // If this is an implicit member access, use a different set of + // diagnostics. + if (!BaseExpr) + return diagnoseInstanceReference(SemaRef, SS, rep, nameInfo); + + SemaRef.Diag(nameInfo.getLoc(), diag::err_qualified_member_of_unrelated) + << SS.getRange() << rep << BaseType; +} + +// Check whether the declarations we found through a nested-name +// specifier in a member expression are actually members of the base +// type. The restriction here is: +// +// C++ [expr.ref]p2: +// ... In these cases, the id-expression shall name a +// member of the class or of one of its base classes. +// +// So it's perfectly legitimate for the nested-name specifier to name +// an unrelated class, and for us to find an overload set including +// decls from classes which are not superclasses, as long as the decl +// we actually pick through overload resolution is from a superclass. +bool Sema::CheckQualifiedMemberReference(Expr *BaseExpr, + QualType BaseType, + const CXXScopeSpec &SS, + const LookupResult &R) { + const RecordType *BaseRT = BaseType->getAs(); + if (!BaseRT) { + // We can't check this yet because the base type is still + // dependent. + assert(BaseType->isDependentType()); + return false; + } + CXXRecordDecl *BaseRecord = cast(BaseRT->getDecl()); + + for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { + // If this is an implicit member reference and we find a + // non-instance member, it's not an error. + if (!BaseExpr && !(*I)->isCXXInstanceMember()) + return false; + + // Note that we use the DC of the decl, not the underlying decl. + DeclContext *DC = (*I)->getDeclContext(); + while (DC->isTransparentContext()) + DC = DC->getParent(); + + if (!DC->isRecord()) + continue; + + llvm::SmallPtrSet MemberRecord; + MemberRecord.insert(cast(DC)->getCanonicalDecl()); + + if (!IsProvablyNotDerivedFrom(*this, BaseRecord, MemberRecord)) + return false; + } + + DiagnoseQualifiedMemberReference(*this, BaseExpr, BaseType, SS, + R.getRepresentativeDecl(), + R.getLookupNameInfo()); + return true; +} + +namespace { + +// Callback to only accept typo corrections that are either a ValueDecl or a +// FunctionTemplateDecl. +class RecordMemberExprValidatorCCC : public CorrectionCandidateCallback { + public: + virtual bool ValidateCandidate(const TypoCorrection &candidate) { + NamedDecl *ND = candidate.getCorrectionDecl(); + return ND && (isa(ND) || isa(ND)); + } +}; + +} + +static bool +LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R, + SourceRange BaseRange, const RecordType *RTy, + SourceLocation OpLoc, CXXScopeSpec &SS, + bool HasTemplateArgs) { + RecordDecl *RDecl = RTy->getDecl(); + if (!SemaRef.isThisOutsideMemberFunctionBody(QualType(RTy, 0)) && + SemaRef.RequireCompleteType(OpLoc, QualType(RTy, 0), + SemaRef.PDiag(diag::err_typecheck_incomplete_tag) + << BaseRange)) + return true; + + if (HasTemplateArgs) { + // LookupTemplateName doesn't expect these both to exist simultaneously. + QualType ObjectType = SS.isSet() ? QualType() : QualType(RTy, 0); + + bool MOUS; + SemaRef.LookupTemplateName(R, 0, SS, ObjectType, false, MOUS); + return false; + } + + DeclContext *DC = RDecl; + if (SS.isSet()) { + // If the member name was a qualified-id, look into the + // nested-name-specifier. + DC = SemaRef.computeDeclContext(SS, false); + + if (SemaRef.RequireCompleteDeclContext(SS, DC)) { + SemaRef.Diag(SS.getRange().getEnd(), diag::err_typecheck_incomplete_tag) + << SS.getRange() << DC; + return true; + } + + assert(DC && "Cannot handle non-computable dependent contexts in lookup"); + + if (!isa(DC)) { + SemaRef.Diag(R.getNameLoc(), diag::err_qualified_member_nonclass) + << DC << SS.getRange(); + return true; + } + } + + // The record definition is complete, now look up the member. + SemaRef.LookupQualifiedName(R, DC); + + if (!R.empty()) + return false; + + // We didn't find anything with the given name, so try to correct + // for typos. + DeclarationName Name = R.getLookupName(); + RecordMemberExprValidatorCCC Validator; + TypoCorrection Corrected = SemaRef.CorrectTypo(R.getLookupNameInfo(), + R.getLookupKind(), NULL, + &SS, Validator, DC); + R.clear(); + if (NamedDecl *ND = Corrected.getCorrectionDecl()) { + std::string CorrectedStr( + Corrected.getAsString(SemaRef.getLangOpts())); + std::string CorrectedQuotedStr( + Corrected.getQuoted(SemaRef.getLangOpts())); + R.setLookupName(Corrected.getCorrection()); + R.addDecl(ND); + SemaRef.Diag(R.getNameLoc(), diag::err_no_member_suggest) + << Name << DC << CorrectedQuotedStr << SS.getRange() + << FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr); + SemaRef.Diag(ND->getLocation(), diag::note_previous_decl) + << ND->getDeclName(); + } + + return false; +} + +ExprResult +Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType, + SourceLocation OpLoc, bool IsArrow, + CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, + NamedDecl *FirstQualifierInScope, + const DeclarationNameInfo &NameInfo, + const TemplateArgumentListInfo *TemplateArgs) { + if (BaseType->isDependentType() || + (SS.isSet() && isDependentScopeSpecifier(SS))) + return ActOnDependentMemberExpr(Base, BaseType, + IsArrow, OpLoc, + SS, TemplateKWLoc, FirstQualifierInScope, + NameInfo, TemplateArgs); + + LookupResult R(*this, NameInfo, LookupMemberName); + + // Implicit member accesses. + if (!Base) { + QualType RecordTy = BaseType; + if (IsArrow) RecordTy = RecordTy->getAs()->getPointeeType(); + if (LookupMemberExprInRecord(*this, R, SourceRange(), + RecordTy->getAs(), + OpLoc, SS, TemplateArgs != 0)) + return ExprError(); + + // Explicit member accesses. + } else { + ExprResult BaseResult = Owned(Base); + ExprResult Result = + LookupMemberExpr(R, BaseResult, IsArrow, OpLoc, + SS, /*ObjCImpDecl*/ 0, TemplateArgs != 0); + + if (BaseResult.isInvalid()) + return ExprError(); + Base = BaseResult.take(); + + if (Result.isInvalid()) { + Owned(Base); + return ExprError(); + } + + if (Result.get()) + return move(Result); + + // LookupMemberExpr can modify Base, and thus change BaseType + BaseType = Base->getType(); + } + + return BuildMemberReferenceExpr(Base, BaseType, + OpLoc, IsArrow, SS, TemplateKWLoc, + FirstQualifierInScope, R, TemplateArgs); +} + +static ExprResult +BuildFieldReferenceExpr(Sema &S, Expr *BaseExpr, bool IsArrow, + const CXXScopeSpec &SS, FieldDecl *Field, + DeclAccessPair FoundDecl, + const DeclarationNameInfo &MemberNameInfo); + +ExprResult +Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS, + SourceLocation loc, + IndirectFieldDecl *indirectField, + Expr *baseObjectExpr, + SourceLocation opLoc) { + // First, build the expression that refers to the base object. + + bool baseObjectIsPointer = false; + Qualifiers baseQuals; + + // Case 1: the base of the indirect field is not a field. + VarDecl *baseVariable = indirectField->getVarDecl(); + CXXScopeSpec EmptySS; + if (baseVariable) { + assert(baseVariable->getType()->isRecordType()); + + // In principle we could have a member access expression that + // accesses an anonymous struct/union that's a static member of + // the base object's class. However, under the current standard, + // static data members cannot be anonymous structs or unions. + // Supporting this is as easy as building a MemberExpr here. + assert(!baseObjectExpr && "anonymous struct/union is static data member?"); + + DeclarationNameInfo baseNameInfo(DeclarationName(), loc); + + ExprResult result + = BuildDeclarationNameExpr(EmptySS, baseNameInfo, baseVariable); + if (result.isInvalid()) return ExprError(); + + baseObjectExpr = result.take(); + baseObjectIsPointer = false; + baseQuals = baseObjectExpr->getType().getQualifiers(); + + // Case 2: the base of the indirect field is a field and the user + // wrote a member expression. + } else if (baseObjectExpr) { + // The caller provided the base object expression. Determine + // whether its a pointer and whether it adds any qualifiers to the + // anonymous struct/union fields we're looking into. + QualType objectType = baseObjectExpr->getType(); + + if (const PointerType *ptr = objectType->getAs()) { + baseObjectIsPointer = true; + objectType = ptr->getPointeeType(); + } else { + baseObjectIsPointer = false; + } + baseQuals = objectType.getQualifiers(); + + // Case 3: the base of the indirect field is a field and we should + // build an implicit member access. + } else { + // We've found a member of an anonymous struct/union that is + // inside a non-anonymous struct/union, so in a well-formed + // program our base object expression is "this". + QualType ThisTy = getCurrentThisType(); + if (ThisTy.isNull()) { + Diag(loc, diag::err_invalid_member_use_in_static_method) + << indirectField->getDeclName(); + return ExprError(); + } + + // Our base object expression is "this". + CheckCXXThisCapture(loc); + baseObjectExpr + = new (Context) CXXThisExpr(loc, ThisTy, /*isImplicit=*/ true); + baseObjectIsPointer = true; + baseQuals = ThisTy->castAs()->getPointeeType().getQualifiers(); + } + + // Build the implicit member references to the field of the + // anonymous struct/union. + Expr *result = baseObjectExpr; + IndirectFieldDecl::chain_iterator + FI = indirectField->chain_begin(), FEnd = indirectField->chain_end(); + + // Build the first member access in the chain with full information. + if (!baseVariable) { + FieldDecl *field = cast(*FI); + + // FIXME: use the real found-decl info! + DeclAccessPair foundDecl = DeclAccessPair::make(field, field->getAccess()); + + // Make a nameInfo that properly uses the anonymous name. + DeclarationNameInfo memberNameInfo(field->getDeclName(), loc); + + result = BuildFieldReferenceExpr(*this, result, baseObjectIsPointer, + EmptySS, field, foundDecl, + memberNameInfo).take(); + baseObjectIsPointer = false; + + // FIXME: check qualified member access + } + + // In all cases, we should now skip the first declaration in the chain. + ++FI; + + while (FI != FEnd) { + FieldDecl *field = cast(*FI++); + + // FIXME: these are somewhat meaningless + DeclarationNameInfo memberNameInfo(field->getDeclName(), loc); + DeclAccessPair foundDecl = DeclAccessPair::make(field, field->getAccess()); + + result = BuildFieldReferenceExpr(*this, result, /*isarrow*/ false, + (FI == FEnd? SS : EmptySS), field, + foundDecl, memberNameInfo).take(); + } + + return Owned(result); +} + +/// \brief Build a MemberExpr AST node. +static MemberExpr *BuildMemberExpr(Sema &SemaRef, + ASTContext &C, Expr *Base, bool isArrow, + const CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, + ValueDecl *Member, + DeclAccessPair FoundDecl, + const DeclarationNameInfo &MemberNameInfo, + QualType Ty, + ExprValueKind VK, ExprObjectKind OK, + const TemplateArgumentListInfo *TemplateArgs = 0) { + assert((!isArrow || Base->isRValue()) && "-> base must be a pointer rvalue"); + MemberExpr *E = + MemberExpr::Create(C, Base, isArrow, SS.getWithLocInContext(C), + TemplateKWLoc, Member, FoundDecl, MemberNameInfo, + TemplateArgs, Ty, VK, OK); + SemaRef.MarkMemberReferenced(E); + return E; +} + +ExprResult +Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, + SourceLocation OpLoc, bool IsArrow, + const CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, + NamedDecl *FirstQualifierInScope, + LookupResult &R, + const TemplateArgumentListInfo *TemplateArgs, + bool SuppressQualifierCheck) { + QualType BaseType = BaseExprType; + if (IsArrow) { + assert(BaseType->isPointerType()); + BaseType = BaseType->castAs()->getPointeeType(); + } + R.setBaseObjectType(BaseType); + + const DeclarationNameInfo &MemberNameInfo = R.getLookupNameInfo(); + DeclarationName MemberName = MemberNameInfo.getName(); + SourceLocation MemberLoc = MemberNameInfo.getLoc(); + + if (R.isAmbiguous()) + return ExprError(); + + if (R.empty()) { + // Rederive where we looked up. + DeclContext *DC = (SS.isSet() + ? computeDeclContext(SS, false) + : BaseType->getAs()->getDecl()); + + Diag(R.getNameLoc(), diag::err_no_member) + << MemberName << DC + << (BaseExpr ? BaseExpr->getSourceRange() : SourceRange()); + return ExprError(); + } + + // Diagnose lookups that find only declarations from a non-base + // type. This is possible for either qualified lookups (which may + // have been qualified with an unrelated type) or implicit member + // expressions (which were found with unqualified lookup and thus + // may have come from an enclosing scope). Note that it's okay for + // lookup to find declarations from a non-base type as long as those + // aren't the ones picked by overload resolution. + if ((SS.isSet() || !BaseExpr || + (isa(BaseExpr) && + cast(BaseExpr)->isImplicit())) && + !SuppressQualifierCheck && + CheckQualifiedMemberReference(BaseExpr, BaseType, SS, R)) + return ExprError(); + + // Construct an unresolved result if we in fact got an unresolved + // result. + if (R.isOverloadedResult() || R.isUnresolvableResult()) { + // Suppress any lookup-related diagnostics; we'll do these when we + // pick a member. + R.suppressDiagnostics(); + + UnresolvedMemberExpr *MemExpr + = UnresolvedMemberExpr::Create(Context, R.isUnresolvableResult(), + BaseExpr, BaseExprType, + IsArrow, OpLoc, + SS.getWithLocInContext(Context), + TemplateKWLoc, MemberNameInfo, + TemplateArgs, R.begin(), R.end()); + + return Owned(MemExpr); + } + + assert(R.isSingleResult()); + DeclAccessPair FoundDecl = R.begin().getPair(); + NamedDecl *MemberDecl = R.getFoundDecl(); + + // FIXME: diagnose the presence of template arguments now. + + // If the decl being referenced had an error, return an error for this + // sub-expr without emitting another error, in order to avoid cascading + // error cases. + if (MemberDecl->isInvalidDecl()) + return ExprError(); + + // Handle the implicit-member-access case. + if (!BaseExpr) { + // If this is not an instance member, convert to a non-member access. + if (!MemberDecl->isCXXInstanceMember()) + return BuildDeclarationNameExpr(SS, R.getLookupNameInfo(), MemberDecl); + + SourceLocation Loc = R.getNameLoc(); + if (SS.getRange().isValid()) + Loc = SS.getRange().getBegin(); + CheckCXXThisCapture(Loc); + BaseExpr = new (Context) CXXThisExpr(Loc, BaseExprType,/*isImplicit=*/true); + } + + bool ShouldCheckUse = true; + if (CXXMethodDecl *MD = dyn_cast(MemberDecl)) { + // Don't diagnose the use of a virtual member function unless it's + // explicitly qualified. + if (MD->isVirtual() && !SS.isSet()) + ShouldCheckUse = false; + } + + // Check the use of this member. + if (ShouldCheckUse && DiagnoseUseOfDecl(MemberDecl, MemberLoc)) { + Owned(BaseExpr); + return ExprError(); + } + + if (FieldDecl *FD = dyn_cast(MemberDecl)) + return BuildFieldReferenceExpr(*this, BaseExpr, IsArrow, + SS, FD, FoundDecl, MemberNameInfo); + + if (IndirectFieldDecl *FD = dyn_cast(MemberDecl)) + // We may have found a field within an anonymous union or struct + // (C++ [class.union]). + return BuildAnonymousStructUnionMemberReference(SS, MemberLoc, FD, + BaseExpr, OpLoc); + + if (VarDecl *Var = dyn_cast(MemberDecl)) { + return Owned(BuildMemberExpr(*this, Context, BaseExpr, IsArrow, SS, + TemplateKWLoc, Var, FoundDecl, MemberNameInfo, + Var->getType().getNonReferenceType(), + VK_LValue, OK_Ordinary)); + } + + if (CXXMethodDecl *MemberFn = dyn_cast(MemberDecl)) { + ExprValueKind valueKind; + QualType type; + if (MemberFn->isInstance()) { + valueKind = VK_RValue; + type = Context.BoundMemberTy; + } else { + valueKind = VK_LValue; + type = MemberFn->getType(); + } + + return Owned(BuildMemberExpr(*this, Context, BaseExpr, IsArrow, SS, + TemplateKWLoc, MemberFn, FoundDecl, + MemberNameInfo, type, valueKind, + OK_Ordinary)); + } + assert(!isa(MemberDecl) && "member function not C++ method?"); + + if (EnumConstantDecl *Enum = dyn_cast(MemberDecl)) { + return Owned(BuildMemberExpr(*this, Context, BaseExpr, IsArrow, SS, + TemplateKWLoc, Enum, FoundDecl, MemberNameInfo, + Enum->getType(), VK_RValue, OK_Ordinary)); + } + + Owned(BaseExpr); + + // We found something that we didn't expect. Complain. + if (isa(MemberDecl)) + Diag(MemberLoc, diag::err_typecheck_member_reference_type) + << MemberName << BaseType << int(IsArrow); + else + Diag(MemberLoc, diag::err_typecheck_member_reference_unknown) + << MemberName << BaseType << int(IsArrow); + + Diag(MemberDecl->getLocation(), diag::note_member_declared_here) + << MemberName; + R.suppressDiagnostics(); + return ExprError(); +} + +/// Given that normal member access failed on the given expression, +/// and given that the expression's type involves builtin-id or +/// builtin-Class, decide whether substituting in the redefinition +/// types would be profitable. The redefinition type is whatever +/// this translation unit tried to typedef to id/Class; we store +/// it to the side and then re-use it in places like this. +static bool ShouldTryAgainWithRedefinitionType(Sema &S, ExprResult &base) { + const ObjCObjectPointerType *opty + = base.get()->getType()->getAs(); + if (!opty) return false; + + const ObjCObjectType *ty = opty->getObjectType(); + + QualType redef; + if (ty->isObjCId()) { + redef = S.Context.getObjCIdRedefinitionType(); + } else if (ty->isObjCClass()) { + redef = S.Context.getObjCClassRedefinitionType(); + } else { + return false; + } + + // Do the substitution as long as the redefinition type isn't just a + // possibly-qualified pointer to builtin-id or builtin-Class again. + opty = redef->getAs(); + if (opty && !opty->getObjectType()->getInterface() != 0) + return false; + + base = S.ImpCastExprToType(base.take(), redef, CK_BitCast); + return true; +} + +static bool isRecordType(QualType T) { + return T->isRecordType(); +} +static bool isPointerToRecordType(QualType T) { + if (const PointerType *PT = T->getAs()) + return PT->getPointeeType()->isRecordType(); + return false; +} + +/// Perform conversions on the LHS of a member access expression. +ExprResult +Sema::PerformMemberExprBaseConversion(Expr *Base, bool IsArrow) { + if (IsArrow && !Base->getType()->isFunctionType()) + return DefaultFunctionArrayLvalueConversion(Base); + + return CheckPlaceholderExpr(Base); +} + +/// Look up the given member of the given non-type-dependent +/// expression. This can return in one of two ways: +/// * If it returns a sentinel null-but-valid result, the caller will +/// assume that lookup was performed and the results written into +/// the provided structure. It will take over from there. +/// * Otherwise, the returned expression will be produced in place of +/// an ordinary member expression. +/// +/// The ObjCImpDecl bit is a gross hack that will need to be properly +/// fixed for ObjC++. +ExprResult +Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, + bool &IsArrow, SourceLocation OpLoc, + CXXScopeSpec &SS, + Decl *ObjCImpDecl, bool HasTemplateArgs) { + assert(BaseExpr.get() && "no base expression"); + + // Perform default conversions. + BaseExpr = PerformMemberExprBaseConversion(BaseExpr.take(), IsArrow); + if (BaseExpr.isInvalid()) + return ExprError(); + + QualType BaseType = BaseExpr.get()->getType(); + assert(!BaseType->isDependentType()); + + DeclarationName MemberName = R.getLookupName(); + SourceLocation MemberLoc = R.getNameLoc(); + + // For later type-checking purposes, turn arrow accesses into dot + // accesses. The only access type we support that doesn't follow + // the C equivalence "a->b === (*a).b" is ObjC property accesses, + // and those never use arrows, so this is unaffected. + if (IsArrow) { + if (const PointerType *Ptr = BaseType->getAs()) + BaseType = Ptr->getPointeeType(); + else if (const ObjCObjectPointerType *Ptr + = BaseType->getAs()) + BaseType = Ptr->getPointeeType(); + else if (BaseType->isRecordType()) { + // Recover from arrow accesses to records, e.g.: + // struct MyRecord foo; + // foo->bar + // This is actually well-formed in C++ if MyRecord has an + // overloaded operator->, but that should have been dealt with + // by now. + Diag(OpLoc, diag::err_typecheck_member_reference_suggestion) + << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange() + << FixItHint::CreateReplacement(OpLoc, "."); + IsArrow = false; + } else if (BaseType->isFunctionType()) { + goto fail; + } else { + Diag(MemberLoc, diag::err_typecheck_member_reference_arrow) + << BaseType << BaseExpr.get()->getSourceRange(); + return ExprError(); + } + } + + // Handle field access to simple records. + if (const RecordType *RTy = BaseType->getAs()) { + if (LookupMemberExprInRecord(*this, R, BaseExpr.get()->getSourceRange(), + RTy, OpLoc, SS, HasTemplateArgs)) + return ExprError(); + + // Returning valid-but-null is how we indicate to the caller that + // the lookup result was filled in. + return Owned((Expr*) 0); + } + + // Handle ivar access to Objective-C objects. + if (const ObjCObjectType *OTy = BaseType->getAs()) { + if (!SS.isEmpty() && !SS.isInvalid()) { + Diag(SS.getRange().getBegin(), diag::err_qualified_objc_access) + << 1 << SS.getScopeRep() + << FixItHint::CreateRemoval(SS.getRange()); + SS.clear(); + } + + IdentifierInfo *Member = MemberName.getAsIdentifierInfo(); + + // There are three cases for the base type: + // - builtin id (qualified or unqualified) + // - builtin Class (qualified or unqualified) + // - an interface + ObjCInterfaceDecl *IDecl = OTy->getInterface(); + if (!IDecl) { + if (getLangOpts().ObjCAutoRefCount && + (OTy->isObjCId() || OTy->isObjCClass())) + goto fail; + // There's an implicit 'isa' ivar on all objects. + // But we only actually find it this way on objects of type 'id', + // apparently.ghjg + if (OTy->isObjCId() && Member->isStr("isa")) { + Diag(MemberLoc, diag::warn_objc_isa_use); + return Owned(new (Context) ObjCIsaExpr(BaseExpr.take(), IsArrow, MemberLoc, + Context.getObjCClassType())); + } + + if (ShouldTryAgainWithRedefinitionType(*this, BaseExpr)) + return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS, + ObjCImpDecl, HasTemplateArgs); + goto fail; + } + + if (RequireCompleteType(OpLoc, BaseType, + PDiag(diag::err_typecheck_incomplete_tag) + << BaseExpr.get()->getSourceRange())) + return ExprError(); + + ObjCInterfaceDecl *ClassDeclared = 0; + ObjCIvarDecl *IV = IDecl->lookupInstanceVariable(Member, ClassDeclared); + + if (!IV) { + // Attempt to correct for typos in ivar names. + DeclFilterCCC Validator; + Validator.IsObjCIvarLookup = IsArrow; + if (TypoCorrection Corrected = CorrectTypo(R.getLookupNameInfo(), + LookupMemberName, NULL, NULL, + Validator, IDecl)) { + IV = Corrected.getCorrectionDeclAs(); + Diag(R.getNameLoc(), + diag::err_typecheck_member_reference_ivar_suggest) + << IDecl->getDeclName() << MemberName << IV->getDeclName() + << FixItHint::CreateReplacement(R.getNameLoc(), + IV->getNameAsString()); + Diag(IV->getLocation(), diag::note_previous_decl) + << IV->getDeclName(); + + // Figure out the class that declares the ivar. + assert(!ClassDeclared); + Decl *D = cast(IV->getDeclContext()); + if (ObjCCategoryDecl *CAT = dyn_cast(D)) + D = CAT->getClassInterface(); + ClassDeclared = cast(D); + } else { + if (IsArrow && IDecl->FindPropertyDeclaration(Member)) { + Diag(MemberLoc, + diag::err_property_found_suggest) + << Member << BaseExpr.get()->getType() + << FixItHint::CreateReplacement(OpLoc, "."); + return ExprError(); + } + + Diag(MemberLoc, diag::err_typecheck_member_reference_ivar) + << IDecl->getDeclName() << MemberName + << BaseExpr.get()->getSourceRange(); + return ExprError(); + } + } + + assert(ClassDeclared); + + // If the decl being referenced had an error, return an error for this + // sub-expr without emitting another error, in order to avoid cascading + // error cases. + if (IV->isInvalidDecl()) + return ExprError(); + + // Check whether we can reference this field. + if (DiagnoseUseOfDecl(IV, MemberLoc)) + return ExprError(); + if (IV->getAccessControl() != ObjCIvarDecl::Public && + IV->getAccessControl() != ObjCIvarDecl::Package) { + ObjCInterfaceDecl *ClassOfMethodDecl = 0; + if (ObjCMethodDecl *MD = getCurMethodDecl()) + ClassOfMethodDecl = MD->getClassInterface(); + else if (ObjCImpDecl && getCurFunctionDecl()) { + // Case of a c-function declared inside an objc implementation. + // FIXME: For a c-style function nested inside an objc implementation + // class, there is no implementation context available, so we pass + // 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. + if (ObjCImplementationDecl *IMPD = + dyn_cast(ObjCImpDecl)) + ClassOfMethodDecl = IMPD->getClassInterface(); + else if (ObjCCategoryImplDecl* CatImplClass = + dyn_cast(ObjCImpDecl)) + ClassOfMethodDecl = CatImplClass->getClassInterface(); + } + if (!getLangOpts().DebuggerSupport) { + if (IV->getAccessControl() == ObjCIvarDecl::Private) { + if (!declaresSameEntity(ClassDeclared, IDecl) || + !declaresSameEntity(ClassOfMethodDecl, ClassDeclared)) + Diag(MemberLoc, diag::error_private_ivar_access) + << IV->getDeclName(); + } else if (!IDecl->isSuperClassOf(ClassOfMethodDecl)) + // @protected + Diag(MemberLoc, diag::error_protected_ivar_access) + << IV->getDeclName(); + } + } + if (getLangOpts().ObjCAutoRefCount) { + Expr *BaseExp = BaseExpr.get()->IgnoreParenImpCasts(); + if (UnaryOperator *UO = dyn_cast(BaseExp)) + if (UO->getOpcode() == UO_Deref) + BaseExp = UO->getSubExpr()->IgnoreParenCasts(); + + if (DeclRefExpr *DE = dyn_cast(BaseExp)) + if (DE->getType().getObjCLifetime() == Qualifiers::OCL_Weak) + Diag(DE->getLocation(), diag::error_arc_weak_ivar_access); + } + + return Owned(new (Context) ObjCIvarRefExpr(IV, IV->getType(), + MemberLoc, BaseExpr.take(), + IsArrow)); + } + + // Objective-C property access. + const ObjCObjectPointerType *OPT; + if (!IsArrow && (OPT = BaseType->getAs())) { + if (!SS.isEmpty() && !SS.isInvalid()) { + Diag(SS.getRange().getBegin(), diag::err_qualified_objc_access) + << 0 << SS.getScopeRep() + << FixItHint::CreateRemoval(SS.getRange()); + SS.clear(); + } + + // This actually uses the base as an r-value. + BaseExpr = DefaultLvalueConversion(BaseExpr.take()); + if (BaseExpr.isInvalid()) + return ExprError(); + + assert(Context.hasSameUnqualifiedType(BaseType, BaseExpr.get()->getType())); + + IdentifierInfo *Member = MemberName.getAsIdentifierInfo(); + + const ObjCObjectType *OT = OPT->getObjectType(); + + // id, with and without qualifiers. + if (OT->isObjCId()) { + // Check protocols on qualified interfaces. + Selector Sel = PP.getSelectorTable().getNullarySelector(Member); + if (Decl *PMDecl = FindGetterSetterNameDecl(OPT, Member, Sel, Context)) { + if (ObjCPropertyDecl *PD = dyn_cast(PMDecl)) { + // Check the use of this declaration + if (DiagnoseUseOfDecl(PD, MemberLoc)) + return ExprError(); + + return Owned(new (Context) ObjCPropertyRefExpr(PD, + Context.PseudoObjectTy, + VK_LValue, + OK_ObjCProperty, + MemberLoc, + BaseExpr.take())); + } + + if (ObjCMethodDecl *OMD = dyn_cast(PMDecl)) { + // Check the use of this method. + if (DiagnoseUseOfDecl(OMD, MemberLoc)) + return ExprError(); + Selector SetterSel = + SelectorTable::constructSetterName(PP.getIdentifierTable(), + PP.getSelectorTable(), Member); + ObjCMethodDecl *SMD = 0; + if (Decl *SDecl = FindGetterSetterNameDecl(OPT, /*Property id*/0, + SetterSel, Context)) + SMD = dyn_cast(SDecl); + + return Owned(new (Context) ObjCPropertyRefExpr(OMD, SMD, + Context.PseudoObjectTy, + VK_LValue, OK_ObjCProperty, + MemberLoc, BaseExpr.take())); + } + } + // Use of id.member can only be for a property reference. Do not + // use the 'id' redefinition in this case. + if (IsArrow && ShouldTryAgainWithRedefinitionType(*this, BaseExpr)) + return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS, + ObjCImpDecl, HasTemplateArgs); + + return ExprError(Diag(MemberLoc, diag::err_property_not_found) + << MemberName << BaseType); + } + + // 'Class', unqualified only. + if (OT->isObjCClass()) { + // Only works in a method declaration (??!). + ObjCMethodDecl *MD = getCurMethodDecl(); + if (!MD) { + if (ShouldTryAgainWithRedefinitionType(*this, BaseExpr)) + return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS, + ObjCImpDecl, HasTemplateArgs); + + goto fail; + } + + // Also must look for a getter name which uses property syntax. + Selector Sel = PP.getSelectorTable().getNullarySelector(Member); + ObjCInterfaceDecl *IFace = MD->getClassInterface(); + ObjCMethodDecl *Getter; + if ((Getter = IFace->lookupClassMethod(Sel))) { + // Check the use of this method. + if (DiagnoseUseOfDecl(Getter, MemberLoc)) + return ExprError(); + } else + Getter = IFace->lookupPrivateMethod(Sel, false); + // If we found a getter then this may be a valid dot-reference, we + // will look for the matching setter, in case it is needed. + Selector SetterSel = + SelectorTable::constructSetterName(PP.getIdentifierTable(), + PP.getSelectorTable(), Member); + ObjCMethodDecl *Setter = IFace->lookupClassMethod(SetterSel); + if (!Setter) { + // If this reference is in an @implementation, also check for 'private' + // methods. + Setter = IFace->lookupPrivateMethod(SetterSel, false); + } + // Look through local category implementations associated with the class. + if (!Setter) + Setter = IFace->getCategoryClassMethod(SetterSel); + + if (Setter && DiagnoseUseOfDecl(Setter, MemberLoc)) + return ExprError(); + + if (Getter || Setter) { + return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter, + Context.PseudoObjectTy, + VK_LValue, OK_ObjCProperty, + MemberLoc, BaseExpr.take())); + } + + if (ShouldTryAgainWithRedefinitionType(*this, BaseExpr)) + return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS, + ObjCImpDecl, HasTemplateArgs); + + return ExprError(Diag(MemberLoc, diag::err_property_not_found) + << MemberName << BaseType); + } + + // Normal property access. + return HandleExprPropertyRefExpr(OPT, BaseExpr.get(), OpLoc, + MemberName, MemberLoc, + SourceLocation(), QualType(), false); + } + + // Handle 'field access' to vectors, such as 'V.xx'. + if (BaseType->isExtVectorType()) { + // FIXME: this expr should store IsArrow. + IdentifierInfo *Member = MemberName.getAsIdentifierInfo(); + ExprValueKind VK = (IsArrow ? VK_LValue : BaseExpr.get()->getValueKind()); + QualType ret = CheckExtVectorComponent(*this, BaseType, VK, OpLoc, + Member, MemberLoc); + if (ret.isNull()) + return ExprError(); + + return Owned(new (Context) ExtVectorElementExpr(ret, VK, BaseExpr.take(), + *Member, MemberLoc)); + } + + // Adjust builtin-sel to the appropriate redefinition type if that's + // not just a pointer to builtin-sel again. + if (IsArrow && + BaseType->isSpecificBuiltinType(BuiltinType::ObjCSel) && + !Context.getObjCSelRedefinitionType()->isObjCSelType()) { + BaseExpr = ImpCastExprToType(BaseExpr.take(), + Context.getObjCSelRedefinitionType(), + CK_BitCast); + return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS, + ObjCImpDecl, HasTemplateArgs); + } + + // Failure cases. + fail: + + // Recover from dot accesses to pointers, e.g.: + // type *foo; + // foo.bar + // This is actually well-formed in two cases: + // - 'type' is an Objective C type + // - 'bar' is a pseudo-destructor name which happens to refer to + // the appropriate pointer type + if (const PointerType *Ptr = BaseType->getAs()) { + if (!IsArrow && Ptr->getPointeeType()->isRecordType() && + MemberName.getNameKind() != DeclarationName::CXXDestructorName) { + Diag(OpLoc, diag::err_typecheck_member_reference_suggestion) + << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange() + << FixItHint::CreateReplacement(OpLoc, "->"); + + // Recurse as an -> access. + IsArrow = true; + return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS, + ObjCImpDecl, HasTemplateArgs); + } + } + + // If the user is trying to apply -> or . to a function name, it's probably + // because they forgot parentheses to call that function. + if (tryToRecoverWithCall(BaseExpr, + PDiag(diag::err_member_reference_needs_call), + /*complain*/ false, + IsArrow ? &isPointerToRecordType : &isRecordType)) { + if (BaseExpr.isInvalid()) + return ExprError(); + BaseExpr = DefaultFunctionArrayConversion(BaseExpr.take()); + return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS, + ObjCImpDecl, HasTemplateArgs); + } + + Diag(MemberLoc, diag::err_typecheck_member_reference_struct_union) + << BaseType << BaseExpr.get()->getSourceRange(); + + return ExprError(); +} + +/// The main callback when the parser finds something like +/// expression . [nested-name-specifier] identifier +/// expression -> [nested-name-specifier] identifier +/// where 'identifier' encompasses a fairly broad spectrum of +/// possibilities, including destructor and operator references. +/// +/// \param OpKind either tok::arrow or tok::period +/// \param HasTrailingLParen whether the next token is '(', which +/// is used to diagnose mis-uses of special members that can +/// only be called +/// \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 +ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base, + SourceLocation OpLoc, + tok::TokenKind OpKind, + CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, + UnqualifiedId &Id, + Decl *ObjCImpDecl, + bool HasTrailingLParen) { + if (SS.isSet() && SS.isInvalid()) + return ExprError(); + + // Warn about the explicit constructor calls Microsoft extension. + if (getLangOpts().MicrosoftExt && + Id.getKind() == UnqualifiedId::IK_ConstructorName) + Diag(Id.getSourceRange().getBegin(), + diag::ext_ms_explicit_constructor_call); + + TemplateArgumentListInfo TemplateArgsBuffer; + + // Decompose the name into its component parts. + DeclarationNameInfo NameInfo; + const TemplateArgumentListInfo *TemplateArgs; + DecomposeUnqualifiedId(Id, TemplateArgsBuffer, + NameInfo, TemplateArgs); + + DeclarationName Name = NameInfo.getName(); + bool IsArrow = (OpKind == tok::arrow); + + NamedDecl *FirstQualifierInScope + = (!SS.isSet() ? 0 : FindFirstQualifierInScope(S, + static_cast(SS.getScopeRep()))); + + // This is a postfix expression, so get rid of ParenListExprs. + ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Base); + if (Result.isInvalid()) return ExprError(); + Base = Result.take(); + + if (Base->getType()->isDependentType() || Name.isDependentName() || + isDependentScopeSpecifier(SS)) { + Result = ActOnDependentMemberExpr(Base, Base->getType(), + IsArrow, OpLoc, + SS, TemplateKWLoc, FirstQualifierInScope, + NameInfo, TemplateArgs); + } else { + LookupResult R(*this, NameInfo, LookupMemberName); + ExprResult BaseResult = Owned(Base); + Result = LookupMemberExpr(R, BaseResult, IsArrow, OpLoc, + SS, ObjCImpDecl, TemplateArgs != 0); + if (BaseResult.isInvalid()) + return ExprError(); + Base = BaseResult.take(); + + if (Result.isInvalid()) { + Owned(Base); + return ExprError(); + } + + if (Result.get()) { + // The only way a reference to a destructor can be used is to + // immediately call it, which falls into this case. If the + // next token is not a '(', produce a diagnostic and build the + // call now. + if (!HasTrailingLParen && + Id.getKind() == UnqualifiedId::IK_DestructorName) + return DiagnoseDtorReference(NameInfo.getLoc(), Result.get()); + + return move(Result); + } + + Result = BuildMemberReferenceExpr(Base, Base->getType(), + OpLoc, IsArrow, SS, TemplateKWLoc, + FirstQualifierInScope, R, TemplateArgs); + } + + return move(Result); +} + +static ExprResult +BuildFieldReferenceExpr(Sema &S, Expr *BaseExpr, bool IsArrow, + const CXXScopeSpec &SS, FieldDecl *Field, + DeclAccessPair FoundDecl, + const DeclarationNameInfo &MemberNameInfo) { + // x.a is an l-value if 'a' has a reference type. Otherwise: + // x.a is an l-value/x-value/pr-value if the base is (and note + // that *x is always an l-value), except that if the base isn't + // an ordinary object then we must have an rvalue. + ExprValueKind VK = VK_LValue; + ExprObjectKind OK = OK_Ordinary; + if (!IsArrow) { + if (BaseExpr->getObjectKind() == OK_Ordinary) + VK = BaseExpr->getValueKind(); + else + VK = VK_RValue; + } + if (VK != VK_RValue && Field->isBitField()) + OK = OK_BitField; + + // Figure out the type of the member; see C99 6.5.2.3p3, C++ [expr.ref] + QualType MemberType = Field->getType(); + if (const ReferenceType *Ref = MemberType->getAs()) { + MemberType = Ref->getPointeeType(); + VK = VK_LValue; + } else { + QualType BaseType = BaseExpr->getType(); + if (IsArrow) BaseType = BaseType->getAs()->getPointeeType(); + + Qualifiers BaseQuals = BaseType.getQualifiers(); + + // GC attributes are never picked up by members. + BaseQuals.removeObjCGCAttr(); + + // CVR attributes from the base are picked up by members, + // except that 'mutable' members don't pick up 'const'. + if (Field->isMutable()) BaseQuals.removeConst(); + + Qualifiers MemberQuals + = S.Context.getCanonicalType(MemberType).getQualifiers(); + + // TR 18037 does not allow fields to be declared with address spaces. + assert(!MemberQuals.hasAddressSpace()); + + Qualifiers Combined = BaseQuals + MemberQuals; + if (Combined != MemberQuals) + MemberType = S.Context.getQualifiedType(MemberType, Combined); + } + + ExprResult Base = + S.PerformObjectMemberConversion(BaseExpr, SS.getScopeRep(), + FoundDecl, Field); + if (Base.isInvalid()) + return ExprError(); + return S.Owned(BuildMemberExpr(S, S.Context, Base.take(), IsArrow, SS, + /*TemplateKWLoc=*/SourceLocation(), + Field, FoundDecl, MemberNameInfo, + MemberType, VK, OK)); +} + +/// 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. +ExprResult +Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, + LookupResult &R, + const TemplateArgumentListInfo *TemplateArgs, + bool IsKnownInstance) { + assert(!R.empty() && !R.isAmbiguous()); + + SourceLocation loc = R.getNameLoc(); + + // We may have found a field within an anonymous union or struct + // (C++ [class.union]). + // FIXME: template-ids inside anonymous structs? + if (IndirectFieldDecl *FD = R.getAsSingle()) + return BuildAnonymousStructUnionMemberReference(SS, R.getNameLoc(), FD); + + // If this is known to be an instance access, go ahead and build an + // implicit 'this' expression now. + // 'this' expression now. + QualType ThisTy = getCurrentThisType(); + assert(!ThisTy.isNull() && "didn't correctly pre-flight capture of 'this'"); + + Expr *baseExpr = 0; // null signifies implicit access + if (IsKnownInstance) { + SourceLocation Loc = R.getNameLoc(); + if (SS.getRange().isValid()) + Loc = SS.getRange().getBegin(); + CheckCXXThisCapture(Loc); + baseExpr = new (Context) CXXThisExpr(loc, ThisTy, /*isImplicit=*/true); + } + + return BuildMemberReferenceExpr(baseExpr, ThisTy, + /*OpLoc*/ SourceLocation(), + /*IsArrow*/ true, + SS, TemplateKWLoc, + /*FirstQualifierInScope*/ 0, + R, TemplateArgs); +} diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp new file mode 100644 index 0000000..b62d56e --- /dev/null +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -0,0 +1,3049 @@ +//===--- SemaExprObjC.cpp - Semantic Analysis for ObjC Expressions --------===// +// +// 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 Objective-C expressions. +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/Initialization.h" +#include "clang/Analysis/DomainSpecific/CocoaConventions.h" +#include "clang/Edit/Rewriters.h" +#include "clang/Edit/Commit.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/ExprObjC.h" +#include "clang/AST/StmtVisitor.h" +#include "clang/AST/TypeLoc.h" +#include "llvm/ADT/SmallString.h" +#include "clang/Lex/Preprocessor.h" + +using namespace clang; +using namespace sema; +using llvm::makeArrayRef; + +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* + // have strings formed out of multiple @ strings with multiple pptokens in + // each one, e.g. @"foo" "bar" @"baz" "qux" which need to be turned into one + // StringLiteral for ObjCStringLiteral to hold onto. + StringLiteral *S = Strings[0]; + + // If we have a multi-part string, merge it all together. + if (NumStrings != 1) { + // Concatenate objc strings. + SmallString<128> StrBuf; + SmallVector StrLocs; + + for (unsigned i = 0; i != NumStrings; ++i) { + S = Strings[i]; + + // ObjC strings can't be wide or UTF. + if (!S->isAscii()) { + Diag(S->getLocStart(), diag::err_cfstring_literal_not_string_constant) + << S->getSourceRange(); + return true; + } + + // Append the string. + StrBuf += S->getString(); + + // Get the locations of the string tokens. + StrLocs.append(S->tokloc_begin(), S->tokloc_end()); + } + + // Create the aggregate string with the appropriate content and location + // information. + S = StringLiteral::Create(Context, StrBuf, + StringLiteral::Ascii, /*Pascal=*/false, + Context.getPointerType(Context.CharTy), + &StrLocs[0], StrLocs.size()); + } + + return BuildObjCStringLiteral(AtLocs[0], S); +} + +ExprResult Sema::BuildObjCStringLiteral(SourceLocation AtLoc, StringLiteral *S){ + // Verify that this composite string is acceptable for ObjC strings. + if (CheckObjCString(S)) + return true; + + // Initialize the constant string interface lazily. This assumes + // the NSString interface is seen in this translation unit. Note: We + // don't use NSConstantString, since the runtime team considers this + // interface private (even though it appears in the header files). + QualType Ty = Context.getObjCConstantStringInterface(); + if (!Ty.isNull()) { + Ty = Context.getObjCObjectPointerType(Ty); + } else if (getLangOpts().NoConstantCFStrings) { + IdentifierInfo *NSIdent=0; + std::string StringClass(getLangOpts().ObjCConstantStringClass); + + if (StringClass.empty()) + NSIdent = &Context.Idents.get("NSConstantString"); + else + NSIdent = &Context.Idents.get(StringClass); + + NamedDecl *IF = LookupSingleName(TUScope, NSIdent, AtLoc, + LookupOrdinaryName); + if (ObjCInterfaceDecl *StrIF = dyn_cast_or_null(IF)) { + Context.setObjCConstantStringInterface(StrIF); + Ty = Context.getObjCConstantStringInterface(); + Ty = Context.getObjCObjectPointerType(Ty); + } else { + // If there is no NSConstantString interface defined then treat this + // as error and recover from it. + Diag(S->getLocStart(), diag::err_no_nsconstant_string_class) << NSIdent + << S->getSourceRange(); + Ty = Context.getObjCIdType(); + } + } else { + IdentifierInfo *NSIdent = &Context.Idents.get("NSString"); + NamedDecl *IF = LookupSingleName(TUScope, NSIdent, AtLoc, + LookupOrdinaryName); + if (ObjCInterfaceDecl *StrIF = dyn_cast_or_null(IF)) { + Context.setObjCConstantStringInterface(StrIF); + Ty = Context.getObjCConstantStringInterface(); + Ty = Context.getObjCObjectPointerType(Ty); + } else { + // If there is no NSString interface defined, implicitly declare + // a @class NSString; and use that instead. This is to make sure + // type of an NSString literal is represented correctly, instead of + // being an 'id' type. + Ty = Context.getObjCNSStringType(); + if (Ty.isNull()) { + ObjCInterfaceDecl *NSStringIDecl = + ObjCInterfaceDecl::Create (Context, + Context.getTranslationUnitDecl(), + SourceLocation(), NSIdent, + 0, SourceLocation()); + Ty = Context.getObjCInterfaceType(NSStringIDecl); + Context.setObjCNSStringType(Ty); + } + Ty = Context.getObjCObjectPointerType(Ty); + } + } + + return new (Context) ObjCStringLiteral(S, Ty, AtLoc); +} + +/// \brief Retrieve the NSNumber factory method that should be used to create +/// an Objective-C literal for the given type. +static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc, + QualType T, QualType ReturnType, + SourceRange Range) { + llvm::Optional Kind + = S.NSAPIObj->getNSNumberFactoryMethodKind(T); + + if (!Kind) { + S.Diag(Loc, diag::err_invalid_nsnumber_type) + << T << Range; + return 0; + } + + // If we already looked up this method, we're done. + if (S.NSNumberLiteralMethods[*Kind]) + return S.NSNumberLiteralMethods[*Kind]; + + Selector Sel = S.NSAPIObj->getNSNumberLiteralSelector(*Kind, + /*Instance=*/false); + + // Look for the appropriate method within NSNumber. + ObjCMethodDecl *Method = S.NSNumberDecl->lookupClassMethod(Sel);; + if (!Method && S.getLangOpts().DebuggerObjCLiteral) { + TypeSourceInfo *ResultTInfo = 0; + Method = ObjCMethodDecl::Create(S.Context, SourceLocation(), SourceLocation(), Sel, + ReturnType, + ResultTInfo, + S.Context.getTranslationUnitDecl(), + false /*Instance*/, false/*isVariadic*/, + /*isSynthesized=*/false, + /*isImplicitlyDeclared=*/true, /*isDefined=*/false, + ObjCMethodDecl::Required, + false); + ParmVarDecl *value = ParmVarDecl::Create(S.Context, Method, + SourceLocation(), SourceLocation(), + &S.Context.Idents.get("value"), + T, /*TInfo=*/0, SC_None, SC_None, 0); + Method->setMethodParams(S.Context, value, ArrayRef()); + } + + if (!Method) { + S.Diag(Loc, diag::err_undeclared_nsnumber_method) << Sel; + return 0; + } + + // Make sure the return type is reasonable. + if (!Method->getResultType()->isObjCObjectPointerType()) { + S.Diag(Loc, diag::err_objc_literal_method_sig) + << Sel; + S.Diag(Method->getLocation(), diag::note_objc_literal_method_return) + << Method->getResultType(); + return 0; + } + + // Note: if the parameter type is out-of-line, we'll catch it later in the + // implicit conversion. + + S.NSNumberLiteralMethods[*Kind] = Method; + return Method; +} + +/// BuildObjCNumericLiteral - builds an ObjCNumericLiteral AST node for the +/// numeric literal expression. Type of the expression will be "NSNumber *" +/// or "id" if NSNumber is unavailable. +ExprResult Sema::BuildObjCNumericLiteral(SourceLocation AtLoc, Expr *Number) { + // Look up the NSNumber class, if we haven't done so already. + if (!NSNumberDecl) { + NamedDecl *IF = LookupSingleName(TUScope, + NSAPIObj->getNSClassId(NSAPI::ClassId_NSNumber), + AtLoc, LookupOrdinaryName); + NSNumberDecl = dyn_cast_or_null(IF); + + if (!NSNumberDecl && getLangOpts().DebuggerObjCLiteral) + NSNumberDecl = ObjCInterfaceDecl::Create (Context, + Context.getTranslationUnitDecl(), + SourceLocation(), + NSAPIObj->getNSClassId(NSAPI::ClassId_NSNumber), + 0, SourceLocation()); + if (!NSNumberDecl) { + Diag(AtLoc, diag::err_undeclared_nsnumber); + return ExprError(); + } + } + + // Determine the type of the literal. + QualType NumberType = Number->getType(); + if (CharacterLiteral *Char = dyn_cast(Number)) { + // In C, character literals have type 'int'. That's not the type we want + // to use to determine the Objective-c literal kind. + switch (Char->getKind()) { + case CharacterLiteral::Ascii: + NumberType = Context.CharTy; + break; + + case CharacterLiteral::Wide: + NumberType = Context.getWCharType(); + break; + + case CharacterLiteral::UTF16: + NumberType = Context.Char16Ty; + break; + + case CharacterLiteral::UTF32: + NumberType = Context.Char32Ty; + break; + } + } + + ObjCMethodDecl *Method = 0; + // Look for the appropriate method within NSNumber. + // Construct the literal. + QualType Ty + = Context.getObjCObjectPointerType( + Context.getObjCInterfaceType(NSNumberDecl)); + Method = getNSNumberFactoryMethod(*this, AtLoc, + NumberType, Ty, + Number->getSourceRange()); + + if (!Method) + return ExprError(); + + // Convert the number to the type that the parameter expects. + QualType ElementT = Method->param_begin()[0]->getType(); + ExprResult ConvertedNumber = PerformImplicitConversion(Number, ElementT, + AA_Sending); + if (ConvertedNumber.isInvalid()) + return ExprError(); + Number = ConvertedNumber.get(); + + return MaybeBindToTemporary( + new (Context) ObjCNumericLiteral(Number, Ty, Method, AtLoc)); +} + +ExprResult Sema::ActOnObjCBoolLiteral(SourceLocation AtLoc, + SourceLocation ValueLoc, + bool Value) { + ExprResult Inner; + if (getLangOpts().CPlusPlus) { + Inner = ActOnCXXBoolLiteral(ValueLoc, Value? tok::kw_true : tok::kw_false); + } else { + // C doesn't actually have a way to represent literal values of type + // _Bool. So, we'll use 0/1 and implicit cast to _Bool. + Inner = ActOnIntegerConstant(ValueLoc, Value? 1 : 0); + Inner = ImpCastExprToType(Inner.get(), Context.BoolTy, + CK_IntegralToBoolean); + } + + return BuildObjCNumericLiteral(AtLoc, Inner.get()); +} + +/// \brief Check that the given expression is a valid element of an Objective-C +/// collection literal. +static ExprResult CheckObjCCollectionLiteralElement(Sema &S, Expr *Element, + QualType T) { + // If the expression is type-dependent, there's nothing for us to do. + if (Element->isTypeDependent()) + return Element; + + ExprResult Result = S.CheckPlaceholderExpr(Element); + if (Result.isInvalid()) + return ExprError(); + Element = Result.get(); + + // In C++, check for an implicit conversion to an Objective-C object pointer + // type. + if (S.getLangOpts().CPlusPlus && Element->getType()->isRecordType()) { + InitializedEntity Entity + = InitializedEntity::InitializeParameter(S.Context, T, /*Consumed=*/false); + InitializationKind Kind + = InitializationKind::CreateCopy(Element->getLocStart(), SourceLocation()); + InitializationSequence Seq(S, Entity, Kind, &Element, 1); + if (!Seq.Failed()) + return Seq.Perform(S, Entity, Kind, MultiExprArg(S, &Element, 1)); + } + + Expr *OrigElement = Element; + + // Perform lvalue-to-rvalue conversion. + Result = S.DefaultLvalueConversion(Element); + if (Result.isInvalid()) + return ExprError(); + Element = Result.get(); + + // Make sure that we have an Objective-C pointer type or block. + if (!Element->getType()->isObjCObjectPointerType() && + !Element->getType()->isBlockPointerType()) { + bool Recovered = false; + + // If this is potentially an Objective-C numeric literal, add the '@'. + if (isa(OrigElement) || + isa(OrigElement) || + isa(OrigElement) || + isa(OrigElement) || + isa(OrigElement)) { + if (S.NSAPIObj->getNSNumberFactoryMethodKind(OrigElement->getType())) { + int Which = isa(OrigElement) ? 1 + : (isa(OrigElement) || + isa(OrigElement)) ? 2 + : 3; + + S.Diag(OrigElement->getLocStart(), diag::err_box_literal_collection) + << Which << OrigElement->getSourceRange() + << FixItHint::CreateInsertion(OrigElement->getLocStart(), "@"); + + Result = S.BuildObjCNumericLiteral(OrigElement->getLocStart(), + OrigElement); + if (Result.isInvalid()) + return ExprError(); + + Element = Result.get(); + Recovered = true; + } + } + // If this is potentially an Objective-C string literal, add the '@'. + else if (StringLiteral *String = dyn_cast(OrigElement)) { + if (String->isAscii()) { + S.Diag(OrigElement->getLocStart(), diag::err_box_literal_collection) + << 0 << OrigElement->getSourceRange() + << FixItHint::CreateInsertion(OrigElement->getLocStart(), "@"); + + Result = S.BuildObjCStringLiteral(OrigElement->getLocStart(), String); + if (Result.isInvalid()) + return ExprError(); + + Element = Result.get(); + Recovered = true; + } + } + + if (!Recovered) { + S.Diag(Element->getLocStart(), diag::err_invalid_collection_element) + << Element->getType(); + return ExprError(); + } + } + + // Make sure that the element has the type that the container factory + // function expects. + return S.PerformCopyInitialization( + InitializedEntity::InitializeParameter(S.Context, T, + /*Consumed=*/false), + Element->getLocStart(), Element); +} + +ExprResult Sema::BuildObjCSubscriptExpression(SourceLocation RB, Expr *BaseExpr, + Expr *IndexExpr, + ObjCMethodDecl *getterMethod, + ObjCMethodDecl *setterMethod) { + // Feature support is for modern abi. + if (!LangOpts.ObjCNonFragileABI) + return ExprError(); + // If the expression is type-dependent, there's nothing for us to do. + assert ((!BaseExpr->isTypeDependent() && !IndexExpr->isTypeDependent()) && + "base or index cannot have dependent type here"); + ExprResult Result = CheckPlaceholderExpr(IndexExpr); + if (Result.isInvalid()) + return ExprError(); + IndexExpr = Result.get(); + + // Perform lvalue-to-rvalue conversion. + Result = DefaultLvalueConversion(BaseExpr); + if (Result.isInvalid()) + return ExprError(); + BaseExpr = Result.get(); + return Owned(ObjCSubscriptRefExpr::Create(Context, + BaseExpr, + IndexExpr, + Context.PseudoObjectTy, + getterMethod, + setterMethod, RB)); + +} + +ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) { + // Look up the NSArray class, if we haven't done so already. + if (!NSArrayDecl) { + NamedDecl *IF = LookupSingleName(TUScope, + NSAPIObj->getNSClassId(NSAPI::ClassId_NSArray), + SR.getBegin(), + LookupOrdinaryName); + NSArrayDecl = dyn_cast_or_null(IF); + if (!NSArrayDecl && getLangOpts().DebuggerObjCLiteral) + NSArrayDecl = ObjCInterfaceDecl::Create (Context, + Context.getTranslationUnitDecl(), + SourceLocation(), + NSAPIObj->getNSClassId(NSAPI::ClassId_NSArray), + 0, SourceLocation()); + + if (!NSArrayDecl) { + Diag(SR.getBegin(), diag::err_undeclared_nsarray); + return ExprError(); + } + } + + // Find the arrayWithObjects:count: method, if we haven't done so already. + QualType IdT = Context.getObjCIdType(); + if (!ArrayWithObjectsMethod) { + Selector + Sel = NSAPIObj->getNSArraySelector(NSAPI::NSArr_arrayWithObjectsCount); + ArrayWithObjectsMethod = NSArrayDecl->lookupClassMethod(Sel); + if (!ArrayWithObjectsMethod && getLangOpts().DebuggerObjCLiteral) { + TypeSourceInfo *ResultTInfo = 0; + ArrayWithObjectsMethod = + ObjCMethodDecl::Create(Context, + SourceLocation(), SourceLocation(), Sel, + IdT, + ResultTInfo, + Context.getTranslationUnitDecl(), + false /*Instance*/, false/*isVariadic*/, + /*isSynthesized=*/false, + /*isImplicitlyDeclared=*/true, /*isDefined=*/false, + ObjCMethodDecl::Required, + false); + SmallVector Params; + ParmVarDecl *objects = ParmVarDecl::Create(Context, ArrayWithObjectsMethod, + SourceLocation(), SourceLocation(), + &Context.Idents.get("objects"), + Context.getPointerType(IdT), + /*TInfo=*/0, + SC_None, + SC_None, + 0); + Params.push_back(objects); + ParmVarDecl *cnt = ParmVarDecl::Create(Context, ArrayWithObjectsMethod, + SourceLocation(), SourceLocation(), + &Context.Idents.get("cnt"), + Context.UnsignedLongTy, + /*TInfo=*/0, + SC_None, + SC_None, + 0); + Params.push_back(cnt); + ArrayWithObjectsMethod->setMethodParams(Context, Params, + ArrayRef()); + + + } + + if (!ArrayWithObjectsMethod) { + Diag(SR.getBegin(), diag::err_undeclared_arraywithobjects) << Sel; + return ExprError(); + } + } + + // Make sure the return type is reasonable. + if (!ArrayWithObjectsMethod->getResultType()->isObjCObjectPointerType()) { + Diag(SR.getBegin(), diag::err_objc_literal_method_sig) + << ArrayWithObjectsMethod->getSelector(); + Diag(ArrayWithObjectsMethod->getLocation(), + diag::note_objc_literal_method_return) + << ArrayWithObjectsMethod->getResultType(); + return ExprError(); + } + + // Dig out the type that all elements should be converted to. + QualType T = ArrayWithObjectsMethod->param_begin()[0]->getType(); + const PointerType *PtrT = T->getAs(); + if (!PtrT || + !Context.hasSameUnqualifiedType(PtrT->getPointeeType(), IdT)) { + Diag(SR.getBegin(), diag::err_objc_literal_method_sig) + << ArrayWithObjectsMethod->getSelector(); + Diag(ArrayWithObjectsMethod->param_begin()[0]->getLocation(), + diag::note_objc_literal_method_param) + << 0 << T + << Context.getPointerType(IdT.withConst()); + return ExprError(); + } + T = PtrT->getPointeeType(); + + // Check that the 'count' parameter is integral. + if (!ArrayWithObjectsMethod->param_begin()[1]->getType()->isIntegerType()) { + Diag(SR.getBegin(), diag::err_objc_literal_method_sig) + << ArrayWithObjectsMethod->getSelector(); + Diag(ArrayWithObjectsMethod->param_begin()[1]->getLocation(), + diag::note_objc_literal_method_param) + << 1 + << ArrayWithObjectsMethod->param_begin()[1]->getType() + << "integral"; + return ExprError(); + } + + // Check that each of the elements provided is valid in a collection literal, + // performing conversions as necessary. + Expr **ElementsBuffer = Elements.get(); + for (unsigned I = 0, N = Elements.size(); I != N; ++I) { + ExprResult Converted = CheckObjCCollectionLiteralElement(*this, + ElementsBuffer[I], + T); + if (Converted.isInvalid()) + return ExprError(); + + ElementsBuffer[I] = Converted.get(); + } + + QualType Ty + = Context.getObjCObjectPointerType( + Context.getObjCInterfaceType(NSArrayDecl)); + + return MaybeBindToTemporary( + ObjCArrayLiteral::Create(Context, + llvm::makeArrayRef(Elements.get(), + Elements.size()), + Ty, ArrayWithObjectsMethod, SR)); +} + +ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR, + ObjCDictionaryElement *Elements, + unsigned NumElements) { + // Look up the NSDictionary class, if we haven't done so already. + if (!NSDictionaryDecl) { + NamedDecl *IF = LookupSingleName(TUScope, + NSAPIObj->getNSClassId(NSAPI::ClassId_NSDictionary), + SR.getBegin(), LookupOrdinaryName); + NSDictionaryDecl = dyn_cast_or_null(IF); + if (!NSDictionaryDecl && getLangOpts().DebuggerObjCLiteral) + NSDictionaryDecl = ObjCInterfaceDecl::Create (Context, + Context.getTranslationUnitDecl(), + SourceLocation(), + NSAPIObj->getNSClassId(NSAPI::ClassId_NSDictionary), + 0, SourceLocation()); + + if (!NSDictionaryDecl) { + Diag(SR.getBegin(), diag::err_undeclared_nsdictionary); + return ExprError(); + } + } + + // Find the dictionaryWithObjects:forKeys:count: method, if we haven't done + // so already. + QualType IdT = Context.getObjCIdType(); + if (!DictionaryWithObjectsMethod) { + Selector Sel = NSAPIObj->getNSDictionarySelector( + NSAPI::NSDict_dictionaryWithObjectsForKeysCount); + DictionaryWithObjectsMethod = NSDictionaryDecl->lookupClassMethod(Sel); + if (!DictionaryWithObjectsMethod && getLangOpts().DebuggerObjCLiteral) { + DictionaryWithObjectsMethod = + ObjCMethodDecl::Create(Context, + SourceLocation(), SourceLocation(), Sel, + IdT, + 0 /*TypeSourceInfo */, + Context.getTranslationUnitDecl(), + false /*Instance*/, false/*isVariadic*/, + /*isSynthesized=*/false, + /*isImplicitlyDeclared=*/true, /*isDefined=*/false, + ObjCMethodDecl::Required, + false); + SmallVector Params; + ParmVarDecl *objects = ParmVarDecl::Create(Context, DictionaryWithObjectsMethod, + SourceLocation(), SourceLocation(), + &Context.Idents.get("objects"), + Context.getPointerType(IdT), + /*TInfo=*/0, + SC_None, + SC_None, + 0); + Params.push_back(objects); + ParmVarDecl *keys = ParmVarDecl::Create(Context, DictionaryWithObjectsMethod, + SourceLocation(), SourceLocation(), + &Context.Idents.get("keys"), + Context.getPointerType(IdT), + /*TInfo=*/0, + SC_None, + SC_None, + 0); + Params.push_back(keys); + ParmVarDecl *cnt = ParmVarDecl::Create(Context, DictionaryWithObjectsMethod, + SourceLocation(), SourceLocation(), + &Context.Idents.get("cnt"), + Context.UnsignedLongTy, + /*TInfo=*/0, + SC_None, + SC_None, + 0); + Params.push_back(cnt); + DictionaryWithObjectsMethod->setMethodParams(Context, Params, + ArrayRef()); + } + + if (!DictionaryWithObjectsMethod) { + Diag(SR.getBegin(), diag::err_undeclared_dictwithobjects) << Sel; + return ExprError(); + } + } + + // Make sure the return type is reasonable. + if (!DictionaryWithObjectsMethod->getResultType()->isObjCObjectPointerType()){ + Diag(SR.getBegin(), diag::err_objc_literal_method_sig) + << DictionaryWithObjectsMethod->getSelector(); + Diag(DictionaryWithObjectsMethod->getLocation(), + diag::note_objc_literal_method_return) + << DictionaryWithObjectsMethod->getResultType(); + return ExprError(); + } + + // Dig out the type that all values should be converted to. + QualType ValueT = DictionaryWithObjectsMethod->param_begin()[0]->getType(); + const PointerType *PtrValue = ValueT->getAs(); + if (!PtrValue || + !Context.hasSameUnqualifiedType(PtrValue->getPointeeType(), IdT)) { + Diag(SR.getBegin(), diag::err_objc_literal_method_sig) + << DictionaryWithObjectsMethod->getSelector(); + Diag(DictionaryWithObjectsMethod->param_begin()[0]->getLocation(), + diag::note_objc_literal_method_param) + << 0 << ValueT + << Context.getPointerType(IdT.withConst()); + return ExprError(); + } + ValueT = PtrValue->getPointeeType(); + + // Dig out the type that all keys should be converted to. + QualType KeyT = DictionaryWithObjectsMethod->param_begin()[1]->getType(); + const PointerType *PtrKey = KeyT->getAs(); + if (!PtrKey || + !Context.hasSameUnqualifiedType(PtrKey->getPointeeType(), + IdT)) { + bool err = true; + if (PtrKey) { + if (QIDNSCopying.isNull()) { + // key argument of selector is id? + if (ObjCProtocolDecl *NSCopyingPDecl = + LookupProtocol(&Context.Idents.get("NSCopying"), SR.getBegin())) { + ObjCProtocolDecl *PQ[] = {NSCopyingPDecl}; + QIDNSCopying = + Context.getObjCObjectType(Context.ObjCBuiltinIdTy, + (ObjCProtocolDecl**) PQ,1); + QIDNSCopying = Context.getObjCObjectPointerType(QIDNSCopying); + } + } + if (!QIDNSCopying.isNull()) + err = !Context.hasSameUnqualifiedType(PtrKey->getPointeeType(), + QIDNSCopying); + } + + if (err) { + Diag(SR.getBegin(), diag::err_objc_literal_method_sig) + << DictionaryWithObjectsMethod->getSelector(); + Diag(DictionaryWithObjectsMethod->param_begin()[1]->getLocation(), + diag::note_objc_literal_method_param) + << 1 << KeyT + << Context.getPointerType(IdT.withConst()); + return ExprError(); + } + } + KeyT = PtrKey->getPointeeType(); + + // Check that the 'count' parameter is integral. + if (!DictionaryWithObjectsMethod->param_begin()[2]->getType() + ->isIntegerType()) { + Diag(SR.getBegin(), diag::err_objc_literal_method_sig) + << DictionaryWithObjectsMethod->getSelector(); + Diag(DictionaryWithObjectsMethod->param_begin()[2]->getLocation(), + diag::note_objc_literal_method_param) + << 2 + << DictionaryWithObjectsMethod->param_begin()[2]->getType() + << "integral"; + return ExprError(); + } + + // Check that each of the keys and values provided is valid in a collection + // literal, performing conversions as necessary. + bool HasPackExpansions = false; + for (unsigned I = 0, N = NumElements; I != N; ++I) { + // Check the key. + ExprResult Key = CheckObjCCollectionLiteralElement(*this, Elements[I].Key, + KeyT); + if (Key.isInvalid()) + return ExprError(); + + // Check the value. + ExprResult Value + = CheckObjCCollectionLiteralElement(*this, Elements[I].Value, ValueT); + if (Value.isInvalid()) + return ExprError(); + + Elements[I].Key = Key.get(); + Elements[I].Value = Value.get(); + + if (Elements[I].EllipsisLoc.isInvalid()) + continue; + + if (!Elements[I].Key->containsUnexpandedParameterPack() && + !Elements[I].Value->containsUnexpandedParameterPack()) { + Diag(Elements[I].EllipsisLoc, + diag::err_pack_expansion_without_parameter_packs) + << SourceRange(Elements[I].Key->getLocStart(), + Elements[I].Value->getLocEnd()); + return ExprError(); + } + + HasPackExpansions = true; + } + + + QualType Ty + = Context.getObjCObjectPointerType( + Context.getObjCInterfaceType(NSDictionaryDecl)); + return MaybeBindToTemporary( + ObjCDictionaryLiteral::Create(Context, + llvm::makeArrayRef(Elements, + NumElements), + HasPackExpansions, + Ty, + DictionaryWithObjectsMethod, SR)); +} + +ExprResult Sema::BuildObjCEncodeExpression(SourceLocation AtLoc, + TypeSourceInfo *EncodedTypeInfo, + SourceLocation RParenLoc) { + QualType EncodedType = EncodedTypeInfo->getType(); + QualType StrTy; + if (EncodedType->isDependentType()) + StrTy = Context.DependentTy; + else { + if (!EncodedType->getAsArrayTypeUnsafe() && //// Incomplete array is handled. + !EncodedType->isVoidType()) // void is handled too. + if (RequireCompleteType(AtLoc, EncodedType, + PDiag(diag::err_incomplete_type_objc_at_encode) + << EncodedTypeInfo->getTypeLoc().getSourceRange())) + return ExprError(); + + std::string Str; + Context.getObjCEncodingForType(EncodedType, Str); + + // The type of @encode is the same as the type of the corresponding string, + // which is an array type. + StrTy = Context.CharTy; + // A C++ string literal has a const-qualified element type (C++ 2.13.4p1). + if (getLangOpts().CPlusPlus || getLangOpts().ConstStrings) + StrTy.addConst(); + StrTy = Context.getConstantArrayType(StrTy, llvm::APInt(32, Str.size()+1), + ArrayType::Normal, 0); + } + + return new (Context) ObjCEncodeExpr(StrTy, EncodedTypeInfo, AtLoc, 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); + if (!TInfo) + TInfo = Context.getTrivialTypeSourceInfo(EncodedType, + PP.getLocForEndOfToken(LParenLoc)); + + return BuildObjCEncodeExpression(AtLoc, TInfo, RParenLoc); +} + +ExprResult Sema::ParseObjCSelectorExpression(Selector Sel, + SourceLocation AtLoc, + SourceLocation SelLoc, + SourceLocation LParenLoc, + SourceLocation RParenLoc) { + ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool(Sel, + SourceRange(LParenLoc, RParenLoc), false, false); + if (!Method) + Method = LookupFactoryMethodInGlobalPool(Sel, + SourceRange(LParenLoc, RParenLoc)); + if (!Method) + Diag(SelLoc, diag::warn_undeclared_selector) << Sel; + + if (!Method || + Method->getImplementationControl() != ObjCMethodDecl::Optional) { + llvm::DenseMap::iterator Pos + = ReferencedSelectors.find(Sel); + if (Pos == ReferencedSelectors.end()) + ReferencedSelectors.insert(std::make_pair(Sel, SelLoc)); + } + + // In ARC, forbid the user from using @selector for + // retain/release/autorelease/dealloc/retainCount. + if (getLangOpts().ObjCAutoRefCount) { + switch (Sel.getMethodFamily()) { + case OMF_retain: + case OMF_release: + case OMF_autorelease: + case OMF_retainCount: + case OMF_dealloc: + Diag(AtLoc, diag::err_arc_illegal_selector) << + Sel << SourceRange(LParenLoc, RParenLoc); + break; + + case OMF_None: + case OMF_alloc: + case OMF_copy: + case OMF_finalize: + case OMF_init: + case OMF_mutableCopy: + case OMF_new: + case OMF_self: + case OMF_performSelector: + break; + } + } + QualType Ty = Context.getObjCSelType(); + return new (Context) ObjCSelectorExpr(Ty, Sel, AtLoc, 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; + return true; + } + + QualType Ty = Context.getObjCProtoType(); + if (Ty.isNull()) + return true; + Ty = Context.getObjCObjectPointerType(Ty); + return new (Context) ObjCProtocolExpr(Ty, PDecl, AtLoc, RParenLoc); +} + +/// Try to capture an implicit reference to 'self'. +ObjCMethodDecl *Sema::tryCaptureObjCSelf(SourceLocation Loc) { + DeclContext *DC = getFunctionLevelDeclContext(); + + // If we're not in an ObjC method, error out. Note that, unlike the + // C++ case, we don't require an instance method --- class methods + // still have a 'self', and we really do still need to capture it! + ObjCMethodDecl *method = dyn_cast(DC); + if (!method) + return 0; + + tryCaptureVariable(method->getSelfDecl(), Loc); + + return method; +} + +static QualType stripObjCInstanceType(ASTContext &Context, QualType T) { + if (T == Context.getObjCInstanceType()) + return Context.getObjCIdType(); + + return T; +} + +QualType Sema::getMessageSendResultType(QualType ReceiverType, + ObjCMethodDecl *Method, + bool isClassMessage, bool isSuperMessage) { + assert(Method && "Must have a method"); + if (!Method->hasRelatedResultType()) + return Method->getSendResultType(); + + // If a method has a related return type: + // - if the method found is an instance method, but the message send + // was a class message send, T is the declared return type of the method + // found + if (Method->isInstanceMethod() && isClassMessage) + return stripObjCInstanceType(Context, Method->getSendResultType()); + + // - if the receiver is super, T is a pointer to the class of the + // enclosing method definition + if (isSuperMessage) { + if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) + if (ObjCInterfaceDecl *Class = CurMethod->getClassInterface()) + return Context.getObjCObjectPointerType( + Context.getObjCInterfaceType(Class)); + } + + // - if the receiver is the name of a class U, T is a pointer to U + if (ReceiverType->getAs() || + ReceiverType->isObjCQualifiedInterfaceType()) + return Context.getObjCObjectPointerType(ReceiverType); + // - if the receiver is of type Class or qualified Class type, + // T is the declared return type of the method. + if (ReceiverType->isObjCClassType() || + ReceiverType->isObjCQualifiedClassType()) + return stripObjCInstanceType(Context, Method->getSendResultType()); + + // - if the receiver is id, qualified id, Class, or qualified Class, T + // is the receiver type, otherwise + // - T is the type of the receiver expression. + return ReceiverType; +} + +void Sema::EmitRelatedResultTypeNote(const Expr *E) { + E = E->IgnoreParenImpCasts(); + const ObjCMessageExpr *MsgSend = dyn_cast(E); + if (!MsgSend) + return; + + const ObjCMethodDecl *Method = MsgSend->getMethodDecl(); + if (!Method) + return; + + if (!Method->hasRelatedResultType()) + return; + + if (Context.hasSameUnqualifiedType(Method->getResultType() + .getNonReferenceType(), + MsgSend->getType())) + return; + + if (!Context.hasSameUnqualifiedType(Method->getResultType(), + Context.getObjCInstanceType())) + return; + + Diag(Method->getLocation(), diag::note_related_result_type_inferred) + << Method->isInstanceMethod() << Method->getSelector() + << MsgSend->getType(); +} + +bool Sema::CheckMessageArgumentTypes(QualType ReceiverType, + Expr **Args, unsigned NumArgs, + Selector Sel, ObjCMethodDecl *Method, + bool isClassMessage, bool isSuperMessage, + SourceLocation lbrac, SourceLocation rbrac, + QualType &ReturnType, ExprValueKind &VK) { + if (!Method) { + // Apply default argument promotion as for (C99 6.5.2.2p6). + for (unsigned i = 0; i != NumArgs; i++) { + if (Args[i]->isTypeDependent()) + continue; + + ExprResult Result = DefaultArgumentPromotion(Args[i]); + if (Result.isInvalid()) + return true; + Args[i] = Result.take(); + } + + unsigned DiagID; + if (getLangOpts().ObjCAutoRefCount) + DiagID = diag::err_arc_method_not_found; + else + DiagID = isClassMessage ? diag::warn_class_method_not_found + : diag::warn_inst_method_not_found; + if (!getLangOpts().DebuggerSupport) + Diag(lbrac, DiagID) + << Sel << isClassMessage << SourceRange(lbrac, rbrac); + + // In debuggers, we want to use __unknown_anytype for these + // results so that clients can cast them. + if (getLangOpts().DebuggerSupport) { + ReturnType = Context.UnknownAnyTy; + } else { + ReturnType = Context.getObjCIdType(); + } + VK = VK_RValue; + return false; + } + + ReturnType = getMessageSendResultType(ReceiverType, Method, isClassMessage, + isSuperMessage); + VK = Expr::getValueKindForType(Method->getResultType()); + + unsigned NumNamedArgs = Sel.getNumArgs(); + // Method might have more arguments than selector indicates. This is due + // to addition of c-style arguments in method. + if (Method->param_size() > Sel.getNumArgs()) + NumNamedArgs = Method->param_size(); + // FIXME. This need be cleaned up. + if (NumArgs < NumNamedArgs) { + Diag(lbrac, diag::err_typecheck_call_too_few_args) + << 2 << NumNamedArgs << NumArgs; + return false; + } + + bool IsError = false; + for (unsigned i = 0; i < NumNamedArgs; i++) { + // We can't do any type-checking on a type-dependent argument. + if (Args[i]->isTypeDependent()) + continue; + + Expr *argExpr = Args[i]; + + ParmVarDecl *param = Method->param_begin()[i]; + assert(argExpr && "CheckMessageArgumentTypes(): missing expression"); + + // Strip the unbridged-cast placeholder expression off unless it's + // a consumed argument. + if (argExpr->hasPlaceholderType(BuiltinType::ARCUnbridgedCast) && + !param->hasAttr()) + argExpr = stripARCUnbridgedCast(argExpr); + + if (RequireCompleteType(argExpr->getSourceRange().getBegin(), + param->getType(), + PDiag(diag::err_call_incomplete_argument) + << argExpr->getSourceRange())) + return true; + + InitializedEntity Entity = InitializedEntity::InitializeParameter(Context, + param); + ExprResult ArgE = PerformCopyInitialization(Entity, lbrac, Owned(argExpr)); + if (ArgE.isInvalid()) + IsError = true; + else + Args[i] = ArgE.takeAs(); + } + + // Promote additional arguments to variadic methods. + if (Method->isVariadic()) { + for (unsigned i = NumNamedArgs; i < NumArgs; ++i) { + if (Args[i]->isTypeDependent()) + continue; + + ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], VariadicMethod, 0); + IsError |= Arg.isInvalid(); + Args[i] = Arg.take(); + } + } else { + // Check for extra arguments to non-variadic methods. + if (NumArgs != NumNamedArgs) { + Diag(Args[NumNamedArgs]->getLocStart(), + diag::err_typecheck_call_too_many_args) + << 2 /*method*/ << NumNamedArgs << NumArgs + << Method->getSourceRange() + << SourceRange(Args[NumNamedArgs]->getLocStart(), + Args[NumArgs-1]->getLocEnd()); + } + } + + DiagnoseSentinelCalls(Method, lbrac, Args, NumArgs); + + // Do additional checkings on method. + IsError |= CheckObjCMethodCall(Method, lbrac, Args, NumArgs); + + return IsError; +} + +bool Sema::isSelfExpr(Expr *receiver) { + // 'self' is objc 'self' in an objc method only. + ObjCMethodDecl *method = + dyn_cast(CurContext->getNonClosureAncestor()); + if (!method) return false; + + receiver = receiver->IgnoreParenLValueCasts(); + if (DeclRefExpr *DRE = dyn_cast(receiver)) + if (DRE->getDecl() == method->getSelfDecl()) + return true; + return false; +} + +// Helper method for ActOnClassMethod/ActOnInstanceMethod. +// Will search "local" class/category implementations for a method decl. +// If failed, then we search in class's root for an instance method. +// Returns 0 if no method is found. +ObjCMethodDecl *Sema::LookupPrivateClassMethod(Selector Sel, + ObjCInterfaceDecl *ClassDecl) { + ObjCMethodDecl *Method = 0; + // lookup in class and all superclasses + while (ClassDecl && !Method) { + if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation()) + Method = ImpDecl->getClassMethod(Sel); + + // Look through local category implementations associated with the class. + if (!Method) + Method = ClassDecl->getCategoryClassMethod(Sel); + + // Before we give up, check if the selector is an instance method. + // But only in the root. This matches gcc's behaviour and what the + // runtime expects. + if (!Method && !ClassDecl->getSuperClass()) { + Method = ClassDecl->lookupInstanceMethod(Sel); + // Look through local category implementations associated + // with the root class. + if (!Method) + Method = LookupPrivateInstanceMethod(Sel, ClassDecl); + } + + ClassDecl = ClassDecl->getSuperClass(); + } + return Method; +} + +ObjCMethodDecl *Sema::LookupPrivateInstanceMethod(Selector Sel, + ObjCInterfaceDecl *ClassDecl) { + if (!ClassDecl->hasDefinition()) + return 0; + + ObjCMethodDecl *Method = 0; + while (ClassDecl && !Method) { + // If we have implementations in scope, check "private" methods. + if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation()) + Method = ImpDecl->getInstanceMethod(Sel); + + // Look through local category implementations associated with the class. + if (!Method) + Method = ClassDecl->getCategoryInstanceMethod(Sel); + ClassDecl = ClassDecl->getSuperClass(); + } + return Method; +} + +/// LookupMethodInType - Look up a method in an ObjCObjectType. +ObjCMethodDecl *Sema::LookupMethodInObjectType(Selector sel, QualType type, + bool isInstance) { + const ObjCObjectType *objType = type->castAs(); + if (ObjCInterfaceDecl *iface = objType->getInterface()) { + // Look it up in the main interface (and categories, etc.) + if (ObjCMethodDecl *method = iface->lookupMethod(sel, isInstance)) + return method; + + // Okay, look for "private" methods declared in any + // @implementations we've seen. + if (isInstance) { + if (ObjCMethodDecl *method = LookupPrivateInstanceMethod(sel, iface)) + return method; + } else { + if (ObjCMethodDecl *method = LookupPrivateClassMethod(sel, iface)) + return method; + } + } + + // Check qualifiers. + for (ObjCObjectType::qual_iterator + i = objType->qual_begin(), e = objType->qual_end(); i != e; ++i) + if (ObjCMethodDecl *method = (*i)->lookupMethod(sel, isInstance)) + return method; + + return 0; +} + +/// LookupMethodInQualifiedType - Lookups up a method in protocol qualifier +/// list of a qualified objective pointer type. +ObjCMethodDecl *Sema::LookupMethodInQualifiedType(Selector Sel, + const ObjCObjectPointerType *OPT, + bool Instance) +{ + ObjCMethodDecl *MD = 0; + for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(), + E = OPT->qual_end(); I != E; ++I) { + ObjCProtocolDecl *PROTO = (*I); + if ((MD = PROTO->lookupMethod(Sel, Instance))) { + return MD; + } + } + return 0; +} + +/// HandleExprPropertyRefExpr - Handle foo.bar where foo is a pointer to an +/// objective C interface. This is a property reference expression. +ExprResult Sema:: +HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, + Expr *BaseExpr, SourceLocation OpLoc, + DeclarationName MemberName, + SourceLocation MemberLoc, + SourceLocation SuperLoc, QualType SuperType, + bool Super) { + const ObjCInterfaceType *IFaceT = OPT->getInterfaceType(); + ObjCInterfaceDecl *IFace = IFaceT->getDecl(); + + if (MemberName.getNameKind() != DeclarationName::Identifier) { + Diag(MemberLoc, diag::err_invalid_property_name) + << MemberName << QualType(OPT, 0); + return ExprError(); + } + + IdentifierInfo *Member = MemberName.getAsIdentifierInfo(); + SourceRange BaseRange = Super? SourceRange(SuperLoc) + : BaseExpr->getSourceRange(); + if (RequireCompleteType(MemberLoc, OPT->getPointeeType(), + PDiag(diag::err_property_not_found_forward_class) + << MemberName << BaseRange)) + return ExprError(); + + // Search for a declared property first. + if (ObjCPropertyDecl *PD = IFace->FindPropertyDeclaration(Member)) { + // Check whether we can reference this property. + if (DiagnoseUseOfDecl(PD, MemberLoc)) + return ExprError(); + + if (Super) + return Owned(new (Context) ObjCPropertyRefExpr(PD, Context.PseudoObjectTy, + VK_LValue, OK_ObjCProperty, + MemberLoc, + SuperLoc, SuperType)); + else + return Owned(new (Context) ObjCPropertyRefExpr(PD, Context.PseudoObjectTy, + VK_LValue, OK_ObjCProperty, + MemberLoc, BaseExpr)); + } + // Check protocols on qualified interfaces. + for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(), + E = OPT->qual_end(); I != E; ++I) + if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(Member)) { + // Check whether we can reference this property. + if (DiagnoseUseOfDecl(PD, MemberLoc)) + return ExprError(); + + if (Super) + return Owned(new (Context) ObjCPropertyRefExpr(PD, + Context.PseudoObjectTy, + VK_LValue, + OK_ObjCProperty, + MemberLoc, + SuperLoc, SuperType)); + else + return Owned(new (Context) ObjCPropertyRefExpr(PD, + Context.PseudoObjectTy, + VK_LValue, + OK_ObjCProperty, + MemberLoc, + BaseExpr)); + } + // If that failed, look for an "implicit" property by seeing if the nullary + // selector is implemented. + + // FIXME: The logic for looking up nullary and unary selectors should be + // shared with the code in ActOnInstanceMessage. + + Selector Sel = PP.getSelectorTable().getNullarySelector(Member); + ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel); + + // May be founf in property's qualified list. + if (!Getter) + Getter = LookupMethodInQualifiedType(Sel, OPT, true); + + // If this reference is in an @implementation, check for 'private' methods. + if (!Getter) + Getter = IFace->lookupPrivateMethod(Sel); + + // Look through local category implementations associated with the class. + if (!Getter) + Getter = IFace->getCategoryInstanceMethod(Sel); + if (Getter) { + // Check if we can reference this property. + if (DiagnoseUseOfDecl(Getter, MemberLoc)) + return ExprError(); + } + // If we found a getter then this may be a valid dot-reference, we + // will look for the matching setter, in case it is needed. + Selector SetterSel = + SelectorTable::constructSetterName(PP.getIdentifierTable(), + PP.getSelectorTable(), Member); + ObjCMethodDecl *Setter = IFace->lookupInstanceMethod(SetterSel); + + // May be founf in property's qualified list. + if (!Setter) + Setter = LookupMethodInQualifiedType(SetterSel, OPT, true); + + if (!Setter) { + // If this reference is in an @implementation, also check for 'private' + // methods. + Setter = IFace->lookupPrivateMethod(SetterSel); + } + // Look through local category implementations associated with the class. + if (!Setter) + Setter = IFace->getCategoryInstanceMethod(SetterSel); + + if (Setter && DiagnoseUseOfDecl(Setter, MemberLoc)) + return ExprError(); + + if (Getter || Setter) { + if (Super) + return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter, + Context.PseudoObjectTy, + VK_LValue, OK_ObjCProperty, + MemberLoc, + SuperLoc, SuperType)); + else + return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter, + Context.PseudoObjectTy, + VK_LValue, OK_ObjCProperty, + MemberLoc, BaseExpr)); + + } + + // Attempt to correct for typos in property names. + DeclFilterCCC Validator; + if (TypoCorrection Corrected = CorrectTypo( + DeclarationNameInfo(MemberName, MemberLoc), LookupOrdinaryName, NULL, + NULL, Validator, IFace, false, OPT)) { + ObjCPropertyDecl *Property = + Corrected.getCorrectionDeclAs(); + DeclarationName TypoResult = Corrected.getCorrection(); + Diag(MemberLoc, diag::err_property_not_found_suggest) + << MemberName << QualType(OPT, 0) << TypoResult + << FixItHint::CreateReplacement(MemberLoc, TypoResult.getAsString()); + Diag(Property->getLocation(), diag::note_previous_decl) + << Property->getDeclName(); + return HandleExprPropertyRefExpr(OPT, BaseExpr, OpLoc, + TypoResult, MemberLoc, + SuperLoc, SuperType, Super); + } + ObjCInterfaceDecl *ClassDeclared; + if (ObjCIvarDecl *Ivar = + IFace->lookupInstanceVariable(Member, ClassDeclared)) { + QualType T = Ivar->getType(); + if (const ObjCObjectPointerType * OBJPT = + T->getAsObjCInterfacePointerType()) { + if (RequireCompleteType(MemberLoc, OBJPT->getPointeeType(), + PDiag(diag::err_property_not_as_forward_class) + << MemberName << BaseExpr->getSourceRange())) + return ExprError(); + } + Diag(MemberLoc, + diag::err_ivar_access_using_property_syntax_suggest) + << MemberName << QualType(OPT, 0) << Ivar->getDeclName() + << FixItHint::CreateReplacement(OpLoc, "->"); + return ExprError(); + } + + Diag(MemberLoc, diag::err_property_not_found) + << MemberName << QualType(OPT, 0); + if (Setter) + Diag(Setter->getLocation(), diag::note_getter_unavailable) + << MemberName << BaseExpr->getSourceRange(); + return ExprError(); +} + + + +ExprResult Sema:: +ActOnClassPropertyRefExpr(IdentifierInfo &receiverName, + IdentifierInfo &propertyName, + SourceLocation receiverNameLoc, + SourceLocation propertyNameLoc) { + + IdentifierInfo *receiverNamePtr = &receiverName; + ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(receiverNamePtr, + receiverNameLoc); + + bool IsSuper = false; + if (IFace == 0) { + // If the "receiver" is 'super' in a method, handle it as an expression-like + // property reference. + if (receiverNamePtr->isStr("super")) { + IsSuper = true; + + if (ObjCMethodDecl *CurMethod = tryCaptureObjCSelf(receiverNameLoc)) { + if (CurMethod->isInstanceMethod()) { + QualType T = + Context.getObjCInterfaceType(CurMethod->getClassInterface()); + T = Context.getObjCObjectPointerType(T); + + return HandleExprPropertyRefExpr(T->getAsObjCInterfacePointerType(), + /*BaseExpr*/0, + SourceLocation()/*OpLoc*/, + &propertyName, + propertyNameLoc, + receiverNameLoc, T, true); + } + + // Otherwise, if this is a class method, try dispatching to our + // superclass. + IFace = CurMethod->getClassInterface()->getSuperClass(); + } + } + + if (IFace == 0) { + Diag(receiverNameLoc, diag::err_expected_ident_or_lparen); + return ExprError(); + } + } + + // Search for a declared property first. + Selector Sel = PP.getSelectorTable().getNullarySelector(&propertyName); + ObjCMethodDecl *Getter = IFace->lookupClassMethod(Sel); + + // If this reference is in an @implementation, check for 'private' methods. + if (!Getter) + if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) + if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) + if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation()) + Getter = ImpDecl->getClassMethod(Sel); + + if (Getter) { + // FIXME: refactor/share with ActOnMemberReference(). + // Check if we can reference this property. + if (DiagnoseUseOfDecl(Getter, propertyNameLoc)) + return ExprError(); + } + + // Look for the matching setter, in case it is needed. + Selector SetterSel = + SelectorTable::constructSetterName(PP.getIdentifierTable(), + PP.getSelectorTable(), &propertyName); + + ObjCMethodDecl *Setter = IFace->lookupClassMethod(SetterSel); + if (!Setter) { + // If this reference is in an @implementation, also check for 'private' + // methods. + if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) + if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) + if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation()) + Setter = ImpDecl->getClassMethod(SetterSel); + } + // Look through local category implementations associated with the class. + if (!Setter) + Setter = IFace->getCategoryClassMethod(SetterSel); + + if (Setter && DiagnoseUseOfDecl(Setter, propertyNameLoc)) + return ExprError(); + + if (Getter || Setter) { + if (IsSuper) + return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter, + Context.PseudoObjectTy, + VK_LValue, OK_ObjCProperty, + propertyNameLoc, + receiverNameLoc, + Context.getObjCInterfaceType(IFace))); + + return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter, + Context.PseudoObjectTy, + VK_LValue, OK_ObjCProperty, + propertyNameLoc, + receiverNameLoc, IFace)); + } + return ExprError(Diag(propertyNameLoc, diag::err_property_not_found) + << &propertyName << Context.getObjCInterfaceType(IFace)); +} + +namespace { + +class ObjCInterfaceOrSuperCCC : public CorrectionCandidateCallback { + public: + ObjCInterfaceOrSuperCCC(ObjCMethodDecl *Method) { + // Determine whether "super" is acceptable in the current context. + if (Method && Method->getClassInterface()) + WantObjCSuper = Method->getClassInterface()->getSuperClass(); + } + + virtual bool ValidateCandidate(const TypoCorrection &candidate) { + return candidate.getCorrectionDeclAs() || + candidate.isKeyword("super"); + } +}; + +} + +Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S, + IdentifierInfo *Name, + SourceLocation NameLoc, + bool IsSuper, + bool HasTrailingDot, + ParsedType &ReceiverType) { + ReceiverType = ParsedType(); + + // If the identifier is "super" and there is no trailing dot, we're + // messaging super. If the identifier is "super" and there is a + // trailing dot, it's an instance message. + if (IsSuper && S->isInObjcMethodScope()) + return HasTrailingDot? ObjCInstanceMessage : ObjCSuperMessage; + + LookupResult Result(*this, Name, NameLoc, LookupOrdinaryName); + LookupName(Result, S); + + switch (Result.getResultKind()) { + case LookupResult::NotFound: + // Normal name lookup didn't find anything. If we're in an + // Objective-C method, look for ivars. If we find one, we're done! + // FIXME: This is a hack. Ivar lookup should be part of normal + // lookup. + if (ObjCMethodDecl *Method = getCurMethodDecl()) { + if (!Method->getClassInterface()) { + // Fall back: let the parser try to parse it as an instance message. + return ObjCInstanceMessage; + } + + ObjCInterfaceDecl *ClassDeclared; + if (Method->getClassInterface()->lookupInstanceVariable(Name, + ClassDeclared)) + return ObjCInstanceMessage; + } + + // Break out; we'll perform typo correction below. + break; + + case LookupResult::NotFoundInCurrentInstantiation: + case LookupResult::FoundOverloaded: + case LookupResult::FoundUnresolvedValue: + case LookupResult::Ambiguous: + Result.suppressDiagnostics(); + return ObjCInstanceMessage; + + case LookupResult::Found: { + // If the identifier is a class or not, and there is a trailing dot, + // it's an instance message. + if (HasTrailingDot) + return ObjCInstanceMessage; + // We found something. If it's a type, then we have a class + // message. Otherwise, it's an instance message. + NamedDecl *ND = Result.getFoundDecl(); + QualType T; + if (ObjCInterfaceDecl *Class = dyn_cast(ND)) + T = Context.getObjCInterfaceType(Class); + else if (TypeDecl *Type = dyn_cast(ND)) + T = Context.getTypeDeclType(Type); + else + return ObjCInstanceMessage; + + // 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 = CreateParsedType(T, TSInfo); + return ObjCClassMessage; + } + } + + ObjCInterfaceOrSuperCCC Validator(getCurMethodDecl()); + if (TypoCorrection Corrected = CorrectTypo(Result.getLookupNameInfo(), + Result.getLookupKind(), S, NULL, + Validator)) { + if (Corrected.isKeyword()) { + // If we've found the keyword "super" (the only keyword that would be + // returned by CorrectTypo), this is a send to super. + Diag(NameLoc, diag::err_unknown_receiver_suggest) + << Name << Corrected.getCorrection() + << FixItHint::CreateReplacement(SourceRange(NameLoc), "super"); + return ObjCSuperMessage; + } else if (ObjCInterfaceDecl *Class = + Corrected.getCorrectionDeclAs()) { + // If we found a declaration, correct when it refers to an Objective-C + // class. + Diag(NameLoc, diag::err_unknown_receiver_suggest) + << Name << Corrected.getCorrection() + << FixItHint::CreateReplacement(SourceRange(NameLoc), + Class->getNameAsString()); + Diag(Class->getLocation(), diag::note_previous_decl) + << Corrected.getCorrection(); + + QualType T = Context.getObjCInterfaceType(Class); + TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(T, NameLoc); + ReceiverType = CreateParsedType(T, TSInfo); + return ObjCClassMessage; + } + } + + // Fall back: let the parser try to parse it as an instance message. + return ObjCInstanceMessage; +} + +ExprResult Sema::ActOnSuperMessage(Scope *S, + SourceLocation SuperLoc, + Selector Sel, + SourceLocation LBracLoc, + ArrayRef SelectorLocs, + SourceLocation RBracLoc, + MultiExprArg Args) { + // Determine whether we are inside a method or not. + ObjCMethodDecl *Method = tryCaptureObjCSelf(SuperLoc); + if (!Method) { + Diag(SuperLoc, diag::err_invalid_receiver_to_message_super); + return ExprError(); + } + + ObjCInterfaceDecl *Class = Method->getClassInterface(); + if (!Class) { + Diag(SuperLoc, diag::error_no_super_class_message) + << Method->getDeclName(); + return ExprError(); + } + + ObjCInterfaceDecl *Super = Class->getSuperClass(); + if (!Super) { + // The current class does not have a superclass. + Diag(SuperLoc, diag::error_root_class_cannot_use_super) + << Class->getIdentifier(); + return ExprError(); + } + + // We are in a method whose class has a superclass, so 'super' + // is acting as a keyword. + if (Method->isInstanceMethod()) { + if (Sel.getMethodFamily() == OMF_dealloc) + ObjCShouldCallSuperDealloc = false; + if (Sel.getMethodFamily() == OMF_finalize) + ObjCShouldCallSuperFinalize = false; + + // Since we are in an instance method, this is an instance + // message to the superclass instance. + QualType SuperTy = Context.getObjCInterfaceType(Super); + SuperTy = Context.getObjCObjectPointerType(SuperTy); + return BuildInstanceMessage(0, SuperTy, SuperLoc, + Sel, /*Method=*/0, + LBracLoc, SelectorLocs, RBracLoc, move(Args)); + } + + // Since we are in a class method, this is a class message to + // the superclass. + return BuildClassMessage(/*ReceiverTypeInfo=*/0, + Context.getObjCInterfaceType(Super), + SuperLoc, Sel, /*Method=*/0, + LBracLoc, SelectorLocs, RBracLoc, move(Args)); +} + + +ExprResult Sema::BuildClassMessageImplicit(QualType ReceiverType, + bool isSuperReceiver, + SourceLocation Loc, + Selector Sel, + ObjCMethodDecl *Method, + MultiExprArg Args) { + TypeSourceInfo *receiverTypeInfo = 0; + if (!ReceiverType.isNull()) + receiverTypeInfo = Context.getTrivialTypeSourceInfo(ReceiverType); + + return BuildClassMessage(receiverTypeInfo, ReceiverType, + /*SuperLoc=*/isSuperReceiver ? Loc : SourceLocation(), + Sel, Method, Loc, Loc, Loc, Args, + /*isImplicit=*/true); + +} + +static void applyCocoaAPICheck(Sema &S, const ObjCMessageExpr *Msg, + unsigned DiagID, + bool (*refactor)(const ObjCMessageExpr *, + const NSAPI &, edit::Commit &)) { + SourceLocation MsgLoc = Msg->getExprLoc(); + if (S.Diags.getDiagnosticLevel(DiagID, MsgLoc) == DiagnosticsEngine::Ignored) + return; + + SourceManager &SM = S.SourceMgr; + edit::Commit ECommit(SM, S.LangOpts); + if (refactor(Msg,*S.NSAPIObj, ECommit)) { + DiagnosticBuilder Builder = S.Diag(MsgLoc, DiagID) + << Msg->getSelector() << Msg->getSourceRange(); + // FIXME: Don't emit diagnostic at all if fixits are non-commitable. + if (!ECommit.isCommitable()) + return; + for (edit::Commit::edit_iterator + I = ECommit.edit_begin(), E = ECommit.edit_end(); I != E; ++I) { + const edit::Commit::Edit &Edit = *I; + switch (Edit.Kind) { + case edit::Commit::Act_Insert: + Builder.AddFixItHint(FixItHint::CreateInsertion(Edit.OrigLoc, + Edit.Text, + Edit.BeforePrev)); + break; + case edit::Commit::Act_InsertFromRange: + Builder.AddFixItHint( + FixItHint::CreateInsertionFromRange(Edit.OrigLoc, + Edit.getInsertFromRange(SM), + Edit.BeforePrev)); + break; + case edit::Commit::Act_Remove: + Builder.AddFixItHint(FixItHint::CreateRemoval(Edit.getFileRange(SM))); + break; + } + } + } +} + +static void checkCocoaAPI(Sema &S, const ObjCMessageExpr *Msg) { + applyCocoaAPICheck(S, Msg, diag::warn_objc_redundant_literal_use, + edit::rewriteObjCRedundantCallWithLiteral); +} + +/// \brief Build an Objective-C class message expression. +/// +/// This routine takes care of both normal class messages and +/// class messages to the superclass. +/// +/// \param ReceiverTypeInfo Type source information that describes the +/// receiver of this message. This may be NULL, in which case we are +/// sending to the superclass and \p SuperLoc must be a valid source +/// location. + +/// \param ReceiverType The type of the object receiving the +/// message. When \p ReceiverTypeInfo is non-NULL, this is the same +/// type as that refers to. For a superclass send, this is the type of +/// the superclass. +/// +/// \param SuperLoc The location of the "super" keyword in a +/// superclass message. +/// +/// \param Sel The selector to which the message is being sent. +/// +/// \param Method The method that this class message is invoking, if +/// already known. +/// +/// \param LBracLoc The location of the opening square bracket ']'. +/// +/// \param RBrac The location of the closing square bracket ']'. +/// +/// \param Args The message arguments. +ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, + QualType ReceiverType, + SourceLocation SuperLoc, + Selector Sel, + ObjCMethodDecl *Method, + SourceLocation LBracLoc, + ArrayRef SelectorLocs, + SourceLocation RBracLoc, + MultiExprArg ArgsIn, + bool isImplicit) { + SourceLocation Loc = SuperLoc.isValid()? SuperLoc + : ReceiverTypeInfo->getTypeLoc().getSourceRange().getBegin(); + if (LBracLoc.isInvalid()) { + Diag(Loc, diag::err_missing_open_square_message_send) + << FixItHint::CreateInsertion(Loc, "["); + LBracLoc = Loc; + } + + if (ReceiverType->isDependentType()) { + // If the receiver type is dependent, we can't type-check anything + // at this point. Build a dependent expression. + unsigned NumArgs = ArgsIn.size(); + Expr **Args = reinterpret_cast(ArgsIn.release()); + assert(SuperLoc.isInvalid() && "Message to super with dependent type"); + return Owned(ObjCMessageExpr::Create(Context, ReceiverType, + VK_RValue, LBracLoc, ReceiverTypeInfo, + Sel, SelectorLocs, /*Method=*/0, + makeArrayRef(Args, NumArgs),RBracLoc, + isImplicit)); + } + + // Find the class to which we are sending this message. + ObjCInterfaceDecl *Class = 0; + const ObjCObjectType *ClassType = ReceiverType->getAs(); + if (!ClassType || !(Class = ClassType->getInterface())) { + Diag(Loc, diag::err_invalid_receiver_class_message) + << ReceiverType; + return ExprError(); + } + assert(Class && "We don't know which class we're messaging?"); + // objc++ diagnoses during typename annotation. + if (!getLangOpts().CPlusPlus) + (void)DiagnoseUseOfDecl(Class, Loc); + // Find the method we are messaging. + if (!Method) { + SourceRange TypeRange + = SuperLoc.isValid()? SourceRange(SuperLoc) + : ReceiverTypeInfo->getTypeLoc().getSourceRange(); + if (RequireCompleteType(Loc, Context.getObjCInterfaceType(Class), + (getLangOpts().ObjCAutoRefCount + ? PDiag(diag::err_arc_receiver_forward_class) + : PDiag(diag::warn_receiver_forward_class)) + << TypeRange)) { + // A forward class used in messaging is treated as a 'Class' + Method = LookupFactoryMethodInGlobalPool(Sel, + SourceRange(LBracLoc, RBracLoc)); + if (Method && !getLangOpts().ObjCAutoRefCount) + Diag(Method->getLocation(), diag::note_method_sent_forward_class) + << Method->getDeclName(); + } + if (!Method) + Method = Class->lookupClassMethod(Sel); + + // If we have an implementation in scope, check "private" methods. + if (!Method) + Method = LookupPrivateClassMethod(Sel, Class); + + if (Method && DiagnoseUseOfDecl(Method, Loc)) + return ExprError(); + } + + // Check the argument types and determine the result type. + QualType ReturnType; + ExprValueKind VK = VK_RValue; + + unsigned NumArgs = ArgsIn.size(); + Expr **Args = reinterpret_cast(ArgsIn.release()); + if (CheckMessageArgumentTypes(ReceiverType, Args, NumArgs, Sel, Method, true, + SuperLoc.isValid(), LBracLoc, RBracLoc, + ReturnType, VK)) + return ExprError(); + + if (Method && !Method->getResultType()->isVoidType() && + RequireCompleteType(LBracLoc, Method->getResultType(), + diag::err_illegal_message_expr_incomplete_type)) + return ExprError(); + + // Construct the appropriate ObjCMessageExpr. + ObjCMessageExpr *Result; + if (SuperLoc.isValid()) + Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc, + SuperLoc, /*IsInstanceSuper=*/false, + ReceiverType, Sel, SelectorLocs, + Method, makeArrayRef(Args, NumArgs), + RBracLoc, isImplicit); + else { + Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc, + ReceiverTypeInfo, Sel, SelectorLocs, + Method, makeArrayRef(Args, NumArgs), + RBracLoc, isImplicit); + if (!isImplicit) + checkCocoaAPI(*this, Result); + } + return MaybeBindToTemporary(Result); +} + +// ActOnClassMessage - used for both unary and keyword messages. +// ArgExprs is optional - if it is present, the number of expressions +// is obtained from Sel.getNumArgs(). +ExprResult Sema::ActOnClassMessage(Scope *S, + ParsedType Receiver, + Selector Sel, + SourceLocation LBracLoc, + ArrayRef SelectorLocs, + SourceLocation RBracLoc, + MultiExprArg Args) { + TypeSourceInfo *ReceiverTypeInfo; + QualType ReceiverType = GetTypeFromParser(Receiver, &ReceiverTypeInfo); + if (ReceiverType.isNull()) + return ExprError(); + + + if (!ReceiverTypeInfo) + ReceiverTypeInfo = Context.getTrivialTypeSourceInfo(ReceiverType, LBracLoc); + + return BuildClassMessage(ReceiverTypeInfo, ReceiverType, + /*SuperLoc=*/SourceLocation(), Sel, /*Method=*/0, + LBracLoc, SelectorLocs, RBracLoc, move(Args)); +} + +ExprResult Sema::BuildInstanceMessageImplicit(Expr *Receiver, + QualType ReceiverType, + SourceLocation Loc, + Selector Sel, + ObjCMethodDecl *Method, + MultiExprArg Args) { + return BuildInstanceMessage(Receiver, ReceiverType, + /*SuperLoc=*/!Receiver ? Loc : SourceLocation(), + Sel, Method, Loc, Loc, Loc, Args, + /*isImplicit=*/true); +} + +/// \brief Build an Objective-C instance message expression. +/// +/// This routine takes care of both normal instance messages and +/// instance messages to the superclass instance. +/// +/// \param Receiver The expression that computes the object that will +/// receive this message. This may be empty, in which case we are +/// sending to the superclass instance and \p SuperLoc must be a valid +/// source location. +/// +/// \param ReceiverType The (static) type of the object receiving the +/// message. When a \p Receiver expression is provided, this is the +/// same type as that expression. For a superclass instance send, this +/// is a pointer to the type of the superclass. +/// +/// \param SuperLoc The location of the "super" keyword in a +/// superclass instance message. +/// +/// \param Sel The selector to which the message is being sent. +/// +/// \param Method The method that this instance message is invoking, if +/// already known. +/// +/// \param LBracLoc The location of the opening square bracket ']'. +/// +/// \param RBrac The location of the closing square bracket ']'. +/// +/// \param Args The message arguments. +ExprResult Sema::BuildInstanceMessage(Expr *Receiver, + QualType ReceiverType, + SourceLocation SuperLoc, + Selector Sel, + ObjCMethodDecl *Method, + SourceLocation LBracLoc, + ArrayRef SelectorLocs, + SourceLocation RBracLoc, + MultiExprArg ArgsIn, + bool isImplicit) { + // The location of the receiver. + SourceLocation Loc = SuperLoc.isValid()? SuperLoc : Receiver->getLocStart(); + + if (LBracLoc.isInvalid()) { + Diag(Loc, diag::err_missing_open_square_message_send) + << FixItHint::CreateInsertion(Loc, "["); + LBracLoc = Loc; + } + + // If we have a receiver expression, perform appropriate promotions + // and determine receiver type. + if (Receiver) { + if (Receiver->hasPlaceholderType()) { + ExprResult Result; + if (Receiver->getType() == Context.UnknownAnyTy) + Result = forceUnknownAnyToType(Receiver, Context.getObjCIdType()); + else + Result = CheckPlaceholderExpr(Receiver); + if (Result.isInvalid()) return ExprError(); + Receiver = Result.take(); + } + + if (Receiver->isTypeDependent()) { + // If the receiver is type-dependent, we can't type-check anything + // at this point. Build a dependent expression. + unsigned NumArgs = ArgsIn.size(); + Expr **Args = reinterpret_cast(ArgsIn.release()); + assert(SuperLoc.isInvalid() && "Message to super with dependent type"); + return Owned(ObjCMessageExpr::Create(Context, Context.DependentTy, + VK_RValue, LBracLoc, Receiver, Sel, + SelectorLocs, /*Method=*/0, + makeArrayRef(Args, NumArgs), + RBracLoc, isImplicit)); + } + + // If necessary, apply function/array conversion to the receiver. + // C99 6.7.5.3p[7,8]. + ExprResult Result = DefaultFunctionArrayLvalueConversion(Receiver); + if (Result.isInvalid()) + return ExprError(); + Receiver = Result.take(); + ReceiverType = Receiver->getType(); + } + + if (!Method) { + // Handle messages to id. + bool receiverIsId = ReceiverType->isObjCIdType(); + if (receiverIsId || ReceiverType->isBlockPointerType() || + (Receiver && Context.isObjCNSObjectType(Receiver->getType()))) { + Method = LookupInstanceMethodInGlobalPool(Sel, + SourceRange(LBracLoc, RBracLoc), + receiverIsId); + if (!Method) + Method = LookupFactoryMethodInGlobalPool(Sel, + SourceRange(LBracLoc, RBracLoc), + receiverIsId); + } else if (ReceiverType->isObjCClassType() || + ReceiverType->isObjCQualifiedClassType()) { + // Handle messages to Class. + // We allow sending a message to a qualified Class ("Class"), which + // is ok as long as one of the protocols implements the selector (if not, warn). + if (const ObjCObjectPointerType *QClassTy + = ReceiverType->getAsObjCQualifiedClassType()) { + // Search protocols for class methods. + Method = LookupMethodInQualifiedType(Sel, QClassTy, false); + if (!Method) { + Method = LookupMethodInQualifiedType(Sel, QClassTy, true); + // warn if instance method found for a Class message. + if (Method) { + Diag(Loc, diag::warn_instance_method_on_class_found) + << Method->getSelector() << Sel; + Diag(Method->getLocation(), diag::note_method_declared_at) + << Method->getDeclName(); + } + } + } else { + if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) { + if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) { + // First check the public methods in the class interface. + Method = ClassDecl->lookupClassMethod(Sel); + + if (!Method) + Method = LookupPrivateClassMethod(Sel, ClassDecl); + } + if (Method && DiagnoseUseOfDecl(Method, Loc)) + return ExprError(); + } + if (!Method) { + // If not messaging 'self', look for any factory method named 'Sel'. + if (!Receiver || !isSelfExpr(Receiver)) { + Method = LookupFactoryMethodInGlobalPool(Sel, + 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), + true); + if (Method) + if (const ObjCInterfaceDecl *ID = + dyn_cast(Method->getDeclContext())) { + if (ID->getSuperClass()) + Diag(Loc, diag::warn_root_inst_method_not_found) + << Sel << SourceRange(LBracLoc, RBracLoc); + } + } + } + } + } + } else { + ObjCInterfaceDecl* ClassDecl = 0; + + // We allow sending a message to a qualified ID ("id"), which is ok as + // long as one of the protocols implements the selector (if not, warn). + if (const ObjCObjectPointerType *QIdTy + = ReceiverType->getAsObjCQualifiedIdType()) { + // Search protocols for instance methods. + Method = LookupMethodInQualifiedType(Sel, QIdTy, true); + if (!Method) + Method = LookupMethodInQualifiedType(Sel, QIdTy, false); + } else if (const ObjCObjectPointerType *OCIType + = ReceiverType->getAsObjCInterfacePointerType()) { + // We allow sending a message to a pointer to an interface (an object). + ClassDecl = OCIType->getInterfaceDecl(); + + // Try to complete the type. Under ARC, this is a hard error from which + // we don't try to recover. + const ObjCInterfaceDecl *forwardClass = 0; + if (RequireCompleteType(Loc, OCIType->getPointeeType(), + getLangOpts().ObjCAutoRefCount + ? PDiag(diag::err_arc_receiver_forward_instance) + << (Receiver ? Receiver->getSourceRange() + : SourceRange(SuperLoc)) + : PDiag(diag::warn_receiver_forward_instance) + << (Receiver ? Receiver->getSourceRange() + : SourceRange(SuperLoc)))) { + if (getLangOpts().ObjCAutoRefCount) + return ExprError(); + + forwardClass = OCIType->getInterfaceDecl(); + Diag(Receiver ? Receiver->getLocStart() + : SuperLoc, diag::note_receiver_is_id); + Method = 0; + } else { + Method = ClassDecl->lookupInstanceMethod(Sel); + } + + if (!Method) + // Search protocol qualifiers. + Method = LookupMethodInQualifiedType(Sel, OCIType, true); + + if (!Method) { + // If we have implementations in scope, check "private" methods. + Method = LookupPrivateInstanceMethod(Sel, ClassDecl); + + if (!Method && getLangOpts().ObjCAutoRefCount) { + Diag(Loc, diag::err_arc_may_not_respond) + << OCIType->getPointeeType() << Sel; + return ExprError(); + } + + if (!Method && (!Receiver || !isSelfExpr(Receiver))) { + // If we still haven't found a method, look in the global pool. This + // behavior isn't very desirable, however we need it for GCC + // compatibility. FIXME: should we deviate?? + if (OCIType->qual_empty()) { + Method = LookupInstanceMethodInGlobalPool(Sel, + SourceRange(LBracLoc, RBracLoc)); + if (Method && !forwardClass) + Diag(Loc, diag::warn_maynot_respond) + << OCIType->getInterfaceDecl()->getIdentifier() << Sel; + } + } + } + if (Method && DiagnoseUseOfDecl(Method, Loc, forwardClass)) + return ExprError(); + } else if (!getLangOpts().ObjCAutoRefCount && + !Context.getObjCIdType().isNull() && + (ReceiverType->isPointerType() || + ReceiverType->isIntegerType())) { + // Implicitly convert integers and pointers to 'id' but emit a warning. + // But not in ARC. + Diag(Loc, diag::warn_bad_receiver_type) + << ReceiverType + << Receiver->getSourceRange(); + if (ReceiverType->isPointerType()) + Receiver = ImpCastExprToType(Receiver, Context.getObjCIdType(), + CK_CPointerToObjCPointerCast).take(); + else { + // TODO: specialized warning on null receivers? + bool IsNull = Receiver->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNull); + Receiver = ImpCastExprToType(Receiver, Context.getObjCIdType(), + IsNull ? CK_NullToPointer : CK_IntegralToPointer).take(); + } + ReceiverType = Receiver->getType(); + } else { + ExprResult ReceiverRes; + if (getLangOpts().CPlusPlus) + ReceiverRes = PerformContextuallyConvertToObjCPointer(Receiver); + if (ReceiverRes.isUsable()) { + Receiver = ReceiverRes.take(); + return BuildInstanceMessage(Receiver, + ReceiverType, + SuperLoc, + Sel, + Method, + LBracLoc, + SelectorLocs, + RBracLoc, + move(ArgsIn)); + } else { + // Reject other random receiver types (e.g. structs). + Diag(Loc, diag::err_bad_receiver_type) + << ReceiverType << Receiver->getSourceRange(); + return ExprError(); + } + } + } + } + + // Check the message arguments. + unsigned NumArgs = ArgsIn.size(); + Expr **Args = reinterpret_cast(ArgsIn.release()); + QualType ReturnType; + ExprValueKind VK = VK_RValue; + bool ClassMessage = (ReceiverType->isObjCClassType() || + ReceiverType->isObjCQualifiedClassType()); + if (CheckMessageArgumentTypes(ReceiverType, Args, NumArgs, Sel, Method, + ClassMessage, SuperLoc.isValid(), + LBracLoc, RBracLoc, ReturnType, VK)) + return ExprError(); + + if (Method && !Method->getResultType()->isVoidType() && + RequireCompleteType(LBracLoc, Method->getResultType(), + diag::err_illegal_message_expr_incomplete_type)) + return ExprError(); + + SourceLocation SelLoc = SelectorLocs.front(); + + // In ARC, forbid the user from sending messages to + // retain/release/autorelease/dealloc/retainCount explicitly. + if (getLangOpts().ObjCAutoRefCount) { + ObjCMethodFamily family = + (Method ? Method->getMethodFamily() : Sel.getMethodFamily()); + switch (family) { + case OMF_init: + if (Method) + checkInitMethod(Method, ReceiverType); + + case OMF_None: + case OMF_alloc: + case OMF_copy: + case OMF_finalize: + case OMF_mutableCopy: + case OMF_new: + case OMF_self: + break; + + case OMF_dealloc: + case OMF_retain: + case OMF_release: + case OMF_autorelease: + case OMF_retainCount: + Diag(Loc, diag::err_arc_illegal_explicit_message) + << Sel << SelLoc; + break; + + case OMF_performSelector: + if (Method && NumArgs >= 1) { + if (ObjCSelectorExpr *SelExp = dyn_cast(Args[0])) { + Selector ArgSel = SelExp->getSelector(); + ObjCMethodDecl *SelMethod = + LookupInstanceMethodInGlobalPool(ArgSel, + SelExp->getSourceRange()); + if (!SelMethod) + SelMethod = + LookupFactoryMethodInGlobalPool(ArgSel, + SelExp->getSourceRange()); + if (SelMethod) { + ObjCMethodFamily SelFamily = SelMethod->getMethodFamily(); + switch (SelFamily) { + case OMF_alloc: + case OMF_copy: + case OMF_mutableCopy: + case OMF_new: + case OMF_self: + case OMF_init: + // Issue error, unless ns_returns_not_retained. + if (!SelMethod->hasAttr()) { + // selector names a +1 method + Diag(SelLoc, + diag::err_arc_perform_selector_retains); + Diag(SelMethod->getLocation(), diag::note_method_declared_at) + << SelMethod->getDeclName(); + } + break; + default: + // +0 call. OK. unless ns_returns_retained. + if (SelMethod->hasAttr()) { + // selector names a +1 method + Diag(SelLoc, + diag::err_arc_perform_selector_retains); + Diag(SelMethod->getLocation(), diag::note_method_declared_at) + << SelMethod->getDeclName(); + } + break; + } + } + } else { + // error (may leak). + Diag(SelLoc, diag::warn_arc_perform_selector_leaks); + Diag(Args[0]->getExprLoc(), diag::note_used_here); + } + } + break; + } + } + + // Construct the appropriate ObjCMessageExpr instance. + ObjCMessageExpr *Result; + if (SuperLoc.isValid()) + Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc, + SuperLoc, /*IsInstanceSuper=*/true, + ReceiverType, Sel, SelectorLocs, Method, + makeArrayRef(Args, NumArgs), RBracLoc, + isImplicit); + else { + Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc, + Receiver, Sel, SelectorLocs, Method, + makeArrayRef(Args, NumArgs), RBracLoc, + isImplicit); + if (!isImplicit) + checkCocoaAPI(*this, Result); + } + + if (getLangOpts().ObjCAutoRefCount) { + if (Receiver && + (Receiver->IgnoreParenImpCasts()->getType().getObjCLifetime() + == Qualifiers::OCL_Weak)) + Diag(Receiver->getLocStart(), diag::warn_receiver_is_weak); + + // In ARC, annotate delegate init calls. + if (Result->getMethodFamily() == OMF_init && + (SuperLoc.isValid() || isSelfExpr(Receiver))) { + // Only consider init calls *directly* in init implementations, + // not within blocks. + ObjCMethodDecl *method = dyn_cast(CurContext); + if (method && method->getMethodFamily() == OMF_init) { + // The implicit assignment to self means we also don't want to + // consume the result. + Result->setDelegateInitCall(true); + return Owned(Result); + } + } + + // In ARC, check for message sends which are likely to introduce + // retain cycles. + checkRetainCycles(Result); + } + + return MaybeBindToTemporary(Result); +} + +// ActOnInstanceMessage - used for both unary and keyword messages. +// ArgExprs is optional - if it is present, the number of expressions +// is obtained from Sel.getNumArgs(). +ExprResult Sema::ActOnInstanceMessage(Scope *S, + Expr *Receiver, + Selector Sel, + SourceLocation LBracLoc, + ArrayRef SelectorLocs, + SourceLocation RBracLoc, + MultiExprArg Args) { + if (!Receiver) + return ExprError(); + + return BuildInstanceMessage(Receiver, Receiver->getType(), + /*SuperLoc=*/SourceLocation(), Sel, /*Method=*/0, + LBracLoc, SelectorLocs, RBracLoc, move(Args)); +} + +enum ARCConversionTypeClass { + /// int, void, struct A + ACTC_none, + + /// id, void (^)() + ACTC_retainable, + + /// id*, id***, void (^*)(), + ACTC_indirectRetainable, + + /// void* might be a normal C type, or it might a CF type. + ACTC_voidPtr, + + /// struct A* + ACTC_coreFoundation +}; +static bool isAnyRetainable(ARCConversionTypeClass ACTC) { + return (ACTC == ACTC_retainable || + ACTC == ACTC_coreFoundation || + ACTC == ACTC_voidPtr); +} +static bool isAnyCLike(ARCConversionTypeClass ACTC) { + return ACTC == ACTC_none || + ACTC == ACTC_voidPtr || + ACTC == ACTC_coreFoundation; +} + +static ARCConversionTypeClass classifyTypeForARCConversion(QualType type) { + bool isIndirect = false; + + // Ignore an outermost reference type. + if (const ReferenceType *ref = type->getAs()) { + type = ref->getPointeeType(); + isIndirect = true; + } + + // Drill through pointers and arrays recursively. + while (true) { + if (const PointerType *ptr = type->getAs()) { + type = ptr->getPointeeType(); + + // The first level of pointer may be the innermost pointer on a CF type. + if (!isIndirect) { + if (type->isVoidType()) return ACTC_voidPtr; + if (type->isRecordType()) return ACTC_coreFoundation; + } + } else if (const ArrayType *array = type->getAsArrayTypeUnsafe()) { + type = QualType(array->getElementType()->getBaseElementTypeUnsafe(), 0); + } else { + break; + } + isIndirect = true; + } + + if (isIndirect) { + if (type->isObjCARCBridgableType()) + return ACTC_indirectRetainable; + return ACTC_none; + } + + if (type->isObjCARCBridgableType()) + return ACTC_retainable; + + return ACTC_none; +} + +namespace { + /// A result from the cast checker. + enum ACCResult { + /// Cannot be casted. + ACC_invalid, + + /// Can be safely retained or not retained. + ACC_bottom, + + /// Can be casted at +0. + ACC_plusZero, + + /// Can be casted at +1. + ACC_plusOne + }; + ACCResult merge(ACCResult left, ACCResult right) { + if (left == right) return left; + if (left == ACC_bottom) return right; + if (right == ACC_bottom) return left; + return ACC_invalid; + } + + /// A checker which white-lists certain expressions whose conversion + /// to or from retainable type would otherwise be forbidden in ARC. + class ARCCastChecker : public StmtVisitor { + typedef StmtVisitor super; + + ASTContext &Context; + ARCConversionTypeClass SourceClass; + ARCConversionTypeClass TargetClass; + + static bool isCFType(QualType type) { + // Someday this can use ns_bridged. For now, it has to do this. + return type->isCARCBridgableType(); + } + + public: + ARCCastChecker(ASTContext &Context, ARCConversionTypeClass source, + ARCConversionTypeClass target) + : Context(Context), SourceClass(source), TargetClass(target) {} + + using super::Visit; + ACCResult Visit(Expr *e) { + return super::Visit(e->IgnoreParens()); + } + + ACCResult VisitStmt(Stmt *s) { + return ACC_invalid; + } + + /// Null pointer constants can be casted however you please. + ACCResult VisitExpr(Expr *e) { + if (e->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull)) + return ACC_bottom; + return ACC_invalid; + } + + /// Objective-C string literals can be safely casted. + ACCResult VisitObjCStringLiteral(ObjCStringLiteral *e) { + // If we're casting to any retainable type, go ahead. Global + // strings are immune to retains, so this is bottom. + if (isAnyRetainable(TargetClass)) return ACC_bottom; + + return ACC_invalid; + } + + /// Look through certain implicit and explicit casts. + ACCResult VisitCastExpr(CastExpr *e) { + switch (e->getCastKind()) { + case CK_NullToPointer: + return ACC_bottom; + + case CK_NoOp: + case CK_LValueToRValue: + case CK_BitCast: + case CK_CPointerToObjCPointerCast: + case CK_BlockPointerToObjCPointerCast: + case CK_AnyPointerToBlockPointerCast: + return Visit(e->getSubExpr()); + + default: + return ACC_invalid; + } + } + + /// Look through unary extension. + ACCResult VisitUnaryExtension(UnaryOperator *e) { + return Visit(e->getSubExpr()); + } + + /// Ignore the LHS of a comma operator. + ACCResult VisitBinComma(BinaryOperator *e) { + return Visit(e->getRHS()); + } + + /// Conditional operators are okay if both sides are okay. + ACCResult VisitConditionalOperator(ConditionalOperator *e) { + ACCResult left = Visit(e->getTrueExpr()); + if (left == ACC_invalid) return ACC_invalid; + return merge(left, Visit(e->getFalseExpr())); + } + + /// Look through pseudo-objects. + ACCResult VisitPseudoObjectExpr(PseudoObjectExpr *e) { + // If we're getting here, we should always have a result. + return Visit(e->getResultExpr()); + } + + /// Statement expressions are okay if their result expression is okay. + ACCResult VisitStmtExpr(StmtExpr *e) { + return Visit(e->getSubStmt()->body_back()); + } + + /// Some declaration references are okay. + ACCResult VisitDeclRefExpr(DeclRefExpr *e) { + // References to global constants from system headers are okay. + // These are things like 'kCFStringTransformToLatin'. They are + // can also be assumed to be immune to retains. + VarDecl *var = dyn_cast(e->getDecl()); + if (isAnyRetainable(TargetClass) && + isAnyRetainable(SourceClass) && + var && + var->getStorageClass() == SC_Extern && + var->getType().isConstQualified() && + Context.getSourceManager().isInSystemHeader(var->getLocation())) { + return ACC_bottom; + } + + // Nothing else. + return ACC_invalid; + } + + /// Some calls are okay. + ACCResult VisitCallExpr(CallExpr *e) { + if (FunctionDecl *fn = e->getDirectCallee()) + if (ACCResult result = checkCallToFunction(fn)) + return result; + + return super::VisitCallExpr(e); + } + + ACCResult checkCallToFunction(FunctionDecl *fn) { + // Require a CF*Ref return type. + if (!isCFType(fn->getResultType())) + return ACC_invalid; + + if (!isAnyRetainable(TargetClass)) + return ACC_invalid; + + // Honor an explicit 'not retained' attribute. + if (fn->hasAttr()) + return ACC_plusZero; + + // Honor an explicit 'retained' attribute, except that for + // now we're not going to permit implicit handling of +1 results, + // because it's a bit frightening. + if (fn->hasAttr()) + return ACC_invalid; // ACC_plusOne if we start accepting this + + // Recognize this specific builtin function, which is used by CFSTR. + unsigned builtinID = fn->getBuiltinID(); + if (builtinID == Builtin::BI__builtin___CFStringMakeConstantString) + return ACC_bottom; + + // Otherwise, don't do anything implicit with an unaudited function. + if (!fn->hasAttr()) + return ACC_invalid; + + // Otherwise, it's +0 unless it follows the create convention. + if (ento::coreFoundation::followsCreateRule(fn)) + return ACC_invalid; // ACC_plusOne if we start accepting this + + return ACC_plusZero; + } + + ACCResult VisitObjCMessageExpr(ObjCMessageExpr *e) { + return checkCallToMethod(e->getMethodDecl()); + } + + ACCResult VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *e) { + ObjCMethodDecl *method; + if (e->isExplicitProperty()) + method = e->getExplicitProperty()->getGetterMethodDecl(); + else + method = e->getImplicitPropertyGetter(); + return checkCallToMethod(method); + } + + ACCResult checkCallToMethod(ObjCMethodDecl *method) { + if (!method) return ACC_invalid; + + // Check for message sends to functions returning CF types. We + // just obey the Cocoa conventions with these, even though the + // return type is CF. + if (!isAnyRetainable(TargetClass) || !isCFType(method->getResultType())) + return ACC_invalid; + + // If the method is explicitly marked not-retained, it's +0. + if (method->hasAttr()) + return ACC_plusZero; + + // If the method is explicitly marked as returning retained, or its + // selector follows a +1 Cocoa convention, treat it as +1. + if (method->hasAttr()) + return ACC_plusOne; + + switch (method->getSelector().getMethodFamily()) { + case OMF_alloc: + case OMF_copy: + case OMF_mutableCopy: + case OMF_new: + return ACC_plusOne; + + default: + // Otherwise, treat it as +0. + return ACC_plusZero; + } + } + }; +} + +static bool +KnownName(Sema &S, const char *name) { + LookupResult R(S, &S.Context.Idents.get(name), SourceLocation(), + Sema::LookupOrdinaryName); + return S.LookupName(R, S.TUScope, false); +} + +static void addFixitForObjCARCConversion(Sema &S, + DiagnosticBuilder &DiagB, + Sema::CheckedConversionKind CCK, + SourceLocation afterLParen, + QualType castType, + Expr *castExpr, + const char *bridgeKeyword, + const char *CFBridgeName) { + // We handle C-style and implicit casts here. + switch (CCK) { + case Sema::CCK_ImplicitConversion: + case Sema::CCK_CStyleCast: + break; + case Sema::CCK_FunctionalCast: + case Sema::CCK_OtherCast: + return; + } + + if (CFBridgeName) { + Expr *castedE = castExpr; + if (CStyleCastExpr *CCE = dyn_cast(castedE)) + castedE = CCE->getSubExpr(); + castedE = castedE->IgnoreImpCasts(); + SourceRange range = castedE->getSourceRange(); + if (isa(castedE)) { + DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(), + CFBridgeName)); + } else { + std::string namePlusParen = CFBridgeName; + namePlusParen += "("; + DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(), + namePlusParen)); + DiagB.AddFixItHint(FixItHint::CreateInsertion( + S.PP.getLocForEndOfToken(range.getEnd()), + ")")); + } + return; + } + + if (CCK == Sema::CCK_CStyleCast) { + DiagB.AddFixItHint(FixItHint::CreateInsertion(afterLParen, bridgeKeyword)); + } else { + std::string castCode = "("; + castCode += bridgeKeyword; + castCode += castType.getAsString(); + castCode += ")"; + Expr *castedE = castExpr->IgnoreImpCasts(); + SourceRange range = castedE->getSourceRange(); + if (isa(castedE)) { + DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(), + castCode)); + } else { + castCode += "("; + DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(), + castCode)); + DiagB.AddFixItHint(FixItHint::CreateInsertion( + S.PP.getLocForEndOfToken(range.getEnd()), + ")")); + } + } +} + +static void +diagnoseObjCARCConversion(Sema &S, SourceRange castRange, + QualType castType, ARCConversionTypeClass castACTC, + Expr *castExpr, ARCConversionTypeClass exprACTC, + Sema::CheckedConversionKind CCK) { + SourceLocation loc = + (castRange.isValid() ? castRange.getBegin() : castExpr->getExprLoc()); + + if (S.makeUnavailableInSystemHeader(loc, + "converts between Objective-C and C pointers in -fobjc-arc")) + return; + + QualType castExprType = castExpr->getType(); + + unsigned srcKind = 0; + switch (exprACTC) { + case ACTC_none: + case ACTC_coreFoundation: + case ACTC_voidPtr: + srcKind = (castExprType->isPointerType() ? 1 : 0); + break; + case ACTC_retainable: + srcKind = (castExprType->isBlockPointerType() ? 2 : 3); + break; + case ACTC_indirectRetainable: + srcKind = 4; + break; + } + + // Check whether this could be fixed with a bridge cast. + SourceLocation afterLParen = S.PP.getLocForEndOfToken(castRange.getBegin()); + SourceLocation noteLoc = afterLParen.isValid() ? afterLParen : loc; + + // Bridge from an ARC type to a CF type. + if (castACTC == ACTC_retainable && isAnyRetainable(exprACTC)) { + + S.Diag(loc, diag::err_arc_cast_requires_bridge) + << unsigned(CCK == Sema::CCK_ImplicitConversion) // cast|implicit + << 2 // of C pointer type + << castExprType + << unsigned(castType->isBlockPointerType()) // to ObjC|block type + << castType + << castRange + << castExpr->getSourceRange(); + bool br = KnownName(S, "CFBridgingRelease"); + { + DiagnosticBuilder DiagB = S.Diag(noteLoc, diag::note_arc_bridge); + addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen, + castType, castExpr, "__bridge ", 0); + } + { + DiagnosticBuilder DiagB = S.Diag(noteLoc, diag::note_arc_bridge_transfer) + << castExprType << br; + addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen, + castType, castExpr, "__bridge_transfer ", + br ? "CFBridgingRelease" : 0); + } + + return; + } + + // Bridge from a CF type to an ARC type. + if (exprACTC == ACTC_retainable && isAnyRetainable(castACTC)) { + bool br = KnownName(S, "CFBridgingRetain"); + S.Diag(loc, diag::err_arc_cast_requires_bridge) + << unsigned(CCK == Sema::CCK_ImplicitConversion) // cast|implicit + << unsigned(castExprType->isBlockPointerType()) // of ObjC|block type + << castExprType + << 2 // to C pointer type + << castType + << castRange + << castExpr->getSourceRange(); + + { + DiagnosticBuilder DiagB = S.Diag(noteLoc, diag::note_arc_bridge); + addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen, + castType, castExpr, "__bridge ", 0); + } + { + DiagnosticBuilder DiagB = S.Diag(noteLoc, diag::note_arc_bridge_retained) + << castType << br; + addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen, + castType, castExpr, "__bridge_retained ", + br ? "CFBridgingRetain" : 0); + } + + return; + } + + S.Diag(loc, diag::err_arc_mismatched_cast) + << (CCK != Sema::CCK_ImplicitConversion) + << srcKind << castExprType << castType + << castRange << castExpr->getSourceRange(); +} + +Sema::ARCConversionResult +Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType, + Expr *&castExpr, CheckedConversionKind CCK) { + QualType castExprType = castExpr->getType(); + + // For the purposes of the classification, we assume reference types + // will bind to temporaries. + QualType effCastType = castType; + if (const ReferenceType *ref = castType->getAs()) + effCastType = ref->getPointeeType(); + + ARCConversionTypeClass exprACTC = classifyTypeForARCConversion(castExprType); + ARCConversionTypeClass castACTC = classifyTypeForARCConversion(effCastType); + if (exprACTC == castACTC) { + // check for viablity and report error if casting an rvalue to a + // life-time qualifier. + if ((castACTC == ACTC_retainable) && + (CCK == CCK_CStyleCast || CCK == CCK_OtherCast) && + (castType != castExprType)) { + const Type *DT = castType.getTypePtr(); + QualType QDT = castType; + // We desugar some types but not others. We ignore those + // that cannot happen in a cast; i.e. auto, and those which + // should not be de-sugared; i.e typedef. + if (const ParenType *PT = dyn_cast(DT)) + QDT = PT->desugar(); + else if (const TypeOfType *TP = dyn_cast(DT)) + QDT = TP->desugar(); + else if (const AttributedType *AT = dyn_cast(DT)) + QDT = AT->desugar(); + if (QDT != castType && + QDT.getObjCLifetime() != Qualifiers::OCL_None) { + SourceLocation loc = + (castRange.isValid() ? castRange.getBegin() + : castExpr->getExprLoc()); + Diag(loc, diag::err_arc_nolifetime_behavior); + } + } + return ACR_okay; + } + + if (isAnyCLike(exprACTC) && isAnyCLike(castACTC)) return ACR_okay; + + // Allow all of these types to be cast to integer types (but not + // vice-versa). + if (castACTC == ACTC_none && castType->isIntegralType(Context)) + return ACR_okay; + + // Allow casts between pointers to lifetime types (e.g., __strong id*) + // and pointers to void (e.g., cv void *). Casting from void* to lifetime* + // must be explicit. + if (exprACTC == ACTC_indirectRetainable && castACTC == ACTC_voidPtr) + return ACR_okay; + if (castACTC == ACTC_indirectRetainable && exprACTC == ACTC_voidPtr && + CCK != CCK_ImplicitConversion) + return ACR_okay; + + switch (ARCCastChecker(Context, exprACTC, castACTC).Visit(castExpr)) { + // For invalid casts, fall through. + case ACC_invalid: + break; + + // Do nothing for both bottom and +0. + case ACC_bottom: + case ACC_plusZero: + return ACR_okay; + + // If the result is +1, consume it here. + case ACC_plusOne: + castExpr = ImplicitCastExpr::Create(Context, castExpr->getType(), + CK_ARCConsumeObject, castExpr, + 0, VK_RValue); + ExprNeedsCleanups = true; + return ACR_okay; + } + + // If this is a non-implicit cast from id or block type to a + // CoreFoundation type, delay complaining in case the cast is used + // in an acceptable context. + if (exprACTC == ACTC_retainable && isAnyRetainable(castACTC) && + CCK != CCK_ImplicitConversion) + return ACR_unbridged; + + diagnoseObjCARCConversion(*this, castRange, castType, castACTC, + castExpr, exprACTC, CCK); + return ACR_okay; +} + +/// Given that we saw an expression with the ARCUnbridgedCastTy +/// placeholder type, complain bitterly. +void Sema::diagnoseARCUnbridgedCast(Expr *e) { + // We expect the spurious ImplicitCastExpr to already have been stripped. + assert(!e->hasPlaceholderType(BuiltinType::ARCUnbridgedCast)); + CastExpr *realCast = cast(e->IgnoreParens()); + + SourceRange castRange; + QualType castType; + CheckedConversionKind CCK; + + if (CStyleCastExpr *cast = dyn_cast(realCast)) { + castRange = SourceRange(cast->getLParenLoc(), cast->getRParenLoc()); + castType = cast->getTypeAsWritten(); + CCK = CCK_CStyleCast; + } else if (ExplicitCastExpr *cast = dyn_cast(realCast)) { + castRange = cast->getTypeInfoAsWritten()->getTypeLoc().getSourceRange(); + castType = cast->getTypeAsWritten(); + CCK = CCK_OtherCast; + } else { + castType = cast->getType(); + CCK = CCK_ImplicitConversion; + } + + ARCConversionTypeClass castACTC = + classifyTypeForARCConversion(castType.getNonReferenceType()); + + Expr *castExpr = realCast->getSubExpr(); + assert(classifyTypeForARCConversion(castExpr->getType()) == ACTC_retainable); + + diagnoseObjCARCConversion(*this, castRange, castType, castACTC, + castExpr, ACTC_retainable, CCK); +} + +/// stripARCUnbridgedCast - Given an expression of ARCUnbridgedCast +/// type, remove the placeholder cast. +Expr *Sema::stripARCUnbridgedCast(Expr *e) { + assert(e->hasPlaceholderType(BuiltinType::ARCUnbridgedCast)); + + if (ParenExpr *pe = dyn_cast(e)) { + Expr *sub = stripARCUnbridgedCast(pe->getSubExpr()); + return new (Context) ParenExpr(pe->getLParen(), pe->getRParen(), sub); + } else if (UnaryOperator *uo = dyn_cast(e)) { + assert(uo->getOpcode() == UO_Extension); + Expr *sub = stripARCUnbridgedCast(uo->getSubExpr()); + return new (Context) UnaryOperator(sub, UO_Extension, sub->getType(), + sub->getValueKind(), sub->getObjectKind(), + uo->getOperatorLoc()); + } else if (GenericSelectionExpr *gse = dyn_cast(e)) { + assert(!gse->isResultDependent()); + + unsigned n = gse->getNumAssocs(); + SmallVector subExprs(n); + SmallVector subTypes(n); + for (unsigned i = 0; i != n; ++i) { + subTypes[i] = gse->getAssocTypeSourceInfo(i); + Expr *sub = gse->getAssocExpr(i); + if (i == gse->getResultIndex()) + sub = stripARCUnbridgedCast(sub); + subExprs[i] = sub; + } + + return new (Context) GenericSelectionExpr(Context, gse->getGenericLoc(), + gse->getControllingExpr(), + subTypes.data(), subExprs.data(), + n, gse->getDefaultLoc(), + gse->getRParenLoc(), + gse->containsUnexpandedParameterPack(), + gse->getResultIndex()); + } else { + assert(isa(e) && "bad form of unbridged cast!"); + return cast(e)->getSubExpr(); + } +} + +bool Sema::CheckObjCARCUnavailableWeakConversion(QualType castType, + QualType exprType) { + QualType canCastType = + Context.getCanonicalType(castType).getUnqualifiedType(); + QualType canExprType = + Context.getCanonicalType(exprType).getUnqualifiedType(); + if (isa(canCastType) && + castType.getObjCLifetime() == Qualifiers::OCL_Weak && + canExprType->isObjCObjectPointerType()) { + if (const ObjCObjectPointerType *ObjT = + canExprType->getAs()) + if (ObjT->getInterfaceDecl()->isArcWeakrefUnavailable()) + return false; + } + return true; +} + +/// Look for an ObjCReclaimReturnedObject cast and destroy it. +static Expr *maybeUndoReclaimObject(Expr *e) { + // For now, we just undo operands that are *immediately* reclaim + // expressions, which prevents the vast majority of potential + // problems here. To catch them all, we'd need to rebuild arbitrary + // value-propagating subexpressions --- we can't reliably rebuild + // in-place because of expression sharing. + if (ImplicitCastExpr *ice = dyn_cast(e)) + if (ice->getCastKind() == CK_ARCReclaimReturnedObject) + return ice->getSubExpr(); + + return e; +} + +ExprResult Sema::BuildObjCBridgedCast(SourceLocation LParenLoc, + ObjCBridgeCastKind Kind, + SourceLocation BridgeKeywordLoc, + TypeSourceInfo *TSInfo, + Expr *SubExpr) { + ExprResult SubResult = UsualUnaryConversions(SubExpr); + if (SubResult.isInvalid()) return ExprError(); + SubExpr = SubResult.take(); + + QualType T = TSInfo->getType(); + QualType FromType = SubExpr->getType(); + + CastKind CK; + + bool MustConsume = false; + if (T->isDependentType() || SubExpr->isTypeDependent()) { + // Okay: we'll build a dependent expression type. + CK = CK_Dependent; + } else if (T->isObjCARCBridgableType() && FromType->isCARCBridgableType()) { + // Casting CF -> id + CK = (T->isBlockPointerType() ? CK_AnyPointerToBlockPointerCast + : CK_CPointerToObjCPointerCast); + switch (Kind) { + case OBC_Bridge: + break; + + case OBC_BridgeRetained: { + bool br = KnownName(*this, "CFBridgingRelease"); + Diag(BridgeKeywordLoc, diag::err_arc_bridge_cast_wrong_kind) + << 2 + << FromType + << (T->isBlockPointerType()? 1 : 0) + << T + << SubExpr->getSourceRange() + << Kind; + Diag(BridgeKeywordLoc, diag::note_arc_bridge) + << FixItHint::CreateReplacement(BridgeKeywordLoc, "__bridge"); + Diag(BridgeKeywordLoc, diag::note_arc_bridge_transfer) + << FromType << br + << FixItHint::CreateReplacement(BridgeKeywordLoc, + br ? "CFBridgingRelease " + : "__bridge_transfer "); + + Kind = OBC_Bridge; + break; + } + + case OBC_BridgeTransfer: + // We must consume the Objective-C object produced by the cast. + MustConsume = true; + break; + } + } else if (T->isCARCBridgableType() && FromType->isObjCARCBridgableType()) { + // Okay: id -> CF + CK = CK_BitCast; + switch (Kind) { + case OBC_Bridge: + // Reclaiming a value that's going to be __bridge-casted to CF + // is very dangerous, so we don't do it. + SubExpr = maybeUndoReclaimObject(SubExpr); + break; + + case OBC_BridgeRetained: + // Produce the object before casting it. + SubExpr = ImplicitCastExpr::Create(Context, FromType, + CK_ARCProduceObject, + SubExpr, 0, VK_RValue); + break; + + case OBC_BridgeTransfer: { + bool br = KnownName(*this, "CFBridgingRetain"); + Diag(BridgeKeywordLoc, diag::err_arc_bridge_cast_wrong_kind) + << (FromType->isBlockPointerType()? 1 : 0) + << FromType + << 2 + << T + << SubExpr->getSourceRange() + << Kind; + + Diag(BridgeKeywordLoc, diag::note_arc_bridge) + << FixItHint::CreateReplacement(BridgeKeywordLoc, "__bridge "); + Diag(BridgeKeywordLoc, diag::note_arc_bridge_retained) + << T << br + << FixItHint::CreateReplacement(BridgeKeywordLoc, + br ? "CFBridgingRetain " : "__bridge_retained"); + + Kind = OBC_Bridge; + break; + } + } + } else { + Diag(LParenLoc, diag::err_arc_bridge_cast_incompatible) + << FromType << T << Kind + << SubExpr->getSourceRange() + << TSInfo->getTypeLoc().getSourceRange(); + return ExprError(); + } + + Expr *Result = new (Context) ObjCBridgedCastExpr(LParenLoc, Kind, CK, + BridgeKeywordLoc, + TSInfo, SubExpr); + + if (MustConsume) { + ExprNeedsCleanups = true; + Result = ImplicitCastExpr::Create(Context, T, CK_ARCConsumeObject, Result, + 0, VK_RValue); + } + + return Result; +} + +ExprResult Sema::ActOnObjCBridgedCast(Scope *S, + SourceLocation LParenLoc, + ObjCBridgeCastKind Kind, + SourceLocation BridgeKeywordLoc, + ParsedType Type, + SourceLocation RParenLoc, + Expr *SubExpr) { + TypeSourceInfo *TSInfo = 0; + QualType T = GetTypeFromParser(Type, &TSInfo); + if (!TSInfo) + TSInfo = Context.getTrivialTypeSourceInfo(T, LParenLoc); + return BuildObjCBridgedCast(LParenLoc, Kind, BridgeKeywordLoc, TSInfo, + SubExpr); +} diff --git a/clang/lib/Sema/SemaFixItUtils.cpp b/clang/lib/Sema/SemaFixItUtils.cpp new file mode 100644 index 0000000..b78ea7d --- /dev/null +++ b/clang/lib/Sema/SemaFixItUtils.cpp @@ -0,0 +1,204 @@ +//===--- SemaFixItUtils.cpp - Sema FixIts ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines helper classes for generation of Sema FixItHints. +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprObjC.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Sema/Sema.h" +#include "clang/Sema/SemaFixItUtils.h" + +using namespace clang; + +bool ConversionFixItGenerator::compareTypesSimple(CanQualType From, + CanQualType To, + Sema &S, + SourceLocation Loc, + ExprValueKind FromVK) { + if (!To.isAtLeastAsQualifiedAs(From)) + return false; + + From = From.getNonReferenceType(); + To = To.getNonReferenceType(); + + // If both are pointer types, work with the pointee types. + if (isa(From) && isa(To)) { + From = S.Context.getCanonicalType( + (cast(From))->getPointeeType()); + To = S.Context.getCanonicalType( + (cast(To))->getPointeeType()); + } + + const CanQualType FromUnq = From.getUnqualifiedType(); + const CanQualType ToUnq = To.getUnqualifiedType(); + + if ((FromUnq == ToUnq || (S.IsDerivedFrom(FromUnq, ToUnq)) ) && + To.isAtLeastAsQualifiedAs(From)) + return true; + return false; +} + +bool ConversionFixItGenerator::tryToFixConversion(const Expr *FullExpr, + const QualType FromTy, + const QualType ToTy, + Sema &S) { + if (!FullExpr) + return false; + + const CanQualType FromQTy = S.Context.getCanonicalType(FromTy); + const CanQualType ToQTy = S.Context.getCanonicalType(ToTy); + const SourceLocation Begin = FullExpr->getSourceRange().getBegin(); + const SourceLocation End = S.PP.getLocForEndOfToken(FullExpr->getSourceRange() + .getEnd()); + + // Strip the implicit casts - those are implied by the compiler, not the + // original source code. + const Expr* Expr = FullExpr->IgnoreImpCasts(); + + bool NeedParen = true; + if (isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(FullExpr) || + isa(Expr) || + isa(Expr) || + isa(Expr)) + NeedParen = false; + + // Check if the argument needs to be dereferenced: + // (type * -> type) or (type * -> type &). + if (const PointerType *FromPtrTy = dyn_cast(FromQTy)) { + OverloadFixItKind FixKind = OFIK_Dereference; + + bool CanConvert = CompareTypes( + S.Context.getCanonicalType(FromPtrTy->getPointeeType()), ToQTy, + S, Begin, VK_LValue); + if (CanConvert) { + // Do not suggest dereferencing a Null pointer. + if (Expr->IgnoreParenCasts()-> + isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull)) + return false; + + if (const UnaryOperator *UO = dyn_cast(Expr)) { + if (UO->getOpcode() == UO_AddrOf) { + FixKind = OFIK_RemoveTakeAddress; + Hints.push_back(FixItHint::CreateRemoval( + CharSourceRange::getTokenRange(Begin, Begin))); + } + } else if (NeedParen) { + Hints.push_back(FixItHint::CreateInsertion(Begin, "*(")); + Hints.push_back(FixItHint::CreateInsertion(End, ")")); + } else { + Hints.push_back(FixItHint::CreateInsertion(Begin, "*")); + } + + NumConversionsFixed++; + if (NumConversionsFixed == 1) + Kind = FixKind; + return true; + } + } + + // Check if the pointer to the argument needs to be passed: + // (type -> type *) or (type & -> type *). + if (isa(ToQTy)) { + bool CanConvert = false; + OverloadFixItKind FixKind = OFIK_TakeAddress; + + // Only suggest taking address of L-values. + if (!Expr->isLValue() || Expr->getObjectKind() != OK_Ordinary) + return false; + + CanConvert = CompareTypes(S.Context.getPointerType(FromQTy), ToQTy, + S, Begin, VK_RValue); + if (CanConvert) { + + if (const UnaryOperator *UO = dyn_cast(Expr)) { + if (UO->getOpcode() == UO_Deref) { + FixKind = OFIK_RemoveDereference; + Hints.push_back(FixItHint::CreateRemoval( + CharSourceRange::getTokenRange(Begin, Begin))); + } + } else if (NeedParen) { + Hints.push_back(FixItHint::CreateInsertion(Begin, "&(")); + Hints.push_back(FixItHint::CreateInsertion(End, ")")); + } else { + Hints.push_back(FixItHint::CreateInsertion(Begin, "&")); + } + + NumConversionsFixed++; + if (NumConversionsFixed == 1) + Kind = FixKind; + return true; + } + } + + return false; +} + +static bool isMacroDefined(const Sema &S, StringRef Name) { + return S.PP.getMacroInfo(&S.getASTContext().Idents.get(Name)); +} + +const char *Sema::getFixItZeroInitializerForType(QualType T) const { + if (T->isScalarType()) { + // Suggest " = 0" for non-enumeration scalar types, unless we can find a + // better initializer. + if (T->isEnumeralType()) + return 0; + if ((T->isObjCObjectPointerType() || T->isBlockPointerType()) && + isMacroDefined(*this, "nil")) + return " = nil"; + if (T->isRealFloatingType()) + return " = 0.0"; + if (T->isBooleanType() && LangOpts.CPlusPlus) + return " = false"; + if (T->isPointerType() || T->isMemberPointerType()) { + if (LangOpts.CPlusPlus0x) + return " = nullptr"; + else if (isMacroDefined(*this, "NULL")) + return " = NULL"; + } + if (T->isCharType()) + return " = '\\0'"; + if (T->isWideCharType()) + return " = L'\\0'"; + if (T->isChar16Type()) + return " = u'\\0'"; + if (T->isChar32Type()) + return " = U'\\0'"; + return " = 0"; + } + + const CXXRecordDecl *RD = T->getAsCXXRecordDecl(); + if (!RD || !RD->hasDefinition()) + return 0; + if (LangOpts.CPlusPlus0x && !RD->hasUserProvidedDefaultConstructor()) + return "{}"; + if (RD->isAggregate()) + return " = {}"; + return 0; +} diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp new file mode 100644 index 0000000..a65b41f --- /dev/null +++ b/clang/lib/Sema/SemaInit.cpp @@ -0,0 +1,6167 @@ +//===--- SemaInit.cpp - Semantic Analysis for Initializers ----------------===// +// +// 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 initializers. +// +//===----------------------------------------------------------------------===// + +#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/AST/ASTContext.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprObjC.h" +#include "clang/AST/TypeLoc.h" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include +using namespace clang; + +//===----------------------------------------------------------------------===// +// Sema Initialization Checking +//===----------------------------------------------------------------------===// + +static Expr *IsStringInit(Expr *Init, const ArrayType *AT, + ASTContext &Context) { + if (!isa(AT) && !isa(AT)) + return 0; + + // See if this is a string literal or @encode. + Init = Init->IgnoreParens(); + + // Handle @encode, which is a narrow string. + if (isa(Init) && AT->getElementType()->isCharType()) + return Init; + + // Otherwise we can only handle string literals. + StringLiteral *SL = dyn_cast(Init); + if (SL == 0) return 0; + + QualType ElemTy = Context.getCanonicalType(AT->getElementType()); + + switch (SL->getKind()) { + case StringLiteral::Ascii: + case StringLiteral::UTF8: + // char array can be initialized with a narrow string. + // Only allow char x[] = "foo"; not char x[] = L"foo"; + return ElemTy->isCharType() ? Init : 0; + case StringLiteral::UTF16: + return ElemTy->isChar16Type() ? Init : 0; + case StringLiteral::UTF32: + return ElemTy->isChar32Type() ? Init : 0; + case StringLiteral::Wide: + // wchar_t array can be initialized with a wide string: C99 6.7.8p15 (with + // correction from DR343): "An array with element type compatible with a + // qualified or unqualified version of wchar_t may be initialized by a wide + // string literal, optionally enclosed in braces." + if (Context.typesAreCompatible(Context.getWCharType(), + ElemTy.getUnqualifiedType())) + return Init; + + return 0; + } + + llvm_unreachable("missed a StringLiteral kind?"); +} + +static Expr *IsStringInit(Expr *init, QualType declType, ASTContext &Context) { + const ArrayType *arrayType = Context.getAsArrayType(declType); + if (!arrayType) return 0; + + return IsStringInit(init, arrayType, Context); +} + +static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT, + Sema &S) { + // Get the length of the string as parsed. + uint64_t StrLength = + cast(Str->getType())->getSize().getZExtValue(); + + + if (const IncompleteArrayType *IAT = dyn_cast(AT)) { + // C99 6.7.8p14. We have an array of character type with unknown size + // being initialized to a string literal. + llvm::APSInt ConstVal(32); + ConstVal = StrLength; + // Return a new array type (C99 6.7.8p22). + DeclT = S.Context.getConstantArrayType(IAT->getElementType(), + ConstVal, + ArrayType::Normal, 0); + return; + } + + const ConstantArrayType *CAT = cast(AT); + + // We have an array of character type with known size. However, + // the size may be smaller or larger than the string we are initializing. + // FIXME: Avoid truncation for 64-bit length strings. + if (S.getLangOpts().CPlusPlus) { + if (StringLiteral *SL = dyn_cast(Str)) { + // For Pascal strings it's OK to strip off the terminating null character, + // so the example below is valid: + // + // unsigned char a[2] = "\pa"; + if (SL->isPascal()) + StrLength--; + } + + // [dcl.init.string]p2 + if (StrLength > CAT->getSize().getZExtValue()) + S.Diag(Str->getLocStart(), + diag::err_initializer_string_for_char_array_too_long) + << Str->getSourceRange(); + } else { + // C99 6.7.8p14. + if (StrLength-1 > CAT->getSize().getZExtValue()) + S.Diag(Str->getLocStart(), + diag::warn_initializer_string_for_char_array_too_long) + << Str->getSourceRange(); + } + + // Set the type to the actual size that we are initializing. If we have + // something like: + // char x[1] = "foo"; + // then this will set the string literal's type to char[1]. + Str->setType(DeclT); +} + +//===----------------------------------------------------------------------===// +// Semantic checking for initializer lists. +//===----------------------------------------------------------------------===// + +/// @brief Semantic checking for initializer lists. +/// +/// The InitListChecker class contains a set of routines that each +/// handle the initialization of a certain kind of entity, e.g., +/// arrays, vectors, struct/union types, scalars, etc. The +/// InitListChecker itself performs a recursive walk of the subobject +/// structure of the type to be initialized, while stepping through +/// the initializer list one element at a time. The IList and Index +/// parameters to each of the Check* routines contain the active +/// (syntactic) initializer list and the index into that initializer +/// list that represents the current initializer. Each routine is +/// responsible for moving that Index forward as it consumes elements. +/// +/// Each Check* routine also has a StructuredList/StructuredIndex +/// arguments, which contains the current "structured" (semantic) +/// initializer list and the index into that initializer list where we +/// are copying initializers as we map them over to the semantic +/// list. Once we have completed our recursive walk of the subobject +/// structure, we will have constructed a full semantic initializer +/// list. +/// +/// C99 designators cause changes in the initializer list traversal, +/// because they make the initialization "jump" into a specific +/// subobject and then continue the initialization from that +/// point. CheckDesignatedInitializer() recursively steps into the +/// designated subobject and manages backing out the recursion to +/// initialize the subobjects after the one designated. +namespace { +class InitListChecker { + Sema &SemaRef; + bool hadError; + bool VerifyOnly; // no diagnostics, no structure building + bool AllowBraceElision; + llvm::DenseMap SyntacticToSemantic; + InitListExpr *FullyStructuredList; + + void CheckImplicitInitList(const InitializedEntity &Entity, + InitListExpr *ParentIList, QualType T, + unsigned &Index, InitListExpr *StructuredList, + unsigned &StructuredIndex); + void CheckExplicitInitList(const InitializedEntity &Entity, + InitListExpr *IList, QualType &T, + unsigned &Index, InitListExpr *StructuredList, + unsigned &StructuredIndex, + bool TopLevelObject = false); + void CheckListElementTypes(const InitializedEntity &Entity, + InitListExpr *IList, QualType &DeclType, + bool SubobjectIsDesignatorContext, + unsigned &Index, + InitListExpr *StructuredList, + unsigned &StructuredIndex, + bool TopLevelObject = false); + void CheckSubElementType(const InitializedEntity &Entity, + InitListExpr *IList, QualType ElemType, + unsigned &Index, + InitListExpr *StructuredList, + unsigned &StructuredIndex); + void CheckComplexType(const InitializedEntity &Entity, + InitListExpr *IList, QualType DeclType, + unsigned &Index, + InitListExpr *StructuredList, + unsigned &StructuredIndex); + void CheckScalarType(const InitializedEntity &Entity, + InitListExpr *IList, QualType DeclType, + unsigned &Index, + InitListExpr *StructuredList, + unsigned &StructuredIndex); + void CheckReferenceType(const InitializedEntity &Entity, + InitListExpr *IList, QualType DeclType, + unsigned &Index, + InitListExpr *StructuredList, + unsigned &StructuredIndex); + void CheckVectorType(const InitializedEntity &Entity, + InitListExpr *IList, QualType DeclType, unsigned &Index, + InitListExpr *StructuredList, + unsigned &StructuredIndex); + void CheckStructUnionTypes(const InitializedEntity &Entity, + InitListExpr *IList, QualType DeclType, + RecordDecl::field_iterator Field, + bool SubobjectIsDesignatorContext, unsigned &Index, + InitListExpr *StructuredList, + unsigned &StructuredIndex, + bool TopLevelObject = false); + void CheckArrayType(const InitializedEntity &Entity, + InitListExpr *IList, QualType &DeclType, + llvm::APSInt elementIndex, + bool SubobjectIsDesignatorContext, unsigned &Index, + InitListExpr *StructuredList, + unsigned &StructuredIndex); + bool CheckDesignatedInitializer(const InitializedEntity &Entity, + InitListExpr *IList, DesignatedInitExpr *DIE, + unsigned DesigIdx, + QualType &CurrentObjectType, + RecordDecl::field_iterator *NextField, + llvm::APSInt *NextElementIndex, + unsigned &Index, + InitListExpr *StructuredList, + unsigned &StructuredIndex, + bool FinishSubobjectInit, + bool TopLevelObject); + InitListExpr *getStructuredSubobjectInit(InitListExpr *IList, unsigned Index, + QualType CurrentObjectType, + InitListExpr *StructuredList, + unsigned StructuredIndex, + SourceRange InitRange); + void UpdateStructuredListElement(InitListExpr *StructuredList, + unsigned &StructuredIndex, + Expr *expr); + int numArrayElements(QualType DeclType); + int numStructUnionElements(QualType DeclType); + + void FillInValueInitForField(unsigned Init, FieldDecl *Field, + const InitializedEntity &ParentEntity, + InitListExpr *ILE, bool &RequiresSecondPass); + void FillInValueInitializations(const InitializedEntity &Entity, + InitListExpr *ILE, bool &RequiresSecondPass); + bool CheckFlexibleArrayInit(const InitializedEntity &Entity, + Expr *InitExpr, FieldDecl *Field, + bool TopLevelObject); + void CheckValueInitializable(const InitializedEntity &Entity); + +public: + InitListChecker(Sema &S, const InitializedEntity &Entity, + InitListExpr *IL, QualType &T, bool VerifyOnly, + bool AllowBraceElision); + bool HadError() { return hadError; } + + // @brief Retrieves the fully-structured initializer list used for + // semantic analysis and code generation. + InitListExpr *getFullyStructuredList() const { return FullyStructuredList; } +}; +} // end anonymous namespace + +void InitListChecker::CheckValueInitializable(const InitializedEntity &Entity) { + assert(VerifyOnly && + "CheckValueInitializable is only inteded for verification mode."); + + SourceLocation Loc; + InitializationKind Kind = InitializationKind::CreateValue(Loc, Loc, Loc, + true); + InitializationSequence InitSeq(SemaRef, Entity, Kind, 0, 0); + if (InitSeq.Failed()) + hadError = true; +} + +void InitListChecker::FillInValueInitForField(unsigned Init, FieldDecl *Field, + const InitializedEntity &ParentEntity, + InitListExpr *ILE, + bool &RequiresSecondPass) { + SourceLocation Loc = ILE->getLocStart(); + unsigned NumInits = ILE->getNumInits(); + InitializedEntity MemberEntity + = InitializedEntity::InitializeMember(Field, &ParentEntity); + if (Init >= NumInits || !ILE->getInit(Init)) { + // FIXME: We probably don't need to handle references + // specially here, since value-initialization of references is + // handled in InitializationSequence. + if (Field->getType()->isReferenceType()) { + // C++ [dcl.init.aggr]p9: + // If an incomplete or empty initializer-list leaves a + // member of reference type uninitialized, the program is + // ill-formed. + SemaRef.Diag(Loc, diag::err_init_reference_member_uninitialized) + << Field->getType() + << ILE->getSyntacticForm()->getSourceRange(); + SemaRef.Diag(Field->getLocation(), + diag::note_uninit_reference_member); + hadError = true; + return; + } + + InitializationKind Kind = InitializationKind::CreateValue(Loc, Loc, Loc, + true); + InitializationSequence InitSeq(SemaRef, MemberEntity, Kind, 0, 0); + if (!InitSeq) { + InitSeq.Diagnose(SemaRef, MemberEntity, Kind, 0, 0); + hadError = true; + return; + } + + ExprResult MemberInit + = InitSeq.Perform(SemaRef, MemberEntity, Kind, MultiExprArg()); + if (MemberInit.isInvalid()) { + hadError = true; + return; + } + + if (hadError) { + // Do nothing + } else if (Init < NumInits) { + ILE->setInit(Init, MemberInit.takeAs()); + } else if (InitSeq.isConstructorInitialization()) { + // Value-initialization requires a constructor call, so + // extend the initializer list to include the constructor + // call and make a note that we'll need to take another pass + // through the initializer list. + ILE->updateInit(SemaRef.Context, Init, MemberInit.takeAs()); + RequiresSecondPass = true; + } + } else if (InitListExpr *InnerILE + = dyn_cast(ILE->getInit(Init))) + FillInValueInitializations(MemberEntity, InnerILE, + RequiresSecondPass); +} + +/// Recursively replaces NULL values within the given initializer list +/// with expressions that perform value-initialization of the +/// appropriate type. +void +InitListChecker::FillInValueInitializations(const InitializedEntity &Entity, + InitListExpr *ILE, + bool &RequiresSecondPass) { + assert((ILE->getType() != SemaRef.Context.VoidTy) && + "Should not have void type"); + SourceLocation Loc = ILE->getLocStart(); + if (ILE->getSyntacticForm()) + Loc = ILE->getSyntacticForm()->getLocStart(); + + if (const RecordType *RType = ILE->getType()->getAs()) { + if (RType->getDecl()->isUnion() && + ILE->getInitializedFieldInUnion()) + FillInValueInitForField(0, ILE->getInitializedFieldInUnion(), + Entity, ILE, RequiresSecondPass); + else { + unsigned Init = 0; + for (RecordDecl::field_iterator + Field = RType->getDecl()->field_begin(), + FieldEnd = RType->getDecl()->field_end(); + Field != FieldEnd; ++Field) { + if (Field->isUnnamedBitfield()) + continue; + + if (hadError) + return; + + FillInValueInitForField(Init, *Field, Entity, ILE, RequiresSecondPass); + if (hadError) + return; + + ++Init; + + // Only look at the first initialization of a union. + if (RType->getDecl()->isUnion()) + break; + } + } + + return; + } + + QualType ElementType; + + InitializedEntity ElementEntity = Entity; + unsigned NumInits = ILE->getNumInits(); + unsigned NumElements = NumInits; + if (const ArrayType *AType = SemaRef.Context.getAsArrayType(ILE->getType())) { + ElementType = AType->getElementType(); + if (const ConstantArrayType *CAType = dyn_cast(AType)) + NumElements = CAType->getSize().getZExtValue(); + ElementEntity = InitializedEntity::InitializeElement(SemaRef.Context, + 0, Entity); + } else if (const VectorType *VType = ILE->getType()->getAs()) { + ElementType = VType->getElementType(); + NumElements = VType->getNumElements(); + ElementEntity = InitializedEntity::InitializeElement(SemaRef.Context, + 0, Entity); + } else + ElementType = ILE->getType(); + + + for (unsigned Init = 0; Init != NumElements; ++Init) { + if (hadError) + return; + + if (ElementEntity.getKind() == InitializedEntity::EK_ArrayElement || + ElementEntity.getKind() == InitializedEntity::EK_VectorElement) + ElementEntity.setElementIndex(Init); + + Expr *InitExpr = (Init < NumInits ? ILE->getInit(Init) : 0); + if (!InitExpr && !ILE->hasArrayFiller()) { + InitializationKind Kind = InitializationKind::CreateValue(Loc, Loc, Loc, + true); + InitializationSequence InitSeq(SemaRef, ElementEntity, Kind, 0, 0); + if (!InitSeq) { + InitSeq.Diagnose(SemaRef, ElementEntity, Kind, 0, 0); + hadError = true; + return; + } + + ExprResult ElementInit + = InitSeq.Perform(SemaRef, ElementEntity, Kind, MultiExprArg()); + if (ElementInit.isInvalid()) { + hadError = true; + return; + } + + if (hadError) { + // Do nothing + } else if (Init < NumInits) { + // For arrays, just set the expression used for value-initialization + // of the "holes" in the array. + if (ElementEntity.getKind() == InitializedEntity::EK_ArrayElement) + ILE->setArrayFiller(ElementInit.takeAs()); + else + ILE->setInit(Init, ElementInit.takeAs()); + } else { + // For arrays, just set the expression used for value-initialization + // of the rest of elements and exit. + if (ElementEntity.getKind() == InitializedEntity::EK_ArrayElement) { + ILE->setArrayFiller(ElementInit.takeAs()); + return; + } + + if (InitSeq.isConstructorInitialization()) { + // Value-initialization requires a constructor call, so + // extend the initializer list to include the constructor + // call and make a note that we'll need to take another pass + // through the initializer list. + ILE->updateInit(SemaRef.Context, Init, ElementInit.takeAs()); + RequiresSecondPass = true; + } + } + } else if (InitListExpr *InnerILE + = dyn_cast_or_null(InitExpr)) + FillInValueInitializations(ElementEntity, InnerILE, RequiresSecondPass); + } +} + + +InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity, + InitListExpr *IL, QualType &T, + bool VerifyOnly, bool AllowBraceElision) + : SemaRef(S), VerifyOnly(VerifyOnly), AllowBraceElision(AllowBraceElision) { + hadError = false; + + unsigned newIndex = 0; + unsigned newStructuredIndex = 0; + FullyStructuredList + = getStructuredSubobjectInit(IL, newIndex, T, 0, 0, IL->getSourceRange()); + CheckExplicitInitList(Entity, IL, T, newIndex, + FullyStructuredList, newStructuredIndex, + /*TopLevelObject=*/true); + + if (!hadError && !VerifyOnly) { + bool RequiresSecondPass = false; + FillInValueInitializations(Entity, FullyStructuredList, RequiresSecondPass); + if (RequiresSecondPass && !hadError) + FillInValueInitializations(Entity, FullyStructuredList, + RequiresSecondPass); + } +} + +int InitListChecker::numArrayElements(QualType DeclType) { + // FIXME: use a proper constant + int maxElements = 0x7FFFFFFF; + if (const ConstantArrayType *CAT = + SemaRef.Context.getAsConstantArrayType(DeclType)) { + maxElements = static_cast(CAT->getSize().getZExtValue()); + } + return maxElements; +} + +int InitListChecker::numStructUnionElements(QualType DeclType) { + RecordDecl *structDecl = DeclType->getAs()->getDecl(); + int InitializableMembers = 0; + for (RecordDecl::field_iterator + Field = structDecl->field_begin(), + FieldEnd = structDecl->field_end(); + Field != FieldEnd; ++Field) { + if (!Field->isUnnamedBitfield()) + ++InitializableMembers; + } + if (structDecl->isUnion()) + return std::min(InitializableMembers, 1); + return InitializableMembers - structDecl->hasFlexibleArrayMember(); +} + +void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity, + InitListExpr *ParentIList, + QualType T, unsigned &Index, + InitListExpr *StructuredList, + unsigned &StructuredIndex) { + int maxElements = 0; + + if (T->isArrayType()) + maxElements = numArrayElements(T); + else if (T->isRecordType()) + maxElements = numStructUnionElements(T); + else if (T->isVectorType()) + maxElements = T->getAs()->getNumElements(); + else + llvm_unreachable("CheckImplicitInitList(): Illegal type"); + + if (maxElements == 0) { + if (!VerifyOnly) + SemaRef.Diag(ParentIList->getInit(Index)->getLocStart(), + diag::err_implicit_empty_initializer); + ++Index; + hadError = true; + return; + } + + // Build a structured initializer list corresponding to this subobject. + InitListExpr *StructuredSubobjectInitList + = getStructuredSubobjectInit(ParentIList, Index, T, StructuredList, + StructuredIndex, + SourceRange(ParentIList->getInit(Index)->getLocStart(), + ParentIList->getSourceRange().getEnd())); + unsigned StructuredSubobjectInitIndex = 0; + + // Check the element types and build the structural subobject. + unsigned StartIndex = Index; + CheckListElementTypes(Entity, ParentIList, T, + /*SubobjectIsDesignatorContext=*/false, Index, + StructuredSubobjectInitList, + StructuredSubobjectInitIndex); + + if (VerifyOnly) { + if (!AllowBraceElision && (T->isArrayType() || T->isRecordType())) + hadError = true; + } else { + StructuredSubobjectInitList->setType(T); + + unsigned EndIndex = (Index == StartIndex? StartIndex : Index - 1); + // Update the structured sub-object initializer so that it's ending + // range corresponds with the end of the last initializer it used. + if (EndIndex < ParentIList->getNumInits()) { + SourceLocation EndLoc + = ParentIList->getInit(EndIndex)->getSourceRange().getEnd(); + StructuredSubobjectInitList->setRBraceLoc(EndLoc); + } + + // Complain about missing braces. + if (T->isArrayType() || T->isRecordType()) { + SemaRef.Diag(StructuredSubobjectInitList->getLocStart(), + AllowBraceElision ? diag::warn_missing_braces : + diag::err_missing_braces) + << StructuredSubobjectInitList->getSourceRange() + << FixItHint::CreateInsertion( + StructuredSubobjectInitList->getLocStart(), "{") + << FixItHint::CreateInsertion( + SemaRef.PP.getLocForEndOfToken( + StructuredSubobjectInitList->getLocEnd()), + "}"); + if (!AllowBraceElision) + hadError = true; + } + } +} + +void InitListChecker::CheckExplicitInitList(const InitializedEntity &Entity, + InitListExpr *IList, QualType &T, + unsigned &Index, + InitListExpr *StructuredList, + unsigned &StructuredIndex, + bool TopLevelObject) { + assert(IList->isExplicit() && "Illegal Implicit InitListExpr"); + if (!VerifyOnly) { + SyntacticToSemantic[IList] = StructuredList; + StructuredList->setSyntacticForm(IList); + } + CheckListElementTypes(Entity, IList, T, /*SubobjectIsDesignatorContext=*/true, + Index, StructuredList, StructuredIndex, TopLevelObject); + if (!VerifyOnly) { + QualType ExprTy = T; + if (!ExprTy->isArrayType()) + ExprTy = ExprTy.getNonLValueExprType(SemaRef.Context); + IList->setType(ExprTy); + StructuredList->setType(ExprTy); + } + if (hadError) + return; + + if (Index < IList->getNumInits()) { + // We have leftover initializers + if (VerifyOnly) { + if (SemaRef.getLangOpts().CPlusPlus || + (SemaRef.getLangOpts().OpenCL && + IList->getType()->isVectorType())) { + hadError = true; + } + return; + } + + if (StructuredIndex == 1 && + IsStringInit(StructuredList->getInit(0), T, SemaRef.Context)) { + unsigned DK = diag::warn_excess_initializers_in_char_array_initializer; + if (SemaRef.getLangOpts().CPlusPlus) { + DK = diag::err_excess_initializers_in_char_array_initializer; + hadError = true; + } + // Special-case + SemaRef.Diag(IList->getInit(Index)->getLocStart(), DK) + << IList->getInit(Index)->getSourceRange(); + } else if (!T->isIncompleteType()) { + // Don't complain for incomplete types, since we'll get an error + // elsewhere + QualType CurrentObjectType = StructuredList->getType(); + int initKind = + CurrentObjectType->isArrayType()? 0 : + CurrentObjectType->isVectorType()? 1 : + CurrentObjectType->isScalarType()? 2 : + CurrentObjectType->isUnionType()? 3 : + 4; + + unsigned DK = diag::warn_excess_initializers; + if (SemaRef.getLangOpts().CPlusPlus) { + DK = diag::err_excess_initializers; + hadError = true; + } + if (SemaRef.getLangOpts().OpenCL && initKind == 1) { + DK = diag::err_excess_initializers; + hadError = true; + } + + SemaRef.Diag(IList->getInit(Index)->getLocStart(), DK) + << initKind << IList->getInit(Index)->getSourceRange(); + } + } + + if (!VerifyOnly && T->isScalarType() && IList->getNumInits() == 1 && + !TopLevelObject) + SemaRef.Diag(IList->getLocStart(), diag::warn_braces_around_scalar_init) + << IList->getSourceRange() + << FixItHint::CreateRemoval(IList->getLocStart()) + << FixItHint::CreateRemoval(IList->getLocEnd()); +} + +void InitListChecker::CheckListElementTypes(const InitializedEntity &Entity, + InitListExpr *IList, + QualType &DeclType, + bool SubobjectIsDesignatorContext, + unsigned &Index, + InitListExpr *StructuredList, + unsigned &StructuredIndex, + bool TopLevelObject) { + if (DeclType->isAnyComplexType() && SubobjectIsDesignatorContext) { + // Explicitly braced initializer for complex type can be real+imaginary + // parts. + CheckComplexType(Entity, IList, DeclType, Index, + StructuredList, StructuredIndex); + } else if (DeclType->isScalarType()) { + CheckScalarType(Entity, IList, DeclType, Index, + StructuredList, StructuredIndex); + } else if (DeclType->isVectorType()) { + CheckVectorType(Entity, IList, DeclType, Index, + StructuredList, StructuredIndex); + } else if (DeclType->isAggregateType()) { + if (DeclType->isRecordType()) { + RecordDecl *RD = DeclType->getAs()->getDecl(); + CheckStructUnionTypes(Entity, IList, DeclType, RD->field_begin(), + SubobjectIsDesignatorContext, Index, + StructuredList, StructuredIndex, + TopLevelObject); + } else if (DeclType->isArrayType()) { + llvm::APSInt Zero( + SemaRef.Context.getTypeSize(SemaRef.Context.getSizeType()), + false); + CheckArrayType(Entity, IList, DeclType, Zero, + SubobjectIsDesignatorContext, Index, + StructuredList, StructuredIndex); + } else + llvm_unreachable("Aggregate that isn't a structure or array?!"); + } else if (DeclType->isVoidType() || DeclType->isFunctionType()) { + // This type is invalid, issue a diagnostic. + ++Index; + if (!VerifyOnly) + SemaRef.Diag(IList->getLocStart(), diag::err_illegal_initializer_type) + << DeclType; + hadError = true; + } else if (DeclType->isRecordType()) { + // C++ [dcl.init]p14: + // [...] If the class is an aggregate (8.5.1), and the initializer + // is a brace-enclosed list, see 8.5.1. + // + // Note: 8.5.1 is handled below; here, we diagnose the case where + // we have an initializer list and a destination type that is not + // an aggregate. + // FIXME: In C++0x, this is yet another form of initialization. + if (!VerifyOnly) + SemaRef.Diag(IList->getLocStart(), diag::err_init_non_aggr_init_list) + << DeclType << IList->getSourceRange(); + hadError = true; + } else if (DeclType->isReferenceType()) { + CheckReferenceType(Entity, IList, DeclType, Index, + StructuredList, StructuredIndex); + } else if (DeclType->isObjCObjectType()) { + if (!VerifyOnly) + SemaRef.Diag(IList->getLocStart(), diag::err_init_objc_class) + << DeclType; + hadError = true; + } else { + if (!VerifyOnly) + SemaRef.Diag(IList->getLocStart(), diag::err_illegal_initializer_type) + << DeclType; + hadError = true; + } +} + +void InitListChecker::CheckSubElementType(const InitializedEntity &Entity, + InitListExpr *IList, + QualType ElemType, + unsigned &Index, + InitListExpr *StructuredList, + unsigned &StructuredIndex) { + Expr *expr = IList->getInit(Index); + if (InitListExpr *SubInitList = dyn_cast(expr)) { + unsigned newIndex = 0; + unsigned newStructuredIndex = 0; + InitListExpr *newStructuredList + = getStructuredSubobjectInit(IList, Index, ElemType, + StructuredList, StructuredIndex, + SubInitList->getSourceRange()); + CheckExplicitInitList(Entity, SubInitList, ElemType, newIndex, + newStructuredList, newStructuredIndex); + ++StructuredIndex; + ++Index; + return; + } else if (ElemType->isScalarType()) { + return CheckScalarType(Entity, IList, ElemType, Index, + StructuredList, StructuredIndex); + } else if (ElemType->isReferenceType()) { + return CheckReferenceType(Entity, IList, ElemType, Index, + StructuredList, StructuredIndex); + } + + if (const ArrayType *arrayType = SemaRef.Context.getAsArrayType(ElemType)) { + // arrayType can be incomplete if we're initializing a flexible + // array member. There's nothing we can do with the completed + // type here, though. + + if (Expr *Str = IsStringInit(expr, arrayType, SemaRef.Context)) { + if (!VerifyOnly) { + CheckStringInit(Str, ElemType, arrayType, SemaRef); + UpdateStructuredListElement(StructuredList, StructuredIndex, Str); + } + ++Index; + return; + } + + // Fall through for subaggregate initialization. + + } else if (SemaRef.getLangOpts().CPlusPlus) { + // C++ [dcl.init.aggr]p12: + // All implicit type conversions (clause 4) are considered when + // initializing the aggregate member with an initializer from + // an initializer-list. If the initializer can initialize a + // member, the member is initialized. [...] + + // FIXME: Better EqualLoc? + InitializationKind Kind = + InitializationKind::CreateCopy(expr->getLocStart(), SourceLocation()); + InitializationSequence Seq(SemaRef, Entity, Kind, &expr, 1); + + if (Seq) { + if (!VerifyOnly) { + ExprResult Result = + Seq.Perform(SemaRef, Entity, Kind, MultiExprArg(&expr, 1)); + if (Result.isInvalid()) + hadError = true; + + UpdateStructuredListElement(StructuredList, StructuredIndex, + Result.takeAs()); + } + ++Index; + return; + } + + // Fall through for subaggregate initialization + } else { + // C99 6.7.8p13: + // + // The initializer for a structure or union object that has + // automatic storage duration shall be either an initializer + // list as described below, or a single expression that has + // compatible structure or union type. In the latter case, the + // initial value of the object, including unnamed members, is + // that of the expression. + ExprResult ExprRes = SemaRef.Owned(expr); + if ((ElemType->isRecordType() || ElemType->isVectorType()) && + SemaRef.CheckSingleAssignmentConstraints(ElemType, ExprRes, + !VerifyOnly) + == Sema::Compatible) { + if (ExprRes.isInvalid()) + hadError = true; + else { + ExprRes = SemaRef.DefaultFunctionArrayLvalueConversion(ExprRes.take()); + if (ExprRes.isInvalid()) + hadError = true; + } + UpdateStructuredListElement(StructuredList, StructuredIndex, + ExprRes.takeAs()); + ++Index; + return; + } + ExprRes.release(); + // Fall through for subaggregate initialization + } + + // C++ [dcl.init.aggr]p12: + // + // [...] Otherwise, if the member is itself a non-empty + // subaggregate, brace elision is assumed and the initializer is + // considered for the initialization of the first member of + // the subaggregate. + if (!SemaRef.getLangOpts().OpenCL && + (ElemType->isAggregateType() || ElemType->isVectorType())) { + CheckImplicitInitList(Entity, IList, ElemType, Index, StructuredList, + StructuredIndex); + ++StructuredIndex; + } else { + if (!VerifyOnly) { + // We cannot initialize this element, so let + // PerformCopyInitialization produce the appropriate diagnostic. + SemaRef.PerformCopyInitialization(Entity, SourceLocation(), + SemaRef.Owned(expr), + /*TopLevelOfInitList=*/true); + } + hadError = true; + ++Index; + ++StructuredIndex; + } +} + +void InitListChecker::CheckComplexType(const InitializedEntity &Entity, + InitListExpr *IList, QualType DeclType, + unsigned &Index, + InitListExpr *StructuredList, + unsigned &StructuredIndex) { + assert(Index == 0 && "Index in explicit init list must be zero"); + + // As an extension, clang supports complex initializers, which initialize + // a complex number component-wise. When an explicit initializer list for + // a complex number contains two two initializers, this extension kicks in: + // it exepcts the initializer list to contain two elements convertible to + // the element type of the complex type. The first element initializes + // the real part, and the second element intitializes the imaginary part. + + if (IList->getNumInits() != 2) + return CheckScalarType(Entity, IList, DeclType, Index, StructuredList, + StructuredIndex); + + // This is an extension in C. (The builtin _Complex type does not exist + // in the C++ standard.) + if (!SemaRef.getLangOpts().CPlusPlus && !VerifyOnly) + SemaRef.Diag(IList->getLocStart(), diag::ext_complex_component_init) + << IList->getSourceRange(); + + // Initialize the complex number. + QualType elementType = DeclType->getAs()->getElementType(); + InitializedEntity ElementEntity = + InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity); + + for (unsigned i = 0; i < 2; ++i) { + ElementEntity.setElementIndex(Index); + CheckSubElementType(ElementEntity, IList, elementType, Index, + StructuredList, StructuredIndex); + } +} + + +void InitListChecker::CheckScalarType(const InitializedEntity &Entity, + InitListExpr *IList, QualType DeclType, + unsigned &Index, + InitListExpr *StructuredList, + unsigned &StructuredIndex) { + if (Index >= IList->getNumInits()) { + if (!VerifyOnly) + SemaRef.Diag(IList->getLocStart(), + SemaRef.getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_empty_scalar_initializer : + diag::err_empty_scalar_initializer) + << IList->getSourceRange(); + hadError = !SemaRef.getLangOpts().CPlusPlus0x; + ++Index; + ++StructuredIndex; + return; + } + + Expr *expr = IList->getInit(Index); + if (InitListExpr *SubIList = dyn_cast(expr)) { + if (!VerifyOnly) + 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)) { + if (!VerifyOnly) + SemaRef.Diag(expr->getLocStart(), + diag::err_designator_for_scalar_init) + << DeclType << expr->getSourceRange(); + hadError = true; + ++Index; + ++StructuredIndex; + return; + } + + if (VerifyOnly) { + if (!SemaRef.CanPerformCopyInitialization(Entity, SemaRef.Owned(expr))) + hadError = true; + ++Index; + return; + } + + ExprResult Result = + SemaRef.PerformCopyInitialization(Entity, expr->getLocStart(), + SemaRef.Owned(expr), + /*TopLevelOfInitList=*/true); + + Expr *ResultExpr = 0; + + if (Result.isInvalid()) + hadError = true; // types weren't compatible. + else { + ResultExpr = Result.takeAs(); + + if (ResultExpr != expr) { + // The type was promoted, update initializer list. + IList->setInit(Index, ResultExpr); + } + } + if (hadError) + ++StructuredIndex; + else + UpdateStructuredListElement(StructuredList, StructuredIndex, ResultExpr); + ++Index; +} + +void InitListChecker::CheckReferenceType(const InitializedEntity &Entity, + InitListExpr *IList, QualType DeclType, + unsigned &Index, + InitListExpr *StructuredList, + unsigned &StructuredIndex) { + if (Index >= IList->getNumInits()) { + // FIXME: It would be wonderful if we could point at the actual member. In + // general, it would be useful to pass location information down the stack, + // so that we know the location (or decl) of the "current object" being + // initialized. + if (!VerifyOnly) + SemaRef.Diag(IList->getLocStart(), + diag::err_init_reference_member_uninitialized) + << DeclType + << IList->getSourceRange(); + hadError = true; + ++Index; + ++StructuredIndex; + return; + } + + Expr *expr = IList->getInit(Index); + if (isa(expr) && !SemaRef.getLangOpts().CPlusPlus0x) { + if (!VerifyOnly) + SemaRef.Diag(IList->getLocStart(), diag::err_init_non_aggr_init_list) + << DeclType << IList->getSourceRange(); + hadError = true; + ++Index; + ++StructuredIndex; + return; + } + + if (VerifyOnly) { + if (!SemaRef.CanPerformCopyInitialization(Entity, SemaRef.Owned(expr))) + hadError = true; + ++Index; + return; + } + + ExprResult Result = + SemaRef.PerformCopyInitialization(Entity, expr->getLocStart(), + SemaRef.Owned(expr), + /*TopLevelOfInitList=*/true); + + if (Result.isInvalid()) + hadError = true; + + expr = Result.takeAs(); + IList->setInit(Index, expr); + + if (hadError) + ++StructuredIndex; + else + UpdateStructuredListElement(StructuredList, StructuredIndex, expr); + ++Index; +} + +void InitListChecker::CheckVectorType(const InitializedEntity &Entity, + InitListExpr *IList, QualType DeclType, + unsigned &Index, + InitListExpr *StructuredList, + unsigned &StructuredIndex) { + const VectorType *VT = DeclType->getAs(); + unsigned maxElements = VT->getNumElements(); + unsigned numEltsInit = 0; + QualType elementType = VT->getElementType(); + + if (Index >= IList->getNumInits()) { + // Make sure the element type can be value-initialized. + if (VerifyOnly) + CheckValueInitializable( + InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity)); + return; + } + + if (!SemaRef.getLangOpts().OpenCL) { + // If the initializing element is a vector, try to copy-initialize + // instead of breaking it apart (which is doomed to failure anyway). + Expr *Init = IList->getInit(Index); + if (!isa(Init) && Init->getType()->isVectorType()) { + if (VerifyOnly) { + if (!SemaRef.CanPerformCopyInitialization(Entity, SemaRef.Owned(Init))) + hadError = true; + ++Index; + return; + } + + ExprResult Result = + SemaRef.PerformCopyInitialization(Entity, Init->getLocStart(), + SemaRef.Owned(Init), + /*TopLevelOfInitList=*/true); + + Expr *ResultExpr = 0; + if (Result.isInvalid()) + hadError = true; // types weren't compatible. + else { + ResultExpr = Result.takeAs(); + + if (ResultExpr != Init) { + // The type was promoted, update initializer list. + IList->setInit(Index, ResultExpr); + } + } + if (hadError) + ++StructuredIndex; + else + UpdateStructuredListElement(StructuredList, StructuredIndex, + ResultExpr); + ++Index; + return; + } + + InitializedEntity ElementEntity = + InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity); + + for (unsigned i = 0; i < maxElements; ++i, ++numEltsInit) { + // Don't attempt to go past the end of the init list + if (Index >= IList->getNumInits()) { + if (VerifyOnly) + CheckValueInitializable(ElementEntity); + break; + } + + ElementEntity.setElementIndex(Index); + CheckSubElementType(ElementEntity, IList, elementType, Index, + StructuredList, StructuredIndex); + } + return; + } + + InitializedEntity ElementEntity = + InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity); + + // OpenCL initializers allows vectors to be constructed from vectors. + for (unsigned i = 0; i < maxElements; ++i) { + // Don't attempt to go past the end of the init list + if (Index >= IList->getNumInits()) + break; + + ElementEntity.setElementIndex(Index); + + QualType IType = IList->getInit(Index)->getType(); + if (!IType->isVectorType()) { + CheckSubElementType(ElementEntity, IList, elementType, Index, + StructuredList, StructuredIndex); + ++numEltsInit; + } else { + QualType VecType; + const VectorType *IVT = IType->getAs(); + unsigned numIElts = IVT->getNumElements(); + + if (IType->isExtVectorType()) + VecType = SemaRef.Context.getExtVectorType(elementType, numIElts); + else + VecType = SemaRef.Context.getVectorType(elementType, numIElts, + IVT->getVectorKind()); + CheckSubElementType(ElementEntity, IList, VecType, Index, + StructuredList, StructuredIndex); + numEltsInit += numIElts; + } + } + + // OpenCL requires all elements to be initialized. + if (numEltsInit != maxElements) { + if (!VerifyOnly) + SemaRef.Diag(IList->getLocStart(), + diag::err_vector_incorrect_num_initializers) + << (numEltsInit < maxElements) << maxElements << numEltsInit; + hadError = true; + } +} + +void InitListChecker::CheckArrayType(const InitializedEntity &Entity, + InitListExpr *IList, QualType &DeclType, + llvm::APSInt elementIndex, + bool SubobjectIsDesignatorContext, + unsigned &Index, + InitListExpr *StructuredList, + unsigned &StructuredIndex) { + const ArrayType *arrayType = SemaRef.Context.getAsArrayType(DeclType); + + // Check for the special-case of initializing an array with a string. + if (Index < IList->getNumInits()) { + if (Expr *Str = IsStringInit(IList->getInit(Index), arrayType, + SemaRef.Context)) { + // We place the string literal directly into the resulting + // initializer list. This is the only place where the structure + // of the structured initializer list doesn't match exactly, + // because doing so would involve allocating one character + // constant for each string. + if (!VerifyOnly) { + CheckStringInit(Str, DeclType, arrayType, SemaRef); + UpdateStructuredListElement(StructuredList, StructuredIndex, Str); + StructuredList->resizeInits(SemaRef.Context, StructuredIndex); + } + ++Index; + return; + } + } + if (const VariableArrayType *VAT = dyn_cast(arrayType)) { + // Check for VLAs; in standard C it would be possible to check this + // earlier, but I don't know where clang accepts VLAs (gcc accepts + // them in all sorts of strange places). + if (!VerifyOnly) + SemaRef.Diag(VAT->getSizeExpr()->getLocStart(), + diag::err_variable_object_no_init) + << VAT->getSizeExpr()->getSourceRange(); + hadError = true; + ++Index; + ++StructuredIndex; + return; + } + + // We might know the maximum number of elements in advance. + llvm::APSInt maxElements(elementIndex.getBitWidth(), + elementIndex.isUnsigned()); + bool maxElementsKnown = false; + if (const ConstantArrayType *CAT = dyn_cast(arrayType)) { + maxElements = CAT->getSize(); + elementIndex = elementIndex.extOrTrunc(maxElements.getBitWidth()); + elementIndex.setIsUnsigned(maxElements.isUnsigned()); + maxElementsKnown = true; + } + + QualType elementType = arrayType->getElementType(); + while (Index < IList->getNumInits()) { + Expr *Init = IList->getInit(Index); + if (DesignatedInitExpr *DIE = dyn_cast(Init)) { + // If we're not the subobject that matches up with the '{' for + // the designator, we shouldn't be handling the + // designator. Return immediately. + if (!SubobjectIsDesignatorContext) + return; + + // Handle this designated initializer. elementIndex will be + // updated to be the next array element we'll initialize. + if (CheckDesignatedInitializer(Entity, IList, DIE, 0, + DeclType, 0, &elementIndex, Index, + StructuredList, StructuredIndex, true, + false)) { + hadError = true; + continue; + } + + if (elementIndex.getBitWidth() > maxElements.getBitWidth()) + maxElements = maxElements.extend(elementIndex.getBitWidth()); + else if (elementIndex.getBitWidth() < maxElements.getBitWidth()) + elementIndex = elementIndex.extend(maxElements.getBitWidth()); + elementIndex.setIsUnsigned(maxElements.isUnsigned()); + + // If the array is of incomplete type, keep track of the number of + // elements in the initializer. + if (!maxElementsKnown && elementIndex > maxElements) + maxElements = elementIndex; + + continue; + } + + // If we know the maximum number of elements, and we've already + // hit it, stop consuming elements in the initializer list. + if (maxElementsKnown && elementIndex == maxElements) + break; + + InitializedEntity ElementEntity = + InitializedEntity::InitializeElement(SemaRef.Context, StructuredIndex, + Entity); + // Check this element. + CheckSubElementType(ElementEntity, IList, elementType, Index, + StructuredList, StructuredIndex); + ++elementIndex; + + // If the array is of incomplete type, keep track of the number of + // elements in the initializer. + if (!maxElementsKnown && elementIndex > maxElements) + maxElements = elementIndex; + } + if (!hadError && DeclType->isIncompleteArrayType() && !VerifyOnly) { + // If this is an incomplete array type, the actual type needs to + // be calculated here. + llvm::APSInt Zero(maxElements.getBitWidth(), maxElements.isUnsigned()); + if (maxElements == Zero) { + // Sizing an array implicitly to zero is not allowed by ISO C, + // but is supported by GNU. + SemaRef.Diag(IList->getLocStart(), + diag::ext_typecheck_zero_array_size); + } + + DeclType = SemaRef.Context.getConstantArrayType(elementType, maxElements, + ArrayType::Normal, 0); + } + if (!hadError && VerifyOnly) { + // Check if there are any members of the array that get value-initialized. + // If so, check if doing that is possible. + // FIXME: This needs to detect holes left by designated initializers too. + if (maxElementsKnown && elementIndex < maxElements) + CheckValueInitializable(InitializedEntity::InitializeElement( + SemaRef.Context, 0, Entity)); + } +} + +bool InitListChecker::CheckFlexibleArrayInit(const InitializedEntity &Entity, + Expr *InitExpr, + FieldDecl *Field, + bool TopLevelObject) { + // Handle GNU flexible array initializers. + unsigned FlexArrayDiag; + if (isa(InitExpr) && + cast(InitExpr)->getNumInits() == 0) { + // Empty flexible array init always allowed as an extension + FlexArrayDiag = diag::ext_flexible_array_init; + } else if (SemaRef.getLangOpts().CPlusPlus) { + // Disallow flexible array init in C++; it is not required for gcc + // compatibility, and it needs work to IRGen correctly in general. + FlexArrayDiag = diag::err_flexible_array_init; + } else if (!TopLevelObject) { + // Disallow flexible array init on non-top-level object + FlexArrayDiag = diag::err_flexible_array_init; + } else if (Entity.getKind() != InitializedEntity::EK_Variable) { + // Disallow flexible array init on anything which is not a variable. + FlexArrayDiag = diag::err_flexible_array_init; + } else if (cast(Entity.getDecl())->hasLocalStorage()) { + // Disallow flexible array init on local variables. + FlexArrayDiag = diag::err_flexible_array_init; + } else { + // Allow other cases. + FlexArrayDiag = diag::ext_flexible_array_init; + } + + if (!VerifyOnly) { + SemaRef.Diag(InitExpr->getLocStart(), + FlexArrayDiag) + << InitExpr->getLocStart(); + SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member) + << Field; + } + + return FlexArrayDiag != diag::ext_flexible_array_init; +} + +void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity, + InitListExpr *IList, + QualType DeclType, + RecordDecl::field_iterator Field, + bool SubobjectIsDesignatorContext, + unsigned &Index, + InitListExpr *StructuredList, + unsigned &StructuredIndex, + bool TopLevelObject) { + RecordDecl* structDecl = DeclType->getAs()->getDecl(); + + // If the record is invalid, some of it's members are invalid. To avoid + // confusion, we forgo checking the intializer for the entire record. + if (structDecl->isInvalidDecl()) { + hadError = true; + return; + } + + if (DeclType->isUnionType() && IList->getNumInits() == 0) { + // Value-initialize the first named member of the union. + RecordDecl *RD = DeclType->getAs()->getDecl(); + for (RecordDecl::field_iterator FieldEnd = RD->field_end(); + Field != FieldEnd; ++Field) { + if (Field->getDeclName()) { + if (VerifyOnly) + CheckValueInitializable( + InitializedEntity::InitializeMember(*Field, &Entity)); + else + StructuredList->setInitializedFieldInUnion(*Field); + break; + } + } + return; + } + + // If structDecl is a forward declaration, this loop won't do + // anything except look at designated initializers; That's okay, + // because an error should get printed out elsewhere. It might be + // worthwhile to skip over the rest of the initializer, though. + RecordDecl *RD = DeclType->getAs()->getDecl(); + RecordDecl::field_iterator FieldEnd = RD->field_end(); + bool InitializedSomething = false; + bool CheckForMissingFields = true; + while (Index < IList->getNumInits()) { + Expr *Init = IList->getInit(Index); + + if (DesignatedInitExpr *DIE = dyn_cast(Init)) { + // If we're not the subobject that matches up with the '{' for + // the designator, we shouldn't be handling the + // designator. Return immediately. + if (!SubobjectIsDesignatorContext) + return; + + // Handle this designated initializer. Field will be updated to + // the next field that we'll be initializing. + if (CheckDesignatedInitializer(Entity, IList, DIE, 0, + DeclType, &Field, 0, Index, + StructuredList, StructuredIndex, + true, TopLevelObject)) + hadError = true; + + InitializedSomething = true; + + // Disable check for missing fields when designators are used. + // This matches gcc behaviour. + CheckForMissingFields = false; + continue; + } + + if (Field == FieldEnd) { + // We've run out of fields. We're done. + break; + } + + // We've already initialized a member of a union. We're done. + if (InitializedSomething && DeclType->isUnionType()) + break; + + // If we've hit the flexible array member at the end, we're done. + if (Field->getType()->isIncompleteArrayType()) + break; + + if (Field->isUnnamedBitfield()) { + // Don't initialize unnamed bitfields, e.g. "int : 20;" + ++Field; + continue; + } + + // Make sure we can use this declaration. + bool InvalidUse; + if (VerifyOnly) + InvalidUse = !SemaRef.CanUseDecl(*Field); + else + InvalidUse = SemaRef.DiagnoseUseOfDecl(*Field, + IList->getInit(Index)->getLocStart()); + if (InvalidUse) { + ++Index; + ++Field; + hadError = true; + continue; + } + + InitializedEntity MemberEntity = + InitializedEntity::InitializeMember(*Field, &Entity); + CheckSubElementType(MemberEntity, IList, Field->getType(), Index, + StructuredList, StructuredIndex); + InitializedSomething = true; + + if (DeclType->isUnionType() && !VerifyOnly) { + // Initialize the first field within the union. + StructuredList->setInitializedFieldInUnion(*Field); + } + + ++Field; + } + + // Emit warnings for missing struct field initializers. + if (!VerifyOnly && InitializedSomething && CheckForMissingFields && + Field != FieldEnd && !Field->getType()->isIncompleteArrayType() && + !DeclType->isUnionType()) { + // It is possible we have one or more unnamed bitfields remaining. + // Find first (if any) named field and emit warning. + for (RecordDecl::field_iterator it = Field, end = RD->field_end(); + it != end; ++it) { + if (!it->isUnnamedBitfield()) { + SemaRef.Diag(IList->getSourceRange().getEnd(), + diag::warn_missing_field_initializers) << it->getName(); + break; + } + } + } + + // Check that any remaining fields can be value-initialized. + if (VerifyOnly && Field != FieldEnd && !DeclType->isUnionType() && + !Field->getType()->isIncompleteArrayType()) { + // FIXME: Should check for holes left by designated initializers too. + for (; Field != FieldEnd && !hadError; ++Field) { + if (!Field->isUnnamedBitfield()) + CheckValueInitializable( + InitializedEntity::InitializeMember(*Field, &Entity)); + } + } + + if (Field == FieldEnd || !Field->getType()->isIncompleteArrayType() || + Index >= IList->getNumInits()) + return; + + if (CheckFlexibleArrayInit(Entity, IList->getInit(Index), *Field, + TopLevelObject)) { + hadError = true; + ++Index; + return; + } + + InitializedEntity MemberEntity = + InitializedEntity::InitializeMember(*Field, &Entity); + + if (isa(IList->getInit(Index))) + CheckSubElementType(MemberEntity, IList, Field->getType(), Index, + StructuredList, StructuredIndex); + else + CheckImplicitInitList(MemberEntity, IList, Field->getType(), Index, + StructuredList, StructuredIndex); +} + +/// \brief Expand a field designator that refers to a member of an +/// anonymous struct or union into a series of field designators that +/// refers to the field within the appropriate subobject. +/// +static void ExpandAnonymousFieldDesignator(Sema &SemaRef, + DesignatedInitExpr *DIE, + unsigned DesigIdx, + IndirectFieldDecl *IndirectField) { + typedef DesignatedInitExpr::Designator Designator; + + // Build the replacement designators. + SmallVector Replacements; + for (IndirectFieldDecl::chain_iterator PI = IndirectField->chain_begin(), + PE = IndirectField->chain_end(); PI != PE; ++PI) { + if (PI + 1 == PE) + Replacements.push_back(Designator((IdentifierInfo *)0, + DIE->getDesignator(DesigIdx)->getDotLoc(), + DIE->getDesignator(DesigIdx)->getFieldLoc())); + else + Replacements.push_back(Designator((IdentifierInfo *)0, SourceLocation(), + SourceLocation())); + assert(isa(*PI)); + Replacements.back().setField(cast(*PI)); + } + + // Expand the current designator into the set of replacement + // designators, so we have a full subobject path down to where the + // member of the anonymous struct/union is actually stored. + DIE->ExpandDesignator(SemaRef.Context, DesigIdx, &Replacements[0], + &Replacements[0] + Replacements.size()); +} + +/// \brief Given an implicit anonymous field, search the IndirectField that +/// corresponds to FieldName. +static IndirectFieldDecl *FindIndirectFieldDesignator(FieldDecl *AnonField, + IdentifierInfo *FieldName) { + assert(AnonField->isAnonymousStructOrUnion()); + Decl *NextDecl = AnonField->getNextDeclInContext(); + while (IndirectFieldDecl *IF = + dyn_cast_or_null(NextDecl)) { + if (FieldName && FieldName == IF->getAnonField()->getIdentifier()) + return IF; + NextDecl = NextDecl->getNextDeclInContext(); + } + return 0; +} + +static DesignatedInitExpr *CloneDesignatedInitExpr(Sema &SemaRef, + DesignatedInitExpr *DIE) { + unsigned NumIndexExprs = DIE->getNumSubExprs() - 1; + SmallVector IndexExprs(NumIndexExprs); + for (unsigned I = 0; I < NumIndexExprs; ++I) + IndexExprs[I] = DIE->getSubExpr(I + 1); + return DesignatedInitExpr::Create(SemaRef.Context, DIE->designators_begin(), + DIE->size(), IndexExprs.data(), + NumIndexExprs, DIE->getEqualOrColonLoc(), + DIE->usesGNUSyntax(), DIE->getInit()); +} + +namespace { + +// Callback to only accept typo corrections that are for field members of +// the given struct or union. +class FieldInitializerValidatorCCC : public CorrectionCandidateCallback { + public: + explicit FieldInitializerValidatorCCC(RecordDecl *RD) + : Record(RD) {} + + virtual bool ValidateCandidate(const TypoCorrection &candidate) { + FieldDecl *FD = candidate.getCorrectionDeclAs(); + return FD && FD->getDeclContext()->getRedeclContext()->Equals(Record); + } + + private: + RecordDecl *Record; +}; + +} + +/// @brief Check the well-formedness of a C99 designated initializer. +/// +/// Determines whether the designated initializer @p DIE, which +/// resides at the given @p Index within the initializer list @p +/// IList, is well-formed for a current object of type @p DeclType +/// (C99 6.7.8). The actual subobject that this designator refers to +/// within the current subobject is returned in either +/// @p NextField or @p NextElementIndex (whichever is appropriate). +/// +/// @param IList The initializer list in which this designated +/// initializer occurs. +/// +/// @param DIE The designated initializer expression. +/// +/// @param DesigIdx The index of the current designator. +/// +/// @param DeclType The type of the "current object" (C99 6.7.8p17), +/// into which the designation in @p DIE should refer. +/// +/// @param NextField If non-NULL and the first designator in @p DIE is +/// a field, this will be set to the field declaration corresponding +/// to the field named by the designator. +/// +/// @param NextElementIndex If non-NULL and the first designator in @p +/// DIE is an array designator or GNU array-range designator, this +/// will be set to the last index initialized by this designator. +/// +/// @param Index Index into @p IList where the designated initializer +/// @p DIE occurs. +/// +/// @param StructuredList The initializer list expression that +/// describes all of the subobject initializers in the order they'll +/// actually be initialized. +/// +/// @returns true if there was an error, false otherwise. +bool +InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, + InitListExpr *IList, + DesignatedInitExpr *DIE, + unsigned DesigIdx, + QualType &CurrentObjectType, + RecordDecl::field_iterator *NextField, + llvm::APSInt *NextElementIndex, + unsigned &Index, + InitListExpr *StructuredList, + unsigned &StructuredIndex, + bool FinishSubobjectInit, + bool TopLevelObject) { + if (DesigIdx == DIE->size()) { + // Check the actual initialization for the designated object type. + bool prevHadError = hadError; + + // Temporarily remove the designator expression from the + // initializer list that the child calls see, so that we don't try + // to re-process the designator. + unsigned OldIndex = Index; + IList->setInit(OldIndex, DIE->getInit()); + + CheckSubElementType(Entity, IList, CurrentObjectType, Index, + StructuredList, StructuredIndex); + + // Restore the designated initializer expression in the syntactic + // form of the initializer list. + if (IList->getInit(OldIndex) != DIE->getInit()) + DIE->setInit(IList->getInit(OldIndex)); + IList->setInit(OldIndex, DIE); + + return hadError && !prevHadError; + } + + DesignatedInitExpr::Designator *D = DIE->getDesignator(DesigIdx); + bool IsFirstDesignator = (DesigIdx == 0); + if (!VerifyOnly) { + assert((IsFirstDesignator || StructuredList) && + "Need a non-designated initializer list to start from"); + + // Determine the structural initializer list that corresponds to the + // current subobject. + StructuredList = IsFirstDesignator? SyntacticToSemantic.lookup(IList) + : getStructuredSubobjectInit(IList, Index, CurrentObjectType, + StructuredList, StructuredIndex, + SourceRange(D->getStartLocation(), + DIE->getSourceRange().getEnd())); + assert(StructuredList && "Expected a structured initializer list"); + } + + if (D->isFieldDesignator()) { + // C99 6.7.8p7: + // + // If a designator has the form + // + // . identifier + // + // then the current object (defined below) shall have + // structure or union type and the identifier shall be the + // name of a member of that type. + const RecordType *RT = CurrentObjectType->getAs(); + if (!RT) { + SourceLocation Loc = D->getDotLoc(); + if (Loc.isInvalid()) + Loc = D->getFieldLoc(); + if (!VerifyOnly) + SemaRef.Diag(Loc, diag::err_field_designator_non_aggr) + << SemaRef.getLangOpts().CPlusPlus << CurrentObjectType; + ++Index; + return true; + } + + // Note: we perform a linear search of the fields here, despite + // the fact that we have a faster lookup method, because we always + // need to compute the field's index. + FieldDecl *KnownField = D->getField(); + IdentifierInfo *FieldName = D->getFieldName(); + unsigned FieldIndex = 0; + RecordDecl::field_iterator + Field = RT->getDecl()->field_begin(), + FieldEnd = RT->getDecl()->field_end(); + for (; Field != FieldEnd; ++Field) { + if (Field->isUnnamedBitfield()) + continue; + + // If we find a field representing an anonymous field, look in the + // IndirectFieldDecl that follow for the designated initializer. + if (!KnownField && Field->isAnonymousStructOrUnion()) { + if (IndirectFieldDecl *IF = + FindIndirectFieldDesignator(*Field, FieldName)) { + // In verify mode, don't modify the original. + if (VerifyOnly) + DIE = CloneDesignatedInitExpr(SemaRef, DIE); + ExpandAnonymousFieldDesignator(SemaRef, DIE, DesigIdx, IF); + D = DIE->getDesignator(DesigIdx); + break; + } + } + if (KnownField && KnownField == *Field) + break; + if (FieldName && FieldName == Field->getIdentifier()) + break; + + ++FieldIndex; + } + + if (Field == FieldEnd) { + if (VerifyOnly) { + ++Index; + return true; // No typo correction when just trying this out. + } + + // There was no normal field in the struct with the designated + // name. Perform another lookup for this name, which may find + // something that we can't designate (e.g., a member function), + // may find nothing, or may find a member of an anonymous + // struct/union. + DeclContext::lookup_result Lookup = RT->getDecl()->lookup(FieldName); + FieldDecl *ReplacementField = 0; + if (Lookup.first == Lookup.second) { + // Name lookup didn't find anything. Determine whether this + // was a typo for another field name. + FieldInitializerValidatorCCC Validator(RT->getDecl()); + TypoCorrection Corrected = SemaRef.CorrectTypo( + DeclarationNameInfo(FieldName, D->getFieldLoc()), + Sema::LookupMemberName, /*Scope=*/0, /*SS=*/0, Validator, + RT->getDecl()); + if (Corrected) { + std::string CorrectedStr( + Corrected.getAsString(SemaRef.getLangOpts())); + std::string CorrectedQuotedStr( + Corrected.getQuoted(SemaRef.getLangOpts())); + ReplacementField = Corrected.getCorrectionDeclAs(); + SemaRef.Diag(D->getFieldLoc(), + diag::err_field_designator_unknown_suggest) + << FieldName << CurrentObjectType << CorrectedQuotedStr + << FixItHint::CreateReplacement(D->getFieldLoc(), CorrectedStr); + SemaRef.Diag(ReplacementField->getLocation(), + diag::note_previous_decl) << CorrectedQuotedStr; + hadError = true; + } else { + SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_unknown) + << FieldName << CurrentObjectType; + ++Index; + return true; + } + } + + if (!ReplacementField) { + // Name lookup found something, but it wasn't a field. + SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_nonfield) + << FieldName; + SemaRef.Diag((*Lookup.first)->getLocation(), + diag::note_field_designator_found); + ++Index; + return true; + } + + if (!KnownField) { + // The replacement field comes from typo correction; find it + // in the list of fields. + FieldIndex = 0; + Field = RT->getDecl()->field_begin(); + for (; Field != FieldEnd; ++Field) { + if (Field->isUnnamedBitfield()) + continue; + + if (ReplacementField == *Field || + Field->getIdentifier() == ReplacementField->getIdentifier()) + break; + + ++FieldIndex; + } + } + } + + // All of the fields of a union are located at the same place in + // the initializer list. + if (RT->getDecl()->isUnion()) { + FieldIndex = 0; + if (!VerifyOnly) + StructuredList->setInitializedFieldInUnion(*Field); + } + + // Make sure we can use this declaration. + bool InvalidUse; + if (VerifyOnly) + InvalidUse = !SemaRef.CanUseDecl(*Field); + else + InvalidUse = SemaRef.DiagnoseUseOfDecl(*Field, D->getFieldLoc()); + if (InvalidUse) { + ++Index; + return true; + } + + if (!VerifyOnly) { + // Update the designator with the field declaration. + D->setField(*Field); + + // Make sure that our non-designated initializer list has space + // for a subobject corresponding to this field. + if (FieldIndex >= StructuredList->getNumInits()) + StructuredList->resizeInits(SemaRef.Context, FieldIndex + 1); + } + + // This designator names a flexible array member. + if (Field->getType()->isIncompleteArrayType()) { + bool Invalid = false; + if ((DesigIdx + 1) != DIE->size()) { + // We can't designate an object within the flexible array + // member (because GCC doesn't allow it). + if (!VerifyOnly) { + DesignatedInitExpr::Designator *NextD + = DIE->getDesignator(DesigIdx + 1); + SemaRef.Diag(NextD->getStartLocation(), + diag::err_designator_into_flexible_array_member) + << SourceRange(NextD->getStartLocation(), + DIE->getSourceRange().getEnd()); + SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member) + << *Field; + } + Invalid = true; + } + + if (!hadError && !isa(DIE->getInit()) && + !isa(DIE->getInit())) { + // The initializer is not an initializer list. + if (!VerifyOnly) { + SemaRef.Diag(DIE->getInit()->getLocStart(), + diag::err_flexible_array_init_needs_braces) + << DIE->getInit()->getSourceRange(); + SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member) + << *Field; + } + Invalid = true; + } + + // Check GNU flexible array initializer. + if (!Invalid && CheckFlexibleArrayInit(Entity, DIE->getInit(), *Field, + TopLevelObject)) + Invalid = true; + + if (Invalid) { + ++Index; + return true; + } + + // Initialize the array. + bool prevHadError = hadError; + unsigned newStructuredIndex = FieldIndex; + unsigned OldIndex = Index; + IList->setInit(Index, DIE->getInit()); + + InitializedEntity MemberEntity = + InitializedEntity::InitializeMember(*Field, &Entity); + CheckSubElementType(MemberEntity, IList, Field->getType(), Index, + StructuredList, newStructuredIndex); + + IList->setInit(OldIndex, DIE); + if (hadError && !prevHadError) { + ++Field; + ++FieldIndex; + if (NextField) + *NextField = Field; + StructuredIndex = FieldIndex; + return true; + } + } else { + // Recurse to check later designated subobjects. + QualType FieldType = (*Field)->getType(); + unsigned newStructuredIndex = FieldIndex; + + InitializedEntity MemberEntity = + InitializedEntity::InitializeMember(*Field, &Entity); + if (CheckDesignatedInitializer(MemberEntity, IList, DIE, DesigIdx + 1, + FieldType, 0, 0, Index, + StructuredList, newStructuredIndex, + true, false)) + return true; + } + + // Find the position of the next field to be initialized in this + // subobject. + ++Field; + ++FieldIndex; + + // If this the first designator, our caller will continue checking + // the rest of this struct/class/union subobject. + if (IsFirstDesignator) { + if (NextField) + *NextField = Field; + StructuredIndex = FieldIndex; + return false; + } + + if (!FinishSubobjectInit) + return false; + + // We've already initialized something in the union; we're done. + if (RT->getDecl()->isUnion()) + return hadError; + + // Check the remaining fields within this class/struct/union subobject. + bool prevHadError = hadError; + + CheckStructUnionTypes(Entity, IList, CurrentObjectType, Field, false, Index, + StructuredList, FieldIndex); + return hadError && !prevHadError; + } + + // C99 6.7.8p6: + // + // If a designator has the form + // + // [ constant-expression ] + // + // then the current object (defined below) shall have array + // type and the expression shall be an integer constant + // expression. If the array is of unknown size, any + // nonnegative value is valid. + // + // Additionally, cope with the GNU extension that permits + // designators of the form + // + // [ constant-expression ... constant-expression ] + const ArrayType *AT = SemaRef.Context.getAsArrayType(CurrentObjectType); + if (!AT) { + if (!VerifyOnly) + SemaRef.Diag(D->getLBracketLoc(), diag::err_array_designator_non_array) + << CurrentObjectType; + ++Index; + return true; + } + + Expr *IndexExpr = 0; + llvm::APSInt DesignatedStartIndex, DesignatedEndIndex; + if (D->isArrayDesignator()) { + IndexExpr = DIE->getArrayIndex(*D); + DesignatedStartIndex = IndexExpr->EvaluateKnownConstInt(SemaRef.Context); + DesignatedEndIndex = DesignatedStartIndex; + } else { + assert(D->isArrayRangeDesignator() && "Need array-range designator"); + + DesignatedStartIndex = + DIE->getArrayRangeStart(*D)->EvaluateKnownConstInt(SemaRef.Context); + DesignatedEndIndex = + DIE->getArrayRangeEnd(*D)->EvaluateKnownConstInt(SemaRef.Context); + IndexExpr = DIE->getArrayRangeEnd(*D); + + // Codegen can't handle evaluating array range designators that have side + // effects, because we replicate the AST value for each initialized element. + // As such, set the sawArrayRangeDesignator() bit if we initialize multiple + // elements with something that has a side effect, so codegen can emit an + // "error unsupported" error instead of miscompiling the app. + if (DesignatedStartIndex.getZExtValue()!=DesignatedEndIndex.getZExtValue()&& + DIE->getInit()->HasSideEffects(SemaRef.Context) && !VerifyOnly) + FullyStructuredList->sawArrayRangeDesignator(); + } + + if (isa(AT)) { + llvm::APSInt MaxElements(cast(AT)->getSize(), false); + DesignatedStartIndex + = DesignatedStartIndex.extOrTrunc(MaxElements.getBitWidth()); + DesignatedStartIndex.setIsUnsigned(MaxElements.isUnsigned()); + DesignatedEndIndex + = DesignatedEndIndex.extOrTrunc(MaxElements.getBitWidth()); + DesignatedEndIndex.setIsUnsigned(MaxElements.isUnsigned()); + if (DesignatedEndIndex >= MaxElements) { + if (!VerifyOnly) + SemaRef.Diag(IndexExpr->getLocStart(), + diag::err_array_designator_too_large) + << DesignatedEndIndex.toString(10) << MaxElements.toString(10) + << IndexExpr->getSourceRange(); + ++Index; + return true; + } + } else { + // Make sure the bit-widths and signedness match. + if (DesignatedStartIndex.getBitWidth() > DesignatedEndIndex.getBitWidth()) + DesignatedEndIndex + = DesignatedEndIndex.extend(DesignatedStartIndex.getBitWidth()); + else if (DesignatedStartIndex.getBitWidth() < + DesignatedEndIndex.getBitWidth()) + DesignatedStartIndex + = DesignatedStartIndex.extend(DesignatedEndIndex.getBitWidth()); + DesignatedStartIndex.setIsUnsigned(true); + DesignatedEndIndex.setIsUnsigned(true); + } + + // Make sure that our non-designated initializer list has space + // for a subobject corresponding to this array element. + if (!VerifyOnly && + DesignatedEndIndex.getZExtValue() >= StructuredList->getNumInits()) + StructuredList->resizeInits(SemaRef.Context, + DesignatedEndIndex.getZExtValue() + 1); + + // Repeatedly perform subobject initializations in the range + // [DesignatedStartIndex, DesignatedEndIndex]. + + // Move to the next designator + unsigned ElementIndex = DesignatedStartIndex.getZExtValue(); + unsigned OldIndex = Index; + + InitializedEntity ElementEntity = + InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity); + + while (DesignatedStartIndex <= DesignatedEndIndex) { + // Recurse to check later designated subobjects. + QualType ElementType = AT->getElementType(); + Index = OldIndex; + + ElementEntity.setElementIndex(ElementIndex); + if (CheckDesignatedInitializer(ElementEntity, IList, DIE, DesigIdx + 1, + ElementType, 0, 0, Index, + StructuredList, ElementIndex, + (DesignatedStartIndex == DesignatedEndIndex), + false)) + return true; + + // Move to the next index in the array that we'll be initializing. + ++DesignatedStartIndex; + ElementIndex = DesignatedStartIndex.getZExtValue(); + } + + // If this the first designator, our caller will continue checking + // the rest of this array subobject. + if (IsFirstDesignator) { + if (NextElementIndex) + *NextElementIndex = DesignatedStartIndex; + StructuredIndex = ElementIndex; + return false; + } + + if (!FinishSubobjectInit) + return false; + + // Check the remaining elements within this array subobject. + bool prevHadError = hadError; + CheckArrayType(Entity, IList, CurrentObjectType, DesignatedStartIndex, + /*SubobjectIsDesignatorContext=*/false, Index, + StructuredList, ElementIndex); + return hadError && !prevHadError; +} + +// Get the structured initializer list for a subobject of type +// @p CurrentObjectType. +InitListExpr * +InitListChecker::getStructuredSubobjectInit(InitListExpr *IList, unsigned Index, + QualType CurrentObjectType, + InitListExpr *StructuredList, + unsigned StructuredIndex, + SourceRange InitRange) { + if (VerifyOnly) + return 0; // No structured list in verification-only mode. + Expr *ExistingInit = 0; + if (!StructuredList) + ExistingInit = SyntacticToSemantic.lookup(IList); + else if (StructuredIndex < StructuredList->getNumInits()) + ExistingInit = StructuredList->getInit(StructuredIndex); + + if (InitListExpr *Result = dyn_cast_or_null(ExistingInit)) + return Result; + + if (ExistingInit) { + // We are creating an initializer list that initializes the + // subobjects of the current object, but there was already an + // initialization that completely initialized the current + // subobject, e.g., by a compound literal: + // + // struct X { int a, b; }; + // struct X xs[] = { [0] = (struct X) { 1, 2 }, [0].b = 3 }; + // + // Here, xs[0].a == 0 and xs[0].b == 3, since the second, + // designated initializer re-initializes the whole + // subobject [0], overwriting previous initializers. + SemaRef.Diag(InitRange.getBegin(), + diag::warn_subobject_initializer_overrides) + << InitRange; + SemaRef.Diag(ExistingInit->getLocStart(), + diag::note_previous_initializer) + << /*FIXME:has side effects=*/0 + << ExistingInit->getSourceRange(); + } + + InitListExpr *Result + = new (SemaRef.Context) InitListExpr(SemaRef.Context, + InitRange.getBegin(), 0, 0, + InitRange.getEnd()); + + QualType ResultType = CurrentObjectType; + if (!ResultType->isArrayType()) + ResultType = ResultType.getNonLValueExprType(SemaRef.Context); + Result->setType(ResultType); + + // Pre-allocate storage for the structured initializer list. + unsigned NumElements = 0; + unsigned NumInits = 0; + bool GotNumInits = false; + if (!StructuredList) { + NumInits = IList->getNumInits(); + GotNumInits = true; + } else if (Index < IList->getNumInits()) { + if (InitListExpr *SubList = dyn_cast(IList->getInit(Index))) { + NumInits = SubList->getNumInits(); + GotNumInits = true; + } + } + + if (const ArrayType *AType + = SemaRef.Context.getAsArrayType(CurrentObjectType)) { + if (const ConstantArrayType *CAType = dyn_cast(AType)) { + NumElements = CAType->getSize().getZExtValue(); + // Simple heuristic so that we don't allocate a very large + // initializer with many empty entries at the end. + if (GotNumInits && NumElements > NumInits) + NumElements = 0; + } + } else if (const VectorType *VType = CurrentObjectType->getAs()) + NumElements = VType->getNumElements(); + else if (const RecordType *RType = CurrentObjectType->getAs()) { + RecordDecl *RDecl = RType->getDecl(); + if (RDecl->isUnion()) + NumElements = 1; + else + NumElements = std::distance(RDecl->field_begin(), + RDecl->field_end()); + } + + Result->reserveInits(SemaRef.Context, NumElements); + + // Link this new initializer list into the structured initializer + // lists. + if (StructuredList) + StructuredList->updateInit(SemaRef.Context, StructuredIndex, Result); + else { + Result->setSyntacticForm(IList); + SyntacticToSemantic[IList] = Result; + } + + return Result; +} + +/// Update the initializer at index @p StructuredIndex within the +/// structured initializer list to the value @p expr. +void InitListChecker::UpdateStructuredListElement(InitListExpr *StructuredList, + unsigned &StructuredIndex, + Expr *expr) { + // No structured initializer list to update + if (!StructuredList) + return; + + if (Expr *PrevInit = StructuredList->updateInit(SemaRef.Context, + StructuredIndex, expr)) { + // This initializer overwrites a previous initializer. Warn. + SemaRef.Diag(expr->getLocStart(), + diag::warn_initializer_overrides) + << expr->getSourceRange(); + SemaRef.Diag(PrevInit->getLocStart(), + diag::note_previous_initializer) + << /*FIXME:has side effects=*/0 + << PrevInit->getSourceRange(); + } + + ++StructuredIndex; +} + +/// Check that the given Index expression is a valid array designator +/// value. This is essentially just a wrapper around +/// VerifyIntegerConstantExpression that also checks for negative values +/// and produces a reasonable diagnostic if there is a +/// failure. Returns the index expression, possibly with an implicit cast +/// added, on success. If everything went okay, Value will receive the +/// value of the constant expression. +static ExprResult +CheckArrayDesignatorExpr(Sema &S, Expr *Index, llvm::APSInt &Value) { + SourceLocation Loc = Index->getLocStart(); + + // Make sure this is an integer constant expression. + ExprResult Result = S.VerifyIntegerConstantExpression(Index, &Value); + if (Result.isInvalid()) + return Result; + + if (Value.isSigned() && Value.isNegative()) + return S.Diag(Loc, diag::err_array_designator_negative) + << Value.toString(10) << Index->getSourceRange(); + + Value.setIsUnsigned(true); + return Result; +} + +ExprResult Sema::ActOnDesignatedInitializer(Designation &Desig, + SourceLocation Loc, + bool GNUSyntax, + ExprResult Init) { + typedef DesignatedInitExpr::Designator ASTDesignator; + + bool Invalid = false; + SmallVector Designators; + SmallVector InitExpressions; + + // Build designators and check array designator expressions. + for (unsigned Idx = 0; Idx < Desig.getNumDesignators(); ++Idx) { + const Designator &D = Desig.getDesignator(Idx); + switch (D.getKind()) { + case Designator::FieldDesignator: + Designators.push_back(ASTDesignator(D.getField(), D.getDotLoc(), + D.getFieldLoc())); + break; + + case Designator::ArrayDesignator: { + Expr *Index = static_cast(D.getArrayIndex()); + llvm::APSInt IndexValue; + if (!Index->isTypeDependent() && !Index->isValueDependent()) + Index = CheckArrayDesignatorExpr(*this, Index, IndexValue).take(); + if (!Index) + Invalid = true; + else { + Designators.push_back(ASTDesignator(InitExpressions.size(), + D.getLBracketLoc(), + D.getRBracketLoc())); + InitExpressions.push_back(Index); + } + break; + } + + case Designator::ArrayRangeDesignator: { + Expr *StartIndex = static_cast(D.getArrayRangeStart()); + Expr *EndIndex = static_cast(D.getArrayRangeEnd()); + llvm::APSInt StartValue; + llvm::APSInt EndValue; + bool StartDependent = StartIndex->isTypeDependent() || + StartIndex->isValueDependent(); + bool EndDependent = EndIndex->isTypeDependent() || + EndIndex->isValueDependent(); + if (!StartDependent) + StartIndex = + CheckArrayDesignatorExpr(*this, StartIndex, StartValue).take(); + if (!EndDependent) + EndIndex = CheckArrayDesignatorExpr(*this, EndIndex, EndValue).take(); + + if (!StartIndex || !EndIndex) + Invalid = true; + else { + // Make sure we're comparing values with the same bit width. + if (StartDependent || EndDependent) { + // Nothing to compute. + } else if (StartValue.getBitWidth() > EndValue.getBitWidth()) + EndValue = EndValue.extend(StartValue.getBitWidth()); + else if (StartValue.getBitWidth() < EndValue.getBitWidth()) + StartValue = StartValue.extend(EndValue.getBitWidth()); + + if (!StartDependent && !EndDependent && EndValue < StartValue) { + Diag(D.getEllipsisLoc(), diag::err_array_designator_empty_range) + << StartValue.toString(10) << EndValue.toString(10) + << StartIndex->getSourceRange() << EndIndex->getSourceRange(); + Invalid = true; + } else { + Designators.push_back(ASTDesignator(InitExpressions.size(), + D.getLBracketLoc(), + D.getEllipsisLoc(), + D.getRBracketLoc())); + InitExpressions.push_back(StartIndex); + InitExpressions.push_back(EndIndex); + } + } + break; + } + } + } + + if (Invalid || Init.isInvalid()) + return ExprError(); + + // Clear out the expressions within the designation. + Desig.ClearExprs(*this); + + DesignatedInitExpr *DIE + = DesignatedInitExpr::Create(Context, + Designators.data(), Designators.size(), + InitExpressions.data(), InitExpressions.size(), + Loc, GNUSyntax, Init.takeAs()); + + if (!getLangOpts().C99) + Diag(DIE->getLocStart(), diag::ext_designated_init) + << DIE->getSourceRange(); + + return Owned(DIE); +} + +//===----------------------------------------------------------------------===// +// Initialization entity +//===----------------------------------------------------------------------===// + +InitializedEntity::InitializedEntity(ASTContext &Context, unsigned Index, + const InitializedEntity &Parent) + : Parent(&Parent), Index(Index) +{ + if (const ArrayType *AT = Context.getAsArrayType(Parent.getType())) { + Kind = EK_ArrayElement; + Type = AT->getElementType(); + } else if (const VectorType *VT = Parent.getType()->getAs()) { + Kind = EK_VectorElement; + Type = VT->getElementType(); + } else { + const ComplexType *CT = Parent.getType()->getAs(); + assert(CT && "Unexpected type"); + Kind = EK_ComplexElement; + Type = CT->getElementType(); + } +} + +InitializedEntity InitializedEntity::InitializeBase(ASTContext &Context, + CXXBaseSpecifier *Base, + bool IsInheritedVirtualBase) +{ + InitializedEntity Result; + Result.Kind = EK_Base; + Result.Base = reinterpret_cast(Base); + if (IsInheritedVirtualBase) + Result.Base |= 0x01; + + Result.Type = Base->getType(); + return Result; +} + +DeclarationName InitializedEntity::getName() const { + switch (getKind()) { + case EK_Parameter: { + ParmVarDecl *D = reinterpret_cast(Parameter & ~0x1); + return (D ? D->getDeclName() : DeclarationName()); + } + + case EK_Variable: + case EK_Member: + return VariableOrMember->getDeclName(); + + case EK_LambdaCapture: + return Capture.Var->getDeclName(); + + case EK_Result: + case EK_Exception: + case EK_New: + case EK_Temporary: + case EK_Base: + case EK_Delegating: + case EK_ArrayElement: + case EK_VectorElement: + case EK_ComplexElement: + case EK_BlockElement: + return DeclarationName(); + } + + llvm_unreachable("Invalid EntityKind!"); +} + +DeclaratorDecl *InitializedEntity::getDecl() const { + switch (getKind()) { + case EK_Variable: + case EK_Member: + return VariableOrMember; + + case EK_Parameter: + return reinterpret_cast(Parameter & ~0x1); + + case EK_Result: + case EK_Exception: + case EK_New: + case EK_Temporary: + case EK_Base: + case EK_Delegating: + case EK_ArrayElement: + case EK_VectorElement: + case EK_ComplexElement: + case EK_BlockElement: + case EK_LambdaCapture: + return 0; + } + + llvm_unreachable("Invalid EntityKind!"); +} + +bool InitializedEntity::allowsNRVO() const { + switch (getKind()) { + case EK_Result: + case EK_Exception: + return LocAndNRVO.NRVO; + + case EK_Variable: + case EK_Parameter: + case EK_Member: + case EK_New: + case EK_Temporary: + case EK_Base: + case EK_Delegating: + case EK_ArrayElement: + case EK_VectorElement: + case EK_ComplexElement: + case EK_BlockElement: + case EK_LambdaCapture: + break; + } + + return false; +} + +//===----------------------------------------------------------------------===// +// Initialization sequence +//===----------------------------------------------------------------------===// + +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_ListConstructorCall: + case SK_UnwrapInitList: + case SK_RewrapInitList: + case SK_ConstructorInitialization: + case SK_ZeroInitialization: + case SK_CAssignment: + case SK_StringInit: + case SK_ObjCObjectConversion: + case SK_ArrayInit: + case SK_ParenthesizedArrayInit: + case SK_PassByIndirectCopyRestore: + case SK_PassByIndirectRestore: + case SK_ProduceObjCObject: + case SK_StdInitializerList: + break; + + case SK_ConversionSequence: + delete ICS; + } +} + +bool InitializationSequence::isDirectReferenceBinding() const { + return !Steps.empty() && Steps.back().Kind == SK_BindReference; +} + +bool InitializationSequence::isAmbiguous() const { + if (!Failed()) + return false; + + switch (getFailureKind()) { + case FK_TooManyInitsForReference: + case FK_ArrayNeedsInitList: + case FK_ArrayNeedsInitListOrStringLiteral: + case FK_AddressOfOverloadFailed: // FIXME: Could do better + case FK_NonConstLValueReferenceBindingToTemporary: + case FK_NonConstLValueReferenceBindingToUnrelated: + case FK_RValueReferenceBindingToLValue: + case FK_ReferenceInitDropsQualifiers: + case FK_ReferenceInitFailed: + case FK_ConversionFailed: + case FK_ConversionFromPropertyFailed: + case FK_TooManyInitsForScalar: + case FK_ReferenceBindingToInitList: + case FK_InitListBadDestinationType: + case FK_DefaultInitOfConst: + case FK_Incomplete: + case FK_ArrayTypeMismatch: + case FK_NonConstantArrayInit: + case FK_ListInitializationFailed: + case FK_VariableLengthArrayHasInitializer: + case FK_PlaceholderType: + case FK_InitListElementCopyFailure: + case FK_ExplicitConstructor: + return false; + + case FK_ReferenceInitOverloadFailed: + case FK_UserConversionOverloadFailed: + case FK_ConstructorOverloadFailed: + case FK_ListConstructorOverloadFailed: + return FailedOverloadResult == OR_Ambiguous; + } + + llvm_unreachable("Invalid EntityKind!"); +} + +bool InitializationSequence::isConstructorInitialization() const { + return !Steps.empty() && Steps.back().Kind == SK_ConstructorInitialization; +} + +void +InitializationSequence +::AddAddressOverloadResolutionStep(FunctionDecl *Function, + DeclAccessPair Found, + bool HadMultipleCandidates) { + Step S; + S.Kind = SK_ResolveAddressOfOverloadedFunction; + S.Type = Function->getType(); + S.Function.HadMultipleCandidates = HadMultipleCandidates; + S.Function.Function = Function; + S.Function.FoundDecl = Found; + Steps.push_back(S); +} + +void InitializationSequence::AddDerivedToBaseCastStep(QualType BaseType, + ExprValueKind VK) { + Step S; + 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; + } + S.Type = BaseType; + Steps.push_back(S); +} + +void InitializationSequence::AddReferenceBindingStep(QualType T, + bool BindingTemporary) { + Step S; + S.Kind = BindingTemporary? SK_BindReferenceToTemporary : SK_BindReference; + S.Type = T; + Steps.push_back(S); +} + +void InitializationSequence::AddExtraneousCopyToTemporary(QualType T) { + Step S; + S.Kind = SK_ExtraneousCopyToTemporary; + S.Type = T; + Steps.push_back(S); +} + +void +InitializationSequence::AddUserConversionStep(FunctionDecl *Function, + DeclAccessPair FoundDecl, + QualType T, + bool HadMultipleCandidates) { + Step S; + S.Kind = SK_UserConversion; + S.Type = T; + S.Function.HadMultipleCandidates = HadMultipleCandidates; + S.Function.Function = Function; + S.Function.FoundDecl = FoundDecl; + Steps.push_back(S); +} + +void InitializationSequence::AddQualificationConversionStep(QualType Ty, + ExprValueKind VK) { + Step S; + 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); +} + +void InitializationSequence::AddConversionSequenceStep( + const ImplicitConversionSequence &ICS, + QualType T) { + Step S; + S.Kind = SK_ConversionSequence; + S.Type = T; + S.ICS = new ImplicitConversionSequence(ICS); + Steps.push_back(S); +} + +void InitializationSequence::AddListInitializationStep(QualType T) { + Step S; + S.Kind = SK_ListInitialization; + S.Type = T; + Steps.push_back(S); +} + +void +InitializationSequence +::AddConstructorInitializationStep(CXXConstructorDecl *Constructor, + AccessSpecifier Access, + QualType T, + bool HadMultipleCandidates, + bool FromInitList, bool AsInitList) { + Step S; + S.Kind = FromInitList && !AsInitList ? SK_ListConstructorCall + : SK_ConstructorInitialization; + S.Type = T; + S.Function.HadMultipleCandidates = HadMultipleCandidates; + S.Function.Function = Constructor; + S.Function.FoundDecl = DeclAccessPair::make(Constructor, Access); + Steps.push_back(S); +} + +void InitializationSequence::AddZeroInitializationStep(QualType T) { + Step S; + S.Kind = SK_ZeroInitialization; + S.Type = T; + Steps.push_back(S); +} + +void InitializationSequence::AddCAssignmentStep(QualType T) { + Step S; + S.Kind = SK_CAssignment; + S.Type = T; + Steps.push_back(S); +} + +void InitializationSequence::AddStringInitStep(QualType T) { + Step S; + S.Kind = SK_StringInit; + S.Type = 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::AddArrayInitStep(QualType T) { + Step S; + S.Kind = SK_ArrayInit; + S.Type = T; + Steps.push_back(S); +} + +void InitializationSequence::AddParenthesizedArrayInitStep(QualType T) { + Step S; + S.Kind = SK_ParenthesizedArrayInit; + S.Type = T; + Steps.push_back(S); +} + +void InitializationSequence::AddPassByIndirectCopyRestoreStep(QualType type, + bool shouldCopy) { + Step s; + s.Kind = (shouldCopy ? SK_PassByIndirectCopyRestore + : SK_PassByIndirectRestore); + s.Type = type; + Steps.push_back(s); +} + +void InitializationSequence::AddProduceObjCObjectStep(QualType T) { + Step S; + S.Kind = SK_ProduceObjCObject; + S.Type = T; + Steps.push_back(S); +} + +void InitializationSequence::AddStdInitializerListConstructionStep(QualType T) { + Step S; + S.Kind = SK_StdInitializerList; + S.Type = T; + Steps.push_back(S); +} + +void InitializationSequence::RewrapReferenceInitList(QualType T, + InitListExpr *Syntactic) { + assert(Syntactic->getNumInits() == 1 && + "Can only rewrap trivial init lists."); + Step S; + S.Kind = SK_UnwrapInitList; + S.Type = Syntactic->getInit(0)->getType(); + Steps.insert(Steps.begin(), S); + + S.Kind = SK_RewrapInitList; + S.Type = T; + S.WrappingSyntacticList = Syntactic; + Steps.push_back(S); +} + +void InitializationSequence::SetOverloadFailure(FailureKind Failure, + OverloadingResult Result) { + setSequenceKind(FailedSequence); + this->Failure = Failure; + this->FailedOverloadResult = Result; +} + +//===----------------------------------------------------------------------===// +// Attempt initialization +//===----------------------------------------------------------------------===// + +static void MaybeProduceObjCObject(Sema &S, + InitializationSequence &Sequence, + const InitializedEntity &Entity) { + if (!S.getLangOpts().ObjCAutoRefCount) return; + + /// When initializing a parameter, produce the value if it's marked + /// __attribute__((ns_consumed)). + if (Entity.getKind() == InitializedEntity::EK_Parameter) { + if (!Entity.isParameterConsumed()) + return; + + assert(Entity.getType()->isObjCRetainableType() && + "consuming an object of unretainable type?"); + Sequence.AddProduceObjCObjectStep(Entity.getType()); + + /// When initializing a return value, if the return type is a + /// retainable type, then returns need to immediately retain the + /// object. If an autorelease is required, it will be done at the + /// last instant. + } else if (Entity.getKind() == InitializedEntity::EK_Result) { + if (!Entity.getType()->isObjCRetainableType()) + return; + + Sequence.AddProduceObjCObjectStep(Entity.getType()); + } +} + +/// \brief When initializing from init list via constructor, deal with the +/// empty init list and std::initializer_list special cases. +/// +/// \return True if this was a special case, false otherwise. +static bool TryListConstructionSpecialCases(Sema &S, + InitListExpr *List, + CXXRecordDecl *DestRecordDecl, + QualType DestType, + InitializationSequence &Sequence) { + // C++11 [dcl.init.list]p3: + // List-initialization of an object or reference of type T is defined as + // follows: + // - If T is an aggregate, aggregate initialization is performed. + if (DestType->isAggregateType()) + return false; + + // - Otherwise, if the initializer list has no elements and T is a class + // type with a default constructor, the object is value-initialized. + if (List->getNumInits() == 0) { + if (CXXConstructorDecl *DefaultConstructor = + S.LookupDefaultConstructor(DestRecordDecl)) { + if (DefaultConstructor->isDeleted() || + S.isFunctionConsideredUnavailable(DefaultConstructor)) { + // Fake an overload resolution failure. + OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet(); + DeclAccessPair FoundDecl = DeclAccessPair::make(DefaultConstructor, + DefaultConstructor->getAccess()); + if (FunctionTemplateDecl *ConstructorTmpl = + dyn_cast(DefaultConstructor)) + S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, + /*ExplicitArgs*/ 0, + ArrayRef(), CandidateSet, + /*SuppressUserConversions*/ false); + else + S.AddOverloadCandidate(DefaultConstructor, FoundDecl, + ArrayRef(), CandidateSet, + /*SuppressUserConversions*/ false); + Sequence.SetOverloadFailure( + InitializationSequence::FK_ListConstructorOverloadFailed, + OR_Deleted); + } else + Sequence.AddConstructorInitializationStep(DefaultConstructor, + DefaultConstructor->getAccess(), + DestType, + /*MultipleCandidates=*/false, + /*FromInitList=*/true, + /*AsInitList=*/false); + return true; + } + } + + // - Otherwise, if T is a specialization of std::initializer_list, [...] + QualType E; + if (S.isStdInitializerList(DestType, &E)) { + // Check that each individual element can be copy-constructed. But since we + // have no place to store further information, we'll recalculate everything + // later. + InitializedEntity HiddenArray = InitializedEntity::InitializeTemporary( + S.Context.getConstantArrayType(E, + llvm::APInt(S.Context.getTypeSize(S.Context.getSizeType()), + List->getNumInits()), + ArrayType::Normal, 0)); + InitializedEntity Element = InitializedEntity::InitializeElement(S.Context, + 0, HiddenArray); + for (unsigned i = 0, n = List->getNumInits(); i < n; ++i) { + Element.setElementIndex(i); + if (!S.CanPerformCopyInitialization(Element, List->getInit(i))) { + Sequence.SetFailed( + InitializationSequence::FK_InitListElementCopyFailure); + return true; + } + } + Sequence.AddStdInitializerListConstructionStep(DestType); + return true; + } + + // Not a special case. + return false; +} + +static OverloadingResult +ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc, + Expr **Args, unsigned NumArgs, + OverloadCandidateSet &CandidateSet, + DeclContext::lookup_iterator Con, + DeclContext::lookup_iterator ConEnd, + OverloadCandidateSet::iterator &Best, + bool CopyInitializing, bool AllowExplicit, + bool OnlyListConstructors, bool InitListSyntax) { + CandidateSet.clear(); + + for (; Con != ConEnd; ++Con) { + NamedDecl *D = *Con; + DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess()); + bool SuppressUserConversions = false; + + // Find the constructor (which may be a template). + CXXConstructorDecl *Constructor = 0; + FunctionTemplateDecl *ConstructorTmpl = dyn_cast(D); + if (ConstructorTmpl) + Constructor = cast( + ConstructorTmpl->getTemplatedDecl()); + else { + Constructor = cast(D); + + // If we're performing copy initialization using a copy constructor, we + // suppress user-defined conversions on the arguments. We do the same for + // move constructors. + if ((CopyInitializing || (InitListSyntax && NumArgs == 1)) && + Constructor->isCopyOrMoveConstructor()) + SuppressUserConversions = true; + } + + if (!Constructor->isInvalidDecl() && + (AllowExplicit || !Constructor->isExplicit()) && + (!OnlyListConstructors || S.isInitListConstructor(Constructor))) { + if (ConstructorTmpl) + S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, + /*ExplicitArgs*/ 0, + llvm::makeArrayRef(Args, NumArgs), + CandidateSet, SuppressUserConversions); + else { + // C++ [over.match.copy]p1: + // - When initializing a temporary to be bound to the first parameter + // of a constructor that takes a reference to possibly cv-qualified + // T as its first argument, called with a single argument in the + // context of direct-initialization, explicit conversion functions + // are also considered. + bool AllowExplicitConv = AllowExplicit && !CopyInitializing && + NumArgs == 1 && + Constructor->isCopyOrMoveConstructor(); + S.AddOverloadCandidate(Constructor, FoundDecl, + llvm::makeArrayRef(Args, NumArgs), CandidateSet, + SuppressUserConversions, + /*PartialOverloading=*/false, + /*AllowExplicit=*/AllowExplicitConv); + } + } + } + + // Perform overload resolution and return the result. + return CandidateSet.BestViableFunction(S, DeclLoc, Best); +} + +/// \brief Attempt initialization by constructor (C++ [dcl.init]), which +/// enumerates the constructors of the initialized entity and performs overload +/// resolution to select the best. +/// If InitListSyntax is true, this is list-initialization of a non-aggregate +/// class type. +static void TryConstructorInitialization(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + Expr **Args, unsigned NumArgs, + QualType DestType, + InitializationSequence &Sequence, + bool InitListSyntax = false) { + assert((!InitListSyntax || (NumArgs == 1 && isa(Args[0]))) && + "InitListSyntax must come with a single initializer list argument."); + + // Check constructor arguments for self reference. + if (DeclaratorDecl *DD = Entity.getDecl()) + // Parameters arguments are occassionially constructed with itself, + // for instance, in recursive functions. Skip them. + if (!isa(DD)) + for (unsigned i = 0; i < NumArgs; ++i) + S.CheckSelfReference(DD, Args[i]); + + // The type we're constructing needs to be complete. + if (S.RequireCompleteType(Kind.getLocation(), DestType, 0)) { + Sequence.setIncompleteTypeFailure(DestType); + return; + } + + const RecordType *DestRecordType = DestType->getAs(); + assert(DestRecordType && "Constructor initialization requires record type"); + CXXRecordDecl *DestRecordDecl + = cast(DestRecordType->getDecl()); + + if (InitListSyntax && + TryListConstructionSpecialCases(S, cast(Args[0]), + DestRecordDecl, DestType, Sequence)) + return; + + // Build the candidate set directly in the initialization sequence + // structure, so that it will persist if we fail. + OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet(); + + // Determine whether we are allowed to call explicit constructors or + // explicit conversion operators. + bool AllowExplicit = Kind.AllowExplicit() || InitListSyntax; + bool CopyInitialization = Kind.getKind() == InitializationKind::IK_Copy; + + // - Otherwise, if T is a class type, constructors are considered. The + // applicable constructors are enumerated, and the best one is chosen + // through overload resolution. + DeclContext::lookup_iterator ConStart, ConEnd; + llvm::tie(ConStart, ConEnd) = S.LookupConstructors(DestRecordDecl); + + OverloadingResult Result = OR_No_Viable_Function; + OverloadCandidateSet::iterator Best; + bool AsInitializerList = false; + + // C++11 [over.match.list]p1: + // When objects of non-aggregate type T are list-initialized, overload + // resolution selects the constructor in two phases: + // - Initially, the candidate functions are the initializer-list + // constructors of the class T and the argument list consists of the + // initializer list as a single argument. + if (InitListSyntax) { + AsInitializerList = true; + Result = ResolveConstructorOverload(S, Kind.getLocation(), Args, NumArgs, + CandidateSet, ConStart, ConEnd, Best, + CopyInitialization, AllowExplicit, + /*OnlyListConstructor=*/true, + InitListSyntax); + + // Time to unwrap the init list. + InitListExpr *ILE = cast(Args[0]); + Args = ILE->getInits(); + NumArgs = ILE->getNumInits(); + } + + // C++11 [over.match.list]p1: + // - If no viable initializer-list constructor is found, overload resolution + // is performed again, where the candidate functions are all the + // constructors of the class T nad the argument list consists of the + // elements of the initializer list. + if (Result == OR_No_Viable_Function) { + AsInitializerList = false; + Result = ResolveConstructorOverload(S, Kind.getLocation(), Args, NumArgs, + CandidateSet, ConStart, ConEnd, Best, + CopyInitialization, AllowExplicit, + /*OnlyListConstructors=*/false, + InitListSyntax); + } + if (Result) { + Sequence.SetOverloadFailure(InitListSyntax ? + InitializationSequence::FK_ListConstructorOverloadFailed : + InitializationSequence::FK_ConstructorOverloadFailed, + Result); + return; + } + + // C++0x [dcl.init]p6: + // If a program calls for the default initialization of an object + // of a const-qualified type T, T shall be a class type with a + // user-provided default constructor. + if (Kind.getKind() == InitializationKind::IK_Default && + Entity.getType().isConstQualified() && + cast(Best->Function)->isImplicit()) { + Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst); + return; + } + + // C++11 [over.match.list]p1: + // In copy-list-initialization, if an explicit constructor is chosen, the + // initializer is ill-formed. + CXXConstructorDecl *CtorDecl = cast(Best->Function); + if (InitListSyntax && !Kind.AllowExplicit() && CtorDecl->isExplicit()) { + Sequence.SetFailed(InitializationSequence::FK_ExplicitConstructor); + return; + } + + // Add the constructor initialization step. Any cv-qualification conversion is + // subsumed by the initialization. + bool HadMultipleCandidates = (CandidateSet.size() > 1); + Sequence.AddConstructorInitializationStep(CtorDecl, + Best->FoundDecl.getAccess(), + DestType, HadMultipleCandidates, + InitListSyntax, AsInitializerList); +} + +static bool +ResolveOverloadedFunctionForReferenceBinding(Sema &S, + Expr *Initializer, + QualType &SourceType, + QualType &UnqualifiedSourceType, + QualType UnqualifiedTargetType, + InitializationSequence &Sequence) { + if (S.Context.getCanonicalType(UnqualifiedSourceType) == + S.Context.OverloadTy) { + DeclAccessPair Found; + bool HadMultipleCandidates = false; + if (FunctionDecl *Fn + = S.ResolveAddressOfOverloadedFunction(Initializer, + UnqualifiedTargetType, + false, Found, + &HadMultipleCandidates)) { + Sequence.AddAddressOverloadResolutionStep(Fn, Found, + HadMultipleCandidates); + SourceType = Fn->getType(); + UnqualifiedSourceType = SourceType.getUnqualifiedType(); + } else if (!UnqualifiedTargetType->isRecordType()) { + Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed); + return true; + } + } + return false; +} + +static void TryReferenceInitializationCore(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + Expr *Initializer, + QualType cv1T1, QualType T1, + Qualifiers T1Quals, + QualType cv2T2, QualType T2, + Qualifiers T2Quals, + InitializationSequence &Sequence); + +static void TryListInitialization(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + InitListExpr *InitList, + InitializationSequence &Sequence); + +/// \brief Attempt list initialization of a reference. +static void TryReferenceListInitialization(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + InitListExpr *InitList, + InitializationSequence &Sequence) +{ + // First, catch C++03 where this isn't possible. + if (!S.getLangOpts().CPlusPlus0x) { + Sequence.SetFailed(InitializationSequence::FK_ReferenceBindingToInitList); + return; + } + + QualType DestType = Entity.getType(); + QualType cv1T1 = DestType->getAs()->getPointeeType(); + Qualifiers T1Quals; + QualType T1 = S.Context.getUnqualifiedArrayType(cv1T1, T1Quals); + + // Reference initialization via an initializer list works thus: + // If the initializer list consists of a single element that is + // reference-related to the referenced type, bind directly to that element + // (possibly creating temporaries). + // Otherwise, initialize a temporary with the initializer list and + // bind to that. + if (InitList->getNumInits() == 1) { + Expr *Initializer = InitList->getInit(0); + QualType cv2T2 = Initializer->getType(); + Qualifiers T2Quals; + QualType T2 = S.Context.getUnqualifiedArrayType(cv2T2, T2Quals); + + // If this fails, creating a temporary wouldn't work either. + if (ResolveOverloadedFunctionForReferenceBinding(S, Initializer, cv2T2, T2, + T1, Sequence)) + return; + + SourceLocation DeclLoc = Initializer->getLocStart(); + bool dummy1, dummy2, dummy3; + Sema::ReferenceCompareResult RefRelationship + = S.CompareReferenceRelationship(DeclLoc, cv1T1, cv2T2, dummy1, + dummy2, dummy3); + if (RefRelationship >= Sema::Ref_Related) { + // Try to bind the reference here. + TryReferenceInitializationCore(S, Entity, Kind, Initializer, cv1T1, T1, + T1Quals, cv2T2, T2, T2Quals, Sequence); + if (Sequence) + Sequence.RewrapReferenceInitList(cv1T1, InitList); + return; + } + } + + // Not reference-related. Create a temporary and bind to that. + InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(cv1T1); + + TryListInitialization(S, TempEntity, Kind, InitList, Sequence); + if (Sequence) { + if (DestType->isRValueReferenceType() || + (T1Quals.hasConst() && !T1Quals.hasVolatile())) + Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/true); + else + Sequence.SetFailed( + InitializationSequence::FK_NonConstLValueReferenceBindingToTemporary); + } +} + +/// \brief Attempt list initialization (C++0x [dcl.init.list]) +static void TryListInitialization(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + InitListExpr *InitList, + InitializationSequence &Sequence) { + QualType DestType = Entity.getType(); + + // C++ doesn't allow scalar initialization with more than one argument. + // But C99 complex numbers are scalars and it makes sense there. + if (S.getLangOpts().CPlusPlus && DestType->isScalarType() && + !DestType->isAnyComplexType() && InitList->getNumInits() > 1) { + Sequence.SetFailed(InitializationSequence::FK_TooManyInitsForScalar); + return; + } + if (DestType->isReferenceType()) { + TryReferenceListInitialization(S, Entity, Kind, InitList, Sequence); + return; + } + if (DestType->isRecordType()) { + if (S.RequireCompleteType(InitList->getLocStart(), DestType, S.PDiag())) { + Sequence.setIncompleteTypeFailure(DestType); + return; + } + + if (!DestType->isAggregateType()) { + if (S.getLangOpts().CPlusPlus0x) { + Expr *Arg = InitList; + // A direct-initializer is not list-syntax, i.e. there's no special + // treatment of "A a({1, 2});". + TryConstructorInitialization(S, Entity, Kind, &Arg, 1, DestType, + Sequence, + Kind.getKind() != InitializationKind::IK_Direct); + } else + Sequence.SetFailed( + InitializationSequence::FK_InitListBadDestinationType); + return; + } + } + + InitListChecker CheckInitList(S, Entity, InitList, + DestType, /*VerifyOnly=*/true, + Kind.getKind() != InitializationKind::IK_DirectList || + !S.getLangOpts().CPlusPlus0x); + if (CheckInitList.HadError()) { + Sequence.SetFailed(InitializationSequence::FK_ListInitializationFailed); + return; + } + + // Add the list initialization step with the built init list. + Sequence.AddListInitializationStep(DestType); +} + +/// \brief Try a reference initialization that involves calling a conversion +/// function. +static OverloadingResult TryRefInitWithConversionFunction(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + Expr *Initializer, + bool AllowRValues, + InitializationSequence &Sequence) { + QualType DestType = Entity.getType(); + QualType cv1T1 = DestType->getAs()->getPointeeType(); + QualType T1 = cv1T1.getUnqualifiedType(); + QualType cv2T2 = Initializer->getType(); + QualType T2 = cv2T2.getUnqualifiedType(); + + bool DerivedToBase; + bool ObjCConversion; + bool ObjCLifetimeConversion; + assert(!S.CompareReferenceRelationship(Initializer->getLocStart(), + T1, T2, DerivedToBase, + ObjCConversion, + ObjCLifetimeConversion) && + "Must have incompatible references when binding via conversion"); + (void)DerivedToBase; + (void)ObjCConversion; + (void)ObjCLifetimeConversion; + + // Build the candidate set directly in the initialization sequence + // structure, so that it will persist if we fail. + OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet(); + CandidateSet.clear(); + + // Determine whether we are allowed to call explicit constructors or + // explicit conversion operators. + bool AllowExplicit = Kind.AllowExplicit(); + bool AllowExplicitConvs = Kind.allowExplicitConversionFunctions(); + + const RecordType *T1RecordType = 0; + if (AllowRValues && (T1RecordType = T1->getAs()) && + !S.RequireCompleteType(Kind.getLocation(), T1, 0)) { + // 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) { + NamedDecl *D = *Con; + DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess()); + + // Find the constructor (which may be a template). + CXXConstructorDecl *Constructor = 0; + FunctionTemplateDecl *ConstructorTmpl = dyn_cast(D); + if (ConstructorTmpl) + Constructor = cast( + ConstructorTmpl->getTemplatedDecl()); + else + Constructor = cast(D); + + if (!Constructor->isInvalidDecl() && + Constructor->isConvertingConstructor(AllowExplicit)) { + if (ConstructorTmpl) + S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, + /*ExplicitArgs*/ 0, + Initializer, CandidateSet, + /*SuppressUserConversions=*/true); + else + S.AddOverloadCandidate(Constructor, FoundDecl, + Initializer, CandidateSet, + /*SuppressUserConversions=*/true); + } + } + } + if (T1RecordType && T1RecordType->getDecl()->isInvalidDecl()) + return OR_No_Viable_Function; + + const RecordType *T2RecordType = 0; + if ((T2RecordType = T2->getAs()) && + !S.RequireCompleteType(Kind.getLocation(), T2, 0)) { + // The type we're converting from is a class type, enumerate its conversion + // functions. + CXXRecordDecl *T2RecordDecl = cast(T2RecordType->getDecl()); + + const UnresolvedSetImpl *Conversions + = T2RecordDecl->getVisibleConversionFunctions(); + for (UnresolvedSetImpl::const_iterator I = Conversions->begin(), + E = Conversions->end(); I != E; ++I) { + NamedDecl *D = *I; + CXXRecordDecl *ActingDC = cast(D->getDeclContext()); + if (isa(D)) + D = cast(D)->getTargetDecl(); + + FunctionTemplateDecl *ConvTemplate = dyn_cast(D); + CXXConversionDecl *Conv; + if (ConvTemplate) + Conv = cast(ConvTemplate->getTemplatedDecl()); + else + Conv = cast(D); + + // If the conversion function doesn't return a reference type, + // it can't be considered for this conversion unless we're allowed to + // consider rvalues. + // FIXME: Do we need to make sure that we only consider conversion + // candidates with reference-compatible results? That might be needed to + // break recursion. + if ((AllowExplicitConvs || !Conv->isExplicit()) && + (AllowRValues || Conv->getConversionType()->isLValueReferenceType())){ + if (ConvTemplate) + S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(), + ActingDC, Initializer, + DestType, CandidateSet); + else + S.AddConversionCandidate(Conv, I.getPair(), ActingDC, + Initializer, DestType, CandidateSet); + } + } + } + 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 + = CandidateSet.BestViableFunction(S, DeclLoc, Best, true)) + return Result; + + FunctionDecl *Function = Best->Function; + + // This is the overload that will actually be used for the initialization, so + // mark it as used. + S.MarkFunctionReferenced(DeclLoc, Function); + + // Compute the returned type of the conversion. + if (isa(Function)) + T2 = Function->getResultType(); + else + T2 = cv1T1; + + // Add the user-defined conversion step. + bool HadMultipleCandidates = (CandidateSet.size() > 1); + Sequence.AddUserConversionStep(Function, Best->FoundDecl, + T2.getNonLValueExprType(S.Context), + HadMultipleCandidates); + + // 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; + bool NewObjCLifetimeConversion = false; + Sema::ReferenceCompareResult NewRefRelationship + = S.CompareReferenceRelationship(DeclLoc, T1, + T2.getNonLValueExprType(S.Context), + NewDerivedToBase, NewObjCConversion, + NewObjCLifetimeConversion); + 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 + // we need to perform to produce a temporary of the right type + // that we'll be binding to. + ImplicitConversionSequence ICS; + ICS.setStandard(); + ICS.Standard = Best->FinalConversion; + T2 = ICS.Standard.getToType(2); + Sequence.AddConversionSequenceStep(ICS, T2); + } else if (NewDerivedToBase) + Sequence.AddDerivedToBaseCastStep( + S.Context.getQualifiedType(T1, + T2.getNonReferenceType().getQualifiers()), + VK); + else if (NewObjCConversion) + Sequence.AddObjCObjectConversionStep( + S.Context.getQualifiedType(T1, + T2.getNonReferenceType().getQualifiers())); + + if (cv1T1.getQualifiers() != T2.getNonReferenceType().getQualifiers()) + Sequence.AddQualificationConversionStep(cv1T1, VK); + + Sequence.AddReferenceBindingStep(cv1T1, !T2->isReferenceType()); + return OR_Success; +} + +static void CheckCXX98CompatAccessibleCopy(Sema &S, + const InitializedEntity &Entity, + Expr *CurInitExpr); + +/// \brief Attempt reference initialization (C++0x [dcl.init.ref]) +static void TryReferenceInitialization(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + Expr *Initializer, + InitializationSequence &Sequence) { + QualType DestType = Entity.getType(); + QualType cv1T1 = DestType->getAs()->getPointeeType(); + Qualifiers T1Quals; + QualType T1 = S.Context.getUnqualifiedArrayType(cv1T1, T1Quals); + QualType cv2T2 = Initializer->getType(); + Qualifiers T2Quals; + QualType T2 = S.Context.getUnqualifiedArrayType(cv2T2, T2Quals); + + // If the initializer is the address of an overloaded function, try + // to resolve the overloaded function. If all goes well, T2 is the + // type of the resulting function. + if (ResolveOverloadedFunctionForReferenceBinding(S, Initializer, cv2T2, T2, + T1, Sequence)) + return; + + // Delegate everything else to a subfunction. + TryReferenceInitializationCore(S, Entity, Kind, Initializer, cv1T1, T1, + T1Quals, cv2T2, T2, T2Quals, Sequence); +} + +/// \brief Reference initialization without resolving overloaded functions. +static void TryReferenceInitializationCore(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + Expr *Initializer, + QualType cv1T1, QualType T1, + Qualifiers T1Quals, + QualType cv2T2, QualType T2, + Qualifiers T2Quals, + InitializationSequence &Sequence) { + QualType DestType = Entity.getType(); + SourceLocation DeclLoc = Initializer->getLocStart(); + // Compute some basic properties of the types and the initializer. + bool isLValueRef = DestType->isLValueReferenceType(); + bool isRValueRef = !isLValueRef; + bool DerivedToBase = false; + bool ObjCConversion = false; + bool ObjCLifetimeConversion = false; + Expr::Classification InitCategory = Initializer->Classify(S.Context); + Sema::ReferenceCompareResult RefRelationship + = S.CompareReferenceRelationship(DeclLoc, cv1T1, cv2T2, DerivedToBase, + ObjCConversion, ObjCLifetimeConversion); + + // C++0x [dcl.init.ref]p5: + // A reference to type "cv1 T1" is initialized by an expression of type + // "cv2 T2" as follows: + // + // - If the reference is an lvalue reference and the initializer + // expression + // Note the analogous bullet points for rvlaue refs to functions. Because + // there are no function rvalues in C++, rvalue refs to functions are treated + // like lvalue refs. + OverloadingResult ConvOvlResult = OR_Success; + bool T1Function = T1->isFunctionType(); + if (isLValueRef || T1Function) { + if (InitCategory.isLValue() && + (RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification || + (Kind.isCStyleOrFunctionalCast() && + RefRelationship == Sema::Ref_Related))) { + // - is an lvalue (but is not a bit-field), and "cv1 T1" is + // reference-compatible with "cv2 T2," or + // + // Per C++ [over.best.ics]p2, we don't diagnose whether the lvalue is a + // bit-field when we're determining whether the reference initialization + // can occur. However, we do pay attention to whether it is a bit-field + // to decide whether we're actually binding to a temporary created from + // the bit-field. + if (DerivedToBase) + Sequence.AddDerivedToBaseCastStep( + S.Context.getQualifiedType(T1, T2Quals), + VK_LValue); + else if (ObjCConversion) + Sequence.AddObjCObjectConversionStep( + S.Context.getQualifiedType(T1, T2Quals)); + + if (T1Quals != T2Quals) + Sequence.AddQualificationConversionStep(cv1T1, VK_LValue); + bool BindingTemporary = T1Quals.hasConst() && !T1Quals.hasVolatile() && + (Initializer->getBitField() || Initializer->refersToVectorElement()); + Sequence.AddReferenceBindingStep(cv1T1, BindingTemporary); + return; + } + + // - has a class type (i.e., T2 is a class type), where T1 is not + // reference-related to T2, and can be implicitly converted to an + // lvalue of type "cv3 T3," where "cv1 T1" is reference-compatible + // with "cv3 T3" (this conversion is selected by enumerating the + // applicable conversion functions (13.3.1.6) and choosing the best + // one through overload resolution (13.3)), + // If we have an rvalue ref to function type here, the rhs must be + // an rvalue. + if (RefRelationship == Sema::Ref_Incompatible && T2->isRecordType() && + (isLValueRef || InitCategory.isRValue())) { + ConvOvlResult = TryRefInitWithConversionFunction(S, Entity, Kind, + Initializer, + /*AllowRValues=*/isRValueRef, + Sequence); + if (ConvOvlResult == OR_Success) + return; + if (ConvOvlResult != OR_No_Viable_Function) { + Sequence.SetOverloadFailure( + InitializationSequence::FK_ReferenceInitOverloadFailed, + ConvOvlResult); + } + } + } + + // - Otherwise, the reference shall be an lvalue reference to a + // non-volatile const type (i.e., cv1 shall be const), or the reference + // shall be an rvalue reference. + if (isLValueRef && !(T1Quals.hasConst() && !T1Quals.hasVolatile())) { + if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy) + Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed); + else if (ConvOvlResult && !Sequence.getFailedCandidateSet().empty()) + Sequence.SetOverloadFailure( + InitializationSequence::FK_ReferenceInitOverloadFailed, + ConvOvlResult); + else + Sequence.SetFailed(InitCategory.isLValue() + ? (RefRelationship == Sema::Ref_Related + ? InitializationSequence::FK_ReferenceInitDropsQualifiers + : InitializationSequence::FK_NonConstLValueReferenceBindingToUnrelated) + : InitializationSequence::FK_NonConstLValueReferenceBindingToTemporary); + + return; + } + + // - If the initializer expression + // - is an xvalue, class prvalue, array prvalue, or function lvalue and + // "cv1 T1" is reference-compatible with "cv2 T2" + // Note: functions are handled below. + if (!T1Function && + (RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification || + (Kind.isCStyleOrFunctionalCast() && + RefRelationship == Sema::Ref_Related)) && + (InitCategory.isXValue() || + (InitCategory.isPRValue() && T2->isRecordType()) || + (InitCategory.isPRValue() && T2->isArrayType()))) { + ExprValueKind ValueKind = InitCategory.isXValue()? VK_XValue : VK_RValue; + if (InitCategory.isPRValue() && T2->isRecordType()) { + // The corresponding bullet in C++03 [dcl.init.ref]p5 gives the + // compiler the freedom to perform a copy here or bind to the + // object, while C++0x requires that we bind directly to the + // object. Hence, we always bind to the object without making an + // extra copy. However, in C++03 requires that we check for the + // presence of a suitable copy constructor: + // + // The constructor that would be used to make the copy shall + // be callable whether or not the copy is actually done. + if (!S.getLangOpts().CPlusPlus0x && !S.getLangOpts().MicrosoftExt) + Sequence.AddExtraneousCopyToTemporary(cv2T2); + else if (S.getLangOpts().CPlusPlus0x) + CheckCXX98CompatAccessibleCopy(S, Entity, Initializer); + } + + if (DerivedToBase) + Sequence.AddDerivedToBaseCastStep(S.Context.getQualifiedType(T1, T2Quals), + ValueKind); + else if (ObjCConversion) + Sequence.AddObjCObjectConversionStep( + S.Context.getQualifiedType(T1, T2Quals)); + + if (T1Quals != T2Quals) + Sequence.AddQualificationConversionStep(cv1T1, ValueKind); + Sequence.AddReferenceBindingStep(cv1T1, + /*bindingTemporary=*/InitCategory.isPRValue()); + return; + } + + // - has a class type (i.e., T2 is a class type), where T1 is not + // reference-related to T2, and can be implicitly converted to an + // xvalue, class prvalue, or function lvalue of type "cv3 T3", + // where "cv1 T1" is reference-compatible with "cv3 T3", + if (T2->isRecordType()) { + if (RefRelationship == Sema::Ref_Incompatible) { + ConvOvlResult = TryRefInitWithConversionFunction(S, Entity, + Kind, Initializer, + /*AllowRValues=*/true, + Sequence); + if (ConvOvlResult) + Sequence.SetOverloadFailure( + InitializationSequence::FK_ReferenceInitOverloadFailed, + ConvOvlResult); + + return; + } + + Sequence.SetFailed(InitializationSequence::FK_ReferenceInitDropsQualifiers); + return; + } + + // - 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 reference is then bound to the + // temporary. [...] + + // Determine whether we are allowed to call explicit constructors or + // explicit conversion operators. + bool AllowExplicit = Kind.AllowExplicit(); + + InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(cv1T1); + + ImplicitConversionSequence ICS + = S.TryImplicitConversion(Initializer, TempEntity.getType(), + /*SuppressUserConversions*/ false, + AllowExplicit, + /*FIXME:InOverloadResolution=*/false, + /*CStyle=*/Kind.isCStyleOrFunctionalCast(), + /*AllowObjCWritebackConversion=*/false); + + if (ICS.isBad()) { + // FIXME: Use the conversion function set stored in ICS to turn + // this into an overloading ambiguity diagnostic. However, we need + // to keep that set as an OverloadCandidateSet rather than as some + // other kind of set. + if (ConvOvlResult && !Sequence.getFailedCandidateSet().empty()) + Sequence.SetOverloadFailure( + InitializationSequence::FK_ReferenceInitOverloadFailed, + ConvOvlResult); + else if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy) + Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed); + else + Sequence.SetFailed(InitializationSequence::FK_ReferenceInitFailed); + return; + } else { + Sequence.AddConversionSequenceStep(ICS, TempEntity.getType()); + } + + // [...] If T1 is reference-related to T2, cv1 must be the + // same cv-qualification as, or greater cv-qualification + // than, cv2; otherwise, the program is ill-formed. + unsigned T1CVRQuals = T1Quals.getCVRQualifiers(); + unsigned T2CVRQuals = T2Quals.getCVRQualifiers(); + if (RefRelationship == Sema::Ref_Related && + (T1CVRQuals | T2CVRQuals) != T1CVRQuals) { + Sequence.SetFailed(InitializationSequence::FK_ReferenceInitDropsQualifiers); + return; + } + + // [...] If T1 is reference-related to T2 and the reference is an rvalue + // reference, the initializer expression shall not be an lvalue. + if (RefRelationship >= Sema::Ref_Related && !isLValueRef && + InitCategory.isLValue()) { + Sequence.SetFailed( + InitializationSequence::FK_RValueReferenceBindingToLValue); + return; + } + + Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/true); + return; +} + +/// \brief Attempt character array initialization from a string literal +/// (C++ [dcl.init.string], C99 6.7.8). +static void TryStringLiteralInitialization(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + Expr *Initializer, + InitializationSequence &Sequence) { + Sequence.AddStringInitStep(Entity.getType()); +} + +/// \brief Attempt value initialization (C++ [dcl.init]p7). +static void TryValueInitialization(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + InitializationSequence &Sequence) { + // C++98 [dcl.init]p5, C++11 [dcl.init]p7: + // + // To value-initialize an object of type T means: + QualType T = Entity.getType(); + + // -- if T is an array type, then each element is value-initialized; + T = S.Context.getBaseElementType(T); + + if (const RecordType *RT = T->getAs()) { + if (CXXRecordDecl *ClassDecl = dyn_cast(RT->getDecl())) { + // C++98: + // -- if T is a class type (clause 9) with a user-declared + // constructor (12.1), then the default constructor for T is + // called (and the initialization is ill-formed if T has no + // accessible default constructor); + if (!S.getLangOpts().CPlusPlus0x) { + if (ClassDecl->hasUserDeclaredConstructor()) + // FIXME: we really want to refer to a single subobject of the array, + // but Entity doesn't have a way to capture that (yet). + return TryConstructorInitialization(S, Entity, Kind, 0, 0, + T, Sequence); + } else { + // C++11: + // -- if T is a class type (clause 9) with either no default constructor + // (12.1 [class.ctor]) or a default constructor that is user-provided + // or deleted, then the object is default-initialized; + CXXConstructorDecl *CD = S.LookupDefaultConstructor(ClassDecl); + if (!CD || !CD->getCanonicalDecl()->isDefaulted() || CD->isDeleted()) + return TryConstructorInitialization(S, Entity, Kind, 0, 0, + T, Sequence); + } + + // -- if T is a (possibly cv-qualified) non-union class type without a + // user-provided or deleted default constructor, then the object is + // zero-initialized and, if T has a non-trivial default constructor, + // default-initialized; + if ((ClassDecl->getTagKind() == TTK_Class || + ClassDecl->getTagKind() == TTK_Struct)) { + Sequence.AddZeroInitializationStep(Entity.getType()); + return TryConstructorInitialization(S, Entity, Kind, 0, 0, T, Sequence); + } + } + } + + Sequence.AddZeroInitializationStep(Entity.getType()); +} + +/// \brief Attempt default initialization (C++ [dcl.init]p6). +static void TryDefaultInitialization(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + InitializationSequence &Sequence) { + assert(Kind.getKind() == InitializationKind::IK_Default); + + // C++ [dcl.init]p6: + // To default-initialize an object of type T means: + // - if T is an array type, each element is default-initialized; + QualType DestType = S.Context.getBaseElementType(Entity.getType()); + + // - if T is a (possibly cv-qualified) class type (Clause 9), the default + // constructor for T is called (and the initialization is ill-formed if + // T has no accessible default constructor); + if (DestType->isRecordType() && S.getLangOpts().CPlusPlus) { + TryConstructorInitialization(S, Entity, Kind, 0, 0, DestType, Sequence); + return; + } + + // - otherwise, no initialization is performed. + + // If a program calls for the default initialization of an object of + // a const-qualified type T, T shall be a class type with a user-provided + // default constructor. + if (DestType.isConstQualified() && S.getLangOpts().CPlusPlus) { + Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst); + return; + } + + // If the destination type has a lifetime property, zero-initialize it. + if (DestType.getQualifiers().hasObjCLifetime()) { + Sequence.AddZeroInitializationStep(Entity.getType()); + return; + } +} + +/// \brief Attempt a user-defined conversion between two types (C++ [dcl.init]), +/// which enumerates all conversion functions and performs overload resolution +/// to select the best. +static void TryUserDefinedConversion(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + Expr *Initializer, + InitializationSequence &Sequence) { + QualType DestType = Entity.getType(); + assert(!DestType->isReferenceType() && "References are handled elsewhere"); + QualType SourceType = Initializer->getType(); + assert((DestType->isRecordType() || SourceType->isRecordType()) && + "Must have a class type to perform a user-defined conversion"); + + // Build the candidate set directly in the initialization sequence + // structure, so that it will persist if we fail. + OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet(); + CandidateSet.clear(); + + // Determine whether we are allowed to call explicit constructors or + // explicit conversion operators. + bool AllowExplicit = Kind.AllowExplicit(); + + if (const RecordType *DestRecordType = DestType->getAs()) { + // The type we're converting to is a class type. Enumerate its constructors + // to see if there is a suitable conversion. + CXXRecordDecl *DestRecordDecl + = cast(DestRecordType->getDecl()); + + // Try to complete the type we're converting to. + if (!S.RequireCompleteType(Kind.getLocation(), DestType, 0)) { + DeclContext::lookup_iterator Con, ConEnd; + for (llvm::tie(Con, ConEnd) = S.LookupConstructors(DestRecordDecl); + Con != ConEnd; ++Con) { + NamedDecl *D = *Con; + DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess()); + + // Find the constructor (which may be a template). + CXXConstructorDecl *Constructor = 0; + FunctionTemplateDecl *ConstructorTmpl + = dyn_cast(D); + if (ConstructorTmpl) + Constructor = cast( + ConstructorTmpl->getTemplatedDecl()); + else + Constructor = cast(D); + + if (!Constructor->isInvalidDecl() && + Constructor->isConvertingConstructor(AllowExplicit)) { + if (ConstructorTmpl) + S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, + /*ExplicitArgs*/ 0, + Initializer, CandidateSet, + /*SuppressUserConversions=*/true); + else + S.AddOverloadCandidate(Constructor, FoundDecl, + Initializer, CandidateSet, + /*SuppressUserConversions=*/true); + } + } + } + } + + SourceLocation DeclLoc = Initializer->getLocStart(); + + if (const RecordType *SourceRecordType = SourceType->getAs()) { + // The type we're converting from is a class type, enumerate its conversion + // functions. + + // We can only enumerate the conversion functions for a complete type; if + // the type isn't complete, simply skip this step. + if (!S.RequireCompleteType(DeclLoc, SourceType, 0)) { + CXXRecordDecl *SourceRecordDecl + = cast(SourceRecordType->getDecl()); + + const UnresolvedSetImpl *Conversions + = SourceRecordDecl->getVisibleConversionFunctions(); + for (UnresolvedSetImpl::const_iterator I = Conversions->begin(), + E = Conversions->end(); + I != E; ++I) { + NamedDecl *D = *I; + CXXRecordDecl *ActingDC = cast(D->getDeclContext()); + if (isa(D)) + D = cast(D)->getTargetDecl(); + + FunctionTemplateDecl *ConvTemplate = dyn_cast(D); + CXXConversionDecl *Conv; + if (ConvTemplate) + Conv = cast(ConvTemplate->getTemplatedDecl()); + else + Conv = cast(D); + + if (AllowExplicit || !Conv->isExplicit()) { + if (ConvTemplate) + S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(), + ActingDC, Initializer, DestType, + CandidateSet); + else + S.AddConversionCandidate(Conv, I.getPair(), ActingDC, + Initializer, DestType, CandidateSet); + } + } + } + } + + // Perform overload resolution. If it fails, return the failed result. + OverloadCandidateSet::iterator Best; + if (OverloadingResult Result + = CandidateSet.BestViableFunction(S, DeclLoc, Best, true)) { + Sequence.SetOverloadFailure( + InitializationSequence::FK_UserConversionOverloadFailed, + Result); + return; + } + + FunctionDecl *Function = Best->Function; + S.MarkFunctionReferenced(DeclLoc, Function); + bool HadMultipleCandidates = (CandidateSet.size() > 1); + + if (isa(Function)) { + // Add the user-defined conversion step. Any cv-qualification conversion is + // subsumed by the initialization. Per DR5, the created temporary is of the + // cv-unqualified type of the destination. + Sequence.AddUserConversionStep(Function, Best->FoundDecl, + DestType.getUnqualifiedType(), + HadMultipleCandidates); + return; + } + + // Add the user-defined conversion step that calls the conversion function. + QualType ConvType = Function->getCallResultType(); + if (ConvType->getAs()) { + // If we're converting to a class type, there may be an copy of + // the resulting temporary object (possible to create an object of + // a base class type). That copy is not a separate conversion, so + // we just make a note of the actual destination type (possibly a + // base class of the type returned by the conversion function) and + // let the user-defined conversion step handle the conversion. + Sequence.AddUserConversionStep(Function, Best->FoundDecl, DestType, + HadMultipleCandidates); + return; + } + + Sequence.AddUserConversionStep(Function, Best->FoundDecl, ConvType, + HadMultipleCandidates); + + // If the conversion following the call to the conversion function + // is interesting, add it as a separate step. + if (Best->FinalConversion.First || Best->FinalConversion.Second || + Best->FinalConversion.Third) { + ImplicitConversionSequence ICS; + ICS.setStandard(); + ICS.Standard = Best->FinalConversion; + Sequence.AddConversionSequenceStep(ICS, DestType); + } +} + +/// The non-zero enum values here are indexes into diagnostic alternatives. +enum InvalidICRKind { IIK_okay, IIK_nonlocal, IIK_nonscalar }; + +/// Determines whether this expression is an acceptable ICR source. +static InvalidICRKind isInvalidICRSource(ASTContext &C, Expr *e, + bool isAddressOf) { + // Skip parens. + e = e->IgnoreParens(); + + // Skip address-of nodes. + if (UnaryOperator *op = dyn_cast(e)) { + if (op->getOpcode() == UO_AddrOf) + return isInvalidICRSource(C, op->getSubExpr(), /*addressof*/ true); + + // Skip certain casts. + } else if (CastExpr *ce = dyn_cast(e)) { + switch (ce->getCastKind()) { + case CK_Dependent: + case CK_BitCast: + case CK_LValueBitCast: + case CK_NoOp: + return isInvalidICRSource(C, ce->getSubExpr(), isAddressOf); + + case CK_ArrayToPointerDecay: + return IIK_nonscalar; + + case CK_NullToPointer: + return IIK_okay; + + default: + break; + } + + // If we have a declaration reference, it had better be a local variable. + } else if (isa(e)) { + if (!isAddressOf) return IIK_nonlocal; + + VarDecl *var = dyn_cast(cast(e)->getDecl()); + if (!var) return IIK_nonlocal; + + return (var->hasLocalStorage() ? IIK_okay : IIK_nonlocal); + + // If we have a conditional operator, check both sides. + } else if (ConditionalOperator *cond = dyn_cast(e)) { + if (InvalidICRKind iik = isInvalidICRSource(C, cond->getLHS(), isAddressOf)) + return iik; + + return isInvalidICRSource(C, cond->getRHS(), isAddressOf); + + // These are never scalar. + } else if (isa(e)) { + return IIK_nonscalar; + + // Otherwise, it needs to be a null pointer constant. + } else { + return (e->isNullPointerConstant(C, Expr::NPC_ValueDependentIsNull) + ? IIK_okay : IIK_nonlocal); + } + + return IIK_nonlocal; +} + +/// Check whether the given expression is a valid operand for an +/// indirect copy/restore. +static void checkIndirectCopyRestoreSource(Sema &S, Expr *src) { + assert(src->isRValue()); + + InvalidICRKind iik = isInvalidICRSource(S.Context, src, false); + if (iik == IIK_okay) return; + + S.Diag(src->getExprLoc(), diag::err_arc_nonlocal_writeback) + << ((unsigned) iik - 1) // shift index into diagnostic explanations + << src->getSourceRange(); +} + +/// \brief Determine whether we have compatible array types for the +/// purposes of GNU by-copy array initialization. +static bool hasCompatibleArrayTypes(ASTContext &Context, + const ArrayType *Dest, + const ArrayType *Source) { + // If the source and destination array types are equivalent, we're + // done. + if (Context.hasSameType(QualType(Dest, 0), QualType(Source, 0))) + return true; + + // Make sure that the element types are the same. + if (!Context.hasSameType(Dest->getElementType(), Source->getElementType())) + return false; + + // The only mismatch we allow is when the destination is an + // incomplete array type and the source is a constant array type. + return Source->isConstantArrayType() && Dest->isIncompleteArrayType(); +} + +static bool tryObjCWritebackConversion(Sema &S, + InitializationSequence &Sequence, + const InitializedEntity &Entity, + Expr *Initializer) { + bool ArrayDecay = false; + QualType ArgType = Initializer->getType(); + QualType ArgPointee; + if (const ArrayType *ArgArrayType = S.Context.getAsArrayType(ArgType)) { + ArrayDecay = true; + ArgPointee = ArgArrayType->getElementType(); + ArgType = S.Context.getPointerType(ArgPointee); + } + + // Handle write-back conversion. + QualType ConvertedArgType; + if (!S.isObjCWritebackConversion(ArgType, Entity.getType(), + ConvertedArgType)) + return false; + + // We should copy unless we're passing to an argument explicitly + // marked 'out'. + bool ShouldCopy = true; + if (ParmVarDecl *param = cast_or_null(Entity.getDecl())) + ShouldCopy = (param->getObjCDeclQualifier() != ParmVarDecl::OBJC_TQ_Out); + + // Do we need an lvalue conversion? + if (ArrayDecay || Initializer->isGLValue()) { + ImplicitConversionSequence ICS; + ICS.setStandard(); + ICS.Standard.setAsIdentityConversion(); + + QualType ResultType; + if (ArrayDecay) { + ICS.Standard.First = ICK_Array_To_Pointer; + ResultType = S.Context.getPointerType(ArgPointee); + } else { + ICS.Standard.First = ICK_Lvalue_To_Rvalue; + ResultType = Initializer->getType().getNonLValueExprType(S.Context); + } + + Sequence.AddConversionSequenceStep(ICS, ResultType); + } + + Sequence.AddPassByIndirectCopyRestoreStep(Entity.getType(), ShouldCopy); + return true; +} + +InitializationSequence::InitializationSequence(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + Expr **Args, + unsigned NumArgs) + : FailedCandidateSet(Kind.getLocation()) { + ASTContext &Context = S.Context; + + // C++0x [dcl.init]p16: + // The semantics of initializers are as follows. The destination type is + // the type of the object or reference being initialized and the source + // type is the type of the initializer expression. The source type is not + // defined when the initializer is a braced-init-list or when it is a + // parenthesized list of expressions. + QualType DestType = Entity.getType(); + + if (DestType->isDependentType() || + Expr::hasAnyTypeDependentArguments(llvm::makeArrayRef(Args, NumArgs))) { + SequenceKind = DependentSequence; + return; + } + + // Almost everything is a normal sequence. + setSequenceKind(NormalSequence); + + for (unsigned I = 0; I != NumArgs; ++I) + if (Args[I]->getType()->isNonOverloadPlaceholderType()) { + // FIXME: should we be doing this here? + ExprResult result = S.CheckPlaceholderExpr(Args[I]); + if (result.isInvalid()) { + SetFailed(FK_PlaceholderType); + return; + } + Args[I] = result.take(); + } + + + QualType SourceType; + Expr *Initializer = 0; + if (NumArgs == 1) { + Initializer = Args[0]; + if (!isa(Initializer)) + SourceType = Initializer->getType(); + } + + // - If the initializer is a (non-parenthesized) braced-init-list, the + // object is list-initialized (8.5.4). + if (Kind.getKind() != InitializationKind::IK_Direct) { + if (InitListExpr *InitList = dyn_cast_or_null(Initializer)) { + TryListInitialization(S, Entity, Kind, InitList, *this); + return; + } + } + + // - If the destination type is a reference type, see 8.5.3. + if (DestType->isReferenceType()) { + // C++0x [dcl.init.ref]p1: + // A variable declared to be a T& or T&&, that is, "reference to type T" + // (8.3.2), shall be initialized by an object, or function, of type T or + // by an object that can be converted into a T. + // (Therefore, multiple arguments are not permitted.) + if (NumArgs != 1) + SetFailed(FK_TooManyInitsForReference); + else + TryReferenceInitialization(S, Entity, Kind, Args[0], *this); + return; + } + + // - If the initializer is (), the object is value-initialized. + if (Kind.getKind() == InitializationKind::IK_Value || + (Kind.getKind() == InitializationKind::IK_Direct && NumArgs == 0)) { + TryValueInitialization(S, Entity, Kind, *this); + return; + } + + // Handle default initialization. + if (Kind.getKind() == InitializationKind::IK_Default) { + TryDefaultInitialization(S, Entity, Kind, *this); + return; + } + + // - If the destination type is an array of characters, an array of + // char16_t, an array of char32_t, or an array of wchar_t, and the + // initializer is a string literal, see 8.5.2. + // - Otherwise, if the destination type is an array, the program is + // ill-formed. + if (const ArrayType *DestAT = Context.getAsArrayType(DestType)) { + if (Initializer && isa(DestAT)) { + SetFailed(FK_VariableLengthArrayHasInitializer); + return; + } + + if (Initializer && IsStringInit(Initializer, DestAT, Context)) { + TryStringLiteralInitialization(S, Entity, Kind, Initializer, *this); + return; + } + + // Note: as an GNU C extension, we allow initialization of an + // array from a compound literal that creates an array of the same + // type, so long as the initializer has no side effects. + if (!S.getLangOpts().CPlusPlus && Initializer && + isa(Initializer->IgnoreParens()) && + Initializer->getType()->isArrayType()) { + const ArrayType *SourceAT + = Context.getAsArrayType(Initializer->getType()); + if (!hasCompatibleArrayTypes(S.Context, DestAT, SourceAT)) + SetFailed(FK_ArrayTypeMismatch); + else if (Initializer->HasSideEffects(S.Context)) + SetFailed(FK_NonConstantArrayInit); + else { + AddArrayInitStep(DestType); + } + } + // Note: as a GNU C++ extension, we allow initialization of a + // class member from a parenthesized initializer list. + else if (S.getLangOpts().CPlusPlus && + Entity.getKind() == InitializedEntity::EK_Member && + Initializer && isa(Initializer)) { + TryListInitialization(S, Entity, Kind, cast(Initializer), + *this); + AddParenthesizedArrayInitStep(DestType); + } else if (DestAT->getElementType()->isAnyCharacterType()) + SetFailed(FK_ArrayNeedsInitListOrStringLiteral); + else + SetFailed(FK_ArrayNeedsInitList); + + return; + } + + // Determine whether we should consider writeback conversions for + // Objective-C ARC. + bool allowObjCWritebackConversion = S.getLangOpts().ObjCAutoRefCount && + Entity.getKind() == InitializedEntity::EK_Parameter; + + // We're at the end of the line for C: it's either a write-back conversion + // or it's a C assignment. There's no need to check anything else. + if (!S.getLangOpts().CPlusPlus) { + // If allowed, check whether this is an Objective-C writeback conversion. + if (allowObjCWritebackConversion && + tryObjCWritebackConversion(S, *this, Entity, Initializer)) { + return; + } + + // Handle initialization in C + AddCAssignmentStep(DestType); + MaybeProduceObjCObject(S, *this, Entity); + return; + } + + assert(S.getLangOpts().CPlusPlus); + + // - If the destination type is a (possibly cv-qualified) class type: + if (DestType->isRecordType()) { + // - If the initialization is direct-initialization, or if it is + // copy-initialization where the cv-unqualified version of the + // source type is the same class as, or a derived class of, the + // class of the destination, constructors are considered. [...] + if (Kind.getKind() == InitializationKind::IK_Direct || + (Kind.getKind() == InitializationKind::IK_Copy && + (Context.hasSameUnqualifiedType(SourceType, DestType) || + S.IsDerivedFrom(SourceType, DestType)))) + TryConstructorInitialization(S, Entity, Kind, Args, NumArgs, + Entity.getType(), *this); + // - Otherwise (i.e., for the remaining copy-initialization cases), + // user-defined conversion sequences that can convert from the source + // type to the destination type or (when a conversion function is + // used) to a derived class thereof are enumerated as described in + // 13.3.1.4, and the best one is chosen through overload resolution + // (13.3). + else + TryUserDefinedConversion(S, Entity, Kind, Initializer, *this); + return; + } + + if (NumArgs > 1) { + SetFailed(FK_TooManyInitsForScalar); + return; + } + assert(NumArgs == 1 && "Zero-argument case handled above"); + + // - Otherwise, if the source type is a (possibly cv-qualified) class + // type, conversion functions are considered. + if (!SourceType.isNull() && SourceType->isRecordType()) { + TryUserDefinedConversion(S, Entity, Kind, Initializer, *this); + MaybeProduceObjCObject(S, *this, Entity); + return; + } + + // - Otherwise, the initial value of the object being initialized is the + // (possibly converted) value of the initializer expression. Standard + // conversions (Clause 4) will be used, if necessary, to convert the + // initializer expression to the cv-unqualified version of the + // destination type; no user-defined conversions are considered. + + ImplicitConversionSequence ICS + = S.TryImplicitConversion(Initializer, Entity.getType(), + /*SuppressUserConversions*/true, + /*AllowExplicitConversions*/ false, + /*InOverloadResolution*/ false, + /*CStyle=*/Kind.isCStyleOrFunctionalCast(), + allowObjCWritebackConversion); + + if (ICS.isStandard() && + ICS.Standard.Second == ICK_Writeback_Conversion) { + // Objective-C ARC writeback conversion. + + // We should copy unless we're passing to an argument explicitly + // marked 'out'. + bool ShouldCopy = true; + if (ParmVarDecl *Param = cast_or_null(Entity.getDecl())) + ShouldCopy = (Param->getObjCDeclQualifier() != ParmVarDecl::OBJC_TQ_Out); + + // If there was an lvalue adjustment, add it as a separate conversion. + if (ICS.Standard.First == ICK_Array_To_Pointer || + ICS.Standard.First == ICK_Lvalue_To_Rvalue) { + ImplicitConversionSequence LvalueICS; + LvalueICS.setStandard(); + LvalueICS.Standard.setAsIdentityConversion(); + LvalueICS.Standard.setAllToTypes(ICS.Standard.getToType(0)); + LvalueICS.Standard.First = ICS.Standard.First; + AddConversionSequenceStep(LvalueICS, ICS.Standard.getToType(0)); + } + + AddPassByIndirectCopyRestoreStep(Entity.getType(), ShouldCopy); + } else if (ICS.isBad()) { + DeclAccessPair dap; + if (Initializer->getType() == Context.OverloadTy && + !S.ResolveAddressOfOverloadedFunction(Initializer + , DestType, false, dap)) + SetFailed(InitializationSequence::FK_AddressOfOverloadFailed); + else + SetFailed(InitializationSequence::FK_ConversionFailed); + } else { + AddConversionSequenceStep(ICS, Entity.getType()); + + MaybeProduceObjCObject(S, *this, Entity); + } +} + +InitializationSequence::~InitializationSequence() { + for (SmallVectorImpl::iterator Step = Steps.begin(), + StepEnd = Steps.end(); + Step != StepEnd; ++Step) + Step->Destroy(); +} + +//===----------------------------------------------------------------------===// +// Perform initialization +//===----------------------------------------------------------------------===// +static Sema::AssignmentAction +getAssignmentAction(const InitializedEntity &Entity) { + switch(Entity.getKind()) { + case InitializedEntity::EK_Variable: + case InitializedEntity::EK_New: + case InitializedEntity::EK_Exception: + case InitializedEntity::EK_Base: + case InitializedEntity::EK_Delegating: + return Sema::AA_Initializing; + + case InitializedEntity::EK_Parameter: + if (Entity.getDecl() && + isa(Entity.getDecl()->getDeclContext())) + return Sema::AA_Sending; + + return Sema::AA_Passing; + + case InitializedEntity::EK_Result: + return Sema::AA_Returning; + + case InitializedEntity::EK_Temporary: + // FIXME: Can we tell apart casting vs. converting? + return Sema::AA_Casting; + + case InitializedEntity::EK_Member: + case InitializedEntity::EK_ArrayElement: + case InitializedEntity::EK_VectorElement: + case InitializedEntity::EK_ComplexElement: + case InitializedEntity::EK_BlockElement: + case InitializedEntity::EK_LambdaCapture: + return Sema::AA_Initializing; + } + + llvm_unreachable("Invalid EntityKind!"); +} + +/// \brief Whether we should binding a created object as a temporary when +/// initializing the given entity. +static bool shouldBindAsTemporary(const InitializedEntity &Entity) { + switch (Entity.getKind()) { + case InitializedEntity::EK_ArrayElement: + case InitializedEntity::EK_Member: + case InitializedEntity::EK_Result: + case InitializedEntity::EK_New: + case InitializedEntity::EK_Variable: + case InitializedEntity::EK_Base: + case InitializedEntity::EK_Delegating: + case InitializedEntity::EK_VectorElement: + case InitializedEntity::EK_ComplexElement: + case InitializedEntity::EK_Exception: + case InitializedEntity::EK_BlockElement: + case InitializedEntity::EK_LambdaCapture: + return false; + + case InitializedEntity::EK_Parameter: + case InitializedEntity::EK_Temporary: + return true; + } + + llvm_unreachable("missed an InitializedEntity kind?"); +} + +/// \brief Whether the given entity, when initialized with an object +/// created for that initialization, requires destruction. +static bool shouldDestroyTemporary(const InitializedEntity &Entity) { + switch (Entity.getKind()) { + case InitializedEntity::EK_Member: + case InitializedEntity::EK_Result: + case InitializedEntity::EK_New: + case InitializedEntity::EK_Base: + case InitializedEntity::EK_Delegating: + case InitializedEntity::EK_VectorElement: + case InitializedEntity::EK_ComplexElement: + case InitializedEntity::EK_BlockElement: + case InitializedEntity::EK_LambdaCapture: + return false; + + case InitializedEntity::EK_Variable: + case InitializedEntity::EK_Parameter: + case InitializedEntity::EK_Temporary: + case InitializedEntity::EK_ArrayElement: + case InitializedEntity::EK_Exception: + return true; + } + + llvm_unreachable("missed an InitializedEntity kind?"); +} + +/// \brief Look for copy and move constructors and constructor templates, for +/// copying an object via direct-initialization (per C++11 [dcl.init]p16). +static void LookupCopyAndMoveConstructors(Sema &S, + OverloadCandidateSet &CandidateSet, + CXXRecordDecl *Class, + Expr *CurInitExpr) { + DeclContext::lookup_iterator Con, ConEnd; + for (llvm::tie(Con, ConEnd) = S.LookupConstructors(Class); + Con != ConEnd; ++Con) { + CXXConstructorDecl *Constructor = 0; + + if ((Constructor = dyn_cast(*Con))) { + // Handle copy/moveconstructors, only. + if (!Constructor || Constructor->isInvalidDecl() || + !Constructor->isCopyOrMoveConstructor() || + !Constructor->isConvertingConstructor(/*AllowExplicit=*/true)) + continue; + + DeclAccessPair FoundDecl + = DeclAccessPair::make(Constructor, Constructor->getAccess()); + S.AddOverloadCandidate(Constructor, FoundDecl, + CurInitExpr, CandidateSet); + continue; + } + + // Handle constructor templates. + FunctionTemplateDecl *ConstructorTmpl = cast(*Con); + if (ConstructorTmpl->isInvalidDecl()) + continue; + + Constructor = cast( + ConstructorTmpl->getTemplatedDecl()); + if (!Constructor->isConvertingConstructor(/*AllowExplicit=*/true)) + continue; + + // FIXME: Do we need to limit this to copy-constructor-like + // candidates? + DeclAccessPair FoundDecl + = DeclAccessPair::make(ConstructorTmpl, ConstructorTmpl->getAccess()); + S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, 0, + CurInitExpr, CandidateSet, true); + } +} + +/// \brief Get the location at which initialization diagnostics should appear. +static SourceLocation getInitializationLoc(const InitializedEntity &Entity, + Expr *Initializer) { + switch (Entity.getKind()) { + case InitializedEntity::EK_Result: + return Entity.getReturnLoc(); + + case InitializedEntity::EK_Exception: + return Entity.getThrowLoc(); + + case InitializedEntity::EK_Variable: + return Entity.getDecl()->getLocation(); + + case InitializedEntity::EK_LambdaCapture: + return Entity.getCaptureLoc(); + + case InitializedEntity::EK_ArrayElement: + case InitializedEntity::EK_Member: + case InitializedEntity::EK_Parameter: + case InitializedEntity::EK_Temporary: + case InitializedEntity::EK_New: + case InitializedEntity::EK_Base: + case InitializedEntity::EK_Delegating: + case InitializedEntity::EK_VectorElement: + case InitializedEntity::EK_ComplexElement: + case InitializedEntity::EK_BlockElement: + return Initializer->getLocStart(); + } + llvm_unreachable("missed an InitializedEntity kind?"); +} + +/// \brief Make a (potentially elidable) temporary copy of the object +/// provided by the given initializer by calling the appropriate copy +/// constructor. +/// +/// \param S The Sema object used for type-checking. +/// +/// \param T The type of the temporary object, which must either be +/// the type of the initializer expression or a superclass thereof. +/// +/// \param Enter The entity being initialized. +/// +/// \param CurInit The initializer expression. +/// +/// \param IsExtraneousCopy Whether this is an "extraneous" copy that +/// is permitted in C++03 (but not C++0x) when binding a reference to +/// an rvalue. +/// +/// \returns An expression that copies the initializer expression into +/// a temporary object, or an error expression if a copy could not be +/// created. +static ExprResult CopyObject(Sema &S, + QualType T, + const InitializedEntity &Entity, + ExprResult CurInit, + bool IsExtraneousCopy) { + // Determine which class type we're copying to. + Expr *CurInitExpr = (Expr *)CurInit.get(); + CXXRecordDecl *Class = 0; + if (const RecordType *Record = T->getAs()) + Class = cast(Record->getDecl()); + if (!Class) + return move(CurInit); + + // C++0x [class.copy]p32: + // When certain criteria are met, an implementation is allowed to + // omit the copy/move construction of a class object, even if the + // copy/move constructor and/or destructor for the object have + // side effects. [...] + // - when a temporary class object that has not been bound to a + // reference (12.2) would be copied/moved to a class object + // with the same cv-unqualified type, the copy/move operation + // can be omitted by constructing the temporary object + // directly into the target of the omitted copy/move + // + // Note that the other three bullets are handled elsewhere. Copy + // elision for return statements and throw expressions are handled as part + // of constructor initialization, while copy elision for exception handlers + // is handled by the run-time. + bool Elidable = CurInitExpr->isTemporaryObject(S.Context, Class); + SourceLocation Loc = getInitializationLoc(Entity, CurInit.get()); + + // Make sure that the type we are copying is complete. + if (S.RequireCompleteType(Loc, T, S.PDiag(diag::err_temp_copy_incomplete))) + return move(CurInit); + + // Perform overload resolution using the class's copy/move constructors. + // Only consider constructors and constructor templates. Per + // C++0x [dcl.init]p16, second bullet to class types, this initialization + // is direct-initialization. + OverloadCandidateSet CandidateSet(Loc); + LookupCopyAndMoveConstructors(S, CandidateSet, Class, CurInitExpr); + + bool HadMultipleCandidates = (CandidateSet.size() > 1); + + OverloadCandidateSet::iterator Best; + switch (CandidateSet.BestViableFunction(S, Loc, Best)) { + case OR_Success: + break; + + case OR_No_Viable_Function: + S.Diag(Loc, IsExtraneousCopy && !S.isSFINAEContext() + ? diag::ext_rvalue_to_reference_temp_copy_no_viable + : diag::err_temp_copy_no_viable) + << (int)Entity.getKind() << CurInitExpr->getType() + << CurInitExpr->getSourceRange(); + CandidateSet.NoteCandidates(S, OCD_AllCandidates, CurInitExpr); + if (!IsExtraneousCopy || S.isSFINAEContext()) + return ExprError(); + return move(CurInit); + + case OR_Ambiguous: + S.Diag(Loc, diag::err_temp_copy_ambiguous) + << (int)Entity.getKind() << CurInitExpr->getType() + << CurInitExpr->getSourceRange(); + CandidateSet.NoteCandidates(S, OCD_ViableCandidates, CurInitExpr); + return ExprError(); + + case OR_Deleted: + S.Diag(Loc, diag::err_temp_copy_deleted) + << (int)Entity.getKind() << CurInitExpr->getType() + << CurInitExpr->getSourceRange(); + S.NoteDeletedFunction(Best->Function); + return ExprError(); + } + + CXXConstructorDecl *Constructor = cast(Best->Function); + ASTOwningVector ConstructorArgs(S); + CurInit.release(); // Ownership transferred into MultiExprArg, below. + + S.CheckConstructorAccess(Loc, Constructor, Entity, + Best->FoundDecl.getAccess(), IsExtraneousCopy); + + if (IsExtraneousCopy) { + // If this is a totally extraneous copy for C++03 reference + // binding purposes, just return the original initialization + // expression. We don't generate an (elided) copy operation here + // because doing so would require us to pass down a flag to avoid + // infinite recursion, where each step adds another extraneous, + // elidable copy. + + // Instantiate the default arguments of any extra parameters in + // the selected copy constructor, as if we were going to create a + // proper call to the copy constructor. + for (unsigned I = 1, N = Constructor->getNumParams(); I != N; ++I) { + ParmVarDecl *Parm = Constructor->getParamDecl(I); + if (S.RequireCompleteType(Loc, Parm->getType(), + S.PDiag(diag::err_call_incomplete_argument))) + break; + + // Build the default argument expression; we don't actually care + // if this succeeds or not, because this routine will complain + // if there was a problem. + S.BuildCXXDefaultArgExpr(Loc, Constructor, Parm); + } + + return S.Owned(CurInitExpr); + } + + S.MarkFunctionReferenced(Loc, Constructor); + + // 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, MultiExprArg(&CurInitExpr, 1), + Loc, ConstructorArgs)) + return ExprError(); + + // Actually perform the constructor call. + CurInit = S.BuildCXXConstructExpr(Loc, T, Constructor, Elidable, + move_arg(ConstructorArgs), + HadMultipleCandidates, + /*ZeroInit*/ false, + CXXConstructExpr::CK_Complete, + SourceRange()); + + // If we're supposed to bind temporaries, do so. + if (!CurInit.isInvalid() && shouldBindAsTemporary(Entity)) + CurInit = S.MaybeBindToTemporary(CurInit.takeAs()); + return move(CurInit); +} + +/// \brief Check whether elidable copy construction for binding a reference to +/// a temporary would have succeeded if we were building in C++98 mode, for +/// -Wc++98-compat. +static void CheckCXX98CompatAccessibleCopy(Sema &S, + const InitializedEntity &Entity, + Expr *CurInitExpr) { + assert(S.getLangOpts().CPlusPlus0x); + + const RecordType *Record = CurInitExpr->getType()->getAs(); + if (!Record) + return; + + SourceLocation Loc = getInitializationLoc(Entity, CurInitExpr); + if (S.Diags.getDiagnosticLevel(diag::warn_cxx98_compat_temp_copy, Loc) + == DiagnosticsEngine::Ignored) + return; + + // Find constructors which would have been considered. + OverloadCandidateSet CandidateSet(Loc); + LookupCopyAndMoveConstructors( + S, CandidateSet, cast(Record->getDecl()), CurInitExpr); + + // Perform overload resolution. + OverloadCandidateSet::iterator Best; + OverloadingResult OR = CandidateSet.BestViableFunction(S, Loc, Best); + + PartialDiagnostic Diag = S.PDiag(diag::warn_cxx98_compat_temp_copy) + << OR << (int)Entity.getKind() << CurInitExpr->getType() + << CurInitExpr->getSourceRange(); + + switch (OR) { + case OR_Success: + S.CheckConstructorAccess(Loc, cast(Best->Function), + Entity, Best->FoundDecl.getAccess(), Diag); + // FIXME: Check default arguments as far as that's possible. + break; + + case OR_No_Viable_Function: + S.Diag(Loc, Diag); + CandidateSet.NoteCandidates(S, OCD_AllCandidates, CurInitExpr); + break; + + case OR_Ambiguous: + S.Diag(Loc, Diag); + CandidateSet.NoteCandidates(S, OCD_ViableCandidates, CurInitExpr); + break; + + case OR_Deleted: + S.Diag(Loc, Diag); + S.NoteDeletedFunction(Best->Function); + break; + } +} + +void InitializationSequence::PrintInitLocationNote(Sema &S, + const InitializedEntity &Entity) { + if (Entity.getKind() == InitializedEntity::EK_Parameter && Entity.getDecl()) { + if (Entity.getDecl()->getLocation().isInvalid()) + return; + + if (Entity.getDecl()->getDeclName()) + S.Diag(Entity.getDecl()->getLocation(), diag::note_parameter_named_here) + << Entity.getDecl()->getDeclName(); + else + S.Diag(Entity.getDecl()->getLocation(), diag::note_parameter_here); + } +} + +static bool isReferenceBinding(const InitializationSequence::Step &s) { + return s.Kind == InitializationSequence::SK_BindReference || + s.Kind == InitializationSequence::SK_BindReferenceToTemporary; +} + +static ExprResult +PerformConstructorInitialization(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + MultiExprArg Args, + const InitializationSequence::Step& Step, + bool &ConstructorInitRequiresZeroInit) { + unsigned NumArgs = Args.size(); + CXXConstructorDecl *Constructor + = cast(Step.Function.Function); + bool HadMultipleCandidates = Step.Function.HadMultipleCandidates; + + // Build a call to the selected constructor. + 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. + assert(Constructor->getParent() && "No parent class for constructor."); + if (Constructor->isDefaulted() && Constructor->isDefaultConstructor() && + Constructor->isTrivial() && !Constructor->isUsed(false)) + S.DefineImplicitDefaultConstructor(Loc, Constructor); + } + + ExprResult CurInit = S.Owned((Expr *)0); + + // C++ [over.match.copy]p1: + // - When initializing a temporary to be bound to the first parameter + // of a constructor that takes a reference to possibly cv-qualified + // T as its first argument, called with a single argument in the + // context of direct-initialization, explicit conversion functions + // are also considered. + bool AllowExplicitConv = Kind.AllowExplicit() && !Kind.isCopyInit() && + Args.size() == 1 && + Constructor->isCopyOrMoveConstructor(); + + // Determine the arguments required to actually perform the constructor + // call. + if (S.CompleteConstructorCall(Constructor, move(Args), + Loc, ConstructorArgs, + AllowExplicitConv)) + return ExprError(); + + + if (Entity.getKind() == InitializedEntity::EK_Temporary && + (Kind.getKind() == InitializationKind::IK_DirectList || + (NumArgs != 1 && // FIXME: Hack to work around cast weirdness + (Kind.getKind() == InitializationKind::IK_Direct || + Kind.getKind() == InitializationKind::IK_Value)))) { + // An explicitly-constructed temporary, e.g., X(1, 2). + unsigned NumExprs = ConstructorArgs.size(); + Expr **Exprs = (Expr **)ConstructorArgs.take(); + S.MarkFunctionReferenced(Loc, Constructor); + S.DiagnoseUseOfDecl(Constructor, Loc); + + TypeSourceInfo *TSInfo = Entity.getTypeSourceInfo(); + if (!TSInfo) + TSInfo = S.Context.getTrivialTypeSourceInfo(Entity.getType(), Loc); + SourceRange ParenRange; + if (Kind.getKind() != InitializationKind::IK_DirectList) + ParenRange = Kind.getParenRange(); + + CurInit = S.Owned(new (S.Context) CXXTemporaryObjectExpr(S.Context, + Constructor, + TSInfo, + Exprs, + NumExprs, + ParenRange, + HadMultipleCandidates, + ConstructorInitRequiresZeroInit)); + } else { + CXXConstructExpr::ConstructionKind ConstructKind = + CXXConstructExpr::CK_Complete; + + if (Entity.getKind() == InitializedEntity::EK_Base) { + ConstructKind = Entity.getBaseSpecifier()->isVirtual() ? + CXXConstructExpr::CK_VirtualBase : + CXXConstructExpr::CK_NonVirtualBase; + } else if (Entity.getKind() == InitializedEntity::EK_Delegating) { + ConstructKind = CXXConstructExpr::CK_Delegating; + } + + // Only get the parenthesis range if it is a direct construction. + SourceRange parenRange = + Kind.getKind() == InitializationKind::IK_Direct ? + Kind.getParenRange() : SourceRange(); + + // If the entity allows NRVO, mark the construction as elidable + // unconditionally. + if (Entity.allowsNRVO()) + CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(), + Constructor, /*Elidable=*/true, + move_arg(ConstructorArgs), + HadMultipleCandidates, + ConstructorInitRequiresZeroInit, + ConstructKind, + parenRange); + else + CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(), + Constructor, + move_arg(ConstructorArgs), + HadMultipleCandidates, + ConstructorInitRequiresZeroInit, + ConstructKind, + parenRange); + } + if (CurInit.isInvalid()) + return ExprError(); + + // Only check access if all of that succeeded. + S.CheckConstructorAccess(Loc, Constructor, Entity, + Step.Function.FoundDecl.getAccess()); + S.DiagnoseUseOfDecl(Step.Function.FoundDecl, Loc); + + if (shouldBindAsTemporary(Entity)) + CurInit = S.MaybeBindToTemporary(CurInit.takeAs()); + + return move(CurInit); +} + +ExprResult +InitializationSequence::Perform(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + MultiExprArg Args, + QualType *ResultType) { + if (Failed()) { + unsigned NumArgs = Args.size(); + Diagnose(S, Entity, Kind, (Expr **)Args.release(), NumArgs); + return ExprError(); + } + + if (getKind() == DependentSequence) { + // If the declaration is a non-dependent, incomplete array type + // that has an initializer, then its type will be completed once + // the initializer is instantiated. + if (ResultType && !Entity.getType()->isDependentType() && + Args.size() == 1) { + QualType DeclType = Entity.getType(); + if (const IncompleteArrayType *ArrayT + = S.Context.getAsIncompleteArrayType(DeclType)) { + // FIXME: We don't currently have the ability to accurately + // compute the length of an initializer list without + // performing full type-checking of the initializer list + // (since we have to determine where braces are implicitly + // introduced and such). So, we fall back to making the array + // type a dependently-sized array type with no specified + // bound. + if (isa((Expr *)Args.get()[0])) { + SourceRange Brackets; + + // Scavange the location of the brackets from the entity, if we can. + if (DeclaratorDecl *DD = Entity.getDecl()) { + if (TypeSourceInfo *TInfo = DD->getTypeSourceInfo()) { + TypeLoc TL = TInfo->getTypeLoc(); + if (IncompleteArrayTypeLoc *ArrayLoc + = dyn_cast(&TL)) + Brackets = ArrayLoc->getBracketsRange(); + } + } + + *ResultType + = S.Context.getDependentSizedArrayType(ArrayT->getElementType(), + /*NumElts=*/0, + ArrayT->getSizeModifier(), + ArrayT->getIndexTypeCVRQualifiers(), + Brackets); + } + + } + } + if (Kind.getKind() == InitializationKind::IK_Direct && + !Kind.isExplicitCast()) { + // Rebuild the ParenListExpr. + SourceRange ParenRange = Kind.getParenRange(); + return S.ActOnParenListExpr(ParenRange.getBegin(), ParenRange.getEnd(), + move(Args)); + } + assert(Kind.getKind() == InitializationKind::IK_Copy || + Kind.isExplicitCast() || + Kind.getKind() == InitializationKind::IK_DirectList); + return ExprResult(Args.release()[0]); + } + + // No steps means no initialization. + if (Steps.empty()) + return S.Owned((Expr *)0); + + QualType DestType = Entity.getType().getNonReferenceType(); + // FIXME: Ugly hack around the fact that Entity.getType() is not + // the same as Entity.getDecl()->getType() in cases involving type merging, + // and we want latter when it makes sense. + if (ResultType) + *ResultType = Entity.getDecl() ? Entity.getDecl()->getType() : + Entity.getType(); + + ExprResult CurInit = S.Owned((Expr *)0); + + // For initialization steps that start with a single initializer, + // grab the only argument out the Args and place it into the "current" + // initializer. + 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_ListConstructorCall: + case SK_ListInitialization: + case SK_UnwrapInitList: + case SK_RewrapInitList: + case SK_CAssignment: + case SK_StringInit: + case SK_ObjCObjectConversion: + case SK_ArrayInit: + case SK_ParenthesizedArrayInit: + case SK_PassByIndirectCopyRestore: + case SK_PassByIndirectRestore: + case SK_ProduceObjCObject: + case SK_StdInitializerList: { + assert(Args.size() == 1); + CurInit = Args.get()[0]; + if (!CurInit.get()) return ExprError(); + break; + } + + case SK_ConstructorInitialization: + case SK_ZeroInitialization: + break; + } + + // Walk through the computed steps for the initialization sequence, + // performing the specified conversions along the way. + bool ConstructorInitRequiresZeroInit = false; + for (step_iterator Step = step_begin(), StepEnd = step_end(); + Step != StepEnd; ++Step) { + if (CurInit.isInvalid()) + return ExprError(); + + QualType SourceType = CurInit.get() ? CurInit.get()->getType() : QualType(); + + switch (Step->Kind) { + case SK_ResolveAddressOfOverloadedFunction: + // Overload resolution determined which function invoke; update the + // initializer to reflect that choice. + S.CheckAddressOfMemberAccess(CurInit.get(), Step->Function.FoundDecl); + S.DiagnoseUseOfDecl(Step->Function.FoundDecl, Kind.getLocation()); + CurInit = S.FixOverloadedFunctionReference(move(CurInit), + Step->Function.FoundDecl, + Step->Function.Function); + 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. + + CXXCastPath BasePath; + + // Casts to inaccessible base classes are allowed with C-style casts. + bool IgnoreBaseAccess = Kind.isCStyleOrFunctionalCast(); + if (S.CheckDerivedToBaseConversion(SourceType, Step->Type, + CurInit.get()->getLocStart(), + CurInit.get()->getSourceRange(), + &BasePath, IgnoreBaseAccess)) + return ExprError(); + + if (S.BasePathInvolvesVirtualBase(BasePath)) { + QualType T = SourceType; + if (const PointerType *Pointer = T->getAs()) + T = Pointer->getPointeeType(); + if (const RecordType *RecordTy = T->getAs()) + S.MarkVTableUsed(CurInit.get()->getLocStart(), + cast(RecordTy->getDecl())); + } + + 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; + } + + case SK_BindReference: + if (FieldDecl *BitField = CurInit.get()->getBitField()) { + // References cannot bind to bit fields (C++ [dcl.init.ref]p5). + S.Diag(Kind.getLocation(), diag::err_reference_bind_to_bitfield) + << Entity.getType().isVolatileQualified() + << BitField->getDeclName() + << CurInit.get()->getSourceRange(); + S.Diag(BitField->getLocation(), diag::note_bitfield_decl); + return ExprError(); + } + + if (CurInit.get()->refersToVectorElement()) { + // References cannot bind to vector elements. + S.Diag(Kind.getLocation(), diag::err_reference_bind_to_vector_element) + << Entity.getType().isVolatileQualified() + << CurInit.get()->getSourceRange(); + PrintInitLocationNote(S, Entity); + return ExprError(); + } + + // Reference binding does not have any corresponding ASTs. + + // Check exception specifications + if (S.CheckExceptionSpecCompatibility(CurInit.get(), DestType)) + return ExprError(); + + break; + + case SK_BindReferenceToTemporary: + // Check exception specifications + if (S.CheckExceptionSpecCompatibility(CurInit.get(), DestType)) + return ExprError(); + + // Materialize the temporary into memory. + CurInit = new (S.Context) MaterializeTemporaryExpr( + Entity.getType().getNonReferenceType(), + CurInit.get(), + Entity.getType()->isLValueReferenceType()); + + // If we're binding to an Objective-C object that has lifetime, we + // need cleanups. + if (S.getLangOpts().ObjCAutoRefCount && + CurInit.get()->getType()->isObjCLifetimeType()) + S.ExprNeedsCleanups = true; + + break; + + case SK_ExtraneousCopyToTemporary: + CurInit = CopyObject(S, Step->Type, Entity, move(CurInit), + /*IsExtraneousCopy=*/true); + break; + + case SK_UserConversion: { + // We have a user-defined conversion that invokes either a constructor + // or a conversion function. + CastKind CastKind; + bool IsCopy = false; + FunctionDecl *Fn = Step->Function.Function; + DeclAccessPair FoundFn = Step->Function.FoundDecl; + bool HadMultipleCandidates = Step->Function.HadMultipleCandidates; + bool CreatedObject = false; + if (CXXConstructorDecl *Constructor = dyn_cast(Fn)) { + // Build a call to the selected constructor. + ASTOwningVector ConstructorArgs(S); + SourceLocation Loc = CurInit.get()->getLocStart(); + CurInit.release(); // Ownership transferred into MultiExprArg, below. + + // Determine the arguments required to actually perform the constructor + // call. + Expr *Arg = CurInit.get(); + if (S.CompleteConstructorCall(Constructor, + MultiExprArg(&Arg, 1), + Loc, ConstructorArgs)) + return ExprError(); + + // Build an expression that constructs a temporary. + CurInit = S.BuildCXXConstructExpr(Loc, Step->Type, Constructor, + move_arg(ConstructorArgs), + HadMultipleCandidates, + /*ZeroInit*/ false, + CXXConstructExpr::CK_Complete, + SourceRange()); + if (CurInit.isInvalid()) + return ExprError(); + + S.CheckConstructorAccess(Kind.getLocation(), Constructor, Entity, + FoundFn.getAccess()); + S.DiagnoseUseOfDecl(FoundFn, Kind.getLocation()); + + CastKind = CK_ConstructorConversion; + QualType Class = S.Context.getTypeDeclType(Constructor->getParent()); + if (S.Context.hasSameUnqualifiedType(SourceType, Class) || + S.IsDerivedFrom(SourceType, Class)) + IsCopy = true; + + CreatedObject = true; + } else { + // Build a call to the conversion function. + CXXConversionDecl *Conversion = cast(Fn); + S.CheckMemberOperatorAccess(Kind.getLocation(), CurInit.get(), 0, + FoundFn); + S.DiagnoseUseOfDecl(FoundFn, Kind.getLocation()); + + // FIXME: Should we move this initialization into a separate + // derived-to-base conversion? I believe the answer is "no", because + // we don't want to turn off access control here for c-style casts. + ExprResult CurInitExprRes = + S.PerformObjectArgumentInitialization(CurInit.take(), /*Qualifier=*/0, + FoundFn, Conversion); + if(CurInitExprRes.isInvalid()) + return ExprError(); + CurInit = move(CurInitExprRes); + + // Build the actual call to the conversion function. + CurInit = S.BuildCXXMemberCallExpr(CurInit.get(), FoundFn, Conversion, + HadMultipleCandidates); + if (CurInit.isInvalid() || !CurInit.get()) + return ExprError(); + + CastKind = CK_UserDefinedConversion; + + CreatedObject = Conversion->getResultType()->isRecordType(); + } + + bool RequiresCopy = !IsCopy && !isReferenceBinding(Steps.back()); + bool MaybeBindToTemp = RequiresCopy || shouldBindAsTemporary(Entity); + + if (!MaybeBindToTemp && CreatedObject && shouldDestroyTemporary(Entity)) { + QualType T = CurInit.get()->getType(); + if (const RecordType *Record = T->getAs()) { + CXXDestructorDecl *Destructor + = S.LookupDestructor(cast(Record->getDecl())); + S.CheckDestructorAccess(CurInit.get()->getLocStart(), Destructor, + S.PDiag(diag::err_access_dtor_temp) << T); + S.MarkFunctionReferenced(CurInit.get()->getLocStart(), Destructor); + S.DiagnoseUseOfDecl(Destructor, CurInit.get()->getLocStart()); + } + } + + CurInit = S.Owned(ImplicitCastExpr::Create(S.Context, + CurInit.get()->getType(), + CastKind, CurInit.get(), 0, + CurInit.get()->getValueKind())); + if (MaybeBindToTemp) + CurInit = S.MaybeBindToTemporary(CurInit.takeAs()); + if (RequiresCopy) + CurInit = CopyObject(S, Entity.getType().getNonReferenceType(), Entity, + move(CurInit), /*IsExtraneousCopy=*/false); + break; + } + + case SK_QualificationConversionLValue: + case SK_QualificationConversionXValue: + case SK_QualificationConversionRValue: { + // Perform a qualification conversion; these can never go wrong. + ExprValueKind VK = + Step->Kind == SK_QualificationConversionLValue ? + VK_LValue : + (Step->Kind == SK_QualificationConversionXValue ? + VK_XValue : + VK_RValue); + CurInit = S.ImpCastExprToType(CurInit.take(), Step->Type, CK_NoOp, VK); + break; + } + + case SK_ConversionSequence: { + Sema::CheckedConversionKind CCK + = Kind.isCStyleCast()? Sema::CCK_CStyleCast + : Kind.isFunctionalCast()? Sema::CCK_FunctionalCast + : Kind.isExplicitCast()? Sema::CCK_OtherCast + : Sema::CCK_ImplicitConversion; + ExprResult CurInitExprRes = + S.PerformImplicitConversion(CurInit.get(), Step->Type, *Step->ICS, + getAssignmentAction(Entity), CCK); + if (CurInitExprRes.isInvalid()) + return ExprError(); + CurInit = move(CurInitExprRes); + break; + } + + case SK_ListInitialization: { + InitListExpr *InitList = cast(CurInit.get()); + // Hack: We must pass *ResultType if available in order to set the type + // of arrays, e.g. in 'int ar[] = {1, 2, 3};'. + // But in 'const X &x = {1, 2, 3};' we're supposed to initialize a + // temporary, not a reference, so we should pass Ty. + // Worst case: 'const int (&arref)[] = {1, 2, 3};'. + // Since this step is never used for a reference directly, we explicitly + // unwrap references here and rewrap them afterwards. + // We also need to create a InitializeTemporary entity for this. + QualType Ty = ResultType ? ResultType->getNonReferenceType() : Step->Type; + bool IsTemporary = Entity.getType()->isReferenceType(); + InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(Ty); + InitListChecker PerformInitList(S, IsTemporary ? TempEntity : Entity, + InitList, Ty, /*VerifyOnly=*/false, + Kind.getKind() != InitializationKind::IK_DirectList || + !S.getLangOpts().CPlusPlus0x); + if (PerformInitList.HadError()) + return ExprError(); + + if (ResultType) { + if ((*ResultType)->isRValueReferenceType()) + Ty = S.Context.getRValueReferenceType(Ty); + else if ((*ResultType)->isLValueReferenceType()) + Ty = S.Context.getLValueReferenceType(Ty, + (*ResultType)->getAs()->isSpelledAsLValue()); + *ResultType = Ty; + } + + InitListExpr *StructuredInitList = + PerformInitList.getFullyStructuredList(); + CurInit.release(); + CurInit = S.Owned(StructuredInitList); + break; + } + + case SK_ListConstructorCall: { + // When an initializer list is passed for a parameter of type "reference + // to object", we don't get an EK_Temporary entity, but instead an + // EK_Parameter entity with reference type. + // FIXME: This is a hack. What we really should do is create a user + // conversion step for this case, but this makes it considerably more + // complicated. For now, this will do. + InitializedEntity TempEntity = InitializedEntity::InitializeTemporary( + Entity.getType().getNonReferenceType()); + bool UseTemporary = Entity.getType()->isReferenceType(); + InitListExpr *InitList = cast(CurInit.get()); + MultiExprArg Arg(InitList->getInits(), InitList->getNumInits()); + CurInit = PerformConstructorInitialization(S, UseTemporary ? TempEntity : + Entity, + Kind, move(Arg), *Step, + ConstructorInitRequiresZeroInit); + break; + } + + case SK_UnwrapInitList: + CurInit = S.Owned(cast(CurInit.take())->getInit(0)); + break; + + case SK_RewrapInitList: { + Expr *E = CurInit.take(); + InitListExpr *Syntactic = Step->WrappingSyntacticList; + InitListExpr *ILE = new (S.Context) InitListExpr(S.Context, + Syntactic->getLBraceLoc(), &E, 1, Syntactic->getRBraceLoc()); + ILE->setSyntacticForm(Syntactic); + ILE->setType(E->getType()); + ILE->setValueKind(E->getValueKind()); + CurInit = S.Owned(ILE); + break; + } + + case SK_ConstructorInitialization: { + // When an initializer list is passed for a parameter of type "reference + // to object", we don't get an EK_Temporary entity, but instead an + // EK_Parameter entity with reference type. + // FIXME: This is a hack. What we really should do is create a user + // conversion step for this case, but this makes it considerably more + // complicated. For now, this will do. + InitializedEntity TempEntity = InitializedEntity::InitializeTemporary( + Entity.getType().getNonReferenceType()); + bool UseTemporary = Entity.getType()->isReferenceType(); + CurInit = PerformConstructorInitialization(S, UseTemporary ? TempEntity + : Entity, + Kind, move(Args), *Step, + ConstructorInitRequiresZeroInit); + break; + } + + case SK_ZeroInitialization: { + step_iterator NextStep = Step; + ++NextStep; + if (NextStep != StepEnd && + NextStep->Kind == SK_ConstructorInitialization) { + // The need for zero-initialization is recorded directly into + // the call to the object's constructor within the next step. + ConstructorInitRequiresZeroInit = true; + } else if (Kind.getKind() == InitializationKind::IK_Value && + S.getLangOpts().CPlusPlus && + !Kind.isImplicitValueInit()) { + TypeSourceInfo *TSInfo = Entity.getTypeSourceInfo(); + if (!TSInfo) + TSInfo = S.Context.getTrivialTypeSourceInfo(Step->Type, + Kind.getRange().getBegin()); + + CurInit = S.Owned(new (S.Context) CXXScalarValueInitExpr( + TSInfo->getType().getNonLValueExprType(S.Context), + TSInfo, + Kind.getRange().getEnd())); + } else { + CurInit = S.Owned(new (S.Context) ImplicitValueInitExpr(Step->Type)); + } + break; + } + + case SK_CAssignment: { + QualType SourceType = CurInit.get()->getType(); + ExprResult Result = move(CurInit); + Sema::AssignConvertType ConvTy = + S.CheckSingleAssignmentConstraints(Step->Type, Result); + if (Result.isInvalid()) + return ExprError(); + CurInit = move(Result); + + // If this is a call, allow conversion to a transparent union. + ExprResult CurInitExprRes = move(CurInit); + if (ConvTy != Sema::Compatible && + Entity.getKind() == InitializedEntity::EK_Parameter && + S.CheckTransparentUnionArgumentConstraints(Step->Type, CurInitExprRes) + == Sema::Compatible) + ConvTy = Sema::Compatible; + if (CurInitExprRes.isInvalid()) + return ExprError(); + CurInit = move(CurInitExprRes); + + bool Complained; + if (S.DiagnoseAssignmentResult(ConvTy, Kind.getLocation(), + Step->Type, SourceType, + CurInit.get(), + getAssignmentAction(Entity), + &Complained)) { + PrintInitLocationNote(S, Entity); + return ExprError(); + } else if (Complained) + PrintInitLocationNote(S, Entity); + break; + } + + case SK_StringInit: { + QualType Ty = Step->Type; + CheckStringInit(CurInit.get(), ResultType ? *ResultType : Ty, + S.Context.getAsArrayType(Ty), S); + break; + } + + case SK_ObjCObjectConversion: + CurInit = S.ImpCastExprToType(CurInit.take(), Step->Type, + CK_ObjCObjectLValueCast, + CurInit.get()->getValueKind()); + break; + + case SK_ArrayInit: + // Okay: we checked everything before creating this step. Note that + // this is a GNU extension. + S.Diag(Kind.getLocation(), diag::ext_array_init_copy) + << Step->Type << CurInit.get()->getType() + << CurInit.get()->getSourceRange(); + + // If the destination type is an incomplete array type, update the + // type accordingly. + if (ResultType) { + if (const IncompleteArrayType *IncompleteDest + = S.Context.getAsIncompleteArrayType(Step->Type)) { + if (const ConstantArrayType *ConstantSource + = S.Context.getAsConstantArrayType(CurInit.get()->getType())) { + *ResultType = S.Context.getConstantArrayType( + IncompleteDest->getElementType(), + ConstantSource->getSize(), + ArrayType::Normal, 0); + } + } + } + break; + + case SK_ParenthesizedArrayInit: + // Okay: we checked everything before creating this step. Note that + // this is a GNU extension. + S.Diag(Kind.getLocation(), diag::ext_array_init_parens) + << CurInit.get()->getSourceRange(); + break; + + case SK_PassByIndirectCopyRestore: + case SK_PassByIndirectRestore: + checkIndirectCopyRestoreSource(S, CurInit.get()); + CurInit = S.Owned(new (S.Context) + ObjCIndirectCopyRestoreExpr(CurInit.take(), Step->Type, + Step->Kind == SK_PassByIndirectCopyRestore)); + break; + + case SK_ProduceObjCObject: + CurInit = S.Owned(ImplicitCastExpr::Create(S.Context, Step->Type, + CK_ARCProduceObject, + CurInit.take(), 0, VK_RValue)); + break; + + case SK_StdInitializerList: { + QualType Dest = Step->Type; + QualType E; + bool Success = S.isStdInitializerList(Dest, &E); + (void)Success; + assert(Success && "Destination type changed?"); + + // If the element type has a destructor, check it. + if (CXXRecordDecl *RD = E->getAsCXXRecordDecl()) { + if (!RD->hasIrrelevantDestructor()) { + if (CXXDestructorDecl *Destructor = S.LookupDestructor(RD)) { + S.MarkFunctionReferenced(Kind.getLocation(), Destructor); + S.CheckDestructorAccess(Kind.getLocation(), Destructor, + S.PDiag(diag::err_access_dtor_temp) << E); + S.DiagnoseUseOfDecl(Destructor, Kind.getLocation()); + } + } + } + + InitListExpr *ILE = cast(CurInit.take()); + unsigned NumInits = ILE->getNumInits(); + SmallVector Converted(NumInits); + InitializedEntity HiddenArray = InitializedEntity::InitializeTemporary( + S.Context.getConstantArrayType(E, + llvm::APInt(S.Context.getTypeSize(S.Context.getSizeType()), + NumInits), + ArrayType::Normal, 0)); + InitializedEntity Element =InitializedEntity::InitializeElement(S.Context, + 0, HiddenArray); + for (unsigned i = 0; i < NumInits; ++i) { + Element.setElementIndex(i); + ExprResult Init = S.Owned(ILE->getInit(i)); + ExprResult Res = S.PerformCopyInitialization(Element, + Init.get()->getExprLoc(), + Init); + assert(!Res.isInvalid() && "Result changed since try phase."); + Converted[i] = Res.take(); + } + InitListExpr *Semantic = new (S.Context) + InitListExpr(S.Context, ILE->getLBraceLoc(), + Converted.data(), NumInits, ILE->getRBraceLoc()); + Semantic->setSyntacticForm(ILE); + Semantic->setType(Dest); + Semantic->setInitializesStdInitializerList(); + CurInit = S.Owned(Semantic); + break; + } + } + } + + // Diagnose non-fatal problems with the completed initialization. + if (Entity.getKind() == InitializedEntity::EK_Member && + cast(Entity.getDecl())->isBitField()) + S.CheckBitFieldInitialization(Kind.getLocation(), + cast(Entity.getDecl()), + CurInit.get()); + + return move(CurInit); +} + +//===----------------------------------------------------------------------===// +// Diagnose initialization failures +//===----------------------------------------------------------------------===// +bool InitializationSequence::Diagnose(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + Expr **Args, unsigned NumArgs) { + if (!Failed()) + return false; + + QualType DestType = Entity.getType(); + switch (Failure) { + case FK_TooManyInitsForReference: + // FIXME: Customize for the initialized entity? + if (NumArgs == 0) + S.Diag(Kind.getLocation(), diag::err_reference_without_init) + << DestType.getNonReferenceType(); + else // FIXME: diagnostic below could be better! + S.Diag(Kind.getLocation(), diag::err_reference_has_multiple_inits) + << SourceRange(Args[0]->getLocStart(), Args[NumArgs - 1]->getLocEnd()); + break; + + case FK_ArrayNeedsInitList: + case FK_ArrayNeedsInitListOrStringLiteral: + S.Diag(Kind.getLocation(), diag::err_array_init_not_init_list) + << (Failure == FK_ArrayNeedsInitListOrStringLiteral); + break; + + case FK_ArrayTypeMismatch: + case FK_NonConstantArrayInit: + S.Diag(Kind.getLocation(), + (Failure == FK_ArrayTypeMismatch + ? diag::err_array_init_different_type + : diag::err_array_init_non_constant_array)) + << DestType.getNonReferenceType() + << Args[0]->getType() + << Args[0]->getSourceRange(); + break; + + case FK_VariableLengthArrayHasInitializer: + S.Diag(Kind.getLocation(), diag::err_variable_object_no_init) + << Args[0]->getSourceRange(); + break; + + case FK_AddressOfOverloadFailed: { + DeclAccessPair Found; + S.ResolveAddressOfOverloadedFunction(Args[0], + DestType.getNonReferenceType(), + true, + Found); + break; + } + + case FK_ReferenceInitOverloadFailed: + case FK_UserConversionOverloadFailed: + switch (FailedOverloadResult) { + case OR_Ambiguous: + if (Failure == FK_UserConversionOverloadFailed) + S.Diag(Kind.getLocation(), diag::err_typecheck_ambiguous_condition) + << Args[0]->getType() << DestType + << Args[0]->getSourceRange(); + else + S.Diag(Kind.getLocation(), diag::err_ref_init_ambiguous) + << DestType << Args[0]->getType() + << Args[0]->getSourceRange(); + + FailedCandidateSet.NoteCandidates(S, OCD_ViableCandidates, + llvm::makeArrayRef(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(); + FailedCandidateSet.NoteCandidates(S, OCD_AllCandidates, + llvm::makeArrayRef(Args, NumArgs)); + break; + + case OR_Deleted: { + S.Diag(Kind.getLocation(), diag::err_typecheck_deleted_function) + << Args[0]->getType() << DestType.getNonReferenceType() + << Args[0]->getSourceRange(); + OverloadCandidateSet::iterator Best; + OverloadingResult Ovl + = FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best, + true); + if (Ovl == OR_Deleted) { + S.NoteDeletedFunction(Best->Function); + } else { + llvm_unreachable("Inconsistent overload resolution?"); + } + break; + } + + case OR_Success: + llvm_unreachable("Conversion did not fail!"); + } + break; + + case FK_NonConstLValueReferenceBindingToTemporary: + if (isa(Args[0])) { + S.Diag(Kind.getLocation(), + diag::err_lvalue_reference_bind_to_initlist) + << DestType.getNonReferenceType().isVolatileQualified() + << DestType.getNonReferenceType() + << Args[0]->getSourceRange(); + break; + } + // Intentional fallthrough + + case FK_NonConstLValueReferenceBindingToUnrelated: + S.Diag(Kind.getLocation(), + Failure == FK_NonConstLValueReferenceBindingToTemporary + ? diag::err_lvalue_reference_bind_to_temporary + : diag::err_lvalue_reference_bind_to_unrelated) + << DestType.getNonReferenceType().isVolatileQualified() + << DestType.getNonReferenceType() + << Args[0]->getType() + << Args[0]->getSourceRange(); + break; + + case FK_RValueReferenceBindingToLValue: + S.Diag(Kind.getLocation(), diag::err_lvalue_to_rvalue_ref) + << DestType.getNonReferenceType() << Args[0]->getType() + << Args[0]->getSourceRange(); + break; + + case FK_ReferenceInitDropsQualifiers: + S.Diag(Kind.getLocation(), diag::err_reference_bind_drops_quals) + << DestType.getNonReferenceType() + << Args[0]->getType() + << Args[0]->getSourceRange(); + break; + + case FK_ReferenceInitFailed: + S.Diag(Kind.getLocation(), diag::err_reference_bind_failed) + << DestType.getNonReferenceType() + << Args[0]->isLValue() + << Args[0]->getType() + << Args[0]->getSourceRange(); + if (DestType.getNonReferenceType()->isObjCObjectPointerType() && + Args[0]->getType()->isObjCObjectPointerType()) + S.EmitRelatedResultTypeNote(Args[0]); + break; + + case FK_ConversionFailed: { + QualType FromType = Args[0]->getType(); + PartialDiagnostic PDiag = S.PDiag(diag::err_init_conversion_failed) + << (int)Entity.getKind() + << DestType + << Args[0]->isLValue() + << FromType + << Args[0]->getSourceRange(); + S.HandleFunctionTypeMismatch(PDiag, FromType, DestType); + S.Diag(Kind.getLocation(), PDiag); + if (DestType.getNonReferenceType()->isObjCObjectPointerType() && + Args[0]->getType()->isObjCObjectPointerType()) + S.EmitRelatedResultTypeNote(Args[0]); + break; + } + + case FK_ConversionFromPropertyFailed: + // No-op. This error has already been reported. + break; + + case FK_TooManyInitsForScalar: { + SourceRange R; + + if (InitListExpr *InitList = dyn_cast(Args[0])) + R = SourceRange(InitList->getInit(0)->getLocEnd(), + InitList->getLocEnd()); + else + R = SourceRange(Args[0]->getLocEnd(), Args[NumArgs - 1]->getLocEnd()); + + R.setBegin(S.PP.getLocForEndOfToken(R.getBegin())); + if (Kind.isCStyleOrFunctionalCast()) + S.Diag(Kind.getLocation(), diag::err_builtin_func_cast_more_than_one_arg) + << R; + else + S.Diag(Kind.getLocation(), diag::err_excess_initializers) + << /*scalar=*/2 << R; + break; + } + + case FK_ReferenceBindingToInitList: + S.Diag(Kind.getLocation(), diag::err_reference_bind_init_list) + << DestType.getNonReferenceType() << Args[0]->getSourceRange(); + break; + + case FK_InitListBadDestinationType: + S.Diag(Kind.getLocation(), diag::err_init_list_bad_dest_type) + << (DestType->isRecordType()) << DestType << Args[0]->getSourceRange(); + break; + + case FK_ListConstructorOverloadFailed: + case FK_ConstructorOverloadFailed: { + SourceRange ArgsRange; + if (NumArgs) + ArgsRange = SourceRange(Args[0]->getLocStart(), + Args[NumArgs - 1]->getLocEnd()); + + if (Failure == FK_ListConstructorOverloadFailed) { + assert(NumArgs == 1 && "List construction from other than 1 argument."); + InitListExpr *InitList = cast(Args[0]); + Args = InitList->getInits(); + NumArgs = InitList->getNumInits(); + } + + // FIXME: Using "DestType" for the entity we're printing is probably + // bad. + switch (FailedOverloadResult) { + case OR_Ambiguous: + S.Diag(Kind.getLocation(), diag::err_ovl_ambiguous_init) + << DestType << ArgsRange; + FailedCandidateSet.NoteCandidates(S, OCD_ViableCandidates, + llvm::makeArrayRef(Args, NumArgs)); + break; + + case OR_No_Viable_Function: + if (Kind.getKind() == InitializationKind::IK_Default && + (Entity.getKind() == InitializedEntity::EK_Base || + Entity.getKind() == InitializedEntity::EK_Member) && + isa(S.CurContext)) { + // This is implicit default initialization of a member or + // base within a constructor. If no viable function was + // found, notify the user that she needs to explicitly + // initialize this base/member. + CXXConstructorDecl *Constructor + = cast(S.CurContext); + if (Entity.getKind() == InitializedEntity::EK_Base) { + S.Diag(Kind.getLocation(), diag::err_missing_default_ctor) + << Constructor->isImplicit() + << S.Context.getTypeDeclType(Constructor->getParent()) + << /*base=*/0 + << Entity.getType(); + + RecordDecl *BaseDecl + = Entity.getBaseSpecifier()->getType()->getAs() + ->getDecl(); + S.Diag(BaseDecl->getLocation(), diag::note_previous_decl) + << S.Context.getTagDeclType(BaseDecl); + } else { + S.Diag(Kind.getLocation(), diag::err_missing_default_ctor) + << Constructor->isImplicit() + << S.Context.getTypeDeclType(Constructor->getParent()) + << /*member=*/1 + << Entity.getName(); + S.Diag(Entity.getDecl()->getLocation(), diag::note_field_decl); + + if (const RecordType *Record + = Entity.getType()->getAs()) + S.Diag(Record->getDecl()->getLocation(), + diag::note_previous_decl) + << S.Context.getTagDeclType(Record->getDecl()); + } + break; + } + + S.Diag(Kind.getLocation(), diag::err_ovl_no_viable_function_in_init) + << DestType << ArgsRange; + FailedCandidateSet.NoteCandidates(S, OCD_AllCandidates, + llvm::makeArrayRef(Args, NumArgs)); + break; + + case OR_Deleted: { + OverloadCandidateSet::iterator Best; + OverloadingResult Ovl + = FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best); + if (Ovl != OR_Deleted) { + S.Diag(Kind.getLocation(), diag::err_ovl_deleted_init) + << true << DestType << ArgsRange; + llvm_unreachable("Inconsistent overload resolution?"); + break; + } + + // If this is a defaulted or implicitly-declared function, then + // it was implicitly deleted. Make it clear that the deletion was + // implicit. + if (S.isImplicitlyDeleted(Best->Function)) + S.Diag(Kind.getLocation(), diag::err_ovl_deleted_special_init) + << S.getSpecialMember(cast(Best->Function)) + << DestType << ArgsRange; + else + S.Diag(Kind.getLocation(), diag::err_ovl_deleted_init) + << true << DestType << ArgsRange; + + S.NoteDeletedFunction(Best->Function); + break; + } + + case OR_Success: + llvm_unreachable("Conversion did not fail!"); + } + } + break; + + case FK_DefaultInitOfConst: + if (Entity.getKind() == InitializedEntity::EK_Member && + isa(S.CurContext)) { + // This is implicit default-initialization of a const member in + // a constructor. Complain that it needs to be explicitly + // initialized. + CXXConstructorDecl *Constructor = cast(S.CurContext); + S.Diag(Kind.getLocation(), diag::err_uninitialized_member_in_ctor) + << Constructor->isImplicit() + << S.Context.getTypeDeclType(Constructor->getParent()) + << /*const=*/1 + << Entity.getName(); + S.Diag(Entity.getDecl()->getLocation(), diag::note_previous_decl) + << Entity.getName(); + } else { + S.Diag(Kind.getLocation(), diag::err_default_init_const) + << DestType << (bool)DestType->getAs(); + } + break; + + case FK_Incomplete: + S.RequireCompleteType(Kind.getLocation(), FailedIncompleteType, + diag::err_init_incomplete_type); + break; + + case FK_ListInitializationFailed: { + // Run the init list checker again to emit diagnostics. + InitListExpr* InitList = cast(Args[0]); + QualType DestType = Entity.getType(); + InitListChecker DiagnoseInitList(S, Entity, InitList, + DestType, /*VerifyOnly=*/false, + Kind.getKind() != InitializationKind::IK_DirectList || + !S.getLangOpts().CPlusPlus0x); + assert(DiagnoseInitList.HadError() && + "Inconsistent init list check result."); + break; + } + + case FK_PlaceholderType: { + // FIXME: Already diagnosed! + break; + } + + case FK_InitListElementCopyFailure: { + // Try to perform all copies again. + InitListExpr* InitList = cast(Args[0]); + unsigned NumInits = InitList->getNumInits(); + QualType DestType = Entity.getType(); + QualType E; + bool Success = S.isStdInitializerList(DestType, &E); + (void)Success; + assert(Success && "Where did the std::initializer_list go?"); + InitializedEntity HiddenArray = InitializedEntity::InitializeTemporary( + S.Context.getConstantArrayType(E, + llvm::APInt(S.Context.getTypeSize(S.Context.getSizeType()), + NumInits), + ArrayType::Normal, 0)); + InitializedEntity Element = InitializedEntity::InitializeElement(S.Context, + 0, HiddenArray); + // Show at most 3 errors. Otherwise, you'd get a lot of errors for errors + // where the init list type is wrong, e.g. + // std::initializer_list list = { 1, 2, 3, 4, 5, 6, 7, 8 }; + // FIXME: Emit a note if we hit the limit? + int ErrorCount = 0; + for (unsigned i = 0; i < NumInits && ErrorCount < 3; ++i) { + Element.setElementIndex(i); + ExprResult Init = S.Owned(InitList->getInit(i)); + if (S.PerformCopyInitialization(Element, Init.get()->getExprLoc(), Init) + .isInvalid()) + ++ErrorCount; + } + break; + } + + case FK_ExplicitConstructor: { + S.Diag(Kind.getLocation(), diag::err_selected_explicit_constructor) + << Args[0]->getSourceRange(); + OverloadCandidateSet::iterator Best; + OverloadingResult Ovl + = FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best); + (void)Ovl; + assert(Ovl == OR_Success && "Inconsistent overload resolution"); + CXXConstructorDecl *CtorDecl = cast(Best->Function); + S.Diag(CtorDecl->getLocation(), diag::note_constructor_declared_here); + break; + } + } + + PrintInitLocationNote(S, Entity); + return true; +} + +void InitializationSequence::dump(raw_ostream &OS) const { + switch (SequenceKind) { + case FailedSequence: { + OS << "Failed sequence: "; + switch (Failure) { + case FK_TooManyInitsForReference: + OS << "too many initializers for reference"; + break; + + case FK_ArrayNeedsInitList: + OS << "array requires initializer list"; + break; + + case FK_ArrayNeedsInitListOrStringLiteral: + OS << "array requires initializer list or string literal"; + break; + + case FK_ArrayTypeMismatch: + OS << "array type mismatch"; + break; + + case FK_NonConstantArrayInit: + OS << "non-constant array initializer"; + break; + + case FK_AddressOfOverloadFailed: + OS << "address of overloaded function failed"; + break; + + case FK_ReferenceInitOverloadFailed: + OS << "overload resolution for reference initialization failed"; + break; + + case FK_NonConstLValueReferenceBindingToTemporary: + OS << "non-const lvalue reference bound to temporary"; + break; + + case FK_NonConstLValueReferenceBindingToUnrelated: + OS << "non-const lvalue reference bound to unrelated type"; + break; + + case FK_RValueReferenceBindingToLValue: + OS << "rvalue reference bound to an lvalue"; + break; + + case FK_ReferenceInitDropsQualifiers: + OS << "reference initialization drops qualifiers"; + break; + + case FK_ReferenceInitFailed: + OS << "reference initialization failed"; + break; + + case FK_ConversionFailed: + OS << "conversion failed"; + break; + + case FK_ConversionFromPropertyFailed: + OS << "conversion from property failed"; + break; + + case FK_TooManyInitsForScalar: + OS << "too many initializers for scalar"; + break; + + case FK_ReferenceBindingToInitList: + OS << "referencing binding to initializer list"; + break; + + case FK_InitListBadDestinationType: + OS << "initializer list for non-aggregate, non-scalar type"; + break; + + case FK_UserConversionOverloadFailed: + OS << "overloading failed for user-defined conversion"; + break; + + case FK_ConstructorOverloadFailed: + OS << "constructor overloading failed"; + break; + + case FK_DefaultInitOfConst: + OS << "default initialization of a const variable"; + break; + + case FK_Incomplete: + OS << "initialization of incomplete type"; + break; + + case FK_ListInitializationFailed: + OS << "list initialization checker failure"; + break; + + case FK_VariableLengthArrayHasInitializer: + OS << "variable length array has an initializer"; + break; + + case FK_PlaceholderType: + OS << "initializer expression isn't contextually valid"; + break; + + case FK_ListConstructorOverloadFailed: + OS << "list constructor overloading failed"; + break; + + case FK_InitListElementCopyFailure: + OS << "copy construction of initializer list element failed"; + break; + + case FK_ExplicitConstructor: + OS << "list copy initialization chose explicit constructor"; + break; + } + OS << '\n'; + return; + } + + case DependentSequence: + OS << "Dependent sequence\n"; + return; + + case NormalSequence: + OS << "Normal sequence: "; + break; + } + + for (step_iterator S = step_begin(), SEnd = step_end(); S != SEnd; ++S) { + if (S != step_begin()) { + OS << " -> "; + } + + switch (S->Kind) { + case SK_ResolveAddressOfOverloadedFunction: + OS << "resolve address of overloaded function"; + break; + + case SK_CastDerivedToBaseRValue: + 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; + + case SK_BindReference: + OS << "bind reference to lvalue"; + break; + + case SK_BindReferenceToTemporary: + OS << "bind reference to a temporary"; + break; + + case SK_ExtraneousCopyToTemporary: + OS << "extraneous C++03 copy to temporary"; + break; + + case SK_UserConversion: + OS << "user-defined conversion via " << *S->Function.Function; + break; + + case SK_QualificationConversionRValue: + OS << "qualification conversion (rvalue)"; + break; + + case SK_QualificationConversionXValue: + OS << "qualification conversion (xvalue)"; + break; + + case SK_QualificationConversionLValue: + OS << "qualification conversion (lvalue)"; + break; + + case SK_ConversionSequence: + OS << "implicit conversion sequence ("; + S->ICS->DebugPrint(); // FIXME: use OS + OS << ")"; + break; + + case SK_ListInitialization: + OS << "list aggregate initialization"; + break; + + case SK_ListConstructorCall: + OS << "list initialization via constructor"; + break; + + case SK_UnwrapInitList: + OS << "unwrap reference initializer list"; + break; + + case SK_RewrapInitList: + OS << "rewrap reference initializer list"; + break; + + case SK_ConstructorInitialization: + OS << "constructor initialization"; + break; + + case SK_ZeroInitialization: + OS << "zero initialization"; + break; + + case SK_CAssignment: + OS << "C assignment"; + break; + + case SK_StringInit: + OS << "string initialization"; + break; + + case SK_ObjCObjectConversion: + OS << "Objective-C object conversion"; + break; + + case SK_ArrayInit: + OS << "array initialization"; + break; + + case SK_ParenthesizedArrayInit: + OS << "parenthesized array initialization"; + break; + + case SK_PassByIndirectCopyRestore: + OS << "pass by indirect copy and restore"; + break; + + case SK_PassByIndirectRestore: + OS << "pass by indirect restore"; + break; + + case SK_ProduceObjCObject: + OS << "Objective-C object retension"; + break; + + case SK_StdInitializerList: + OS << "std::initializer_list from initializer list"; + break; + } + } +} + +void InitializationSequence::dump() const { + dump(llvm::errs()); +} + +static void DiagnoseNarrowingInInitList(Sema &S, InitializationSequence &Seq, + QualType EntityType, + const Expr *PreInit, + const Expr *PostInit) { + if (Seq.step_begin() == Seq.step_end() || PreInit->isValueDependent()) + return; + + // A narrowing conversion can only appear as the final implicit conversion in + // an initialization sequence. + const InitializationSequence::Step &LastStep = Seq.step_end()[-1]; + if (LastStep.Kind != InitializationSequence::SK_ConversionSequence) + return; + + const ImplicitConversionSequence &ICS = *LastStep.ICS; + const StandardConversionSequence *SCS = 0; + switch (ICS.getKind()) { + case ImplicitConversionSequence::StandardConversion: + SCS = &ICS.Standard; + break; + case ImplicitConversionSequence::UserDefinedConversion: + SCS = &ICS.UserDefined.After; + break; + case ImplicitConversionSequence::AmbiguousConversion: + case ImplicitConversionSequence::EllipsisConversion: + case ImplicitConversionSequence::BadConversion: + return; + } + + // Determine the type prior to the narrowing conversion. If a conversion + // operator was used, this may be different from both the type of the entity + // and of the pre-initialization expression. + QualType PreNarrowingType = PreInit->getType(); + if (Seq.step_begin() + 1 != Seq.step_end()) + PreNarrowingType = Seq.step_end()[-2].Type; + + // C++11 [dcl.init.list]p7: Check whether this is a narrowing conversion. + APValue ConstantValue; + QualType ConstantType; + switch (SCS->getNarrowingKind(S.Context, PostInit, ConstantValue, + ConstantType)) { + case NK_Not_Narrowing: + // No narrowing occurred. + return; + + case NK_Type_Narrowing: + // This was a floating-to-integer conversion, which is always considered a + // narrowing conversion even if the value is a constant and can be + // represented exactly as an integer. + S.Diag(PostInit->getLocStart(), + S.getLangOpts().MicrosoftExt || !S.getLangOpts().CPlusPlus0x? + diag::warn_init_list_type_narrowing + : S.isSFINAEContext()? + diag::err_init_list_type_narrowing_sfinae + : diag::err_init_list_type_narrowing) + << PostInit->getSourceRange() + << PreNarrowingType.getLocalUnqualifiedType() + << EntityType.getLocalUnqualifiedType(); + break; + + case NK_Constant_Narrowing: + // A constant value was narrowed. + S.Diag(PostInit->getLocStart(), + S.getLangOpts().MicrosoftExt || !S.getLangOpts().CPlusPlus0x? + diag::warn_init_list_constant_narrowing + : S.isSFINAEContext()? + diag::err_init_list_constant_narrowing_sfinae + : diag::err_init_list_constant_narrowing) + << PostInit->getSourceRange() + << ConstantValue.getAsString(S.getASTContext(), ConstantType) + << EntityType.getLocalUnqualifiedType(); + break; + + case NK_Variable_Narrowing: + // A variable's value may have been narrowed. + S.Diag(PostInit->getLocStart(), + S.getLangOpts().MicrosoftExt || !S.getLangOpts().CPlusPlus0x? + diag::warn_init_list_variable_narrowing + : S.isSFINAEContext()? + diag::err_init_list_variable_narrowing_sfinae + : diag::err_init_list_variable_narrowing) + << PostInit->getSourceRange() + << PreNarrowingType.getLocalUnqualifiedType() + << EntityType.getLocalUnqualifiedType(); + break; + } + + SmallString<128> StaticCast; + llvm::raw_svector_ostream OS(StaticCast); + OS << "static_cast<"; + if (const TypedefType *TT = EntityType->getAs()) { + // It's important to use the typedef's name if there is one so that the + // fixit doesn't break code using types like int64_t. + // + // FIXME: This will break if the typedef requires qualification. But + // getQualifiedNameAsString() includes non-machine-parsable components. + OS << *TT->getDecl(); + } else if (const BuiltinType *BT = EntityType->getAs()) + OS << BT->getName(S.getLangOpts()); + else { + // Oops, we didn't find the actual type of the variable. Don't emit a fixit + // with a broken cast. + return; + } + OS << ">("; + S.Diag(PostInit->getLocStart(), diag::note_init_list_narrowing_override) + << PostInit->getSourceRange() + << FixItHint::CreateInsertion(PostInit->getLocStart(), OS.str()) + << FixItHint::CreateInsertion( + S.getPreprocessor().getLocForEndOfToken(PostInit->getLocEnd()), ")"); +} + +//===----------------------------------------------------------------------===// +// Initialization helper functions +//===----------------------------------------------------------------------===// +bool +Sema::CanPerformCopyInitialization(const InitializedEntity &Entity, + ExprResult Init) { + if (Init.isInvalid()) + return false; + + Expr *InitE = Init.get(); + assert(InitE && "No initialization expression"); + + InitializationKind Kind = InitializationKind::CreateCopy(SourceLocation(), + SourceLocation()); + InitializationSequence Seq(*this, Entity, Kind, &InitE, 1); + return !Seq.Failed(); +} + +ExprResult +Sema::PerformCopyInitialization(const InitializedEntity &Entity, + SourceLocation EqualLoc, + ExprResult Init, + bool TopLevelOfInitList, + bool AllowExplicit) { + if (Init.isInvalid()) + return ExprError(); + + Expr *InitE = Init.get(); + assert(InitE && "No initialization expression?"); + + if (EqualLoc.isInvalid()) + EqualLoc = InitE->getLocStart(); + + InitializationKind Kind = InitializationKind::CreateCopy(InitE->getLocStart(), + EqualLoc, + AllowExplicit); + InitializationSequence Seq(*this, Entity, Kind, &InitE, 1); + Init.release(); + + ExprResult Result = Seq.Perform(*this, Entity, Kind, MultiExprArg(&InitE, 1)); + + if (!Result.isInvalid() && TopLevelOfInitList) + DiagnoseNarrowingInInitList(*this, Seq, Entity.getType(), + InitE, Result.get()); + + return Result; +} diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp new file mode 100644 index 0000000..6ef8d88 --- /dev/null +++ b/clang/lib/Sema/SemaLambda.cpp @@ -0,0 +1,820 @@ +//===--- SemaLambda.cpp - Semantic Analysis for C++11 Lambdas -------------===// +// +// 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 C++ lambda expressions. +// +//===----------------------------------------------------------------------===// +#include "clang/Sema/DeclSpec.h" +#include "clang/Sema/Initialization.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/SemaInternal.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/AST/ExprCXX.h" +using namespace clang; +using namespace sema; + +CXXRecordDecl *Sema::createLambdaClosureType(SourceRange IntroducerRange, + bool KnownDependent) { + DeclContext *DC = CurContext; + while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isFileContext())) + DC = DC->getParent(); + + // Start constructing the lambda class. + CXXRecordDecl *Class = CXXRecordDecl::CreateLambda(Context, DC, + IntroducerRange.getBegin(), + KnownDependent); + DC->addDecl(Class); + + return Class; +} + +/// \brief Determine whether the given context is or is enclosed in an inline +/// function. +static bool isInInlineFunction(const DeclContext *DC) { + while (!DC->isFileContext()) { + if (const FunctionDecl *FD = dyn_cast(DC)) + if (FD->isInlined()) + return true; + + DC = DC->getLexicalParent(); + } + + return false; +} + +CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class, + SourceRange IntroducerRange, + TypeSourceInfo *MethodType, + SourceLocation EndLoc, + llvm::ArrayRef Params, + llvm::Optional ManglingNumber, + Decl *ContextDecl) { + // C++11 [expr.prim.lambda]p5: + // The closure type for a lambda-expression has a public inline function + // call operator (13.5.4) whose parameters and return type are described by + // the lambda-expression's parameter-declaration-clause and + // trailing-return-type respectively. + DeclarationName MethodName + = Context.DeclarationNames.getCXXOperatorName(OO_Call); + DeclarationNameLoc MethodNameLoc; + MethodNameLoc.CXXOperatorName.BeginOpNameLoc + = IntroducerRange.getBegin().getRawEncoding(); + MethodNameLoc.CXXOperatorName.EndOpNameLoc + = IntroducerRange.getEnd().getRawEncoding(); + CXXMethodDecl *Method + = CXXMethodDecl::Create(Context, Class, EndLoc, + DeclarationNameInfo(MethodName, + IntroducerRange.getBegin(), + MethodNameLoc), + MethodType->getType(), MethodType, + /*isStatic=*/false, + SC_None, + /*isInline=*/true, + /*isConstExpr=*/false, + EndLoc); + Method->setAccess(AS_public); + + // Temporarily set the lexical declaration context to the current + // context, so that the Scope stack matches the lexical nesting. + Method->setLexicalDeclContext(CurContext); + + // Add parameters. + if (!Params.empty()) { + Method->setParams(Params); + CheckParmsForFunctionDef(const_cast(Params.begin()), + const_cast(Params.end()), + /*CheckParameterNames=*/false); + + for (CXXMethodDecl::param_iterator P = Method->param_begin(), + PEnd = Method->param_end(); + P != PEnd; ++P) + (*P)->setOwningFunction(Method); + } + + // If we don't already have a mangling number for this lambda expression, + // allocate one now. + if (!ManglingNumber) { + ContextDecl = ExprEvalContexts.back().LambdaContextDecl; + + enum ContextKind { + Normal, + DefaultArgument, + DataMember, + StaticDataMember + } Kind = Normal; + + // Default arguments of member function parameters that appear in a class + // definition, as well as the initializers of data members, receive special + // treatment. Identify them. + if (ContextDecl) { + if (ParmVarDecl *Param = dyn_cast(ContextDecl)) { + if (const DeclContext *LexicalDC + = Param->getDeclContext()->getLexicalParent()) + if (LexicalDC->isRecord()) + Kind = DefaultArgument; + } else if (VarDecl *Var = dyn_cast(ContextDecl)) { + if (Var->getDeclContext()->isRecord()) + Kind = StaticDataMember; + } else if (isa(ContextDecl)) { + Kind = DataMember; + } + } + + switch (Kind) { + case Normal: + if (CurContext->isDependentContext() || isInInlineFunction(CurContext)) + ManglingNumber = Context.getLambdaManglingNumber(Method); + else + ManglingNumber = 0; + + // There is no special context for this lambda. + ContextDecl = 0; + break; + + case StaticDataMember: + if (!CurContext->isDependentContext()) { + ManglingNumber = 0; + ContextDecl = 0; + break; + } + // Fall through to assign a mangling number. + + case DataMember: + case DefaultArgument: + ManglingNumber = ExprEvalContexts.back().getLambdaMangleContext() + .getManglingNumber(Method); + break; + } + } + + Class->setLambdaMangling(*ManglingNumber, ContextDecl); + return Method; +} + +LambdaScopeInfo *Sema::enterLambdaScope(CXXMethodDecl *CallOperator, + SourceRange IntroducerRange, + LambdaCaptureDefault CaptureDefault, + bool ExplicitParams, + bool ExplicitResultType, + bool Mutable) { + PushLambdaScope(CallOperator->getParent(), CallOperator); + LambdaScopeInfo *LSI = getCurLambda(); + if (CaptureDefault == LCD_ByCopy) + LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByval; + else if (CaptureDefault == LCD_ByRef) + LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByref; + LSI->IntroducerRange = IntroducerRange; + LSI->ExplicitParams = ExplicitParams; + LSI->Mutable = Mutable; + + if (ExplicitResultType) { + LSI->ReturnType = CallOperator->getResultType(); + + if (!LSI->ReturnType->isDependentType() && + !LSI->ReturnType->isVoidType()) { + if (RequireCompleteType(CallOperator->getLocStart(), LSI->ReturnType, + diag::err_lambda_incomplete_result)) { + // Do nothing. + } else if (LSI->ReturnType->isObjCObjectOrInterfaceType()) { + Diag(CallOperator->getLocStart(), diag::err_lambda_objc_object_result) + << LSI->ReturnType; + } + } + } else { + LSI->HasImplicitReturnType = true; + } + + return LSI; +} + +void Sema::finishLambdaExplicitCaptures(LambdaScopeInfo *LSI) { + LSI->finishedExplicitCaptures(); +} + +void Sema::addLambdaParameters(CXXMethodDecl *CallOperator, Scope *CurScope) { + // Introduce our parameters into the function scope + for (unsigned p = 0, NumParams = CallOperator->getNumParams(); + p < NumParams; ++p) { + ParmVarDecl *Param = CallOperator->getParamDecl(p); + + // If this has an identifier, add it to the scope stack. + if (CurScope && Param->getIdentifier()) { + CheckShadow(CurScope, Param); + + PushOnScopeChains(Param, CurScope); + } + } +} + +void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, + Declarator &ParamInfo, + Scope *CurScope) { + // Determine if we're within a context where we know that the lambda will + // be dependent, because there are template parameters in scope. + bool KnownDependent = false; + if (Scope *TmplScope = CurScope->getTemplateParamParent()) + if (!TmplScope->decl_empty()) + KnownDependent = true; + + CXXRecordDecl *Class = createLambdaClosureType(Intro.Range, KnownDependent); + + // Determine the signature of the call operator. + TypeSourceInfo *MethodTyInfo; + bool ExplicitParams = true; + bool ExplicitResultType = true; + SourceLocation EndLoc; + llvm::ArrayRef Params; + if (ParamInfo.getNumTypeObjects() == 0) { + // C++11 [expr.prim.lambda]p4: + // If a lambda-expression does not include a lambda-declarator, it is as + // if the lambda-declarator were (). + FunctionProtoType::ExtProtoInfo EPI; + EPI.HasTrailingReturn = true; + EPI.TypeQuals |= DeclSpec::TQ_const; + QualType MethodTy = Context.getFunctionType(Context.DependentTy, + /*Args=*/0, /*NumArgs=*/0, EPI); + MethodTyInfo = Context.getTrivialTypeSourceInfo(MethodTy); + ExplicitParams = false; + ExplicitResultType = false; + EndLoc = Intro.Range.getEnd(); + } else { + assert(ParamInfo.isFunctionDeclarator() && + "lambda-declarator is a function"); + DeclaratorChunk::FunctionTypeInfo &FTI = ParamInfo.getFunctionTypeInfo(); + + // C++11 [expr.prim.lambda]p5: + // This function call operator is declared const (9.3.1) if and only if + // the lambda-expression's parameter-declaration-clause is not followed + // by mutable. It is neither virtual nor declared volatile. [...] + if (!FTI.hasMutableQualifier()) + FTI.TypeQuals |= DeclSpec::TQ_const; + + MethodTyInfo = GetTypeForDeclarator(ParamInfo, CurScope); + assert(MethodTyInfo && "no type from lambda-declarator"); + EndLoc = ParamInfo.getSourceRange().getEnd(); + + ExplicitResultType + = MethodTyInfo->getType()->getAs()->getResultType() + != Context.DependentTy; + + TypeLoc TL = MethodTyInfo->getTypeLoc(); + FunctionProtoTypeLoc Proto = cast(TL); + Params = llvm::ArrayRef(Proto.getParmArray(), + Proto.getNumArgs()); + } + + CXXMethodDecl *Method = startLambdaDefinition(Class, Intro.Range, + MethodTyInfo, EndLoc, Params); + + if (ExplicitParams) + CheckCXXDefaultArguments(Method); + + // Attributes on the lambda apply to the method. + ProcessDeclAttributes(CurScope, Method, ParamInfo); + + // Introduce the function call operator as the current declaration context. + PushDeclContext(CurScope, Method); + + // Introduce the lambda scope. + LambdaScopeInfo *LSI + = enterLambdaScope(Method, Intro.Range, Intro.Default, ExplicitParams, + ExplicitResultType, + (Method->getTypeQualifiers() & Qualifiers::Const) == 0); + + // Handle explicit captures. + SourceLocation PrevCaptureLoc + = Intro.Default == LCD_None? Intro.Range.getBegin() : Intro.DefaultLoc; + for (llvm::SmallVector::const_iterator + C = Intro.Captures.begin(), + E = Intro.Captures.end(); + C != E; + PrevCaptureLoc = C->Loc, ++C) { + if (C->Kind == LCK_This) { + // C++11 [expr.prim.lambda]p8: + // An identifier or this shall not appear more than once in a + // lambda-capture. + if (LSI->isCXXThisCaptured()) { + Diag(C->Loc, diag::err_capture_more_than_once) + << "'this'" + << SourceRange(LSI->getCXXThisCapture().getLocation()) + << FixItHint::CreateRemoval( + SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc)); + continue; + } + + // C++11 [expr.prim.lambda]p8: + // If a lambda-capture includes a capture-default that is =, the + // lambda-capture shall not contain this [...]. + if (Intro.Default == LCD_ByCopy) { + Diag(C->Loc, diag::err_this_capture_with_copy_default) + << FixItHint::CreateRemoval( + SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc)); + continue; + } + + // C++11 [expr.prim.lambda]p12: + // If this is captured by a local lambda expression, its nearest + // enclosing function shall be a non-static member function. + QualType ThisCaptureType = getCurrentThisType(); + if (ThisCaptureType.isNull()) { + Diag(C->Loc, diag::err_this_capture) << true; + continue; + } + + CheckCXXThisCapture(C->Loc, /*Explicit=*/true); + continue; + } + + assert(C->Id && "missing identifier for capture"); + + // C++11 [expr.prim.lambda]p8: + // If a lambda-capture includes a capture-default that is &, the + // identifiers in the lambda-capture shall not be preceded by &. + // If a lambda-capture includes a capture-default that is =, [...] + // each identifier it contains shall be preceded by &. + if (C->Kind == LCK_ByRef && Intro.Default == LCD_ByRef) { + Diag(C->Loc, diag::err_reference_capture_with_reference_default) + << FixItHint::CreateRemoval( + SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc)); + continue; + } else if (C->Kind == LCK_ByCopy && Intro.Default == LCD_ByCopy) { + Diag(C->Loc, diag::err_copy_capture_with_copy_default) + << FixItHint::CreateRemoval( + SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc)); + continue; + } + + DeclarationNameInfo Name(C->Id, C->Loc); + LookupResult R(*this, Name, LookupOrdinaryName); + LookupName(R, CurScope); + if (R.isAmbiguous()) + continue; + if (R.empty()) { + // FIXME: Disable corrections that would add qualification? + CXXScopeSpec ScopeSpec; + DeclFilterCCC Validator; + if (DiagnoseEmptyLookup(CurScope, ScopeSpec, R, Validator)) + continue; + } + + // C++11 [expr.prim.lambda]p10: + // The identifiers in a capture-list are looked up using the usual rules + // for unqualified name lookup (3.4.1); each such lookup shall find a + // variable with automatic storage duration declared in the reaching + // scope of the local lambda expression. + // + // Note that the 'reaching scope' check happens in tryCaptureVariable(). + VarDecl *Var = R.getAsSingle(); + if (!Var) { + Diag(C->Loc, diag::err_capture_does_not_name_variable) << C->Id; + continue; + } + + if (!Var->hasLocalStorage()) { + Diag(C->Loc, diag::err_capture_non_automatic_variable) << C->Id; + Diag(Var->getLocation(), diag::note_previous_decl) << C->Id; + continue; + } + + // C++11 [expr.prim.lambda]p8: + // An identifier or this shall not appear more than once in a + // lambda-capture. + if (LSI->isCaptured(Var)) { + Diag(C->Loc, diag::err_capture_more_than_once) + << C->Id + << SourceRange(LSI->getCapture(Var).getLocation()) + << FixItHint::CreateRemoval( + SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc)); + continue; + } + + // C++11 [expr.prim.lambda]p23: + // A capture followed by an ellipsis is a pack expansion (14.5.3). + SourceLocation EllipsisLoc; + if (C->EllipsisLoc.isValid()) { + if (Var->isParameterPack()) { + EllipsisLoc = C->EllipsisLoc; + } else { + Diag(C->EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) + << SourceRange(C->Loc); + + // Just ignore the ellipsis. + } + } else if (Var->isParameterPack()) { + Diag(C->Loc, diag::err_lambda_unexpanded_pack); + continue; + } + + TryCaptureKind Kind = C->Kind == LCK_ByRef ? TryCapture_ExplicitByRef : + TryCapture_ExplicitByVal; + tryCaptureVariable(Var, C->Loc, Kind, EllipsisLoc); + } + finishLambdaExplicitCaptures(LSI); + + // Add lambda parameters into scope. + addLambdaParameters(Method, CurScope); + + // Enter a new evaluation context to insulate the lambda from any + // cleanups from the enclosing full-expression. + PushExpressionEvaluationContext(PotentiallyEvaluated); +} + +void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope, + bool IsInstantiation) { + // Leave the expression-evaluation context. + DiscardCleanupsInEvaluationContext(); + PopExpressionEvaluationContext(); + + // Leave the context of the lambda. + if (!IsInstantiation) + PopDeclContext(); + + // Finalize the lambda. + LambdaScopeInfo *LSI = getCurLambda(); + CXXRecordDecl *Class = LSI->Lambda; + Class->setInvalidDecl(); + SmallVector Fields(Class->field_begin(), Class->field_end()); + ActOnFields(0, Class->getLocation(), Class, Fields, + SourceLocation(), SourceLocation(), 0); + CheckCompletedCXXClass(Class); + + PopFunctionScopeInfo(); +} + +/// \brief Add a lambda's conversion to function pointer, as described in +/// C++11 [expr.prim.lambda]p6. +static void addFunctionPointerConversion(Sema &S, + SourceRange IntroducerRange, + CXXRecordDecl *Class, + CXXMethodDecl *CallOperator) { + // Add the conversion to function pointer. + const FunctionProtoType *Proto + = CallOperator->getType()->getAs(); + QualType FunctionPtrTy; + QualType FunctionTy; + { + FunctionProtoType::ExtProtoInfo ExtInfo = Proto->getExtProtoInfo(); + ExtInfo.TypeQuals = 0; + FunctionTy = S.Context.getFunctionType(Proto->getResultType(), + Proto->arg_type_begin(), + Proto->getNumArgs(), + ExtInfo); + FunctionPtrTy = S.Context.getPointerType(FunctionTy); + } + + FunctionProtoType::ExtProtoInfo ExtInfo; + ExtInfo.TypeQuals = Qualifiers::Const; + QualType ConvTy = S.Context.getFunctionType(FunctionPtrTy, 0, 0, ExtInfo); + + SourceLocation Loc = IntroducerRange.getBegin(); + DeclarationName Name + = S.Context.DeclarationNames.getCXXConversionFunctionName( + S.Context.getCanonicalType(FunctionPtrTy)); + DeclarationNameLoc NameLoc; + NameLoc.NamedType.TInfo = S.Context.getTrivialTypeSourceInfo(FunctionPtrTy, + Loc); + CXXConversionDecl *Conversion + = CXXConversionDecl::Create(S.Context, Class, Loc, + DeclarationNameInfo(Name, Loc, NameLoc), + ConvTy, + S.Context.getTrivialTypeSourceInfo(ConvTy, + Loc), + /*isInline=*/false, /*isExplicit=*/false, + /*isConstexpr=*/false, + CallOperator->getBody()->getLocEnd()); + Conversion->setAccess(AS_public); + Conversion->setImplicit(true); + Class->addDecl(Conversion); + + // Add a non-static member function "__invoke" that will be the result of + // the conversion. + Name = &S.Context.Idents.get("__invoke"); + CXXMethodDecl *Invoke + = CXXMethodDecl::Create(S.Context, Class, Loc, + DeclarationNameInfo(Name, Loc), FunctionTy, + CallOperator->getTypeSourceInfo(), + /*IsStatic=*/true, SC_Static, /*IsInline=*/true, + /*IsConstexpr=*/false, + CallOperator->getBody()->getLocEnd()); + SmallVector InvokeParams; + for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I) { + ParmVarDecl *From = CallOperator->getParamDecl(I); + InvokeParams.push_back(ParmVarDecl::Create(S.Context, Invoke, + From->getLocStart(), + From->getLocation(), + From->getIdentifier(), + From->getType(), + From->getTypeSourceInfo(), + From->getStorageClass(), + From->getStorageClassAsWritten(), + /*DefaultArg=*/0)); + } + Invoke->setParams(InvokeParams); + Invoke->setAccess(AS_private); + Invoke->setImplicit(true); + Class->addDecl(Invoke); +} + +/// \brief Add a lambda's conversion to block pointer. +static void addBlockPointerConversion(Sema &S, + SourceRange IntroducerRange, + CXXRecordDecl *Class, + CXXMethodDecl *CallOperator) { + const FunctionProtoType *Proto + = CallOperator->getType()->getAs(); + QualType BlockPtrTy; + { + FunctionProtoType::ExtProtoInfo ExtInfo = Proto->getExtProtoInfo(); + ExtInfo.TypeQuals = 0; + QualType FunctionTy + = S.Context.getFunctionType(Proto->getResultType(), + Proto->arg_type_begin(), + Proto->getNumArgs(), + ExtInfo); + BlockPtrTy = S.Context.getBlockPointerType(FunctionTy); + } + + FunctionProtoType::ExtProtoInfo ExtInfo; + ExtInfo.TypeQuals = Qualifiers::Const; + QualType ConvTy = S.Context.getFunctionType(BlockPtrTy, 0, 0, ExtInfo); + + SourceLocation Loc = IntroducerRange.getBegin(); + DeclarationName Name + = S.Context.DeclarationNames.getCXXConversionFunctionName( + S.Context.getCanonicalType(BlockPtrTy)); + DeclarationNameLoc NameLoc; + NameLoc.NamedType.TInfo = S.Context.getTrivialTypeSourceInfo(BlockPtrTy, Loc); + CXXConversionDecl *Conversion + = CXXConversionDecl::Create(S.Context, Class, Loc, + DeclarationNameInfo(Name, Loc, NameLoc), + ConvTy, + S.Context.getTrivialTypeSourceInfo(ConvTy, Loc), + /*isInline=*/false, /*isExplicit=*/false, + /*isConstexpr=*/false, + CallOperator->getBody()->getLocEnd()); + Conversion->setAccess(AS_public); + Conversion->setImplicit(true); + Class->addDecl(Conversion); +} + +ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, + Scope *CurScope, + bool IsInstantiation) { + // Collect information from the lambda scope. + llvm::SmallVector Captures; + llvm::SmallVector CaptureInits; + LambdaCaptureDefault CaptureDefault; + CXXRecordDecl *Class; + CXXMethodDecl *CallOperator; + SourceRange IntroducerRange; + bool ExplicitParams; + bool ExplicitResultType; + bool LambdaExprNeedsCleanups; + llvm::SmallVector ArrayIndexVars; + llvm::SmallVector ArrayIndexStarts; + { + LambdaScopeInfo *LSI = getCurLambda(); + CallOperator = LSI->CallOperator; + Class = LSI->Lambda; + IntroducerRange = LSI->IntroducerRange; + ExplicitParams = LSI->ExplicitParams; + ExplicitResultType = !LSI->HasImplicitReturnType; + LambdaExprNeedsCleanups = LSI->ExprNeedsCleanups; + ArrayIndexVars.swap(LSI->ArrayIndexVars); + ArrayIndexStarts.swap(LSI->ArrayIndexStarts); + + // Translate captures. + for (unsigned I = 0, N = LSI->Captures.size(); I != N; ++I) { + LambdaScopeInfo::Capture From = LSI->Captures[I]; + assert(!From.isBlockCapture() && "Cannot capture __block variables"); + bool IsImplicit = I >= LSI->NumExplicitCaptures; + + // Handle 'this' capture. + if (From.isThisCapture()) { + Captures.push_back(LambdaExpr::Capture(From.getLocation(), + IsImplicit, + LCK_This)); + CaptureInits.push_back(new (Context) CXXThisExpr(From.getLocation(), + getCurrentThisType(), + /*isImplicit=*/true)); + continue; + } + + VarDecl *Var = From.getVariable(); + LambdaCaptureKind Kind = From.isCopyCapture()? LCK_ByCopy : LCK_ByRef; + Captures.push_back(LambdaExpr::Capture(From.getLocation(), IsImplicit, + Kind, Var, From.getEllipsisLoc())); + CaptureInits.push_back(From.getCopyExpr()); + } + + switch (LSI->ImpCaptureStyle) { + case CapturingScopeInfo::ImpCap_None: + CaptureDefault = LCD_None; + break; + + case CapturingScopeInfo::ImpCap_LambdaByval: + CaptureDefault = LCD_ByCopy; + break; + + case CapturingScopeInfo::ImpCap_LambdaByref: + CaptureDefault = LCD_ByRef; + break; + + case CapturingScopeInfo::ImpCap_Block: + llvm_unreachable("block capture in lambda"); + break; + } + + // C++11 [expr.prim.lambda]p4: + // If a lambda-expression does not include a + // trailing-return-type, it is as if the trailing-return-type + // denotes the following type: + // FIXME: Assumes current resolution to core issue 975. + if (LSI->HasImplicitReturnType) { + // - if there are no return statements in the + // compound-statement, or all return statements return + // either an expression of type void or no expression or + // braced-init-list, the type void; + if (LSI->ReturnType.isNull()) { + LSI->ReturnType = Context.VoidTy; + } else { + // C++11 [expr.prim.lambda]p4: + // - if the compound-statement is of the form + // + // { attribute-specifier-seq[opt] return expression ; } + // + // the type of the returned expression after + // lvalue-to-rvalue conversion (4.1), array-to-pointer + // conver- sion (4.2), and function-to-pointer conversion + // (4.3); + // + // Since we're accepting the resolution to a post-C++11 core + // issue with a non-trivial extension, provide a warning (by + // default). + CompoundStmt *CompoundBody = cast(Body); + if (!(CompoundBody->size() == 1 && + isa(*CompoundBody->body_begin())) && + !Context.hasSameType(LSI->ReturnType, Context.VoidTy)) + Diag(IntroducerRange.getBegin(), + diag::ext_lambda_implies_void_return); + } + + // Create a function type with the inferred return type. + const FunctionProtoType *Proto + = CallOperator->getType()->getAs(); + QualType FunctionTy + = Context.getFunctionType(LSI->ReturnType, + Proto->arg_type_begin(), + Proto->getNumArgs(), + Proto->getExtProtoInfo()); + CallOperator->setType(FunctionTy); + } + + // C++ [expr.prim.lambda]p7: + // The lambda-expression's compound-statement yields the + // function-body (8.4) of the function call operator [...]. + ActOnFinishFunctionBody(CallOperator, Body, IsInstantiation); + CallOperator->setLexicalDeclContext(Class); + Class->addDecl(CallOperator); + PopExpressionEvaluationContext(); + + // C++11 [expr.prim.lambda]p6: + // The closure type for a lambda-expression with no lambda-capture + // has a public non-virtual non-explicit const conversion function + // to pointer to function having the same parameter and return + // types as the closure type's function call operator. + if (Captures.empty() && CaptureDefault == LCD_None) + addFunctionPointerConversion(*this, IntroducerRange, Class, + CallOperator); + + // Objective-C++: + // The closure type for a lambda-expression has a public non-virtual + // non-explicit const conversion function to a block pointer having the + // same parameter and return types as the closure type's function call + // operator. + if (getLangOpts().Blocks && getLangOpts().ObjC1) + addBlockPointerConversion(*this, IntroducerRange, Class, CallOperator); + + // Finalize the lambda class. + SmallVector Fields(Class->field_begin(), Class->field_end()); + ActOnFields(0, Class->getLocation(), Class, Fields, + SourceLocation(), SourceLocation(), 0); + CheckCompletedCXXClass(Class); + } + + if (LambdaExprNeedsCleanups) + ExprNeedsCleanups = true; + + LambdaExpr *Lambda = LambdaExpr::Create(Context, Class, IntroducerRange, + CaptureDefault, Captures, + ExplicitParams, ExplicitResultType, + CaptureInits, ArrayIndexVars, + ArrayIndexStarts, Body->getLocEnd()); + + // C++11 [expr.prim.lambda]p2: + // A lambda-expression shall not appear in an unevaluated operand + // (Clause 5). + if (!CurContext->isDependentContext()) { + switch (ExprEvalContexts.back().Context) { + case Unevaluated: + // We don't actually diagnose this case immediately, because we + // could be within a context where we might find out later that + // the expression is potentially evaluated (e.g., for typeid). + ExprEvalContexts.back().Lambdas.push_back(Lambda); + break; + + case ConstantEvaluated: + case PotentiallyEvaluated: + case PotentiallyEvaluatedIfUsed: + break; + } + } + + return MaybeBindToTemporary(Lambda); +} + +ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation, + SourceLocation ConvLocation, + CXXConversionDecl *Conv, + Expr *Src) { + // Make sure that the lambda call operator is marked used. + CXXRecordDecl *Lambda = Conv->getParent(); + CXXMethodDecl *CallOperator + = cast( + *Lambda->lookup( + Context.DeclarationNames.getCXXOperatorName(OO_Call)).first); + CallOperator->setReferenced(); + CallOperator->setUsed(); + + ExprResult Init = PerformCopyInitialization( + InitializedEntity::InitializeBlock(ConvLocation, + Src->getType(), + /*NRVO=*/false), + CurrentLocation, Src); + if (!Init.isInvalid()) + Init = ActOnFinishFullExpr(Init.take()); + + if (Init.isInvalid()) + return ExprError(); + + // Create the new block to be returned. + BlockDecl *Block = BlockDecl::Create(Context, CurContext, ConvLocation); + + // Set the type information. + Block->setSignatureAsWritten(CallOperator->getTypeSourceInfo()); + Block->setIsVariadic(CallOperator->isVariadic()); + Block->setBlockMissingReturnType(false); + + // Add parameters. + SmallVector BlockParams; + for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I) { + ParmVarDecl *From = CallOperator->getParamDecl(I); + BlockParams.push_back(ParmVarDecl::Create(Context, Block, + From->getLocStart(), + From->getLocation(), + From->getIdentifier(), + From->getType(), + From->getTypeSourceInfo(), + From->getStorageClass(), + From->getStorageClassAsWritten(), + /*DefaultArg=*/0)); + } + Block->setParams(BlockParams); + + Block->setIsConversionFromLambda(true); + + // Add capture. The capture uses a fake variable, which doesn't correspond + // to any actual memory location. However, the initializer copy-initializes + // the lambda object. + TypeSourceInfo *CapVarTSI = + Context.getTrivialTypeSourceInfo(Src->getType()); + VarDecl *CapVar = VarDecl::Create(Context, Block, ConvLocation, + ConvLocation, 0, + Src->getType(), CapVarTSI, + SC_None, SC_None); + BlockDecl::Capture Capture(/*Variable=*/CapVar, /*ByRef=*/false, + /*Nested=*/false, /*Copy=*/Init.take()); + Block->setCaptures(Context, &Capture, &Capture + 1, + /*CapturesCXXThis=*/false); + + // Add a fake function body to the block. IR generation is responsible + // for filling in the actual body, which cannot be expressed as an AST. + Block->setBody(new (Context) CompoundStmt(Context, 0, 0, + ConvLocation, + ConvLocation)); + + // Create the block literal expression. + Expr *BuildBlock = new (Context) BlockExpr(Block, Conv->getConversionType()); + ExprCleanupObjects.push_back(Block); + ExprNeedsCleanups = true; + + return BuildBlock; +} diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp new file mode 100644 index 0000000..9f5138b --- /dev/null +++ b/clang/lib/Sema/SemaLookup.cpp @@ -0,0 +1,4060 @@ +//===--------------------- SemaLookup.cpp - Name Lookup ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements name lookup for C, C++, Objective-C, and +// Objective-C++. +// +//===----------------------------------------------------------------------===// +#include "clang/Sema/Sema.h" +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/Overload.h" +#include "clang/Sema/DeclSpec.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/TemplateDeduction.h" +#include "clang/Sema/ExternalSemaSource.h" +#include "clang/Sema/TypoCorrection.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/CXXInheritance.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclLookups.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" +#include "clang/Basic/Builtins.h" +#include "clang/Basic/LangOptions.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/TinyPtrVector.h" +#include "llvm/ADT/edit_distance.h" +#include "llvm/Support/ErrorHandling.h" +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace clang; +using namespace sema; + +namespace { + class UnqualUsingEntry { + const DeclContext *Nominated; + const DeclContext *CommonAncestor; + + public: + UnqualUsingEntry(const DeclContext *Nominated, + const DeclContext *CommonAncestor) + : Nominated(Nominated), CommonAncestor(CommonAncestor) { + } + + const DeclContext *getCommonAncestor() const { + return CommonAncestor; + } + + const DeclContext *getNominatedNamespace() const { + return Nominated; + } + + // Sort by the pointer value of the common ancestor. + struct Comparator { + bool operator()(const UnqualUsingEntry &L, const UnqualUsingEntry &R) { + return L.getCommonAncestor() < R.getCommonAncestor(); + } + + bool operator()(const UnqualUsingEntry &E, const DeclContext *DC) { + return E.getCommonAncestor() < DC; + } + + bool operator()(const DeclContext *DC, const UnqualUsingEntry &E) { + return DC < E.getCommonAncestor(); + } + }; + }; + + /// A collection of using directives, as used by C++ unqualified + /// lookup. + class UnqualUsingDirectiveSet { + typedef SmallVector ListTy; + + ListTy list; + llvm::SmallPtrSet visited; + + public: + UnqualUsingDirectiveSet() {} + + void visitScopeChain(Scope *S, Scope *InnermostFileScope) { + // C++ [namespace.udir]p1: + // During unqualified name lookup, the names appear as if they + // were declared in the nearest enclosing namespace which contains + // both the using-directive and the nominated namespace. + DeclContext *InnermostFileDC + = static_cast(InnermostFileScope->getEntity()); + assert(InnermostFileDC && InnermostFileDC->isFileContext()); + + for (; S; S = S->getParent()) { + // C++ [namespace.udir]p1: + // A using-directive shall not appear in class scope, but may + // appear in namespace scope or in block scope. + DeclContext *Ctx = static_cast(S->getEntity()); + if (Ctx && Ctx->isFileContext()) { + visit(Ctx, Ctx); + } else if (!Ctx || Ctx->isFunctionOrMethod()) { + Scope::udir_iterator I = S->using_directives_begin(), + End = S->using_directives_end(); + for (; I != End; ++I) + visit(*I, InnermostFileDC); + } + } + } + + // Visits a context and collect all of its using directives + // recursively. Treats all using directives as if they were + // declared in the context. + // + // A given context is only every visited once, so it is important + // that contexts be visited from the inside out in order to get + // the effective DCs right. + void visit(DeclContext *DC, DeclContext *EffectiveDC) { + if (!visited.insert(DC)) + return; + + addUsingDirectives(DC, EffectiveDC); + } + + // Visits a using directive and collects all of its using + // directives recursively. Treats all using directives as if they + // were declared in the effective DC. + void visit(UsingDirectiveDecl *UD, DeclContext *EffectiveDC) { + DeclContext *NS = UD->getNominatedNamespace(); + if (!visited.insert(NS)) + return; + + addUsingDirective(UD, EffectiveDC); + addUsingDirectives(NS, EffectiveDC); + } + + // Adds all the using directives in a context (and those nominated + // by its using directives, transitively) as if they appeared in + // the given effective context. + void addUsingDirectives(DeclContext *DC, DeclContext *EffectiveDC) { + SmallVector queue; + while (true) { + DeclContext::udir_iterator I, End; + for (llvm::tie(I, End) = DC->getUsingDirectives(); I != End; ++I) { + UsingDirectiveDecl *UD = *I; + DeclContext *NS = UD->getNominatedNamespace(); + if (visited.insert(NS)) { + addUsingDirective(UD, EffectiveDC); + queue.push_back(NS); + } + } + + if (queue.empty()) + return; + + DC = queue.back(); + queue.pop_back(); + } + } + + // Add a using directive as if it had been declared in the given + // context. This helps implement C++ [namespace.udir]p3: + // The using-directive is transitive: if a scope contains a + // using-directive that nominates a second namespace that itself + // contains using-directives, the effect is as if the + // using-directives from the second namespace also appeared in + // the first. + void addUsingDirective(UsingDirectiveDecl *UD, DeclContext *EffectiveDC) { + // Find the common ancestor between the effective context and + // the nominated namespace. + DeclContext *Common = UD->getNominatedNamespace(); + while (!Common->Encloses(EffectiveDC)) + Common = Common->getParent(); + Common = Common->getPrimaryContext(); + + list.push_back(UnqualUsingEntry(UD->getNominatedNamespace(), Common)); + } + + void done() { + std::sort(list.begin(), list.end(), UnqualUsingEntry::Comparator()); + } + + typedef ListTy::const_iterator const_iterator; + + const_iterator begin() const { return list.begin(); } + const_iterator end() const { return list.end(); } + + std::pair + getNamespacesFor(DeclContext *DC) const { + return std::equal_range(begin(), end(), DC->getPrimaryContext(), + UnqualUsingEntry::Comparator()); + } + }; +} + +// Retrieve the set of identifier namespaces that correspond to a +// specific kind of name lookup. +static inline unsigned getIDNS(Sema::LookupNameKind NameKind, + bool CPlusPlus, + bool Redeclaration) { + unsigned IDNS = 0; + switch (NameKind) { + case Sema::LookupObjCImplicitSelfParam: + case Sema::LookupOrdinaryName: + case Sema::LookupRedeclarationWithLinkage: + IDNS = Decl::IDNS_Ordinary; + if (CPlusPlus) { + IDNS |= Decl::IDNS_Tag | Decl::IDNS_Member | Decl::IDNS_Namespace; + if (Redeclaration) + IDNS |= Decl::IDNS_TagFriend | Decl::IDNS_OrdinaryFriend; + } + break; + + case Sema::LookupOperatorName: + // Operator lookup is its own crazy thing; it is not the same + // as (e.g.) looking up an operator name for redeclaration. + assert(!Redeclaration && "cannot do redeclaration operator lookup"); + IDNS = Decl::IDNS_NonMemberOperator; + break; + + case Sema::LookupTagName: + if (CPlusPlus) { + IDNS = Decl::IDNS_Type; + + // When looking for a redeclaration of a tag name, we add: + // 1) TagFriend to find undeclared friend decls + // 2) Namespace because they can't "overload" with tag decls. + // 3) Tag because it includes class templates, which can't + // "overload" with tag decls. + if (Redeclaration) + IDNS |= Decl::IDNS_Tag | Decl::IDNS_TagFriend | Decl::IDNS_Namespace; + } else { + IDNS = Decl::IDNS_Tag; + } + break; + case Sema::LookupLabel: + IDNS = Decl::IDNS_Label; + break; + + case Sema::LookupMemberName: + IDNS = Decl::IDNS_Member; + if (CPlusPlus) + IDNS |= Decl::IDNS_Tag | Decl::IDNS_Ordinary; + break; + + case Sema::LookupNestedNameSpecifierName: + IDNS = Decl::IDNS_Type | Decl::IDNS_Namespace; + break; + + case Sema::LookupNamespaceName: + IDNS = Decl::IDNS_Namespace; + break; + + case Sema::LookupUsingDeclName: + IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Tag + | Decl::IDNS_Member | Decl::IDNS_Using; + break; + + 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; +} + +void LookupResult::configure() { + IDNS = getIDNS(LookupKind, SemaRef.getLangOpts().CPlusPlus, + isForRedeclaration()); + + // If we're looking for one of the allocation or deallocation + // operators, make sure that the implicitly-declared new and delete + // operators can be found. + if (!isForRedeclaration()) { + switch (NameInfo.getName().getCXXOverloadedOperator()) { + case OO_New: + case OO_Delete: + case OO_Array_New: + case OO_Array_Delete: + SemaRef.DeclareGlobalNewDelete(); + break; + + default: + break; + } + } +} + +void LookupResult::sanityImpl() const { + // Note that this function is never called by NDEBUG builds. See + // LookupResult::sanity(). + 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 || + Ambiguity == AmbiguousBaseSubobjectTypes))); + assert((Paths != NULL) == (ResultKind == Ambiguous && + (Ambiguity == AmbiguousBaseSubobjectTypes || + Ambiguity == AmbiguousBaseSubobjects))); +} + +// Necessary because CXXBasePaths is not complete in Sema.h +void LookupResult::deletePaths(CXXBasePaths *Paths) { + delete Paths; +} + +static NamedDecl *getVisibleDecl(NamedDecl *D); + +NamedDecl *LookupResult::getAcceptableDeclSlow(NamedDecl *D) const { + return getVisibleDecl(D); +} + +/// Resolves the result kind of this lookup. +void LookupResult::resolveKind() { + unsigned N = Decls.size(); + + // Fast case: no possible ambiguity. + if (N == 0) { + assert(ResultKind == NotFound || ResultKind == NotFoundInCurrentInstantiation); + return; + } + + // If there's a single decl, we need to examine it to decide what + // kind of lookup this is. + if (N == 1) { + NamedDecl *D = (*Decls.begin())->getUnderlyingDecl(); + if (isa(D)) + ResultKind = FoundOverloaded; + else if (isa(D)) + ResultKind = FoundUnresolvedValue; + return; + } + + // Don't do any extra resolution if we've already resolved as ambiguous. + 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; + + unsigned UniqueTagIndex = 0; + + unsigned I = 0; + while (I < N) { + 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 { + if (HasNonFunction) + Ambiguous = true; + HasNonFunction = true; + } + I++; + } + + // C++ [basic.scope.hiding]p2: + // A class name or enumeration name can be hidden by the name of + // an object, function, or enumerator declared in the same + // scope. If a class or enumeration name and an object, function, + // or enumerator are declared in the same scope (in any order) + // with the same name, the class or enumeration name is hidden + // wherever the object, function, or enumerator name is visible. + // But it's still an error if there are distinct tag types found, + // even if they're not visible. (ref?) + if (HideTags && HasTag && !Ambiguous && + (HasFunction || HasNonFunction || HasUnresolved)) { + if (Decls[UniqueTagIndex]->getDeclContext()->getRedeclContext()->Equals( + Decls[UniqueTagIndex? 0 : N-1]->getDeclContext()->getRedeclContext())) + Decls[UniqueTagIndex] = Decls[--N]; + else + Ambiguous = true; + } + + Decls.set_size(N); + + if (HasNonFunction && (HasFunction || HasUnresolved)) + Ambiguous = true; + + if (Ambiguous) + setAmbiguous(LookupResult::AmbiguousReference); + else if (HasUnresolved) + ResultKind = LookupResult::FoundUnresolvedValue; + else if (N > 1 || HasFunctionTemplate) + ResultKind = LookupResult::FoundOverloaded; + else + ResultKind = LookupResult::Found; +} + +void LookupResult::addDeclsFromBasePaths(const CXXBasePaths &P) { + CXXBasePaths::const_paths_iterator I, E; + DeclContext::lookup_iterator DI, DE; + for (I = P.begin(), E = P.end(); I != E; ++I) + for (llvm::tie(DI,DE) = I->Decls; DI != DE; ++DI) + addDecl(*DI); +} + +void LookupResult::setAmbiguousBaseSubobjects(CXXBasePaths &P) { + Paths = new CXXBasePaths; + Paths->swap(P); + addDeclsFromBasePaths(*Paths); + resolveKind(); + setAmbiguous(AmbiguousBaseSubobjects); +} + +void LookupResult::setAmbiguousBaseSubobjectTypes(CXXBasePaths &P) { + Paths = new CXXBasePaths; + Paths->swap(P); + addDeclsFromBasePaths(*Paths); + resolveKind(); + setAmbiguous(AmbiguousBaseSubobjectTypes); +} + +void LookupResult::print(raw_ostream &Out) { + Out << Decls.size() << " result(s)"; + if (isAmbiguous()) Out << ", ambiguous"; + if (Paths) Out << ", base paths present"; + + for (iterator I = begin(), E = end(); I != E; ++I) { + Out << "\n"; + (*I)->print(Out, 2); + } +} + +/// \brief Lookup a builtin function, when name lookup would otherwise +/// fail. +static bool LookupBuiltin(Sema &S, LookupResult &R) { + Sema::LookupNameKind NameKind = R.getLookupKind(); + + // If we didn't find a use of this identifier, and if the identifier + // corresponds to a compiler builtin, create the decl object for the builtin + // now, injecting it into translation unit scope, and return it. + if (NameKind == Sema::LookupOrdinaryName || + NameKind == Sema::LookupRedeclarationWithLinkage) { + IdentifierInfo *II = R.getLookupName().getAsIdentifierInfo(); + if (II) { + // If this is a builtin on this (or all) targets, create the decl. + if (unsigned BuiltinID = II->getBuiltinID()) { + // In C++, we don't have any predefined library functions like + // 'malloc'. Instead, we'll just error. + if (S.getLangOpts().CPlusPlus && + S.Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) + return false; + + if (NamedDecl *D = S.LazilyCreateBuiltin((IdentifierInfo *)II, + BuiltinID, S.TUScope, + R.isForRedeclaration(), + R.getNameLoc())) { + R.addDecl(D); + return true; + } + + if (R.isForRedeclaration()) { + // If we're redeclaring this function anyway, forget that + // this was a builtin at all. + S.Context.BuiltinInfo.ForgetBuiltin(BuiltinID, S.Context.Idents); + } + + return false; + } + } + } + + return false; +} + +/// \brief Determine whether we can declare a special member function within +/// the class at this point. +static bool CanDeclareSpecialMemberFunction(ASTContext &Context, + const CXXRecordDecl *Class) { + // We need to have a definition for the class. + if (!Class->getDefinition() || Class->isDependentContext()) + return false; + + // We can't be in the middle of defining the class. + if (const RecordType *RecordTy + = Context.getTypeDeclType(Class)->getAs()) + return !RecordTy->isBeingDefined(); + + return false; +} + +void Sema::ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class) { + if (!CanDeclareSpecialMemberFunction(Context, Class)) + return; + + // If the default constructor has not yet been declared, do so now. + if (Class->needsImplicitDefaultConstructor()) + DeclareImplicitDefaultConstructor(Class); + + // If the copy constructor has not yet been declared, do so now. + if (!Class->hasDeclaredCopyConstructor()) + DeclareImplicitCopyConstructor(Class); + + // If the copy assignment operator has not yet been declared, do so now. + if (!Class->hasDeclaredCopyAssignment()) + DeclareImplicitCopyAssignment(Class); + + if (getLangOpts().CPlusPlus0x) { + // If the move constructor has not yet been declared, do so now. + if (Class->needsImplicitMoveConstructor()) + DeclareImplicitMoveConstructor(Class); // might not actually do it + + // If the move assignment operator has not yet been declared, do so now. + if (Class->needsImplicitMoveAssignment()) + DeclareImplicitMoveAssignment(Class); // might not actually do it + } + + // If the destructor has not yet been declared, do so now. + if (!Class->hasDeclaredDestructor()) + DeclareImplicitDestructor(Class); +} + +/// \brief Determine whether this is the name of an implicitly-declared +/// special member function. +static bool isImplicitlyDeclaredMemberFunctionName(DeclarationName Name) { + switch (Name.getNameKind()) { + case DeclarationName::CXXConstructorName: + case DeclarationName::CXXDestructorName: + return true; + + case DeclarationName::CXXOperatorName: + return Name.getCXXOverloadedOperator() == OO_Equal; + + default: + break; + } + + return false; +} + +/// \brief If there are any implicit member functions with the given name +/// that need to be declared in the given declaration context, do so. +static void DeclareImplicitMemberFunctionsWithName(Sema &S, + DeclarationName Name, + const DeclContext *DC) { + if (!DC) + return; + + switch (Name.getNameKind()) { + case DeclarationName::CXXConstructorName: + if (const CXXRecordDecl *Record = dyn_cast(DC)) + if (Record->getDefinition() && + CanDeclareSpecialMemberFunction(S.Context, Record)) { + CXXRecordDecl *Class = const_cast(Record); + if (Record->needsImplicitDefaultConstructor()) + S.DeclareImplicitDefaultConstructor(Class); + if (!Record->hasDeclaredCopyConstructor()) + S.DeclareImplicitCopyConstructor(Class); + if (S.getLangOpts().CPlusPlus0x && + Record->needsImplicitMoveConstructor()) + S.DeclareImplicitMoveConstructor(Class); + } + break; + + case DeclarationName::CXXDestructorName: + if (const CXXRecordDecl *Record = dyn_cast(DC)) + if (Record->getDefinition() && !Record->hasDeclaredDestructor() && + CanDeclareSpecialMemberFunction(S.Context, Record)) + S.DeclareImplicitDestructor(const_cast(Record)); + break; + + case DeclarationName::CXXOperatorName: + if (Name.getCXXOverloadedOperator() != OO_Equal) + break; + + if (const CXXRecordDecl *Record = dyn_cast(DC)) { + if (Record->getDefinition() && + CanDeclareSpecialMemberFunction(S.Context, Record)) { + CXXRecordDecl *Class = const_cast(Record); + if (!Record->hasDeclaredCopyAssignment()) + S.DeclareImplicitCopyAssignment(Class); + if (S.getLangOpts().CPlusPlus0x && + Record->needsImplicitMoveAssignment()) + S.DeclareImplicitMoveAssignment(Class); + } + } + break; + + default: + break; + } +} + +// Adds all qualifying matches for a name within a decl context to the +// given lookup result. Returns true if any matches were found. +static bool LookupDirect(Sema &S, LookupResult &R, const DeclContext *DC) { + bool Found = false; + + // Lazily declare C++ special member functions. + if (S.getLangOpts().CPlusPlus) + DeclareImplicitMemberFunctionsWithName(S, R.getLookupName(), DC); + + // Perform lookup into this declaration context. + DeclContext::lookup_const_iterator I, E; + for (llvm::tie(I, E) = DC->lookup(R.getLookupName()); I != E; ++I) { + NamedDecl *D = *I; + if ((D = R.getAcceptableDecl(D))) { + R.addDecl(D); + Found = true; + } + } + + if (!Found && DC->isTranslationUnit() && LookupBuiltin(S, R)) + return true; + + if (R.getLookupName().getNameKind() + != DeclarationName::CXXConversionFunctionName || + R.getLookupName().getCXXNameType()->isDependentType() || + !isa(DC)) + return Found; + + // C++ [temp.mem]p6: + // A specialization of a conversion function template is not found by + // name lookup. Instead, any conversion function templates visible in the + // context of the use are considered. [...] + const CXXRecordDecl *Record = cast(DC); + if (!Record->isCompleteDefinition()) + return Found; + + const UnresolvedSetImpl *Unresolved = Record->getConversionFunctions(); + for (UnresolvedSetImpl::iterator U = Unresolved->begin(), + UEnd = Unresolved->end(); U != UEnd; ++U) { + FunctionTemplateDecl *ConvTemplate = dyn_cast(*U); + if (!ConvTemplate) + continue; + + // When we're performing lookup for the purposes of redeclaration, just + // add the conversion function template. When we deduce template + // arguments for specializations, we'll end up unifying the return + // type of the new declaration with the type of the function template. + if (R.isForRedeclaration()) { + R.addDecl(ConvTemplate); + Found = true; + continue; + } + + // C++ [temp.mem]p6: + // [...] For each such operator, if argument deduction succeeds + // (14.9.2.3), the resulting specialization is used as if found by + // name lookup. + // + // When referencing a conversion function for any purpose other than + // a redeclaration (such that we'll be building an expression with the + // 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. + TemplateDeductionInfo Info(R.getSema().Context, R.getNameLoc()); + FunctionDecl *Specialization = 0; + + const FunctionProtoType *ConvProto + = ConvTemplate->getTemplatedDecl()->getType()->getAs(); + assert(ConvProto && "Nonsensical conversion function template type"); + + // Compute the type of the function that we would expect the conversion + // function to have, if it were to match the name given. + // FIXME: Calling convention! + FunctionProtoType::ExtProtoInfo EPI = ConvProto->getExtProtoInfo(); + EPI.ExtInfo = EPI.ExtInfo.withCallingConv(CC_Default); + EPI.ExceptionSpecType = EST_None; + EPI.NumExceptions = 0; + QualType ExpectedType + = R.getSema().Context.getFunctionType(R.getLookupName().getCXXNameType(), + 0, 0, EPI); + + // Perform template argument deduction against the type that we would + // expect the function to have. + if (R.getSema().DeduceTemplateArguments(ConvTemplate, 0, ExpectedType, + Specialization, Info) + == Sema::TDK_Success) { + R.addDecl(Specialization); + Found = true; + } + } + + return Found; +} + +// Performs C++ unqualified lookup into the given file context. +static bool +CppNamespaceLookup(Sema &S, LookupResult &R, ASTContext &Context, + DeclContext *NS, UnqualUsingDirectiveSet &UDirs) { + + assert(NS && NS->isFileContext() && "CppNamespaceLookup() requires namespace!"); + + // Perform direct name lookup into the LookupCtx. + bool Found = LookupDirect(S, R, NS); + + // Perform direct name lookup into the namespaces nominated by the + // using directives whose common ancestor is this namespace. + UnqualUsingDirectiveSet::const_iterator UI, UEnd; + llvm::tie(UI, UEnd) = UDirs.getNamespacesFor(NS); + + for (; UI != UEnd; ++UI) + if (LookupDirect(S, R, UI->getNominatedNamespace())) + Found = true; + + R.resolveKind(); + + return Found; +} + +static bool isNamespaceOrTranslationUnitScope(Scope *S) { + if (DeclContext *Ctx = static_cast(S->getEntity())) + return Ctx->isFileContext(); + return false; +} + +// Find the next outer declaration context from this scope. This +// routine actually returns the semantic outer context, which may +// differ from the lexical context (encoded directly in the Scope +// stack) when we are parsing a member of a class template. In this +// case, the second element of the pair will be true, to indicate that +// name lookup should continue searching in this semantic context when +// it leaves the current template parameter scope. +static std::pair findOuterContext(Scope *S) { + DeclContext *DC = static_cast(S->getEntity()); + DeclContext *Lexical = 0; + for (Scope *OuterS = S->getParent(); OuterS; + OuterS = OuterS->getParent()) { + if (OuterS->getEntity()) { + Lexical = static_cast(OuterS->getEntity()); + break; + } + } + + // C++ [temp.local]p8: + // In the definition of a member of a class template that appears + // outside of the namespace containing the class template + // definition, the name of a template-parameter hides the name of + // a member of this namespace. + // + // Example: + // + // namespace N { + // class C { }; + // + // template class B { + // void f(T); + // }; + // } + // + // template void N::B::f(C) { + // C b; // C is the template parameter, not N::C + // } + // + // In this example, the lexical context we return is the + // TranslationUnit, while the semantic context is the namespace N. + if (!Lexical || !DC || !S->getParent() || + !S->getParent()->isTemplateParamScope()) + return std::make_pair(Lexical, false); + + // Find the outermost template parameter scope. + // For the example, this is the scope for the template parameters of + // template. + Scope *OutermostTemplateScope = S->getParent(); + while (OutermostTemplateScope->getParent() && + OutermostTemplateScope->getParent()->isTemplateParamScope()) + OutermostTemplateScope = OutermostTemplateScope->getParent(); + + // Find the namespace context in which the original scope occurs. In + // the example, this is namespace N. + DeclContext *Semantic = DC; + while (!Semantic->isFileContext()) + Semantic = Semantic->getParent(); + + // Find the declaration context just outside of the template + // parameter scope. This is the context in which the template is + // being lexically declaration (a namespace context). In the + // example, this is the global scope. + if (Lexical->isFileContext() && !Lexical->Equals(Semantic) && + Lexical->Encloses(Semantic)) + return std::make_pair(Semantic, true); + + return std::make_pair(Lexical, false); +} + +bool Sema::CppLookupName(LookupResult &R, Scope *S) { + assert(getLangOpts().CPlusPlus && "Can perform only C++ lookup"); + + DeclarationName Name = R.getLookupName(); + + // If this is the name of an implicitly-declared special member function, + // go through the scope stack to implicitly declare + if (isImplicitlyDeclaredMemberFunctionName(Name)) { + for (Scope *PreS = S; PreS; PreS = PreS->getParent()) + if (DeclContext *DC = static_cast(PreS->getEntity())) + DeclareImplicitMemberFunctionsWithName(*this, Name, DC); + } + + // Implicitly declare member functions with the name we're looking for, if in + // fact we are in a scope where it matters. + + Scope *Initial = S; + IdentifierResolver::iterator + I = IdResolver.begin(Name), + IEnd = IdResolver.end(); + + // First we lookup local scope. + // We don't consider using-directives, as per 7.3.4.p1 [namespace.udir] + // ...During unqualified name lookup (3.4.1), the names appear as if + // they were declared in the nearest enclosing namespace which contains + // both the using-directive and the nominated namespace. + // [Note: in this context, "contains" means "contains directly or + // indirectly". + // + // For example: + // namespace A { int i; } + // void foo() { + // int i; + // { + // using namespace A; + // ++i; // finds local 'i', A::i appears at global scope + // } + // } + // + DeclContext *OutsideOfTemplateParamDC = 0; + for (; S && !isNamespaceOrTranslationUnitScope(S); S = S->getParent()) { + DeclContext *Ctx = static_cast(S->getEntity()); + + // Check whether the IdResolver has anything in this scope. + bool Found = false; + for (; I != IEnd && S->isDeclScope(*I); ++I) { + if (NamedDecl *ND = R.getAcceptableDecl(*I)) { + Found = true; + R.addDecl(ND); + } + } + if (Found) { + R.resolveKind(); + if (S->isClassScope()) + if (CXXRecordDecl *Record = dyn_cast_or_null(Ctx)) + R.setNamingClass(Record); + return true; + } + + if (!Ctx && S->isTemplateParamScope() && OutsideOfTemplateParamDC && + S->getParent() && !S->getParent()->isTemplateParamScope()) { + // We've just searched the last template parameter scope and + // found nothing, so look into the the contexts between the + // lexical and semantic declaration contexts returned by + // findOuterContext(). This implements the name lookup behavior + // of C++ [temp.local]p8. + Ctx = OutsideOfTemplateParamDC; + OutsideOfTemplateParamDC = 0; + } + + if (Ctx) { + DeclContext *OuterCtx; + bool SearchAfterTemplateScope; + llvm::tie(OuterCtx, SearchAfterTemplateScope) = findOuterContext(S); + if (SearchAfterTemplateScope) + OutsideOfTemplateParamDC = OuterCtx; + + for (; Ctx && !Ctx->Equals(OuterCtx); Ctx = Ctx->getLookupParent()) { + // We do not directly look into transparent contexts, since + // those entities will be found in the nearest enclosing + // non-transparent context. + if (Ctx->isTransparentContext()) + continue; + + // We do not look directly into function or method contexts, + // since all of the local variables and parameters of the + // function/method are present within the Scope. + if (Ctx->isFunctionOrMethod()) { + // If we have an Objective-C instance method, look for ivars + // in the corresponding interface. + if (ObjCMethodDecl *Method = dyn_cast(Ctx)) { + if (Method->isInstanceMethod() && Name.getAsIdentifierInfo()) + if (ObjCInterfaceDecl *Class = Method->getClassInterface()) { + ObjCInterfaceDecl *ClassDeclared; + if (ObjCIvarDecl *Ivar = Class->lookupInstanceVariable( + Name.getAsIdentifierInfo(), + ClassDeclared)) { + if (NamedDecl *ND = R.getAcceptableDecl(Ivar)) { + R.addDecl(ND); + R.resolveKind(); + return true; + } + } + } + } + + continue; + } + + // Perform qualified name lookup into this context. + // FIXME: In some cases, we know that every name that could be found by + // this qualified name lookup will also be on the identifier chain. For + // example, inside a class without any base classes, we never need to + // perform qualified lookup because all of the members are on top of the + // identifier chain. + if (LookupQualifiedName(R, Ctx, /*InUnqualifiedLookup=*/true)) + return true; + } + } + } + + // Stop if we ran out of scopes. + // FIXME: This really, really shouldn't be happening. + if (!S) return false; + + // If we are looking for members, no need to look into global/namespace scope. + if (R.getLookupKind() == LookupMemberName) + return false; + + // Collect UsingDirectiveDecls in all scopes, and recursively all + // nominated namespaces by those using-directives. + // + // FIXME: Cache this sorted list in Scope structure, and DeclContext, so we + // don't build it for each lookup! + + UnqualUsingDirectiveSet UDirs; + UDirs.visitScopeChain(Initial, S); + UDirs.done(); + + // Lookup namespace scope, and global scope. + // Unqualified name lookup in C++ requires looking into scopes + // that aren't strictly lexical, and therefore we walk through the + // context as well as walking through the scopes. + + for (; S; S = S->getParent()) { + // Check whether the IdResolver has anything in this scope. + bool Found = false; + for (; I != IEnd && S->isDeclScope(*I); ++I) { + if (NamedDecl *ND = R.getAcceptableDecl(*I)) { + // We found something. Look for anything else in our scope + // with this same name and in an acceptable identifier + // namespace, so that we can construct an overload set if we + // need to. + Found = true; + R.addDecl(ND); + } + } + + if (Found && S->isTemplateParamScope()) { + R.resolveKind(); + return true; + } + + DeclContext *Ctx = static_cast(S->getEntity()); + if (!Ctx && S->isTemplateParamScope() && OutsideOfTemplateParamDC && + S->getParent() && !S->getParent()->isTemplateParamScope()) { + // We've just searched the last template parameter scope and + // found nothing, so look into the the contexts between the + // lexical and semantic declaration contexts returned by + // findOuterContext(). This implements the name lookup behavior + // of C++ [temp.local]p8. + Ctx = OutsideOfTemplateParamDC; + OutsideOfTemplateParamDC = 0; + } + + if (Ctx) { + DeclContext *OuterCtx; + bool SearchAfterTemplateScope; + llvm::tie(OuterCtx, SearchAfterTemplateScope) = findOuterContext(S); + if (SearchAfterTemplateScope) + OutsideOfTemplateParamDC = OuterCtx; + + for (; Ctx && !Ctx->Equals(OuterCtx); Ctx = Ctx->getLookupParent()) { + // We do not directly look into transparent contexts, since + // those entities will be found in the nearest enclosing + // non-transparent context. + if (Ctx->isTransparentContext()) + continue; + + // If we have a context, and it's not a context stashed in the + // template parameter scope for an out-of-line definition, also + // look into that context. + if (!(Found && S && S->isTemplateParamScope())) { + assert(Ctx->isFileContext() && + "We should have been looking only at file context here already."); + + // Look into context considering using-directives. + if (CppNamespaceLookup(*this, R, Context, Ctx, UDirs)) + Found = true; + } + + if (Found) { + R.resolveKind(); + return true; + } + + if (R.isForRedeclaration() && !Ctx->isTransparentContext()) + return false; + } + } + + if (R.isForRedeclaration() && Ctx && !Ctx->isTransparentContext()) + return false; + } + + return !R.empty(); +} + +/// \brief Retrieve the visible declaration corresponding to D, if any. +/// +/// This routine determines whether the declaration D is visible in the current +/// module, with the current imports. If not, it checks whether any +/// redeclaration of D is visible, and if so, returns that declaration. +/// +/// \returns D, or a visible previous declaration of D, whichever is more recent +/// and visible. If no declaration of D is visible, returns null. +static NamedDecl *getVisibleDecl(NamedDecl *D) { + if (LookupResult::isVisible(D)) + return D; + + for (Decl::redecl_iterator RD = D->redecls_begin(), RDEnd = D->redecls_end(); + RD != RDEnd; ++RD) { + if (NamedDecl *ND = dyn_cast(*RD)) { + if (LookupResult::isVisible(ND)) + return ND; + } + } + + return 0; +} + +/// @brief Perform unqualified name lookup starting from a given +/// scope. +/// +/// Unqualified name lookup (C++ [basic.lookup.unqual], C99 6.2.1) is +/// used to find names within the current scope. For example, 'x' in +/// @code +/// int x; +/// int f() { +/// return x; // unqualified name look finds 'x' in the global scope +/// } +/// @endcode +/// +/// Different lookup criteria can find different names. For example, a +/// particular scope can have both a struct and a function of the same +/// name, and each can be found by certain lookup criteria. For more +/// information about lookup criteria, see the documentation for the +/// class LookupCriteria. +/// +/// @param S The scope from which unqualified name lookup will +/// begin. If the lookup criteria permits, name lookup may also search +/// in the parent scopes. +/// +/// @param Name The name of the entity that we are searching for. +/// +/// @param Loc If provided, the source location where we're performing +/// name lookup. At present, this is only used to produce diagnostics when +/// C library functions (like "malloc") are implicitly declared. +/// +/// @returns The result of name lookup, which includes zero or more +/// declarations and possibly additional information used to diagnose +/// ambiguities. +bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) { + DeclarationName Name = R.getLookupName(); + if (!Name) return false; + + LookupNameKind NameKind = R.getLookupKind(); + + if (!getLangOpts().CPlusPlus) { + // Unqualified name lookup in C/Objective-C is purely lexical, so + // search in the declarations attached to the name. + if (NameKind == Sema::LookupRedeclarationWithLinkage) { + // Find the nearest non-transparent declaration scope. + while (!(S->getFlags() & Scope::DeclScope) || + (S->getEntity() && + static_cast(S->getEntity()) + ->isTransparentContext())) + S = S->getParent(); + } + + unsigned IDNS = R.getIdentifierNamespace(); + + // Scan up the scope chain looking for a decl that matches this + // identifier that is in the appropriate namespace. This search + // should not take long, as shadowing of names is uncommon, and + // deep shadowing is extremely uncommon. + bool LeftStartingScope = false; + + for (IdentifierResolver::iterator I = IdResolver.begin(Name), + IEnd = IdResolver.end(); + I != IEnd; ++I) + if ((*I)->isInIdentifierNamespace(IDNS)) { + if (NameKind == LookupRedeclarationWithLinkage) { + // Determine whether this (or a previous) declaration is + // out-of-scope. + if (!LeftStartingScope && !S->isDeclScope(*I)) + LeftStartingScope = true; + + // If we found something outside of our starting scope that + // does not have linkage, skip it. + if (LeftStartingScope && !((*I)->hasLinkage())) + continue; + } + else if (NameKind == LookupObjCImplicitSelfParam && + !isa(*I)) + continue; + + // If this declaration is module-private and it came from an AST + // file, we can't see it. + NamedDecl *D = R.isHiddenDeclarationVisible()? *I : getVisibleDecl(*I); + if (!D) + continue; + + R.addDecl(D); + + // Check whether there are any other declarations with the same name + // and in the same scope. + if (I != IEnd) { + // Find the scope in which this declaration was declared (if it + // actually exists in a Scope). + while (S && !S->isDeclScope(D)) + S = S->getParent(); + + // If the scope containing the declaration is the translation unit, + // then we'll need to perform our checks based on the matching + // DeclContexts rather than matching scopes. + if (S && isNamespaceOrTranslationUnitScope(S)) + S = 0; + + // Compute the DeclContext, if we need it. + DeclContext *DC = 0; + if (!S) + DC = (*I)->getDeclContext()->getRedeclContext(); + + IdentifierResolver::iterator LastI = I; + for (++LastI; LastI != IEnd; ++LastI) { + if (S) { + // Match based on scope. + if (!S->isDeclScope(*LastI)) + break; + } else { + // Match based on DeclContext. + DeclContext *LastDC + = (*LastI)->getDeclContext()->getRedeclContext(); + if (!LastDC->Equals(DC)) + break; + } + + // If the declaration isn't in the right namespace, skip it. + if (!(*LastI)->isInIdentifierNamespace(IDNS)) + continue; + + D = R.isHiddenDeclarationVisible()? *LastI : getVisibleDecl(*LastI); + if (D) + R.addDecl(D); + } + + R.resolveKind(); + } + return true; + } + } else { + // Perform C++ unqualified name lookup. + if (CppLookupName(R, S)) + return true; + } + + // If we didn't find a use of this identifier, and if the identifier + // corresponds to a compiler builtin, create the decl object for the builtin + // now, injecting it into translation unit scope, and return it. + if (AllowBuiltinCreation && LookupBuiltin(*this, R)) + return true; + + // If we didn't find a use of this identifier, the ExternalSource + // may be able to handle the situation. + // Note: some lookup failures are expected! + // See e.g. R.isForRedeclaration(). + return (ExternalSource && ExternalSource->LookupUnqualified(R, S)); +} + +/// @brief Perform qualified name lookup in the namespaces nominated by +/// using directives by the given context. +/// +/// C++98 [namespace.qual]p2: +/// Given X::m (where X is a user-declared namespace), or given ::m +/// (where X is the global namespace), let S be the set of all +/// declarations of m in X and in the transitive closure of all +/// namespaces nominated by using-directives in X and its used +/// namespaces, except that using-directives are ignored in any +/// namespace, including X, directly containing one or more +/// declarations of m. No namespace is searched more than once in +/// the lookup of a name. If S is the empty set, the program is +/// ill-formed. Otherwise, if S has exactly one member, or if the +/// context of the reference is a using-declaration +/// (namespace.udecl), S is the required set of declarations of +/// m. Otherwise if the use of m is not one that allows a unique +/// declaration to be chosen from S, the program is ill-formed. +/// C++98 [namespace.qual]p5: +/// During the lookup of a qualified namespace member name, if the +/// lookup finds more than one declaration of the member, and if one +/// declaration introduces a class name or enumeration name and the +/// other declarations either introduce the same object, the same +/// enumerator or a set of functions, the non-type name hides the +/// class or enumeration name if and only if the declarations are +/// from the same namespace; otherwise (the declarations are from +/// different namespaces), the program is ill-formed. +static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R, + DeclContext *StartDC) { + assert(StartDC->isFileContext() && "start context is not a file context"); + + DeclContext::udir_iterator I = StartDC->using_directives_begin(); + DeclContext::udir_iterator E = StartDC->using_directives_end(); + + if (I == E) return false; + + // We have at least added all these contexts to the queue. + llvm::SmallPtrSet Visited; + Visited.insert(StartDC); + + // We have not yet looked into these namespaces, much less added + // their "using-children" to the queue. + SmallVector Queue; + + // We have already looked into the initial namespace; seed the queue + // with its using-children. + for (; I != E; ++I) { + NamespaceDecl *ND = (*I)->getNominatedNamespace()->getOriginalNamespace(); + if (Visited.insert(ND)) + Queue.push_back(ND); + } + + // The easiest way to implement the restriction in [namespace.qual]p5 + // is to check whether any of the individual results found a tag + // and, if so, to declare an ambiguity if the final result is not + // a tag. + bool FoundTag = false; + bool FoundNonTag = false; + + LookupResult LocalR(LookupResult::Temporary, R); + + bool Found = false; + while (!Queue.empty()) { + NamespaceDecl *ND = Queue.back(); + Queue.pop_back(); + + // We go through some convolutions here to avoid copying results + // between LookupResults. + bool UseLocal = !R.empty(); + LookupResult &DirectR = UseLocal ? LocalR : R; + bool FoundDirect = LookupDirect(S, DirectR, ND); + + if (FoundDirect) { + // First do any local hiding. + DirectR.resolveKind(); + + // If the local result is a tag, remember that. + if (DirectR.isSingleTagDecl()) + FoundTag = true; + else + FoundNonTag = true; + + // Append the local results to the total results if necessary. + if (UseLocal) { + R.addAllDecls(LocalR); + LocalR.clear(); + } + } + + // If we find names in this namespace, ignore its using directives. + if (FoundDirect) { + Found = true; + continue; + } + + for (llvm::tie(I,E) = ND->getUsingDirectives(); I != E; ++I) { + NamespaceDecl *Nom = (*I)->getNominatedNamespace(); + if (Visited.insert(Nom)) + Queue.push_back(Nom); + } + } + + if (Found) { + if (FoundTag && FoundNonTag) + R.setAmbiguousQualifiedTagHiding(); + else + R.resolveKind(); + } + + 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 Determine whether the given set of member declarations contains only +/// static members, nested types, and enumerators. +template +static bool HasOnlyStaticMembers(InputIterator First, InputIterator Last) { + Decl *D = (*First)->getUnderlyingDecl(); + if (isa(D) || isa(D) || isa(D)) + return true; + + if (isa(D)) { + // Determine whether all of the methods are static. + bool AllMethodsAreStatic = true; + for(; First != Last; ++First) { + D = (*First)->getUnderlyingDecl(); + + if (!isa(D)) { + assert(isa(D) && "Non-function must be a tag decl"); + break; + } + + if (!cast(D)->isStatic()) { + AllMethodsAreStatic = false; + break; + } + } + + if (AllMethodsAreStatic) + return true; + } + + return false; +} + +/// \brief Perform qualified name lookup into a given context. +/// +/// Qualified name lookup (C++ [basic.lookup.qual]) is used to find +/// names when the context of those names is explicit specified, e.g., +/// "std::vector" or "x->member", or as part of unqualified name lookup. +/// +/// Different lookup criteria can find different names. For example, a +/// particular scope can have both a struct and a function of the same +/// name, and each can be found by certain lookup criteria. For more +/// information about lookup criteria, see the documentation for the +/// class LookupCriteria. +/// +/// \param R captures both the lookup criteria and any lookup results found. +/// +/// \param LookupCtx The context in which qualified name lookup will +/// search. If the lookup criteria permits, name lookup may also search +/// in the parent contexts or (for C++ classes) base classes. +/// +/// \param InUnqualifiedLookup true if this is qualified name lookup that +/// occurs as part of unqualified name lookup. +/// +/// \returns true if lookup succeeded, false if it failed. +bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, + bool InUnqualifiedLookup) { + assert(LookupCtx && "Sema::LookupQualifiedName requires a lookup context"); + + if (!R.getLookupName()) + return false; + + // Make sure that the declaration context is complete. + assert((!isa(LookupCtx) || + LookupCtx->isDependentContext() || + cast(LookupCtx)->isCompleteDefinition() || + cast(LookupCtx)->isBeingDefined()) && + "Declaration context must already be complete!"); + + // Perform qualified name lookup into the LookupCtx. + if (LookupDirect(*this, R, LookupCtx)) { + R.resolveKind(); + if (isa(LookupCtx)) + R.setNamingClass(cast(LookupCtx)); + return true; + } + + // Don't descend into implied contexts for redeclarations. + // C++98 [namespace.qual]p6: + // In a declaration for a namespace member in which the + // declarator-id is a qualified-id, given that the qualified-id + // for the namespace member has the form + // nested-name-specifier unqualified-id + // the unqualified-id shall name a member of the namespace + // designated by the nested-name-specifier. + // See also [class.mfct]p5 and [class.static.data]p2. + if (R.isForRedeclaration()) + return false; + + // If this is a namespace, look it up in the implied namespaces. + if (LookupCtx->isFileContext()) + return LookupQualifiedNameInUsingDirectives(*this, R, LookupCtx); + + // If this isn't a C++ class, we aren't allowed to look into base + // classes, we're done. + CXXRecordDecl *LookupRec = dyn_cast(LookupCtx); + if (!LookupRec || !LookupRec->getDefinition()) + return false; + + // If we're performing qualified name lookup into a dependent class, + // then we are actually looking into a current instantiation. If we have any + // dependent base classes, then we either have to delay lookup until + // template instantiation time (at which point all bases will be available) + // or we have to fail. + if (!InUnqualifiedLookup && LookupRec->isDependentContext() && + LookupRec->hasAnyDependentBases()) { + R.setNotFoundInCurrentInstantiation(); + return false; + } + + // Perform lookup into our base classes. + CXXBasePaths Paths; + Paths.setOrigin(LookupRec); + + // Look for this member in our base classes + CXXRecordDecl::BaseMatchesCallback *BaseCallback = 0; + switch (R.getLookupKind()) { + case LookupObjCImplicitSelfParam: + case LookupOrdinaryName: + case LookupMemberName: + case LookupRedeclarationWithLinkage: + BaseCallback = &CXXRecordDecl::FindOrdinaryMember; + break; + + case LookupTagName: + BaseCallback = &CXXRecordDecl::FindTagMember; + break; + + case LookupAnyName: + BaseCallback = &LookupAnyMember; + break; + + case LookupUsingDeclName: + // This lookup is for redeclarations only. + + case LookupOperatorName: + case LookupNamespaceName: + case LookupObjCProtocolName: + case LookupLabel: + // These lookups will never find a member in a C++ class (or base class). + return false; + + case LookupNestedNameSpecifierName: + BaseCallback = &CXXRecordDecl::FindNestedNameSpecifierMember; + break; + } + + if (!LookupRec->lookupInBases(BaseCallback, + R.getLookupName().getAsOpaquePtr(), Paths)) + return false; + + R.setNamingClass(LookupRec); + + // C++ [class.member.lookup]p2: + // [...] If the resulting set of declarations are not all from + // sub-objects of the same type, or the set has a nonstatic member + // and includes members from distinct sub-objects, there is an + // ambiguity and the program is ill-formed. Otherwise that set is + // the result of the lookup. + QualType SubobjectType; + int SubobjectNumber = 0; + AccessSpecifier SubobjectAccess = AS_none; + + for (CXXBasePaths::paths_iterator Path = Paths.begin(), PathEnd = Paths.end(); + Path != PathEnd; ++Path) { + const CXXBasePathElement &PathElement = Path->back(); + + // Pick the best (i.e. most permissive i.e. numerically lowest) access + // across all paths. + SubobjectAccess = std::min(SubobjectAccess, Path->Access); + + // Determine whether we're looking at a distinct sub-object or not. + if (SubobjectType.isNull()) { + // This is the first subobject we've looked at. Record its type. + SubobjectType = Context.getCanonicalType(PathElement.Base->getType()); + SubobjectNumber = PathElement.SubobjectNumber; + continue; + } + + if (SubobjectType + != Context.getCanonicalType(PathElement.Base->getType())) { + // We found members of the given name in two subobjects of + // different types. If the declaration sets aren't the same, this + // this lookup is ambiguous. + if (HasOnlyStaticMembers(Path->Decls.first, Path->Decls.second)) { + CXXBasePaths::paths_iterator FirstPath = Paths.begin(); + DeclContext::lookup_iterator FirstD = FirstPath->Decls.first; + DeclContext::lookup_iterator CurrentD = Path->Decls.first; + + while (FirstD != FirstPath->Decls.second && + CurrentD != Path->Decls.second) { + if ((*FirstD)->getUnderlyingDecl()->getCanonicalDecl() != + (*CurrentD)->getUnderlyingDecl()->getCanonicalDecl()) + break; + + ++FirstD; + ++CurrentD; + } + + if (FirstD == FirstPath->Decls.second && + CurrentD == Path->Decls.second) + continue; + } + + R.setAmbiguousBaseSubobjectTypes(Paths); + return true; + } + + if (SubobjectNumber != PathElement.SubobjectNumber) { + // We have a different subobject of the same type. + + // C++ [class.member.lookup]p5: + // A static member, a nested type or an enumerator defined in + // a base class T can unambiguously be found even if an object + // has more than one base class subobject of type T. + if (HasOnlyStaticMembers(Path->Decls.first, Path->Decls.second)) + continue; + + // We have found a nonstatic member name in multiple, distinct + // subobjects. Name lookup is ambiguous. + R.setAmbiguousBaseSubobjects(Paths); + return true; + } + } + + // Lookup in a base class succeeded; return these results. + + DeclContext::lookup_iterator I, E; + for (llvm::tie(I,E) = Paths.front().Decls; I != E; ++I) { + NamedDecl *D = *I; + AccessSpecifier AS = CXXRecordDecl::MergeAccess(SubobjectAccess, + D->getAccess()); + R.addDecl(D, AS); + } + R.resolveKind(); + return true; +} + +/// @brief Performs name lookup for a name that was parsed in the +/// source code, and may contain a C++ scope specifier. +/// +/// This routine is a convenience routine meant to be called from +/// contexts that receive a name and an optional C++ scope specifier +/// (e.g., "N::M::x"). It will then perform either qualified or +/// unqualified name lookup (with LookupQualifiedName or LookupName, +/// respectively) on the given name and return those results. +/// +/// @param S The scope from which unqualified name lookup will +/// begin. +/// +/// @param SS An optional C++ scope-specifier, e.g., "::N::M". +/// +/// @param EnteringContext Indicates whether we are going to enter the +/// context of the scope-specifier SS (if present). +/// +/// @returns True if any decls were found (but possibly ambiguous) +bool Sema::LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, + bool AllowBuiltinCreation, bool EnteringContext) { + if (SS && SS->isInvalid()) { + // When the scope specifier is invalid, don't even look for + // anything. + return false; + } + + if (SS && SS->isSet()) { + if (DeclContext *DC = computeDeclContext(*SS, EnteringContext)) { + // We have resolved the scope specifier to a particular declaration + // contex, and will perform name lookup in that context. + if (!DC->isDependentContext() && RequireCompleteDeclContext(*SS, DC)) + return false; + + R.setContextRange(SS->getRange()); + return LookupQualifiedName(R, DC); + } + + // We could not resolve the scope specified to a specific declaration + // context, which means that SS refers to an unknown specialization. + // Name lookup can't find anything in this case. + R.setNotFoundInCurrentInstantiation(); + R.setContextRange(SS->getRange()); + return false; + } + + // Perform unqualified name lookup starting in the given scope. + return LookupName(R, S, AllowBuiltinCreation); +} + + +/// @brief Produce a diagnostic describing the ambiguity that resulted +/// from name lookup. +/// +/// @param Result The ambiguous name lookup result. +/// +/// @param Name The name of the entity that name lookup was +/// searching for. +/// +/// @param NameLoc The location of the name within the source code. +/// +/// @param LookupRange A source range that provides more +/// source-location information concerning the lookup itself. For +/// example, this range might highlight a nested-name-specifier that +/// precedes the name. +/// +/// @returns true +bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result) { + assert(Result.isAmbiguous() && "Lookup result must be ambiguous"); + + DeclarationName Name = Result.getLookupName(); + SourceLocation NameLoc = Result.getNameLoc(); + SourceRange LookupRange = Result.getContextRange(); + + switch (Result.getAmbiguityKind()) { + case LookupResult::AmbiguousBaseSubobjects: { + CXXBasePaths *Paths = Result.getBasePaths(); + QualType SubobjectType = Paths->front().back().Base->getType(); + Diag(NameLoc, diag::err_ambiguous_member_multiple_subobjects) + << Name << SubobjectType << getAmbiguousPathsDisplayString(*Paths) + << LookupRange; + + DeclContext::lookup_iterator Found = Paths->front().Decls.first; + while (isa(*Found) && + cast(*Found)->isStatic()) + ++Found; + + Diag((*Found)->getLocation(), diag::note_ambiguous_member_found); + + return true; + } + + case LookupResult::AmbiguousBaseSubobjectTypes: { + Diag(NameLoc, diag::err_ambiguous_member_multiple_subobject_types) + << Name << LookupRange; + + CXXBasePaths *Paths = Result.getBasePaths(); + std::set DeclsPrinted; + for (CXXBasePaths::paths_iterator Path = Paths->begin(), + PathEnd = Paths->end(); + Path != PathEnd; ++Path) { + Decl *D = *Path->Decls.first; + if (DeclsPrinted.insert(D).second) + Diag(D->getLocation(), diag::note_ambiguous_member_found); + } + + return true; + } + + case LookupResult::AmbiguousTagHiding: { + Diag(NameLoc, diag::err_ambiguous_tag_hiding) << Name << LookupRange; + + llvm::SmallPtrSet TagDecls; + + LookupResult::iterator DI, DE = Result.end(); + for (DI = Result.begin(); DI != DE; ++DI) + if (TagDecl *TD = dyn_cast(*DI)) { + TagDecls.insert(TD); + Diag(TD->getLocation(), diag::note_hidden_tag); + } + + for (DI = Result.begin(); DI != DE; ++DI) + if (!isa(*DI)) + Diag((*DI)->getLocation(), diag::note_hiding_object); + + // For recovery purposes, go ahead and implement the hiding. + LookupResult::Filter F = Result.makeFilter(); + while (F.hasNext()) { + if (TagDecls.count(F.next())) + F.erase(); + } + F.done(); + + return true; + } + + case LookupResult::AmbiguousReference: { + Diag(NameLoc, diag::err_ambiguous_reference) << Name << LookupRange; + + LookupResult::iterator DI = Result.begin(), DE = Result.end(); + for (; DI != DE; ++DI) + Diag((*DI)->getLocation(), diag::note_ambiguous_candidate) << *DI; + + return true; + } + } + + llvm_unreachable("unknown ambiguity kind"); +} + +namespace { + struct AssociatedLookup { + AssociatedLookup(Sema &S, + Sema::AssociatedNamespaceSet &Namespaces, + Sema::AssociatedClassSet &Classes) + : S(S), Namespaces(Namespaces), Classes(Classes) { + } + + Sema &S; + Sema::AssociatedNamespaceSet &Namespaces; + Sema::AssociatedClassSet &Classes; + }; +} + +static void +addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType T); + +static void CollectEnclosingNamespace(Sema::AssociatedNamespaceSet &Namespaces, + DeclContext *Ctx) { + // Add the associated namespace for this class. + + // We don't use DeclContext::getEnclosingNamespaceContext() as this may + // be a locally scoped record. + + // 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()) + Namespaces.insert(Ctx->getPrimaryContext()); +} + +// \brief Add the associated classes and namespaces for argument-dependent +// lookup that involves a template argument (C++ [basic.lookup.koenig]p2). +static void +addAssociatedClassesAndNamespaces(AssociatedLookup &Result, + const TemplateArgument &Arg) { + // C++ [basic.lookup.koenig]p2, last bullet: + // -- [...] ; + switch (Arg.getKind()) { + case TemplateArgument::Null: + break; + + case TemplateArgument::Type: + // [...] the namespaces and classes associated with the types of the + // template arguments provided for template type parameters (excluding + // template template parameters) + addAssociatedClassesAndNamespaces(Result, Arg.getAsType()); + break; + + case TemplateArgument::Template: + case TemplateArgument::TemplateExpansion: { + // [...] the namespaces in which any template template arguments are + // defined; and the classes in which any member templates used as + // template template arguments are defined. + TemplateName Template = Arg.getAsTemplateOrTemplatePattern(); + if (ClassTemplateDecl *ClassTemplate + = dyn_cast(Template.getAsTemplateDecl())) { + DeclContext *Ctx = ClassTemplate->getDeclContext(); + if (CXXRecordDecl *EnclosingClass = dyn_cast(Ctx)) + Result.Classes.insert(EnclosingClass); + // Add the associated namespace for this class. + CollectEnclosingNamespace(Result.Namespaces, Ctx); + } + break; + } + + case TemplateArgument::Declaration: + case TemplateArgument::Integral: + case TemplateArgument::Expression: + // [Note: non-type template arguments do not contribute to the set of + // associated namespaces. ] + break; + + case TemplateArgument::Pack: + for (TemplateArgument::pack_iterator P = Arg.pack_begin(), + PEnd = Arg.pack_end(); + P != PEnd; ++P) + addAssociatedClassesAndNamespaces(Result, *P); + break; + } +} + +// \brief Add the associated classes and namespaces for +// argument-dependent lookup with an argument of class type +// (C++ [basic.lookup.koenig]p2). +static void +addAssociatedClassesAndNamespaces(AssociatedLookup &Result, + CXXRecordDecl *Class) { + + // Just silently ignore anything whose name is __va_list_tag. + if (Class->getDeclName() == Result.S.VAListTagName) + return; + + // C++ [basic.lookup.koenig]p2: + // [...] + // -- If T is a class type (including unions), its associated + // classes are: the class itself; the class of which it is a + // member, if any; and its direct and indirect base + // classes. Its associated namespaces are the namespaces in + // which its associated classes are defined. + + // Add the class of which it is a member, if any. + DeclContext *Ctx = Class->getDeclContext(); + if (CXXRecordDecl *EnclosingClass = dyn_cast(Ctx)) + Result.Classes.insert(EnclosingClass); + // Add the associated namespace for this class. + CollectEnclosingNamespace(Result.Namespaces, Ctx); + + // Add the class itself. If we've already seen this class, we don't + // need to visit base classes. + if (!Result.Classes.insert(Class)) + return; + + // -- If T is a template-id, its associated namespaces and classes are + // the namespace in which the template is defined; for member + // templates, the member template's class; the namespaces and classes + // associated with the types of the template arguments provided for + // template type parameters (excluding template template parameters); the + // namespaces in which any template template arguments are defined; and + // the classes in which any member templates used as template template + // arguments are defined. [Note: non-type template arguments do not + // contribute to the set of associated namespaces. ] + if (ClassTemplateSpecializationDecl *Spec + = dyn_cast(Class)) { + DeclContext *Ctx = Spec->getSpecializedTemplate()->getDeclContext(); + if (CXXRecordDecl *EnclosingClass = dyn_cast(Ctx)) + Result.Classes.insert(EnclosingClass); + // Add the associated namespace for this class. + CollectEnclosingNamespace(Result.Namespaces, Ctx); + + const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); + for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) + addAssociatedClassesAndNamespaces(Result, TemplateArgs[I]); + } + + // Only recurse into base classes for complete types. + if (!Class->hasDefinition()) { + // FIXME: we might need to instantiate templates here + return; + } + + // Add direct and indirect base classes along with their associated + // namespaces. + SmallVector Bases; + Bases.push_back(Class); + while (!Bases.empty()) { + // Pop this class off the stack. + Class = Bases.back(); + Bases.pop_back(); + + // Visit the base classes. + for (CXXRecordDecl::base_class_iterator Base = Class->bases_begin(), + BaseEnd = Class->bases_end(); + Base != BaseEnd; ++Base) { + const RecordType *BaseType = Base->getType()->getAs(); + // In dependent contexts, we do ADL twice, and the first time around, + // the base type might be a dependent TemplateSpecializationType, or a + // TemplateTypeParmType. If that happens, simply ignore it. + // FIXME: If we want to support export, we probably need to add the + // namespace of the template in a TemplateSpecializationType, or even + // the classes and namespaces of known non-dependent arguments. + if (!BaseType) + continue; + CXXRecordDecl *BaseDecl = cast(BaseType->getDecl()); + if (Result.Classes.insert(BaseDecl)) { + // Find the associated namespace for this base class. + DeclContext *BaseCtx = BaseDecl->getDeclContext(); + CollectEnclosingNamespace(Result.Namespaces, BaseCtx); + + // Make sure we visit the bases of this base class. + if (BaseDecl->bases_begin() != BaseDecl->bases_end()) + Bases.push_back(BaseDecl); + } + } + } +} + +// \brief Add the associated classes and namespaces for +// argument-dependent lookup with an argument of type T +// (C++ [basic.lookup.koenig]p2). +static void +addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) { + // C++ [basic.lookup.koenig]p2: + // + // For each argument type T in the function call, there is a set + // of zero or more associated namespaces and a set of zero or more + // associated classes to be considered. The sets of namespaces and + // classes is determined entirely by the types of the function + // arguments (and the namespace of any template template + // argument). Typedef names and using-declarations used to specify + // the types do not contribute to this set. The sets of namespaces + // and classes are determined in the following way: + + SmallVector Queue; + const Type *T = Ty->getCanonicalTypeInternal().getTypePtr(); + + while (true) { + switch (T->getTypeClass()) { + +#define TYPE(Class, Base) +#define DEPENDENT_TYPE(Class, Base) case Type::Class: +#define NON_CANONICAL_TYPE(Class, Base) case Type::Class: +#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class: +#define ABSTRACT_TYPE(Class, Base) +#include "clang/AST/TypeNodes.def" + // T is canonical. We can also ignore dependent types because + // we don't need to do ADL at the definition point, but if we + // wanted to implement template export (or if we find some other + // use for associated classes and namespaces...) this would be + // wrong. + break; + + // -- If T is a pointer to U or an array of U, its associated + // namespaces and classes are those associated with U. + case Type::Pointer: + T = cast(T)->getPointeeType().getTypePtr(); + continue; + case Type::ConstantArray: + case Type::IncompleteArray: + case Type::VariableArray: + T = cast(T)->getElementType().getTypePtr(); + continue; + + // -- If T is a fundamental type, its associated sets of + // namespaces and classes are both empty. + case Type::Builtin: + break; + + // -- If T is a class type (including unions), its associated + // classes are: the class itself; the class of which it is a + // member, if any; and its direct and indirect base + // classes. Its associated namespaces are the namespaces in + // which its associated classes are defined. + case Type::Record: { + CXXRecordDecl *Class + = cast(cast(T)->getDecl()); + addAssociatedClassesAndNamespaces(Result, Class); + break; + } + + // -- If T is an enumeration type, its associated namespace is + // the namespace in which it is defined. If it is class + // member, its associated class is the member's class; else + // it has no associated class. + case Type::Enum: { + EnumDecl *Enum = cast(T)->getDecl(); + + DeclContext *Ctx = Enum->getDeclContext(); + if (CXXRecordDecl *EnclosingClass = dyn_cast(Ctx)) + Result.Classes.insert(EnclosingClass); + + // Add the associated namespace for this class. + CollectEnclosingNamespace(Result.Namespaces, Ctx); + + break; + } + + // -- If T is a function type, its associated namespaces and + // classes are those associated with the function parameter + // types and those associated with the return type. + case Type::FunctionProto: { + const FunctionProtoType *Proto = cast(T); + for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(), + ArgEnd = Proto->arg_type_end(); + Arg != ArgEnd; ++Arg) + Queue.push_back(Arg->getTypePtr()); + // fallthrough + } + case Type::FunctionNoProto: { + const FunctionType *FnType = cast(T); + T = FnType->getResultType().getTypePtr(); + continue; + } + + // -- If T is a pointer to a member function of a class X, its + // associated namespaces and classes are those associated + // with the function parameter types and return type, + // together with those associated with X. + // + // -- If T is a pointer to a data member of class X, its + // associated namespaces and classes are those associated + // with the member type together with those associated with + // X. + case Type::MemberPointer: { + const MemberPointerType *MemberPtr = cast(T); + + // Queue up the class type into which this points. + Queue.push_back(MemberPtr->getClass()); + + // And directly continue with the pointee type. + T = MemberPtr->getPointeeType().getTypePtr(); + continue; + } + + // As an extension, treat this like a normal pointer. + case Type::BlockPointer: + T = cast(T)->getPointeeType().getTypePtr(); + continue; + + // References aren't covered by the standard, but that's such an + // obvious defect that we cover them anyway. + case Type::LValueReference: + case Type::RValueReference: + T = cast(T)->getPointeeType().getTypePtr(); + continue; + + // These are fundamental types. + case Type::Vector: + case Type::ExtVector: + case Type::Complex: + break; + + // If T is an Objective-C object or interface type, or a pointer to an + // object or interface type, the associated namespace is the global + // namespace. + case Type::ObjCObject: + case Type::ObjCInterface: + case Type::ObjCObjectPointer: + Result.Namespaces.insert(Result.S.Context.getTranslationUnitDecl()); + break; + + // Atomic types are just wrappers; use the associations of the + // contained type. + case Type::Atomic: + T = cast(T)->getValueType().getTypePtr(); + continue; + } + + if (Queue.empty()) break; + T = Queue.back(); + Queue.pop_back(); + } +} + +/// \brief Find the associated classes and namespaces for +/// argument-dependent lookup for a call with the given set of +/// arguments. +/// +/// This routine computes the sets of associated classes and associated +/// namespaces searched by argument-dependent lookup +/// (C++ [basic.lookup.argdep]) for a given set of arguments. +void +Sema::FindAssociatedClassesAndNamespaces(llvm::ArrayRef Args, + AssociatedNamespaceSet &AssociatedNamespaces, + AssociatedClassSet &AssociatedClasses) { + AssociatedNamespaces.clear(); + AssociatedClasses.clear(); + + AssociatedLookup Result(*this, AssociatedNamespaces, AssociatedClasses); + + // C++ [basic.lookup.koenig]p2: + // For each argument type T in the function call, there is a set + // of zero or more associated namespaces and a set of zero or more + // associated classes to be considered. The sets of namespaces and + // classes is determined entirely by the types of the function + // arguments (and the namespace of any template template + // argument). + for (unsigned ArgIdx = 0; ArgIdx != Args.size(); ++ArgIdx) { + Expr *Arg = Args[ArgIdx]; + + if (Arg->getType() != Context.OverloadTy) { + addAssociatedClassesAndNamespaces(Result, Arg->getType()); + continue; + } + + // [...] In addition, if the argument is the name or address of a + // set of overloaded functions and/or function templates, its + // associated classes and namespaces are the union of those + // associated with each of the members of the set: the namespace + // in which the function or function template is defined and the + // classes and namespaces associated with its (non-dependent) + // parameter types and return type. + Arg = Arg->IgnoreParens(); + if (UnaryOperator *unaryOp = dyn_cast(Arg)) + if (unaryOp->getOpcode() == UO_AddrOf) + Arg = unaryOp->getSubExpr(); + + UnresolvedLookupExpr *ULE = dyn_cast(Arg); + if (!ULE) continue; + + for (UnresolvedSetIterator I = ULE->decls_begin(), E = ULE->decls_end(); + I != E; ++I) { + // Look through any using declarations to find the underlying function. + NamedDecl *Fn = (*I)->getUnderlyingDecl(); + + FunctionDecl *FDecl = dyn_cast(Fn); + if (!FDecl) + FDecl = cast(Fn)->getTemplatedDecl(); + + // Add the classes and namespaces associated with the parameter + // types and return type of this function. + addAssociatedClassesAndNamespaces(Result, FDecl->getType()); + } + } +} + +/// IsAcceptableNonMemberOperatorCandidate - Determine whether Fn is +/// an acceptable non-member overloaded operator for a call whose +/// arguments have types T1 (and, if non-empty, T2). This routine +/// implements the check in C++ [over.match.oper]p3b2 concerning +/// enumeration types. +static bool +IsAcceptableNonMemberOperatorCandidate(FunctionDecl *Fn, + QualType T1, QualType T2, + ASTContext &Context) { + if (T1->isDependentType() || (!T2.isNull() && T2->isDependentType())) + return true; + + if (T1->isRecordType() || (!T2.isNull() && T2->isRecordType())) + return true; + + const FunctionProtoType *Proto = Fn->getType()->getAs(); + if (Proto->getNumArgs() < 1) + return false; + + if (T1->isEnumeralType()) { + QualType ArgType = Proto->getArgType(0).getNonReferenceType(); + if (Context.hasSameUnqualifiedType(T1, ArgType)) + return true; + } + + if (Proto->getNumArgs() < 2) + return false; + + if (!T2.isNull() && T2->isEnumeralType()) { + QualType ArgType = Proto->getArgType(1).getNonReferenceType(); + if (Context.hasSameUnqualifiedType(T2, ArgType)) + return true; + } + + return false; +} + +NamedDecl *Sema::LookupSingleName(Scope *S, DeclarationName Name, + SourceLocation Loc, + LookupNameKind NameKind, + RedeclarationKind Redecl) { + LookupResult R(*this, Name, Loc, NameKind, Redecl); + LookupName(R, S); + return R.getAsSingle(); +} + +/// \brief Find the protocol with the given name, if any. +ObjCProtocolDecl *Sema::LookupProtocol(IdentifierInfo *II, + SourceLocation IdLoc, + RedeclarationKind Redecl) { + Decl *D = LookupSingleName(TUScope, II, IdLoc, + LookupObjCProtocolName, Redecl); + return cast_or_null(D); +} + +void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S, + QualType T1, QualType T2, + UnresolvedSetImpl &Functions) { + // C++ [over.match.oper]p3: + // -- The set of non-member candidates is the result of the + // unqualified lookup of operator@ in the context of the + // expression according to the usual rules for name lookup in + // unqualified function calls (3.4.2) except that all member + // functions are ignored. However, if no operand has a class + // type, only those non-member functions in the lookup set + // that have a first parameter of type T1 or "reference to + // (possibly cv-qualified) T1", when T1 is an enumeration + // type, or (if there is a right operand) a second parameter + // of type T2 or "reference to (possibly cv-qualified) T2", + // when T2 is an enumeration type, are candidate functions. + DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op); + LookupResult Operators(*this, OpName, SourceLocation(), LookupOperatorName); + LookupName(Operators, S); + + assert(!Operators.isAmbiguous() && "Operator lookup cannot be ambiguous"); + + if (Operators.empty()) + return; + + for (LookupResult::iterator Op = Operators.begin(), OpEnd = Operators.end(); + Op != OpEnd; ++Op) { + NamedDecl *Found = (*Op)->getUnderlyingDecl(); + if (FunctionDecl *FD = dyn_cast(Found)) { + if (IsAcceptableNonMemberOperatorCandidate(FD, T1, T2, Context)) + Functions.addDecl(*Op, Op.getAccess()); // FIXME: canonical FD + } else if (FunctionTemplateDecl *FunTmpl + = dyn_cast(Found)) { + // FIXME: friend operators? + // FIXME: do we need to check IsAcceptableNonMemberOperatorCandidate, + // later? + if (!FunTmpl->getDeclContext()->isRecord()) + Functions.addDecl(*Op, Op.getAccess()); + } + } +} + +Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD, + CXXSpecialMember SM, + bool ConstArg, + bool VolatileArg, + bool RValueThis, + bool ConstThis, + bool VolatileThis) { + RD = RD->getDefinition(); + assert((RD && !RD->isBeingDefined()) && + "doing special member lookup into record that isn't fully complete"); + if (RValueThis || ConstThis || VolatileThis) + assert((SM == CXXCopyAssignment || SM == CXXMoveAssignment) && + "constructors and destructors always have unqualified lvalue this"); + if (ConstArg || VolatileArg) + assert((SM != CXXDefaultConstructor && SM != CXXDestructor) && + "parameter-less special members can't have qualified arguments"); + + llvm::FoldingSetNodeID ID; + ID.AddPointer(RD); + ID.AddInteger(SM); + ID.AddInteger(ConstArg); + ID.AddInteger(VolatileArg); + ID.AddInteger(RValueThis); + ID.AddInteger(ConstThis); + ID.AddInteger(VolatileThis); + + void *InsertPoint; + SpecialMemberOverloadResult *Result = + SpecialMemberCache.FindNodeOrInsertPos(ID, InsertPoint); + + // This was already cached + if (Result) + return Result; + + Result = BumpAlloc.Allocate(); + Result = new (Result) SpecialMemberOverloadResult(ID); + SpecialMemberCache.InsertNode(Result, InsertPoint); + + if (SM == CXXDestructor) { + if (!RD->hasDeclaredDestructor()) + DeclareImplicitDestructor(RD); + CXXDestructorDecl *DD = RD->getDestructor(); + assert(DD && "record without a destructor"); + Result->setMethod(DD); + Result->setKind(DD->isDeleted() ? + SpecialMemberOverloadResult::NoMemberOrDeleted : + SpecialMemberOverloadResult::Success); + return Result; + } + + // Prepare for overload resolution. Here we construct a synthetic argument + // if necessary and make sure that implicit functions are declared. + CanQualType CanTy = Context.getCanonicalType(Context.getTagDeclType(RD)); + DeclarationName Name; + Expr *Arg = 0; + unsigned NumArgs; + + QualType ArgType = CanTy; + ExprValueKind VK = VK_LValue; + + if (SM == CXXDefaultConstructor) { + Name = Context.DeclarationNames.getCXXConstructorName(CanTy); + NumArgs = 0; + if (RD->needsImplicitDefaultConstructor()) + DeclareImplicitDefaultConstructor(RD); + } else { + if (SM == CXXCopyConstructor || SM == CXXMoveConstructor) { + Name = Context.DeclarationNames.getCXXConstructorName(CanTy); + if (!RD->hasDeclaredCopyConstructor()) + DeclareImplicitCopyConstructor(RD); + if (getLangOpts().CPlusPlus0x && RD->needsImplicitMoveConstructor()) + DeclareImplicitMoveConstructor(RD); + } else { + Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal); + if (!RD->hasDeclaredCopyAssignment()) + DeclareImplicitCopyAssignment(RD); + if (getLangOpts().CPlusPlus0x && RD->needsImplicitMoveAssignment()) + DeclareImplicitMoveAssignment(RD); + } + + if (ConstArg) + ArgType.addConst(); + if (VolatileArg) + ArgType.addVolatile(); + + // This isn't /really/ specified by the standard, but it's implied + // we should be working from an RValue in the case of move to ensure + // that we prefer to bind to rvalue references, and an LValue in the + // case of copy to ensure we don't bind to rvalue references. + // Possibly an XValue is actually correct in the case of move, but + // there is no semantic difference for class types in this restricted + // case. + if (SM == CXXCopyConstructor || SM == CXXCopyAssignment) + VK = VK_LValue; + else + VK = VK_RValue; + } + + OpaqueValueExpr FakeArg(SourceLocation(), ArgType, VK); + + if (SM != CXXDefaultConstructor) { + NumArgs = 1; + Arg = &FakeArg; + } + + // Create the object argument + QualType ThisTy = CanTy; + if (ConstThis) + ThisTy.addConst(); + if (VolatileThis) + ThisTy.addVolatile(); + Expr::Classification Classification = + OpaqueValueExpr(SourceLocation(), ThisTy, + RValueThis ? VK_RValue : VK_LValue).Classify(Context); + + // Now we perform lookup on the name we computed earlier and do overload + // resolution. Lookup is only performed directly into the class since there + // will always be a (possibly implicit) declaration to shadow any others. + OverloadCandidateSet OCS((SourceLocation())); + DeclContext::lookup_iterator I, E; + + llvm::tie(I, E) = RD->lookup(Name); + assert((I != E) && + "lookup for a constructor or assignment operator was empty"); + for ( ; I != E; ++I) { + Decl *Cand = *I; + + if (Cand->isInvalidDecl()) + continue; + + if (UsingShadowDecl *U = dyn_cast(Cand)) { + // FIXME: [namespace.udecl]p15 says that we should only consider a + // using declaration here if it does not match a declaration in the + // derived class. We do not implement this correctly in other cases + // either. + Cand = U->getTargetDecl(); + + if (Cand->isInvalidDecl()) + continue; + } + + if (CXXMethodDecl *M = dyn_cast(Cand)) { + if (SM == CXXCopyAssignment || SM == CXXMoveAssignment) + AddMethodCandidate(M, DeclAccessPair::make(M, AS_public), RD, ThisTy, + Classification, llvm::makeArrayRef(&Arg, NumArgs), + OCS, true); + else + AddOverloadCandidate(M, DeclAccessPair::make(M, AS_public), + llvm::makeArrayRef(&Arg, NumArgs), OCS, true); + } else if (FunctionTemplateDecl *Tmpl = + dyn_cast(Cand)) { + if (SM == CXXCopyAssignment || SM == CXXMoveAssignment) + AddMethodTemplateCandidate(Tmpl, DeclAccessPair::make(Tmpl, AS_public), + RD, 0, ThisTy, Classification, + llvm::makeArrayRef(&Arg, NumArgs), + OCS, true); + else + AddTemplateOverloadCandidate(Tmpl, DeclAccessPair::make(Tmpl, AS_public), + 0, llvm::makeArrayRef(&Arg, NumArgs), + OCS, true); + } else { + assert(isa(Cand) && "illegal Kind of operator = Decl"); + } + } + + OverloadCandidateSet::iterator Best; + switch (OCS.BestViableFunction(*this, SourceLocation(), Best)) { + case OR_Success: + Result->setMethod(cast(Best->Function)); + Result->setKind(SpecialMemberOverloadResult::Success); + break; + + case OR_Deleted: + Result->setMethod(cast(Best->Function)); + Result->setKind(SpecialMemberOverloadResult::NoMemberOrDeleted); + break; + + case OR_Ambiguous: + Result->setMethod(0); + Result->setKind(SpecialMemberOverloadResult::Ambiguous); + break; + + case OR_No_Viable_Function: + Result->setMethod(0); + Result->setKind(SpecialMemberOverloadResult::NoMemberOrDeleted); + break; + } + + return Result; +} + +/// \brief Look up the default constructor for the given class. +CXXConstructorDecl *Sema::LookupDefaultConstructor(CXXRecordDecl *Class) { + SpecialMemberOverloadResult *Result = + LookupSpecialMember(Class, CXXDefaultConstructor, false, false, false, + false, false); + + return cast_or_null(Result->getMethod()); +} + +/// \brief Look up the copying constructor for the given class. +CXXConstructorDecl *Sema::LookupCopyingConstructor(CXXRecordDecl *Class, + unsigned Quals) { + assert(!(Quals & ~(Qualifiers::Const | Qualifiers::Volatile)) && + "non-const, non-volatile qualifiers for copy ctor arg"); + SpecialMemberOverloadResult *Result = + LookupSpecialMember(Class, CXXCopyConstructor, Quals & Qualifiers::Const, + Quals & Qualifiers::Volatile, false, false, false); + + return cast_or_null(Result->getMethod()); +} + +/// \brief Look up the moving constructor for the given class. +CXXConstructorDecl *Sema::LookupMovingConstructor(CXXRecordDecl *Class) { + SpecialMemberOverloadResult *Result = + LookupSpecialMember(Class, CXXMoveConstructor, false, + false, false, false, false); + + return cast_or_null(Result->getMethod()); +} + +/// \brief Look up the constructors for the given class. +DeclContext::lookup_result Sema::LookupConstructors(CXXRecordDecl *Class) { + // If the implicit constructors have not yet been declared, do so now. + if (CanDeclareSpecialMemberFunction(Context, Class)) { + if (Class->needsImplicitDefaultConstructor()) + DeclareImplicitDefaultConstructor(Class); + if (!Class->hasDeclaredCopyConstructor()) + DeclareImplicitCopyConstructor(Class); + if (getLangOpts().CPlusPlus0x && Class->needsImplicitMoveConstructor()) + DeclareImplicitMoveConstructor(Class); + } + + CanQualType T = Context.getCanonicalType(Context.getTypeDeclType(Class)); + DeclarationName Name = Context.DeclarationNames.getCXXConstructorName(T); + return Class->lookup(Name); +} + +/// \brief Look up the copying assignment operator for the given class. +CXXMethodDecl *Sema::LookupCopyingAssignment(CXXRecordDecl *Class, + unsigned Quals, bool RValueThis, + unsigned ThisQuals) { + assert(!(Quals & ~(Qualifiers::Const | Qualifiers::Volatile)) && + "non-const, non-volatile qualifiers for copy assignment arg"); + assert(!(ThisQuals & ~(Qualifiers::Const | Qualifiers::Volatile)) && + "non-const, non-volatile qualifiers for copy assignment this"); + SpecialMemberOverloadResult *Result = + LookupSpecialMember(Class, CXXCopyAssignment, Quals & Qualifiers::Const, + Quals & Qualifiers::Volatile, RValueThis, + ThisQuals & Qualifiers::Const, + ThisQuals & Qualifiers::Volatile); + + return Result->getMethod(); +} + +/// \brief Look up the moving assignment operator for the given class. +CXXMethodDecl *Sema::LookupMovingAssignment(CXXRecordDecl *Class, + bool RValueThis, + unsigned ThisQuals) { + assert(!(ThisQuals & ~(Qualifiers::Const | Qualifiers::Volatile)) && + "non-const, non-volatile qualifiers for copy assignment this"); + SpecialMemberOverloadResult *Result = + LookupSpecialMember(Class, CXXMoveAssignment, false, false, RValueThis, + ThisQuals & Qualifiers::Const, + ThisQuals & Qualifiers::Volatile); + + return Result->getMethod(); +} + +/// \brief Look for the destructor of the given class. +/// +/// During semantic analysis, this routine should be used in lieu of +/// CXXRecordDecl::getDestructor(). +/// +/// \returns The destructor for this class. +CXXDestructorDecl *Sema::LookupDestructor(CXXRecordDecl *Class) { + return cast(LookupSpecialMember(Class, CXXDestructor, + false, false, false, + false, false)->getMethod()); +} + +/// LookupLiteralOperator - Determine which literal operator should be used for +/// a user-defined literal, per C++11 [lex.ext]. +/// +/// Normal overload resolution is not used to select which literal operator to +/// call for a user-defined literal. Look up the provided literal operator name, +/// and filter the results to the appropriate set for the given argument types. +Sema::LiteralOperatorLookupResult +Sema::LookupLiteralOperator(Scope *S, LookupResult &R, + ArrayRef ArgTys, + bool AllowRawAndTemplate) { + LookupName(R, S); + assert(R.getResultKind() != LookupResult::Ambiguous && + "literal operator lookup can't be ambiguous"); + + // Filter the lookup results appropriately. + LookupResult::Filter F = R.makeFilter(); + + bool FoundTemplate = false; + bool FoundRaw = false; + bool FoundExactMatch = false; + + while (F.hasNext()) { + Decl *D = F.next(); + if (UsingShadowDecl *USD = dyn_cast(D)) + D = USD->getTargetDecl(); + + bool IsTemplate = isa(D); + bool IsRaw = false; + bool IsExactMatch = false; + + if (FunctionDecl *FD = dyn_cast(D)) { + if (FD->getNumParams() == 1 && + FD->getParamDecl(0)->getType()->getAs()) + IsRaw = true; + else { + IsExactMatch = true; + for (unsigned ArgIdx = 0; ArgIdx != ArgTys.size(); ++ArgIdx) { + QualType ParamTy = FD->getParamDecl(ArgIdx)->getType(); + if (!Context.hasSameUnqualifiedType(ArgTys[ArgIdx], ParamTy)) { + IsExactMatch = false; + break; + } + } + } + } + + if (IsExactMatch) { + FoundExactMatch = true; + AllowRawAndTemplate = false; + if (FoundRaw || FoundTemplate) { + // Go through again and remove the raw and template decls we've + // already found. + F.restart(); + FoundRaw = FoundTemplate = false; + } + } else if (AllowRawAndTemplate && (IsTemplate || IsRaw)) { + FoundTemplate |= IsTemplate; + FoundRaw |= IsRaw; + } else { + F.erase(); + } + } + + F.done(); + + // C++11 [lex.ext]p3, p4: If S contains a literal operator with a matching + // parameter type, that is used in preference to a raw literal operator + // or literal operator template. + if (FoundExactMatch) + return LOLR_Cooked; + + // C++11 [lex.ext]p3, p4: S shall contain a raw literal operator or a literal + // operator template, but not both. + if (FoundRaw && FoundTemplate) { + Diag(R.getNameLoc(), diag::err_ovl_ambiguous_call) << R.getLookupName(); + for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { + Decl *D = *I; + if (UsingShadowDecl *USD = dyn_cast(D)) + D = USD->getTargetDecl(); + if (FunctionTemplateDecl *FunTmpl = dyn_cast(D)) + D = FunTmpl->getTemplatedDecl(); + NoteOverloadCandidate(cast(D)); + } + return LOLR_Error; + } + + if (FoundRaw) + return LOLR_Raw; + + if (FoundTemplate) + return LOLR_Template; + + // Didn't find anything we could use. + Diag(R.getNameLoc(), diag::err_ovl_no_viable_literal_operator) + << R.getLookupName() << (int)ArgTys.size() << ArgTys[0] + << (ArgTys.size() == 2 ? ArgTys[1] : QualType()) << AllowRawAndTemplate; + return LOLR_Error; +} + +void ADLResult::insert(NamedDecl *New) { + NamedDecl *&Old = Decls[cast(New->getCanonicalDecl())]; + + // If we haven't yet seen a decl for this key, or the last decl + // was exactly this one, we're done. + if (Old == 0 || Old == New) { + Old = New; + return; + } + + // Otherwise, decide which is a more recent redeclaration. + FunctionDecl *OldFD, *NewFD; + if (isa(New)) { + OldFD = cast(Old)->getTemplatedDecl(); + NewFD = cast(New)->getTemplatedDecl(); + } else { + OldFD = cast(Old); + NewFD = cast(New); + } + + FunctionDecl *Cursor = NewFD; + while (true) { + Cursor = Cursor->getPreviousDecl(); + + // If we got to the end without finding OldFD, OldFD is the newer + // declaration; leave things as they are. + if (!Cursor) return; + + // If we do find OldFD, then NewFD is newer. + if (Cursor == OldFD) break; + + // Otherwise, keep looking. + } + + Old = New; +} + +void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator, + SourceLocation Loc, + llvm::ArrayRef Args, + ADLResult &Result, + bool StdNamespaceIsAssociated) { + // Find all of the associated namespaces and classes based on the + // arguments we have. + AssociatedNamespaceSet AssociatedNamespaces; + AssociatedClassSet AssociatedClasses; + FindAssociatedClassesAndNamespaces(Args, + AssociatedNamespaces, + AssociatedClasses); + if (StdNamespaceIsAssociated && StdNamespace) + AssociatedNamespaces.insert(getStdNamespace()); + + QualType T1, T2; + if (Operator) { + T1 = Args[0]->getType(); + if (Args.size() >= 2) + T2 = Args[1]->getType(); + } + + // Try to complete all associated classes, in case they contain a + // declaration of a friend function. + for (AssociatedClassSet::iterator C = AssociatedClasses.begin(), + CEnd = AssociatedClasses.end(); + C != CEnd; ++C) + RequireCompleteType(Loc, Context.getRecordType(*C), 0); + + // C++ [basic.lookup.argdep]p3: + // Let X be the lookup set produced by unqualified lookup (3.4.1) + // and let Y be the lookup set produced by argument dependent + // lookup (defined as follows). If X contains [...] then Y is + // empty. Otherwise Y is the set of declarations found in the + // namespaces associated with the argument types as described + // below. The set of declarations found by the lookup of the name + // is the union of X and Y. + // + // Here, we compute Y and add its members to the overloaded + // candidate set. + for (AssociatedNamespaceSet::iterator NS = AssociatedNamespaces.begin(), + NSEnd = AssociatedNamespaces.end(); + NS != NSEnd; ++NS) { + // When considering an associated namespace, the lookup is the + // same as the lookup performed when the associated namespace is + // used as a qualifier (3.4.3.2) except that: + // + // -- Any using-directives in the associated namespace are + // ignored. + // + // -- Any namespace-scope friend functions declared in + // associated classes are visible within their respective + // namespaces even if they are not visible during an ordinary + // lookup (11.4). + DeclContext::lookup_iterator I, E; + for (llvm::tie(I, E) = (*NS)->lookup(Name); I != E; ++I) { + NamedDecl *D = *I; + // If the only declaration here is an ordinary friend, consider + // it only if it was declared in an associated classes. + if (D->getIdentifierNamespace() == Decl::IDNS_OrdinaryFriend) { + DeclContext *LexDC = D->getLexicalDeclContext(); + if (!AssociatedClasses.count(cast(LexDC))) + continue; + } + + if (isa(D)) + D = cast(D)->getTargetDecl(); + + if (isa(D)) { + if (Operator && + !IsAcceptableNonMemberOperatorCandidate(cast(D), + T1, T2, Context)) + continue; + } else if (!isa(D)) + continue; + + Result.insert(D); + } + } +} + +//---------------------------------------------------------------------------- +// Search for all visible declarations. +//---------------------------------------------------------------------------- +VisibleDeclConsumer::~VisibleDeclConsumer() { } + +namespace { + +class ShadowContextRAII; + +class VisibleDeclsRecord { +public: + /// \brief An entry in the shadow map, which is optimized to store a + /// single declaration (the common case) but can also store a list + /// of declarations. + typedef llvm::TinyPtrVector ShadowMapEntry; + +private: + /// \brief A mapping from declaration names to the declarations that have + /// this name within a particular scope. + typedef llvm::DenseMap ShadowMap; + + /// \brief A list of shadow maps, which is used to model name hiding. + std::list ShadowMaps; + + /// \brief The declaration contexts we have already visited. + llvm::SmallPtrSet VisitedContexts; + + friend class ShadowContextRAII; + +public: + /// \brief Determine whether we have already visited this context + /// (and, if not, note that we are going to visit that context now). + bool visitedContext(DeclContext *Ctx) { + return !VisitedContexts.insert(Ctx); + } + + bool alreadyVisitedContext(DeclContext *Ctx) { + return VisitedContexts.count(Ctx); + } + + /// \brief Determine whether the given declaration is hidden in the + /// current scope. + /// + /// \returns the declaration that hides the given declaration, or + /// NULL if no such declaration exists. + NamedDecl *checkHidden(NamedDecl *ND); + + /// \brief Add a declaration to the current shadow map. + void add(NamedDecl *ND) { + ShadowMaps.back()[ND->getDeclName()].push_back(ND); + } +}; + +/// \brief RAII object that records when we've entered a shadow context. +class ShadowContextRAII { + VisibleDeclsRecord &Visible; + + typedef VisibleDeclsRecord::ShadowMap ShadowMap; + +public: + ShadowContextRAII(VisibleDeclsRecord &Visible) : Visible(Visible) { + Visible.ShadowMaps.push_back(ShadowMap()); + } + + ~ShadowContextRAII() { + Visible.ShadowMaps.pop_back(); + } +}; + +} // end anonymous namespace + +NamedDecl *VisibleDeclsRecord::checkHidden(NamedDecl *ND) { + // Look through using declarations. + ND = ND->getUnderlyingDecl(); + + unsigned IDNS = ND->getIdentifierNamespace(); + std::list::reverse_iterator SM = ShadowMaps.rbegin(); + for (std::list::reverse_iterator SMEnd = ShadowMaps.rend(); + SM != SMEnd; ++SM) { + ShadowMap::iterator Pos = SM->find(ND->getDeclName()); + if (Pos == SM->end()) + continue; + + for (ShadowMapEntry::iterator I = Pos->second.begin(), + IEnd = Pos->second.end(); + I != IEnd; ++I) { + // A tag declaration does not hide a non-tag declaration. + if ((*I)->hasTagIdentifierNamespace() && + (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary | + Decl::IDNS_ObjCProtocol))) + continue; + + // Protocols are in distinct namespaces from everything else. + if ((((*I)->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol) + || (IDNS & Decl::IDNS_ObjCProtocol)) && + (*I)->getIdentifierNamespace() != IDNS) + continue; + + // Functions and function templates in the same scope overload + // rather than hide. FIXME: Look for hiding based on function + // signatures! + if ((*I)->isFunctionOrFunctionTemplate() && + ND->isFunctionOrFunctionTemplate() && + SM == ShadowMaps.rbegin()) + continue; + + // We've found a declaration that hides this one. + return *I; + } + } + + return 0; +} + +static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result, + bool QualifiedNameLookup, + bool InBaseClass, + VisibleDeclConsumer &Consumer, + VisibleDeclsRecord &Visited) { + if (!Ctx) + return; + + // Make sure we don't visit the same context twice. + if (Visited.visitedContext(Ctx->getPrimaryContext())) + return; + + if (CXXRecordDecl *Class = dyn_cast(Ctx)) + Result.getSema().ForceDeclarationOfImplicitMembers(Class); + + // Enumerate all of the results in this context. + for (DeclContext::all_lookups_iterator L = Ctx->lookups_begin(), + LEnd = Ctx->lookups_end(); + L != LEnd; ++L) { + for (DeclContext::lookup_result R = *L; R.first != R.second; ++R.first) { + if (NamedDecl *ND = dyn_cast(*R.first)) { + if ((ND = Result.getAcceptableDecl(ND))) { + Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass); + Visited.add(ND); + } + } + } + } + + // Traverse using directives for qualified name lookup. + if (QualifiedNameLookup) { + ShadowContextRAII Shadow(Visited); + DeclContext::udir_iterator I, E; + for (llvm::tie(I, E) = Ctx->getUsingDirectives(); I != E; ++I) { + LookupVisibleDecls((*I)->getNominatedNamespace(), Result, + QualifiedNameLookup, InBaseClass, Consumer, Visited); + } + } + + // Traverse the contexts of inherited C++ classes. + if (CXXRecordDecl *Record = dyn_cast(Ctx)) { + if (!Record->hasDefinition()) + return; + + for (CXXRecordDecl::base_class_iterator B = Record->bases_begin(), + BEnd = Record->bases_end(); + B != BEnd; ++B) { + QualType BaseType = B->getType(); + + // Don't look into dependent bases, because name lookup can't look + // there anyway. + if (BaseType->isDependentType()) + continue; + + const RecordType *Record = BaseType->getAs(); + if (!Record) + continue; + + // FIXME: It would be nice to be able to determine whether referencing + // a particular member would be ambiguous. For example, given + // + // struct A { int member; }; + // struct B { int member; }; + // struct C : A, B { }; + // + // void f(C *c) { c->### } + // + // accessing 'member' would result in an ambiguity. However, we + // could be smart enough to qualify the member with the base + // class, e.g., + // + // c->B::member + // + // or + // + // c->A::member + + // Find results in this base class (and its bases). + ShadowContextRAII Shadow(Visited); + LookupVisibleDecls(Record->getDecl(), Result, QualifiedNameLookup, + true, Consumer, Visited); + } + } + + // Traverse the contexts of Objective-C classes. + if (ObjCInterfaceDecl *IFace = dyn_cast(Ctx)) { + // Traverse categories. + for (ObjCCategoryDecl *Category = IFace->getCategoryList(); + Category; Category = Category->getNextClassCategory()) { + ShadowContextRAII Shadow(Visited); + LookupVisibleDecls(Category, Result, QualifiedNameLookup, false, + Consumer, Visited); + } + + // Traverse protocols. + 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); + } + + // Traverse the superclass. + if (IFace->getSuperClass()) { + ShadowContextRAII Shadow(Visited); + LookupVisibleDecls(IFace->getSuperClass(), Result, QualifiedNameLookup, + true, Consumer, Visited); + } + + // If there is an implementation, traverse it. We do this to find + // synthesized ivars. + if (IFace->getImplementation()) { + ShadowContextRAII Shadow(Visited); + LookupVisibleDecls(IFace->getImplementation(), Result, + QualifiedNameLookup, InBaseClass, Consumer, Visited); + } + } else if (ObjCProtocolDecl *Protocol = dyn_cast(Ctx)) { + for (ObjCProtocolDecl::protocol_iterator I = Protocol->protocol_begin(), + E = Protocol->protocol_end(); I != E; ++I) { + ShadowContextRAII Shadow(Visited); + LookupVisibleDecls(*I, Result, QualifiedNameLookup, false, Consumer, + Visited); + } + } else if (ObjCCategoryDecl *Category = dyn_cast(Ctx)) { + for (ObjCCategoryDecl::protocol_iterator I = Category->protocol_begin(), + E = Category->protocol_end(); I != E; ++I) { + ShadowContextRAII Shadow(Visited); + LookupVisibleDecls(*I, Result, QualifiedNameLookup, false, Consumer, + Visited); + } + + // If there is an implementation, traverse it. + if (Category->getImplementation()) { + ShadowContextRAII Shadow(Visited); + LookupVisibleDecls(Category->getImplementation(), Result, + QualifiedNameLookup, true, Consumer, Visited); + } + } +} + +static void LookupVisibleDecls(Scope *S, LookupResult &Result, + UnqualUsingDirectiveSet &UDirs, + VisibleDeclConsumer &Consumer, + VisibleDeclsRecord &Visited) { + if (!S) + return; + + 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(*D)) + if ((ND = Result.getAcceptableDecl(ND))) { + Consumer.FoundDecl(ND, Visited.checkHidden(ND), 0, false); + Visited.add(ND); + } + } + } + + // FIXME: C++ [temp.local]p8 + DeclContext *Entity = 0; + if (S->getEntity()) { + // Look into this scope's declaration context, along with any of its + // parent lookup contexts (e.g., enclosing classes), up to the point + // where we hit the context stored in the next outer scope. + Entity = (DeclContext *)S->getEntity(); + DeclContext *OuterCtx = findOuterContext(S).first; // FIXME + + for (DeclContext *Ctx = Entity; Ctx && !Ctx->Equals(OuterCtx); + Ctx = Ctx->getLookupParent()) { + if (ObjCMethodDecl *Method = dyn_cast(Ctx)) { + if (Method->isInstanceMethod()) { + // For instance methods, look for ivars in the method's interface. + LookupResult IvarResult(Result.getSema(), Result.getLookupName(), + Result.getNameLoc(), Sema::LookupMemberName); + if (ObjCInterfaceDecl *IFace = Method->getClassInterface()) { + LookupVisibleDecls(IFace, IvarResult, /*QualifiedNameLookup=*/false, + /*InBaseClass=*/false, Consumer, Visited); + } + } + + // We've already performed all of the name lookup that we need + // to for Objective-C methods; the next context will be the + // outer scope. + break; + } + + if (Ctx->isFunctionOrMethod()) + continue; + + LookupVisibleDecls(Ctx, Result, /*QualifiedNameLookup=*/false, + /*InBaseClass=*/false, Consumer, Visited); + } + } else if (!S->getParent()) { + // Look into the translation unit scope. We walk through the translation + // unit's declaration context, because the Scope itself won't have all of + // the declarations if we loaded a precompiled header. + // FIXME: We would like the translation unit's Scope object to point to the + // translation unit, so we don't need this special "if" branch. However, + // doing so would force the normal C++ name-lookup code to look into the + // translation unit decl when the IdentifierInfo chains would suffice. + // Once we fix that problem (which is part of a more general "don't look + // in DeclContexts unless we have to" optimization), we can eliminate this. + Entity = Result.getSema().Context.getTranslationUnitDecl(); + LookupVisibleDecls(Entity, Result, /*QualifiedNameLookup=*/false, + /*InBaseClass=*/false, Consumer, Visited); + } + + if (Entity) { + // Lookup visible declarations in any namespaces found by using + // directives. + UnqualUsingDirectiveSet::const_iterator UI, UEnd; + llvm::tie(UI, UEnd) = UDirs.getNamespacesFor(Entity); + for (; UI != UEnd; ++UI) + LookupVisibleDecls(const_cast(UI->getNominatedNamespace()), + Result, /*QualifiedNameLookup=*/false, + /*InBaseClass=*/false, Consumer, Visited); + } + + // Lookup names in the parent scope. + ShadowContextRAII Shadow(Visited); + LookupVisibleDecls(S->getParent(), Result, UDirs, Consumer, Visited); +} + +void Sema::LookupVisibleDecls(Scope *S, LookupNameKind Kind, + VisibleDeclConsumer &Consumer, + bool IncludeGlobalScope) { + // Determine the set of using directives available during + // unqualified name lookup. + Scope *Initial = S; + UnqualUsingDirectiveSet UDirs; + if (getLangOpts().CPlusPlus) { + // Find the first namespace or translation-unit scope. + while (S && !isNamespaceOrTranslationUnitScope(S)) + S = S->getParent(); + + UDirs.visitScopeChain(Initial, S); + } + UDirs.done(); + + // 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, + 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); +} + +/// LookupOrCreateLabel - Do a name lookup of a label with the specified name. +/// If GnuLabelLoc is a valid source location, then this is a definition +/// of an __label__ label name, otherwise it is a normal label definition +/// or use. +LabelDecl *Sema::LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc, + SourceLocation GnuLabelLoc) { + // Do a lookup to see if we have a label with this name already. + NamedDecl *Res = 0; + + if (GnuLabelLoc.isValid()) { + // Local label definitions always shadow existing labels. + Res = LabelDecl::Create(Context, CurContext, Loc, II, GnuLabelLoc); + Scope *S = CurScope; + PushOnScopeChains(Res, S, true); + return cast(Res); + } + + // Not a GNU local label. + Res = LookupSingleName(CurScope, II, Loc, LookupLabel, NotForRedeclaration); + // If we found a label, check to see if it is in the same context as us. + // When in a Block, we don't want to reuse a label in an enclosing function. + if (Res && Res->getDeclContext() != CurContext) + Res = 0; + if (Res == 0) { + // If not forward referenced or defined already, create the backing decl. + Res = LabelDecl::Create(Context, CurContext, Loc, II); + Scope *S = CurScope->getFnParent(); + assert(S && "Not in a function?"); + PushOnScopeChains(Res, S, true); + } + return cast(Res); +} + +//===----------------------------------------------------------------------===// +// Typo correction +//===----------------------------------------------------------------------===// + +namespace { + +typedef llvm::StringMap TypoResultsMap; +typedef std::map TypoEditDistanceMap; + +static const unsigned MaxTypoDistanceResultSets = 5; + +class TypoCorrectionConsumer : public VisibleDeclConsumer { + /// \brief The name written that is a typo in the source. + StringRef Typo; + + /// \brief The results found that have the smallest edit distance + /// found (so far) with the typo name. + /// + /// The pointer value being set to the current DeclContext indicates + /// whether there is a keyword with this name. + TypoEditDistanceMap BestResults; + + Sema &SemaRef; + +public: + explicit TypoCorrectionConsumer(Sema &SemaRef, IdentifierInfo *Typo) + : Typo(Typo->getName()), + SemaRef(SemaRef) { } + + virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx, + bool InBaseClass); + void FoundName(StringRef Name); + void addKeywordResult(StringRef Keyword); + void addName(StringRef Name, NamedDecl *ND, unsigned Distance, + NestedNameSpecifier *NNS=NULL, bool isKeyword=false); + void addCorrection(TypoCorrection Correction); + + typedef TypoResultsMap::iterator result_iterator; + typedef TypoEditDistanceMap::iterator distance_iterator; + distance_iterator begin() { return BestResults.begin(); } + distance_iterator end() { return BestResults.end(); } + void erase(distance_iterator I) { BestResults.erase(I); } + unsigned size() const { return BestResults.size(); } + bool empty() const { return BestResults.empty(); } + + TypoCorrection &operator[](StringRef Name) { + return BestResults.begin()->second[Name]; + } + + unsigned getBestEditDistance(bool Normalized) { + if (BestResults.empty()) + return (std::numeric_limits::max)(); + + unsigned BestED = BestResults.begin()->first; + return Normalized ? TypoCorrection::NormalizeEditDistance(BestED) : BestED; + } +}; + +} + +void TypoCorrectionConsumer::FoundDecl(NamedDecl *ND, NamedDecl *Hiding, + DeclContext *Ctx, bool InBaseClass) { + // Don't consider hidden names for typo correction. + if (Hiding) + return; + + // Only consider entities with identifiers for names, ignoring + // special names (constructors, overloaded operators, selectors, + // etc.). + IdentifierInfo *Name = ND->getIdentifier(); + if (!Name) + return; + + FoundName(Name->getName()); +} + +void TypoCorrectionConsumer::FoundName(StringRef Name) { + // Use a simple length-based heuristic to determine the minimum possible + // edit distance. If the minimum isn't good enough, bail out early. + unsigned MinED = abs((int)Name.size() - (int)Typo.size()); + if (MinED && Typo.size() / MinED < 3) + return; + + // Compute an upper bound on the allowable edit distance, so that the + // edit-distance algorithm can short-circuit. + unsigned UpperBound = (Typo.size() + 2) / 3; + + // Compute the edit distance between the typo and the name of this + // entity, and add the identifier to the list of results. + addName(Name, NULL, Typo.edit_distance(Name, true, UpperBound)); +} + +void TypoCorrectionConsumer::addKeywordResult(StringRef Keyword) { + // Compute the edit distance between the typo and this keyword, + // and add the keyword to the list of results. + addName(Keyword, NULL, Typo.edit_distance(Keyword), NULL, true); +} + +void TypoCorrectionConsumer::addName(StringRef Name, + NamedDecl *ND, + unsigned Distance, + NestedNameSpecifier *NNS, + bool isKeyword) { + TypoCorrection TC(&SemaRef.Context.Idents.get(Name), ND, NNS, Distance); + if (isKeyword) TC.makeKeyword(); + addCorrection(TC); +} + +void TypoCorrectionConsumer::addCorrection(TypoCorrection Correction) { + StringRef Name = Correction.getCorrectionAsIdentifierInfo()->getName(); + TypoResultsMap &Map = BestResults[Correction.getEditDistance(false)]; + + TypoCorrection &CurrentCorrection = Map[Name]; + if (!CurrentCorrection || + // FIXME: The following should be rolled up into an operator< on + // TypoCorrection with a more principled definition. + CurrentCorrection.isKeyword() < Correction.isKeyword() || + Correction.getAsString(SemaRef.getLangOpts()) < + CurrentCorrection.getAsString(SemaRef.getLangOpts())) + CurrentCorrection = Correction; + + while (BestResults.size() > MaxTypoDistanceResultSets) + erase(llvm::prior(BestResults.end())); +} + +// Fill the supplied vector with the IdentifierInfo pointers for each piece of +// the given NestedNameSpecifier (i.e. given a NestedNameSpecifier "foo::bar::", +// fill the vector with the IdentifierInfo pointers for "foo" and "bar"). +static void getNestedNameSpecifierIdentifiers( + NestedNameSpecifier *NNS, + SmallVectorImpl &Identifiers) { + if (NestedNameSpecifier *Prefix = NNS->getPrefix()) + getNestedNameSpecifierIdentifiers(Prefix, Identifiers); + else + Identifiers.clear(); + + const IdentifierInfo *II = NULL; + + switch (NNS->getKind()) { + case NestedNameSpecifier::Identifier: + II = NNS->getAsIdentifier(); + break; + + case NestedNameSpecifier::Namespace: + if (NNS->getAsNamespace()->isAnonymousNamespace()) + return; + II = NNS->getAsNamespace()->getIdentifier(); + break; + + case NestedNameSpecifier::NamespaceAlias: + II = NNS->getAsNamespaceAlias()->getIdentifier(); + break; + + case NestedNameSpecifier::TypeSpecWithTemplate: + case NestedNameSpecifier::TypeSpec: + II = QualType(NNS->getAsType(), 0).getBaseTypeIdentifier(); + break; + + case NestedNameSpecifier::Global: + return; + } + + if (II) + Identifiers.push_back(II); +} + +namespace { + +class SpecifierInfo { + public: + DeclContext* DeclCtx; + NestedNameSpecifier* NameSpecifier; + unsigned EditDistance; + + SpecifierInfo(DeclContext *Ctx, NestedNameSpecifier *NNS, unsigned ED) + : DeclCtx(Ctx), NameSpecifier(NNS), EditDistance(ED) {} +}; + +typedef SmallVector DeclContextList; +typedef SmallVector SpecifierInfoList; + +class NamespaceSpecifierSet { + ASTContext &Context; + DeclContextList CurContextChain; + SmallVector CurContextIdentifiers; + SmallVector CurNameSpecifierIdentifiers; + bool isSorted; + + SpecifierInfoList Specifiers; + llvm::SmallSetVector Distances; + llvm::DenseMap DistanceMap; + + /// \brief Helper for building the list of DeclContexts between the current + /// context and the top of the translation unit + static DeclContextList BuildContextChain(DeclContext *Start); + + void SortNamespaces(); + + public: + NamespaceSpecifierSet(ASTContext &Context, DeclContext *CurContext, + CXXScopeSpec *CurScopeSpec) + : Context(Context), CurContextChain(BuildContextChain(CurContext)), + isSorted(true) { + if (CurScopeSpec && CurScopeSpec->getScopeRep()) + getNestedNameSpecifierIdentifiers(CurScopeSpec->getScopeRep(), + CurNameSpecifierIdentifiers); + // Build the list of identifiers that would be used for an absolute + // (from the global context) NestedNameSpecifier refering to the current + // context. + for (DeclContextList::reverse_iterator C = CurContextChain.rbegin(), + CEnd = CurContextChain.rend(); + C != CEnd; ++C) { + if (NamespaceDecl *ND = dyn_cast_or_null(*C)) + CurContextIdentifiers.push_back(ND->getIdentifier()); + } + } + + /// \brief Add the namespace to the set, computing the corresponding + /// NestedNameSpecifier and its distance in the process. + void AddNamespace(NamespaceDecl *ND); + + typedef SpecifierInfoList::iterator iterator; + iterator begin() { + if (!isSorted) SortNamespaces(); + return Specifiers.begin(); + } + iterator end() { return Specifiers.end(); } +}; + +} + +DeclContextList NamespaceSpecifierSet::BuildContextChain(DeclContext *Start) { + assert(Start && "Bulding a context chain from a null context"); + DeclContextList Chain; + for (DeclContext *DC = Start->getPrimaryContext(); DC != NULL; + DC = DC->getLookupParent()) { + NamespaceDecl *ND = dyn_cast_or_null(DC); + if (!DC->isInlineNamespace() && !DC->isTransparentContext() && + !(ND && ND->isAnonymousNamespace())) + Chain.push_back(DC->getPrimaryContext()); + } + return Chain; +} + +void NamespaceSpecifierSet::SortNamespaces() { + SmallVector sortedDistances; + sortedDistances.append(Distances.begin(), Distances.end()); + + if (sortedDistances.size() > 1) + std::sort(sortedDistances.begin(), sortedDistances.end()); + + Specifiers.clear(); + for (SmallVector::iterator DI = sortedDistances.begin(), + DIEnd = sortedDistances.end(); + DI != DIEnd; ++DI) { + SpecifierInfoList &SpecList = DistanceMap[*DI]; + Specifiers.append(SpecList.begin(), SpecList.end()); + } + + isSorted = true; +} + +void NamespaceSpecifierSet::AddNamespace(NamespaceDecl *ND) { + DeclContext *Ctx = cast(ND); + NestedNameSpecifier *NNS = NULL; + unsigned NumSpecifiers = 0; + DeclContextList NamespaceDeclChain(BuildContextChain(Ctx)); + DeclContextList FullNamespaceDeclChain(NamespaceDeclChain); + + // Eliminate common elements from the two DeclContext chains. + for (DeclContextList::reverse_iterator C = CurContextChain.rbegin(), + CEnd = CurContextChain.rend(); + C != CEnd && !NamespaceDeclChain.empty() && + NamespaceDeclChain.back() == *C; ++C) { + NamespaceDeclChain.pop_back(); + } + + // Add an explicit leading '::' specifier if needed. + if (NamespaceDecl *ND = + NamespaceDeclChain.empty() ? NULL : + dyn_cast_or_null(NamespaceDeclChain.back())) { + IdentifierInfo *Name = ND->getIdentifier(); + if (std::find(CurContextIdentifiers.begin(), CurContextIdentifiers.end(), + Name) != CurContextIdentifiers.end() || + std::find(CurNameSpecifierIdentifiers.begin(), + CurNameSpecifierIdentifiers.end(), + Name) != CurNameSpecifierIdentifiers.end()) { + NamespaceDeclChain = FullNamespaceDeclChain; + NNS = NestedNameSpecifier::GlobalSpecifier(Context); + } + } + + // Build the NestedNameSpecifier from what is left of the NamespaceDeclChain + for (DeclContextList::reverse_iterator C = NamespaceDeclChain.rbegin(), + CEnd = NamespaceDeclChain.rend(); + C != CEnd; ++C) { + NamespaceDecl *ND = dyn_cast_or_null(*C); + if (ND) { + NNS = NestedNameSpecifier::Create(Context, NNS, ND); + ++NumSpecifiers; + } + } + + // If the built NestedNameSpecifier would be replacing an existing + // NestedNameSpecifier, use the number of component identifiers that + // would need to be changed as the edit distance instead of the number + // of components in the built NestedNameSpecifier. + if (NNS && !CurNameSpecifierIdentifiers.empty()) { + SmallVector NewNameSpecifierIdentifiers; + getNestedNameSpecifierIdentifiers(NNS, NewNameSpecifierIdentifiers); + NumSpecifiers = llvm::ComputeEditDistance( + llvm::ArrayRef(CurNameSpecifierIdentifiers), + llvm::ArrayRef(NewNameSpecifierIdentifiers)); + } + + isSorted = false; + Distances.insert(NumSpecifiers); + DistanceMap[NumSpecifiers].push_back(SpecifierInfo(Ctx, NNS, NumSpecifiers)); +} + +/// \brief Perform name lookup for a possible result for typo correction. +static void LookupPotentialTypoResult(Sema &SemaRef, + LookupResult &Res, + IdentifierInfo *Name, + Scope *S, CXXScopeSpec *SS, + DeclContext *MemberContext, + bool EnteringContext, + bool isObjCIvarLookup) { + Res.suppressDiagnostics(); + Res.clear(); + Res.setLookupName(Name); + if (MemberContext) { + if (ObjCInterfaceDecl *Class = dyn_cast(MemberContext)) { + if (isObjCIvarLookup) { + if (ObjCIvarDecl *Ivar = Class->lookupInstanceVariable(Name)) { + Res.addDecl(Ivar); + Res.resolveKind(); + return; + } + } + + if (ObjCPropertyDecl *Prop = Class->FindPropertyDeclaration(Name)) { + Res.addDecl(Prop); + Res.resolveKind(); + return; + } + } + + SemaRef.LookupQualifiedName(Res, MemberContext); + return; + } + + SemaRef.LookupParsedName(Res, S, SS, /*AllowBuiltinCreation=*/false, + EnteringContext); + + // Fake ivar lookup; this should really be part of + // LookupParsedName. + if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) { + if (Method->isInstanceMethod() && Method->getClassInterface() && + (Res.empty() || + (Res.isSingleResult() && + Res.getFoundDecl()->isDefinedOutsideFunctionOrMethod()))) { + if (ObjCIvarDecl *IV + = Method->getClassInterface()->lookupInstanceVariable(Name)) { + Res.addDecl(IV); + Res.resolveKind(); + } + } + } +} + +/// \brief Add keywords to the consumer as possible typo corrections. +static void AddKeywordsToConsumer(Sema &SemaRef, + TypoCorrectionConsumer &Consumer, + Scope *S, CorrectionCandidateCallback &CCC) { + if (CCC.WantObjCSuper) + Consumer.addKeywordResult("super"); + + if (CCC.WantTypeSpecifiers) { + // Add type-specifier keywords to the set of results. + const char *CTypeSpecs[] = { + "char", "const", "double", "enum", "float", "int", "long", "short", + "signed", "struct", "union", "unsigned", "void", "volatile", + "_Complex", "_Imaginary", + // storage-specifiers as well + "extern", "inline", "static", "typedef" + }; + + const unsigned NumCTypeSpecs = sizeof(CTypeSpecs) / sizeof(CTypeSpecs[0]); + for (unsigned I = 0; I != NumCTypeSpecs; ++I) + Consumer.addKeywordResult(CTypeSpecs[I]); + + if (SemaRef.getLangOpts().C99) + Consumer.addKeywordResult("restrict"); + if (SemaRef.getLangOpts().Bool || SemaRef.getLangOpts().CPlusPlus) + Consumer.addKeywordResult("bool"); + else if (SemaRef.getLangOpts().C99) + Consumer.addKeywordResult("_Bool"); + + if (SemaRef.getLangOpts().CPlusPlus) { + Consumer.addKeywordResult("class"); + Consumer.addKeywordResult("typename"); + Consumer.addKeywordResult("wchar_t"); + + if (SemaRef.getLangOpts().CPlusPlus0x) { + Consumer.addKeywordResult("char16_t"); + Consumer.addKeywordResult("char32_t"); + Consumer.addKeywordResult("constexpr"); + Consumer.addKeywordResult("decltype"); + Consumer.addKeywordResult("thread_local"); + } + } + + if (SemaRef.getLangOpts().GNUMode) + Consumer.addKeywordResult("typeof"); + } + + if (CCC.WantCXXNamedCasts && SemaRef.getLangOpts().CPlusPlus) { + Consumer.addKeywordResult("const_cast"); + Consumer.addKeywordResult("dynamic_cast"); + Consumer.addKeywordResult("reinterpret_cast"); + Consumer.addKeywordResult("static_cast"); + } + + if (CCC.WantExpressionKeywords) { + Consumer.addKeywordResult("sizeof"); + if (SemaRef.getLangOpts().Bool || SemaRef.getLangOpts().CPlusPlus) { + Consumer.addKeywordResult("false"); + Consumer.addKeywordResult("true"); + } + + if (SemaRef.getLangOpts().CPlusPlus) { + const char *CXXExprs[] = { + "delete", "new", "operator", "throw", "typeid" + }; + const unsigned NumCXXExprs = sizeof(CXXExprs) / sizeof(CXXExprs[0]); + for (unsigned I = 0; I != NumCXXExprs; ++I) + Consumer.addKeywordResult(CXXExprs[I]); + + if (isa(SemaRef.CurContext) && + cast(SemaRef.CurContext)->isInstance()) + Consumer.addKeywordResult("this"); + + if (SemaRef.getLangOpts().CPlusPlus0x) { + Consumer.addKeywordResult("alignof"); + Consumer.addKeywordResult("nullptr"); + } + } + } + + if (CCC.WantRemainingKeywords) { + if (SemaRef.getCurFunctionOrMethodDecl() || SemaRef.getCurBlock()) { + // Statements. + const char *CStmts[] = { + "do", "else", "for", "goto", "if", "return", "switch", "while" }; + const unsigned NumCStmts = sizeof(CStmts) / sizeof(CStmts[0]); + for (unsigned I = 0; I != NumCStmts; ++I) + Consumer.addKeywordResult(CStmts[I]); + + if (SemaRef.getLangOpts().CPlusPlus) { + Consumer.addKeywordResult("catch"); + Consumer.addKeywordResult("try"); + } + + if (S && S->getBreakParent()) + Consumer.addKeywordResult("break"); + + if (S && S->getContinueParent()) + Consumer.addKeywordResult("continue"); + + if (!SemaRef.getCurFunction()->SwitchStack.empty()) { + Consumer.addKeywordResult("case"); + Consumer.addKeywordResult("default"); + } + } else { + if (SemaRef.getLangOpts().CPlusPlus) { + Consumer.addKeywordResult("namespace"); + Consumer.addKeywordResult("template"); + } + + if (S && S->isClassScope()) { + Consumer.addKeywordResult("explicit"); + Consumer.addKeywordResult("friend"); + Consumer.addKeywordResult("mutable"); + Consumer.addKeywordResult("private"); + Consumer.addKeywordResult("protected"); + Consumer.addKeywordResult("public"); + Consumer.addKeywordResult("virtual"); + } + } + + if (SemaRef.getLangOpts().CPlusPlus) { + Consumer.addKeywordResult("using"); + + if (SemaRef.getLangOpts().CPlusPlus0x) + Consumer.addKeywordResult("static_assert"); + } + } +} + +static bool isCandidateViable(CorrectionCandidateCallback &CCC, + TypoCorrection &Candidate) { + Candidate.setCallbackDistance(CCC.RankCandidate(Candidate)); + return Candidate.getEditDistance(false) != TypoCorrection::InvalidDistance; +} + +/// \brief Try to "correct" a typo in the source code by finding +/// visible declarations whose names are similar to the name that was +/// present in the source code. +/// +/// \param TypoName the \c DeclarationNameInfo structure that contains +/// the name that was present in the source code along with its location. +/// +/// \param LookupKind the name-lookup criteria used to search for the name. +/// +/// \param S the scope in which name lookup occurs. +/// +/// \param SS the nested-name-specifier that precedes the name we're +/// looking for, if present. +/// +/// \param CCC A CorrectionCandidateCallback object that provides further +/// validation of typo correction candidates. It also provides flags for +/// determining the set of keywords permitted. +/// +/// \param MemberContext if non-NULL, the context in which to look for +/// a member access expression. +/// +/// \param EnteringContext whether we're entering the context described by +/// the nested-name-specifier SS. +/// +/// \param OPT when non-NULL, the search for visible declarations will +/// also walk the protocols in the qualified interfaces of \p OPT. +/// +/// \returns a \c TypoCorrection containing the corrected name if the typo +/// along with information such as the \c NamedDecl where the corrected name +/// was declared, and any additional \c NestedNameSpecifier needed to access +/// it (C++ only). The \c TypoCorrection is empty if there is no correction. +TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, + Sema::LookupNameKind LookupKind, + Scope *S, CXXScopeSpec *SS, + CorrectionCandidateCallback &CCC, + DeclContext *MemberContext, + bool EnteringContext, + const ObjCObjectPointerType *OPT) { + if (Diags.hasFatalErrorOccurred() || !getLangOpts().SpellChecking) + return TypoCorrection(); + + // In Microsoft mode, don't perform typo correction in a template member + // function dependent context because it interferes with the "lookup into + // dependent bases of class templates" feature. + if (getLangOpts().MicrosoftMode && CurContext->isDependentContext() && + isa(CurContext)) + return TypoCorrection(); + + // We only attempt to correct typos for identifiers. + IdentifierInfo *Typo = TypoName.getName().getAsIdentifierInfo(); + if (!Typo) + return TypoCorrection(); + + // If the scope specifier itself was invalid, don't try to correct + // typos. + if (SS && SS->isInvalid()) + return TypoCorrection(); + + // Never try to correct typos during template deduction or + // instantiation. + if (!ActiveTemplateInstantiations.empty()) + return TypoCorrection(); + + NamespaceSpecifierSet Namespaces(Context, CurContext, SS); + + TypoCorrectionConsumer Consumer(*this, Typo); + + // If a callback object considers an empty typo correction candidate to be + // viable, assume it does not do any actual validation of the candidates. + TypoCorrection EmptyCorrection; + bool ValidatingCallback = !isCandidateViable(CCC, EmptyCorrection); + + // Perform name lookup to find visible, similarly-named entities. + bool IsUnqualifiedLookup = false; + DeclContext *QualifiedDC = MemberContext; + if (MemberContext) { + LookupVisibleDecls(MemberContext, LookupKind, Consumer); + + // Look in qualified interfaces. + if (OPT) { + for (ObjCObjectPointerType::qual_iterator + I = OPT->qual_begin(), E = OPT->qual_end(); + I != E; ++I) + LookupVisibleDecls(*I, LookupKind, Consumer); + } + } else if (SS && SS->isSet()) { + QualifiedDC = computeDeclContext(*SS, EnteringContext); + if (!QualifiedDC) + return TypoCorrection(); + + // Provide a stop gap for files that are just seriously broken. Trying + // to correct all typos can turn into a HUGE performance penalty, causing + // some files to take minutes to get rejected by the parser. + if (TyposCorrected + UnqualifiedTyposCorrected.size() >= 20) + return TypoCorrection(); + ++TyposCorrected; + + LookupVisibleDecls(QualifiedDC, LookupKind, Consumer); + } else { + IsUnqualifiedLookup = true; + UnqualifiedTyposCorrectedMap::iterator Cached + = UnqualifiedTyposCorrected.find(Typo); + if (Cached != UnqualifiedTyposCorrected.end()) { + // Add the cached value, unless it's a keyword or fails validation. In the + // keyword case, we'll end up adding the keyword below. + if (Cached->second) { + if (!Cached->second.isKeyword() && + isCandidateViable(CCC, Cached->second)) + Consumer.addCorrection(Cached->second); + } else { + // Only honor no-correction cache hits when a callback that will validate + // correction candidates is not being used. + if (!ValidatingCallback) + return TypoCorrection(); + } + } + if (Cached == UnqualifiedTyposCorrected.end()) { + // Provide a stop gap for files that are just seriously broken. Trying + // to correct all typos can turn into a HUGE performance penalty, causing + // some files to take minutes to get rejected by the parser. + if (TyposCorrected + UnqualifiedTyposCorrected.size() >= 20) + return TypoCorrection(); + } + } + + // Determine whether we are going to search in the various namespaces for + // corrections. + bool SearchNamespaces + = getLangOpts().CPlusPlus && + (IsUnqualifiedLookup || (QualifiedDC && QualifiedDC->isNamespace())); + + if (IsUnqualifiedLookup || SearchNamespaces) { + // For unqualified lookup, look through all of the names that we have + // seen in this translation unit. + // FIXME: Re-add the ability to skip very unlikely potential corrections. + for (IdentifierTable::iterator I = Context.Idents.begin(), + IEnd = Context.Idents.end(); + I != IEnd; ++I) + Consumer.FoundName(I->getKey()); + + // Walk through identifiers in external identifier sources. + // FIXME: Re-add the ability to skip very unlikely potential corrections. + if (IdentifierInfoLookup *External + = Context.Idents.getExternalIdentifierLookup()) { + OwningPtr Iter(External->getIdentifiers()); + do { + StringRef Name = Iter->Next(); + if (Name.empty()) + break; + + Consumer.FoundName(Name); + } while (true); + } + } + + AddKeywordsToConsumer(*this, Consumer, S, CCC); + + // If we haven't found anything, we're done. + if (Consumer.empty()) { + // If this was an unqualified lookup, note that no correction was found. + if (IsUnqualifiedLookup) + (void)UnqualifiedTyposCorrected[Typo]; + + return TypoCorrection(); + } + + // Make sure that the user typed at least 3 characters for each correction + // made. Otherwise, we don't even both looking at the results. + unsigned ED = Consumer.getBestEditDistance(true); + if (ED > 0 && Typo->getName().size() / ED < 3) { + // If this was an unqualified lookup, note that no correction was found. + if (IsUnqualifiedLookup) + (void)UnqualifiedTyposCorrected[Typo]; + + return TypoCorrection(); + } + + // Build the NestedNameSpecifiers for the KnownNamespaces, if we're going + // to search those namespaces. + if (SearchNamespaces) { + // Load any externally-known namespaces. + if (ExternalSource && !LoadedExternalKnownNamespaces) { + SmallVector ExternalKnownNamespaces; + LoadedExternalKnownNamespaces = true; + ExternalSource->ReadKnownNamespaces(ExternalKnownNamespaces); + for (unsigned I = 0, N = ExternalKnownNamespaces.size(); I != N; ++I) + KnownNamespaces[ExternalKnownNamespaces[I]] = true; + } + + for (llvm::DenseMap::iterator + KNI = KnownNamespaces.begin(), + KNIEnd = KnownNamespaces.end(); + KNI != KNIEnd; ++KNI) + Namespaces.AddNamespace(KNI->first); + } + + // Weed out any names that could not be found by name lookup or, if a + // CorrectionCandidateCallback object was provided, failed validation. + llvm::SmallVector QualifiedResults; + LookupResult TmpRes(*this, TypoName, LookupKind); + TmpRes.suppressDiagnostics(); + while (!Consumer.empty()) { + TypoCorrectionConsumer::distance_iterator DI = Consumer.begin(); + unsigned ED = DI->first; + for (TypoCorrectionConsumer::result_iterator I = DI->second.begin(), + IEnd = DI->second.end(); + I != IEnd; /* Increment in loop. */) { + // If the item already has been looked up or is a keyword, keep it. + // If a validator callback object was given, drop the correction + // unless it passes validation. + if (I->second.isResolved()) { + TypoCorrectionConsumer::result_iterator Prev = I; + ++I; + if (!isCandidateViable(CCC, Prev->second)) + DI->second.erase(Prev); + continue; + } + + // Perform name lookup on this name. + IdentifierInfo *Name = I->second.getCorrectionAsIdentifierInfo(); + LookupPotentialTypoResult(*this, TmpRes, Name, S, SS, MemberContext, + EnteringContext, CCC.IsObjCIvarLookup); + + switch (TmpRes.getResultKind()) { + case LookupResult::NotFound: + case LookupResult::NotFoundInCurrentInstantiation: + case LookupResult::FoundUnresolvedValue: + QualifiedResults.push_back(I->second); + // We didn't find this name in our scope, or didn't like what we found; + // ignore it. + { + TypoCorrectionConsumer::result_iterator Next = I; + ++Next; + DI->second.erase(I); + I = Next; + } + break; + + case LookupResult::Ambiguous: + // We don't deal with ambiguities. + return TypoCorrection(); + + case LookupResult::FoundOverloaded: { + TypoCorrectionConsumer::result_iterator Prev = I; + // Store all of the Decls for overloaded symbols + for (LookupResult::iterator TRD = TmpRes.begin(), + TRDEnd = TmpRes.end(); + TRD != TRDEnd; ++TRD) + I->second.addCorrectionDecl(*TRD); + ++I; + if (!isCandidateViable(CCC, Prev->second)) + DI->second.erase(Prev); + break; + } + + case LookupResult::Found: { + TypoCorrectionConsumer::result_iterator Prev = I; + I->second.setCorrectionDecl(TmpRes.getAsSingle()); + ++I; + if (!isCandidateViable(CCC, Prev->second)) + DI->second.erase(Prev); + break; + } + + } + } + + if (DI->second.empty()) + Consumer.erase(DI); + else if (!getLangOpts().CPlusPlus || QualifiedResults.empty() || !ED) + // If there are results in the closest possible bucket, stop + break; + + // Only perform the qualified lookups for C++ + if (SearchNamespaces) { + TmpRes.suppressDiagnostics(); + for (llvm::SmallVector::iterator QRI = QualifiedResults.begin(), + QRIEnd = QualifiedResults.end(); + QRI != QRIEnd; ++QRI) { + for (NamespaceSpecifierSet::iterator NI = Namespaces.begin(), + NIEnd = Namespaces.end(); + NI != NIEnd; ++NI) { + DeclContext *Ctx = NI->DeclCtx; + + // FIXME: Stop searching once the namespaces are too far away to create + // acceptable corrections for this identifier (since the namespaces + // are sorted in ascending order by edit distance). + + TmpRes.clear(); + TmpRes.setLookupName(QRI->getCorrectionAsIdentifierInfo()); + if (!LookupQualifiedName(TmpRes, Ctx)) continue; + + // Any corrections added below will be validated in subsequent + // iterations of the main while() loop over the Consumer's contents. + switch (TmpRes.getResultKind()) { + case LookupResult::Found: { + TypoCorrection TC(*QRI); + TC.setCorrectionDecl(TmpRes.getAsSingle()); + TC.setCorrectionSpecifier(NI->NameSpecifier); + TC.setQualifierDistance(NI->EditDistance); + Consumer.addCorrection(TC); + break; + } + case LookupResult::FoundOverloaded: { + TypoCorrection TC(*QRI); + TC.setCorrectionSpecifier(NI->NameSpecifier); + TC.setQualifierDistance(NI->EditDistance); + for (LookupResult::iterator TRD = TmpRes.begin(), + TRDEnd = TmpRes.end(); + TRD != TRDEnd; ++TRD) + TC.addCorrectionDecl(*TRD); + Consumer.addCorrection(TC); + break; + } + case LookupResult::NotFound: + case LookupResult::NotFoundInCurrentInstantiation: + case LookupResult::Ambiguous: + case LookupResult::FoundUnresolvedValue: + break; + } + } + } + } + + QualifiedResults.clear(); + } + + // No corrections remain... + if (Consumer.empty()) return TypoCorrection(); + + TypoResultsMap &BestResults = Consumer.begin()->second; + ED = TypoCorrection::NormalizeEditDistance(Consumer.begin()->first); + + if (ED > 0 && Typo->getName().size() / ED < 3) { + // If this was an unqualified lookup and we believe the callback + // object wouldn't have filtered out possible corrections, note + // that no correction was found. + if (IsUnqualifiedLookup && !ValidatingCallback) + (void)UnqualifiedTyposCorrected[Typo]; + + return TypoCorrection(); + } + + // If only a single name remains, return that result. + if (BestResults.size() == 1) { + const llvm::StringMapEntry &Correction = *(BestResults.begin()); + const TypoCorrection &Result = Correction.second; + + // Don't correct to a keyword that's the same as the typo; the keyword + // wasn't actually in scope. + if (ED == 0 && Result.isKeyword()) return TypoCorrection(); + + // Record the correction for unqualified lookup. + if (IsUnqualifiedLookup) + UnqualifiedTyposCorrected[Typo] = Result; + + return Result; + } + else if (BestResults.size() > 1 + // Ugly hack equivalent to CTC == CTC_ObjCMessageReceiver; + // WantObjCSuper is only true for CTC_ObjCMessageReceiver and for + // some instances of CTC_Unknown, while WantRemainingKeywords is true + // for CTC_Unknown but not for CTC_ObjCMessageReceiver. + && CCC.WantObjCSuper && !CCC.WantRemainingKeywords + && BestResults["super"].isKeyword()) { + // Prefer 'super' when we're completing in a message-receiver + // context. + + // Don't correct to a keyword that's the same as the typo; the keyword + // wasn't actually in scope. + if (ED == 0) return TypoCorrection(); + + // Record the correction for unqualified lookup. + if (IsUnqualifiedLookup) + UnqualifiedTyposCorrected[Typo] = BestResults["super"]; + + return BestResults["super"]; + } + + // If this was an unqualified lookup and we believe the callback object did + // not filter out possible corrections, note that no correction was found. + if (IsUnqualifiedLookup && !ValidatingCallback) + (void)UnqualifiedTyposCorrected[Typo]; + + return TypoCorrection(); +} + +void TypoCorrection::addCorrectionDecl(NamedDecl *CDecl) { + if (!CDecl) return; + + if (isKeyword()) + CorrectionDecls.clear(); + + CorrectionDecls.push_back(CDecl); + + if (!CorrectionName) + CorrectionName = CDecl->getDeclName(); +} + +std::string TypoCorrection::getAsString(const LangOptions &LO) const { + if (CorrectionNameSpec) { + std::string tmpBuffer; + llvm::raw_string_ostream PrefixOStream(tmpBuffer); + CorrectionNameSpec->print(PrefixOStream, PrintingPolicy(LO)); + CorrectionName.printName(PrefixOStream); + return PrefixOStream.str(); + } + + return CorrectionName.getAsString(); +} diff --git a/clang/lib/Sema/SemaObjCProperty.cpp b/clang/lib/Sema/SemaObjCProperty.cpp new file mode 100644 index 0000000..5ece8f1 --- /dev/null +++ b/clang/lib/Sema/SemaObjCProperty.cpp @@ -0,0 +1,1953 @@ +//===--- SemaObjCProperty.cpp - Semantic Analysis for ObjC @property ------===// +// +// 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 Objective C @property and +// @synthesize declarations. +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/Initialization.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/ExprObjC.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/ASTMutationListener.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/SmallString.h" + +using namespace clang; + +//===----------------------------------------------------------------------===// +// Grammar actions. +//===----------------------------------------------------------------------===// + +/// getImpliedARCOwnership - Given a set of property attributes and a +/// type, infer an expected lifetime. The type's ownership qualification +/// is not considered. +/// +/// Returns OCL_None if the attributes as stated do not imply an ownership. +/// Never returns OCL_Autoreleasing. +static Qualifiers::ObjCLifetime getImpliedARCOwnership( + ObjCPropertyDecl::PropertyAttributeKind attrs, + QualType type) { + // retain, strong, copy, weak, and unsafe_unretained are only legal + // on properties of retainable pointer type. + if (attrs & (ObjCPropertyDecl::OBJC_PR_retain | + ObjCPropertyDecl::OBJC_PR_strong | + ObjCPropertyDecl::OBJC_PR_copy)) { + return type->getObjCARCImplicitLifetime(); + } else if (attrs & ObjCPropertyDecl::OBJC_PR_weak) { + return Qualifiers::OCL_Weak; + } else if (attrs & ObjCPropertyDecl::OBJC_PR_unsafe_unretained) { + return Qualifiers::OCL_ExplicitNone; + } + + // assign can appear on other types, so we have to check the + // property type. + if (attrs & ObjCPropertyDecl::OBJC_PR_assign && + type->isObjCRetainableType()) { + return Qualifiers::OCL_ExplicitNone; + } + + return Qualifiers::OCL_None; +} + +/// Check the internal consistency of a property declaration. +static void checkARCPropertyDecl(Sema &S, ObjCPropertyDecl *property) { + if (property->isInvalidDecl()) return; + + ObjCPropertyDecl::PropertyAttributeKind propertyKind + = property->getPropertyAttributes(); + Qualifiers::ObjCLifetime propertyLifetime + = property->getType().getObjCLifetime(); + + // Nothing to do if we don't have a lifetime. + if (propertyLifetime == Qualifiers::OCL_None) return; + + Qualifiers::ObjCLifetime expectedLifetime + = getImpliedARCOwnership(propertyKind, property->getType()); + if (!expectedLifetime) { + // We have a lifetime qualifier but no dominating property + // attribute. That's okay, but restore reasonable invariants by + // setting the property attribute according to the lifetime + // qualifier. + ObjCPropertyDecl::PropertyAttributeKind attr; + if (propertyLifetime == Qualifiers::OCL_Strong) { + attr = ObjCPropertyDecl::OBJC_PR_strong; + } else if (propertyLifetime == Qualifiers::OCL_Weak) { + attr = ObjCPropertyDecl::OBJC_PR_weak; + } else { + assert(propertyLifetime == Qualifiers::OCL_ExplicitNone); + attr = ObjCPropertyDecl::OBJC_PR_unsafe_unretained; + } + property->setPropertyAttributes(attr); + return; + } + + if (propertyLifetime == expectedLifetime) return; + + property->setInvalidDecl(); + S.Diag(property->getLocation(), + diag::err_arc_inconsistent_property_ownership) + << property->getDeclName() + << expectedLifetime + << propertyLifetime; +} + +Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, + SourceLocation LParenLoc, + FieldDeclarator &FD, + ObjCDeclSpec &ODS, + Selector GetterSel, + Selector SetterSel, + bool *isOverridingProperty, + tok::ObjCKeywordKind MethodImplKind, + DeclContext *lexicalDC) { + unsigned Attributes = ODS.getPropertyAttributes(); + TypeSourceInfo *TSI = GetTypeForDeclarator(FD.D, S); + QualType T = TSI->getType(); + if ((getLangOpts().getGC() != LangOptions::NonGC && + T.isObjCGCWeak()) || + (getLangOpts().ObjCAutoRefCount && + T.getObjCLifetime() == Qualifiers::OCL_Weak)) + Attributes |= ObjCDeclSpec::DQ_PR_weak; + + bool isReadWrite = ((Attributes & ObjCDeclSpec::DQ_PR_readwrite) || + // default is readwrite! + !(Attributes & ObjCDeclSpec::DQ_PR_readonly)); + // property is defaulted to 'assign' if it is readwrite and is + // not retain or copy + bool isAssign = ((Attributes & ObjCDeclSpec::DQ_PR_assign) || + (isReadWrite && + !(Attributes & ObjCDeclSpec::DQ_PR_retain) && + !(Attributes & ObjCDeclSpec::DQ_PR_strong) && + !(Attributes & ObjCDeclSpec::DQ_PR_copy) && + !(Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) && + !(Attributes & ObjCDeclSpec::DQ_PR_weak))); + + // Proceed with constructing the ObjCPropertDecls. + ObjCContainerDecl *ClassDecl = cast(CurContext); + + if (ObjCCategoryDecl *CDecl = dyn_cast(ClassDecl)) + if (CDecl->IsClassExtension()) { + Decl *Res = HandlePropertyInClassExtension(S, AtLoc, LParenLoc, + FD, GetterSel, SetterSel, + isAssign, isReadWrite, + Attributes, + ODS.getPropertyAttributes(), + isOverridingProperty, TSI, + MethodImplKind); + if (Res) { + CheckObjCPropertyAttributes(Res, AtLoc, Attributes); + if (getLangOpts().ObjCAutoRefCount) + checkARCPropertyDecl(*this, cast(Res)); + } + return Res; + } + + ObjCPropertyDecl *Res = CreatePropertyDecl(S, ClassDecl, AtLoc, LParenLoc, FD, + GetterSel, SetterSel, + isAssign, isReadWrite, + Attributes, + ODS.getPropertyAttributes(), + TSI, MethodImplKind); + if (lexicalDC) + Res->setLexicalDeclContext(lexicalDC); + + // Validate the attributes on the @property. + CheckObjCPropertyAttributes(Res, AtLoc, Attributes); + + if (getLangOpts().ObjCAutoRefCount) + checkARCPropertyDecl(*this, Res); + + return Res; +} + +static ObjCPropertyDecl::PropertyAttributeKind +makePropertyAttributesAsWritten(unsigned Attributes) { + unsigned attributesAsWritten = 0; + if (Attributes & ObjCDeclSpec::DQ_PR_readonly) + attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_readonly; + if (Attributes & ObjCDeclSpec::DQ_PR_readwrite) + attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_readwrite; + if (Attributes & ObjCDeclSpec::DQ_PR_getter) + attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_getter; + if (Attributes & ObjCDeclSpec::DQ_PR_setter) + attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_setter; + if (Attributes & ObjCDeclSpec::DQ_PR_assign) + attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_assign; + if (Attributes & ObjCDeclSpec::DQ_PR_retain) + attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_retain; + if (Attributes & ObjCDeclSpec::DQ_PR_strong) + attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_strong; + if (Attributes & ObjCDeclSpec::DQ_PR_weak) + attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_weak; + if (Attributes & ObjCDeclSpec::DQ_PR_copy) + attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_copy; + if (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) + attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_unsafe_unretained; + if (Attributes & ObjCDeclSpec::DQ_PR_nonatomic) + attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_nonatomic; + if (Attributes & ObjCDeclSpec::DQ_PR_atomic) + attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_atomic; + + return (ObjCPropertyDecl::PropertyAttributeKind)attributesAsWritten; +} + +Decl * +Sema::HandlePropertyInClassExtension(Scope *S, + SourceLocation AtLoc, + SourceLocation LParenLoc, + FieldDeclarator &FD, + Selector GetterSel, Selector SetterSel, + const bool isAssign, + const bool isReadWrite, + const unsigned Attributes, + const unsigned AttributesAsWritten, + bool *isOverridingProperty, + TypeSourceInfo *T, + tok::ObjCKeywordKind MethodImplKind) { + ObjCCategoryDecl *CDecl = cast(CurContext); + // Diagnose if this property is already in continuation class. + DeclContext *DC = CurContext; + IdentifierInfo *PropertyId = FD.D.getIdentifier(); + ObjCInterfaceDecl *CCPrimary = CDecl->getClassInterface(); + + if (CCPrimary) + // Check for duplicate declaration of this property in current and + // other class extensions. + for (const ObjCCategoryDecl *ClsExtDecl = + CCPrimary->getFirstClassExtension(); + ClsExtDecl; ClsExtDecl = ClsExtDecl->getNextClassExtension()) { + if (ObjCPropertyDecl *prevDecl = + ObjCPropertyDecl::findPropertyDecl(ClsExtDecl, PropertyId)) { + Diag(AtLoc, diag::err_duplicate_property); + Diag(prevDecl->getLocation(), diag::note_property_declare); + return 0; + } + } + + // Create a new ObjCPropertyDecl with the DeclContext being + // the class extension. + // FIXME. We should really be using CreatePropertyDecl for this. + ObjCPropertyDecl *PDecl = + ObjCPropertyDecl::Create(Context, DC, FD.D.getIdentifierLoc(), + PropertyId, AtLoc, LParenLoc, T); + PDecl->setPropertyAttributesAsWritten( + makePropertyAttributesAsWritten(AttributesAsWritten)); + if (Attributes & ObjCDeclSpec::DQ_PR_readonly) + PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly); + if (Attributes & ObjCDeclSpec::DQ_PR_readwrite) + PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readwrite); + // Set setter/getter selector name. Needed later. + PDecl->setGetterName(GetterSel); + PDecl->setSetterName(SetterSel); + ProcessDeclAttributes(S, PDecl, FD.D); + DC->addDecl(PDecl); + + // We need to look in the @interface to see if the @property was + // already declared. + if (!CCPrimary) { + Diag(CDecl->getLocation(), diag::err_continuation_class); + *isOverridingProperty = true; + return 0; + } + + // Find the property in continuation class's primary class only. + ObjCPropertyDecl *PIDecl = + CCPrimary->FindPropertyVisibleInPrimaryClass(PropertyId); + + if (!PIDecl) { + // No matching property found in the primary class. Just fall thru + // and add property to continuation class's primary class. + ObjCPropertyDecl *PrimaryPDecl = + CreatePropertyDecl(S, CCPrimary, AtLoc, LParenLoc, + FD, GetterSel, SetterSel, isAssign, isReadWrite, + Attributes,AttributesAsWritten, T, MethodImplKind, DC); + + // A case of continuation class adding a new property in the class. This + // is not what it was meant for. However, gcc supports it and so should we. + // Make sure setter/getters are declared here. + ProcessPropertyDecl(PrimaryPDecl, CCPrimary, /* redeclaredProperty = */ 0, + /* lexicalDC = */ CDecl); + PDecl->setGetterMethodDecl(PrimaryPDecl->getGetterMethodDecl()); + PDecl->setSetterMethodDecl(PrimaryPDecl->getSetterMethodDecl()); + if (ASTMutationListener *L = Context.getASTMutationListener()) + L->AddedObjCPropertyInClassExtension(PrimaryPDecl, /*OrigProp=*/0, CDecl); + return PrimaryPDecl; + } + if (!Context.hasSameType(PIDecl->getType(), PDecl->getType())) { + bool IncompatibleObjC = false; + QualType ConvertedType; + // Relax the strict type matching for property type in continuation class. + // Allow property object type of continuation class to be different as long + // as it narrows the object type in its primary class property. Note that + // this conversion is safe only because the wider type is for a 'readonly' + // property in primary class and 'narrowed' type for a 'readwrite' property + // in continuation class. + if (!isa(PIDecl->getType()) || + !isa(PDecl->getType()) || + (!isObjCPointerConversion(PDecl->getType(), PIDecl->getType(), + ConvertedType, IncompatibleObjC)) + || IncompatibleObjC) { + Diag(AtLoc, + diag::err_type_mismatch_continuation_class) << PDecl->getType(); + Diag(PIDecl->getLocation(), diag::note_property_declare); + } + } + + // The property 'PIDecl's readonly attribute will be over-ridden + // with continuation class's readwrite property attribute! + unsigned PIkind = PIDecl->getPropertyAttributesAsWritten(); + if (isReadWrite && (PIkind & ObjCPropertyDecl::OBJC_PR_readonly)) { + unsigned retainCopyNonatomic = + (ObjCPropertyDecl::OBJC_PR_retain | + ObjCPropertyDecl::OBJC_PR_strong | + ObjCPropertyDecl::OBJC_PR_copy | + ObjCPropertyDecl::OBJC_PR_nonatomic); + if ((Attributes & retainCopyNonatomic) != + (PIkind & retainCopyNonatomic)) { + Diag(AtLoc, diag::warn_property_attr_mismatch); + Diag(PIDecl->getLocation(), diag::note_property_declare); + } + DeclContext *DC = cast(CCPrimary); + if (!ObjCPropertyDecl::findPropertyDecl(DC, + PIDecl->getDeclName().getAsIdentifierInfo())) { + // Protocol is not in the primary class. Must build one for it. + ObjCDeclSpec ProtocolPropertyODS; + // FIXME. Assuming that ObjCDeclSpec::ObjCPropertyAttributeKind + // and ObjCPropertyDecl::PropertyAttributeKind have identical + // values. Should consolidate both into one enum type. + ProtocolPropertyODS. + setPropertyAttributes((ObjCDeclSpec::ObjCPropertyAttributeKind) + PIkind); + // Must re-establish the context from class extension to primary + // class context. + ContextRAII SavedContext(*this, CCPrimary); + + Decl *ProtocolPtrTy = + ActOnProperty(S, AtLoc, LParenLoc, FD, ProtocolPropertyODS, + PIDecl->getGetterName(), + PIDecl->getSetterName(), + isOverridingProperty, + MethodImplKind, + /* lexicalDC = */ CDecl); + PIDecl = cast(ProtocolPtrTy); + } + PIDecl->makeitReadWriteAttribute(); + if (Attributes & ObjCDeclSpec::DQ_PR_retain) + PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain); + if (Attributes & ObjCDeclSpec::DQ_PR_strong) + PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong); + if (Attributes & ObjCDeclSpec::DQ_PR_copy) + PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy); + PIDecl->setSetterName(SetterSel); + } else { + // Tailor the diagnostics for the common case where a readwrite + // property is declared both in the @interface and the continuation. + // This is a common error where the user often intended the original + // declaration to be readonly. + unsigned diag = + (Attributes & ObjCDeclSpec::DQ_PR_readwrite) && + (PIkind & ObjCPropertyDecl::OBJC_PR_readwrite) + ? diag::err_use_continuation_class_redeclaration_readwrite + : diag::err_use_continuation_class; + Diag(AtLoc, diag) + << CCPrimary->getDeclName(); + Diag(PIDecl->getLocation(), diag::note_property_declare); + } + *isOverridingProperty = true; + // Make sure setter decl is synthesized, and added to primary class's list. + ProcessPropertyDecl(PIDecl, CCPrimary, PDecl, CDecl); + PDecl->setGetterMethodDecl(PIDecl->getGetterMethodDecl()); + PDecl->setSetterMethodDecl(PIDecl->getSetterMethodDecl()); + if (ASTMutationListener *L = Context.getASTMutationListener()) + L->AddedObjCPropertyInClassExtension(PDecl, PIDecl, CDecl); + return 0; +} + +ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S, + ObjCContainerDecl *CDecl, + SourceLocation AtLoc, + SourceLocation LParenLoc, + FieldDeclarator &FD, + Selector GetterSel, + Selector SetterSel, + const bool isAssign, + const bool isReadWrite, + const unsigned Attributes, + const unsigned AttributesAsWritten, + TypeSourceInfo *TInfo, + tok::ObjCKeywordKind MethodImplKind, + DeclContext *lexicalDC){ + IdentifierInfo *PropertyId = FD.D.getIdentifier(); + QualType T = TInfo->getType(); + + // Issue a warning if property is 'assign' as default and its object, which is + // gc'able conforms to NSCopying protocol + if (getLangOpts().getGC() != LangOptions::NonGC && + isAssign && !(Attributes & ObjCDeclSpec::DQ_PR_assign)) + if (const ObjCObjectPointerType *ObjPtrTy = + T->getAs()) { + ObjCInterfaceDecl *IDecl = ObjPtrTy->getObjectType()->getInterface(); + if (IDecl) + if (ObjCProtocolDecl* PNSCopying = + LookupProtocol(&Context.Idents.get("NSCopying"), AtLoc)) + if (IDecl->ClassImplementsProtocol(PNSCopying, true)) + Diag(AtLoc, diag::warn_implements_nscopying) << PropertyId; + } + if (T->isObjCObjectType()) + Diag(FD.D.getIdentifierLoc(), diag::err_statically_allocated_object); + + DeclContext *DC = cast(CDecl); + ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, DC, + FD.D.getIdentifierLoc(), + PropertyId, AtLoc, LParenLoc, TInfo); + + if (ObjCPropertyDecl *prevDecl = + ObjCPropertyDecl::findPropertyDecl(DC, PropertyId)) { + Diag(PDecl->getLocation(), diag::err_duplicate_property); + Diag(prevDecl->getLocation(), diag::note_property_declare); + PDecl->setInvalidDecl(); + } + else { + DC->addDecl(PDecl); + if (lexicalDC) + PDecl->setLexicalDeclContext(lexicalDC); + } + + if (T->isArrayType() || T->isFunctionType()) { + Diag(AtLoc, diag::err_property_type) << T; + PDecl->setInvalidDecl(); + } + + ProcessDeclAttributes(S, PDecl, FD.D); + + // Regardless of setter/getter attribute, we save the default getter/setter + // selector names in anticipation of declaration of setter/getter methods. + PDecl->setGetterName(GetterSel); + PDecl->setSetterName(SetterSel); + PDecl->setPropertyAttributesAsWritten( + makePropertyAttributesAsWritten(AttributesAsWritten)); + + if (Attributes & ObjCDeclSpec::DQ_PR_readonly) + PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly); + + if (Attributes & ObjCDeclSpec::DQ_PR_getter) + PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_getter); + + if (Attributes & ObjCDeclSpec::DQ_PR_setter) + PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_setter); + + if (isReadWrite) + PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readwrite); + + if (Attributes & ObjCDeclSpec::DQ_PR_retain) + PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain); + + if (Attributes & ObjCDeclSpec::DQ_PR_strong) + PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong); + + if (Attributes & ObjCDeclSpec::DQ_PR_weak) + PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_weak); + + if (Attributes & ObjCDeclSpec::DQ_PR_copy) + PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy); + + if (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) + PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_unsafe_unretained); + + if (isAssign) + PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_assign); + + // In the semantic attributes, one of nonatomic or atomic is always set. + if (Attributes & ObjCDeclSpec::DQ_PR_nonatomic) + PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nonatomic); + else + PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_atomic); + + // 'unsafe_unretained' is alias for 'assign'. + if (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) + PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_assign); + if (isAssign) + PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_unsafe_unretained); + + if (MethodImplKind == tok::objc_required) + PDecl->setPropertyImplementation(ObjCPropertyDecl::Required); + else if (MethodImplKind == tok::objc_optional) + PDecl->setPropertyImplementation(ObjCPropertyDecl::Optional); + + return PDecl; +} + +static void checkARCPropertyImpl(Sema &S, SourceLocation propertyImplLoc, + ObjCPropertyDecl *property, + ObjCIvarDecl *ivar) { + if (property->isInvalidDecl() || ivar->isInvalidDecl()) return; + + QualType ivarType = ivar->getType(); + Qualifiers::ObjCLifetime ivarLifetime = ivarType.getObjCLifetime(); + + // The lifetime implied by the property's attributes. + Qualifiers::ObjCLifetime propertyLifetime = + getImpliedARCOwnership(property->getPropertyAttributes(), + property->getType()); + + // We're fine if they match. + if (propertyLifetime == ivarLifetime) return; + + // These aren't valid lifetimes for object ivars; don't diagnose twice. + if (ivarLifetime == Qualifiers::OCL_None || + ivarLifetime == Qualifiers::OCL_Autoreleasing) + return; + + switch (propertyLifetime) { + case Qualifiers::OCL_Strong: + S.Diag(propertyImplLoc, diag::err_arc_strong_property_ownership) + << property->getDeclName() + << ivar->getDeclName() + << ivarLifetime; + break; + + case Qualifiers::OCL_Weak: + S.Diag(propertyImplLoc, diag::error_weak_property) + << property->getDeclName() + << ivar->getDeclName(); + break; + + case Qualifiers::OCL_ExplicitNone: + S.Diag(propertyImplLoc, diag::err_arc_assign_property_ownership) + << property->getDeclName() + << ivar->getDeclName() + << ((property->getPropertyAttributesAsWritten() + & ObjCPropertyDecl::OBJC_PR_assign) != 0); + break; + + case Qualifiers::OCL_Autoreleasing: + llvm_unreachable("properties cannot be autoreleasing"); + + case Qualifiers::OCL_None: + // Any other property should be ignored. + return; + } + + S.Diag(property->getLocation(), diag::note_property_declare); +} + +/// setImpliedPropertyAttributeForReadOnlyProperty - +/// This routine evaludates life-time attributes for a 'readonly' +/// property with no known lifetime of its own, using backing +/// 'ivar's attribute, if any. If no backing 'ivar', property's +/// life-time is assumed 'strong'. +static void setImpliedPropertyAttributeForReadOnlyProperty( + ObjCPropertyDecl *property, ObjCIvarDecl *ivar) { + Qualifiers::ObjCLifetime propertyLifetime = + getImpliedARCOwnership(property->getPropertyAttributes(), + property->getType()); + if (propertyLifetime != Qualifiers::OCL_None) + return; + + if (!ivar) { + // if no backing ivar, make property 'strong'. + property->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong); + return; + } + // property assumes owenership of backing ivar. + QualType ivarType = ivar->getType(); + Qualifiers::ObjCLifetime ivarLifetime = ivarType.getObjCLifetime(); + if (ivarLifetime == Qualifiers::OCL_Strong) + property->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong); + else if (ivarLifetime == Qualifiers::OCL_Weak) + property->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_weak); + return; +} + +/// ActOnPropertyImplDecl - This routine performs semantic checks and +/// builds the AST node for a property implementation declaration; declared +/// as @synthesize or @dynamic. +/// +Decl *Sema::ActOnPropertyImplDecl(Scope *S, + SourceLocation AtLoc, + SourceLocation PropertyLoc, + bool Synthesize, + IdentifierInfo *PropertyId, + IdentifierInfo *PropertyIvar, + SourceLocation PropertyIvarLoc) { + ObjCContainerDecl *ClassImpDecl = + dyn_cast(CurContext); + // Make sure we have a context for the property implementation declaration. + if (!ClassImpDecl) { + Diag(AtLoc, diag::error_missing_property_context); + return 0; + } + if (PropertyIvarLoc.isInvalid()) + PropertyIvarLoc = PropertyLoc; + ObjCPropertyDecl *property = 0; + ObjCInterfaceDecl* IDecl = 0; + // Find the class or category class where this property must have + // a declaration. + ObjCImplementationDecl *IC = 0; + ObjCCategoryImplDecl* CatImplClass = 0; + if ((IC = dyn_cast(ClassImpDecl))) { + IDecl = IC->getClassInterface(); + // We always synthesize an interface for an implementation + // without an interface decl. So, IDecl is always non-zero. + assert(IDecl && + "ActOnPropertyImplDecl - @implementation without @interface"); + + // Look for this property declaration in the @implementation's @interface + property = IDecl->FindPropertyDeclaration(PropertyId); + if (!property) { + Diag(PropertyLoc, diag::error_bad_property_decl) << IDecl->getDeclName(); + return 0; + } + unsigned PIkind = property->getPropertyAttributesAsWritten(); + if ((PIkind & (ObjCPropertyDecl::OBJC_PR_atomic | + ObjCPropertyDecl::OBJC_PR_nonatomic) ) == 0) { + if (AtLoc.isValid()) + Diag(AtLoc, diag::warn_implicit_atomic_property); + else + Diag(IC->getLocation(), diag::warn_auto_implicit_atomic_property); + Diag(property->getLocation(), diag::note_property_declare); + } + + 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 0; + } + } + } else if ((CatImplClass = dyn_cast(ClassImpDecl))) { + if (Synthesize) { + Diag(AtLoc, diag::error_synthesize_category_decl); + return 0; + } + IDecl = CatImplClass->getClassInterface(); + if (!IDecl) { + Diag(AtLoc, diag::error_missing_property_interface); + return 0; + } + ObjCCategoryDecl *Category = + IDecl->FindCategoryDeclaration(CatImplClass->getIdentifier()); + + // If category for this implementation not found, it is an error which + // has already been reported eralier. + if (!Category) + 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 0; + } + } else { + Diag(AtLoc, diag::error_bad_property_context); + return 0; + } + ObjCIvarDecl *Ivar = 0; + // Check that we have a valid, previously declared ivar for @synthesize + if (Synthesize) { + // @synthesize + if (!PropertyIvar) + PropertyIvar = PropertyId; + // Check that this is a previously declared 'ivar' in 'IDecl' interface + ObjCInterfaceDecl *ClassDeclared; + Ivar = IDecl->lookupInstanceVariable(PropertyIvar, ClassDeclared); + QualType PropType = property->getType(); + QualType PropertyIvarType = PropType.getNonReferenceType(); + + if (getLangOpts().ObjCAutoRefCount && + (property->getPropertyAttributesAsWritten() & + ObjCPropertyDecl::OBJC_PR_readonly) && + PropertyIvarType->isObjCRetainableType()) { + setImpliedPropertyAttributeForReadOnlyProperty(property, Ivar); + } + + ObjCPropertyDecl::PropertyAttributeKind kind + = property->getPropertyAttributes(); + + // Add GC __weak to the ivar type if the property is weak. + if ((kind & ObjCPropertyDecl::OBJC_PR_weak) && + getLangOpts().getGC() != LangOptions::NonGC) { + assert(!getLangOpts().ObjCAutoRefCount); + if (PropertyIvarType.isObjCGCStrong()) { + Diag(PropertyLoc, diag::err_gc_weak_property_strong_type); + Diag(property->getLocation(), diag::note_property_declare); + } else { + PropertyIvarType = + Context.getObjCGCQualType(PropertyIvarType, Qualifiers::Weak); + } + } + + if (!Ivar) { + // In ARC, give the ivar a lifetime qualifier based on the + // property attributes. + if (getLangOpts().ObjCAutoRefCount && + !PropertyIvarType.getObjCLifetime() && + PropertyIvarType->isObjCRetainableType()) { + + // It's an error if we have to do this and the user didn't + // explicitly write an ownership attribute on the property. + if (!property->hasWrittenStorageAttribute() && + !(kind & ObjCPropertyDecl::OBJC_PR_strong)) { + Diag(PropertyLoc, + diag::err_arc_objc_property_default_assign_on_object); + Diag(property->getLocation(), diag::note_property_declare); + } else { + Qualifiers::ObjCLifetime lifetime = + getImpliedARCOwnership(kind, PropertyIvarType); + assert(lifetime && "no lifetime for property?"); + if (lifetime == Qualifiers::OCL_Weak) { + bool err = false; + if (const ObjCObjectPointerType *ObjT = + PropertyIvarType->getAs()) + if (ObjT->getInterfaceDecl()->isArcWeakrefUnavailable()) { + Diag(PropertyLoc, diag::err_arc_weak_unavailable_property); + Diag(property->getLocation(), diag::note_property_declare); + err = true; + } + if (!err && !getLangOpts().ObjCRuntimeHasWeak) { + Diag(PropertyLoc, diag::err_arc_weak_no_runtime); + Diag(property->getLocation(), diag::note_property_declare); + } + } + + Qualifiers qs; + qs.addObjCLifetime(lifetime); + PropertyIvarType = Context.getQualifiedType(PropertyIvarType, qs); + } + } + + if (kind & ObjCPropertyDecl::OBJC_PR_weak && + !getLangOpts().ObjCAutoRefCount && + getLangOpts().getGC() == LangOptions::NonGC) { + Diag(PropertyLoc, diag::error_synthesize_weak_non_arc_or_gc); + Diag(property->getLocation(), diag::note_property_declare); + } + + Ivar = ObjCIvarDecl::Create(Context, ClassImpDecl, + PropertyIvarLoc,PropertyIvarLoc, PropertyIvar, + PropertyIvarType, /*Dinfo=*/0, + ObjCIvarDecl::Private, + (Expr *)0, true); + ClassImpDecl->addDecl(Ivar); + IDecl->makeDeclVisibleInContext(Ivar); + property->setPropertyIvarDecl(Ivar); + + if (!getLangOpts().ObjCNonFragileABI) + Diag(PropertyLoc, diag::error_missing_property_ivar_decl) << PropertyId; + // Note! I deliberately want it to fall thru so, we have a + // a property implementation and to avoid future warnings. + } else if (getLangOpts().ObjCNonFragileABI && + !declaresSameEntity(ClassDeclared, IDecl)) { + Diag(PropertyLoc, diag::error_ivar_in_superclass_use) + << property->getDeclName() << Ivar->getDeclName() + << ClassDeclared->getDeclName(); + Diag(Ivar->getLocation(), diag::note_previous_access_declaration) + << Ivar << Ivar->getName(); + // Note! I deliberately want it to fall thru so more errors are caught. + } + QualType IvarType = Context.getCanonicalType(Ivar->getType()); + + // Check that type of property and its ivar are type compatible. + if (Context.getCanonicalType(PropertyIvarType) != IvarType) { + bool compat = false; + if (isa(PropertyIvarType) + && isa(IvarType)) + compat = + Context.canAssignObjCInterfaces( + PropertyIvarType->getAs(), + IvarType->getAs()); + else { + compat = (CheckAssignmentConstraints(PropertyIvarLoc, PropertyIvarType, + IvarType) + == Compatible); + } + if (!compat) { + Diag(PropertyLoc, diag::error_property_ivar_type) + << property->getDeclName() << PropType + << Ivar->getDeclName() << IvarType; + Diag(Ivar->getLocation(), diag::note_ivar_decl); + // Note! I deliberately want it to fall thru so, we have a + // a property implementation and to avoid future warnings. + } + + // FIXME! Rules for properties are somewhat different that those + // for assignments. Use a new routine to consolidate all cases; + // specifically for property redeclarations as well as for ivars. + QualType lhsType =Context.getCanonicalType(PropertyIvarType).getUnqualifiedType(); + QualType rhsType =Context.getCanonicalType(IvarType).getUnqualifiedType(); + if (lhsType != rhsType && + lhsType->isArithmeticType()) { + Diag(PropertyLoc, diag::error_property_ivar_type) + << property->getDeclName() << PropType + << Ivar->getDeclName() << IvarType; + Diag(Ivar->getLocation(), diag::note_ivar_decl); + // Fall thru - see previous comment + } + // __weak is explicit. So it works on Canonical type. + if ((PropType.isObjCGCWeak() && !IvarType.isObjCGCWeak() && + getLangOpts().getGC() != LangOptions::NonGC)) { + Diag(PropertyLoc, diag::error_weak_property) + << property->getDeclName() << Ivar->getDeclName(); + Diag(Ivar->getLocation(), diag::note_ivar_decl); + // Fall thru - see previous comment + } + // Fall thru - see previous comment + if ((property->getType()->isObjCObjectPointerType() || + PropType.isObjCGCStrong()) && IvarType.isObjCGCWeak() && + getLangOpts().getGC() != LangOptions::NonGC) { + Diag(PropertyLoc, diag::error_strong_property) + << property->getDeclName() << Ivar->getDeclName(); + // Fall thru - see previous comment + } + } + if (getLangOpts().ObjCAutoRefCount) + checkARCPropertyImpl(*this, PropertyLoc, property, Ivar); + } else if (PropertyIvar) + // @dynamic + Diag(PropertyLoc, diag::error_dynamic_property_ivar_decl); + + assert (property && "ActOnPropertyImplDecl - property declaration missing"); + ObjCPropertyImplDecl *PIDecl = + ObjCPropertyImplDecl::Create(Context, CurContext, AtLoc, PropertyLoc, + property, + (Synthesize ? + ObjCPropertyImplDecl::Synthesize + : ObjCPropertyImplDecl::Dynamic), + Ivar, PropertyIvarLoc); + if (ObjCMethodDecl *getterMethod = property->getGetterMethodDecl()) { + getterMethod->createImplicitParams(Context, IDecl); + if (getLangOpts().CPlusPlus && Synthesize && + Ivar->getType()->isRecordType()) { + // For Objective-C++, need to synthesize the AST for the IVAR object to be + // returned by the getter as it must conform to C++'s copy-return rules. + // FIXME. Eventually we want to do this for Objective-C as well. + ImplicitParamDecl *SelfDecl = getterMethod->getSelfDecl(); + DeclRefExpr *SelfExpr = + new (Context) DeclRefExpr(SelfDecl, false, SelfDecl->getType(), + VK_RValue, SourceLocation()); + Expr *IvarRefExpr = + new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), AtLoc, + SelfExpr, true, true); + ExprResult Res = + PerformCopyInitialization(InitializedEntity::InitializeResult( + SourceLocation(), + getterMethod->getResultType(), + /*NRVO=*/false), + SourceLocation(), + Owned(IvarRefExpr)); + if (!Res.isInvalid()) { + Expr *ResExpr = Res.takeAs(); + if (ResExpr) + ResExpr = MaybeCreateExprWithCleanups(ResExpr); + PIDecl->setGetterCXXConstructor(ResExpr); + } + } + if (property->hasAttr() && + !getterMethod->hasAttr()) { + Diag(getterMethod->getLocation(), + diag::warn_property_getter_owning_mismatch); + Diag(property->getLocation(), diag::note_property_declare); + } + } + if (ObjCMethodDecl *setterMethod = property->getSetterMethodDecl()) { + setterMethod->createImplicitParams(Context, IDecl); + if (getLangOpts().CPlusPlus && Synthesize + && Ivar->getType()->isRecordType()) { + // FIXME. Eventually we want to do this for Objective-C as well. + ImplicitParamDecl *SelfDecl = setterMethod->getSelfDecl(); + DeclRefExpr *SelfExpr = + new (Context) DeclRefExpr(SelfDecl, false, SelfDecl->getType(), + VK_RValue, SourceLocation()); + Expr *lhs = + new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), AtLoc, + SelfExpr, true, true); + ObjCMethodDecl::param_iterator P = setterMethod->param_begin(); + ParmVarDecl *Param = (*P); + QualType T = Param->getType().getNonReferenceType(); + Expr *rhs = new (Context) DeclRefExpr(Param, false, T, + VK_LValue, SourceLocation()); + ExprResult Res = BuildBinOp(S, lhs->getLocEnd(), + BO_Assign, lhs, rhs); + if (property->getPropertyAttributes() & + ObjCPropertyDecl::OBJC_PR_atomic) { + Expr *callExpr = Res.takeAs(); + if (const CXXOperatorCallExpr *CXXCE = + dyn_cast_or_null(callExpr)) + if (const FunctionDecl *FuncDecl = CXXCE->getDirectCallee()) + if (!FuncDecl->isTrivial()) + if (property->getType()->isReferenceType()) { + Diag(PropertyLoc, + diag::err_atomic_property_nontrivial_assign_op) + << property->getType(); + Diag(FuncDecl->getLocStart(), + diag::note_callee_decl) << FuncDecl; + } + } + PIDecl->setSetterCXXAssignment(Res.takeAs()); + } + } + + if (IC) { + if (Synthesize) + if (ObjCPropertyImplDecl *PPIDecl = + IC->FindPropertyImplIvarDecl(PropertyIvar)) { + Diag(PropertyLoc, diag::error_duplicate_ivar_use) + << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier() + << PropertyIvar; + Diag(PPIDecl->getLocation(), diag::note_previous_use); + } + + if (ObjCPropertyImplDecl *PPIDecl + = IC->FindPropertyImplDecl(PropertyId)) { + Diag(PropertyLoc, diag::error_property_implemented) << PropertyId; + Diag(PPIDecl->getLocation(), diag::note_previous_declaration); + return 0; + } + IC->addPropertyImplementation(PIDecl); + if (getLangOpts().ObjCDefaultSynthProperties && + getLangOpts().ObjCNonFragileABI2 && + !IDecl->isObjCRequiresPropertyDefs()) { + // 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=0; + 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() && + declaresSameEntity(IC->getClassInterface(), ClassDeclared)) { + Diag(Ivar->getLocation(), diag::err_undeclared_var_use) + << PropertyId; + Ivar->setInvalidDecl(); + } + } + } else { + if (Synthesize) + if (ObjCPropertyImplDecl *PPIDecl = + CatImplClass->FindPropertyImplIvarDecl(PropertyIvar)) { + Diag(PropertyLoc, diag::error_duplicate_ivar_use) + << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier() + << PropertyIvar; + Diag(PPIDecl->getLocation(), diag::note_previous_use); + } + + if (ObjCPropertyImplDecl *PPIDecl = + CatImplClass->FindPropertyImplDecl(PropertyId)) { + Diag(PropertyLoc, diag::error_property_implemented) << PropertyId; + Diag(PPIDecl->getLocation(), diag::note_previous_declaration); + return 0; + } + CatImplClass->addPropertyImplementation(PIDecl); + } + + return PIDecl; +} + +//===----------------------------------------------------------------------===// +// Helper methods. +//===----------------------------------------------------------------------===// + +/// DiagnosePropertyMismatch - Compares two properties for their +/// attributes and types and warns on a variety of inconsistencies. +/// +void +Sema::DiagnosePropertyMismatch(ObjCPropertyDecl *Property, + ObjCPropertyDecl *SuperProperty, + const IdentifierInfo *inheritedName) { + ObjCPropertyDecl::PropertyAttributeKind CAttr = + Property->getPropertyAttributes(); + ObjCPropertyDecl::PropertyAttributeKind SAttr = + SuperProperty->getPropertyAttributes(); + if ((CAttr & ObjCPropertyDecl::OBJC_PR_readonly) + && (SAttr & ObjCPropertyDecl::OBJC_PR_readwrite)) + Diag(Property->getLocation(), diag::warn_readonly_property) + << Property->getDeclName() << inheritedName; + if ((CAttr & ObjCPropertyDecl::OBJC_PR_copy) + != (SAttr & ObjCPropertyDecl::OBJC_PR_copy)) + Diag(Property->getLocation(), diag::warn_property_attribute) + << Property->getDeclName() << "copy" << inheritedName; + else if (!(SAttr & ObjCPropertyDecl::OBJC_PR_readonly)){ + unsigned CAttrRetain = + (CAttr & + (ObjCPropertyDecl::OBJC_PR_retain | ObjCPropertyDecl::OBJC_PR_strong)); + unsigned SAttrRetain = + (SAttr & + (ObjCPropertyDecl::OBJC_PR_retain | ObjCPropertyDecl::OBJC_PR_strong)); + bool CStrong = (CAttrRetain != 0); + bool SStrong = (SAttrRetain != 0); + if (CStrong != SStrong) + Diag(Property->getLocation(), diag::warn_property_attribute) + << Property->getDeclName() << "retain (or strong)" << inheritedName; + } + + if ((CAttr & ObjCPropertyDecl::OBJC_PR_nonatomic) + != (SAttr & ObjCPropertyDecl::OBJC_PR_nonatomic)) + Diag(Property->getLocation(), diag::warn_property_attribute) + << Property->getDeclName() << "atomic" << inheritedName; + if (Property->getSetterName() != SuperProperty->getSetterName()) + Diag(Property->getLocation(), diag::warn_property_attribute) + << Property->getDeclName() << "setter" << inheritedName; + if (Property->getGetterName() != SuperProperty->getGetterName()) + Diag(Property->getLocation(), diag::warn_property_attribute) + << Property->getDeclName() << "getter" << inheritedName; + + QualType LHSType = + Context.getCanonicalType(SuperProperty->getType()); + QualType RHSType = + Context.getCanonicalType(Property->getType()); + + if (!Context.propertyTypesAreCompatible(LHSType, RHSType)) { + // Do cases not handled in above. + // FIXME. For future support of covariant property types, revisit this. + bool IncompatibleObjC = false; + QualType ConvertedType; + if (!isObjCPointerConversion(RHSType, LHSType, + ConvertedType, IncompatibleObjC) || + IncompatibleObjC) { + Diag(Property->getLocation(), diag::warn_property_types_are_incompatible) + << Property->getType() << SuperProperty->getType() << inheritedName; + Diag(SuperProperty->getLocation(), diag::note_property_declare); + } + } +} + +bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property, + ObjCMethodDecl *GetterMethod, + SourceLocation Loc) { + if (GetterMethod && + !Context.hasSameType(GetterMethod->getResultType().getNonReferenceType(), + property->getType().getNonReferenceType())) { + AssignConvertType result = Incompatible; + if (property->getType()->isObjCObjectPointerType()) + result = CheckAssignmentConstraints(Loc, GetterMethod->getResultType(), + property->getType()); + if (result != Compatible) { + Diag(Loc, diag::warn_accessor_property_type_mismatch) + << property->getDeclName() + << GetterMethod->getSelector(); + Diag(GetterMethod->getLocation(), diag::note_declared_at); + return true; + } + } + return false; +} + +/// ComparePropertiesInBaseAndSuper - This routine compares property +/// declarations in base and its super class, if any, and issues +/// diagnostics in a variety of inconsistent situations. +/// +void Sema::ComparePropertiesInBaseAndSuper(ObjCInterfaceDecl *IDecl) { + ObjCInterfaceDecl *SDecl = IDecl->getSuperClass(); + if (!SDecl) + return; + // FIXME: O(N^2) + for (ObjCInterfaceDecl::prop_iterator S = SDecl->prop_begin(), + E = SDecl->prop_end(); S != E; ++S) { + ObjCPropertyDecl *SuperPDecl = (*S); + // Does property in super class has declaration in current class? + for (ObjCInterfaceDecl::prop_iterator I = IDecl->prop_begin(), + E = IDecl->prop_end(); I != E; ++I) { + ObjCPropertyDecl *PDecl = (*I); + if (SuperPDecl->getIdentifier() == PDecl->getIdentifier()) + DiagnosePropertyMismatch(PDecl, SuperPDecl, + SDecl->getIdentifier()); + } + } +} + +/// MatchOneProtocolPropertiesInClass - This routine goes thru the list +/// of properties declared in a protocol and compares their attribute against +/// the same property declared in the class or category. +void +Sema::MatchOneProtocolPropertiesInClass(Decl *CDecl, + ObjCProtocolDecl *PDecl) { + ObjCInterfaceDecl *IDecl = dyn_cast_or_null(CDecl); + if (!IDecl) { + // Category + ObjCCategoryDecl *CatDecl = static_cast(CDecl); + assert (CatDecl && "MatchOneProtocolPropertiesInClass"); + if (!CatDecl->IsClassExtension()) + for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), + E = PDecl->prop_end(); P != E; ++P) { + ObjCPropertyDecl *Pr = (*P); + ObjCCategoryDecl::prop_iterator CP, CE; + // Is this property already in category's list of properties? + for (CP = CatDecl->prop_begin(), CE = CatDecl->prop_end(); CP!=CE; ++CP) + if ((*CP)->getIdentifier() == Pr->getIdentifier()) + break; + if (CP != CE) + // Property protocol already exist in class. Diagnose any mismatch. + DiagnosePropertyMismatch((*CP), Pr, PDecl->getIdentifier()); + } + return; + } + for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), + E = PDecl->prop_end(); P != E; ++P) { + ObjCPropertyDecl *Pr = (*P); + ObjCInterfaceDecl::prop_iterator CP, CE; + // Is this property already in class's list of properties? + for (CP = IDecl->prop_begin(), CE = IDecl->prop_end(); CP != CE; ++CP) + if ((*CP)->getIdentifier() == Pr->getIdentifier()) + break; + if (CP != CE) + // Property protocol already exist in class. Diagnose any mismatch. + DiagnosePropertyMismatch((*CP), Pr, PDecl->getIdentifier()); + } +} + +/// CompareProperties - This routine compares properties +/// 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, Decl *ClassOrProtocol) { + Decl *ClassDecl = ClassOrProtocol; + ObjCInterfaceDecl *IDecl = dyn_cast_or_null(CDecl); + + if (!IDecl) { + // Category + ObjCCategoryDecl *CatDecl = static_cast(CDecl); + assert (CatDecl && "CompareProperties"); + if (ObjCCategoryDecl *MDecl = dyn_cast(ClassDecl)) { + for (ObjCCategoryDecl::protocol_iterator P = MDecl->protocol_begin(), + E = MDecl->protocol_end(); P != E; ++P) + // Match properties of category with those of protocol (*P) + MatchOneProtocolPropertiesInClass(CatDecl, *P); + + // Go thru the list of protocols for this category and recursively match + // their properties with those in the category. + for (ObjCCategoryDecl::protocol_iterator P = CatDecl->protocol_begin(), + E = CatDecl->protocol_end(); P != E; ++P) + CompareProperties(CatDecl, *P); + } else { + ObjCProtocolDecl *MD = cast(ClassDecl); + for (ObjCProtocolDecl::protocol_iterator P = MD->protocol_begin(), + E = MD->protocol_end(); P != E; ++P) + MatchOneProtocolPropertiesInClass(CatDecl, *P); + } + return; + } + + if (ObjCInterfaceDecl *MDecl = dyn_cast(ClassDecl)) { + 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::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(), + E = MD->protocol_end(); P != E; ++P) + MatchOneProtocolPropertiesInClass(IDecl, *P); + } +} + +/// isPropertyReadonly - Return true if property is readonly, by searching +/// for the property in the class and in its categories and implementations +/// +bool Sema::isPropertyReadonly(ObjCPropertyDecl *PDecl, + ObjCInterfaceDecl *IDecl) { + // by far the most common case. + if (!PDecl->isReadOnly()) + return false; + // Even if property is ready only, if interface has a user defined setter, + // it is not considered read only. + if (IDecl->getInstanceMethod(PDecl->getSetterName())) + return false; + + // Main class has the property as 'readonly'. Must search + // through the category list to see if the property's + // attribute has been over-ridden to 'readwrite'. + for (ObjCCategoryDecl *Category = IDecl->getCategoryList(); + Category; Category = Category->getNextClassCategory()) { + // Even if property is ready only, if a category has a user defined setter, + // it is not considered read only. + if (Category->getInstanceMethod(PDecl->getSetterName())) + return false; + ObjCPropertyDecl *P = + Category->FindPropertyDeclaration(PDecl->getIdentifier()); + if (P && !P->isReadOnly()) + return false; + } + + // Also, check for definition of a setter method in the implementation if + // all else failed. + if (ObjCMethodDecl *OMD = dyn_cast(CurContext)) { + if (ObjCImplementationDecl *IMD = + dyn_cast(OMD->getDeclContext())) { + if (IMD->getInstanceMethod(PDecl->getSetterName())) + return false; + } else if (ObjCCategoryImplDecl *CIMD = + dyn_cast(OMD->getDeclContext())) { + if (CIMD->getInstanceMethod(PDecl->getSetterName())) + return false; + } + } + // Lastly, look through the implementation (if one is in scope). + if (ObjCImplementationDecl *ImpDecl = IDecl->getImplementation()) + if (ImpDecl->getInstanceMethod(PDecl->getSetterName())) + return false; + // If all fails, look at the super class. + if (ObjCInterfaceDecl *SIDecl = IDecl->getSuperClass()) + return isPropertyReadonly(PDecl, SIDecl); + return true; +} + +/// CollectImmediateProperties - This routine collects all properties in +/// the class and its conforming protocols; but not those it its super class. +void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl, + llvm::DenseMap& PropMap, + llvm::DenseMap& SuperPropMap) { + if (ObjCInterfaceDecl *IDecl = dyn_cast(CDecl)) { + for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(), + E = IDecl->prop_end(); P != E; ++P) { + ObjCPropertyDecl *Prop = (*P); + PropMap[Prop->getIdentifier()] = Prop; + } + // scan through class's protocols. + 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)) { + if (!CATDecl->IsClassExtension()) + for (ObjCContainerDecl::prop_iterator P = CATDecl->prop_begin(), + E = CATDecl->prop_end(); P != E; ++P) { + ObjCPropertyDecl *Prop = (*P); + PropMap[Prop->getIdentifier()] = Prop; + } + // scan through class's protocols. + for (ObjCCategoryDecl::protocol_iterator PI = CATDecl->protocol_begin(), + E = CATDecl->protocol_end(); PI != E; ++PI) + CollectImmediateProperties((*PI), PropMap, SuperPropMap); + } + else if (ObjCProtocolDecl *PDecl = dyn_cast(CDecl)) { + for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), + E = PDecl->prop_end(); P != E; ++P) { + ObjCPropertyDecl *Prop = (*P); + ObjCPropertyDecl *PropertyFromSuper = SuperPropMap[Prop->getIdentifier()]; + // Exclude property for protocols which conform to class's super-class, + // as super-class has to implement the property. + if (!PropertyFromSuper || + PropertyFromSuper->getIdentifier() != Prop->getIdentifier()) { + ObjCPropertyDecl *&PropEntry = PropMap[Prop->getIdentifier()]; + if (!PropEntry) + PropEntry = Prop; + } + } + // scan through protocol's protocols. + for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(), + E = PDecl->protocol_end(); PI != E; ++PI) + CollectImmediateProperties((*PI), PropMap, SuperPropMap); + } +} + +/// CollectClassPropertyImplementations - This routine collects list of +/// properties to be implemented in the class. This includes, class's +/// and its conforming protocols' properties. +static void CollectClassPropertyImplementations(ObjCContainerDecl *CDecl, + llvm::DenseMap& PropMap) { + if (ObjCInterfaceDecl *IDecl = dyn_cast(CDecl)) { + for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(), + E = IDecl->prop_end(); P != E; ++P) { + ObjCPropertyDecl *Prop = (*P); + PropMap[Prop->getIdentifier()] = Prop; + } + 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)) { + for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), + E = PDecl->prop_end(); P != E; ++P) { + ObjCPropertyDecl *Prop = (*P); + if (!PropMap.count(Prop->getIdentifier())) + PropMap[Prop->getIdentifier()] = Prop; + } + // scan through protocol's protocols. + for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(), + E = PDecl->protocol_end(); PI != E; ++PI) + CollectClassPropertyImplementations((*PI), PropMap); + } +} + +/// CollectSuperClassPropertyImplementations - This routine collects list of +/// properties to be implemented in super class(s) and also coming from their +/// conforming protocols. +static void CollectSuperClassPropertyImplementations(ObjCInterfaceDecl *CDecl, + llvm::DenseMap& PropMap) { + if (ObjCInterfaceDecl *SDecl = CDecl->getSuperClass()) { + while (SDecl) { + CollectClassPropertyImplementations(SDecl, PropMap); + SDecl = SDecl->getSuperClass(); + } + } +} + +/// LookupPropertyDecl - Looks up a property in the current class and all +/// its protocols. +ObjCPropertyDecl *Sema::LookupPropertyDecl(const ObjCContainerDecl *CDecl, + IdentifierInfo *II) { + if (const ObjCInterfaceDecl *IDecl = + dyn_cast(CDecl)) { + for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(), + E = IDecl->prop_end(); P != E; ++P) { + ObjCPropertyDecl *Prop = (*P); + if (Prop->getIdentifier() == II) + return Prop; + } + // scan through class's protocols. + 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; + } + } + else if (const ObjCProtocolDecl *PDecl = + dyn_cast(CDecl)) { + for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), + E = PDecl->prop_end(); P != E; ++P) { + ObjCPropertyDecl *Prop = (*P); + if (Prop->getIdentifier() == II) + return Prop; + } + // scan through protocol's protocols. + for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(), + E = PDecl->protocol_end(); PI != E; ++PI) { + ObjCPropertyDecl *Prop = LookupPropertyDecl((*PI), II); + if (Prop) + return Prop; + } + } + return 0; +} + +static IdentifierInfo * getDefaultSynthIvarName(ObjCPropertyDecl *Prop, + ASTContext &Ctx) { + SmallString<128> ivarName; + { + llvm::raw_svector_ostream os(ivarName); + os << '_' << Prop->getIdentifier()->getName(); + } + return &Ctx.Idents.get(ivarName.str()); +} + +/// DefaultSynthesizeProperties - This routine default synthesizes all +/// properties which must be synthesized in class's @implementation. +void Sema::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl* IMPDecl, + ObjCInterfaceDecl *IDecl) { + + llvm::DenseMap PropMap; + CollectClassPropertyImplementations(IDecl, PropMap); + if (PropMap.empty()) + return; + llvm::DenseMap SuperPropMap; + CollectSuperClassPropertyImplementations(IDecl, SuperPropMap); + + for (llvm::DenseMap::iterator + P = PropMap.begin(), E = PropMap.end(); P != E; ++P) { + ObjCPropertyDecl *Prop = P->second; + // If property to be implemented in the super class, ignore. + if (SuperPropMap[Prop->getIdentifier()]) + continue; + // Is there a matching propery synthesize/dynamic? + if (Prop->isInvalidDecl() || + Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional || + IMPDecl->FindPropertyImplIvarDecl(Prop->getIdentifier())) + continue; + // 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; + } + if (isa(Prop->getDeclContext())) { + // We won't auto-synthesize properties declared in protocols. + Diag(IMPDecl->getLocation(), + diag::warn_auto_synthesizing_protocol_property); + Diag(Prop->getLocation(), diag::note_property_declare); + continue; + } + + // We use invalid SourceLocations for the synthesized ivars since they + // aren't really synthesized at a particular location; they just exist. + // Saying that they are located at the @implementation isn't really going + // to help users. + ActOnPropertyImplDecl(S, SourceLocation(), SourceLocation(), + true, + /* property = */ Prop->getIdentifier(), + /* ivar = */ getDefaultSynthIvarName(Prop, Context), + SourceLocation()); + } +} + +void Sema::DefaultSynthesizeProperties(Scope *S, Decl *D) { + if (!LangOpts.ObjCDefaultSynthProperties || !LangOpts.ObjCNonFragileABI2) + return; + ObjCImplementationDecl *IC=dyn_cast_or_null(D); + if (!IC) + return; + if (ObjCInterfaceDecl* IDecl = IC->getClassInterface()) + if (!IDecl->isObjCRequiresPropertyDefs()) + DefaultSynthesizeProperties(S, IC, IDecl); +} + +void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl, + ObjCContainerDecl *CDecl, + const llvm::DenseSet& InsMap) { + llvm::DenseMap SuperPropMap; + if (ObjCInterfaceDecl *IDecl = dyn_cast(CDecl)) + CollectSuperClassPropertyImplementations(IDecl, SuperPropMap); + + llvm::DenseMap PropMap; + CollectImmediateProperties(CDecl, PropMap, SuperPropMap); + if (PropMap.empty()) + return; + + llvm::DenseSet PropImplMap; + for (ObjCImplDecl::propimpl_iterator + I = IMPDecl->propimpl_begin(), + EI = IMPDecl->propimpl_end(); I != EI; ++I) + PropImplMap.insert((*I)->getPropertyDecl()); + + for (llvm::DenseMap::iterator + P = PropMap.begin(), E = PropMap.end(); P != E; ++P) { + ObjCPropertyDecl *Prop = P->second; + // Is there a matching propery synthesize/dynamic? + if (Prop->isInvalidDecl() || + Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional || + PropImplMap.count(Prop) || Prop->hasAttr()) + continue; + if (!InsMap.count(Prop->getGetterName())) { + Diag(IMPDecl->getLocation(), + isa(CDecl) ? + diag::warn_setter_getter_impl_required_in_category : + diag::warn_setter_getter_impl_required) + << Prop->getDeclName() << Prop->getGetterName(); + Diag(Prop->getLocation(), + diag::note_property_declare); + if (LangOpts.ObjCDefaultSynthProperties && LangOpts.ObjCNonFragileABI2) + if (ObjCInterfaceDecl *ID = dyn_cast(CDecl)) + if (const ObjCInterfaceDecl *RID = ID->isObjCRequiresPropertyDefs()) + Diag(RID->getLocation(), diag::note_suppressed_class_declare); + + } + + if (!Prop->isReadOnly() && !InsMap.count(Prop->getSetterName())) { + Diag(IMPDecl->getLocation(), + isa(CDecl) ? + diag::warn_setter_getter_impl_required_in_category : + diag::warn_setter_getter_impl_required) + << Prop->getDeclName() << Prop->getSetterName(); + Diag(Prop->getLocation(), + diag::note_property_declare); + if (LangOpts.ObjCDefaultSynthProperties && LangOpts.ObjCNonFragileABI2) + if (ObjCInterfaceDecl *ID = dyn_cast(CDecl)) + if (const ObjCInterfaceDecl *RID = ID->isObjCRequiresPropertyDefs()) + Diag(RID->getLocation(), diag::note_suppressed_class_declare); + } + } +} + +void +Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl, + ObjCContainerDecl* IDecl) { + // Rules apply in non-GC mode only + if (getLangOpts().getGC() != LangOptions::NonGC) + return; + for (ObjCContainerDecl::prop_iterator I = IDecl->prop_begin(), + E = IDecl->prop_end(); + I != E; ++I) { + ObjCPropertyDecl *Property = (*I); + ObjCMethodDecl *GetterMethod = 0; + ObjCMethodDecl *SetterMethod = 0; + bool LookedUpGetterSetter = false; + + unsigned Attributes = Property->getPropertyAttributes(); + unsigned AttributesAsWritten = Property->getPropertyAttributesAsWritten(); + + if (!(AttributesAsWritten & ObjCPropertyDecl::OBJC_PR_atomic) && + !(AttributesAsWritten & ObjCPropertyDecl::OBJC_PR_nonatomic)) { + GetterMethod = IMPDecl->getInstanceMethod(Property->getGetterName()); + SetterMethod = IMPDecl->getInstanceMethod(Property->getSetterName()); + LookedUpGetterSetter = true; + if (GetterMethod) { + Diag(GetterMethod->getLocation(), + diag::warn_default_atomic_custom_getter_setter) + << Property->getIdentifier() << 0; + Diag(Property->getLocation(), diag::note_property_declare); + } + if (SetterMethod) { + Diag(SetterMethod->getLocation(), + diag::warn_default_atomic_custom_getter_setter) + << Property->getIdentifier() << 1; + Diag(Property->getLocation(), diag::note_property_declare); + } + } + + // We only care about readwrite atomic property. + if ((Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) || + !(Attributes & ObjCPropertyDecl::OBJC_PR_readwrite)) + continue; + if (const ObjCPropertyImplDecl *PIDecl + = IMPDecl->FindPropertyImplDecl(Property->getIdentifier())) { + if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) + continue; + if (!LookedUpGetterSetter) { + GetterMethod = IMPDecl->getInstanceMethod(Property->getGetterName()); + SetterMethod = IMPDecl->getInstanceMethod(Property->getSetterName()); + LookedUpGetterSetter = true; + } + if ((GetterMethod && !SetterMethod) || (!GetterMethod && SetterMethod)) { + SourceLocation MethodLoc = + (GetterMethod ? GetterMethod->getLocation() + : SetterMethod->getLocation()); + Diag(MethodLoc, diag::warn_atomic_property_rule) + << Property->getIdentifier() << (GetterMethod != 0) + << (SetterMethod != 0); + // fixit stuff. + if (!AttributesAsWritten) { + if (Property->getLParenLoc().isValid()) { + // @property () ... case. + SourceRange PropSourceRange(Property->getAtLoc(), + Property->getLParenLoc()); + Diag(Property->getLocation(), diag::note_atomic_property_fixup_suggest) << + FixItHint::CreateReplacement(PropSourceRange, "@property (nonatomic"); + } + else { + //@property id etc. + SourceLocation endLoc = + Property->getTypeSourceInfo()->getTypeLoc().getBeginLoc(); + endLoc = endLoc.getLocWithOffset(-1); + SourceRange PropSourceRange(Property->getAtLoc(), endLoc); + Diag(Property->getLocation(), diag::note_atomic_property_fixup_suggest) << + FixItHint::CreateReplacement(PropSourceRange, "@property (nonatomic) "); + } + } + else if (!(AttributesAsWritten & ObjCPropertyDecl::OBJC_PR_atomic)) { + // @property () ... case. + SourceLocation endLoc = Property->getLParenLoc(); + SourceRange PropSourceRange(Property->getAtLoc(), endLoc); + Diag(Property->getLocation(), diag::note_atomic_property_fixup_suggest) << + FixItHint::CreateReplacement(PropSourceRange, "@property (nonatomic, "); + } + else + Diag(MethodLoc, diag::note_atomic_property_fixup_suggest); + Diag(Property->getLocation(), diag::note_property_declare); + } + } + } +} + +void Sema::DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D) { + if (getLangOpts().getGC() == LangOptions::GCOnly) + return; + + for (ObjCImplementationDecl::propimpl_iterator + i = D->propimpl_begin(), e = D->propimpl_end(); i != e; ++i) { + ObjCPropertyImplDecl *PID = *i; + if (PID->getPropertyImplementation() != ObjCPropertyImplDecl::Synthesize) + continue; + + const ObjCPropertyDecl *PD = PID->getPropertyDecl(); + if (PD && !PD->hasAttr() && + !D->getInstanceMethod(PD->getGetterName())) { + ObjCMethodDecl *method = PD->getGetterMethodDecl(); + if (!method) + continue; + ObjCMethodFamily family = method->getMethodFamily(); + if (family == OMF_alloc || family == OMF_copy || + family == OMF_mutableCopy || family == OMF_new) { + if (getLangOpts().ObjCAutoRefCount) + Diag(PID->getLocation(), diag::err_ownin_getter_rule); + else + Diag(PID->getLocation(), diag::warn_owning_getter_rule); + Diag(PD->getLocation(), diag::note_property_declare); + } + } + } +} + +/// AddPropertyAttrs - Propagates attributes from a property to the +/// implicitly-declared getter or setter for that property. +static void AddPropertyAttrs(Sema &S, ObjCMethodDecl *PropertyMethod, + ObjCPropertyDecl *Property) { + // Should we just clone all attributes over? + for (Decl::attr_iterator A = Property->attr_begin(), + AEnd = Property->attr_end(); + A != AEnd; ++A) { + if (isa(*A) || + isa(*A) || + isa(*A)) + PropertyMethod->addAttr((*A)->clone(S.Context)); + } +} + +/// ProcessPropertyDecl - Make sure that any user-defined setter/getter methods +/// have the property type and issue diagnostics if they don't. +/// Also synthesize a getter/setter method if none exist (and update the +/// appropriate lookup tables. FIXME: Should reconsider if adding synthesized +/// methods is the "right" thing to do. +void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property, + ObjCContainerDecl *CD, + ObjCPropertyDecl *redeclaredProperty, + ObjCContainerDecl *lexicalDC) { + + ObjCMethodDecl *GetterMethod, *SetterMethod; + + GetterMethod = CD->getInstanceMethod(property->getGetterName()); + SetterMethod = CD->getInstanceMethod(property->getSetterName()); + DiagnosePropertyAccessorMismatch(property, GetterMethod, + property->getLocation()); + + if (SetterMethod) { + ObjCPropertyDecl::PropertyAttributeKind CAttr = + property->getPropertyAttributes(); + if ((!(CAttr & ObjCPropertyDecl::OBJC_PR_readonly)) && + Context.getCanonicalType(SetterMethod->getResultType()) != + Context.VoidTy) + Diag(SetterMethod->getLocation(), diag::err_setter_type_void); + if (SetterMethod->param_size() != 1 || + !Context.hasSameUnqualifiedType( + (*SetterMethod->param_begin())->getType().getNonReferenceType(), + property->getType().getNonReferenceType())) { + Diag(property->getLocation(), + diag::warn_accessor_property_type_mismatch) + << property->getDeclName() + << SetterMethod->getSelector(); + Diag(SetterMethod->getLocation(), diag::note_declared_at); + } + } + + // Synthesize getter/setter methods if none exist. + // Find the default getter and if one not found, add one. + // FIXME: The synthesized property we set here is misleading. We almost always + // synthesize these methods unless the user explicitly provided prototypes + // (which is odd, but allowed). Sema should be typechecking that the + // declarations jive in that situation (which it is not currently). + if (!GetterMethod) { + // No instance method of same name as property getter name was found. + // Declare a getter method and add it to the list of methods + // for this class. + SourceLocation Loc = redeclaredProperty ? + redeclaredProperty->getLocation() : + property->getLocation(); + + GetterMethod = ObjCMethodDecl::Create(Context, Loc, Loc, + property->getGetterName(), + property->getType(), 0, CD, /*isInstance=*/true, + /*isVariadic=*/false, /*isSynthesized=*/true, + /*isImplicitlyDeclared=*/true, /*isDefined=*/false, + (property->getPropertyImplementation() == + ObjCPropertyDecl::Optional) ? + ObjCMethodDecl::Optional : + ObjCMethodDecl::Required); + CD->addDecl(GetterMethod); + + AddPropertyAttrs(*this, GetterMethod, property); + + // FIXME: Eventually this shouldn't be needed, as the lexical context + // and the real context should be the same. + if (lexicalDC) + GetterMethod->setLexicalDeclContext(lexicalDC); + if (property->hasAttr()) + GetterMethod->addAttr( + ::new (Context) NSReturnsNotRetainedAttr(Loc, Context)); + } else + // A user declared getter will be synthesize when @synthesize of + // the property with the same name is seen in the @implementation + GetterMethod->setSynthesized(true); + property->setGetterMethodDecl(GetterMethod); + + // Skip setter if property is read-only. + if (!property->isReadOnly()) { + // Find the default setter and if one not found, add one. + if (!SetterMethod) { + // No instance method of same name as property setter name was found. + // Declare a setter method and add it to the list of methods + // for this class. + SourceLocation Loc = redeclaredProperty ? + redeclaredProperty->getLocation() : + property->getLocation(); + + SetterMethod = + ObjCMethodDecl::Create(Context, Loc, Loc, + property->getSetterName(), Context.VoidTy, 0, + CD, /*isInstance=*/true, /*isVariadic=*/false, + /*isSynthesized=*/true, + /*isImplicitlyDeclared=*/true, + /*isDefined=*/false, + (property->getPropertyImplementation() == + ObjCPropertyDecl::Optional) ? + ObjCMethodDecl::Optional : + ObjCMethodDecl::Required); + + // Invent the arguments for the setter. We don't bother making a + // nice name for the argument. + ParmVarDecl *Argument = ParmVarDecl::Create(Context, SetterMethod, + Loc, Loc, + property->getIdentifier(), + property->getType().getUnqualifiedType(), + /*TInfo=*/0, + SC_None, + SC_None, + 0); + SetterMethod->setMethodParams(Context, Argument, + ArrayRef()); + + AddPropertyAttrs(*this, SetterMethod, property); + + CD->addDecl(SetterMethod); + // FIXME: Eventually this shouldn't be needed, as the lexical context + // and the real context should be the same. + if (lexicalDC) + SetterMethod->setLexicalDeclContext(lexicalDC); + } else + // A user declared setter will be synthesize when @synthesize of + // the property with the same name is seen in the @implementation + SetterMethod->setSynthesized(true); + property->setSetterMethodDecl(SetterMethod); + } + // Add any synthesized methods to the global pool. This allows us to + // handle the following, which is supported by GCC (and part of the design). + // + // @interface Foo + // @property double bar; + // @end + // + // void thisIsUnfortunate() { + // id foo; + // double bar = [foo bar]; + // } + // + if (GetterMethod) + AddInstanceMethodToGlobalPool(GetterMethod); + if (SetterMethod) + AddInstanceMethodToGlobalPool(SetterMethod); +} + +void Sema::CheckObjCPropertyAttributes(Decl *PDecl, + SourceLocation Loc, + unsigned &Attributes) { + // FIXME: Improve the reported location. + if (!PDecl || PDecl->isInvalidDecl()) + return; + + ObjCPropertyDecl *PropertyDecl = cast(PDecl); + QualType PropertyTy = PropertyDecl->getType(); + + if (getLangOpts().ObjCAutoRefCount && + (Attributes & ObjCDeclSpec::DQ_PR_readonly) && + PropertyTy->isObjCRetainableType()) { + // 'readonly' property with no obvious lifetime. + // its life time will be determined by its backing ivar. + unsigned rel = (ObjCDeclSpec::DQ_PR_unsafe_unretained | + ObjCDeclSpec::DQ_PR_copy | + ObjCDeclSpec::DQ_PR_retain | + ObjCDeclSpec::DQ_PR_strong | + ObjCDeclSpec::DQ_PR_weak | + ObjCDeclSpec::DQ_PR_assign); + if ((Attributes & rel) == 0) + return; + } + + // readonly and readwrite/assign/retain/copy conflict. + if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) && + (Attributes & (ObjCDeclSpec::DQ_PR_readwrite | + ObjCDeclSpec::DQ_PR_assign | + ObjCDeclSpec::DQ_PR_unsafe_unretained | + ObjCDeclSpec::DQ_PR_copy | + ObjCDeclSpec::DQ_PR_retain | + ObjCDeclSpec::DQ_PR_strong))) { + const char * which = (Attributes & ObjCDeclSpec::DQ_PR_readwrite) ? + "readwrite" : + (Attributes & ObjCDeclSpec::DQ_PR_assign) ? + "assign" : + (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) ? + "unsafe_unretained" : + (Attributes & ObjCDeclSpec::DQ_PR_copy) ? + "copy" : "retain"; + + Diag(Loc, (Attributes & (ObjCDeclSpec::DQ_PR_readwrite)) ? + diag::err_objc_property_attr_mutually_exclusive : + diag::warn_objc_property_attr_mutually_exclusive) + << "readonly" << which; + } + + // Check for copy or retain on non-object types. + if ((Attributes & (ObjCDeclSpec::DQ_PR_weak | ObjCDeclSpec::DQ_PR_copy | + ObjCDeclSpec::DQ_PR_retain | ObjCDeclSpec::DQ_PR_strong)) && + !PropertyTy->isObjCRetainableType() && + !PropertyDecl->getAttr()) { + Diag(Loc, diag::err_objc_property_requires_object) + << (Attributes & ObjCDeclSpec::DQ_PR_weak ? "weak" : + Attributes & ObjCDeclSpec::DQ_PR_copy ? "copy" : "retain (or strong)"); + Attributes &= ~(ObjCDeclSpec::DQ_PR_weak | ObjCDeclSpec::DQ_PR_copy | + ObjCDeclSpec::DQ_PR_retain | ObjCDeclSpec::DQ_PR_strong); + PropertyDecl->setInvalidDecl(); + } + + // Check for more than one of { assign, copy, retain }. + if (Attributes & ObjCDeclSpec::DQ_PR_assign) { + if (Attributes & ObjCDeclSpec::DQ_PR_copy) { + Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) + << "assign" << "copy"; + Attributes &= ~ObjCDeclSpec::DQ_PR_copy; + } + if (Attributes & ObjCDeclSpec::DQ_PR_retain) { + Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) + << "assign" << "retain"; + Attributes &= ~ObjCDeclSpec::DQ_PR_retain; + } + if (Attributes & ObjCDeclSpec::DQ_PR_strong) { + Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) + << "assign" << "strong"; + Attributes &= ~ObjCDeclSpec::DQ_PR_strong; + } + if (getLangOpts().ObjCAutoRefCount && + (Attributes & ObjCDeclSpec::DQ_PR_weak)) { + Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) + << "assign" << "weak"; + Attributes &= ~ObjCDeclSpec::DQ_PR_weak; + } + } else if (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) { + if (Attributes & ObjCDeclSpec::DQ_PR_copy) { + Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) + << "unsafe_unretained" << "copy"; + Attributes &= ~ObjCDeclSpec::DQ_PR_copy; + } + if (Attributes & ObjCDeclSpec::DQ_PR_retain) { + Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) + << "unsafe_unretained" << "retain"; + Attributes &= ~ObjCDeclSpec::DQ_PR_retain; + } + if (Attributes & ObjCDeclSpec::DQ_PR_strong) { + Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) + << "unsafe_unretained" << "strong"; + Attributes &= ~ObjCDeclSpec::DQ_PR_strong; + } + if (getLangOpts().ObjCAutoRefCount && + (Attributes & ObjCDeclSpec::DQ_PR_weak)) { + Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) + << "unsafe_unretained" << "weak"; + Attributes &= ~ObjCDeclSpec::DQ_PR_weak; + } + } else if (Attributes & ObjCDeclSpec::DQ_PR_copy) { + if (Attributes & ObjCDeclSpec::DQ_PR_retain) { + Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) + << "copy" << "retain"; + Attributes &= ~ObjCDeclSpec::DQ_PR_retain; + } + if (Attributes & ObjCDeclSpec::DQ_PR_strong) { + Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) + << "copy" << "strong"; + Attributes &= ~ObjCDeclSpec::DQ_PR_strong; + } + if (Attributes & ObjCDeclSpec::DQ_PR_weak) { + Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) + << "copy" << "weak"; + Attributes &= ~ObjCDeclSpec::DQ_PR_weak; + } + } + else if ((Attributes & ObjCDeclSpec::DQ_PR_retain) && + (Attributes & ObjCDeclSpec::DQ_PR_weak)) { + Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) + << "retain" << "weak"; + Attributes &= ~ObjCDeclSpec::DQ_PR_retain; + } + else if ((Attributes & ObjCDeclSpec::DQ_PR_strong) && + (Attributes & ObjCDeclSpec::DQ_PR_weak)) { + Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) + << "strong" << "weak"; + Attributes &= ~ObjCDeclSpec::DQ_PR_weak; + } + + if ((Attributes & ObjCDeclSpec::DQ_PR_atomic) && + (Attributes & ObjCDeclSpec::DQ_PR_nonatomic)) { + Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) + << "atomic" << "nonatomic"; + Attributes &= ~ObjCDeclSpec::DQ_PR_atomic; + } + + // Warn if user supplied no assignment attribute, property is + // readwrite, and this is an object type. + if (!(Attributes & (ObjCDeclSpec::DQ_PR_assign | ObjCDeclSpec::DQ_PR_copy | + ObjCDeclSpec::DQ_PR_unsafe_unretained | + ObjCDeclSpec::DQ_PR_retain | ObjCDeclSpec::DQ_PR_strong | + ObjCDeclSpec::DQ_PR_weak)) && + PropertyTy->isObjCObjectPointerType()) { + if (getLangOpts().ObjCAutoRefCount) + // With arc, @property definitions should default to (strong) when + // not specified; including when property is 'readonly'. + PropertyDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong); + else if (!(Attributes & ObjCDeclSpec::DQ_PR_readonly)) { + bool isAnyClassTy = + (PropertyTy->isObjCClassType() || + PropertyTy->isObjCQualifiedClassType()); + // In non-gc, non-arc mode, 'Class' is treated as a 'void *' no need to + // issue any warning. + if (isAnyClassTy && getLangOpts().getGC() == LangOptions::NonGC) + ; + else { + // Skip this warning in gc-only mode. + if (getLangOpts().getGC() != LangOptions::GCOnly) + Diag(Loc, diag::warn_objc_property_no_assignment_attribute); + + // If non-gc code warn that this is likely inappropriate. + if (getLangOpts().getGC() == LangOptions::NonGC) + Diag(Loc, diag::warn_objc_property_default_assign_on_object); + } + } + + // FIXME: Implement warning dependent on NSCopying being + // implemented. See also: + // + // (please trim this list while you are at it). + } + + if (!(Attributes & ObjCDeclSpec::DQ_PR_copy) + &&!(Attributes & ObjCDeclSpec::DQ_PR_readonly) + && getLangOpts().getGC() == LangOptions::GCOnly + && PropertyTy->isBlockPointerType()) + Diag(Loc, diag::warn_objc_property_copy_missing_on_block); + else if (getLangOpts().ObjCAutoRefCount && + (Attributes & ObjCDeclSpec::DQ_PR_retain) && + !(Attributes & ObjCDeclSpec::DQ_PR_readonly) && + !(Attributes & ObjCDeclSpec::DQ_PR_strong) && + PropertyTy->isBlockPointerType()) + Diag(Loc, diag::warn_objc_property_retain_of_block); + + if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) && + (Attributes & ObjCDeclSpec::DQ_PR_setter)) + Diag(Loc, diag::warn_objc_readonly_property_has_setter); + +} diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp new file mode 100644 index 0000000..50230f0 --- /dev/null +++ b/clang/lib/Sema/SemaOverload.cpp @@ -0,0 +1,11229 @@ +//===--- SemaOverload.cpp - 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 provides Sema routines for C++ overloading. +// +//===----------------------------------------------------------------------===// + +#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/ExprObjC.h" +#include "clang/AST/TypeOrdering.h" +#include "clang/Basic/PartialDiagnostic.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/STLExtras.h" +#include + +namespace clang { +using namespace sema; + +/// A convenience routine for creating a decayed reference to a +/// function. +static ExprResult +CreateFunctionRefExpr(Sema &S, FunctionDecl *Fn, bool HadMultipleCandidates, + SourceLocation Loc = SourceLocation(), + const DeclarationNameLoc &LocInfo = DeclarationNameLoc()){ + DeclRefExpr *DRE = new (S.Context) DeclRefExpr(Fn, false, Fn->getType(), + VK_LValue, Loc, LocInfo); + if (HadMultipleCandidates) + DRE->setHadMultipleCandidates(true); + ExprResult E = S.Owned(DRE); + E = S.DefaultFunctionArrayConversion(E.take()); + if (E.isInvalid()) + return ExprError(); + return move(E); +} + +static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, + bool InOverloadResolution, + StandardConversionSequence &SCS, + bool CStyle, + bool AllowObjCWritebackConversion); + +static bool IsTransparentUnionStandardConversion(Sema &S, Expr* From, + QualType &ToType, + bool InOverloadResolution, + StandardConversionSequence &SCS, + bool CStyle); +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. +ImplicitConversionCategory +GetConversionCategory(ImplicitConversionKind Kind) { + static const ImplicitConversionCategory + Category[(int)ICK_Num_Conversion_Kinds] = { + ICC_Identity, + ICC_Lvalue_Transformation, + ICC_Lvalue_Transformation, + ICC_Lvalue_Transformation, + ICC_Identity, + ICC_Qualification_Adjustment, + ICC_Promotion, + ICC_Promotion, + ICC_Promotion, + ICC_Conversion, + ICC_Conversion, + ICC_Conversion, + ICC_Conversion, + ICC_Conversion, + ICC_Conversion, + ICC_Conversion, + ICC_Conversion, + ICC_Conversion, + ICC_Conversion, + ICC_Conversion, + ICC_Conversion, + ICC_Conversion + }; + return Category[(int)Kind]; +} + +/// GetConversionRank - Retrieve the implicit conversion rank +/// corresponding to the given implicit conversion kind. +ImplicitConversionRank GetConversionRank(ImplicitConversionKind Kind) { + static const ImplicitConversionRank + Rank[(int)ICK_Num_Conversion_Kinds] = { + ICR_Exact_Match, + ICR_Exact_Match, + ICR_Exact_Match, + ICR_Exact_Match, + ICR_Exact_Match, + ICR_Exact_Match, + ICR_Promotion, + ICR_Promotion, + ICR_Promotion, + ICR_Conversion, + ICR_Conversion, + ICR_Conversion, + ICR_Conversion, + ICR_Conversion, + ICR_Conversion, + ICR_Conversion, + ICR_Conversion, + ICR_Conversion, + ICR_Conversion, + ICR_Conversion, + ICR_Complex_Real_Conversion, + ICR_Conversion, + ICR_Conversion, + ICR_Writeback_Conversion + }; + return Rank[(int)Kind]; +} + +/// GetImplicitConversionName - Return the name of this kind of +/// implicit conversion. +const char* GetImplicitConversionName(ImplicitConversionKind Kind) { + static const char* const Name[(int)ICK_Num_Conversion_Kinds] = { + "No conversion", + "Lvalue-to-rvalue", + "Array-to-pointer", + "Function-to-pointer", + "Noreturn adjustment", + "Qualification", + "Integral promotion", + "Floating point promotion", + "Complex promotion", + "Integral conversion", + "Floating conversion", + "Complex conversion", + "Floating-integral conversion", + "Pointer conversion", + "Pointer-to-member conversion", + "Boolean conversion", + "Compatible-types conversion", + "Derived-to-base conversion", + "Vector conversion", + "Vector splat", + "Complex-real conversion", + "Block Pointer conversion", + "Transparent Union Conversion" + "Writeback conversion" + }; + return Name[Kind]; +} + +/// StandardConversionSequence - Set the standard conversion +/// sequence to the identity conversion. +void StandardConversionSequence::setAsIdentityConversion() { + First = ICK_Identity; + Second = ICK_Identity; + Third = ICK_Identity; + DeprecatedStringLiteralToCharPtr = false; + QualificationIncludesObjCLifetime = false; + ReferenceBinding = false; + DirectBinding = false; + IsLvalueReference = true; + BindsToFunctionLvalue = false; + BindsToRvalue = false; + BindsImplicitObjectArgumentWithoutRefQualifier = false; + ObjCLifetimeConversionBinding = false; + CopyConstructor = 0; +} + +/// getRank - Retrieve the rank of this standard conversion sequence +/// (C++ 13.3.3.1.1p3). The rank is the largest rank of each of the +/// implicit conversions. +ImplicitConversionRank StandardConversionSequence::getRank() const { + ImplicitConversionRank Rank = ICR_Exact_Match; + if (GetConversionRank(First) > Rank) + Rank = GetConversionRank(First); + if (GetConversionRank(Second) > Rank) + Rank = GetConversionRank(Second); + if (GetConversionRank(Third) > Rank) + Rank = GetConversionRank(Third); + return Rank; +} + +/// isPointerConversionToBool - Determines whether this conversion is +/// a conversion of a pointer or pointer-to-member to bool. This is +/// used as part of the ranking of standard conversion sequences +/// (C++ 13.3.3.2p4). +bool StandardConversionSequence::isPointerConversionToBool() const { + // Note that FromType has not necessarily been transformed by the + // array-to-pointer or function-to-pointer implicit conversions, so + // check for their presence as well as checking whether FromType is + // a pointer. + if (getToType(1)->isBooleanType() && + (getFromType()->isPointerType() || + getFromType()->isObjCObjectPointerType() || + getFromType()->isBlockPointerType() || + getFromType()->isNullPtrType() || + First == ICK_Array_To_Pointer || First == ICK_Function_To_Pointer)) + return true; + + return false; +} + +/// isPointerConversionToVoidPointer - Determines whether this +/// conversion is a conversion of a pointer to a void pointer. This is +/// used as part of the ranking of standard conversion sequences (C++ +/// 13.3.3.2p4). +bool +StandardConversionSequence:: +isPointerConversionToVoidPointer(ASTContext& Context) const { + QualType FromType = getFromType(); + QualType ToType = getToType(1); + + // Note that FromType has not necessarily been transformed by the + // array-to-pointer implicit conversion, so check for its presence + // and redo the conversion to get a pointer. + if (First == ICK_Array_To_Pointer) + FromType = Context.getArrayDecayedType(FromType); + + if (Second == ICK_Pointer_Conversion && FromType->isAnyPointerType()) + if (const PointerType* ToPtrType = ToType->getAs()) + return ToPtrType->getPointeeType()->isVoidType(); + + return false; +} + +/// Skip any implicit casts which could be either part of a narrowing conversion +/// or after one in an implicit conversion. +static const Expr *IgnoreNarrowingConversion(const Expr *Converted) { + while (const ImplicitCastExpr *ICE = dyn_cast(Converted)) { + switch (ICE->getCastKind()) { + case CK_NoOp: + case CK_IntegralCast: + case CK_IntegralToBoolean: + case CK_IntegralToFloating: + case CK_FloatingToIntegral: + case CK_FloatingToBoolean: + case CK_FloatingCast: + Converted = ICE->getSubExpr(); + continue; + + default: + return Converted; + } + } + + return Converted; +} + +/// Check if this standard conversion sequence represents a narrowing +/// conversion, according to C++11 [dcl.init.list]p7. +/// +/// \param Ctx The AST context. +/// \param Converted The result of applying this standard conversion sequence. +/// \param ConstantValue If this is an NK_Constant_Narrowing conversion, the +/// value of the expression prior to the narrowing conversion. +/// \param ConstantType If this is an NK_Constant_Narrowing conversion, the +/// type of the expression prior to the narrowing conversion. +NarrowingKind +StandardConversionSequence::getNarrowingKind(ASTContext &Ctx, + const Expr *Converted, + APValue &ConstantValue, + QualType &ConstantType) const { + assert(Ctx.getLangOpts().CPlusPlus && "narrowing check outside C++"); + + // C++11 [dcl.init.list]p7: + // A narrowing conversion is an implicit conversion ... + QualType FromType = getToType(0); + QualType ToType = getToType(1); + switch (Second) { + // -- from a floating-point type to an integer type, or + // + // -- from an integer type or unscoped enumeration type to a floating-point + // type, except where the source is a constant expression and the actual + // value after conversion will fit into the target type and will produce + // the original value when converted back to the original type, or + case ICK_Floating_Integral: + if (FromType->isRealFloatingType() && ToType->isIntegralType(Ctx)) { + return NK_Type_Narrowing; + } else if (FromType->isIntegralType(Ctx) && ToType->isRealFloatingType()) { + llvm::APSInt IntConstantValue; + const Expr *Initializer = IgnoreNarrowingConversion(Converted); + if (Initializer && + Initializer->isIntegerConstantExpr(IntConstantValue, Ctx)) { + // Convert the integer to the floating type. + llvm::APFloat Result(Ctx.getFloatTypeSemantics(ToType)); + Result.convertFromAPInt(IntConstantValue, IntConstantValue.isSigned(), + llvm::APFloat::rmNearestTiesToEven); + // And back. + llvm::APSInt ConvertedValue = IntConstantValue; + bool ignored; + Result.convertToInteger(ConvertedValue, + llvm::APFloat::rmTowardZero, &ignored); + // If the resulting value is different, this was a narrowing conversion. + if (IntConstantValue != ConvertedValue) { + ConstantValue = APValue(IntConstantValue); + ConstantType = Initializer->getType(); + return NK_Constant_Narrowing; + } + } else { + // Variables are always narrowings. + return NK_Variable_Narrowing; + } + } + return NK_Not_Narrowing; + + // -- from long double to double or float, or from double to float, except + // where the source is a constant expression and the actual value after + // conversion is within the range of values that can be represented (even + // if it cannot be represented exactly), or + case ICK_Floating_Conversion: + if (FromType->isRealFloatingType() && ToType->isRealFloatingType() && + Ctx.getFloatingTypeOrder(FromType, ToType) == 1) { + // FromType is larger than ToType. + const Expr *Initializer = IgnoreNarrowingConversion(Converted); + if (Initializer->isCXX11ConstantExpr(Ctx, &ConstantValue)) { + // Constant! + assert(ConstantValue.isFloat()); + llvm::APFloat FloatVal = ConstantValue.getFloat(); + // Convert the source value into the target type. + bool ignored; + llvm::APFloat::opStatus ConvertStatus = FloatVal.convert( + Ctx.getFloatTypeSemantics(ToType), + llvm::APFloat::rmNearestTiesToEven, &ignored); + // If there was no overflow, the source value is within the range of + // values that can be represented. + if (ConvertStatus & llvm::APFloat::opOverflow) { + ConstantType = Initializer->getType(); + return NK_Constant_Narrowing; + } + } else { + return NK_Variable_Narrowing; + } + } + return NK_Not_Narrowing; + + // -- from an integer type or unscoped enumeration type to an integer type + // that cannot represent all the values of the original type, except where + // the source is a constant expression and the actual value after + // conversion will fit into the target type and will produce the original + // value when converted back to the original type. + case ICK_Boolean_Conversion: // Bools are integers too. + if (!FromType->isIntegralOrUnscopedEnumerationType()) { + // Boolean conversions can be from pointers and pointers to members + // [conv.bool], and those aren't considered narrowing conversions. + return NK_Not_Narrowing; + } // Otherwise, fall through to the integral case. + case ICK_Integral_Conversion: { + assert(FromType->isIntegralOrUnscopedEnumerationType()); + assert(ToType->isIntegralOrUnscopedEnumerationType()); + const bool FromSigned = FromType->isSignedIntegerOrEnumerationType(); + const unsigned FromWidth = Ctx.getIntWidth(FromType); + const bool ToSigned = ToType->isSignedIntegerOrEnumerationType(); + const unsigned ToWidth = Ctx.getIntWidth(ToType); + + if (FromWidth > ToWidth || + (FromWidth == ToWidth && FromSigned != ToSigned)) { + // Not all values of FromType can be represented in ToType. + llvm::APSInt InitializerValue; + const Expr *Initializer = IgnoreNarrowingConversion(Converted); + if (Initializer->isIntegerConstantExpr(InitializerValue, Ctx)) { + ConstantValue = APValue(InitializerValue); + + // Add a bit to the InitializerValue so we don't have to worry about + // signed vs. unsigned comparisons. + InitializerValue = InitializerValue.extend( + InitializerValue.getBitWidth() + 1); + // Convert the initializer to and from the target width and signed-ness. + llvm::APSInt ConvertedValue = InitializerValue; + ConvertedValue = ConvertedValue.trunc(ToWidth); + ConvertedValue.setIsSigned(ToSigned); + ConvertedValue = ConvertedValue.extend(InitializerValue.getBitWidth()); + ConvertedValue.setIsSigned(InitializerValue.isSigned()); + // If the result is different, this was a narrowing conversion. + if (ConvertedValue != InitializerValue) { + ConstantType = Initializer->getType(); + return NK_Constant_Narrowing; + } + } else { + // Variables are always narrowings. + return NK_Variable_Narrowing; + } + } + return NK_Not_Narrowing; + } + + default: + // Other kinds of conversions are not narrowings. + return NK_Not_Narrowing; + } +} + +/// DebugPrint - Print this standard conversion sequence to standard +/// error. Useful for debugging overloading issues. +void StandardConversionSequence::DebugPrint() const { + raw_ostream &OS = llvm::errs(); + bool PrintedSomething = false; + if (First != ICK_Identity) { + OS << GetImplicitConversionName(First); + PrintedSomething = true; + } + + if (Second != ICK_Identity) { + if (PrintedSomething) { + OS << " -> "; + } + OS << GetImplicitConversionName(Second); + + if (CopyConstructor) { + OS << " (by copy constructor)"; + } else if (DirectBinding) { + OS << " (direct reference binding)"; + } else if (ReferenceBinding) { + OS << " (reference binding)"; + } + PrintedSomething = true; + } + + if (Third != ICK_Identity) { + if (PrintedSomething) { + OS << " -> "; + } + OS << GetImplicitConversionName(Third); + PrintedSomething = true; + } + + if (!PrintedSomething) { + OS << "No conversions required"; + } +} + +/// DebugPrint - Print this user-defined conversion sequence to standard +/// error. Useful for debugging overloading issues. +void UserDefinedConversionSequence::DebugPrint() const { + raw_ostream &OS = llvm::errs(); + if (Before.First || Before.Second || Before.Third) { + Before.DebugPrint(); + OS << " -> "; + } + if (ConversionFunction) + OS << '\'' << *ConversionFunction << '\''; + else + OS << "aggregate initialization"; + if (After.First || After.Second || After.Third) { + OS << " -> "; + After.DebugPrint(); + } +} + +/// DebugPrint - Print this implicit conversion sequence to standard +/// error. Useful for debugging overloading issues. +void ImplicitConversionSequence::DebugPrint() const { + raw_ostream &OS = llvm::errs(); + switch (ConversionKind) { + case StandardConversion: + OS << "Standard conversion: "; + Standard.DebugPrint(); + break; + case UserDefinedConversion: + OS << "User-defined conversion: "; + UserDefined.DebugPrint(); + break; + case EllipsisConversion: + OS << "Ellipsis conversion"; + break; + case AmbiguousConversion: + OS << "Ambiguous conversion"; + break; + case BadConversion: + OS << "Bad conversion"; + break; + } + + OS << "\n"; +} + +void AmbiguousConversionSequence::construct() { + new (&conversions()) ConversionSet(); +} + +void AmbiguousConversionSequence::destruct() { + conversions().~ConversionSet(); +} + +void +AmbiguousConversionSequence::copyFrom(const AmbiguousConversionSequence &O) { + FromTypePtr = O.FromTypePtr; + ToTypePtr = O.ToTypePtr; + new (&conversions()) ConversionSet(O.conversions()); +} + +namespace { + // Structure used by OverloadCandidate::DeductionFailureInfo to store + // template parameter and template argument information. + struct DFIParamWithArguments { + TemplateParameter Param; + TemplateArgument FirstArg; + TemplateArgument SecondArg; + }; +} + +/// \brief Convert from Sema's representation of template deduction information +/// to the form used in overload-candidate information. +OverloadCandidate::DeductionFailureInfo +static MakeDeductionFailureInfo(ASTContext &Context, + Sema::TemplateDeductionResult TDK, + TemplateDeductionInfo &Info) { + OverloadCandidate::DeductionFailureInfo Result; + Result.Result = static_cast(TDK); + Result.Data = 0; + switch (TDK) { + case Sema::TDK_Success: + case Sema::TDK_InstantiationDepth: + case Sema::TDK_TooManyArguments: + case Sema::TDK_TooFewArguments: + break; + + case Sema::TDK_Incomplete: + case Sema::TDK_InvalidExplicitArguments: + Result.Data = Info.Param.getOpaqueValue(); + break; + + case Sema::TDK_Inconsistent: + 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; + Saved->FirstArg = Info.FirstArg; + Saved->SecondArg = Info.SecondArg; + Result.Data = Saved; + break; + } + + case Sema::TDK_SubstitutionFailure: + Result.Data = Info.take(); + break; + + case Sema::TDK_NonDeducedMismatch: + case Sema::TDK_FailedOverloadResolution: + break; + } + + return Result; +} + +void OverloadCandidate::DeductionFailureInfo::Destroy() { + switch (static_cast(Result)) { + case Sema::TDK_Success: + case Sema::TDK_InstantiationDepth: + case Sema::TDK_Incomplete: + case Sema::TDK_TooManyArguments: + case Sema::TDK_TooFewArguments: + case Sema::TDK_InvalidExplicitArguments: + break; + + case Sema::TDK_Inconsistent: + case Sema::TDK_Underqualified: + // FIXME: Destroy the data? + Data = 0; + break; + + case Sema::TDK_SubstitutionFailure: + // FIXME: Destroy the template arugment list? + Data = 0; + break; + + // Unhandled + case Sema::TDK_NonDeducedMismatch: + case Sema::TDK_FailedOverloadResolution: + break; + } +} + +TemplateParameter +OverloadCandidate::DeductionFailureInfo::getTemplateParameter() { + switch (static_cast(Result)) { + case Sema::TDK_Success: + case Sema::TDK_InstantiationDepth: + case Sema::TDK_TooManyArguments: + case Sema::TDK_TooFewArguments: + case Sema::TDK_SubstitutionFailure: + return TemplateParameter(); + + case Sema::TDK_Incomplete: + case Sema::TDK_InvalidExplicitArguments: + return TemplateParameter::getFromOpaqueValue(Data); + + case Sema::TDK_Inconsistent: + case Sema::TDK_Underqualified: + return static_cast(Data)->Param; + + // Unhandled + case Sema::TDK_NonDeducedMismatch: + case Sema::TDK_FailedOverloadResolution: + break; + } + + return TemplateParameter(); +} + +TemplateArgumentList * +OverloadCandidate::DeductionFailureInfo::getTemplateArgumentList() { + switch (static_cast(Result)) { + case Sema::TDK_Success: + case Sema::TDK_InstantiationDepth: + case Sema::TDK_TooManyArguments: + case Sema::TDK_TooFewArguments: + case Sema::TDK_Incomplete: + case Sema::TDK_InvalidExplicitArguments: + case Sema::TDK_Inconsistent: + case Sema::TDK_Underqualified: + return 0; + + case Sema::TDK_SubstitutionFailure: + return static_cast(Data); + + // Unhandled + case Sema::TDK_NonDeducedMismatch: + case Sema::TDK_FailedOverloadResolution: + break; + } + + return 0; +} + +const TemplateArgument *OverloadCandidate::DeductionFailureInfo::getFirstArg() { + switch (static_cast(Result)) { + case Sema::TDK_Success: + case Sema::TDK_InstantiationDepth: + case Sema::TDK_Incomplete: + case Sema::TDK_TooManyArguments: + case Sema::TDK_TooFewArguments: + case Sema::TDK_InvalidExplicitArguments: + case Sema::TDK_SubstitutionFailure: + return 0; + + case Sema::TDK_Inconsistent: + case Sema::TDK_Underqualified: + return &static_cast(Data)->FirstArg; + + // Unhandled + case Sema::TDK_NonDeducedMismatch: + case Sema::TDK_FailedOverloadResolution: + break; + } + + return 0; +} + +const TemplateArgument * +OverloadCandidate::DeductionFailureInfo::getSecondArg() { + switch (static_cast(Result)) { + case Sema::TDK_Success: + case Sema::TDK_InstantiationDepth: + case Sema::TDK_Incomplete: + case Sema::TDK_TooManyArguments: + case Sema::TDK_TooFewArguments: + case Sema::TDK_InvalidExplicitArguments: + case Sema::TDK_SubstitutionFailure: + return 0; + + case Sema::TDK_Inconsistent: + case Sema::TDK_Underqualified: + return &static_cast(Data)->SecondArg; + + // Unhandled + case Sema::TDK_NonDeducedMismatch: + case Sema::TDK_FailedOverloadResolution: + break; + } + + return 0; +} + +void OverloadCandidateSet::clear() { + for (iterator i = begin(), e = end(); i != e; ++i) + for (unsigned ii = 0, ie = i->NumConversions; ii != ie; ++ii) + i->Conversions[ii].~ImplicitConversionSequence(); + NumInlineSequences = 0; + Candidates.clear(); + Functions.clear(); +} + +namespace { + class UnbridgedCastsSet { + struct Entry { + Expr **Addr; + Expr *Saved; + }; + SmallVector Entries; + + public: + void save(Sema &S, Expr *&E) { + assert(E->hasPlaceholderType(BuiltinType::ARCUnbridgedCast)); + Entry entry = { &E, E }; + Entries.push_back(entry); + E = S.stripARCUnbridgedCast(E); + } + + void restore() { + for (SmallVectorImpl::iterator + i = Entries.begin(), e = Entries.end(); i != e; ++i) + *i->Addr = i->Saved; + } + }; +} + +/// checkPlaceholderForOverload - Do any interesting placeholder-like +/// preprocessing on the given expression. +/// +/// \param unbridgedCasts a collection to which to add unbridged casts; +/// without this, they will be immediately diagnosed as errors +/// +/// Return true on unrecoverable error. +static bool checkPlaceholderForOverload(Sema &S, Expr *&E, + UnbridgedCastsSet *unbridgedCasts = 0) { + if (const BuiltinType *placeholder = E->getType()->getAsPlaceholderType()) { + // We can't handle overloaded expressions here because overload + // resolution might reasonably tweak them. + if (placeholder->getKind() == BuiltinType::Overload) return false; + + // If the context potentially accepts unbridged ARC casts, strip + // the unbridged cast and add it to the collection for later restoration. + if (placeholder->getKind() == BuiltinType::ARCUnbridgedCast && + unbridgedCasts) { + unbridgedCasts->save(S, E); + return false; + } + + // Go ahead and check everything else. + ExprResult result = S.CheckPlaceholderExpr(E); + if (result.isInvalid()) + return true; + + E = result.take(); + return false; + } + + // Nothing to do. + return false; +} + +/// checkArgPlaceholdersForOverload - Check a set of call operands for +/// placeholders. +static bool checkArgPlaceholdersForOverload(Sema &S, Expr **args, + unsigned numArgs, + UnbridgedCastsSet &unbridged) { + for (unsigned i = 0; i != numArgs; ++i) + if (checkPlaceholderForOverload(S, args[i], &unbridged)) + return true; + + return false; +} + +// IsOverload - Determine whether the given New declaration is an +// overload of the declarations in Old. This routine returns false if +// New and Old cannot be overloaded, e.g., if New has the same +// signature as some function in Old (C++ 1.3.10) or if the Old +// declarations aren't functions (or function templates) at all. When +// it does return false, MatchedDecl will point to the decl that New +// cannot be overloaded with. This decl may be a UsingShadowDecl on +// top of the underlying declaration. +// +// Example: Given the following input: +// +// void f(int, float); // #1 +// void f(int, int); // #2 +// int f(int, int); // #3 +// +// When we process #1, there is no previous declaration of "f", +// so IsOverload will not be used. +// +// When we process #2, Old contains only the FunctionDecl for #1. By +// comparing the parameter types, we see that #1 and #2 are overloaded +// (since they have different signatures), so this routine returns +// false; MatchedDecl is unchanged. +// +// When we process #3, Old is an overload set containing #1 and #2. We +// compare the signatures of #3 to #1 (they're overloaded, so we do +// nothing) and then #3 to #2. Since the signatures of #3 and #2 are +// identical (return types of functions are not part of the +// signature), IsOverload returns false and MatchedDecl will be set to +// point to the FunctionDecl for #2. +// +// 'NewIsUsingShadowDecl' indicates that 'New' is being introduced +// into a class by a using declaration. The rules for whether to hide +// shadow declarations ignore some properties which otherwise figure +// into a function template's signature. +Sema::OverloadKind +Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old, + NamedDecl *&Match, bool NewIsUsingDecl) { + for (LookupResult::iterator I = Old.begin(), E = Old.end(); + I != E; ++I) { + NamedDecl *OldD = *I; + + bool OldIsUsingDecl = false; + if (isa(OldD)) { + OldIsUsingDecl = true; + + // We can always introduce two using declarations into the same + // context, even if they have identical signatures. + if (NewIsUsingDecl) continue; + + OldD = cast(OldD)->getTargetDecl(); + } + + // If either declaration was introduced by a using declaration, + // we'll need to use slightly different rules for matching. + // Essentially, these rules are the normal rules, except that + // function templates hide function templates with different + // return types or template parameter lists. + bool UseMemberUsingDeclRules = + (OldIsUsingDecl || NewIsUsingDecl) && CurContext->isRecord(); + + if (FunctionTemplateDecl *OldT = dyn_cast(OldD)) { + if (!IsOverload(New, OldT->getTemplatedDecl(), UseMemberUsingDeclRules)) { + if (UseMemberUsingDeclRules && OldIsUsingDecl) { + HideUsingShadowDecl(S, cast(*I)); + continue; + } + + Match = *I; + return Ovl_Match; + } + } else if (FunctionDecl *OldF = dyn_cast(OldD)) { + if (!IsOverload(New, OldF, UseMemberUsingDeclRules)) { + if (UseMemberUsingDeclRules && OldIsUsingDecl) { + HideUsingShadowDecl(S, cast(*I)); + continue; + } + + Match = *I; + return Ovl_Match; + } + } else if (isa(OldD)) { + // We can overload with these, which can show up when doing + // redeclaration checks for UsingDecls. + assert(Old.getLookupKind() == LookupUsingDeclName); + } else if (isa(OldD)) { + // We can always overload with tags by hiding them. + } else if (isa(OldD)) { + // Optimistically assume that an unresolved using decl will + // overload; if it doesn't, we'll have to diagnose during + // template instantiation. + } else { + // (C++ 13p1): + // Only function declarations can be overloaded; object and type + // declarations cannot be overloaded. + Match = *I; + return Ovl_NonFunction; + } + } + + return Ovl_Overload; +} + +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(); + + // C++ [temp.fct]p2: + // A function template can be overloaded with other function templates + // and with normal (non-template) functions. + if ((OldTemplate == 0) != (NewTemplate == 0)) + return true; + + // Is the function New an overload of the function Old? + QualType OldQType = Context.getCanonicalType(Old->getType()); + QualType NewQType = Context.getCanonicalType(New->getType()); + + // Compare the signatures (C++ 1.3.10) of the two functions to + // determine whether they are overloads. If we find any mismatch + // in the signature, they are overloads. + + // If either of these functions is a K&R-style function (no + // prototype), then we consider them to have matching signatures. + if (isa(OldQType.getTypePtr()) || + isa(NewQType.getTypePtr())) + return false; + + const FunctionProtoType* OldType = cast(OldQType); + const FunctionProtoType* NewType = cast(NewQType); + + // The signature of a function includes the types of its + // parameters (C++ 1.3.10), which includes the presence or absence + // of the ellipsis; see C++ DR 357). + if (OldQType != NewQType && + (OldType->getNumArgs() != NewType->getNumArgs() || + OldType->isVariadic() != NewType->isVariadic() || + !FunctionArgTypesAreEqual(OldType, NewType))) + return true; + + // C++ [temp.over.link]p4: + // The signature of a function template consists of its function + // signature, its return type and its template parameter list. The names + // of the template parameters are significant only for establishing the + // relationship between the template parameters and the rest of the + // signature. + // + // We check the return type and template parameter lists for function + // templates first; the remaining checks follow. + // + // However, we don't consider either of these when deciding whether + // a member introduced by a shadow declaration is hidden. + if (!UseUsingDeclRules && NewTemplate && + (!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(), + OldTemplate->getTemplateParameters(), + false, TPL_TemplateMatch) || + OldType->getResultType() != NewType->getResultType())) + return true; + + // If the function is a class member, its signature includes the + // cv-qualifiers (if any) and ref-qualifier (if any) on the function itself. + // + // As part of this, also check whether one of the member functions + // is static, in which case they are not overloads (C++ + // 13.1p2). While not part of the definition of the signature, + // this check is important to determine whether these functions + // can be overloaded. + CXXMethodDecl* OldMethod = dyn_cast(Old); + CXXMethodDecl* NewMethod = dyn_cast(New); + if (OldMethod && NewMethod && + !OldMethod->isStatic() && !NewMethod->isStatic() && + (OldMethod->getTypeQualifiers() != NewMethod->getTypeQualifiers() || + OldMethod->getRefQualifier() != NewMethod->getRefQualifier())) { + if (!UseUsingDeclRules && + OldMethod->getRefQualifier() != NewMethod->getRefQualifier() && + (OldMethod->getRefQualifier() == RQ_None || + NewMethod->getRefQualifier() == RQ_None)) { + // C++0x [over.load]p2: + // - Member function declarations with the same name and the same + // parameter-type-list as well as member function template + // declarations with the same name, the same parameter-type-list, and + // the same template parameter lists cannot be overloaded if any of + // them, but not all, have a ref-qualifier (8.3.5). + Diag(NewMethod->getLocation(), diag::err_ref_qualifier_overload) + << NewMethod->getRefQualifier() << OldMethod->getRefQualifier(); + Diag(OldMethod->getLocation(), diag::note_previous_declaration); + } + + return true; + } + + // The signatures match; this is not an overload. + return false; +} + +/// \brief Checks availability of the function depending on the current +/// function context. Inside an unavailable function, unavailability is ignored. +/// +/// \returns true if \arg FD is unavailable and current context is inside +/// an available function, false otherwise. +bool Sema::isFunctionConsideredUnavailable(FunctionDecl *FD) { + return FD->isUnavailable() && !cast(CurContext)->isUnavailable(); +} + +/// \brief Tries a user-defined conversion from From to ToType. +/// +/// Produces an implicit conversion sequence for when a standard conversion +/// is not an option. See TryImplicitConversion for more information. +static ImplicitConversionSequence +TryUserDefinedConversion(Sema &S, Expr *From, QualType ToType, + bool SuppressUserConversions, + bool AllowExplicit, + bool InOverloadResolution, + bool CStyle, + bool AllowObjCWritebackConversion) { + ImplicitConversionSequence 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(S, From, ToType, ICS.UserDefined, Conversions, + AllowExplicit); + + if (UserDefResult == OR_Success) { + ICS.setUserDefined(); + // 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 + // constructor (i.e., a user-defined conversion function) is + // called for those cases. + if (CXXConstructorDecl *Constructor + = dyn_cast(ICS.UserDefined.ConversionFunction)) { + QualType FromCanon + = S.Context.getCanonicalType(From->getType().getUnqualifiedType()); + QualType ToCanon + = S.Context.getCanonicalType(ToType).getUnqualifiedType(); + if (Constructor->isCopyConstructor() && + (FromCanon == ToCanon || S.IsDerivedFrom(FromCanon, ToCanon))) { + // Turn this into a "standard" conversion sequence, so that it + // gets ranked with standard conversion sequences. + ICS.setStandard(); + ICS.Standard.setAsIdentityConversion(); + ICS.Standard.setFromType(From->getType()); + ICS.Standard.setAllToTypes(ToType); + ICS.Standard.CopyConstructor = Constructor; + if (ToCanon != FromCanon) + ICS.Standard.Second = ICK_Derived_To_Base; + } + } + + // C++ [over.best.ics]p4: + // However, when considering the argument of a user-defined + // conversion function that is a candidate by 13.3.1.3 when + // invoked for the copying of the temporary in the second step + // of a class copy-initialization, or by 13.3.1.4, 13.3.1.5, or + // 13.3.1.6 in all cases, only standard conversion sequences and + // ellipsis conversion sequences are allowed. + if (SuppressUserConversions && ICS.isUserDefined()) { + ICS.setBad(BadConversionSequence::suppressed_user, From, ToType); + } + } else if (UserDefResult == OR_Ambiguous && !SuppressUserConversions) { + ICS.setAmbiguous(); + ICS.Ambiguous.setFromType(From->getType()); + ICS.Ambiguous.setToType(ToType); + for (OverloadCandidateSet::iterator Cand = Conversions.begin(); + Cand != Conversions.end(); ++Cand) + if (Cand->Viable) + ICS.Ambiguous.addConversion(Cand->Function); + } else { + ICS.setBad(BadConversionSequence::no_conversion, From, ToType); + } + + return ICS; +} + +/// TryImplicitConversion - Attempt to perform an implicit conversion +/// from the given expression (Expr) to the given type (ToType). This +/// function returns an implicit conversion sequence that can be used +/// to perform the initialization. Given +/// +/// void f(float f); +/// void g(int i) { f(i); } +/// +/// this routine would produce an implicit conversion sequence to +/// describe the initialization of f from i, which will be a standard +/// conversion sequence containing an lvalue-to-rvalue conversion (C++ +/// 4.1) followed by a floating-integral conversion (C++ 4.9). +// +/// Note that this routine only determines how the conversion can be +/// performed; it does not actually perform the conversion. As such, +/// it will not produce any diagnostics if no conversion is available, +/// but will instead return an implicit conversion sequence of kind +/// "BadConversion". +/// +/// If @p SuppressUserConversions, then user-defined conversions are +/// not permitted. +/// If @p AllowExplicit, then explicit user-defined conversions are +/// permitted. +/// +/// \param AllowObjCWritebackConversion Whether we allow the Objective-C +/// writeback conversion, which allows __autoreleasing id* parameters to +/// be initialized with __strong id* or __weak id* arguments. +static ImplicitConversionSequence +TryImplicitConversion(Sema &S, Expr *From, QualType ToType, + bool SuppressUserConversions, + bool AllowExplicit, + bool InOverloadResolution, + bool CStyle, + bool AllowObjCWritebackConversion) { + ImplicitConversionSequence ICS; + if (IsStandardConversion(S, From, ToType, InOverloadResolution, + ICS.Standard, CStyle, AllowObjCWritebackConversion)){ + ICS.setStandard(); + return ICS; + } + + if (!S.getLangOpts().CPlusPlus) { + 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); + ICS.Standard.setAllToTypes(ToType); + + // We don't actually check at this point whether there is a valid + // copy/move constructor, since overloading just assumes that it + // 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 (!S.Context.hasSameUnqualifiedType(FromType, ToType)) + ICS.Standard.Second = ICK_Derived_To_Base; + + return ICS; + } + + return TryUserDefinedConversion(S, From, ToType, SuppressUserConversions, + AllowExplicit, InOverloadResolution, CStyle, + AllowObjCWritebackConversion); +} + +ImplicitConversionSequence +Sema::TryImplicitConversion(Expr *From, QualType ToType, + bool SuppressUserConversions, + bool AllowExplicit, + bool InOverloadResolution, + bool CStyle, + bool AllowObjCWritebackConversion) { + return clang::TryImplicitConversion(*this, From, ToType, + SuppressUserConversions, AllowExplicit, + InOverloadResolution, CStyle, + AllowObjCWritebackConversion); +} + +/// PerformImplicitConversion - Perform an implicit conversion of the +/// expression From to the type ToType. Returns the +/// converted expression. Flavor is the kind of conversion we're +/// performing, used in the error message. If @p AllowExplicit, +/// explicit user-defined conversions are permitted. +ExprResult +Sema::PerformImplicitConversion(Expr *From, QualType ToType, + AssignmentAction Action, bool AllowExplicit) { + ImplicitConversionSequence ICS; + return PerformImplicitConversion(From, ToType, Action, AllowExplicit, ICS); +} + +ExprResult +Sema::PerformImplicitConversion(Expr *From, QualType ToType, + AssignmentAction Action, bool AllowExplicit, + ImplicitConversionSequence& ICS) { + if (checkPlaceholderForOverload(*this, From)) + return ExprError(); + + // Objective-C ARC: Determine whether we will allow the writeback conversion. + bool AllowObjCWritebackConversion + = getLangOpts().ObjCAutoRefCount && + (Action == AA_Passing || Action == AA_Sending); + + ICS = clang::TryImplicitConversion(*this, From, ToType, + /*SuppressUserConversions=*/false, + AllowExplicit, + /*InOverloadResolution=*/false, + /*CStyle=*/false, + AllowObjCWritebackConversion); + return PerformImplicitConversion(From, ToType, ICS, Action); +} + +/// \brief Determine whether the conversion from FromType to ToType is a valid +/// conversion that strips "noreturn" off the nested function type. +bool Sema::IsNoReturnConversion(QualType FromType, QualType ToType, + QualType &ResultTy) { + if (Context.hasSameUnqualifiedType(FromType, ToType)) + return false; + + // Permit the conversion F(t __attribute__((noreturn))) -> F(t) + // where F adds one of the following at most once: + // - a pointer + // - a member pointer + // - a block pointer + CanQualType CanTo = Context.getCanonicalType(ToType); + CanQualType CanFrom = Context.getCanonicalType(FromType); + Type::TypeClass TyClass = CanTo->getTypeClass(); + if (TyClass != CanFrom->getTypeClass()) return false; + if (TyClass != Type::FunctionProto && TyClass != Type::FunctionNoProto) { + if (TyClass == Type::Pointer) { + CanTo = CanTo.getAs()->getPointeeType(); + CanFrom = CanFrom.getAs()->getPointeeType(); + } else if (TyClass == Type::BlockPointer) { + CanTo = CanTo.getAs()->getPointeeType(); + CanFrom = CanFrom.getAs()->getPointeeType(); + } else if (TyClass == Type::MemberPointer) { + CanTo = CanTo.getAs()->getPointeeType(); + CanFrom = CanFrom.getAs()->getPointeeType(); + } else { + return false; + } + + TyClass = CanTo->getTypeClass(); + if (TyClass != CanFrom->getTypeClass()) return false; + if (TyClass != Type::FunctionProto && TyClass != Type::FunctionNoProto) + return false; + } + + const FunctionType *FromFn = cast(CanFrom); + FunctionType::ExtInfo EInfo = FromFn->getExtInfo(); + if (!EInfo.getNoReturn()) return false; + + FromFn = Context.adjustFunctionType(FromFn, EInfo.withNoReturn(false)); + assert(QualType(FromFn, 0).isCanonical()); + if (QualType(FromFn, 0) != CanTo) return false; + + ResultTy = ToType; + return true; +} + +/// \brief Determine whether the conversion from FromType to ToType is a valid +/// vector conversion. +/// +/// \param ICK Will be set to the vector conversion kind, if this is a vector +/// conversion. +static bool IsVectorConversion(ASTContext &Context, QualType FromType, + QualType ToType, ImplicitConversionKind &ICK) { + // We need at least one of these types to be a vector type to have a vector + // conversion. + if (!ToType->isVectorType() && !FromType->isVectorType()) + return false; + + // Identical types require no conversions. + if (Context.hasSameUnqualifiedType(FromType, ToType)) + return false; + + // There are no conversions between extended vector types, only identity. + if (ToType->isExtVectorType()) { + // There are no conversions between extended vector types other than the + // identity conversion. + if (FromType->isExtVectorType()) + return false; + + // Vector splat from any arithmetic type to a vector. + if (FromType->isArithmeticType()) { + ICK = ICK_Vector_Splat; + 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.getLangOpts().LaxVectorConversions && + (Context.getTypeSize(FromType) == Context.getTypeSize(ToType)))) { + ICK = ICK_Vector_Conversion; + return true; + } + } + + return false; +} + +static bool tryAtomicConversion(Sema &S, Expr *From, QualType ToType, + bool InOverloadResolution, + StandardConversionSequence &SCS, + bool CStyle); + +/// IsStandardConversion - Determines whether there is a standard +/// conversion sequence (C++ [conv], C++ [over.ics.scs]) from the +/// expression From to the type ToType. Standard conversion sequences +/// only consider non-class types; for conversions that involve class +/// types, use TryImplicitConversion. If a conversion exists, SCS will +/// 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. +static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, + bool InOverloadResolution, + StandardConversionSequence &SCS, + bool CStyle, + bool AllowObjCWritebackConversion) { + QualType FromType = From->getType(); + + // Standard conversions (C++ [conv]) + SCS.setAsIdentityConversion(); + SCS.DeprecatedStringLiteralToCharPtr = false; + SCS.IncompatibleObjC = false; + SCS.setFromType(FromType); + SCS.CopyConstructor = 0; + + // 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 (S.getLangOpts().CPlusPlus) + return false; + + // When we're overloading in C, we allow, as standard conversions, + } + + // The first conversion can be an lvalue-to-rvalue conversion, + // array-to-pointer conversion, or function-to-pointer conversion + // (C++ 4p1). + + if (FromType == S.Context.OverloadTy) { + DeclAccessPair AccessPair; + if (FunctionDecl *Fn + = 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(); + + // we can sometimes resolve &foo regardless of ToType, so check + // if the type matches (identity) or we are converting to bool + if (!S.Context.hasSameUnqualifiedType( + S.ExtractUnqualifiedFunctionType(ToType), FromType)) { + QualType resultTy; + // if the function type matches except for [[noreturn]], it's ok + if (!S.IsNoReturnConversion(FromType, + S.ExtractUnqualifiedFunctionType(ToType), resultTy)) + // otherwise, only a boolean conversion is standard + if (!ToType->isBooleanType()) + return false; + } + + // Check if the "from" expression is taking the address of an overloaded + // function and recompute the FromType accordingly. Take advantage of the + // fact that non-static member functions *must* have such an address-of + // expression. + CXXMethodDecl *Method = dyn_cast(Fn); + if (Method && !Method->isStatic()) { + assert(isa(From->IgnoreParens()) && + "Non-unary operator on non-static member address"); + assert(cast(From->IgnoreParens())->getOpcode() + == UO_AddrOf && + "Non-address-of operator on non-static member address"); + const Type *ClassType + = S.Context.getTypeDeclType(Method->getParent()).getTypePtr(); + FromType = S.Context.getMemberPointerType(FromType, ClassType); + } else if (isa(From->IgnoreParens())) { + assert(cast(From->IgnoreParens())->getOpcode() == + UO_AddrOf && + "Non-address-of operator for overloaded function expression"); + FromType = S.Context.getPointerType(FromType); + } + + // Check that we've computed the proper type after overload resolution. + assert(S.Context.hasSameType( + FromType, + S.FixOverloadedFunctionReference(From, AccessPair, Fn)->getType())); + } else { + return false; + } + } + // Lvalue-to-rvalue conversion (C++11 4.1): + // A glvalue (3.10) of a non-function, non-array type T can + // be converted to a prvalue. + bool argIsLValue = From->isGLValue(); + if (argIsLValue && + !FromType->isFunctionType() && !FromType->isArrayType() && + S.Context.getCanonicalType(FromType) != S.Context.OverloadTy) { + SCS.First = ICK_Lvalue_To_Rvalue; + + // C11 6.3.2.1p2: + // ... if the lvalue has atomic type, the value has the non-atomic version + // of the type of the lvalue ... + if (const AtomicType *Atomic = FromType->getAs()) + FromType = Atomic->getValueType(); + + // If T is a non-class type, the type of the rvalue is the + // cv-unqualified version of T. Otherwise, the type of the rvalue + // is T (C++ 4.1p1). C++ can't get here with class types; in C, we + // just strip the qualifiers because they don't matter. + FromType = FromType.getUnqualifiedType(); + } else if (FromType->isArrayType()) { + // Array-to-pointer conversion (C++ 4.2) + SCS.First = ICK_Array_To_Pointer; + + // 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 = S.Context.getArrayDecayedType(FromType); + + if (S.IsStringLiteralToNonConstPointerConversion(From, ToType)) { + // This conversion is deprecated. (C++ D.4). + SCS.DeprecatedStringLiteralToCharPtr = true; + + // For the purpose of ranking in overload resolution + // (13.3.3.1.1), this conversion is considered an + // array-to-pointer conversion followed by a qualification + // conversion (4.4). (C++ 4.2p2) + SCS.Second = ICK_Identity; + SCS.Third = ICK_Qualification; + SCS.QualificationIncludesObjCLifetime = false; + SCS.setAllToTypes(FromType); + return true; + } + } else if (FromType->isFunctionType() && argIsLValue) { + // Function-to-pointer conversion (C++ 4.3). + SCS.First = ICK_Function_To_Pointer; + + // 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 = S.Context.getPointerType(FromType); + } else { + // We don't require any conversions for the first step. + SCS.First = ICK_Identity; + } + SCS.setToType(0, FromType); + + // 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 (C++ 4p1). + // For overloading in C, this can also be a "compatible-type" + // conversion. + bool IncompatibleObjC = false; + ImplicitConversionKind SecondICK = ICK_Identity; + 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 (S.IsIntegralPromotion(From, FromType, ToType)) { + // Integral promotion (C++ 4.5). + SCS.Second = ICK_Integral_Promotion; + FromType = ToType.getUnqualifiedType(); + } else if (S.IsFloatingPointPromotion(FromType, ToType)) { + // Floating point promotion (C++ 4.6). + SCS.Second = ICK_Floating_Promotion; + FromType = ToType.getUnqualifiedType(); + } else if (S.IsComplexPromotion(FromType, ToType)) { + // Complex promotion (Clang extension) + SCS.Second = ICK_Complex_Promotion; + FromType = ToType.getUnqualifiedType(); + } else if (ToType->isBooleanType() && + (FromType->isArithmeticType() || + FromType->isAnyPointerType() || + FromType->isBlockPointerType() || + FromType->isMemberPointerType() || + FromType->isNullPtrType())) { + // Boolean conversions (C++ 4.12). + SCS.Second = ICK_Boolean_Conversion; + FromType = S.Context.BoolTy; + } else if (FromType->isIntegralOrUnscopedEnumerationType() && + ToType->isIntegralType(S.Context)) { + // Integral conversions (C++ 4.7). + SCS.Second = ICK_Integral_Conversion; + FromType = ToType.getUnqualifiedType(); + } else if (FromType->isAnyComplexType() && ToType->isComplexType()) { + // Complex conversions (C99 6.3.1.6) + SCS.Second = ICK_Complex_Conversion; + FromType = ToType.getUnqualifiedType(); + } else if ((FromType->isAnyComplexType() && ToType->isArithmeticType()) || + (ToType->isAnyComplexType() && FromType->isArithmeticType())) { + // Complex-real conversions (C99 6.3.1.7) + SCS.Second = ICK_Complex_Real; + FromType = ToType.getUnqualifiedType(); + } else if (FromType->isRealFloatingType() && ToType->isRealFloatingType()) { + // Floating point conversions (C++ 4.8). + SCS.Second = ICK_Floating_Conversion; + FromType = ToType.getUnqualifiedType(); + } else if ((FromType->isRealFloatingType() && + ToType->isIntegralType(S.Context)) || + (FromType->isIntegralOrUnscopedEnumerationType() && + ToType->isRealFloatingType())) { + // Floating-integral conversions (C++ 4.9). + SCS.Second = ICK_Floating_Integral; + FromType = ToType.getUnqualifiedType(); + } else if (S.IsBlockPointerConversion(FromType, ToType, FromType)) { + SCS.Second = ICK_Block_Pointer_Conversion; + } else if (AllowObjCWritebackConversion && + S.isObjCWritebackConversion(FromType, ToType, FromType)) { + SCS.Second = ICK_Writeback_Conversion; + } else if (S.IsPointerConversion(From, FromType, ToType, InOverloadResolution, + FromType, IncompatibleObjC)) { + // Pointer conversions (C++ 4.10). + SCS.Second = ICK_Pointer_Conversion; + SCS.IncompatibleObjC = IncompatibleObjC; + FromType = FromType.getUnqualifiedType(); + } else if (S.IsMemberPointerConversion(From, FromType, ToType, + InOverloadResolution, FromType)) { + // Pointer to member conversions (4.11). + SCS.Second = ICK_Pointer_Member; + } else if (IsVectorConversion(S.Context, FromType, ToType, SecondICK)) { + SCS.Second = SecondICK; + FromType = ToType.getUnqualifiedType(); + } else if (!S.getLangOpts().CPlusPlus && + S.Context.typesAreCompatible(ToType, FromType)) { + // Compatible conversions (Clang extension for C function overloading) + SCS.Second = ICK_Compatible_Conversion; + FromType = ToType.getUnqualifiedType(); + } else if (S.IsNoReturnConversion(FromType, ToType, FromType)) { + // Treat a conversion that strips "noreturn" as an identity conversion. + SCS.Second = ICK_NoReturn_Adjustment; + } else if (IsTransparentUnionStandardConversion(S, From, ToType, + InOverloadResolution, + SCS, CStyle)) { + SCS.Second = ICK_TransparentUnionConversion; + FromType = ToType; + } else if (tryAtomicConversion(S, From, ToType, InOverloadResolution, SCS, + CStyle)) { + // tryAtomicConversion has updated the standard conversion sequence + // appropriately. + return true; + } else { + // No second conversion required. + SCS.Second = ICK_Identity; + } + SCS.setToType(1, FromType); + + QualType CanonFrom; + QualType CanonTo; + // The third conversion can be a qualification conversion (C++ 4p1). + bool ObjCLifetimeConversion; + if (S.IsQualificationConversion(FromType, ToType, CStyle, + ObjCLifetimeConversion)) { + SCS.Third = ICK_Qualification; + SCS.QualificationIncludesObjCLifetime = ObjCLifetimeConversion; + FromType = ToType; + CanonFrom = S.Context.getCanonicalType(FromType); + CanonTo = S.Context.getCanonicalType(ToType); + } else { + // No conversion required + SCS.Third = ICK_Identity; + + // C++ [over.best.ics]p6: + // [...] Any difference in top-level cv-qualification is + // subsumed by the initialization itself and does not constitute + // a conversion. [...] + CanonFrom = S.Context.getCanonicalType(FromType); + CanonTo = S.Context.getCanonicalType(ToType); + if (CanonFrom.getLocalUnqualifiedType() + == CanonTo.getLocalUnqualifiedType() && + (CanonFrom.getLocalCVRQualifiers() != CanonTo.getLocalCVRQualifiers() + || CanonFrom.getObjCGCAttr() != CanonTo.getObjCGCAttr() + || CanonFrom.getObjCLifetime() != CanonTo.getObjCLifetime())) { + FromType = ToType; + CanonFrom = CanonTo; + } + } + SCS.setToType(2, FromType); + + // If we have not converted the argument type to the parameter type, + // this is a bad conversion sequence. + if (CanonFrom != CanonTo) + return false; + + return true; +} + +static bool +IsTransparentUnionStandardConversion(Sema &S, Expr* From, + QualType &ToType, + bool InOverloadResolution, + StandardConversionSequence &SCS, + bool CStyle) { + + const RecordType *UT = ToType->getAsUnionType(); + if (!UT || !UT->getDecl()->hasAttr()) + return false; + // The field to initialize within the transparent union. + RecordDecl *UD = UT->getDecl(); + // It's compatible if the expression matches any of the fields. + for (RecordDecl::field_iterator it = UD->field_begin(), + itend = UD->field_end(); + it != itend; ++it) { + if (IsStandardConversion(S, From, it->getType(), InOverloadResolution, SCS, + CStyle, /*ObjCWritebackConversion=*/false)) { + ToType = it->getType(); + return true; + } + } + return false; +} + +/// IsIntegralPromotion - Determines whether the conversion from the +/// expression From (whose potentially-adjusted type is FromType) to +/// ToType is an integral promotion (C++ 4.5). If so, returns true and +/// sets PromotedType to the promoted type. +bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) { + const BuiltinType *To = ToType->getAs(); + // All integers are built-in. + if (!To) { + return false; + } + + // An rvalue of type char, signed char, unsigned char, short int, or + // unsigned short int can be converted to an rvalue of type int if + // int can represent all the values of the source type; otherwise, + // the source rvalue can be converted to an rvalue of type unsigned + // int (C++ 4.5p1). + if (FromType->isPromotableIntegerType() && !FromType->isBooleanType() && + !FromType->isEnumeralType()) { + if (// We can promote any signed, promotable integer type to an int + (FromType->isSignedIntegerType() || + // We can promote any unsigned integer type whose size is + // less than int to an int. + (!FromType->isSignedIntegerType() && + Context.getTypeSize(FromType) < Context.getTypeSize(ToType)))) { + return To->getKind() == BuiltinType::Int; + } + + return To->getKind() == BuiltinType::UInt; + } + + // C++0x [conv.prom]p3: + // A prvalue of an unscoped enumeration type whose underlying type is not + // fixed (7.2) can be converted to an rvalue a prvalue of the first of the + // following types that can represent all the values of the enumeration + // (i.e., the values in the range bmin to bmax as described in 7.2): int, + // unsigned int, long int, unsigned long int, long long int, or unsigned + // long long int. If none of the types in that list can represent all the + // values of the enumeration, an rvalue a prvalue of an unscoped enumeration + // type can be converted to an rvalue a prvalue of the extended integer type + // with lowest integer conversion rank (4.13) greater than the rank of long + // long in which all the values of the enumeration can be represented. If + // there are two such extended types, the signed one is chosen. + if (const EnumType *FromEnumType = FromType->getAs()) { + // C++0x 7.2p9: Note that this implicit enum to int conversion is not + // provided for a scoped enumeration. + if (FromEnumType->getDecl()->isScoped()) + return false; + + // We have already pre-calculated the promotion type, so this is trivial. + if (ToType->isIntegerType() && + !RequireCompleteType(From->getLocStart(), FromType, PDiag())) + return Context.hasSameUnqualifiedType(ToType, + FromEnumType->getDecl()->getPromotionType()); + } + + // C++0x [conv.prom]p2: + // A prvalue of type char16_t, char32_t, or wchar_t (3.9.1) can be converted + // to an rvalue a prvalue of the first of the following types that can + // represent all the values of its underlying type: int, unsigned int, + // long int, unsigned long int, long long int, or unsigned long long int. + // If none of the types in that list can represent all the values of its + // underlying type, an rvalue a prvalue of type char16_t, char32_t, + // or wchar_t can be converted to an rvalue a prvalue of its underlying + // type. + if (FromType->isAnyCharacterType() && !FromType->isCharType() && + ToType->isIntegerType()) { + // Determine whether the type we're converting from is signed or + // unsigned. + bool FromIsSigned = FromType->isSignedIntegerType(); + uint64_t FromSize = Context.getTypeSize(FromType); + + // The types we'll try to promote to, in the appropriate + // order. Try each of these types. + QualType PromoteTypes[6] = { + Context.IntTy, Context.UnsignedIntTy, + Context.LongTy, Context.UnsignedLongTy , + Context.LongLongTy, Context.UnsignedLongLongTy + }; + for (int Idx = 0; Idx < 6; ++Idx) { + uint64_t ToSize = Context.getTypeSize(PromoteTypes[Idx]); + if (FromSize < ToSize || + (FromSize == ToSize && + FromIsSigned == PromoteTypes[Idx]->isSignedIntegerType())) { + // We found the type that we can promote to. If this is the + // type we wanted, we have a promotion. Otherwise, no + // promotion. + return Context.hasSameUnqualifiedType(ToType, PromoteTypes[Idx]); + } + } + } + + // An rvalue for an integral bit-field (9.6) can be converted to an + // rvalue of type int if int can represent all the values of the + // bit-field; otherwise, it can be converted to unsigned int if + // unsigned int can represent all the values of the bit-field. If + // the bit-field is larger yet, no integral promotion applies to + // it. If the bit-field has an enumerated type, it is treated as any + // other value of that type for promotion purposes (C++ 4.5p3). + // FIXME: We should delay checking of bit-fields until we actually perform the + // conversion. + using llvm::APSInt; + if (From) + if (FieldDecl *MemberDecl = From->getBitField()) { + APSInt BitWidth; + if (FromType->isIntegralType(Context) && + MemberDecl->getBitWidth()->isIntegerConstantExpr(BitWidth, Context)) { + APSInt ToSize(BitWidth.getBitWidth(), BitWidth.isUnsigned()); + ToSize = Context.getTypeSize(ToType); + + // Are we promoting to an int from a bitfield that fits in an int? + if (BitWidth < ToSize || + (FromType->isSignedIntegerType() && BitWidth <= ToSize)) { + return To->getKind() == BuiltinType::Int; + } + + // Are we promoting to an unsigned int from an unsigned bitfield + // that fits into an unsigned int? + if (FromType->isUnsignedIntegerType() && BitWidth <= ToSize) { + return To->getKind() == BuiltinType::UInt; + } + + return false; + } + } + + // An rvalue of type bool can be converted to an rvalue of type int, + // with false becoming zero and true becoming one (C++ 4.5p4). + if (FromType->isBooleanType() && To->getKind() == BuiltinType::Int) { + return true; + } + + return false; +} + +/// IsFloatingPointPromotion - Determines whether the conversion from +/// FromType to ToType is a floating point promotion (C++ 4.6). If so, +/// returns true and sets PromotedType to the promoted type. +bool Sema::IsFloatingPointPromotion(QualType FromType, QualType ToType) { + if (const BuiltinType *FromBuiltin = FromType->getAs()) + if (const BuiltinType *ToBuiltin = ToType->getAs()) { + /// An rvalue of type float can be converted to an rvalue of type + /// double. (C++ 4.6p1). + if (FromBuiltin->getKind() == BuiltinType::Float && + ToBuiltin->getKind() == BuiltinType::Double) + return true; + + // C99 6.3.1.5p1: + // When a float is promoted to double or long double, or a + // double is promoted to long double [...]. + if (!getLangOpts().CPlusPlus && + (FromBuiltin->getKind() == BuiltinType::Float || + FromBuiltin->getKind() == BuiltinType::Double) && + (ToBuiltin->getKind() == BuiltinType::LongDouble)) + return true; + + // Half can be promoted to float. + if (FromBuiltin->getKind() == BuiltinType::Half && + ToBuiltin->getKind() == BuiltinType::Float) + return true; + } + + return false; +} + +/// \brief Determine if a conversion is a complex promotion. +/// +/// A complex promotion is defined as a complex -> complex conversion +/// where the conversion between the underlying real types is a +/// floating-point or integral promotion. +bool Sema::IsComplexPromotion(QualType FromType, QualType ToType) { + const ComplexType *FromComplex = FromType->getAs(); + if (!FromComplex) + return false; + + const ComplexType *ToComplex = ToType->getAs(); + if (!ToComplex) + return false; + + return IsFloatingPointPromotion(FromComplex->getElementType(), + ToComplex->getElementType()) || + IsIntegralPromotion(0, FromComplex->getElementType(), + ToComplex->getElementType()); +} + +/// BuildSimilarlyQualifiedPointerType - In a pointer conversion from +/// the pointer type FromPtr to a pointer to type ToPointee, with the +/// same type qualifiers as FromPtr has on its pointee type. ToType, +/// if non-empty, will be a pointer to ToType that may or may not have +/// the right set of qualifiers on its pointee. +/// +static QualType +BuildSimilarlyQualifiedPointerType(const Type *FromPtr, + QualType ToPointee, QualType ToType, + ASTContext &Context, + bool StripObjCLifetime = false) { + assert((FromPtr->getTypeClass() == Type::Pointer || + FromPtr->getTypeClass() == Type::ObjCObjectPointer) && + "Invalid similarly-qualified pointer type"); + + /// Conversions to 'id' subsume cv-qualifier conversions. + if (ToType->isObjCIdType() || ToType->isObjCQualifiedIdType()) + return ToType.getUnqualifiedType(); + + QualType CanonFromPointee + = Context.getCanonicalType(FromPtr->getPointeeType()); + QualType CanonToPointee = Context.getCanonicalType(ToPointee); + Qualifiers Quals = CanonFromPointee.getQualifiers(); + + if (StripObjCLifetime) + Quals.removeObjCLifetime(); + + // Exact qualifier match -> return the pointer type we're converting to. + if (CanonToPointee.getLocalQualifiers() == Quals) { + // ToType is exactly what we need. Return it. + if (!ToType.isNull()) + return ToType.getUnqualifiedType(); + + // Build a pointer to ToPointee. It has the right qualifiers + // already. + if (isa(ToType)) + return Context.getObjCObjectPointerType(ToPointee); + return Context.getPointerType(ToPointee); + } + + // Just build a canonical type that has the right qualifiers. + QualType QualifiedCanonToPointee + = Context.getQualifiedType(CanonToPointee.getLocalUnqualifiedType(), Quals); + + if (isa(ToType)) + return Context.getObjCObjectPointerType(QualifiedCanonToPointee); + return Context.getPointerType(QualifiedCanonToPointee); +} + +static bool isNullPointerConstantForConversion(Expr *Expr, + bool InOverloadResolution, + ASTContext &Context) { + // Handle value-dependent integral null pointer constants correctly. + // http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#903 + if (Expr->isValueDependent() && !Expr->isTypeDependent() && + Expr->getType()->isIntegerType() && !Expr->getType()->isEnumeralType()) + return !InOverloadResolution; + + return Expr->isNullPointerConstant(Context, + InOverloadResolution? Expr::NPC_ValueDependentIsNotNull + : Expr::NPC_ValueDependentIsNull); +} + +/// IsPointerConversion - Determines whether the conversion of the +/// expression From, which has the (possibly adjusted) type FromType, +/// can be converted to the type ToType via a pointer conversion (C++ +/// 4.10). If so, returns true and places the converted type (that +/// might differ from ToType in its cv-qualifiers at some level) into +/// ConvertedType. +/// +/// This routine also supports conversions to and from block pointers +/// and conversions with Objective-C's 'id', 'id', and +/// pointers to interfaces. FIXME: Once we've determined the +/// appropriate overloading rules for Objective-C, we may want to +/// split the Objective-C checks into a different routine; however, +/// GCC seems to consider all of these conversions to be pointer +/// conversions, so for now they live here. IncompatibleObjC will be +/// set if the conversion is an allowed Objective-C conversion that +/// should result in a warning. +bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType, + bool InOverloadResolution, + QualType& ConvertedType, + bool &IncompatibleObjC) { + IncompatibleObjC = false; + if (isObjCPointerConversion(FromType, ToType, ConvertedType, + IncompatibleObjC)) + return true; + + // Conversion from a null pointer constant to any Objective-C pointer type. + if (ToType->isObjCObjectPointerType() && + isNullPointerConstantForConversion(From, InOverloadResolution, Context)) { + ConvertedType = ToType; + return true; + } + + // Blocks: Block pointers can be converted to void*. + if (FromType->isBlockPointerType() && ToType->isPointerType() && + ToType->getAs()->getPointeeType()->isVoidType()) { + ConvertedType = ToType; + return true; + } + // Blocks: A null pointer constant can be converted to a block + // pointer type. + if (ToType->isBlockPointerType() && + isNullPointerConstantForConversion(From, InOverloadResolution, Context)) { + ConvertedType = ToType; + return true; + } + + // If the left-hand-side is nullptr_t, the right side can be a null + // pointer constant. + if (ToType->isNullPtrType() && + isNullPointerConstantForConversion(From, InOverloadResolution, Context)) { + ConvertedType = ToType; + return true; + } + + const PointerType* ToTypePtr = ToType->getAs(); + if (!ToTypePtr) + return false; + + // A null pointer constant can be converted to a pointer type (C++ 4.10p1). + if (isNullPointerConstantForConversion(From, InOverloadResolution, Context)) { + ConvertedType = ToType; + return true; + } + + // Beyond this point, both types need to be pointers + // , including objective-c pointers. + QualType ToPointeeType = ToTypePtr->getPointeeType(); + if (FromType->isObjCObjectPointerType() && ToPointeeType->isVoidType() && + !getLangOpts().ObjCAutoRefCount) { + ConvertedType = BuildSimilarlyQualifiedPointerType( + FromType->getAs(), + ToPointeeType, + ToType, Context); + return true; + } + const PointerType *FromTypePtr = FromType->getAs(); + if (!FromTypePtr) + return false; + + 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->isIncompleteOrObjectType() && + ToPointeeType->isVoidType()) { + ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr, + ToPointeeType, + ToType, Context, + /*StripObjCLifetime=*/true); + return true; + } + + // MSVC allows implicit function to void* type conversion. + if (getLangOpts().MicrosoftExt && FromPointeeType->isFunctionType() && + ToPointeeType->isVoidType()) { + ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr, + ToPointeeType, + ToType, Context); + return true; + } + + // When we're overloading in C, we allow a special kind of pointer + // conversion for compatible-but-not-identical pointee types. + if (!getLangOpts().CPlusPlus && + Context.typesAreCompatible(FromPointeeType, ToPointeeType)) { + ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr, + ToPointeeType, + ToType, Context); + return true; + } + + // C++ [conv.ptr]p3: + // + // An rvalue of type "pointer to cv D," where D is a class type, + // can be converted to an rvalue of type "pointer to cv B," where + // B is a base class (clause 10) of D. If B is an inaccessible + // (clause 11) or ambiguous (10.2) base class of D, a program that + // necessitates this conversion is ill-formed. The result of the + // conversion is a pointer to the base class sub-object of the + // derived class object. The null pointer value is converted to + // the null pointer value of the destination type. + // + // Note that we do not check for ambiguity or inaccessibility + // here. That is handled by CheckPointerConversion. + if (getLangOpts().CPlusPlus && + FromPointeeType->isRecordType() && ToPointeeType->isRecordType() && + !Context.hasSameUnqualifiedType(FromPointeeType, ToPointeeType) && + !RequireCompleteType(From->getLocStart(), FromPointeeType, PDiag()) && + IsDerivedFrom(FromPointeeType, ToPointeeType)) { + ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr, + ToPointeeType, + ToType, Context); + return true; + } + + if (FromPointeeType->isVectorType() && ToPointeeType->isVectorType() && + Context.areCompatibleVectorTypes(FromPointeeType, ToPointeeType)) { + ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr, + ToPointeeType, + ToType, Context); + return true; + } + + return false; +} + +/// \brief Adopt the given qualifiers for the given type. +static QualType AdoptQualifiers(ASTContext &Context, QualType T, Qualifiers Qs){ + Qualifiers TQs = T.getQualifiers(); + + // Check whether qualifiers already match. + if (TQs == Qs) + return T; + + if (Qs.compatiblyIncludes(TQs)) + return Context.getQualifiedType(T, Qs); + + return Context.getQualifiedType(T.getUnqualifiedType(), Qs); +} + +/// isObjCPointerConversion - Determines whether this is an +/// Objective-C pointer conversion. Subroutine of IsPointerConversion, +/// with the same arguments and return values. +bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, + QualType& ConvertedType, + bool &IncompatibleObjC) { + if (!getLangOpts().ObjC1) + return false; + + // The set of qualifiers on the type we're converting from. + Qualifiers FromQualifiers = FromType.getQualifiers(); + + // First, we handle all conversions on ObjC object pointer types. + const ObjCObjectPointerType* ToObjCPtr = + ToType->getAs(); + const ObjCObjectPointerType *FromObjCPtr = + FromType->getAs(); + + if (ToObjCPtr && FromObjCPtr) { + // If the pointee types are the same (ignoring qualifications), + // then this is not a pointer conversion. + if (Context.hasSameUnqualifiedType(ToObjCPtr->getPointeeType(), + FromObjCPtr->getPointeeType())) + return false; + + // Check for compatible + // Objective C++: We're able to convert between "id" or "Class" and a + // pointer to any interface (in both directions). + if (ToObjCPtr->isObjCBuiltinType() && FromObjCPtr->isObjCBuiltinType()) { + ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers); + return true; + } + // Conversions with Objective-C's id<...>. + if ((FromObjCPtr->isObjCQualifiedIdType() || + ToObjCPtr->isObjCQualifiedIdType()) && + Context.ObjCQualifiedIdTypesAreCompatible(ToType, FromType, + /*compare=*/false)) { + ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers); + return true; + } + // Objective C++: We're able to convert from a pointer to an + // interface to a pointer to a different interface. + if (Context.canAssignObjCInterfaces(ToObjCPtr, FromObjCPtr)) { + const ObjCInterfaceType* LHS = ToObjCPtr->getInterfaceType(); + const ObjCInterfaceType* RHS = FromObjCPtr->getInterfaceType(); + if (getLangOpts().CPlusPlus && LHS && RHS && + !ToObjCPtr->getPointeeType().isAtLeastAsQualifiedAs( + FromObjCPtr->getPointeeType())) + return false; + ConvertedType = BuildSimilarlyQualifiedPointerType(FromObjCPtr, + ToObjCPtr->getPointeeType(), + ToType, Context); + ConvertedType = AdoptQualifiers(Context, ConvertedType, FromQualifiers); + return true; + } + + if (Context.canAssignObjCInterfaces(FromObjCPtr, ToObjCPtr)) { + // Okay: this is some kind of implicit downcast of Objective-C + // interfaces, which is permitted. However, we're going to + // complain about it. + IncompatibleObjC = true; + ConvertedType = BuildSimilarlyQualifiedPointerType(FromObjCPtr, + ToObjCPtr->getPointeeType(), + ToType, Context); + ConvertedType = AdoptQualifiers(Context, ConvertedType, FromQualifiers); + return true; + } + } + // Beyond this point, both types need to be C pointers or block pointers. + QualType ToPointeeType; + if (const PointerType *ToCPtr = ToType->getAs()) + ToPointeeType = ToCPtr->getPointeeType(); + else if (const BlockPointerType *ToBlockPtr = + ToType->getAs()) { + // Objective C++: We're able to convert from a pointer to any object + // to a block pointer type. + if (FromObjCPtr && FromObjCPtr->isObjCBuiltinType()) { + ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers); + return true; + } + ToPointeeType = ToBlockPtr->getPointeeType(); + } + else if (FromType->getAs() && + ToObjCPtr && ToObjCPtr->isObjCBuiltinType()) { + // Objective C++: We're able to convert from a block pointer type to a + // pointer to any object. + ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers); + return true; + } + else + return false; + + QualType FromPointeeType; + if (const PointerType *FromCPtr = FromType->getAs()) + FromPointeeType = FromCPtr->getPointeeType(); + else if (const BlockPointerType *FromBlockPtr = + FromType->getAs()) + FromPointeeType = FromBlockPtr->getPointeeType(); + else + return false; + + // If we have pointers to pointers, recursively check whether this + // is an Objective-C conversion. + if (FromPointeeType->isPointerType() && ToPointeeType->isPointerType() && + isObjCPointerConversion(FromPointeeType, ToPointeeType, ConvertedType, + IncompatibleObjC)) { + // We always complain about this conversion. + IncompatibleObjC = true; + ConvertedType = Context.getPointerType(ConvertedType); + ConvertedType = AdoptQualifiers(Context, ConvertedType, FromQualifiers); + return true; + } + // Allow conversion of pointee being objective-c pointer to another one; + // as in I* to id. + if (FromPointeeType->getAs() && + ToPointeeType->getAs() && + isObjCPointerConversion(FromPointeeType, ToPointeeType, ConvertedType, + IncompatibleObjC)) { + + ConvertedType = Context.getPointerType(ConvertedType); + ConvertedType = AdoptQualifiers(Context, ConvertedType, FromQualifiers); + return true; + } + + // If we have pointers to functions or blocks, check whether the only + // differences in the argument and result types are in Objective-C + // pointer conversions. If so, we permit the conversion (but + // complain about it). + const FunctionProtoType *FromFunctionType + = FromPointeeType->getAs(); + const FunctionProtoType *ToFunctionType + = ToPointeeType->getAs(); + if (FromFunctionType && ToFunctionType) { + // If the function types are exactly the same, this isn't an + // Objective-C pointer conversion. + if (Context.getCanonicalType(FromPointeeType) + == Context.getCanonicalType(ToPointeeType)) + return false; + + // Perform the quick checks that will tell us whether these + // function types are obviously different. + if (FromFunctionType->getNumArgs() != ToFunctionType->getNumArgs() || + FromFunctionType->isVariadic() != ToFunctionType->isVariadic() || + FromFunctionType->getTypeQuals() != ToFunctionType->getTypeQuals()) + return false; + + bool HasObjCConversion = false; + if (Context.getCanonicalType(FromFunctionType->getResultType()) + == Context.getCanonicalType(ToFunctionType->getResultType())) { + // Okay, the types match exactly. Nothing to do. + } else if (isObjCPointerConversion(FromFunctionType->getResultType(), + ToFunctionType->getResultType(), + ConvertedType, IncompatibleObjC)) { + // Okay, we have an Objective-C pointer conversion. + HasObjCConversion = true; + } else { + // Function types are too different. Abort. + return false; + } + + // Check argument types. + for (unsigned ArgIdx = 0, NumArgs = FromFunctionType->getNumArgs(); + ArgIdx != NumArgs; ++ArgIdx) { + QualType FromArgType = FromFunctionType->getArgType(ArgIdx); + QualType ToArgType = ToFunctionType->getArgType(ArgIdx); + if (Context.getCanonicalType(FromArgType) + == Context.getCanonicalType(ToArgType)) { + // Okay, the types match exactly. Nothing to do. + } else if (isObjCPointerConversion(FromArgType, ToArgType, + ConvertedType, IncompatibleObjC)) { + // Okay, we have an Objective-C pointer conversion. + HasObjCConversion = true; + } else { + // Argument types are too different. Abort. + return false; + } + } + + if (HasObjCConversion) { + // We had an Objective-C conversion. Allow this pointer + // conversion, but complain about it. + ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers); + IncompatibleObjC = true; + return true; + } + } + + return false; +} + +/// \brief Determine whether this is an Objective-C writeback conversion, +/// used for parameter passing when performing automatic reference counting. +/// +/// \param FromType The type we're converting form. +/// +/// \param ToType The type we're converting to. +/// +/// \param ConvertedType The type that will be produced after applying +/// this conversion. +bool Sema::isObjCWritebackConversion(QualType FromType, QualType ToType, + QualType &ConvertedType) { + if (!getLangOpts().ObjCAutoRefCount || + Context.hasSameUnqualifiedType(FromType, ToType)) + return false; + + // Parameter must be a pointer to __autoreleasing (with no other qualifiers). + QualType ToPointee; + if (const PointerType *ToPointer = ToType->getAs()) + ToPointee = ToPointer->getPointeeType(); + else + return false; + + Qualifiers ToQuals = ToPointee.getQualifiers(); + if (!ToPointee->isObjCLifetimeType() || + ToQuals.getObjCLifetime() != Qualifiers::OCL_Autoreleasing || + !ToQuals.withoutObjCLifetime().empty()) + return false; + + // Argument must be a pointer to __strong to __weak. + QualType FromPointee; + if (const PointerType *FromPointer = FromType->getAs()) + FromPointee = FromPointer->getPointeeType(); + else + return false; + + Qualifiers FromQuals = FromPointee.getQualifiers(); + if (!FromPointee->isObjCLifetimeType() || + (FromQuals.getObjCLifetime() != Qualifiers::OCL_Strong && + FromQuals.getObjCLifetime() != Qualifiers::OCL_Weak)) + return false; + + // Make sure that we have compatible qualifiers. + FromQuals.setObjCLifetime(Qualifiers::OCL_Autoreleasing); + if (!ToQuals.compatiblyIncludes(FromQuals)) + return false; + + // Remove qualifiers from the pointee type we're converting from; they + // aren't used in the compatibility check belong, and we'll be adding back + // qualifiers (with __autoreleasing) if the compatibility check succeeds. + FromPointee = FromPointee.getUnqualifiedType(); + + // The unqualified form of the pointee types must be compatible. + ToPointee = ToPointee.getUnqualifiedType(); + bool IncompatibleObjC; + if (Context.typesAreCompatible(FromPointee, ToPointee)) + FromPointee = ToPointee; + else if (!isObjCPointerConversion(FromPointee, ToPointee, FromPointee, + IncompatibleObjC)) + return false; + + /// \brief Construct the type we're converting to, which is a pointer to + /// __autoreleasing pointee. + FromPointee = Context.getQualifiedType(FromPointee, FromQuals); + ConvertedType = Context.getPointerType(FromPointee); + return true; +} + +bool Sema::IsBlockPointerConversion(QualType FromType, QualType ToType, + QualType& ConvertedType) { + QualType ToPointeeType; + if (const BlockPointerType *ToBlockPtr = + ToType->getAs()) + ToPointeeType = ToBlockPtr->getPointeeType(); + else + return false; + + QualType FromPointeeType; + if (const BlockPointerType *FromBlockPtr = + FromType->getAs()) + FromPointeeType = FromBlockPtr->getPointeeType(); + else + return false; + // We have pointer to blocks, check whether the only + // differences in the argument and result types are in Objective-C + // pointer conversions. If so, we permit the conversion. + + const FunctionProtoType *FromFunctionType + = FromPointeeType->getAs(); + const FunctionProtoType *ToFunctionType + = ToPointeeType->getAs(); + + if (!FromFunctionType || !ToFunctionType) + return false; + + if (Context.hasSameType(FromPointeeType, ToPointeeType)) + return true; + + // Perform the quick checks that will tell us whether these + // function types are obviously different. + if (FromFunctionType->getNumArgs() != ToFunctionType->getNumArgs() || + FromFunctionType->isVariadic() != ToFunctionType->isVariadic()) + return false; + + FunctionType::ExtInfo FromEInfo = FromFunctionType->getExtInfo(); + FunctionType::ExtInfo ToEInfo = ToFunctionType->getExtInfo(); + if (FromEInfo != ToEInfo) + return false; + + bool IncompatibleObjC = false; + if (Context.hasSameType(FromFunctionType->getResultType(), + ToFunctionType->getResultType())) { + // Okay, the types match exactly. Nothing to do. + } else { + QualType RHS = FromFunctionType->getResultType(); + QualType LHS = ToFunctionType->getResultType(); + if ((!getLangOpts().CPlusPlus || !RHS->isRecordType()) && + !RHS.hasQualifiers() && LHS.hasQualifiers()) + LHS = LHS.getUnqualifiedType(); + + if (Context.hasSameType(RHS,LHS)) { + // OK exact match. + } else if (isObjCPointerConversion(RHS, LHS, + ConvertedType, IncompatibleObjC)) { + if (IncompatibleObjC) + return false; + // Okay, we have an Objective-C pointer conversion. + } + else + return false; + } + + // Check argument types. + for (unsigned ArgIdx = 0, NumArgs = FromFunctionType->getNumArgs(); + ArgIdx != NumArgs; ++ArgIdx) { + IncompatibleObjC = false; + QualType FromArgType = FromFunctionType->getArgType(ArgIdx); + QualType ToArgType = ToFunctionType->getArgType(ArgIdx); + if (Context.hasSameType(FromArgType, ToArgType)) { + // Okay, the types match exactly. Nothing to do. + } else if (isObjCPointerConversion(ToArgType, FromArgType, + ConvertedType, IncompatibleObjC)) { + if (IncompatibleObjC) + return false; + // Okay, we have an Objective-C pointer conversion. + } else + // Argument types are too different. Abort. + return false; + } + if (LangOpts.ObjCAutoRefCount && + !Context.FunctionTypesMatchOnNSConsumedAttrs(FromFunctionType, + ToFunctionType)) + return false; + + ConvertedType = ToType; + return true; +} + +enum { + ft_default, + ft_different_class, + ft_parameter_arity, + ft_parameter_mismatch, + ft_return_type, + ft_qualifer_mismatch +}; + +/// HandleFunctionTypeMismatch - Gives diagnostic information for differeing +/// function types. Catches different number of parameter, mismatch in +/// parameter types, and different return types. +void Sema::HandleFunctionTypeMismatch(PartialDiagnostic &PDiag, + QualType FromType, QualType ToType) { + // If either type is not valid, include no extra info. + if (FromType.isNull() || ToType.isNull()) { + PDiag << ft_default; + return; + } + + // Get the function type from the pointers. + if (FromType->isMemberPointerType() && ToType->isMemberPointerType()) { + const MemberPointerType *FromMember = FromType->getAs(), + *ToMember = ToType->getAs(); + if (FromMember->getClass() != ToMember->getClass()) { + PDiag << ft_different_class << QualType(ToMember->getClass(), 0) + << QualType(FromMember->getClass(), 0); + return; + } + FromType = FromMember->getPointeeType(); + ToType = ToMember->getPointeeType(); + } + + if (FromType->isPointerType()) + FromType = FromType->getPointeeType(); + if (ToType->isPointerType()) + ToType = ToType->getPointeeType(); + + // Remove references. + FromType = FromType.getNonReferenceType(); + ToType = ToType.getNonReferenceType(); + + // Don't print extra info for non-specialized template functions. + if (FromType->isInstantiationDependentType() && + !FromType->getAs()) { + PDiag << ft_default; + return; + } + + // No extra info for same types. + if (Context.hasSameType(FromType, ToType)) { + PDiag << ft_default; + return; + } + + const FunctionProtoType *FromFunction = FromType->getAs(), + *ToFunction = ToType->getAs(); + + // Both types need to be function types. + if (!FromFunction || !ToFunction) { + PDiag << ft_default; + return; + } + + if (FromFunction->getNumArgs() != ToFunction->getNumArgs()) { + PDiag << ft_parameter_arity << ToFunction->getNumArgs() + << FromFunction->getNumArgs(); + return; + } + + // Handle different parameter types. + unsigned ArgPos; + if (!FunctionArgTypesAreEqual(FromFunction, ToFunction, &ArgPos)) { + PDiag << ft_parameter_mismatch << ArgPos + 1 + << ToFunction->getArgType(ArgPos) + << FromFunction->getArgType(ArgPos); + return; + } + + // Handle different return type. + if (!Context.hasSameType(FromFunction->getResultType(), + ToFunction->getResultType())) { + PDiag << ft_return_type << ToFunction->getResultType() + << FromFunction->getResultType(); + return; + } + + unsigned FromQuals = FromFunction->getTypeQuals(), + ToQuals = ToFunction->getTypeQuals(); + if (FromQuals != ToQuals) { + PDiag << ft_qualifer_mismatch << ToQuals << FromQuals; + return; + } + + // Unable to find a difference, so add no extra info. + PDiag << ft_default; +} + +/// FunctionArgTypesAreEqual - This routine checks two function proto types +/// for equality of their argument types. Caller has already checked that +/// they have same number of arguments. This routine assumes that Objective-C +/// pointer types which only differ in their protocol qualifiers are equal. +/// If the parameters are different, ArgPos will have the the parameter index +/// of the first different parameter. +bool Sema::FunctionArgTypesAreEqual(const FunctionProtoType *OldType, + const FunctionProtoType *NewType, + unsigned *ArgPos) { + if (!getLangOpts().ObjC1) { + for (FunctionProtoType::arg_type_iterator O = OldType->arg_type_begin(), + N = NewType->arg_type_begin(), + E = OldType->arg_type_end(); O && (O != E); ++O, ++N) { + if (!Context.hasSameType(*O, *N)) { + if (ArgPos) *ArgPos = O - OldType->arg_type_begin(); + return false; + } + } + return true; + } + + for (FunctionProtoType::arg_type_iterator O = OldType->arg_type_begin(), + N = NewType->arg_type_begin(), + E = OldType->arg_type_end(); O && (O != E); ++O, ++N) { + QualType ToType = (*O); + QualType FromType = (*N); + if (!Context.hasSameType(ToType, FromType)) { + if (const PointerType *PTTo = ToType->getAs()) { + if (const PointerType *PTFr = FromType->getAs()) + if ((PTTo->getPointeeType()->isObjCQualifiedIdType() && + PTFr->getPointeeType()->isObjCQualifiedIdType()) || + (PTTo->getPointeeType()->isObjCQualifiedClassType() && + PTFr->getPointeeType()->isObjCQualifiedClassType())) + continue; + } + else if (const ObjCObjectPointerType *PTTo = + ToType->getAs()) { + if (const ObjCObjectPointerType *PTFr = + FromType->getAs()) + if (Context.hasSameUnqualifiedType( + PTTo->getObjectType()->getBaseType(), + PTFr->getObjectType()->getBaseType())) + continue; + } + if (ArgPos) *ArgPos = O - OldType->arg_type_begin(); + return false; + } + } + return true; +} + +/// CheckPointerConversion - Check the pointer conversion from the +/// expression From to the type ToType. This routine checks for +/// ambiguous or inaccessible derived-to-base pointer +/// conversions for which IsPointerConversion has already returned +/// true. It returns true and produces a diagnostic if there was an +/// error, or returns false otherwise. +bool Sema::CheckPointerConversion(Expr *From, QualType ToType, + CastKind &Kind, + CXXCastPath& BasePath, + bool IgnoreBaseAccess) { + QualType FromType = From->getType(); + bool IsCStyleOrFunctionalCast = IgnoreBaseAccess; + + Kind = CK_BitCast; + + if (!IsCStyleOrFunctionalCast && + Context.hasSameUnqualifiedType(From->getType(), Context.BoolTy) && + From->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull)) + DiagRuntimeBehavior(From->getExprLoc(), From, + PDiag(diag::warn_impcast_bool_to_null_pointer) + << ToType << From->getSourceRange()); + + if (const PointerType *ToPtrType = ToType->getAs()) { + if (const PointerType *FromPtrType = FromType->getAs()) { + QualType FromPointeeType = FromPtrType->getPointeeType(), + ToPointeeType = ToPtrType->getPointeeType(); + + if (FromPointeeType->isRecordType() && ToPointeeType->isRecordType() && + !Context.hasSameUnqualifiedType(FromPointeeType, ToPointeeType)) { + // We must have a derived-to-base conversion. Check an + // ambiguous or inaccessible conversion. + if (CheckDerivedToBaseConversion(FromPointeeType, ToPointeeType, + From->getExprLoc(), + From->getSourceRange(), &BasePath, + IgnoreBaseAccess)) + return true; + + // The conversion was successful. + Kind = CK_DerivedToBase; + } + } + } else if (const ObjCObjectPointerType *ToPtrType = + ToType->getAs()) { + if (const ObjCObjectPointerType *FromPtrType = + FromType->getAs()) { + // Objective-C++ conversions are always okay. + // FIXME: We should have a different class of conversions for the + // Objective-C++ implicit conversions. + if (FromPtrType->isObjCBuiltinType() || ToPtrType->isObjCBuiltinType()) + return false; + } else if (FromType->isBlockPointerType()) { + Kind = CK_BlockPointerToObjCPointerCast; + } else { + Kind = CK_CPointerToObjCPointerCast; + } + } else if (ToType->isBlockPointerType()) { + if (!FromType->isBlockPointerType()) + Kind = CK_AnyPointerToBlockPointerCast; + } + + // We shouldn't fall into this case unless it's valid for other + // reasons. + if (From->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) + Kind = CK_NullToPointer; + + return false; +} + +/// IsMemberPointerConversion - Determines whether the conversion of the +/// expression From, which has the (possibly adjusted) type FromType, can be +/// converted to the type ToType via a member pointer conversion (C++ 4.11). +/// If so, returns true and places the converted type (that might differ from +/// ToType in its cv-qualifiers at some level) into ConvertedType. +bool Sema::IsMemberPointerConversion(Expr *From, QualType FromType, + QualType ToType, + bool InOverloadResolution, + QualType &ConvertedType) { + const MemberPointerType *ToTypePtr = ToType->getAs(); + if (!ToTypePtr) + return false; + + // A null pointer constant can be converted to a member pointer (C++ 4.11p1) + if (From->isNullPointerConstant(Context, + InOverloadResolution? Expr::NPC_ValueDependentIsNotNull + : Expr::NPC_ValueDependentIsNull)) { + ConvertedType = ToType; + return true; + } + + // Otherwise, both types have to be member pointers. + const MemberPointerType *FromTypePtr = FromType->getAs(); + if (!FromTypePtr) + return false; + + // A pointer to member of B can be converted to a pointer to member of D, + // where D is derived from B (C++ 4.11p2). + QualType FromClass(FromTypePtr->getClass(), 0); + QualType ToClass(ToTypePtr->getClass(), 0); + + if (!Context.hasSameUnqualifiedType(FromClass, ToClass) && + !RequireCompleteType(From->getLocStart(), ToClass, PDiag()) && + IsDerivedFrom(ToClass, FromClass)) { + ConvertedType = Context.getMemberPointerType(FromTypePtr->getPointeeType(), + ToClass.getTypePtr()); + return true; + } + + return false; +} + +/// CheckMemberPointerConversion - Check the member pointer conversion from the +/// expression From to the type ToType. This routine checks for ambiguous or +/// virtual or inaccessible base-to-derived member pointer conversions +/// for which IsMemberPointerConversion has already returned true. It returns +/// true and produces a diagnostic if there was an error, or returns false +/// otherwise. +bool Sema::CheckMemberPointerConversion(Expr *From, QualType ToType, + CastKind &Kind, + CXXCastPath &BasePath, + bool IgnoreBaseAccess) { + QualType FromType = From->getType(); + const MemberPointerType *FromPtrType = FromType->getAs(); + if (!FromPtrType) { + // This must be a null pointer to member pointer conversion + assert(From->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNull) && + "Expr must be null pointer constant!"); + Kind = CK_NullToMemberPointer; + return false; + } + + const MemberPointerType *ToPtrType = ToType->getAs(); + assert(ToPtrType && "No member pointer cast has a target type " + "that is not a member pointer."); + + QualType FromClass = QualType(FromPtrType->getClass(), 0); + QualType ToClass = QualType(ToPtrType->getClass(), 0); + + // FIXME: What about dependent types? + assert(FromClass->isRecordType() && "Pointer into non-class."); + assert(ToClass->isRecordType() && "Pointer into non-class."); + + CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, + /*DetectVirtual=*/true); + bool DerivationOkay = IsDerivedFrom(ToClass, FromClass, Paths); + assert(DerivationOkay && + "Should not have been called if derivation isn't OK."); + (void)DerivationOkay; + + if (Paths.isAmbiguous(Context.getCanonicalType(FromClass). + getUnqualifiedType())) { + std::string PathDisplayStr = getAmbiguousPathsDisplayString(Paths); + Diag(From->getExprLoc(), diag::err_ambiguous_memptr_conv) + << 0 << FromClass << ToClass << PathDisplayStr << From->getSourceRange(); + return true; + } + + if (const RecordType *VBase = Paths.getDetectedVirtual()) { + Diag(From->getExprLoc(), diag::err_memptr_conv_via_virtual) + << FromClass << ToClass << QualType(VBase, 0) + << From->getSourceRange(); + return true; + } + + if (!IgnoreBaseAccess) + CheckBaseClassAccess(From->getExprLoc(), FromClass, ToClass, + Paths.front(), + diag::err_downcast_from_inaccessible_base); + + // Must be a base to derived member conversion. + BuildBasePathArray(Paths, BasePath); + Kind = CK_BaseToDerivedMemberPointer; + return false; +} + +/// IsQualificationConversion - Determines whether the conversion from +/// an rvalue of type FromType to ToType is a qualification conversion +/// (C++ 4.4). +/// +/// \param ObjCLifetimeConversion Output parameter that will be set to indicate +/// when the qualification conversion involves a change in the Objective-C +/// object lifetime. +bool +Sema::IsQualificationConversion(QualType FromType, QualType ToType, + bool CStyle, bool &ObjCLifetimeConversion) { + FromType = Context.getCanonicalType(FromType); + ToType = Context.getCanonicalType(ToType); + ObjCLifetimeConversion = false; + + // If FromType and ToType are the same type, this is not a + // qualification conversion. + if (FromType.getUnqualifiedType() == ToType.getUnqualifiedType()) + return false; + + // (C++ 4.4p4): + // A conversion can add cv-qualifiers at levels other than the first + // in multi-level pointers, subject to the following rules: [...] + bool PreviousToQualsIncludeConst = true; + bool UnwrappedAnyPointer = false; + while (Context.UnwrapSimilarPointerTypes(FromType, ToType)) { + // 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 + // pointers or pointers-to-members and do it all again + // until there are no more pointers or pointers-to-members left to + // unwrap. + UnwrappedAnyPointer = true; + + Qualifiers FromQuals = FromType.getQualifiers(); + Qualifiers ToQuals = ToType.getQualifiers(); + + // Objective-C ARC: + // Check Objective-C lifetime conversions. + if (FromQuals.getObjCLifetime() != ToQuals.getObjCLifetime() && + UnwrappedAnyPointer) { + if (ToQuals.compatiblyIncludesObjCLifetime(FromQuals)) { + ObjCLifetimeConversion = true; + FromQuals.removeObjCLifetime(); + ToQuals.removeObjCLifetime(); + } else { + // Qualification conversions cannot cast between different + // Objective-C lifetime qualifiers. + return false; + } + } + + // Allow addition/removal of GC attributes but not changing GC attributes. + if (FromQuals.getObjCGCAttr() != ToQuals.getObjCGCAttr() && + (!FromQuals.hasObjCGCAttr() || !ToQuals.hasObjCGCAttr())) { + FromQuals.removeObjCGCAttr(); + ToQuals.removeObjCGCAttr(); + } + + // -- for every j > 0, if const is in cv 1,j then const is in cv + // 2,j, and similarly for volatile. + if (!CStyle && !ToQuals.compatiblyIncludes(FromQuals)) + return false; + + // -- if the cv 1,j and cv 2,j are different, then const is in + // every cv for 0 < k < j. + if (!CStyle && FromQuals.getCVRQualifiers() != ToQuals.getCVRQualifiers() + && !PreviousToQualsIncludeConst) + return false; + + // Keep track of whether all prior cv-qualifiers in the "to" type + // include const. + PreviousToQualsIncludeConst + = PreviousToQualsIncludeConst && ToQuals.hasConst(); + } + + // We are left with FromType and ToType being the pointee types + // after unwrapping the original FromType and ToType the same number + // of types. If we unwrapped any pointers, and if FromType and + // ToType have the same unqualified type (since we checked + // qualifiers above), then this is a qualification conversion. + return UnwrappedAnyPointer && Context.hasSameUnqualifiedType(FromType,ToType); +} + +/// \brief - Determine whether this is a conversion from a scalar type to an +/// atomic type. +/// +/// If successful, updates \c SCS's second and third steps in the conversion +/// sequence to finish the conversion. +static bool tryAtomicConversion(Sema &S, Expr *From, QualType ToType, + bool InOverloadResolution, + StandardConversionSequence &SCS, + bool CStyle) { + const AtomicType *ToAtomic = ToType->getAs(); + if (!ToAtomic) + return false; + + StandardConversionSequence InnerSCS; + if (!IsStandardConversion(S, From, ToAtomic->getValueType(), + InOverloadResolution, InnerSCS, + CStyle, /*AllowObjCWritebackConversion=*/false)) + return false; + + SCS.Second = InnerSCS.Second; + SCS.setToType(1, InnerSCS.getToType(1)); + SCS.Third = InnerSCS.Third; + SCS.QualificationIncludesObjCLifetime + = InnerSCS.QualificationIncludesObjCLifetime; + SCS.setToType(2, InnerSCS.getToType(2)); + return true; +} + +static bool isFirstArgumentCompatibleWithType(ASTContext &Context, + CXXConstructorDecl *Constructor, + QualType Type) { + const FunctionProtoType *CtorType = + Constructor->getType()->getAs(); + if (CtorType->getNumArgs() > 0) { + QualType FirstArg = CtorType->getArgType(0); + if (Context.hasSameUnqualifiedType(Type, FirstArg.getNonReferenceType())) + return true; + } + return false; +} + +static OverloadingResult +IsInitializerListConstructorConversion(Sema &S, Expr *From, QualType ToType, + CXXRecordDecl *To, + UserDefinedConversionSequence &User, + OverloadCandidateSet &CandidateSet, + bool AllowExplicit) { + DeclContext::lookup_iterator Con, ConEnd; + for (llvm::tie(Con, ConEnd) = S.LookupConstructors(To); + Con != ConEnd; ++Con) { + NamedDecl *D = *Con; + DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess()); + + // Find the constructor (which may be a template). + CXXConstructorDecl *Constructor = 0; + FunctionTemplateDecl *ConstructorTmpl + = dyn_cast(D); + if (ConstructorTmpl) + Constructor + = cast(ConstructorTmpl->getTemplatedDecl()); + else + Constructor = cast(D); + + bool Usable = !Constructor->isInvalidDecl() && + S.isInitListConstructor(Constructor) && + (AllowExplicit || !Constructor->isExplicit()); + if (Usable) { + // If the first argument is (a reference to) the target type, + // suppress conversions. + bool SuppressUserConversions = + isFirstArgumentCompatibleWithType(S.Context, Constructor, ToType); + if (ConstructorTmpl) + S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, + /*ExplicitArgs*/ 0, + From, CandidateSet, + SuppressUserConversions); + else + S.AddOverloadCandidate(Constructor, FoundDecl, + From, CandidateSet, + SuppressUserConversions); + } + } + + bool HadMultipleCandidates = (CandidateSet.size() > 1); + + OverloadCandidateSet::iterator Best; + switch (CandidateSet.BestViableFunction(S, From->getLocStart(), Best, true)) { + case OR_Success: { + // Record the standard conversion we used and the conversion function. + CXXConstructorDecl *Constructor = cast(Best->Function); + S.MarkFunctionReferenced(From->getLocStart(), Constructor); + + QualType ThisType = Constructor->getThisType(S.Context); + // Initializer lists don't have conversions as such. + User.Before.setAsIdentityConversion(); + User.HadMultipleCandidates = HadMultipleCandidates; + User.ConversionFunction = Constructor; + User.FoundConversionFunction = Best->FoundDecl; + User.After.setAsIdentityConversion(); + User.After.setFromType(ThisType->getAs()->getPointeeType()); + User.After.setAllToTypes(ToType); + return OR_Success; + } + + case OR_No_Viable_Function: + return OR_No_Viable_Function; + case OR_Deleted: + return OR_Deleted; + case OR_Ambiguous: + return OR_Ambiguous; + } + + llvm_unreachable("Invalid OverloadResult!"); +} + +/// Determines whether there is a user-defined conversion sequence +/// (C++ [over.ics.user]) that converts expression From to the type +/// ToType. If such a conversion exists, User will contain the +/// user-defined conversion sequence that performs such a conversion +/// and this routine will return true. Otherwise, this routine returns +/// false and User is unspecified. +/// +/// \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). +static OverloadingResult +IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, + UserDefinedConversionSequence &User, + OverloadCandidateSet &CandidateSet, + bool AllowExplicit) { + // Whether we will only visit constructors. + bool ConstructorsOnly = false; + + // If the type we are conversion to is a class type, enumerate its + // constructors. + if (const RecordType *ToRecordType = ToType->getAs()) { + // C++ [over.match.ctor]p1: + // When objects of class type are direct-initialized (8.5), or + // copy-initialized from an expression of the same or a + // derived class type (8.5), overload resolution selects the + // constructor. [...] For copy-initialization, the candidate + // 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 (S.Context.hasSameUnqualifiedType(ToType, From->getType()) || + (From->getType()->getAs() && + S.IsDerivedFrom(From->getType(), ToType))) + ConstructorsOnly = true; + + S.RequireCompleteType(From->getLocStart(), ToType, S.PDiag()); + // RequireCompleteType may have returned true due to some invalid decl + // during template instantiation, but ToType may be complete enough now + // to try to recover. + if (ToType->isIncompleteType()) { + // We're not going to find any constructors. + } else if (CXXRecordDecl *ToRecordDecl + = dyn_cast(ToRecordType->getDecl())) { + + Expr **Args = &From; + unsigned NumArgs = 1; + bool ListInitializing = false; + if (InitListExpr *InitList = dyn_cast(From)) { + // But first, see if there is an init-list-contructor that will work. + OverloadingResult Result = IsInitializerListConstructorConversion( + S, From, ToType, ToRecordDecl, User, CandidateSet, AllowExplicit); + if (Result != OR_No_Viable_Function) + return Result; + // Never mind. + CandidateSet.clear(); + + // If we're list-initializing, we pass the individual elements as + // arguments, not the entire list. + Args = InitList->getInits(); + NumArgs = InitList->getNumInits(); + ListInitializing = true; + } + + DeclContext::lookup_iterator Con, ConEnd; + for (llvm::tie(Con, ConEnd) = S.LookupConstructors(ToRecordDecl); + Con != ConEnd; ++Con) { + NamedDecl *D = *Con; + DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess()); + + // Find the constructor (which may be a template). + CXXConstructorDecl *Constructor = 0; + FunctionTemplateDecl *ConstructorTmpl + = dyn_cast(D); + if (ConstructorTmpl) + Constructor + = cast(ConstructorTmpl->getTemplatedDecl()); + else + Constructor = cast(D); + + bool Usable = !Constructor->isInvalidDecl(); + if (ListInitializing) + Usable = Usable && (AllowExplicit || !Constructor->isExplicit()); + else + Usable = Usable &&Constructor->isConvertingConstructor(AllowExplicit); + if (Usable) { + bool SuppressUserConversions = !ConstructorsOnly; + if (SuppressUserConversions && ListInitializing) { + SuppressUserConversions = false; + if (NumArgs == 1) { + // If the first argument is (a reference to) the target type, + // suppress conversions. + SuppressUserConversions = isFirstArgumentCompatibleWithType( + S.Context, Constructor, ToType); + } + } + if (ConstructorTmpl) + S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, + /*ExplicitArgs*/ 0, + llvm::makeArrayRef(Args, NumArgs), + CandidateSet, SuppressUserConversions); + else + // Allow one user-defined conversion when user specifies a + // From->ToType conversion via an static cast (c-style, etc). + S.AddOverloadCandidate(Constructor, FoundDecl, + llvm::makeArrayRef(Args, NumArgs), + CandidateSet, SuppressUserConversions); + } + } + } + } + + // Enumerate conversion functions, if we're allowed to. + if (ConstructorsOnly || isa(From)) { + } 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()) { + if (CXXRecordDecl *FromRecordDecl + = dyn_cast(FromRecordType->getDecl())) { + // Add all of the conversion functions as candidates. + const UnresolvedSetImpl *Conversions + = FromRecordDecl->getVisibleConversionFunctions(); + for (UnresolvedSetImpl::iterator I = Conversions->begin(), + E = Conversions->end(); I != E; ++I) { + DeclAccessPair FoundDecl = I.getPair(); + NamedDecl *D = FoundDecl.getDecl(); + CXXRecordDecl *ActingContext = cast(D->getDeclContext()); + if (isa(D)) + D = cast(D)->getTargetDecl(); + + CXXConversionDecl *Conv; + FunctionTemplateDecl *ConvTemplate; + if ((ConvTemplate = dyn_cast(D))) + Conv = cast(ConvTemplate->getTemplatedDecl()); + else + Conv = cast(D); + + if (AllowExplicit || !Conv->isExplicit()) { + if (ConvTemplate) + S.AddTemplateConversionCandidate(ConvTemplate, FoundDecl, + ActingContext, From, ToType, + CandidateSet); + else + S.AddConversionCandidate(Conv, FoundDecl, ActingContext, + From, ToType, CandidateSet); + } + } + } + } + + bool HadMultipleCandidates = (CandidateSet.size() > 1); + + OverloadCandidateSet::iterator Best; + switch (CandidateSet.BestViableFunction(S, From->getLocStart(), Best, true)) { + case OR_Success: + // Record the standard conversion we used and the conversion function. + if (CXXConstructorDecl *Constructor + = dyn_cast(Best->Function)) { + S.MarkFunctionReferenced(From->getLocStart(), Constructor); + + // 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 (isa(From)) { + // Initializer lists don't have conversions as such. + User.Before.setAsIdentityConversion(); + } else { + if (Best->Conversions[0].isEllipsis()) + User.EllipsisConversion = true; + else { + User.Before = Best->Conversions[0].Standard; + User.EllipsisConversion = false; + } + } + User.HadMultipleCandidates = HadMultipleCandidates; + User.ConversionFunction = Constructor; + User.FoundConversionFunction = Best->FoundDecl; + User.After.setAsIdentityConversion(); + User.After.setFromType(ThisType->getAs()->getPointeeType()); + User.After.setAllToTypes(ToType); + return OR_Success; + } + if (CXXConversionDecl *Conversion + = dyn_cast(Best->Function)) { + S.MarkFunctionReferenced(From->getLocStart(), Conversion); + + // 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.HadMultipleCandidates = HadMultipleCandidates; + User.ConversionFunction = Conversion; + User.FoundConversionFunction = Best->FoundDecl; + 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; + } + llvm_unreachable("Not a constructor or conversion function?"); + + 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; + } + + llvm_unreachable("Invalid OverloadResult!"); +} + +bool +Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) { + ImplicitConversionSequence ICS; + OverloadCandidateSet CandidateSet(From->getExprLoc()); + OverloadingResult OvResult = + IsUserDefinedConversion(*this, From, ToType, ICS.UserDefined, + CandidateSet, false); + if (OvResult == OR_Ambiguous) + Diag(From->getLocStart(), + diag::err_typecheck_ambiguous_condition) + << From->getType() << ToType << From->getSourceRange(); + else if (OvResult == OR_No_Viable_Function && !CandidateSet.empty()) + Diag(From->getLocStart(), + diag::err_typecheck_nonviable_condition) + << From->getType() << ToType << From->getSourceRange(); + else + return false; + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, From); + return true; +} + +/// \brief Compare the user-defined conversion functions or constructors +/// of two user-defined conversion sequences to determine whether any ordering +/// is possible. +static ImplicitConversionSequence::CompareKind +compareConversionFunctions(Sema &S, + FunctionDecl *Function1, + FunctionDecl *Function2) { + if (!S.getLangOpts().ObjC1 || !S.getLangOpts().CPlusPlus0x) + return ImplicitConversionSequence::Indistinguishable; + + // Objective-C++: + // If both conversion functions are implicitly-declared conversions from + // a lambda closure type to a function pointer and a block pointer, + // respectively, always prefer the conversion to a function pointer, + // because the function pointer is more lightweight and is more likely + // to keep code working. + CXXConversionDecl *Conv1 = dyn_cast(Function1); + if (!Conv1) + return ImplicitConversionSequence::Indistinguishable; + + CXXConversionDecl *Conv2 = dyn_cast(Function2); + if (!Conv2) + return ImplicitConversionSequence::Indistinguishable; + + if (Conv1->getParent()->isLambda() && Conv2->getParent()->isLambda()) { + bool Block1 = Conv1->getConversionType()->isBlockPointerType(); + bool Block2 = Conv2->getConversionType()->isBlockPointerType(); + if (Block1 != Block2) + return Block1? ImplicitConversionSequence::Worse + : ImplicitConversionSequence::Better; + } + + return ImplicitConversionSequence::Indistinguishable; +} + +/// 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). +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) + // -- a standard conversion sequence (13.3.3.1.1) is a better + // conversion sequence than a user-defined conversion sequence or + // an ellipsis conversion sequence, and + // -- a user-defined conversion sequence (13.3.3.1.2) is a better + // conversion sequence than an ellipsis conversion sequence + // (13.3.3.1.3). + // + // C++0x [over.best.ics]p10: + // For the purpose of ranking implicit conversion sequences as + // described in 13.3.3.2, the ambiguous conversion sequence is + // treated as a user-defined sequence that is indistinguishable + // from any other user-defined conversion sequence. + if (ICS1.getKindRank() < ICS2.getKindRank()) + return ImplicitConversionSequence::Better; + if (ICS2.getKindRank() < ICS1.getKindRank()) + return ImplicitConversionSequence::Worse; + + // The following checks require both conversion sequences to be of + // the same kind. + if (ICS1.getKind() != ICS2.getKind()) + return ImplicitConversionSequence::Indistinguishable; + + ImplicitConversionSequence::CompareKind Result = + ImplicitConversionSequence::Indistinguishable; + + // Two implicit conversion sequences of the same form are + // indistinguishable conversion sequences unless one of the + // following rules apply: (C++ 13.3.3.2p3): + if (ICS1.isStandard()) + Result = 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 + // they contain the same user-defined conversion function or + // constructor and if the second standard conversion sequence of + // U1 is better than the second standard conversion sequence of + // U2 (C++ 13.3.3.2p3). + if (ICS1.UserDefined.ConversionFunction == + ICS2.UserDefined.ConversionFunction) + Result = CompareStandardConversionSequences(S, + ICS1.UserDefined.After, + ICS2.UserDefined.After); + else + Result = compareConversionFunctions(S, + ICS1.UserDefined.ConversionFunction, + ICS2.UserDefined.ConversionFunction); + } + + // List-initialization sequence L1 is a better conversion sequence than + // list-initialization sequence L2 if L1 converts to std::initializer_list + // for some X and L2 does not. + if (Result == ImplicitConversionSequence::Indistinguishable && + !ICS1.isBad() && + ICS1.isListInitializationSequence() && + ICS2.isListInitializationSequence()) { + if (ICS1.isStdInitializerListElement() && + !ICS2.isStdInitializerListElement()) + return ImplicitConversionSequence::Better; + if (!ICS1.isStdInitializerListElement() && + ICS2.isStdInitializerListElement()) + return ImplicitConversionSequence::Worse; + } + + return Result; +} + +static bool hasSimilarType(ASTContext &Context, QualType T1, QualType T2) { + while (Context.UnwrapSimilarPointerTypes(T1, T2)) { + Qualifiers Quals; + T1 = Context.getUnqualifiedArrayType(T1, Quals); + T2 = Context.getUnqualifiedArrayType(T2, Quals); + } + + return Context.hasSameUnqualifiedType(T1, T2); +} + +// Per 13.3.3.2p3, compare the given standard conversion sequences to +// determine if one is a proper subset of the other. +static ImplicitConversionSequence::CompareKind +compareStandardConversionSubsets(ASTContext &Context, + const StandardConversionSequence& SCS1, + const StandardConversionSequence& SCS2) { + ImplicitConversionSequence::CompareKind Result + = ImplicitConversionSequence::Indistinguishable; + + // the identity conversion sequence is considered to be a subsequence of + // any non-identity conversion sequence + if (SCS1.isIdentityConversion() && !SCS2.isIdentityConversion()) + return ImplicitConversionSequence::Better; + else if (!SCS1.isIdentityConversion() && SCS2.isIdentityConversion()) + return ImplicitConversionSequence::Worse; + + if (SCS1.Second != SCS2.Second) { + if (SCS1.Second == ICK_Identity) + Result = ImplicitConversionSequence::Better; + else if (SCS2.Second == ICK_Identity) + Result = ImplicitConversionSequence::Worse; + else + return ImplicitConversionSequence::Indistinguishable; + } else if (!hasSimilarType(Context, SCS1.getToType(1), SCS2.getToType(1))) + return ImplicitConversionSequence::Indistinguishable; + + if (SCS1.Third == SCS2.Third) { + return Context.hasSameType(SCS1.getToType(2), SCS2.getToType(2))? Result + : ImplicitConversionSequence::Indistinguishable; + } + + if (SCS1.Third == ICK_Identity) + return Result == ImplicitConversionSequence::Worse + ? ImplicitConversionSequence::Indistinguishable + : ImplicitConversionSequence::Better; + + if (SCS2.Third == ICK_Identity) + return Result == ImplicitConversionSequence::Better + ? ImplicitConversionSequence::Indistinguishable + : ImplicitConversionSequence::Worse; + + return ImplicitConversionSequence::Indistinguishable; +} + +/// \brief Determine whether one of the given reference bindings is better +/// than the other based on what kind of bindings they are. +static bool isBetterReferenceBindingKind(const StandardConversionSequence &SCS1, + const StandardConversionSequence &SCS2) { + // C++0x [over.ics.rank]p3b4: + // -- S1 and S2 are reference bindings (8.5.3) and neither refers to an + // implicit object parameter of a non-static member function declared + // without a ref-qualifier, and *either* S1 binds an rvalue reference + // to an rvalue and S2 binds an lvalue reference *or S1 binds an + // lvalue reference to a function lvalue and S2 binds an rvalue + // reference*. + // + // FIXME: Rvalue references. We're going rogue with the above edits, + // because the semantics in the current C++0x working paper (N3225 at the + // time of this writing) break the standard definition of std::forward + // and std::reference_wrapper when dealing with references to functions. + // Proposed wording changes submitted to CWG for consideration. + if (SCS1.BindsImplicitObjectArgumentWithoutRefQualifier || + SCS2.BindsImplicitObjectArgumentWithoutRefQualifier) + return false; + + return (!SCS1.IsLvalueReference && SCS1.BindsToRvalue && + SCS2.IsLvalueReference) || + (SCS1.IsLvalueReference && SCS1.BindsToFunctionLvalue && + !SCS2.IsLvalueReference); +} + +/// 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). +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): + + // -- S1 is a proper subsequence of S2 (comparing the conversion + // sequences in the canonical form defined by 13.3.3.1.1, + // excluding any Lvalue Transformation; the identity conversion + // sequence is considered to be a subsequence of any + // non-identity conversion sequence) or, if not that, + if (ImplicitConversionSequence::CompareKind CK + = compareStandardConversionSubsets(S.Context, SCS1, SCS2)) + return CK; + + // -- the rank of S1 is better than the rank of S2 (by the rules + // defined below), or, if not that, + ImplicitConversionRank Rank1 = SCS1.getRank(); + ImplicitConversionRank Rank2 = SCS2.getRank(); + if (Rank1 < Rank2) + return ImplicitConversionSequence::Better; + else if (Rank2 < Rank1) + return ImplicitConversionSequence::Worse; + + // (C++ 13.3.3.2p4): Two conversion sequences with the same rank + // are indistinguishable unless one of the following rules + // applies: + + // A conversion that is not a conversion of a pointer, or + // pointer to member, to bool is better than another conversion + // that is such a conversion. + if (SCS1.isPointerConversionToBool() != SCS2.isPointerConversionToBool()) + return SCS2.isPointerConversionToBool() + ? ImplicitConversionSequence::Better + : ImplicitConversionSequence::Worse; + + // C++ [over.ics.rank]p4b2: + // + // If class B is derived directly or indirectly from class A, + // conversion of B* to A* is better than conversion of B* to + // void*, and conversion of A* to void* is better than conversion + // of B* to void*. + bool SCS1ConvertsToVoid + = SCS1.isPointerConversionToVoidPointer(S.Context); + bool SCS2ConvertsToVoid + = 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. + return SCS2ConvertsToVoid ? ImplicitConversionSequence::Better + : ImplicitConversionSequence::Worse; + } else if (!SCS1ConvertsToVoid && !SCS2ConvertsToVoid) { + // Neither conversion sequence converts to a void pointer; compare + // their derived-to-base conversions. + if (ImplicitConversionSequence::CompareKind DerivedCK + = CompareDerivedToBaseConversions(S, SCS1, SCS2)) + return DerivedCK; + } else if (SCS1ConvertsToVoid && SCS2ConvertsToVoid && + !S.Context.hasSameType(SCS1.getFromType(), SCS2.getFromType())) { + // Both conversion sequences are conversions to void + // pointers. Compare the source types to determine if there's an + // inheritance relationship in their sources. + QualType FromType1 = SCS1.getFromType(); + QualType FromType2 = SCS2.getFromType(); + + // 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 = S.Context.getArrayDecayedType(FromType1); + if (SCS2.First == ICK_Array_To_Pointer) + FromType2 = S.Context.getArrayDecayedType(FromType2); + + QualType FromPointee1 = FromType1->getPointeeType().getUnqualifiedType(); + QualType FromPointee2 = FromType2->getPointeeType().getUnqualifiedType(); + + if (S.IsDerivedFrom(FromPointee2, FromPointee1)) + return ImplicitConversionSequence::Better; + else if (S.IsDerivedFrom(FromPointee1, FromPointee2)) + return ImplicitConversionSequence::Worse; + + // Objective-C++: If one interface is more specific than the + // other, it is the better one. + const ObjCObjectPointerType* FromObjCPtr1 + = FromType1->getAs(); + const ObjCObjectPointerType* FromObjCPtr2 + = FromType2->getAs(); + if (FromObjCPtr1 && FromObjCPtr2) { + bool AssignLeft = S.Context.canAssignObjCInterfaces(FromObjCPtr1, + FromObjCPtr2); + bool AssignRight = S.Context.canAssignObjCInterfaces(FromObjCPtr2, + FromObjCPtr1); + if (AssignLeft != AssignRight) { + return AssignLeft? ImplicitConversionSequence::Better + : ImplicitConversionSequence::Worse; + } + } + } + + // Compare based on qualification conversions (C++ 13.3.3.2p3, + // bullet 3). + if (ImplicitConversionSequence::CompareKind QualCK + = CompareQualificationConversions(S, SCS1, SCS2)) + return QualCK; + + if (SCS1.ReferenceBinding && SCS2.ReferenceBinding) { + // Check for a better reference binding based on the kind of bindings. + if (isBetterReferenceBindingKind(SCS1, SCS2)) + return ImplicitConversionSequence::Better; + else if (isBetterReferenceBindingKind(SCS2, SCS1)) + return ImplicitConversionSequence::Worse; + + // C++ [over.ics.rank]p3b4: + // -- S1 and S2 are reference bindings (8.5.3), and the types to + // which the references refer are the same type except for + // top-level cv-qualifiers, and the type to which the reference + // initialized by S2 refers is more cv-qualified than the type + // to which the reference initialized by S1 refers. + QualType T1 = SCS1.getToType(2); + QualType T2 = SCS2.getToType(2); + T1 = S.Context.getCanonicalType(T1); + T2 = S.Context.getCanonicalType(T2); + Qualifiers T1Quals, T2Quals; + QualType UnqualT1 = S.Context.getUnqualifiedArrayType(T1, T1Quals); + QualType UnqualT2 = S.Context.getUnqualifiedArrayType(T2, T2Quals); + if (UnqualT1 == UnqualT2) { + // Objective-C++ ARC: If the references refer to objects with different + // lifetimes, prefer bindings that don't change lifetime. + if (SCS1.ObjCLifetimeConversionBinding != + SCS2.ObjCLifetimeConversionBinding) { + return SCS1.ObjCLifetimeConversionBinding + ? ImplicitConversionSequence::Worse + : ImplicitConversionSequence::Better; + } + + // If the type is an array type, promote the element qualifiers to the + // type for comparison. + if (isa(T1) && T1Quals) + T1 = S.Context.getQualifiedType(UnqualT1, T1Quals); + if (isa(T2) && T2Quals) + T2 = S.Context.getQualifiedType(UnqualT2, T2Quals); + if (T2.isMoreQualifiedThan(T1)) + return ImplicitConversionSequence::Better; + else if (T1.isMoreQualifiedThan(T2)) + return ImplicitConversionSequence::Worse; + } + } + + // In Microsoft mode, prefer an integral conversion to a + // floating-to-integral conversion if the integral conversion + // is between types of the same size. + // For example: + // void f(float); + // void f(int); + // int main { + // long a; + // f(a); + // } + // Here, MSVC will call f(int) instead of generating a compile error + // as clang will do in standard mode. + if (S.getLangOpts().MicrosoftMode && + SCS1.Second == ICK_Integral_Conversion && + SCS2.Second == ICK_Floating_Integral && + S.Context.getTypeSize(SCS1.getFromType()) == + S.Context.getTypeSize(SCS1.getToType(2))) + return ImplicitConversionSequence::Better; + + return ImplicitConversionSequence::Indistinguishable; +} + +/// CompareQualificationConversions - Compares two standard conversion +/// sequences to determine whether they can be ranked based on their +/// qualification conversions (C++ 13.3.3.2p3 bullet 3). +ImplicitConversionSequence::CompareKind +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 + // cv-qualification signature of type T1 is a proper subset of + // the cv-qualification signature of type T2, and S1 is not the + // deprecated string literal array-to-pointer conversion (4.2). + if (SCS1.First != SCS2.First || SCS1.Second != SCS2.Second || + SCS1.Third != SCS2.Third || SCS1.Third != ICK_Qualification) + return ImplicitConversionSequence::Indistinguishable; + + // FIXME: the example in the standard doesn't use a qualification + // conversion (!) + QualType T1 = SCS1.getToType(2); + QualType T2 = SCS2.getToType(2); + T1 = S.Context.getCanonicalType(T1); + T2 = S.Context.getCanonicalType(T2); + Qualifiers T1Quals, 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. + if (UnqualT1 == UnqualT2) + return ImplicitConversionSequence::Indistinguishable; + + // If the type is an array type, promote the element qualifiers to the type + // for comparison. + if (isa(T1) && T1Quals) + T1 = S.Context.getQualifiedType(UnqualT1, T1Quals); + if (isa(T2) && T2Quals) + T2 = S.Context.getQualifiedType(UnqualT2, T2Quals); + + ImplicitConversionSequence::CompareKind Result + = ImplicitConversionSequence::Indistinguishable; + + // Objective-C++ ARC: + // Prefer qualification conversions not involving a change in lifetime + // to qualification conversions that do not change lifetime. + if (SCS1.QualificationIncludesObjCLifetime != + SCS2.QualificationIncludesObjCLifetime) { + Result = SCS1.QualificationIncludesObjCLifetime + ? ImplicitConversionSequence::Worse + : ImplicitConversionSequence::Better; + } + + 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 + // pointers or pointers-to-members and do it all again + // until there are no more pointers or pointers-to-members left + // to unwrap. This essentially mimics what + // IsQualificationConversion does, but here we're checking for a + // strict subset of qualifiers. + if (T1.getCVRQualifiers() == T2.getCVRQualifiers()) + // The qualifiers are the same, so this doesn't tell us anything + // about how the sequences rank. + ; + else if (T2.isMoreQualifiedThan(T1)) { + // T1 has fewer qualifiers, so it could be the better sequence. + if (Result == ImplicitConversionSequence::Worse) + // Neither has qualifiers that are a subset of the other's + // qualifiers. + return ImplicitConversionSequence::Indistinguishable; + + Result = ImplicitConversionSequence::Better; + } else if (T1.isMoreQualifiedThan(T2)) { + // T2 has fewer qualifiers, so it could be the better sequence. + if (Result == ImplicitConversionSequence::Better) + // Neither has qualifiers that are a subset of the other's + // qualifiers. + return ImplicitConversionSequence::Indistinguishable; + + Result = ImplicitConversionSequence::Worse; + } else { + // Qualifiers are disjoint. + return ImplicitConversionSequence::Indistinguishable; + } + + // If the types after this point are equivalent, we're done. + if (S.Context.hasSameUnqualifiedType(T1, T2)) + break; + } + + // Check that the winning standard conversion sequence isn't using + // the deprecated string literal array to pointer conversion. + switch (Result) { + case ImplicitConversionSequence::Better: + if (SCS1.DeprecatedStringLiteralToCharPtr) + Result = ImplicitConversionSequence::Indistinguishable; + break; + + case ImplicitConversionSequence::Indistinguishable: + break; + + case ImplicitConversionSequence::Worse: + if (SCS2.DeprecatedStringLiteralToCharPtr) + Result = ImplicitConversionSequence::Indistinguishable; + break; + } + + return Result; +} + +/// CompareDerivedToBaseConversions - Compares two standard conversion +/// sequences to determine whether they can be ranked based on their +/// various kinds of derived-to-base conversions (C++ +/// [over.ics.rank]p4b3). As part of these checks, we also look at +/// conversions between Objective-C interface types. +ImplicitConversionSequence::CompareKind +CompareDerivedToBaseConversions(Sema &S, + const StandardConversionSequence& SCS1, + const StandardConversionSequence& SCS2) { + QualType FromType1 = SCS1.getFromType(); + QualType ToType1 = SCS1.getToType(1); + QualType FromType2 = SCS2.getFromType(); + QualType ToType2 = SCS2.getToType(1); + + // 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 = S.Context.getArrayDecayedType(FromType1); + if (SCS2.First == ICK_Array_To_Pointer) + FromType2 = S.Context.getArrayDecayedType(FromType2); + + // Canonicalize all of the types. + 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: + // + // If class B is derived directly or indirectly from class A and + // class C is derived directly or indirectly from B, + // + // Compare based on pointer conversions. + if (SCS1.Second == ICK_Pointer_Conversion && + SCS2.Second == ICK_Pointer_Conversion && + /*FIXME: Remove if Objective-C id conversions get their own rank*/ + FromType1->isPointerType() && FromType2->isPointerType() && + ToType1->isPointerType() && ToType2->isPointerType()) { + QualType FromPointee1 + = FromType1->getAs()->getPointeeType().getUnqualifiedType(); + QualType ToPointee1 + = ToType1->getAs()->getPointeeType().getUnqualifiedType(); + QualType FromPointee2 + = FromType2->getAs()->getPointeeType().getUnqualifiedType(); + QualType ToPointee2 + = ToType2->getAs()->getPointeeType().getUnqualifiedType(); + + // -- conversion of C* to B* is better than conversion of C* to A*, + if (FromPointee1 == FromPointee2 && ToPointee1 != ToPointee2) { + if (S.IsDerivedFrom(ToPointee1, ToPointee2)) + return ImplicitConversionSequence::Better; + else if (S.IsDerivedFrom(ToPointee2, ToPointee1)) + return ImplicitConversionSequence::Worse; + } + + // -- conversion of B* to A* is better than conversion of C* to A*, + if (FromPointee1 != FromPointee2 && ToPointee1 == ToPointee2) { + if (S.IsDerivedFrom(FromPointee2, FromPointee1)) + return ImplicitConversionSequence::Better; + else if (S.IsDerivedFrom(FromPointee1, FromPointee2)) + return ImplicitConversionSequence::Worse; + } + } else if (SCS1.Second == ICK_Pointer_Conversion && + SCS2.Second == ICK_Pointer_Conversion) { + const ObjCObjectPointerType *FromPtr1 + = FromType1->getAs(); + const ObjCObjectPointerType *FromPtr2 + = FromType2->getAs(); + const ObjCObjectPointerType *ToPtr1 + = ToType1->getAs(); + const ObjCObjectPointerType *ToPtr2 + = ToType2->getAs(); + + if (FromPtr1 && FromPtr2 && ToPtr1 && ToPtr2) { + // Apply the same conversion ranking rules for Objective-C pointer types + // that we do for C++ pointers to class types. However, we employ the + // Objective-C pseudo-subtyping relationship used for assignment of + // Objective-C pointer types. + bool FromAssignLeft + = S.Context.canAssignObjCInterfaces(FromPtr1, FromPtr2); + bool FromAssignRight + = S.Context.canAssignObjCInterfaces(FromPtr2, FromPtr1); + bool ToAssignLeft + = S.Context.canAssignObjCInterfaces(ToPtr1, ToPtr2); + bool ToAssignRight + = S.Context.canAssignObjCInterfaces(ToPtr2, ToPtr1); + + // A conversion to an a non-id object pointer type or qualified 'id' + // type is better than a conversion to 'id'. + if (ToPtr1->isObjCIdType() && + (ToPtr2->isObjCQualifiedIdType() || ToPtr2->getInterfaceDecl())) + return ImplicitConversionSequence::Worse; + if (ToPtr2->isObjCIdType() && + (ToPtr1->isObjCQualifiedIdType() || ToPtr1->getInterfaceDecl())) + return ImplicitConversionSequence::Better; + + // A conversion to a non-id object pointer type is better than a + // conversion to a qualified 'id' type + if (ToPtr1->isObjCQualifiedIdType() && ToPtr2->getInterfaceDecl()) + return ImplicitConversionSequence::Worse; + if (ToPtr2->isObjCQualifiedIdType() && ToPtr1->getInterfaceDecl()) + return ImplicitConversionSequence::Better; + + // A conversion to an a non-Class object pointer type or qualified 'Class' + // type is better than a conversion to 'Class'. + if (ToPtr1->isObjCClassType() && + (ToPtr2->isObjCQualifiedClassType() || ToPtr2->getInterfaceDecl())) + return ImplicitConversionSequence::Worse; + if (ToPtr2->isObjCClassType() && + (ToPtr1->isObjCQualifiedClassType() || ToPtr1->getInterfaceDecl())) + return ImplicitConversionSequence::Better; + + // A conversion to a non-Class object pointer type is better than a + // conversion to a qualified 'Class' type. + if (ToPtr1->isObjCQualifiedClassType() && ToPtr2->getInterfaceDecl()) + return ImplicitConversionSequence::Worse; + if (ToPtr2->isObjCQualifiedClassType() && ToPtr1->getInterfaceDecl()) + return ImplicitConversionSequence::Better; + + // -- "conversion of C* to B* is better than conversion of C* to A*," + if (S.Context.hasSameType(FromType1, FromType2) && + !FromPtr1->isObjCIdType() && !FromPtr1->isObjCClassType() && + (ToAssignLeft != ToAssignRight)) + return ToAssignLeft? ImplicitConversionSequence::Worse + : ImplicitConversionSequence::Better; + + // -- "conversion of B* to A* is better than conversion of C* to A*," + if (S.Context.hasSameUnqualifiedType(ToType1, ToType2) && + (FromAssignLeft != FromAssignRight)) + return FromAssignLeft? ImplicitConversionSequence::Better + : ImplicitConversionSequence::Worse; + } + } + + // Ranking of member-pointer types. + if (SCS1.Second == ICK_Pointer_Member && SCS2.Second == ICK_Pointer_Member && + FromType1->isMemberPointerType() && FromType2->isMemberPointerType() && + ToType1->isMemberPointerType() && ToType2->isMemberPointerType()) { + const MemberPointerType * FromMemPointer1 = + FromType1->getAs(); + const MemberPointerType * ToMemPointer1 = + ToType1->getAs(); + const MemberPointerType * FromMemPointer2 = + FromType2->getAs(); + const MemberPointerType * ToMemPointer2 = + ToType2->getAs(); + const Type *FromPointeeType1 = FromMemPointer1->getClass(); + const Type *ToPointeeType1 = ToMemPointer1->getClass(); + const Type *FromPointeeType2 = FromMemPointer2->getClass(); + const Type *ToPointeeType2 = ToMemPointer2->getClass(); + QualType FromPointee1 = QualType(FromPointeeType1, 0).getUnqualifiedType(); + QualType ToPointee1 = QualType(ToPointeeType1, 0).getUnqualifiedType(); + QualType FromPointee2 = QualType(FromPointeeType2, 0).getUnqualifiedType(); + 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 (S.IsDerivedFrom(ToPointee1, ToPointee2)) + return ImplicitConversionSequence::Worse; + 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 (S.IsDerivedFrom(FromPointee1, FromPointee2)) + return ImplicitConversionSequence::Better; + else if (S.IsDerivedFrom(FromPointee2, FromPointee1)) + return ImplicitConversionSequence::Worse; + } + } + + if (SCS1.Second == ICK_Derived_To_Base) { + // -- conversion of C to B is better than conversion of C to A, + // -- 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 (S.Context.hasSameUnqualifiedType(FromType1, FromType2) && + !S.Context.hasSameUnqualifiedType(ToType1, ToType2)) { + if (S.IsDerivedFrom(ToType1, ToType2)) + return ImplicitConversionSequence::Better; + else if (S.IsDerivedFrom(ToType2, ToType1)) + return ImplicitConversionSequence::Worse; + } + + // -- conversion of B to A is better than conversion of C to A. + // -- 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 (!S.Context.hasSameUnqualifiedType(FromType1, FromType2) && + S.Context.hasSameUnqualifiedType(ToType1, ToType2)) { + if (S.IsDerivedFrom(FromType2, FromType1)) + return ImplicitConversionSequence::Better; + else if (S.IsDerivedFrom(FromType1, FromType2)) + return ImplicitConversionSequence::Worse; + } + } + + return ImplicitConversionSequence::Indistinguishable; +} + +/// CompareReferenceRelationship - Compare the two types T1 and T2 to +/// determine whether they are reference-related, +/// reference-compatible, reference-compatible with added +/// qualification, or incompatible, for use in C++ initialization by +/// reference (C++ [dcl.ref.init]p4). Neither type can be a reference +/// type, and the first type (T1) is the pointee type of the reference +/// type being initialized. +Sema::ReferenceCompareResult +Sema::CompareReferenceRelationship(SourceLocation Loc, + QualType OrigT1, QualType OrigT2, + bool &DerivedToBase, + bool &ObjCConversion, + bool &ObjCLifetimeConversion) { + assert(!OrigT1->isReferenceType() && + "T1 must be the pointee type of the reference type"); + assert(!OrigT2->isReferenceType() && "T2 cannot be a reference type"); + + QualType T1 = Context.getCanonicalType(OrigT1); + QualType T2 = Context.getCanonicalType(OrigT2); + Qualifiers T1Quals, T2Quals; + QualType UnqualT1 = Context.getUnqualifiedArrayType(T1, T1Quals); + QualType UnqualT2 = Context.getUnqualifiedArrayType(T2, T2Quals); + + // C++ [dcl.init.ref]p4: + // 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. + DerivedToBase = false; + ObjCConversion = false; + ObjCLifetimeConversion = 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; + + // At this point, we know that T1 and T2 are reference-related (at + // least). + + // 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); + if (isa(T2) && T2Quals) + T2 = Context.getQualifiedType(UnqualT2, T2Quals); + + // C++ [dcl.init.ref]p4: + // "cv1 T1" is reference-compatible with "cv2 T2" if T1 is + // reference-related to T2 and cv1 is the same cv-qualification + // as, or greater cv-qualification than, cv2. For purposes of + // overload resolution, cases for which cv1 is greater + // cv-qualification than cv2 are identified as + // reference-compatible with added qualification (see 13.3.3.2). + // + // Note that we also require equivalence of Objective-C GC and address-space + // qualifiers when performing these computations, so that e.g., an int in + // address space 1 is not reference-compatible with an int in address + // space 2. + if (T1Quals.getObjCLifetime() != T2Quals.getObjCLifetime() && + T1Quals.compatiblyIncludesObjCLifetime(T2Quals)) { + T1Quals.removeObjCLifetime(); + T2Quals.removeObjCLifetime(); + ObjCLifetimeConversion = true; + } + + if (T1Quals == T2Quals) + return Ref_Compatible; + else if (T1Quals.compatiblyIncludes(T2Quals)) + return Ref_Compatible_With_Added_Qualification; + else + return Ref_Related; +} + +/// \brief Look for a user-defined conversion to an value reference-compatible +/// with DeclType. Return true if something definite is found. +static bool +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()); + + OverloadCandidateSet CandidateSet(DeclLoc); + const UnresolvedSetImpl *Conversions + = T2RecordDecl->getVisibleConversionFunctions(); + for (UnresolvedSetImpl::iterator I = Conversions->begin(), + E = Conversions->end(); I != E; ++I) { + NamedDecl *D = *I; + CXXRecordDecl *ActingDC = cast(D->getDeclContext()); + if (isa(D)) + D = cast(D)->getTargetDecl(); + + FunctionTemplateDecl *ConvTemplate + = dyn_cast(D); + CXXConversionDecl *Conv; + if (ConvTemplate) + Conv = cast(ConvTemplate->getTemplatedDecl()); + else + Conv = cast(D); + + // 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; + bool ObjCLifetimeConversion = false; + + // If we are initializing an rvalue reference, don't permit conversion + // functions that return lvalues. + if (!ConvTemplate && DeclType->isRValueReferenceType()) { + const ReferenceType *RefType + = Conv->getConversionType()->getAs(); + if (RefType && !RefType->getPointeeType()->isFunctionType()) + continue; + } + + if (!ConvTemplate && + S.CompareReferenceRelationship( + DeclLoc, + Conv->getConversionType().getNonReferenceType() + .getUnqualifiedType(), + DeclType.getNonReferenceType().getUnqualifiedType(), + DerivedToBase, ObjCConversion, ObjCLifetimeConversion) == + 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, DeclType, CandidateSet); + else + S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Init, + DeclType, CandidateSet); + } + + bool HadMultipleCandidates = (CandidateSet.size() > 1); + + OverloadCandidateSet::iterator Best; + switch (CandidateSet.BestViableFunction(S, DeclLoc, Best, true)) { + case OR_Success: + // C++ [over.ics.ref]p1: + // + // [...] If the parameter binds directly to the result of + // applying a conversion function to the argument + // expression, the implicit conversion sequence is a + // user-defined conversion sequence (13.3.3.1.2), with the + // second standard conversion sequence either an identity + // conversion or, if the conversion function returns an + // entity of a type that is a derived class of the parameter + // type, a derived-to-base Conversion. + if (!Best->FinalConversion.DirectBinding) + return false; + + if (Best->Function) + S.MarkFunctionReferenced(DeclLoc, Best->Function); + ICS.setUserDefined(); + ICS.UserDefined.Before = Best->Conversions[0].Standard; + ICS.UserDefined.After = Best->FinalConversion; + ICS.UserDefined.HadMultipleCandidates = HadMultipleCandidates; + ICS.UserDefined.ConversionFunction = Best->Function; + ICS.UserDefined.FoundConversionFunction = Best->FoundDecl; + ICS.UserDefined.EllipsisConversion = false; + assert(ICS.UserDefined.After.ReferenceBinding && + ICS.UserDefined.After.DirectBinding && + "Expected a direct reference binding!"); + return true; + + case OR_Ambiguous: + ICS.setAmbiguous(); + for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(); + Cand != CandidateSet.end(); ++Cand) + if (Cand->Viable) + ICS.Ambiguous.addConversion(Cand->Function); + return true; + + case OR_No_Viable_Function: + case OR_Deleted: + // There was no suitable conversion, or we found a deleted + // conversion; continue with other checks. + return false; + } + + llvm_unreachable("Invalid OverloadResult!"); +} + +/// \brief Compute an implicit conversion sequence for reference +/// initialization. +static ImplicitConversionSequence +TryReferenceInit(Sema &S, Expr *Init, QualType DeclType, + SourceLocation DeclLoc, + bool SuppressUserConversions, + bool AllowExplicit) { + assert(DeclType->isReferenceType() && "Reference init needs a reference"); + + // Most paths end in a failed conversion. + ImplicitConversionSequence ICS; + ICS.setBad(BadConversionSequence::no_conversion, Init, DeclType); + + QualType T1 = DeclType->getAs()->getPointeeType(); + QualType T2 = Init->getType(); + + // If the initializer is the address of an overloaded function, try + // to resolve the overloaded function. If all goes well, T2 is the + // type of the resulting function. + if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy) { + DeclAccessPair Found; + if (FunctionDecl *Fn = S.ResolveAddressOfOverloadedFunction(Init, DeclType, + false, Found)) + T2 = Fn->getType(); + } + + // Compute some basic properties of the types and the initializer. + bool isRValRef = DeclType->isRValueReferenceType(); + bool DerivedToBase = false; + bool ObjCConversion = false; + bool ObjCLifetimeConversion = false; + Expr::Classification InitCategory = Init->Classify(S.Context); + Sema::ReferenceCompareResult RefRelationship + = S.CompareReferenceRelationship(DeclLoc, T1, T2, DerivedToBase, + ObjCConversion, ObjCLifetimeConversion); + + + // C++0x [dcl.init.ref]p5: + // A reference to type "cv1 T1" is initialized by an expression + // of type "cv2 T2" as follows: + + // -- If reference is an lvalue reference and the initializer expression + if (!isRValRef) { + // -- is an lvalue (but is not a bit-field), and "cv1 T1" is + // reference-compatible with "cv2 T2," or + // + // Per C++ [over.ics.ref]p4, we don't check the bit-field property here. + if (InitCategory.isLValue() && + RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification) { + // C++ [over.ics.ref]p1: + // When a parameter of reference type binds directly (8.5.3) + // to an argument expression, the implicit conversion sequence + // is the identity conversion, unless the argument expression + // has a type that is a derived class of the parameter type, + // in which case the implicit conversion sequence is a + // derived-to-base Conversion (13.3.3.1). + 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 = true; + ICS.Standard.IsLvalueReference = !isRValRef; + ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType(); + ICS.Standard.BindsToRvalue = false; + ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false; + ICS.Standard.ObjCLifetimeConversionBinding = ObjCLifetimeConversion; + ICS.Standard.CopyConstructor = 0; + + // Nothing more to do: the inaccessibility/ambiguity check for + // derived-to-base conversions is suppressed when we're + // computing the implicit conversion sequence (C++ + // [over.best.ics]p2). + return ICS; + } + + // -- has a class type (i.e., T2 is a class type), where T1 is + // not reference-related to T2, and can be implicitly + // converted to an lvalue of type "cv3 T3," where "cv1 T1" + // is reference-compatible with "cv3 T3" 92) (this + // conversion is selected by enumerating the applicable + // conversion functions (13.3.1.6) and choosing the best + // one through overload resolution (13.3)), + if (!SuppressUserConversions && T2->isRecordType() && + !S.RequireCompleteType(DeclLoc, T2, 0) && + RefRelationship == Sema::Ref_Incompatible) { + if (FindConversionForRefInit(S, ICS, DeclType, DeclLoc, + Init, T2, /*AllowRvalues=*/false, + AllowExplicit)) + return ICS; + } + } + + // -- Otherwise, the reference shall be an lvalue reference to a + // non-volatile const type (i.e., cv1 shall be const), or the reference + // shall be an rvalue reference. + // + // We actually handle one oddity of C++ [over.ics.ref] at this + // point, which is that, due to p2 (which short-circuits reference + // binding by only attempting a simple conversion for non-direct + // bindings) and p3's strange wording, we allow a const volatile + // reference to bind to an rvalue. Hence the check for the presence + // of "const" rather than checking for "const" being the only + // qualifier. + // This is also the point where rvalue references and lvalue inits no longer + // go together. + if (!isRValRef && !T1.isConstQualified()) + return ICS; + + // -- If the initializer expression + // + // -- is an xvalue, class prvalue, array prvalue or function + // lvalue and "cv1 T1" is reference-compatible with "cv2 T2", or + if (RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification && + (InitCategory.isXValue() || + (InitCategory.isPRValue() && (T2->isRecordType() || T2->isArrayType())) || + (InitCategory.isLValue() && T2->isFunctionType()))) { + 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; + // In C++0x, this is always a direct binding. In C++98/03, it's a direct + // binding unless we're binding to a class prvalue. + // Note: Although xvalues wouldn't normally show up in C++98/03 code, we + // allow the use of rvalue references in C++98/03 for the benefit of + // standard library implementors; therefore, we need the xvalue check here. + ICS.Standard.DirectBinding = + S.getLangOpts().CPlusPlus0x || + (InitCategory.isPRValue() && !T2->isRecordType()); + ICS.Standard.IsLvalueReference = !isRValRef; + ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType(); + ICS.Standard.BindsToRvalue = InitCategory.isRValue(); + ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false; + ICS.Standard.ObjCLifetimeConversionBinding = ObjCLifetimeConversion; + ICS.Standard.CopyConstructor = 0; + return ICS; + } + + // -- has a class type (i.e., T2 is a class type), where T1 is not + // reference-related to T2, and can be implicitly converted to + // an xvalue, class prvalue, or function lvalue of type + // "cv3 T3", where "cv1 T1" is reference-compatible with + // "cv3 T3", + // + // then the reference is bound to the value of the initializer + // expression in the first case and to the result of the conversion + // in the second case (or, in either case, to an appropriate base + // class subobject). + if (!SuppressUserConversions && RefRelationship == Sema::Ref_Incompatible && + T2->isRecordType() && !S.RequireCompleteType(DeclLoc, T2, 0) && + FindConversionForRefInit(S, ICS, DeclType, DeclLoc, + Init, T2, /*AllowRvalues=*/true, + AllowExplicit)) { + // In the second case, if the reference is an rvalue reference + // and the second standard conversion sequence of the + // user-defined conversion sequence includes an lvalue-to-rvalue + // conversion, the program is ill-formed. + if (ICS.isUserDefined() && isRValRef && + ICS.UserDefined.After.First == ICK_Lvalue_To_Rvalue) + ICS.setBad(BadConversionSequence::no_conversion, Init, DeclType); + + 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 + // reference is then bound to the temporary. If T1 is + // reference-related to T2, cv1 must be the same + // cv-qualification as, or greater cv-qualification than, + // cv2; otherwise, the program is ill-formed. + if (RefRelationship == Sema::Ref_Related) { + // If cv1 == cv2 or cv1 is a greater cv-qualified than cv2, then + // we would be reference-compatible or reference-compatible with + // added qualification. But that wasn't the case, so the reference + // initialization fails. + // + // Note that we only want to check address spaces and cvr-qualifiers here. + // ObjC GC and lifetime qualifiers aren't important. + Qualifiers T1Quals = T1.getQualifiers(); + Qualifiers T2Quals = T2.getQualifiers(); + T1Quals.removeObjCGCAttr(); + T1Quals.removeObjCLifetime(); + T2Quals.removeObjCGCAttr(); + T2Quals.removeObjCLifetime(); + if (!T1Quals.compatiblyIncludes(T2Quals)) + return ICS; + } + + // If at least one of the types is a class type, the types are not + // related, and we aren't allowed any user conversions, the + // reference binding fails. This case is important for breaking + // recursion, since TryImplicitConversion below will attempt to + // create a temporary through the use of a copy constructor. + if (SuppressUserConversions && RefRelationship == Sema::Ref_Incompatible && + (T1->isRecordType() || T2->isRecordType())) + return ICS; + + // If T1 is reference-related to T2 and the reference is an rvalue + // reference, the initializer expression shall not be an lvalue. + if (RefRelationship >= Sema::Ref_Related && + isRValRef && Init->Classify(S.Context).isLValue()) + return ICS; + + // C++ [over.ics.ref]p2: + // When a parameter of reference type is not bound directly to + // an argument expression, the conversion sequence is the one + // required to convert the argument expression to the + // underlying type of the reference according to + // 13.3.3.1. Conceptually, this conversion sequence corresponds + // to copy-initializing a temporary of the underlying type with + // the argument expression. Any difference in top-level + // cv-qualification is subsumed by the initialization itself + // and does not constitute a conversion. + ICS = TryImplicitConversion(S, Init, T1, SuppressUserConversions, + /*AllowExplicit=*/false, + /*InOverloadResolution=*/false, + /*CStyle=*/false, + /*AllowObjCWritebackConversion=*/false); + + // Of course, that's still a reference binding. + if (ICS.isStandard()) { + ICS.Standard.ReferenceBinding = true; + ICS.Standard.IsLvalueReference = !isRValRef; + ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType(); + ICS.Standard.BindsToRvalue = true; + ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false; + ICS.Standard.ObjCLifetimeConversionBinding = false; + } else if (ICS.isUserDefined()) { + // Don't allow rvalue references to bind to lvalues. + if (DeclType->isRValueReferenceType()) { + if (const ReferenceType *RefType + = ICS.UserDefined.ConversionFunction->getResultType() + ->getAs()) { + if (!RefType->getPointeeType()->isFunctionType()) { + ICS.setBad(BadConversionSequence::lvalue_ref_to_rvalue, Init, + DeclType); + return ICS; + } + } + } + + ICS.UserDefined.After.ReferenceBinding = true; + ICS.UserDefined.After.IsLvalueReference = !isRValRef; + ICS.UserDefined.After.BindsToFunctionLvalue = T2->isFunctionType(); + ICS.UserDefined.After.BindsToRvalue = true; + ICS.UserDefined.After.BindsImplicitObjectArgumentWithoutRefQualifier = false; + ICS.UserDefined.After.ObjCLifetimeConversionBinding = false; + } + + return ICS; +} + +static ImplicitConversionSequence +TryCopyInitialization(Sema &S, Expr *From, QualType ToType, + bool SuppressUserConversions, + bool InOverloadResolution, + bool AllowObjCWritebackConversion, + bool AllowExplicit = false); + +/// TryListConversion - Try to copy-initialize a value of type ToType from the +/// initializer list From. +static ImplicitConversionSequence +TryListConversion(Sema &S, InitListExpr *From, QualType ToType, + bool SuppressUserConversions, + bool InOverloadResolution, + bool AllowObjCWritebackConversion) { + // C++11 [over.ics.list]p1: + // When an argument is an initializer list, it is not an expression and + // special rules apply for converting it to a parameter type. + + ImplicitConversionSequence Result; + Result.setBad(BadConversionSequence::no_conversion, From, ToType); + Result.setListInitializationSequence(); + + // We need a complete type for what follows. Incomplete types can never be + // initialized from init lists. + if (S.RequireCompleteType(From->getLocStart(), ToType, S.PDiag())) + return Result; + + // C++11 [over.ics.list]p2: + // If the parameter type is std::initializer_list or "array of X" and + // all the elements can be implicitly converted to X, the implicit + // conversion sequence is the worst conversion necessary to convert an + // element of the list to X. + bool toStdInitializerList = false; + QualType X; + if (ToType->isArrayType()) + X = S.Context.getBaseElementType(ToType); + else + toStdInitializerList = S.isStdInitializerList(ToType, &X); + if (!X.isNull()) { + for (unsigned i = 0, e = From->getNumInits(); i < e; ++i) { + Expr *Init = From->getInit(i); + ImplicitConversionSequence ICS = + TryCopyInitialization(S, Init, X, SuppressUserConversions, + InOverloadResolution, + AllowObjCWritebackConversion); + // If a single element isn't convertible, fail. + if (ICS.isBad()) { + Result = ICS; + break; + } + // Otherwise, look for the worst conversion. + if (Result.isBad() || + CompareImplicitConversionSequences(S, ICS, Result) == + ImplicitConversionSequence::Worse) + Result = ICS; + } + + // For an empty list, we won't have computed any conversion sequence. + // Introduce the identity conversion sequence. + if (From->getNumInits() == 0) { + Result.setStandard(); + Result.Standard.setAsIdentityConversion(); + Result.Standard.setFromType(ToType); + Result.Standard.setAllToTypes(ToType); + } + + Result.setListInitializationSequence(); + Result.setStdInitializerListElement(toStdInitializerList); + return Result; + } + + // C++11 [over.ics.list]p3: + // Otherwise, if the parameter is a non-aggregate class X and overload + // resolution chooses a single best constructor [...] the implicit + // conversion sequence is a user-defined conversion sequence. If multiple + // constructors are viable but none is better than the others, the + // implicit conversion sequence is a user-defined conversion sequence. + if (ToType->isRecordType() && !ToType->isAggregateType()) { + // This function can deal with initializer lists. + Result = TryUserDefinedConversion(S, From, ToType, SuppressUserConversions, + /*AllowExplicit=*/false, + InOverloadResolution, /*CStyle=*/false, + AllowObjCWritebackConversion); + Result.setListInitializationSequence(); + return Result; + } + + // C++11 [over.ics.list]p4: + // Otherwise, if the parameter has an aggregate type which can be + // initialized from the initializer list [...] the implicit conversion + // sequence is a user-defined conversion sequence. + if (ToType->isAggregateType()) { + // Type is an aggregate, argument is an init list. At this point it comes + // down to checking whether the initialization works. + // FIXME: Find out whether this parameter is consumed or not. + InitializedEntity Entity = + InitializedEntity::InitializeParameter(S.Context, ToType, + /*Consumed=*/false); + if (S.CanPerformCopyInitialization(Entity, S.Owned(From))) { + Result.setUserDefined(); + Result.UserDefined.Before.setAsIdentityConversion(); + // Initializer lists don't have a type. + Result.UserDefined.Before.setFromType(QualType()); + Result.UserDefined.Before.setAllToTypes(QualType()); + + Result.UserDefined.After.setAsIdentityConversion(); + Result.UserDefined.After.setFromType(ToType); + Result.UserDefined.After.setAllToTypes(ToType); + Result.UserDefined.ConversionFunction = 0; + } + return Result; + } + + // C++11 [over.ics.list]p5: + // Otherwise, if the parameter is a reference, see 13.3.3.1.4. + if (ToType->isReferenceType()) { + // The standard is notoriously unclear here, since 13.3.3.1.4 doesn't + // mention initializer lists in any way. So we go by what list- + // initialization would do and try to extrapolate from that. + + QualType T1 = ToType->getAs()->getPointeeType(); + + // If the initializer list has a single element that is reference-related + // to the parameter type, we initialize the reference from that. + if (From->getNumInits() == 1) { + Expr *Init = From->getInit(0); + + QualType T2 = Init->getType(); + + // If the initializer is the address of an overloaded function, try + // to resolve the overloaded function. If all goes well, T2 is the + // type of the resulting function. + if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy) { + DeclAccessPair Found; + if (FunctionDecl *Fn = S.ResolveAddressOfOverloadedFunction( + Init, ToType, false, Found)) + T2 = Fn->getType(); + } + + // Compute some basic properties of the types and the initializer. + bool dummy1 = false; + bool dummy2 = false; + bool dummy3 = false; + Sema::ReferenceCompareResult RefRelationship + = S.CompareReferenceRelationship(From->getLocStart(), T1, T2, dummy1, + dummy2, dummy3); + + if (RefRelationship >= Sema::Ref_Related) + return TryReferenceInit(S, Init, ToType, + /*FIXME:*/From->getLocStart(), + SuppressUserConversions, + /*AllowExplicit=*/false); + } + + // Otherwise, we bind the reference to a temporary created from the + // initializer list. + Result = TryListConversion(S, From, T1, SuppressUserConversions, + InOverloadResolution, + AllowObjCWritebackConversion); + if (Result.isFailure()) + return Result; + assert(!Result.isEllipsis() && + "Sub-initialization cannot result in ellipsis conversion."); + + // Can we even bind to a temporary? + if (ToType->isRValueReferenceType() || + (T1.isConstQualified() && !T1.isVolatileQualified())) { + StandardConversionSequence &SCS = Result.isStandard() ? Result.Standard : + Result.UserDefined.After; + SCS.ReferenceBinding = true; + SCS.IsLvalueReference = ToType->isLValueReferenceType(); + SCS.BindsToRvalue = true; + SCS.BindsToFunctionLvalue = false; + SCS.BindsImplicitObjectArgumentWithoutRefQualifier = false; + SCS.ObjCLifetimeConversionBinding = false; + } else + Result.setBad(BadConversionSequence::lvalue_ref_to_rvalue, + From, ToType); + return Result; + } + + // C++11 [over.ics.list]p6: + // Otherwise, if the parameter type is not a class: + if (!ToType->isRecordType()) { + // - if the initializer list has one element, the implicit conversion + // sequence is the one required to convert the element to the + // parameter type. + unsigned NumInits = From->getNumInits(); + if (NumInits == 1) + Result = TryCopyInitialization(S, From->getInit(0), ToType, + SuppressUserConversions, + InOverloadResolution, + AllowObjCWritebackConversion); + // - if the initializer list has no elements, the implicit conversion + // sequence is the identity conversion. + else if (NumInits == 0) { + Result.setStandard(); + Result.Standard.setAsIdentityConversion(); + Result.Standard.setFromType(ToType); + Result.Standard.setAllToTypes(ToType); + } + Result.setListInitializationSequence(); + return Result; + } + + // C++11 [over.ics.list]p7: + // In all cases other than those enumerated above, no conversion is possible + return Result; +} + +/// TryCopyInitialization - Try to copy-initialize a value of type +/// ToType from the expression From. Return the implicit conversion +/// sequence required to pass this argument, which may be a bad +/// conversion sequence (meaning that the argument cannot be passed to +/// a parameter of this type). If @p SuppressUserConversions, then we +/// do not permit any user-defined conversion sequences. +static ImplicitConversionSequence +TryCopyInitialization(Sema &S, Expr *From, QualType ToType, + bool SuppressUserConversions, + bool InOverloadResolution, + bool AllowObjCWritebackConversion, + bool AllowExplicit) { + if (InitListExpr *FromInitList = dyn_cast(From)) + return TryListConversion(S, FromInitList, ToType, SuppressUserConversions, + InOverloadResolution,AllowObjCWritebackConversion); + + if (ToType->isReferenceType()) + return TryReferenceInit(S, From, ToType, + /*FIXME:*/From->getLocStart(), + SuppressUserConversions, + AllowExplicit); + + return TryImplicitConversion(S, From, ToType, + SuppressUserConversions, + /*AllowExplicit=*/false, + InOverloadResolution, + /*CStyle=*/false, + AllowObjCWritebackConversion); +} + +static bool TryCopyInitialization(const CanQualType FromQTy, + const CanQualType ToQTy, + Sema &S, + SourceLocation Loc, + ExprValueKind FromVK) { + OpaqueValueExpr TmpExpr(Loc, FromQTy, FromVK); + ImplicitConversionSequence ICS = + TryCopyInitialization(S, &TmpExpr, ToQTy, true, true, false); + + return !ICS.isBad(); +} + +/// TryObjectArgumentInitialization - Try to initialize the object +/// parameter of the given member function (@c Method) from the +/// expression @p From. +static ImplicitConversionSequence +TryObjectArgumentInitialization(Sema &S, QualType OrigFromType, + Expr::Classification FromClassification, + 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 = S.Context.getCVRQualifiedType(ClassType, Quals); + + // Set up the conversion sequence as a "bad" conversion, to allow us + // to exit early. + ImplicitConversionSequence ICS; + + // We need to have an object of class type. + QualType FromType = OrigFromType; + if (const PointerType *PT = FromType->getAs()) { + FromType = PT->getPointeeType(); + + // When we had a pointer, it's implicitly dereferenced, so we + // better have an lvalue. + assert(FromClassification.isLValue()); + } + + assert(FromType->isRecordType()); + + // C++0x [over.match.funcs]p4: + // For non-static member functions, the type of the implicit object + // parameter is + // + // - "lvalue reference to cv X" for functions declared without a + // ref-qualifier or with the & ref-qualifier + // - "rvalue reference to cv X" for functions declared with the && + // ref-qualifier + // + // where X is the class of which the function is a member and cv is the + // cv-qualification on the member function declaration. + // + // However, when finding an implicit conversion sequence for the argument, we + // are not allowed to create temporaries or perform user-defined conversions + // (C++ [over.match.funcs]p5). We perform a simplified version of + // reference binding here, that allows class rvalues to bind to + // non-constant references. + + // First check the qualifiers. + QualType FromTypeCanon = S.Context.getCanonicalType(FromType); + if (ImplicitParamType.getCVRQualifiers() + != FromTypeCanon.getLocalCVRQualifiers() && + !ImplicitParamType.isAtLeastAsQualifiedAs(FromTypeCanon)) { + ICS.setBad(BadConversionSequence::bad_qualifiers, + OrigFromType, ImplicitParamType); + return ICS; + } + + // Check that we have either the same type or a derived type. It + // affects the conversion rank. + QualType ClassTypeCanon = S.Context.getCanonicalType(ClassType); + ImplicitConversionKind SecondKind; + if (ClassTypeCanon == FromTypeCanon.getLocalUnqualifiedType()) { + SecondKind = ICK_Identity; + } else if (S.IsDerivedFrom(FromType, ClassType)) + SecondKind = ICK_Derived_To_Base; + else { + ICS.setBad(BadConversionSequence::unrelated_class, + FromType, ImplicitParamType); + return ICS; + } + + // Check the ref-qualifier. + switch (Method->getRefQualifier()) { + case RQ_None: + // Do nothing; we don't care about lvalueness or rvalueness. + break; + + case RQ_LValue: + if (!FromClassification.isLValue() && Quals != Qualifiers::Const) { + // non-const lvalue reference cannot bind to an rvalue + ICS.setBad(BadConversionSequence::lvalue_ref_to_rvalue, FromType, + ImplicitParamType); + return ICS; + } + break; + + case RQ_RValue: + if (!FromClassification.isRValue()) { + // rvalue reference cannot bind to an lvalue + ICS.setBad(BadConversionSequence::rvalue_ref_to_lvalue, FromType, + ImplicitParamType); + return ICS; + } + break; + } + + // Success. Mark this as a reference binding. + ICS.setStandard(); + ICS.Standard.setAsIdentityConversion(); + ICS.Standard.Second = SecondKind; + ICS.Standard.setFromType(FromType); + ICS.Standard.setAllToTypes(ImplicitParamType); + ICS.Standard.ReferenceBinding = true; + ICS.Standard.DirectBinding = true; + ICS.Standard.IsLvalueReference = Method->getRefQualifier() != RQ_RValue; + ICS.Standard.BindsToFunctionLvalue = false; + ICS.Standard.BindsToRvalue = FromClassification.isRValue(); + ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier + = (Method->getRefQualifier() == RQ_None); + return ICS; +} + +/// PerformObjectArgumentInitialization - Perform initialization of +/// the implicit object parameter for the given Method with the given +/// expression. +ExprResult +Sema::PerformObjectArgumentInitialization(Expr *From, + NestedNameSpecifier *Qualifier, + NamedDecl *FoundDecl, + CXXMethodDecl *Method) { + QualType FromRecordType, DestType; + QualType ImplicitParamRecordType = + Method->getThisType(Context)->getAs()->getPointeeType(); + + Expr::Classification FromClassification; + if (const PointerType *PT = From->getType()->getAs()) { + FromRecordType = PT->getPointeeType(); + DestType = Method->getThisType(Context); + FromClassification = Expr::Classification::makeSimpleLValue(); + } else { + FromRecordType = From->getType(); + DestType = ImplicitParamRecordType; + FromClassification = From->Classify(Context); + } + + // Note that we always use the true parent context when performing + // the actual argument initialization. + ImplicitConversionSequence ICS + = TryObjectArgumentInitialization(*this, From->getType(), FromClassification, + Method, Method->getParent()); + if (ICS.isBad()) { + if (ICS.Bad.Kind == BadConversionSequence::bad_qualifiers) { + Qualifiers FromQs = FromRecordType.getQualifiers(); + Qualifiers ToQs = DestType.getQualifiers(); + unsigned CVR = FromQs.getCVRQualifiers() & ~ToQs.getCVRQualifiers(); + if (CVR) { + Diag(From->getLocStart(), + diag::err_member_function_call_bad_cvr) + << Method->getDeclName() << FromRecordType << (CVR - 1) + << From->getSourceRange(); + Diag(Method->getLocation(), diag::note_previous_decl) + << Method->getDeclName(); + return ExprError(); + } + } + + return Diag(From->getLocStart(), + diag::err_implicit_object_parameter_init) + << ImplicitParamRecordType << FromRecordType << From->getSourceRange(); + } + + if (ICS.Standard.Second == ICK_Derived_To_Base) { + ExprResult FromRes = + PerformObjectMemberConversion(From, Qualifier, FoundDecl, Method); + if (FromRes.isInvalid()) + return ExprError(); + From = FromRes.take(); + } + + if (!Context.hasSameType(From->getType(), DestType)) + From = ImpCastExprToType(From, DestType, CK_NoOp, + From->getValueKind()).take(); + return Owned(From); +} + +/// TryContextuallyConvertToBool - Attempt to contextually convert the +/// expression From to bool (C++0x [conv]p3). +static ImplicitConversionSequence +TryContextuallyConvertToBool(Sema &S, Expr *From) { + // FIXME: This is pretty broken. + return TryImplicitConversion(S, From, S.Context.BoolTy, + // FIXME: Are these flags correct? + /*SuppressUserConversions=*/false, + /*AllowExplicit=*/true, + /*InOverloadResolution=*/false, + /*CStyle=*/false, + /*AllowObjCWritebackConversion=*/false); +} + +/// PerformContextuallyConvertToBool - Perform a contextual conversion +/// of the expression From to bool (C++0x [conv]p3). +ExprResult Sema::PerformContextuallyConvertToBool(Expr *From) { + if (checkPlaceholderForOverload(*this, From)) + return ExprError(); + + ImplicitConversionSequence ICS = TryContextuallyConvertToBool(*this, From); + if (!ICS.isBad()) + return PerformImplicitConversion(From, Context.BoolTy, ICS, AA_Converting); + + if (!DiagnoseMultipleUserDefinedConversion(From, Context.BoolTy)) + return Diag(From->getLocStart(), + diag::err_typecheck_bool_condition) + << From->getType() << From->getSourceRange(); + return ExprError(); +} + +/// Check that the specified conversion is permitted in a converted constant +/// expression, according to C++11 [expr.const]p3. Return true if the conversion +/// is acceptable. +static bool CheckConvertedConstantConversions(Sema &S, + StandardConversionSequence &SCS) { + // Since we know that the target type is an integral or unscoped enumeration + // type, most conversion kinds are impossible. All possible First and Third + // conversions are fine. + switch (SCS.Second) { + case ICK_Identity: + case ICK_Integral_Promotion: + case ICK_Integral_Conversion: + return true; + + case ICK_Boolean_Conversion: + // Conversion from an integral or unscoped enumeration type to bool is + // classified as ICK_Boolean_Conversion, but it's also an integral + // conversion, so it's permitted in a converted constant expression. + return SCS.getFromType()->isIntegralOrUnscopedEnumerationType() && + SCS.getToType(2)->isBooleanType(); + + case ICK_Floating_Integral: + case ICK_Complex_Real: + return false; + + case ICK_Lvalue_To_Rvalue: + case ICK_Array_To_Pointer: + case ICK_Function_To_Pointer: + case ICK_NoReturn_Adjustment: + case ICK_Qualification: + case ICK_Compatible_Conversion: + case ICK_Vector_Conversion: + case ICK_Vector_Splat: + case ICK_Derived_To_Base: + case ICK_Pointer_Conversion: + case ICK_Pointer_Member: + case ICK_Block_Pointer_Conversion: + case ICK_Writeback_Conversion: + case ICK_Floating_Promotion: + case ICK_Complex_Promotion: + case ICK_Complex_Conversion: + case ICK_Floating_Conversion: + case ICK_TransparentUnionConversion: + llvm_unreachable("unexpected second conversion kind"); + + case ICK_Num_Conversion_Kinds: + break; + } + + llvm_unreachable("unknown conversion kind"); +} + +/// CheckConvertedConstantExpression - Check that the expression From is a +/// converted constant expression of type T, perform the conversion and produce +/// the converted expression, per C++11 [expr.const]p3. +ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T, + llvm::APSInt &Value, + CCEKind CCE) { + assert(LangOpts.CPlusPlus0x && "converted constant expression outside C++11"); + assert(T->isIntegralOrEnumerationType() && "unexpected converted const type"); + + if (checkPlaceholderForOverload(*this, From)) + return ExprError(); + + // C++11 [expr.const]p3 with proposed wording fixes: + // A converted constant expression of type T is a core constant expression, + // implicitly converted to a prvalue of type T, where the converted + // expression is a literal constant expression and the implicit conversion + // sequence contains only user-defined conversions, lvalue-to-rvalue + // conversions, integral promotions, and integral conversions other than + // narrowing conversions. + ImplicitConversionSequence ICS = + TryImplicitConversion(From, T, + /*SuppressUserConversions=*/false, + /*AllowExplicit=*/false, + /*InOverloadResolution=*/false, + /*CStyle=*/false, + /*AllowObjcWritebackConversion=*/false); + StandardConversionSequence *SCS = 0; + switch (ICS.getKind()) { + case ImplicitConversionSequence::StandardConversion: + if (!CheckConvertedConstantConversions(*this, ICS.Standard)) + return Diag(From->getLocStart(), + diag::err_typecheck_converted_constant_expression_disallowed) + << From->getType() << From->getSourceRange() << T; + SCS = &ICS.Standard; + break; + case ImplicitConversionSequence::UserDefinedConversion: + // We are converting from class type to an integral or enumeration type, so + // the Before sequence must be trivial. + if (!CheckConvertedConstantConversions(*this, ICS.UserDefined.After)) + return Diag(From->getLocStart(), + diag::err_typecheck_converted_constant_expression_disallowed) + << From->getType() << From->getSourceRange() << T; + SCS = &ICS.UserDefined.After; + break; + case ImplicitConversionSequence::AmbiguousConversion: + case ImplicitConversionSequence::BadConversion: + if (!DiagnoseMultipleUserDefinedConversion(From, T)) + return Diag(From->getLocStart(), + diag::err_typecheck_converted_constant_expression) + << From->getType() << From->getSourceRange() << T; + return ExprError(); + + case ImplicitConversionSequence::EllipsisConversion: + llvm_unreachable("ellipsis conversion in converted constant expression"); + } + + ExprResult Result = PerformImplicitConversion(From, T, ICS, AA_Converting); + if (Result.isInvalid()) + return Result; + + // Check for a narrowing implicit conversion. + APValue PreNarrowingValue; + QualType PreNarrowingType; + switch (SCS->getNarrowingKind(Context, Result.get(), PreNarrowingValue, + PreNarrowingType)) { + case NK_Variable_Narrowing: + // Implicit conversion to a narrower type, and the value is not a constant + // expression. We'll diagnose this in a moment. + case NK_Not_Narrowing: + break; + + case NK_Constant_Narrowing: + Diag(From->getLocStart(), + isSFINAEContext() ? diag::err_cce_narrowing_sfinae : + diag::err_cce_narrowing) + << CCE << /*Constant*/1 + << PreNarrowingValue.getAsString(Context, PreNarrowingType) << T; + break; + + case NK_Type_Narrowing: + Diag(From->getLocStart(), + isSFINAEContext() ? diag::err_cce_narrowing_sfinae : + diag::err_cce_narrowing) + << CCE << /*Constant*/0 << From->getType() << T; + break; + } + + // Check the expression is a constant expression. + llvm::SmallVector Notes; + Expr::EvalResult Eval; + Eval.Diag = &Notes; + + if (!Result.get()->EvaluateAsRValue(Eval, Context)) { + // The expression can't be folded, so we can't keep it at this position in + // the AST. + Result = ExprError(); + } else { + Value = Eval.Val.getInt(); + + if (Notes.empty()) { + // It's a constant expression. + return Result; + } + } + + // It's not a constant expression. Produce an appropriate diagnostic. + if (Notes.size() == 1 && + Notes[0].second.getDiagID() == diag::note_invalid_subexpr_in_const_expr) + Diag(Notes[0].first, diag::err_expr_not_cce) << CCE; + else { + Diag(From->getLocStart(), diag::err_expr_not_cce) + << CCE << From->getSourceRange(); + for (unsigned I = 0; I < Notes.size(); ++I) + Diag(Notes[I].first, Notes[I].second); + } + return Result; +} + +/// dropPointerConversions - If the given standard conversion sequence +/// involves any pointer conversions, remove them. This may change +/// the result type of the conversion sequence. +static void dropPointerConversion(StandardConversionSequence &SCS) { + if (SCS.Second == ICK_Pointer_Conversion) { + SCS.Second = ICK_Identity; + SCS.Third = ICK_Identity; + SCS.ToTypePtrs[2] = SCS.ToTypePtrs[1] = SCS.ToTypePtrs[0]; + } +} + +/// TryContextuallyConvertToObjCPointer - Attempt to contextually +/// convert the expression From to an Objective-C pointer type. +static ImplicitConversionSequence +TryContextuallyConvertToObjCPointer(Sema &S, Expr *From) { + // Do an implicit conversion to 'id'. + QualType Ty = S.Context.getObjCIdType(); + ImplicitConversionSequence ICS + = TryImplicitConversion(S, From, Ty, + // FIXME: Are these flags correct? + /*SuppressUserConversions=*/false, + /*AllowExplicit=*/true, + /*InOverloadResolution=*/false, + /*CStyle=*/false, + /*AllowObjCWritebackConversion=*/false); + + // Strip off any final conversions to 'id'. + switch (ICS.getKind()) { + case ImplicitConversionSequence::BadConversion: + case ImplicitConversionSequence::AmbiguousConversion: + case ImplicitConversionSequence::EllipsisConversion: + break; + + case ImplicitConversionSequence::UserDefinedConversion: + dropPointerConversion(ICS.UserDefined.After); + break; + + case ImplicitConversionSequence::StandardConversion: + dropPointerConversion(ICS.Standard); + break; + } + + return ICS; +} + +/// PerformContextuallyConvertToObjCPointer - Perform a contextual +/// conversion of the expression From to an Objective-C pointer type. +ExprResult Sema::PerformContextuallyConvertToObjCPointer(Expr *From) { + if (checkPlaceholderForOverload(*this, From)) + return ExprError(); + + QualType Ty = Context.getObjCIdType(); + ImplicitConversionSequence ICS = + TryContextuallyConvertToObjCPointer(*this, From); + if (!ICS.isBad()) + return PerformImplicitConversion(From, Ty, ICS, AA_Converting); + return ExprError(); +} + +/// Determine whether the provided type is an integral type, or an enumeration +/// type of a permitted flavor. +static bool isIntegralOrEnumerationType(QualType T, bool AllowScopedEnum) { + return AllowScopedEnum ? T->isIntegralOrEnumerationType() + : T->isIntegralOrUnscopedEnumerationType(); +} + +/// \brief Attempt to convert the given expression to an integral or +/// enumeration type. +/// +/// This routine will attempt to convert an expression of class type to an +/// integral or enumeration type, if that class type only has a single +/// conversion to an integral or enumeration type. +/// +/// \param Loc The source location of the construct that requires the +/// conversion. +/// +/// \param FromE The expression we're converting from. +/// +/// \param NotIntDiag The diagnostic to be emitted if the expression does not +/// have integral or enumeration type. +/// +/// \param IncompleteDiag The diagnostic to be emitted if the expression has +/// incomplete class type. +/// +/// \param ExplicitConvDiag The diagnostic to be emitted if we're calling an +/// explicit conversion function (because no implicit conversion functions +/// were available). This is a recovery mode. +/// +/// \param ExplicitConvNote The note to be emitted with \p ExplicitConvDiag, +/// showing which conversion was picked. +/// +/// \param AmbigDiag The diagnostic to be emitted if there is more than one +/// conversion function that could convert to integral or enumeration type. +/// +/// \param AmbigNote The note to be emitted with \p AmbigDiag for each +/// usable conversion function. +/// +/// \param ConvDiag The diagnostic to be emitted if we are calling a conversion +/// function, which may be an extension in this case. +/// +/// \param AllowScopedEnumerations Specifies whether conversions to scoped +/// enumerations should be considered. +/// +/// \returns The expression, converted to an integral or enumeration type if +/// successful. +ExprResult +Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From, + const PartialDiagnostic &NotIntDiag, + const PartialDiagnostic &IncompleteDiag, + const PartialDiagnostic &ExplicitConvDiag, + const PartialDiagnostic &ExplicitConvNote, + const PartialDiagnostic &AmbigDiag, + const PartialDiagnostic &AmbigNote, + const PartialDiagnostic &ConvDiag, + bool AllowScopedEnumerations) { + // We can't perform any more checking for type-dependent expressions. + if (From->isTypeDependent()) + return Owned(From); + + // Process placeholders immediately. + if (From->hasPlaceholderType()) { + ExprResult result = CheckPlaceholderExpr(From); + if (result.isInvalid()) return result; + From = result.take(); + } + + // If the expression already has integral or enumeration type, we're golden. + QualType T = From->getType(); + if (isIntegralOrEnumerationType(T, AllowScopedEnumerations)) + return DefaultLvalueConversion(From); + + // FIXME: Check for missing '()' if T is a function type? + + // If we don't have a class type in C++, there's no way we can get an + // expression of integral or enumeration type. + const RecordType *RecordTy = T->getAs(); + if (!RecordTy || !getLangOpts().CPlusPlus) { + if (NotIntDiag.getDiagID()) + Diag(Loc, NotIntDiag) << T << From->getSourceRange(); + return Owned(From); + } + + // We must have a complete class type. + if (RequireCompleteType(Loc, T, IncompleteDiag)) + return Owned(From); + + // Look for a conversion to an integral or enumeration type. + UnresolvedSet<4> ViableConversions; + UnresolvedSet<4> ExplicitConversions; + const UnresolvedSetImpl *Conversions + = cast(RecordTy->getDecl())->getVisibleConversionFunctions(); + + bool HadMultipleCandidates = (Conversions->size() > 1); + + for (UnresolvedSetImpl::iterator I = Conversions->begin(), + E = Conversions->end(); + I != E; + ++I) { + if (CXXConversionDecl *Conversion + = dyn_cast((*I)->getUnderlyingDecl())) { + if (isIntegralOrEnumerationType( + Conversion->getConversionType().getNonReferenceType(), + AllowScopedEnumerations)) { + if (Conversion->isExplicit()) + ExplicitConversions.addDecl(I.getDecl(), I.getAccess()); + else + ViableConversions.addDecl(I.getDecl(), I.getAccess()); + } + } + } + + switch (ViableConversions.size()) { + case 0: + if (ExplicitConversions.size() == 1 && ExplicitConvDiag.getDiagID()) { + DeclAccessPair Found = ExplicitConversions[0]; + CXXConversionDecl *Conversion + = cast(Found->getUnderlyingDecl()); + + // The user probably meant to invoke the given explicit + // conversion; use it. + QualType ConvTy + = Conversion->getConversionType().getNonReferenceType(); + std::string TypeStr; + ConvTy.getAsStringInternal(TypeStr, getPrintingPolicy()); + + Diag(Loc, ExplicitConvDiag) + << T << ConvTy + << FixItHint::CreateInsertion(From->getLocStart(), + "static_cast<" + TypeStr + ">(") + << FixItHint::CreateInsertion(PP.getLocForEndOfToken(From->getLocEnd()), + ")"); + Diag(Conversion->getLocation(), ExplicitConvNote) + << ConvTy->isEnumeralType() << ConvTy; + + // If we aren't in a SFINAE context, build a call to the + // explicit conversion function. + if (isSFINAEContext()) + return ExprError(); + + CheckMemberOperatorAccess(From->getExprLoc(), From, 0, Found); + ExprResult Result = BuildCXXMemberCallExpr(From, Found, Conversion, + HadMultipleCandidates); + if (Result.isInvalid()) + return ExprError(); + // Record usage of conversion in an implicit cast. + From = ImplicitCastExpr::Create(Context, Result.get()->getType(), + CK_UserDefinedConversion, + Result.get(), 0, + Result.get()->getValueKind()); + } + + // We'll complain below about a non-integral condition type. + break; + + case 1: { + // Apply this conversion. + DeclAccessPair Found = ViableConversions[0]; + CheckMemberOperatorAccess(From->getExprLoc(), From, 0, Found); + + CXXConversionDecl *Conversion + = cast(Found->getUnderlyingDecl()); + QualType ConvTy + = Conversion->getConversionType().getNonReferenceType(); + if (ConvDiag.getDiagID()) { + if (isSFINAEContext()) + return ExprError(); + + Diag(Loc, ConvDiag) + << T << ConvTy->isEnumeralType() << ConvTy << From->getSourceRange(); + } + + ExprResult Result = BuildCXXMemberCallExpr(From, Found, Conversion, + HadMultipleCandidates); + if (Result.isInvalid()) + return ExprError(); + // Record usage of conversion in an implicit cast. + From = ImplicitCastExpr::Create(Context, Result.get()->getType(), + CK_UserDefinedConversion, + Result.get(), 0, + Result.get()->getValueKind()); + break; + } + + default: + if (!AmbigDiag.getDiagID()) + return Owned(From); + + Diag(Loc, AmbigDiag) + << T << From->getSourceRange(); + for (unsigned I = 0, N = ViableConversions.size(); I != N; ++I) { + CXXConversionDecl *Conv + = cast(ViableConversions[I]->getUnderlyingDecl()); + QualType ConvTy = Conv->getConversionType().getNonReferenceType(); + Diag(Conv->getLocation(), AmbigNote) + << ConvTy->isEnumeralType() << ConvTy; + } + return Owned(From); + } + + if (!isIntegralOrEnumerationType(From->getType(), AllowScopedEnumerations) && + NotIntDiag.getDiagID()) + Diag(Loc, NotIntDiag) << From->getType() << From->getSourceRange(); + + return DefaultLvalueConversion(From); +} + +/// AddOverloadCandidate - Adds the given function to the set of +/// candidate functions, using the given function call arguments. If +/// @p SuppressUserConversions, then don't allow user-defined +/// conversions via constructors or conversion operators. +/// +/// \para PartialOverloading true if we are performing "partial" overloading +/// based on an incomplete set of function arguments. This feature is used by +/// code completion. +void +Sema::AddOverloadCandidate(FunctionDecl *Function, + DeclAccessPair FoundDecl, + llvm::ArrayRef Args, + OverloadCandidateSet& CandidateSet, + bool SuppressUserConversions, + bool PartialOverloading, + bool AllowExplicit) { + const FunctionProtoType* Proto + = dyn_cast(Function->getType()->getAs()); + assert(Proto && "Functions without a prototype cannot be overloaded"); + assert(!Function->getDescribedFunctionTemplate() && + "Use AddTemplateOverloadCandidate for function templates"); + + if (CXXMethodDecl *Method = dyn_cast(Function)) { + if (!isa(Method)) { + // If we get here, it's because we're calling a member function + // that is named without a member access expression (e.g., + // "this->f") that was either written explicitly or created + // implicitly. This can happen with a qualified call to a member + // function, e.g., X::f(). We use an empty type for the implied + // object argument (C++ [over.call.func]p3), and the acting context + // is irrelevant. + AddMethodCandidate(Method, FoundDecl, Method->getParent(), + QualType(), Expr::Classification::makeSimpleLValue(), + Args, CandidateSet, SuppressUserConversions); + return; + } + // We treat a constructor like a non-member function, since its object + // argument doesn't participate in overload resolution. + } + + if (!CandidateSet.isNewCandidate(Function)) + return; + + // Overload resolution is always an unevaluated context. + EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated); + + if (CXXConstructorDecl *Constructor = dyn_cast(Function)){ + // C++ [class.copy]p3: + // A member function template is never instantiated to perform the copy + // of a class object to an object of its class type. + QualType ClassType = Context.getTypeDeclType(Constructor->getParent()); + if (Args.size() == 1 && + Constructor->isSpecializationCopyingObject() && + (Context.hasSameUnqualifiedType(ClassType, Args[0]->getType()) || + IsDerivedFrom(Args[0]->getType(), ClassType))) + return; + } + + // Add this candidate + OverloadCandidate &Candidate = CandidateSet.addCandidate(Args.size()); + Candidate.FoundDecl = FoundDecl; + Candidate.Function = Function; + Candidate.Viable = true; + Candidate.IsSurrogate = false; + Candidate.IgnoreObjectArgument = false; + Candidate.ExplicitCallArguments = Args.size(); + + unsigned NumArgsInProto = Proto->getNumArgs(); + + // (C++ 13.3.2p2): A candidate function having fewer than m + // parameters is viable only if it has an ellipsis in its parameter + // list (8.3.5). + if ((Args.size() + (PartialOverloading && Args.size())) > NumArgsInProto && + !Proto->isVariadic()) { + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_too_many_arguments; + return; + } + + // (C++ 13.3.2p2): A candidate function having more than m parameters + // is viable only if the (m+1)st parameter has a default argument + // (8.3.6). For the purposes of overload resolution, the + // parameter list is truncated on the right, so that there are + // exactly m parameters. + unsigned MinRequiredArgs = Function->getMinRequiredArguments(); + if (Args.size() < MinRequiredArgs && !PartialOverloading) { + // Not enough arguments. + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_too_few_arguments; + return; + } + + // (CUDA B.1): Check for invalid calls between targets. + if (getLangOpts().CUDA) + if (const FunctionDecl *Caller = dyn_cast(CurContext)) + if (CheckCUDATarget(Caller, Function)) { + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_bad_target; + return; + } + + // Determine the implicit conversion sequences for each of the + // arguments. + for (unsigned ArgIdx = 0; ArgIdx < Args.size(); ++ArgIdx) { + if (ArgIdx < NumArgsInProto) { + // (C++ 13.3.2p3): for F to be a viable function, there shall + // exist for each argument an implicit conversion sequence + // (13.3.3.1) that converts that argument to the corresponding + // parameter of F. + QualType ParamType = Proto->getArgType(ArgIdx); + Candidate.Conversions[ArgIdx] + = TryCopyInitialization(*this, Args[ArgIdx], ParamType, + SuppressUserConversions, + /*InOverloadResolution=*/true, + /*AllowObjCWritebackConversion=*/ + getLangOpts().ObjCAutoRefCount, + AllowExplicit); + if (Candidate.Conversions[ArgIdx].isBad()) { + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_bad_conversion; + break; + } + } else { + // (C++ 13.3.2p2): For the purposes of overload resolution, any + // argument for which there is no corresponding parameter is + // considered to ""match the ellipsis" (C+ 13.3.3.1.3). + Candidate.Conversions[ArgIdx].setEllipsis(); + } + } +} + +/// \brief Add all of the function declarations in the given function set to +/// the overload canddiate set. +void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns, + llvm::ArrayRef Args, + OverloadCandidateSet& CandidateSet, + bool SuppressUserConversions, + TemplateArgumentListInfo *ExplicitTemplateArgs) { + for (UnresolvedSetIterator F = Fns.begin(), E = Fns.end(); F != E; ++F) { + NamedDecl *D = F.getDecl()->getUnderlyingDecl(); + if (FunctionDecl *FD = dyn_cast(D)) { + if (isa(FD) && !cast(FD)->isStatic()) + AddMethodCandidate(cast(FD), F.getPair(), + cast(FD)->getParent(), + Args[0]->getType(), Args[0]->Classify(Context), + Args.slice(1), CandidateSet, + SuppressUserConversions); + else + AddOverloadCandidate(FD, F.getPair(), Args, CandidateSet, + SuppressUserConversions); + } else { + FunctionTemplateDecl *FunTmpl = cast(D); + if (isa(FunTmpl->getTemplatedDecl()) && + !cast(FunTmpl->getTemplatedDecl())->isStatic()) + AddMethodTemplateCandidate(FunTmpl, F.getPair(), + cast(FunTmpl->getDeclContext()), + ExplicitTemplateArgs, + Args[0]->getType(), + Args[0]->Classify(Context), Args.slice(1), + CandidateSet, SuppressUserConversions); + else + AddTemplateOverloadCandidate(FunTmpl, F.getPair(), + ExplicitTemplateArgs, Args, + CandidateSet, SuppressUserConversions); + } + } +} + +/// AddMethodCandidate - Adds a named decl (which is some kind of +/// method) as a method candidate to the given overload set. +void Sema::AddMethodCandidate(DeclAccessPair FoundDecl, + QualType ObjectType, + Expr::Classification ObjectClassification, + Expr **Args, unsigned NumArgs, + OverloadCandidateSet& CandidateSet, + bool SuppressUserConversions) { + NamedDecl *Decl = FoundDecl.getDecl(); + CXXRecordDecl *ActingContext = cast(Decl->getDeclContext()); + + if (isa(Decl)) + Decl = cast(Decl)->getTargetDecl(); + + if (FunctionTemplateDecl *TD = dyn_cast(Decl)) { + assert(isa(TD->getTemplatedDecl()) && + "Expected a member function template"); + AddMethodTemplateCandidate(TD, FoundDecl, ActingContext, + /*ExplicitArgs*/ 0, + ObjectType, ObjectClassification, + llvm::makeArrayRef(Args, NumArgs), CandidateSet, + SuppressUserConversions); + } else { + AddMethodCandidate(cast(Decl), FoundDecl, ActingContext, + ObjectType, ObjectClassification, + llvm::makeArrayRef(Args, NumArgs), + CandidateSet, SuppressUserConversions); + } +} + +/// AddMethodCandidate - Adds the given C++ member function to the set +/// of candidate functions, using the given function call arguments +/// and the object argument (@c Object). For example, in a call +/// @c o.f(a1,a2), @c Object will contain @c o and @c Args will contain +/// both @c a1 and @c a2. If @p SuppressUserConversions, then don't +/// allow user-defined conversions via constructors or conversion +/// operators. +void +Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, + CXXRecordDecl *ActingContext, QualType ObjectType, + Expr::Classification ObjectClassification, + llvm::ArrayRef Args, + OverloadCandidateSet& CandidateSet, + bool SuppressUserConversions) { + const FunctionProtoType* Proto + = dyn_cast(Method->getType()->getAs()); + assert(Proto && "Methods without a prototype cannot be overloaded"); + assert(!isa(Method) && + "Use AddOverloadCandidate for constructors"); + + if (!CandidateSet.isNewCandidate(Method)) + return; + + // Overload resolution is always an unevaluated context. + EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated); + + // Add this candidate + OverloadCandidate &Candidate = CandidateSet.addCandidate(Args.size() + 1); + Candidate.FoundDecl = FoundDecl; + Candidate.Function = Method; + Candidate.IsSurrogate = false; + Candidate.IgnoreObjectArgument = false; + Candidate.ExplicitCallArguments = Args.size(); + + unsigned NumArgsInProto = Proto->getNumArgs(); + + // (C++ 13.3.2p2): A candidate function having fewer than m + // parameters is viable only if it has an ellipsis in its parameter + // list (8.3.5). + if (Args.size() > NumArgsInProto && !Proto->isVariadic()) { + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_too_many_arguments; + return; + } + + // (C++ 13.3.2p2): A candidate function having more than m parameters + // is viable only if the (m+1)st parameter has a default argument + // (8.3.6). For the purposes of overload resolution, the + // parameter list is truncated on the right, so that there are + // exactly m parameters. + unsigned MinRequiredArgs = Method->getMinRequiredArguments(); + if (Args.size() < MinRequiredArgs) { + // Not enough arguments. + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_too_few_arguments; + return; + } + + Candidate.Viable = true; + + if (Method->isStatic() || ObjectType.isNull()) + // The implicit object argument is ignored. + Candidate.IgnoreObjectArgument = true; + else { + // Determine the implicit conversion sequence for the object + // parameter. + Candidate.Conversions[0] + = TryObjectArgumentInitialization(*this, ObjectType, ObjectClassification, + Method, ActingContext); + if (Candidate.Conversions[0].isBad()) { + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_bad_conversion; + return; + } + } + + // Determine the implicit conversion sequences for each of the + // arguments. + for (unsigned ArgIdx = 0; ArgIdx < Args.size(); ++ArgIdx) { + if (ArgIdx < NumArgsInProto) { + // (C++ 13.3.2p3): for F to be a viable function, there shall + // exist for each argument an implicit conversion sequence + // (13.3.3.1) that converts that argument to the corresponding + // parameter of F. + QualType ParamType = Proto->getArgType(ArgIdx); + Candidate.Conversions[ArgIdx + 1] + = TryCopyInitialization(*this, Args[ArgIdx], ParamType, + SuppressUserConversions, + /*InOverloadResolution=*/true, + /*AllowObjCWritebackConversion=*/ + getLangOpts().ObjCAutoRefCount); + if (Candidate.Conversions[ArgIdx + 1].isBad()) { + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_bad_conversion; + break; + } + } else { + // (C++ 13.3.2p2): For the purposes of overload resolution, any + // argument for which there is no corresponding parameter is + // considered to ""match the ellipsis" (C+ 13.3.3.1.3). + Candidate.Conversions[ArgIdx + 1].setEllipsis(); + } + } +} + +/// \brief Add a C++ member function template as a candidate to the candidate +/// set, using template argument deduction to produce an appropriate member +/// function template specialization. +void +Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, + DeclAccessPair FoundDecl, + CXXRecordDecl *ActingContext, + TemplateArgumentListInfo *ExplicitTemplateArgs, + QualType ObjectType, + Expr::Classification ObjectClassification, + llvm::ArrayRef Args, + OverloadCandidateSet& CandidateSet, + bool SuppressUserConversions) { + if (!CandidateSet.isNewCandidate(MethodTmpl)) + return; + + // C++ [over.match.funcs]p7: + // In each case where a candidate is a function template, candidate + // function template specializations are generated using template argument + // deduction (14.8.3, 14.8.2). Those candidates are then handled as + // candidate functions in the usual way.113) A given name can refer to one + // or more function templates and also to a set of overloaded non-template + // functions. In such a case, the candidate functions generated from each + // function template are combined with the set of non-template candidate + // functions. + TemplateDeductionInfo Info(Context, CandidateSet.getLocation()); + FunctionDecl *Specialization = 0; + if (TemplateDeductionResult Result + = DeduceTemplateArguments(MethodTmpl, ExplicitTemplateArgs, Args, + Specialization, Info)) { + OverloadCandidate &Candidate = CandidateSet.addCandidate(); + Candidate.FoundDecl = FoundDecl; + Candidate.Function = MethodTmpl->getTemplatedDecl(); + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_bad_deduction; + Candidate.IsSurrogate = false; + Candidate.IgnoreObjectArgument = false; + Candidate.ExplicitCallArguments = Args.size(); + Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result, + Info); + return; + } + + // Add the function template specialization produced by template argument + // deduction as a candidate. + assert(Specialization && "Missing member function template specialization?"); + assert(isa(Specialization) && + "Specialization is not a member function?"); + AddMethodCandidate(cast(Specialization), FoundDecl, + ActingContext, ObjectType, ObjectClassification, Args, + CandidateSet, SuppressUserConversions); +} + +/// \brief Add a C++ function template specialization as a candidate +/// in the candidate set, using template argument deduction to produce +/// an appropriate function template specialization. +void +Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, + DeclAccessPair FoundDecl, + TemplateArgumentListInfo *ExplicitTemplateArgs, + llvm::ArrayRef Args, + OverloadCandidateSet& CandidateSet, + bool SuppressUserConversions) { + if (!CandidateSet.isNewCandidate(FunctionTemplate)) + return; + + // C++ [over.match.funcs]p7: + // In each case where a candidate is a function template, candidate + // function template specializations are generated using template argument + // deduction (14.8.3, 14.8.2). Those candidates are then handled as + // candidate functions in the usual way.113) A given name can refer to one + // or more function templates and also to a set of overloaded non-template + // functions. In such a case, the candidate functions generated from each + // function template are combined with the set of non-template candidate + // functions. + TemplateDeductionInfo Info(Context, CandidateSet.getLocation()); + FunctionDecl *Specialization = 0; + if (TemplateDeductionResult Result + = DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs, Args, + Specialization, Info)) { + OverloadCandidate &Candidate = CandidateSet.addCandidate(); + Candidate.FoundDecl = FoundDecl; + Candidate.Function = FunctionTemplate->getTemplatedDecl(); + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_bad_deduction; + Candidate.IsSurrogate = false; + Candidate.IgnoreObjectArgument = false; + Candidate.ExplicitCallArguments = Args.size(); + Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result, + Info); + return; + } + + // Add the function template specialization produced by template argument + // deduction as a candidate. + assert(Specialization && "Missing function template specialization?"); + AddOverloadCandidate(Specialization, FoundDecl, Args, CandidateSet, + SuppressUserConversions); +} + +/// AddConversionCandidate - Add a C++ conversion function as a +/// candidate in the candidate set (C++ [over.match.conv], +/// C++ [over.match.copy]). From is the expression we're converting from, +/// and ToType is the type that we're eventually trying to convert to +/// (which may or may not be the same type as the type that the +/// conversion function produces). +void +Sema::AddConversionCandidate(CXXConversionDecl *Conversion, + DeclAccessPair FoundDecl, + CXXRecordDecl *ActingContext, + Expr *From, QualType ToType, + OverloadCandidateSet& CandidateSet) { + assert(!Conversion->getDescribedFunctionTemplate() && + "Conversion function templates use AddTemplateConversionCandidate"); + QualType ConvType = Conversion->getConversionType().getNonReferenceType(); + if (!CandidateSet.isNewCandidate(Conversion)) + return; + + // Overload resolution is always an unevaluated context. + EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated); + + // Add this candidate + OverloadCandidate &Candidate = CandidateSet.addCandidate(1); + Candidate.FoundDecl = FoundDecl; + Candidate.Function = Conversion; + Candidate.IsSurrogate = false; + Candidate.IgnoreObjectArgument = false; + Candidate.FinalConversion.setAsIdentityConversion(); + Candidate.FinalConversion.setFromType(ConvType); + Candidate.FinalConversion.setAllToTypes(ToType); + Candidate.Viable = true; + Candidate.ExplicitCallArguments = 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. + QualType ImplicitParamType = From->getType(); + if (const PointerType *FromPtrType = ImplicitParamType->getAs()) + ImplicitParamType = FromPtrType->getPointeeType(); + CXXRecordDecl *ConversionContext + = cast(ImplicitParamType->getAs()->getDecl()); + + Candidate.Conversions[0] + = TryObjectArgumentInitialization(*this, From->getType(), + From->Classify(Context), + 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] + QualType FromCanon + = Context.getCanonicalType(From->getType().getUnqualifiedType()); + QualType ToCanon = Context.getCanonicalType(ToType).getUnqualifiedType(); + if (FromCanon == ToCanon || IsDerivedFrom(FromCanon, ToCanon)) { + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_trivial_conversion; + return; + } + + // To determine what the conversion from the result of calling the + // conversion function to the type we're eventually trying to + // convert to (ToType), we need to synthesize a call to the + // conversion function and attempt copy initialization from it. This + // makes sure that we get the right semantics with respect to + // lvalues/rvalues and the type. Fortunately, we can allocate this + // call on the stack and we don't need its arguments to be + // well-formed. + DeclRefExpr ConversionRef(Conversion, false, Conversion->getType(), + VK_LValue, From->getLocStart()); + ImplicitCastExpr ConversionFn(ImplicitCastExpr::OnStack, + Context.getPointerType(Conversion->getType()), + CK_FunctionToPointerDecay, + &ConversionRef, VK_RValue); + + QualType ConversionType = Conversion->getConversionType(); + if (RequireCompleteType(From->getLocStart(), ConversionType, 0)) { + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_bad_final_conversion; + return; + } + + ExprValueKind VK = Expr::getValueKindForType(ConversionType); + + // 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 + // allocator). + QualType CallResultType = ConversionType.getNonLValueExprType(Context); + CallExpr Call(Context, &ConversionFn, 0, 0, CallResultType, VK, + From->getLocStart()); + ImplicitConversionSequence ICS = + TryCopyInitialization(*this, &Call, ToType, + /*SuppressUserConversions=*/true, + /*InOverloadResolution=*/false, + /*AllowObjCWritebackConversion=*/false); + + switch (ICS.getKind()) { + case ImplicitConversionSequence::StandardConversion: + Candidate.FinalConversion = ICS.Standard; + + // C++ [over.ics.user]p3: + // If the user-defined conversion is specified by a specialization of a + // conversion function template, the second standard conversion sequence + // shall have exact match rank. + if (Conversion->getPrimaryTemplate() && + GetConversionRank(ICS.Standard.Second) != ICR_Exact_Match) { + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_final_conversion_not_exact; + } + + // C++0x [dcl.init.ref]p5: + // In the second case, if the reference is an rvalue reference and + // the second standard conversion sequence of the user-defined + // conversion sequence includes an lvalue-to-rvalue conversion, the + // program is ill-formed. + if (ToType->isRValueReferenceType() && + ICS.Standard.First == ICK_Lvalue_To_Rvalue) { + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_bad_final_conversion; + } + break; + + case ImplicitConversionSequence::BadConversion: + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_bad_final_conversion; + break; + + default: + llvm_unreachable( + "Can only end up with a standard conversion sequence or failure"); + } +} + +/// \brief Adds a conversion function template specialization +/// candidate to the overload set, using template argument deduction +/// to deduce the template arguments of the conversion function +/// template from the type that we are converting to (C++ +/// [temp.deduct.conv]). +void +Sema::AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate, + DeclAccessPair FoundDecl, + CXXRecordDecl *ActingDC, + Expr *From, QualType ToType, + OverloadCandidateSet &CandidateSet) { + assert(isa(FunctionTemplate->getTemplatedDecl()) && + "Only conversion function templates permitted here"); + + if (!CandidateSet.isNewCandidate(FunctionTemplate)) + return; + + TemplateDeductionInfo Info(Context, CandidateSet.getLocation()); + CXXConversionDecl *Specialization = 0; + if (TemplateDeductionResult Result + = DeduceTemplateArguments(FunctionTemplate, ToType, + Specialization, Info)) { + OverloadCandidate &Candidate = CandidateSet.addCandidate(); + Candidate.FoundDecl = FoundDecl; + Candidate.Function = FunctionTemplate->getTemplatedDecl(); + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_bad_deduction; + Candidate.IsSurrogate = false; + Candidate.IgnoreObjectArgument = false; + Candidate.ExplicitCallArguments = 1; + Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result, + Info); + return; + } + + // Add the conversion function template specialization produced by + // template argument deduction as a candidate. + assert(Specialization && "Missing function template specialization?"); + AddConversionCandidate(Specialization, FoundDecl, ActingDC, From, ToType, + CandidateSet); +} + +/// AddSurrogateCandidate - Adds a "surrogate" candidate function that +/// converts the given @c Object to a function pointer via the +/// conversion function @c Conversion, and then attempts to call it +/// with the given arguments (C++ [over.call.object]p2-4). Proto is +/// the type of function that we'll eventually be calling. +void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion, + DeclAccessPair FoundDecl, + CXXRecordDecl *ActingContext, + const FunctionProtoType *Proto, + Expr *Object, + llvm::ArrayRef Args, + OverloadCandidateSet& CandidateSet) { + if (!CandidateSet.isNewCandidate(Conversion)) + return; + + // Overload resolution is always an unevaluated context. + EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated); + + OverloadCandidate &Candidate = CandidateSet.addCandidate(Args.size() + 1); + Candidate.FoundDecl = FoundDecl; + Candidate.Function = 0; + Candidate.Surrogate = Conversion; + Candidate.Viable = true; + Candidate.IsSurrogate = true; + Candidate.IgnoreObjectArgument = false; + Candidate.ExplicitCallArguments = Args.size(); + + // Determine the implicit conversion sequence for the implicit + // object parameter. + ImplicitConversionSequence ObjectInit + = TryObjectArgumentInitialization(*this, Object->getType(), + Object->Classify(Context), + Conversion, ActingContext); + if (ObjectInit.isBad()) { + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_bad_conversion; + Candidate.Conversions[0] = ObjectInit; + return; + } + + // The first conversion is actually a user-defined conversion whose + // first conversion is ObjectInit's standard conversion (which is + // effectively a reference binding). Record it as such. + Candidate.Conversions[0].setUserDefined(); + Candidate.Conversions[0].UserDefined.Before = ObjectInit.Standard; + Candidate.Conversions[0].UserDefined.EllipsisConversion = false; + Candidate.Conversions[0].UserDefined.HadMultipleCandidates = false; + Candidate.Conversions[0].UserDefined.ConversionFunction = Conversion; + Candidate.Conversions[0].UserDefined.FoundConversionFunction = FoundDecl; + Candidate.Conversions[0].UserDefined.After + = Candidate.Conversions[0].UserDefined.Before; + Candidate.Conversions[0].UserDefined.After.setAsIdentityConversion(); + + // Find the + unsigned NumArgsInProto = Proto->getNumArgs(); + + // (C++ 13.3.2p2): A candidate function having fewer than m + // parameters is viable only if it has an ellipsis in its parameter + // list (8.3.5). + if (Args.size() > NumArgsInProto && !Proto->isVariadic()) { + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_too_many_arguments; + return; + } + + // Function types don't have any default arguments, so just check if + // we have enough arguments. + if (Args.size() < NumArgsInProto) { + // Not enough arguments. + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_too_few_arguments; + return; + } + + // Determine the implicit conversion sequences for each of the + // arguments. + for (unsigned ArgIdx = 0; ArgIdx < Args.size(); ++ArgIdx) { + if (ArgIdx < NumArgsInProto) { + // (C++ 13.3.2p3): for F to be a viable function, there shall + // exist for each argument an implicit conversion sequence + // (13.3.3.1) that converts that argument to the corresponding + // parameter of F. + QualType ParamType = Proto->getArgType(ArgIdx); + Candidate.Conversions[ArgIdx + 1] + = TryCopyInitialization(*this, Args[ArgIdx], ParamType, + /*SuppressUserConversions=*/false, + /*InOverloadResolution=*/false, + /*AllowObjCWritebackConversion=*/ + getLangOpts().ObjCAutoRefCount); + if (Candidate.Conversions[ArgIdx + 1].isBad()) { + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_bad_conversion; + break; + } + } else { + // (C++ 13.3.2p2): For the purposes of overload resolution, any + // argument for which there is no corresponding parameter is + // considered to ""match the ellipsis" (C+ 13.3.3.1.3). + Candidate.Conversions[ArgIdx + 1].setEllipsis(); + } + } +} + +/// \brief Add overload candidates for overloaded operators that are +/// member functions. +/// +/// Add the overloaded operator candidates that are member functions +/// for the operator Op that was used in an operator expression such +/// as "x Op y". , Args/NumArgs provides the operator arguments, and +/// CandidateSet will store the added overload candidates. (C++ +/// [over.match.oper]). +void Sema::AddMemberOperatorCandidates(OverloadedOperatorKind Op, + SourceLocation OpLoc, + Expr **Args, unsigned NumArgs, + OverloadCandidateSet& CandidateSet, + SourceRange OpRange) { + DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op); + + // C++ [over.match.oper]p3: + // For a unary operator @ with an operand of a type whose + // cv-unqualified version is T1, and for a binary operator @ with + // a left operand of a type whose cv-unqualified version is T1 and + // a right operand of a type whose cv-unqualified version is T2, + // three sets of candidate functions, designated member + // candidates, non-member candidates and built-in candidates, are + // constructed as follows: + QualType T1 = Args[0]->getType(); + + // -- If T1 is a class type, the set of member candidates is the + // result of the qualified lookup of T1::operator@ + // (13.3.1.1.1); otherwise, the set of member candidates is + // empty. + if (const RecordType *T1Rec = T1->getAs()) { + // Complete the type if it can be completed. Otherwise, we're done. + if (RequireCompleteType(OpLoc, T1, PDiag())) + return; + + LookupResult Operators(*this, OpName, OpLoc, LookupOrdinaryName); + LookupQualifiedName(Operators, T1Rec->getDecl()); + Operators.suppressDiagnostics(); + + for (LookupResult::iterator Oper = Operators.begin(), + OperEnd = Operators.end(); + Oper != OperEnd; + ++Oper) + AddMethodCandidate(Oper.getPair(), Args[0]->getType(), + Args[0]->Classify(Context), Args + 1, NumArgs - 1, + CandidateSet, + /* SuppressUserConversions = */ false); + } +} + +/// AddBuiltinCandidate - Add a candidate for a built-in +/// operator. ResultTy and ParamTys are the result and parameter types +/// of the built-in candidate, respectively. Args and NumArgs are the +/// arguments being passed to the candidate. IsAssignmentOperator +/// should be true when this built-in candidate is an assignment +/// operator. NumContextualBoolArguments is the number of arguments +/// (at the beginning of the argument list) that will be contextually +/// converted to bool. +void Sema::AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys, + Expr **Args, unsigned NumArgs, + OverloadCandidateSet& CandidateSet, + bool IsAssignmentOperator, + unsigned NumContextualBoolArguments) { + // Overload resolution is always an unevaluated context. + EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated); + + // Add this candidate + OverloadCandidate &Candidate = CandidateSet.addCandidate(NumArgs); + Candidate.FoundDecl = DeclAccessPair::make(0, AS_none); + Candidate.Function = 0; + Candidate.IsSurrogate = false; + Candidate.IgnoreObjectArgument = false; + Candidate.BuiltinTypes.ResultTy = ResultTy; + for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) + Candidate.BuiltinTypes.ParamTypes[ArgIdx] = ParamTys[ArgIdx]; + + // Determine the implicit conversion sequences for each of the + // arguments. + Candidate.Viable = true; + Candidate.ExplicitCallArguments = NumArgs; + for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) { + // C++ [over.match.oper]p4: + // For the built-in assignment operators, conversions of the + // left operand are restricted as follows: + // -- no temporaries are introduced to hold the left operand, and + // -- no user-defined conversions are applied to the left + // operand to achieve a type match with the left-most + // parameter of a built-in candidate. + // + // We block these conversions by turning off user-defined + // conversions, since that is the only way that initialization of + // a reference to a non-class type can occur from something that + // is not of the same type. + if (ArgIdx < NumContextualBoolArguments) { + assert(ParamTys[ArgIdx] == Context.BoolTy && + "Contextual conversion to bool requires bool type"); + Candidate.Conversions[ArgIdx] + = TryContextuallyConvertToBool(*this, Args[ArgIdx]); + } else { + Candidate.Conversions[ArgIdx] + = TryCopyInitialization(*this, Args[ArgIdx], ParamTys[ArgIdx], + ArgIdx == 0 && IsAssignmentOperator, + /*InOverloadResolution=*/false, + /*AllowObjCWritebackConversion=*/ + getLangOpts().ObjCAutoRefCount); + } + if (Candidate.Conversions[ArgIdx].isBad()) { + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_bad_conversion; + break; + } + } +} + +/// BuiltinCandidateTypeSet - A set of types that will be used for the +/// candidate operator functions for built-in operators (C++ +/// [over.built]). The types are separated into pointer types and +/// enumeration types. +class BuiltinCandidateTypeSet { + /// TypeSet - A set of types. + typedef llvm::SmallPtrSet TypeSet; + + /// PointerTypes - The set of pointer types that will be used in the + /// built-in candidates. + TypeSet PointerTypes; + + /// MemberPointerTypes - The set of member pointer types that will be + /// used in the built-in candidates. + TypeSet MemberPointerTypes; + + /// EnumerationTypes - The set of enumeration types that will be + /// used in the built-in candidates. + TypeSet EnumerationTypes; + + /// \brief The set of vector types that will be used in the built-in + /// candidates. + TypeSet VectorTypes; + + /// \brief A flag indicating non-record types are viable candidates + bool HasNonRecordTypes; + + /// \brief A flag indicating whether either arithmetic or enumeration types + /// were present in the candidate set. + bool HasArithmeticOrEnumeralTypes; + + /// \brief A flag indicating whether the nullptr type was present in the + /// candidate set. + bool HasNullPtrType; + + /// Sema - The semantic analysis instance where we are building the + /// candidate type set. + Sema &SemaRef; + + /// Context - The AST context in which we will build the type sets. + ASTContext &Context; + + bool AddPointerWithMoreQualifiedTypeVariants(QualType Ty, + const Qualifiers &VisibleQuals); + bool AddMemberPointerWithMoreQualifiedTypeVariants(QualType Ty); + +public: + /// iterator - Iterates through the types that are part of the set. + typedef TypeSet::iterator iterator; + + BuiltinCandidateTypeSet(Sema &SemaRef) + : HasNonRecordTypes(false), + HasArithmeticOrEnumeralTypes(false), + HasNullPtrType(false), + SemaRef(SemaRef), + Context(SemaRef.Context) { } + + void AddTypesConvertedFrom(QualType Ty, + SourceLocation Loc, + bool AllowUserConversions, + bool AllowExplicitConversions, + const Qualifiers &VisibleTypeConversionsQuals); + + /// pointer_begin - First pointer type found; + iterator pointer_begin() { return PointerTypes.begin(); } + + /// pointer_end - Past the last pointer type found; + iterator pointer_end() { return PointerTypes.end(); } + + /// member_pointer_begin - First member pointer type found; + iterator member_pointer_begin() { return MemberPointerTypes.begin(); } + + /// member_pointer_end - Past the last member pointer type found; + iterator member_pointer_end() { return MemberPointerTypes.end(); } + + /// enumeration_begin - First enumeration type found; + iterator enumeration_begin() { return EnumerationTypes.begin(); } + + /// enumeration_end - Past the last enumeration type found; + iterator enumeration_end() { return EnumerationTypes.end(); } + + iterator vector_begin() { return VectorTypes.begin(); } + iterator vector_end() { return VectorTypes.end(); } + + bool hasNonRecordTypes() { return HasNonRecordTypes; } + bool hasArithmeticOrEnumeralTypes() { return HasArithmeticOrEnumeralTypes; } + bool hasNullPtrType() const { return HasNullPtrType; } +}; + +/// AddPointerWithMoreQualifiedTypeVariants - Add the pointer type @p Ty to +/// the set of pointer types along with any more-qualified variants of +/// that type. For example, if @p Ty is "int const *", this routine +/// will add "int const *", "int const volatile *", "int const +/// restrict *", and "int const volatile restrict *" to the set of +/// pointer types. Returns true if the add of @p Ty itself succeeded, +/// false otherwise. +/// +/// FIXME: what to do about extended qualifiers? +bool +BuiltinCandidateTypeSet::AddPointerWithMoreQualifiedTypeVariants(QualType Ty, + const Qualifiers &VisibleQuals) { + + // Insert this type. + if (!PointerTypes.insert(Ty)) + return false; + + QualType PointeeTy; + const PointerType *PointerTy = Ty->getAs(); + bool buildObjCPtr = false; + if (!PointerTy) { + if (const ObjCObjectPointerType *PTy = Ty->getAs()) { + PointeeTy = PTy->getPointeeType(); + buildObjCPtr = true; + } + else + llvm_unreachable("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, + // and those shouldn't have qualifier variants anyway. + if (PointeeTy->isArrayType()) + return true; + unsigned BaseCVR = PointeeTy.getCVRQualifiers(); + if (const ConstantArrayType *Array =Context.getAsConstantArrayType(PointeeTy)) + BaseCVR = Array->getElementType().getCVRQualifiers(); + bool hasVolatile = VisibleQuals.hasVolatile(); + bool hasRestrict = VisibleQuals.hasRestrict(); + + // Iterate through all strict supersets of BaseCVR. + for (unsigned CVR = BaseCVR+1; CVR <= Qualifiers::CVRMask; ++CVR) { + if ((CVR | BaseCVR) != CVR) continue; + // Skip over Volatile/Restrict if no Volatile/Restrict found anywhere + // in the types. + if ((CVR & Qualifiers::Volatile) && !hasVolatile) continue; + if ((CVR & Qualifiers::Restrict) && !hasRestrict) continue; + QualType QPointeeTy = Context.getCVRQualifiedType(PointeeTy, CVR); + if (!buildObjCPtr) + PointerTypes.insert(Context.getPointerType(QPointeeTy)); + else + PointerTypes.insert(Context.getObjCObjectPointerType(QPointeeTy)); + } + + return true; +} + +/// AddMemberPointerWithMoreQualifiedTypeVariants - Add the pointer type @p Ty +/// to the set of pointer types along with any more-qualified variants of +/// that type. For example, if @p Ty is "int const *", this routine +/// will add "int const *", "int const volatile *", "int const +/// restrict *", and "int const volatile restrict *" to the set of +/// pointer types. Returns true if the add of @p Ty itself succeeded, +/// false otherwise. +/// +/// FIXME: what to do about extended qualifiers? +bool +BuiltinCandidateTypeSet::AddMemberPointerWithMoreQualifiedTypeVariants( + QualType Ty) { + // Insert this type. + if (!MemberPointerTypes.insert(Ty)) + return false; + + const MemberPointerType *PointerTy = Ty->getAs(); + assert(PointerTy && "type was not a member pointer type!"); + + QualType 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, + // and those shouldn't have qualifier variants anyway. + if (PointeeTy->isArrayType()) + return true; + const Type *ClassTy = PointerTy->getClass(); + + // Iterate through all strict supersets of the pointee type's CVR + // qualifiers. + unsigned BaseCVR = PointeeTy.getCVRQualifiers(); + for (unsigned CVR = BaseCVR+1; CVR <= Qualifiers::CVRMask; ++CVR) { + if ((CVR | BaseCVR) != CVR) continue; + + QualType QPointeeTy = Context.getCVRQualifiedType(PointeeTy, CVR); + MemberPointerTypes.insert( + Context.getMemberPointerType(QPointeeTy, ClassTy)); + } + + return true; +} + +/// AddTypesConvertedFrom - Add each of the types to which the type @p +/// Ty can be implicit converted to the given set of @p Types. We're +/// primarily interested in pointer types and enumeration types. We also +/// take member pointer types, for the conditional operator. +/// AllowUserConversions is true if we should look at the conversion +/// functions of a class type, and AllowExplicitConversions if we +/// should also include the explicit conversion functions of a class +/// type. +void +BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty, + SourceLocation Loc, + bool AllowUserConversions, + bool AllowExplicitConversions, + const Qualifiers &VisibleQuals) { + // Only deal with canonical types. + Ty = Context.getCanonicalType(Ty); + + // Look through reference types; they aren't part of the type of an + // expression for the purposes of conversions. + if (const ReferenceType *RefTy = Ty->getAs()) + Ty = RefTy->getPointeeType(); + + // If we're dealing with an array type, decay to the pointer. + if (Ty->isArrayType()) + Ty = SemaRef.Context.getArrayDecayedType(Ty); + + // Otherwise, we don't care about qualifiers on the type. + Ty = Ty.getLocalUnqualifiedType(); + + // Flag if we ever add a non-record type. + const RecordType *TyRec = Ty->getAs(); + HasNonRecordTypes = HasNonRecordTypes || !TyRec; + + // Flag if we encounter an arithmetic type. + HasArithmeticOrEnumeralTypes = + HasArithmeticOrEnumeralTypes || Ty->isArithmeticType(); + + 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)) + return; + } else if (Ty->isMemberPointerType()) { + // Member pointers are far easier, since the pointee can't be converted. + if (!AddMemberPointerWithMoreQualifiedTypeVariants(Ty)) + return; + } else if (Ty->isEnumeralType()) { + HasArithmeticOrEnumeralTypes = true; + EnumerationTypes.insert(Ty); + } else if (Ty->isVectorType()) { + // We treat vector types as arithmetic types in many contexts as an + // extension. + HasArithmeticOrEnumeralTypes = true; + VectorTypes.insert(Ty); + } else if (Ty->isNullPtrType()) { + HasNullPtrType = true; + } else if (AllowUserConversions && TyRec) { + // No conversion functions in incomplete types. + if (SemaRef.RequireCompleteType(Loc, Ty, 0)) + return; + + CXXRecordDecl *ClassDecl = cast(TyRec->getDecl()); + const UnresolvedSetImpl *Conversions + = ClassDecl->getVisibleConversionFunctions(); + for (UnresolvedSetImpl::iterator I = Conversions->begin(), + E = Conversions->end(); I != E; ++I) { + NamedDecl *D = I.getDecl(); + if (isa(D)) + D = cast(D)->getTargetDecl(); + + // Skip conversion function templates; they don't tell us anything + // about which builtin types we can convert to. + if (isa(D)) + continue; + + CXXConversionDecl *Conv = cast(D); + if (AllowExplicitConversions || !Conv->isExplicit()) { + AddTypesConvertedFrom(Conv->getConversionType(), Loc, false, false, + VisibleQuals); + } + } + } +} + +/// \brief Helper function for AddBuiltinOperatorCandidates() that adds +/// the volatile- and non-volatile-qualified assignment operators for the +/// given type to the candidate set. +static void AddBuiltinAssignmentOperatorCandidates(Sema &S, + QualType T, + Expr **Args, + unsigned NumArgs, + OverloadCandidateSet &CandidateSet) { + QualType ParamTypes[2]; + + // T& operator=(T&, T) + ParamTypes[0] = S.Context.getLValueReferenceType(T); + ParamTypes[1] = T; + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet, + /*IsAssignmentOperator=*/true); + + if (!S.Context.getCanonicalType(T).isVolatileQualified()) { + // volatile T& operator=(volatile T&, T) + ParamTypes[0] + = S.Context.getLValueReferenceType(S.Context.getVolatileType(T)); + ParamTypes[1] = T; + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet, + /*IsAssignmentOperator=*/true); + } +} + +/// CollectVRQualifiers - This routine returns Volatile/Restrict qualifiers, +/// if any, found in visible type conversion functions found in ArgExpr's type. +static Qualifiers CollectVRQualifiers(ASTContext &Context, Expr* ArgExpr) { + Qualifiers VRQuals; + const RecordType *TyRec; + if (const MemberPointerType *RHSMPType = + ArgExpr->getType()->getAs()) + TyRec = RHSMPType->getClass()->getAs(); + else + TyRec = ArgExpr->getType()->getAs(); + if (!TyRec) { + // Just to be safe, assume the worst case. + VRQuals.addVolatile(); + VRQuals.addRestrict(); + return VRQuals; + } + + CXXRecordDecl *ClassDecl = cast(TyRec->getDecl()); + if (!ClassDecl->hasDefinition()) + return VRQuals; + + const UnresolvedSetImpl *Conversions = + ClassDecl->getVisibleConversionFunctions(); + + for (UnresolvedSetImpl::iterator I = Conversions->begin(), + E = Conversions->end(); I != E; ++I) { + NamedDecl *D = I.getDecl(); + if (isa(D)) + D = cast(D)->getTargetDecl(); + if (CXXConversionDecl *Conv = dyn_cast(D)) { + QualType CanTy = Context.getCanonicalType(Conv->getConversionType()); + if (const ReferenceType *ResTypeRef = CanTy->getAs()) + CanTy = ResTypeRef->getPointeeType(); + // Need to go down the pointer/mempointer chain and add qualifiers + // as see them. + bool done = false; + while (!done) { + if (const PointerType *ResTypePtr = CanTy->getAs()) + CanTy = ResTypePtr->getPointeeType(); + else if (const MemberPointerType *ResTypeMPtr = + CanTy->getAs()) + CanTy = ResTypeMPtr->getPointeeType(); + else + done = true; + if (CanTy.isVolatileQualified()) + VRQuals.addVolatile(); + if (CanTy.isRestrictQualified()) + VRQuals.addRestrict(); + if (VRQuals.hasRestrict() && VRQuals.hasVolatile()) + return VRQuals; + } + } + } + return VRQuals; +} + +namespace { + +/// \brief Helper class to manage the addition of builtin operator overload +/// candidates. It provides shared state and utility methods used throughout +/// the process, as well as a helper method to add each group of builtin +/// operator overloads from the standard to a candidate set. +class BuiltinOperatorOverloadBuilder { + // Common instance state available to all overload candidate addition methods. + Sema &S; + Expr **Args; + unsigned NumArgs; + Qualifiers VisibleTypeConversionsQuals; + bool HasArithmeticOrEnumeralCandidateType; + SmallVectorImpl &CandidateTypes; + OverloadCandidateSet &CandidateSet; + + // Define some constants used to index and iterate over the arithemetic types + // provided via the getArithmeticType() method below. + // The "promoted arithmetic types" are the arithmetic + // types are that preserved by promotion (C++ [over.built]p2). + static const unsigned FirstIntegralType = 3; + static const unsigned LastIntegralType = 18; + static const unsigned FirstPromotedIntegralType = 3, + LastPromotedIntegralType = 9; + static const unsigned FirstPromotedArithmeticType = 0, + LastPromotedArithmeticType = 9; + static const unsigned NumArithmeticTypes = 18; + + /// \brief Get the canonical type for a given arithmetic type index. + CanQualType getArithmeticType(unsigned index) { + assert(index < NumArithmeticTypes); + static CanQualType ASTContext::* const + ArithmeticTypes[NumArithmeticTypes] = { + // Start of promoted types. + &ASTContext::FloatTy, + &ASTContext::DoubleTy, + &ASTContext::LongDoubleTy, + + // Start of integral types. + &ASTContext::IntTy, + &ASTContext::LongTy, + &ASTContext::LongLongTy, + &ASTContext::UnsignedIntTy, + &ASTContext::UnsignedLongTy, + &ASTContext::UnsignedLongLongTy, + // End of promoted types. + + &ASTContext::BoolTy, + &ASTContext::CharTy, + &ASTContext::WCharTy, + &ASTContext::Char16Ty, + &ASTContext::Char32Ty, + &ASTContext::SignedCharTy, + &ASTContext::ShortTy, + &ASTContext::UnsignedCharTy, + &ASTContext::UnsignedShortTy, + // End of integral types. + // FIXME: What about complex? + }; + return S.Context.*ArithmeticTypes[index]; + } + + /// \brief Gets the canonical type resulting from the usual arithemetic + /// converions for the given arithmetic types. + CanQualType getUsualArithmeticConversions(unsigned L, unsigned R) { + // Accelerator table for performing the usual arithmetic conversions. + // The rules are basically: + // - if either is floating-point, use the wider floating-point + // - if same signedness, use the higher rank + // - if same size, use unsigned of the higher rank + // - use the larger type + // These rules, together with the axiom that higher ranks are + // never smaller, are sufficient to precompute all of these results + // *except* when dealing with signed types of higher rank. + // (we could precompute SLL x UI for all known platforms, but it's + // better not to make any assumptions). + enum PromotedType { + Flt, Dbl, LDbl, SI, SL, SLL, UI, UL, ULL, Dep=-1 + }; + static PromotedType ConversionsTable[LastPromotedArithmeticType] + [LastPromotedArithmeticType] = { + /* Flt*/ { Flt, Dbl, LDbl, Flt, Flt, Flt, Flt, Flt, Flt }, + /* Dbl*/ { Dbl, Dbl, LDbl, Dbl, Dbl, Dbl, Dbl, Dbl, Dbl }, + /*LDbl*/ { LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl }, + /* SI*/ { Flt, Dbl, LDbl, SI, SL, SLL, UI, UL, ULL }, + /* SL*/ { Flt, Dbl, LDbl, SL, SL, SLL, Dep, UL, ULL }, + /* SLL*/ { Flt, Dbl, LDbl, SLL, SLL, SLL, Dep, Dep, ULL }, + /* UI*/ { Flt, Dbl, LDbl, UI, Dep, Dep, UI, UL, ULL }, + /* UL*/ { Flt, Dbl, LDbl, UL, UL, Dep, UL, UL, ULL }, + /* ULL*/ { Flt, Dbl, LDbl, ULL, ULL, ULL, ULL, ULL, ULL }, + }; + + assert(L < LastPromotedArithmeticType); + assert(R < LastPromotedArithmeticType); + int Idx = ConversionsTable[L][R]; + + // Fast path: the table gives us a concrete answer. + if (Idx != Dep) return getArithmeticType(Idx); + + // Slow path: we need to compare widths. + // An invariant is that the signed type has higher rank. + CanQualType LT = getArithmeticType(L), + RT = getArithmeticType(R); + unsigned LW = S.Context.getIntWidth(LT), + RW = S.Context.getIntWidth(RT); + + // If they're different widths, use the signed type. + if (LW > RW) return LT; + else if (LW < RW) return RT; + + // Otherwise, use the unsigned type of the signed type's rank. + if (L == SL || R == SL) return S.Context.UnsignedLongTy; + assert(L == SLL || R == SLL); + return S.Context.UnsignedLongLongTy; + } + + /// \brief Helper method to factor out the common pattern of adding overloads + /// for '++' and '--' builtin operators. + void addPlusPlusMinusMinusStyleOverloads(QualType CandidateTy, + bool HasVolatile) { + QualType ParamTypes[2] = { + S.Context.getLValueReferenceType(CandidateTy), + S.Context.IntTy + }; + + // Non-volatile version. + if (NumArgs == 1) + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet); + else + S.AddBuiltinCandidate(CandidateTy, ParamTypes, Args, 2, CandidateSet); + + // Use a heuristic to reduce number of builtin candidates in the set: + // add volatile version only if there are conversions to a volatile type. + if (HasVolatile) { + ParamTypes[0] = + S.Context.getLValueReferenceType( + S.Context.getVolatileType(CandidateTy)); + if (NumArgs == 1) + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet); + else + S.AddBuiltinCandidate(CandidateTy, ParamTypes, Args, 2, CandidateSet); + } + } + +public: + BuiltinOperatorOverloadBuilder( + Sema &S, Expr **Args, unsigned NumArgs, + Qualifiers VisibleTypeConversionsQuals, + bool HasArithmeticOrEnumeralCandidateType, + SmallVectorImpl &CandidateTypes, + OverloadCandidateSet &CandidateSet) + : S(S), Args(Args), NumArgs(NumArgs), + VisibleTypeConversionsQuals(VisibleTypeConversionsQuals), + HasArithmeticOrEnumeralCandidateType( + HasArithmeticOrEnumeralCandidateType), + CandidateTypes(CandidateTypes), + CandidateSet(CandidateSet) { + // Validate some of our static helper constants in debug builds. + assert(getArithmeticType(FirstPromotedIntegralType) == S.Context.IntTy && + "Invalid first promoted integral type"); + assert(getArithmeticType(LastPromotedIntegralType - 1) + == S.Context.UnsignedLongLongTy && + "Invalid last promoted integral type"); + assert(getArithmeticType(FirstPromotedArithmeticType) + == S.Context.FloatTy && + "Invalid first promoted arithmetic type"); + assert(getArithmeticType(LastPromotedArithmeticType - 1) + == S.Context.UnsignedLongLongTy && + "Invalid last promoted arithmetic type"); + } + + // C++ [over.built]p3: + // + // For every pair (T, VQ), where T is an arithmetic type, and VQ + // is either volatile or empty, there exist candidate operator + // functions of the form + // + // VQ T& operator++(VQ T&); + // T operator++(VQ T&, int); + // + // C++ [over.built]p4: + // + // For every pair (T, VQ), where T is an arithmetic type other + // than bool, and VQ is either volatile or empty, there exist + // candidate operator functions of the form + // + // VQ T& operator--(VQ T&); + // T operator--(VQ T&, int); + void addPlusPlusMinusMinusArithmeticOverloads(OverloadedOperatorKind Op) { + if (!HasArithmeticOrEnumeralCandidateType) + return; + + for (unsigned Arith = (Op == OO_PlusPlus? 0 : 1); + Arith < NumArithmeticTypes; ++Arith) { + addPlusPlusMinusMinusStyleOverloads( + getArithmeticType(Arith), + VisibleTypeConversionsQuals.hasVolatile()); + } + } + + // C++ [over.built]p5: + // + // For every pair (T, VQ), where T is a cv-qualified or + // cv-unqualified object type, and VQ is either volatile or + // empty, there exist candidate operator functions of the form + // + // T*VQ& operator++(T*VQ&); + // T*VQ& operator--(T*VQ&); + // T* operator++(T*VQ&, int); + // T* operator--(T*VQ&, int); + void addPlusPlusMinusMinusPointerOverloads() { + for (BuiltinCandidateTypeSet::iterator + Ptr = CandidateTypes[0].pointer_begin(), + PtrEnd = CandidateTypes[0].pointer_end(); + Ptr != PtrEnd; ++Ptr) { + // Skip pointer types that aren't pointers to object types. + if (!(*Ptr)->getPointeeType()->isObjectType()) + continue; + + addPlusPlusMinusMinusStyleOverloads(*Ptr, + (!S.Context.getCanonicalType(*Ptr).isVolatileQualified() && + VisibleTypeConversionsQuals.hasVolatile())); + } + } + + // C++ [over.built]p6: + // For every cv-qualified or cv-unqualified object type T, there + // exist candidate operator functions of the form + // + // T& operator*(T*); + // + // C++ [over.built]p7: + // For every function type T that does not have cv-qualifiers or a + // ref-qualifier, there exist candidate operator functions of the form + // T& operator*(T*); + void addUnaryStarPointerOverloads() { + for (BuiltinCandidateTypeSet::iterator + Ptr = CandidateTypes[0].pointer_begin(), + PtrEnd = CandidateTypes[0].pointer_end(); + Ptr != PtrEnd; ++Ptr) { + QualType ParamTy = *Ptr; + QualType PointeeTy = ParamTy->getPointeeType(); + if (!PointeeTy->isObjectType() && !PointeeTy->isFunctionType()) + continue; + + if (const FunctionProtoType *Proto =PointeeTy->getAs()) + if (Proto->getTypeQuals() || Proto->getRefQualifier()) + continue; + + S.AddBuiltinCandidate(S.Context.getLValueReferenceType(PointeeTy), + &ParamTy, Args, 1, CandidateSet); + } + } + + // C++ [over.built]p9: + // For every promoted arithmetic type T, there exist candidate + // operator functions of the form + // + // T operator+(T); + // T operator-(T); + void addUnaryPlusOrMinusArithmeticOverloads() { + if (!HasArithmeticOrEnumeralCandidateType) + return; + + for (unsigned Arith = FirstPromotedArithmeticType; + Arith < LastPromotedArithmeticType; ++Arith) { + QualType ArithTy = getArithmeticType(Arith); + S.AddBuiltinCandidate(ArithTy, &ArithTy, Args, 1, CandidateSet); + } + + // Extension: We also add these operators for vector types. + for (BuiltinCandidateTypeSet::iterator + Vec = CandidateTypes[0].vector_begin(), + VecEnd = CandidateTypes[0].vector_end(); + Vec != VecEnd; ++Vec) { + QualType VecTy = *Vec; + S.AddBuiltinCandidate(VecTy, &VecTy, Args, 1, CandidateSet); + } + } + + // C++ [over.built]p8: + // For every type T, there exist candidate operator functions of + // the form + // + // T* operator+(T*); + void addUnaryPlusPointerOverloads() { + for (BuiltinCandidateTypeSet::iterator + Ptr = CandidateTypes[0].pointer_begin(), + PtrEnd = CandidateTypes[0].pointer_end(); + Ptr != PtrEnd; ++Ptr) { + QualType ParamTy = *Ptr; + S.AddBuiltinCandidate(ParamTy, &ParamTy, Args, 1, CandidateSet); + } + } + + // C++ [over.built]p10: + // For every promoted integral type T, there exist candidate + // operator functions of the form + // + // T operator~(T); + void addUnaryTildePromotedIntegralOverloads() { + if (!HasArithmeticOrEnumeralCandidateType) + return; + + for (unsigned Int = FirstPromotedIntegralType; + Int < LastPromotedIntegralType; ++Int) { + QualType IntTy = getArithmeticType(Int); + S.AddBuiltinCandidate(IntTy, &IntTy, Args, 1, CandidateSet); + } + + // Extension: We also add this operator for vector types. + for (BuiltinCandidateTypeSet::iterator + Vec = CandidateTypes[0].vector_begin(), + VecEnd = CandidateTypes[0].vector_end(); + Vec != VecEnd; ++Vec) { + QualType VecTy = *Vec; + S.AddBuiltinCandidate(VecTy, &VecTy, Args, 1, CandidateSet); + } + } + + // C++ [over.match.oper]p16: + // For every pointer to member type T, there exist candidate operator + // functions of the form + // + // bool operator==(T,T); + // bool operator!=(T,T); + void addEqualEqualOrNotEqualMemberPointerOverloads() { + /// Set of (canonical) types that we've already handled. + llvm::SmallPtrSet AddedTypes; + + for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) { + for (BuiltinCandidateTypeSet::iterator + MemPtr = CandidateTypes[ArgIdx].member_pointer_begin(), + MemPtrEnd = CandidateTypes[ArgIdx].member_pointer_end(); + MemPtr != MemPtrEnd; + ++MemPtr) { + // Don't add the same builtin candidate twice. + if (!AddedTypes.insert(S.Context.getCanonicalType(*MemPtr))) + continue; + + QualType ParamTypes[2] = { *MemPtr, *MemPtr }; + S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, 2, + CandidateSet); + } + } + } + + // C++ [over.built]p15: + // + // For every T, where T is an enumeration type, a pointer type, or + // std::nullptr_t, there exist candidate operator functions of the form + // + // bool operator<(T, T); + // bool operator>(T, T); + // bool operator<=(T, T); + // bool operator>=(T, T); + // bool operator==(T, T); + // bool operator!=(T, T); + void addRelationalPointerOrEnumeralOverloads() { + // C++ [over.built]p1: + // If there is a user-written candidate with the same name and parameter + // types as a built-in candidate operator function, the built-in operator + // function is hidden and is not included in the set of candidate + // functions. + // + // The text is actually in a note, but if we don't implement it then we end + // up with ambiguities when the user provides an overloaded operator for + // an enumeration type. Note that only enumeration types have this problem, + // so we track which enumeration types we've seen operators for. Also, the + // only other overloaded operator with enumeration argumenst, operator=, + // cannot be overloaded for enumeration types, so this is the only place + // where we must suppress candidates like this. + llvm::DenseSet > + UserDefinedBinaryOperators; + + for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) { + if (CandidateTypes[ArgIdx].enumeration_begin() != + CandidateTypes[ArgIdx].enumeration_end()) { + for (OverloadCandidateSet::iterator C = CandidateSet.begin(), + CEnd = CandidateSet.end(); + C != CEnd; ++C) { + if (!C->Viable || !C->Function || C->Function->getNumParams() != 2) + continue; + + QualType FirstParamType = + C->Function->getParamDecl(0)->getType().getUnqualifiedType(); + QualType SecondParamType = + C->Function->getParamDecl(1)->getType().getUnqualifiedType(); + + // Skip if either parameter isn't of enumeral type. + if (!FirstParamType->isEnumeralType() || + !SecondParamType->isEnumeralType()) + continue; + + // Add this operator to the set of known user-defined operators. + UserDefinedBinaryOperators.insert( + std::make_pair(S.Context.getCanonicalType(FirstParamType), + S.Context.getCanonicalType(SecondParamType))); + } + } + } + + /// Set of (canonical) types that we've already handled. + llvm::SmallPtrSet AddedTypes; + + for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) { + for (BuiltinCandidateTypeSet::iterator + Ptr = CandidateTypes[ArgIdx].pointer_begin(), + PtrEnd = CandidateTypes[ArgIdx].pointer_end(); + Ptr != PtrEnd; ++Ptr) { + // Don't add the same builtin candidate twice. + if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr))) + continue; + + QualType ParamTypes[2] = { *Ptr, *Ptr }; + S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, 2, + CandidateSet); + } + for (BuiltinCandidateTypeSet::iterator + Enum = CandidateTypes[ArgIdx].enumeration_begin(), + EnumEnd = CandidateTypes[ArgIdx].enumeration_end(); + Enum != EnumEnd; ++Enum) { + CanQualType CanonType = S.Context.getCanonicalType(*Enum); + + // Don't add the same builtin candidate twice, or if a user defined + // candidate exists. + if (!AddedTypes.insert(CanonType) || + UserDefinedBinaryOperators.count(std::make_pair(CanonType, + CanonType))) + continue; + + QualType ParamTypes[2] = { *Enum, *Enum }; + S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, 2, + CandidateSet); + } + + if (CandidateTypes[ArgIdx].hasNullPtrType()) { + CanQualType NullPtrTy = S.Context.getCanonicalType(S.Context.NullPtrTy); + if (AddedTypes.insert(NullPtrTy) && + !UserDefinedBinaryOperators.count(std::make_pair(NullPtrTy, + NullPtrTy))) { + QualType ParamTypes[2] = { NullPtrTy, NullPtrTy }; + S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, 2, + CandidateSet); + } + } + } + } + + // C++ [over.built]p13: + // + // For every cv-qualified or cv-unqualified object type T + // there exist candidate operator functions of the form + // + // T* operator+(T*, ptrdiff_t); + // T& operator[](T*, ptrdiff_t); [BELOW] + // T* operator-(T*, ptrdiff_t); + // T* operator+(ptrdiff_t, T*); + // T& operator[](ptrdiff_t, T*); [BELOW] + // + // C++ [over.built]p14: + // + // For every T, where T is a pointer to object type, there + // exist candidate operator functions of the form + // + // ptrdiff_t operator-(T, T); + void addBinaryPlusOrMinusPointerOverloads(OverloadedOperatorKind Op) { + /// Set of (canonical) types that we've already handled. + llvm::SmallPtrSet AddedTypes; + + for (int Arg = 0; Arg < 2; ++Arg) { + QualType AsymetricParamTypes[2] = { + S.Context.getPointerDiffType(), + S.Context.getPointerDiffType(), + }; + for (BuiltinCandidateTypeSet::iterator + Ptr = CandidateTypes[Arg].pointer_begin(), + PtrEnd = CandidateTypes[Arg].pointer_end(); + Ptr != PtrEnd; ++Ptr) { + QualType PointeeTy = (*Ptr)->getPointeeType(); + if (!PointeeTy->isObjectType()) + continue; + + AsymetricParamTypes[Arg] = *Ptr; + if (Arg == 0 || Op == OO_Plus) { + // operator+(T*, ptrdiff_t) or operator-(T*, ptrdiff_t) + // T* operator+(ptrdiff_t, T*); + S.AddBuiltinCandidate(*Ptr, AsymetricParamTypes, Args, 2, + CandidateSet); + } + if (Op == OO_Minus) { + // ptrdiff_t operator-(T, T); + if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr))) + continue; + + QualType ParamTypes[2] = { *Ptr, *Ptr }; + S.AddBuiltinCandidate(S.Context.getPointerDiffType(), ParamTypes, + Args, 2, CandidateSet); + } + } + } + } + + // C++ [over.built]p12: + // + // For every pair of promoted arithmetic types L and R, there + // exist candidate operator functions of the form + // + // LR operator*(L, R); + // LR operator/(L, R); + // LR operator+(L, R); + // LR operator-(L, R); + // bool operator<(L, R); + // bool operator>(L, R); + // bool operator<=(L, R); + // bool operator>=(L, R); + // bool operator==(L, R); + // bool operator!=(L, R); + // + // where LR is the result of the usual arithmetic conversions + // between types L and R. + // + // C++ [over.built]p24: + // + // For every pair of promoted arithmetic types L and R, there exist + // candidate operator functions of the form + // + // LR operator?(bool, L, R); + // + // where LR is the result of the usual arithmetic conversions + // between types L and R. + // Our candidates ignore the first parameter. + void addGenericBinaryArithmeticOverloads(bool isComparison) { + if (!HasArithmeticOrEnumeralCandidateType) + return; + + for (unsigned Left = FirstPromotedArithmeticType; + Left < LastPromotedArithmeticType; ++Left) { + for (unsigned Right = FirstPromotedArithmeticType; + Right < LastPromotedArithmeticType; ++Right) { + QualType LandR[2] = { getArithmeticType(Left), + getArithmeticType(Right) }; + QualType Result = + isComparison ? S.Context.BoolTy + : getUsualArithmeticConversions(Left, Right); + S.AddBuiltinCandidate(Result, LandR, Args, 2, CandidateSet); + } + } + + // Extension: Add the binary operators ==, !=, <, <=, >=, >, *, /, and the + // conditional operator for vector types. + for (BuiltinCandidateTypeSet::iterator + Vec1 = CandidateTypes[0].vector_begin(), + Vec1End = CandidateTypes[0].vector_end(); + Vec1 != Vec1End; ++Vec1) { + for (BuiltinCandidateTypeSet::iterator + Vec2 = CandidateTypes[1].vector_begin(), + Vec2End = CandidateTypes[1].vector_end(); + Vec2 != Vec2End; ++Vec2) { + QualType LandR[2] = { *Vec1, *Vec2 }; + QualType Result = S.Context.BoolTy; + if (!isComparison) { + if ((*Vec1)->isExtVectorType() || !(*Vec2)->isExtVectorType()) + Result = *Vec1; + else + Result = *Vec2; + } + + S.AddBuiltinCandidate(Result, LandR, Args, 2, CandidateSet); + } + } + } + + // C++ [over.built]p17: + // + // For every pair of promoted integral types L and R, there + // exist candidate operator functions of the form + // + // LR operator%(L, R); + // LR operator&(L, R); + // LR operator^(L, R); + // LR operator|(L, R); + // L operator<<(L, R); + // L operator>>(L, R); + // + // where LR is the result of the usual arithmetic conversions + // between types L and R. + void addBinaryBitwiseArithmeticOverloads(OverloadedOperatorKind Op) { + if (!HasArithmeticOrEnumeralCandidateType) + return; + + for (unsigned Left = FirstPromotedIntegralType; + Left < LastPromotedIntegralType; ++Left) { + for (unsigned Right = FirstPromotedIntegralType; + Right < LastPromotedIntegralType; ++Right) { + QualType LandR[2] = { getArithmeticType(Left), + getArithmeticType(Right) }; + QualType Result = (Op == OO_LessLess || Op == OO_GreaterGreater) + ? LandR[0] + : getUsualArithmeticConversions(Left, Right); + S.AddBuiltinCandidate(Result, LandR, Args, 2, CandidateSet); + } + } + } + + // C++ [over.built]p20: + // + // For every pair (T, VQ), where T is an enumeration or + // pointer to member type and VQ is either volatile or + // empty, there exist candidate operator functions of the form + // + // VQ T& operator=(VQ T&, T); + void addAssignmentMemberPointerOrEnumeralOverloads() { + /// Set of (canonical) types that we've already handled. + llvm::SmallPtrSet AddedTypes; + + for (unsigned ArgIdx = 0; ArgIdx < 2; ++ArgIdx) { + for (BuiltinCandidateTypeSet::iterator + Enum = CandidateTypes[ArgIdx].enumeration_begin(), + EnumEnd = CandidateTypes[ArgIdx].enumeration_end(); + Enum != EnumEnd; ++Enum) { + if (!AddedTypes.insert(S.Context.getCanonicalType(*Enum))) + continue; + + AddBuiltinAssignmentOperatorCandidates(S, *Enum, Args, 2, + CandidateSet); + } + + for (BuiltinCandidateTypeSet::iterator + MemPtr = CandidateTypes[ArgIdx].member_pointer_begin(), + MemPtrEnd = CandidateTypes[ArgIdx].member_pointer_end(); + MemPtr != MemPtrEnd; ++MemPtr) { + if (!AddedTypes.insert(S.Context.getCanonicalType(*MemPtr))) + continue; + + AddBuiltinAssignmentOperatorCandidates(S, *MemPtr, Args, 2, + CandidateSet); + } + } + } + + // C++ [over.built]p19: + // + // For every pair (T, VQ), where T is any type and VQ is either + // volatile or empty, there exist candidate operator functions + // of the form + // + // T*VQ& operator=(T*VQ&, T*); + // + // C++ [over.built]p21: + // + // For every pair (T, VQ), where T is a cv-qualified or + // cv-unqualified object type and VQ is either volatile or + // empty, there exist candidate operator functions of the form + // + // T*VQ& operator+=(T*VQ&, ptrdiff_t); + // T*VQ& operator-=(T*VQ&, ptrdiff_t); + void addAssignmentPointerOverloads(bool isEqualOp) { + /// Set of (canonical) types that we've already handled. + llvm::SmallPtrSet AddedTypes; + + for (BuiltinCandidateTypeSet::iterator + Ptr = CandidateTypes[0].pointer_begin(), + PtrEnd = CandidateTypes[0].pointer_end(); + Ptr != PtrEnd; ++Ptr) { + // If this is operator=, keep track of the builtin candidates we added. + if (isEqualOp) + AddedTypes.insert(S.Context.getCanonicalType(*Ptr)); + else if (!(*Ptr)->getPointeeType()->isObjectType()) + continue; + + // non-volatile version + QualType ParamTypes[2] = { + S.Context.getLValueReferenceType(*Ptr), + isEqualOp ? *Ptr : S.Context.getPointerDiffType(), + }; + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet, + /*IsAssigmentOperator=*/ isEqualOp); + + if (!S.Context.getCanonicalType(*Ptr).isVolatileQualified() && + VisibleTypeConversionsQuals.hasVolatile()) { + // volatile version + ParamTypes[0] = + S.Context.getLValueReferenceType(S.Context.getVolatileType(*Ptr)); + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet, + /*IsAssigmentOperator=*/isEqualOp); + } + } + + if (isEqualOp) { + for (BuiltinCandidateTypeSet::iterator + Ptr = CandidateTypes[1].pointer_begin(), + PtrEnd = CandidateTypes[1].pointer_end(); + Ptr != PtrEnd; ++Ptr) { + // Make sure we don't add the same candidate twice. + if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr))) + continue; + + QualType ParamTypes[2] = { + S.Context.getLValueReferenceType(*Ptr), + *Ptr, + }; + + // non-volatile version + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet, + /*IsAssigmentOperator=*/true); + + if (!S.Context.getCanonicalType(*Ptr).isVolatileQualified() && + VisibleTypeConversionsQuals.hasVolatile()) { + // volatile version + ParamTypes[0] = + S.Context.getLValueReferenceType(S.Context.getVolatileType(*Ptr)); + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, + CandidateSet, /*IsAssigmentOperator=*/true); + } + } + } + } + + // C++ [over.built]p18: + // + // For every triple (L, VQ, R), where L is an arithmetic type, + // VQ is either volatile or empty, and R is a promoted + // arithmetic type, there exist candidate operator functions of + // the form + // + // VQ L& operator=(VQ L&, R); + // VQ L& operator*=(VQ L&, R); + // VQ L& operator/=(VQ L&, R); + // VQ L& operator+=(VQ L&, R); + // VQ L& operator-=(VQ L&, R); + void addAssignmentArithmeticOverloads(bool isEqualOp) { + if (!HasArithmeticOrEnumeralCandidateType) + return; + + for (unsigned Left = 0; Left < NumArithmeticTypes; ++Left) { + for (unsigned Right = FirstPromotedArithmeticType; + Right < LastPromotedArithmeticType; ++Right) { + QualType ParamTypes[2]; + ParamTypes[1] = getArithmeticType(Right); + + // Add this built-in operator as a candidate (VQ is empty). + ParamTypes[0] = + S.Context.getLValueReferenceType(getArithmeticType(Left)); + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet, + /*IsAssigmentOperator=*/isEqualOp); + + // Add this built-in operator as a candidate (VQ is 'volatile'). + if (VisibleTypeConversionsQuals.hasVolatile()) { + ParamTypes[0] = + S.Context.getVolatileType(getArithmeticType(Left)); + ParamTypes[0] = S.Context.getLValueReferenceType(ParamTypes[0]); + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, + CandidateSet, + /*IsAssigmentOperator=*/isEqualOp); + } + } + } + + // Extension: Add the binary operators =, +=, -=, *=, /= for vector types. + for (BuiltinCandidateTypeSet::iterator + Vec1 = CandidateTypes[0].vector_begin(), + Vec1End = CandidateTypes[0].vector_end(); + Vec1 != Vec1End; ++Vec1) { + for (BuiltinCandidateTypeSet::iterator + Vec2 = CandidateTypes[1].vector_begin(), + Vec2End = CandidateTypes[1].vector_end(); + Vec2 != Vec2End; ++Vec2) { + QualType ParamTypes[2]; + ParamTypes[1] = *Vec2; + // Add this built-in operator as a candidate (VQ is empty). + ParamTypes[0] = S.Context.getLValueReferenceType(*Vec1); + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet, + /*IsAssigmentOperator=*/isEqualOp); + + // Add this built-in operator as a candidate (VQ is 'volatile'). + if (VisibleTypeConversionsQuals.hasVolatile()) { + ParamTypes[0] = S.Context.getVolatileType(*Vec1); + ParamTypes[0] = S.Context.getLValueReferenceType(ParamTypes[0]); + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, + CandidateSet, + /*IsAssigmentOperator=*/isEqualOp); + } + } + } + } + + // C++ [over.built]p22: + // + // For every triple (L, VQ, R), where L is an integral type, VQ + // is either volatile or empty, and R is a promoted integral + // type, there exist candidate operator functions of the form + // + // VQ L& operator%=(VQ L&, R); + // VQ L& operator<<=(VQ L&, R); + // VQ L& operator>>=(VQ L&, R); + // VQ L& operator&=(VQ L&, R); + // VQ L& operator^=(VQ L&, R); + // VQ L& operator|=(VQ L&, R); + void addAssignmentIntegralOverloads() { + if (!HasArithmeticOrEnumeralCandidateType) + return; + + for (unsigned Left = FirstIntegralType; Left < LastIntegralType; ++Left) { + for (unsigned Right = FirstPromotedIntegralType; + Right < LastPromotedIntegralType; ++Right) { + QualType ParamTypes[2]; + ParamTypes[1] = getArithmeticType(Right); + + // Add this built-in operator as a candidate (VQ is empty). + ParamTypes[0] = + S.Context.getLValueReferenceType(getArithmeticType(Left)); + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet); + if (VisibleTypeConversionsQuals.hasVolatile()) { + // Add this built-in operator as a candidate (VQ is 'volatile'). + ParamTypes[0] = getArithmeticType(Left); + ParamTypes[0] = S.Context.getVolatileType(ParamTypes[0]); + ParamTypes[0] = S.Context.getLValueReferenceType(ParamTypes[0]); + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, + CandidateSet); + } + } + } + } + + // C++ [over.operator]p23: + // + // There also exist candidate operator functions of the form + // + // bool operator!(bool); + // bool operator&&(bool, bool); + // bool operator||(bool, bool); + void addExclaimOverload() { + QualType ParamTy = S.Context.BoolTy; + S.AddBuiltinCandidate(ParamTy, &ParamTy, Args, 1, CandidateSet, + /*IsAssignmentOperator=*/false, + /*NumContextualBoolArguments=*/1); + } + void addAmpAmpOrPipePipeOverload() { + QualType ParamTypes[2] = { S.Context.BoolTy, S.Context.BoolTy }; + S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, 2, CandidateSet, + /*IsAssignmentOperator=*/false, + /*NumContextualBoolArguments=*/2); + } + + // C++ [over.built]p13: + // + // For every cv-qualified or cv-unqualified object type T there + // exist candidate operator functions of the form + // + // T* operator+(T*, ptrdiff_t); [ABOVE] + // T& operator[](T*, ptrdiff_t); + // T* operator-(T*, ptrdiff_t); [ABOVE] + // T* operator+(ptrdiff_t, T*); [ABOVE] + // T& operator[](ptrdiff_t, T*); + void addSubscriptOverloads() { + for (BuiltinCandidateTypeSet::iterator + Ptr = CandidateTypes[0].pointer_begin(), + PtrEnd = CandidateTypes[0].pointer_end(); + Ptr != PtrEnd; ++Ptr) { + QualType ParamTypes[2] = { *Ptr, S.Context.getPointerDiffType() }; + QualType PointeeType = (*Ptr)->getPointeeType(); + if (!PointeeType->isObjectType()) + continue; + + QualType ResultTy = S.Context.getLValueReferenceType(PointeeType); + + // T& operator[](T*, ptrdiff_t) + S.AddBuiltinCandidate(ResultTy, ParamTypes, Args, 2, CandidateSet); + } + + for (BuiltinCandidateTypeSet::iterator + Ptr = CandidateTypes[1].pointer_begin(), + PtrEnd = CandidateTypes[1].pointer_end(); + Ptr != PtrEnd; ++Ptr) { + QualType ParamTypes[2] = { S.Context.getPointerDiffType(), *Ptr }; + QualType PointeeType = (*Ptr)->getPointeeType(); + if (!PointeeType->isObjectType()) + continue; + + QualType ResultTy = S.Context.getLValueReferenceType(PointeeType); + + // T& operator[](ptrdiff_t, T*) + S.AddBuiltinCandidate(ResultTy, ParamTypes, Args, 2, CandidateSet); + } + } + + // C++ [over.built]p11: + // For every quintuple (C1, C2, T, CV1, CV2), where C2 is a class type, + // C1 is the same type as C2 or is a derived class of C2, T is an object + // type or a function type, and CV1 and CV2 are cv-qualifier-seqs, + // there exist candidate operator functions of the form + // + // CV12 T& operator->*(CV1 C1*, CV2 T C2::*); + // + // where CV12 is the union of CV1 and CV2. + void addArrowStarOverloads() { + for (BuiltinCandidateTypeSet::iterator + Ptr = CandidateTypes[0].pointer_begin(), + PtrEnd = CandidateTypes[0].pointer_end(); + Ptr != PtrEnd; ++Ptr) { + QualType C1Ty = (*Ptr); + QualType C1; + QualifierCollector Q1; + 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[1].member_pointer_begin(), + MemPtrEnd = CandidateTypes[1].member_pointer_end(); + MemPtr != MemPtrEnd; ++MemPtr) { + const MemberPointerType *mptr = cast(*MemPtr); + QualType C2 = QualType(mptr->getClass(), 0); + C2 = C2.getUnqualifiedType(); + if (C1 != C2 && !S.IsDerivedFrom(C1, C2)) + break; + QualType ParamTypes[2] = { *Ptr, *MemPtr }; + // build CV12 T& + QualType T = mptr->getPointeeType(); + if (!VisibleTypeConversionsQuals.hasVolatile() && + T.isVolatileQualified()) + continue; + if (!VisibleTypeConversionsQuals.hasRestrict() && + T.isRestrictQualified()) + continue; + T = Q1.apply(S.Context, T); + QualType ResultTy = S.Context.getLValueReferenceType(T); + S.AddBuiltinCandidate(ResultTy, ParamTypes, Args, 2, CandidateSet); + } + } + } + + // Note that we don't consider the first argument, since it has been + // contextually converted to bool long ago. The candidates below are + // therefore added as binary. + // + // C++ [over.built]p25: + // For every type T, where T is a pointer, pointer-to-member, or scoped + // enumeration type, there exist candidate operator functions of the form + // + // T operator?(bool, T, T); + // + void addConditionalOperatorOverloads() { + /// Set of (canonical) types that we've already handled. + llvm::SmallPtrSet AddedTypes; + + for (unsigned ArgIdx = 0; ArgIdx < 2; ++ArgIdx) { + for (BuiltinCandidateTypeSet::iterator + Ptr = CandidateTypes[ArgIdx].pointer_begin(), + PtrEnd = CandidateTypes[ArgIdx].pointer_end(); + Ptr != PtrEnd; ++Ptr) { + if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr))) + continue; + + QualType ParamTypes[2] = { *Ptr, *Ptr }; + S.AddBuiltinCandidate(*Ptr, ParamTypes, Args, 2, CandidateSet); + } + + for (BuiltinCandidateTypeSet::iterator + MemPtr = CandidateTypes[ArgIdx].member_pointer_begin(), + MemPtrEnd = CandidateTypes[ArgIdx].member_pointer_end(); + MemPtr != MemPtrEnd; ++MemPtr) { + if (!AddedTypes.insert(S.Context.getCanonicalType(*MemPtr))) + continue; + + QualType ParamTypes[2] = { *MemPtr, *MemPtr }; + S.AddBuiltinCandidate(*MemPtr, ParamTypes, Args, 2, CandidateSet); + } + + if (S.getLangOpts().CPlusPlus0x) { + for (BuiltinCandidateTypeSet::iterator + Enum = CandidateTypes[ArgIdx].enumeration_begin(), + EnumEnd = CandidateTypes[ArgIdx].enumeration_end(); + Enum != EnumEnd; ++Enum) { + if (!(*Enum)->getAs()->getDecl()->isScoped()) + continue; + + if (!AddedTypes.insert(S.Context.getCanonicalType(*Enum))) + continue; + + QualType ParamTypes[2] = { *Enum, *Enum }; + S.AddBuiltinCandidate(*Enum, ParamTypes, Args, 2, CandidateSet); + } + } + } + } +}; + +} // end anonymous namespace + +/// AddBuiltinOperatorCandidates - Add the appropriate built-in +/// operator overloads to the candidate set (C++ [over.built]), based +/// on the operator @p Op and the arguments given. For example, if the +/// operator is a binary '+', this routine might add "int +/// operator+(int, int)" to cover integer addition. +void +Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, + SourceLocation OpLoc, + Expr **Args, unsigned NumArgs, + OverloadCandidateSet& CandidateSet) { + // Find all of the types that the arguments can convert to, but only + // if the operator we're looking at has built-in operator candidates + // that make use of these types. Also record whether we encounter non-record + // candidate types or either arithmetic or enumeral candidate types. + Qualifiers VisibleTypeConversionsQuals; + VisibleTypeConversionsQuals.addConst(); + for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) + VisibleTypeConversionsQuals += CollectVRQualifiers(Context, Args[ArgIdx]); + + bool HasNonRecordCandidateType = false; + bool HasArithmeticOrEnumeralCandidateType = false; + SmallVector CandidateTypes; + for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) { + CandidateTypes.push_back(BuiltinCandidateTypeSet(*this)); + CandidateTypes[ArgIdx].AddTypesConvertedFrom(Args[ArgIdx]->getType(), + OpLoc, + true, + (Op == OO_Exclaim || + Op == OO_AmpAmp || + Op == OO_PipePipe), + VisibleTypeConversionsQuals); + HasNonRecordCandidateType = HasNonRecordCandidateType || + CandidateTypes[ArgIdx].hasNonRecordTypes(); + HasArithmeticOrEnumeralCandidateType = + HasArithmeticOrEnumeralCandidateType || + CandidateTypes[ArgIdx].hasArithmeticOrEnumeralTypes(); + } + + // Exit early when no non-record types have been added to the candidate set + // for any of the arguments to the operator. + // + // We can't exit early for !, ||, or &&, since there we have always have + // 'bool' overloads. + if (!HasNonRecordCandidateType && + !(Op == OO_Exclaim || Op == OO_AmpAmp || Op == OO_PipePipe)) + return; + + // Setup an object to manage the common state for building overloads. + BuiltinOperatorOverloadBuilder OpBuilder(*this, Args, NumArgs, + VisibleTypeConversionsQuals, + HasArithmeticOrEnumeralCandidateType, + CandidateTypes, CandidateSet); + + // Dispatch over the operation to add in only those overloads which apply. + switch (Op) { + case OO_None: + case NUM_OVERLOADED_OPERATORS: + llvm_unreachable("Expected an overloaded operator"); + + case OO_New: + case OO_Delete: + case OO_Array_New: + case OO_Array_Delete: + case OO_Call: + llvm_unreachable( + "Special operators don't use AddBuiltinOperatorCandidates"); + + case OO_Comma: + case OO_Arrow: + // C++ [over.match.oper]p3: + // -- For the operator ',', the unary operator '&', or the + // operator '->', the built-in candidates set is empty. + break; + + case OO_Plus: // '+' is either unary or binary + if (NumArgs == 1) + OpBuilder.addUnaryPlusPointerOverloads(); + // Fall through. + + case OO_Minus: // '-' is either unary or binary + if (NumArgs == 1) { + OpBuilder.addUnaryPlusOrMinusArithmeticOverloads(); + } else { + OpBuilder.addBinaryPlusOrMinusPointerOverloads(Op); + OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/false); + } + break; + + case OO_Star: // '*' is either unary or binary + if (NumArgs == 1) + OpBuilder.addUnaryStarPointerOverloads(); + else + OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/false); + break; + + case OO_Slash: + OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/false); + break; + + case OO_PlusPlus: + case OO_MinusMinus: + OpBuilder.addPlusPlusMinusMinusArithmeticOverloads(Op); + OpBuilder.addPlusPlusMinusMinusPointerOverloads(); + break; + + case OO_EqualEqual: + case OO_ExclaimEqual: + OpBuilder.addEqualEqualOrNotEqualMemberPointerOverloads(); + // Fall through. + + case OO_Less: + case OO_Greater: + case OO_LessEqual: + case OO_GreaterEqual: + OpBuilder.addRelationalPointerOrEnumeralOverloads(); + OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/true); + break; + + case OO_Percent: + case OO_Caret: + case OO_Pipe: + case OO_LessLess: + case OO_GreaterGreater: + OpBuilder.addBinaryBitwiseArithmeticOverloads(Op); + break; + + case OO_Amp: // '&' is either unary or binary + if (NumArgs == 1) + // C++ [over.match.oper]p3: + // -- For the operator ',', the unary operator '&', or the + // operator '->', the built-in candidates set is empty. + break; + + OpBuilder.addBinaryBitwiseArithmeticOverloads(Op); + break; + + case OO_Tilde: + OpBuilder.addUnaryTildePromotedIntegralOverloads(); + break; + + case OO_Equal: + OpBuilder.addAssignmentMemberPointerOrEnumeralOverloads(); + // Fall through. + + case OO_PlusEqual: + case OO_MinusEqual: + OpBuilder.addAssignmentPointerOverloads(Op == OO_Equal); + // Fall through. + + case OO_StarEqual: + case OO_SlashEqual: + OpBuilder.addAssignmentArithmeticOverloads(Op == OO_Equal); + break; + + case OO_PercentEqual: + case OO_LessLessEqual: + case OO_GreaterGreaterEqual: + case OO_AmpEqual: + case OO_CaretEqual: + case OO_PipeEqual: + OpBuilder.addAssignmentIntegralOverloads(); + break; + + case OO_Exclaim: + OpBuilder.addExclaimOverload(); + break; + + case OO_AmpAmp: + case OO_PipePipe: + OpBuilder.addAmpAmpOrPipePipeOverload(); + break; + + case OO_Subscript: + OpBuilder.addSubscriptOverloads(); + break; + + case OO_ArrowStar: + OpBuilder.addArrowStarOverloads(); + break; + + case OO_Conditional: + OpBuilder.addConditionalOperatorOverloads(); + OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/false); + break; + } +} + +/// \brief Add function candidates found via argument-dependent lookup +/// to the set of overloading candidates. +/// +/// This routine performs argument-dependent name lookup based on the +/// given function name (which may also be an operator name) and adds +/// all of the overload candidates found by ADL to the overload +/// candidate set (C++ [basic.lookup.argdep]). +void +Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, + bool Operator, SourceLocation Loc, + llvm::ArrayRef Args, + TemplateArgumentListInfo *ExplicitTemplateArgs, + OverloadCandidateSet& CandidateSet, + bool PartialOverloading, + bool StdNamespaceIsAssociated) { + ADLResult Fns; + + // FIXME: This approach for uniquing ADL results (and removing + // redundant candidates from the set) relies on pointer-equality, + // which means we need to key off the canonical decl. However, + // always going back to the canonical decl might not get us the + // right set of default arguments. What default arguments are + // we supposed to consider on ADL candidates, anyway? + + // FIXME: Pass in the explicit template arguments? + ArgumentDependentLookup(Name, Operator, Loc, Args, Fns, + StdNamespaceIsAssociated); + + // Erase all of the candidates we already knew about. + for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(), + CandEnd = CandidateSet.end(); + Cand != CandEnd; ++Cand) + if (Cand->Function) { + Fns.erase(Cand->Function); + if (FunctionTemplateDecl *FunTmpl = Cand->Function->getPrimaryTemplate()) + Fns.erase(FunTmpl); + } + + // For each of the ADL candidates we found, add it to the overload + // set. + for (ADLResult::iterator I = Fns.begin(), E = Fns.end(); I != E; ++I) { + DeclAccessPair FoundDecl = DeclAccessPair::make(*I, AS_none); + if (FunctionDecl *FD = dyn_cast(*I)) { + if (ExplicitTemplateArgs) + continue; + + AddOverloadCandidate(FD, FoundDecl, Args, CandidateSet, false, + PartialOverloading); + } else + AddTemplateOverloadCandidate(cast(*I), + FoundDecl, ExplicitTemplateArgs, + Args, CandidateSet); + } +} + +/// isBetterOverloadCandidate - Determines whether the first overload +/// candidate is a better candidate than the second (C++ 13.3.3p1). +bool +isBetterOverloadCandidate(Sema &S, + const OverloadCandidate &Cand1, + const OverloadCandidate &Cand2, + SourceLocation Loc, + bool UserDefinedConversion) { + // Define viable functions to be better candidates than non-viable + // functions. + if (!Cand2.Viable) + return Cand1.Viable; + else if (!Cand1.Viable) + return false; + + // C++ [over.match.best]p1: + // + // -- if F is a static member function, ICS1(F) is defined such + // that ICS1(F) is neither better nor worse than ICS1(G) for + // any function G, and, symmetrically, ICS1(G) is neither + // better nor worse than ICS1(F). + unsigned StartArg = 0; + if (Cand1.IgnoreObjectArgument || Cand2.IgnoreObjectArgument) + StartArg = 1; + + // C++ [over.match.best]p1: + // A viable function F1 is defined to be a better function than another + // viable function F2 if for all arguments i, ICSi(F1) is not a worse + // conversion sequence than ICSi(F2), and then... + unsigned NumArgs = Cand1.NumConversions; + assert(Cand2.NumConversions == NumArgs && "Overload candidate mismatch"); + bool HasBetterConversion = false; + for (unsigned ArgIdx = StartArg; ArgIdx < NumArgs; ++ArgIdx) { + switch (CompareImplicitConversionSequences(S, + Cand1.Conversions[ArgIdx], + Cand2.Conversions[ArgIdx])) { + case ImplicitConversionSequence::Better: + // Cand1 has a better conversion sequence. + HasBetterConversion = true; + break; + + case ImplicitConversionSequence::Worse: + // Cand1 can't be better than Cand2. + return false; + + case ImplicitConversionSequence::Indistinguishable: + // Do nothing. + break; + } + } + + // -- for some argument j, ICSj(F1) is a better conversion sequence than + // ICSj(F2), or, if not that, + if (HasBetterConversion) + return true; + + // - F1 is a non-template function and F2 is a function template + // specialization, or, if not that, + if ((!Cand1.Function || !Cand1.Function->getPrimaryTemplate()) && + Cand2.Function && Cand2.Function->getPrimaryTemplate()) + return true; + + // -- F1 and F2 are function template specializations, and the function + // template for F1 is more specialized than the template for F2 + // according to the partial ordering rules described in 14.5.5.2, or, + // if not that, + if (Cand1.Function && Cand1.Function->getPrimaryTemplate() && + Cand2.Function && Cand2.Function->getPrimaryTemplate()) { + if (FunctionTemplateDecl *BetterTemplate + = S.getMoreSpecializedTemplate(Cand1.Function->getPrimaryTemplate(), + Cand2.Function->getPrimaryTemplate(), + Loc, + isa(Cand1.Function)? TPOC_Conversion + : TPOC_Call, + Cand1.ExplicitCallArguments)) + return BetterTemplate == Cand1.Function->getPrimaryTemplate(); + } + + // -- the context is an initialization by user-defined conversion + // (see 8.5, 13.3.1.5) and the standard conversion sequence + // from the return type of F1 to the destination type (i.e., + // the type of the entity being initialized) is a better + // conversion sequence than the standard conversion sequence + // from the return type of F2 to the destination type. + if (UserDefinedConversion && Cand1.Function && Cand2.Function && + isa(Cand1.Function) && + isa(Cand2.Function)) { + // First check whether we prefer one of the conversion functions over the + // other. This only distinguishes the results in non-standard, extension + // cases such as the conversion from a lambda closure type to a function + // pointer or block. + ImplicitConversionSequence::CompareKind FuncResult + = compareConversionFunctions(S, Cand1.Function, Cand2.Function); + if (FuncResult != ImplicitConversionSequence::Indistinguishable) + return FuncResult; + + switch (CompareStandardConversionSequences(S, + Cand1.FinalConversion, + Cand2.FinalConversion)) { + case ImplicitConversionSequence::Better: + // Cand1 has a better conversion sequence. + return true; + + case ImplicitConversionSequence::Worse: + // Cand1 can't be better than Cand2. + return false; + + case ImplicitConversionSequence::Indistinguishable: + // Do nothing + break; + } + } + + return false; +} + +/// \brief Computes the best viable function (C++ 13.3.3) +/// within an overload candidate set. +/// +/// \param CandidateSet the set of candidate functions. +/// +/// \param Loc the location of the function name (or operator symbol) for +/// which overload resolution occurs. +/// +/// \param Best f overload resolution was successful or found a deleted +/// function, Best points to the candidate function found. +/// +/// \returns The result of overload resolution. +OverloadingResult +OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc, + iterator &Best, + bool UserDefinedConversion) { + // Find the best viable function. + Best = end(); + for (iterator Cand = begin(); Cand != end(); ++Cand) { + if (Cand->Viable) + if (Best == end() || isBetterOverloadCandidate(S, *Cand, *Best, Loc, + UserDefinedConversion)) + Best = Cand; + } + + // If we didn't find any viable functions, abort. + 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 (iterator Cand = begin(); Cand != end(); ++Cand) { + if (Cand->Viable && + Cand != Best && + !isBetterOverloadCandidate(S, *Best, *Cand, Loc, + UserDefinedConversion)) { + Best = end(); + return OR_Ambiguous; + } + } + + // Best is the best viable function. + if (Best->Function && + (Best->Function->isDeleted() || + S.isFunctionConsideredUnavailable(Best->Function))) + return OR_Deleted; + + return OR_Success; +} + +namespace { + +enum OverloadCandidateKind { + oc_function, + oc_method, + oc_constructor, + oc_function_template, + oc_method_template, + oc_constructor_template, + oc_implicit_default_constructor, + oc_implicit_copy_constructor, + oc_implicit_move_constructor, + oc_implicit_copy_assignment, + oc_implicit_move_assignment, + oc_implicit_inherited_constructor +}; + +OverloadCandidateKind ClassifyOverloadCandidate(Sema &S, + FunctionDecl *Fn, + std::string &Description) { + bool isTemplate = false; + + if (FunctionTemplateDecl *FunTmpl = Fn->getPrimaryTemplate()) { + isTemplate = true; + Description = S.getTemplateArgumentBindingsText( + FunTmpl->getTemplateParameters(), *Fn->getTemplateSpecializationArgs()); + } + + if (CXXConstructorDecl *Ctor = dyn_cast(Fn)) { + if (!Ctor->isImplicit()) + return isTemplate ? oc_constructor_template : oc_constructor; + + if (Ctor->getInheritedConstructor()) + return oc_implicit_inherited_constructor; + + if (Ctor->isDefaultConstructor()) + return oc_implicit_default_constructor; + + if (Ctor->isMoveConstructor()) + return oc_implicit_move_constructor; + + assert(Ctor->isCopyConstructor() && + "unexpected sort of implicit constructor"); + return oc_implicit_copy_constructor; + } + + if (CXXMethodDecl *Meth = dyn_cast(Fn)) { + // This actually gets spelled 'candidate function' for now, but + // it doesn't hurt to split it out. + if (!Meth->isImplicit()) + return isTemplate ? oc_method_template : oc_method; + + if (Meth->isMoveAssignmentOperator()) + return oc_implicit_move_assignment; + + if (Meth->isCopyAssignmentOperator()) + return oc_implicit_copy_assignment; + + assert(isa(Meth) && "expected conversion"); + return oc_method; + } + + return isTemplate ? oc_function_template : oc_function; +} + +void MaybeEmitInheritedConstructorNote(Sema &S, FunctionDecl *Fn) { + const CXXConstructorDecl *Ctor = dyn_cast(Fn); + if (!Ctor) return; + + Ctor = Ctor->getInheritedConstructor(); + if (!Ctor) return; + + S.Diag(Ctor->getLocation(), diag::note_ovl_candidate_inherited_constructor); +} + +} // end anonymous namespace + +// Notes the location of an overload candidate. +void Sema::NoteOverloadCandidate(FunctionDecl *Fn, QualType DestType) { + std::string FnDesc; + OverloadCandidateKind K = ClassifyOverloadCandidate(*this, Fn, FnDesc); + PartialDiagnostic PD = PDiag(diag::note_ovl_candidate) + << (unsigned) K << FnDesc; + HandleFunctionTypeMismatch(PD, Fn->getType(), DestType); + Diag(Fn->getLocation(), PD); + MaybeEmitInheritedConstructorNote(*this, Fn); +} + +//Notes the location of all overload candidates designated through +// OverloadedExpr +void Sema::NoteAllOverloadCandidates(Expr* OverloadedExpr, QualType DestType) { + assert(OverloadedExpr->getType() == Context.OverloadTy); + + OverloadExpr::FindResult Ovl = OverloadExpr::find(OverloadedExpr); + OverloadExpr *OvlExpr = Ovl.Expression; + + for (UnresolvedSetIterator I = OvlExpr->decls_begin(), + IEnd = OvlExpr->decls_end(); + I != IEnd; ++I) { + if (FunctionTemplateDecl *FunTmpl = + dyn_cast((*I)->getUnderlyingDecl()) ) { + NoteOverloadCandidate(FunTmpl->getTemplatedDecl(), DestType); + } else if (FunctionDecl *Fun + = dyn_cast((*I)->getUnderlyingDecl()) ) { + NoteOverloadCandidate(Fun, DestType); + } + } +} + +/// 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 ImplicitConversionSequence::DiagnoseAmbiguousConversion( + Sema &S, + SourceLocation CaretLoc, + const PartialDiagnostic &PDiag) const { + S.Diag(CaretLoc, PDiag) + << Ambiguous.getFromType() << Ambiguous.getToType(); + for (AmbiguousConversionSequence::const_iterator + I = Ambiguous.begin(), E = Ambiguous.end(); I != E; ++I) { + S.NoteOverloadCandidate(*I); + } +} + +namespace { + +void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) { + const ImplicitConversionSequence &Conv = Cand->Conversions[I]; + assert(Conv.isBad()); + assert(Cand->Function && "for now, candidate must be a function"); + FunctionDecl *Fn = Cand->Function; + + // There's a conversion slot for the object argument if this is a + // non-constructor method. Note that 'I' corresponds the + // conversion-slot index. + bool isObjectArgument = false; + if (isa(Fn) && !isa(Fn)) { + if (I == 0) + isObjectArgument = true; + else + I--; + } + + std::string FnDesc; + OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Fn, FnDesc); + + Expr *FromExpr = Conv.Bad.FromExpr; + QualType FromTy = Conv.Bad.getFromType(); + QualType ToTy = Conv.Bad.getToType(); + + if (FromTy == S.Context.OverloadTy) { + assert(FromExpr && "overload set argument came from implicit argument?"); + Expr *E = FromExpr->IgnoreParens(); + if (isa(E)) + E = cast(E)->getSubExpr()->IgnoreParens(); + DeclarationName Name = cast(E)->getName(); + + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_overload) + << (unsigned) FnKind << FnDesc + << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) + << ToTy << Name << I+1; + MaybeEmitInheritedConstructorNote(S, Fn); + return; + } + + // Do some hand-waving analysis to see if the non-viability is due + // to a qualifier mismatch. + CanQualType CFromTy = S.Context.getCanonicalType(FromTy); + CanQualType CToTy = S.Context.getCanonicalType(ToTy); + if (CanQual RT = CToTy->getAs()) + CToTy = RT->getPointeeType(); + else { + // TODO: detect and diagnose the full richness of const mismatches. + if (CanQual FromPT = CFromTy->getAs()) + if (CanQual ToPT = CToTy->getAs()) + CFromTy = FromPT->getPointeeType(), CToTy = ToPT->getPointeeType(); + } + + if (CToTy.getUnqualifiedType() == CFromTy.getUnqualifiedType() && + !CToTy.isAtLeastAsQualifiedAs(CFromTy)) { + Qualifiers FromQs = CFromTy.getQualifiers(); + Qualifiers ToQs = CToTy.getQualifiers(); + + if (FromQs.getAddressSpace() != ToQs.getAddressSpace()) { + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_addrspace) + << (unsigned) FnKind << FnDesc + << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) + << FromTy + << FromQs.getAddressSpace() << ToQs.getAddressSpace() + << (unsigned) isObjectArgument << I+1; + MaybeEmitInheritedConstructorNote(S, Fn); + return; + } + + if (FromQs.getObjCLifetime() != ToQs.getObjCLifetime()) { + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_ownership) + << (unsigned) FnKind << FnDesc + << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) + << FromTy + << FromQs.getObjCLifetime() << ToQs.getObjCLifetime() + << (unsigned) isObjectArgument << I+1; + MaybeEmitInheritedConstructorNote(S, Fn); + return; + } + + if (FromQs.getObjCGCAttr() != ToQs.getObjCGCAttr()) { + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_gc) + << (unsigned) FnKind << FnDesc + << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) + << FromTy + << FromQs.getObjCGCAttr() << ToQs.getObjCGCAttr() + << (unsigned) isObjectArgument << I+1; + MaybeEmitInheritedConstructorNote(S, Fn); + return; + } + + unsigned CVR = FromQs.getCVRQualifiers() & ~ToQs.getCVRQualifiers(); + assert(CVR && "unexpected qualifiers mismatch"); + + if (isObjectArgument) { + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_cvr_this) + << (unsigned) FnKind << FnDesc + << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) + << FromTy << (CVR - 1); + } else { + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_cvr) + << (unsigned) FnKind << FnDesc + << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) + << FromTy << (CVR - 1) << I+1; + } + MaybeEmitInheritedConstructorNote(S, Fn); + return; + } + + // Special diagnostic for failure to convert an initializer list, since + // telling the user that it has type void is not useful. + if (FromExpr && isa(FromExpr)) { + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_list_argument) + << (unsigned) FnKind << FnDesc + << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) + << FromTy << ToTy << (unsigned) isObjectArgument << I+1; + MaybeEmitInheritedConstructorNote(S, Fn); + return; + } + + // Diagnose references or pointers to incomplete types differently, + // since it's far from impossible that the incompleteness triggered + // the failure. + QualType TempFromTy = FromTy.getNonReferenceType(); + if (const PointerType *PTy = TempFromTy->getAs()) + TempFromTy = PTy->getPointeeType(); + if (TempFromTy->isIncompleteType()) { + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_conv_incomplete) + << (unsigned) FnKind << FnDesc + << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) + << FromTy << ToTy << (unsigned) isObjectArgument << I+1; + MaybeEmitInheritedConstructorNote(S, Fn); + return; + } + + // Diagnose base -> derived pointer conversions. + unsigned BaseToDerivedConversion = 0; + if (const PointerType *FromPtrTy = FromTy->getAs()) { + if (const PointerType *ToPtrTy = ToTy->getAs()) { + if (ToPtrTy->getPointeeType().isAtLeastAsQualifiedAs( + FromPtrTy->getPointeeType()) && + !FromPtrTy->getPointeeType()->isIncompleteType() && + !ToPtrTy->getPointeeType()->isIncompleteType() && + S.IsDerivedFrom(ToPtrTy->getPointeeType(), + FromPtrTy->getPointeeType())) + BaseToDerivedConversion = 1; + } + } else if (const ObjCObjectPointerType *FromPtrTy + = FromTy->getAs()) { + if (const ObjCObjectPointerType *ToPtrTy + = ToTy->getAs()) + if (const ObjCInterfaceDecl *FromIface = FromPtrTy->getInterfaceDecl()) + if (const ObjCInterfaceDecl *ToIface = ToPtrTy->getInterfaceDecl()) + if (ToPtrTy->getPointeeType().isAtLeastAsQualifiedAs( + FromPtrTy->getPointeeType()) && + FromIface->isSuperClassOf(ToIface)) + BaseToDerivedConversion = 2; + } else if (const ReferenceType *ToRefTy = ToTy->getAs()) { + if (ToRefTy->getPointeeType().isAtLeastAsQualifiedAs(FromTy) && + !FromTy->isIncompleteType() && + !ToRefTy->getPointeeType()->isIncompleteType() && + S.IsDerivedFrom(ToRefTy->getPointeeType(), FromTy)) + BaseToDerivedConversion = 3; + } + + if (BaseToDerivedConversion) { + S.Diag(Fn->getLocation(), + diag::note_ovl_candidate_bad_base_to_derived_conv) + << (unsigned) FnKind << FnDesc + << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) + << (BaseToDerivedConversion - 1) + << FromTy << ToTy << I+1; + MaybeEmitInheritedConstructorNote(S, Fn); + return; + } + + if (isa(CFromTy) && + isa(CToTy)) { + Qualifiers FromQs = CFromTy.getQualifiers(); + Qualifiers ToQs = CToTy.getQualifiers(); + if (FromQs.getObjCLifetime() != ToQs.getObjCLifetime()) { + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_arc_conv) + << (unsigned) FnKind << FnDesc + << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) + << FromTy << ToTy << (unsigned) isObjectArgument << I+1; + MaybeEmitInheritedConstructorNote(S, Fn); + return; + } + } + + // Emit the generic diagnostic and, optionally, add the hints to it. + PartialDiagnostic FDiag = S.PDiag(diag::note_ovl_candidate_bad_conv); + FDiag << (unsigned) FnKind << FnDesc + << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) + << FromTy << ToTy << (unsigned) isObjectArgument << I + 1 + << (unsigned) (Cand->Fix.Kind); + + // If we can fix the conversion, suggest the FixIts. + for (std::vector::iterator HI = Cand->Fix.Hints.begin(), + HE = Cand->Fix.Hints.end(); HI != HE; ++HI) + FDiag << *HI; + S.Diag(Fn->getLocation(), FDiag); + + MaybeEmitInheritedConstructorNote(S, Fn); +} + +void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand, + unsigned NumFormalArgs) { + // TODO: treat calls to a missing default constructor as a special case + + FunctionDecl *Fn = Cand->Function; + const FunctionProtoType *FnTy = Fn->getType()->getAs(); + + unsigned MinParams = Fn->getMinRequiredArguments(); + + // With invalid overloaded operators, it's possible that we think we + // have an arity mismatch when it fact it looks like we have the + // right number of arguments, because only overloaded operators have + // the weird behavior of overloading member and non-member functions. + // Just don't report anything. + if (Fn->isInvalidDecl() && + Fn->getDeclName().getNameKind() == DeclarationName::CXXOperatorName) + return; + + // at least / at most / exactly + unsigned mode, modeCount; + if (NumFormalArgs < MinParams) { + assert((Cand->FailureKind == ovl_fail_too_few_arguments) || + (Cand->FailureKind == ovl_fail_bad_deduction && + Cand->DeductionFailure.Result == Sema::TDK_TooFewArguments)); + if (MinParams != FnTy->getNumArgs() || + FnTy->isVariadic() || FnTy->isTemplateVariadic()) + mode = 0; // "at least" + else + mode = 2; // "exactly" + modeCount = MinParams; + } else { + assert((Cand->FailureKind == ovl_fail_too_many_arguments) || + (Cand->FailureKind == ovl_fail_bad_deduction && + Cand->DeductionFailure.Result == Sema::TDK_TooManyArguments)); + if (MinParams != FnTy->getNumArgs()) + mode = 1; // "at most" + else + mode = 2; // "exactly" + modeCount = FnTy->getNumArgs(); + } + + std::string Description; + OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Fn, Description); + + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_arity) + << (unsigned) FnKind << (Fn->getDescribedFunctionTemplate() != 0) << mode + << modeCount << NumFormalArgs; + MaybeEmitInheritedConstructorNote(S, Fn); +} + +/// Diagnose a failed template-argument deduction. +void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand, + unsigned NumArgs) { + FunctionDecl *Fn = Cand->Function; // pattern + + TemplateParameter Param = Cand->DeductionFailure.getTemplateParameter(); + NamedDecl *ParamD; + (ParamD = Param.dyn_cast()) || + (ParamD = Param.dyn_cast()) || + (ParamD = Param.dyn_cast()); + switch (Cand->DeductionFailure.Result) { + case Sema::TDK_Success: + llvm_unreachable("TDK_success while diagnosing bad deduction"); + + case Sema::TDK_Incomplete: { + assert(ParamD && "no parameter found for incomplete deduction result"); + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_incomplete_deduction) + << ParamD->getDeclName(); + MaybeEmitInheritedConstructorNote(S, Fn); + return; + } + + 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; + Qs.strip(Param); + QualType NonCanonParam = Qs.apply(S.Context, 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; + MaybeEmitInheritedConstructorNote(S, Fn); + return; + } + + case Sema::TDK_Inconsistent: { + assert(ParamD && "no parameter found for inconsistent deduction result"); + int which = 0; + if (isa(ParamD)) + which = 0; + else if (isa(ParamD)) + which = 1; + else { + which = 2; + } + + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_inconsistent_deduction) + << which << ParamD->getDeclName() + << *Cand->DeductionFailure.getFirstArg() + << *Cand->DeductionFailure.getSecondArg(); + MaybeEmitInheritedConstructorNote(S, Fn); + return; + } + + case Sema::TDK_InvalidExplicitArguments: + assert(ParamD && "no parameter found for invalid explicit arguments"); + if (ParamD->getDeclName()) + S.Diag(Fn->getLocation(), + diag::note_ovl_candidate_explicit_arg_mismatch_named) + << ParamD->getDeclName(); + else { + int index = 0; + if (TemplateTypeParmDecl *TTP = dyn_cast(ParamD)) + index = TTP->getIndex(); + else if (NonTypeTemplateParmDecl *NTTP + = dyn_cast(ParamD)) + index = NTTP->getIndex(); + else + index = cast(ParamD)->getIndex(); + S.Diag(Fn->getLocation(), + diag::note_ovl_candidate_explicit_arg_mismatch_unnamed) + << (index + 1); + } + MaybeEmitInheritedConstructorNote(S, Fn); + return; + + case Sema::TDK_TooManyArguments: + case Sema::TDK_TooFewArguments: + DiagnoseArityMismatch(S, Cand, NumArgs); + return; + + case Sema::TDK_InstantiationDepth: + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_instantiation_depth); + MaybeEmitInheritedConstructorNote(S, Fn); + return; + + case Sema::TDK_SubstitutionFailure: { + std::string ArgString; + if (TemplateArgumentList *Args + = Cand->DeductionFailure.getTemplateArgumentList()) + ArgString = S.getTemplateArgumentBindingsText( + Fn->getDescribedFunctionTemplate()->getTemplateParameters(), + *Args); + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_substitution_failure) + << ArgString; + MaybeEmitInheritedConstructorNote(S, Fn); + return; + } + + // TODO: diagnose these individually, then kill off + // note_ovl_candidate_bad_deduction, which is uselessly vague. + case Sema::TDK_NonDeducedMismatch: + case Sema::TDK_FailedOverloadResolution: + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_deduction); + MaybeEmitInheritedConstructorNote(S, Fn); + return; + } +} + +/// CUDA: diagnose an invalid call across targets. +void DiagnoseBadTarget(Sema &S, OverloadCandidate *Cand) { + FunctionDecl *Caller = cast(S.CurContext); + FunctionDecl *Callee = Cand->Function; + + Sema::CUDAFunctionTarget CallerTarget = S.IdentifyCUDATarget(Caller), + CalleeTarget = S.IdentifyCUDATarget(Callee); + + std::string FnDesc; + OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Callee, FnDesc); + + S.Diag(Callee->getLocation(), diag::note_ovl_candidate_bad_target) + << (unsigned) FnKind << CalleeTarget << CallerTarget; +} + +/// Generates a 'note' diagnostic for an overload candidate. We've +/// already generated a primary error at the call site. +/// +/// It really does need to be a single diagnostic with its caret +/// pointed at the candidate declaration. Yes, this creates some +/// major challenges of technical writing. Yes, this makes pointing +/// out problems with specific arguments quite awkward. It's still +/// better than generating twenty screens of text for every failed +/// overload. +/// +/// It would be great to be able to express per-candidate problems +/// more richly for those diagnostic clients that cared, but we'd +/// still have to be just as careful with the default diagnostics. +void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand, + unsigned NumArgs) { + FunctionDecl *Fn = Cand->Function; + + // Note deleted candidates, but only if they're viable. + if (Cand->Viable && (Fn->isDeleted() || + S.isFunctionConsideredUnavailable(Fn))) { + std::string FnDesc; + OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Fn, FnDesc); + + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_deleted) + << FnKind << FnDesc + << (Fn->isDeleted() ? (Fn->isDeletedAsWritten() ? 1 : 2) : 0); + MaybeEmitInheritedConstructorNote(S, Fn); + return; + } + + // We don't really have anything else to say about viable candidates. + if (Cand->Viable) { + S.NoteOverloadCandidate(Fn); + return; + } + + switch (Cand->FailureKind) { + case ovl_fail_too_many_arguments: + case ovl_fail_too_few_arguments: + return DiagnoseArityMismatch(S, Cand, NumArgs); + + case ovl_fail_bad_deduction: + return DiagnoseBadDeduction(S, Cand, NumArgs); + + case ovl_fail_trivial_conversion: + case ovl_fail_bad_final_conversion: + case ovl_fail_final_conversion_not_exact: + return S.NoteOverloadCandidate(Fn); + + case ovl_fail_bad_conversion: { + unsigned I = (Cand->IgnoreObjectArgument ? 1 : 0); + for (unsigned N = Cand->NumConversions; I != N; ++I) + if (Cand->Conversions[I].isBad()) + return DiagnoseBadConversion(S, Cand, I); + + // FIXME: this currently happens when we're called from SemaInit + // when user-conversion overload fails. Figure out how to handle + // those conditions and diagnose them well. + return S.NoteOverloadCandidate(Fn); + } + + case ovl_fail_bad_target: + return DiagnoseBadTarget(S, Cand); + } +} + +void NoteSurrogateCandidate(Sema &S, OverloadCandidate *Cand) { + // Desugar the type of the surrogate down to a function type, + // retaining as many typedefs as possible while still showing + // the function type (and, therefore, its parameter types). + QualType FnType = Cand->Surrogate->getConversionType(); + bool isLValueReference = false; + bool isRValueReference = false; + bool isPointer = false; + if (const LValueReferenceType *FnTypeRef = + FnType->getAs()) { + FnType = FnTypeRef->getPointeeType(); + isLValueReference = true; + } else if (const RValueReferenceType *FnTypeRef = + FnType->getAs()) { + FnType = FnTypeRef->getPointeeType(); + isRValueReference = true; + } + if (const PointerType *FnTypePtr = FnType->getAs()) { + FnType = FnTypePtr->getPointeeType(); + isPointer = true; + } + // Desugar down to a function type. + FnType = QualType(FnType->getAs(), 0); + // Reconstruct the pointer/reference as appropriate. + if (isPointer) FnType = S.Context.getPointerType(FnType); + if (isRValueReference) FnType = S.Context.getRValueReferenceType(FnType); + if (isLValueReference) FnType = S.Context.getLValueReferenceType(FnType); + + S.Diag(Cand->Surrogate->getLocation(), diag::note_ovl_surrogate_cand) + << FnType; + MaybeEmitInheritedConstructorNote(S, Cand->Surrogate); +} + +void NoteBuiltinOperatorCandidate(Sema &S, + const char *Opc, + SourceLocation OpLoc, + OverloadCandidate *Cand) { + assert(Cand->NumConversions <= 2 && "builtin operator is not binary"); + std::string TypeStr("operator"); + TypeStr += Opc; + TypeStr += "("; + TypeStr += Cand->BuiltinTypes.ParamTypes[0].getAsString(); + if (Cand->NumConversions == 1) { + TypeStr += ")"; + S.Diag(OpLoc, diag::note_ovl_builtin_unary_candidate) << TypeStr; + } else { + TypeStr += ", "; + TypeStr += Cand->BuiltinTypes.ParamTypes[1].getAsString(); + TypeStr += ")"; + S.Diag(OpLoc, diag::note_ovl_builtin_binary_candidate) << TypeStr; + } +} + +void NoteAmbiguousUserConversions(Sema &S, SourceLocation OpLoc, + OverloadCandidate *Cand) { + unsigned NoOperands = Cand->NumConversions; + for (unsigned ArgIdx = 0; ArgIdx < NoOperands; ++ArgIdx) { + const ImplicitConversionSequence &ICS = Cand->Conversions[ArgIdx]; + if (ICS.isBad()) break; // all meaningless after first invalid + if (!ICS.isAmbiguous()) continue; + + ICS.DiagnoseAmbiguousConversion(S, OpLoc, + S.PDiag(diag::note_ambiguous_type_conversion)); + } +} + +SourceLocation GetLocationForCandidate(const OverloadCandidate *Cand) { + if (Cand->Function) + return Cand->Function->getLocation(); + if (Cand->IsSurrogate) + return Cand->Surrogate->getLocation(); + return SourceLocation(); +} + +static unsigned +RankDeductionFailure(const OverloadCandidate::DeductionFailureInfo &DFI) { + switch ((Sema::TemplateDeductionResult)DFI.Result) { + case Sema::TDK_Success: + llvm_unreachable("TDK_success while diagnosing bad deduction"); + + case Sema::TDK_Incomplete: + return 1; + + case Sema::TDK_Underqualified: + case Sema::TDK_Inconsistent: + return 2; + + case Sema::TDK_SubstitutionFailure: + case Sema::TDK_NonDeducedMismatch: + return 3; + + case Sema::TDK_InstantiationDepth: + case Sema::TDK_FailedOverloadResolution: + return 4; + + case Sema::TDK_InvalidExplicitArguments: + return 5; + + case Sema::TDK_TooManyArguments: + case Sema::TDK_TooFewArguments: + return 6; + } + llvm_unreachable("Unhandled deduction result"); +} + +struct CompareOverloadCandidatesForDisplay { + Sema &S; + CompareOverloadCandidatesForDisplay(Sema &S) : S(S) {} + + bool operator()(const OverloadCandidate *L, + const OverloadCandidate *R) { + // Fast-path this check. + if (L == R) return false; + + // Order first by viability. + if (L->Viable) { + if (!R->Viable) return true; + + // TODO: introduce a tri-valued comparison for overload + // candidates. Would be more worthwhile if we had a sort + // that could exploit it. + if (isBetterOverloadCandidate(S, *L, *R, SourceLocation())) return true; + if (isBetterOverloadCandidate(S, *R, *L, SourceLocation())) return false; + } else if (R->Viable) + return false; + + assert(L->Viable == R->Viable); + + // Criteria by which we can sort non-viable candidates: + if (!L->Viable) { + // 1. Arity mismatches come after other candidates. + if (L->FailureKind == ovl_fail_too_many_arguments || + L->FailureKind == ovl_fail_too_few_arguments) + return false; + if (R->FailureKind == ovl_fail_too_many_arguments || + R->FailureKind == ovl_fail_too_few_arguments) + return true; + + // 2. Bad conversions come first and are ordered by the number + // of bad conversions and quality of good conversions. + if (L->FailureKind == ovl_fail_bad_conversion) { + if (R->FailureKind != ovl_fail_bad_conversion) + return true; + + // The conversion that can be fixed with a smaller number of changes, + // comes first. + unsigned numLFixes = L->Fix.NumConversionsFixed; + unsigned numRFixes = R->Fix.NumConversionsFixed; + numLFixes = (numLFixes == 0) ? UINT_MAX : numLFixes; + numRFixes = (numRFixes == 0) ? UINT_MAX : numRFixes; + if (numLFixes != numRFixes) { + if (numLFixes < numRFixes) + return true; + else + return false; + } + + // If there's any ordering between the defined conversions... + // FIXME: this might not be transitive. + assert(L->NumConversions == R->NumConversions); + + int leftBetter = 0; + unsigned I = (L->IgnoreObjectArgument || R->IgnoreObjectArgument); + for (unsigned E = L->NumConversions; I != E; ++I) { + switch (CompareImplicitConversionSequences(S, + L->Conversions[I], + R->Conversions[I])) { + case ImplicitConversionSequence::Better: + leftBetter++; + break; + + case ImplicitConversionSequence::Worse: + leftBetter--; + break; + + case ImplicitConversionSequence::Indistinguishable: + break; + } + } + if (leftBetter > 0) return true; + if (leftBetter < 0) return false; + + } else if (R->FailureKind == ovl_fail_bad_conversion) + return false; + + if (L->FailureKind == ovl_fail_bad_deduction) { + if (R->FailureKind != ovl_fail_bad_deduction) + return true; + + if (L->DeductionFailure.Result != R->DeductionFailure.Result) + return RankDeductionFailure(L->DeductionFailure) + < RankDeductionFailure(R->DeductionFailure); + } else if (R->FailureKind == ovl_fail_bad_deduction) + return false; + + // TODO: others? + } + + // Sort everything else by location. + SourceLocation LLoc = GetLocationForCandidate(L); + SourceLocation RLoc = GetLocationForCandidate(R); + + // Put candidates without locations (e.g. builtins) at the end. + if (LLoc.isInvalid()) return false; + if (RLoc.isInvalid()) return true; + + return S.SourceMgr.isBeforeInTranslationUnit(LLoc, RLoc); + } +}; + +/// CompleteNonViableCandidate - Normally, overload resolution only +/// computes up to the first. Produces the FixIt set if possible. +void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand, + llvm::ArrayRef Args) { + assert(!Cand->Viable); + + // Don't do anything on failures other than bad conversion. + if (Cand->FailureKind != ovl_fail_bad_conversion) return; + + // We only want the FixIts if all the arguments can be corrected. + bool Unfixable = false; + // Use a implicit copy initialization to check conversion fixes. + Cand->Fix.setConversionChecker(TryCopyInitialization); + + // Skip forward to the first bad conversion. + unsigned ConvIdx = (Cand->IgnoreObjectArgument ? 1 : 0); + unsigned ConvCount = Cand->NumConversions; + while (true) { + assert(ConvIdx != ConvCount && "no bad conversion in candidate"); + ConvIdx++; + if (Cand->Conversions[ConvIdx - 1].isBad()) { + Unfixable = !Cand->TryToFixBadConversion(ConvIdx - 1, S); + break; + } + } + + if (ConvIdx == ConvCount) + return; + + assert(!Cand->Conversions[ConvIdx].isInitialized() && + "remaining conversion is initialized?"); + + // FIXME: this should probably be preserved from the overload + // operation somehow. + bool SuppressUserConversions = false; + + const FunctionProtoType* Proto; + unsigned ArgIdx = ConvIdx; + + if (Cand->IsSurrogate) { + QualType ConvType + = Cand->Surrogate->getConversionType().getNonReferenceType(); + if (const PointerType *ConvPtrType = ConvType->getAs()) + ConvType = ConvPtrType->getPointeeType(); + Proto = ConvType->getAs(); + ArgIdx--; + } else if (Cand->Function) { + Proto = Cand->Function->getType()->getAs(); + if (isa(Cand->Function) && + !isa(Cand->Function)) + ArgIdx--; + } else { + // Builtin binary operator with a bad first conversion. + assert(ConvCount <= 3); + for (; ConvIdx != ConvCount; ++ConvIdx) + Cand->Conversions[ConvIdx] + = TryCopyInitialization(S, Args[ConvIdx], + Cand->BuiltinTypes.ParamTypes[ConvIdx], + SuppressUserConversions, + /*InOverloadResolution*/ true, + /*AllowObjCWritebackConversion=*/ + S.getLangOpts().ObjCAutoRefCount); + return; + } + + // Fill in the rest of the conversions. + unsigned NumArgsInProto = Proto->getNumArgs(); + for (; ConvIdx != ConvCount; ++ConvIdx, ++ArgIdx) { + if (ArgIdx < NumArgsInProto) { + Cand->Conversions[ConvIdx] + = TryCopyInitialization(S, Args[ArgIdx], Proto->getArgType(ArgIdx), + SuppressUserConversions, + /*InOverloadResolution=*/true, + /*AllowObjCWritebackConversion=*/ + S.getLangOpts().ObjCAutoRefCount); + // Store the FixIt in the candidate if it exists. + if (!Unfixable && Cand->Conversions[ConvIdx].isBad()) + Unfixable = !Cand->TryToFixBadConversion(ConvIdx, S); + } + else + Cand->Conversions[ConvIdx].setEllipsis(); + } +} + +} // end anonymous namespace + +/// PrintOverloadCandidates - When overload resolution fails, prints +/// diagnostic messages containing the candidates in the candidate +/// set. +void OverloadCandidateSet::NoteCandidates(Sema &S, + OverloadCandidateDisplayKind OCD, + llvm::ArrayRef Args, + 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. + SmallVector Cands; + 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(S, Cand, Args); + if (Cand->Function || Cand->IsSurrogate) + Cands.push_back(Cand); + // Otherwise, this a non-viable builtin candidate. We do not, in general, + // want to list every possible builtin candidate. + } + } + + std::sort(Cands.begin(), Cands.end(), + CompareOverloadCandidatesForDisplay(S)); + + bool ReportedAmbiguousConversions = false; + + SmallVectorImpl::iterator I, E; + const DiagnosticsEngine::OverloadsShown ShowOverloads = + S.Diags.getShowOverloads(); + unsigned CandsShown = 0; + for (I = Cands.begin(), E = Cands.end(); I != E; ++I) { + OverloadCandidate *Cand = *I; + + // Set an arbitrary limit on the number of candidate functions we'll spam + // the user with. FIXME: This limit should depend on details of the + // candidate list. + if (CandsShown >= 4 && ShowOverloads == DiagnosticsEngine::Ovl_Best) { + break; + } + ++CandsShown; + + if (Cand->Function) + NoteFunctionCandidate(S, Cand, Args.size()); + else if (Cand->IsSurrogate) + NoteSurrogateCandidate(S, Cand); + else { + assert(Cand->Viable && + "Non-viable built-in candidates are not added to Cands."); + // Generally we only see ambiguities including viable builtin + // operators if overload resolution got screwed up by an + // ambiguous user-defined conversion. + // + // FIXME: It's quite possible for different conversions to see + // different ambiguities, though. + if (!ReportedAmbiguousConversions) { + NoteAmbiguousUserConversions(S, OpLoc, Cand); + ReportedAmbiguousConversions = true; + } + + // If this is a viable builtin, print it. + NoteBuiltinOperatorCandidate(S, Opc, OpLoc, Cand); + } + } + + if (I != E) + S.Diag(OpLoc, diag::note_ovl_too_many_candidates) << int(E - I); +} + +// [PossiblyAFunctionType] --> [Return] +// NonFunctionType --> NonFunctionType +// R (A) --> R(A) +// R (*)(A) --> R (A) +// R (&)(A) --> R (A) +// R (S::*)(A) --> R (A) +QualType Sema::ExtractUnqualifiedFunctionType(QualType PossiblyAFunctionType) { + QualType Ret = PossiblyAFunctionType; + if (const PointerType *ToTypePtr = + PossiblyAFunctionType->getAs()) + Ret = ToTypePtr->getPointeeType(); + else if (const ReferenceType *ToTypeRef = + PossiblyAFunctionType->getAs()) + Ret = ToTypeRef->getPointeeType(); + else if (const MemberPointerType *MemTypePtr = + PossiblyAFunctionType->getAs()) + Ret = MemTypePtr->getPointeeType(); + Ret = + Context.getCanonicalType(Ret).getUnqualifiedType(); + return Ret; +} + +// A helper class to help with address of function resolution +// - allows us to avoid passing around all those ugly parameters +class AddressOfFunctionResolver +{ + Sema& S; + Expr* SourceExpr; + const QualType& TargetType; + QualType TargetFunctionType; // Extracted function type from target type + + bool Complain; + //DeclAccessPair& ResultFunctionAccessPair; + ASTContext& Context; + + bool TargetTypeIsNonStaticMemberFunction; + bool FoundNonTemplateFunction; + + OverloadExpr::FindResult OvlExprInfo; + OverloadExpr *OvlExpr; + TemplateArgumentListInfo OvlExplicitTemplateArgs; + SmallVector, 4> Matches; + +public: + AddressOfFunctionResolver(Sema &S, Expr* SourceExpr, + const QualType& TargetType, bool Complain) + : S(S), SourceExpr(SourceExpr), TargetType(TargetType), + Complain(Complain), Context(S.getASTContext()), + TargetTypeIsNonStaticMemberFunction( + !!TargetType->getAs()), + FoundNonTemplateFunction(false), + OvlExprInfo(OverloadExpr::find(SourceExpr)), + OvlExpr(OvlExprInfo.Expression) + { + ExtractUnqualifiedFunctionTypeFromTargetType(); + + if (!TargetFunctionType->isFunctionType()) { + if (OvlExpr->hasExplicitTemplateArgs()) { + DeclAccessPair dap; + if (FunctionDecl* Fn = S.ResolveSingleFunctionTemplateSpecialization( + OvlExpr, false, &dap) ) { + + if (CXXMethodDecl *Method = dyn_cast(Fn)) { + if (!Method->isStatic()) { + // If the target type is a non-function type and the function + // found is a non-static member function, pretend as if that was + // the target, it's the only possible type to end up with. + TargetTypeIsNonStaticMemberFunction = true; + + // And skip adding the function if its not in the proper form. + // We'll diagnose this due to an empty set of functions. + if (!OvlExprInfo.HasFormOfMemberPointer) + return; + } + } + + Matches.push_back(std::make_pair(dap,Fn)); + } + } + return; + } + + if (OvlExpr->hasExplicitTemplateArgs()) + OvlExpr->getExplicitTemplateArgs().copyInto(OvlExplicitTemplateArgs); + + if (FindAllFunctionsThatMatchTargetTypeExactly()) { + // C++ [over.over]p4: + // If more than one function is selected, [...] + if (Matches.size() > 1) { + if (FoundNonTemplateFunction) + EliminateAllTemplateMatches(); + else + EliminateAllExceptMostSpecializedTemplate(); + } + } + } + +private: + bool isTargetTypeAFunction() const { + return TargetFunctionType->isFunctionType(); + } + + // [ToType] [Return] + + // R (*)(A) --> R (A), IsNonStaticMemberFunction = false + // R (&)(A) --> R (A), IsNonStaticMemberFunction = false + // R (S::*)(A) --> R (A), IsNonStaticMemberFunction = true + void inline ExtractUnqualifiedFunctionTypeFromTargetType() { + TargetFunctionType = S.ExtractUnqualifiedFunctionType(TargetType); + } + + // return true if any matching specializations were found + bool AddMatchingTemplateFunction(FunctionTemplateDecl* FunctionTemplate, + const DeclAccessPair& CurAccessFunPair) { + if (CXXMethodDecl *Method + = dyn_cast(FunctionTemplate->getTemplatedDecl())) { + // Skip non-static function templates when converting to pointer, and + // static when converting to member pointer. + if (Method->isStatic() == TargetTypeIsNonStaticMemberFunction) + return false; + } + else if (TargetTypeIsNonStaticMemberFunction) + return false; + + // C++ [over.over]p2: + // If the name is a function template, template argument deduction is + // done (14.8.2.2), and if the argument deduction succeeds, the + // resulting template argument list is used to generate a single + // function template specialization, which is added to the set of + // overloaded functions considered. + FunctionDecl *Specialization = 0; + TemplateDeductionInfo Info(Context, OvlExpr->getNameLoc()); + if (Sema::TemplateDeductionResult Result + = S.DeduceTemplateArguments(FunctionTemplate, + &OvlExplicitTemplateArgs, + TargetFunctionType, Specialization, + Info)) { + // FIXME: make a note of the failed deduction for diagnostics. + (void)Result; + return false; + } + + // Template argument deduction ensures that we have an exact match. + // This function template specicalization works. + Specialization = cast(Specialization->getCanonicalDecl()); + assert(TargetFunctionType + == Context.getCanonicalType(Specialization->getType())); + Matches.push_back(std::make_pair(CurAccessFunPair, Specialization)); + return true; + } + + bool AddMatchingNonTemplateFunction(NamedDecl* Fn, + const DeclAccessPair& CurAccessFunPair) { + if (CXXMethodDecl *Method = dyn_cast(Fn)) { + // Skip non-static functions when converting to pointer, and static + // when converting to member pointer. + if (Method->isStatic() == TargetTypeIsNonStaticMemberFunction) + return false; + } + else if (TargetTypeIsNonStaticMemberFunction) + return false; + + if (FunctionDecl *FunDecl = dyn_cast(Fn)) { + if (S.getLangOpts().CUDA) + if (FunctionDecl *Caller = dyn_cast(S.CurContext)) + if (S.CheckCUDATarget(Caller, FunDecl)) + return false; + + QualType ResultTy; + if (Context.hasSameUnqualifiedType(TargetFunctionType, + FunDecl->getType()) || + S.IsNoReturnConversion(FunDecl->getType(), TargetFunctionType, + ResultTy)) { + Matches.push_back(std::make_pair(CurAccessFunPair, + cast(FunDecl->getCanonicalDecl()))); + FoundNonTemplateFunction = true; + return true; + } + } + + return false; + } + + bool FindAllFunctionsThatMatchTargetTypeExactly() { + bool Ret = false; + + // 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 (IsInvalidFormOfPointerToMemberFunction()) + return false; + + for (UnresolvedSetIterator I = OvlExpr->decls_begin(), + E = OvlExpr->decls_end(); + I != E; ++I) { + // Look through any using declarations to find the underlying function. + NamedDecl *Fn = (*I)->getUnderlyingDecl(); + + // C++ [over.over]p3: + // Non-member functions and static member functions match + // targets of type "pointer-to-function" or "reference-to-function." + // Nonstatic member functions match targets of + // type "pointer-to-member-function." + // Note that according to DR 247, the containing class does not matter. + if (FunctionTemplateDecl *FunctionTemplate + = dyn_cast(Fn)) { + if (AddMatchingTemplateFunction(FunctionTemplate, I.getPair())) + Ret = true; + } + // If we have explicit template arguments supplied, skip non-templates. + else if (!OvlExpr->hasExplicitTemplateArgs() && + AddMatchingNonTemplateFunction(Fn, I.getPair())) + Ret = true; + } + assert(Ret || Matches.empty()); + return Ret; + } + + void EliminateAllExceptMostSpecializedTemplate() { + // [...] and any given function template specialization F1 is + // eliminated if the set contains a second function template + // specialization whose function template is more specialized + // than the function template of F1 according to the partial + // ordering rules of 14.5.5.2. + + // The algorithm specified above is quadratic. We instead use a + // two-pass algorithm (similar to the one used to identify the + // best viable function in an overload set) that identifies the + // best function template (if it exists). + + UnresolvedSet<4> MatchesCopy; // TODO: avoid! + for (unsigned I = 0, E = Matches.size(); I != E; ++I) + MatchesCopy.addDecl(Matches[I].second, Matches[I].first.getAccess()); + + UnresolvedSetIterator Result = + S.getMostSpecialized(MatchesCopy.begin(), MatchesCopy.end(), + TPOC_Other, 0, SourceExpr->getLocStart(), + S.PDiag(), + S.PDiag(diag::err_addr_ovl_ambiguous) + << Matches[0].second->getDeclName(), + S.PDiag(diag::note_ovl_candidate) + << (unsigned) oc_function_template, + Complain, TargetFunctionType); + + if (Result != MatchesCopy.end()) { + // Make it the first and only element + Matches[0].first = Matches[Result - MatchesCopy.begin()].first; + Matches[0].second = cast(*Result); + Matches.resize(1); + } + } + + void EliminateAllTemplateMatches() { + // [...] any function template specializations in the set are + // eliminated if the set also contains a non-template function, [...] + for (unsigned I = 0, N = Matches.size(); I != N; ) { + if (Matches[I].second->getPrimaryTemplate() == 0) + ++I; + else { + Matches[I] = Matches[--N]; + Matches.set_size(N); + } + } + } + +public: + void ComplainNoMatchesFound() const { + assert(Matches.empty()); + S.Diag(OvlExpr->getLocStart(), diag::err_addr_ovl_no_viable) + << OvlExpr->getName() << TargetFunctionType + << OvlExpr->getSourceRange(); + S.NoteAllOverloadCandidates(OvlExpr, TargetFunctionType); + } + + bool IsInvalidFormOfPointerToMemberFunction() const { + return TargetTypeIsNonStaticMemberFunction && + !OvlExprInfo.HasFormOfMemberPointer; + } + + void ComplainIsInvalidFormOfPointerToMemberFunction() const { + // 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. + S.Diag(OvlExpr->getNameLoc(), diag::err_addr_ovl_no_qualifier) + << TargetType << OvlExpr->getSourceRange(); + } + + void ComplainOfInvalidConversion() const { + S.Diag(OvlExpr->getLocStart(), diag::err_addr_ovl_not_func_ptrref) + << OvlExpr->getName() << TargetType; + } + + void ComplainMultipleMatchesFound() const { + assert(Matches.size() > 1); + S.Diag(OvlExpr->getLocStart(), diag::err_addr_ovl_ambiguous) + << OvlExpr->getName() + << OvlExpr->getSourceRange(); + S.NoteAllOverloadCandidates(OvlExpr, TargetFunctionType); + } + + bool hadMultipleCandidates() const { return (OvlExpr->getNumDecls() > 1); } + + int getNumMatches() const { return Matches.size(); } + + FunctionDecl* getMatchingFunctionDecl() const { + if (Matches.size() != 1) return 0; + return Matches[0].second; + } + + const DeclAccessPair* getMatchingFunctionAccessPair() const { + if (Matches.size() != 1) return 0; + return &Matches[0].first; + } +}; + +/// ResolveAddressOfOverloadedFunction - Try to resolve the address of +/// an overloaded function (C++ [over.over]), where @p From is an +/// expression with overloaded function type and @p ToType is the type +/// we're trying to resolve to. For example: +/// +/// @code +/// int f(double); +/// int f(int); +/// +/// int (*pfd)(double) = f; // selects f(double) +/// @endcode +/// +/// This routine returns the resulting FunctionDecl if it could be +/// resolved, and NULL otherwise. When @p Complain is true, this +/// routine will emit diagnostics if there is an error. +FunctionDecl * +Sema::ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr, + QualType TargetType, + bool Complain, + DeclAccessPair &FoundResult, + bool *pHadMultipleCandidates) { + assert(AddressOfExpr->getType() == Context.OverloadTy); + + AddressOfFunctionResolver Resolver(*this, AddressOfExpr, TargetType, + Complain); + int NumMatches = Resolver.getNumMatches(); + FunctionDecl* Fn = 0; + if (NumMatches == 0 && Complain) { + if (Resolver.IsInvalidFormOfPointerToMemberFunction()) + Resolver.ComplainIsInvalidFormOfPointerToMemberFunction(); + else + Resolver.ComplainNoMatchesFound(); + } + else if (NumMatches > 1 && Complain) + Resolver.ComplainMultipleMatchesFound(); + else if (NumMatches == 1) { + Fn = Resolver.getMatchingFunctionDecl(); + assert(Fn); + FoundResult = *Resolver.getMatchingFunctionAccessPair(); + MarkFunctionReferenced(AddressOfExpr->getLocStart(), Fn); + if (Complain) + CheckAddressOfMemberAccess(AddressOfExpr, FoundResult); + } + + if (pHadMultipleCandidates) + *pHadMultipleCandidates = Resolver.hadMultipleCandidates(); + return Fn; +} + +/// \brief Given an expression that refers to an overloaded function, try to +/// resolve that overloaded function expression down to a single function. +/// +/// This routine can only resolve template-ids that refer to a single function +/// template, where that template-id refers to a single template whose template +/// arguments are either provided by the template-id or have defaults, +/// as described in C++0x [temp.arg.explicit]p3. +FunctionDecl * +Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl, + bool Complain, + DeclAccessPair *FoundResult) { + // C++ [over.over]p1: + // [...] [Note: any redundant set of parentheses surrounding the + // overloaded function name is ignored (5.1). ] + // C++ [over.over]p1: + // [...] The overloaded function name can be preceded by the & + // operator. + + // If we didn't actually find any template-ids, we're done. + if (!ovl->hasExplicitTemplateArgs()) + return 0; + + TemplateArgumentListInfo ExplicitTemplateArgs; + ovl->getExplicitTemplateArgs().copyInto(ExplicitTemplateArgs); + + // Look through all of the overloaded functions, searching for one + // whose type matches exactly. + FunctionDecl *Matched = 0; + for (UnresolvedSetIterator I = ovl->decls_begin(), + E = ovl->decls_end(); I != E; ++I) { + // C++0x [temp.arg.explicit]p3: + // [...] In contexts where deduction is done and fails, or in contexts + // where deduction is not done, if a template argument list is + // specified and it, along with any default template arguments, + // identifies a single function template specialization, then the + // template-id is an lvalue for the function template specialization. + FunctionTemplateDecl *FunctionTemplate + = cast((*I)->getUnderlyingDecl()); + + // C++ [over.over]p2: + // If the name is a function template, template argument deduction is + // done (14.8.2.2), and if the argument deduction succeeds, the + // resulting template argument list is used to generate a single + // function template specialization, which is added to the set of + // overloaded functions considered. + FunctionDecl *Specialization = 0; + TemplateDeductionInfo Info(Context, ovl->getNameLoc()); + if (TemplateDeductionResult Result + = DeduceTemplateArguments(FunctionTemplate, &ExplicitTemplateArgs, + Specialization, Info)) { + // FIXME: make a note of the failed deduction for diagnostics. + (void)Result; + continue; + } + + assert(Specialization && "no specialization and no error?"); + + // Multiple matches; we can't resolve to a single declaration. + if (Matched) { + if (Complain) { + Diag(ovl->getExprLoc(), diag::err_addr_ovl_ambiguous) + << ovl->getName(); + NoteAllOverloadCandidates(ovl); + } + return 0; + } + + Matched = Specialization; + if (FoundResult) *FoundResult = I.getPair(); + } + + return Matched; +} + + + + +// Resolve and fix an overloaded expression that can be resolved +// because it identifies a single function template specialization. +// +// Last three arguments should only be supplied if Complain = true +// +// Return true if it was logically possible to so resolve the +// expression, regardless of whether or not it succeeded. Always +// returns true if 'complain' is set. +bool Sema::ResolveAndFixSingleFunctionTemplateSpecialization( + ExprResult &SrcExpr, bool doFunctionPointerConverion, + bool complain, const SourceRange& OpRangeForComplaining, + QualType DestTypeForComplaining, + unsigned DiagIDForComplaining) { + assert(SrcExpr.get()->getType() == Context.OverloadTy); + + OverloadExpr::FindResult ovl = OverloadExpr::find(SrcExpr.get()); + + DeclAccessPair found; + ExprResult SingleFunctionExpression; + if (FunctionDecl *fn = ResolveSingleFunctionTemplateSpecialization( + ovl.Expression, /*complain*/ false, &found)) { + if (DiagnoseUseOfDecl(fn, SrcExpr.get()->getLocStart())) { + SrcExpr = ExprError(); + return true; + } + + // It is only correct to resolve to an instance method if we're + // resolving a form that's permitted to be a pointer to member. + // Otherwise we'll end up making a bound member expression, which + // is illegal in all the contexts we resolve like this. + if (!ovl.HasFormOfMemberPointer && + isa(fn) && + cast(fn)->isInstance()) { + if (!complain) return false; + + Diag(ovl.Expression->getExprLoc(), + diag::err_bound_member_function) + << 0 << ovl.Expression->getSourceRange(); + + // TODO: I believe we only end up here if there's a mix of + // static and non-static candidates (otherwise the expression + // would have 'bound member' type, not 'overload' type). + // Ideally we would note which candidate was chosen and why + // the static candidates were rejected. + SrcExpr = ExprError(); + return true; + } + + // Fix the expresion to refer to 'fn'. + SingleFunctionExpression = + Owned(FixOverloadedFunctionReference(SrcExpr.take(), found, fn)); + + // If desired, do function-to-pointer decay. + if (doFunctionPointerConverion) { + SingleFunctionExpression = + DefaultFunctionArrayLvalueConversion(SingleFunctionExpression.take()); + if (SingleFunctionExpression.isInvalid()) { + SrcExpr = ExprError(); + return true; + } + } + } + + if (!SingleFunctionExpression.isUsable()) { + if (complain) { + Diag(OpRangeForComplaining.getBegin(), DiagIDForComplaining) + << ovl.Expression->getName() + << DestTypeForComplaining + << OpRangeForComplaining + << ovl.Expression->getQualifierLoc().getSourceRange(); + NoteAllOverloadCandidates(SrcExpr.get()); + + SrcExpr = ExprError(); + return true; + } + + return false; + } + + SrcExpr = SingleFunctionExpression; + return true; +} + +/// \brief Add a single candidate to the overload set. +static void AddOverloadedCallCandidate(Sema &S, + DeclAccessPair FoundDecl, + TemplateArgumentListInfo *ExplicitTemplateArgs, + llvm::ArrayRef Args, + OverloadCandidateSet &CandidateSet, + bool PartialOverloading, + bool KnownValid) { + NamedDecl *Callee = FoundDecl.getDecl(); + if (isa(Callee)) + Callee = cast(Callee)->getTargetDecl(); + + if (FunctionDecl *Func = dyn_cast(Callee)) { + if (ExplicitTemplateArgs) { + assert(!KnownValid && "Explicit template arguments?"); + return; + } + S.AddOverloadCandidate(Func, FoundDecl, Args, CandidateSet, false, + PartialOverloading); + return; + } + + if (FunctionTemplateDecl *FuncTemplate + = dyn_cast(Callee)) { + S.AddTemplateOverloadCandidate(FuncTemplate, FoundDecl, + ExplicitTemplateArgs, Args, CandidateSet); + return; + } + + assert(!KnownValid && "unhandled case in overloaded call candidate"); +} + +/// \brief Add the overload candidates named by callee and/or found by argument +/// dependent lookup to the given overload set. +void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE, + llvm::ArrayRef Args, + OverloadCandidateSet &CandidateSet, + bool PartialOverloading) { + +#ifndef NDEBUG + // Verify that ArgumentDependentLookup is consistent with the rules + // in C++0x [basic.lookup.argdep]p3: + // + // Let X be the lookup set produced by unqualified lookup (3.4.1) + // and let Y be the lookup set produced by argument dependent + // lookup (defined as follows). If X contains + // + // -- a declaration of a class member, or + // + // -- a block-scope function declaration that is not a + // using-declaration, or + // + // -- a declaration that is neither a function or a function + // template + // + // then Y is empty. + + if (ULE->requiresADL()) { + for (UnresolvedLookupExpr::decls_iterator I = ULE->decls_begin(), + E = ULE->decls_end(); I != E; ++I) { + assert(!(*I)->getDeclContext()->isRecord()); + assert(isa(*I) || + !(*I)->getDeclContext()->isFunctionOrMethod()); + assert((*I)->getUnderlyingDecl()->isFunctionOrFunctionTemplate()); + } + } +#endif + + // It would be nice to avoid this copy. + TemplateArgumentListInfo TABuffer; + TemplateArgumentListInfo *ExplicitTemplateArgs = 0; + if (ULE->hasExplicitTemplateArgs()) { + ULE->copyTemplateArgumentsInto(TABuffer); + ExplicitTemplateArgs = &TABuffer; + } + + for (UnresolvedLookupExpr::decls_iterator I = ULE->decls_begin(), + E = ULE->decls_end(); I != E; ++I) + AddOverloadedCallCandidate(*this, I.getPair(), ExplicitTemplateArgs, Args, + CandidateSet, PartialOverloading, + /*KnownValid*/ true); + + if (ULE->requiresADL()) + AddArgumentDependentLookupCandidates(ULE->getName(), /*Operator*/ false, + ULE->getExprLoc(), + Args, ExplicitTemplateArgs, + CandidateSet, PartialOverloading, + ULE->isStdAssociatedNamespace()); +} + +/// Attempt to recover from an ill-formed use of a non-dependent name in a +/// template, where the non-dependent name was declared after the template +/// was defined. This is common in code written for a compilers which do not +/// correctly implement two-stage name lookup. +/// +/// Returns true if a viable candidate was found and a diagnostic was issued. +static bool +DiagnoseTwoPhaseLookup(Sema &SemaRef, SourceLocation FnLoc, + const CXXScopeSpec &SS, LookupResult &R, + TemplateArgumentListInfo *ExplicitTemplateArgs, + llvm::ArrayRef Args) { + if (SemaRef.ActiveTemplateInstantiations.empty() || !SS.isEmpty()) + return false; + + for (DeclContext *DC = SemaRef.CurContext; DC; DC = DC->getParent()) { + if (DC->isTransparentContext()) + continue; + + SemaRef.LookupQualifiedName(R, DC); + + if (!R.empty()) { + R.suppressDiagnostics(); + + if (isa(DC)) { + // Don't diagnose names we find in classes; we get much better + // diagnostics for these from DiagnoseEmptyLookup. + R.clear(); + return false; + } + + OverloadCandidateSet Candidates(FnLoc); + for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) + AddOverloadedCallCandidate(SemaRef, I.getPair(), + ExplicitTemplateArgs, Args, + Candidates, false, /*KnownValid*/ false); + + OverloadCandidateSet::iterator Best; + if (Candidates.BestViableFunction(SemaRef, FnLoc, Best) != OR_Success) { + // No viable functions. Don't bother the user with notes for functions + // which don't work and shouldn't be found anyway. + R.clear(); + return false; + } + + // Find the namespaces where ADL would have looked, and suggest + // declaring the function there instead. + Sema::AssociatedNamespaceSet AssociatedNamespaces; + Sema::AssociatedClassSet AssociatedClasses; + SemaRef.FindAssociatedClassesAndNamespaces(Args, + AssociatedNamespaces, + AssociatedClasses); + // Never suggest declaring a function within namespace 'std'. + Sema::AssociatedNamespaceSet SuggestedNamespaces; + if (DeclContext *Std = SemaRef.getStdNamespace()) { + for (Sema::AssociatedNamespaceSet::iterator + it = AssociatedNamespaces.begin(), + end = AssociatedNamespaces.end(); it != end; ++it) { + if (!Std->Encloses(*it)) + SuggestedNamespaces.insert(*it); + } + } else { + // Lacking the 'std::' namespace, use all of the associated namespaces. + SuggestedNamespaces = AssociatedNamespaces; + } + + SemaRef.Diag(R.getNameLoc(), diag::err_not_found_by_two_phase_lookup) + << R.getLookupName(); + if (SuggestedNamespaces.empty()) { + SemaRef.Diag(Best->Function->getLocation(), + diag::note_not_found_by_two_phase_lookup) + << R.getLookupName() << 0; + } else if (SuggestedNamespaces.size() == 1) { + SemaRef.Diag(Best->Function->getLocation(), + diag::note_not_found_by_two_phase_lookup) + << R.getLookupName() << 1 << *SuggestedNamespaces.begin(); + } else { + // FIXME: It would be useful to list the associated namespaces here, + // but the diagnostics infrastructure doesn't provide a way to produce + // a localized representation of a list of items. + SemaRef.Diag(Best->Function->getLocation(), + diag::note_not_found_by_two_phase_lookup) + << R.getLookupName() << 2; + } + + // Try to recover by calling this function. + return true; + } + + R.clear(); + } + + return false; +} + +/// Attempt to recover from ill-formed use of a non-dependent operator in a +/// template, where the non-dependent operator was declared after the template +/// was defined. +/// +/// Returns true if a viable candidate was found and a diagnostic was issued. +static bool +DiagnoseTwoPhaseOperatorLookup(Sema &SemaRef, OverloadedOperatorKind Op, + SourceLocation OpLoc, + llvm::ArrayRef Args) { + DeclarationName OpName = + SemaRef.Context.DeclarationNames.getCXXOperatorName(Op); + LookupResult R(SemaRef, OpName, OpLoc, Sema::LookupOperatorName); + return DiagnoseTwoPhaseLookup(SemaRef, OpLoc, CXXScopeSpec(), R, + /*ExplicitTemplateArgs=*/0, Args); +} + +namespace { +// Callback to limit the allowed keywords and to only accept typo corrections +// that are keywords or whose decls refer to functions (or template functions) +// that accept the given number of arguments. +class RecoveryCallCCC : public CorrectionCandidateCallback { + public: + RecoveryCallCCC(Sema &SemaRef, unsigned NumArgs, bool HasExplicitTemplateArgs) + : NumArgs(NumArgs), HasExplicitTemplateArgs(HasExplicitTemplateArgs) { + WantTypeSpecifiers = SemaRef.getLangOpts().CPlusPlus; + WantRemainingKeywords = false; + } + + virtual bool ValidateCandidate(const TypoCorrection &candidate) { + if (!candidate.getCorrectionDecl()) + return candidate.isKeyword(); + + for (TypoCorrection::const_decl_iterator DI = candidate.begin(), + DIEnd = candidate.end(); DI != DIEnd; ++DI) { + FunctionDecl *FD = 0; + NamedDecl *ND = (*DI)->getUnderlyingDecl(); + if (FunctionTemplateDecl *FTD = dyn_cast(ND)) + FD = FTD->getTemplatedDecl(); + if (!HasExplicitTemplateArgs && !FD) { + if (!(FD = dyn_cast(ND)) && isa(ND)) { + // If the Decl is neither a function nor a template function, + // determine if it is a pointer or reference to a function. If so, + // check against the number of arguments expected for the pointee. + QualType ValType = cast(ND)->getType(); + if (ValType->isAnyPointerType() || ValType->isReferenceType()) + ValType = ValType->getPointeeType(); + if (const FunctionProtoType *FPT = ValType->getAs()) + if (FPT->getNumArgs() == NumArgs) + return true; + } + } + if (FD && FD->getNumParams() >= NumArgs && + FD->getMinRequiredArguments() <= NumArgs) + return true; + } + return false; + } + + private: + unsigned NumArgs; + bool HasExplicitTemplateArgs; +}; + +// Callback that effectively disabled typo correction +class NoTypoCorrectionCCC : public CorrectionCandidateCallback { + public: + NoTypoCorrectionCCC() { + WantTypeSpecifiers = false; + WantExpressionKeywords = false; + WantCXXNamedCasts = false; + WantRemainingKeywords = false; + } + + virtual bool ValidateCandidate(const TypoCorrection &candidate) { + return false; + } +}; +} + +/// Attempts to recover from a call where no functions were found. +/// +/// Returns true if new candidates were found. +static ExprResult +BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, + UnresolvedLookupExpr *ULE, + SourceLocation LParenLoc, + llvm::MutableArrayRef Args, + SourceLocation RParenLoc, + bool EmptyLookup, bool AllowTypoCorrection) { + + CXXScopeSpec SS; + SS.Adopt(ULE->getQualifierLoc()); + SourceLocation TemplateKWLoc = ULE->getTemplateKeywordLoc(); + + TemplateArgumentListInfo TABuffer; + TemplateArgumentListInfo *ExplicitTemplateArgs = 0; + if (ULE->hasExplicitTemplateArgs()) { + ULE->copyTemplateArgumentsInto(TABuffer); + ExplicitTemplateArgs = &TABuffer; + } + + LookupResult R(SemaRef, ULE->getName(), ULE->getNameLoc(), + Sema::LookupOrdinaryName); + RecoveryCallCCC Validator(SemaRef, Args.size(), ExplicitTemplateArgs != 0); + NoTypoCorrectionCCC RejectAll; + CorrectionCandidateCallback *CCC = AllowTypoCorrection ? + (CorrectionCandidateCallback*)&Validator : + (CorrectionCandidateCallback*)&RejectAll; + if (!DiagnoseTwoPhaseLookup(SemaRef, Fn->getExprLoc(), SS, R, + ExplicitTemplateArgs, Args) && + (!EmptyLookup || + SemaRef.DiagnoseEmptyLookup(S, SS, R, *CCC, + ExplicitTemplateArgs, Args))) + 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. + ExprResult NewFn = ExprError(); + if ((*R.begin())->isCXXClassMember()) + NewFn = SemaRef.BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc, + R, ExplicitTemplateArgs); + else if (ExplicitTemplateArgs || TemplateKWLoc.isValid()) + NewFn = SemaRef.BuildTemplateIdExpr(SS, TemplateKWLoc, R, false, + ExplicitTemplateArgs); + else + NewFn = SemaRef.BuildDeclarationNameExpr(SS, R, false); + + if (NewFn.isInvalid()) + return ExprError(); + + // This shouldn't cause an infinite loop because we're giving it + // an expression with viable lookup results, which should never + // end up here. + return SemaRef.ActOnCallExpr(/*Scope*/ 0, NewFn.take(), LParenLoc, + MultiExprArg(Args.data(), Args.size()), + RParenLoc); +} + +/// ResolveOverloadedCallFn - Given the call expression that calls Fn +/// (which eventually refers to the declaration Func) and the call +/// arguments Args/NumArgs, attempt to resolve the function call down +/// to a specific function. If overload resolution succeeds, returns +/// the function declaration produced by overload +/// resolution. Otherwise, emits diagnostics, deletes all of the +/// arguments and Fn, and returns NULL. +ExprResult +Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, + SourceLocation LParenLoc, + Expr **Args, unsigned NumArgs, + SourceLocation RParenLoc, + Expr *ExecConfig, + bool AllowTypoCorrection) { +#ifndef NDEBUG + if (ULE->requiresADL()) { + // To do ADL, we must have found an unqualified name. + assert(!ULE->getQualifier() && "qualified name with ADL"); + + // We don't perform ADL for implicit declarations of builtins. + // Verify that this was correctly set up. + FunctionDecl *F; + if (ULE->decls_begin() + 1 == ULE->decls_end() && + (F = dyn_cast(*ULE->decls_begin())) && + F->getBuiltinID() && F->isImplicit()) + llvm_unreachable("performing ADL for builtin"); + + // We don't perform ADL in C. + assert(getLangOpts().CPlusPlus && "ADL enabled in C"); + } else + assert(!ULE->isStdAssociatedNamespace() && + "std is associated namespace but not doing ADL"); +#endif + + UnbridgedCastsSet UnbridgedCasts; + if (checkArgPlaceholdersForOverload(*this, Args, NumArgs, UnbridgedCasts)) + return ExprError(); + + OverloadCandidateSet CandidateSet(Fn->getExprLoc()); + + // Add the functions denoted by the callee to the set of candidate + // functions, including those from argument-dependent lookup. + AddOverloadedCallCandidates(ULE, llvm::makeArrayRef(Args, NumArgs), + CandidateSet); + + // If we found nothing, try to recover. + // BuildRecoveryCallExpr diagnoses the error itself, so we just bail + // out if it fails. + if (CandidateSet.empty()) { + // In Microsoft mode, if we are inside a template class member function then + // create a type dependent CallExpr. The goal is to postpone name lookup + // to instantiation time to be able to search into type dependent base + // classes. + if (getLangOpts().MicrosoftMode && CurContext->isDependentContext() && + (isa(CurContext) || isa(CurContext))) { + CallExpr *CE = new (Context) CallExpr(Context, Fn, Args, NumArgs, + Context.DependentTy, VK_RValue, + RParenLoc); + CE->setTypeDependent(true); + return Owned(CE); + } + return BuildRecoveryCallExpr(*this, S, Fn, ULE, LParenLoc, + llvm::MutableArrayRef(Args, NumArgs), + RParenLoc, /*EmptyLookup=*/true, + AllowTypoCorrection); + } + + UnbridgedCasts.restore(); + + OverloadCandidateSet::iterator Best; + switch (CandidateSet.BestViableFunction(*this, Fn->getLocStart(), Best)) { + case OR_Success: { + FunctionDecl *FDecl = Best->Function; + MarkFunctionReferenced(Fn->getExprLoc(), FDecl); + CheckUnresolvedLookupAccess(ULE, Best->FoundDecl); + DiagnoseUseOfDecl(FDecl, ULE->getNameLoc()); + Fn = FixOverloadedFunctionReference(Fn, Best->FoundDecl, FDecl); + return BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, NumArgs, RParenLoc, + ExecConfig); + } + + case OR_No_Viable_Function: { + // Try to recover by looking for viable functions which the user might + // have meant to call. + ExprResult Recovery = BuildRecoveryCallExpr(*this, S, Fn, ULE, LParenLoc, + llvm::MutableArrayRef(Args, NumArgs), + RParenLoc, + /*EmptyLookup=*/false, + AllowTypoCorrection); + if (!Recovery.isInvalid()) + return Recovery; + + Diag(Fn->getLocStart(), + diag::err_ovl_no_viable_function_in_call) + << ULE->getName() << Fn->getSourceRange(); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, + llvm::makeArrayRef(Args, NumArgs)); + break; + } + + case OR_Ambiguous: + Diag(Fn->getLocStart(), diag::err_ovl_ambiguous_call) + << ULE->getName() << Fn->getSourceRange(); + CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, + llvm::makeArrayRef(Args, NumArgs)); + break; + + case OR_Deleted: + { + Diag(Fn->getLocStart(), diag::err_ovl_deleted_call) + << Best->Function->isDeleted() + << ULE->getName() + << getDeletedOrUnavailableSuffix(Best->Function) + << Fn->getSourceRange(); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, + llvm::makeArrayRef(Args, NumArgs)); + + // We emitted an error for the unvailable/deleted function call but keep + // the call in the AST. + FunctionDecl *FDecl = Best->Function; + Fn = FixOverloadedFunctionReference(Fn, Best->FoundDecl, FDecl); + return BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, NumArgs, + RParenLoc, ExecConfig); + } + } + + // Overload resolution failed. + return ExprError(); +} + +static bool IsOverloaded(const UnresolvedSetImpl &Functions) { + return Functions.size() > 1 || + (Functions.size() == 1 && isa(*Functions.begin())); +} + +/// \brief Create a unary operation that may resolve to an overloaded +/// operator. +/// +/// \param OpLoc The location of the operator itself (e.g., '*'). +/// +/// \param OpcIn The UnaryOperator::Opcode that describes this +/// operator. +/// +/// \param Functions The set of non-member functions that will be +/// considered by overload resolution. The caller needs to build this +/// set based on the context using, e.g., +/// LookupOverloadedOperatorName() and ArgumentDependentLookup(). This +/// set should not contain any member functions; those will be added +/// by CreateOverloadedUnaryOp(). +/// +/// \param input The input argument. +ExprResult +Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, + const UnresolvedSetImpl &Fns, + Expr *Input) { + UnaryOperator::Opcode Opc = static_cast(OpcIn); + + 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); + + if (checkPlaceholderForOverload(*this, Input)) + return ExprError(); + + Expr *Args[2] = { Input, 0 }; + unsigned NumArgs = 1; + + // 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 == UO_PostInc || Opc == UO_PostDec) { + llvm::APSInt Zero(Context.getTypeSize(Context.IntTy), false); + Args[1] = IntegerLiteral::Create(Context, Zero, Context.IntTy, + SourceLocation()); + NumArgs = 2; + } + + if (Input->isTypeDependent()) { + if (Fns.empty()) + return Owned(new (Context) UnaryOperator(Input, + Opc, + Context.DependentTy, + VK_RValue, OK_Ordinary, + OpLoc)); + + CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators + UnresolvedLookupExpr *Fn + = UnresolvedLookupExpr::Create(Context, NamingClass, + NestedNameSpecifierLoc(), OpNameInfo, + /*ADL*/ true, IsOverloaded(Fns), + Fns.begin(), Fns.end()); + return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn, + &Args[0], NumArgs, + Context.DependentTy, + VK_RValue, + OpLoc)); + } + + // Build an empty overload set. + OverloadCandidateSet CandidateSet(OpLoc); + + // Add the candidates from the given function set. + AddFunctionCandidates(Fns, llvm::makeArrayRef(Args, NumArgs), CandidateSet, + false); + + // Add operator candidates that are member functions. + AddMemberOperatorCandidates(Op, OpLoc, &Args[0], NumArgs, CandidateSet); + + // Add candidates from ADL. + AddArgumentDependentLookupCandidates(OpName, /*Operator*/ true, + OpLoc, llvm::makeArrayRef(Args, NumArgs), + /*ExplicitTemplateArgs*/ 0, + CandidateSet); + + // Add builtin operator candidates. + AddBuiltinOperatorCandidates(Op, OpLoc, &Args[0], NumArgs, CandidateSet); + + bool HadMultipleCandidates = (CandidateSet.size() > 1); + + // Perform overload resolution. + OverloadCandidateSet::iterator Best; + switch (CandidateSet.BestViableFunction(*this, OpLoc, Best)) { + case OR_Success: { + // We found a built-in operator or an overloaded operator. + FunctionDecl *FnDecl = Best->Function; + + if (FnDecl) { + // We matched an overloaded operator. Build a call to that + // operator. + + MarkFunctionReferenced(OpLoc, FnDecl); + + // Convert the arguments. + if (CXXMethodDecl *Method = dyn_cast(FnDecl)) { + CheckMemberOperatorAccess(OpLoc, Args[0], 0, Best->FoundDecl); + + ExprResult InputRes = + PerformObjectArgumentInitialization(Input, /*Qualifier=*/0, + Best->FoundDecl, Method); + if (InputRes.isInvalid()) + return ExprError(); + Input = InputRes.take(); + } else { + // Convert the arguments. + ExprResult InputInit + = PerformCopyInitialization(InitializedEntity::InitializeParameter( + Context, + FnDecl->getParamDecl(0)), + SourceLocation(), + Input); + if (InputInit.isInvalid()) + return ExprError(); + Input = InputInit.take(); + } + + DiagnoseUseOfDecl(Best->FoundDecl, OpLoc); + + // Determine the result type. + QualType ResultTy = FnDecl->getResultType(); + ExprValueKind VK = Expr::getValueKindForType(ResultTy); + ResultTy = ResultTy.getNonLValueExprType(Context); + + // Build the actual expression node. + ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl, + HadMultipleCandidates, OpLoc); + if (FnExpr.isInvalid()) + return ExprError(); + + Args[0] = Input; + CallExpr *TheCall = + new (Context) CXXOperatorCallExpr(Context, Op, FnExpr.take(), + Args, NumArgs, ResultTy, VK, OpLoc); + + if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall, + FnDecl)) + return ExprError(); + + 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 + // operator node. + ExprResult InputRes = + PerformImplicitConversion(Input, Best->BuiltinTypes.ParamTypes[0], + Best->Conversions[0], AA_Passing); + if (InputRes.isInvalid()) + return ExprError(); + Input = InputRes.take(); + break; + } + } + + case OR_No_Viable_Function: + // This is an erroneous use of an operator which can be overloaded by + // a non-member function. Check for non-member operators which were + // defined too late to be candidates. + if (DiagnoseTwoPhaseOperatorLookup(*this, Op, OpLoc, + llvm::makeArrayRef(Args, NumArgs))) + // FIXME: Recover by calling the found function. + return ExprError(); + + // No viable function; fall through to handling this as a + // built-in operator, which will produce an error message for us. + break; + + case OR_Ambiguous: + Diag(OpLoc, diag::err_ovl_ambiguous_oper_unary) + << UnaryOperator::getOpcodeStr(Opc) + << Input->getType() + << Input->getSourceRange(); + CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, + llvm::makeArrayRef(Args, NumArgs), + UnaryOperator::getOpcodeStr(Opc), OpLoc); + return ExprError(); + + case OR_Deleted: + Diag(OpLoc, diag::err_ovl_deleted_oper) + << Best->Function->isDeleted() + << UnaryOperator::getOpcodeStr(Opc) + << getDeletedOrUnavailableSuffix(Best->Function) + << Input->getSourceRange(); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, + llvm::makeArrayRef(Args, NumArgs), + UnaryOperator::getOpcodeStr(Opc), OpLoc); + 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. + return CreateBuiltinUnaryOp(OpLoc, Opc, Input); +} + +/// \brief Create a binary operation that may resolve to an overloaded +/// operator. +/// +/// \param OpLoc The location of the operator itself (e.g., '+'). +/// +/// \param OpcIn The BinaryOperator::Opcode that describes this +/// operator. +/// +/// \param Functions The set of non-member functions that will be +/// considered by overload resolution. The caller needs to build this +/// set based on the context using, e.g., +/// LookupOverloadedOperatorName() and ArgumentDependentLookup(). This +/// set should not contain any member functions; those will be added +/// by CreateOverloadedBinOp(). +/// +/// \param LHS Left-hand argument. +/// \param RHS Right-hand argument. +ExprResult +Sema::CreateOverloadedBinOp(SourceLocation OpLoc, + unsigned OpcIn, + const UnresolvedSetImpl &Fns, + Expr *LHS, Expr *RHS) { + Expr *Args[2] = { LHS, RHS }; + LHS=RHS=0; //Please use only Args instead of LHS/RHS couple + + BinaryOperator::Opcode Opc = static_cast(OpcIn); + OverloadedOperatorKind Op = BinaryOperator::getOverloadedOperator(Opc); + DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op); + + // If either side is type-dependent, create an appropriate dependent + // expression. + if (Args[0]->isTypeDependent() || Args[1]->isTypeDependent()) { + if (Fns.empty()) { + // If there are no functions to store, just build a dependent + // BinaryOperator or CompoundAssignment. + if (Opc <= BO_Assign || Opc > BO_OrAssign) + return Owned(new (Context) BinaryOperator(Args[0], Args[1], Opc, + Context.DependentTy, + VK_RValue, OK_Ordinary, + OpLoc)); + + return Owned(new (Context) CompoundAssignOperator(Args[0], Args[1], Opc, + Context.DependentTy, + VK_LValue, + OK_Ordinary, + Context.DependentTy, + Context.DependentTy, + 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, NamingClass, + NestedNameSpecifierLoc(), OpNameInfo, + /*ADL*/ true, IsOverloaded(Fns), + Fns.begin(), Fns.end()); + return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn, + Args, 2, + Context.DependentTy, + VK_RValue, + OpLoc)); + } + + // Always do placeholder-like conversions on the RHS. + if (checkPlaceholderForOverload(*this, Args[1])) + return ExprError(); + + // Do placeholder-like conversion on the LHS; note that we should + // not get here with a PseudoObject LHS. + assert(Args[0]->getObjectKind() != OK_ObjCProperty); + if (checkPlaceholderForOverload(*this, Args[0])) + return ExprError(); + + // If this is the assignment operator, we only perform overload resolution + // if the left-hand side is a class or enumeration type. This is actually + // a hack. The standard requires that we do overload resolution between the + // 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 == BO_Assign && !Args[0]->getType()->isOverloadableType()) + return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]); + + // If this is the .* operator, which is not overloadable, just + // create a built-in binary operator. + if (Opc == BO_PtrMemD) + return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]); + + // Build an empty overload set. + OverloadCandidateSet CandidateSet(OpLoc); + + // Add the candidates from the given function set. + AddFunctionCandidates(Fns, Args, CandidateSet, false); + + // Add operator candidates that are member functions. + AddMemberOperatorCandidates(Op, OpLoc, Args, 2, CandidateSet); + + // Add candidates from ADL. + AddArgumentDependentLookupCandidates(OpName, /*Operator*/ true, + OpLoc, Args, + /*ExplicitTemplateArgs*/ 0, + CandidateSet); + + // Add builtin operator candidates. + AddBuiltinOperatorCandidates(Op, OpLoc, Args, 2, CandidateSet); + + bool HadMultipleCandidates = (CandidateSet.size() > 1); + + // Perform overload resolution. + OverloadCandidateSet::iterator Best; + switch (CandidateSet.BestViableFunction(*this, OpLoc, Best)) { + case OR_Success: { + // We found a built-in operator or an overloaded operator. + FunctionDecl *FnDecl = Best->Function; + + if (FnDecl) { + // We matched an overloaded operator. Build a call to that + // operator. + + MarkFunctionReferenced(OpLoc, FnDecl); + + // Convert the arguments. + if (CXXMethodDecl *Method = dyn_cast(FnDecl)) { + // Best->Access is only meaningful for class members. + CheckMemberOperatorAccess(OpLoc, Args[0], Args[1], Best->FoundDecl); + + ExprResult Arg1 = + PerformCopyInitialization( + InitializedEntity::InitializeParameter(Context, + FnDecl->getParamDecl(0)), + SourceLocation(), Owned(Args[1])); + if (Arg1.isInvalid()) + return ExprError(); + + ExprResult Arg0 = + PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0, + Best->FoundDecl, Method); + if (Arg0.isInvalid()) + return ExprError(); + Args[0] = Arg0.takeAs(); + Args[1] = RHS = Arg1.takeAs(); + } else { + // Convert the arguments. + ExprResult Arg0 = PerformCopyInitialization( + InitializedEntity::InitializeParameter(Context, + FnDecl->getParamDecl(0)), + SourceLocation(), Owned(Args[0])); + if (Arg0.isInvalid()) + return ExprError(); + + ExprResult Arg1 = + PerformCopyInitialization( + InitializedEntity::InitializeParameter(Context, + FnDecl->getParamDecl(1)), + SourceLocation(), Owned(Args[1])); + if (Arg1.isInvalid()) + return ExprError(); + Args[0] = LHS = Arg0.takeAs(); + Args[1] = RHS = Arg1.takeAs(); + } + + DiagnoseUseOfDecl(Best->FoundDecl, OpLoc); + + // Determine the result type. + QualType ResultTy = FnDecl->getResultType(); + ExprValueKind VK = Expr::getValueKindForType(ResultTy); + ResultTy = ResultTy.getNonLValueExprType(Context); + + // Build the actual expression node. + ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl, + HadMultipleCandidates, OpLoc); + if (FnExpr.isInvalid()) + return ExprError(); + + CXXOperatorCallExpr *TheCall = + new (Context) CXXOperatorCallExpr(Context, Op, FnExpr.take(), + Args, 2, ResultTy, VK, OpLoc); + + if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall, + FnDecl)) + return ExprError(); + + 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 + // operator node. + ExprResult ArgsRes0 = + PerformImplicitConversion(Args[0], Best->BuiltinTypes.ParamTypes[0], + Best->Conversions[0], AA_Passing); + if (ArgsRes0.isInvalid()) + return ExprError(); + Args[0] = ArgsRes0.take(); + + ExprResult ArgsRes1 = + PerformImplicitConversion(Args[1], Best->BuiltinTypes.ParamTypes[1], + Best->Conversions[1], AA_Passing); + if (ArgsRes1.isInvalid()) + return ExprError(); + Args[1] = ArgsRes1.take(); + break; + } + } + + case OR_No_Viable_Function: { + // C++ [over.match.oper]p9: + // 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 == 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 + ExprResult Result = ExprError(); + if (Args[0]->getType()->isRecordType() && + Opc >= BO_Assign && Opc <= BO_OrAssign) { + Diag(OpLoc, diag::err_ovl_no_viable_oper) + << BinaryOperator::getOpcodeStr(Opc) + << Args[0]->getSourceRange() << Args[1]->getSourceRange(); + } else { + // This is an erroneous use of an operator which can be overloaded by + // a non-member function. Check for non-member operators which were + // defined too late to be candidates. + if (DiagnoseTwoPhaseOperatorLookup(*this, Op, OpLoc, Args)) + // FIXME: Recover by calling the found function. + return ExprError(); + + // No viable function; try to create a built-in operation, which will + // produce an error. Then, show the non-viable candidates. + Result = CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]); + } + assert(Result.isInvalid() && + "C++ binary operator overloading is missing candidates!"); + if (Result.isInvalid()) + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, + BinaryOperator::getOpcodeStr(Opc), OpLoc); + return move(Result); + } + + case OR_Ambiguous: + Diag(OpLoc, diag::err_ovl_ambiguous_oper_binary) + << BinaryOperator::getOpcodeStr(Opc) + << Args[0]->getType() << Args[1]->getType() + << Args[0]->getSourceRange() << Args[1]->getSourceRange(); + CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args, + BinaryOperator::getOpcodeStr(Opc), OpLoc); + return ExprError(); + + case OR_Deleted: + if (isImplicitlyDeleted(Best->Function)) { + CXXMethodDecl *Method = cast(Best->Function); + Diag(OpLoc, diag::err_ovl_deleted_special_oper) + << getSpecialMember(Method) + << BinaryOperator::getOpcodeStr(Opc) + << getDeletedOrUnavailableSuffix(Best->Function); + + if (getSpecialMember(Method) != CXXInvalid) { + // The user probably meant to call this special member. Just + // explain why it's deleted. + NoteDeletedFunction(Method); + return ExprError(); + } + } else { + Diag(OpLoc, diag::err_ovl_deleted_oper) + << Best->Function->isDeleted() + << BinaryOperator::getOpcodeStr(Opc) + << getDeletedOrUnavailableSuffix(Best->Function) + << Args[0]->getSourceRange() << Args[1]->getSourceRange(); + } + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, + BinaryOperator::getOpcodeStr(Opc), OpLoc); + return ExprError(); + } + + // We matched a built-in operator; build it. + return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]); +} + +ExprResult +Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, + SourceLocation RLoc, + Expr *Base, Expr *Idx) { + Expr *Args[2] = { Base, Idx }; + DeclarationName OpName = + Context.DeclarationNames.getCXXOperatorName(OO_Subscript); + + // If either side is type-dependent, create an appropriate dependent + // expression. + 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, NamingClass, + NestedNameSpecifierLoc(), OpNameInfo, + /*ADL*/ true, /*Overloaded*/ false, + UnresolvedSetIterator(), + UnresolvedSetIterator()); + // Can't add any actual overloads yet + + return Owned(new (Context) CXXOperatorCallExpr(Context, OO_Subscript, Fn, + Args, 2, + Context.DependentTy, + VK_RValue, + RLoc)); + } + + // Handle placeholders on both operands. + if (checkPlaceholderForOverload(*this, Args[0])) + return ExprError(); + if (checkPlaceholderForOverload(*this, Args[1])) + return ExprError(); + + // Build an empty overload set. + OverloadCandidateSet CandidateSet(LLoc); + + // Subscript can only be overloaded as a member function. + + // Add operator candidates that are member functions. + AddMemberOperatorCandidates(OO_Subscript, LLoc, Args, 2, CandidateSet); + + // Add builtin operator candidates. + AddBuiltinOperatorCandidates(OO_Subscript, LLoc, Args, 2, CandidateSet); + + bool HadMultipleCandidates = (CandidateSet.size() > 1); + + // Perform overload resolution. + OverloadCandidateSet::iterator Best; + switch (CandidateSet.BestViableFunction(*this, LLoc, Best)) { + case OR_Success: { + // We found a built-in operator or an overloaded operator. + FunctionDecl *FnDecl = Best->Function; + + if (FnDecl) { + // We matched an overloaded operator. Build a call to that + // operator. + + MarkFunctionReferenced(LLoc, FnDecl); + + CheckMemberOperatorAccess(LLoc, Args[0], Args[1], Best->FoundDecl); + DiagnoseUseOfDecl(Best->FoundDecl, LLoc); + + // Convert the arguments. + CXXMethodDecl *Method = cast(FnDecl); + ExprResult Arg0 = + PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0, + Best->FoundDecl, Method); + if (Arg0.isInvalid()) + return ExprError(); + Args[0] = Arg0.take(); + + // Convert the arguments. + ExprResult InputInit + = PerformCopyInitialization(InitializedEntity::InitializeParameter( + Context, + FnDecl->getParamDecl(0)), + SourceLocation(), + Owned(Args[1])); + if (InputInit.isInvalid()) + return ExprError(); + + Args[1] = InputInit.takeAs(); + + // Determine the result type + QualType ResultTy = FnDecl->getResultType(); + ExprValueKind VK = Expr::getValueKindForType(ResultTy); + ResultTy = ResultTy.getNonLValueExprType(Context); + + // Build the actual expression node. + DeclarationNameInfo OpLocInfo(OpName, LLoc); + OpLocInfo.setCXXOperatorNameRange(SourceRange(LLoc, RLoc)); + ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl, + HadMultipleCandidates, + OpLocInfo.getLoc(), + OpLocInfo.getInfo()); + if (FnExpr.isInvalid()) + return ExprError(); + + CXXOperatorCallExpr *TheCall = + new (Context) CXXOperatorCallExpr(Context, OO_Subscript, + FnExpr.take(), Args, 2, + ResultTy, VK, RLoc); + + if (CheckCallReturnType(FnDecl->getResultType(), LLoc, TheCall, + FnDecl)) + return ExprError(); + + 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 + // operator node. + ExprResult ArgsRes0 = + PerformImplicitConversion(Args[0], Best->BuiltinTypes.ParamTypes[0], + Best->Conversions[0], AA_Passing); + if (ArgsRes0.isInvalid()) + return ExprError(); + Args[0] = ArgsRes0.take(); + + ExprResult ArgsRes1 = + PerformImplicitConversion(Args[1], Best->BuiltinTypes.ParamTypes[1], + Best->Conversions[1], AA_Passing); + if (ArgsRes1.isInvalid()) + return ExprError(); + Args[1] = ArgsRes1.take(); + + break; + } + } + + case OR_No_Viable_Function: { + if (CandidateSet.empty()) + Diag(LLoc, diag::err_ovl_no_oper) + << Args[0]->getType() << /*subscript*/ 0 + << Args[0]->getSourceRange() << Args[1]->getSourceRange(); + else + Diag(LLoc, diag::err_ovl_no_viable_subscript) + << Args[0]->getType() + << Args[0]->getSourceRange() << Args[1]->getSourceRange(); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, + "[]", LLoc); + return ExprError(); + } + + case OR_Ambiguous: + Diag(LLoc, diag::err_ovl_ambiguous_oper_binary) + << "[]" + << Args[0]->getType() << Args[1]->getType() + << Args[0]->getSourceRange() << Args[1]->getSourceRange(); + CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args, + "[]", LLoc); + return ExprError(); + + case OR_Deleted: + Diag(LLoc, diag::err_ovl_deleted_oper) + << Best->Function->isDeleted() << "[]" + << getDeletedOrUnavailableSuffix(Best->Function) + << Args[0]->getSourceRange() << Args[1]->getSourceRange(); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, + "[]", LLoc); + return ExprError(); + } + + // We matched a built-in operator; build it. + return CreateBuiltinArraySubscriptExpr(Args[0], LLoc, Args[1], RLoc); +} + +/// BuildCallToMemberFunction - Build a call to a member +/// function. MemExpr is the expression that refers to the member +/// function (and includes the object parameter), Args/NumArgs are the +/// arguments to the function call (not including the object +/// parameter). The caller needs to validate that the member +/// expression refers to a non-static member function or an overloaded +/// member function. +ExprResult +Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, + SourceLocation LParenLoc, Expr **Args, + unsigned NumArgs, SourceLocation RParenLoc) { + assert(MemExprE->getType() == Context.BoundMemberTy || + MemExprE->getType() == Context.OverloadTy); + + // Dig out the member expression. This holds both the object + // argument and the member function we're referring to. + Expr *NakedMemExpr = MemExprE->IgnoreParens(); + + // Determine whether this is a call to a pointer-to-member function. + if (BinaryOperator *op = dyn_cast(NakedMemExpr)) { + assert(op->getType() == Context.BoundMemberTy); + assert(op->getOpcode() == BO_PtrMemD || op->getOpcode() == BO_PtrMemI); + + QualType fnType = + op->getRHS()->getType()->castAs()->getPointeeType(); + + const FunctionProtoType *proto = fnType->castAs(); + QualType resultType = proto->getCallResultType(Context); + ExprValueKind valueKind = Expr::getValueKindForType(proto->getResultType()); + + // Check that the object type isn't more qualified than the + // member function we're calling. + Qualifiers funcQuals = Qualifiers::fromCVRMask(proto->getTypeQuals()); + + QualType objectType = op->getLHS()->getType(); + if (op->getOpcode() == BO_PtrMemI) + objectType = objectType->castAs()->getPointeeType(); + Qualifiers objectQuals = objectType.getQualifiers(); + + Qualifiers difference = objectQuals - funcQuals; + difference.removeObjCGCAttr(); + difference.removeAddressSpace(); + if (difference) { + std::string qualsString = difference.getAsString(); + Diag(LParenLoc, diag::err_pointer_to_member_call_drops_quals) + << fnType.getUnqualifiedType() + << qualsString + << (qualsString.find(' ') == std::string::npos ? 1 : 2); + } + + CXXMemberCallExpr *call + = new (Context) CXXMemberCallExpr(Context, MemExprE, Args, NumArgs, + resultType, valueKind, RParenLoc); + + if (CheckCallReturnType(proto->getResultType(), + op->getRHS()->getLocStart(), + call, 0)) + return ExprError(); + + if (ConvertArgumentsForCall(call, op, 0, proto, Args, NumArgs, RParenLoc)) + return ExprError(); + + return MaybeBindToTemporary(call); + } + + UnbridgedCastsSet UnbridgedCasts; + if (checkArgPlaceholdersForOverload(*this, Args, NumArgs, UnbridgedCasts)) + return ExprError(); + + MemberExpr *MemExpr; + CXXMethodDecl *Method = 0; + DeclAccessPair FoundDecl = DeclAccessPair::make(0, AS_public); + NestedNameSpecifier *Qualifier = 0; + if (isa(NakedMemExpr)) { + MemExpr = cast(NakedMemExpr); + Method = cast(MemExpr->getMemberDecl()); + FoundDecl = MemExpr->getFoundDecl(); + Qualifier = MemExpr->getQualifier(); + UnbridgedCasts.restore(); + } else { + UnresolvedMemberExpr *UnresExpr = cast(NakedMemExpr); + Qualifier = UnresExpr->getQualifier(); + + QualType ObjectType = UnresExpr->getBaseType(); + Expr::Classification ObjectClassification + = UnresExpr->isArrow()? Expr::Classification::makeSimpleLValue() + : UnresExpr->getBase()->Classify(Context); + + // Add overload candidates + OverloadCandidateSet CandidateSet(UnresExpr->getMemberLoc()); + + // FIXME: avoid copy. + TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = 0; + if (UnresExpr->hasExplicitTemplateArgs()) { + UnresExpr->copyTemplateArgumentsInto(TemplateArgsBuffer); + TemplateArgs = &TemplateArgsBuffer; + } + + for (UnresolvedMemberExpr::decls_iterator I = UnresExpr->decls_begin(), + E = UnresExpr->decls_end(); I != E; ++I) { + + NamedDecl *Func = *I; + CXXRecordDecl *ActingDC = cast(Func->getDeclContext()); + if (isa(Func)) + Func = cast(Func)->getTargetDecl(); + + + // Microsoft supports direct constructor calls. + if (getLangOpts().MicrosoftExt && isa(Func)) { + AddOverloadCandidate(cast(Func), I.getPair(), + llvm::makeArrayRef(Args, NumArgs), CandidateSet); + } else if ((Method = dyn_cast(Func))) { + // If explicit template arguments were provided, we can't call a + // non-template member function. + if (TemplateArgs) + continue; + + AddMethodCandidate(Method, I.getPair(), ActingDC, ObjectType, + ObjectClassification, + llvm::makeArrayRef(Args, NumArgs), CandidateSet, + /*SuppressUserConversions=*/false); + } else { + AddMethodTemplateCandidate(cast(Func), + I.getPair(), ActingDC, TemplateArgs, + ObjectType, ObjectClassification, + llvm::makeArrayRef(Args, NumArgs), + CandidateSet, + /*SuppressUsedConversions=*/false); + } + } + + DeclarationName DeclName = UnresExpr->getMemberName(); + + UnbridgedCasts.restore(); + + OverloadCandidateSet::iterator Best; + switch (CandidateSet.BestViableFunction(*this, UnresExpr->getLocStart(), + Best)) { + case OR_Success: + Method = cast(Best->Function); + MarkFunctionReferenced(UnresExpr->getMemberLoc(), Method); + FoundDecl = Best->FoundDecl; + CheckUnresolvedMemberAccess(UnresExpr, Best->FoundDecl); + DiagnoseUseOfDecl(Best->FoundDecl, UnresExpr->getNameLoc()); + break; + + case OR_No_Viable_Function: + Diag(UnresExpr->getMemberLoc(), + diag::err_ovl_no_viable_member_function_in_call) + << DeclName << MemExprE->getSourceRange(); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, + llvm::makeArrayRef(Args, NumArgs)); + // FIXME: Leaking incoming expressions! + return ExprError(); + + case OR_Ambiguous: + Diag(UnresExpr->getMemberLoc(), diag::err_ovl_ambiguous_member_call) + << DeclName << MemExprE->getSourceRange(); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, + llvm::makeArrayRef(Args, NumArgs)); + // FIXME: Leaking incoming expressions! + return ExprError(); + + case OR_Deleted: + Diag(UnresExpr->getMemberLoc(), diag::err_ovl_deleted_member_call) + << Best->Function->isDeleted() + << DeclName + << getDeletedOrUnavailableSuffix(Best->Function) + << MemExprE->getSourceRange(); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, + llvm::makeArrayRef(Args, NumArgs)); + // FIXME: Leaking incoming expressions! + return ExprError(); + } + + MemExprE = FixOverloadedFunctionReference(MemExprE, FoundDecl, Method); + + // If overload resolution picked a static member, build a + // non-member call based on that function. + if (Method->isStatic()) { + return BuildResolvedCallExpr(MemExprE, Method, LParenLoc, + Args, NumArgs, RParenLoc); + } + + MemExpr = cast(MemExprE->IgnoreParens()); + } + + QualType ResultType = Method->getResultType(); + ExprValueKind VK = Expr::getValueKindForType(ResultType); + ResultType = ResultType.getNonLValueExprType(Context); + + assert(Method && "Member call to something that isn't a method?"); + CXXMemberCallExpr *TheCall = + new (Context) CXXMemberCallExpr(Context, MemExprE, Args, NumArgs, + ResultType, VK, RParenLoc); + + // Check for a valid return type. + if (CheckCallReturnType(Method->getResultType(), MemExpr->getMemberLoc(), + TheCall, Method)) + return ExprError(); + + // Convert the object argument (for a non-static member function call). + // We only need to do this if there was actually an overload; otherwise + // it was done at lookup. + if (!Method->isStatic()) { + ExprResult ObjectArg = + PerformObjectArgumentInitialization(MemExpr->getBase(), Qualifier, + FoundDecl, Method); + if (ObjectArg.isInvalid()) + return ExprError(); + MemExpr->setBase(ObjectArg.take()); + } + + // Convert the rest of the arguments + const FunctionProtoType *Proto = + Method->getType()->getAs(); + if (ConvertArgumentsForCall(TheCall, MemExpr, Method, Proto, Args, NumArgs, + RParenLoc)) + return ExprError(); + + DiagnoseSentinelCalls(Method, LParenLoc, Args, NumArgs); + + if (CheckFunctionCall(Method, TheCall)) + return ExprError(); + + if ((isa(CurContext) || + isa(CurContext)) && + TheCall->getMethodDecl()->isPure()) { + const CXXMethodDecl *MD = TheCall->getMethodDecl(); + + if (isa(MemExpr->getBase()->IgnoreParenCasts())) { + Diag(MemExpr->getLocStart(), + diag::warn_call_to_pure_virtual_member_function_from_ctor_dtor) + << MD->getDeclName() << isa(CurContext) + << MD->getParent()->getDeclName(); + + Diag(MD->getLocStart(), diag::note_previous_decl) << MD->getDeclName(); + } + } + 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. +ExprResult +Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, + SourceLocation LParenLoc, + Expr **Args, unsigned NumArgs, + SourceLocation RParenLoc) { + if (checkPlaceholderForOverload(*this, Obj)) + return ExprError(); + ExprResult Object = Owned(Obj); + + UnbridgedCastsSet UnbridgedCasts; + if (checkArgPlaceholdersForOverload(*this, Args, NumArgs, UnbridgedCasts)) + return ExprError(); + + assert(Object.get()->getType()->isRecordType() && "Requires object type argument"); + const RecordType *Record = Object.get()->getType()->getAs(); + + // C++ [over.call.object]p1: + // If the primary-expression E in the function call syntax + // evaluates to a class object of type "cv T", then the set of + // candidate functions includes at least the function call + // operators of T. The function call operators of T are obtained by + // ordinary lookup of the name operator() in the context of + // (E).operator(). + OverloadCandidateSet CandidateSet(LParenLoc); + DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Call); + + if (RequireCompleteType(LParenLoc, Object.get()->getType(), + PDiag(diag::err_incomplete_object_call) + << Object.get()->getSourceRange())) + return true; + + LookupResult R(*this, OpName, LParenLoc, LookupOrdinaryName); + LookupQualifiedName(R, Record->getDecl()); + R.suppressDiagnostics(); + + for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end(); + Oper != OperEnd; ++Oper) { + AddMethodCandidate(Oper.getPair(), Object.get()->getType(), + Object.get()->Classify(Context), Args, NumArgs, CandidateSet, + /*SuppressUserConversions=*/ false); + } + + // C++ [over.call.object]p2: + // In addition, for each (non-explicit in C++0x) conversion function + // declared in T of the form + // + // operator conversion-type-id () cv-qualifier; + // + // where cv-qualifier is the same cv-qualification as, or a + // greater cv-qualification than, cv, and where conversion-type-id + // denotes the type "pointer to function of (P1,...,Pn) returning + // R", or the type "reference to pointer to function of + // (P1,...,Pn) returning R", or the type "reference to function + // of (P1,...,Pn) returning R", a surrogate call function [...] + // is also considered as a candidate function. Similarly, + // surrogate call functions are added to the set of candidate + // functions for each conversion function declared in an + // accessible base class provided the function is not hidden + // within T by another intervening declaration. + const UnresolvedSetImpl *Conversions + = cast(Record->getDecl())->getVisibleConversionFunctions(); + for (UnresolvedSetImpl::iterator I = Conversions->begin(), + E = Conversions->end(); I != E; ++I) { + NamedDecl *D = *I; + CXXRecordDecl *ActingContext = cast(D->getDeclContext()); + if (isa(D)) + D = cast(D)->getTargetDecl(); + + // Skip over templated conversion functions; they aren't + // surrogates. + if (isa(D)) + continue; + + CXXConversionDecl *Conv = cast(D); + if (!Conv->isExplicit()) { + // Strip the reference type (if any) and then the pointer type (if + // any) to get down to what might be a function type. + QualType ConvType = Conv->getConversionType().getNonReferenceType(); + if (const PointerType *ConvPtrType = ConvType->getAs()) + ConvType = ConvPtrType->getPointeeType(); + + if (const FunctionProtoType *Proto = ConvType->getAs()) + { + AddSurrogateCandidate(Conv, I.getPair(), ActingContext, Proto, + Object.get(), llvm::makeArrayRef(Args, NumArgs), + CandidateSet); + } + } + } + + bool HadMultipleCandidates = (CandidateSet.size() > 1); + + // Perform overload resolution. + OverloadCandidateSet::iterator Best; + switch (CandidateSet.BestViableFunction(*this, Object.get()->getLocStart(), + Best)) { + case OR_Success: + // Overload resolution succeeded; we'll build the appropriate call + // below. + break; + + case OR_No_Viable_Function: + if (CandidateSet.empty()) + Diag(Object.get()->getLocStart(), diag::err_ovl_no_oper) + << Object.get()->getType() << /*call*/ 1 + << Object.get()->getSourceRange(); + else + Diag(Object.get()->getLocStart(), + diag::err_ovl_no_viable_object_call) + << Object.get()->getType() << Object.get()->getSourceRange(); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, + llvm::makeArrayRef(Args, NumArgs)); + break; + + case OR_Ambiguous: + Diag(Object.get()->getLocStart(), + diag::err_ovl_ambiguous_object_call) + << Object.get()->getType() << Object.get()->getSourceRange(); + CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, + llvm::makeArrayRef(Args, NumArgs)); + break; + + case OR_Deleted: + Diag(Object.get()->getLocStart(), + diag::err_ovl_deleted_object_call) + << Best->Function->isDeleted() + << Object.get()->getType() + << getDeletedOrUnavailableSuffix(Best->Function) + << Object.get()->getSourceRange(); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, + llvm::makeArrayRef(Args, NumArgs)); + break; + } + + if (Best == CandidateSet.end()) + return true; + + UnbridgedCasts.restore(); + + if (Best->Function == 0) { + // Since there is no function declaration, this is one of the + // surrogate candidates. Dig out the conversion function. + CXXConversionDecl *Conv + = cast( + Best->Conversions[0].UserDefined.ConversionFunction); + + CheckMemberOperatorAccess(LParenLoc, Object.get(), 0, Best->FoundDecl); + DiagnoseUseOfDecl(Best->FoundDecl, LParenLoc); + + // We selected one of the surrogate functions that converts the + // object parameter to a function pointer. Perform the conversion + // on the object argument, then let ActOnCallExpr finish the job. + + // Create an implicit member expr to refer to the conversion operator. + // and then call it. + ExprResult Call = BuildCXXMemberCallExpr(Object.get(), Best->FoundDecl, + Conv, HadMultipleCandidates); + if (Call.isInvalid()) + return ExprError(); + // Record usage of conversion in an implicit cast. + Call = Owned(ImplicitCastExpr::Create(Context, Call.get()->getType(), + CK_UserDefinedConversion, + Call.get(), 0, VK_RValue)); + + return ActOnCallExpr(S, Call.get(), LParenLoc, MultiExprArg(Args, NumArgs), + RParenLoc); + } + + MarkFunctionReferenced(LParenLoc, Best->Function); + CheckMemberOperatorAccess(LParenLoc, Object.get(), 0, Best->FoundDecl); + DiagnoseUseOfDecl(Best->FoundDecl, LParenLoc); + + // We found an overloaded operator(). Build a CXXOperatorCallExpr + // that calls this method, using Object for the implicit object + // parameter and passing along the remaining arguments. + CXXMethodDecl *Method = cast(Best->Function); + const FunctionProtoType *Proto = + Method->getType()->getAs(); + + unsigned NumArgsInProto = Proto->getNumArgs(); + unsigned NumArgsToCheck = NumArgs; + + // Build the full argument list for the method call (the + // implicit object parameter is placed at the beginning of the + // list). + Expr **MethodArgs; + if (NumArgs < NumArgsInProto) { + NumArgsToCheck = NumArgsInProto; + MethodArgs = new Expr*[NumArgsInProto + 1]; + } else { + MethodArgs = new Expr*[NumArgs + 1]; + } + MethodArgs[0] = Object.get(); + for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) + MethodArgs[ArgIdx + 1] = Args[ArgIdx]; + + DeclarationNameInfo OpLocInfo( + Context.DeclarationNames.getCXXOperatorName(OO_Call), LParenLoc); + OpLocInfo.setCXXOperatorNameRange(SourceRange(LParenLoc, RParenLoc)); + ExprResult NewFn = CreateFunctionRefExpr(*this, Method, + HadMultipleCandidates, + OpLocInfo.getLoc(), + OpLocInfo.getInfo()); + if (NewFn.isInvalid()) + return true; + + // Once we've built TheCall, all of the expressions are properly + // owned. + QualType ResultTy = Method->getResultType(); + ExprValueKind VK = Expr::getValueKindForType(ResultTy); + ResultTy = ResultTy.getNonLValueExprType(Context); + + CXXOperatorCallExpr *TheCall = + new (Context) CXXOperatorCallExpr(Context, OO_Call, NewFn.take(), + MethodArgs, NumArgs + 1, + ResultTy, VK, RParenLoc); + delete [] MethodArgs; + + if (CheckCallReturnType(Method->getResultType(), LParenLoc, TheCall, + Method)) + return true; + + // We may have default arguments. If so, we need to allocate more + // slots in the call for them. + if (NumArgs < NumArgsInProto) + TheCall->setNumArgs(Context, NumArgsInProto + 1); + else if (NumArgs > NumArgsInProto) + NumArgsToCheck = NumArgsInProto; + + bool IsError = false; + + // Initialize the implicit object parameter. + ExprResult ObjRes = + PerformObjectArgumentInitialization(Object.get(), /*Qualifier=*/0, + Best->FoundDecl, Method); + if (ObjRes.isInvalid()) + IsError = true; + else + Object = move(ObjRes); + TheCall->setArg(0, Object.take()); + + // Check the argument types. + for (unsigned i = 0; i != NumArgsToCheck; i++) { + Expr *Arg; + if (i < NumArgs) { + Arg = Args[i]; + + // Pass the argument. + + ExprResult InputInit + = PerformCopyInitialization(InitializedEntity::InitializeParameter( + Context, + Method->getParamDecl(i)), + SourceLocation(), Arg); + + IsError |= InputInit.isInvalid(); + Arg = InputInit.takeAs(); + } else { + ExprResult DefArg + = BuildCXXDefaultArgExpr(LParenLoc, Method, Method->getParamDecl(i)); + if (DefArg.isInvalid()) { + IsError = true; + break; + } + + Arg = DefArg.takeAs(); + } + + TheCall->setArg(i + 1, Arg); + } + + // If this is a variadic call, handle args passed through "...". + if (Proto->isVariadic()) { + // Promote the arguments (C99 6.5.2.2p7). + for (unsigned i = NumArgsInProto; i != NumArgs; i++) { + ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], VariadicMethod, 0); + IsError |= Arg.isInvalid(); + TheCall->setArg(i + 1, Arg.take()); + } + } + + if (IsError) return true; + + DiagnoseSentinelCalls(Method, LParenLoc, Args, NumArgs); + + if (CheckFunctionCall(Method, TheCall)) + return true; + + 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. +ExprResult +Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) { + assert(Base->getType()->isRecordType() && + "left-hand side must have class type"); + + if (checkPlaceholderForOverload(*this, Base)) + return ExprError(); + + SourceLocation Loc = Base->getExprLoc(); + + // C++ [over.ref]p1: + // + // [...] An expression x->m is interpreted as (x.operator->())->m + // for a class object x of type T if T::operator->() exists and if + // the operator is selected as the best match function by the + // overload resolution mechanism (13.3). + DeclarationName OpName = + Context.DeclarationNames.getCXXOperatorName(OO_Arrow); + OverloadCandidateSet CandidateSet(Loc); + const RecordType *BaseRecord = Base->getType()->getAs(); + + if (RequireCompleteType(Loc, Base->getType(), + PDiag(diag::err_typecheck_incomplete_tag) + << Base->getSourceRange())) + return ExprError(); + + LookupResult R(*this, OpName, OpLoc, LookupOrdinaryName); + LookupQualifiedName(R, BaseRecord->getDecl()); + R.suppressDiagnostics(); + + for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end(); + Oper != OperEnd; ++Oper) { + AddMethodCandidate(Oper.getPair(), Base->getType(), Base->Classify(Context), + 0, 0, CandidateSet, /*SuppressUserConversions=*/false); + } + + bool HadMultipleCandidates = (CandidateSet.size() > 1); + + // Perform overload resolution. + OverloadCandidateSet::iterator Best; + switch (CandidateSet.BestViableFunction(*this, OpLoc, Best)) { + case OR_Success: + // Overload resolution succeeded; we'll build the call below. + break; + + case OR_No_Viable_Function: + if (CandidateSet.empty()) + Diag(OpLoc, diag::err_typecheck_member_reference_arrow) + << Base->getType() << Base->getSourceRange(); + else + Diag(OpLoc, diag::err_ovl_no_viable_oper) + << "operator->" << Base->getSourceRange(); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Base); + return ExprError(); + + case OR_Ambiguous: + Diag(OpLoc, diag::err_ovl_ambiguous_oper_unary) + << "->" << Base->getType() << Base->getSourceRange(); + CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Base); + return ExprError(); + + case OR_Deleted: + Diag(OpLoc, diag::err_ovl_deleted_oper) + << Best->Function->isDeleted() + << "->" + << getDeletedOrUnavailableSuffix(Best->Function) + << Base->getSourceRange(); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Base); + return ExprError(); + } + + MarkFunctionReferenced(OpLoc, Best->Function); + CheckMemberOperatorAccess(OpLoc, Base, 0, Best->FoundDecl); + DiagnoseUseOfDecl(Best->FoundDecl, OpLoc); + + // Convert the object parameter. + CXXMethodDecl *Method = cast(Best->Function); + ExprResult BaseResult = + PerformObjectArgumentInitialization(Base, /*Qualifier=*/0, + Best->FoundDecl, Method); + if (BaseResult.isInvalid()) + return ExprError(); + Base = BaseResult.take(); + + // Build the operator call. + ExprResult FnExpr = CreateFunctionRefExpr(*this, Method, + HadMultipleCandidates, OpLoc); + if (FnExpr.isInvalid()) + return ExprError(); + + QualType ResultTy = Method->getResultType(); + ExprValueKind VK = Expr::getValueKindForType(ResultTy); + ResultTy = ResultTy.getNonLValueExprType(Context); + CXXOperatorCallExpr *TheCall = + new (Context) CXXOperatorCallExpr(Context, OO_Arrow, FnExpr.take(), + &Base, 1, ResultTy, VK, OpLoc); + + if (CheckCallReturnType(Method->getResultType(), OpLoc, TheCall, + Method)) + return ExprError(); + + return MaybeBindToTemporary(TheCall); +} + +/// BuildLiteralOperatorCall - Build a UserDefinedLiteral by creating a call to +/// a literal operator described by the provided lookup results. +ExprResult Sema::BuildLiteralOperatorCall(LookupResult &R, + DeclarationNameInfo &SuffixInfo, + ArrayRef Args, + SourceLocation LitEndLoc, + TemplateArgumentListInfo *TemplateArgs) { + SourceLocation UDSuffixLoc = SuffixInfo.getCXXLiteralOperatorNameLoc(); + + OverloadCandidateSet CandidateSet(UDSuffixLoc); + AddFunctionCandidates(R.asUnresolvedSet(), Args, CandidateSet, true, + TemplateArgs); + + bool HadMultipleCandidates = (CandidateSet.size() > 1); + + // Perform overload resolution. This will usually be trivial, but might need + // to perform substitutions for a literal operator template. + OverloadCandidateSet::iterator Best; + switch (CandidateSet.BestViableFunction(*this, UDSuffixLoc, Best)) { + case OR_Success: + case OR_Deleted: + break; + + case OR_No_Viable_Function: + Diag(UDSuffixLoc, diag::err_ovl_no_viable_function_in_call) + << R.getLookupName(); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args); + return ExprError(); + + case OR_Ambiguous: + Diag(R.getNameLoc(), diag::err_ovl_ambiguous_call) << R.getLookupName(); + CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args); + return ExprError(); + } + + FunctionDecl *FD = Best->Function; + MarkFunctionReferenced(UDSuffixLoc, FD); + DiagnoseUseOfDecl(Best->FoundDecl, UDSuffixLoc); + + ExprResult Fn = CreateFunctionRefExpr(*this, FD, HadMultipleCandidates, + SuffixInfo.getLoc(), + SuffixInfo.getInfo()); + if (Fn.isInvalid()) + return true; + + // Check the argument types. This should almost always be a no-op, except + // that array-to-pointer decay is applied to string literals. + Expr *ConvArgs[2]; + for (unsigned ArgIdx = 0; ArgIdx != Args.size(); ++ArgIdx) { + ExprResult InputInit = PerformCopyInitialization( + InitializedEntity::InitializeParameter(Context, FD->getParamDecl(ArgIdx)), + SourceLocation(), Args[ArgIdx]); + if (InputInit.isInvalid()) + return true; + ConvArgs[ArgIdx] = InputInit.take(); + } + + QualType ResultTy = FD->getResultType(); + ExprValueKind VK = Expr::getValueKindForType(ResultTy); + ResultTy = ResultTy.getNonLValueExprType(Context); + + UserDefinedLiteral *UDL = + new (Context) UserDefinedLiteral(Context, Fn.take(), ConvArgs, Args.size(), + ResultTy, VK, LitEndLoc, UDSuffixLoc); + + if (CheckCallReturnType(FD->getResultType(), UDSuffixLoc, UDL, FD)) + return ExprError(); + + if (CheckFunctionCall(FD, UDL)) + return ExprError(); + + return MaybeBindToTemporary(UDL); +} + +/// FixOverloadedFunctionReference - E is an expression that refers to +/// a C++ overloaded function (possibly with some parentheses and +/// perhaps a '&' around it). We have resolved the overloaded function +/// to the function declaration Fn, so patch up the expression E to +/// refer (possibly indirectly) to Fn. Returns the new expr. +Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, + FunctionDecl *Fn) { + if (ParenExpr *PE = dyn_cast(E)) { + Expr *SubExpr = FixOverloadedFunctionReference(PE->getSubExpr(), + Found, Fn); + if (SubExpr == PE->getSubExpr()) + return PE; + + return new (Context) ParenExpr(PE->getLParen(), PE->getRParen(), SubExpr); + } + + if (ImplicitCastExpr *ICE = dyn_cast(E)) { + Expr *SubExpr = FixOverloadedFunctionReference(ICE->getSubExpr(), + Found, Fn); + 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; + + return ImplicitCastExpr::Create(Context, ICE->getType(), + ICE->getCastKind(), + SubExpr, 0, + ICE->getValueKind()); + } + + if (UnaryOperator *UnOp = dyn_cast(E)) { + assert(UnOp->getOpcode() == UO_AddrOf && + "Can only take the address of an overloaded function"); + if (CXXMethodDecl *Method = dyn_cast(Fn)) { + if (Method->isStatic()) { + // Do nothing: static member functions aren't any different + // from non-member functions. + } else { + // Fix the sub expression, which really has to be an + // UnresolvedLookupExpr holding an overloaded member function + // or template. + Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(), + Found, Fn); + if (SubExpr == UnOp->getSubExpr()) + return UnOp; + + assert(isa(SubExpr) + && "fixed to something other than a decl ref"); + assert(cast(SubExpr)->getQualifier() + && "fixed to a member ref with no nested name qualifier"); + + // We have taken the address of a pointer to member + // function. Perform the computation here so that we get the + // appropriate pointer to member type. + QualType ClassType + = Context.getTypeDeclType(cast(Method->getDeclContext())); + QualType MemPtrType + = Context.getMemberPointerType(Fn->getType(), ClassType.getTypePtr()); + + return new (Context) UnaryOperator(SubExpr, UO_AddrOf, MemPtrType, + VK_RValue, OK_Ordinary, + UnOp->getOperatorLoc()); + } + } + Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(), + Found, Fn); + if (SubExpr == UnOp->getSubExpr()) + return UnOp; + + return new (Context) UnaryOperator(SubExpr, UO_AddrOf, + Context.getPointerType(SubExpr->getType()), + VK_RValue, OK_Ordinary, + UnOp->getOperatorLoc()); + } + + if (UnresolvedLookupExpr *ULE = dyn_cast(E)) { + // FIXME: avoid copy. + TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = 0; + if (ULE->hasExplicitTemplateArgs()) { + ULE->copyTemplateArgumentsInto(TemplateArgsBuffer); + TemplateArgs = &TemplateArgsBuffer; + } + + DeclRefExpr *DRE = DeclRefExpr::Create(Context, + ULE->getQualifierLoc(), + ULE->getTemplateKeywordLoc(), + Fn, + /*enclosing*/ false, // FIXME? + ULE->getNameLoc(), + Fn->getType(), + VK_LValue, + Found.getDecl(), + TemplateArgs); + MarkDeclRefReferenced(DRE); + DRE->setHadMultipleCandidates(ULE->getNumDecls() > 1); + return DRE; + } + + if (UnresolvedMemberExpr *MemExpr = dyn_cast(E)) { + // FIXME: avoid copy. + TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = 0; + if (MemExpr->hasExplicitTemplateArgs()) { + MemExpr->copyTemplateArgumentsInto(TemplateArgsBuffer); + TemplateArgs = &TemplateArgsBuffer; + } + + Expr *Base; + + // If we're filling in a static method where we used to have an + // implicit member access, rewrite to a simple decl ref. + if (MemExpr->isImplicitAccess()) { + if (cast(Fn)->isStatic()) { + DeclRefExpr *DRE = DeclRefExpr::Create(Context, + MemExpr->getQualifierLoc(), + MemExpr->getTemplateKeywordLoc(), + Fn, + /*enclosing*/ false, + MemExpr->getMemberLoc(), + Fn->getType(), + VK_LValue, + Found.getDecl(), + TemplateArgs); + MarkDeclRefReferenced(DRE); + DRE->setHadMultipleCandidates(MemExpr->getNumDecls() > 1); + return DRE; + } else { + SourceLocation Loc = MemExpr->getMemberLoc(); + if (MemExpr->getQualifier()) + Loc = MemExpr->getQualifierLoc().getBeginLoc(); + CheckCXXThisCapture(Loc); + Base = new (Context) CXXThisExpr(Loc, + MemExpr->getBaseType(), + /*isImplicit=*/true); + } + } else + Base = MemExpr->getBase(); + + ExprValueKind valueKind; + QualType type; + if (cast(Fn)->isStatic()) { + valueKind = VK_LValue; + type = Fn->getType(); + } else { + valueKind = VK_RValue; + type = Context.BoundMemberTy; + } + + MemberExpr *ME = MemberExpr::Create(Context, Base, + MemExpr->isArrow(), + MemExpr->getQualifierLoc(), + MemExpr->getTemplateKeywordLoc(), + Fn, + Found, + MemExpr->getMemberNameInfo(), + TemplateArgs, + type, valueKind, OK_Ordinary); + ME->setHadMultipleCandidates(true); + return ME; + } + + llvm_unreachable("Invalid reference to overloaded function"); +} + +ExprResult Sema::FixOverloadedFunctionReference(ExprResult E, + DeclAccessPair Found, + FunctionDecl *Fn) { + return Owned(FixOverloadedFunctionReference((Expr *)E.get(), Found, Fn)); +} + +} // end namespace clang diff --git a/clang/lib/Sema/SemaPseudoObject.cpp b/clang/lib/Sema/SemaPseudoObject.cpp new file mode 100644 index 0000000..0e66329 --- /dev/null +++ b/clang/lib/Sema/SemaPseudoObject.cpp @@ -0,0 +1,1373 @@ +//===--- SemaPseudoObject.cpp - Semantic Analysis for Pseudo-Objects ------===// +// +// 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 expressions involving +// pseudo-object references. Pseudo-objects are conceptual objects +// whose storage is entirely abstract and all accesses to which are +// translated through some sort of abstraction barrier. +// +// For example, Objective-C objects can have "properties", either +// declared or undeclared. A property may be accessed by writing +// expr.prop +// where 'expr' is an r-value of Objective-C pointer type and 'prop' +// is the name of the property. If this expression is used in a context +// needing an r-value, it is treated as if it were a message-send +// of the associated 'getter' selector, typically: +// [expr prop] +// If it is used as the LHS of a simple assignment, it is treated +// as a message-send of the associated 'setter' selector, typically: +// [expr setProp: RHS] +// If it is used as the LHS of a compound assignment, or the operand +// of a unary increment or decrement, both are required; for example, +// 'expr.prop *= 100' would be translated to: +// [expr setProp: [expr prop] * 100] +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/Initialization.h" +#include "clang/AST/ExprObjC.h" +#include "clang/Lex/Preprocessor.h" + +using namespace clang; +using namespace sema; + +namespace { + // Basically just a very focused copy of TreeTransform. + template struct Rebuilder { + Sema &S; + Rebuilder(Sema &S) : S(S) {} + + T &getDerived() { return static_cast(*this); } + + Expr *rebuild(Expr *e) { + // Fast path: nothing to look through. + if (typename T::specific_type *specific + = dyn_cast(e)) + return getDerived().rebuildSpecific(specific); + + // Otherwise, we should look through and rebuild anything that + // IgnoreParens would. + + if (ParenExpr *parens = dyn_cast(e)) { + e = rebuild(parens->getSubExpr()); + return new (S.Context) ParenExpr(parens->getLParen(), + parens->getRParen(), + e); + } + + if (UnaryOperator *uop = dyn_cast(e)) { + assert(uop->getOpcode() == UO_Extension); + e = rebuild(uop->getSubExpr()); + return new (S.Context) UnaryOperator(e, uop->getOpcode(), + uop->getType(), + uop->getValueKind(), + uop->getObjectKind(), + uop->getOperatorLoc()); + } + + if (GenericSelectionExpr *gse = dyn_cast(e)) { + assert(!gse->isResultDependent()); + unsigned resultIndex = gse->getResultIndex(); + unsigned numAssocs = gse->getNumAssocs(); + + SmallVector assocs(numAssocs); + SmallVector assocTypes(numAssocs); + + for (unsigned i = 0; i != numAssocs; ++i) { + Expr *assoc = gse->getAssocExpr(i); + if (i == resultIndex) assoc = rebuild(assoc); + assocs[i] = assoc; + assocTypes[i] = gse->getAssocTypeSourceInfo(i); + } + + return new (S.Context) GenericSelectionExpr(S.Context, + gse->getGenericLoc(), + gse->getControllingExpr(), + assocTypes.data(), + assocs.data(), + numAssocs, + gse->getDefaultLoc(), + gse->getRParenLoc(), + gse->containsUnexpandedParameterPack(), + resultIndex); + } + + llvm_unreachable("bad expression to rebuild!"); + } + }; + + struct ObjCPropertyRefRebuilder : Rebuilder { + Expr *NewBase; + ObjCPropertyRefRebuilder(Sema &S, Expr *newBase) + : Rebuilder(S), NewBase(newBase) {} + + typedef ObjCPropertyRefExpr specific_type; + Expr *rebuildSpecific(ObjCPropertyRefExpr *refExpr) { + // Fortunately, the constraint that we're rebuilding something + // with a base limits the number of cases here. + assert(refExpr->getBase()); + + if (refExpr->isExplicitProperty()) { + return new (S.Context) + ObjCPropertyRefExpr(refExpr->getExplicitProperty(), + refExpr->getType(), refExpr->getValueKind(), + refExpr->getObjectKind(), refExpr->getLocation(), + NewBase); + } + return new (S.Context) + ObjCPropertyRefExpr(refExpr->getImplicitPropertyGetter(), + refExpr->getImplicitPropertySetter(), + refExpr->getType(), refExpr->getValueKind(), + refExpr->getObjectKind(),refExpr->getLocation(), + NewBase); + } + }; + + struct ObjCSubscriptRefRebuilder : Rebuilder { + Expr *NewBase; + Expr *NewKeyExpr; + ObjCSubscriptRefRebuilder(Sema &S, Expr *newBase, Expr *newKeyExpr) + : Rebuilder(S), + NewBase(newBase), NewKeyExpr(newKeyExpr) {} + + typedef ObjCSubscriptRefExpr specific_type; + Expr *rebuildSpecific(ObjCSubscriptRefExpr *refExpr) { + assert(refExpr->getBaseExpr()); + assert(refExpr->getKeyExpr()); + + return new (S.Context) + ObjCSubscriptRefExpr(NewBase, + NewKeyExpr, + refExpr->getType(), refExpr->getValueKind(), + refExpr->getObjectKind(),refExpr->getAtIndexMethodDecl(), + refExpr->setAtIndexMethodDecl(), + refExpr->getRBracket()); + } + }; + + class PseudoOpBuilder { + public: + Sema &S; + unsigned ResultIndex; + SourceLocation GenericLoc; + SmallVector Semantics; + + PseudoOpBuilder(Sema &S, SourceLocation genericLoc) + : S(S), ResultIndex(PseudoObjectExpr::NoResult), + GenericLoc(genericLoc) {} + + virtual ~PseudoOpBuilder() {} + + /// Add a normal semantic expression. + void addSemanticExpr(Expr *semantic) { + Semantics.push_back(semantic); + } + + /// Add the 'result' semantic expression. + void addResultSemanticExpr(Expr *resultExpr) { + assert(ResultIndex == PseudoObjectExpr::NoResult); + ResultIndex = Semantics.size(); + Semantics.push_back(resultExpr); + } + + ExprResult buildRValueOperation(Expr *op); + ExprResult buildAssignmentOperation(Scope *Sc, + SourceLocation opLoc, + BinaryOperatorKind opcode, + Expr *LHS, Expr *RHS); + ExprResult buildIncDecOperation(Scope *Sc, SourceLocation opLoc, + UnaryOperatorKind opcode, + Expr *op); + + ExprResult complete(Expr *syntacticForm); + + OpaqueValueExpr *capture(Expr *op); + OpaqueValueExpr *captureValueAsResult(Expr *op); + + void setResultToLastSemantic() { + assert(ResultIndex == PseudoObjectExpr::NoResult); + ResultIndex = Semantics.size() - 1; + } + + /// Return true if assignments have a non-void result. + virtual bool assignmentsHaveResult() { return true; } + + virtual Expr *rebuildAndCaptureObject(Expr *) = 0; + virtual ExprResult buildGet() = 0; + virtual ExprResult buildSet(Expr *, SourceLocation, + bool captureSetValueAsResult) = 0; + }; + + /// A PseudoOpBuilder for Objective-C @properties. + class ObjCPropertyOpBuilder : public PseudoOpBuilder { + ObjCPropertyRefExpr *RefExpr; + ObjCPropertyRefExpr *SyntacticRefExpr; + OpaqueValueExpr *InstanceReceiver; + ObjCMethodDecl *Getter; + + ObjCMethodDecl *Setter; + Selector SetterSelector; + Selector GetterSelector; + + public: + ObjCPropertyOpBuilder(Sema &S, ObjCPropertyRefExpr *refExpr) : + PseudoOpBuilder(S, refExpr->getLocation()), RefExpr(refExpr), + SyntacticRefExpr(0), InstanceReceiver(0), Getter(0), Setter(0) { + } + + ExprResult buildRValueOperation(Expr *op); + ExprResult buildAssignmentOperation(Scope *Sc, + SourceLocation opLoc, + BinaryOperatorKind opcode, + Expr *LHS, Expr *RHS); + ExprResult buildIncDecOperation(Scope *Sc, SourceLocation opLoc, + UnaryOperatorKind opcode, + Expr *op); + + bool tryBuildGetOfReference(Expr *op, ExprResult &result); + bool findSetter(); + bool findGetter(); + + Expr *rebuildAndCaptureObject(Expr *syntacticBase); + ExprResult buildGet(); + ExprResult buildSet(Expr *op, SourceLocation, bool); + }; + + /// A PseudoOpBuilder for Objective-C array/dictionary indexing. + class ObjCSubscriptOpBuilder : public PseudoOpBuilder { + ObjCSubscriptRefExpr *RefExpr; + OpaqueValueExpr *InstanceBase; + OpaqueValueExpr *InstanceKey; + ObjCMethodDecl *AtIndexGetter; + Selector AtIndexGetterSelector; + + ObjCMethodDecl *AtIndexSetter; + Selector AtIndexSetterSelector; + + public: + ObjCSubscriptOpBuilder(Sema &S, ObjCSubscriptRefExpr *refExpr) : + PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()), + RefExpr(refExpr), + InstanceBase(0), InstanceKey(0), + AtIndexGetter(0), AtIndexSetter(0) { } + + ExprResult buildRValueOperation(Expr *op); + ExprResult buildAssignmentOperation(Scope *Sc, + SourceLocation opLoc, + BinaryOperatorKind opcode, + Expr *LHS, Expr *RHS); + Expr *rebuildAndCaptureObject(Expr *syntacticBase); + + bool findAtIndexGetter(); + bool findAtIndexSetter(); + + ExprResult buildGet(); + ExprResult buildSet(Expr *op, SourceLocation, bool); + }; + +} + +/// Capture the given expression in an OpaqueValueExpr. +OpaqueValueExpr *PseudoOpBuilder::capture(Expr *e) { + // Make a new OVE whose source is the given expression. + OpaqueValueExpr *captured = + new (S.Context) OpaqueValueExpr(GenericLoc, e->getType(), + e->getValueKind(), e->getObjectKind(), + e); + + // Make sure we bind that in the semantics. + addSemanticExpr(captured); + return captured; +} + +/// Capture the given expression as the result of this pseudo-object +/// operation. This routine is safe against expressions which may +/// already be captured. +/// +/// \param Returns the captured expression, which will be the +/// same as the input if the input was already captured +OpaqueValueExpr *PseudoOpBuilder::captureValueAsResult(Expr *e) { + assert(ResultIndex == PseudoObjectExpr::NoResult); + + // If the expression hasn't already been captured, just capture it + // and set the new semantic + if (!isa(e)) { + OpaqueValueExpr *cap = capture(e); + setResultToLastSemantic(); + return cap; + } + + // Otherwise, it must already be one of our semantic expressions; + // set ResultIndex to its index. + unsigned index = 0; + for (;; ++index) { + assert(index < Semantics.size() && + "captured expression not found in semantics!"); + if (e == Semantics[index]) break; + } + ResultIndex = index; + return cast(e); +} + +/// The routine which creates the final PseudoObjectExpr. +ExprResult PseudoOpBuilder::complete(Expr *syntactic) { + return PseudoObjectExpr::Create(S.Context, syntactic, + Semantics, ResultIndex); +} + +/// The main skeleton for building an r-value operation. +ExprResult PseudoOpBuilder::buildRValueOperation(Expr *op) { + Expr *syntacticBase = rebuildAndCaptureObject(op); + + ExprResult getExpr = buildGet(); + if (getExpr.isInvalid()) return ExprError(); + addResultSemanticExpr(getExpr.take()); + + return complete(syntacticBase); +} + +/// The basic skeleton for building a simple or compound +/// assignment operation. +ExprResult +PseudoOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation opcLoc, + BinaryOperatorKind opcode, + Expr *LHS, Expr *RHS) { + assert(BinaryOperator::isAssignmentOp(opcode)); + + Expr *syntacticLHS = rebuildAndCaptureObject(LHS); + OpaqueValueExpr *capturedRHS = capture(RHS); + + Expr *syntactic; + + ExprResult result; + if (opcode == BO_Assign) { + result = capturedRHS; + syntactic = new (S.Context) BinaryOperator(syntacticLHS, capturedRHS, + opcode, capturedRHS->getType(), + capturedRHS->getValueKind(), + OK_Ordinary, opcLoc); + } else { + ExprResult opLHS = buildGet(); + if (opLHS.isInvalid()) return ExprError(); + + // Build an ordinary, non-compound operation. + BinaryOperatorKind nonCompound = + BinaryOperator::getOpForCompoundAssignment(opcode); + result = S.BuildBinOp(Sc, opcLoc, nonCompound, + opLHS.take(), capturedRHS); + if (result.isInvalid()) return ExprError(); + + syntactic = + new (S.Context) CompoundAssignOperator(syntacticLHS, capturedRHS, opcode, + result.get()->getType(), + result.get()->getValueKind(), + OK_Ordinary, + opLHS.get()->getType(), + result.get()->getType(), + opcLoc); + } + + // The result of the assignment, if not void, is the value set into + // the l-value. + result = buildSet(result.take(), opcLoc, assignmentsHaveResult()); + if (result.isInvalid()) return ExprError(); + addSemanticExpr(result.take()); + + return complete(syntactic); +} + +/// The basic skeleton for building an increment or decrement +/// operation. +ExprResult +PseudoOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc, + UnaryOperatorKind opcode, + Expr *op) { + assert(UnaryOperator::isIncrementDecrementOp(opcode)); + + Expr *syntacticOp = rebuildAndCaptureObject(op); + + // Load the value. + ExprResult result = buildGet(); + if (result.isInvalid()) return ExprError(); + + QualType resultType = result.get()->getType(); + + // That's the postfix result. + if (UnaryOperator::isPostfix(opcode) && assignmentsHaveResult()) { + result = capture(result.take()); + setResultToLastSemantic(); + } + + // Add or subtract a literal 1. + llvm::APInt oneV(S.Context.getTypeSize(S.Context.IntTy), 1); + Expr *one = IntegerLiteral::Create(S.Context, oneV, S.Context.IntTy, + GenericLoc); + + if (UnaryOperator::isIncrementOp(opcode)) { + result = S.BuildBinOp(Sc, opcLoc, BO_Add, result.take(), one); + } else { + result = S.BuildBinOp(Sc, opcLoc, BO_Sub, result.take(), one); + } + if (result.isInvalid()) return ExprError(); + + // Store that back into the result. The value stored is the result + // of a prefix operation. + result = buildSet(result.take(), opcLoc, + UnaryOperator::isPrefix(opcode) && assignmentsHaveResult()); + if (result.isInvalid()) return ExprError(); + addSemanticExpr(result.take()); + + UnaryOperator *syntactic = + new (S.Context) UnaryOperator(syntacticOp, opcode, resultType, + VK_LValue, OK_Ordinary, opcLoc); + return complete(syntactic); +} + + +//===----------------------------------------------------------------------===// +// Objective-C @property and implicit property references +//===----------------------------------------------------------------------===// + +/// Look up a method in the receiver type of an Objective-C property +/// reference. +static ObjCMethodDecl *LookupMethodInReceiverType(Sema &S, Selector sel, + const ObjCPropertyRefExpr *PRE) { + if (PRE->isObjectReceiver()) { + const ObjCObjectPointerType *PT = + PRE->getBase()->getType()->castAs(); + + // Special case for 'self' in class method implementations. + if (PT->isObjCClassType() && + S.isSelfExpr(const_cast(PRE->getBase()))) { + // This cast is safe because isSelfExpr is only true within + // methods. + ObjCMethodDecl *method = + cast(S.CurContext->getNonClosureAncestor()); + return S.LookupMethodInObjectType(sel, + S.Context.getObjCInterfaceType(method->getClassInterface()), + /*instance*/ false); + } + + return S.LookupMethodInObjectType(sel, PT->getPointeeType(), true); + } + + if (PRE->isSuperReceiver()) { + if (const ObjCObjectPointerType *PT = + PRE->getSuperReceiverType()->getAs()) + return S.LookupMethodInObjectType(sel, PT->getPointeeType(), true); + + return S.LookupMethodInObjectType(sel, PRE->getSuperReceiverType(), false); + } + + assert(PRE->isClassReceiver() && "Invalid expression"); + QualType IT = S.Context.getObjCInterfaceType(PRE->getClassReceiver()); + return S.LookupMethodInObjectType(sel, IT, false); +} + +bool ObjCPropertyOpBuilder::findGetter() { + if (Getter) return true; + + // For implicit properties, just trust the lookup we already did. + if (RefExpr->isImplicitProperty()) { + if ((Getter = RefExpr->getImplicitPropertyGetter())) { + GetterSelector = Getter->getSelector(); + return true; + } + else { + // Must build the getter selector the hard way. + ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter(); + assert(setter && "both setter and getter are null - cannot happen"); + IdentifierInfo *setterName = + setter->getSelector().getIdentifierInfoForSlot(0); + const char *compStr = setterName->getNameStart(); + compStr += 3; + IdentifierInfo *getterName = &S.Context.Idents.get(compStr); + GetterSelector = + S.PP.getSelectorTable().getNullarySelector(getterName); + return false; + + } + } + + ObjCPropertyDecl *prop = RefExpr->getExplicitProperty(); + Getter = LookupMethodInReceiverType(S, prop->getGetterName(), RefExpr); + return (Getter != 0); +} + +/// Try to find the most accurate setter declaration for the property +/// reference. +/// +/// \return true if a setter was found, in which case Setter +bool ObjCPropertyOpBuilder::findSetter() { + // For implicit properties, just trust the lookup we already did. + if (RefExpr->isImplicitProperty()) { + if (ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter()) { + Setter = setter; + SetterSelector = setter->getSelector(); + return true; + } else { + IdentifierInfo *getterName = + RefExpr->getImplicitPropertyGetter()->getSelector() + .getIdentifierInfoForSlot(0); + SetterSelector = + SelectorTable::constructSetterName(S.PP.getIdentifierTable(), + S.PP.getSelectorTable(), + getterName); + return false; + } + } + + // For explicit properties, this is more involved. + ObjCPropertyDecl *prop = RefExpr->getExplicitProperty(); + SetterSelector = prop->getSetterName(); + + // Do a normal method lookup first. + if (ObjCMethodDecl *setter = + LookupMethodInReceiverType(S, SetterSelector, RefExpr)) { + Setter = setter; + return true; + } + + // That can fail in the somewhat crazy situation that we're + // type-checking a message send within the @interface declaration + // that declared the @property. But it's not clear that that's + // valuable to support. + + return false; +} + +/// Capture the base object of an Objective-C property expression. +Expr *ObjCPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) { + assert(InstanceReceiver == 0); + + // If we have a base, capture it in an OVE and rebuild the syntactic + // form to use the OVE as its base. + if (RefExpr->isObjectReceiver()) { + InstanceReceiver = capture(RefExpr->getBase()); + + syntacticBase = + ObjCPropertyRefRebuilder(S, InstanceReceiver).rebuild(syntacticBase); + } + + if (ObjCPropertyRefExpr * + refE = dyn_cast(syntacticBase->IgnoreParens())) + SyntacticRefExpr = refE; + + return syntacticBase; +} + +/// Load from an Objective-C property reference. +ExprResult ObjCPropertyOpBuilder::buildGet() { + findGetter(); + assert(Getter); + + if (SyntacticRefExpr) + SyntacticRefExpr->setIsMessagingGetter(); + + QualType receiverType; + if (RefExpr->isClassReceiver()) { + receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver()); + } else if (RefExpr->isSuperReceiver()) { + receiverType = RefExpr->getSuperReceiverType(); + } else { + assert(InstanceReceiver); + receiverType = InstanceReceiver->getType(); + } + + // Build a message-send. + ExprResult msg; + if (Getter->isInstanceMethod() || RefExpr->isObjectReceiver()) { + assert(InstanceReceiver || RefExpr->isSuperReceiver()); + msg = S.BuildInstanceMessageImplicit(InstanceReceiver, receiverType, + GenericLoc, Getter->getSelector(), + Getter, MultiExprArg()); + } else { + msg = S.BuildClassMessageImplicit(receiverType, RefExpr->isSuperReceiver(), + GenericLoc, + Getter->getSelector(), Getter, + MultiExprArg()); + } + return msg; +} + +/// Store to an Objective-C property reference. +/// +/// \param bindSetValueAsResult - If true, capture the actual +/// value being set as the value of the property operation. +ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc, + bool captureSetValueAsResult) { + bool hasSetter = findSetter(); + assert(hasSetter); (void) hasSetter; + + if (SyntacticRefExpr) + SyntacticRefExpr->setIsMessagingSetter(); + + QualType receiverType; + if (RefExpr->isClassReceiver()) { + receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver()); + } else if (RefExpr->isSuperReceiver()) { + receiverType = RefExpr->getSuperReceiverType(); + } else { + assert(InstanceReceiver); + receiverType = InstanceReceiver->getType(); + } + + // Use assignment constraints when possible; they give us better + // diagnostics. "When possible" basically means anything except a + // C++ class type. + if (!S.getLangOpts().CPlusPlus || !op->getType()->isRecordType()) { + QualType paramType = (*Setter->param_begin())->getType(); + if (!S.getLangOpts().CPlusPlus || !paramType->isRecordType()) { + ExprResult opResult = op; + Sema::AssignConvertType assignResult + = S.CheckSingleAssignmentConstraints(paramType, opResult); + if (S.DiagnoseAssignmentResult(assignResult, opcLoc, paramType, + op->getType(), opResult.get(), + Sema::AA_Assigning)) + return ExprError(); + + op = opResult.take(); + assert(op && "successful assignment left argument invalid?"); + } + } + + // Arguments. + Expr *args[] = { op }; + + // Build a message-send. + ExprResult msg; + if (Setter->isInstanceMethod() || RefExpr->isObjectReceiver()) { + msg = S.BuildInstanceMessageImplicit(InstanceReceiver, receiverType, + GenericLoc, SetterSelector, Setter, + MultiExprArg(args, 1)); + } else { + msg = S.BuildClassMessageImplicit(receiverType, RefExpr->isSuperReceiver(), + GenericLoc, + SetterSelector, Setter, + MultiExprArg(args, 1)); + } + + if (!msg.isInvalid() && captureSetValueAsResult) { + ObjCMessageExpr *msgExpr = + cast(msg.get()->IgnoreImplicit()); + Expr *arg = msgExpr->getArg(0); + msgExpr->setArg(0, captureValueAsResult(arg)); + } + + return msg; +} + +/// @property-specific behavior for doing lvalue-to-rvalue conversion. +ExprResult ObjCPropertyOpBuilder::buildRValueOperation(Expr *op) { + // Explicit properties always have getters, but implicit ones don't. + // Check that before proceeding. + if (RefExpr->isImplicitProperty() && + !RefExpr->getImplicitPropertyGetter()) { + S.Diag(RefExpr->getLocation(), diag::err_getter_not_found) + << RefExpr->getBase()->getType(); + return ExprError(); + } + + ExprResult result = PseudoOpBuilder::buildRValueOperation(op); + if (result.isInvalid()) return ExprError(); + + if (RefExpr->isExplicitProperty() && !Getter->hasRelatedResultType()) + S.DiagnosePropertyAccessorMismatch(RefExpr->getExplicitProperty(), + Getter, RefExpr->getLocation()); + + // As a special case, if the method returns 'id', try to get + // a better type from the property. + if (RefExpr->isExplicitProperty() && result.get()->isRValue() && + result.get()->getType()->isObjCIdType()) { + QualType propType = RefExpr->getExplicitProperty()->getType(); + if (const ObjCObjectPointerType *ptr + = propType->getAs()) { + if (!ptr->isObjCIdType()) + result = S.ImpCastExprToType(result.get(), propType, CK_BitCast); + } + } + + return result; +} + +/// Try to build this as a call to a getter that returns a reference. +/// +/// \return true if it was possible, whether or not it actually +/// succeeded +bool ObjCPropertyOpBuilder::tryBuildGetOfReference(Expr *op, + ExprResult &result) { + if (!S.getLangOpts().CPlusPlus) return false; + + findGetter(); + assert(Getter && "property has no setter and no getter!"); + + // Only do this if the getter returns an l-value reference type. + QualType resultType = Getter->getResultType(); + if (!resultType->isLValueReferenceType()) return false; + + result = buildRValueOperation(op); + return true; +} + +/// @property-specific behavior for doing assignments. +ExprResult +ObjCPropertyOpBuilder::buildAssignmentOperation(Scope *Sc, + SourceLocation opcLoc, + BinaryOperatorKind opcode, + Expr *LHS, Expr *RHS) { + assert(BinaryOperator::isAssignmentOp(opcode)); + + // If there's no setter, we have no choice but to try to assign to + // the result of the getter. + if (!findSetter()) { + ExprResult result; + if (tryBuildGetOfReference(LHS, result)) { + if (result.isInvalid()) return ExprError(); + return S.BuildBinOp(Sc, opcLoc, opcode, result.take(), RHS); + } + + // Otherwise, it's an error. + S.Diag(opcLoc, diag::err_nosetter_property_assignment) + << unsigned(RefExpr->isImplicitProperty()) + << SetterSelector + << LHS->getSourceRange() << RHS->getSourceRange(); + return ExprError(); + } + + // If there is a setter, we definitely want to use it. + + // Verify that we can do a compound assignment. + if (opcode != BO_Assign && !findGetter()) { + S.Diag(opcLoc, diag::err_nogetter_property_compound_assignment) + << LHS->getSourceRange() << RHS->getSourceRange(); + return ExprError(); + } + + ExprResult result = + PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS); + if (result.isInvalid()) return ExprError(); + + // Various warnings about property assignments in ARC. + if (S.getLangOpts().ObjCAutoRefCount && InstanceReceiver) { + S.checkRetainCycles(InstanceReceiver->getSourceExpr(), RHS); + S.checkUnsafeExprAssigns(opcLoc, LHS, RHS); + } + + return result; +} + +/// @property-specific behavior for doing increments and decrements. +ExprResult +ObjCPropertyOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc, + UnaryOperatorKind opcode, + Expr *op) { + // If there's no setter, we have no choice but to try to assign to + // the result of the getter. + if (!findSetter()) { + ExprResult result; + if (tryBuildGetOfReference(op, result)) { + if (result.isInvalid()) return ExprError(); + return S.BuildUnaryOp(Sc, opcLoc, opcode, result.take()); + } + + // Otherwise, it's an error. + S.Diag(opcLoc, diag::err_nosetter_property_incdec) + << unsigned(RefExpr->isImplicitProperty()) + << unsigned(UnaryOperator::isDecrementOp(opcode)) + << SetterSelector + << op->getSourceRange(); + return ExprError(); + } + + // If there is a setter, we definitely want to use it. + + // We also need a getter. + if (!findGetter()) { + assert(RefExpr->isImplicitProperty()); + S.Diag(opcLoc, diag::err_nogetter_property_incdec) + << unsigned(UnaryOperator::isDecrementOp(opcode)) + << GetterSelector + << op->getSourceRange(); + return ExprError(); + } + + return PseudoOpBuilder::buildIncDecOperation(Sc, opcLoc, opcode, op); +} + +// ObjCSubscript build stuff. +// + +/// objective-c subscripting-specific behavior for doing lvalue-to-rvalue +/// conversion. +/// FIXME. Remove this routine if it is proven that no additional +/// specifity is needed. +ExprResult ObjCSubscriptOpBuilder::buildRValueOperation(Expr *op) { + ExprResult result = PseudoOpBuilder::buildRValueOperation(op); + if (result.isInvalid()) return ExprError(); + return result; +} + +/// objective-c subscripting-specific behavior for doing assignments. +ExprResult +ObjCSubscriptOpBuilder::buildAssignmentOperation(Scope *Sc, + SourceLocation opcLoc, + BinaryOperatorKind opcode, + Expr *LHS, Expr *RHS) { + assert(BinaryOperator::isAssignmentOp(opcode)); + // There must be a method to do the Index'ed assignment. + if (!findAtIndexSetter()) + return ExprError(); + + // Verify that we can do a compound assignment. + if (opcode != BO_Assign && !findAtIndexGetter()) + return ExprError(); + + ExprResult result = + PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS); + if (result.isInvalid()) return ExprError(); + + // Various warnings about objc Index'ed assignments in ARC. + if (S.getLangOpts().ObjCAutoRefCount && InstanceBase) { + S.checkRetainCycles(InstanceBase->getSourceExpr(), RHS); + S.checkUnsafeExprAssigns(opcLoc, LHS, RHS); + } + + return result; +} + +/// Capture the base object of an Objective-C Index'ed expression. +Expr *ObjCSubscriptOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) { + assert(InstanceBase == 0); + + // Capture base expression in an OVE and rebuild the syntactic + // form to use the OVE as its base expression. + InstanceBase = capture(RefExpr->getBaseExpr()); + InstanceKey = capture(RefExpr->getKeyExpr()); + + syntacticBase = + ObjCSubscriptRefRebuilder(S, InstanceBase, + InstanceKey).rebuild(syntacticBase); + + return syntacticBase; +} + +/// CheckSubscriptingKind - This routine decide what type +/// of indexing represented by "FromE" is being done. +Sema::ObjCSubscriptKind + Sema::CheckSubscriptingKind(Expr *FromE) { + // If the expression already has integral or enumeration type, we're golden. + QualType T = FromE->getType(); + if (T->isIntegralOrEnumerationType()) + return OS_Array; + + // If we don't have a class type in C++, there's no way we can get an + // expression of integral or enumeration type. + const RecordType *RecordTy = T->getAs(); + if (!RecordTy && T->isObjCObjectPointerType()) + // All other scalar cases are assumed to be dictionary indexing which + // caller handles, with diagnostics if needed. + return OS_Dictionary; + if (!getLangOpts().CPlusPlus || + !RecordTy || RecordTy->isIncompleteType()) { + // No indexing can be done. Issue diagnostics and quit. + const Expr *IndexExpr = FromE->IgnoreParenImpCasts(); + if (isa(IndexExpr)) + Diag(FromE->getExprLoc(), diag::err_objc_subscript_pointer) + << T << FixItHint::CreateInsertion(FromE->getExprLoc(), "@"); + else + Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion) + << T; + return OS_Error; + } + + // We must have a complete class type. + if (RequireCompleteType(FromE->getExprLoc(), T, + PDiag(diag::err_objc_index_incomplete_class_type) + << FromE->getSourceRange())) + return OS_Error; + + // Look for a conversion to an integral, enumeration type, or + // objective-C pointer type. + UnresolvedSet<4> ViableConversions; + UnresolvedSet<4> ExplicitConversions; + const UnresolvedSetImpl *Conversions + = cast(RecordTy->getDecl())->getVisibleConversionFunctions(); + + int NoIntegrals=0, NoObjCIdPointers=0; + SmallVector ConversionDecls; + + for (UnresolvedSetImpl::iterator I = Conversions->begin(), + E = Conversions->end(); + I != E; + ++I) { + if (CXXConversionDecl *Conversion + = dyn_cast((*I)->getUnderlyingDecl())) { + QualType CT = Conversion->getConversionType().getNonReferenceType(); + if (CT->isIntegralOrEnumerationType()) { + ++NoIntegrals; + ConversionDecls.push_back(Conversion); + } + else if (CT->isObjCIdType() ||CT->isBlockPointerType()) { + ++NoObjCIdPointers; + ConversionDecls.push_back(Conversion); + } + } + } + if (NoIntegrals ==1 && NoObjCIdPointers == 0) + return OS_Array; + if (NoIntegrals == 0 && NoObjCIdPointers == 1) + return OS_Dictionary; + if (NoIntegrals == 0 && NoObjCIdPointers == 0) { + // No conversion function was found. Issue diagnostic and return. + Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion) + << FromE->getType(); + return OS_Error; + } + Diag(FromE->getExprLoc(), diag::err_objc_multiple_subscript_type_conversion) + << FromE->getType(); + for (unsigned int i = 0; i < ConversionDecls.size(); i++) + Diag(ConversionDecls[i]->getLocation(), diag::not_conv_function_declared_at); + + return OS_Error; +} + +bool ObjCSubscriptOpBuilder::findAtIndexGetter() { + if (AtIndexGetter) + return true; + + Expr *BaseExpr = RefExpr->getBaseExpr(); + QualType BaseT = BaseExpr->getType(); + + QualType ResultType; + if (const ObjCObjectPointerType *PTy = + BaseT->getAs()) { + ResultType = PTy->getPointeeType(); + if (const ObjCObjectType *iQFaceTy = + ResultType->getAsObjCQualifiedInterfaceType()) + ResultType = iQFaceTy->getBaseType(); + } + Sema::ObjCSubscriptKind Res = + S.CheckSubscriptingKind(RefExpr->getKeyExpr()); + if (Res == Sema::OS_Error) + return false; + bool arrayRef = (Res == Sema::OS_Array); + + if (ResultType.isNull()) { + S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_base_type) + << BaseExpr->getType() << arrayRef; + return false; + } + if (!arrayRef) { + // dictionary subscripting. + // - (id)objectForKeyedSubscript:(id)key; + IdentifierInfo *KeyIdents[] = { + &S.Context.Idents.get("objectForKeyedSubscript") + }; + AtIndexGetterSelector = S.Context.Selectors.getSelector(1, KeyIdents); + } + else { + // - (id)objectAtIndexedSubscript:(size_t)index; + IdentifierInfo *KeyIdents[] = { + &S.Context.Idents.get("objectAtIndexedSubscript") + }; + + AtIndexGetterSelector = S.Context.Selectors.getSelector(1, KeyIdents); + } + + AtIndexGetter = S.LookupMethodInObjectType(AtIndexGetterSelector, ResultType, + true /*instance*/); + bool receiverIdType = (BaseT->isObjCIdType() || + BaseT->isObjCQualifiedIdType()); + + if (!AtIndexGetter && S.getLangOpts().DebuggerObjCLiteral) { + AtIndexGetter = ObjCMethodDecl::Create(S.Context, SourceLocation(), + SourceLocation(), AtIndexGetterSelector, + S.Context.getObjCIdType() /*ReturnType*/, + 0 /*TypeSourceInfo */, + S.Context.getTranslationUnitDecl(), + true /*Instance*/, false/*isVariadic*/, + /*isSynthesized=*/false, + /*isImplicitlyDeclared=*/true, /*isDefined=*/false, + ObjCMethodDecl::Required, + false); + ParmVarDecl *Argument = ParmVarDecl::Create(S.Context, AtIndexGetter, + SourceLocation(), SourceLocation(), + arrayRef ? &S.Context.Idents.get("index") + : &S.Context.Idents.get("key"), + arrayRef ? S.Context.UnsignedLongTy + : S.Context.getObjCIdType(), + /*TInfo=*/0, + SC_None, + SC_None, + 0); + AtIndexGetter->setMethodParams(S.Context, Argument, + ArrayRef()); + } + + if (!AtIndexGetter) { + if (!receiverIdType) { + S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_method_not_found) + << BaseExpr->getType() << 0 << arrayRef; + return false; + } + AtIndexGetter = + S.LookupInstanceMethodInGlobalPool(AtIndexGetterSelector, + RefExpr->getSourceRange(), + true, false); + } + + if (AtIndexGetter) { + QualType T = AtIndexGetter->param_begin()[0]->getType(); + if ((arrayRef && !T->isIntegralOrEnumerationType()) || + (!arrayRef && !T->isObjCObjectPointerType())) { + S.Diag(RefExpr->getKeyExpr()->getExprLoc(), + arrayRef ? diag::err_objc_subscript_index_type + : diag::err_objc_subscript_key_type) << T; + S.Diag(AtIndexGetter->param_begin()[0]->getLocation(), + diag::note_parameter_type) << T; + return false; + } + QualType R = AtIndexGetter->getResultType(); + if (!R->isObjCObjectPointerType()) { + S.Diag(RefExpr->getKeyExpr()->getExprLoc(), + diag::err_objc_indexing_method_result_type) << R << arrayRef; + S.Diag(AtIndexGetter->getLocation(), diag::note_method_declared_at) << + AtIndexGetter->getDeclName(); + } + } + return true; +} + +bool ObjCSubscriptOpBuilder::findAtIndexSetter() { + if (AtIndexSetter) + return true; + + Expr *BaseExpr = RefExpr->getBaseExpr(); + QualType BaseT = BaseExpr->getType(); + + QualType ResultType; + if (const ObjCObjectPointerType *PTy = + BaseT->getAs()) { + ResultType = PTy->getPointeeType(); + if (const ObjCObjectType *iQFaceTy = + ResultType->getAsObjCQualifiedInterfaceType()) + ResultType = iQFaceTy->getBaseType(); + } + + Sema::ObjCSubscriptKind Res = + S.CheckSubscriptingKind(RefExpr->getKeyExpr()); + if (Res == Sema::OS_Error) + return false; + bool arrayRef = (Res == Sema::OS_Array); + + if (ResultType.isNull()) { + S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_base_type) + << BaseExpr->getType() << arrayRef; + return false; + } + + if (!arrayRef) { + // dictionary subscripting. + // - (void)setObject:(id)object forKeyedSubscript:(id)key; + IdentifierInfo *KeyIdents[] = { + &S.Context.Idents.get("setObject"), + &S.Context.Idents.get("forKeyedSubscript") + }; + AtIndexSetterSelector = S.Context.Selectors.getSelector(2, KeyIdents); + } + else { + // - (void)setObject:(id)object atIndexedSubscript:(NSInteger)index; + IdentifierInfo *KeyIdents[] = { + &S.Context.Idents.get("setObject"), + &S.Context.Idents.get("atIndexedSubscript") + }; + AtIndexSetterSelector = S.Context.Selectors.getSelector(2, KeyIdents); + } + AtIndexSetter = S.LookupMethodInObjectType(AtIndexSetterSelector, ResultType, + true /*instance*/); + + bool receiverIdType = (BaseT->isObjCIdType() || + BaseT->isObjCQualifiedIdType()); + + if (!AtIndexSetter && S.getLangOpts().DebuggerObjCLiteral) { + TypeSourceInfo *ResultTInfo = 0; + QualType ReturnType = S.Context.VoidTy; + AtIndexSetter = ObjCMethodDecl::Create(S.Context, SourceLocation(), + SourceLocation(), AtIndexSetterSelector, + ReturnType, + ResultTInfo, + S.Context.getTranslationUnitDecl(), + true /*Instance*/, false/*isVariadic*/, + /*isSynthesized=*/false, + /*isImplicitlyDeclared=*/true, /*isDefined=*/false, + ObjCMethodDecl::Required, + false); + SmallVector Params; + ParmVarDecl *object = ParmVarDecl::Create(S.Context, AtIndexSetter, + SourceLocation(), SourceLocation(), + &S.Context.Idents.get("object"), + S.Context.getObjCIdType(), + /*TInfo=*/0, + SC_None, + SC_None, + 0); + Params.push_back(object); + ParmVarDecl *key = ParmVarDecl::Create(S.Context, AtIndexSetter, + SourceLocation(), SourceLocation(), + arrayRef ? &S.Context.Idents.get("index") + : &S.Context.Idents.get("key"), + arrayRef ? S.Context.UnsignedLongTy + : S.Context.getObjCIdType(), + /*TInfo=*/0, + SC_None, + SC_None, + 0); + Params.push_back(key); + AtIndexSetter->setMethodParams(S.Context, Params, ArrayRef()); + } + + if (!AtIndexSetter) { + if (!receiverIdType) { + S.Diag(BaseExpr->getExprLoc(), + diag::err_objc_subscript_method_not_found) + << BaseExpr->getType() << 1 << arrayRef; + return false; + } + AtIndexSetter = + S.LookupInstanceMethodInGlobalPool(AtIndexSetterSelector, + RefExpr->getSourceRange(), + true, false); + } + + bool err = false; + if (AtIndexSetter && arrayRef) { + QualType T = AtIndexSetter->param_begin()[1]->getType(); + if (!T->isIntegralOrEnumerationType()) { + S.Diag(RefExpr->getKeyExpr()->getExprLoc(), + diag::err_objc_subscript_index_type) << T; + S.Diag(AtIndexSetter->param_begin()[1]->getLocation(), + diag::note_parameter_type) << T; + err = true; + } + T = AtIndexSetter->param_begin()[0]->getType(); + if (!T->isObjCObjectPointerType()) { + S.Diag(RefExpr->getBaseExpr()->getExprLoc(), + diag::err_objc_subscript_object_type) << T << arrayRef; + S.Diag(AtIndexSetter->param_begin()[0]->getLocation(), + diag::note_parameter_type) << T; + err = true; + } + } + else if (AtIndexSetter && !arrayRef) + for (unsigned i=0; i <2; i++) { + QualType T = AtIndexSetter->param_begin()[i]->getType(); + if (!T->isObjCObjectPointerType()) { + if (i == 1) + S.Diag(RefExpr->getKeyExpr()->getExprLoc(), + diag::err_objc_subscript_key_type) << T; + else + S.Diag(RefExpr->getBaseExpr()->getExprLoc(), + diag::err_objc_subscript_dic_object_type) << T; + S.Diag(AtIndexSetter->param_begin()[i]->getLocation(), + diag::note_parameter_type) << T; + err = true; + } + } + + return !err; +} + +// Get the object at "Index" position in the container. +// [BaseExpr objectAtIndexedSubscript : IndexExpr]; +ExprResult ObjCSubscriptOpBuilder::buildGet() { + if (!findAtIndexGetter()) + return ExprError(); + + QualType receiverType = InstanceBase->getType(); + + // Build a message-send. + ExprResult msg; + Expr *Index = InstanceKey; + + // Arguments. + Expr *args[] = { Index }; + assert(InstanceBase); + msg = S.BuildInstanceMessageImplicit(InstanceBase, receiverType, + GenericLoc, + AtIndexGetterSelector, AtIndexGetter, + MultiExprArg(args, 1)); + return msg; +} + +/// Store into the container the "op" object at "Index"'ed location +/// by building this messaging expression: +/// - (void)setObject:(id)object atIndexedSubscript:(NSInteger)index; +/// \param bindSetValueAsResult - If true, capture the actual +/// value being set as the value of the property operation. +ExprResult ObjCSubscriptOpBuilder::buildSet(Expr *op, SourceLocation opcLoc, + bool captureSetValueAsResult) { + if (!findAtIndexSetter()) + return ExprError(); + + QualType receiverType = InstanceBase->getType(); + Expr *Index = InstanceKey; + + // Arguments. + Expr *args[] = { op, Index }; + + // Build a message-send. + ExprResult msg = S.BuildInstanceMessageImplicit(InstanceBase, receiverType, + GenericLoc, + AtIndexSetterSelector, + AtIndexSetter, + MultiExprArg(args, 2)); + + if (!msg.isInvalid() && captureSetValueAsResult) { + ObjCMessageExpr *msgExpr = + cast(msg.get()->IgnoreImplicit()); + Expr *arg = msgExpr->getArg(0); + msgExpr->setArg(0, captureValueAsResult(arg)); + } + + return msg; +} + +//===----------------------------------------------------------------------===// +// General Sema routines. +//===----------------------------------------------------------------------===// + +ExprResult Sema::checkPseudoObjectRValue(Expr *E) { + Expr *opaqueRef = E->IgnoreParens(); + if (ObjCPropertyRefExpr *refExpr + = dyn_cast(opaqueRef)) { + ObjCPropertyOpBuilder builder(*this, refExpr); + return builder.buildRValueOperation(E); + } + else if (ObjCSubscriptRefExpr *refExpr + = dyn_cast(opaqueRef)) { + ObjCSubscriptOpBuilder builder(*this, refExpr); + return builder.buildRValueOperation(E); + } else { + llvm_unreachable("unknown pseudo-object kind!"); + } +} + +/// Check an increment or decrement of a pseudo-object expression. +ExprResult Sema::checkPseudoObjectIncDec(Scope *Sc, SourceLocation opcLoc, + UnaryOperatorKind opcode, Expr *op) { + // Do nothing if the operand is dependent. + if (op->isTypeDependent()) + return new (Context) UnaryOperator(op, opcode, Context.DependentTy, + VK_RValue, OK_Ordinary, opcLoc); + + assert(UnaryOperator::isIncrementDecrementOp(opcode)); + Expr *opaqueRef = op->IgnoreParens(); + if (ObjCPropertyRefExpr *refExpr + = dyn_cast(opaqueRef)) { + ObjCPropertyOpBuilder builder(*this, refExpr); + return builder.buildIncDecOperation(Sc, opcLoc, opcode, op); + } else if (isa(opaqueRef)) { + Diag(opcLoc, diag::err_illegal_container_subscripting_op); + return ExprError(); + } else { + llvm_unreachable("unknown pseudo-object kind!"); + } +} + +ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc, + BinaryOperatorKind opcode, + Expr *LHS, Expr *RHS) { + // Do nothing if either argument is dependent. + if (LHS->isTypeDependent() || RHS->isTypeDependent()) + return new (Context) BinaryOperator(LHS, RHS, opcode, Context.DependentTy, + VK_RValue, OK_Ordinary, opcLoc); + + // Filter out non-overload placeholder types in the RHS. + if (RHS->getType()->isNonOverloadPlaceholderType()) { + ExprResult result = CheckPlaceholderExpr(RHS); + if (result.isInvalid()) return ExprError(); + RHS = result.take(); + } + + Expr *opaqueRef = LHS->IgnoreParens(); + if (ObjCPropertyRefExpr *refExpr + = dyn_cast(opaqueRef)) { + ObjCPropertyOpBuilder builder(*this, refExpr); + return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS); + } else if (ObjCSubscriptRefExpr *refExpr + = dyn_cast(opaqueRef)) { + ObjCSubscriptOpBuilder builder(*this, refExpr); + return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS); + } else { + llvm_unreachable("unknown pseudo-object kind!"); + } +} + +/// Given a pseudo-object reference, rebuild it without the opaque +/// values. Basically, undo the behavior of rebuildAndCaptureObject. +/// This should never operate in-place. +static Expr *stripOpaqueValuesFromPseudoObjectRef(Sema &S, Expr *E) { + Expr *opaqueRef = E->IgnoreParens(); + if (ObjCPropertyRefExpr *refExpr + = dyn_cast(opaqueRef)) { + // Class and super property references don't have opaque values in them. + if (refExpr->isClassReceiver() || refExpr->isSuperReceiver()) + return E; + + assert(refExpr->isObjectReceiver() && "Unknown receiver kind?"); + OpaqueValueExpr *baseOVE = cast(refExpr->getBase()); + return ObjCPropertyRefRebuilder(S, baseOVE->getSourceExpr()).rebuild(E); + } else if (ObjCSubscriptRefExpr *refExpr + = dyn_cast(opaqueRef)) { + OpaqueValueExpr *baseOVE = cast(refExpr->getBaseExpr()); + OpaqueValueExpr *keyOVE = cast(refExpr->getKeyExpr()); + return ObjCSubscriptRefRebuilder(S, baseOVE->getSourceExpr(), + keyOVE->getSourceExpr()).rebuild(E); + } else { + llvm_unreachable("unknown pseudo-object kind!"); + } +} + +/// Given a pseudo-object expression, recreate what it looks like +/// syntactically without the attendant OpaqueValueExprs. +/// +/// This is a hack which should be removed when TreeTransform is +/// capable of rebuilding a tree without stripping implicit +/// operations. +Expr *Sema::recreateSyntacticForm(PseudoObjectExpr *E) { + Expr *syntax = E->getSyntacticForm(); + if (UnaryOperator *uop = dyn_cast(syntax)) { + Expr *op = stripOpaqueValuesFromPseudoObjectRef(*this, uop->getSubExpr()); + return new (Context) UnaryOperator(op, uop->getOpcode(), uop->getType(), + uop->getValueKind(), uop->getObjectKind(), + uop->getOperatorLoc()); + } else if (CompoundAssignOperator *cop + = dyn_cast(syntax)) { + Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, cop->getLHS()); + Expr *rhs = cast(cop->getRHS())->getSourceExpr(); + return new (Context) CompoundAssignOperator(lhs, rhs, cop->getOpcode(), + cop->getType(), + cop->getValueKind(), + cop->getObjectKind(), + cop->getComputationLHSType(), + cop->getComputationResultType(), + cop->getOperatorLoc()); + } else if (BinaryOperator *bop = dyn_cast(syntax)) { + Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, bop->getLHS()); + Expr *rhs = cast(bop->getRHS())->getSourceExpr(); + return new (Context) BinaryOperator(lhs, rhs, bop->getOpcode(), + bop->getType(), bop->getValueKind(), + bop->getObjectKind(), + bop->getOperatorLoc()); + } else { + assert(syntax->hasPlaceholderType(BuiltinType::PseudoObject)); + return stripOpaqueValuesFromPseudoObjectRef(*this, syntax); + } +} diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp new file mode 100644 index 0000000..9052278 --- /dev/null +++ b/clang/lib/Sema/SemaStmt.cpp @@ -0,0 +1,2663 @@ +//===--- SemaStmt.cpp - Semantic Analysis for Statements ------------------===// +// +// 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 statements. +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/Initialization.h" +#include "clang/Sema/Lookup.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/CharUnits.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprObjC.h" +#include "clang/AST/StmtObjC.h" +#include "clang/AST/StmtCXX.h" +#include "clang/AST/TypeLoc.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Basic/TargetInfo.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +using namespace clang; +using namespace sema; + +StmtResult Sema::ActOnExprStmt(FullExprArg expr) { + Expr *E = expr.get(); + if (!E) // FIXME: FullExprArg has no error state? + 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. + + // Same thing in for stmt first clause (when expr) and third clause. + return Owned(static_cast(E)); +} + + +StmtResult Sema::ActOnNullStmt(SourceLocation SemiLoc, + bool HasLeadingEmptyMacro) { + return Owned(new (Context) NullStmt(SemiLoc, HasLeadingEmptyMacro)); +} + +StmtResult Sema::ActOnDeclStmt(DeclGroupPtrTy dg, SourceLocation StartLoc, + SourceLocation EndLoc) { + DeclGroupRef DG = dg.getAsVal(); + + // If we have an invalid decl, just return an error. + if (DG.isNull()) return StmtError(); + + return Owned(new (Context) DeclStmt(DG, StartLoc, EndLoc)); +} + +void Sema::ActOnForEachDeclStmt(DeclGroupPtrTy dg) { + DeclGroupRef DG = dg.getAsVal(); + + // If we have an invalid decl, just return. + if (DG.isNull() || !DG.isSingleDecl()) return; + VarDecl *var = cast(DG.getSingleDecl()); + + // suppress any potential 'unused variable' warning. + var->setUsed(); + + // foreach variables are never actually initialized in the way that + // the parser came up with. + var->setInit(0); + + // In ARC, we don't need to retain the iteration variable of a fast + // enumeration loop. Rather than actually trying to catch that + // during declaration processing, we remove the consequences here. + if (getLangOpts().ObjCAutoRefCount) { + QualType type = var->getType(); + + // Only do this if we inferred the lifetime. Inferred lifetime + // will show up as a local qualifier because explicit lifetime + // should have shown up as an AttributedType instead. + if (type.getLocalQualifiers().getObjCLifetime() == Qualifiers::OCL_Strong) { + // Add 'const' and mark the variable as pseudo-strong. + var->setType(type.withConst()); + var->setARCPseudoStrong(true); + } + } +} + +/// \brief Diagnose unused '==' and '!=' as likely typos for '=' or '|='. +/// +/// Adding a cast to void (or other expression wrappers) will prevent the +/// warning from firing. +static bool DiagnoseUnusedComparison(Sema &S, const Expr *E) { + SourceLocation Loc; + bool IsNotEqual, CanAssign; + + if (const BinaryOperator *Op = dyn_cast(E)) { + if (Op->getOpcode() != BO_EQ && Op->getOpcode() != BO_NE) + return false; + + Loc = Op->getOperatorLoc(); + IsNotEqual = Op->getOpcode() == BO_NE; + CanAssign = Op->getLHS()->IgnoreParenImpCasts()->isLValue(); + } else if (const CXXOperatorCallExpr *Op = dyn_cast(E)) { + if (Op->getOperator() != OO_EqualEqual && + Op->getOperator() != OO_ExclaimEqual) + return false; + + Loc = Op->getOperatorLoc(); + IsNotEqual = Op->getOperator() == OO_ExclaimEqual; + CanAssign = Op->getArg(0)->IgnoreParenImpCasts()->isLValue(); + } else { + // Not a typo-prone comparison. + return false; + } + + // Suppress warnings when the operator, suspicious as it may be, comes from + // a macro expansion. + if (Loc.isMacroID()) + return false; + + S.Diag(Loc, diag::warn_unused_comparison) + << (unsigned)IsNotEqual << E->getSourceRange(); + + // If the LHS is a plausible entity to assign to, provide a fixit hint to + // correct common typos. + if (CanAssign) { + if (IsNotEqual) + S.Diag(Loc, diag::note_inequality_comparison_to_or_assign) + << FixItHint::CreateReplacement(Loc, "|="); + else + S.Diag(Loc, diag::note_equality_comparison_to_assign) + << FixItHint::CreateReplacement(Loc, "="); + } + + return true; +} + +void Sema::DiagnoseUnusedExprResult(const Stmt *S) { + if (const LabelStmt *Label = dyn_cast_or_null(S)) + return DiagnoseUnusedExprResult(Label->getSubStmt()); + + const Expr *E = dyn_cast_or_null(S); + if (!E) + return; + + SourceLocation Loc; + SourceRange R1, R2; + if (SourceMgr.isInSystemMacro(E->getExprLoc()) || + !E->isUnusedResultAWarning(Loc, R1, R2, Context)) + return; + + // Okay, we have an unused result. Depending on what the base expression is, + // we might want to make a more specific diagnostic. Check for one of these + // cases now. + unsigned DiagID = diag::warn_unused_expr; + if (const ExprWithCleanups *Temps = dyn_cast(E)) + E = Temps->getSubExpr(); + if (const CXXBindTemporaryExpr *TempExpr = dyn_cast(E)) + E = TempExpr->getSubExpr(); + + if (DiagnoseUnusedComparison(*this, E)) + return; + + E = E->IgnoreParenImpCasts(); + if (const CallExpr *CE = dyn_cast(E)) { + if (E->getType()->isVoidType()) + return; + + // If the callee has attribute pure, const, or warn_unused_result, warn with + // a more specific message to make it clear what is happening. + if (const Decl *FD = CE->getCalleeDecl()) { + if (FD->getAttr()) { + Diag(Loc, diag::warn_unused_result) << R1 << R2; + return; + } + if (FD->getAttr()) { + Diag(Loc, diag::warn_unused_call) << R1 << R2 << "pure"; + return; + } + if (FD->getAttr()) { + Diag(Loc, diag::warn_unused_call) << R1 << R2 << "const"; + return; + } + } + } else if (const ObjCMessageExpr *ME = dyn_cast(E)) { + if (getLangOpts().ObjCAutoRefCount && ME->isDelegateInitCall()) { + Diag(Loc, diag::err_arc_unused_init_message) << R1; + return; + } + const ObjCMethodDecl *MD = ME->getMethodDecl(); + if (MD && MD->getAttr()) { + Diag(Loc, diag::warn_unused_result) << R1 << R2; + return; + } + } else if (const PseudoObjectExpr *POE = dyn_cast(E)) { + const Expr *Source = POE->getSyntacticForm(); + if (isa(Source)) + DiagID = diag::warn_unused_container_subscript_expr; + else + DiagID = diag::warn_unused_property_expr; + } else if (const CXXFunctionalCastExpr *FC + = dyn_cast(E)) { + if (isa(FC->getSubExpr()) || + isa(FC->getSubExpr())) + return; + } + // Diagnose "(void*) blah" as a typo for "(void) blah". + else if (const CStyleCastExpr *CE = dyn_cast(E)) { + TypeSourceInfo *TI = CE->getTypeInfoAsWritten(); + QualType T = TI->getType(); + + // We really do want to use the non-canonical type here. + if (T == Context.VoidPtrTy) { + PointerTypeLoc TL = cast(TI->getTypeLoc()); + + Diag(Loc, diag::warn_unused_voidptr) + << FixItHint::CreateRemoval(TL.getStarLoc()); + return; + } + } + + DiagRuntimeBehavior(Loc, 0, PDiag(DiagID) << R1 << R2); +} + +void Sema::ActOnStartOfCompoundStmt() { + PushCompoundScope(); +} + +void Sema::ActOnFinishOfCompoundStmt() { + PopCompoundScope(); +} + +sema::CompoundScopeInfo &Sema::getCurCompoundScope() const { + return getCurFunction()->CompoundScopes.back(); +} + +StmtResult +Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R, + MultiStmtArg elts, bool isStmtExpr) { + unsigned NumElts = elts.size(); + Stmt **Elts = reinterpret_cast(elts.release()); + // If we're in C89 mode, check that we don't have any decls after stmts. If + // so, emit an extension diagnostic. + if (!getLangOpts().C99 && !getLangOpts().CPlusPlus) { + // Note that __extension__ can be around a decl. + unsigned i = 0; + // Skip over all declarations. + for (; i != NumElts && isa(Elts[i]); ++i) + /*empty*/; + + // We found the end of the list or a statement. Scan for another declstmt. + for (; i != NumElts && !isa(Elts[i]); ++i) + /*empty*/; + + if (i != NumElts) { + Decl *D = *cast(Elts[i])->decl_begin(); + Diag(D->getLocation(), diag::ext_mixed_decls_code); + } + } + // Warn about unused expressions in statements. + for (unsigned i = 0; i != NumElts; ++i) { + // Ignore statements that are last in a statement expression. + if (isStmtExpr && i == NumElts - 1) + continue; + + DiagnoseUnusedExprResult(Elts[i]); + } + + // Check for suspicious empty body (null statement) in `for' and `while' + // statements. Don't do anything for template instantiations, this just adds + // noise. + if (NumElts != 0 && !CurrentInstantiationScope && + getCurCompoundScope().HasEmptyLoopBodies) { + for (unsigned i = 0; i != NumElts - 1; ++i) + DiagnoseEmptyLoopBody(Elts[i], Elts[i + 1]); + } + + return Owned(new (Context) CompoundStmt(Context, Elts, NumElts, L, R)); +} + +StmtResult +Sema::ActOnCaseStmt(SourceLocation CaseLoc, Expr *LHSVal, + SourceLocation DotDotDotLoc, Expr *RHSVal, + SourceLocation ColonLoc) { + assert((LHSVal != 0) && "missing expression in case statement"); + + if (getCurFunction()->SwitchStack.empty()) { + Diag(CaseLoc, diag::err_case_not_in_switch); + return StmtError(); + } + + if (!getLangOpts().CPlusPlus0x) { + // C99 6.8.4.2p3: The expression shall be an integer constant. + // However, GCC allows any evaluatable integer expression. + if (!LHSVal->isTypeDependent() && !LHSVal->isValueDependent()) { + LHSVal = VerifyIntegerConstantExpression(LHSVal).take(); + if (!LHSVal) + return StmtError(); + } + + // GCC extension: The expression shall be an integer constant. + + if (RHSVal && !RHSVal->isTypeDependent() && !RHSVal->isValueDependent()) { + RHSVal = VerifyIntegerConstantExpression(RHSVal).take(); + // Recover from an error by just forgetting about it. + } + } + + CaseStmt *CS = new (Context) CaseStmt(LHSVal, RHSVal, CaseLoc, DotDotDotLoc, + ColonLoc); + getCurFunction()->SwitchStack.back()->addSwitchCase(CS); + return Owned(CS); +} + +/// ActOnCaseStmtBody - This installs a statement as the body of a case. +void Sema::ActOnCaseStmtBody(Stmt *caseStmt, Stmt *SubStmt) { + DiagnoseUnusedExprResult(SubStmt); + + CaseStmt *CS = static_cast(caseStmt); + CS->setSubStmt(SubStmt); +} + +StmtResult +Sema::ActOnDefaultStmt(SourceLocation DefaultLoc, SourceLocation ColonLoc, + Stmt *SubStmt, Scope *CurScope) { + DiagnoseUnusedExprResult(SubStmt); + + if (getCurFunction()->SwitchStack.empty()) { + Diag(DefaultLoc, diag::err_default_not_in_switch); + return Owned(SubStmt); + } + + DefaultStmt *DS = new (Context) DefaultStmt(DefaultLoc, ColonLoc, SubStmt); + getCurFunction()->SwitchStack.back()->addSwitchCase(DS); + return Owned(DS); +} + +StmtResult +Sema::ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl, + SourceLocation ColonLoc, Stmt *SubStmt) { + // If the label was multiply defined, reject it now. + if (TheDecl->getStmt()) { + Diag(IdentLoc, diag::err_redefinition_of_label) << TheDecl->getDeclName(); + Diag(TheDecl->getLocation(), diag::note_previous_definition); + return Owned(SubStmt); + } + + // Otherwise, things are good. Fill in the declaration and return it. + LabelStmt *LS = new (Context) LabelStmt(IdentLoc, TheDecl, SubStmt); + TheDecl->setStmt(LS); + if (!TheDecl->isGnuLocal()) + TheDecl->setLocation(IdentLoc); + return Owned(LS); +} + +StmtResult Sema::ActOnAttributedStmt(SourceLocation AttrLoc, + const AttrVec &Attrs, + Stmt *SubStmt) { + // Fill in the declaration and return it. Variable length will require to + // change this to AttributedStmt::Create(Context, ....); + // and probably using ArrayRef + AttributedStmt *LS = new (Context) AttributedStmt(AttrLoc, Attrs, SubStmt); + return Owned(LS); +} + +StmtResult +Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar, + Stmt *thenStmt, SourceLocation ElseLoc, + Stmt *elseStmt) { + ExprResult CondResult(CondVal.release()); + + VarDecl *ConditionVar = 0; + if (CondVar) { + ConditionVar = cast(CondVar); + CondResult = CheckConditionVariable(ConditionVar, IfLoc, true); + if (CondResult.isInvalid()) + return StmtError(); + } + Expr *ConditionExpr = CondResult.takeAs(); + if (!ConditionExpr) + return StmtError(); + + DiagnoseUnusedExprResult(thenStmt); + + if (!elseStmt) { + DiagnoseEmptyStmtBody(ConditionExpr->getLocEnd(), thenStmt, + diag::warn_empty_if_body); + } + + DiagnoseUnusedExprResult(elseStmt); + + return Owned(new (Context) IfStmt(Context, IfLoc, ConditionVar, ConditionExpr, + thenStmt, ElseLoc, elseStmt)); +} + +/// ConvertIntegerToTypeWarnOnOverflow - Convert the specified APInt to have +/// the specified width and sign. If an overflow occurs, detect it and emit +/// the specified diagnostic. +void Sema::ConvertIntegerToTypeWarnOnOverflow(llvm::APSInt &Val, + unsigned NewWidth, bool NewSign, + SourceLocation Loc, + unsigned DiagID) { + // Perform a conversion to the promoted condition type if needed. + if (NewWidth > Val.getBitWidth()) { + // If this is an extension, just do it. + Val = Val.extend(NewWidth); + Val.setIsSigned(NewSign); + + // If the input was signed and negative and the output is + // unsigned, don't bother to warn: this is implementation-defined + // behavior. + // FIXME: Introduce a second, default-ignored warning for this case? + } else if (NewWidth < Val.getBitWidth()) { + // If this is a truncation, check for overflow. + llvm::APSInt ConvVal(Val); + ConvVal = ConvVal.trunc(NewWidth); + ConvVal.setIsSigned(NewSign); + ConvVal = ConvVal.extend(Val.getBitWidth()); + ConvVal.setIsSigned(Val.isSigned()); + if (ConvVal != Val) + Diag(Loc, DiagID) << Val.toString(10) << ConvVal.toString(10); + + // Regardless of whether a diagnostic was emitted, really do the + // truncation. + Val = Val.trunc(NewWidth); + Val.setIsSigned(NewSign); + } else if (NewSign != Val.isSigned()) { + // Convert the sign to match the sign of the condition. This can cause + // overflow as well: unsigned(INTMIN) + // We don't diagnose this overflow, because it is implementation-defined + // behavior. + // FIXME: Introduce a second, default-ignored warning for this case? + llvm::APSInt OldVal(Val); + Val.setIsSigned(NewSign); + } +} + +namespace { + struct CaseCompareFunctor { + bool operator()(const std::pair &LHS, + const llvm::APSInt &RHS) { + return LHS.first < RHS; + } + bool operator()(const std::pair &LHS, + const std::pair &RHS) { + return LHS.first < RHS.first; + } + bool operator()(const llvm::APSInt &LHS, + const std::pair &RHS) { + return LHS < RHS.first; + } + }; +} + +/// CmpCaseVals - Comparison predicate for sorting case values. +/// +static bool CmpCaseVals(const std::pair& lhs, + const std::pair& rhs) { + if (lhs.first < rhs.first) + return true; + + if (lhs.first == rhs.first && + lhs.second->getCaseLoc().getRawEncoding() + < rhs.second->getCaseLoc().getRawEncoding()) + return true; + return false; +} + +/// CmpEnumVals - Comparison predicate for sorting enumeration values. +/// +static bool CmpEnumVals(const std::pair& lhs, + const std::pair& rhs) +{ + return lhs.first < rhs.first; +} + +/// EqEnumVals - Comparison preficate for uniqing enumeration values. +/// +static bool EqEnumVals(const std::pair& lhs, + const std::pair& rhs) +{ + return lhs.first == rhs.first; +} + +/// GetTypeBeforeIntegralPromotion - Returns the pre-promotion type of +/// potentially integral-promoted expression @p expr. +static QualType GetTypeBeforeIntegralPromotion(Expr *&expr) { + if (ExprWithCleanups *cleanups = dyn_cast(expr)) + expr = cleanups->getSubExpr(); + while (ImplicitCastExpr *impcast = dyn_cast(expr)) { + if (impcast->getCastKind() != CK_IntegralCast) break; + expr = impcast->getSubExpr(); + } + return expr->getType(); +} + +StmtResult +Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, Expr *Cond, + Decl *CondVar) { + ExprResult CondResult; + + VarDecl *ConditionVar = 0; + if (CondVar) { + ConditionVar = cast(CondVar); + CondResult = CheckConditionVariable(ConditionVar, SourceLocation(), false); + if (CondResult.isInvalid()) + return StmtError(); + + Cond = CondResult.release(); + } + + if (!Cond) + return StmtError(); + + CondResult + = ConvertToIntegralOrEnumerationType(SwitchLoc, Cond, + PDiag(diag::err_typecheck_statement_requires_integer), + PDiag(diag::err_switch_incomplete_class_type) + << 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), + /*AllowScopedEnumerations*/ true); + if (CondResult.isInvalid()) return StmtError(); + Cond = CondResult.take(); + + // C99 6.8.4.2p5 - Integer promotions are performed on the controlling expr. + CondResult = UsualUnaryConversions(Cond); + if (CondResult.isInvalid()) return StmtError(); + Cond = CondResult.take(); + + if (!CondVar) { + CheckImplicitConversions(Cond, SwitchLoc); + CondResult = MaybeCreateExprWithCleanups(Cond); + if (CondResult.isInvalid()) + return StmtError(); + Cond = CondResult.take(); + } + + getCurFunction()->setHasBranchIntoScope(); + + SwitchStmt *SS = new (Context) SwitchStmt(Context, ConditionVar, Cond); + getCurFunction()->SwitchStack.push_back(SS); + return Owned(SS); +} + +static void AdjustAPSInt(llvm::APSInt &Val, unsigned BitWidth, bool IsSigned) { + if (Val.getBitWidth() < BitWidth) + Val = Val.extend(BitWidth); + else if (Val.getBitWidth() > BitWidth) + Val = Val.trunc(BitWidth); + Val.setIsSigned(IsSigned); +} + +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); + getCurFunction()->SwitchStack.pop_back(); + + Expr *CondExpr = SS->getCond(); + if (!CondExpr) return StmtError(); + + QualType CondType = CondExpr->getType(); + + Expr *CondExprBeforePromotion = CondExpr; + QualType CondTypeBeforePromotion = + GetTypeBeforeIntegralPromotion(CondExprBeforePromotion); + + // C++ 6.4.2.p2: + // Integral promotions are performed (on the switch condition). + // + // A case value unrepresentable by the original switch condition + // type (before the promotion) doesn't make sense, even when it can + // be represented by the promoted type. Therefore we need to find + // the pre-promotion type of the switch condition. + if (!CondExpr->isTypeDependent()) { + // We have already converted the expression to an integral or enumeration + // type, when we started the switch statement. If we don't have an + // appropriate type now, just return an error. + if (!CondType->isIntegralOrEnumerationType()) + return StmtError(); + + if (CondExpr->isKnownToHaveBooleanValue()) { + // switch(bool_expr) {...} is often a programmer error, e.g. + // switch(n && mask) { ... } // Doh - should be "n & mask". + // One can always use an if statement instead of switch(bool_expr). + Diag(SwitchLoc, diag::warn_bool_switch_condition) + << CondExpr->getSourceRange(); + } + } + + // Get the bitwidth of the switched-on value before promotions. We must + // convert the integer case values to this width before comparison. + bool HasDependentValue + = CondExpr->isTypeDependent() || CondExpr->isValueDependent(); + unsigned CondWidth + = HasDependentValue ? 0 : Context.getIntWidth(CondTypeBeforePromotion); + bool CondIsSigned + = CondTypeBeforePromotion->isSignedIntegerOrEnumerationType(); + + // Accumulate all of the case values in a vector so that we can sort them + // and detect duplicates. This vector contains the APInt for the case after + // it has been converted to the condition type. + typedef SmallVector, 64> CaseValsTy; + CaseValsTy CaseVals; + + // Keep track of any GNU case ranges we see. The APSInt is the low value. + typedef std::vector > CaseRangesTy; + CaseRangesTy CaseRanges; + + DefaultStmt *TheDefaultStmt = 0; + + bool CaseListIsErroneous = false; + + for (SwitchCase *SC = SS->getSwitchCaseList(); SC && !HasDependentValue; + SC = SC->getNextSwitchCase()) { + + if (DefaultStmt *DS = dyn_cast(SC)) { + if (TheDefaultStmt) { + Diag(DS->getDefaultLoc(), diag::err_multiple_default_labels_defined); + Diag(TheDefaultStmt->getDefaultLoc(), diag::note_duplicate_case_prev); + + // FIXME: Remove the default statement from the switch block so that + // we'll return a valid AST. This requires recursing down the AST and + // finding it, not something we are set up to do right now. For now, + // just lop the entire switch stmt out of the AST. + CaseListIsErroneous = true; + } + TheDefaultStmt = DS; + + } else { + CaseStmt *CS = cast(SC); + + Expr *Lo = CS->getLHS(); + + if (Lo->isTypeDependent() || Lo->isValueDependent()) { + HasDependentValue = true; + break; + } + + llvm::APSInt LoVal; + + if (getLangOpts().CPlusPlus0x) { + // C++11 [stmt.switch]p2: the constant-expression shall be a converted + // constant expression of the promoted type of the switch condition. + ExprResult ConvLo = + CheckConvertedConstantExpression(Lo, CondType, LoVal, CCEK_CaseValue); + if (ConvLo.isInvalid()) { + CaseListIsErroneous = true; + continue; + } + Lo = ConvLo.take(); + } else { + // We already verified that the expression has a i-c-e value (C99 + // 6.8.4.2p3) - get that value now. + LoVal = Lo->EvaluateKnownConstInt(Context); + + // If the LHS is not the same type as the condition, insert an implicit + // cast. + Lo = DefaultLvalueConversion(Lo).take(); + Lo = ImpCastExprToType(Lo, CondType, CK_IntegralCast).take(); + } + + // Convert the value to the same width/sign as the condition had prior to + // integral promotions. + // + // FIXME: This causes us to reject valid code: + // switch ((char)c) { case 256: case 0: return 0; } + // Here we claim there is a duplicated condition value, but there is not. + ConvertIntegerToTypeWarnOnOverflow(LoVal, CondWidth, CondIsSigned, + Lo->getLocStart(), + diag::warn_case_value_overflow); + + CS->setLHS(Lo); + + // If this is a case range, remember it in CaseRanges, otherwise CaseVals. + if (CS->getRHS()) { + if (CS->getRHS()->isTypeDependent() || + CS->getRHS()->isValueDependent()) { + HasDependentValue = true; + break; + } + CaseRanges.push_back(std::make_pair(LoVal, CS)); + } else + CaseVals.push_back(std::make_pair(LoVal, CS)); + } + } + + if (!HasDependentValue) { + // If we don't have a default statement, check whether the + // condition is constant. + llvm::APSInt ConstantCondValue; + bool HasConstantCond = false; + if (!HasDependentValue && !TheDefaultStmt) { + HasConstantCond + = CondExprBeforePromotion->EvaluateAsInt(ConstantCondValue, Context, + Expr::SE_AllowSideEffects); + assert(!HasConstantCond || + (ConstantCondValue.getBitWidth() == CondWidth && + ConstantCondValue.isSigned() == CondIsSigned)); + } + bool ShouldCheckConstantCond = HasConstantCond; + + // Sort all the scalar case values so we can easily detect duplicates. + std::stable_sort(CaseVals.begin(), CaseVals.end(), CmpCaseVals); + + if (!CaseVals.empty()) { + for (unsigned i = 0, e = CaseVals.size(); i != e; ++i) { + if (ShouldCheckConstantCond && + CaseVals[i].first == ConstantCondValue) + ShouldCheckConstantCond = false; + + if (i != 0 && CaseVals[i].first == CaseVals[i-1].first) { + // If we have a duplicate, report it. + Diag(CaseVals[i].second->getLHS()->getLocStart(), + diag::err_duplicate_case) << CaseVals[i].first.toString(10); + Diag(CaseVals[i-1].second->getLHS()->getLocStart(), + diag::note_duplicate_case_prev); + // FIXME: We really want to remove the bogus case stmt from the + // substmt, but we have no way to do this right now. + CaseListIsErroneous = true; + } + } + } + + // Detect duplicate case ranges, which usually don't exist at all in + // the first place. + if (!CaseRanges.empty()) { + // Sort all the case ranges by their low value so we can easily detect + // overlaps between ranges. + std::stable_sort(CaseRanges.begin(), CaseRanges.end()); + + // Scan the ranges, computing the high values and removing empty ranges. + std::vector HiVals; + for (unsigned i = 0, e = CaseRanges.size(); i != e; ++i) { + llvm::APSInt &LoVal = CaseRanges[i].first; + CaseStmt *CR = CaseRanges[i].second; + Expr *Hi = CR->getRHS(); + llvm::APSInt HiVal; + + if (getLangOpts().CPlusPlus0x) { + // C++11 [stmt.switch]p2: the constant-expression shall be a converted + // constant expression of the promoted type of the switch condition. + ExprResult ConvHi = + CheckConvertedConstantExpression(Hi, CondType, HiVal, + CCEK_CaseValue); + if (ConvHi.isInvalid()) { + CaseListIsErroneous = true; + continue; + } + Hi = ConvHi.take(); + } else { + HiVal = Hi->EvaluateKnownConstInt(Context); + + // If the RHS is not the same type as the condition, insert an + // implicit cast. + Hi = DefaultLvalueConversion(Hi).take(); + Hi = ImpCastExprToType(Hi, CondType, CK_IntegralCast).take(); + } + + // Convert the value to the same width/sign as the condition. + ConvertIntegerToTypeWarnOnOverflow(HiVal, CondWidth, CondIsSigned, + Hi->getLocStart(), + diag::warn_case_value_overflow); + + CR->setRHS(Hi); + + // If the low value is bigger than the high value, the case is empty. + if (LoVal > HiVal) { + Diag(CR->getLHS()->getLocStart(), diag::warn_case_empty_range) + << SourceRange(CR->getLHS()->getLocStart(), + Hi->getLocEnd()); + CaseRanges.erase(CaseRanges.begin()+i); + --i, --e; + continue; + } + + if (ShouldCheckConstantCond && + LoVal <= ConstantCondValue && + ConstantCondValue <= HiVal) + ShouldCheckConstantCond = false; + + HiVals.push_back(HiVal); + } + + // Rescan the ranges, looking for overlap with singleton values and other + // ranges. Since the range list is sorted, we only need to compare case + // ranges with their neighbors. + for (unsigned i = 0, e = CaseRanges.size(); i != e; ++i) { + llvm::APSInt &CRLo = CaseRanges[i].first; + llvm::APSInt &CRHi = HiVals[i]; + CaseStmt *CR = CaseRanges[i].second; + + // Check to see whether the case range overlaps with any + // singleton cases. + CaseStmt *OverlapStmt = 0; + llvm::APSInt OverlapVal(32); + + // Find the smallest value >= the lower bound. If I is in the + // case range, then we have overlap. + CaseValsTy::iterator I = std::lower_bound(CaseVals.begin(), + CaseVals.end(), CRLo, + CaseCompareFunctor()); + if (I != CaseVals.end() && I->first < CRHi) { + OverlapVal = I->first; // Found overlap with scalar. + OverlapStmt = I->second; + } + + // Find the smallest value bigger than the upper bound. + I = std::upper_bound(I, CaseVals.end(), CRHi, CaseCompareFunctor()); + if (I != CaseVals.begin() && (I-1)->first >= CRLo) { + OverlapVal = (I-1)->first; // Found overlap with scalar. + OverlapStmt = (I-1)->second; + } + + // Check to see if this case stmt overlaps with the subsequent + // case range. + if (i && CRLo <= HiVals[i-1]) { + OverlapVal = HiVals[i-1]; // Found overlap with range. + OverlapStmt = CaseRanges[i-1].second; + } + + if (OverlapStmt) { + // If we have a duplicate, report it. + Diag(CR->getLHS()->getLocStart(), diag::err_duplicate_case) + << OverlapVal.toString(10); + Diag(OverlapStmt->getLHS()->getLocStart(), + diag::note_duplicate_case_prev); + // FIXME: We really want to remove the bogus case stmt from the + // substmt, but we have no way to do this right now. + CaseListIsErroneous = true; + } + } + } + + // Complain if we have a constant condition and we didn't find a match. + if (!CaseListIsErroneous && ShouldCheckConstantCond) { + // TODO: it would be nice if we printed enums as enums, chars as + // chars, etc. + Diag(CondExpr->getExprLoc(), diag::warn_missing_case_for_condition) + << ConstantCondValue.toString(10) + << CondExpr->getSourceRange(); + } + + // Check to see if switch is over an Enum and handles all of its + // values. We only issue a warning if there is not 'default:', but + // we still do the analysis to preserve this information in the AST + // (which can be used by flow-based analyes). + // + const EnumType *ET = CondTypeBeforePromotion->getAs(); + + // If switch has default case, then ignore it. + if (!CaseListIsErroneous && !HasConstantCond && ET) { + const EnumDecl *ED = ET->getDecl(); + typedef SmallVector, 64> + EnumValsTy; + EnumValsTy EnumVals; + + // Gather all enum values, set their type and sort them, + // allowing easier comparison with CaseVals. + for (EnumDecl::enumerator_iterator EDI = ED->enumerator_begin(); + EDI != ED->enumerator_end(); ++EDI) { + llvm::APSInt Val = EDI->getInitVal(); + AdjustAPSInt(Val, CondWidth, CondIsSigned); + EnumVals.push_back(std::make_pair(Val, *EDI)); + } + std::stable_sort(EnumVals.begin(), EnumVals.end(), CmpEnumVals); + EnumValsTy::iterator EIend = + std::unique(EnumVals.begin(), EnumVals.end(), EqEnumVals); + + // See which case values aren't in enum. + EnumValsTy::const_iterator EI = EnumVals.begin(); + for (CaseValsTy::const_iterator CI = CaseVals.begin(); + CI != CaseVals.end(); CI++) { + while (EI != EIend && EI->first < CI->first) + EI++; + if (EI == EIend || EI->first > CI->first) + Diag(CI->second->getLHS()->getExprLoc(), diag::warn_not_in_enum) + << CondTypeBeforePromotion; + } + // See which of case ranges aren't in enum + EI = EnumVals.begin(); + for (CaseRangesTy::const_iterator RI = CaseRanges.begin(); + RI != CaseRanges.end() && EI != EIend; RI++) { + while (EI != EIend && EI->first < RI->first) + EI++; + + if (EI == EIend || EI->first != RI->first) { + Diag(RI->second->getLHS()->getExprLoc(), diag::warn_not_in_enum) + << CondTypeBeforePromotion; + } + + llvm::APSInt Hi = + RI->second->getRHS()->EvaluateKnownConstInt(Context); + AdjustAPSInt(Hi, CondWidth, CondIsSigned); + while (EI != EIend && EI->first < Hi) + EI++; + if (EI == EIend || EI->first != Hi) + Diag(RI->second->getRHS()->getExprLoc(), diag::warn_not_in_enum) + << CondTypeBeforePromotion; + } + + // Check which enum vals aren't in switch + CaseValsTy::const_iterator CI = CaseVals.begin(); + CaseRangesTy::const_iterator RI = CaseRanges.begin(); + bool hasCasesNotInSwitch = false; + + SmallVector UnhandledNames; + + for (EI = EnumVals.begin(); EI != EIend; EI++){ + // Drop unneeded case values + llvm::APSInt CIVal; + while (CI != CaseVals.end() && CI->first < EI->first) + CI++; + + if (CI != CaseVals.end() && CI->first == EI->first) + continue; + + // Drop unneeded case ranges + for (; RI != CaseRanges.end(); RI++) { + llvm::APSInt Hi = + RI->second->getRHS()->EvaluateKnownConstInt(Context); + AdjustAPSInt(Hi, CondWidth, CondIsSigned); + if (EI->first <= Hi) + break; + } + + if (RI == CaseRanges.end() || EI->first < RI->first) { + hasCasesNotInSwitch = true; + UnhandledNames.push_back(EI->second->getDeclName()); + } + } + + if (TheDefaultStmt && UnhandledNames.empty()) + Diag(TheDefaultStmt->getDefaultLoc(), diag::warn_unreachable_default); + + // Produce a nice diagnostic if multiple values aren't handled. + switch (UnhandledNames.size()) { + case 0: break; + case 1: + Diag(CondExpr->getExprLoc(), TheDefaultStmt + ? diag::warn_def_missing_case1 : diag::warn_missing_case1) + << UnhandledNames[0]; + break; + case 2: + Diag(CondExpr->getExprLoc(), TheDefaultStmt + ? diag::warn_def_missing_case2 : diag::warn_missing_case2) + << UnhandledNames[0] << UnhandledNames[1]; + break; + case 3: + Diag(CondExpr->getExprLoc(), TheDefaultStmt + ? diag::warn_def_missing_case3 : diag::warn_missing_case3) + << UnhandledNames[0] << UnhandledNames[1] << UnhandledNames[2]; + break; + default: + Diag(CondExpr->getExprLoc(), TheDefaultStmt + ? diag::warn_def_missing_cases : diag::warn_missing_cases) + << (unsigned)UnhandledNames.size() + << UnhandledNames[0] << UnhandledNames[1] << UnhandledNames[2]; + break; + } + + if (!hasCasesNotInSwitch) + SS->setAllEnumCasesCovered(); + } + } + + DiagnoseEmptyStmtBody(CondExpr->getLocEnd(), BodyStmt, + diag::warn_empty_switch_body); + + // FIXME: If the case list was broken is some way, we don't have a good system + // to patch it up. Instead, just return the whole substmt as broken. + if (CaseListIsErroneous) + return StmtError(); + + return Owned(SS); +} + +StmtResult +Sema::ActOnWhileStmt(SourceLocation WhileLoc, FullExprArg Cond, + Decl *CondVar, Stmt *Body) { + ExprResult CondResult(Cond.release()); + + VarDecl *ConditionVar = 0; + if (CondVar) { + ConditionVar = cast(CondVar); + CondResult = CheckConditionVariable(ConditionVar, WhileLoc, true); + if (CondResult.isInvalid()) + return StmtError(); + } + Expr *ConditionExpr = CondResult.take(); + if (!ConditionExpr) + return StmtError(); + + DiagnoseUnusedExprResult(Body); + + if (isa(Body)) + getCurCompoundScope().setHasEmptyLoopBodies(); + + return Owned(new (Context) WhileStmt(Context, ConditionVar, ConditionExpr, + Body, WhileLoc)); +} + +StmtResult +Sema::ActOnDoStmt(SourceLocation DoLoc, Stmt *Body, + SourceLocation WhileLoc, SourceLocation CondLParen, + Expr *Cond, SourceLocation CondRParen) { + assert(Cond && "ActOnDoStmt(): missing expression"); + + ExprResult CondResult = CheckBooleanCondition(Cond, DoLoc); + if (CondResult.isInvalid() || CondResult.isInvalid()) + return StmtError(); + Cond = CondResult.take(); + + CheckImplicitConversions(Cond, DoLoc); + CondResult = MaybeCreateExprWithCleanups(Cond); + if (CondResult.isInvalid()) + return StmtError(); + Cond = CondResult.take(); + + DiagnoseUnusedExprResult(Body); + + return Owned(new (Context) DoStmt(Body, Cond, DoLoc, WhileLoc, CondRParen)); +} + +StmtResult +Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, + Stmt *First, FullExprArg second, Decl *secondVar, + FullExprArg third, + SourceLocation RParenLoc, Stmt *Body) { + if (!getLangOpts().CPlusPlus) { + if (DeclStmt *DS = dyn_cast_or_null(First)) { + // C99 6.8.5p3: The declaration part of a 'for' statement shall only + // declare identifiers for objects having storage class 'auto' or + // 'register'. + for (DeclStmt::decl_iterator DI=DS->decl_begin(), DE=DS->decl_end(); + DI!=DE; ++DI) { + VarDecl *VD = dyn_cast(*DI); + if (VD && VD->isLocalVarDecl() && !VD->hasLocalStorage()) + VD = 0; + if (VD == 0) + Diag((*DI)->getLocation(), diag::err_non_variable_decl_in_for); + // FIXME: mark decl erroneous! + } + } + } + + ExprResult SecondResult(second.release()); + VarDecl *ConditionVar = 0; + if (secondVar) { + ConditionVar = cast(secondVar); + SecondResult = CheckConditionVariable(ConditionVar, ForLoc, true); + if (SecondResult.isInvalid()) + return StmtError(); + } + + Expr *Third = third.release().takeAs(); + + DiagnoseUnusedExprResult(First); + DiagnoseUnusedExprResult(Third); + DiagnoseUnusedExprResult(Body); + + if (isa(Body)) + getCurCompoundScope().setHasEmptyLoopBodies(); + + return Owned(new (Context) ForStmt(Context, First, + SecondResult.take(), ConditionVar, + Third, Body, ForLoc, LParenLoc, + RParenLoc)); +} + +/// In an Objective C collection iteration statement: +/// for (x in y) +/// x can be an arbitrary l-value expression. Bind it up as a +/// full-expression. +StmtResult Sema::ActOnForEachLValueExpr(Expr *E) { + // Reduce placeholder expressions here. Note that this rejects the + // use of pseudo-object l-values in this position. + ExprResult result = CheckPlaceholderExpr(E); + if (result.isInvalid()) return StmtError(); + E = result.take(); + + CheckImplicitConversions(E); + + result = MaybeCreateExprWithCleanups(E); + if (result.isInvalid()) return StmtError(); + + return Owned(static_cast(result.take())); +} + +ExprResult +Sema::ActOnObjCForCollectionOperand(SourceLocation forLoc, Expr *collection) { + assert(collection); + + // Bail out early if we've got a type-dependent expression. + if (collection->isTypeDependent()) return Owned(collection); + + // Perform normal l-value conversion. + ExprResult result = DefaultFunctionArrayLvalueConversion(collection); + if (result.isInvalid()) + return ExprError(); + collection = result.take(); + + // The operand needs to have object-pointer type. + // TODO: should we do a contextual conversion? + const ObjCObjectPointerType *pointerType = + collection->getType()->getAs(); + if (!pointerType) + return Diag(forLoc, diag::err_collection_expr_type) + << collection->getType() << collection->getSourceRange(); + + // Check that the operand provides + // - countByEnumeratingWithState:objects:count: + const ObjCObjectType *objectType = pointerType->getObjectType(); + ObjCInterfaceDecl *iface = objectType->getInterface(); + + // If we have a forward-declared type, we can't do this check. + // Under ARC, it is an error not to have a forward-declared class. + if (iface && + RequireCompleteType(forLoc, QualType(objectType, 0), + getLangOpts().ObjCAutoRefCount + ? PDiag(diag::err_arc_collection_forward) + << collection->getSourceRange() + : PDiag(0))) { + // Otherwise, if we have any useful type information, check that + // the type declares the appropriate method. + } else if (iface || !objectType->qual_empty()) { + IdentifierInfo *selectorIdents[] = { + &Context.Idents.get("countByEnumeratingWithState"), + &Context.Idents.get("objects"), + &Context.Idents.get("count") + }; + Selector selector = Context.Selectors.getSelector(3, &selectorIdents[0]); + + ObjCMethodDecl *method = 0; + + // If there's an interface, look in both the public and private APIs. + if (iface) { + method = iface->lookupInstanceMethod(selector); + if (!method) method = LookupPrivateInstanceMethod(selector, iface); + } + + // Also check protocol qualifiers. + if (!method) + method = LookupMethodInQualifiedType(selector, pointerType, + /*instance*/ true); + + // If we didn't find it anywhere, give up. + if (!method) { + Diag(forLoc, diag::warn_collection_expr_type) + << collection->getType() << selector << collection->getSourceRange(); + } + + // TODO: check for an incompatible signature? + } + + // Wrap up any cleanups in the expression. + return Owned(MaybeCreateExprWithCleanups(collection)); +} + +StmtResult +Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc, + SourceLocation LParenLoc, + Stmt *First, Expr *Second, + SourceLocation RParenLoc, Stmt *Body) { + if (First) { + QualType FirstType; + if (DeclStmt *DS = dyn_cast(First)) { + if (!DS->isSingleDecl()) + return StmtError(Diag((*DS->decl_begin())->getLocation(), + diag::err_toomany_element_decls)); + + VarDecl *D = cast(DS->getSingleDecl()); + FirstType = D->getType(); + // C99 6.8.5p3: The declaration part of a 'for' statement shall only + // declare identifiers for objects having storage class 'auto' or + // 'register'. + if (!D->hasLocalStorage()) + return StmtError(Diag(D->getLocation(), + diag::err_non_variable_decl_in_for)); + } else { + Expr *FirstE = cast(First); + if (!FirstE->isTypeDependent() && !FirstE->isLValue()) + return StmtError(Diag(First->getLocStart(), + diag::err_selector_element_not_lvalue) + << First->getSourceRange()); + + FirstType = static_cast(First)->getType(); + } + if (!FirstType->isDependentType() && + !FirstType->isObjCObjectPointerType() && + !FirstType->isBlockPointerType()) + Diag(ForLoc, diag::err_selector_element_type) + << FirstType << First->getSourceRange(); + } + + return Owned(new (Context) ObjCForCollectionStmt(First, Second, Body, + ForLoc, RParenLoc)); +} + +namespace { + +enum BeginEndFunction { + BEF_begin, + BEF_end +}; + +/// Build a variable declaration for a for-range statement. +static VarDecl *BuildForRangeVarDecl(Sema &SemaRef, SourceLocation Loc, + QualType Type, const char *Name) { + DeclContext *DC = SemaRef.CurContext; + IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name); + TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc); + VarDecl *Decl = VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type, + TInfo, SC_Auto, SC_None); + Decl->setImplicit(); + return Decl; +} + +/// Finish building a variable declaration for a for-range statement. +/// \return true if an error occurs. +static bool FinishForRangeVarDecl(Sema &SemaRef, VarDecl *Decl, Expr *Init, + SourceLocation Loc, int diag) { + // Deduce the type for the iterator variable now rather than leaving it to + // AddInitializerToDecl, so we can produce a more suitable diagnostic. + TypeSourceInfo *InitTSI = 0; + if ((!isa(Init) && Init->getType()->isVoidType()) || + SemaRef.DeduceAutoType(Decl->getTypeSourceInfo(), Init, InitTSI) == + Sema::DAR_Failed) + SemaRef.Diag(Loc, diag) << Init->getType(); + if (!InitTSI) { + Decl->setInvalidDecl(); + return true; + } + Decl->setTypeSourceInfo(InitTSI); + Decl->setType(InitTSI->getType()); + + // In ARC, infer lifetime. + // FIXME: ARC may want to turn this into 'const __unsafe_unretained' if + // we're doing the equivalent of fast iteration. + if (SemaRef.getLangOpts().ObjCAutoRefCount && + SemaRef.inferObjCARCLifetime(Decl)) + Decl->setInvalidDecl(); + + SemaRef.AddInitializerToDecl(Decl, Init, /*DirectInit=*/false, + /*TypeMayContainAuto=*/false); + SemaRef.FinalizeDeclaration(Decl); + SemaRef.CurContext->addHiddenDecl(Decl); + return false; +} + +/// Produce a note indicating which begin/end function was implicitly called +/// by a C++0x for-range statement. This is often not obvious from the code, +/// nor from the diagnostics produced when analysing the implicit expressions +/// required in a for-range statement. +void NoteForRangeBeginEndFunction(Sema &SemaRef, Expr *E, + BeginEndFunction BEF) { + CallExpr *CE = dyn_cast(E); + if (!CE) + return; + FunctionDecl *D = dyn_cast(CE->getCalleeDecl()); + if (!D) + return; + SourceLocation Loc = D->getLocation(); + + std::string Description; + bool IsTemplate = false; + if (FunctionTemplateDecl *FunTmpl = D->getPrimaryTemplate()) { + Description = SemaRef.getTemplateArgumentBindingsText( + FunTmpl->getTemplateParameters(), *D->getTemplateSpecializationArgs()); + IsTemplate = true; + } + + SemaRef.Diag(Loc, diag::note_for_range_begin_end) + << BEF << IsTemplate << Description << E->getType(); +} + +/// Build a call to 'begin' or 'end' for a C++0x for-range statement. If the +/// given LookupResult is non-empty, it is assumed to describe a member which +/// will be invoked. Otherwise, the function will be found via argument +/// dependent lookup. +static ExprResult BuildForRangeBeginEndCall(Sema &SemaRef, Scope *S, + SourceLocation Loc, + VarDecl *Decl, + BeginEndFunction BEF, + const DeclarationNameInfo &NameInfo, + LookupResult &MemberLookup, + Expr *Range) { + ExprResult CallExpr; + if (!MemberLookup.empty()) { + ExprResult MemberRef = + SemaRef.BuildMemberReferenceExpr(Range, Range->getType(), Loc, + /*IsPtr=*/false, CXXScopeSpec(), + /*TemplateKWLoc=*/SourceLocation(), + /*FirstQualifierInScope=*/0, + MemberLookup, + /*TemplateArgs=*/0); + if (MemberRef.isInvalid()) + return ExprError(); + CallExpr = SemaRef.ActOnCallExpr(S, MemberRef.get(), Loc, MultiExprArg(), + Loc, 0); + if (CallExpr.isInvalid()) + return ExprError(); + } else { + UnresolvedSet<0> FoundNames; + // C++0x [stmt.ranged]p1: For the purposes of this name lookup, namespace + // std is an associated namespace. + UnresolvedLookupExpr *Fn = + UnresolvedLookupExpr::Create(SemaRef.Context, /*NamingClass=*/0, + NestedNameSpecifierLoc(), NameInfo, + /*NeedsADL=*/true, /*Overloaded=*/false, + FoundNames.begin(), FoundNames.end(), + /*LookInStdNamespace=*/true); + CallExpr = SemaRef.BuildOverloadedCallExpr(S, Fn, Fn, Loc, &Range, 1, Loc, + 0, /*AllowTypoCorrection=*/false); + if (CallExpr.isInvalid()) { + SemaRef.Diag(Range->getLocStart(), diag::note_for_range_type) + << Range->getType(); + return ExprError(); + } + } + if (FinishForRangeVarDecl(SemaRef, Decl, CallExpr.get(), Loc, + diag::err_for_range_iter_deduction_failure)) { + NoteForRangeBeginEndFunction(SemaRef, CallExpr.get(), BEF); + return ExprError(); + } + return CallExpr; +} + +} + +/// ActOnCXXForRangeStmt - Check and build a C++0x for-range statement. +/// +/// C++0x [stmt.ranged]: +/// A range-based for statement is equivalent to +/// +/// { +/// auto && __range = range-init; +/// for ( auto __begin = begin-expr, +/// __end = end-expr; +/// __begin != __end; +/// ++__begin ) { +/// for-range-declaration = *__begin; +/// statement +/// } +/// } +/// +/// The body of the loop is not available yet, since it cannot be analysed until +/// we have determined the type of the for-range-declaration. +StmtResult +Sema::ActOnCXXForRangeStmt(SourceLocation ForLoc, SourceLocation LParenLoc, + Stmt *First, SourceLocation ColonLoc, Expr *Range, + SourceLocation RParenLoc) { + if (!First || !Range) + return StmtError(); + + DeclStmt *DS = dyn_cast(First); + assert(DS && "first part of for range not a decl stmt"); + + if (!DS->isSingleDecl()) { + Diag(DS->getStartLoc(), diag::err_type_defined_in_for_range); + return StmtError(); + } + if (DS->getSingleDecl()->isInvalidDecl()) + return StmtError(); + + if (DiagnoseUnexpandedParameterPack(Range, UPPC_Expression)) + return StmtError(); + + // Build auto && __range = range-init + SourceLocation RangeLoc = Range->getLocStart(); + VarDecl *RangeVar = BuildForRangeVarDecl(*this, RangeLoc, + Context.getAutoRRefDeductType(), + "__range"); + if (FinishForRangeVarDecl(*this, RangeVar, Range, RangeLoc, + diag::err_for_range_deduction_failure)) + return StmtError(); + + // Claim the type doesn't contain auto: we've already done the checking. + DeclGroupPtrTy RangeGroup = + BuildDeclaratorGroup((Decl**)&RangeVar, 1, /*TypeMayContainAuto=*/false); + StmtResult RangeDecl = ActOnDeclStmt(RangeGroup, RangeLoc, RangeLoc); + if (RangeDecl.isInvalid()) + return StmtError(); + + return BuildCXXForRangeStmt(ForLoc, ColonLoc, RangeDecl.get(), + /*BeginEndDecl=*/0, /*Cond=*/0, /*Inc=*/0, DS, + RParenLoc); +} + +/// BuildCXXForRangeStmt - Build or instantiate a C++0x for-range statement. +StmtResult +Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc, + Stmt *RangeDecl, Stmt *BeginEnd, Expr *Cond, + Expr *Inc, Stmt *LoopVarDecl, + SourceLocation RParenLoc) { + Scope *S = getCurScope(); + + DeclStmt *RangeDS = cast(RangeDecl); + VarDecl *RangeVar = cast(RangeDS->getSingleDecl()); + QualType RangeVarType = RangeVar->getType(); + + DeclStmt *LoopVarDS = cast(LoopVarDecl); + VarDecl *LoopVar = cast(LoopVarDS->getSingleDecl()); + + StmtResult BeginEndDecl = BeginEnd; + ExprResult NotEqExpr = Cond, IncrExpr = Inc; + + if (!BeginEndDecl.get() && !RangeVarType->isDependentType()) { + SourceLocation RangeLoc = RangeVar->getLocation(); + + const QualType RangeVarNonRefType = RangeVarType.getNonReferenceType(); + + ExprResult BeginRangeRef = BuildDeclRefExpr(RangeVar, RangeVarNonRefType, + VK_LValue, ColonLoc); + if (BeginRangeRef.isInvalid()) + return StmtError(); + + ExprResult EndRangeRef = BuildDeclRefExpr(RangeVar, RangeVarNonRefType, + VK_LValue, ColonLoc); + if (EndRangeRef.isInvalid()) + return StmtError(); + + QualType AutoType = Context.getAutoDeductType(); + Expr *Range = RangeVar->getInit(); + if (!Range) + return StmtError(); + QualType RangeType = Range->getType(); + + if (RequireCompleteType(RangeLoc, RangeType, + PDiag(diag::err_for_range_incomplete_type))) + return StmtError(); + + // Build auto __begin = begin-expr, __end = end-expr. + VarDecl *BeginVar = BuildForRangeVarDecl(*this, ColonLoc, AutoType, + "__begin"); + VarDecl *EndVar = BuildForRangeVarDecl(*this, ColonLoc, AutoType, + "__end"); + + // Build begin-expr and end-expr and attach to __begin and __end variables. + ExprResult BeginExpr, EndExpr; + if (const ArrayType *UnqAT = RangeType->getAsArrayTypeUnsafe()) { + // - if _RangeT is an array type, begin-expr and end-expr are __range and + // __range + __bound, respectively, where __bound is the array bound. If + // _RangeT is an array of unknown size or an array of incomplete type, + // the program is ill-formed; + + // begin-expr is __range. + BeginExpr = BeginRangeRef; + if (FinishForRangeVarDecl(*this, BeginVar, BeginRangeRef.get(), ColonLoc, + diag::err_for_range_iter_deduction_failure)) { + NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin); + return StmtError(); + } + + // Find the array bound. + ExprResult BoundExpr; + if (const ConstantArrayType *CAT = dyn_cast(UnqAT)) + BoundExpr = Owned(IntegerLiteral::Create(Context, CAT->getSize(), + Context.getPointerDiffType(), + RangeLoc)); + else if (const VariableArrayType *VAT = + dyn_cast(UnqAT)) + BoundExpr = VAT->getSizeExpr(); + else { + // Can't be a DependentSizedArrayType or an IncompleteArrayType since + // UnqAT is not incomplete and Range is not type-dependent. + llvm_unreachable("Unexpected array type in for-range"); + } + + // end-expr is __range + __bound. + EndExpr = ActOnBinOp(S, ColonLoc, tok::plus, EndRangeRef.get(), + BoundExpr.get()); + if (EndExpr.isInvalid()) + return StmtError(); + if (FinishForRangeVarDecl(*this, EndVar, EndExpr.get(), ColonLoc, + diag::err_for_range_iter_deduction_failure)) { + NoteForRangeBeginEndFunction(*this, EndExpr.get(), BEF_end); + return StmtError(); + } + } else { + DeclarationNameInfo BeginNameInfo(&PP.getIdentifierTable().get("begin"), + ColonLoc); + DeclarationNameInfo EndNameInfo(&PP.getIdentifierTable().get("end"), + ColonLoc); + + LookupResult BeginMemberLookup(*this, BeginNameInfo, LookupMemberName); + LookupResult EndMemberLookup(*this, EndNameInfo, LookupMemberName); + + if (CXXRecordDecl *D = RangeType->getAsCXXRecordDecl()) { + // - if _RangeT is a class type, the unqualified-ids begin and end are + // looked up in the scope of class _RangeT as if by class member access + // lookup (3.4.5), and if either (or both) finds at least one + // declaration, begin-expr and end-expr are __range.begin() and + // __range.end(), respectively; + LookupQualifiedName(BeginMemberLookup, D); + LookupQualifiedName(EndMemberLookup, D); + + if (BeginMemberLookup.empty() != EndMemberLookup.empty()) { + Diag(ColonLoc, diag::err_for_range_member_begin_end_mismatch) + << RangeType << BeginMemberLookup.empty(); + return StmtError(); + } + } else { + // - otherwise, begin-expr and end-expr are begin(__range) and + // end(__range), respectively, where begin and end are looked up with + // argument-dependent lookup (3.4.2). For the purposes of this name + // lookup, namespace std is an associated namespace. + } + + BeginExpr = BuildForRangeBeginEndCall(*this, S, ColonLoc, BeginVar, + BEF_begin, BeginNameInfo, + BeginMemberLookup, + BeginRangeRef.get()); + if (BeginExpr.isInvalid()) + return StmtError(); + + EndExpr = BuildForRangeBeginEndCall(*this, S, ColonLoc, EndVar, + BEF_end, EndNameInfo, + EndMemberLookup, EndRangeRef.get()); + if (EndExpr.isInvalid()) + return StmtError(); + } + + // C++0x [decl.spec.auto]p6: BeginType and EndType must be the same. + QualType BeginType = BeginVar->getType(), EndType = EndVar->getType(); + if (!Context.hasSameType(BeginType, EndType)) { + Diag(RangeLoc, diag::err_for_range_begin_end_types_differ) + << BeginType << EndType; + NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin); + NoteForRangeBeginEndFunction(*this, EndExpr.get(), BEF_end); + } + + Decl *BeginEndDecls[] = { BeginVar, EndVar }; + // Claim the type doesn't contain auto: we've already done the checking. + DeclGroupPtrTy BeginEndGroup = + BuildDeclaratorGroup(BeginEndDecls, 2, /*TypeMayContainAuto=*/false); + BeginEndDecl = ActOnDeclStmt(BeginEndGroup, ColonLoc, ColonLoc); + + const QualType BeginRefNonRefType = BeginType.getNonReferenceType(); + ExprResult BeginRef = BuildDeclRefExpr(BeginVar, BeginRefNonRefType, + VK_LValue, ColonLoc); + if (BeginRef.isInvalid()) + return StmtError(); + + ExprResult EndRef = BuildDeclRefExpr(EndVar, EndType.getNonReferenceType(), + VK_LValue, ColonLoc); + if (EndRef.isInvalid()) + return StmtError(); + + // Build and check __begin != __end expression. + NotEqExpr = ActOnBinOp(S, ColonLoc, tok::exclaimequal, + BeginRef.get(), EndRef.get()); + NotEqExpr = ActOnBooleanCondition(S, ColonLoc, NotEqExpr.get()); + NotEqExpr = ActOnFinishFullExpr(NotEqExpr.get()); + if (NotEqExpr.isInvalid()) { + NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin); + if (!Context.hasSameType(BeginType, EndType)) + NoteForRangeBeginEndFunction(*this, EndExpr.get(), BEF_end); + return StmtError(); + } + + // Build and check ++__begin expression. + BeginRef = BuildDeclRefExpr(BeginVar, BeginRefNonRefType, + VK_LValue, ColonLoc); + if (BeginRef.isInvalid()) + return StmtError(); + + IncrExpr = ActOnUnaryOp(S, ColonLoc, tok::plusplus, BeginRef.get()); + IncrExpr = ActOnFinishFullExpr(IncrExpr.get()); + if (IncrExpr.isInvalid()) { + NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin); + return StmtError(); + } + + // Build and check *__begin expression. + BeginRef = BuildDeclRefExpr(BeginVar, BeginRefNonRefType, + VK_LValue, ColonLoc); + if (BeginRef.isInvalid()) + return StmtError(); + + ExprResult DerefExpr = ActOnUnaryOp(S, ColonLoc, tok::star, BeginRef.get()); + if (DerefExpr.isInvalid()) { + NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin); + return StmtError(); + } + + // Attach *__begin as initializer for VD. + if (!LoopVar->isInvalidDecl()) { + AddInitializerToDecl(LoopVar, DerefExpr.get(), /*DirectInit=*/false, + /*TypeMayContainAuto=*/true); + if (LoopVar->isInvalidDecl()) + NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin); + } + } else { + // The range is implicitly used as a placeholder when it is dependent. + RangeVar->setUsed(); + } + + return Owned(new (Context) CXXForRangeStmt(RangeDS, + cast_or_null(BeginEndDecl.get()), + NotEqExpr.take(), IncrExpr.take(), + LoopVarDS, /*Body=*/0, ForLoc, + ColonLoc, RParenLoc)); +} + +/// FinishCXXForRangeStmt - Attach the body to a C++0x for-range statement. +/// This is a separate step from ActOnCXXForRangeStmt because analysis of the +/// body cannot be performed until after the type of the range variable is +/// determined. +StmtResult Sema::FinishCXXForRangeStmt(Stmt *S, Stmt *B) { + if (!S || !B) + return StmtError(); + + CXXForRangeStmt *ForStmt = cast(S); + ForStmt->setBody(B); + + DiagnoseEmptyStmtBody(ForStmt->getRParenLoc(), B, + diag::warn_empty_range_based_for_body); + + return S; +} + +StmtResult Sema::ActOnGotoStmt(SourceLocation GotoLoc, + SourceLocation LabelLoc, + LabelDecl *TheDecl) { + getCurFunction()->setHasBranchIntoScope(); + TheDecl->setUsed(); + return Owned(new (Context) GotoStmt(TheDecl, GotoLoc, LabelLoc)); +} + +StmtResult +Sema::ActOnIndirectGotoStmt(SourceLocation GotoLoc, SourceLocation StarLoc, + Expr *E) { + // Convert operand to void* + if (!E->isTypeDependent()) { + QualType ETy = E->getType(); + QualType DestTy = Context.getPointerType(Context.VoidTy.withConst()); + ExprResult ExprRes = Owned(E); + AssignConvertType ConvTy = + CheckSingleAssignmentConstraints(DestTy, ExprRes); + if (ExprRes.isInvalid()) + return StmtError(); + E = ExprRes.take(); + if (DiagnoseAssignmentResult(ConvTy, StarLoc, DestTy, ETy, E, AA_Passing)) + return StmtError(); + E = MaybeCreateExprWithCleanups(E); + } + + getCurFunction()->setHasIndirectGoto(); + + return Owned(new (Context) IndirectGotoStmt(GotoLoc, StarLoc, E)); +} + +StmtResult +Sema::ActOnContinueStmt(SourceLocation ContinueLoc, Scope *CurScope) { + Scope *S = CurScope->getContinueParent(); + if (!S) { + // C99 6.8.6.2p1: A break shall appear only in or as a loop body. + return StmtError(Diag(ContinueLoc, diag::err_continue_not_in_loop)); + } + + return Owned(new (Context) ContinueStmt(ContinueLoc)); +} + +StmtResult +Sema::ActOnBreakStmt(SourceLocation BreakLoc, Scope *CurScope) { + Scope *S = CurScope->getBreakParent(); + if (!S) { + // C99 6.8.6.3p1: A break shall appear only in or as a switch/loop body. + return StmtError(Diag(BreakLoc, diag::err_break_not_in_loop_or_switch)); + } + + return Owned(new (Context) BreakStmt(BreakLoc)); +} + +/// \brief Determine whether the given expression is a candidate for +/// copy elision in either a return statement or a throw expression. +/// +/// \param ReturnType If we're determining the copy elision candidate for +/// a return statement, this is the return type of the function. If we're +/// determining the copy elision candidate for a throw expression, this will +/// be a NULL type. +/// +/// \param E The expression being returned from the function or block, or +/// being thrown. +/// +/// \param AllowFunctionParameter Whether we allow function parameters to +/// be considered NRVO candidates. C++ prohibits this for NRVO itself, but +/// we re-use this logic to determine whether we should try to move as part of +/// a return or throw (which does allow function parameters). +/// +/// \returns The NRVO candidate variable, if the return statement may use the +/// NRVO, or NULL if there is no such candidate. +const VarDecl *Sema::getCopyElisionCandidate(QualType ReturnType, + Expr *E, + bool AllowFunctionParameter) { + QualType ExprType = E->getType(); + // - in a return statement in a function with ... + // ... a class return type ... + if (!ReturnType.isNull()) { + if (!ReturnType->isRecordType()) + return 0; + // ... the same cv-unqualified type as the function return type ... + if (!Context.hasSameUnqualifiedType(ReturnType, ExprType)) + return 0; + } + + // ... the expression is the name of a non-volatile automatic object + // (other than a function or catch-clause parameter)) ... + const DeclRefExpr *DR = dyn_cast(E->IgnoreParens()); + if (!DR) + return 0; + const VarDecl *VD = dyn_cast(DR->getDecl()); + if (!VD) + return 0; + + // ...object (other than a function or catch-clause parameter)... + if (VD->getKind() != Decl::Var && + !(AllowFunctionParameter && VD->getKind() == Decl::ParmVar)) + return 0; + if (VD->isExceptionVariable()) return 0; + + // ...automatic... + if (!VD->hasLocalStorage()) return 0; + + // ...non-volatile... + if (VD->getType().isVolatileQualified()) return 0; + if (VD->getType()->isReferenceType()) return 0; + + // __block variables can't be allocated in a way that permits NRVO. + if (VD->hasAttr()) return 0; + + // Variables with higher required alignment than their type's ABI + // alignment cannot use NRVO. + if (VD->hasAttr() && + Context.getDeclAlign(VD) > Context.getTypeAlignInChars(VD->getType())) + return 0; + + return VD; +} + +/// \brief Perform the initialization of a potentially-movable value, which +/// is the result of return value. +/// +/// This routine implements C++0x [class.copy]p33, which attempts to treat +/// returned lvalues as rvalues in certain cases (to prefer move construction), +/// then falls back to treating them as lvalues if that failed. +ExprResult +Sema::PerformMoveOrCopyInitialization(const InitializedEntity &Entity, + const VarDecl *NRVOCandidate, + QualType ResultType, + Expr *Value, + bool AllowNRVO) { + // C++0x [class.copy]p33: + // When the criteria for elision of a copy operation are met or would + // be met save for the fact that the source object is a function + // parameter, and the object to be copied is designated by an lvalue, + // overload resolution to select the constructor for the copy is first + // performed as if the object were designated by an rvalue. + ExprResult Res = ExprError(); + if (AllowNRVO && + (NRVOCandidate || getCopyElisionCandidate(ResultType, Value, true))) { + ImplicitCastExpr AsRvalue(ImplicitCastExpr::OnStack, + Value->getType(), CK_LValueToRValue, + Value, VK_XValue); + + Expr *InitExpr = &AsRvalue; + InitializationKind Kind + = InitializationKind::CreateCopy(Value->getLocStart(), + Value->getLocStart()); + InitializationSequence Seq(*this, Entity, Kind, &InitExpr, 1); + + // [...] If overload resolution fails, or if the type of the first + // parameter of the selected constructor is not an rvalue reference + // to the object's type (possibly cv-qualified), overload resolution + // is performed again, considering the object as an lvalue. + if (Seq) { + for (InitializationSequence::step_iterator Step = Seq.step_begin(), + StepEnd = Seq.step_end(); + Step != StepEnd; ++Step) { + if (Step->Kind != InitializationSequence::SK_ConstructorInitialization) + continue; + + CXXConstructorDecl *Constructor + = cast(Step->Function.Function); + + const RValueReferenceType *RRefType + = Constructor->getParamDecl(0)->getType() + ->getAs(); + + // If we don't meet the criteria, break out now. + if (!RRefType || + !Context.hasSameUnqualifiedType(RRefType->getPointeeType(), + Context.getTypeDeclType(Constructor->getParent()))) + break; + + // Promote "AsRvalue" to the heap, since we now need this + // expression node to persist. + Value = ImplicitCastExpr::Create(Context, Value->getType(), + CK_LValueToRValue, Value, 0, + VK_XValue); + + // Complete type-checking the initialization of the return type + // using the constructor we found. + Res = Seq.Perform(*this, Entity, Kind, MultiExprArg(&Value, 1)); + } + } + } + + // Either we didn't meet the criteria for treating an lvalue as an rvalue, + // above, or overload resolution failed. Either way, we need to try + // (again) now with the return value expression as written. + if (Res.isInvalid()) + Res = PerformCopyInitialization(Entity, SourceLocation(), Value); + + return Res; +} + +/// ActOnCapScopeReturnStmt - Utility routine to type-check return statements +/// for capturing scopes. +/// +StmtResult +Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { + // If this is the first return we've seen, infer the return type. + // [expr.prim.lambda]p4 in C++11; block literals follow a superset of those + // rules which allows multiple return statements. + CapturingScopeInfo *CurCap = cast(getCurFunction()); + if (CurCap->HasImplicitReturnType) { + QualType ReturnT; + if (RetValExp && !isa(RetValExp)) { + ExprResult Result = DefaultFunctionArrayLvalueConversion(RetValExp); + if (Result.isInvalid()) + return StmtError(); + RetValExp = Result.take(); + + if (!RetValExp->isTypeDependent()) + ReturnT = RetValExp->getType(); + else + ReturnT = Context.DependentTy; + } else { + if (RetValExp) { + // C++11 [expr.lambda.prim]p4 bans inferring the result from an + // initializer list, because it is not an expression (even + // though we represent it as one). We still deduce 'void'. + Diag(ReturnLoc, diag::err_lambda_return_init_list) + << RetValExp->getSourceRange(); + } + + ReturnT = Context.VoidTy; + } + // We require the return types to strictly match here. + if (!CurCap->ReturnType.isNull() && + !CurCap->ReturnType->isDependentType() && + !ReturnT->isDependentType() && + !Context.hasSameType(ReturnT, CurCap->ReturnType)) { + Diag(ReturnLoc, diag::err_typecheck_missing_return_type_incompatible) + << ReturnT << CurCap->ReturnType + << (getCurLambda() != 0); + return StmtError(); + } + CurCap->ReturnType = ReturnT; + } + QualType FnRetType = CurCap->ReturnType; + assert(!FnRetType.isNull()); + + if (BlockScopeInfo *CurBlock = dyn_cast(CurCap)) { + if (CurBlock->FunctionType->getAs()->getNoReturnAttr()) { + Diag(ReturnLoc, diag::err_noreturn_block_has_return_expr); + return StmtError(); + } + } else { + LambdaScopeInfo *LSI = cast(CurCap); + if (LSI->CallOperator->getType()->getAs()->getNoReturnAttr()){ + Diag(ReturnLoc, diag::err_noreturn_lambda_has_return_expr); + return StmtError(); + } + } + + // Otherwise, verify that this result type matches the previous one. We are + // pickier with blocks than for normal functions because we don't have GCC + // compatibility to worry about here. + const VarDecl *NRVOCandidate = 0; + if (FnRetType->isDependentType()) { + // Delay processing for now. TODO: there are lots of dependent + // types we can conclusively prove aren't void. + } else if (FnRetType->isVoidType()) { + if (RetValExp && !isa(RetValExp) && + !(getLangOpts().CPlusPlus && + (RetValExp->isTypeDependent() || + RetValExp->getType()->isVoidType()))) { + if (!getLangOpts().CPlusPlus && + RetValExp->getType()->isVoidType()) + Diag(ReturnLoc, diag::ext_return_has_void_expr) << "literal" << 2; + else { + Diag(ReturnLoc, diag::err_return_block_has_expr); + RetValExp = 0; + } + } + } else if (!RetValExp) { + return StmtError(Diag(ReturnLoc, diag::err_block_return_missing_expr)); + } else if (!RetValExp->isTypeDependent()) { + // we have a non-void block with an expression, continue checking + + // C99 6.8.6.4p3(136): The return statement is not an assignment. The + // overlap restriction of subclause 6.5.16.1 does not apply to the case of + // function return. + + // In C++ the return statement is handled via a copy initialization. + // the C version of which boils down to CheckSingleAssignmentConstraints. + NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, false); + InitializedEntity Entity = InitializedEntity::InitializeResult(ReturnLoc, + FnRetType, + NRVOCandidate != 0); + ExprResult Res = PerformMoveOrCopyInitialization(Entity, NRVOCandidate, + FnRetType, RetValExp); + if (Res.isInvalid()) { + // FIXME: Cleanup temporaries here, anyway? + return StmtError(); + } + RetValExp = Res.take(); + CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc); + } + + if (RetValExp) { + CheckImplicitConversions(RetValExp, ReturnLoc); + RetValExp = MaybeCreateExprWithCleanups(RetValExp); + } + ReturnStmt *Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, + NRVOCandidate); + + // If we need to check for the named return value optimization, save the + // return statement in our scope for later processing. + if (getLangOpts().CPlusPlus && FnRetType->isRecordType() && + !CurContext->isDependentContext()) + FunctionScopes.back()->Returns.push_back(Result); + + return Owned(Result); +} + +StmtResult +Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { + // Check for unexpanded parameter packs. + if (RetValExp && DiagnoseUnexpandedParameterPack(RetValExp)) + return StmtError(); + + if (isa(getCurFunction())) + return ActOnCapScopeReturnStmt(ReturnLoc, RetValExp); + + QualType FnRetType; + QualType RelatedRetType; + if (const FunctionDecl *FD = getCurFunctionDecl()) { + FnRetType = FD->getResultType(); + if (FD->hasAttr() || + FD->getType()->getAs()->getNoReturnAttr()) + Diag(ReturnLoc, diag::warn_noreturn_function_has_return_expr) + << FD->getDeclName(); + } else if (ObjCMethodDecl *MD = getCurMethodDecl()) { + FnRetType = MD->getResultType(); + if (MD->hasRelatedResultType() && MD->getClassInterface()) { + // In the implementation of a method with a related return type, the + // type used to type-check the validity of return statements within the + // method body is a pointer to the type of the class being implemented. + RelatedRetType = Context.getObjCInterfaceType(MD->getClassInterface()); + RelatedRetType = Context.getObjCObjectPointerType(RelatedRetType); + } + } else // If we don't have a function/method context, bail. + return StmtError(); + + ReturnStmt *Result = 0; + if (FnRetType->isVoidType()) { + if (RetValExp) { + if (isa(RetValExp)) { + // We simply never allow init lists as the return value of void + // functions. This is compatible because this was never allowed before, + // so there's no legacy code to deal with. + NamedDecl *CurDecl = getCurFunctionOrMethodDecl(); + int FunctionKind = 0; + if (isa(CurDecl)) + FunctionKind = 1; + else if (isa(CurDecl)) + FunctionKind = 2; + else if (isa(CurDecl)) + FunctionKind = 3; + + Diag(ReturnLoc, diag::err_return_init_list) + << CurDecl->getDeclName() << FunctionKind + << RetValExp->getSourceRange(); + + // Drop the expression. + RetValExp = 0; + } else if (!RetValExp->isTypeDependent()) { + // C99 6.8.6.4p1 (ext_ since GCC warns) + unsigned D = diag::ext_return_has_expr; + if (RetValExp->getType()->isVoidType()) + D = diag::ext_return_has_void_expr; + else { + ExprResult Result = Owned(RetValExp); + Result = IgnoredValueConversions(Result.take()); + if (Result.isInvalid()) + return StmtError(); + RetValExp = Result.take(); + RetValExp = ImpCastExprToType(RetValExp, + Context.VoidTy, CK_ToVoid).take(); + } + + // return (some void expression); is legal in C++. + if (D != diag::ext_return_has_void_expr || + !getLangOpts().CPlusPlus) { + NamedDecl *CurDecl = getCurFunctionOrMethodDecl(); + + int FunctionKind = 0; + if (isa(CurDecl)) + FunctionKind = 1; + else if (isa(CurDecl)) + FunctionKind = 2; + else if (isa(CurDecl)) + FunctionKind = 3; + + Diag(ReturnLoc, D) + << CurDecl->getDeclName() << FunctionKind + << RetValExp->getSourceRange(); + } + } + + if (RetValExp) { + CheckImplicitConversions(RetValExp, ReturnLoc); + RetValExp = MaybeCreateExprWithCleanups(RetValExp); + } + } + + Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, 0); + } else if (!RetValExp && !FnRetType->isDependentType()) { + unsigned DiagID = diag::warn_return_missing_expr; // C90 6.6.6.4p4 + // C99 6.8.6.4p1 (ext_ since GCC warns) + if (getLangOpts().C99) DiagID = diag::ext_return_missing_expr; + + if (FunctionDecl *FD = getCurFunctionDecl()) + Diag(ReturnLoc, DiagID) << FD->getIdentifier() << 0/*fn*/; + else + Diag(ReturnLoc, DiagID) << getCurMethodDecl()->getDeclName() << 1/*meth*/; + Result = new (Context) ReturnStmt(ReturnLoc); + } else { + const VarDecl *NRVOCandidate = 0; + if (!FnRetType->isDependentType() && !RetValExp->isTypeDependent()) { + // we have a non-void function with an expression, continue checking + + if (!RelatedRetType.isNull()) { + // If we have a related result type, perform an extra conversion here. + // FIXME: The diagnostics here don't really describe what is happening. + InitializedEntity Entity = + InitializedEntity::InitializeTemporary(RelatedRetType); + + ExprResult Res = PerformCopyInitialization(Entity, SourceLocation(), + RetValExp); + if (Res.isInvalid()) { + // FIXME: Cleanup temporaries here, anyway? + return StmtError(); + } + RetValExp = Res.takeAs(); + } + + // C99 6.8.6.4p3(136): The return statement is not an assignment. The + // overlap restriction of subclause 6.5.16.1 does not apply to the case of + // function return. + + // In C++ the return statement is handled via a copy initialization, + // the C version of which boils down to CheckSingleAssignmentConstraints. + NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, false); + InitializedEntity Entity = InitializedEntity::InitializeResult(ReturnLoc, + FnRetType, + NRVOCandidate != 0); + ExprResult Res = PerformMoveOrCopyInitialization(Entity, NRVOCandidate, + FnRetType, RetValExp); + if (Res.isInvalid()) { + // FIXME: Cleanup temporaries here, anyway? + return StmtError(); + } + + RetValExp = Res.takeAs(); + if (RetValExp) + CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc); + } + + if (RetValExp) { + CheckImplicitConversions(RetValExp, ReturnLoc); + RetValExp = MaybeCreateExprWithCleanups(RetValExp); + } + Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, NRVOCandidate); + } + + // If we need to check for the named return value optimization, save the + // return statement in our scope for later processing. + if (getLangOpts().CPlusPlus && FnRetType->isRecordType() && + !CurContext->isDependentContext()) + FunctionScopes.back()->Returns.push_back(Result); + + return Owned(Result); +} + +/// CheckAsmLValue - GNU C has an extremely ugly extension whereby they silently +/// ignore "noop" casts in places where an lvalue is required by an inline asm. +/// We emulate this behavior when -fheinous-gnu-extensions is specified, but +/// provide a strong guidance to not use it. +/// +/// This method checks to see if the argument is an acceptable l-value and +/// returns false if it is a case we can handle. +static bool CheckAsmLValue(const Expr *E, Sema &S) { + // Type dependent expressions will be checked during instantiation. + if (E->isTypeDependent()) + return false; + + if (E->isLValue()) + return false; // Cool, this is an lvalue. + + // Okay, this is not an lvalue, but perhaps it is the result of a cast that we + // are supposed to allow. + const Expr *E2 = E->IgnoreParenNoopCasts(S.Context); + if (E != E2 && E2->isLValue()) { + if (!S.getLangOpts().HeinousExtensions) + S.Diag(E2->getLocStart(), diag::err_invalid_asm_cast_lvalue) + << E->getSourceRange(); + else + S.Diag(E2->getLocStart(), diag::warn_invalid_asm_cast_lvalue) + << E->getSourceRange(); + // Accept, even if we emitted an error diagnostic. + return false; + } + + // None of the above, just randomly invalid non-lvalue. + return true; +} + +/// isOperandMentioned - Return true if the specified operand # is mentioned +/// anywhere in the decomposed asm string. +static bool isOperandMentioned(unsigned OpNo, + ArrayRef AsmStrPieces) { + for (unsigned p = 0, e = AsmStrPieces.size(); p != e; ++p) { + const AsmStmt::AsmStringPiece &Piece = AsmStrPieces[p]; + if (!Piece.isOperand()) continue; + + // If this is a reference to the input and if the input was the smaller + // one, then we have to reject this asm. + if (Piece.getOperandNo() == OpNo) + return true; + } + + return false; +} + +StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple, + bool IsVolatile, unsigned NumOutputs, + unsigned NumInputs, IdentifierInfo **Names, + MultiExprArg constraints, MultiExprArg exprs, + Expr *asmString, MultiExprArg clobbers, + SourceLocation RParenLoc, bool MSAsm) { + unsigned NumClobbers = clobbers.size(); + StringLiteral **Constraints = + reinterpret_cast(constraints.get()); + Expr **Exprs = exprs.get(); + StringLiteral *AsmString = cast(asmString); + StringLiteral **Clobbers = reinterpret_cast(clobbers.get()); + + SmallVector OutputConstraintInfos; + + // The parser verifies that there is a string literal here. + if (!AsmString->isAscii()) + return StmtError(Diag(AsmString->getLocStart(),diag::err_asm_wide_character) + << AsmString->getSourceRange()); + + for (unsigned i = 0; i != NumOutputs; i++) { + StringLiteral *Literal = Constraints[i]; + if (!Literal->isAscii()) + return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) + << Literal->getSourceRange()); + + StringRef OutputName; + if (Names[i]) + OutputName = Names[i]->getName(); + + TargetInfo::ConstraintInfo Info(Literal->getString(), OutputName); + if (!Context.getTargetInfo().validateOutputConstraint(Info)) + return StmtError(Diag(Literal->getLocStart(), + diag::err_asm_invalid_output_constraint) + << Info.getConstraintStr()); + + // Check that the output exprs are valid lvalues. + Expr *OutputExpr = Exprs[i]; + if (CheckAsmLValue(OutputExpr, *this)) { + return StmtError(Diag(OutputExpr->getLocStart(), + diag::err_asm_invalid_lvalue_in_output) + << OutputExpr->getSourceRange()); + } + + OutputConstraintInfos.push_back(Info); + } + + SmallVector InputConstraintInfos; + + for (unsigned i = NumOutputs, e = NumOutputs + NumInputs; i != e; i++) { + StringLiteral *Literal = Constraints[i]; + if (!Literal->isAscii()) + return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) + << Literal->getSourceRange()); + + StringRef InputName; + if (Names[i]) + InputName = Names[i]->getName(); + + TargetInfo::ConstraintInfo Info(Literal->getString(), InputName); + if (!Context.getTargetInfo().validateInputConstraint(OutputConstraintInfos.data(), + NumOutputs, Info)) { + return StmtError(Diag(Literal->getLocStart(), + diag::err_asm_invalid_input_constraint) + << Info.getConstraintStr()); + } + + Expr *InputExpr = Exprs[i]; + + // Only allow void types for memory constraints. + if (Info.allowsMemory() && !Info.allowsRegister()) { + if (CheckAsmLValue(InputExpr, *this)) + return StmtError(Diag(InputExpr->getLocStart(), + diag::err_asm_invalid_lvalue_in_input) + << Info.getConstraintStr() + << InputExpr->getSourceRange()); + } + + if (Info.allowsRegister()) { + if (InputExpr->getType()->isVoidType()) { + return StmtError(Diag(InputExpr->getLocStart(), + diag::err_asm_invalid_type_in_input) + << InputExpr->getType() << Info.getConstraintStr() + << InputExpr->getSourceRange()); + } + } + + ExprResult Result = DefaultFunctionArrayLvalueConversion(Exprs[i]); + if (Result.isInvalid()) + return StmtError(); + + Exprs[i] = Result.take(); + InputConstraintInfos.push_back(Info); + } + + // Check that the clobbers are valid. + for (unsigned i = 0; i != NumClobbers; i++) { + StringLiteral *Literal = Clobbers[i]; + if (!Literal->isAscii()) + return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) + << Literal->getSourceRange()); + + StringRef Clobber = Literal->getString(); + + if (!Context.getTargetInfo().isValidClobber(Clobber)) + return StmtError(Diag(Literal->getLocStart(), + diag::err_asm_unknown_register_name) << Clobber); + } + + AsmStmt *NS = + new (Context) AsmStmt(Context, AsmLoc, IsSimple, IsVolatile, MSAsm, + NumOutputs, NumInputs, Names, Constraints, Exprs, + AsmString, NumClobbers, Clobbers, RParenLoc); + // Validate the asm string, ensuring it makes sense given the operands we + // have. + SmallVector Pieces; + unsigned DiagOffs; + if (unsigned DiagID = NS->AnalyzeAsmString(Pieces, Context, DiagOffs)) { + Diag(getLocationOfStringLiteralByte(AsmString, DiagOffs), DiagID) + << AsmString->getSourceRange(); + return StmtError(); + } + + // Validate tied input operands for type mismatches. + for (unsigned i = 0, e = InputConstraintInfos.size(); i != e; ++i) { + TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i]; + + // If this is a tied constraint, verify that the output and input have + // either exactly the same type, or that they are int/ptr operands with the + // same size (int/long, int*/long, are ok etc). + if (!Info.hasTiedOperand()) continue; + + unsigned TiedTo = Info.getTiedOperand(); + unsigned InputOpNo = i+NumOutputs; + Expr *OutputExpr = Exprs[TiedTo]; + Expr *InputExpr = Exprs[InputOpNo]; + + if (OutputExpr->isTypeDependent() || InputExpr->isTypeDependent()) + continue; + + QualType InTy = InputExpr->getType(); + QualType OutTy = OutputExpr->getType(); + if (Context.hasSameType(InTy, OutTy)) + continue; // All types can be tied to themselves. + + // Decide if the input and output are in the same domain (integer/ptr or + // floating point. + enum AsmDomain { + AD_Int, AD_FP, AD_Other + } InputDomain, OutputDomain; + + if (InTy->isIntegerType() || InTy->isPointerType()) + InputDomain = AD_Int; + else if (InTy->isRealFloatingType()) + InputDomain = AD_FP; + else + InputDomain = AD_Other; + + if (OutTy->isIntegerType() || OutTy->isPointerType()) + OutputDomain = AD_Int; + else if (OutTy->isRealFloatingType()) + OutputDomain = AD_FP; + else + OutputDomain = AD_Other; + + // They are ok if they are the same size and in the same domain. This + // allows tying things like: + // void* to int* + // void* to int if they are the same size. + // double to long double if they are the same size. + // + uint64_t OutSize = Context.getTypeSize(OutTy); + uint64_t InSize = Context.getTypeSize(InTy); + if (OutSize == InSize && InputDomain == OutputDomain && + InputDomain != AD_Other) + continue; + + // If the smaller input/output operand is not mentioned in the asm string, + // then we can promote the smaller one to a larger input and the asm string + // won't notice. + bool SmallerValueMentioned = false; + + // If this is a reference to the input and if the input was the smaller + // one, then we have to reject this asm. + if (isOperandMentioned(InputOpNo, Pieces)) { + // This is a use in the asm string of the smaller operand. Since we + // codegen this by promoting to a wider value, the asm will get printed + // "wrong". + SmallerValueMentioned |= InSize < OutSize; + } + if (isOperandMentioned(TiedTo, Pieces)) { + // If this is a reference to the output, and if the output is the larger + // value, then it's ok because we'll promote the input to the larger type. + SmallerValueMentioned |= OutSize < InSize; + } + + // If the smaller value wasn't mentioned in the asm string, and if the + // output was a register, just extend the shorter one to the size of the + // larger one. + if (!SmallerValueMentioned && InputDomain != AD_Other && + OutputConstraintInfos[TiedTo].allowsRegister()) + continue; + + // Either both of the operands were mentioned or the smaller one was + // mentioned. One more special case that we'll allow: if the tied input is + // integer, unmentioned, and is a constant, then we'll allow truncating it + // down to the size of the destination. + if (InputDomain == AD_Int && OutputDomain == AD_Int && + !isOperandMentioned(InputOpNo, Pieces) && + InputExpr->isEvaluatable(Context)) { + CastKind castKind = + (OutTy->isBooleanType() ? CK_IntegralToBoolean : CK_IntegralCast); + InputExpr = ImpCastExprToType(InputExpr, OutTy, castKind).take(); + Exprs[InputOpNo] = InputExpr; + NS->setInputExpr(i, InputExpr); + continue; + } + + Diag(InputExpr->getLocStart(), + diag::err_asm_tying_incompatible_types) + << InTy << OutTy << OutputExpr->getSourceRange() + << InputExpr->getSourceRange(); + return StmtError(); + } + + return Owned(NS); +} + +StmtResult +Sema::ActOnObjCAtCatchStmt(SourceLocation AtLoc, + 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)); +} + +StmtResult +Sema::ActOnObjCAtFinallyStmt(SourceLocation AtLoc, Stmt *Body) { + return Owned(new (Context) ObjCAtFinallyStmt(AtLoc, Body)); +} + +StmtResult +Sema::ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try, + MultiStmtArg CatchStmts, Stmt *Finally) { + if (!getLangOpts().ObjCExceptions) + Diag(AtLoc, diag::err_objc_exceptions_disabled) << "@try"; + + getCurFunction()->setHasBranchProtectedScope(); + unsigned NumCatchStmts = CatchStmts.size(); + return Owned(ObjCAtTryStmt::Create(Context, AtLoc, Try, + CatchStmts.release(), + NumCatchStmts, + Finally)); +} + +StmtResult Sema::BuildObjCAtThrowStmt(SourceLocation AtLoc, + Expr *Throw) { + if (Throw) { + Throw = MaybeCreateExprWithCleanups(Throw); + ExprResult Result = DefaultLvalueConversion(Throw); + if (Result.isInvalid()) + return StmtError(); + + Throw = Result.take(); + QualType ThrowType = Throw->getType(); + // Make sure the expression type is an ObjC pointer or "void *". + if (!ThrowType->isDependentType() && + !ThrowType->isObjCObjectPointerType()) { + const PointerType *PT = ThrowType->getAs(); + if (!PT || !PT->getPointeeType()->isVoidType()) + return StmtError(Diag(AtLoc, diag::error_objc_throw_expects_object) + << Throw->getType() << Throw->getSourceRange()); + } + } + + return Owned(new (Context) ObjCAtThrowStmt(AtLoc, Throw)); +} + +StmtResult +Sema::ActOnObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw, + Scope *CurScope) { + if (!getLangOpts().ObjCExceptions) + Diag(AtLoc, diag::err_objc_exceptions_disabled) << "@throw"; + + if (!Throw) { + // @throw without an expression designates a rethrow (which much occur + // in the context of an @catch clause). + Scope *AtCatchParent = CurScope; + while (AtCatchParent && !AtCatchParent->isAtCatchScope()) + AtCatchParent = AtCatchParent->getParent(); + if (!AtCatchParent) + return StmtError(Diag(AtLoc, diag::error_rethrow_used_outside_catch)); + } + + return BuildObjCAtThrowStmt(AtLoc, Throw); +} + +ExprResult +Sema::ActOnObjCAtSynchronizedOperand(SourceLocation atLoc, Expr *operand) { + ExprResult result = DefaultLvalueConversion(operand); + if (result.isInvalid()) + return ExprError(); + operand = result.take(); + + // Make sure the expression type is an ObjC pointer or "void *". + QualType type = operand->getType(); + if (!type->isDependentType() && + !type->isObjCObjectPointerType()) { + const PointerType *pointerType = type->getAs(); + if (!pointerType || !pointerType->getPointeeType()->isVoidType()) + return Diag(atLoc, diag::error_objc_synchronized_expects_object) + << type << operand->getSourceRange(); + } + + // The operand to @synchronized is a full-expression. + return MaybeCreateExprWithCleanups(operand); +} + +StmtResult +Sema::ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, Expr *SyncExpr, + Stmt *SyncBody) { + // We can't jump into or indirect-jump out of a @synchronized block. + getCurFunction()->setHasBranchProtectedScope(); + 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. +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), + HandlerBlock)); +} + +StmtResult +Sema::ActOnObjCAutoreleasePoolStmt(SourceLocation AtLoc, Stmt *Body) { + getCurFunction()->setHasBranchProtectedScope(); + return Owned(new (Context) ObjCAutoreleasePoolStmt(AtLoc, Body)); +} + +namespace { + +class TypeWithHandler { + QualType t; + CXXCatchStmt *stmt; +public: + TypeWithHandler(const QualType &type, CXXCatchStmt *statement) + : t(type), stmt(statement) {} + + // An arbitrary order is fine as long as it places identical + // types next to each other. + bool operator<(const TypeWithHandler &y) const { + if (t.getAsOpaquePtr() < y.t.getAsOpaquePtr()) + return true; + if (t.getAsOpaquePtr() > y.t.getAsOpaquePtr()) + return false; + else + return getTypeSpecStartLoc() < y.getTypeSpecStartLoc(); + } + + bool operator==(const TypeWithHandler& other) const { + return t == other.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. +StmtResult +Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, + MultiStmtArg RawHandlers) { + // Don't report an error if 'try' is used in system headers. + if (!getLangOpts().CXXExceptions && + !getSourceManager().isInSystemHeader(TryLoc)) + Diag(TryLoc, diag::err_exceptions_disabled) << "try"; + + unsigned NumHandlers = RawHandlers.size(); + assert(NumHandlers > 0 && + "The parser shouldn't call this if there are no handlers."); + Stmt **Handlers = RawHandlers.get(); + + SmallVector TypesWithHandlers; + + for (unsigned i = 0; i < NumHandlers; ++i) { + CXXCatchStmt *Handler = cast(Handlers[i]); + if (!Handler->getExceptionDecl()) { + if (i < NumHandlers - 1) + return StmtError(Diag(Handler->getLocStart(), + diag::err_early_catch_all)); + + continue; + } + + const QualType CaughtType = Handler->getCaughtType(); + const QualType CanonicalCaughtType = Context.getCanonicalType(CaughtType); + TypesWithHandlers.push_back(TypeWithHandler(CanonicalCaughtType, Handler)); + } + + // Detect handlers for the same type as an earlier one. + if (NumHandlers > 1) { + llvm::array_pod_sort(TypesWithHandlers.begin(), TypesWithHandlers.end()); + + TypeWithHandler prev = TypesWithHandlers[0]; + for (unsigned i = 1; i < TypesWithHandlers.size(); ++i) { + TypeWithHandler curr = TypesWithHandlers[i]; + + if (curr == prev) { + Diag(curr.getTypeSpecStartLoc(), + diag::warn_exception_caught_by_earlier_handler) + << curr.getCatchStmt()->getCaughtType().getAsString(); + Diag(prev.getTypeSpecStartLoc(), + diag::note_previous_exception_handler) + << prev.getCatchStmt()->getCaughtType().getAsString(); + } + + prev = curr; + } + } + + 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. + + return Owned(CXXTryStmt::Create(Context, TryLoc, TryBlock, + Handlers, NumHandlers)); +} + +StmtResult +Sema::ActOnSEHTryBlock(bool IsCXXTry, + SourceLocation TryLoc, + Stmt *TryBlock, + Stmt *Handler) { + assert(TryBlock && Handler); + + getCurFunction()->setHasBranchProtectedScope(); + + return Owned(SEHTryStmt::Create(Context,IsCXXTry,TryLoc,TryBlock,Handler)); +} + +StmtResult +Sema::ActOnSEHExceptBlock(SourceLocation Loc, + Expr *FilterExpr, + Stmt *Block) { + assert(FilterExpr && Block); + + if(!FilterExpr->getType()->isIntegerType()) { + return StmtError(Diag(FilterExpr->getExprLoc(), + diag::err_filter_expression_integral) + << FilterExpr->getType()); + } + + return Owned(SEHExceptStmt::Create(Context,Loc,FilterExpr,Block)); +} + +StmtResult +Sema::ActOnSEHFinallyBlock(SourceLocation Loc, + Stmt *Block) { + assert(Block); + return Owned(SEHFinallyStmt::Create(Context,Loc,Block)); +} + +StmtResult Sema::BuildMSDependentExistsStmt(SourceLocation KeywordLoc, + bool IsIfExists, + NestedNameSpecifierLoc QualifierLoc, + DeclarationNameInfo NameInfo, + Stmt *Nested) +{ + return new (Context) MSDependentExistsStmt(KeywordLoc, IsIfExists, + QualifierLoc, NameInfo, + cast(Nested)); +} + + +StmtResult Sema::ActOnMSDependentExistsStmt(SourceLocation KeywordLoc, + bool IsIfExists, + CXXScopeSpec &SS, + UnqualifiedId &Name, + Stmt *Nested) { + return BuildMSDependentExistsStmt(KeywordLoc, IsIfExists, + SS.getWithLocInContext(Context), + GetNameFromUnqualifiedId(Name), + Nested); +} diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp new file mode 100644 index 0000000..21c3297 --- /dev/null +++ b/clang/lib/Sema/SemaStmtAttr.cpp @@ -0,0 +1,48 @@ +//===--- SemaStmtAttr.cpp - Statement Attribute Handling ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements stmt-related attribute processing. +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/SemaInternal.h" +#include "TargetAttributesSema.h" +#include "clang/AST/ASTContext.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Sema/DelayedDiagnostic.h" +#include "clang/Sema/Lookup.h" +#include "llvm/ADT/StringExtras.h" +using namespace clang; +using namespace sema; + + +static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const AttributeList &A) { + switch (A.getKind()) { + default: + // if we're here, then we parsed an attribute, but didn't recognize it as a + // statement attribute => it is declaration attribute + S.Diag(A.getRange().getBegin(), diag::warn_attribute_invalid_on_stmt) << + A.getName()->getName(); + return 0; + } +} + +StmtResult Sema::ProcessStmtAttributes(Stmt *S, AttributeList *AttrList, + SourceRange Range) { + AttrVec Attrs; + for (const AttributeList* l = AttrList; l; l = l->getNext()) { + if (Attr *a = ProcessStmtAttribute(*this, S, *l)) + Attrs.push_back(a); + } + + if (Attrs.empty()) + return S; + + return ActOnAttributedStmt(Range.getBegin(), Attrs, S); +} diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp new file mode 100644 index 0000000..51ce2a1 --- /dev/null +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -0,0 +1,7192 @@ +//===------- SemaTemplate.cpp - Semantic Analysis for C++ Templates -------===/ +// +// 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 C++ templates. +//===----------------------------------------------------------------------===/ + +#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/AST/RecursiveASTVisitor.h" +#include "clang/AST/TypeVisitor.h" +#include "clang/Sema/DeclSpec.h" +#include "clang/Sema/ParsedTemplate.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/PartialDiagnostic.h" +#include "llvm/ADT/SmallBitVector.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +using namespace clang; +using namespace sema; + +// Exported for use by Parser. +SourceRange +clang::getTemplateParamsRange(TemplateParameterList const * const *Ps, + unsigned N) { + if (!N) return SourceRange(); + return SourceRange(Ps[0]->getTemplateLoc(), Ps[N-1]->getRAngleLoc()); +} + +/// \brief Determine whether the declaration found is acceptable as the name +/// of a template and, if so, return that template declaration. Otherwise, +/// returns NULL. +static NamedDecl *isAcceptableTemplateName(ASTContext &Context, + NamedDecl *Orig, + bool AllowFunctionTemplates) { + NamedDecl *D = Orig->getUnderlyingDecl(); + + if (isa(D)) { + if (!AllowFunctionTemplates && isa(D)) + return 0; + + return Orig; + } + + if (CXXRecordDecl *Record = dyn_cast(D)) { + // C++ [temp.local]p1: + // Like normal (non-template) classes, class templates have an + // injected-class-name (Clause 9). The injected-class-name + // can be used with or without a template-argument-list. When + // it is used without a template-argument-list, it is + // equivalent to the injected-class-name followed by the + // template-parameters of the class template enclosed in + // <>. When it is used with a template-argument-list, it + // refers to the specified class template specialization, + // which could be the current specialization or another + // specialization. + if (Record->isInjectedClassName()) { + Record = cast(Record->getDeclContext()); + if (Record->getDescribedClassTemplate()) + return Record->getDescribedClassTemplate(); + + if (ClassTemplateSpecializationDecl *Spec + = dyn_cast(Record)) + return Spec->getSpecializedTemplate(); + } + + return 0; + } + + return 0; +} + +void Sema::FilterAcceptableTemplateNames(LookupResult &R, + bool AllowFunctionTemplates) { + // The set of class templates we've already seen. + llvm::SmallPtrSet ClassTemplates; + LookupResult::Filter filter = R.makeFilter(); + while (filter.hasNext()) { + NamedDecl *Orig = filter.next(); + NamedDecl *Repl = isAcceptableTemplateName(Context, Orig, + AllowFunctionTemplates); + if (!Repl) + filter.erase(); + else if (Repl != Orig) { + + // C++ [temp.local]p3: + // A lookup that finds an injected-class-name (10.2) can result in an + // ambiguity in certain cases (for example, if it is found in more than + // one base class). If all of the injected-class-names that are found + // refer to specializations of the same class template, and if the name + // is used as a template-name, the reference refers to the class + // template itself and not a specialization thereof, and is not + // ambiguous. + if (ClassTemplateDecl *ClassTmpl = dyn_cast(Repl)) + if (!ClassTemplates.insert(ClassTmpl)) { + filter.erase(); + continue; + } + + // 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(); +} + +bool Sema::hasAnyAcceptableTemplateNames(LookupResult &R, + bool AllowFunctionTemplates) { + for (LookupResult::iterator I = R.begin(), IEnd = R.end(); I != IEnd; ++I) + if (isAcceptableTemplateName(Context, *I, AllowFunctionTemplates)) + return true; + + return false; +} + +TemplateNameKind Sema::isTemplateName(Scope *S, + CXXScopeSpec &SS, + bool hasTemplateKeyword, + UnqualifiedId &Name, + ParsedType ObjectTypePtr, + bool EnteringContext, + TemplateTy &TemplateResult, + bool &MemberOfUnknownSpecialization) { + assert(getLangOpts().CPlusPlus && "No template names in C!"); + + DeclarationName TName; + MemberOfUnknownSpecialization = false; + + switch (Name.getKind()) { + case UnqualifiedId::IK_Identifier: + TName = DeclarationName(Name.Identifier); + break; + + case UnqualifiedId::IK_OperatorFunctionId: + TName = Context.DeclarationNames.getCXXOperatorName( + Name.OperatorFunctionId.Operator); + break; + + case UnqualifiedId::IK_LiteralOperatorId: + TName = Context.DeclarationNames.getCXXLiteralOperatorName(Name.Identifier); + break; + + default: + return TNK_Non_template; + } + + QualType ObjectType = ObjectTypePtr.get(); + + LookupResult R(*this, TName, Name.getLocStart(), LookupOrdinaryName); + LookupTemplateName(R, S, SS, ObjectType, EnteringContext, + MemberOfUnknownSpecialization); + 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; + + unsigned ResultCount = R.end() - R.begin(); + if (ResultCount > 1) { + // We assume that we'll preserve the qualifier from a function + // 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, + hasTemplateKeyword, TD); + } else { + Template = TemplateName(TD); + } + + if (isa(TD)) { + TemplateKind = TNK_Function_template; + + // We'll do this lookup again later. + R.suppressDiagnostics(); + } else { + assert(isa(TD) || isa(TD) || + isa(TD)); + TemplateKind = TNK_Type_template; + } + } + + TemplateResult = TemplateTy::make(Template); + return TemplateKind; +} + +bool Sema::DiagnoseUnknownTemplateName(const IdentifierInfo &II, + SourceLocation IILoc, + Scope *S, + const CXXScopeSpec *SS, + TemplateTy &SuggestedTemplate, + TemplateNameKind &SuggestedKind) { + // We can't recover unless there's a dependent scope specifier preceding the + // template name. + // FIXME: Typo correction? + if (!SS || !SS->isSet() || !isDependentScopeSpecifier(*SS) || + computeDeclContext(*SS)) + return false; + + // The code is missing a 'template' keyword prior to the dependent template + // name. + NestedNameSpecifier *Qualifier = (NestedNameSpecifier*)SS->getScopeRep(); + Diag(IILoc, diag::err_template_kw_missing) + << Qualifier << II.getName() + << FixItHint::CreateInsertion(IILoc, "template "); + SuggestedTemplate + = TemplateTy::make(Context.getDependentTemplateName(Qualifier, &II)); + SuggestedKind = TNK_Dependent_template_name; + return true; +} + +void Sema::LookupTemplateName(LookupResult &Found, + Scope *S, CXXScopeSpec &SS, + QualType ObjectType, + bool EnteringContext, + bool &MemberOfUnknownSpecialization) { + // Determine where to perform name lookup + MemberOfUnknownSpecialization = false; + DeclContext *LookupCtx = 0; + bool isDependent = false; + if (!ObjectType.isNull()) { + // This nested-name-specifier occurs in a member access expression, e.g., + // x->B::f, and we are looking into the type of the object. + assert(!SS.isSet() && "ObjectType and scope specifier cannot coexist"); + LookupCtx = computeDeclContext(ObjectType); + isDependent = ObjectType->isDependentType(); + assert((isDependent || !ObjectType->isIncompleteType()) && + "Caller should have completed object type"); + + // Template names cannot appear inside an Objective-C class or object type. + if (ObjectType->isObjCObjectOrInterfaceType()) { + Found.clear(); + return; + } + } else if (SS.isSet()) { + // This nested-name-specifier occurs after another nested-name-specifier, + // so long into the context associated with the prior nested-name-specifier. + LookupCtx = computeDeclContext(SS, EnteringContext); + isDependent = isDependentScopeSpecifier(SS); + + // The declaration context must be complete. + if (LookupCtx && RequireCompleteDeclContext(SS, LookupCtx)) + return; + } + + bool ObjectTypeSearchedInScope = false; + bool AllowFunctionTemplatesInLookup = true; + if (LookupCtx) { + // Perform "qualified" name lookup into the declaration context we + // computed, which is either the type of the base of a member access + // expression or the declaration context associated with a prior + // nested-name-specifier. + LookupQualifiedName(Found, LookupCtx); + if (!ObjectType.isNull() && Found.empty()) { + // C++ [basic.lookup.classref]p1: + // In a class member access expression (5.2.5), if the . or -> token is + // immediately followed by an identifier followed by a <, the + // identifier must be looked up to determine whether the < is the + // beginning of a template argument list (14.2) or a less-than operator. + // The identifier is first looked up in the class of the object + // 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. + if (S) LookupName(Found, S); + ObjectTypeSearchedInScope = true; + AllowFunctionTemplatesInLookup = false; + } + } else if (isDependent && (!S || ObjectType.isNull())) { + // We cannot look into a dependent object type or nested nme + // specifier. + MemberOfUnknownSpecialization = true; + return; + } else { + // Perform unqualified name lookup in the current scope. + LookupName(Found, S); + + if (!ObjectType.isNull()) + AllowFunctionTemplatesInLookup = false; + } + + if (Found.empty() && !isDependent) { + // If we did not find any names, attempt to correct any typos. + DeclarationName Name = Found.getLookupName(); + Found.clear(); + // Simple filter callback that, for keywords, only accepts the C++ *_cast + CorrectionCandidateCallback FilterCCC; + FilterCCC.WantTypeSpecifiers = false; + FilterCCC.WantExpressionKeywords = false; + FilterCCC.WantRemainingKeywords = false; + FilterCCC.WantCXXNamedCasts = true; + if (TypoCorrection Corrected = CorrectTypo(Found.getLookupNameInfo(), + Found.getLookupKind(), S, &SS, + FilterCCC, LookupCtx)) { + Found.setLookupName(Corrected.getCorrection()); + if (Corrected.getCorrectionDecl()) + Found.addDecl(Corrected.getCorrectionDecl()); + FilterAcceptableTemplateNames(Found); + if (!Found.empty()) { + std::string CorrectedStr(Corrected.getAsString(getLangOpts())); + std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOpts())); + if (LookupCtx) + Diag(Found.getNameLoc(), diag::err_no_member_template_suggest) + << Name << LookupCtx << CorrectedQuotedStr << SS.getRange() + << FixItHint::CreateReplacement(Found.getNameLoc(), CorrectedStr); + else + Diag(Found.getNameLoc(), diag::err_no_template_suggest) + << Name << CorrectedQuotedStr + << FixItHint::CreateReplacement(Found.getNameLoc(), CorrectedStr); + if (TemplateDecl *Template = Found.getAsSingle()) + Diag(Template->getLocation(), diag::note_previous_decl) + << CorrectedQuotedStr; + } + } else { + Found.setLookupName(Name); + } + } + + FilterAcceptableTemplateNames(Found, AllowFunctionTemplatesInLookup); + if (Found.empty()) { + if (isDependent) + MemberOfUnknownSpecialization = true; + return; + } + + if (S && !ObjectType.isNull() && !ObjectTypeSearchedInScope) { + // C++ [basic.lookup.classref]p1: + // [...] If the lookup in the class of the object expression finds a + // template, the name is also looked up in the context of the entire + // postfix-expression and [...] + // + LookupResult FoundOuter(*this, Found.getLookupName(), Found.getNameLoc(), + LookupOrdinaryName); + LookupName(FoundOuter, S); + FilterAcceptableTemplateNames(FoundOuter, /*AllowFunctionTemplates=*/false); + + if (FoundOuter.empty()) { + // - if the name is not found, the name found in the class of the + // object expression is used, otherwise + } else if (!FoundOuter.getAsSingle() || + FoundOuter.isAmbiguous()) { + // - if the name is found in the context of the entire + // postfix-expression and does not name a class template, the name + // found in the class of the object expression is used, otherwise + FoundOuter.clear(); + } else if (!Found.isSuppressingDiagnostics()) { + // - if the name found is a class template, it must refer to the same + // entity as the one found in the class of the object expression, + // otherwise the program is ill-formed. + if (!Found.isSingleResult() || + Found.getFoundDecl()->getCanonicalDecl() + != FoundOuter.getFoundDecl()->getCanonicalDecl()) { + Diag(Found.getNameLoc(), + diag::ext_nested_name_member_ref_lookup_ambiguous) + << Found.getLookupName() + << ObjectType; + Diag(Found.getRepresentativeDecl()->getLocation(), + diag::note_ambig_member_ref_object_type) + << ObjectType; + Diag(FoundOuter.getFoundDecl()->getLocation(), + diag::note_ambig_member_ref_scope); + + // Recover by taking the template that we found in the object + // expression's type. + } + } + } +} + +/// ActOnDependentIdExpression - Handle a dependent id-expression that +/// was just parsed. This is only possible with an explicit scope +/// specifier naming a dependent type. +ExprResult +Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, + const DeclarationNameInfo &NameInfo, + bool isAddressOfOperand, + const TemplateArgumentListInfo *TemplateArgs) { + DeclContext *DC = getFunctionLevelDeclContext(); + + if (!isAddressOfOperand && + isa(DC) && + cast(DC)->isInstance()) { + QualType ThisType = cast(DC)->getThisType(Context); + + // Since the 'this' expression is synthesized, we don't need to + // perform the double-lookup check. + NamedDecl *FirstQualifierInScope = 0; + + return Owned(CXXDependentScopeMemberExpr::Create(Context, + /*This*/ 0, ThisType, + /*IsArrow*/ true, + /*Op*/ SourceLocation(), + SS.getWithLocInContext(Context), + TemplateKWLoc, + FirstQualifierInScope, + NameInfo, + TemplateArgs)); + } + + return BuildDependentDeclRefExpr(SS, TemplateKWLoc, NameInfo, TemplateArgs); +} + +ExprResult +Sema::BuildDependentDeclRefExpr(const CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, + const DeclarationNameInfo &NameInfo, + const TemplateArgumentListInfo *TemplateArgs) { + return Owned(DependentScopeDeclRefExpr::Create(Context, + SS.getWithLocInContext(Context), + TemplateKWLoc, + NameInfo, + TemplateArgs)); +} + +/// DiagnoseTemplateParameterShadow - Produce a diagnostic complaining +/// that the template parameter 'PrevDecl' is being shadowed by a new +/// declaration at location Loc. Returns true to indicate that this is +/// an error, and false otherwise. +void Sema::DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl) { + assert(PrevDecl->isTemplateParameter() && "Not a template parameter"); + + // Microsoft Visual C++ permits template parameters to be shadowed. + if (getLangOpts().MicrosoftExt) + return; + + // C++ [temp.local]p4: + // A template-parameter shall not be redeclared within its + // scope (including nested scopes). + Diag(Loc, diag::err_template_param_shadow) + << cast(PrevDecl)->getDeclName(); + Diag(PrevDecl->getLocation(), diag::note_template_param_here); + return; +} + +/// 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(Decl *&D) { + if (TemplateDecl *Temp = dyn_cast_or_null(D)) { + D = Temp->getTemplatedDecl(); + return Temp; + } + return 0; +} + +ParsedTemplateArgument ParsedTemplateArgument::getTemplatePackExpansion( + SourceLocation EllipsisLoc) const { + assert(Kind == Template && + "Only template template arguments can be pack expansions here"); + assert(getAsTemplate().get().containsUnexpandedParameterPack() && + "Template template argument pack expansion without packs"); + ParsedTemplateArgument Result(*this); + Result.EllipsisLoc = EllipsisLoc; + return Result; +} + +static TemplateArgumentLoc translateTemplateArgument(Sema &SemaRef, + const ParsedTemplateArgument &Arg) { + + switch (Arg.getKind()) { + case ParsedTemplateArgument::Type: { + TypeSourceInfo *DI; + QualType T = SemaRef.GetTypeFromParser(Arg.getAsType(), &DI); + if (!DI) + DI = SemaRef.Context.getTrivialTypeSourceInfo(T, Arg.getLocation()); + return TemplateArgumentLoc(TemplateArgument(T), DI); + } + + case ParsedTemplateArgument::NonType: { + Expr *E = static_cast(Arg.getAsExpr()); + return TemplateArgumentLoc(TemplateArgument(E), E); + } + + case ParsedTemplateArgument::Template: { + TemplateName Template = Arg.getAsTemplate().get(); + TemplateArgument TArg; + if (Arg.getEllipsisLoc().isValid()) + TArg = TemplateArgument(Template, llvm::Optional()); + else + TArg = Template; + return TemplateArgumentLoc(TArg, + Arg.getScopeSpec().getWithLocInContext( + SemaRef.Context), + Arg.getLocation(), + Arg.getEllipsisLoc()); + } + } + + llvm_unreachable("Unhandled parsed template argument"); +} + +/// \brief Translates template arguments as provided by the parser +/// into template arguments used by semantic analysis. +void Sema::translateTemplateArguments(const ASTTemplateArgsPtr &TemplateArgsIn, + TemplateArgumentListInfo &TemplateArgs) { + for (unsigned I = 0, Last = TemplateArgsIn.size(); I != Last; ++I) + TemplateArgs.addArgument(translateTemplateArgument(*this, + TemplateArgsIn[I])); +} + +/// ActOnTypeParameter - Called when a C++ template type parameter +/// (e.g., "typename T") has been parsed. Typename specifies whether +/// the keyword "typename" was used to declare the type parameter +/// (otherwise, "class" was used), and KeyLoc is the location of the +/// "class" or "typename" keyword. ParamName is the name of the +/// parameter (NULL indicates an unnamed template parameter) and +/// ParamNameLoc is the location of the parameter name (if any). +/// If the type parameter has a default argument, it will be added +/// later via ActOnTypeParameterDefault. +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; + + if (ParamName) { + NamedDecl *PrevDecl = LookupSingleName(S, ParamName, ParamNameLoc, + LookupOrdinaryName, + ForRedeclaration); + if (PrevDecl && PrevDecl->isTemplateParameter()) { + DiagnoseTemplateParameterShadow(ParamNameLoc, PrevDecl); + PrevDecl = 0; + } + } + + SourceLocation Loc = ParamNameLoc; + if (!ParamName) + Loc = KeyLoc; + + TemplateTypeParmDecl *Param + = TemplateTypeParmDecl::Create(Context, Context.getTranslationUnitDecl(), + KeyLoc, Loc, Depth, Position, ParamName, + Typename, Ellipsis); + Param->setAccess(AS_public); + if (Invalid) + Param->setInvalidDecl(); + + if (ParamName) { + // Add the template parameter into the current scope. + S->AddDecl(Param); + IdResolver.AddDecl(Param); + } + + // C++0x [temp.param]p9: + // A default template-argument may be specified for any kind of + // template-parameter that is not a template parameter pack. + if (DefaultArg && Ellipsis) { + Diag(EqualLoc, diag::err_template_param_pack_default_arg); + DefaultArg = ParsedType(); + } + + // Handle the default argument, if provided. + if (DefaultArg) { + TypeSourceInfo *DefaultTInfo; + GetTypeFromParser(DefaultArg, &DefaultTInfo); + + assert(DefaultTInfo && "expected source information for type"); + + // Check for unexpanded parameter packs. + if (DiagnoseUnexpandedParameterPack(Loc, DefaultTInfo, + UPPC_DefaultArgument)) + return Param; + + // Check the template argument itself. + if (CheckTemplateArgument(Param, DefaultTInfo)) { + Param->setInvalidDecl(); + return Param; + } + + Param->setDefaultArgument(DefaultTInfo, false); + } + + return Param; +} + +/// \brief Check that the type of a non-type template parameter is +/// well-formed. +/// +/// \returns the (possibly-promoted) parameter type if valid; +/// otherwise, produces a diagnostic and returns a NULL type. +QualType +Sema::CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc) { + // We don't allow variably-modified types as the type of non-type template + // parameters. + if (T->isVariablyModifiedType()) { + Diag(Loc, diag::err_variably_modified_nontype_template_param) + << T; + return QualType(); + } + + // C++ [temp.param]p4: + // + // A non-type template-parameter shall have one of the following + // (optionally cv-qualified) types: + // + // -- integral or enumeration type, + if (T->isIntegralOrEnumerationType() || + // -- pointer to object or pointer to function, + T->isPointerType() || + // -- reference to object or reference to function, + T->isReferenceType() || + // -- pointer to member, + T->isMemberPointerType() || + // -- std::nullptr_t. + T->isNullPtrType() || + // If T is a dependent type, we can't do the check now, so we + // assume that it is well-formed. + T->isDependentType()) { + // C++ [temp.param]p5: The top-level cv-qualifiers on the template-parameter + // are ignored when determining its type. + return T.getUnqualifiedType(); + } + + // C++ [temp.param]p8: + // + // A non-type template-parameter of type "array of T" or + // "function returning T" is adjusted to be of type "pointer to + // T" or "pointer to function returning T", respectively. + else if (T->isArrayType()) + // FIXME: Keep the type prior to promotion? + return Context.getArrayDecayedType(T); + else if (T->isFunctionType()) + // FIXME: Keep the type prior to promotion? + return Context.getPointerType(T); + + Diag(Loc, diag::err_template_nontype_parm_bad_type) + << T; + + return QualType(); +} + +Decl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, + unsigned Depth, + unsigned Position, + SourceLocation EqualLoc, + Expr *Default) { + TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); + QualType T = TInfo->getType(); + + assert(S->isTemplateParamScope() && + "Non-type template parameter not in template parameter scope!"); + bool Invalid = false; + + IdentifierInfo *ParamName = D.getIdentifier(); + if (ParamName) { + NamedDecl *PrevDecl = LookupSingleName(S, ParamName, D.getIdentifierLoc(), + LookupOrdinaryName, + ForRedeclaration); + if (PrevDecl && PrevDecl->isTemplateParameter()) { + DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl); + PrevDecl = 0; + } + } + + T = CheckNonTypeTemplateParameterType(T, D.getIdentifierLoc()); + if (T.isNull()) { + T = Context.IntTy; // Recover with an 'int' type. + Invalid = true; + } + + bool IsParameterPack = D.hasEllipsis(); + NonTypeTemplateParmDecl *Param + = NonTypeTemplateParmDecl::Create(Context, Context.getTranslationUnitDecl(), + D.getLocStart(), + D.getIdentifierLoc(), + Depth, Position, ParamName, T, + IsParameterPack, TInfo); + Param->setAccess(AS_public); + + if (Invalid) + Param->setInvalidDecl(); + + if (D.getIdentifier()) { + // Add the template parameter into the current scope. + S->AddDecl(Param); + IdResolver.AddDecl(Param); + } + + // C++0x [temp.param]p9: + // A default template-argument may be specified for any kind of + // template-parameter that is not a template parameter pack. + if (Default && IsParameterPack) { + Diag(EqualLoc, diag::err_template_param_pack_default_arg); + Default = 0; + } + + // Check the well-formedness of the default template argument, if provided. + if (Default) { + // Check for unexpanded parameter packs. + if (DiagnoseUnexpandedParameterPack(Default, UPPC_DefaultArgument)) + return Param; + + TemplateArgument Converted; + ExprResult DefaultRes = CheckTemplateArgument(Param, Param->getType(), Default, Converted); + if (DefaultRes.isInvalid()) { + Param->setInvalidDecl(); + return Param; + } + Default = DefaultRes.take(); + + Param->setDefaultArgument(Default, false); + } + + return Param; +} + +/// ActOnTemplateTemplateParameter - Called when a C++ template template +/// parameter (e.g. T in template