diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema')
37 files changed, 9350 insertions, 4191 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp b/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp index 6a42224..e482172 100644 --- a/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -24,12 +24,13 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/StmtObjC.h" #include "clang/AST/StmtCXX.h" +#include "clang/AST/EvaluatedExprVisitor.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/CFGStmtMap.h" -#include "clang/Analysis/Analyses/UninitializedValuesV2.h" +#include "clang/Analysis/Analyses/UninitializedValues.h" #include "llvm/ADT/BitVector.h" #include "llvm/Support/Casting.h" @@ -129,12 +130,27 @@ static ControlFlowKind CheckFallThrough(AnalysisContext &AC) { // 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(); + bool hasNoReturnDtor = false; + for ( ; ri != re ; ++ri) { CFGElement CE = *ri; + + // FIXME: The right solution is to just sever the edges in the + // CFG itself. + if (const CFGImplicitDtor *iDtor = ri->getAs<CFGImplicitDtor>()) + if (iDtor->isNoReturn(AC.getASTContext())) { + hasNoReturnDtor = true; + HasFakeEdge = true; + break; + } + if (isa<CFGStmt>(CE)) break; } + if (hasNoReturnDtor) + continue; + // No more CFGElements in the block? if (ri == re) { if (B.getTerminator() && isa<CXXTryStmt>(B.getTerminator())) { @@ -363,17 +379,145 @@ static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body, //===----------------------------------------------------------------------===// 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<ContainsReference> { + bool FoundReference; + const DeclRefExpr *Needle; + +public: + ContainsReference(ASTContext &Context, const DeclRefExpr *Needle) + : EvaluatedExprVisitor<ContainsReference>(Context), + FoundReference(false), Needle(Needle) {} + + void VisitExpr(Expr *E) { + // Stop evaluating if we already have a reference. + if (FoundReference) + return; + + EvaluatedExprVisitor<ContainsReference>::VisitExpr(E); + } + + void VisitDeclRefExpr(DeclRefExpr *E) { + if (E == Needle) + FoundReference = true; + else + EvaluatedExprVisitor<ContainsReference>::VisitDeclRefExpr(E); + } + + bool doesContainReference() const { return FoundReference; } +}; +} + +/// 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 isSelfInit = false; + + if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(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 (DRE == Initializer->IgnoreParenImpCasts()) + return false; + + ContainsReference CR(S.Context, DRE); + CR.Visit(const_cast<Expr*>(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<BlockExpr>(E); + 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. + if (!isSelfInit) + S.Diag(VD->getLocStart(), diag::note_uninit_var_def) + << VD->getDeclName(); + + return true; +} + +static void SuggestInitializationFixit(Sema &S, const VarDecl *VD) { + // Don't issue a fixit if there is already an initializer. + if (VD->getInit()) + return; + + // Suggest possible initialization (if any). + const char *initialization = 0; + QualType VariableTy = VD->getType().getCanonicalType(); + + if (VariableTy->getAs<ObjCObjectPointerType>()) { + // Check if 'nil' is defined. + if (S.PP.getMacroInfo(&S.getASTContext().Idents.get("nil"))) + initialization = " = nil"; + else + initialization = " = 0"; + } + else if (VariableTy->isRealFloatingType()) + initialization = " = 0.0"; + else if (VariableTy->isBooleanType() && S.Context.getLangOptions().CPlusPlus) + initialization = " = false"; + else if (VariableTy->isEnumeralType()) + return; + else if (VariableTy->isScalarType()) + initialization = " = 0"; + + if (initialization) { + SourceLocation loc = S.PP.getLocForEndOfToken(VD->getLocEnd()); + S.Diag(loc, diag::note_var_fixit_add_initialization) + << FixItHint::CreateInsertion(loc, initialization); + } +} + +typedef std::pair<const Expr*, bool> UninitUse; + +namespace { struct SLocSort { - bool operator()(const Expr *a, const Expr *b) { - SourceLocation aLoc = a->getLocStart(); - SourceLocation bLoc = b->getLocStart(); + 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 llvm::SmallVector<const Expr *, 2> UsesVec; + typedef llvm::SmallVector<UninitUse, 2> UsesVec; typedef llvm::DenseMap<const VarDecl *, UsesVec*> UsesMap; UsesMap *uses; @@ -383,7 +527,8 @@ public: flushDiagnostics(); } - void handleUseOfUninitVariable(const Expr *ex, const VarDecl *vd) { + void handleUseOfUninitVariable(const Expr *ex, const VarDecl *vd, + bool isAlwaysUninit) { if (!uses) uses = new UsesMap(); @@ -391,7 +536,7 @@ public: if (!vec) vec = new UsesVec(); - vec->push_back(ex); + vec->push_back(std::make_pair(ex, isAlwaysUninit)); } void flushDiagnostics() { @@ -409,54 +554,19 @@ public: // a stable ordering. std::sort(vec->begin(), vec->end(), SLocSort()); - for (UsesVec::iterator vi = vec->begin(), ve = vec->end(); vi != ve; ++vi) - { - if (const DeclRefExpr *dr = dyn_cast<DeclRefExpr>(*vi)) { - S.Diag(dr->getLocStart(), diag::warn_uninit_var) - << vd->getDeclName() << dr->getSourceRange(); - } - else { - const BlockExpr *be = cast<BlockExpr>(*vi); - S.Diag(be->getLocStart(), diag::warn_uninit_var_captured_by_block) - << vd->getDeclName(); - } - - // Report where the variable was declared. - S.Diag(vd->getLocStart(), diag::note_uninit_var_def) - << vd->getDeclName(); - - // Only report the fixit once. - if (fixitIssued) + for (UsesVec::iterator vi = vec->begin(), ve = vec->end(); vi != ve; + ++vi) { + if (!DiagnoseUninitializedUse(S, vd, vi->first, + /*isAlwaysUninit=*/vi->second)) continue; - - fixitIssued = true; - - // Suggest possible initialization (if any). - const char *initialization = 0; - QualType vdTy = vd->getType().getCanonicalType(); - - if (vdTy->getAs<ObjCObjectPointerType>()) { - // Check if 'nil' is defined. - if (S.PP.getMacroInfo(&S.getASTContext().Idents.get("nil"))) - initialization = " = nil"; - else - initialization = " = 0"; - } - else if (vdTy->isRealFloatingType()) - initialization = " = 0.0"; - else if (vdTy->isBooleanType() && S.Context.getLangOptions().CPlusPlus) - initialization = " = false"; - else if (vdTy->isEnumeralType()) - continue; - else if (vdTy->isScalarType()) - initialization = " = 0"; - - if (initialization) { - SourceLocation loc = S.PP.getLocForEndOfToken(vd->getLocEnd()); - S.Diag(loc, diag::note_var_fixit_add_initialization) - << FixItHint::CreateInsertion(loc, initialization); + + // Suggest a fixit hint the first time we diagnose a use of a variable. + if (!fixitIssued) { + SuggestInitializationFixit(S, vd); + fixitIssued = true; } } + delete vec; } delete uses; @@ -531,25 +641,41 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, // Emit delayed diagnostics. if (!fscope->PossiblyUnreachableDiags.empty()) { bool analyzed = false; - if (CFGReachabilityAnalysis *cra = AC.getCFGReachablityAnalysis()) - if (CFGStmtMap *csm = AC.getCFGStmtMap()) { - analyzed = true; - for (llvm::SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator - i = fscope->PossiblyUnreachableDiags.begin(), - e = fscope->PossiblyUnreachableDiags.end(); - i != e; ++i) { - const sema::PossiblyUnreachableDiag &D = *i; - if (const CFGBlock *blk = csm->getBlock(D.stmt)) { + + // Register the expressions with the CFGBuilder. + for (llvm::SmallVectorImpl<sema::PossiblyUnreachableDiag>::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 (llvm::SmallVectorImpl<sema::PossiblyUnreachableDiag>::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); + assert(block); + if (CFGReverseBlockReachabilityAnalysis *cra = AC.getCFGReachablityAnalysis()) { // Can this block be reached from the entrance? - if (cra->isReachable(&AC.getCFG()->getEntry(), blk)) + if (cra->isReachable(&AC.getCFG()->getEntry(), block)) S.Diag(D.Loc, D.PD); - } - else { - // Emit the warning anyway if we cannot map to a basic 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); @@ -569,25 +695,10 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, CheckUnreachable(S, AC); if (Diags.getDiagnosticLevel(diag::warn_uninit_var, D->getLocStart()) + != Diagnostic::Ignored || + Diags.getDiagnosticLevel(diag::warn_maybe_uninit_var, D->getLocStart()) != Diagnostic::Ignored) { - ASTContext &ctx = D->getASTContext(); - llvm::OwningPtr<CFG> tmpCFG; - bool useAlternateCFG = false; - if (ctx.getLangOptions().CPlusPlus) { - // Temporary workaround: implicit dtors in the CFG can confuse - // the path-sensitivity in the uninitialized values analysis. - // For now create (if necessary) a separate CFG without implicit dtors. - // FIXME: We should not need to do this, as it results in multiple - // CFGs getting constructed. - CFG::BuildOptions B; - B.AddEHEdges = false; - B.AddImplicitDtors = false; - B.AddInitializers = true; - tmpCFG.reset(CFG::buildCFG(D, AC.getBody(), &ctx, B)); - useAlternateCFG = true; - } - CFG *cfg = useAlternateCFG ? tmpCFG.get() : AC.getCFG(); - if (cfg) { + if (CFG *cfg = AC.getCFG()) { UninitValsDiagReporter reporter(S); runUninitializedVariablesAnalysis(*cast<DeclContext>(D), *cfg, AC, reporter); diff --git a/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp b/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp index c0a3053..619a5b9 100644 --- a/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp @@ -12,28 +12,89 @@ //===----------------------------------------------------------------------===// #include "clang/Sema/AttributeList.h" +#include "clang/AST/Expr.h" #include "clang/Basic/IdentifierTable.h" #include "llvm/ADT/StringSwitch.h" using namespace clang; -AttributeList::AttributeList(llvm::BumpPtrAllocator &Alloc, - IdentifierInfo *aName, SourceLocation aLoc, - IdentifierInfo *sName, SourceLocation sLoc, - IdentifierInfo *pName, SourceLocation pLoc, - Expr **ExprList, unsigned numArgs, - bool declspec, bool cxx0x) - : AttrName(aName), AttrLoc(aLoc), ScopeName(sName), - ScopeLoc(sLoc), - ParmName(pName), ParmLoc(pLoc), NumArgs(numArgs), Next(0), - DeclspecAttribute(declspec), CXX0XAttribute(cxx0x), Invalid(false) { - - if (numArgs == 0) - Args = 0; - else { - // Allocate the Args array using the BumpPtrAllocator. - Args = Alloc.Allocate<Expr*>(numArgs); - memcpy(Args, ExprList, numArgs*sizeof(Args[0])); +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<AttributeFactory>::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) { @@ -83,6 +144,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) { .Case("may_alias", AT_may_alias) .Case("base_check", AT_base_check) .Case("deprecated", AT_deprecated) + .Case("availability", AT_availability) .Case("visibility", AT_visibility) .Case("destructor", AT_destructor) .Case("format_arg", AT_format_arg) @@ -94,10 +156,12 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) { .Case("unavailable", AT_unavailable) .Case("overloadable", AT_overloadable) .Case("address_space", AT_address_space) + .Case("opencl_image_access", AT_opencl_image_access) .Case("always_inline", AT_always_inline) .Case("returns_twice", IgnoredAttribute) .Case("vec_type_hint", IgnoredAttribute) .Case("objc_exception", AT_objc_exception) + .Case("objc_method_family", AT_objc_method_family) .Case("ext_vector_type", AT_ext_vector_type) .Case("neon_vector_type", AT_neon_vector_type) .Case("neon_polyvector_type", AT_neon_polyvector_type) @@ -137,5 +201,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) { .Case("nocommon", AT_nocommon) .Case("opencl_kernel_function", AT_opencl_kernel_function) .Case("uuid", AT_uuid) + .Case("pcs", AT_pcs) + .Case("ms_struct", AT_MsStruct) .Default(UnknownAttribute); } diff --git a/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp b/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp index b7037ce..2334ab5 100644 --- a/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp @@ -375,12 +375,21 @@ void CodeCompletionResult::computeCursorKindAndAvailability() { switch (Kind) { case RK_Declaration: // Set the availability based on attributes. - Availability = CXAvailability_Available; - if (Declaration->getAttr<UnavailableAttr>()) - Availability = CXAvailability_NotAvailable; - else if (Declaration->getAttr<DeprecatedAttr>()) + switch (Declaration->getAvailability()) { + 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<FunctionDecl>(Declaration)) if (Function->isDeleted()) Availability = CXAvailability_NotAvailable; diff --git a/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp index 037594a..0f20d10 100644 --- a/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp @@ -47,278 +47,130 @@ void UnqualifiedId::setConstructorTemplateId(TemplateIdAnnotation *TemplateId) { EndLocation = TemplateId->RAngleLoc; } -CXXScopeSpec::CXXScopeSpec(const CXXScopeSpec &Other) - : Range(Other.Range), ScopeRep(Other.ScopeRep), Buffer(0), - BufferSize(Other.BufferSize), BufferCapacity(Other.BufferSize) -{ - if (BufferSize) { - Buffer = static_cast<char *>(malloc(BufferSize)); - memcpy(Buffer, Other.Buffer, BufferSize); - } -} - -CXXScopeSpec &CXXScopeSpec::operator=(const CXXScopeSpec &Other) { - Range = Other.Range; - ScopeRep = Other.ScopeRep; - if (Buffer && Other.Buffer && BufferCapacity >= Other.BufferSize) { - // Re-use our storage. - BufferSize = Other.BufferSize; - memcpy(Buffer, Other.Buffer, BufferSize); - return *this; - } - - if (BufferCapacity) - free(Buffer); - if (Other.Buffer) { - BufferSize = Other.BufferSize; - BufferCapacity = BufferSize; - Buffer = static_cast<char *>(malloc(BufferSize)); - memcpy(Buffer, Other.Buffer, BufferSize); - } else { - Buffer = 0; - BufferSize = 0; - BufferCapacity = 0; - } - return *this; -} - -CXXScopeSpec::~CXXScopeSpec() { - if (BufferCapacity) - free(Buffer); -} - -namespace { - void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize, - unsigned &BufferCapacity) { - if (BufferSize + (End - Start) > BufferCapacity) { - // Reallocate the buffer. - unsigned NewCapacity - = std::max((unsigned)(BufferCapacity? BufferCapacity * 2 - : sizeof(void*) * 2), - (unsigned)(BufferSize + (End - Start))); - char *NewBuffer = static_cast<char *>(malloc(NewCapacity)); - memcpy(NewBuffer, Buffer, BufferSize); - - if (BufferCapacity) - free(Buffer); - Buffer = NewBuffer; - BufferCapacity = NewCapacity; - } - - memcpy(Buffer + BufferSize, Start, End - Start); - BufferSize += End-Start; - } - - /// \brief Save a source location to the given buffer. - void SaveSourceLocation(SourceLocation Loc, char *&Buffer, - unsigned &BufferSize, unsigned &BufferCapacity) { - unsigned Raw = Loc.getRawEncoding(); - Append(reinterpret_cast<char *>(&Raw), - reinterpret_cast<char *>(&Raw) + sizeof(unsigned), - Buffer, BufferSize, BufferCapacity); - } - - /// \brief Save a pointer to the given buffer. - void SavePointer(void *Ptr, char *&Buffer, unsigned &BufferSize, - unsigned &BufferCapacity) { - Append(reinterpret_cast<char *>(&Ptr), - reinterpret_cast<char *>(&Ptr) + sizeof(void *), - Buffer, BufferSize, BufferCapacity); - } -} void CXXScopeSpec::Extend(ASTContext &Context, SourceLocation TemplateKWLoc, TypeLoc TL, SourceLocation ColonColonLoc) { - ScopeRep = NestedNameSpecifier::Create(Context, ScopeRep, - TemplateKWLoc.isValid(), - TL.getTypePtr()); + Builder.Extend(Context, TemplateKWLoc, TL, ColonColonLoc); if (Range.getBegin().isInvalid()) Range.setBegin(TL.getBeginLoc()); Range.setEnd(ColonColonLoc); - // Push source-location info into the buffer. - SavePointer(TL.getOpaqueData(), Buffer, BufferSize, BufferCapacity); - SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); - - assert(Range == NestedNameSpecifierLoc(ScopeRep, Buffer).getSourceRange() && + assert(Range == Builder.getSourceRange() && "NestedNameSpecifierLoc range computation incorrect"); } void CXXScopeSpec::Extend(ASTContext &Context, IdentifierInfo *Identifier, SourceLocation IdentifierLoc, SourceLocation ColonColonLoc) { - ScopeRep = NestedNameSpecifier::Create(Context, ScopeRep, Identifier); + Builder.Extend(Context, Identifier, IdentifierLoc, ColonColonLoc); + if (Range.getBegin().isInvalid()) Range.setBegin(IdentifierLoc); Range.setEnd(ColonColonLoc); - // Push source-location info into the buffer. - SaveSourceLocation(IdentifierLoc, Buffer, BufferSize, BufferCapacity); - SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); - - assert(Range == NestedNameSpecifierLoc(ScopeRep, Buffer).getSourceRange() && + assert(Range == Builder.getSourceRange() && "NestedNameSpecifierLoc range computation incorrect"); } void CXXScopeSpec::Extend(ASTContext &Context, NamespaceDecl *Namespace, SourceLocation NamespaceLoc, SourceLocation ColonColonLoc) { - ScopeRep = NestedNameSpecifier::Create(Context, ScopeRep, Namespace); + Builder.Extend(Context, Namespace, NamespaceLoc, ColonColonLoc); + if (Range.getBegin().isInvalid()) Range.setBegin(NamespaceLoc); Range.setEnd(ColonColonLoc); - // Push source-location info into the buffer. - SaveSourceLocation(NamespaceLoc, Buffer, BufferSize, BufferCapacity); - SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); - - assert(Range == NestedNameSpecifierLoc(ScopeRep, Buffer).getSourceRange() && + assert(Range == Builder.getSourceRange() && "NestedNameSpecifierLoc range computation incorrect"); } void CXXScopeSpec::Extend(ASTContext &Context, NamespaceAliasDecl *Alias, SourceLocation AliasLoc, SourceLocation ColonColonLoc) { - ScopeRep = NestedNameSpecifier::Create(Context, ScopeRep, Alias); + Builder.Extend(Context, Alias, AliasLoc, ColonColonLoc); + if (Range.getBegin().isInvalid()) Range.setBegin(AliasLoc); Range.setEnd(ColonColonLoc); - // Push source-location info into the buffer. - SaveSourceLocation(AliasLoc, Buffer, BufferSize, BufferCapacity); - SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); - - assert(Range == NestedNameSpecifierLoc(ScopeRep, Buffer).getSourceRange() && + assert(Range == Builder.getSourceRange() && "NestedNameSpecifierLoc range computation incorrect"); } void CXXScopeSpec::MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc) { - assert(!ScopeRep && "Already have a nested-name-specifier!?"); - ScopeRep = NestedNameSpecifier::GlobalSpecifier(Context); - Range = SourceRange(ColonColonLoc); + Builder.MakeGlobal(Context, ColonColonLoc); - // Push source-location info into the buffer. - SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); + Range = SourceRange(ColonColonLoc); - assert(Range == NestedNameSpecifierLoc(ScopeRep, Buffer).getSourceRange() && + assert(Range == Builder.getSourceRange() && "NestedNameSpecifierLoc range computation incorrect"); } void CXXScopeSpec::MakeTrivial(ASTContext &Context, NestedNameSpecifier *Qualifier, SourceRange R) { - ScopeRep = Qualifier; + Builder.MakeTrivial(Context, Qualifier, R); Range = R; - - // Construct bogus (but well-formed) source information for the - // nested-name-specifier. - BufferSize = 0; - llvm::SmallVector<NestedNameSpecifier *, 4> Stack; - for (NestedNameSpecifier *NNS = Qualifier; NNS; NNS = NNS->getPrefix()) - Stack.push_back(NNS); - while (!Stack.empty()) { - NestedNameSpecifier *NNS = Stack.back(); - Stack.pop_back(); - switch (NNS->getKind()) { - case NestedNameSpecifier::Identifier: - case NestedNameSpecifier::Namespace: - case NestedNameSpecifier::NamespaceAlias: - SaveSourceLocation(R.getBegin(), Buffer, BufferSize, BufferCapacity); - break; - - case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: { - TypeSourceInfo *TSInfo - = Context.getTrivialTypeSourceInfo(QualType(NNS->getAsType(), 0), - R.getBegin()); - SavePointer(TSInfo->getTypeLoc().getOpaqueData(), Buffer, BufferSize, - BufferCapacity); - break; - } - - case NestedNameSpecifier::Global: - break; - } - - // Save the location of the '::'. - SaveSourceLocation(Stack.empty()? R.getEnd() : R.getBegin(), - Buffer, BufferSize, BufferCapacity); - } } void CXXScopeSpec::Adopt(NestedNameSpecifierLoc Other) { if (!Other) { Range = SourceRange(); - ScopeRep = 0; + Builder.Clear(); return; } - - if (BufferCapacity) - free(Buffer); - - // Rather than copying the data (which is wasteful), "adopt" the - // pointer (which points into the ASTContext) but set the capacity to zero to - // indicate that we don't own it. + Range = Other.getSourceRange(); - ScopeRep = Other.getNestedNameSpecifier(); - Buffer = static_cast<char *>(Other.getOpaqueData()); - BufferSize = Other.getDataLength(); - BufferCapacity = 0; + Builder.Adopt(Other); } NestedNameSpecifierLoc CXXScopeSpec::getWithLocInContext(ASTContext &Context) const { - if (isEmpty() || isInvalid()) + if (!Builder.getRepresentation()) return NestedNameSpecifierLoc(); - // If we adopted our data pointer from elsewhere in the AST context, there's - // no need to copy the memory. - if (BufferCapacity == 0) - return NestedNameSpecifierLoc(ScopeRep, Buffer); - - void *Mem = Context.Allocate(BufferSize, llvm::alignOf<void *>()); - memcpy(Mem, Buffer, BufferSize); - return NestedNameSpecifierLoc(ScopeRep, Mem); + 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(const ParsedAttributes &attrs, - bool hasProto, bool isVariadic, +DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic, SourceLocation EllipsisLoc, ParamInfo *ArgInfo, unsigned NumArgs, unsigned TypeQuals, bool RefQualifierIsLvalueRef, SourceLocation RefQualifierLoc, - bool hasExceptionSpec, - SourceLocation ThrowLoc, - bool hasAnyExceptionSpec, + ExceptionSpecificationType + ESpecType, + SourceLocation ESpecLoc, ParsedType *Exceptions, SourceRange *ExceptionRanges, unsigned NumExceptions, - SourceLocation LPLoc, - SourceLocation RPLoc, + Expr *NoexceptExpr, + SourceLocation LocalRangeBegin, + SourceLocation LocalRangeEnd, Declarator &TheDeclarator, ParsedType TrailingReturnType) { DeclaratorChunk I; - I.Kind = Function; - I.Loc = LPLoc; - I.EndLoc = RPLoc; - I.Fun.AttrList = attrs.getList(); - 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.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.hasExceptionSpec = hasExceptionSpec; - I.Fun.ThrowLoc = ThrowLoc.getRawEncoding(); - I.Fun.hasAnyExceptionSpec = hasAnyExceptionSpec; - I.Fun.NumExceptions = NumExceptions; - I.Fun.Exceptions = 0; + I.Fun.RefQualifierLoc = RefQualifierLoc.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. @@ -338,13 +190,25 @@ DeclaratorChunk DeclaratorChunk::getFunction(const ParsedAttributes &attrs, } memcpy(I.Fun.ArgInfo, ArgInfo, sizeof(ArgInfo[0])*NumArgs); } - // new[] an exception array if needed - if (NumExceptions) { - I.Fun.Exceptions = new DeclaratorChunk::TypeAndRange[NumExceptions]; - for (unsigned i = 0; i != NumExceptions; ++i) { - I.Fun.Exceptions[i].Ty = Exceptions[i]; - I.Fun.Exceptions[i].Range = ExceptionRanges[i]; + + // 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; } @@ -445,6 +309,7 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T) { case DeclSpec::TST_typeofExpr: return "typeof"; case DeclSpec::TST_auto: return "auto"; case DeclSpec::TST_decltype: return "(decltype)"; + case DeclSpec::TST_unknown_anytype: return "__unknown_anytype"; case DeclSpec::TST_error: return "(error)"; } llvm_unreachable("Unknown typespec!"); @@ -515,12 +380,14 @@ bool DeclSpec::SetStorageClassSpecThread(SourceLocation Loc, bool DeclSpec::SetTypeSpecWidth(TSW W, SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID) { - if (TypeSpecWidth != TSW_unspecified && - // Allow turning long -> long long. - (W != TSW_longlong || TypeSpecWidth != TSW_long)) + // 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; - TSWLoc = Loc; if (TypeAltiVecVector && !TypeAltiVecBool && ((TypeSpecWidth == TSW_long) || (TypeSpecWidth == TSW_longlong))) { PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType); @@ -554,6 +421,14 @@ 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) { @@ -563,7 +438,8 @@ bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc, } TypeSpecType = T; TypeRep = Rep; - TSTLoc = Loc; + TSTLoc = TagKwLoc; + TSTNameLoc = TagNameLoc; TypeSpecOwned = false; return false; } @@ -582,6 +458,7 @@ bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc, TypeSpecType = T; ExprRep = Rep; TSTLoc = Loc; + TSTNameLoc = Loc; TypeSpecOwned = false; return false; } @@ -590,6 +467,14 @@ 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. @@ -600,7 +485,8 @@ bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc, } TypeSpecType = T; DeclRep = Rep; - TSTLoc = Loc; + TSTLoc = TagKwLoc; + TSTNameLoc = TagNameLoc; TypeSpecOwned = Owned; return false; } @@ -615,13 +501,13 @@ bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc, DiagID = diag::err_invalid_decl_spec_combination; return true; } + TSTLoc = Loc; + TSTNameLoc = Loc; if (TypeAltiVecVector && (T == TST_bool) && !TypeAltiVecBool) { TypeAltiVecBool = true; - TSTLoc = Loc; return false; } TypeSpecType = T; - TSTLoc = Loc; TypeSpecOwned = false; if (TypeAltiVecVector && !TypeAltiVecBool && (TypeSpecType == TST_double)) { PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType); @@ -653,6 +539,7 @@ bool DeclSpec::SetTypeAltiVecPixel(bool isAltiVecPixel, SourceLocation Loc, } TypeAltiVecPixel = isAltiVecPixel; TSTLoc = Loc; + TSTNameLoc = Loc; return false; } @@ -660,6 +547,7 @@ bool DeclSpec::SetTypeSpecError() { TypeSpecType = TST_error; TypeSpecOwned = false; TSTLoc = SourceLocation(); + TSTNameLoc = SourceLocation(); return false; } @@ -929,6 +817,8 @@ void UnqualifiedId::setOperatorFunctionId(SourceLocation OperatorLoc, bool VirtSpecifiers::SetSpecifier(Specifier VS, SourceLocation Loc, const char *&PrevSpec) { + LastLocation = Loc; + if (Specifiers & VS) { PrevSpec = getSpecifierName(VS); return true; @@ -940,7 +830,6 @@ bool VirtSpecifiers::SetSpecifier(Specifier VS, SourceLocation Loc, default: assert(0 && "Unknown specifier!"); case VS_Override: VS_overrideLoc = Loc; break; case VS_Final: VS_finalLoc = Loc; break; - case VS_New: VS_newLoc = Loc; break; } return false; @@ -951,33 +840,5 @@ const char *VirtSpecifiers::getSpecifierName(Specifier VS) { default: assert(0 && "Unknown specifier"); case VS_Override: return "override"; case VS_Final: return "final"; - case VS_New: return "new"; } } - -bool ClassVirtSpecifiers::SetSpecifier(Specifier CVS, SourceLocation Loc, - const char *&PrevSpec) { - if (Specifiers & CVS) { - PrevSpec = getSpecifierName(CVS); - return true; - } - - Specifiers |= CVS; - - switch (CVS) { - default: assert(0 && "Unknown specifier!"); - case CVS_Final: CVS_finalLoc = Loc; break; - case CVS_Explicit: CVS_explicitLoc = Loc; break; - } - - return false; -} - -const char *ClassVirtSpecifiers::getSpecifierName(Specifier CVS) { - switch (CVS) { - default: assert(0 && "Unknown specifier"); - case CVS_Final: return "final"; - case CVS_Explicit: return "explicit"; - } -} - diff --git a/contrib/llvm/tools/clang/lib/Sema/DelayedDiagnostic.cpp b/contrib/llvm/tools/clang/lib/Sema/DelayedDiagnostic.cpp new file mode 100644 index 0000000..af548fe --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/DelayedDiagnostic.cpp @@ -0,0 +1,51 @@ +//===--- 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 <string.h> +using namespace clang; +using namespace sema; + +DelayedDiagnostic DelayedDiagnostic::makeDeprecation(SourceLocation Loc, + const NamedDecl *D, + llvm::StringRef Msg) { + DelayedDiagnostic DD; + DD.Kind = Deprecation; + DD.Triggered = false; + DD.Loc = Loc; + DD.DeprecationData.Decl = D; + 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; + } +} diff --git a/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp b/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp index 3f16ed7..95420a3 100644 --- a/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp @@ -104,7 +104,8 @@ IdentifierResolver::~IdentifierResolver() { /// 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) const { + ASTContext &Context, Scope *S, + bool ExplicitInstantiationOrSpecialization) const { Ctx = Ctx->getRedeclContext(); if (Ctx->isFunctionOrMethod()) { @@ -135,7 +136,10 @@ bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx, return false; } - return D->getDeclContext()->getRedeclContext()->Equals(Ctx); + DeclContext *DCtx = D->getDeclContext()->getRedeclContext(); + return ExplicitInstantiationOrSpecialization + ? Ctx->InEnclosingNamespaceSetOf(DCtx) + : Ctx->Equals(DCtx); } /// AddDecl - Link the decl to its shadowed decl chain. @@ -164,6 +168,44 @@ void IdentifierResolver::AddDecl(NamedDecl *D) { IDI->AddDecl(D); } +void IdentifierResolver::InsertDeclAfter(iterator Pos, NamedDecl *D) { + DeclarationName Name = D->getDeclName(); + void *Ptr = Name.getFETokenInfo<void>(); + + 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<NamedDecl*>(Ptr); + RemoveDecl(PrevD); + AddDecl(D); + AddDecl(PrevD); + } else { + // Add new declaration after the existing declaration. + AddDecl(D); + } + + return; + } + + if (IdentifierInfo *II = Name.getAsIdentifierInfo()) + II->setIsFromAST(false); + + // 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) { diff --git a/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp b/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp index b73f0e9..867d78f 100644 --- a/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp @@ -149,6 +149,11 @@ static std::pair<unsigned,unsigned> return std::make_pair((unsigned) diag::note_protected_by_vla_typedef, 0); } + if (const TypeAliasDecl *TD = dyn_cast<TypeAliasDecl>(D)) { + if (TD->getUnderlyingType()->isVariablyModifiedType()) + return std::make_pair((unsigned) diag::note_protected_by_vla_type_alias, 0); + } + return std::make_pair(0U, 0U); } diff --git a/contrib/llvm/tools/clang/lib/Sema/Scope.cpp b/contrib/llvm/tools/clang/lib/Sema/Scope.cpp new file mode 100644 index 0000000..833a59f --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/Scope.cpp @@ -0,0 +1,57 @@ +//===- 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) { + Depth = parent->Depth + 1; + PrototypeDepth = parent->PrototypeDepth; + PrototypeIndex = 0; + FnParent = parent->FnParent; + BreakParent = parent->BreakParent; + ContinueParent = parent->ContinueParent; + ControlParent = parent->ControlParent; + BlockParent = parent->BlockParent; + TemplateParamParent = parent->TemplateParamParent; + } else { + Depth = 0; + PrototypeDepth = 0; + PrototypeIndex = 0; + FnParent = BreakParent = ContinueParent = BlockParent = 0; + ControlParent = 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 & ControlScope) ControlParent = 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(); +} diff --git a/contrib/llvm/tools/clang/lib/Sema/Sema.cpp b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp index 0c39e13..7707fb1 100644 --- a/contrib/llvm/tools/clang/lib/Sema/Sema.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp @@ -67,12 +67,14 @@ void Sema::ActOnTranslationUnitScope(Scope *S) { TInfo = Context.getTrivialTypeSourceInfo(Context.Int128Ty); PushOnScopeChains(TypedefDecl::Create(Context, CurContext, SourceLocation(), + SourceLocation(), &Context.Idents.get("__int128_t"), TInfo), TUScope); TInfo = Context.getTrivialTypeSourceInfo(Context.UnsignedInt128Ty); PushOnScopeChains(TypedefDecl::Create(Context, CurContext, SourceLocation(), + SourceLocation(), &Context.Idents.get("__uint128_t"), TInfo), TUScope); Context.setInt128Installed(); @@ -87,7 +89,8 @@ void Sema::ActOnTranslationUnitScope(Scope *S) { QualType SelT = Context.getPointerType(Context.ObjCBuiltinSelTy); TypeSourceInfo *SelInfo = Context.getTrivialTypeSourceInfo(SelT); TypedefDecl *SelTypedef - = TypedefDecl::Create(Context, CurContext, SourceLocation(), + = TypedefDecl::Create(Context, CurContext, + SourceLocation(), SourceLocation(), &Context.Idents.get("SEL"), SelInfo); PushOnScopeChains(SelTypedef, TUScope); Context.setObjCSelType(Context.getTypeDeclType(SelTypedef)); @@ -109,7 +112,8 @@ void Sema::ActOnTranslationUnitScope(Scope *S) { T = Context.getObjCObjectPointerType(T); TypeSourceInfo *IdInfo = Context.getTrivialTypeSourceInfo(T); TypedefDecl *IdTypedef - = TypedefDecl::Create(Context, CurContext, SourceLocation(), + = TypedefDecl::Create(Context, CurContext, + SourceLocation(), SourceLocation(), &Context.Idents.get("id"), IdInfo); PushOnScopeChains(IdTypedef, TUScope); Context.setObjCIdType(Context.getTypeDeclType(IdTypedef)); @@ -121,7 +125,8 @@ void Sema::ActOnTranslationUnitScope(Scope *S) { T = Context.getObjCObjectPointerType(T); TypeSourceInfo *ClassInfo = Context.getTrivialTypeSourceInfo(T); TypedefDecl *ClassTypedef - = TypedefDecl::Create(Context, CurContext, SourceLocation(), + = TypedefDecl::Create(Context, CurContext, + SourceLocation(), SourceLocation(), &Context.Idents.get("Class"), ClassInfo); PushOnScopeChains(ClassTypedef, TUScope); Context.setObjCClassType(Context.getTypeDeclType(ClassTypedef)); @@ -136,7 +141,8 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, LangOpts(pp.getLangOptions()), PP(pp), Context(ctxt), Consumer(consumer), Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()), ExternalSource(0), CodeCompleter(CodeCompleter), CurContext(0), - PackContext(0), VisContext(0), + PackContext(0), MSStructPragmaOn(false), VisContext(0), + LateTemplateParser(0), OpaqueParser(0), IdResolver(pp.getLangOptions()), CXXTypeInfoDecl(0), MSVCGuidDecl(0), GlobalNewDeleteDeclared(false), CompleteTranslationUnit(CompleteTranslationUnit), @@ -178,7 +184,7 @@ 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]; @@ -195,39 +201,58 @@ Sema::~Sema() { ExternalSema->ForgetSema(); } +ASTMutationListener *Sema::getASTMutationListener() const { + return getASTConsumer().GetASTMutationListener(); +} + /// 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. -void Sema::ImpCastExprToType(Expr *&Expr, QualType Ty, - CastKind Kind, ExprValueKind VK, - const CXXCastPath *BasePath) { - QualType ExprTy = Context.getCanonicalType(Expr->getType()); +ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty, + CastKind Kind, ExprValueKind VK, + const CXXCastPath *BasePath) { + QualType ExprTy = Context.getCanonicalType(E->getType()); QualType TypeTy = Context.getCanonicalType(Ty); if (ExprTy == TypeTy) - return; + return Owned(E); // 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 = Expr->getType(); + QualType T = E->getType(); if (const PointerType *Pointer = T->getAs<PointerType>()) T = Pointer->getPointeeType(); if (const RecordType *RecordTy = T->getAs<RecordType>()) - MarkVTableUsed(Expr->getLocStart(), + MarkVTableUsed(E->getLocStart(), cast<CXXRecordDecl>(RecordTy->getDecl())); } - if (ImplicitCastExpr *ImpCast = dyn_cast<ImplicitCastExpr>(Expr)) { + if (ImplicitCastExpr *ImpCast = dyn_cast<ImplicitCastExpr>(E)) { if (ImpCast->getCastKind() == Kind && (!BasePath || BasePath->empty())) { ImpCast->setType(Ty); ImpCast->setValueKind(VK); - return; + return Owned(E); } } - Expr = ImplicitCastExpr::Create(Context, Ty, Kind, Expr, BasePath, VK); + 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_Pointer: 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; } ExprValueKind Sema::CastCategory(Expr *E) { @@ -352,22 +377,30 @@ void Sema::ActOnEndOfTranslationUnit() { } } - // 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(); + bool SomethingChanged; + do { + SomethingChanged = false; + + // If DefinedUsedVTables ends up marking any virtual member functions it + // might lead to more pending template instantiations, which we then need + // to instantiate. + if (DefineUsedVTables()) + SomethingChanged = true; + + // 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. + if (PerformPendingInstantiations()) + SomethingChanged = true; + + } while (SomethingChanged); } // Remove file scoped decls that turned out to be used. @@ -451,16 +484,32 @@ void Sema::ActOnEndOfTranslationUnit() { const FunctionDecl *DiagD; if (!FD->hasBody(DiagD)) DiagD = FD; - Diag(DiagD->getLocation(), - isa<CXXMethodDecl>(DiagD) ? diag::warn_unused_member_function - : diag::warn_unused_function) - << DiagD->getDeclName(); + if (DiagD->isDeleted()) + continue; // Deleted functions are supposed to be unused. + if (DiagD->isReferenced()) { + if (isa<CXXMethodDecl>(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<CXXMethodDecl>(DiagD) ? diag::warn_unused_member_function + : diag::warn_unused_function) + << DiagD->getDeclName(); + } } else { const VarDecl *DiagD = cast<VarDecl>(*I)->getDefinition(); if (!DiagD) DiagD = cast<VarDecl>(*I); - Diag(DiagD->getLocation(), diag::warn_unused_variable) - << DiagD->getDeclName(); + 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(); + } } } @@ -585,6 +634,27 @@ Sema::Diag(SourceLocation Loc, const PartialDiagnostic& PD) { return Builder; } +/// \brief Looks through the macro-instantiation chain for the given +/// location, looking for a macro instantiation with the given name. +/// If one is found, returns true and sets the location to that +/// instantiation loc. +bool Sema::findMacroSpelling(SourceLocation &locref, llvm::StringRef name) { + SourceLocation loc = locref; + if (!loc.isMacroID()) return false; + + // There's no good way right now to look at the intermediate + // instantiations, so just jump to the instantiation location. + loc = getSourceManager().getInstantiationLoc(loc); + + // If that's written with the name, stop here. + llvm::SmallVector<char, 16> buffer; + if (getPreprocessor().getSpelling(loc, buffer) == name) { + locref = loc; + return true; + } + return false; +} + /// \brief Determines the active Scope associated with the given declaration /// context. /// diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp index 4f9bf1c..411d424 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp @@ -1011,16 +1011,16 @@ static void DiagnoseAccessPath(Sema &S, // Find an original declaration. while (D->isOutOfLine()) { NamedDecl *PrevDecl = 0; - if (isa<VarDecl>(D)) - PrevDecl = cast<VarDecl>(D)->getPreviousDeclaration(); - else if (isa<FunctionDecl>(D)) - PrevDecl = cast<FunctionDecl>(D)->getPreviousDeclaration(); - else if (isa<TypedefDecl>(D)) - PrevDecl = cast<TypedefDecl>(D)->getPreviousDeclaration(); - else if (isa<TagDecl>(D)) { + if (VarDecl *VD = dyn_cast<VarDecl>(D)) + PrevDecl = VD->getPreviousDeclaration(); + else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) + PrevDecl = FD->getPreviousDeclaration(); + else if (TypedefNameDecl *TND = dyn_cast<TypedefNameDecl>(D)) + PrevDecl = TND->getPreviousDeclaration(); + else if (TagDecl *TD = dyn_cast<TagDecl>(D)) { if (isa<RecordDecl>(D) && cast<RecordDecl>(D)->isInjectedClassName()) break; - PrevDecl = cast<TagDecl>(D)->getPreviousDeclaration(); + PrevDecl = TD->getPreviousDeclaration(); } if (!PrevDecl) break; D = PrevDecl; diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp index 794b0b1..53dd297 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp @@ -129,6 +129,12 @@ void Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) { } } +void Sema::AddMsStructLayoutForRecord(RecordDecl *RD) { + if (!MSStructPragmaOn) + return; + RD->addAttr(::new (Context) MsStructAttr(SourceLocation(), Context)); +} + void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind, SourceLocation PragmaLoc, SourceLocation KindLoc) { @@ -263,6 +269,10 @@ void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name, } } +void Sema::ActOnPragmaMSStruct(PragmaMSStructKind Kind) { + MSStructPragmaOn = (Kind == PMSST_ON); +} + void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope, SourceLocation PragmaLoc) { @@ -297,7 +307,7 @@ void Sema::AddPushedVisibilityAttribute(Decl *D) { if (!VisContext) return; - if (D->hasAttr<VisibilityAttr>()) + if (isa<NamedDecl>(D) && cast<NamedDecl>(D)->getExplicitVisibility()) return; VisStack *Stack = static_cast<VisStack*>(VisContext); diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCXXCast.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCXXCast.cpp index 506d261..ed54f0f 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaCXXCast.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaCXXCast.cpp @@ -42,21 +42,21 @@ enum CastType { -static void CheckConstCast(Sema &Self, Expr *&SrcExpr, QualType DestType, +static void CheckConstCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, ExprValueKind &VK, const SourceRange &OpRange, const SourceRange &DestRange); -static void CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType, +static void CheckReinterpretCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, ExprValueKind &VK, const SourceRange &OpRange, const SourceRange &DestRange, CastKind &Kind); -static void CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType, +static void CheckStaticCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, ExprValueKind &VK, const SourceRange &OpRange, CastKind &Kind, CXXCastPath &BasePath); -static void CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType, +static void CheckDynamicCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, ExprValueKind &VK, const SourceRange &OpRange, const SourceRange &DestRange, @@ -100,7 +100,7 @@ static TryCastResult TryStaticDowncast(Sema &Self, CanQualType SrcType, QualType OrigDestType, unsigned &msg, CastKind &Kind, CXXCastPath &BasePath); -static TryCastResult TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr, +static TryCastResult TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, QualType SrcType, QualType DestType,bool CStyle, const SourceRange &OpRange, @@ -108,12 +108,12 @@ static TryCastResult TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr, CastKind &Kind, CXXCastPath &BasePath); -static TryCastResult TryStaticImplicitCast(Sema &Self, Expr *&SrcExpr, +static TryCastResult TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, bool CStyle, const SourceRange &OpRange, unsigned &msg, CastKind &Kind); -static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr, +static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, bool CStyle, const SourceRange &OpRange, unsigned &msg, @@ -121,24 +121,13 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr, CXXCastPath &BasePath); static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType, bool CStyle, unsigned &msg); -static TryCastResult TryReinterpretCast(Sema &Self, Expr *&SrcExpr, +static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, bool CStyle, const SourceRange &OpRange, unsigned &msg, CastKind &Kind); -static ExprResult -ResolveAndFixSingleFunctionTemplateSpecialization( - Sema &Self, Expr *SrcExpr, - bool DoFunctionPointerConverion = false, - bool Complain = false, - const SourceRange& OpRangeForComplaining = SourceRange(), - QualType DestTypeForComplaining = QualType(), - unsigned DiagIDForComplaining = 0); - - - /// ActOnCXXNamedCast - Parse {dynamic,static,reinterpret,const}_cast's. ExprResult Sema::ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, @@ -159,8 +148,9 @@ Sema::ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, ExprResult Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, - TypeSourceInfo *DestTInfo, Expr *Ex, + TypeSourceInfo *DestTInfo, Expr *E, SourceRange AngleBrackets, SourceRange Parens) { + ExprResult Ex = Owned(E); QualType DestType = DestTInfo->getType(); SourceRange OpRange(OpLoc, Parens.getEnd()); @@ -168,11 +158,7 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, // 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->isTypeDependent(); - - if (Ex->isBoundMemberFunction(Context)) - Diag(Ex->getLocStart(), diag::err_invalid_use_of_bound_member_func) - << Ex->getSourceRange(); + bool TypeDependent = DestType->isDependentType() || Ex.get()->isTypeDependent(); ExprValueKind VK = VK_RValue; if (TypeDependent) @@ -182,42 +168,54 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, default: llvm_unreachable("Unknown C++ cast!"); case tok::kw_const_cast: - if (!TypeDependent) + if (!TypeDependent) { CheckConstCast(*this, Ex, DestType, VK, OpRange, DestRange); + if (Ex.isInvalid()) + return ExprError(); + } return Owned(CXXConstCastExpr::Create(Context, DestType.getNonLValueExprType(Context), - VK, Ex, DestTInfo, OpLoc, + VK, Ex.take(), DestTInfo, OpLoc, Parens.getEnd())); case tok::kw_dynamic_cast: { CastKind Kind = CK_Dependent; CXXCastPath BasePath; - if (!TypeDependent) + if (!TypeDependent) { CheckDynamicCast(*this, Ex, DestType, VK, OpRange, DestRange, Kind, BasePath); + if (Ex.isInvalid()) + return ExprError(); + } return Owned(CXXDynamicCastExpr::Create(Context, DestType.getNonLValueExprType(Context), - VK, Kind, Ex, &BasePath, DestTInfo, + VK, Kind, Ex.take(), &BasePath, DestTInfo, OpLoc, Parens.getEnd())); } case tok::kw_reinterpret_cast: { CastKind Kind = CK_Dependent; - if (!TypeDependent) + if (!TypeDependent) { CheckReinterpretCast(*this, Ex, DestType, VK, OpRange, DestRange, Kind); + if (Ex.isInvalid()) + return ExprError(); + } return Owned(CXXReinterpretCastExpr::Create(Context, DestType.getNonLValueExprType(Context), - VK, Kind, Ex, 0, + VK, Kind, Ex.take(), 0, DestTInfo, OpLoc, Parens.getEnd())); } case tok::kw_static_cast: { CastKind Kind = CK_Dependent; CXXCastPath BasePath; - if (!TypeDependent) + if (!TypeDependent) { CheckStaticCast(*this, Ex, DestType, VK, OpRange, Kind, BasePath); + if (Ex.isInvalid()) + return ExprError(); + } return Owned(CXXStaticCastExpr::Create(Context, DestType.getNonLValueExprType(Context), - VK, Kind, Ex, &BasePath, + VK, Kind, Ex.take(), &BasePath, DestTInfo, OpLoc, Parens.getEnd())); } } @@ -303,6 +301,11 @@ static bool tryDiagnoseOverloadedCast(Sema &S, CastType CT, /// Diagnose a failed cast. static void diagnoseBadCast(Sema &S, unsigned msg, CastType castType, SourceRange opRange, Expr *src, QualType destType) { + 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)) return; @@ -388,15 +391,17 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType) { UnwrappedDestType = Self.Context.getCanonicalType(DestType); llvm::SmallVector<Qualifiers, 8> cv1, cv2; - // Find the qualifications. + // 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)) { Qualifiers SrcQuals; Self.Context.getUnqualifiedArrayType(UnwrappedSrcType, SrcQuals); - cv1.push_back(SrcQuals); + cv1.push_back(Qualifiers::fromCVRMask(SrcQuals.getCVRQualifiers())); Qualifiers DestQuals; Self.Context.getUnqualifiedArrayType(UnwrappedDestType, DestQuals); - cv2.push_back(DestQuals); + cv2.push_back(Qualifiers::fromCVRMask(DestQuals.getCVRQualifiers())); } if (cv1.empty()) return false; @@ -424,11 +429,11 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType) { /// Refer to C++ 5.2.7 for details. Dynamic casts are used mostly for runtime- /// checked downcasts in class hierarchies. static void -CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType, +CheckDynamicCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, ExprValueKind &VK, const SourceRange &OpRange, const SourceRange &DestRange, CastKind &Kind, CXXCastPath &BasePath) { - QualType OrigDestType = DestType, OrigSrcType = SrcExpr->getType(); + QualType OrigDestType = DestType, OrigSrcType = SrcExpr.get()->getType(); DestType = Self.Context.getCanonicalType(DestType); // C++ 5.2.7p1: T shall be a pointer or reference to a complete class type, @@ -475,11 +480,11 @@ CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType, SrcPointee = SrcPointer->getPointeeType(); } else { Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_ptr) - << OrigSrcType << SrcExpr->getSourceRange(); + << OrigSrcType << SrcExpr.get()->getSourceRange(); return; } } else if (DestReference->isLValueReferenceType()) { - if (!SrcExpr->isLValue()) { + if (!SrcExpr.get()->isLValue()) { Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_rvalue) << CT_Dynamic << OrigSrcType << OrigDestType << OpRange; } @@ -492,11 +497,11 @@ CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType, if (SrcRecord) { if (Self.RequireCompleteType(OpRange.getBegin(), SrcPointee, Self.PDiag(diag::err_bad_dynamic_cast_incomplete) - << SrcExpr->getSourceRange())) + << SrcExpr.get()->getSourceRange())) return; } else { Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_class) - << SrcPointee.getUnqualifiedType() << SrcExpr->getSourceRange(); + << SrcPointee.getUnqualifiedType() << SrcExpr.get()->getSourceRange(); return; } @@ -508,7 +513,7 @@ CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType, // 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_const_away) + Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_qualifiers_away) << CT_Dynamic << OrigSrcType << OrigDestType << OpRange; return; } @@ -543,7 +548,7 @@ CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType, assert(SrcDecl && "Definition missing"); if (!cast<CXXRecordDecl>(SrcDecl)->isPolymorphic()) { Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_polymorphic) - << SrcPointee.getUnqualifiedType() << SrcExpr->getSourceRange(); + << SrcPointee.getUnqualifiedType() << SrcExpr.get()->getSourceRange(); } Self.MarkVTableUsed(OpRange.getBegin(), cast<CXXRecordDecl>(SrcRecord->getDecl())); @@ -558,17 +563,20 @@ CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType, /// const char *str = "literal"; /// legacy_function(const_cast\<char*\>(str)); void -CheckConstCast(Sema &Self, Expr *&SrcExpr, QualType DestType, ExprValueKind &VK, +CheckConstCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, ExprValueKind &VK, const SourceRange &OpRange, const SourceRange &DestRange) { VK = Expr::getValueKindForType(DestType); - if (VK == VK_RValue) - Self.DefaultFunctionArrayLvalueConversion(SrcExpr); + if (VK == VK_RValue) { + 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; - if (TryConstCast(Self, SrcExpr, DestType, /*CStyle*/false, msg) != TC_Success + if (TryConstCast(Self, SrcExpr.get(), DestType, /*CStyle*/false, msg) != TC_Success && msg != 0) Self.Diag(OpRange.getBegin(), msg) << CT_Const - << SrcExpr->getType() << DestType << OpRange; + << SrcExpr.get()->getType() << DestType << OpRange; } /// CheckReinterpretCast - Check that a reinterpret_cast\<DestType\>(SrcExpr) is @@ -577,27 +585,32 @@ CheckConstCast(Sema &Self, Expr *&SrcExpr, QualType DestType, ExprValueKind &VK, /// like this: /// char *bytes = reinterpret_cast\<char*\>(int_ptr); void -CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType, +CheckReinterpretCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, ExprValueKind &VK, const SourceRange &OpRange, const SourceRange &DestRange, CastKind &Kind) { VK = Expr::getValueKindForType(DestType); - if (VK == VK_RValue) - Self.DefaultFunctionArrayLvalueConversion(SrcExpr); + if (VK == VK_RValue) { + 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; if (TryReinterpretCast(Self, SrcExpr, DestType, /*CStyle*/false, OpRange, msg, Kind) != TC_Success && msg != 0) { - if (SrcExpr->getType() == Self.Context.OverloadTy) { + if (SrcExpr.isInvalid()) // if conversion failed, don't report another error + return; + if (SrcExpr.get()->getType() == Self.Context.OverloadTy) { //FIXME: &f<int>; is overloaded and resolvable Self.Diag(OpRange.getBegin(), diag::err_bad_reinterpret_cast_overload) - << OverloadExpr::find(SrcExpr).Expression->getName() + << OverloadExpr::find(SrcExpr.get()).Expression->getName() << DestType << OpRange; - Self.NoteAllOverloadCandidates(SrcExpr); + Self.NoteAllOverloadCandidates(SrcExpr.get()); } else { - diagnoseBadCast(Self, msg, CT_Reinterpret, OpRange, SrcExpr, DestType); + diagnoseBadCast(Self, msg, CT_Reinterpret, OpRange, SrcExpr.get(), DestType); } } } @@ -607,23 +620,25 @@ CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType, /// 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 -CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType, +CheckStaticCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, ExprValueKind &VK, const SourceRange &OpRange, CastKind &Kind, CXXCastPath &BasePath) { // This test is outside everything else because it's the only case where // a non-lvalue-reference target type does not lead to decay. // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void". if (DestType->isVoidType()) { - Self.IgnoredValueConversions(SrcExpr); - if (SrcExpr->getType() == Self.Context.OverloadTy) { + SrcExpr = Self.IgnoredValueConversions(SrcExpr.take()); + if (SrcExpr.isInvalid()) // if conversion failed, don't report another error + return; + if (SrcExpr.get()->getType() == Self.Context.OverloadTy) { ExprResult SingleFunctionExpression = - ResolveAndFixSingleFunctionTemplateSpecialization(Self, SrcExpr, + Self.ResolveAndFixSingleFunctionTemplateSpecialization(SrcExpr.get(), false, // Decay Function to ptr true, // Complain OpRange, DestType, diag::err_bad_static_cast_overload); if (SingleFunctionExpression.isUsable()) { - SrcExpr = SingleFunctionExpression.release(); + SrcExpr = SingleFunctionExpression; Kind = CK_ToVoid; } } @@ -633,29 +648,35 @@ CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType, } VK = Expr::getValueKindForType(DestType); - if (VK == VK_RValue && !DestType->isRecordType()) - Self.DefaultFunctionArrayLvalueConversion(SrcExpr); + if (VK == VK_RValue && !DestType->isRecordType()) { + 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; if (TryStaticCast(Self, SrcExpr, DestType, /*CStyle*/false, OpRange, msg, Kind, BasePath) != TC_Success && msg != 0) { - if (SrcExpr->getType() == Self.Context.OverloadTy) { - OverloadExpr* oe = OverloadExpr::find(SrcExpr).Expression; + 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->getQualifierRange(); - Self.NoteAllOverloadCandidates(SrcExpr); + << oe->getName() << DestType << OpRange + << oe->getQualifierLoc().getSourceRange(); + Self.NoteAllOverloadCandidates(SrcExpr.get()); } else { - diagnoseBadCast(Self, msg, CT_Static, OpRange, SrcExpr, DestType); + diagnoseBadCast(Self, msg, CT_Static, OpRange, SrcExpr.get(), DestType); } } else if (Kind == CK_BitCast) - Self.CheckCastAlign(SrcExpr, DestType, OpRange); + Self.CheckCastAlign(SrcExpr.get(), DestType, OpRange); } /// 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, Expr *&SrcExpr, +static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, bool CStyle, const SourceRange &OpRange, unsigned &msg, CastKind &Kind, @@ -680,7 +701,7 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr, // 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, DestType, CStyle, OpRange, + tcr = TryStaticReferenceDowncast(Self, SrcExpr.get(), DestType, CStyle, OpRange, msg, Kind, BasePath); if (tcr != TC_NotApplicable) return tcr; @@ -688,7 +709,7 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr, // 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, DestType, CStyle, Kind, BasePath, + tcr = TryLValueToRValueCast(Self, SrcExpr.get(), DestType, CStyle, Kind, BasePath, msg); if (tcr != TC_NotApplicable) return tcr; @@ -697,6 +718,8 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr, // [...] if the declaration "T t(e);" is well-formed, [...]. tcr = TryStaticImplicitCast(Self, SrcExpr, DestType, CStyle, OpRange, msg, Kind); + if (SrcExpr.isInvalid()) + return TC_Failed; if (tcr != TC_NotApplicable) return tcr; @@ -708,7 +731,7 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr, // In the CStyle case, the earlier attempt to const_cast should have taken // care of reverse qualification conversions. - QualType SrcType = Self.Context.getCanonicalType(SrcExpr->getType()); + 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 @@ -772,7 +795,7 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr, // This is definitely the intended conversion, but it might fail due // to a const violation. if (!CStyle && !DestPointee.isAtLeastAsQualifiedAs(SrcPointee)) { - msg = diag::err_bad_cxx_cast_const_away; + msg = diag::err_bad_cxx_cast_qualifiers_away; return TC_Failed; } Kind = CK_BitCast; @@ -963,7 +986,7 @@ TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType, // Must preserve cv, as always, unless we're in C-style mode. if (!CStyle && !DestType.isAtLeastAsQualifiedAs(SrcType)) { - msg = diag::err_bad_cxx_cast_const_away; + msg = diag::err_bad_cxx_cast_qualifiers_away; return TC_Failed; } @@ -1038,7 +1061,7 @@ TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType, /// where B is a base class of D [...]. /// TryCastResult -TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr, QualType SrcType, +TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, QualType SrcType, QualType DestType, bool CStyle, const SourceRange &OpRange, unsigned &msg, CastKind &Kind, @@ -1049,9 +1072,9 @@ TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr, QualType SrcType, bool WasOverloadedFunction = false; DeclAccessPair FoundOverload; - if (SrcExpr->getType() == Self.Context.OverloadTy) { + if (SrcExpr.get()->getType() == Self.Context.OverloadTy) { if (FunctionDecl *Fn - = Self.ResolveAddressOfOverloadedFunction(SrcExpr, DestType, false, + = Self.ResolveAddressOfOverloadedFunction(SrcExpr.get(), DestType, false, FoundOverload)) { CXXMethodDecl *M = cast<CXXMethodDecl>(Fn); SrcType = Self.Context.getMemberPointerType(Fn->getType(), @@ -1122,7 +1145,7 @@ TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr, QualType SrcType, if (WasOverloadedFunction) { // Resolve the address of the overloaded function again, this time // allowing complaints if something goes wrong. - FunctionDecl *Fn = Self.ResolveAddressOfOverloadedFunction(SrcExpr, + FunctionDecl *Fn = Self.ResolveAddressOfOverloadedFunction(SrcExpr.get(), DestType, true, FoundOverload); @@ -1132,7 +1155,7 @@ TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr, QualType SrcType, } SrcExpr = Self.FixOverloadedFunctionReference(SrcExpr, FoundOverload, Fn); - if (!SrcExpr) { + if (!SrcExpr.isUsable()) { msg = 0; return TC_Failed; } @@ -1149,7 +1172,7 @@ TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr, QualType SrcType, /// 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, Expr *&SrcExpr, QualType DestType, +TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, bool CStyle, const SourceRange &OpRange, unsigned &msg, CastKind &Kind) { if (DestType->isRecordType()) { @@ -1163,7 +1186,8 @@ TryStaticImplicitCast(Sema &Self, Expr *&SrcExpr, QualType DestType, InitializedEntity Entity = InitializedEntity::InitializeTemporary(DestType); InitializationKind InitKind = InitializationKind::CreateCast(/*FIXME:*/OpRange, CStyle); - InitializationSequence InitSeq(Self, Entity, InitKind, &SrcExpr, 1); + 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. @@ -1176,7 +1200,7 @@ TryStaticImplicitCast(Sema &Self, Expr *&SrcExpr, QualType DestType, return TC_NotApplicable; ExprResult Result - = InitSeq.Perform(Self, Entity, InitKind, MultiExprArg(Self, &SrcExpr, 1)); + = InitSeq.Perform(Self, Entity, InitKind, MultiExprArg(Self, &SrcExprRaw, 1)); if (Result.isInvalid()) { msg = 0; return TC_Failed; @@ -1187,7 +1211,7 @@ TryStaticImplicitCast(Sema &Self, Expr *&SrcExpr, QualType DestType, else Kind = CK_NoOp; - SrcExpr = Result.takeAs<Expr>(); + SrcExpr = move(Result); return TC_Success; } @@ -1240,16 +1264,21 @@ static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType, // Unwrap the pointers. Ignore qualifiers. Terminate early if the types are // completely equal. - // FIXME: const_cast should probably not be able to convert between pointers - // to different address spaces. // 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 Quals; - SrcType = Self.Context.getUnqualifiedArrayType(SrcType, Quals); - DestType = Self.Context.getUnqualifiedArrayType(DestType, Quals); + 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. @@ -1259,43 +1288,8 @@ static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType, return TC_Success; } -// A helper function to 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 -static ExprResult ResolveAndFixSingleFunctionTemplateSpecialization( - Sema &Self, Expr *SrcExpr, - bool DoFunctionPointerConverion, - bool Complain, - const SourceRange& OpRangeForComplaining, - QualType DestTypeForComplaining, - unsigned DiagIDForComplaining) { - assert(SrcExpr->getType() == Self.Context.OverloadTy); - DeclAccessPair Found; - Expr* SingleFunctionExpression = 0; - if (FunctionDecl* Fn = Self.ResolveSingleFunctionTemplateSpecialization( - SrcExpr, false, // false -> Complain - &Found)) { - if (!Self.DiagnoseUseOfDecl(Fn, SrcExpr->getSourceRange().getBegin())) { - // mark the expression as resolved to Fn - SingleFunctionExpression = Self.FixOverloadedFunctionReference(SrcExpr, - Found, Fn); - - if (DoFunctionPointerConverion) - Self.DefaultFunctionArrayLvalueConversion(SingleFunctionExpression); - } - } - if (!SingleFunctionExpression && Complain) { - OverloadExpr* oe = OverloadExpr::find(SrcExpr).Expression; - Self.Diag(OpRangeForComplaining.getBegin(), DiagIDForComplaining) - << oe->getName() << DestTypeForComplaining << OpRangeForComplaining - << oe->getQualifierRange(); - Self.NoteAllOverloadCandidates(SrcExpr); - } - return SingleFunctionExpression; -} -static TryCastResult TryReinterpretCast(Sema &Self, Expr *&SrcExpr, +static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, bool CStyle, const SourceRange &OpRange, unsigned &msg, @@ -1303,19 +1297,19 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *&SrcExpr, bool IsLValueCast = false; DestType = Self.Context.getCanonicalType(DestType); - QualType SrcType = SrcExpr->getType(); + 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<int> resolves to an lvalue unambiguously ExprResult SingleFunctionExpr = - ResolveAndFixSingleFunctionTemplateSpecialization(Self, SrcExpr, + Self.ResolveAndFixSingleFunctionTemplateSpecialization(SrcExpr.get(), Expr::getValueKindForType(DestType) == VK_RValue // Convert Fun to Ptr ); if (SingleFunctionExpr.isUsable()) { - SrcExpr = SingleFunctionExpr.release(); - SrcType = SrcExpr->getType(); + SrcExpr = move(SingleFunctionExpr); + SrcType = SrcExpr.get()->getType(); } else return TC_NotApplicable; @@ -1323,7 +1317,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *&SrcExpr, if (const ReferenceType *DestTypeTmp = DestType->getAs<ReferenceType>()) { bool LValue = DestTypeTmp->isLValueReferenceType(); - if (LValue && !SrcExpr->isLValue()) { + 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; @@ -1333,6 +1327,23 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *&SrcExpr, // C++ 5.2.10p10: [...] a reference cast reinterpret_cast<T&>(x) has the // same effect as the conversion *reinterpret_cast<T*>(&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; + } + 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); @@ -1359,7 +1370,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *&SrcExpr, // A reinterpret_cast followed by a const_cast can, though, so in C-style, // we accept it. if (!CStyle && CastsAwayConstness(Self, SrcType, DestType)) { - msg = diag::err_bad_cxx_cast_const_away; + msg = diag::err_bad_cxx_cast_qualifiers_away; return TC_Failed; } @@ -1472,7 +1483,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *&SrcExpr, // C++ 5.2.10p2: The reinterpret_cast operator shall not cast away constness. // The C-style cast operator can. if (!CStyle && CastsAwayConstness(Self, SrcType, DestType)) { - msg = diag::err_bad_cxx_cast_const_away; + msg = diag::err_bad_cxx_cast_qualifiers_away; return TC_Failed; } @@ -1525,39 +1536,39 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *&SrcExpr, return TC_Success; } -bool +ExprResult Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK, - Expr *&CastExpr, CastKind &Kind, + Expr *CastExpr, CastKind &Kind, CXXCastPath &BasePath, bool FunctionalStyle) { - if (CastExpr->isBoundMemberFunction(Context)) - return Diag(CastExpr->getLocStart(), - diag::err_invalid_use_of_bound_member_func) - << CastExpr->getSourceRange(); - // This test is outside everything else because it's the only case where // a non-lvalue-reference target type does not lead to decay. // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void". if (CastTy->isVoidType()) { - IgnoredValueConversions(CastExpr); - bool ret = false; // false is 'able to convert' + Kind = CK_ToVoid; + + ExprResult CastExprRes = IgnoredValueConversions(CastExpr); + if (CastExprRes.isInvalid()) + return ExprError(); + CastExpr = CastExprRes.take(); + + if (CastExpr->getType() == Context.BoundMemberTy) + return CheckPlaceholderExpr(CastExpr); // will always fail + if (CastExpr->getType() == Context.OverloadTy) { ExprResult SingleFunctionExpr = - ResolveAndFixSingleFunctionTemplateSpecialization(*this, - CastExpr, - /* Decay Function to ptr */ false, - /* Complain */ true, - R, CastTy, diag::err_bad_cstyle_cast_overload); - if (SingleFunctionExpr.isUsable()) { - CastExpr = SingleFunctionExpr.release(); - Kind = CK_ToVoid; - } - else - ret = true; + ResolveAndFixSingleFunctionTemplateSpecialization( + CastExpr, /* Decay Function to ptr */ false, + /* Complain */ true, R, CastTy, + diag::err_bad_cstyle_cast_overload); + if (SingleFunctionExpr.isInvalid()) + return ExprError(); + CastExpr = SingleFunctionExpr.take(); } - else - Kind = CK_ToVoid; - return ret; + + assert(!CastExpr->getType()->isPlaceholderType()); + + return Owned(CastExpr); } // Make sure we determine the value kind before we bail out for @@ -1567,11 +1578,24 @@ Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK, // If the type is dependent, we won't do any other semantic analysis now. if (CastTy->isDependentType() || CastExpr->isTypeDependent()) { Kind = CK_Dependent; - return false; + return Owned(CastExpr); + } + + if (VK == VK_RValue && !CastTy->isRecordType()) { + ExprResult CastExprRes = DefaultFunctionArrayLvalueConversion(CastExpr); + if (CastExprRes.isInvalid()) + return ExprError(); + CastExpr = CastExprRes.take(); } - if (VK == VK_RValue && !CastTy->isRecordType()) - DefaultFunctionArrayLvalueConversion(CastExpr); + // AltiVec vector initialization with a single literal. + if (const VectorType *vecTy = CastTy->getAs<VectorType>()) + if (vecTy->getVectorKind() == VectorType::AltiVecVector + && (CastExpr->getType()->isIntegerType() + || CastExpr->getType()->isFloatingType())) { + Kind = CK_VectorSplat; + return Owned(CastExpr); + } // C++ [expr.cast]p5: The conversions performed by // - a const_cast, @@ -1592,25 +1616,32 @@ Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK, if (tcr == TC_NotApplicable) { // ... or if that is not possible, a static_cast, ignoring const, ... - tcr = TryStaticCast(*this, CastExpr, CastTy, /*CStyle*/true, R, msg, Kind, - BasePath); + ExprResult CastExprRes = Owned(CastExpr); + tcr = TryStaticCast(*this, CastExprRes, CastTy, /*CStyle*/true, R, msg, + Kind, BasePath); + if (CastExprRes.isInvalid()) + return ExprError(); + CastExpr = CastExprRes.take(); if (tcr == TC_NotApplicable) { // ... and finally a reinterpret_cast, ignoring const. - tcr = TryReinterpretCast(*this, CastExpr, CastTy, /*CStyle*/true, R, msg, - Kind); + CastExprRes = Owned(CastExpr); + tcr = TryReinterpretCast(*this, CastExprRes, CastTy, /*CStyle*/true, R, + msg, Kind); + if (CastExprRes.isInvalid()) + return ExprError(); + CastExpr = CastExprRes.take(); } } if (tcr != TC_Success && msg != 0) { if (CastExpr->getType() == Context.OverloadTy) { DeclAccessPair Found; - FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(CastExpr, + FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(CastExpr, CastTy, /* Complain */ true, Found); - assert(!Fn - && "cast failed but able to resolve overload expression!!"); + assert(!Fn && "cast failed but able to resolve overload expression!!"); (void)Fn; } else { @@ -1621,5 +1652,8 @@ Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK, else if (Kind == CK_BitCast) CheckCastAlign(CastExpr, CastTy, R); - return tcr != TC_Success; + if (tcr != TC_Success) + return ExprError(); + + return Owned(CastExpr); } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp index 7ad4b45..7049f6b 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -255,7 +255,7 @@ bool Sema::isAcceptableNestedNameSpecifier(NamedDecl *SD) { QualType T = Context.getTypeDeclType(cast<TypeDecl>(SD)); if (T->isDependentType()) return true; - else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) { + else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(SD)) { if (TD->getUnderlyingType()->isRecordType() || (Context.getLangOptions().CPlusPlus0x && TD->getUnderlyingType()->isEnumeralType())) @@ -549,7 +549,7 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, } else if (isa<RecordDecl>(SD)) { RecordTypeLoc RecordTL = TLB.push<RecordTypeLoc>(T); RecordTL.setNameLoc(IdentifierLoc); - } else if (isa<TypedefDecl>(SD)) { + } else if (isa<TypedefNameDecl>(SD)) { TypedefTypeLoc TypedefTL = TLB.push<TypedefTypeLoc>(T); TypedefTL.setNameLoc(IdentifierLoc); } else if (isa<EnumDecl>(SD)) { @@ -641,20 +641,87 @@ bool Sema::IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS, } bool Sema::ActOnCXXNestedNameSpecifier(Scope *S, - ParsedType Type, + SourceLocation TemplateLoc, + CXXScopeSpec &SS, + TemplateTy Template, + SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, + ASTTemplateArgsPtr TemplateArgsIn, + SourceLocation RAngleLoc, SourceLocation CCLoc, - CXXScopeSpec &SS) { + bool EnteringContext) { if (SS.isInvalid()) return true; - TypeSourceInfo *TSInfo; - QualType T = GetTypeFromParser(Type, &TSInfo); + // 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<NestedNameSpecifier*>(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<DependentTemplateSpecializationTypeLoc>(T); + SpecTL.setLAngleLoc(LAngleLoc); + SpecTL.setRAngleLoc(RAngleLoc); + SpecTL.setKeywordLoc(SourceLocation()); + SpecTL.setNameLoc(TemplateNameLoc); + SpecTL.setQualifierLoc(SS.getWithLocInContext(Context)); + for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) + SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo()); + + SS.Extend(Context, TemplateLoc, Builder.getTypeLocInContext(Context, T), + CCLoc); + return false; + } + + + if (Template.get().getAsOverloadedTemplate() || + isa<FunctionTemplateDecl>(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; - assert(TSInfo && "Not TypeSourceInfo in nested-name-specifier?"); - // FIXME: location of the 'template' keyword? - SS.Extend(Context, SourceLocation(), TSInfo->getTypeLoc(), CCLoc); + // FIXME: Template aliases will need to check the resulting type to make + // sure that it's either dependent or a tag type. + + // Provide source-location information for the template specialization + // type. + TypeLocBuilder Builder; + TemplateSpecializationTypeLoc SpecTL + = Builder.push<TemplateSpecializationTypeLoc>(T); + + SpecTL.setLAngleLoc(LAngleLoc); + SpecTL.setRAngleLoc(RAngleLoc); + SpecTL.setTemplateNameLoc(TemplateNameLoc); + for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) + SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo()); + + + SS.Extend(Context, TemplateLoc, Builder.getTypeLocInContext(Context, T), + CCLoc); return false; } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp index 3ffa748..5b645df 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp @@ -180,6 +180,7 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { case Builtin::BI__sync_bool_compare_and_swap: case Builtin::BI__sync_lock_test_and_set: case Builtin::BI__sync_lock_release: + case Builtin::BI__sync_swap: return SemaBuiltinAtomicOverloaded(move(TheCallResult)); } @@ -313,9 +314,14 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) { for (specific_attr_iterator<NonNullAttr> i = FDecl->specific_attr_begin<NonNullAttr>(), e = FDecl->specific_attr_end<NonNullAttr>(); i != e; ++i) { - CheckNonNullArguments(*i, TheCall); + CheckNonNullArguments(*i, TheCall->getArgs(), + TheCall->getCallee()->getLocStart()); } + // Memset handling + if (FnInfo->isStr("memset")) + CheckMemsetArguments(TheCall); + return false; } @@ -414,7 +420,8 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) { 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_lock_release), + BUILTIN_ROW(__sync_swap) }; #undef BUILTIN_ROW @@ -467,6 +474,7 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) { NumFixed = 0; ResultType = Context.VoidTy; break; + case Builtin::BI__sync_swap: BuiltinIndex = 14; break; } // Now that we know how many fixed arguments we expect, first check that we @@ -491,14 +499,14 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) { // deduce the types of the rest of the arguments accordingly. Walk // the remaining arguments, converting them to the deduced value type. for (unsigned i = 0; i != NumFixed; ++i) { - Expr *Arg = TheCall->getArg(i+1); + ExprResult Arg = TheCall->getArg(i+1); // If the argument is an implicit cast, then there was a promotion due to // "...", just remove it now. - if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg)) { + if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg.get())) { Arg = ICE->getSubExpr(); ICE->setSubExpr(0); - TheCall->setArg(i+1, Arg); + TheCall->setArg(i+1, Arg.get()); } // GCC does an implicit conversion to the pointer or integer ValType. This @@ -506,7 +514,8 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) { CastKind Kind = CK_Invalid; ExprValueKind VK = VK_RValue; CXXCastPath BasePath; - if (CheckCastTypes(Arg->getSourceRange(), ValType, Arg, Kind, VK, BasePath)) + Arg = CheckCastTypes(Arg.get()->getSourceRange(), ValType, Arg.take(), Kind, VK, BasePath); + if (Arg.isInvalid()) return ExprError(); // Okay, we have something that *can* be converted to the right type. Check @@ -515,8 +524,8 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) { // pass in 42. The 42 gets converted to char. This is even more strange // for things like 45.123 -> char, etc. // FIXME: Do this check. - ImpCastExprToType(Arg, ValType, Kind, VK, &BasePath); - TheCall->setArg(i+1, Arg); + Arg = ImpCastExprToType(Arg.take(), ValType, Kind, VK, &BasePath); + TheCall->setArg(i+1, Arg.get()); } // Switch the DeclRefExpr to refer to the new decl. @@ -525,9 +534,10 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) { // Set the callee in the CallExpr. // FIXME: This leaks the original parens and implicit casts. - Expr *PromotedCall = DRE; - UsualUnaryConversions(PromotedCall); - TheCall->setCallee(PromotedCall); + ExprResult PromotedCall = UsualUnaryConversions(DRE); + 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 @@ -552,12 +562,6 @@ bool Sema::CheckObjCString(Expr *Arg) { return true; } - size_t NulPos = Literal->getString().find('\0'); - if (NulPos != llvm::StringRef::npos) { - Diag(getLocationOfStringLiteralByte(Literal, NulPos), - diag::warn_cfstring_literal_contains_nul_character) - << Arg->getSourceRange(); - } if (Literal->containsNonAsciiOrNull()) { llvm::StringRef String = Literal->getString(); unsigned NumBytes = String.size(); @@ -650,29 +654,31 @@ bool Sema::SemaBuiltinUnorderedCompare(CallExpr *TheCall) { << SourceRange(TheCall->getArg(2)->getLocStart(), (*(TheCall->arg_end()-1))->getLocEnd()); - Expr *OrigArg0 = TheCall->getArg(0); - Expr *OrigArg1 = TheCall->getArg(1); + 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); - TheCall->setArg(1, OrigArg1); + TheCall->setArg(0, OrigArg0.get()); + TheCall->setArg(1, OrigArg1.get()); - if (OrigArg0->isTypeDependent() || OrigArg1->isTypeDependent()) + 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->getLocStart(), + return Diag(OrigArg0.get()->getLocStart(), diag::err_typecheck_call_invalid_ordered_compare) - << OrigArg0->getType() << OrigArg1->getType() - << SourceRange(OrigArg0->getLocStart(), OrigArg1->getLocEnd()); + << OrigArg0.get()->getType() << OrigArg1.get()->getType() + << SourceRange(OrigArg0.get()->getLocStart(), OrigArg1.get()->getLocEnd()); return false; } @@ -860,7 +866,7 @@ bool Sema::SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum, /// SemaBuiltinObjectSize - Handle __builtin_object_size(void *ptr, /// int type). This simply type checks that type is one of the defined /// constants (0-3). -// For compatability check 0-3, llvm only handles 0 and 2. +// For compatibility check 0-3, llvm only handles 0 and 2. bool Sema::SemaBuiltinObjectSize(CallExpr *TheCall) { llvm::APSInt Result; @@ -903,6 +909,8 @@ bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall, if (E->isTypeDependent() || E->isValueDependent()) return false; + E = E->IgnoreParens(); + switch (E->getStmtClass()) { case Stmt::BinaryConditionalOperatorClass: case Stmt::ConditionalOperatorClass: { @@ -925,11 +933,6 @@ bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall, goto tryAgain; } - case Stmt::ParenExprClass: { - E = cast<ParenExpr>(E)->getSubExpr(); - goto tryAgain; - } - case Stmt::OpaqueValueExprClass: if (const Expr *src = cast<OpaqueValueExpr>(E)->getSourceExpr()) { E = src; @@ -1036,15 +1039,15 @@ bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall, void Sema::CheckNonNullArguments(const NonNullAttr *NonNull, - const CallExpr *TheCall) { + const Expr * const *ExprArgs, + SourceLocation CallSiteLoc) { for (NonNullAttr::args_iterator i = NonNull->args_begin(), e = NonNull->args_end(); i != e; ++i) { - const Expr *ArgExpr = TheCall->getArg(*i); + const Expr *ArgExpr = ExprArgs[*i]; if (ArgExpr->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull)) - Diag(TheCall->getCallee()->getLocStart(), diag::warn_null_arg) - << ArgExpr->getSourceRange(); + Diag(CallSiteLoc, diag::warn_null_arg) << ArgExpr->getSourceRange(); } } @@ -1218,10 +1221,12 @@ void CheckFormatHandler::HandleZeroPosition(const char *startPos, } void CheckFormatHandler::HandleNullChar(const char *nullCharacter) { - // The presence of a null character is likely an error. - S.Diag(getLocationOfByte(nullCharacter), - diag::warn_printf_format_string_contains_null_char) - << getFormatStringRange(); + if (!IsObjCLiteral) { + // The presence of a null character is likely an error. + S.Diag(getLocationOfByte(nullCharacter), + diag::warn_printf_format_string_contains_null_char) + << getFormatStringRange(); + } } const Expr *CheckFormatHandler::getDataArg(unsigned i) const { @@ -1825,6 +1830,54 @@ void Sema::CheckFormatString(const StringLiteral *FExpr, } } +//===--- CHECK: Standard memory functions ---------------------------------===// + +/// \brief Check for dangerous or invalid arguments to memset(). +/// +/// This issues warnings on known problematic or dangerous or unspecified +/// arguments to the standard 'memset' function call. +/// +/// \param Call The call expression to diagnose. +void Sema::CheckMemsetArguments(const CallExpr *Call) { + // It is possible to have a non-standard definition of memset. Validate + // we have the proper number of arguments, and if not, abort further + // checking. + if (Call->getNumArgs() != 3) + return; + + const Expr *Dest = Call->getArg(0)->IgnoreParenImpCasts(); + + // The type checking for this warning is moderately expensive, only do it + // when enabled. + if (getDiagnostics().getDiagnosticLevel(diag::warn_non_pod_memset, + Dest->getExprLoc()) == + Diagnostic::Ignored) + return; + + QualType DestTy = Dest->getType(); + if (const PointerType *DestPtrTy = DestTy->getAs<PointerType>()) { + QualType PointeeTy = DestPtrTy->getPointeeType(); + if (PointeeTy->isVoidType()) + return; + + // Check the C++11 POD definition regardless of language mode; it is more + // relaxed than earlier definitions and we don't want spurrious warnings. + if (PointeeTy->isCXX11PODType()) + return; + + DiagRuntimeBehavior( + Dest->getExprLoc(), Dest, + PDiag(diag::warn_non_pod_memset) + << PointeeTy << Call->getCallee()->getSourceRange()); + + SourceRange ArgRange = Call->getArg(0)->getSourceRange(); + DiagRuntimeBehavior( + Dest->getExprLoc(), Dest, + PDiag(diag::note_non_pod_memset_silence) + << FixItHint::CreateInsertion(ArgRange.getBegin(), "(void*)")); + } +} + //===--- CHECK: Return Address of Stack Variable --------------------------===// static Expr *EvalVal(Expr *E, llvm::SmallVectorImpl<DeclRefExpr *> &refVars); @@ -1928,14 +1981,12 @@ static Expr *EvalAddr(Expr *E, llvm::SmallVectorImpl<DeclRefExpr *> &refVars) { 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::ParenExprClass: - // Ignore parentheses. - return EvalAddr(cast<ParenExpr>(E)->getSubExpr(), refVars); - case Stmt::DeclRefExprClass: { DeclRefExpr *DR = cast<DeclRefExpr>(E); @@ -2065,6 +2116,8 @@ do { // 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<ImplicitCastExpr>(E); @@ -2098,12 +2151,6 @@ do { return NULL; } - case Stmt::ParenExprClass: { - // Ignore parentheses. - E = cast<ParenExpr>(E)->getSubExpr(); - continue; - } - 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 @@ -2782,10 +2829,48 @@ void AnalyzeAssignment(Sema &S, BinaryOperator *E) { } /// Diagnose an implicit cast; purely a helper for CheckImplicitConversion. +void DiagnoseImpCast(Sema &S, Expr *E, QualType SourceType, QualType T, + SourceLocation CContext, unsigned diag) { + S.Diag(E->getExprLoc(), diag) + << SourceType << T << E->getSourceRange() << SourceRange(CContext); +} + +/// Diagnose an implicit cast; purely a helper for CheckImplicitConversion. void DiagnoseImpCast(Sema &S, Expr *E, QualType T, SourceLocation CContext, unsigned diag) { - S.Diag(E->getExprLoc(), diag) - << E->getType() << T << E->getSourceRange() << SourceRange(CContext); + DiagnoseImpCast(S, E, E->getType(), T, CContext, diag); +} + +/// Diagnose an implicit cast from a literal expression. Also attemps to supply +/// fixit hints when the cast wouldn't lose information to simply write the +/// expression with the expected type. +void DiagnoseFloatingLiteralImpCast(Sema &S, FloatingLiteral *FL, QualType T, + SourceLocation CContext) { + // Emit the primary warning first, then try to emit a fixit hint note if + // reasonable. + S.Diag(FL->getExprLoc(), diag::warn_impcast_literal_float_to_integer) + << FL->getType() << T << FL->getSourceRange() << SourceRange(CContext); + + const llvm::APFloat &Value = FL->getValue(); + + // Don't attempt to fix PPC double double literals. + if (&Value.getSemantics() == &llvm::APFloat::PPCDoubleDouble) + return; + + // Try to convert this exactly to an 64-bit integer. FIXME: It would be + // nice to support arbitrarily large integers here. + bool isExact = false; + uint64_t IntegerPart; + if (Value.convertToInteger(&IntegerPart, 64, /*isSigned=*/true, + llvm::APFloat::rmTowardZero, &isExact) + != llvm::APFloat::opOK || !isExact) + return; + + llvm::APInt IntegerValue(64, IntegerPart, /*isSigned=*/true); + + std::string LiteralValue = IntegerValue.toString(10, /*isSigned=*/true); + S.Diag(FL->getExprLoc(), diag::note_fix_integral_float_as_integer) + << FixItHint::CreateReplacement(FL->getSourceRange(), LiteralValue); } std::string PrettyPrintInRange(const llvm::APSInt &Value, IntRange Range) { @@ -2797,6 +2882,11 @@ std::string PrettyPrintInRange(const llvm::APSInt &Value, IntRange Range) { return ValueInRange.toString(10); } +static bool isFromSystemMacro(Sema &S, SourceLocation loc) { + SourceManager &smgr = S.Context.getSourceManager(); + return loc.isMacroID() && smgr.isInSystemHeader(smgr.getSpellingLoc(loc)); +} + void CheckImplicitConversion(Sema &S, Expr *E, QualType T, SourceLocation CC, bool *ICContext = 0) { if (E->isTypeDependent() || E->isValueDependent()) return; @@ -2806,11 +2896,12 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, if (Source == Target) return; if (Target->isDependentType()) return; - // If the conversion context location is invalid or instantiated - // from a system macro, don't complain. - if (CC.isInvalid() || - (CC.isMacroID() && S.Context.getSourceManager().isInSystemHeader( - S.Context.getSourceManager().getSpellingLoc(CC)))) + // 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 + // instantiation 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; // Never diagnose implicit casts to bool. @@ -2819,8 +2910,11 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, // Strip vector types. if (isa<VectorType>(Source)) { - if (!isa<VectorType>(Target)) + if (!isa<VectorType>(Target)) { + if (isFromSystemMacro(S, CC)) + return; return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_vector_scalar); + } Source = cast<VectorType>(Source)->getElementType().getTypePtr(); Target = cast<VectorType>(Target)->getElementType().getTypePtr(); @@ -2828,8 +2922,12 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, // Strip complex types. if (isa<ComplexType>(Source)) { - if (!isa<ComplexType>(Target)) + if (!isa<ComplexType>(Target)) { + if (isFromSystemMacro(S, CC)) + return; + return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_complex_scalar); + } Source = cast<ComplexType>(Source)->getElementType().getTypePtr(); Target = cast<ComplexType>(Target)->getElementType().getTypePtr(); @@ -2857,17 +2955,22 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, return; } + if (isFromSystemMacro(S, CC)) + return; + DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_float_precision); } return; } - // If the target is integral, always warn. + // If the target is integral, always warn. if ((TargetBT && TargetBT->isInteger())) { + if (isFromSystemMacro(S, CC)) + return; + Expr *InnerE = E->IgnoreParenImpCasts(); - if (FloatingLiteral *LiteralExpr = dyn_cast<FloatingLiteral>(InnerE)) { - DiagnoseImpCast(S, LiteralExpr, T, CC, - diag::warn_impcast_literal_float_to_integer); + if (FloatingLiteral *FL = dyn_cast<FloatingLiteral>(InnerE)) { + DiagnoseFloatingLiteralImpCast(S, FL, T, CC); } else { DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_float_integer); } @@ -2887,6 +2990,9 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, // TODO: this should happen for bitfield stores, too. llvm::APSInt Value(32); if (E->isIntegerConstantExpr(Value, S.Context)) { + if (isFromSystemMacro(S, CC)) + return; + std::string PrettySourceValue = Value.toString(10); std::string PrettyTargetValue = PrettyPrintInRange(Value, TargetRange); @@ -2898,6 +3004,10 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, // People want to build with -Wshorten-64-to-32 and not -Wconversion // and by god we'll let them. + + if (isFromSystemMacro(S, CC)) + return; + if (SourceRange.Width == 64 && TargetRange.Width == 32) return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_integer_64_32); return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_integer_precision); @@ -2906,6 +3016,10 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, if ((TargetRange.NonNegative && !SourceRange.NonNegative) || (!TargetRange.NonNegative && SourceRange.NonNegative && SourceRange.Width == TargetRange.Width)) { + + if (isFromSystemMacro(S, CC)) + return; + unsigned DiagID = diag::warn_impcast_integer_sign; // Traditionally, gcc has warned about this under -Wsign-compare. @@ -2922,15 +3036,31 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, } // 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.getLangOptions().CPlusPlus) { + if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) + if (EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(DRE->getDecl())) { + EnumDecl *Enum = cast<EnumDecl>(ECD->getDeclContext()); + SourceType = S.Context.getTypeDeclType(Enum); + Source = S.Context.getCanonicalType(SourceType).getTypePtr(); + } + } + if (const EnumType *SourceEnum = Source->getAs<EnumType>()) if (const EnumType *TargetEnum = Target->getAs<EnumType>()) if ((SourceEnum->getDecl()->getIdentifier() || - SourceEnum->getDecl()->getTypedefForAnonDecl()) && + SourceEnum->getDecl()->getTypedefNameForAnonDecl()) && (TargetEnum->getDecl()->getIdentifier() || - TargetEnum->getDecl()->getTypedefForAnonDecl()) && - SourceEnum != TargetEnum) - return DiagnoseImpCast(S, E, T, CC, + TargetEnum->getDecl()->getTypedefNameForAnonDecl()) && + SourceEnum != TargetEnum) { + if (isFromSystemMacro(S, CC)) + return; + + return DiagnoseImpCast(S, E, SourceType, T, CC, diag::warn_impcast_different_enum_types); + } return; } @@ -3039,7 +3169,7 @@ void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) { if (isa<StmtExpr>(E)) return; // Don't descend into unevaluated contexts. - if (isa<SizeOfAlignOfExpr>(E)) return; + if (isa<UnaryExprOrTypeTraitExpr>(E)) return; // Now just recurse over the expression's children. CC = E->getExprLoc(); @@ -3169,10 +3299,11 @@ void Sema::CheckCastAlign(Expr *Op, QualType T, SourceRange TRange) { << TRange << Op->getSourceRange(); } -void Sema::CheckArrayAccess(const clang::ArraySubscriptExpr *E) { +static void CheckArrayAccess_Check(Sema &S, + const clang::ArraySubscriptExpr *E) { const Expr *BaseExpr = E->getBase()->IgnoreParenImpCasts(); const ConstantArrayType *ArrayTy = - Context.getAsConstantArrayType(BaseExpr->getType()); + S.Context.getAsConstantArrayType(BaseExpr->getType()); if (!ArrayTy) return; @@ -3180,7 +3311,7 @@ void Sema::CheckArrayAccess(const clang::ArraySubscriptExpr *E) { if (IndexExpr->isValueDependent()) return; llvm::APSInt index; - if (!IndexExpr->isIntegerConstantExpr(index, Context)) + if (!IndexExpr->isIntegerConstantExpr(index, S.Context)) return; if (index.isUnsigned() || !index.isNegative()) { @@ -3195,15 +3326,16 @@ void Sema::CheckArrayAccess(const clang::ArraySubscriptExpr *E) { if (index.slt(size)) return; - DiagRuntimeBehavior(E->getBase()->getLocStart(), BaseExpr, - PDiag(diag::warn_array_index_exceeds_bounds) - << index.toString(10, true) << size.toString(10, true) - << IndexExpr->getSourceRange()); + S.DiagRuntimeBehavior(E->getBase()->getLocStart(), BaseExpr, + S.PDiag(diag::warn_array_index_exceeds_bounds) + << index.toString(10, true) + << size.toString(10, true) + << IndexExpr->getSourceRange()); } else { - DiagRuntimeBehavior(E->getBase()->getLocStart(), BaseExpr, - PDiag(diag::warn_array_index_precedes_bounds) - << index.toString(10, true) - << IndexExpr->getSourceRange()); + S.DiagRuntimeBehavior(E->getBase()->getLocStart(), BaseExpr, + S.PDiag(diag::warn_array_index_precedes_bounds) + << index.toString(10, true) + << IndexExpr->getSourceRange()); } const NamedDecl *ND = NULL; @@ -3212,8 +3344,28 @@ void Sema::CheckArrayAccess(const clang::ArraySubscriptExpr *E) { if (const MemberExpr *ME = dyn_cast<MemberExpr>(BaseExpr)) ND = dyn_cast<NamedDecl>(ME->getMemberDecl()); if (ND) - DiagRuntimeBehavior(ND->getLocStart(), BaseExpr, - PDiag(diag::note_array_index_out_of_bounds) - << ND->getDeclName()); + S.DiagRuntimeBehavior(ND->getLocStart(), BaseExpr, + S.PDiag(diag::note_array_index_out_of_bounds) + << ND->getDeclName()); } +void Sema::CheckArrayAccess(const Expr *expr) { + while (true) { + expr = expr->IgnoreParens(); + switch (expr->getStmtClass()) { + case Stmt::ArraySubscriptExprClass: + CheckArrayAccess_Check(*this, cast<ArraySubscriptExpr>(expr)); + return; + case Stmt::ConditionalOperatorClass: { + const ConditionalOperator *cond = cast<ConditionalOperator>(expr); + if (const Expr *lhs = cond->getLHS()) + CheckArrayAccess(lhs); + if (const Expr *rhs = cond->getRHS()) + CheckArrayAccess(rhs); + return; + } + default: + return; + } + } +} diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp index bab665a..cc8726d 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp @@ -667,8 +667,39 @@ QualType clang::getDeclUsageType(ASTContext &C, NamedDecl *ND) { T = Value->getType(); else return QualType(); - - return T.getNonReferenceType(); + + // 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<ReferenceType>()) { + T = Ref->getPointeeType(); + continue; + } + + if (const PointerType *Pointer = T->getAs<PointerType>()) { + if (Pointer->getPointeeType()->isFunctionType()) { + T = Pointer->getPointeeType(); + continue; + } + + break; + } + + if (const BlockPointerType *Block = T->getAs<BlockPointerType>()) { + T = Block->getPointeeType(); + continue; + } + + if (const FunctionType *Function = T->getAs<FunctionType>()) { + T = Function->getResultType(); + continue; + } + + break; + } while (true); + + return T; } void ResultBuilder::AdjustResultPriorityForDecl(Result &R) { @@ -1482,7 +1513,8 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, case Sema::PCC_Statement: { AddTypedefResult(Results); - if (SemaRef.getLangOptions().CPlusPlus && Results.includeCodePatterns()) { + if (SemaRef.getLangOptions().CPlusPlus && Results.includeCodePatterns() && + SemaRef.getLangOptions().CXXExceptions) { Builder.AddTypedTextChunk("try"); Builder.AddChunk(CodeCompletionString::CK_LeftBrace); Builder.AddPlaceholderChunk("statements"); @@ -1655,15 +1687,17 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Results.AddResult(Result("true")); Results.AddResult(Result("false")); - // 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())); + if (SemaRef.getLangOptions().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"); @@ -1695,13 +1729,15 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Builder.AddChunk(CodeCompletionString::CK_RightParen); Results.AddResult(Result(Builder.TakeString())); - // typeid ( expression-or-type ) - Builder.AddTypedTextChunk("typeid"); - Builder.AddChunk(CodeCompletionString::CK_LeftParen); - Builder.AddPlaceholderChunk("expression-or-type"); - Builder.AddChunk(CodeCompletionString::CK_RightParen); - Results.AddResult(Result(Builder.TakeString())); - + if (SemaRef.getLangOptions().RTTI) { + // typeid ( expression-or-type ) + 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); @@ -1738,11 +1774,13 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Builder.AddPlaceholderChunk("expression"); Results.AddResult(Result(Builder.TakeString())); - // throw expression - Builder.AddTypedTextChunk("throw"); - Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); - Builder.AddPlaceholderChunk("expression"); - Results.AddResult(Result(Builder.TakeString())); + if (SemaRef.getLangOptions().CXXExceptions) { + // throw expression + Builder.AddTypedTextChunk("throw"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("expression"); + Results.AddResult(Result(Builder.TakeString())); + } // FIXME: Rethrow? } @@ -1785,9 +1823,9 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, /// /// This routine provides a fast path where we provide constant strings for /// common type names. -const char *GetCompletionTypeString(QualType T, - ASTContext &Context, - CodeCompletionAllocator &Allocator) { +static const char *GetCompletionTypeString(QualType T, + ASTContext &Context, + CodeCompletionAllocator &Allocator) { PrintingPolicy Policy(Context.PrintingPolicy); Policy.AnonymousTagLocations = false; @@ -1799,7 +1837,7 @@ const char *GetCompletionTypeString(QualType T, // Anonymous tag types are constant strings. if (const TagType *TagT = dyn_cast<TagType>(T)) if (TagDecl *Tag = TagT->getDecl()) - if (!Tag->getIdentifier() && !Tag->getTypedefForAnonDecl()) { + if (!Tag->getIdentifier() && !Tag->getTypedefNameForAnonDecl()) { switch (Tag->getTagKind()) { case TTK_Struct: return "struct <anonymous>"; case TTK_Class: return "class <anonymous>"; @@ -1902,7 +1940,7 @@ static std::string FormatFunctionParameter(ASTContext &Context, // Look through typedefs. if (TypedefTypeLoc *TypedefTL = dyn_cast<TypedefTypeLoc>(&TL)) { if (TypeSourceInfo *InnerTSInfo - = TypedefTL->getTypedefDecl()->getTypeSourceInfo()) { + = TypedefTL->getTypedefNameDecl()->getTypeSourceInfo()) { TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc(); continue; } @@ -2602,6 +2640,7 @@ CXCursorKind clang::getCursorKindForDecl(Decl *D) { 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; @@ -4816,8 +4855,12 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver, // If necessary, apply function/array conversion to the receiver. // C99 6.7.5.3p[7,8]. - if (RecExpr) - DefaultFunctionArrayLvalueConversion(RecExpr); + 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)) @@ -5327,16 +5370,65 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S, Class = cast<ObjCCategoryImplDecl>(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().str(); + std::string NameWithSuffix = PropertyName->getName().str(); + NameWithSuffix += '_'; for(; Class; Class = Class->getSuperClass()) { - // FIXME: We could screen the type of each ivar for compatibility with - // the property, but is that being too paternal? - for (ObjCInterfaceDecl::ivar_iterator IVar = Class->ivar_begin(), - IVarEnd = Class->ivar_end(); - IVar != IVarEnd; ++IVar) - Results.AddResult(Result(*IVar, 0), CurContext, 0, false); + 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, Priority,CXAvailability_Available); + + Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context, + Allocator)); + Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix)); + Results.AddResult(Result(Builder.TakeString(), Priority, + CXCursor_ObjCIvarDecl)); } + Results.ExitScope(); HandleCodeCompleteResults(this, CodeCompleter, diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp index d6efd7a..7214988 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp @@ -17,6 +17,7 @@ #include "clang/Sema/CXXFieldCollector.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" +#include "TypeLocBuilder.h" #include "clang/AST/APValue.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" @@ -24,6 +25,7 @@ #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" @@ -61,7 +63,8 @@ Sema::DeclGroupPtrTy Sema::ConvertDeclToDeclGroup(Decl *Ptr) { ParsedType Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, Scope *S, CXXScopeSpec *SS, bool isClassName, bool HasTrailingDot, - ParsedType ObjectTypePtr) { + ParsedType ObjectTypePtr, + bool WantNontrivialTypeSourceInfo) { // Determine where we will perform name lookup. DeclContext *LookupCtx = 0; if (ObjectTypePtr) { @@ -87,10 +90,15 @@ ParsedType Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, // 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, SS->getScopeRep(), II, - SourceLocation(), SS->getRange(), NameLoc); - return ParsedType::make(T); + CheckTypenameType(ETK_None, SourceLocation(), QualifierLoc, + II, NameLoc); + + return ParsedType::make(T); } return ParsedType(); @@ -189,10 +197,23 @@ ParsedType Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, if (T.isNull()) T = Context.getTypeDeclType(TD); - if (SS) - T = getElaboratedType(ETK_None, *SS, T); - + if (SS && SS->isNotEmpty()) { + 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<ElaboratedTypeLoc>(T); + ElabTL.setKeywordLoc(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<ObjCInterfaceDecl>(IIDecl)) { + (void)DiagnoseUseOfDecl(IDecl, NameLoc); if (!HasTrailingDot) T = Context.getObjCInterfaceType(IDecl); } @@ -229,6 +250,33 @@ DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) { 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 T> class A { +/// public: +/// typedef int TYPE; +/// }; +/// template<class T> class B : public A<T> { +/// public: +/// A<T>::TYPE a; // no typename required because A<T> is a base class. +/// }; +/// @endcode +bool Sema::isMicrosoftMissingTypename(const CXXScopeSpec *SS) { + if (CurContext->isRecord()) { + const Type *Ty = SS->getScopeRep()->getAsType(); + + CXXRecordDecl *RD = cast<CXXRecordDecl>(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 false; +} + bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II, SourceLocation IILoc, Scope *S, @@ -263,7 +311,9 @@ bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II, Diag(Result->getLocation(), diag::note_previous_decl) << Result->getDeclName(); - SuggestedType = getTypeName(*Result->getIdentifier(), IILoc, S, SS); + SuggestedType = getTypeName(*Result->getIdentifier(), IILoc, S, SS, + false, false, ParsedType(), + /*NonTrivialTypeSourceInfo=*/true); return true; } } else if (Lookup.empty()) { @@ -304,7 +354,11 @@ bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II, Diag(IILoc, diag::err_typename_nested_not_found) << &II << DC << SS->getRange(); else if (isDependentScopeSpecifier(*SS)) { - Diag(SS->getRange().getBegin(), diag::err_typename_missing) + unsigned DiagID = diag::err_typename_missing; + if (getLangOptions().Microsoft && isMicrosoftMissingTypename(SS)) + 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 "); @@ -317,6 +371,328 @@ bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II, 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().getLangOptions().CPlusPlus && + NextToken.is(tok::less); + + for (LookupResult::iterator I = R.begin(), IEnd = R.end(); I != IEnd; ++I) { + if (isa<TypeDecl>(*I) || isa<ObjCInterfaceDecl>(*I)) + return true; + + if (CheckTemplate && isa<TemplateDecl>(*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; + + // Synthesize ivars lazily. + if (getLangOptions().ObjCDefaultSynthProperties && + getLangOptions().ObjCNonFragileABI2) { + if (SynthesizeProvisionalIvar(Result, Name, NameLoc)) { + if (const ObjCPropertyDecl *Property = + canSynthesizeProvisionalIvar(Name)) { + Diag(NameLoc, diag::warn_synthesized_ivar_access) << Name; + Diag(Property->getLocation(), diag::note_property_declare); + } + + // FIXME: This is strange. Shouldn't we just take the ivar returned + // from SynthesizeProvisionalIvar and continue with that? + 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 (getLangOptions().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 (!getLangOptions().CPlusPlus && !SecondTry) { + Result.clear(LookupTagName); + LookupParsedName(Result, S, &SS); + if (TagDecl *Tag = Result.getAsSingle<TagDecl>()) { + 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 << getLangOptions().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) { + if (DeclarationName Corrected = CorrectTypo(Result, S, &SS)) { + unsigned UnqualifiedDiag = diag::err_undeclared_var_use_suggest; + unsigned QualifiedDiag = diag::err_no_member_suggest; + + NamedDecl *FirstDecl = Result.empty()? 0 : *Result.begin(); + NamedDecl *UnderlyingFirstDecl + = FirstDecl? FirstDecl->getUnderlyingDecl() : 0; + if (getLangOptions().CPlusPlus && NextToken.is(tok::less) && + UnderlyingFirstDecl && isa<TemplateDecl>(UnderlyingFirstDecl)) { + UnqualifiedDiag = diag::err_no_template_suggest; + QualifiedDiag = diag::err_no_member_template_suggest; + } else if (UnderlyingFirstDecl && + (isa<TypeDecl>(UnderlyingFirstDecl) || + isa<ObjCInterfaceDecl>(UnderlyingFirstDecl) || + isa<ObjCCompatibleAliasDecl>(UnderlyingFirstDecl))) { + UnqualifiedDiag = diag::err_unknown_typename_suggest; + QualifiedDiag = diag::err_unknown_nested_typename_suggest; + } + + if (SS.isEmpty()) + Diag(NameLoc, UnqualifiedDiag) + << Name << Corrected + << FixItHint::CreateReplacement(NameLoc, Corrected.getAsString()); + else + Diag(NameLoc, QualifiedDiag) + << Name << computeDeclContext(SS, false) << Corrected + << SS.getRange() + << FixItHint::CreateReplacement(NameLoc, Corrected.getAsString()); + + // Update the name, so that the caller has the new name. + Name = Corrected.getAsIdentifierInfo(); + + // Typo correction corrected to a keyword. + if (Result.empty()) + return Corrected.getAsIdentifierInfo(); + + Diag(FirstDecl->getLocation(), diag::note_previous_decl) + << FirstDecl->getDeclName(); + + // 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<ObjCIvarDecl>()) { + 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, NameInfo, /*TemplateArgs=*/0); + + case LookupResult::Found: + case LookupResult::FoundOverloaded: + case LookupResult::FoundUnresolvedValue: + break; + + case LookupResult::Ambiguous: + if (getLangOptions().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 (getLangOptions().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<TemplateDecl>((*Result.begin())->getUnderlyingDecl()); + IsFunctionTemplate = isa<FunctionTemplateDecl>(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<TypeDecl>(FirstDecl)) { + DiagnoseUseOfDecl(Type, NameLoc); + QualType T = Context.getTypeDeclType(Type); + return ParsedType::make(T); + } + + ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(FirstDecl); + if (!Class) { + // FIXME: It's unfortunate that we don't have a Type node for handling this. + if (ObjCCompatibleAliasDecl *Alias + = dyn_cast<ObjCCompatibleAliasDecl>(FirstDecl)) + Class = Alias->getClassInterface(); + } + + if (Class) { + DiagnoseUseOfDecl(Class, NameLoc); + + if (NextToken.is(tok::period)) { + // Interface. <something> 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, 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. @@ -472,11 +848,30 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) { } S->AddDecl(D); - IdResolver.AddDecl(D); + + if (isa<LabelDecl>(D) && !cast<LabelDecl>(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); + } } -bool Sema::isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S) { - return IdResolver.isDeclInScope(D, Ctx, Context, S); +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) { @@ -498,12 +893,13 @@ static bool isOutOfScopePreviousDeclaration(NamedDecl *, /// as determined by isDeclInScope. static void FilterLookupForScope(Sema &SemaRef, LookupResult &R, DeclContext *Ctx, Scope *S, - bool ConsiderLinkage) { + bool ConsiderLinkage, + bool ExplicitInstantiationOrSpecialization) { LookupResult::Filter F = R.makeFilter(); while (F.hasNext()) { NamedDecl *D = F.next(); - if (SemaRef.isDeclInScope(D, Ctx, S)) + if (SemaRef.isDeclInScope(D, Ctx, S, ExplicitInstantiationOrSpecialization)) continue; if (ConsiderLinkage && @@ -841,7 +1237,7 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, FunctionDecl *New = FunctionDecl::Create(Context, Context.getTranslationUnitDecl(), - Loc, II, R, /*TInfo=*/0, + Loc, Loc, II, R, /*TInfo=*/0, SC_Extern, SC_None, false, /*hasPrototype=*/true); @@ -851,10 +1247,15 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, // FunctionDecl. if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(R)) { llvm::SmallVector<ParmVarDecl*, 16> Params; - for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i) - Params.push_back(ParmVarDecl::Create(Context, New, SourceLocation(), 0, - FT->getArgType(i), /*TInfo=*/0, - SC_None, SC_None, 0)); + 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.data(), Params.size()); } @@ -871,12 +1272,12 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, return New; } -/// MergeTypeDefDecl - We just parsed a typedef 'New' which has the +/// 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::MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls) { +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; @@ -936,7 +1337,7 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls) { // Determine the "old" type we'll use for checking and diagnostics. QualType OldType; - if (TypedefDecl *OldTypedef = dyn_cast<TypedefDecl>(Old)) + if (TypedefNameDecl *OldTypedef = dyn_cast<TypedefNameDecl>(Old)) OldType = OldTypedef->getUnderlyingType(); else OldType = Context.getTypeDeclType(Old); @@ -947,8 +1348,11 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls) { if (OldType != New->getUnderlyingType() && Context.getCanonicalType(OldType) != Context.getCanonicalType(New->getUnderlyingType())) { + int Kind = 0; + if (isa<TypeAliasDecl>(Old)) + Kind = 1; Diag(New->getLocation(), diag::err_redefinition_different_typedef) - << New->getUnderlyingType() << OldType; + << Kind << New->getUnderlyingType() << OldType; if (Old->getLocation().isValid()) Diag(Old->getLocation(), diag::note_previous_definition); return New->setInvalidDecl(); @@ -958,8 +1362,8 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls) { // declaration was a typedef. // FIXME: this is a potential source of wierdness if the type // spellings don't match exactly. - if (isa<TypedefDecl>(Old)) - New->setPreviousDeclaration(cast<TypedefDecl>(Old)); + if (TypedefNameDecl *Typedef = dyn_cast<TypedefNameDecl>(Old)) + New->setPreviousDeclaration(Typedef); if (getLangOptions().Microsoft) return; @@ -993,7 +1397,7 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls) { // }; // // since that was the intent of DR56. - if (!isa<TypedefDecl >(Old)) + if (!isa<TypedefNameDecl>(Old)) return; Diag(New->getLocation(), diag::err_redefinition) @@ -1033,23 +1437,58 @@ DeclHasAttr(const Decl *D, const Attr *A) { return false; } -/// MergeDeclAttributes - append attributes from the Old decl to the New one. -static void MergeDeclAttributes(Decl *New, Decl *Old, ASTContext &C) { - if (!Old->hasAttrs()) +/// mergeDeclAttributes - Copy attributes from the Old decl to the New one. +static void mergeDeclAttributes(Decl *newDecl, const Decl *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 (!New->hasAttrs()) - New->setAttrs(AttrVec()); + if (!foundAny) newDecl->setAttrs(AttrVec()); + for (specific_attr_iterator<InheritableAttr> - i = Old->specific_attr_begin<InheritableAttr>(), - e = Old->specific_attr_end<InheritableAttr>(); i != e; ++i) { - if (!DeclHasAttr(New, *i)) { - InheritableAttr *NewAttr = cast<InheritableAttr>((*i)->clone(C)); - NewAttr->setInherited(true); - New->addAttr(NewAttr); + i = oldDecl->specific_attr_begin<InheritableAttr>(), + e = oldDecl->specific_attr_end<InheritableAttr>(); i != e; ++i) { + if (!DeclHasAttr(newDecl, *i)) { + InheritableAttr *newAttr = cast<InheritableAttr>((*i)->clone(C)); + newAttr->setInherited(true); + newDecl->addAttr(newAttr); + foundAny = true; } } + + if (!foundAny) newDecl->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<InheritableParamAttr> + i = oldDecl->specific_attr_begin<InheritableParamAttr>(), + e = oldDecl->specific_attr_end<InheritableParamAttr>(); i != e; ++i) { + if (!DeclHasAttr(newDecl, *i)) { + InheritableAttr *newAttr = cast<InheritableParamAttr>((*i)->clone(C)); + newAttr->setInherited(true); + newDecl->addAttr(newAttr); + foundAny = true; + } + } + + if (!foundAny) newDecl->dropAttrs(); } namespace { @@ -1145,10 +1584,14 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { New->getStorageClass() == SC_Static && Old->getStorageClass() != SC_Static && !canRedefineFunction(Old, getLangOptions())) { - Diag(New->getLocation(), diag::err_static_non_static) - << New; - Diag(Old->getLocation(), PrevDiag); - return true; + if (getLangOptions().Microsoft) { + 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 @@ -1191,8 +1634,9 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { } // Merge regparm attribute. - if (OldTypeInfo.getRegParm() != NewTypeInfo.getRegParm()) { - if (NewTypeInfo.getRegParm()) { + if (OldTypeInfo.getHasRegParm() != NewTypeInfo.getHasRegParm() || + OldTypeInfo.getRegParm() != NewTypeInfo.getRegParm()) { + if (NewTypeInfo.getHasRegParm()) { Diag(New->getLocation(), diag::err_regparm_mismatch) << NewType->getRegParmType() << OldType->getRegParmType(); @@ -1335,10 +1779,12 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { 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); } @@ -1450,7 +1896,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { /// \returns false bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) { // Merge the attributes - MergeDeclAttributes(New, Old, Context); + mergeDeclAttributes(New, Old, Context); // Merge the storage class. if (Old->getStorageClass() != SC_Extern && @@ -1465,14 +1911,33 @@ bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) { if (Old->isDeleted()) New->setDeleted(); + // 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 (getLangOptions().CPlusPlus) return MergeCXXFunctionDecl(New, Old); return false; } -/// MergeVarDecl - We parsed a variable 'New' which has the same name and scope -/// as a previous declaration 'Old'. Figure out how to merge their types, +void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod, + const ObjCMethodDecl *oldMethod) { + // Merge the attributes. + mergeDeclAttributes(newMethod, oldMethod, Context); + + // Merge attributes from the parameters. + for (ObjCMethodDecl::param_iterator oi = oldMethod->param_begin(), + ni = newMethod->param_begin(), ne = newMethod->param_end(); + ni != ne; ++ni, ++oi) + mergeParamDeclAttributes(*ni, *oi, Context); +} + +/// 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 @@ -1489,8 +1954,10 @@ void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old) { 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())) - 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 @@ -1564,7 +2031,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { New->setInvalidDecl(); } - MergeDeclAttributes(New, Old, Context); + mergeDeclAttributes(New, Old, Context); // Merge the types. MergeVarDeclTypes(New, Old); @@ -1664,12 +2131,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { /// 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) { - // FIXME: Error on inline/virtual/explicit - // FIXME: Warn on useless __thread - // FIXME: Warn on useless const/volatile - // FIXME: Warn on useless static/extern/typedef/private_extern/mutable - // FIXME: Warn on useless attributes + DeclSpec &DS) { Decl *TagD = 0; TagDecl *Tag = 0; if (DS.getTypeSpecType() == DeclSpec::TST_class || @@ -1703,6 +2165,10 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, return 0; return ActOnFriendTypeDecl(S, DS, MultiTemplateParamsArg(*this, 0, 0)); } + + // Track whether we warned about the fact that there aren't any + // declarators. + bool emittedWarning = false; if (RecordDecl *Record = dyn_cast_or_null<RecordDecl>(Tag)) { ProcessDeclAttributeList(S, Record, DS.getAttributes().getList()); @@ -1715,6 +2181,7 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, Diag(DS.getSourceRange().getBegin(), diag::ext_no_declarators) << DS.getSourceRange(); + emittedWarning = true; } } @@ -1740,12 +2207,16 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DS.getStorageClassSpec() != DeclSpec::SCS_typedef) if (EnumDecl *Enum = dyn_cast_or_null<EnumDecl>(Tag)) if (Enum->enumerator_begin() == Enum->enumerator_end() && - !Enum->getIdentifier() && !Enum->isInvalidDecl()) + !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() && - DS.getTypeSpecType() != DeclSpec::TST_error) { + 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 && @@ -1757,7 +2228,40 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, Diag(DS.getSourceRange().getBegin(), 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"; + + // FIXME: Warn on useless attributes return TagD; } @@ -2062,7 +2566,9 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, // Create a declaration for this anonymous struct/union. NamedDecl *Anon = 0; if (RecordDecl *OwningClass = dyn_cast<RecordDecl>(Owner)) { - Anon = FieldDecl::Create(Context, OwningClass, Record->getLocation(), + Anon = FieldDecl::Create(Context, OwningClass, + DS.getSourceRange().getBegin(), + Record->getLocation(), /*IdentifierInfo=*/0, Context.getTypeDeclType(Record), TInfo, @@ -2086,8 +2592,9 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, VarDecl::StorageClass SCAsWritten = StorageClassSpecToVarDeclStorageClass(SCSpec); - Anon = VarDecl::Create(Context, Owner, Record->getLocation(), - /*IdentifierInfo=*/0, + Anon = VarDecl::Create(Context, Owner, + DS.getSourceRange().getBegin(), + Record->getLocation(), /*IdentifierInfo=*/0, Context.getTypeDeclType(Record), TInfo, SC, SCAsWritten); } @@ -2151,6 +2658,7 @@ Decl *Sema::BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS, NamedDecl* Anon = FieldDecl::Create(Context, cast<RecordDecl>(CurContext), DS.getSourceRange().getBegin(), + DS.getSourceRange().getBegin(), /*IdentifierInfo=*/0, Context.getTypeDeclType(Record), TInfo, @@ -2379,6 +2887,26 @@ Decl *Sema::ActOnDeclarator(Scope *S, Declarator &D) { return HandleDeclarator(S, D, MultiTemplateParamsArg(*this), false); } +/// 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<CXXRecordDecl>(DC)) + if (Record->getIdentifier() && Record->getDeclName() == Name) { + Diag(NameInfo.getLoc(), diag::err_member_name_of_class) << Name; + return true; + } + + return false; +} + Decl *Sema::HandleDeclarator(Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists, bool IsFunctionDefinition) { @@ -2466,23 +2994,12 @@ Decl *Sema::HandleDeclarator(Scope *S, Declarator &D, D.setInvalidType(); } } - - // 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; - if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC)) - if (Record->getIdentifier() && Record->getDeclName() == Name) { - Diag(D.getIdentifierLoc(), diag::err_member_name_of_class) - << Name; - - // 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; - } + + 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; @@ -2777,6 +3294,15 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, // Handle attributes prior to checking for duplicates in MergeVarDecl ProcessDeclAttributes(S, NewTD, D); + return ActOnTypedefNameDecl(S, DC, NewTD, Previous, Redeclaration); +} + +/// 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) { // 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 @@ -2792,18 +3318,17 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, TryToFixInvalidVariablyModifiedType(T, Context, SizeIsNegative, Oversized); if (!FixedTy.isNull()) { - Diag(D.getIdentifierLoc(), diag::warn_illegal_constant_array_size); + Diag(NewTD->getLocation(), diag::warn_illegal_constant_array_size); NewTD->setTypeSourceInfo(Context.getTrivialTypeSourceInfo(FixedTy)); } else { if (SizeIsNegative) - Diag(D.getIdentifierLoc(), diag::err_typecheck_negative_array_size); + Diag(NewTD->getLocation(), diag::err_typecheck_negative_array_size); else if (T->isVariableArrayType()) - Diag(D.getIdentifierLoc(), diag::err_vla_decl_in_file_scope); + Diag(NewTD->getLocation(), diag::err_vla_decl_in_file_scope); else if (Oversized.getBoolValue()) - Diag(D.getIdentifierLoc(), diag::err_array_too_large) - << Oversized.toString(10); + Diag(NewTD->getLocation(), diag::err_array_too_large) << Oversized.toString(10); else - Diag(D.getIdentifierLoc(), diag::err_vm_decl_in_file_scope); + Diag(NewTD->getLocation(), diag::err_vm_decl_in_file_scope); NewTD->setInvalidDecl(); } } @@ -2811,10 +3336,11 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, // Merge the decl with the existing one if appropriate. If the decl is // in an outer scope, it isn't the same thing. - FilterLookupForScope(*this, Previous, DC, S, /*ConsiderLinkage*/ false); + FilterLookupForScope(*this, Previous, DC, S, /*ConsiderLinkage*/ false, + /*ExplicitInstantiationOrSpecialization=*/false); if (!Previous.empty()) { Redeclaration = true; - MergeTypeDefDecl(NewTD, Previous); + MergeTypedefNameDecl(NewTD, Previous); } // If this is the C FILE type, notify the AST context. @@ -2952,8 +3478,9 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, bool isExplicitSpecialization = false; VarDecl *NewVD; if (!getLangOptions().CPlusPlus) { - NewVD = VarDecl::Create(Context, DC, D.getIdentifierLoc(), - II, R, TInfo, SC, SCAsWritten); + NewVD = VarDecl::Create(Context, DC, D.getSourceRange().getBegin(), + D.getIdentifierLoc(), II, + R, TInfo, SC, SCAsWritten); if (D.isInvalidType()) NewVD->setInvalidDecl(); @@ -2988,7 +3515,6 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, // Match up the template parameter lists with the scope specifier, then // determine whether we have a template or a template specialization. isExplicitSpecialization = false; - unsigned NumMatchedTemplateParamLists = TemplateParamLists.size(); bool Invalid = false; if (TemplateParameterList *TemplateParams = MatchTemplateParametersToScopeSpecifier( @@ -2999,9 +3525,6 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, /*never a friend*/ false, isExplicitSpecialization, Invalid)) { - // All but one template parameter lists have been matching. - --NumMatchedTemplateParamLists; - if (TemplateParams->size() > 0) { // There is no such thing as a variable template. Diag(D.getIdentifierLoc(), diag::err_template_variable) @@ -3017,13 +3540,13 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, << II << SourceRange(TemplateParams->getTemplateLoc(), TemplateParams->getRAngleLoc()); - isExplicitSpecialization = true; } } - NewVD = VarDecl::Create(Context, DC, D.getIdentifierLoc(), - II, R, TInfo, SC, SCAsWritten); + NewVD = VarDecl::Create(Context, DC, D.getSourceRange().getBegin(), + 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. @@ -3036,9 +3559,9 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, SetNestedNameSpecifier(NewVD, D); - if (NumMatchedTemplateParamLists > 0 && D.getCXXScopeSpec().isSet()) { + if (TemplateParamLists.size() > 0 && D.getCXXScopeSpec().isSet()) { NewVD->setTemplateParameterListsInfo(Context, - NumMatchedTemplateParamLists, + TemplateParamLists.size(), TemplateParamLists.release()); } } @@ -3092,7 +3615,8 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, // 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(*this, Previous, DC, S, NewVD->hasLinkage()); + FilterLookupForScope(*this, Previous, DC, S, NewVD->hasLinkage(), + isExplicitSpecialization); if (!getLangOptions().CPlusPlus) CheckVariableDeclaration(NewVD, Previous, Redeclaration); @@ -3169,10 +3693,11 @@ void Sema::CheckShadow(Scope *S, VarDecl *D, const LookupResult& R) { return; // Don't diagnose declarations at file scope. - DeclContext *NewDC = D->getDeclContext(); - if (NewDC->isFileContext()) + 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; @@ -3189,17 +3714,6 @@ void Sema::CheckShadow(Scope *S, VarDecl *D, const LookupResult& R) { if (VarDecl *shadowedVar = dyn_cast<VarDecl>(ShadowedDecl)) if (shadowedVar->isExternC()) { - // Don't warn for this case: - // - // @code - // extern int bob; - // void f() { - // extern int bob; - // } - // @endcode - if (D->isExternC()) - return; - // For shadowing external vars, make sure that we point to the global // declaration, not a locally scoped extern declaration. for (VarDecl::redecl_iterator @@ -3528,8 +4042,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, FunctionTemplateDecl *FunctionTemplate = 0; bool isExplicitSpecialization = false; bool isFunctionTemplateSpecialization = false; - unsigned NumMatchedTemplateParamLists = 0; - + if (!getLangOptions().CPlusPlus) { // Determine whether the function was written with a // prototype. This true when: @@ -3540,7 +4053,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, (D.isFunctionDeclarator() && D.getFunctionTypeInfo().hasPrototype) || (!isa<FunctionType>(R.getTypePtr()) && R->isFunctionProtoType()); - NewFD = FunctionDecl::Create(Context, DC, + NewFD = FunctionDecl::Create(Context, DC, D.getSourceRange().getBegin(), NameInfo, R, TInfo, SC, SCAsWritten, isInline, HasPrototype); if (D.isInvalidType()) @@ -3549,7 +4062,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // Set the lexical context. NewFD->setLexicalDeclContext(CurContext); // Filter out previous declarations that don't match the scope. - FilterLookupForScope(*this, Previous, DC, S, NewFD->hasLinkage()); + FilterLookupForScope(*this, Previous, DC, S, NewFD->hasLinkage(), + /*ExplicitInstantiationOrSpecialization=*/false); } else { isFriend = D.getDeclSpec().isFriendSpecified(); bool isVirtual = D.getDeclSpec().isVirtualSpecified(); @@ -3566,14 +4080,6 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, AbstractReturnType)) D.setInvalidType(); - - if (isFriend) { - // C++ [class.friend]p5 - // A function can be defined in a friend declaration of a - // class . . . . Such a function is implicitly inline. - isInline |= IsFunctionDefinition; - } - if (Name.getNameKind() == DeclarationName::CXXConstructorName) { // This is a C++ constructor declaration. assert(DC->isRecord() && @@ -3584,6 +4090,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // Create the new declaration NewFD = CXXConstructorDecl::Create(Context, cast<CXXRecordDecl>(DC), + D.getSourceRange().getBegin(), NameInfo, R, TInfo, isExplicit, isInline, /*isImplicitlyDeclared=*/false); @@ -3594,6 +4101,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, NewFD = CXXDestructorDecl::Create(Context, cast<CXXRecordDecl>(DC), + D.getSourceRange().getBegin(), NameInfo, R, TInfo, isInline, /*isImplicitlyDeclared=*/false); @@ -3603,8 +4111,9 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // Create a FunctionDecl to satisfy the function definition parsing // code path. - NewFD = FunctionDecl::Create(Context, DC, D.getIdentifierLoc(), - Name, R, TInfo, SC, SCAsWritten, isInline, + NewFD = FunctionDecl::Create(Context, DC, D.getSourceRange().getBegin(), + D.getIdentifierLoc(), Name, R, TInfo, + SC, SCAsWritten, isInline, /*hasPrototype=*/true); D.setInvalidType(); } @@ -3617,8 +4126,10 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, CheckConversionDeclarator(D, R, SC); NewFD = CXXConversionDecl::Create(Context, cast<CXXRecordDecl>(DC), + D.getSourceRange().getBegin(), NameInfo, R, TInfo, - isInline, isExplicit); + isInline, isExplicit, + SourceLocation()); isVirtualOkay = true; } else if (DC->isRecord()) { @@ -3636,7 +4147,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, } 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). @@ -3649,25 +4160,34 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, if (Name.getCXXOverloadedOperator() == OO_Delete || Name.getCXXOverloadedOperator() == OO_Array_Delete) isStatic = true; - + // This is a C++ method declaration. NewFD = CXXMethodDecl::Create(Context, cast<CXXRecordDecl>(DC), + D.getSourceRange().getBegin(), NameInfo, R, TInfo, - isStatic, SCAsWritten, isInline); + isStatic, SCAsWritten, isInline, + SourceLocation()); isVirtualOkay = !isStatic; } else { // Determine whether the function was written with a // prototype. This true when: // - we're in C++ (where every function has a prototype), - NewFD = FunctionDecl::Create(Context, DC, + NewFD = FunctionDecl::Create(Context, DC, D.getSourceRange().getBegin(), NameInfo, R, TInfo, SC, SCAsWritten, isInline, true/*HasPrototype*/); } + + if (isFriend && !isInline && 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; - NumMatchedTemplateParamLists = TemplateParamLists.size(); if (D.isInvalidType()) NewFD->setInvalidDecl(); @@ -3680,7 +4200,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // determine whether we have a template or a template specialization. bool Invalid = false; if (TemplateParameterList *TemplateParams - = MatchTemplateParametersToScopeSpecifier( + = MatchTemplateParametersToScopeSpecifier( D.getDeclSpec().getSourceRange().getBegin(), D.getCXXScopeSpec(), TemplateParamLists.get(), @@ -3688,54 +4208,71 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, isFriend, isExplicitSpecialization, Invalid)) { - // All but one template parameter lists have been matching. - --NumMatchedTemplateParamLists; - - if (TemplateParams->size() > 0) { - // This is a function template - - // Check that we can declare a template here. - if (CheckTemplateDeclScope(S, TemplateParams)) - return 0; - - FunctionTemplate = FunctionTemplateDecl::Create(Context, DC, - NewFD->getLocation(), - Name, TemplateParams, - NewFD); - FunctionTemplate->setLexicalDeclContext(CurContext); - NewFD->setDescribedFunctionTemplate(FunctionTemplate); - } else { - // This is a function template specialization. - isFunctionTemplateSpecialization = true; - - // C++0x [temp.expl.spec]p20 forbids "template<> friend void foo(int);". - if (isFriend && isFunctionTemplateSpecialization) { - // 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); - } + if (TemplateParams->size() > 0) { + // This is a function template - Diag(D.getIdentifierLoc(), diag::err_template_spec_decl_friend) - << Name << RemoveRange - << FixItHint::CreateRemoval(RemoveRange) - << FixItHint::CreateInsertion(InsertLoc, "<>"); - } - } + // 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 (NumMatchedTemplateParamLists > 0 && D.getCXXScopeSpec().isSet()) { - NewFD->setTemplateParameterListsInfo(Context, - NumMatchedTemplateParamLists, - TemplateParamLists.release()); + 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) { @@ -3802,7 +4339,9 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, } // Filter out previous declarations that don't match the scope. - FilterLookupForScope(*this, Previous, DC, S, NewFD->hasLinkage()); + FilterLookupForScope(*this, Previous, DC, S, NewFD->hasLinkage(), + isExplicitSpecialization || + isFunctionTemplateSpecialization); if (isFriend) { // For now, claim that the objects have no previous declaration. @@ -3863,8 +4402,13 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // In C++, the empty parameter-type-list must be spelled "void"; a // typedef of void is not permitted. if (getLangOptions().CPlusPlus && - Param->getType().getUnqualifiedType() != Context.VoidTy) - Diag(Param->getLocation(), diag::err_param_typedef_of_void); + Param->getType().getUnqualifiedType() != Context.VoidTy) { + bool IsTypeAlias = false; + if (const TypedefType *TT = Param->getType()->getAs<TypedefType>()) + IsTypeAlias = isa<TypeAliasDecl>(TT->getDecl()); + 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<ParmVarDecl>(FTI.ArgInfo[i].Param); @@ -3892,6 +4436,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, 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 { @@ -3977,9 +4522,15 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, Previous)) NewFD->setInvalidDecl(); } else if (isFunctionTemplateSpecialization) { - if (CheckFunctionTemplateSpecialization(NewFD, - (HasExplicitTemplateArgs ? &TemplateArgs : 0), - Previous)) + if (CurContext->isDependentContext() && CurContext->isRecord() + && !isFriend) { + Diag(NewFD->getLocation(), diag::err_function_specialization_in_class) + << NewFD->getDeclName(); + NewFD->setInvalidDecl(); + return 0; + } else if (CheckFunctionTemplateSpecialization(NewFD, + (HasExplicitTemplateArgs ? &TemplateArgs : 0), + Previous)) NewFD->setInvalidDecl(); } else if (isExplicitSpecialization && isa<CXXMethodDecl>(NewFD)) { if (CheckMemberSpecialization(NewFD, Previous)) @@ -4049,7 +4600,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // are situations where these conditions don't apply and we // can actually do this check immediately. if (isFriend && - (NumMatchedTemplateParamLists || + (TemplateParamLists.size() || D.getCXXScopeSpec().getScopeRep()->isDependent() || CurContext->isDependentContext())) { // ignore these @@ -4146,7 +4697,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, RegisterLocallyScopedExternCDecl(NewFD, Previous, S); // Set this FunctionDecl's range up to the right paren. - NewFD->setLocEnd(D.getSourceRange().getEnd()); + NewFD->setRangeEnd(D.getSourceRange().getEnd()); if (getLangOptions().CPlusPlus) { if (FunctionTemplate) { @@ -4420,8 +4971,7 @@ void Sema::CheckMain(FunctionDecl* FD) { // 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.Target.getTriple().getOS() == llvm::Triple::Darwin) + if (nparams == 4 && Context.Target.getTriple().isOSDarwin()) HasExtraParameters = false; if (HasExtraParameters) { @@ -4493,6 +5043,46 @@ bool Sema::CheckForConstantInitializer(Expr *Init, QualType DclT) { 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<SelfReferenceChecker> { + Sema &S; + Decl *OrigDecl; + + public: + typedef EvaluatedExprVisitor<SelfReferenceChecker> Inherited; + + SelfReferenceChecker(Sema &S, Decl *OrigDecl) : Inherited(S.Context), + S(S), OrigDecl(OrigDecl) { } + + void VisitExpr(Expr *E) { + if (isa<ObjCMessageExpr>(*E)) return; + Inherited::VisitExpr(E); + } + + void VisitImplicitCastExpr(ImplicitCastExpr *E) { + CheckForSelfReference(E); + Inherited::VisitImplicitCastExpr(E); + } + + void CheckForSelfReference(ImplicitCastExpr *E) { + if (E->getCastKind() != CK_LValueToRValue) return; + Expr* SubExpr = E->getSubExpr()->IgnoreParenImpCasts(); + DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(SubExpr); + if (!DRE) return; + Decl* ReferenceDecl = DRE->getDecl(); + if (OrigDecl != ReferenceDecl) return; + LookupResult Result(S, DRE->getNameInfo(), Sema::LookupOrdinaryName, + Sema::NotForRedeclaration); + S.Diag(SubExpr->getLocStart(), diag::warn_uninit_self_reference_in_init) + << Result.getLookupName() << OrigDecl->getLocation() + << SubExpr->getSourceRange(); + } + }; +} + /// AddInitializerToDecl - Adds the initializer Init to the /// declaration dcl. If DirectInit is true, this is C++ direct /// initialization rather than copy initialization. @@ -4503,6 +5093,17 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, if (RealDecl == 0 || RealDecl->isInvalidDecl()) return; + // Check for self-references within variable initializers. + if (VarDecl *vd = dyn_cast<VarDecl>(RealDecl)) { + // Variables declared within a function/method body are handled + // by a dataflow analysis. + if (!vd->hasLocalStorage() && !vd->isStaticLocal()) + SelfReferenceChecker(*this, RealDecl).VisitExpr(Init); + } + else { + SelfReferenceChecker(*this, RealDecl).VisitExpr(Init); + } + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(RealDecl)) { // With declarators parsed the way they are, the parser cannot // distinguish between a normal initializer and a pure-specifier. @@ -4533,15 +5134,17 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, // C++0x [decl.spec.auto]p6. Deduce the type which 'auto' stands in for. if (TypeMayContainAuto && VDecl->getType()->getContainedAutoType()) { - QualType DeducedType; - if (!DeduceAutoType(VDecl->getType(), Init, DeducedType)) { + TypeSourceInfo *DeducedType = 0; + if (!DeduceAutoType(VDecl->getTypeSourceInfo(), Init, DeducedType)) Diag(VDecl->getLocation(), diag::err_auto_var_deduction_failure) << VDecl->getDeclName() << VDecl->getType() << Init->getType() << Init->getSourceRange(); + if (!DeducedType) { RealDecl->setInvalidDecl(); return; } - VDecl->setType(DeducedType); + VDecl->setTypeSourceInfo(DeducedType); + VDecl->setType(DeducedType->getType()); // If this is a redeclaration, check that the type we just deduced matches // the previously declared type. @@ -4952,7 +5555,7 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl, const RecordType *Record = Context.getBaseElementType(Type)->getAs<RecordType>(); - if (Record && getLangOptions().CPlusPlus && !getLangOptions().CPlusPlus0x && + if (Record && getLangOptions().CPlusPlus && cast<CXXRecordDecl>(Record->getDecl())->isPOD()) { // C++03 [dcl.init]p9: // If no initializer is specified for an object, and the @@ -4965,7 +5568,6 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl, // any, have an indeterminate initial value); if the object // or any of its subobjects are of const-qualified type, the // program is ill-formed. - // FIXME: DPG thinks it is very fishy that C++0x disables this. } else { // Check for jumps past the implicit initializer. C++0x // clarifies that this applies to a "variable with automatic @@ -4990,6 +5592,47 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl, } } +void Sema::ActOnCXXForRangeDecl(Decl *D) { + VarDecl *VD = dyn_cast<VarDecl>(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; + } + // FIXME: constexpr isn't allowed here. + //if (DS.isConstexprSpecified()) + // 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; @@ -5058,7 +5701,7 @@ Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, if (Decl *D = Group[i]) Decls.push_back(D); - return BuildDeclaratorGroup(Decls.data(), Decls.size(), + return BuildDeclaratorGroup(Decls.data(), Decls.size(), DS.getTypeSpecType() == DeclSpec::TST_auto); } @@ -5195,12 +5838,18 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { // the enclosing context. This prevents them from accidentally // looking like class members in C++. ParmVarDecl *New = CheckParameter(Context.getTranslationUnitDecl(), - TInfo, parmDeclType, II, - D.getIdentifierLoc(), + D.getSourceRange().getBegin(), + D.getIdentifierLoc(), II, + parmDeclType, TInfo, StorageClass, StorageClassAsWritten); if (D.isInvalidType()) - New->setInvalidDecl(); + 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); @@ -5220,7 +5869,10 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { ParmVarDecl *Sema::BuildParmVarDeclForTypedef(DeclContext *DC, SourceLocation Loc, QualType T) { - ParmVarDecl *Param = ParmVarDecl::Create(Context, DC, Loc, 0, + /* 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(); @@ -5272,14 +5924,13 @@ void Sema::DiagnoseSizeOfParametersAndReturnValue(ParmVarDecl * const *Param, } } -ParmVarDecl *Sema::CheckParameter(DeclContext *DC, - TypeSourceInfo *TSInfo, QualType T, - IdentifierInfo *Name, - SourceLocation NameLoc, +ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc, + SourceLocation NameLoc, IdentifierInfo *Name, + QualType T, TypeSourceInfo *TSInfo, VarDecl::StorageClass StorageClass, VarDecl::StorageClass StorageClassAsWritten) { - ParmVarDecl *New = ParmVarDecl::Create(Context, DC, NameLoc, Name, - adjustParameterType(T), TSInfo, + ParmVarDecl *New = ParmVarDecl::Create(Context, DC, StartLoc, NameLoc, Name, + adjustParameterType(T), TSInfo, StorageClass, StorageClassAsWritten, 0); @@ -5331,7 +5982,8 @@ void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D, // Implicitly declare the argument as type 'int' for lack of a better // type. - DeclSpec DS; + AttributeFactory attrs; + DeclSpec DS(attrs); const char* PrevSpec; // unused unsigned DiagID; // unused DS.SetTypeSpecType(DeclSpec::TST_int, FTI.ArgInfo[i].IdentLoc, @@ -5374,7 +6026,7 @@ static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD) { return false; // Don't warn about inline functions. - if (FD->isInlineSpecified()) + if (FD->isInlined()) return false; // Don't warn about function templates. @@ -5400,6 +6052,22 @@ static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD) { 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->hasBody(Definition) && + !canRedefineFunction(Definition, getLangOptions())) { + if (getLangOptions().GNUMode && Definition->isInlineSpecified() && + Definition->getStorageClass() == SC_Extern) + Diag(FD->getLocation(), diag::err_redefinition_extern_inline) + << FD->getDeclName() << getLangOptions().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(); @@ -5417,19 +6085,8 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) { PushFunctionScope(); // See if this is a redefinition. - // But don't complain if we're in GNU89 mode and the previous definition - // was an extern inline function. - const FunctionDecl *Definition; - if (FD->hasBody(Definition) && - !canRedefineFunction(Definition, getLangOptions())) { - if (getLangOptions().GNUMode && Definition->isInlineSpecified() && - Definition->getStorageClass() == SC_Extern) - Diag(FD->getLocation(), diag::err_redefinition_extern_inline) - << FD->getDeclName() << getLangOptions().CPlusPlus; - else - Diag(FD->getLocation(), diag::err_redefinition) << FD->getDeclName(); - Diag(Definition->getLocation(), diag::note_previous_definition); - } + if (!FD->isLateTemplateParsed()) + CheckForFunctionRedefinition(FD); // Builtin functions cannot be defined. if (unsigned BuiltinID = FD->getBuiltinID()) { @@ -5481,7 +6138,9 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) { DLLImportAttr *DA = FD->getAttr<DLLImportAttr>(); if (DA && (!FD->getAttr<DLLExportAttr>())) { // dllimport attribute cannot be directly applied to definition. - if (!DA->isInherited()) { + // Microsoft accepts dllimport for functions defined within class scope. + if (!DA->isInherited() && + !(LangOpts.Microsoft && FD->getLexicalDeclContext()->isRecord())) { Diag(FD->getLocation(), diag::err_attribute_can_be_applied_only_to_symbol_declaration) << "dllimport"; @@ -5615,7 +6274,8 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, // 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()) + if (PP.getDiagnostics().hasErrorOccurred() || + PP.getDiagnostics().getSuppressAllDiagnostics()) ExprTemporaries.clear(); else if (!isa<FunctionTemplateDecl>(dcl)) { // Since the body is valid, issue any analysis-based warnings that are @@ -5666,17 +6326,18 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, // Set a Declarator for the implicit definition: int foo(); const char *Dummy; - DeclSpec DS; + 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(ParsedAttributes(), - false, false, SourceLocation(), 0, + D.AddTypeInfo(DeclaratorChunk::getFunction(false, false, SourceLocation(), 0, 0, 0, true, SourceLocation(), - false, SourceLocation(), - false, 0,0,0, Loc, Loc, D), + EST_None, SourceLocation(), + 0, 0, 0, 0, Loc, Loc, D), + DS.getAttributes(), SourceLocation()); D.SetIdentifier(&II, Loc); @@ -5784,6 +6445,7 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T, // Scope manipulation handled by caller. TypedefDecl *NewTD = TypedefDecl::Create(Context, CurContext, + D.getSourceRange().getBegin(), D.getIdentifierLoc(), D.getIdentifier(), TInfo); @@ -5810,7 +6472,7 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T, // 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->getTypedefForAnonDecl()) break; + if (tagFromDeclSpec->getTypedefNameForAnonDecl()) break; // A well-formed anonymous tag must always be a TUK_Definition. assert(tagFromDeclSpec->isThisDeclarationADefinition()); @@ -5820,7 +6482,7 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T, break; // Otherwise, set this is the anon-decl typedef for the tag. - tagFromDeclSpec->setTypedefForAnonDecl(NewTD); + tagFromDeclSpec->setTypedefNameForAnonDecl(NewTD); break; } @@ -5897,36 +6559,33 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // FIXME: Check explicit specializations more carefully. bool isExplicitSpecialization = false; - unsigned NumMatchedTemplateParamLists = TemplateParameterLists.size(); 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 (NumMatchedTemplateParamLists || + if (TemplateParameterLists.size() > 0 || (SS.isNotEmpty() && TUK != TUK_Reference)) { if (TemplateParameterList *TemplateParams = MatchTemplateParametersToScopeSpecifier(KWLoc, SS, TemplateParameterLists.get(), - TemplateParameterLists.size(), + TemplateParameterLists.size(), TUK == TUK_Friend, isExplicitSpecialization, Invalid)) { - // All but one template parameter lists have been matching. - --NumMatchedTemplateParamLists; - 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); - TemplateParameterLists.release(); + TemplateParams, AS, + TemplateParameterLists.size() - 1, + (TemplateParameterList**) TemplateParameterLists.release()); return Result.get(); } else { // The "template<>" header is extraneous. @@ -6164,7 +6823,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // 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 (getLangOptions().CPlusPlus) { - if (TypedefDecl *TD = dyn_cast<TypedefDecl>(PrevDecl)) { + if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(PrevDecl)) { if (const TagType *TT = TD->getUnderlyingType()->getAs<TagType>()) { TagDecl *Tag = TT->getDecl(); if (Tag->getDeclName() == Name && @@ -6184,7 +6843,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // 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)) { + 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, KWLoc, *Name)) { @@ -6322,30 +6981,34 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, !Previous.isForRedeclaration()) { unsigned Kind = 0; if (isa<TypedefDecl>(PrevDecl)) Kind = 1; - else if (isa<ClassTemplateDecl>(PrevDecl)) Kind = 2; + else if (isa<TypeAliasDecl>(PrevDecl)) Kind = 2; + else if (isa<ClassTemplateDecl>(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)) { + } 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<TypedefDecl>(PrevDecl)) Kind = 1; - else if (isa<ClassTemplateDecl>(PrevDecl)) Kind = 2; + else if (isa<TypeAliasDecl>(PrevDecl)) Kind = 2; + else if (isa<ClassTemplateDecl>(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 (isa<TypedefDecl>(PrevDecl)) { + } else if (TypedefNameDecl *TND = dyn_cast<TypedefNameDecl>(PrevDecl)) { + unsigned Kind = 0; + if (isa<TypeAliasDecl>(PrevDecl)) Kind = 1; Diag(NameLoc, diag::err_tag_definition_of_typedef) - << Name - << cast<TypedefDecl>(PrevDecl)->getUnderlyingType(); + << Name << Kind << TND->getUnderlyingType(); Diag(PrevDecl->getLocation(), diag::note_previous_decl) << PrevDecl; Invalid = true; @@ -6385,7 +7048,7 @@ CreateNewDecl: 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, Loc, Name, KWLoc, + New = EnumDecl::Create(Context, SearchDC, KWLoc, Loc, Name, cast_or_null<EnumDecl>(PrevDecl), ScopedEnum, ScopedEnumUsesClassTag, !EnumUnderlying.isNull()); // If this is an undefined enum, warn. @@ -6431,13 +7094,13 @@ CreateNewDecl: // struct X { int A; } D; D should chain to X. if (getLangOptions().CPlusPlus) { // FIXME: Look for a way to use RecordDecl for simple structs. - New = CXXRecordDecl::Create(Context, Kind, SearchDC, Loc, Name, KWLoc, + New = CXXRecordDecl::Create(Context, Kind, SearchDC, KWLoc, Loc, Name, cast_or_null<CXXRecordDecl>(PrevDecl)); - + if (isStdBadAlloc && (!StdBadAlloc || getStdBadAlloc()->isImplicit())) StdBadAlloc = cast<CXXRecordDecl>(New); } else - New = RecordDecl::Create(Context, Kind, SearchDC, Loc, Name, KWLoc, + New = RecordDecl::Create(Context, Kind, SearchDC, KWLoc, Loc, Name, cast_or_null<RecordDecl>(PrevDecl)); } @@ -6445,9 +7108,9 @@ CreateNewDecl: if (SS.isNotEmpty()) { if (SS.isSet()) { New->setQualifierInfo(SS.getWithLocInContext(Context)); - if (NumMatchedTemplateParamLists > 0) { + if (TemplateParameterLists.size() > 0) { New->setTemplateParameterListsInfo(Context, - NumMatchedTemplateParamLists, + TemplateParameterLists.size(), (TemplateParameterList**) TemplateParameterLists.release()); } } @@ -6466,6 +7129,8 @@ CreateNewDecl: // the #pragma tokens are effectively skipped over during the // parsing of the struct). AddAlignmentAttributesForRecord(RD); + + AddMsStructLayoutForRecord(RD); } // If this is a specialization of a member class (of a class template), @@ -6541,7 +7206,7 @@ void Sema::ActOnTagStartDefinition(Scope *S, Decl *TagD) { } void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD, - ClassVirtSpecifiers &CVS, + SourceLocation FinalLoc, SourceLocation LBraceLoc) { AdjustDeclIfTemplate(TagD); CXXRecordDecl *Record = cast<CXXRecordDecl>(TagD); @@ -6551,10 +7216,8 @@ void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD, if (!Record->getIdentifier()) return; - if (CVS.isFinalSpecified()) - Record->addAttr(new (Context) FinalAttr(CVS.getFinalLoc(), Context)); - if (CVS.isExplicitSpecified()) - Record->addAttr(new (Context) ExplicitAttr(CVS.getExplicitLoc(), Context)); + if (FinalLoc.isValid()) + Record->addAttr(new (Context) FinalAttr(FinalLoc, Context)); // C++ [class]p2: // [...] The class-name is also inserted into the scope of the @@ -6562,10 +7225,9 @@ void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD, // 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->getLocation(), + = CXXRecordDecl::Create(Context, Record->getTagKind(), CurContext, + Record->getLocStart(), Record->getLocation(), Record->getIdentifier(), - Record->getTagKeywordLoc(), /*PrevDecl=*/0, /*DelayTypeCreation=*/true); Context.getTypeDeclType(InjectedClassName, Record); @@ -6852,7 +7514,7 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, } } - FieldDecl *NewFD = FieldDecl::Create(Context, Record, Loc, II, T, TInfo, + FieldDecl *NewFD = FieldDecl::Create(Context, Record, TSSL, Loc, II, T, TInfo, BitWidth, Mutable); if (InvalidDecl) NewFD->setInvalidDecl(); @@ -7152,8 +7814,8 @@ Decl *Sema::ActOnIvar(Scope *S, } // Construct the decl. - ObjCIvarDecl *NewID = ObjCIvarDecl::Create(Context, - EnclosingContext, Loc, II, T, + ObjCIvarDecl *NewID = ObjCIvarDecl::Create(Context, EnclosingContext, + DeclStart, Loc, II, T, TInfo, ac, (Expr *)BitfieldWidth); if (II) { @@ -7216,7 +7878,7 @@ void Sema::ActOnLastBitfield(SourceLocation DeclLoc, Decl *EnclosingDecl, Expr * BW = IntegerLiteral::Create(Context, Zero, Context.CharTy, DeclLoc); Ivar = ObjCIvarDecl::Create(Context, cast<ObjCContainerDecl>(EnclosingDecl), - DeclLoc, 0, + DeclLoc, DeclLoc, 0, Context.CharTy, Context.CreateTypeSourceInfo(Context.CharTy), ObjCIvarDecl::Private, BW, @@ -7281,20 +7943,27 @@ void Sema::ActOnFields(Scope* S, continue; } else if (FDTy->isIncompleteArrayType() && Record && ((i == NumFields - 1 && !Record->isUnion()) || - (getLangOptions().Microsoft && + ((getLangOptions().Microsoft || getLangOptions().CPlusPlus) && (i == NumFields - 1 || Record->isUnion())))) { // Flexible array member. - // Microsoft is more permissive regarding flexible array. + // 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 (getLangOptions().Microsoft) { if (Record->isUnion()) - Diag(FD->getLocation(), diag::ext_flexible_array_union) + Diag(FD->getLocation(), diag::ext_flexible_array_union_ms) + << FD->getDeclName(); + else if (NumFields == 1) + Diag(FD->getLocation(), diag::ext_flexible_array_empty_aggregate_ms) + << FD->getDeclName() << Record->getTagKind(); + } else if (getLangOptions().CPlusPlus) { + if (Record->isUnion()) + Diag(FD->getLocation(), diag::ext_flexible_array_union_gnu) << FD->getDeclName(); else if (NumFields == 1) - Diag(FD->getLocation(), diag::ext_flexible_array_empty_aggregate) + Diag(FD->getLocation(), diag::ext_flexible_array_empty_aggregate_gnu) << FD->getDeclName() << Record->getTagKind(); - } else if (NumNamedMembers < 1) { + } else if (NumNamedMembers < 1) { Diag(FD->getLocation(), diag::err_flexible_array_empty_struct) << FD->getDeclName(); FD->setInvalidDecl(); @@ -7547,7 +8216,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, << (EnumVal.isUnsigned() || EnumVal.isNonNegative()); else if (!Context.hasSameType(Val->getType(), Context.IntTy)) { // Force the type of the expression to 'int'. - ImpCastExprToType(Val, Context.IntTy, CK_IntegralCast); + Val = ImpCastExprToType(Val, Context.IntTy, CK_IntegralCast).take(); } } @@ -7560,12 +8229,12 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, if (!isRepresentableIntegerValue(Context, EnumVal, EltTy)) { if (getLangOptions().Microsoft) { Diag(IdLoc, diag::ext_enumerator_too_large) << EltTy; - ImpCastExprToType(Val, EltTy, CK_IntegralCast); + Val = ImpCastExprToType(Val, EltTy, CK_IntegralCast).take(); } else Diag(IdLoc, diag::err_enumerator_too_large) << EltTy; } else - ImpCastExprToType(Val, EltTy, CK_IntegralCast); + Val = ImpCastExprToType(Val, EltTy, CK_IntegralCast).take(); } else { // C++0x [dcl.enum]p5: @@ -7949,11 +8618,14 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, NumPositiveBits, NumNegativeBits); } -Decl *Sema::ActOnFileScopeAsmDecl(SourceLocation Loc, Expr *expr) { +Decl *Sema::ActOnFileScopeAsmDecl(Expr *expr, + SourceLocation StartLoc, + SourceLocation EndLoc) { StringLiteral *AsmString = cast<StringLiteral>(expr); FileScopeAsmDecl *New = FileScopeAsmDecl::Create(Context, CurContext, - Loc, AsmString); + AsmString, StartLoc, + EndLoc); CurContext->addDecl(New); return New; } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp index 893cf6a..7f93ab7 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp @@ -24,6 +24,26 @@ 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 { + ExpectedFunction, + ExpectedUnion, + ExpectedVariableOrFunction, + ExpectedFunctionOrMethod, + ExpectedParameter, + ExpectedParameterOrMethod, + ExpectedFunctionMethodOrBlock, + ExpectedClassOrVirtualMethod, + ExpectedFunctionMethodOrParameter, + ExpectedClass, + ExpectedVirtualMethod, + ExpectedClassMember, + ExpectedVariable, + ExpectedMethod, + ExpectedVariableFunctionOrLabel +}; + //===----------------------------------------------------------------------===// // Helper functions //===----------------------------------------------------------------------===// @@ -35,7 +55,7 @@ static const FunctionType *getFunctionType(const Decl *d, Ty = decl->getType(); else if (const FieldDecl *decl = dyn_cast<FieldDecl>(d)) Ty = decl->getType(); - else if (const TypedefDecl* decl = dyn_cast<TypedefDecl>(d)) + else if (const TypedefNameDecl* decl = dyn_cast<TypedefNameDecl>(d)) Ty = decl->getUnderlyingType(); else return 0; @@ -81,8 +101,8 @@ static bool isFunctionOrMethodOrBlock(const Decl *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<DeclaratorDecl>(d) || isa<BlockDecl>(d) || isa<TypedefDecl>(d); + // In some sense, TypedefNameDecl really *ought* to be a DeclaratorDecl. + return isa<DeclaratorDecl>(d) || isa<BlockDecl>(d) || isa<TypedefNameDecl>(d); } /// hasFunctionProto - Return true if the given decl has a argument @@ -182,7 +202,7 @@ static inline bool isCFStringType(QualType T, ASTContext &Ctx) { static void HandleExtVectorTypeAttr(Scope *scope, Decl *d, const AttributeList &Attr, Sema &S) { - TypedefDecl *tDecl = dyn_cast<TypedefDecl>(d); + TypedefNameDecl *tDecl = dyn_cast<TypedefNameDecl>(d); if (tDecl == 0) { S.Diag(Attr.getLoc(), diag::err_typecheck_ext_vector_not_typedef); return; @@ -241,6 +261,13 @@ static void HandlePackedAttr(Decl *d, const AttributeList &Attr, Sema &S) { S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); } +static void HandleMsStructAttr(Decl *d, const AttributeList &Attr, Sema &S) { + if (TagDecl *TD = dyn_cast<TagDecl>(d)) + TD->addAttr(::new (S.Context) MsStructAttr(Attr.getLoc(), S.Context)); + else + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); +} + static void HandleIBAction(Decl *d, const AttributeList &Attr, Sema &S) { // check the attribute arguments. if (Attr.getNumArgs() > 0) { @@ -332,7 +359,7 @@ static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) { // ignore it as well if (!isFunctionOrMethod(d) || !hasFunctionProto(d)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 0 /*function*/; + << Attr.getName() << ExpectedFunction; return; } @@ -474,8 +501,8 @@ static void HandleOwnershipAttr(Decl *d, const AttributeList &AL, Sema &S) { } if (!isFunction(d) || !hasFunctionProto(d)) { - S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) << AL.getName() - << 0 /*function*/; + S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) + << AL.getName() << ExpectedFunction; return; } @@ -615,7 +642,7 @@ static void HandleWeakRefAttr(Decl *d, const AttributeList &Attr, Sema &S) { if (!isa<VarDecl>(d) && !isa<FunctionDecl>(d)) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) - << Attr.getName() << 2 /*variables and functions*/; + << Attr.getName() << ExpectedVariableOrFunction; return; } @@ -701,7 +728,7 @@ static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - if (S.Context.Target.getTriple().getOS() == llvm::Triple::Darwin) { + if (S.Context.Target.getTriple().isOSDarwin()) { S.Diag(Attr.getLoc(), diag::err_alias_not_supported_on_darwin); return; } @@ -722,7 +749,7 @@ static void HandleNakedAttr(Decl *d, const AttributeList &Attr, if (!isa<FunctionDecl>(d)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 0 /*function*/; + << Attr.getName() << ExpectedFunction; return; } @@ -732,14 +759,14 @@ static void HandleNakedAttr(Decl *d, const AttributeList &Attr, static void HandleAlwaysInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) { // Check the attribute arguments. - if (Attr.getNumArgs() != 0) { + if (Attr.hasParameterOrArguments()) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; return; } if (!isa<FunctionDecl>(d)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 0 /*function*/; + << Attr.getName() << ExpectedFunction; return; } @@ -748,7 +775,7 @@ static void HandleAlwaysInlineAttr(Decl *d, const AttributeList &Attr, static void HandleMallocAttr(Decl *d, const AttributeList &Attr, Sema &S) { // Check the attribute arguments. - if (Attr.getNumArgs() != 0) { + if (Attr.hasParameterOrArguments()) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; return; } @@ -780,7 +807,7 @@ static void HandleNoCommonAttr(Decl *d, const AttributeList &Attr, Sema &S) { d->addAttr(::new (S.Context) NoCommonAttr(Attr.getLoc(), S.Context)); else S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 12 /* variable */; + << Attr.getName() << ExpectedVariable; } static void HandleCommonAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -789,7 +816,7 @@ static void HandleCommonAttr(Decl *d, const AttributeList &Attr, Sema &S) { d->addAttr(::new (S.Context) CommonAttr(Attr.getLoc(), S.Context)); else S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 12 /* variable */; + << Attr.getName() << ExpectedVariable; } static void HandleNoReturnAttr(Decl *d, const AttributeList &attr, Sema &S) { @@ -799,7 +826,7 @@ static void HandleNoReturnAttr(Decl *d, const AttributeList &attr, Sema &S) { if (!isa<ObjCMethodDecl>(d)) { S.Diag(attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << attr.getName() << 0 /*function*/; + << attr.getName() << ExpectedFunctionOrMethod; return; } @@ -807,7 +834,7 @@ static void HandleNoReturnAttr(Decl *d, const AttributeList &attr, Sema &S) { } bool Sema::CheckNoReturnAttr(const AttributeList &attr) { - if (attr.getNumArgs() != 0) { + if (attr.hasParameterOrArguments()) { Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; attr.setInvalid(); return true; @@ -834,7 +861,7 @@ static void HandleAnalyzerNoReturnAttr(Decl *d, const AttributeList &Attr, S.Diag(Attr.getLoc(), Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type : diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 0 /*function*/; + << Attr.getName() << ExpectedFunctionMethodOrBlock; return; } } @@ -870,7 +897,7 @@ static void HandleVecReturnAttr(Decl *d, const AttributeList &Attr, */ if (!isa<RecordDecl>(d)) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) - << Attr.getName() << 9 /*class*/; + << Attr.getName() << ExpectedClass; return; } @@ -907,7 +934,7 @@ static void HandleVecReturnAttr(Decl *d, const AttributeList &Attr, static void HandleDependencyAttr(Decl *d, const AttributeList &Attr, Sema &S) { if (!isFunctionOrMethod(d) && !isa<ParmVarDecl>(d)) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) - << Attr.getName() << 8 /*function, method, or parameter*/; + << Attr.getName() << ExpectedFunctionMethodOrParameter; return; } // FIXME: Actually store the attribute on the declaration @@ -915,7 +942,7 @@ static void HandleDependencyAttr(Decl *d, const AttributeList &Attr, Sema &S) { static void HandleUnusedAttr(Decl *d, const AttributeList &Attr, Sema &S) { // check the attribute arguments. - if (Attr.getNumArgs() != 0) { + if (Attr.hasParameterOrArguments()) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; return; } @@ -923,7 +950,7 @@ static void HandleUnusedAttr(Decl *d, const AttributeList &Attr, Sema &S) { if (!isa<VarDecl>(d) && !isa<ObjCIvarDecl>(d) && !isFunctionOrMethod(d) && !isa<TypeDecl>(d) && !isa<LabelDecl>(d)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 14 /*variable, function, labels*/; + << Attr.getName() << ExpectedVariableFunctionOrLabel; return; } @@ -932,7 +959,7 @@ static void HandleUnusedAttr(Decl *d, const AttributeList &Attr, Sema &S) { static void HandleUsedAttr(Decl *d, const AttributeList &Attr, Sema &S) { // check the attribute arguments. - if (Attr.getNumArgs() != 0) { + if (Attr.hasParameterOrArguments()) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; return; } @@ -944,7 +971,7 @@ static void HandleUsedAttr(Decl *d, const AttributeList &Attr, Sema &S) { } } else if (!isFunctionOrMethod(d)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 2 /*variable and function*/; + << Attr.getName() << ExpectedVariableOrFunction; return; } @@ -953,9 +980,8 @@ static void HandleUsedAttr(Decl *d, const AttributeList &Attr, Sema &S) { static void HandleConstructorAttr(Decl *d, const AttributeList &Attr, Sema &S) { // check the attribute arguments. - if (Attr.getNumArgs() != 0 && Attr.getNumArgs() != 1) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) - << "0 or 1"; + if (Attr.getNumArgs() > 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1; return; } @@ -974,7 +1000,7 @@ static void HandleConstructorAttr(Decl *d, const AttributeList &Attr, Sema &S) { if (!isa<FunctionDecl>(d)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 0 /*function*/; + << Attr.getName() << ExpectedFunction; return; } @@ -984,9 +1010,8 @@ static void HandleConstructorAttr(Decl *d, const AttributeList &Attr, Sema &S) { static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) { // check the attribute arguments. - if (Attr.getNumArgs() != 0 && Attr.getNumArgs() != 1) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) - << "0 or 1"; + if (Attr.getNumArgs() > 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1; return; } @@ -1005,7 +1030,7 @@ static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) { if (!isa<FunctionDecl>(d)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 0 /*function*/; + << Attr.getName() << ExpectedFunction; return; } @@ -1016,8 +1041,7 @@ static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) { static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) { unsigned NumArgs = Attr.getNumArgs(); if (NumArgs > 1) { - S.Diag(Attr.getLoc(), - diag::err_attribute_wrong_number_arguments) << "0 or 1"; + S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1; return; } @@ -1039,8 +1063,7 @@ static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) { static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) { unsigned NumArgs = Attr.getNumArgs(); if (NumArgs > 1) { - S.Diag(Attr.getLoc(), - diag::err_attribute_wrong_number_arguments) << "0 or 1"; + S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1; return; } @@ -1058,6 +1081,59 @@ static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) { d->addAttr(::new (S.Context) UnavailableAttr(Attr.getLoc(), S.Context, Str)); } +static void HandleAvailabilityAttr(Decl *d, const AttributeList &Attr, + Sema &S) { + IdentifierInfo *Platform = Attr.getParameterName(); + SourceLocation PlatformLoc = Attr.getParameterLoc(); + + llvm::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; + } + + d->addAttr(::new (S.Context) AvailabilityAttr(Attr.getLoc(), S.Context, + Platform, + Introduced.Version, + Deprecated.Version, + Obsoleted.Version, + IsUnavailable)); +} + static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) { // check the attribute arguments. if (Attr.getNumArgs() != 1) { @@ -1094,6 +1170,51 @@ static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) { d->addAttr(::new (S.Context) VisibilityAttr(Attr.getLoc(), S.Context, type)); } +static void HandleObjCMethodFamilyAttr(Decl *decl, const AttributeList &attr, + Sema &S) { + ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(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; + } + + llvm::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; + } + + decl->addAttr(new (S.Context) ObjCMethodFamilyAttr(attr.getLoc(), + S.Context, family)); +} + static void HandleObjCExceptionAttr(Decl *D, const AttributeList &Attr, Sema &S) { if (Attr.getNumArgs() != 0) { @@ -1115,7 +1236,7 @@ static void HandleObjCNSObject(Decl *D, const AttributeList &Attr, Sema &S) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; return; } - if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) { + if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) { QualType T = TD->getUnderlyingType(); if (!T->isPointerType() || !T->getAs<PointerType>()->getPointeeType()->isRecordType()) { @@ -1168,8 +1289,7 @@ static void HandleBlocksAttr(Decl *d, const AttributeList &Attr, Sema &S) { static void HandleSentinelAttr(Decl *d, const AttributeList &Attr, Sema &S) { // check the attribute arguments. if (Attr.getNumArgs() > 2) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) - << "0, 1 or 2"; + S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 2; return; } @@ -1247,12 +1367,12 @@ static void HandleSentinelAttr(Decl *d, const AttributeList &Attr, Sema &S) { } } else { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 6 /*function, method or block */; + << Attr.getName() << ExpectedFunctionMethodOrBlock; return; } } else { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 6 /*function, method or block */; + << Attr.getName() << ExpectedFunctionMethodOrBlock; return; } d->addAttr(::new (S.Context) SentinelAttr(Attr.getLoc(), S.Context, sentinel, @@ -1268,7 +1388,7 @@ static void HandleWarnUnusedResult(Decl *D, const AttributeList &Attr, Sema &S) if (!isFunction(D) && !isa<ObjCMethodDecl>(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 0 /*function*/; + << Attr.getName() << ExpectedFunctionOrMethod; return; } @@ -1289,14 +1409,14 @@ static void HandleWarnUnusedResult(Decl *D, const AttributeList &Attr, Sema &S) static void HandleWeakAttr(Decl *d, const AttributeList &attr, Sema &S) { // check the attribute arguments. - if (attr.getNumArgs() != 0) { + if (attr.hasParameterOrArguments()) { S.Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; return; } if (!isa<VarDecl>(d) && !isa<FunctionDecl>(d)) { S.Diag(attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << attr.getName() << 2 /*variables and functions*/; + << attr.getName() << ExpectedVariableOrFunction; return; } @@ -1320,27 +1440,19 @@ static void HandleWeakImportAttr(Decl *D, const AttributeList &Attr, Sema &S) { // weak_import only applies to variable & function declarations. bool isDef = false; - if (VarDecl *VD = dyn_cast<VarDecl>(D)) { - isDef = (!VD->hasExternalStorage() || VD->getInit()); - } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { - isDef = FD->hasBody(); - } else if (isa<ObjCPropertyDecl>(D) || isa<ObjCMethodDecl>(D)) { - // We ignore weak import on properties and methods - return; - } else if (!(S.LangOpts.ObjCNonFragileABI && isa<ObjCInterfaceDecl>(D))) { - // Don't issue the warning for darwin as target; yet, ignore the attribute. - if (S.Context.Target.getTriple().getOS() != llvm::Triple::Darwin || - !isa<ObjCInterfaceDecl>(D)) + 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<ObjCPropertyDecl>(D) || isa<ObjCMethodDecl>(D) || + (S.Context.Target.getTriple().isOSDarwin() && + isa<ObjCInterfaceDecl>(D))) { + // Nothing to warn about here. + } else S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 2 /*variable and function*/; - return; - } + << Attr.getName() << ExpectedVariableOrFunction; - // Merge should handle any subsequent violations. - if (isDef) { - S.Diag(Attr.getLoc(), - diag::warn_attribute_weak_import_invalid_on_definition) - << "weak_import" << 2 /*variable and function*/; return; } @@ -1409,7 +1521,7 @@ static void HandleSectionAttr(Decl *D, const AttributeList &Attr, Sema &S) { static void HandleNothrowAttr(Decl *d, const AttributeList &Attr, Sema &S) { // check the attribute arguments. - if (Attr.getNumArgs() != 0) { + if (Attr.hasParameterOrArguments()) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; return; } @@ -1419,7 +1531,7 @@ static void HandleNothrowAttr(Decl *d, const AttributeList &Attr, Sema &S) { static void HandleConstAttr(Decl *d, const AttributeList &Attr, Sema &S) { // check the attribute arguments. - if (Attr.getNumArgs() != 0) { + if (Attr.hasParameterOrArguments()) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; return; } @@ -1506,7 +1618,7 @@ static void HandleFormatArgAttr(Decl *d, const AttributeList &Attr, Sema &S) { } if (!isFunctionOrMethod(d) || !hasFunctionProto(d)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 0 /*function*/; + << Attr.getName() << ExpectedFunction; return; } @@ -1674,7 +1786,7 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) { if (!isFunctionOrMethodOrBlock(d) || !hasFunctionProto(d)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 0 /*function*/; + << Attr.getName() << ExpectedFunction; return; } @@ -1807,7 +1919,7 @@ static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr, // Try to find the underlying union declaration. RecordDecl *RD = 0; - TypedefDecl *TD = dyn_cast<TypedefDecl>(d); + TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(d); if (TD && TD->getUnderlyingType()->isUnionType()) RD = TD->getUnderlyingType()->getAsUnionType()->getDecl(); else @@ -1815,7 +1927,7 @@ static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr, if (!RD || !RD->isUnion()) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 1 /*union*/; + << Attr.getName() << ExpectedUnion; return; } @@ -1998,7 +2110,7 @@ static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) { } QualType OldTy; - if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) + if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) OldTy = TD->getUnderlyingType(); else if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) OldTy = VD->getType(); @@ -2097,7 +2209,7 @@ static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) { } // Install the new type. - if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) { + if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) { // FIXME: preserve existing source info. TD->setTypeSourceInfo(S.Context.getTrivialTypeSourceInfo(NewTy)); } else @@ -2113,7 +2225,7 @@ static void HandleNoDebugAttr(Decl *d, const AttributeList &Attr, Sema &S) { if (!isFunctionOrMethod(d)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 0 /*function*/; + << Attr.getName() << ExpectedFunction; return; } @@ -2129,7 +2241,7 @@ static void HandleNoInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) { if (!isa<FunctionDecl>(d)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 0 /*function*/; + << Attr.getName() << ExpectedFunction; return; } @@ -2146,7 +2258,7 @@ static void HandleNoInstrumentFunctionAttr(Decl *d, const AttributeList &Attr, if (!isa<FunctionDecl>(d)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 0 /*function*/; + << Attr.getName() << ExpectedFunction; return; } @@ -2157,14 +2269,14 @@ static void HandleNoInstrumentFunctionAttr(Decl *d, const AttributeList &Attr, static void HandleConstantAttr(Decl *d, const AttributeList &Attr, Sema &S) { if (S.LangOpts.CUDA) { // check the attribute arguments. - if (Attr.getNumArgs() != 0) { + if (Attr.hasParameterOrArguments()) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; return; } if (!isa<VarDecl>(d)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 12 /*variable*/; + << Attr.getName() << ExpectedVariable; return; } @@ -2184,7 +2296,7 @@ static void HandleDeviceAttr(Decl *d, const AttributeList &Attr, Sema &S) { if (!isa<FunctionDecl>(d) && !isa<VarDecl>(d)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 2 /*variable and function*/; + << Attr.getName() << ExpectedVariableOrFunction; return; } @@ -2204,7 +2316,7 @@ static void HandleGlobalAttr(Decl *d, const AttributeList &Attr, Sema &S) { if (!isa<FunctionDecl>(d)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 0 /*function*/; + << Attr.getName() << ExpectedFunction; return; } @@ -2239,7 +2351,7 @@ static void HandleHostAttr(Decl *d, const AttributeList &Attr, Sema &S) { if (!isa<FunctionDecl>(d)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 0 /*function*/; + << Attr.getName() << ExpectedFunction; return; } @@ -2259,7 +2371,7 @@ static void HandleSharedAttr(Decl *d, const AttributeList &Attr, Sema &S) { if (!isa<VarDecl>(d)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 12 /*variable*/; + << Attr.getName() << ExpectedVariable; return; } @@ -2279,7 +2391,7 @@ static void HandleGNUInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) { FunctionDecl *Fn = dyn_cast<FunctionDecl>(d); if (Fn == 0) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 0 /*function*/; + << Attr.getName() << ExpectedFunction; return; } @@ -2302,7 +2414,7 @@ static void HandleCallConvAttr(Decl *d, const AttributeList &attr, Sema &S) { if (!isa<ObjCMethodDecl>(d)) { S.Diag(attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << attr.getName() << 0 /*function*/; + << attr.getName() << ExpectedFunctionOrMethod; return; } @@ -2322,6 +2434,30 @@ static void HandleCallConvAttr(Decl *d, const AttributeList &attr, Sema &S) { case AttributeList::AT_pascal: d->addAttr(::new (S.Context) PascalAttr(attr.getLoc(), S.Context)); return; + case AttributeList::AT_pcs: { + Expr *Arg = attr.getArg(0); + StringLiteral *Str = dyn_cast<StringLiteral>(Arg); + if (Str == 0 || Str->isWide()) { + S.Diag(attr.getLoc(), diag::err_attribute_argument_n_not_string) + << "pcs" << 1; + attr.setInvalid(); + return; + } + + llvm::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.getLoc(), S.Context, PCS)); + } default: llvm_unreachable("unexpected attribute kind"); return; @@ -2337,19 +2473,42 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC) { if (attr.isInvalid()) return true; - if (attr.getNumArgs() != 0) { + 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. + // 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<StringLiteral>(Arg); + if (Str == 0 || Str->isWide()) { + Diag(attr.getLoc(), diag::err_attribute_argument_n_not_string) + << "pcs" << 1; + attr.setInvalid(); + return true; + } + + llvm::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 true; } @@ -2365,7 +2524,7 @@ static void HandleRegparmAttr(Decl *d, const AttributeList &attr, Sema &S) { if (!isa<ObjCMethodDecl>(d)) { S.Diag(attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << attr.getName() << 0 /*function*/; + << attr.getName() << ExpectedFunctionOrMethod; return; } @@ -2416,14 +2575,14 @@ static void HandleLaunchBoundsAttr(Decl *d, const AttributeList &Attr, Sema &S){ if (S.LangOpts.CUDA) { // check the attribute arguments. if (Attr.getNumArgs() != 1 && Attr.getNumArgs() != 2) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) - << "1 or 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() << 0 /*function*/; + << Attr.getName() << ExpectedFunctionOrMethod; return; } @@ -2472,7 +2631,7 @@ static void HandleNSConsumedAttr(Decl *d, const AttributeList &attr, Sema &S) { ParmVarDecl *param = dyn_cast<ParmVarDecl>(d); if (!param) { S.Diag(d->getLocStart(), diag::warn_attribute_wrong_decl_type) - << SourceRange(attr.getLoc()) << attr.getName() << 4 /*parameter*/; + << SourceRange(attr.getLoc()) << attr.getName() << ExpectedParameter; return; } @@ -2501,7 +2660,7 @@ static void HandleNSConsumesSelfAttr(Decl *d, const AttributeList &attr, Sema &S) { if (!isa<ObjCMethodDecl>(d)) { S.Diag(d->getLocStart(), diag::warn_attribute_wrong_decl_type) - << SourceRange(attr.getLoc()) << attr.getName() << 13 /*method*/; + << SourceRange(attr.getLoc()) << attr.getName() << ExpectedMethod; return; } @@ -2520,7 +2679,7 @@ static void HandleNSReturnsRetainedAttr(Decl *d, const AttributeList &attr, else { S.Diag(d->getLocStart(), diag::warn_attribute_wrong_decl_type) << SourceRange(attr.getLoc()) << attr.getName() - << 3 /* function or method */; + << ExpectedFunctionOrMethod; return; } @@ -2664,6 +2823,7 @@ static void ProcessInheritableDeclAttr(Scope *scope, Decl *D, case AttributeList::AT_IBOutletCollection: HandleIBOutletCollection(D, Attr, S); 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: @@ -2684,6 +2844,7 @@ static void ProcessInheritableDeclAttr(Scope *scope, Decl *D, case AttributeList::AT_analyzer_noreturn: HandleAnalyzerNoReturnAttr (D, Attr, S); break; case AttributeList::AT_annotate: HandleAnnotateAttr (D, Attr, S); break; + case AttributeList::AT_availability:HandleAvailabilityAttr(D, Attr, S); break; case AttributeList::AT_carries_dependency: HandleDependencyAttr (D, Attr, S); break; case AttributeList::AT_common: HandleCommonAttr (D, Attr, S); break; @@ -2736,6 +2897,7 @@ static void ProcessInheritableDeclAttr(Scope *scope, Decl *D, HandleInitPriorityAttr(D, Attr, S); break; case AttributeList::AT_packed: HandlePackedAttr (D, Attr, S); break; + case AttributeList::AT_MsStruct: HandleMsStructAttr (D, Attr, S); break; case AttributeList::AT_section: HandleSectionAttr (D, Attr, S); break; case AttributeList::AT_unavailable: HandleUnavailableAttr (D, Attr, S); break; case AttributeList::AT_unused: HandleUnusedAttr (D, Attr, S); break; @@ -2752,6 +2914,9 @@ static void ProcessInheritableDeclAttr(Scope *scope, Decl *D, case AttributeList::AT_objc_exception: HandleObjCExceptionAttr(D, Attr, S); break; + case AttributeList::AT_objc_method_family: + HandleObjCMethodFamilyAttr(D, Attr, S); + break; case AttributeList::AT_nsobject: HandleObjCNSObject (D, Attr, S); break; case AttributeList::AT_blocks: HandleBlocksAttr (D, Attr, S); break; case AttributeList::AT_sentinel: HandleSentinelAttr (D, Attr, S); break; @@ -2772,6 +2937,7 @@ static void ProcessInheritableDeclAttr(Scope *scope, Decl *D, case AttributeList::AT_fastcall: case AttributeList::AT_thiscall: case AttributeList::AT_pascal: + case AttributeList::AT_pcs: HandleCallConvAttr(D, Attr, S); break; case AttributeList::AT_opencl_kernel_function: @@ -2837,6 +3003,7 @@ NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II) { NamedDecl *NewD = 0; if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) { NewD = FunctionDecl::Create(FD->getASTContext(), FD->getDeclContext(), + FD->getInnerLocStart(), FD->getLocation(), DeclarationName(II), FD->getType(), FD->getTypeSourceInfo()); if (FD->getQualifier()) { @@ -2845,7 +3012,7 @@ NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II) { } } else if (VarDecl *VD = dyn_cast<VarDecl>(ND)) { NewD = VarDecl::Create(VD->getASTContext(), VD->getDeclContext(), - VD->getLocation(), II, + VD->getInnerLocStart(), VD->getLocation(), II, VD->getType(), VD->getTypeSourceInfo(), VD->getStorageClass(), VD->getStorageClassAsWritten()); @@ -2986,14 +3153,14 @@ void Sema::DelayedDiagnostics::popParsingDecl(Sema &S, ParsingDeclState state, // 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.Stack[i].Destroy(); DD.StackSize = state.SavedStackSize; } static bool isDeclDeprecated(Decl *D) { do { - if (D->hasAttr<DeprecatedAttr>()) + if (D->isDeprecated()) return true; } while ((D = cast_or_null<Decl>(D->getDeclContext()))); return false; @@ -3016,7 +3183,7 @@ void Sema::HandleDelayedDeprecationCheck(DelayedDiagnostic &DD, void Sema::EmitDeprecationWarning(NamedDecl *D, llvm::StringRef Message, SourceLocation Loc, - bool UnknownObjCClass) { + const ObjCInterfaceDecl *UnknownObjCClass) { // Delay if we're currently parsing a declaration. if (DelayedDiagnostics.shouldDelayDiagnostics()) { DelayedDiagnostics.add(DelayedDiagnostic::makeDeprecation(Loc, D, Message)); @@ -3032,7 +3199,9 @@ void Sema::EmitDeprecationWarning(NamedDecl *D, llvm::StringRef Message, else { if (!UnknownObjCClass) Diag(Loc, diag::warn_deprecated) << D->getDeclName(); - else + else { Diag(Loc, diag::warn_deprecated_fwdclass_message) << D->getDeclName(); + Diag(UnknownObjCClass->getLocation(), diag::note_forward_class); + } } } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp index f483262..27632a1 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp @@ -18,9 +18,11 @@ #include "clang/Sema/Lookup.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/StmtVisitor.h" #include "clang/AST/TypeLoc.h" @@ -287,17 +289,37 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) { ParmVarDecl *NewParam = New->getParamDecl(p); if (OldParam->hasDefaultArg() && NewParam->hasDefaultArg()) { + + 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 (getLangOptions().Microsoft) { + CXXMethodDecl* MD = dyn_cast<CXXMethodDecl>(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(), - diag::err_param_default_argument_redefinition) + Diag(NewParam->getLocation(), DiagDefaultParamID) << NewParam->getDefaultArgRange(); // Look for the function declaration where the default argument was @@ -312,7 +334,6 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) { Diag(OldParam->getLocation(), diag::note_previous_definition) << OldParam->getDefaultArgRange(); - Invalid = true; } else if (OldParam->hasDefaultArg()) { // Merge the old default argument into the new parameter. // It's important to use getInit() here; getDefaultArg() @@ -382,6 +403,48 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) { 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 (!getLangOptions().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<ReferenceType>()) { + NewType = R->getPointeeType(); + OldType = OldType->getAs<ReferenceType>()->getPointeeType(); + } else if (const PointerType *P = NewType->getAs<PointerType>()) { + NewType = P->getPointeeType(); + OldType = OldType->getAs<PointerType>()->getPointeeType(); + } else if (const MemberPointerType *M = NewType->getAs<MemberPointerType>()) { + NewType = M->getPointeeType(); + OldType = OldType->getAs<MemberPointerType>()->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<FunctionProtoType>(), Old->getLocation(), + NewType->getAs<FunctionProtoType>(), New->getLocation())) { + New->setInvalidDecl(); + } +} + /// CheckCXXDefaultArguments - Verify that the default arguments for a /// function declaration are well-formed according to C++ /// [dcl.fct.default]. @@ -520,10 +583,9 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, CXXRecordDecl * CXXBaseDecl = cast<CXXRecordDecl>(BaseDecl); assert(CXXBaseDecl && "Base type is not a C++ type"); - // C++ [class.derived]p2: - // If a class is marked with the class-virt-specifier final and it appears - // as a base-type-specifier in a base-clause (10 class.derived), the program - // is ill-formed. + // 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<FinalAttr>()) { Diag(BaseLoc, diag::err_class_marked_final_used_as_base) << CXXBaseDecl->getDeclName(); @@ -876,26 +938,6 @@ void Sema::CheckOverrideControl(const Decl *D) { << MD->getDeclName(); return; } - - // C++0x [class.derived]p8: - // In a class definition marked with the class-virt-specifier explicit, - // if a virtual member function that is neither implicitly-declared nor a - // destructor overrides a member function of a base class and it is not - // marked with the virt-specifier override, the program is ill-formed. - if (MD->getParent()->hasAttr<ExplicitAttr>() && !isa<CXXDestructorDecl>(MD) && - HasOverriddenMethods && !MD->hasAttr<OverrideAttr>()) { - llvm::SmallVector<const CXXMethodDecl*, 4> - OverriddenMethods(MD->begin_overridden_methods(), - MD->end_overridden_methods()); - - Diag(MD->getLocation(), diag::err_function_overriding_without_override) - << MD->getDeclName() - << (unsigned)OverriddenMethods.size(); - - for (unsigned I = 0; I != OverriddenMethods.size(); ++I) - Diag(OverriddenMethods[I]->getLocation(), - diag::note_overridden_virtual_function); - } } /// CheckIfOverriddenFunctionIsMarkedFinal - Checks whether a virtual member @@ -1068,6 +1110,12 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, 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<CXXMethodDecl>(Member)) + MD->setRangeEnd(VS.getLastLocation()); + } + CheckOverrideControl(Member); assert((Name || isInstField) && "No identifier for non-field ?"); @@ -1225,10 +1273,9 @@ Sema::ActOnMemInitializer(Decl *ConstructorD, 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, - (NestedNameSpecifier *)SS.getScopeRep(), - *MemberOrBase, SourceLocation(), - SS.getRange(), IdLoc); + BaseType = CheckTypenameType(ETK_None, SourceLocation(), + SS.getWithLocInContext(Context), + *MemberOrBase, IdLoc); if (BaseType.isNull()) return true; @@ -1356,7 +1403,7 @@ static bool InitExprContainsUninitializedFields(const Stmt *S, *L = ME->getMemberLoc(); return true; } - } else if (isa<SizeOfAlignOfExpr>(S)) { + } else if (isa<UnaryExprOrTypeTraitExpr>(S)) { // sizeof/alignof doesn't reference contents, do not warn. return false; } else if (const UnaryOperator *UOE = dyn_cast<UnaryOperator>(S)) { @@ -1476,17 +1523,61 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr **Args, MemInitResult Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr **Args, unsigned NumArgs, + SourceLocation NameLoc, SourceLocation LParenLoc, SourceLocation RParenLoc, - CXXRecordDecl *ClassDecl, - SourceLocation EllipsisLoc) { + CXXRecordDecl *ClassDecl) { SourceLocation Loc = TInfo->getTypeLoc().getLocalSourceRange().getBegin(); if (!LangOpts.CPlusPlus0x) return Diag(Loc, diag::err_delegation_0x_only) << TInfo->getTypeLoc().getLocalSourceRange(); - return Diag(Loc, diag::err_delegation_unimplemented) - << TInfo->getTypeLoc().getLocalSourceRange(); + // Initialize the object. + InitializedEntity DelegationEntity = InitializedEntity::InitializeDelegation( + QualType(ClassDecl->getTypeForDecl(), 0)); + InitializationKind Kind = + InitializationKind::CreateDirect(NameLoc, LParenLoc, RParenLoc); + + InitializationSequence InitSeq(*this, DelegationEntity, Kind, Args, NumArgs); + + ExprResult DelegationInit = + InitSeq.Perform(*this, DelegationEntity, Kind, + MultiExprArg(*this, Args, NumArgs), 0); + if (DelegationInit.isInvalid()) + return true; + + CXXConstructExpr *ConExpr = cast<CXXConstructExpr>(DelegationInit.get()); + CXXConstructorDecl *Constructor = ConExpr->getConstructor(); + assert(Constructor && "Delegating constructor with no target?"); + + CheckImplicitConversions(DelegationInit.get(), LParenLoc); + + // 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; + + // 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()) { + ExprResult Init + = Owned(new (Context) ParenListExpr(Context, LParenLoc, Args, + NumArgs, RParenLoc)); + return new (Context) CXXCtorInitializer(Context, Loc, LParenLoc, + Constructor, Init.takeAs<Expr>(), + RParenLoc); + } + + return new (Context) CXXCtorInitializer(Context, Loc, LParenLoc, Constructor, + DelegationInit.takeAs<Expr>(), + RParenLoc); } MemInitResult @@ -1538,9 +1629,8 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, if (!Dependent) { if (Context.hasSameUnqualifiedType(QualType(ClassDecl->getTypeForDecl(),0), BaseType)) - return BuildDelegatingInitializer(BaseTInfo, Args, NumArgs, - LParenLoc, RParenLoc, ClassDecl, - EllipsisLoc); + return BuildDelegatingInitializer(BaseTInfo, Args, NumArgs, BaseLoc, + LParenLoc, RParenLoc, ClassDecl); FindBaseInitializer(*this, ClassDecl, BaseType, DirectBaseSpec, VirtualBaseSpec); @@ -1684,7 +1774,7 @@ BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, QualType ParamType = Param->getType().getNonReferenceType(); Expr *CopyCtorArg = - DeclRefExpr::Create(SemaRef.Context, 0, SourceRange(), Param, + DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(), Param, Constructor->getLocation(), ParamType, VK_LValue, 0); @@ -1695,9 +1785,9 @@ BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, CXXCastPath BasePath; BasePath.push_back(BaseSpec); - SemaRef.ImpCastExprToType(CopyCtorArg, ArgTy, - CK_UncheckedDerivedToBase, - VK_LValue, &BasePath); + CopyCtorArg = SemaRef.ImpCastExprToType(CopyCtorArg, ArgTy, + CK_UncheckedDerivedToBase, + VK_LValue, &BasePath).take(); InitializationKind InitKind = InitializationKind::CreateDirect(Constructor->getLocation(), @@ -1745,7 +1835,7 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, QualType ParamType = Param->getType().getNonReferenceType(); Expr *MemberExprBase = - DeclRefExpr::Create(SemaRef.Context, 0, SourceRange(), Param, + DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(), Param, Loc, ParamType, VK_LValue, 0); // Build a reference to this field within the parameter. @@ -1783,7 +1873,7 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, IterationVarName = &SemaRef.Context.Idents.get(OS.str()); } VarDecl *IterationVar - = VarDecl::Create(SemaRef.Context, SemaRef.CurContext, Loc, + = VarDecl::Create(SemaRef.Context, SemaRef.CurContext, Loc, Loc, IterationVarName, SizeType, SemaRef.Context.getTrivialTypeSourceInfo(SizeType, Loc), SC_None, SC_None); @@ -1978,6 +2068,30 @@ static bool CollectFieldInitializer(BaseAndFieldInfo &Info, return false; } + +bool +Sema::SetDelegatingInitializer(CXXConstructorDecl *Constructor, + CXXCtorInitializer *Initializer) { + Constructor->setNumCtorInitializers(1); + CXXCtorInitializer **initializer = + new (Context) CXXCtorInitializer*[1]; + memcpy(initializer, &Initializer, sizeof (CXXCtorInitializer*)); + Constructor->setCtorInitializers(initializer); + + // FIXME: This doesn't catch indirect loops yet + CXXConstructorDecl *Target = Initializer->getTargetConstructor(); + while (Target) { + if (Target == Constructor) { + Diag(Initializer->getSourceLocation(), diag::err_delegating_ctor_loop) + << Constructor; + return true; + } + Target = Target->getTargetConstructor(); + } + + return false; +} + bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, @@ -2340,10 +2454,23 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl, if (CheckRedundantInit(*this, Init, Members[Field]) || CheckRedundantUnionInit(*this, Init, MemberUnions)) HadError = true; - } else { + } 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); + // Return immediately as the initializer is set. + return; } } @@ -2380,10 +2507,13 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location, continue; CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl()); + if (FieldClassDecl->isInvalidDecl()) + continue; if (FieldClassDecl->hasTrivialDestructor()) continue; CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl); + assert(Dtor && "No dtor found for FieldClassDecl!"); CheckDestructorAccess(Field->getLocation(), Dtor, PDiag(diag::err_access_dtor_field) << Field->getDeclName() @@ -2404,12 +2534,16 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location, if (Base->isVirtual()) DirectVirtualBases.insert(RT); - // Ignore trivial destructors. CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(RT->getDecl()); + // If our base class is invalid, we probably can't get its dtor anyway. + if (BaseClassDecl->isInvalidDecl()) + continue; + // Ignore trivial destructors. if (BaseClassDecl->hasTrivialDestructor()) 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->getSourceRange().getBegin(), Dtor, @@ -2431,12 +2565,16 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location, if (DirectVirtualBases.count(RT)) continue; - // Ignore trivial destructors. CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(RT->getDecl()); + // If our base class is invalid, we probably can't get its dtor anyway. + if (BaseClassDecl->isInvalidDecl()) + continue; + // Ignore trivial destructors. if (BaseClassDecl->hasTrivialDestructor()) continue; CXXDestructorDecl *Dtor = LookupDestructor(BaseClassDecl); + assert(Dtor && "No dtor found for BaseClassDecl!"); CheckDestructorAccess(ClassDecl->getLocation(), Dtor, PDiag(diag::err_access_dtor_vbase) << VBase->getType()); @@ -2786,7 +2924,8 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { for (CXXRecordDecl::method_iterator M = Record->method_begin(), MEnd = Record->method_end(); M != MEnd; ++M) { - DiagnoseHiddenVirtualMethods(Record, *M); + if (!(*M)->isStatic()) + DiagnoseHiddenVirtualMethods(Record, *M); } } @@ -2801,12 +2940,14 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { } /// \brief Data used with FindHiddenVirtualMethod -struct FindHiddenVirtualMethodData { - Sema *S; - CXXMethodDecl *Method; - llvm::SmallPtrSet<const CXXMethodDecl *, 8> OverridenAndUsingBaseMethods; - llvm::SmallVector<CXXMethodDecl *, 8> OverloadedMethods; -}; +namespace { + struct FindHiddenVirtualMethodData { + Sema *S; + CXXMethodDecl *Method; + llvm::SmallPtrSet<const CXXMethodDecl *, 8> OverridenAndUsingBaseMethods; + llvm::SmallVector<CXXMethodDecl *, 8> OverloadedMethods; + }; +} /// \brief Member lookup function that determines whether a given C++ /// method overloads virtual methods in a base class without overriding any, @@ -2917,53 +3058,101 @@ namespace { /// implicitly-declared special member functions. class ImplicitExceptionSpecification { ASTContext &Context; - bool AllowsAllExceptions; + // We order exception specifications thus: + // noexcept is the most restrictive, but is only used in C++0x. + // throw() comes next. + // Then a throw(collected exceptions) + // Finally no specification. + // throw(...) is used instead if any called function uses it. + ExceptionSpecificationType ComputedEST; llvm::SmallPtrSet<CanQualType, 4> ExceptionsSeen; llvm::SmallVector<QualType, 4> Exceptions; - + + void ClearExceptions() { + ExceptionsSeen.clear(); + Exceptions.clear(); + } + public: explicit ImplicitExceptionSpecification(ASTContext &Context) - : Context(Context), AllowsAllExceptions(false) { } - - /// \brief Whether the special member function should have any - /// exception specification at all. - bool hasExceptionSpecification() const { - return !AllowsAllExceptions; + : Context(Context), ComputedEST(EST_BasicNoexcept) { + if (!Context.getLangOptions().CPlusPlus0x) + ComputedEST = EST_DynamicNone; } - - /// \brief Whether the special member function should have a - /// throw(...) exception specification (a Microsoft extension). - bool hasAnyExceptionSpecification() const { - return false; + + /// \brief Get the computed exception specification type. + ExceptionSpecificationType getExceptionSpecType() const { + assert(ComputedEST != EST_ComputedNoexcept && + "noexcept(expr) should not be a possible result"); + return ComputedEST; } - + /// \brief The number of exceptions in the exception specification. unsigned size() const { return Exceptions.size(); } - + /// \brief The set of exceptions in the exception specification. const QualType *data() const { return Exceptions.data(); } - - /// \brief Note that + + /// \brief Integrate another called method into the collected data. void CalledDecl(CXXMethodDecl *Method) { - // If we already know that we allow all exceptions, do nothing. - if (AllowsAllExceptions || !Method) + // If we have an MSAny spec already, don't bother. + if (!Method || ComputedEST == EST_MSAny) return; - + const FunctionProtoType *Proto = Method->getType()->getAs<FunctionProtoType>(); - + + ExceptionSpecificationType EST = Proto->getExceptionSpecType(); + // If this function can throw any exceptions, make a note of that. - if (!Proto->hasExceptionSpec() || Proto->hasAnyExceptionSpec()) { - AllowsAllExceptions = true; - ExceptionsSeen.clear(); - Exceptions.clear(); + if (EST == EST_MSAny || EST == EST_None) { + ClearExceptions(); + ComputedEST = EST; return; } - + + // 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(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) + E != EEnd; ++E) if (ExceptionsSeen.insert(Context.getCanonicalType(*E))) Exceptions.push_back(*E); } @@ -3006,6 +3195,25 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *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<NamedDecl>(*Param); + if (Named->getDeclName()) { + S->AddDecl(Named); + IdResolver.AddDecl(Named); + } + } + } +} + void Sema::ActOnReenterTemplateScope(Scope *S, Decl *D) { if (!D) return; @@ -3256,9 +3464,9 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R, // be used as the identifier in the declarator for a destructor // declaration. QualType DeclaratorType = GetTypeFromParser(D.getName().DestructorName); - if (isa<TypedefType>(DeclaratorType)) + if (const TypedefType *TT = DeclaratorType->getAs<TypedefType>()) Diag(D.getIdentifierLoc(), diag::err_destructor_typedef_name) - << DeclaratorType; + << DeclaratorType << isa<TypeAliasDecl>(TT->getDecl()); // C++ [class.dtor]p2: // A destructor is used to destroy objects of its class type. A @@ -3488,14 +3696,16 @@ Decl *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) { /// definition. Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, SourceLocation InlineLoc, + SourceLocation NamespaceLoc, SourceLocation IdentLoc, IdentifierInfo *II, SourceLocation LBrace, AttributeList *AttrList) { - // anonymous namespace starts at its left brace + SourceLocation StartLoc = InlineLoc.isValid() ? InlineLoc : NamespaceLoc; + // For anonymous namespace, take the location of the left brace. + SourceLocation Loc = II ? IdentLoc : LBrace; NamespaceDecl *Namespc = NamespaceDecl::Create(Context, CurContext, - (II ? IdentLoc : LBrace) , II); - Namespc->setLBracLoc(LBrace); + StartLoc, Loc, II); Namespc->setInline(InlineLoc.isValid()); Scope *DeclRegionScope = NamespcScope->getParent(); @@ -3654,7 +3864,7 @@ static inline NamespaceDecl *getNamespaceDecl(NamedDecl *D) { void Sema::ActOnFinishNamespaceDef(Decl *Dcl, SourceLocation RBrace) { NamespaceDecl *Namespc = dyn_cast_or_null<NamespaceDecl>(Dcl); assert(Namespc && "Invalid parameter, expected NamespaceDecl"); - Namespc->setRBracLoc(RBrace); + Namespc->setRBraceLoc(RBrace); PopDeclContext(); if (Namespc->hasAttr<VisibilityAttr>()) PopPragmaVisibility(); @@ -3677,7 +3887,7 @@ NamespaceDecl *Sema::getOrCreateStdNamespace() { // The "std" namespace has not yet been defined, so build one implicitly. StdNamespace = NamespaceDecl::Create(Context, Context.getTranslationUnitDecl(), - SourceLocation(), + SourceLocation(), SourceLocation(), &PP.getIdentifierTable().get("std")); getStdNamespace()->setImplicit(true); } @@ -3685,6 +3895,19 @@ NamespaceDecl *Sema::getOrCreateStdNamespace() { return getStdNamespace(); } +/// \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; + } +} + Decl *Sema::ActOnUsingDirective(Scope *S, SourceLocation UsingLoc, SourceLocation NamespcLoc, @@ -3769,6 +3992,12 @@ Decl *Sema::ActOnUsingDirective(Scope *S, UDir = UsingDirectiveDecl::Create(Context, CurContext, UsingLoc, NamespcLoc, SS.getWithLocInContext(Context), IdentLoc, Named, CommonAncestor); + + if (IsUsingDirectiveInToplevelContext(CurContext) && + !SourceMgr.isFromMainFile(SourceMgr.getInstantiationLoc(IdentLoc))) { + Diag(IdentLoc, diag::warn_using_directive_in_header); + } + PushUsingDirective(S, UDir); } else { Diag(IdentLoc, diag::err_expected_namespace_name) << SS.getRange(); @@ -3870,8 +4099,8 @@ IsEquivalentForUsingDecl(ASTContext &Context, NamedDecl *D1, NamedDecl *D2, return true; } - if (TypedefDecl *TD1 = dyn_cast<TypedefDecl>(D1)) - if (TypedefDecl *TD2 = dyn_cast<TypedefDecl>(D2)) { + if (TypedefNameDecl *TD1 = dyn_cast<TypedefNameDecl>(D1)) + if (TypedefNameDecl *TD2 = dyn_cast<TypedefNameDecl>(D2)) { SuppressRedeclaration = true; return Context.hasSameType(TD1->getUnderlyingType(), TD2->getUnderlyingType()); @@ -4470,6 +4699,61 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc, return true; } +Decl *Sema::ActOnAliasDeclaration(Scope *S, + AccessSpecifier AS, + SourceLocation UsingLoc, + UnqualifiedId &Name, + TypeResult Type) { + 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; + + LookupResult Previous(*this, NameInfo, LookupOrdinaryName, ForRedeclaration); + LookupName(Previous, S); + + // Warn about shadowing the name of a template parameter. + if (Previous.isSingleResult() && + Previous.getFoundDecl()->isTemplateParameter()) { + if (DiagnoseTemplateParameterShadow(Name.StartLocation, + Previous.getFoundDecl())) + Invalid = true; + 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(); + + bool Redeclaration = false; + ActOnTypedefNameDecl(S, CurContext, NewTD, Previous, Redeclaration); + + if (!Redeclaration) + PushOnScopeChains(NewTD, S); + + return NewTD; +} + Decl *Sema::ActOnNamespaceAliasDef(Scope *S, SourceLocation NamespaceLoc, SourceLocation AliasLoc, @@ -4609,7 +4893,7 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( // exception-specification. [...] ImplicitExceptionSpecification ExceptSpec(Context); - // Direct base-class destructors. + // Direct base-class constructors. for (CXXRecordDecl::base_class_iterator B = ClassDecl->bases_begin(), BEnd = ClassDecl->bases_end(); B != BEnd; ++B) { @@ -4625,8 +4909,8 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( ExceptSpec.CalledDecl(Constructor); } } - - // Virtual base-class destructors. + + // Virtual base-class constructors. for (CXXRecordDecl::base_class_iterator B = ClassDecl->vbases_begin(), BEnd = ClassDecl->vbases_end(); B != BEnd; ++B) { @@ -4639,8 +4923,8 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( ExceptSpec.CalledDecl(Constructor); } } - - // Field destructors. + + // Field constructors. for (RecordDecl::field_iterator F = ClassDecl->field_begin(), FEnd = ClassDecl->field_end(); F != FEnd; ++F) { @@ -4657,19 +4941,19 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( } FunctionProtoType::ExtProtoInfo EPI; - EPI.HasExceptionSpec = ExceptSpec.hasExceptionSpecification(); - EPI.HasAnyExceptionSpec = ExceptSpec.hasAnyExceptionSpecification(); + EPI.ExceptionSpecType = ExceptSpec.getExceptionSpecType(); EPI.NumExceptions = ExceptSpec.size(); EPI.Exceptions = ExceptSpec.data(); - + // 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, ClassDecl->getLocation()); + DeclarationNameInfo NameInfo(Name, ClassLoc); CXXConstructorDecl *DefaultCon - = CXXConstructorDecl::Create(Context, ClassDecl, NameInfo, + = CXXConstructorDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, Context.getFunctionType(Context.VoidTy, 0, 0, EPI), /*TInfo=*/0, @@ -4714,6 +4998,10 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, Constructor->setUsed(); MarkVTableUsed(CurrentLocation, ClassDecl); + + if (ASTMutationListener *L = getASTMutationListener()) { + L->CompletedImplicitDefinition(Constructor); + } } void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) { @@ -4865,15 +5153,16 @@ void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) { // user-writtern inline constructor [...] DeclarationNameInfo DNI(CreatedCtorName, UsingLoc); CXXConstructorDecl *NewCtor = CXXConstructorDecl::Create( - Context, ClassDecl, DNI, QualType(NewCtorType, 0), /*TInfo=*/0, - BaseCtor->isExplicit(), /*Inline=*/true, + Context, ClassDecl, UsingLoc, DNI, QualType(NewCtorType, 0), + /*TInfo=*/0, BaseCtor->isExplicit(), /*Inline=*/true, /*ImplicitlyDeclared=*/true); NewCtor->setAccess(BaseCtor->getAccess()); // Build up the parameter decls and add them. llvm::SmallVector<ParmVarDecl *, 16> ParamDecls; for (unsigned i = 0; i < params; ++i) { - ParamDecls.push_back(ParmVarDecl::Create(Context, NewCtor, UsingLoc, + ParamDecls.push_back(ParmVarDecl::Create(Context, NewCtor, + UsingLoc, UsingLoc, /*IdentifierInfo=*/0, BaseCtorType->getArgType(i), /*TInfo=*/0, SC_None, @@ -4931,24 +5220,24 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) { ExceptSpec.CalledDecl( LookupDestructor(cast<CXXRecordDecl>(RecordTy->getDecl()))); } - + // Create the actual destructor declaration. FunctionProtoType::ExtProtoInfo EPI; - EPI.HasExceptionSpec = ExceptSpec.hasExceptionSpecification(); - EPI.HasAnyExceptionSpec = ExceptSpec.hasAnyExceptionSpecification(); + EPI.ExceptionSpecType = ExceptSpec.getExceptionSpecType(); EPI.NumExceptions = ExceptSpec.size(); EPI.Exceptions = ExceptSpec.data(); 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, ClassDecl->getLocation()); + DeclarationNameInfo NameInfo(Name, ClassLoc); CXXDestructorDecl *Destructor - = CXXDestructorDecl::Create(Context, ClassDecl, NameInfo, Ty, 0, - /*isInline=*/true, - /*isImplicitlyDeclared=*/true); + = CXXDestructorDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, Ty, 0, + /*isInline=*/true, + /*isImplicitlyDeclared=*/true); Destructor->setAccess(AS_public); Destructor->setImplicit(); Destructor->setTrivial(ClassDecl->hasTrivialDestructor()); @@ -4998,6 +5287,10 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation, Destructor->setUsed(); MarkVTableUsed(CurrentLocation, ClassDecl); + + if (ASTMutationListener *L = getASTMutationListener()) { + L->CompletedImplicitDefinition(Destructor); + } } /// \brief Builds a statement that copies the given entity from \p From to @@ -5133,7 +5426,7 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, OS << "__i" << Depth; IterationVarName = &S.Context.Idents.get(OS.str()); } - VarDecl *IterationVar = VarDecl::Create(S.Context, S.CurContext, Loc, + VarDecl *IterationVar = VarDecl::Create(S.Context, S.CurContext, Loc, Loc, IterationVarName, SizeType, S.Context.getTrivialTypeSourceInfo(SizeType, Loc), SC_None, SC_None); @@ -5328,30 +5621,30 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { ExceptSpec.CalledDecl(CopyAssign); } } - + // An implicitly-declared copy assignment operator is an inline public // member of its class. FunctionProtoType::ExtProtoInfo EPI; - EPI.HasExceptionSpec = ExceptSpec.hasExceptionSpecification(); - EPI.HasAnyExceptionSpec = ExceptSpec.hasAnyExceptionSpecification(); + EPI.ExceptionSpecType = ExceptSpec.getExceptionSpecType(); EPI.NumExceptions = ExceptSpec.size(); EPI.Exceptions = ExceptSpec.data(); DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal); - DeclarationNameInfo NameInfo(Name, ClassDecl->getLocation()); + SourceLocation ClassLoc = ClassDecl->getLocation(); + DeclarationNameInfo NameInfo(Name, ClassLoc); CXXMethodDecl *CopyAssignment - = CXXMethodDecl::Create(Context, ClassDecl, NameInfo, + = CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, Context.getFunctionType(RetType, &ArgType, 1, EPI), /*TInfo=*/0, /*isStatic=*/false, /*StorageClassAsWritten=*/SC_None, - /*isInline=*/true); + /*isInline=*/true, + SourceLocation()); CopyAssignment->setAccess(AS_public); CopyAssignment->setImplicit(); CopyAssignment->setTrivial(ClassDecl->hasTrivialCopyAssignment()); // Add the parameter to the operator. ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyAssignment, - ClassDecl->getLocation(), - /*Id=*/0, + ClassLoc, ClassLoc, /*Id=*/0, ArgType, /*TInfo=*/0, SC_None, SC_None, 0); @@ -5440,21 +5733,19 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, // Construct the "from" expression, which is an implicit cast to the // appropriately-qualified base type. Expr *From = OtherRef; - ImpCastExprToType(From, Context.getQualifiedType(BaseType, OtherQuals), - CK_UncheckedDerivedToBase, - VK_LValue, &BasePath); + 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. - Expr *ToE = To.takeAs<Expr>(); - ImpCastExprToType(ToE, - Context.getCVRQualifiedType(BaseType, - CopyAssignOperator->getTypeQualifiers()), - CK_UncheckedDerivedToBase, - VK_LValue, &BasePath); - To = Owned(ToE); + To = ImpCastExprToType(To.take(), + Context.getCVRQualifiedType(BaseType, + CopyAssignOperator->getTypeQualifiers()), + CK_UncheckedDerivedToBase, + VK_LValue, &BasePath); // Build the copy. StmtResult Copy = BuildSingleCopyAssign(*this, Loc, BaseType, @@ -5659,6 +5950,10 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, /*isStmtExpr=*/false); assert(!Body.isInvalid() && "Compound statement creation cannot fail"); CopyAssignOperator->setBody(Body.takeAs<Stmt>()); + + if (ASTMutationListener *L = getASTMutationListener()) { + L->CompletedImplicitDefinition(CopyAssignOperator); + } } CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( @@ -5790,20 +6085,20 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( ExceptSpec.CalledDecl(CopyConstructor); } } - + // An implicitly-declared copy constructor is an inline public // member of its class. FunctionProtoType::ExtProtoInfo EPI; - EPI.HasExceptionSpec = ExceptSpec.hasExceptionSpecification(); - EPI.HasAnyExceptionSpec = ExceptSpec.hasAnyExceptionSpecification(); + EPI.ExceptionSpecType = ExceptSpec.getExceptionSpecType(); EPI.NumExceptions = ExceptSpec.size(); EPI.Exceptions = ExceptSpec.data(); DeclarationName Name = Context.DeclarationNames.getCXXConstructorName( Context.getCanonicalType(ClassType)); - DeclarationNameInfo NameInfo(Name, ClassDecl->getLocation()); + SourceLocation ClassLoc = ClassDecl->getLocation(); + DeclarationNameInfo NameInfo(Name, ClassLoc); CXXConstructorDecl *CopyConstructor - = CXXConstructorDecl::Create(Context, ClassDecl, NameInfo, + = CXXConstructorDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, Context.getFunctionType(Context.VoidTy, &ArgType, 1, EPI), /*TInfo=*/0, @@ -5818,7 +6113,7 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( // Add the parameter to the constructor. ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyConstructor, - ClassDecl->getLocation(), + ClassLoc, ClassLoc, /*IdentifierInfo=*/0, ArgType, /*TInfo=*/0, SC_None, @@ -5859,6 +6154,10 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation, } CopyConstructor->setUsed(); + + if (ASTMutationListener *L = getASTMutationListener()) { + L->CompletedImplicitDefinition(CopyConstructor); + } } ExprResult @@ -5903,6 +6202,13 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, unsigned NumExprs = ExprArgs.size(); Expr **Exprs = (Expr **)ExprArgs.release(); + for (specific_attr_iterator<NonNullAttr> + i = Constructor->specific_attr_begin<NonNullAttr>(), + e = Constructor->specific_attr_end<NonNullAttr>(); i != e; ++i) { + const NonNullAttr *NonNull = *i; + CheckNonNullArguments(NonNull, ExprArgs.get(), ConstructLoc); + } + MarkDeclarationReferenced(ConstructLoc, Constructor); return Owned(CXXConstructExpr::Create(Context, DeclInitType, ConstructLoc, Constructor, Elidable, Exprs, NumExprs, @@ -5932,20 +6238,29 @@ bool Sema::InitializeVarWithConstructor(VarDecl *VD, } void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) { + if (VD->isInvalidDecl()) return; + CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Record->getDecl()); - if (!ClassDecl->isInvalidDecl() && !VD->isInvalidDecl() && - !ClassDecl->hasTrivialDestructor() && !ClassDecl->isDependentContext()) { - CXXDestructorDecl *Destructor = LookupDestructor(ClassDecl); - MarkDeclarationReferenced(VD->getLocation(), Destructor); - CheckDestructorAccess(VD->getLocation(), Destructor, - PDiag(diag::err_access_dtor_var) - << VD->getDeclName() - << VD->getType()); + if (ClassDecl->isInvalidDecl()) return; + if (ClassDecl->hasTrivialDestructor()) return; + if (ClassDecl->isDependentContext()) return; - // TODO: this should be re-enabled for static locals by !CXAAtExit - if (!VD->isInvalidDecl() && VD->hasGlobalStorage() && !VD->isStaticLocal()) - Diag(VD->getLocation(), diag::warn_global_destructor); - } + CXXDestructorDecl *Destructor = LookupDestructor(ClassDecl); + MarkDeclarationReferenced(VD->getLocation(), Destructor); + CheckDestructorAccess(VD->getLocation(), Destructor, + PDiag(diag::err_access_dtor_var) + << VD->getDeclName() + << VD->getType()); + + 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); } /// AddCXXDirectInitializerToDecl - This action is called immediately after @@ -5983,15 +6298,17 @@ void Sema::AddCXXDirectInitializerToDecl(Decl *RealDecl, } Expr *Init = Exprs.get()[0]; - QualType DeducedType; - if (!DeduceAutoType(VDecl->getType(), Init, DeducedType)) { + TypeSourceInfo *DeducedType = 0; + if (!DeduceAutoType(VDecl->getTypeSourceInfo(), Init, DeducedType)) Diag(VDecl->getLocation(), diag::err_auto_var_deduction_failure) << VDecl->getDeclName() << VDecl->getType() << Init->getType() << Init->getSourceRange(); + if (!DeducedType) { RealDecl->setInvalidDecl(); return; } - VDecl->setType(DeducedType); + VDecl->setTypeSourceInfo(DeducedType); + VDecl->setType(DeducedType->getType()); // If this is a redeclaration, check that the type we just deduced matches // the previously declared type. @@ -6523,8 +6840,7 @@ Decl *Sema::ActOnStartLinkageSpecification(Scope *S, SourceLocation ExternLoc, // FIXME: Add all the various semantics of linkage specifications LinkageSpecDecl *D = LinkageSpecDecl::Create(Context, CurContext, - LangLoc, Language, - LBraceLoc.isValid()); + ExternLoc, LangLoc, Language); CurContext->addDecl(D); PushDeclContext(S, D); return D; @@ -6535,20 +6851,26 @@ Decl *Sema::ActOnStartLinkageSpecification(Scope *S, SourceLocation ExternLoc, /// 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) + Decl *LinkageSpec, + SourceLocation RBraceLoc) { + if (LinkageSpec) { + if (RBraceLoc.isValid()) { + LinkageSpecDecl* LSDecl = cast<LinkageSpecDecl>(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, +VarDecl *Sema::BuildExceptionDeclaration(Scope *S, TypeSourceInfo *TInfo, - IdentifierInfo *Name, - SourceLocation Loc) { + SourceLocation StartLoc, + SourceLocation Loc, + IdentifierInfo *Name) { bool Invalid = false; QualType ExDeclType = TInfo->getType(); @@ -6608,19 +6930,15 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, Diag(Loc, diag::err_objc_object_catch); Invalid = true; } else if (T->isObjCObjectPointerType()) { - if (!getLangOptions().NeXTRuntime) { - Diag(Loc, diag::err_objc_pointer_cxx_catch_gnu); - Invalid = true; - } else if (!getLangOptions().ObjCNonFragileABI) { + if (!getLangOptions().ObjCNonFragileABI) { Diag(Loc, diag::err_objc_pointer_cxx_catch_fragile); Invalid = true; } } } - VarDecl *ExDecl = VarDecl::Create(Context, CurContext, Loc, - Name, ExDeclType, TInfo, SC_None, - SC_None); + VarDecl *ExDecl = VarDecl::Create(Context, CurContext, StartLoc, Loc, Name, + ExDeclType, TInfo, SC_None, SC_None); ExDecl->setExceptionVariable(true); if (!Invalid) { @@ -6703,9 +7021,9 @@ Decl *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) { } VarDecl *ExDecl = BuildExceptionDeclaration(S, TInfo, - D.getIdentifier(), - D.getIdentifierLoc()); - + D.getSourceRange().getBegin(), + D.getIdentifierLoc(), + D.getIdentifier()); if (Invalid) ExDecl->setInvalidDecl(); @@ -6719,21 +7037,23 @@ Decl *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) { return ExDecl; } -Decl *Sema::ActOnStaticAssertDeclaration(SourceLocation AssertLoc, +Decl *Sema::ActOnStaticAssertDeclaration(SourceLocation StaticAssertLoc, Expr *AssertExpr, - Expr *AssertMessageExpr_) { + Expr *AssertMessageExpr_, + SourceLocation RParenLoc) { StringLiteral *AssertMessage = cast<StringLiteral>(AssertMessageExpr_); if (!AssertExpr->isTypeDependent() && !AssertExpr->isValueDependent()) { llvm::APSInt Value(32); if (!AssertExpr->isIntegerConstantExpr(Value, Context)) { - Diag(AssertLoc, diag::err_static_assert_expression_is_not_constant) << + Diag(StaticAssertLoc, + diag::err_static_assert_expression_is_not_constant) << AssertExpr->getSourceRange(); return 0; } if (Value == 0) { - Diag(AssertLoc, diag::err_static_assert_failed) + Diag(StaticAssertLoc, diag::err_static_assert_failed) << AssertMessage->getString() << AssertExpr->getSourceRange(); } } @@ -6741,8 +7061,8 @@ Decl *Sema::ActOnStaticAssertDeclaration(SourceLocation AssertLoc, if (DiagnoseUnexpandedParameterPack(AssertExpr, UPPC_StaticAssertExpression)) return 0; - Decl *Decl = StaticAssertDecl::Create(Context, CurContext, AssertLoc, - AssertExpr, AssertMessage); + Decl *Decl = StaticAssertDecl::Create(Context, CurContext, StaticAssertLoc, + AssertExpr, AssertMessage, RParenLoc); CurContext->addDecl(Decl); return Decl; @@ -6815,7 +7135,6 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec); bool isExplicitSpecialization = false; - unsigned NumMatchedTemplateParamLists = TempParamLists.size(); bool Invalid = false; if (TemplateParameterList *TemplateParams @@ -6825,16 +7144,16 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, /*friend*/ true, isExplicitSpecialization, Invalid)) { - --NumMatchedTemplateParamLists; - 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).take(); + TemplateParams, AS_public, + TempParamLists.size() - 1, + (TemplateParameterList**) TempParamLists.release()).take(); } else { // The "template<>" header is extraneous. Diag(TemplateParams->getTemplateLoc(), diag::err_template_tag_noparams) @@ -6848,7 +7167,7 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, assert(SS.isNotEmpty() && "valid templated tag with no SS and no direct?"); bool isAllExplicitSpecializations = true; - for (unsigned I = 0; I != NumMatchedTemplateParamLists; ++I) { + for (unsigned I = TempParamLists.size(); I-- > 0; ) { if (TempParamLists.get()[I]->size()) { isAllExplicitSpecializations = false; break; @@ -6861,10 +7180,11 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, // about the template header and build an appropriate non-templated // friend. TODO: for source fidelity, remember the headers. if (isAllExplicitSpecializations) { + NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context); ElaboratedTypeKeyword Keyword = TypeWithKeyword::getKeywordForTagTypeKind(Kind); - QualType T = CheckTypenameType(Keyword, SS.getScopeRep(), *Name, - TagLoc, SS.getRange(), NameLoc); + QualType T = CheckTypenameType(Keyword, TagLoc, QualifierLoc, + *Name, NameLoc); if (T.isNull()) return 0; @@ -6872,12 +7192,12 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, if (isa<DependentNameType>(T)) { DependentNameTypeLoc TL = cast<DependentNameTypeLoc>(TSI->getTypeLoc()); TL.setKeywordLoc(TagLoc); - TL.setQualifierRange(SS.getRange()); + TL.setQualifierLoc(QualifierLoc); TL.setNameLoc(NameLoc); } else { ElaboratedTypeLoc TL = cast<ElaboratedTypeLoc>(TSI->getTypeLoc()); TL.setKeywordLoc(TagLoc); - TL.setQualifierRange(SS.getRange()); + TL.setQualifierLoc(QualifierLoc); cast<TypeSpecTypeLoc>(TL.getNamedTypeLoc()).setNameLoc(NameLoc); } @@ -6896,7 +7216,7 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T); DependentNameTypeLoc TL = cast<DependentNameTypeLoc>(TSI->getTypeLoc()); TL.setKeywordLoc(TagLoc); - TL.setQualifierRange(SS.getRange()); + TL.setQualifierLoc(SS.getWithLocInContext(Context)); TL.setNameLoc(NameLoc); FriendDecl *Friend = FriendDecl::Create(Context, CurContext, NameLoc, @@ -7359,10 +7679,14 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New, /// /// \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) @@ -7379,7 +7703,7 @@ bool Sema::CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange) { /// class X. void Sema::ActOnCXXEnterDeclInitializer(Scope *S, Decl *D) { // If there is no declaration, there was an error parsing it. - if (D == 0) return; + if (D == 0 || D->isInvalidDecl()) return; // We should only get called for declarations with scope specifiers, like: // int foo::bar; @@ -7391,7 +7715,7 @@ void Sema::ActOnCXXEnterDeclInitializer(Scope *S, Decl *D) { /// 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) return; + if (D == 0 || D->isInvalidDecl()) return; assert(D->isOutOfLine()); ExitDeclaratorContext(S); @@ -7472,6 +7796,7 @@ bool Sema::DefineUsedVTables() { // 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) @@ -7524,6 +7849,7 @@ bool Sema::DefineUsedVTables() { // 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<CXXRecordDecl>(Class->getCanonicalDecl()); Consumer.HandleVTable(Class, VTablesUsed[Canonical]); @@ -7537,7 +7863,7 @@ bool Sema::DefineUsedVTables() { } VTableUses.clear(); - return true; + return DefinedAnything; } void Sema::MarkVirtualMembersReferenced(SourceLocation Loc, diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp index 652318f..7b235ba 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp @@ -28,7 +28,7 @@ static void DiagnoseObjCImplementedDeprecations(Sema &S, NamedDecl *ND, SourceLocation ImplLoc, int select) { - if (ND && ND->getAttr<DeprecatedAttr>()) { + if (ND && ND->isDeprecated()) { S.Diag(ImplLoc, diag::warn_deprecated_def) << select; if (select == 0) S.Diag(ND->getLocation(), diag::note_method_declared_at); @@ -174,7 +174,8 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, 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 TypedefDecl *TDecl = dyn_cast_or_null<TypedefDecl>(PrevDecl)) { + if (const TypedefNameDecl *TDecl = + dyn_cast_or_null<TypedefNameDecl>(PrevDecl)) { QualType T = TDecl->getUnderlyingType(); if (T->isObjCObjectType()) { if (NamedDecl *IDecl = T->getAs<ObjCObjectType>()->getInterface()) @@ -193,7 +194,7 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, } } - if (!dyn_cast_or_null<TypedefDecl>(PrevDecl)) { + if (!dyn_cast_or_null<TypedefNameDecl>(PrevDecl)) { if (!SuperClassDecl) Diag(SuperLoc, diag::err_undef_superclass) << SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc); @@ -242,7 +243,8 @@ Decl *Sema::ActOnCompatiblityAlias(SourceLocation AtLoc, // Check for class declaration NamedDecl *CDeclU = LookupSingleName(TUScope, ClassName, ClassLocation, LookupOrdinaryName, ForRedeclaration); - if (const TypedefDecl *TDecl = dyn_cast_or_null<TypedefDecl>(CDeclU)) { + if (const TypedefNameDecl *TDecl = + dyn_cast_or_null<TypedefNameDecl>(CDeclU)) { QualType T = TDecl->getUnderlyingType(); if (T->isObjCObjectType()) { if (NamedDecl *IDecl = T->getAs<ObjCObjectType>()->getInterface()) { @@ -1242,7 +1244,7 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc, // @class XCElementToggler; // // FIXME: Make an extension? - TypedefDecl *TDD = dyn_cast<TypedefDecl>(PrevDecl); + TypedefNameDecl *TDD = dyn_cast<TypedefNameDecl>(PrevDecl); if (!TDD || !TDD->getUnderlyingType()->isObjCObjectType()) { Diag(AtClassLoc, diag::err_redefinition_different_kind) << IdentList[i]; Diag(PrevDecl->getLocation(), diag::note_previous_definition); @@ -1369,15 +1371,14 @@ void Sema::AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl, PrevObjCMethod->setDefined(impl); // If a method is deprecated, push it in the global pool. // This is used for better diagnostics. - if (Method->getAttr<DeprecatedAttr>()) { - if (!PrevObjCMethod->getAttr<DeprecatedAttr>()) + 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->getAttr<UnavailableAttr>()) { - if (!PrevObjCMethod->getAttr<UnavailableAttr>() && - !PrevObjCMethod->getAttr<DeprecatedAttr>()) + if (Method->isUnavailable()) { + if (PrevObjCMethod->getAvailability() < AR_Deprecated) List->Method = Method; } return; @@ -1475,7 +1476,7 @@ void Sema::CompareMethodParamsInBaseAndSuper(Decl *ClassDecl, assert(PrevI != SuperMethodDecl->param_end() && "Param mismatch"); QualType T1 = Context.getCanonicalType((*ParamI)->getType()); QualType T2 = Context.getCanonicalType((*PrevI)->getType()); - // If type of arguement of method in this class does not match its + // 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) @@ -1535,7 +1536,7 @@ void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, SourceLocation L = ClassDecl->getLocation(); AtEnd.setBegin(L); AtEnd.setEnd(L); - Diag(L, diag::warn_missing_atend); + Diag(L, diag::err_missing_atend); } // FIXME: Remove these and use the ObjCContainerDecl/DeclContext. @@ -1697,21 +1698,7 @@ void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, /// objective-c's type qualifier from the parser version of the same info. static Decl::ObjCDeclQualifier CvtQTToAstBitMask(ObjCDeclSpec::ObjCDeclQualifier PQTVal) { - Decl::ObjCDeclQualifier ret = Decl::OBJC_TQ_None; - if (PQTVal & ObjCDeclSpec::DQ_In) - ret = (Decl::ObjCDeclQualifier)(ret | Decl::OBJC_TQ_In); - if (PQTVal & ObjCDeclSpec::DQ_Inout) - ret = (Decl::ObjCDeclQualifier)(ret | Decl::OBJC_TQ_Inout); - if (PQTVal & ObjCDeclSpec::DQ_Out) - ret = (Decl::ObjCDeclQualifier)(ret | Decl::OBJC_TQ_Out); - if (PQTVal & ObjCDeclSpec::DQ_Bycopy) - ret = (Decl::ObjCDeclQualifier)(ret | Decl::OBJC_TQ_Bycopy); - if (PQTVal & ObjCDeclSpec::DQ_Byref) - ret = (Decl::ObjCDeclQualifier)(ret | Decl::OBJC_TQ_Byref); - if (PQTVal & ObjCDeclSpec::DQ_Oneway) - ret = (Decl::ObjCDeclQualifier)(ret | Decl::OBJC_TQ_Oneway); - - return ret; + return (Decl::ObjCDeclQualifier) (unsigned) PQTVal; } static inline @@ -1736,7 +1723,7 @@ Decl *Sema::ActOnMethodDeclaration( ObjCArgInfo *ArgInfo, DeclaratorChunk::ParamInfo *CParamInfo, unsigned CNumArgs, // c-style args AttributeList *AttrList, tok::ObjCKeywordKind MethodDeclKind, - bool isVariadic) { + bool isVariadic, bool MethodDefinition) { // Make sure we can establish a context for the method. if (!ClassDecl) { Diag(MethodLoc, diag::error_missing_method_context); @@ -1789,25 +1776,24 @@ Decl *Sema::ActOnMethodDeclaration( if (R.isSingleResult()) { NamedDecl *PrevDecl = R.getFoundDecl(); if (S->isDeclScope(PrevDecl)) { - // FIXME. This should be an error; but will break projects. - Diag(ArgInfo[i].NameLoc, diag::warn_method_param_redefinition) + 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); } } - ParmVarDecl* Param - = ParmVarDecl::Create(Context, ObjCMethod, ArgInfo[i].NameLoc, - ArgInfo[i].Name, ArgType, DI, - SC_None, SC_None, 0); + SourceLocation StartLoc = DI + ? DI->getTypeLoc().getBeginLoc() + : ArgInfo[i].NameLoc; - if (ArgType->isObjCObjectType()) { - Diag(ArgInfo[i].NameLoc, - diag::err_object_cannot_be_passed_returned_by_value) - << 1 << ArgType; - Param->setInvalidDecl(); - } + 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())); @@ -1888,16 +1874,9 @@ Decl *Sema::ActOnMethodDeclaration( Diag(PrevMethod->getLocation(), diag::note_previous_declaration); } - // If the interface declared this method, and it was deprecated there, - // mark it deprecated here. + // Merge information down from the interface declaration if we have one. if (InterfaceMD) - if (Attr *DA = InterfaceMD->getAttr<DeprecatedAttr>()) { - StringLiteral *SE = StringLiteral::CreateEmpty(Context, 1); - ObjCMethod->addAttr(::new (Context) - DeprecatedAttr(DA->getLocation(), - Context, - SE->getString())); - } + mergeObjCMethodDecls(ObjCMethod, InterfaceMD); return ObjCMethod; } @@ -1935,7 +1914,9 @@ void Sema::ActOnDefs(Scope *S, Decl *TagD, SourceLocation DeclStart, for (unsigned i = 0; i < Ivars.size(); i++) { FieldDecl* ID = cast<FieldDecl>(Ivars[i]); RecordDecl *Record = dyn_cast<RecordDecl>(TagD); - Decl *FD = ObjCAtDefsFieldDecl::Create(Context, Record, ID->getLocation(), + Decl *FD = ObjCAtDefsFieldDecl::Create(Context, Record, + /*FIXME: StartL=*/ID->getLocation(), + ID->getLocation(), ID->getIdentifier(), ID->getType(), ID->getBitWidth()); Decls.push_back(FD); @@ -1953,17 +1934,17 @@ void Sema::ActOnDefs(Scope *S, Decl *TagD, SourceLocation DeclStart, } /// \brief Build a type-check a new Objective-C exception variable declaration. -VarDecl *Sema::BuildObjCExceptionDecl(TypeSourceInfo *TInfo, - QualType T, - IdentifierInfo *Name, - SourceLocation NameLoc, +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(NameLoc, diag::err_arg_with_address_space); + Diag(IdLoc, diag::err_arg_with_address_space); Invalid = true; } @@ -1975,14 +1956,14 @@ VarDecl *Sema::BuildObjCExceptionDecl(TypeSourceInfo *TInfo, // Okay: we don't know what this type will instantiate to. } else if (!T->isObjCObjectPointerType()) { Invalid = true; - Diag(NameLoc ,diag::err_catch_param_not_objc_type); + Diag(IdLoc ,diag::err_catch_param_not_objc_type); } else if (T->isObjCQualifiedIdType()) { Invalid = true; - Diag(NameLoc, diag::err_illegal_qualifiers_on_catch_parm); + Diag(IdLoc, diag::err_illegal_qualifiers_on_catch_parm); } - VarDecl *New = VarDecl::Create(Context, CurContext, NameLoc, Name, T, TInfo, - SC_None, SC_None); + VarDecl *New = VarDecl::Create(Context, CurContext, StartLoc, IdLoc, Id, + T, TInfo, SC_None, SC_None); New->setExceptionVariable(true); if (Invalid) @@ -2023,8 +2004,10 @@ Decl *Sema::ActOnObjCExceptionDecl(Scope *S, Declarator &D) { << Context.getTypeDeclType(OwnedDecl); } - VarDecl *New = BuildObjCExceptionDecl(TInfo, ExceptionType, D.getIdentifier(), - D.getIdentifierLoc(), + VarDecl *New = BuildObjCExceptionDecl(TInfo, ExceptionType, + D.getSourceRange().getBegin(), + D.getIdentifierLoc(), + D.getIdentifier(), D.isInvalidType()); // Parameter declarators cannot be qualified (C++ [dcl.meaning]p1). diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp index 5d7993b..f1033dc 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp @@ -96,16 +96,24 @@ bool Sema::CheckDistantExceptionSpec(QualType T) { } 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; - if (!CheckEquivalentExceptionSpec(PDiag(diag::err_mismatched_exception_spec), + unsigned DiagID = diag::err_mismatched_exception_spec; + if (getLangOptions().Microsoft) + DiagID = diag::warn_mismatched_exception_spec; + + if (!CheckEquivalentExceptionSpec(PDiag(DiagID), PDiag(diag::note_previous_declaration), Old->getType()->getAs<FunctionProtoType>(), Old->getLocation(), New->getType()->getAs<FunctionProtoType>(), New->getLocation(), &MissingExceptionSpecification, - &MissingEmptyExceptionSpecification)) + &MissingEmptyExceptionSpecification, + /*AllowNoexceptAllMatchWithNoSpec=*/true, + IsOperatorNew)) return false; // The failure was something other than an empty exception @@ -129,9 +137,7 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { Context.getSourceManager().isInSystemHeader(Old->getLocation())) && Old->isExternC()) { FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo(); - EPI.HasExceptionSpec = true; - EPI.HasAnyExceptionSpec = false; - EPI.NumExceptions = 0; + EPI.ExceptionSpecType = EST_DynamicNone; QualType NewType = Context.getFunctionType(NewProto->getResultType(), NewProto->arg_type_begin(), NewProto->getNumArgs(), @@ -145,10 +151,14 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { = Old->getType()->getAs<FunctionProtoType>(); FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo(); - EPI.HasExceptionSpec = OldProto->hasExceptionSpec(); - EPI.HasAnyExceptionSpec = OldProto->hasAnyExceptionSpec(); - EPI.NumExceptions = OldProto->getNumExceptions(); - EPI.Exceptions = OldProto->exception_begin(); + 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. @@ -160,7 +170,7 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { // If exceptions are disabled, suppress the warning about missing // exception specifications for new and delete operators. - if (!getLangOptions().Exceptions) { + if (!getLangOptions().CXXExceptions) { switch (New->getDeclName().getCXXOverloadedOperator()) { case OO_New: case OO_Array_New: @@ -178,30 +188,53 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { // Warn about the lack of exception specification. llvm::SmallString<128> ExceptionSpecString; llvm::raw_svector_ostream OS(ExceptionSpecString); - 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(Context.PrintingPolicy); + 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(Context.PrintingPolicy); + } + OS << ")"; + break; + } + + case EST_BasicNoexcept: + OS << "noexcept"; + break; + + case EST_ComputedNoexcept: + OS << "noexcept("; + OldProto->getNoexceptExpr()->printPretty(OS, Context, 0, + Context.PrintingPolicy); + OS << ")"; + break; + + default: + assert(false && "This spec type is compatible with none."); } - OS << ")"; OS.flush(); - SourceLocation AfterParenLoc; + SourceLocation FixItLoc; if (TypeSourceInfo *TSInfo = New->getTypeSourceInfo()) { TypeLoc TL = TSInfo->getTypeLoc().IgnoreParens(); if (const FunctionTypeLoc *FTLoc = dyn_cast<FunctionTypeLoc>(&TL)) - AfterParenLoc = PP.getLocForEndOfToken(FTLoc->getRParenLoc()); + FixItLoc = PP.getLocForEndOfToken(FTLoc->getLocalRangeEnd()); } - if (AfterParenLoc.isInvalid()) + if (FixItLoc.isInvalid()) Diag(New->getLocation(), diag::warn_missing_exception_specification) << New << OS.str(); else { @@ -209,7 +242,7 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { // late-specified return types. Diag(New->getLocation(), diag::warn_missing_exception_specification) << New << OS.str() - << FixItHint::CreateInsertion(AfterParenLoc, " " + OS.str().str()); + << FixItHint::CreateInsertion(FixItLoc, " " + OS.str().str()); } if (!Old->getLocation().isInvalid()) @@ -218,7 +251,7 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { return false; } - Diag(New->getLocation(), diag::err_mismatched_exception_spec); + Diag(New->getLocation(), DiagID); Diag(Old->getLocation(), diag::note_previous_declaration); return true; } @@ -230,26 +263,29 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { bool Sema::CheckEquivalentExceptionSpec( const FunctionProtoType *Old, SourceLocation OldLoc, const FunctionProtoType *New, SourceLocation NewLoc) { + unsigned DiagID = diag::err_mismatched_exception_spec; + if (getLangOptions().Microsoft) + DiagID = diag::warn_mismatched_exception_spec; return CheckEquivalentExceptionSpec( - PDiag(diag::err_mismatched_exception_spec), + PDiag(DiagID), PDiag(diag::note_previous_declaration), Old, OldLoc, New, NewLoc); } -/// 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 PartialDiagnostic &DiagID, +/// 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, + const FunctionProtoType *Old, SourceLocation OldLoc, - const FunctionProtoType *New, + const FunctionProtoType *New, SourceLocation NewLoc, bool *MissingExceptionSpecification, - bool *MissingEmptyExceptionSpecification) { + bool*MissingEmptyExceptionSpecification, + bool AllowNoexceptAllMatchWithNoSpec, + bool IsOperatorNew) { // Just completely ignore this under -fno-exceptions. - if (!getLangOptions().Exceptions) + if (!getLangOptions().CXXExceptions) return false; if (MissingExceptionSpecification) @@ -258,29 +294,133 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID, if (MissingEmptyExceptionSpecification) *MissingEmptyExceptionSpecification = false; - bool OldAny = !Old->hasExceptionSpec() || Old->hasAnyExceptionSpec(); - bool NewAny = !New->hasExceptionSpec() || New->hasAnyExceptionSpec(); - if (getLangOptions().Microsoft) { - // Treat throw(whatever) as throw(...) to be compatible with MS headers. - if (New->hasExceptionSpec() && New->getNumExceptions() > 0) - NewAny = true; - if (Old->hasExceptionSpec() && Old->getNumExceptions() > 0) - OldAny = true; + // 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, + // - one exception-specification is a noexcept-specification allowing all + // exceptions and the other is of the form throw(type-id-list), or + // - 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. + // + // CWG 1073 Proposed resolution: Strike the third bullet above. + // + // 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(); + + // 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; } - if (OldAny && NewAny) + // 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; - if (OldAny || NewAny) { + + // 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 (getLangOptions().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<NamespaceDecl>(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 && - !Old->hasAnyExceptionSpec() && Old->getNumExceptions() == 0) { - // The old type has a throw() exception specification and the - // new type has no exception specification, and the caller asked + 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; } @@ -294,8 +434,11 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID, return true; } + assert(OldEST == EST_Dynamic && NewEST == EST_Dynamic && + "Exception compatibility logic error: non-dynamic spec slipped through."); + bool Success = true; - // Both have a definite exception spec. Collect the first set, then compare + // Both have a dynamic exception spec. Collect the first set, then compare // to the second. llvm::SmallPtrSet<CanQualType, 8> OldTypes, NewTypes; for (FunctionProtoType::exception_iterator I = Old->exception_begin(), @@ -331,7 +474,7 @@ bool Sema::CheckExceptionSpecSubset( const FunctionProtoType *Subset, SourceLocation SubLoc) { // Just auto-succeed under -fno-exceptions. - if (!getLangOptions().Exceptions) + if (!getLangOptions().CXXExceptions) return false; // FIXME: As usual, we could be more specific in our error messages, but @@ -340,19 +483,66 @@ bool Sema::CheckExceptionSpecSubset( if (!SubLoc.isValid()) SubLoc = SuperLoc; + ExceptionSpecificationType SuperEST = Superset->getExceptionSpecType(); + // If superset contains everything, we're done. - if (!Superset->hasExceptionSpec() || Superset->hasAnyExceptionSpec()) + 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(); + // It does not. If the subset contains everything, we've failed. - if (!Subset->hasExceptionSpec() || Subset->hasAnyExceptionSpec()) { + 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; } - // Neither contains everything. Do a proper comparison. + 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. diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp index 415ab3f..20b92b8 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp @@ -16,6 +16,7 @@ #include "clang/Sema/Lookup.h" #include "clang/Sema/AnalysisBasedWarnings.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTMutationListener.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" @@ -56,7 +57,7 @@ using namespace sema; /// referenced), false otherwise. /// bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, - bool UnknownObjCClass) { + const ObjCInterfaceDecl *UnknownObjCClass) { if (getLangOptions().CPlusPlus && isa<FunctionDecl>(D)) { // If there were any diagnostics suppressed by template argument deduction, // emit them now. @@ -68,7 +69,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, 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 remove this + // 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(); @@ -82,13 +83,28 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, return true; } - // See if the decl is deprecated. - if (const DeprecatedAttr *DA = D->getAttr<DeprecatedAttr>()) - EmitDeprecationWarning(D, DA->getMessage(), Loc, UnknownObjCClass); + // See if this is a deleted function. + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + if (FD->isDeleted()) { + Diag(Loc, diag::err_deleted_function_use); + Diag(D->getLocation(), diag::note_unavailable_here) << true; + return true; + } + } - // See if the decl is unavailable - if (const UnavailableAttr *UA = D->getAttr<UnavailableAttr>()) { - if (UA->getMessage().empty()) { + // See if this declaration is unavailable or deprecated. + std::string Message; + switch (D->getAvailability(&Message)) { + case AR_Available: + case AR_NotYetIntroduced: + break; + + case AR_Deprecated: + EmitDeprecationWarning(D, Message, Loc, UnknownObjCClass); + break; + + case AR_Unavailable: + if (Message.empty()) { if (!UnknownObjCClass) Diag(Loc, diag::err_unavailable) << D->getDeclName(); else @@ -97,17 +113,9 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, } else Diag(Loc, diag::err_unavailable_message) - << D->getDeclName() << UA->getMessage(); - Diag(D->getLocation(), diag::note_unavailable_here) << 0; - } - - // See if this is a deleted function. - if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { - if (FD->isDeleted()) { - Diag(Loc, diag::err_deleted_function_use); - Diag(D->getLocation(), diag::note_unavailable_here) << true; - return true; - } + << D->getDeclName() << Message; + Diag(D->getLocation(), diag::note_unavailable_here) << 0; + break; } // Warn if this is used but marked unused. @@ -117,6 +125,23 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, 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 on method dispatch calls /// (and other functions in future), which have been declared with sentinel /// attribute. It warns if call does not have the sentinel argument. @@ -232,13 +257,13 @@ SourceRange Sema::getExprRange(ExprTy *E) const { //===----------------------------------------------------------------------===// /// DefaultFunctionArrayConversion (C99 6.3.2.1p3, C99 6.3.2.1p4). -void Sema::DefaultFunctionArrayConversion(Expr *&E) { +ExprResult Sema::DefaultFunctionArrayConversion(Expr *E) { QualType Ty = E->getType(); assert(!Ty.isNull() && "DefaultFunctionArrayConversion - missing type"); if (Ty->isFunctionType()) - ImpCastExprToType(E, Context.getPointerType(Ty), - CK_FunctionToPointerDecay); + 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 @@ -252,25 +277,48 @@ void Sema::DefaultFunctionArrayConversion(Expr *&E) { // T" can be converted to an rvalue of type "pointer to T". // if (getLangOptions().C99 || getLangOptions().CPlusPlus || E->isLValue()) - ImpCastExprToType(E, Context.getArrayDecayedType(Ty), - CK_ArrayToPointerDecay); + 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<UnaryOperator>(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)); } } -void Sema::DefaultLvalueConversion(Expr *&E) { +ExprResult Sema::DefaultLvalueConversion(Expr *E) { // C++ [conv.lval]p1: // A glvalue of a non-function, non-array type T can be // converted to a prvalue. - if (!E->isGLValue()) return; + if (!E->isGLValue()) return Owned(E); QualType T = E->getType(); assert(!T.isNull() && "r-value conversion on typeless expression?"); // Create a load out of an ObjCProperty l-value, if necessary. if (E->getObjectKind() == OK_ObjCProperty) { - ConvertPropertyForRValue(E); + ExprResult Res = ConvertPropertyForRValue(E); + if (Res.isInvalid()) + return Owned(E); + E = Res.take(); if (!E->isGLValue()) - return; + return Owned(E); } // We don't want to throw lvalue-to-rvalue casts on top of @@ -279,7 +327,7 @@ void Sema::DefaultLvalueConversion(Expr *&E) { (E->getType() == Context.OverloadTy || T->isDependentType() || T->isRecordType())) - return; + 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 @@ -287,7 +335,9 @@ void Sema::DefaultLvalueConversion(Expr *&E) { // 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; + return Owned(E); + + CheckForNullPointerDereference(*this, E); // C++ [conv.lval]p1: // [...] If T is a non-class type, the type of the prvalue is the @@ -301,27 +351,34 @@ void Sema::DefaultLvalueConversion(Expr *&E) { if (T.hasQualifiers()) T = T.getUnqualifiedType(); - if (const ArraySubscriptExpr *ae = dyn_cast<ArraySubscriptExpr>(E)) - CheckArrayAccess(ae); + CheckArrayAccess(E); - E = ImplicitCastExpr::Create(Context, T, CK_LValueToRValue, - E, 0, VK_RValue); + return Owned(ImplicitCastExpr::Create(Context, T, CK_LValueToRValue, + E, 0, VK_RValue)); } -void Sema::DefaultFunctionArrayLvalueConversion(Expr *&E) { - DefaultFunctionArrayConversion(E); - DefaultLvalueConversion(E); +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 surpressed. For example, the array->pointer conversion doesn't +/// 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. -Expr *Sema::UsualUnaryConversions(Expr *&E) { +ExprResult Sema::UsualUnaryConversions(Expr *E) { // First, convert to an r-value. - DefaultFunctionArrayLvalueConversion(E); + ExprResult Res = DefaultFunctionArrayLvalueConversion(E); + if (Res.isInvalid()) + return Owned(E); + E = Res.take(); QualType Ty = E->getType(); assert(!Ty.isNull() && "UsualUnaryConversions - missing type"); @@ -345,60 +402,66 @@ Expr *Sema::UsualUnaryConversions(Expr *&E) { QualType PTy = Context.isPromotableBitField(E); if (!PTy.isNull()) { - ImpCastExprToType(E, PTy, CK_IntegralCast); - return E; + E = ImpCastExprToType(E, PTy, CK_IntegralCast).take(); + return Owned(E); } if (Ty->isPromotableIntegerType()) { QualType PT = Context.getPromotedIntegerType(Ty); - ImpCastExprToType(E, PT, CK_IntegralCast); - return E; + E = ImpCastExprToType(E, PT, CK_IntegralCast).take(); + return Owned(E); } } - - return 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(). -void Sema::DefaultArgumentPromotion(Expr *&Expr) { - QualType Ty = Expr->getType(); +ExprResult Sema::DefaultArgumentPromotion(Expr *E) { + QualType Ty = E->getType(); assert(!Ty.isNull() && "DefaultArgumentPromotion - missing type"); - UsualUnaryConversions(Expr); + 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)) - return ImpCastExprToType(Expr, Context.DoubleTy, CK_FloatingCast); + E = ImpCastExprToType(E, Context.DoubleTy, CK_FloatingCast).take(); + + 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. This returns true if the argument type is -/// completely illegal. -bool Sema::DefaultVariadicArgumentPromotion(Expr *&Expr, VariadicCallType CT, +/// interfaces passed by value. +ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT, FunctionDecl *FDecl) { - DefaultArgumentPromotion(Expr); + ExprResult ExprRes = DefaultArgumentPromotion(E); + if (ExprRes.isInvalid()) + return ExprError(); + E = ExprRes.take(); // __builtin_va_start takes the second argument as a "varargs" argument, but // it doesn't actually do anything with it. It doesn't need to be non-pod // etc. if (FDecl && FDecl->getBuiltinID() == Builtin::BI__builtin_va_start) - return false; + return Owned(E); - if (Expr->getType()->isObjCObjectType() && - DiagRuntimeBehavior(Expr->getLocStart(), 0, + if (E->getType()->isObjCObjectType() && + DiagRuntimeBehavior(E->getLocStart(), 0, PDiag(diag::err_cannot_pass_objc_interface_to_vararg) - << Expr->getType() << CT)) - return true; + << E->getType() << CT)) + return ExprError(); - if (!Expr->getType()->isPODType() && - DiagRuntimeBehavior(Expr->getLocStart(), 0, + if (!E->getType()->isPODType() && + DiagRuntimeBehavior(E->getLocStart(), 0, PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg) - << Expr->getType() << CT)) - return true; + << E->getType() << CT)) + return ExprError(); - return false; + return Owned(E); } /// UsualArithmeticConversions - Performs various conversions that are common to @@ -407,19 +470,24 @@ bool Sema::DefaultVariadicArgumentPromotion(Expr *&Expr, VariadicCallType CT, /// responsible for emitting appropriate error diagnostics. /// FIXME: verify the conversion rules for "complex int" are consistent with /// GCC. -QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr, +QualType Sema::UsualArithmeticConversions(ExprResult &lhsExpr, ExprResult &rhsExpr, bool isCompAssign) { - if (!isCompAssign) - UsualUnaryConversions(lhsExpr); + if (!isCompAssign) { + lhsExpr = UsualUnaryConversions(lhsExpr.take()); + if (lhsExpr.isInvalid()) + return QualType(); + } - UsualUnaryConversions(rhsExpr); + rhsExpr = UsualUnaryConversions(rhsExpr.take()); + if (rhsExpr.isInvalid()) + return QualType(); // For conversion purposes, we ignore any qualifiers. // For example, "const float" and "float" are equivalent. QualType lhs = - Context.getCanonicalType(lhsExpr->getType()).getUnqualifiedType(); + Context.getCanonicalType(lhsExpr.get()->getType()).getUnqualifiedType(); QualType rhs = - Context.getCanonicalType(rhsExpr->getType()).getUnqualifiedType(); + Context.getCanonicalType(rhsExpr.get()->getType()).getUnqualifiedType(); // If both types are identical, no conversion is needed. if (lhs == rhs) @@ -434,11 +502,11 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr, QualType lhs_unpromoted = lhs; if (lhs->isPromotableIntegerType()) lhs = Context.getPromotedIntegerType(lhs); - QualType LHSBitfieldPromoteTy = Context.isPromotableBitField(lhsExpr); + QualType LHSBitfieldPromoteTy = Context.isPromotableBitField(lhsExpr.get()); if (!LHSBitfieldPromoteTy.isNull()) lhs = LHSBitfieldPromoteTy; if (lhs != lhs_unpromoted && !isCompAssign) - ImpCastExprToType(lhsExpr, lhs, CK_IntegralCast); + lhsExpr = ImpCastExprToType(lhsExpr.take(), lhs, CK_IntegralCast); // If both types are identical, no conversion is needed. if (lhs == rhs) @@ -455,11 +523,11 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr, if (!RHSComplexFloat && !rhs->isRealFloatingType()) { if (rhs->isIntegerType()) { QualType fp = cast<ComplexType>(lhs)->getElementType(); - ImpCastExprToType(rhsExpr, fp, CK_IntegralToFloating); - ImpCastExprToType(rhsExpr, lhs, CK_FloatingRealToComplex); + rhsExpr = ImpCastExprToType(rhsExpr.take(), fp, CK_IntegralToFloating); + rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_FloatingRealToComplex); } else { assert(rhs->isComplexIntegerType()); - ImpCastExprToType(rhsExpr, lhs, CK_IntegralComplexToFloatingComplex); + rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_IntegralComplexToFloatingComplex); } return lhs; } @@ -469,11 +537,11 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr, // int -> float -> _Complex float if (lhs->isIntegerType()) { QualType fp = cast<ComplexType>(rhs)->getElementType(); - ImpCastExprToType(lhsExpr, fp, CK_IntegralToFloating); - ImpCastExprToType(lhsExpr, rhs, CK_FloatingRealToComplex); + lhsExpr = ImpCastExprToType(lhsExpr.take(), fp, CK_IntegralToFloating); + lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_FloatingRealToComplex); } else { assert(lhs->isComplexIntegerType()); - ImpCastExprToType(lhsExpr, rhs, CK_IntegralComplexToFloatingComplex); + lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_IntegralComplexToFloatingComplex); } } return rhs; @@ -495,13 +563,13 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr, if (LHSComplexFloat && RHSComplexFloat) { if (order > 0) { // _Complex float -> _Complex double - ImpCastExprToType(rhsExpr, lhs, CK_FloatingComplexCast); + rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_FloatingComplexCast); return lhs; } else if (order < 0) { // _Complex float -> _Complex double if (!isCompAssign) - ImpCastExprToType(lhsExpr, rhs, CK_FloatingComplexCast); + lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_FloatingComplexCast); return rhs; } return lhs; @@ -513,8 +581,8 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr, if (order > 0) { // LHS is wider // float -> _Complex double QualType fp = cast<ComplexType>(lhs)->getElementType(); - ImpCastExprToType(rhsExpr, fp, CK_FloatingCast); - ImpCastExprToType(rhsExpr, lhs, CK_FloatingRealToComplex); + rhsExpr = ImpCastExprToType(rhsExpr.take(), fp, CK_FloatingCast); + rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_FloatingRealToComplex); return lhs; } @@ -522,11 +590,11 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr, QualType result = (order == 0 ? lhs : Context.getComplexType(rhs)); // double -> _Complex double - ImpCastExprToType(rhsExpr, result, CK_FloatingRealToComplex); + rhsExpr = ImpCastExprToType(rhsExpr.take(), result, CK_FloatingRealToComplex); // _Complex float -> _Complex double if (!isCompAssign && order < 0) - ImpCastExprToType(lhsExpr, result, CK_FloatingComplexCast); + lhsExpr = ImpCastExprToType(lhsExpr.take(), result, CK_FloatingComplexCast); return result; } @@ -539,8 +607,8 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr, // float -> _Complex double if (!isCompAssign) { QualType fp = cast<ComplexType>(rhs)->getElementType(); - ImpCastExprToType(lhsExpr, fp, CK_FloatingCast); - ImpCastExprToType(lhsExpr, rhs, CK_FloatingRealToComplex); + lhsExpr = ImpCastExprToType(lhsExpr.take(), fp, CK_FloatingCast); + lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_FloatingRealToComplex); } return rhs; } @@ -550,11 +618,11 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr, // double -> _Complex double if (!isCompAssign) - ImpCastExprToType(lhsExpr, result, CK_FloatingRealToComplex); + lhsExpr = ImpCastExprToType(lhsExpr.take(), result, CK_FloatingRealToComplex); // _Complex float -> _Complex double if (order > 0) - ImpCastExprToType(rhsExpr, result, CK_FloatingComplexCast); + rhsExpr = ImpCastExprToType(rhsExpr.take(), result, CK_FloatingComplexCast); return result; } @@ -568,13 +636,13 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr, if (LHSFloat && RHSFloat) { int order = Context.getFloatingTypeOrder(lhs, rhs); if (order > 0) { - ImpCastExprToType(rhsExpr, lhs, CK_FloatingCast); + rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_FloatingCast); return lhs; } assert(order < 0 && "illegal float comparison"); if (!isCompAssign) - ImpCastExprToType(lhsExpr, rhs, CK_FloatingCast); + lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_FloatingCast); return rhs; } @@ -582,7 +650,7 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr, if (LHSFloat) { if (rhs->isIntegerType()) { // Convert rhs to the lhs floating point type. - ImpCastExprToType(rhsExpr, lhs, CK_IntegralToFloating); + rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_IntegralToFloating); return lhs; } @@ -591,11 +659,11 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr, QualType result = Context.getComplexType(lhs); // _Complex int -> _Complex float - ImpCastExprToType(rhsExpr, result, CK_IntegralComplexToFloatingComplex); + rhsExpr = ImpCastExprToType(rhsExpr.take(), result, CK_IntegralComplexToFloatingComplex); // float -> _Complex float if (!isCompAssign) - ImpCastExprToType(lhsExpr, result, CK_FloatingRealToComplex); + lhsExpr = ImpCastExprToType(lhsExpr.take(), result, CK_FloatingRealToComplex); return result; } @@ -604,7 +672,7 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr, if (lhs->isIntegerType()) { // Convert lhs to the rhs floating point type. if (!isCompAssign) - ImpCastExprToType(lhsExpr, rhs, CK_IntegralToFloating); + lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_IntegralToFloating); return rhs; } @@ -614,10 +682,10 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr, // _Complex int -> _Complex float if (!isCompAssign) - ImpCastExprToType(lhsExpr, result, CK_IntegralComplexToFloatingComplex); + lhsExpr = ImpCastExprToType(lhsExpr.take(), result, CK_IntegralComplexToFloatingComplex); // float -> _Complex float - ImpCastExprToType(rhsExpr, result, CK_FloatingRealToComplex); + rhsExpr = ImpCastExprToType(rhsExpr.take(), result, CK_FloatingRealToComplex); return result; } @@ -633,21 +701,21 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr, assert(order && "inequal types with equal element ordering"); if (order > 0) { // _Complex int -> _Complex long - ImpCastExprToType(rhsExpr, lhs, CK_IntegralComplexCast); + rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_IntegralComplexCast); return lhs; } if (!isCompAssign) - ImpCastExprToType(lhsExpr, rhs, CK_IntegralComplexCast); + lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_IntegralComplexCast); return rhs; } else if (lhsComplexInt) { // int -> _Complex int - ImpCastExprToType(rhsExpr, lhs, CK_IntegralRealToComplex); + rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_IntegralRealToComplex); return lhs; } else if (rhsComplexInt) { // int -> _Complex int if (!isCompAssign) - ImpCastExprToType(lhsExpr, rhs, CK_IntegralRealToComplex); + lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_IntegralRealToComplex); return rhs; } @@ -659,29 +727,29 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr, if (lhsSigned == rhsSigned) { // Same signedness; use the higher-ranked type if (compare >= 0) { - ImpCastExprToType(rhsExpr, lhs, CK_IntegralCast); + rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_IntegralCast); return lhs; } else if (!isCompAssign) - ImpCastExprToType(lhsExpr, rhs, CK_IntegralCast); + lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_IntegralCast); return rhs; } else if (compare != (lhsSigned ? 1 : -1)) { // The unsigned type has greater than or equal rank to the // signed type, so use the unsigned type if (rhsSigned) { - ImpCastExprToType(rhsExpr, lhs, CK_IntegralCast); + rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_IntegralCast); return lhs; } else if (!isCompAssign) - ImpCastExprToType(lhsExpr, rhs, CK_IntegralCast); + lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_IntegralCast); return rhs; } else if (Context.getIntWidth(lhs) != Context.getIntWidth(rhs)) { // 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) { - ImpCastExprToType(rhsExpr, lhs, CK_IntegralCast); + rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_IntegralCast); return lhs; } else if (!isCompAssign) - ImpCastExprToType(lhsExpr, rhs, CK_IntegralCast); + lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_IntegralCast); return rhs; } else { // The signed type is higher-ranked than the unsigned type, @@ -690,9 +758,9 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr, // to the signed type. QualType result = Context.getCorrespondingUnsignedType(lhsSigned ? lhs : rhs); - ImpCastExprToType(rhsExpr, result, CK_IntegralCast); + rhsExpr = ImpCastExprToType(rhsExpr.take(), result, CK_IntegralCast); if (!isCompAssign) - ImpCastExprToType(lhsExpr, result, CK_IntegralCast); + lhsExpr = ImpCastExprToType(lhsExpr.take(), result, CK_IntegralCast); return result; } } @@ -702,6 +770,163 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr, //===----------------------------------------------------------------------===// +ExprResult +Sema::ActOnGenericSelectionExpr(SourceLocation KeyLoc, + SourceLocation DefaultLoc, + SourceLocation RParenLoc, + Expr *ControllingExpr, + MultiTypeArg types, + MultiExprArg exprs) { + unsigned NumAssocs = types.size(); + assert(NumAssocs == exprs.size()); + + ParsedType *ParsedTypes = types.release(); + Expr **Exprs = exprs.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 { + // C1X 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; + } + + // C1X 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)); + + llvm::SmallVector<unsigned, 1> 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); + } + + // C1X 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 (llvm::SmallVector<unsigned, 1>::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(); + } + + // C1X 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(); + } + + // C1X 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)); +} + /// 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 @@ -721,8 +946,10 @@ Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks) { StringTokLocs.push_back(StringToks[i].getLocation()); QualType StrTy = Context.CharTy; - if (Literal.AnyWide) StrTy = Context.getWCharType(); - if (Literal.Pascal) StrTy = Context.UnsignedCharTy; + if (Literal.AnyWide) + StrTy = Context.getWCharType(); + else if (Literal.Pascal) + StrTy = Context.UnsignedCharTy; // A C++ string literal has a const-qualified element type (C++ 2.13.4p1). if (getLangOptions().CPlusPlus || getLangOptions().ConstStrings) @@ -738,7 +965,7 @@ Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks) { // Pass &StringTokLocs[0], StringTokLocs.size() to factory! return Owned(StringLiteral::Create(Context, Literal.GetString(), Literal.GetStringLength(), - Literal.AnyWide, StrTy, + Literal.AnyWide, Literal.Pascal, StrTy, &StringTokLocs[0], StringTokLocs.size())); } @@ -783,11 +1010,20 @@ diagnoseUncapturableValueReference(Sema &S, SourceLocation loc, // diagnose this. if (!S.CurContext->isFunctionOrMethod()) return CR_NoCapture; - // This particular madness can happen in ill-formed default - // arguments; claim it's okay and let downstream code handle it. - if (isa<ParmVarDecl>(var) && - S.CurContext == var->getDeclContext()->getParent()) - return CR_NoCapture; + // Certain madnesses can happen with parameter declarations, which + // we want to ignore. + if (isa<ParmVarDecl>(var)) { + // - If the parameter still belongs to the translation unit, then + // we're actually just using one parameter in the declaration of + // the next. This is useful in e.g. VLAs. + if (isa<TranslationUnitDecl>(var->getDeclContext())) + return CR_NoCapture; + + // - This particular madness can happen in ill-formed default + // arguments; claim it's okay and let downstream code handle it. + if (S.CurContext == var->getDeclContext()->getParent()) + return CR_NoCapture; + } DeclarationName functionName; if (FunctionDecl *fn = dyn_cast<FunctionDecl>(var->getDeclContext())) @@ -889,8 +1125,18 @@ static CaptureResult shouldCaptureValueReference(Sema &S, SourceLocation loc, // Build a copy expression. Expr *copyExpr = 0; - if (!byRef && S.getLangOptions().CPlusPlus && - !type->isDependentType() && type->isStructureOrClassType()) { + const RecordType *rtype; + if (!byRef && S.getLangOptions().CPlusPlus && !type->isDependentType() && + (rtype = type->getAs<RecordType>())) { + + // 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<ParmVarDecl>(var)) + S.FinalizeVarWithDestructor(var, rtype); + // 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. @@ -974,8 +1220,8 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, MarkDeclarationReferenced(NameInfo.getLoc(), D); Expr *E = DeclRefExpr::Create(Context, - SS? (NestedNameSpecifier *)SS->getScopeRep() : 0, - SS? SS->getRange() : SourceRange(), + SS? SS->getWithLocInContext(Context) + : NestedNameSpecifierLoc(), D, NameInfo, Ty, VK); // Just in case we're building an illegal pointer-to-member. @@ -1261,12 +1507,24 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, return IMA_Error_StaticContext; } + CXXRecordDecl * + contextClass = cast<CXXMethodDecl>(DC)->getParent()->getCanonicalDecl(); + + // [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 != R.getNamingClass()->getCanonicalDecl() && + contextClass->isProvablyNotDerivedFrom(R.getNamingClass())) + return (hasNonInstance ? IMA_Mixed_Unrelated : 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, - cast<CXXMethodDecl>(DC)->getParent(), - Classes)) + if (IsProvablyNotDerivedFrom(SemaRef, contextClass, Classes)) return (hasNonInstance ? IMA_Mixed_Unrelated : IMA_Error_Unrelated); return (hasNonInstance ? IMA_Mixed : IMA_Instance); @@ -1350,10 +1608,13 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, TemplateArgumentListInfo TList; if (ULE->hasExplicitTemplateArgs()) ULE->copyTemplateArgumentsInto(TList); + + CXXScopeSpec SS; + SS.Adopt(ULE->getQualifierLoc()); CXXDependentScopeMemberExpr *DepExpr = CXXDependentScopeMemberExpr::Create( Context, DepThis, DepThisType, true, SourceLocation(), - ULE->getQualifier(), ULE->getQualifierRange(), NULL, + SS.getWithLocInContext(Context), NULL, R.getLookupNameInfo(), &TList); CallsUndergoingInstantiation.back()->setCallee(DepExpr); } else { @@ -1479,11 +1740,10 @@ bool Sema::canSynthesizeProvisionalIvar(ObjCPropertyDecl *Property) { return true; } -static ObjCIvarDecl *SynthesizeProvisionalIvar(Sema &SemaRef, - LookupResult &Lookup, - IdentifierInfo *II, - SourceLocation NameLoc) { - ObjCMethodDecl *CurMeth = SemaRef.getCurMethodDecl(); +ObjCIvarDecl *Sema::SynthesizeProvisionalIvar(LookupResult &Lookup, + IdentifierInfo *II, + SourceLocation NameLoc) { + ObjCMethodDecl *CurMeth = getCurMethodDecl(); bool LookForIvars; if (Lookup.empty()) LookForIvars = true; @@ -1503,7 +1763,7 @@ static ObjCIvarDecl *SynthesizeProvisionalIvar(Sema &SemaRef, if (!ClassImpDecl) return 0; bool DynamicImplSeen = false; - ObjCPropertyDecl *property = SemaRef.LookupPropertyDecl(IDecl, II); + ObjCPropertyDecl *property = LookupPropertyDecl(IDecl, II); if (!property) return 0; if (ObjCPropertyImplDecl *PIDecl = ClassImpDecl->FindPropertyImplDecl(II)) { @@ -1515,9 +1775,9 @@ static ObjCIvarDecl *SynthesizeProvisionalIvar(Sema &SemaRef, return 0; } if (!DynamicImplSeen) { - QualType PropType = SemaRef.Context.getCanonicalType(property->getType()); - ObjCIvarDecl *Ivar = ObjCIvarDecl::Create(SemaRef.Context, ClassImpDecl, - NameLoc, + QualType PropType = Context.getCanonicalType(property->getType()); + ObjCIvarDecl *Ivar = ObjCIvarDecl::Create(Context, ClassImpDecl, + NameLoc, NameLoc, II, PropType, /*Dinfo=*/0, ObjCIvarDecl::Private, (Expr *)0, true); @@ -1619,7 +1879,7 @@ ExprResult Sema::ActOnIdExpression(Scope *S, // Synthesize ivars lazily. if (getLangOptions().ObjCDefaultSynthProperties && getLangOptions().ObjCNonFragileABI2) { - if (SynthesizeProvisionalIvar(*this, R, II, NameLoc)) { + if (SynthesizeProvisionalIvar(R, II, NameLoc)) { if (const ObjCPropertyDecl *Property = canSynthesizeProvisionalIvar(II)) { Diag(NameLoc, diag::warn_synthesized_ivar_access) << II; @@ -1850,13 +2110,35 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S, if (SelfExpr.isInvalid()) return ExprError(); - Expr *SelfE = SelfExpr.take(); - DefaultLvalueConversion(SelfE); + SelfExpr = DefaultLvalueConversion(SelfExpr.take()); + if (SelfExpr.isInvalid()) + return ExprError(); MarkDeclarationReferenced(Loc, IV); + Expr *base = SelfExpr.take(); + base = base->IgnoreParenImpCasts(); + if (const DeclRefExpr *DE = dyn_cast<DeclRefExpr>(base)) { + const NamedDecl *ND = DE->getDecl(); + if (!isa<ImplicitParamDecl>(ND)) { + // relax the rule such that it is allowed to have a shadow 'self' + // where stand-alone ivar can be found in this 'self' object. + // This is to match gcc's behavior. + ObjCInterfaceDecl *selfIFace = 0; + if (const ObjCObjectPointerType *OPT = + base->getType()->getAsObjCInterfacePointerType()) + selfIFace = OPT->getInterfaceDecl(); + if (!selfIFace || + !selfIFace->lookupInstanceVariable(IV->getIdentifier())) { + Diag(Loc, diag::error_implicit_ivar_access) + << IV->getDeclName(); + Diag(ND->getLocation(), diag::note_declared_at); + return ExprError(); + } + } + } return Owned(new (Context) ObjCIvarRefExpr(IV, IV->getType(), Loc, - SelfE, true, true)); + SelfExpr.take(), true, true)); } } else if (CurMethod->isInstanceMethod()) { // We should warn if a local variable hides an ivar. @@ -1902,14 +2184,14 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S, /// * Finally we cast from the declaring class to the "true" /// declaring class of the member. This conversion does not /// obey access control. -bool -Sema::PerformObjectMemberConversion(Expr *&From, +ExprResult +Sema::PerformObjectMemberConversion(Expr *From, NestedNameSpecifier *Qualifier, NamedDecl *FoundDecl, NamedDecl *Member) { CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Member->getDeclContext()); if (!RD) - return false; + return Owned(From); QualType DestRecordType; QualType DestType; @@ -1929,7 +2211,7 @@ Sema::PerformObjectMemberConversion(Expr *&From, } } else if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Member)) { if (Method->isStatic()) - return false; + return Owned(From); DestType = Method->getThisType(Context); DestRecordType = DestType->getPointeeType(); @@ -1943,15 +2225,15 @@ Sema::PerformObjectMemberConversion(Expr *&From, } } else { // No conversion necessary. - return false; + return Owned(From); } if (DestType->isDependentType() || FromType->isDependentType()) - return false; + return Owned(From); // If the unqualified types are the same, no conversion is necessary. if (Context.hasSameUnqualifiedType(FromRecordType, DestRecordType)) - return false; + return Owned(From); SourceRange FromRange = From->getSourceRange(); SourceLocation FromLoc = FromRange.getBegin(); @@ -1990,12 +2272,12 @@ Sema::PerformObjectMemberConversion(Expr *&From, CXXCastPath BasePath; if (CheckDerivedToBaseConversion(FromRecordType, QRecordType, FromLoc, FromRange, &BasePath)) - return true; + return ExprError(); if (PointerConversions) QType = Context.getPointerType(QType); - ImpCastExprToType(From, QType, CK_UncheckedDerivedToBase, - VK, &BasePath); + From = ImpCastExprToType(From, QType, CK_UncheckedDerivedToBase, + VK, &BasePath).take(); FromType = QType; FromRecordType = QRecordType; @@ -2003,7 +2285,7 @@ Sema::PerformObjectMemberConversion(Expr *&From, // If the qualifier type was the same as the destination type, // we're done. if (Context.hasSameUnqualifiedType(FromRecordType, DestRecordType)) - return false; + return Owned(From); } } @@ -2026,13 +2308,13 @@ Sema::PerformObjectMemberConversion(Expr *&From, CXXCastPath BasePath; if (CheckDerivedToBaseConversion(FromRecordType, URecordType, FromLoc, FromRange, &BasePath)) - return true; + return ExprError(); QualType UType = URecordType; if (PointerConversions) UType = Context.getPointerType(UType); - ImpCastExprToType(From, UType, CK_UncheckedDerivedToBase, - VK, &BasePath); + From = ImpCastExprToType(From, UType, CK_UncheckedDerivedToBase, + VK, &BasePath).take(); FromType = UType; FromRecordType = URecordType; } @@ -2046,11 +2328,10 @@ Sema::PerformObjectMemberConversion(Expr *&From, if (CheckDerivedToBaseConversion(FromRecordType, DestRecordType, FromLoc, FromRange, &BasePath, IgnoreAccess)) - return true; + return ExprError(); - ImpCastExprToType(From, DestType, CK_UncheckedDerivedToBase, - VK, &BasePath); - return false; + return ImpCastExprToType(From, DestType, CK_UncheckedDerivedToBase, + VK, &BasePath); } /// \brief Build a MemberExpr AST node. @@ -2061,14 +2342,7 @@ static MemberExpr *BuildMemberExpr(ASTContext &C, Expr *Base, bool isArrow, QualType Ty, ExprValueKind VK, ExprObjectKind OK, const TemplateArgumentListInfo *TemplateArgs = 0) { - NestedNameSpecifier *Qualifier = 0; - SourceRange QualifierRange; - if (SS.isSet()) { - Qualifier = (NestedNameSpecifier *) SS.getScopeRep(); - QualifierRange = SS.getRange(); - } - - return MemberExpr::Create(C, Base, isArrow, Qualifier, QualifierRange, + return MemberExpr::Create(C, Base, isArrow, SS.getWithLocInContext(C), Member, FoundDecl, MemberNameInfo, TemplateArgs, Ty, VK, OK); } @@ -2123,10 +2397,12 @@ BuildFieldReferenceExpr(Sema &S, Expr *BaseExpr, bool IsArrow, } S.MarkDeclarationReferenced(MemberNameInfo.getLoc(), Field); - if (S.PerformObjectMemberConversion(BaseExpr, SS.getScopeRep(), - FoundDecl, Field)) + ExprResult Base = + S.PerformObjectMemberConversion(BaseExpr, SS.getScopeRep(), + FoundDecl, Field); + if (Base.isInvalid()) return ExprError(); - return S.Owned(BuildMemberExpr(S.Context, BaseExpr, IsArrow, SS, + return S.Owned(BuildMemberExpr(S.Context, Base.take(), IsArrow, SS, Field, FoundDecl, MemberNameInfo, MemberType, VK, OK)); } @@ -2234,7 +2510,7 @@ bool Sema::UseArgumentDependentLookup(const CXXScopeSpec &SS, /// 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<TypedefDecl>(D)) { + if (isa<TypedefNameDecl>(D)) { S.Diag(Loc, diag::err_unexpected_typedef) << D->getDeclName(); return true; } @@ -2276,8 +2552,8 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, UnresolvedLookupExpr *ULE = UnresolvedLookupExpr::Create(Context, R.getNamingClass(), - (NestedNameSpecifier*) SS.getScopeRep(), - SS.getRange(), R.getLookupNameInfo(), + SS.getWithLocInContext(Context), + R.getLookupNameInfo(), NeedsADL, R.isOverloadedResult(), R.begin(), R.end()); @@ -2433,6 +2709,16 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, break; case Decl::Function: { + const FunctionType *fty = type->castAs<FunctionType>(); + + // 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 (getLangOptions().CPlusPlus) { valueKind = VK_LValue; @@ -2444,10 +2730,10 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, // used for checking compatibility. Therefore, when referencing // the function, we pretend that we don't have the full function // type. - if (!cast<FunctionDecl>(VD)->hasPrototype()) - if (const FunctionProtoType *proto = type->getAs<FunctionProtoType>()) - type = Context.getFunctionNoProtoType(proto->getResultType(), - proto->getExtInfo()); + if (!cast<FunctionDecl>(VD)->hasPrototype() && + isa<FunctionProtoType>(fty)) + type = Context.getFunctionNoProtoType(fty->getResultType(), + fty->getExtInfo()); // Functions are r-values in C. valueKind = VK_RValue; @@ -2455,6 +2741,16 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, } 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<FunctionProtoType>(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<CXXMethodDecl>(VD)->isStatic()) { valueKind = VK_LValue; @@ -2478,8 +2774,7 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, return ExprError(); } -ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, - tok::TokenKind Kind) { +ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) { PredefinedExpr::IdentType IT; switch (Kind) { @@ -2606,9 +2901,14 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok) { bool isExact = (result == APFloat::opOK); Res = FloatingLiteral::Create(Context, Val, isExact, Ty, Tok.getLocation()); - if (getLangOptions().SinglePrecisionConstants && Ty == Context.DoubleTy) - ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast); - + if (Ty == Context.DoubleTy) { + if (getLangOptions().SinglePrecisionConstants) { + Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).take(); + } else if (getLangOptions().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 { @@ -2716,10 +3016,10 @@ ExprResult Sema::ActOnParenExpr(SourceLocation L, /// The UsualUnaryConversions() function is *not* called by this routine. /// See C99 6.3.2.1p[2-4] for more details. -bool Sema::CheckSizeOfAlignOfOperand(QualType exprType, - SourceLocation OpLoc, - SourceRange ExprRange, - bool isSizeof) { +bool Sema::CheckUnaryExprOrTypeTraitOperand(QualType exprType, + SourceLocation OpLoc, + SourceRange ExprRange, + UnaryExprOrTypeTrait ExprKind) { if (exprType->isDependentType()) return false; @@ -2730,30 +3030,47 @@ bool Sema::CheckSizeOfAlignOfOperand(QualType exprType, if (const ReferenceType *Ref = exprType->getAs<ReferenceType>()) exprType = Ref->getPointeeType(); + // [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 (ExprKind == UETT_VecStep) { + if (!(exprType->isArithmeticType() || exprType->isVoidType() || + exprType->isVectorType())) { + Diag(OpLoc, diag::err_vecstep_non_scalar_vector_type) + << exprType << ExprRange; + return true; + } + } + // C99 6.5.3.4p1: if (exprType->isFunctionType()) { // alignof(function) is allowed as an extension. - if (isSizeof) - Diag(OpLoc, diag::ext_sizeof_function_type) << ExprRange; + if (ExprKind == UETT_SizeOf) + Diag(OpLoc, diag::ext_sizeof_function_type) + << ExprRange; return false; } - // Allow sizeof(void)/alignof(void) as an extension. + // Allow sizeof(void)/alignof(void) as an extension. vec_step(void) is not + // an extension, as void is a built-in scalar type (OpenCL 1.1 6.1.1). if (exprType->isVoidType()) { - Diag(OpLoc, diag::ext_sizeof_void_type) - << (isSizeof ? "sizeof" : "__alignof") << ExprRange; + if (ExprKind != UETT_VecStep) + Diag(OpLoc, diag::ext_sizeof_void_type) + << ExprKind << ExprRange; return false; } if (RequireCompleteType(OpLoc, exprType, PDiag(diag::err_sizeof_alignof_incomplete_type) - << int(!isSizeof) << ExprRange)) + << ExprKind << ExprRange)) return true; // Reject sizeof(interface) and sizeof(interface<proto>) in 64-bit mode. if (LangOpts.ObjCNonFragileABI && exprType->isObjCObjectType()) { Diag(OpLoc, diag::err_sizeof_nonfragile_interface) - << exprType << isSizeof << ExprRange; + << exprType << (ExprKind == UETT_SizeOf) + << ExprRange; return true; } @@ -2783,109 +3100,132 @@ static bool CheckAlignOfExpr(Sema &S, Expr *E, SourceLocation OpLoc, if (isa<FieldDecl>(ME->getMemberDecl())) return false; - return S.CheckSizeOfAlignOfOperand(E->getType(), OpLoc, ExprRange, false); + return S.CheckUnaryExprOrTypeTraitOperand(E->getType(), OpLoc, ExprRange, + UETT_AlignOf); +} + +bool Sema::CheckVecStepExpr(Expr *E, SourceLocation OpLoc, + SourceRange ExprRange) { + E = E->IgnoreParens(); + + // Cannot know anything else if the expression is dependent. + if (E->isTypeDependent()) + return false; + + return CheckUnaryExprOrTypeTraitOperand(E->getType(), OpLoc, ExprRange, + UETT_VecStep); } /// \brief Build a sizeof or alignof expression given a type operand. ExprResult -Sema::CreateSizeOfAlignOfExpr(TypeSourceInfo *TInfo, - SourceLocation OpLoc, - bool isSizeOf, SourceRange R) { +Sema::CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo, + SourceLocation OpLoc, + UnaryExprOrTypeTrait ExprKind, + SourceRange R) { if (!TInfo) return ExprError(); QualType T = TInfo->getType(); if (!T->isDependentType() && - CheckSizeOfAlignOfOperand(T, OpLoc, R, isSizeOf)) + 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) SizeOfAlignOfExpr(isSizeOf, TInfo, - Context.getSizeType(), OpLoc, - R.getEnd())); + 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::CreateSizeOfAlignOfExpr(Expr *E, SourceLocation OpLoc, - bool isSizeOf, SourceRange R) { +Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc, + UnaryExprOrTypeTrait ExprKind, + SourceRange R) { // Verify that the operand is valid. bool isInvalid = false; if (E->isTypeDependent()) { // Delay type-checking for type-dependent expressions. - } else if (!isSizeOf) { + } else if (ExprKind == UETT_AlignOf) { isInvalid = CheckAlignOfExpr(*this, E, OpLoc, R); + } else if (ExprKind == UETT_VecStep) { + isInvalid = CheckVecStepExpr(E, OpLoc, R); } else if (E->getBitField()) { // C99 6.5.3.4p1. Diag(OpLoc, diag::err_sizeof_alignof_bitfield) << 0; isInvalid = true; } else if (E->getType()->isPlaceholderType()) { - ExprResult PE = CheckPlaceholderExpr(E, OpLoc); + ExprResult PE = CheckPlaceholderExpr(E); if (PE.isInvalid()) return ExprError(); - return CreateSizeOfAlignOfExpr(PE.take(), OpLoc, isSizeOf, R); + return CreateUnaryExprOrTypeTraitExpr(PE.take(), OpLoc, ExprKind, R); } else { - isInvalid = CheckSizeOfAlignOfOperand(E->getType(), OpLoc, R, true); + isInvalid = CheckUnaryExprOrTypeTraitOperand(E->getType(), OpLoc, R, + UETT_SizeOf); } if (isInvalid) return ExprError(); // C99 6.5.3.4p4: the type (an unsigned integer type) is size_t. - return Owned(new (Context) SizeOfAlignOfExpr(isSizeOf, E, - Context.getSizeType(), OpLoc, - R.getEnd())); + return Owned(new (Context) UnaryExprOrTypeTraitExpr(ExprKind, E, + Context.getSizeType(), + OpLoc, R.getEnd())); } -/// ActOnSizeOfAlignOfExpr - Handle @c sizeof(type) and @c sizeof @c expr and -/// the same for @c alignof and @c __alignof +/// 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::ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType, - void *TyOrEx, const SourceRange &ArgRange) { +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 CreateSizeOfAlignOfExpr(TInfo, OpLoc, isSizeof, ArgRange); + return CreateUnaryExprOrTypeTraitExpr(TInfo, OpLoc, ExprKind, ArgRange); } Expr *ArgEx = (Expr *)TyOrEx; ExprResult Result - = CreateSizeOfAlignOfExpr(ArgEx, OpLoc, isSizeof, ArgEx->getSourceRange()); + = CreateUnaryExprOrTypeTraitExpr(ArgEx, OpLoc, ExprKind, + ArgEx->getSourceRange()); return move(Result); } -static QualType CheckRealImagOperand(Sema &S, Expr *&V, SourceLocation Loc, +static QualType CheckRealImagOperand(Sema &S, ExprResult &V, SourceLocation Loc, bool isReal) { - if (V->isTypeDependent()) + if (V.get()->isTypeDependent()) return S.Context.DependentTy; // _Real and _Imag are only l-values for normal l-values. - if (V->getObjectKind() != OK_Ordinary) - S.DefaultLvalueConversion(V); + 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->getType()->getAs<ComplexType>()) + if (const ComplexType *CT = V.get()->getType()->getAs<ComplexType>()) return CT->getElementType(); // Otherwise they pass through real integer and floating point types here. - if (V->getType()->isArithmeticType()) - return V->getType(); + if (V.get()->getType()->isArithmeticType()) + return V.get()->getType(); // Test for placeholders. - ExprResult PR = S.CheckPlaceholderExpr(V, Loc); + ExprResult PR = S.CheckPlaceholderExpr(V.get()); if (PR.isInvalid()) return QualType(); - if (PR.take() != V) { - V = PR.take(); + 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->getType() + S.Diag(Loc, diag::err_realimag_invalid_type) << V.get()->getType() << (isReal ? "__real" : "__imag"); return QualType(); } @@ -2955,9 +3295,16 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, Expr *RHSExp = Idx; // Perform default conversions. - if (!LHSExp->getType()->getAs<VectorType>()) - DefaultFunctionArrayLvalueConversion(LHSExp); - DefaultFunctionArrayLvalueConversion(RHSExp); + if (!LHSExp->getType()->getAs<VectorType>()) { + 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; @@ -3010,8 +3357,8 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, // force the promotion here. Diag(LHSExp->getLocStart(), diag::ext_subscript_non_lvalue) << LHSExp->getSourceRange(); - ImpCastExprToType(LHSExp, Context.getArrayDecayedType(LHSTy), - CK_ArrayToPointerDecay); + LHSExp = ImpCastExprToType(LHSExp, Context.getArrayDecayedType(LHSTy), + CK_ArrayToPointerDecay).take(); LHSTy = LHSExp->getType(); BaseExpr = LHSExp; @@ -3021,8 +3368,8 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, // Same as previous, except for 123[f().a] case Diag(RHSExp->getLocStart(), diag::ext_subscript_non_lvalue) << RHSExp->getSourceRange(); - ImpCastExprToType(RHSExp, Context.getArrayDecayedType(RHSTy), - CK_ArrayToPointerDecay); + RHSExp = ImpCastExprToType(RHSExp, Context.getArrayDecayedType(RHSTy), + CK_ArrayToPointerDecay).take(); RHSTy = RHSExp->getType(); BaseExpr = RHSExp; @@ -3269,8 +3616,7 @@ Sema::ActOnDependentMemberExpr(Expr *BaseExpr, QualType BaseType, // must have pointer type, and the accessed type is the pointee. return Owned(CXXDependentScopeMemberExpr::Create(Context, BaseExpr, BaseType, IsArrow, OpLoc, - SS.getScopeRep(), - SS.getRange(), + SS.getWithLocInContext(Context), FirstQualifierInScope, NameInfo, TemplateArgs)); } @@ -3441,10 +3787,15 @@ Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType, // Explicit member accesses. } else { + ExprResult BaseResult = Owned(Base); ExprResult Result = - LookupMemberExpr(R, Base, IsArrow, OpLoc, + 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(); @@ -3477,7 +3828,6 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, } R.setBaseObjectType(BaseType); - NestedNameSpecifier *Qualifier = SS.getScopeRep(); const DeclarationNameInfo &MemberNameInfo = R.getLookupNameInfo(); DeclarationName MemberName = MemberNameInfo.getName(); SourceLocation MemberLoc = MemberNameInfo.getLoc(); @@ -3522,7 +3872,7 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, = UnresolvedMemberExpr::Create(Context, R.isUnresolvableResult(), BaseExpr, BaseExprType, IsArrow, OpLoc, - Qualifier, SS.getRange(), + SS.getWithLocInContext(Context), MemberNameInfo, TemplateArgs, R.begin(), R.end()); @@ -3569,8 +3919,12 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, // Perform a property load on the base regardless of whether we // actually need it for the declaration. - if (BaseExpr->getObjectKind() == OK_ObjCProperty) - ConvertPropertyForRValue(BaseExpr); + if (BaseExpr->getObjectKind() == OK_ObjCProperty) { + ExprResult Result = ConvertPropertyForRValue(BaseExpr); + if (Result.isInvalid()) + return ExprError(); + BaseExpr = Result.take(); + } if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl)) return BuildFieldReferenceExpr(*this, BaseExpr, IsArrow, @@ -3591,12 +3945,20 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, } if (CXXMethodDecl *MemberFn = dyn_cast<CXXMethodDecl>(MemberDecl)) { + ExprValueKind valueKind; + QualType type; + if (MemberFn->isInstance()) { + valueKind = VK_RValue; + type = Context.BoundMemberTy; + } else { + valueKind = VK_LValue; + type = MemberFn->getType(); + } + MarkDeclarationReferenced(MemberLoc, MemberDecl); return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS, MemberFn, FoundDecl, MemberNameInfo, - MemberFn->getType(), - MemberFn->isInstance() ? VK_RValue : VK_LValue, - OK_Ordinary)); + type, valueKind, OK_Ordinary)); } assert(!isa<FunctionDecl>(MemberDecl) && "member function not C++ method?"); @@ -3629,9 +3991,9 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, /// 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, Expr *&base) { +static bool ShouldTryAgainWithRedefinitionType(Sema &S, ExprResult &base) { const ObjCObjectPointerType *opty - = base->getType()->getAs<ObjCObjectPointerType>(); + = base.get()->getType()->getAs<ObjCObjectPointerType>(); if (!opty) return false; const ObjCObjectType *ty = opty->getObjectType(); @@ -3651,7 +4013,7 @@ static bool ShouldTryAgainWithRedefinitionType(Sema &S, Expr *&base) { if (opty && !opty->getObjectType()->getInterface() != 0) return false; - S.ImpCastExprToType(base, redef, CK_BitCast); + base = S.ImpCastExprToType(base.take(), redef, CK_BitCast); return true; } @@ -3666,17 +4028,22 @@ static bool ShouldTryAgainWithRedefinitionType(Sema &S, Expr *&base) { /// The ObjCImpDecl bit is a gross hack that will need to be properly /// fixed for ObjC++. ExprResult -Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, +Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, bool &IsArrow, SourceLocation OpLoc, CXXScopeSpec &SS, Decl *ObjCImpDecl, bool HasTemplateArgs) { - assert(BaseExpr && "no base expression"); + assert(BaseExpr.get() && "no base expression"); // Perform default conversions. - DefaultFunctionArrayConversion(BaseExpr); - if (IsArrow) DefaultLvalueConversion(BaseExpr); + BaseExpr = DefaultFunctionArrayConversion(BaseExpr.take()); - QualType BaseType = BaseExpr->getType(); + if (IsArrow) { + BaseExpr = DefaultLvalueConversion(BaseExpr.take()); + if (BaseExpr.isInvalid()) + return ExprError(); + } + + QualType BaseType = BaseExpr.get()->getType(); assert(!BaseType->isDependentType()); DeclarationName MemberName = R.getLookupName(); @@ -3700,19 +4067,21 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, // overloaded operator->, but that should have been dealt with // by now. Diag(OpLoc, diag::err_typecheck_member_reference_suggestion) - << BaseType << int(IsArrow) << BaseExpr->getSourceRange() + << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange() << FixItHint::CreateReplacement(OpLoc, "."); IsArrow = false; + } else if (BaseType == Context.BoundMemberTy) { + goto fail; } else { Diag(MemberLoc, diag::err_typecheck_member_reference_arrow) - << BaseType << BaseExpr->getSourceRange(); + << BaseType << BaseExpr.get()->getSourceRange(); return ExprError(); } } // Handle field access to simple records. if (const RecordType *RTy = BaseType->getAs<RecordType>()) { - if (LookupMemberExprInRecord(*this, R, BaseExpr->getSourceRange(), + if (LookupMemberExprInRecord(*this, R, BaseExpr.get()->getSourceRange(), RTy, OpLoc, SS, HasTemplateArgs)) return ExprError(); @@ -3735,7 +4104,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, // But we only actually find it this way on objects of type 'id', // apparently. if (OTy->isObjCId() && Member->isStr("isa")) - return Owned(new (Context) ObjCIsaExpr(BaseExpr, IsArrow, MemberLoc, + return Owned(new (Context) ObjCIsaExpr(BaseExpr.take(), IsArrow, MemberLoc, Context.getObjCClassType())); if (ShouldTryAgainWithRedefinitionType(*this, BaseExpr)) @@ -3768,7 +4137,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, Diag(MemberLoc, diag::err_typecheck_member_reference_ivar) << IDecl->getDeclName() << MemberName - << BaseExpr->getSourceRange(); + << BaseExpr.get()->getSourceRange(); return ExprError(); } } @@ -3814,7 +4183,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, } return Owned(new (Context) ObjCIvarRefExpr(IV, IV->getType(), - MemberLoc, BaseExpr, + MemberLoc, BaseExpr.take(), IsArrow)); } @@ -3822,8 +4191,11 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, const ObjCObjectPointerType *OPT; if (!IsArrow && (OPT = BaseType->getAs<ObjCObjectPointerType>())) { // This actually uses the base as an r-value. - DefaultLvalueConversion(BaseExpr); - assert(Context.hasSameUnqualifiedType(BaseType, BaseExpr->getType())); + BaseExpr = DefaultLvalueConversion(BaseExpr.take()); + if (BaseExpr.isInvalid()) + return ExprError(); + + assert(Context.hasSameUnqualifiedType(BaseType, BaseExpr.get()->getType())); IdentifierInfo *Member = MemberName.getAsIdentifierInfo(); @@ -3843,7 +4215,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, VK_LValue, OK_ObjCProperty, MemberLoc, - BaseExpr)); + BaseExpr.take())); } if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(PMDecl)) { @@ -3867,11 +4239,12 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, return Owned(new (Context) ObjCPropertyRefExpr(OMD, SMD, PType, VK, OK, - MemberLoc, BaseExpr)); + MemberLoc, BaseExpr.take())); } } - - if (ShouldTryAgainWithRedefinitionType(*this, BaseExpr)) + // 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); @@ -3937,7 +4310,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, // FIXME: we must check that the setter has property type. return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter, PType, VK, OK, - MemberLoc, BaseExpr)); + MemberLoc, BaseExpr.take())); } if (ShouldTryAgainWithRedefinitionType(*this, BaseExpr)) @@ -3949,7 +4322,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, } // Normal property access. - return HandleExprPropertyRefExpr(OPT, BaseExpr, MemberName, MemberLoc, + return HandleExprPropertyRefExpr(OPT, BaseExpr.get(), MemberName, MemberLoc, SourceLocation(), QualType(), false); } @@ -3957,13 +4330,13 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, if (BaseType->isExtVectorType()) { // FIXME: this expr should store IsArrow. IdentifierInfo *Member = MemberName.getAsIdentifierInfo(); - ExprValueKind VK = (IsArrow ? VK_LValue : BaseExpr->getValueKind()); + 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, + return Owned(new (Context) ExtVectorElementExpr(ret, VK, BaseExpr.take(), *Member, MemberLoc)); } @@ -3972,7 +4345,8 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, if (IsArrow && BaseType->isSpecificBuiltinType(BuiltinType::ObjCSel) && !Context.ObjCSelRedefinitionType->isObjCSelType()) { - ImpCastExprToType(BaseExpr, Context.ObjCSelRedefinitionType, CK_BitCast); + BaseExpr = ImpCastExprToType(BaseExpr.take(), Context.ObjCSelRedefinitionType, + CK_BitCast); return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS, ObjCImpDecl, HasTemplateArgs); } @@ -3991,7 +4365,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, if (!IsArrow && Ptr->getPointeeType()->isRecordType() && MemberName.getNameKind() != DeclarationName::CXXDestructorName) { Diag(OpLoc, diag::err_typecheck_member_reference_suggestion) - << BaseType << int(IsArrow) << BaseExpr->getSourceRange() + << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange() << FixItHint::CreateReplacement(OpLoc, "->"); // Recurse as an -> access. @@ -4006,11 +4380,11 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, bool TryCall = false; bool Overloaded = false; UnresolvedSet<8> AllOverloads; - if (const OverloadExpr *Overloads = dyn_cast<OverloadExpr>(BaseExpr)) { + if (const OverloadExpr *Overloads = dyn_cast<OverloadExpr>(BaseExpr.get())) { AllOverloads.append(Overloads->decls_begin(), Overloads->decls_end()); TryCall = true; Overloaded = true; - } else if (DeclRefExpr *DeclRef = dyn_cast<DeclRefExpr>(BaseExpr)) { + } else if (DeclRefExpr *DeclRef = dyn_cast<DeclRefExpr>(BaseExpr.get())) { if (FunctionDecl* Fun = dyn_cast<FunctionDecl>(DeclRef->getDecl())) { AllOverloads.addDecl(Fun); TryCall = true; @@ -4024,22 +4398,25 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, bool HasViableZeroArgOverload = false; for (OverloadExpr::decls_iterator it = AllOverloads.begin(), DeclsEnd = AllOverloads.end(); it != DeclsEnd; ++it) { - const FunctionDecl *OverloadDecl = cast<FunctionDecl>(*it); - QualType ResultTy = OverloadDecl->getResultType(); - if ((!IsArrow && ResultTy->isRecordType()) || - (IsArrow && ResultTy->isPointerType() && - ResultTy->getPointeeType()->isRecordType())) { - ViableOverloads.addDecl(*it); - if (OverloadDecl->getMinRequiredArguments() == 0) { - HasViableZeroArgOverload = true; + // Our overload set may include TemplateDecls, which we'll ignore for the + // purposes of determining whether we can issue a '()' fixit. + if (const FunctionDecl *OverloadDecl = dyn_cast<FunctionDecl>(*it)) { + QualType ResultTy = OverloadDecl->getResultType(); + if ((!IsArrow && ResultTy->isRecordType()) || + (IsArrow && ResultTy->isPointerType() && + ResultTy->getPointeeType()->isRecordType())) { + ViableOverloads.addDecl(*it); + if (OverloadDecl->getMinRequiredArguments() == 0) { + HasViableZeroArgOverload = true; + } } } } if (!HasViableZeroArgOverload || ViableOverloads.size() != 1) { - Diag(BaseExpr->getExprLoc(), diag::err_member_reference_needs_call) - << 1 << 0 - << BaseExpr->getSourceRange(); + Diag(BaseExpr.get()->getExprLoc(), diag::err_member_reference_needs_call) + << (AllOverloads.size() > 1) << 0 + << BaseExpr.get()->getSourceRange(); int ViableOverloadCount = ViableOverloads.size(); int I; for (I = 0; I < ViableOverloadCount; ++I) { @@ -4052,7 +4429,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, diag::note_member_ref_possible_intended_overload); } if (I != ViableOverloadCount) { - Diag(BaseExpr->getExprLoc(), diag::note_ovl_too_many_candidates) + Diag(BaseExpr.get()->getExprLoc(), diag::note_ovl_too_many_candidates) << int(ViableOverloadCount - I); } return ExprError(); @@ -4068,6 +4445,16 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, } } else if ((Fun = BaseType->getAs<FunctionType>())) { TryCall = true; + } else if (BaseType == 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 fnType = Expr::findBoundMemberType(BaseExpr.get()); + if (!fnType.isNull()) { + TryCall = true; + Fun = fnType->castAs<FunctionType>(); + } } if (TryCall) { @@ -4088,24 +4475,24 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, // can emit a fixit and carry on pretending that BaseExpr was actually a // CallExpr. SourceLocation ParenInsertionLoc = - PP.getLocForEndOfToken(BaseExpr->getLocEnd()); - Diag(BaseExpr->getExprLoc(), diag::err_member_reference_needs_call) + PP.getLocForEndOfToken(BaseExpr.get()->getLocEnd()); + Diag(BaseExpr.get()->getExprLoc(), diag::err_member_reference_needs_call) << int(Overloaded) << 1 - << BaseExpr->getSourceRange() + << BaseExpr.get()->getSourceRange() << FixItHint::CreateInsertion(ParenInsertionLoc, "()"); - ExprResult NewBase = ActOnCallExpr(0, BaseExpr, ParenInsertionLoc, + ExprResult NewBase = ActOnCallExpr(0, BaseExpr.take(), ParenInsertionLoc, MultiExprArg(*this, 0, 0), ParenInsertionLoc); if (NewBase.isInvalid()) return ExprError(); - BaseExpr = NewBase.takeAs<Expr>(); - DefaultFunctionArrayConversion(BaseExpr); + BaseExpr = NewBase; + BaseExpr = DefaultFunctionArrayConversion(BaseExpr.take()); return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS, ObjCImpDecl, HasTemplateArgs); } Diag(MemberLoc, diag::err_typecheck_member_reference_struct_union) - << BaseType << BaseExpr->getSourceRange(); + << BaseType << BaseExpr.get()->getSourceRange(); return ExprError(); } @@ -4167,8 +4554,12 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base, NameInfo, TemplateArgs); } else { LookupResult R(*this, NameInfo, LookupMemberName); - Result = LookupMemberExpr(R, Base, IsArrow, OpLoc, + 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); @@ -4313,6 +4704,13 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, << NumArgsInProto << NumArgs << Fn->getSourceRange() << SourceRange(Args[NumArgsInProto]->getLocStart(), Args[NumArgs-1]->getLocEnd()); + + // Emit the location of the prototype. + if (FDecl && !FDecl->getBuiltinID()) + Diag(FDecl->getLocStart(), + diag::note_typecheck_call_too_many_args) + << FDecl; + // This deletes the extra arguments. Call->setNumArgs(Context, NumArgsInProto); return true; @@ -4394,16 +4792,37 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, // If this is a variadic call, handle args passed through "...". if (CallType != VariadicDoesNotApply) { - // Promote the arguments (C99 6.5.2.2p7). - for (unsigned i = ArgIx; i != NumArgs; ++i) { - Expr *Arg = Args[i]; - Invalid |= DefaultVariadicArgumentPromotion(Arg, CallType, FDecl); - AllArgs.push_back(Arg); + + // 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<ExplicitCastExpr>(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()); + } } } return Invalid; } +/// 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. @@ -4464,94 +4883,39 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, return Owned(BuildCallToObjectOfClassType(S, Fn, LParenLoc, Args, NumArgs, RParenLoc)); - Expr *NakedFn = Fn->IgnoreParens(); - - // Determine whether this is a call to an unresolved member function. - if (UnresolvedMemberExpr *MemE = dyn_cast<UnresolvedMemberExpr>(NakedFn)) { - // If lookup was unresolved but not dependent (i.e. didn't find - // an unresolved using declaration), it has to be an overloaded - // function set, which means it must contain either multiple - // declarations (all methods or method templates) or a single - // method template. - assert((MemE->getNumDecls() > 1) || - isa<FunctionTemplateDecl>( - (*MemE->decls_begin())->getUnderlyingDecl())); - (void)MemE; + 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); } + } - // Determine whether this is a call to a member function. - if (MemberExpr *MemExpr = dyn_cast<MemberExpr>(NakedFn)) { - NamedDecl *MemDecl = MemExpr->getMemberDecl(); - if (isa<CXXMethodDecl>(MemDecl)) + // 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 if there's an '&' involved. + if (!find.IsAddressOfOperand) { + OverloadExpr *ovl = find.Expression; + if (isa<UnresolvedLookupExpr>(ovl)) { + UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(ovl); + return BuildOverloadedCallExpr(S, Fn, ULE, LParenLoc, Args, NumArgs, + RParenLoc, ExecConfig); + } else { return BuildCallToMemberFunction(S, Fn, LParenLoc, Args, NumArgs, RParenLoc); - } - - // Determine whether this is a call to a pointer-to-member function. - if (BinaryOperator *BO = dyn_cast<BinaryOperator>(NakedFn)) { - if (BO->getOpcode() == BO_PtrMemD || - BO->getOpcode() == BO_PtrMemI) { - if (const FunctionProtoType *FPT - = BO->getType()->getAs<FunctionProtoType>()) { - QualType ResultTy = FPT->getCallResultType(Context); - ExprValueKind VK = Expr::getValueKindForType(FPT->getResultType()); - - // Check that the object type isn't more qualified than the - // member function we're calling. - Qualifiers FuncQuals = Qualifiers::fromCVRMask(FPT->getTypeQuals()); - Qualifiers ObjectQuals - = BO->getOpcode() == BO_PtrMemD - ? BO->getLHS()->getType().getQualifiers() - : BO->getLHS()->getType()->getAs<PointerType>() - ->getPointeeType().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) - << BO->getType().getUnqualifiedType() - << QualsString - << (QualsString.find(' ') == std::string::npos? 1 : 2); - } - - CXXMemberCallExpr *TheCall - = new (Context) CXXMemberCallExpr(Context, Fn, Args, - NumArgs, ResultTy, VK, - RParenLoc); - - if (CheckCallReturnType(FPT->getResultType(), - BO->getRHS()->getSourceRange().getBegin(), - TheCall, 0)) - return ExprError(); - - if (ConvertArgumentsForCall(TheCall, BO, 0, FPT, Args, NumArgs, - RParenLoc)) - return ExprError(); - - return MaybeBindToTemporary(TheCall); - } - return ExprError(Diag(Fn->getLocStart(), - diag::err_typecheck_call_not_function) - << Fn->getType() << Fn->getSourceRange()); } } } // If we're directly calling a function, get the appropriate declaration. - // Also, in C++, keep track of whether we should perform argument-dependent - // lookup and whether there were any explicitly-specified template arguments. Expr *NakedFn = Fn->IgnoreParens(); - if (isa<UnresolvedLookupExpr>(NakedFn)) { - UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(NakedFn); - return BuildOverloadedCallExpr(S, Fn, ULE, LParenLoc, Args, NumArgs, - RParenLoc, ExecConfig); - } NamedDecl *NDecl = 0; if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(NakedFn)) @@ -4560,6 +4924,8 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, if (isa<DeclRefExpr>(NakedFn)) NDecl = cast<DeclRefExpr>(NakedFn)->getDecl(); + else if (isa<MemberExpr>(NakedFn)) + NDecl = cast<MemberExpr>(NakedFn)->getMemberDecl(); return BuildResolvedCallExpr(Fn, NDecl, LParenLoc, Args, NumArgs, RParenLoc, ExecConfig); @@ -4595,7 +4961,10 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, FunctionDecl *FDecl = dyn_cast_or_null<FunctionDecl>(NDecl); // Promote the function operand. - UsualUnaryConversions(Fn); + 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. @@ -4621,6 +4990,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, if (BuiltinID && Context.BuiltinInfo.hasCustomTypechecking(BuiltinID)) return CheckBuiltinFunctionCall(BuiltinID, TheCall); + retry: const FunctionType *FuncT; if (const PointerType *PT = Fn->getType()->getAs<PointerType>()) { // C99 6.5.2.2p1 - "The expression that denotes the called function shall @@ -4633,6 +5003,15 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, Fn->getType()->getAs<BlockPointerType>()) { FuncT = BPT->getPointeeType()->castAs<FunctionType>(); } 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()); } @@ -4703,7 +5082,12 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, Arg = ArgE.takeAs<Expr>(); } else { - DefaultArgumentPromotion(Arg); + ExprResult ArgE = DefaultArgumentPromotion(Arg); + + if (ArgE.isInvalid()) + return true; + + Arg = ArgE.takeAs<Expr>(); } if (RequireCompleteType(Arg->getSourceRange().getBegin(), @@ -4819,12 +5203,12 @@ Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg initlist, /// Prepares for a scalar cast, performing all the necessary stages /// except the final cast and returning the kind required. -static CastKind PrepareScalarCast(Sema &S, Expr *&Src, QualType DestTy) { +static CastKind PrepareScalarCast(Sema &S, 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->getType(); + QualType SrcTy = Src.get()->getType(); if (S.Context.hasSameUnqualifiedType(SrcTy, DestTy)) return CK_NoOp; @@ -4854,7 +5238,7 @@ static CastKind PrepareScalarCast(Sema &S, Expr *&Src, QualType DestTy) { case Type::STK_Integral: switch (DestTy->getScalarTypeKind()) { case Type::STK_Pointer: - if (Src->isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNull)) + if (Src.get()->isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNull)) return CK_NullToPointer; return CK_IntegralToPointer; case Type::STK_Bool: @@ -4864,12 +5248,12 @@ static CastKind PrepareScalarCast(Sema &S, Expr *&Src, QualType DestTy) { case Type::STK_Floating: return CK_IntegralToFloating; case Type::STK_IntegralComplex: - S.ImpCastExprToType(Src, DestTy->getAs<ComplexType>()->getElementType(), - CK_IntegralCast); + Src = S.ImpCastExprToType(Src.take(), DestTy->getAs<ComplexType>()->getElementType(), + CK_IntegralCast); return CK_IntegralRealToComplex; case Type::STK_FloatingComplex: - S.ImpCastExprToType(Src, DestTy->getAs<ComplexType>()->getElementType(), - CK_IntegralToFloating); + Src = S.ImpCastExprToType(Src.take(), DestTy->getAs<ComplexType>()->getElementType(), + CK_IntegralToFloating); return CK_FloatingRealToComplex; case Type::STK_MemberPointer: llvm_unreachable("member pointer type in C"); @@ -4885,12 +5269,12 @@ static CastKind PrepareScalarCast(Sema &S, Expr *&Src, QualType DestTy) { case Type::STK_Integral: return CK_FloatingToIntegral; case Type::STK_FloatingComplex: - S.ImpCastExprToType(Src, DestTy->getAs<ComplexType>()->getElementType(), - CK_FloatingCast); + Src = S.ImpCastExprToType(Src.take(), DestTy->getAs<ComplexType>()->getElementType(), + CK_FloatingCast); return CK_FloatingRealToComplex; case Type::STK_IntegralComplex: - S.ImpCastExprToType(Src, DestTy->getAs<ComplexType>()->getElementType(), - CK_FloatingToIntegral); + Src = S.ImpCastExprToType(Src.take(), DestTy->getAs<ComplexType>()->getElementType(), + CK_FloatingToIntegral); return CK_IntegralRealToComplex; case Type::STK_Pointer: llvm_unreachable("valid float->pointer cast?"); @@ -4909,14 +5293,14 @@ static CastKind PrepareScalarCast(Sema &S, Expr *&Src, QualType DestTy) { QualType ET = SrcTy->getAs<ComplexType>()->getElementType(); if (S.Context.hasSameType(ET, DestTy)) return CK_FloatingComplexToReal; - S.ImpCastExprToType(Src, ET, CK_FloatingComplexToReal); + Src = S.ImpCastExprToType(Src.take(), ET, CK_FloatingComplexToReal); return CK_FloatingCast; } case Type::STK_Bool: return CK_FloatingComplexToBoolean; case Type::STK_Integral: - S.ImpCastExprToType(Src, SrcTy->getAs<ComplexType>()->getElementType(), - CK_FloatingComplexToReal); + Src = S.ImpCastExprToType(Src.take(), SrcTy->getAs<ComplexType>()->getElementType(), + CK_FloatingComplexToReal); return CK_FloatingToIntegral; case Type::STK_Pointer: llvm_unreachable("valid complex float->pointer cast?"); @@ -4935,14 +5319,14 @@ static CastKind PrepareScalarCast(Sema &S, Expr *&Src, QualType DestTy) { QualType ET = SrcTy->getAs<ComplexType>()->getElementType(); if (S.Context.hasSameType(ET, DestTy)) return CK_IntegralComplexToReal; - S.ImpCastExprToType(Src, ET, CK_IntegralComplexToReal); + Src = S.ImpCastExprToType(Src.take(), ET, CK_IntegralComplexToReal); return CK_IntegralCast; } case Type::STK_Bool: return CK_IntegralComplexToBoolean; case Type::STK_Floating: - S.ImpCastExprToType(Src, SrcTy->getAs<ComplexType>()->getElementType(), - CK_IntegralComplexToReal); + Src = S.ImpCastExprToType(Src.take(), SrcTy->getAs<ComplexType>()->getElementType(), + CK_IntegralComplexToReal); return CK_IntegralToFloating; case Type::STK_Pointer: llvm_unreachable("valid complex int->pointer cast?"); @@ -4957,15 +5341,20 @@ static CastKind PrepareScalarCast(Sema &S, Expr *&Src, QualType DestTy) { } /// CheckCastTypes - Check type constraints for casting between types. -bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, - Expr *&castExpr, CastKind& Kind, ExprValueKind &VK, - CXXCastPath &BasePath, bool FunctionalStyle) { +ExprResult Sema::CheckCastTypes(SourceRange TyR, QualType castType, + Expr *castExpr, CastKind& Kind, ExprValueKind &VK, + CXXCastPath &BasePath, bool FunctionalStyle) { + if (castExpr->getType() == Context.UnknownAnyTy) + return checkUnknownAnyCast(TyR, castType, castExpr, Kind, VK, BasePath); + if (getLangOptions().CPlusPlus) return CXXCheckCStyleCast(SourceRange(TyR.getBegin(), castExpr->getLocEnd()), castType, VK, castExpr, Kind, BasePath, FunctionalStyle); + assert(!castExpr->getType()->isPlaceholderType()); + // We only support r-value casts in C. VK = VK_RValue; @@ -4973,18 +5362,24 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, // type needs to be scalar. if (castType->isVoidType()) { // We don't necessarily do lvalue-to-rvalue conversions on this. - IgnoredValueConversions(castExpr); + ExprResult castExprRes = IgnoredValueConversions(castExpr); + if (castExprRes.isInvalid()) + return ExprError(); + castExpr = castExprRes.take(); // Cast to void allows any expr type. Kind = CK_ToVoid; - return false; + return Owned(castExpr); } - DefaultFunctionArrayLvalueConversion(castExpr); + ExprResult castExprRes = DefaultFunctionArrayLvalueConversion(castExpr); + if (castExprRes.isInvalid()) + return ExprError(); + castExpr = castExprRes.take(); if (RequireCompleteType(TyR.getBegin(), castType, diag::err_typecheck_cast_to_incomplete)) - return true; + return ExprError(); if (!castType->isScalarType() && !castType->isVectorType()) { if (Context.hasSameUnqualifiedType(castType, castExpr->getType()) && @@ -4994,7 +5389,7 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Diag(TyR.getBegin(), diag::ext_typecheck_cast_nonscalar) << castType << castExpr->getSourceRange(); Kind = CK_NoOp; - return false; + return Owned(castExpr); } if (castType->isUnionType()) { @@ -5011,16 +5406,19 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, break; } } - if (Field == FieldEnd) - return Diag(TyR.getBegin(), diag::err_typecheck_cast_to_union_no_type) + if (Field == FieldEnd) { + Diag(TyR.getBegin(), diag::err_typecheck_cast_to_union_no_type) << castExpr->getType() << castExpr->getSourceRange(); + return ExprError(); + } Kind = CK_ToUnion; - return false; + return Owned(castExpr); } // Reject any other conversions to non-scalar types. - return Diag(TyR.getBegin(), diag::err_typecheck_cond_expect_scalar) + Diag(TyR.getBegin(), diag::err_typecheck_cond_expect_scalar) << castType << castExpr->getSourceRange(); + return ExprError(); } // The type we're casting to is known to be a scalar or vector. @@ -5028,49 +5426,73 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, // Require the operand to be a scalar or vector. if (!castExpr->getType()->isScalarType() && !castExpr->getType()->isVectorType()) { - return Diag(castExpr->getLocStart(), + Diag(castExpr->getLocStart(), diag::err_typecheck_expect_scalar_operand) << castExpr->getType() << castExpr->getSourceRange(); + return ExprError(); } if (castType->isExtVectorType()) return CheckExtVectorCast(TyR, castType, castExpr, Kind); - if (castType->isVectorType()) - return CheckVectorCast(TyR, castType, castExpr->getType(), Kind); - if (castExpr->getType()->isVectorType()) - return CheckVectorCast(TyR, castExpr->getType(), castType, Kind); + if (castType->isVectorType()) { + if (castType->getAs<VectorType>()->getVectorKind() == + VectorType::AltiVecVector && + (castExpr->getType()->isIntegerType() || + castExpr->getType()->isFloatingType())) { + Kind = CK_VectorSplat; + return Owned(castExpr); + } else if (CheckVectorCast(TyR, castType, castExpr->getType(), Kind)) { + return ExprError(); + } else + return Owned(castExpr); + } + if (castExpr->getType()->isVectorType()) { + if (CheckVectorCast(TyR, castExpr->getType(), castType, Kind)) + return ExprError(); + else + return Owned(castExpr); + } // 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<ObjCSelectorExpr>(castExpr)) - return Diag(castExpr->getLocStart(), diag::err_cast_selector_expr); + if (isa<ObjCSelectorExpr>(castExpr)) { + Diag(castExpr->getLocStart(), diag::err_cast_selector_expr); + return ExprError(); + } // If either type is a pointer, the other type has to be either an // integer or a pointer. if (!castType->isArithmeticType()) { QualType castExprType = castExpr->getType(); if (!castExprType->isIntegralType(Context) && - castExprType->isArithmeticType()) - return Diag(castExpr->getLocStart(), - diag::err_cast_pointer_from_non_pointer_int) + castExprType->isArithmeticType()) { + Diag(castExpr->getLocStart(), + diag::err_cast_pointer_from_non_pointer_int) << castExprType << castExpr->getSourceRange(); + return ExprError(); + } } else if (!castExpr->getType()->isArithmeticType()) { - if (!castType->isIntegralType(Context) && castType->isArithmeticType()) - return Diag(castExpr->getLocStart(), - diag::err_cast_pointer_to_non_pointer_int) + if (!castType->isIntegralType(Context) && castType->isArithmeticType()) { + Diag(castExpr->getLocStart(), diag::err_cast_pointer_to_non_pointer_int) << castType << castExpr->getSourceRange(); + return ExprError(); + } } - Kind = PrepareScalarCast(*this, castExpr, castType); + castExprRes = Owned(castExpr); + Kind = PrepareScalarCast(*this, castExprRes, castType); + if (castExprRes.isInvalid()) + return ExprError(); + castExpr = castExprRes.take(); if (Kind == CK_BitCast) CheckCastAlign(castExpr, castType, TyR); - return false; + return Owned(castExpr); } bool Sema::CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty, @@ -5093,8 +5515,8 @@ bool Sema::CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty, return false; } -bool Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, Expr *&CastExpr, - CastKind &Kind) { +ExprResult Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, + Expr *CastExpr, CastKind &Kind) { assert(DestTy->isExtVectorType() && "Not an extended vector type!"); QualType SrcTy = CastExpr->getType(); @@ -5102,11 +5524,13 @@ bool Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, Expr *&CastExpr, // If SrcTy is a VectorType, the total size must match to explicitly cast to // an ExtVectorType. if (SrcTy->isVectorType()) { - if (Context.getTypeSize(DestTy) != Context.getTypeSize(SrcTy)) - return Diag(R.getBegin(),diag::err_invalid_conversion_between_ext_vectors) + if (Context.getTypeSize(DestTy) != Context.getTypeSize(SrcTy)) { + Diag(R.getBegin(),diag::err_invalid_conversion_between_ext_vectors) << DestTy << SrcTy << R; + return ExprError(); + } Kind = CK_BitCast; - return false; + return Owned(CastExpr); } // All non-pointer scalars can be cast to ExtVector type. The appropriate @@ -5118,11 +5542,14 @@ bool Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, Expr *&CastExpr, << DestTy << SrcTy << R; QualType DestElemTy = DestTy->getAs<ExtVectorType>()->getElementType(); - ImpCastExprToType(CastExpr, DestElemTy, - PrepareScalarCast(*this, CastExpr, DestElemTy)); + ExprResult CastExprRes = Owned(CastExpr); + CastKind CK = PrepareScalarCast(*this, CastExprRes, DestElemTy); + if (CastExprRes.isInvalid()) + return ExprError(); + CastExpr = ImpCastExprToType(CastExprRes.take(), DestElemTy, CK).take(); Kind = CK_VectorSplat; - return false; + return Owned(CastExpr); } ExprResult @@ -5150,12 +5577,15 @@ Sema::BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty, CastKind Kind = CK_Invalid; ExprValueKind VK = VK_RValue; CXXCastPath BasePath; - if (CheckCastTypes(SourceRange(LParenLoc, RParenLoc), Ty->getType(), castExpr, - Kind, VK, BasePath)) + ExprResult CastResult = + CheckCastTypes(SourceRange(LParenLoc, RParenLoc), Ty->getType(), castExpr, + Kind, VK, BasePath); + if (CastResult.isInvalid()) return ExprError(); + castExpr = CastResult.take(); return Owned(CStyleCastExpr::Create(Context, - Ty->getType().getNonLValueExprType(Context), + Ty->getType().getNonLValueExprType(Context), VK, Kind, castExpr, &BasePath, Ty, LParenLoc, RParenLoc)); } @@ -5185,9 +5615,9 @@ Sema::ActOnCastOfParenListExpr(Scope *S, SourceLocation LParenLoc, TypeSourceInfo *TInfo) { ParenListExpr *PE = cast<ParenListExpr>(Op); QualType Ty = TInfo->getType(); - bool isAltiVecLiteral = false; + bool isVectorLiteral = false; - // Check for an altivec literal, + // Check for an altivec or OpenCL literal, // i.e. all the elements are integer constants. if (getLangOptions().AltiVec && Ty->isVectorType()) { if (PE->getNumExprs() == 0) { @@ -5196,18 +5626,45 @@ Sema::ActOnCastOfParenListExpr(Scope *S, SourceLocation LParenLoc, } if (PE->getNumExprs() == 1) { if (!PE->getExpr(0)->getType()->isVectorType()) - isAltiVecLiteral = true; + isVectorLiteral = true; } else - isAltiVecLiteral = true; + isVectorLiteral = true; } - // If this is an altivec initializer, '(' type ')' '(' init, ..., init ')' + // If this is a vector initializer, '(' type ')' '(' init, ..., init ')' // then handle it as such. - if (isAltiVecLiteral) { + if (isVectorLiteral) { llvm::SmallVector<Expr *, 8> initExprs; - for (unsigned i = 0, e = PE->getNumExprs(); i != e; ++i) - initExprs.push_back(PE->getExpr(i)); + // '(...)' 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 (Ty->getAs<VectorType>()->getVectorKind() == + VectorType::AltiVecVector) { + unsigned numElems = Ty->getAs<VectorType>()->getNumElements(); + // 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 (PE->getNumExprs() == 1) { + QualType ElemTy = Ty->getAs<VectorType>()->getElementType(); + ExprResult Literal = Owned(PE->getExpr(0)); + Literal = ImpCastExprToType(Literal.take(), ElemTy, + PrepareScalarCast(*this, Literal, ElemTy)); + return BuildCStyleCastExpr(LParenLoc, TInfo, RParenLoc, Literal.take()); + } + else if (PE->getNumExprs() < numElems) { + Diag(PE->getExprLoc(), + diag::err_incorrect_number_of_vector_initializers); + return ExprError(); + } + else + for (unsigned i = 0, e = PE->getNumExprs(); i != e; ++i) + initExprs.push_back(PE->getExpr(i)); + } + else + for (unsigned i = 0, e = PE->getNumExprs(); i != e; ++i) + initExprs.push_back(PE->getExpr(i)); // FIXME: This means that pretty-printing the final AST will produce curly // braces instead of the original commas. @@ -5265,11 +5722,8 @@ bool Sema::DiagnoseConditionalForNull(Expr *LHS, Expr *RHS, // In this case, check to make sure that we got here from a "NULL" // string in the source code. NullExpr = NullExpr->IgnoreParenImpCasts(); - SourceManager& SM = Context.getSourceManager(); - SourceLocation Loc = SM.getInstantiationLoc(NullExpr->getExprLoc()); - unsigned Len = - Lexer::MeasureTokenLength(Loc, SM, Context.getLangOptions()); - if (Len != 4 || memcmp(SM.getCharacterData(Loc), "NULL", 4)) + SourceLocation loc = NullExpr->getExprLoc(); + if (!findMacroSpelling(loc, "NULL")) return false; } @@ -5283,23 +5737,17 @@ bool Sema::DiagnoseConditionalForNull(Expr *LHS, Expr *RHS, /// 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(Expr *&Cond, Expr *&LHS, Expr *&RHS, +QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, ExprResult &RHS, ExprValueKind &VK, ExprObjectKind &OK, SourceLocation QuestionLoc) { - // If both LHS and RHS are overloaded functions, try to resolve them. - if (Context.hasSameType(LHS->getType(), RHS->getType()) && - LHS->getType()->isSpecificBuiltinType(BuiltinType::Overload)) { - ExprResult LHSResult = CheckPlaceholderExpr(LHS, QuestionLoc); - if (LHSResult.isInvalid()) - return QualType(); - ExprResult RHSResult = CheckPlaceholderExpr(RHS, QuestionLoc); - if (RHSResult.isInvalid()) - return QualType(); + ExprResult lhsResult = CheckPlaceholderExpr(LHS.get()); + if (!lhsResult.isUsable()) return QualType(); + LHS = move(lhsResult); - LHS = LHSResult.take(); - RHS = RHSResult.take(); - } + ExprResult rhsResult = CheckPlaceholderExpr(RHS.get()); + if (!rhsResult.isUsable()) return QualType(); + RHS = move(rhsResult); // C++ is sufficiently different to merit its own checker. if (getLangOptions().CPlusPlus) @@ -5308,12 +5756,19 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, VK = VK_RValue; OK = OK_Ordinary; - UsualUnaryConversions(Cond); - UsualUnaryConversions(LHS); - UsualUnaryConversions(RHS); - QualType CondTy = Cond->getType(); - QualType LHSTy = LHS->getType(); - QualType RHSTy = RHS->getType(); + 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 (!CondTy->isScalarType()) { // C99 6.5.15p2 @@ -5321,14 +5776,14 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, // Throw an error if its not either. if (getLangOptions().OpenCL) { if (!CondTy->isVectorType()) { - Diag(Cond->getLocStart(), + Diag(Cond.get()->getLocStart(), diag::err_typecheck_cond_expect_scalar_or_vector) << CondTy; return QualType(); } } else { - Diag(Cond->getLocStart(), diag::err_typecheck_cond_expect_scalar) + Diag(Cond.get()->getLocStart(), diag::err_typecheck_cond_expect_scalar) << CondTy; return QualType(); } @@ -5344,25 +5799,27 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, if (getLangOptions().OpenCL && CondTy->isVectorType()) { // Both operands should be of scalar type. if (!LHSTy->isScalarType()) { - Diag(LHS->getLocStart(), diag::err_typecheck_cond_expect_scalar) + Diag(LHS.get()->getLocStart(), diag::err_typecheck_cond_expect_scalar) << CondTy; return QualType(); } if (!RHSTy->isScalarType()) { - Diag(RHS->getLocStart(), diag::err_typecheck_cond_expect_scalar) + Diag(RHS.get()->getLocStart(), diag::err_typecheck_cond_expect_scalar) << CondTy; return QualType(); } // Implicity convert these scalars to the type of the condition. - ImpCastExprToType(LHS, CondTy, CK_IntegralCast); - ImpCastExprToType(RHS, CondTy, CK_IntegralCast); + LHS = ImpCastExprToType(LHS.take(), CondTy, CK_IntegralCast); + RHS = ImpCastExprToType(RHS.take(), CondTy, CK_IntegralCast); } // 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); - return LHS->getType(); + 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 @@ -5380,32 +5837,34 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, // The following || allows only one side to be void (a GCC-ism). if (LHSTy->isVoidType() || RHSTy->isVoidType()) { if (!LHSTy->isVoidType()) - Diag(RHS->getLocStart(), diag::ext_typecheck_cond_one_void) - << RHS->getSourceRange(); + Diag(RHS.get()->getLocStart(), diag::ext_typecheck_cond_one_void) + << RHS.get()->getSourceRange(); if (!RHSTy->isVoidType()) - Diag(LHS->getLocStart(), diag::ext_typecheck_cond_one_void) - << LHS->getSourceRange(); - ImpCastExprToType(LHS, Context.VoidTy, CK_ToVoid); - ImpCastExprToType(RHS, Context.VoidTy, CK_ToVoid); + Diag(LHS.get()->getLocStart(), diag::ext_typecheck_cond_one_void) + << LHS.get()->getSourceRange(); + LHS = ImpCastExprToType(LHS.take(), Context.VoidTy, CK_ToVoid); + RHS = ImpCastExprToType(RHS.take(), Context.VoidTy, CK_ToVoid); return Context.VoidTy; } // C99 6.5.15p6 - "if one operand is a null pointer constant, the result has // the type of the other operand." if ((LHSTy->isAnyPointerType() || LHSTy->isBlockPointerType()) && - RHS->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { + RHS.get()->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { // promote the null to a pointer. - ImpCastExprToType(RHS, LHSTy, CK_NullToPointer); + RHS = ImpCastExprToType(RHS.take(), LHSTy, CK_NullToPointer); return LHSTy; } if ((RHSTy->isAnyPointerType() || RHSTy->isBlockPointerType()) && - LHS->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { - ImpCastExprToType(LHS, RHSTy, CK_NullToPointer); + LHS.get()->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { + LHS = ImpCastExprToType(LHS.take(), RHSTy, CK_NullToPointer); 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; @@ -5415,12 +5874,12 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, if (!LHSTy->isBlockPointerType() || !RHSTy->isBlockPointerType()) { if (LHSTy->isVoidPointerType() || RHSTy->isVoidPointerType()) { QualType destType = Context.getPointerType(Context.VoidTy); - ImpCastExprToType(LHS, destType, CK_BitCast); - ImpCastExprToType(RHS, destType, CK_BitCast); + LHS = ImpCastExprToType(LHS.take(), destType, CK_BitCast); + RHS = ImpCastExprToType(RHS.take(), destType, CK_BitCast); return destType; } Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands) - << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange(); + << LHSTy << RHSTy << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); return QualType(); } // We have 2 block pointer types. @@ -5435,18 +5894,18 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, if (!Context.typesAreCompatible(lhptee.getUnqualifiedType(), rhptee.getUnqualifiedType())) { Diag(QuestionLoc, diag::warn_typecheck_cond_incompatible_pointers) - << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange(); + << 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 = Context.getPointerType(Context.VoidTy); - ImpCastExprToType(LHS, incompatTy, CK_BitCast); - ImpCastExprToType(RHS, incompatTy, CK_BitCast); + LHS = ImpCastExprToType(LHS.take(), incompatTy, CK_BitCast); + RHS = ImpCastExprToType(RHS.take(), incompatTy, CK_BitCast); return incompatTy; } // The block pointer types are compatible. - ImpCastExprToType(LHS, LHSTy, CK_BitCast); - ImpCastExprToType(RHS, LHSTy, CK_BitCast); + LHS = ImpCastExprToType(LHS.take(), LHSTy, CK_BitCast); + RHS = ImpCastExprToType(RHS.take(), LHSTy, CK_BitCast); return LHSTy; } @@ -5463,9 +5922,9 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, = Context.getQualifiedType(lhptee, rhptee.getQualifiers()); QualType destType = Context.getPointerType(destPointee); // Add qualifiers if necessary. - ImpCastExprToType(LHS, destType, CK_NoOp); + LHS = ImpCastExprToType(LHS.take(), destType, CK_NoOp); // Promote to void*. - ImpCastExprToType(RHS, destType, CK_BitCast); + RHS = ImpCastExprToType(RHS.take(), destType, CK_BitCast); return destType; } if (rhptee->isVoidType() && lhptee->isIncompleteOrObjectType()) { @@ -5473,9 +5932,9 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, = Context.getQualifiedType(rhptee, lhptee.getQualifiers()); QualType destType = Context.getPointerType(destPointee); // Add qualifiers if necessary. - ImpCastExprToType(RHS, destType, CK_NoOp); + RHS = ImpCastExprToType(RHS.take(), destType, CK_NoOp); // Promote to void*. - ImpCastExprToType(LHS, destType, CK_BitCast); + LHS = ImpCastExprToType(LHS.take(), destType, CK_BitCast); return destType; } @@ -5486,13 +5945,13 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, if (!Context.typesAreCompatible(lhptee.getUnqualifiedType(), rhptee.getUnqualifiedType())) { Diag(QuestionLoc, diag::warn_typecheck_cond_incompatible_pointers) - << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange(); + << 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 = Context.getPointerType(Context.VoidTy); - ImpCastExprToType(LHS, incompatTy, CK_BitCast); - ImpCastExprToType(RHS, incompatTy, CK_BitCast); + LHS = ImpCastExprToType(LHS.take(), incompatTy, CK_BitCast); + RHS = ImpCastExprToType(RHS.take(), incompatTy, CK_BitCast); return incompatTy; } // The pointer types are compatible. @@ -5502,8 +5961,8 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, // type. // FIXME: Need to calculate the composite type. // FIXME: Need to add qualifiers - ImpCastExprToType(LHS, LHSTy, CK_BitCast); - ImpCastExprToType(RHS, LHSTy, CK_BitCast); + LHS = ImpCastExprToType(LHS.take(), LHSTy, CK_BitCast); + RHS = ImpCastExprToType(RHS.take(), LHSTy, CK_BitCast); return LHSTy; } @@ -5511,69 +5970,69 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, // null pointers have been filtered out by this point. if (RHSTy->isPointerType() && LHSTy->isIntegerType()) { Diag(QuestionLoc, diag::warn_typecheck_cond_pointer_integer_mismatch) - << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange(); - ImpCastExprToType(LHS, RHSTy, CK_IntegralToPointer); + << LHSTy << RHSTy << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + LHS = ImpCastExprToType(LHS.take(), RHSTy, CK_IntegralToPointer); return RHSTy; } if (LHSTy->isPointerType() && RHSTy->isIntegerType()) { Diag(QuestionLoc, diag::warn_typecheck_cond_pointer_integer_mismatch) - << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange(); - ImpCastExprToType(RHS, LHSTy, CK_IntegralToPointer); + << LHSTy << RHSTy << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + RHS = ImpCastExprToType(RHS.take(), LHSTy, CK_IntegralToPointer); 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, RHS, QuestionLoc)) + 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->getSourceRange() << RHS->getSourceRange(); + << 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(Expr *&LHS, Expr *&RHS, +QualType Sema::FindCompositeObjCPointerType(ExprResult &LHS, ExprResult &RHS, SourceLocation QuestionLoc) { - QualType LHSTy = LHS->getType(); - QualType RHSTy = RHS->getType(); + 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.ObjCClassRedefinitionType))) { - ImpCastExprToType(RHS, LHSTy, CK_BitCast); + RHS = ImpCastExprToType(RHS.take(), LHSTy, CK_BitCast); return LHSTy; } if (RHSTy->isObjCClassType() && (Context.hasSameType(LHSTy, Context.ObjCClassRedefinitionType))) { - ImpCastExprToType(LHS, RHSTy, CK_BitCast); + LHS = ImpCastExprToType(LHS.take(), RHSTy, CK_BitCast); return RHSTy; } // And the same for struct objc_object* / id if (LHSTy->isObjCIdType() && (Context.hasSameType(RHSTy, Context.ObjCIdRedefinitionType))) { - ImpCastExprToType(RHS, LHSTy, CK_BitCast); + RHS = ImpCastExprToType(RHS.take(), LHSTy, CK_BitCast); return LHSTy; } if (RHSTy->isObjCIdType() && (Context.hasSameType(LHSTy, Context.ObjCIdRedefinitionType))) { - ImpCastExprToType(LHS, RHSTy, CK_BitCast); + LHS = ImpCastExprToType(LHS.take(), RHSTy, CK_BitCast); return RHSTy; } // And the same for struct objc_selector* / SEL if (Context.isObjCSelType(LHSTy) && (Context.hasSameType(RHSTy, Context.ObjCSelRedefinitionType))) { - ImpCastExprToType(RHS, LHSTy, CK_BitCast); + RHS = ImpCastExprToType(RHS.take(), LHSTy, CK_BitCast); return LHSTy; } if (Context.isObjCSelType(RHSTy) && (Context.hasSameType(LHSTy, Context.ObjCSelRedefinitionType))) { - ImpCastExprToType(LHS, RHSTy, CK_BitCast); + LHS = ImpCastExprToType(LHS.take(), RHSTy, CK_BitCast); return RHSTy; } // Check constraints for Objective-C object pointers types. @@ -5620,15 +6079,15 @@ QualType Sema::FindCompositeObjCPointerType(Expr *&LHS, Expr *&RHS, else { Diag(QuestionLoc, diag::ext_typecheck_cond_incompatible_operands) << LHSTy << RHSTy - << LHS->getSourceRange() << RHS->getSourceRange(); + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); QualType incompatTy = Context.getObjCIdType(); - ImpCastExprToType(LHS, incompatTy, CK_BitCast); - ImpCastExprToType(RHS, incompatTy, CK_BitCast); + LHS = ImpCastExprToType(LHS.take(), incompatTy, CK_BitCast); + RHS = ImpCastExprToType(RHS.take(), incompatTy, CK_BitCast); return incompatTy; } // The object pointer types are compatible. - ImpCastExprToType(LHS, compositeType, CK_BitCast); - ImpCastExprToType(RHS, compositeType, CK_BitCast); + LHS = ImpCastExprToType(LHS.take(), compositeType, CK_BitCast); + RHS = ImpCastExprToType(RHS.take(), compositeType, CK_BitCast); return compositeType; } // Check Objective-C object pointer types and 'void *' @@ -5639,9 +6098,9 @@ QualType Sema::FindCompositeObjCPointerType(Expr *&LHS, Expr *&RHS, = Context.getQualifiedType(lhptee, rhptee.getQualifiers()); QualType destType = Context.getPointerType(destPointee); // Add qualifiers if necessary. - ImpCastExprToType(LHS, destType, CK_NoOp); + LHS = ImpCastExprToType(LHS.take(), destType, CK_NoOp); // Promote to void*. - ImpCastExprToType(RHS, destType, CK_BitCast); + RHS = ImpCastExprToType(RHS.take(), destType, CK_BitCast); return destType; } if (LHSTy->isObjCObjectPointerType() && RHSTy->isVoidPointerType()) { @@ -5651,9 +6110,9 @@ QualType Sema::FindCompositeObjCPointerType(Expr *&LHS, Expr *&RHS, = Context.getQualifiedType(rhptee, lhptee.getQualifiers()); QualType destType = Context.getPointerType(destPointee); // Add qualifiers if necessary. - ImpCastExprToType(RHS, destType, CK_NoOp); + RHS = ImpCastExprToType(RHS.take(), destType, CK_NoOp); // Promote to void*. - ImpCastExprToType(LHS, destType, CK_BitCast); + LHS = ImpCastExprToType(LHS.take(), destType, CK_BitCast); return destType; } return QualType(); @@ -5681,7 +6140,10 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc, && commonExpr->isOrdinaryOrBitFieldObject() && RHSExpr->isOrdinaryOrBitFieldObject() && Context.hasSameType(commonExpr->getType(), RHSExpr->getType()))) { - UsualUnaryConversions(commonExpr); + ExprResult commonRes = UsualUnaryConversions(commonExpr); + if (commonRes.isInvalid()) + return ExprError(); + commonExpr = commonRes.take(); } opaqueValue = new (Context) OpaqueValueExpr(commonExpr->getExprLoc(), @@ -5693,19 +6155,21 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc, ExprValueKind VK = VK_RValue; ExprObjectKind OK = OK_Ordinary; - QualType result = CheckConditionalOperands(CondExpr, LHSExpr, RHSExpr, + ExprResult Cond = Owned(CondExpr), LHS = Owned(LHSExpr), RHS = Owned(RHSExpr); + QualType result = CheckConditionalOperands(Cond, LHS, RHS, VK, OK, QuestionLoc); - if (result.isNull()) + if (result.isNull() || Cond.isInvalid() || LHS.isInvalid() || + RHS.isInvalid()) return ExprError(); if (!commonExpr) - return Owned(new (Context) ConditionalOperator(CondExpr, QuestionLoc, - LHSExpr, ColonLoc, - RHSExpr, result, VK, OK)); + return Owned(new (Context) ConditionalOperator(Cond.take(), QuestionLoc, + LHS.take(), ColonLoc, + RHS.take(), result, VK, OK)); return Owned(new (Context) - BinaryConditionalOperator(commonExpr, opaqueValue, CondExpr, LHSExpr, - RHSExpr, QuestionLoc, ColonLoc, result, VK, OK)); + BinaryConditionalOperator(commonExpr, opaqueValue, Cond.take(), LHS.take(), + RHS.take(), QuestionLoc, ColonLoc, result, VK, OK)); } // checkPointerTypesForAssignment - This is a very tricky routine (despite @@ -5736,6 +6200,12 @@ checkPointerTypesForAssignment(Sema &S, QualType lhsType, QualType rhsType) { if (lhq.getAddressSpace() != rhq.getAddressSpace()) ConvTy = Sema::IncompatiblePointerDiscardsQualifiers; + // It's okay to add or remove GC qualifiers when converting to + // and from void*. + else if (lhq.withoutObjCGCAttr().compatiblyIncludes(rhq.withoutObjCGCAttr()) + && (lhptee->isVoidType() || rhptee->isVoidType())) + ; // keep old + // For GCC compatibility, other qualifier mismatches are treated // as still compatible in C. else ConvTy = Sema::CompatiblePointerDiscardsQualifiers; @@ -5885,7 +6355,7 @@ Sema::CheckAssignmentConstraints(SourceLocation Loc, // adds casts to this they'll be wasted, but fortunately that doesn't // usually happen on valid code. OpaqueValueExpr rhs(Loc, rhsType, VK_RValue); - Expr *rhsPtr = &rhs; + ExprResult rhsPtr = &rhs; CastKind K = CK_Invalid; return CheckAssignmentConstraints(lhsType, rhsPtr, K); @@ -5909,9 +6379,9 @@ Sema::CheckAssignmentConstraints(SourceLocation Loc, /// /// Sets 'Kind' for any result kind except Incompatible. Sema::AssignConvertType -Sema::CheckAssignmentConstraints(QualType lhsType, Expr *&rhs, +Sema::CheckAssignmentConstraints(QualType lhsType, ExprResult &rhs, CastKind &Kind) { - QualType rhsType = rhs->getType(); + QualType rhsType = rhs.get()->getType(); // Get canonical types. We're not formatting these types, just comparing // them. @@ -5950,7 +6420,7 @@ Sema::CheckAssignmentConstraints(QualType lhsType, Expr *&rhs, QualType elType = cast<ExtVectorType>(lhsType)->getElementType(); if (elType != rhsType) { Kind = PrepareScalarCast(*this, rhs, elType); - ImpCastExprToType(rhs, elType, Kind); + rhs = ImpCastExprToType(rhs.take(), elType, Kind); } Kind = CK_VectorSplat; return Compatible; @@ -6151,10 +6621,11 @@ Sema::CheckAssignmentConstraints(QualType lhsType, Expr *&rhs, /// \brief Constructs a transparent union from an expression that is /// used to initialize the transparent union. -static void ConstructTransparentUnion(ASTContext &C, Expr *&E, +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()); @@ -6164,13 +6635,14 @@ static void ConstructTransparentUnion(ASTContext &C, Expr *&E, // Build a compound literal constructing a value of the transparent // union type from this initializer list. TypeSourceInfo *unionTInfo = C.getTrivialTypeSourceInfo(UnionType); - E = new (C) CompoundLiteralExpr(SourceLocation(), unionTInfo, UnionType, - VK_RValue, Initializer, false); + EResult = S.Owned( + new (C) CompoundLiteralExpr(SourceLocation(), unionTInfo, UnionType, + VK_RValue, Initializer, false)); } Sema::AssignConvertType -Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType, Expr *&rExpr) { - QualType FromType = rExpr->getType(); +Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType, ExprResult &rExpr) { + QualType FromType = rExpr.get()->getType(); // If the ArgType is a Union type, we want to handle a potential // transparent_union GCC extension. @@ -6191,25 +6663,23 @@ Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType, Expr *&rExpr) { // 2) null pointer constant if (FromType->isPointerType()) if (FromType->getAs<PointerType>()->getPointeeType()->isVoidType()) { - ImpCastExprToType(rExpr, it->getType(), CK_BitCast); + rExpr = ImpCastExprToType(rExpr.take(), it->getType(), CK_BitCast); InitField = *it; break; } - if (rExpr->isNullPointerConstant(Context, + if (rExpr.get()->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { - ImpCastExprToType(rExpr, it->getType(), CK_NullToPointer); + rExpr = ImpCastExprToType(rExpr.take(), it->getType(), CK_NullToPointer); InitField = *it; break; } } - Expr *rhs = rExpr; CastKind Kind = CK_Invalid; - if (CheckAssignmentConstraints(it->getType(), rhs, Kind) + if (CheckAssignmentConstraints(it->getType(), rExpr, Kind) == Compatible) { - ImpCastExprToType(rhs, it->getType(), Kind); - rExpr = rhs; + rExpr = ImpCastExprToType(rExpr.take(), it->getType(), Kind); InitField = *it; break; } @@ -6218,20 +6688,23 @@ Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType, Expr *&rExpr) { if (!InitField) return Incompatible; - ConstructTransparentUnion(Context, rExpr, ArgType, InitField); + ConstructTransparentUnion(*this, Context, rExpr, ArgType, InitField); return Compatible; } Sema::AssignConvertType -Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) { +Sema::CheckSingleAssignmentConstraints(QualType lhsType, ExprResult &rExpr) { if (getLangOptions().CPlusPlus) { if (!lhsType->isRecordType()) { // 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. - if (PerformImplicitConversion(rExpr, lhsType.getUnqualifiedType(), - AA_Assigning)) + ExprResult Res = PerformImplicitConversion(rExpr.get(), + lhsType.getUnqualifiedType(), + AA_Assigning); + if (Res.isInvalid()) return Incompatible; + rExpr = move(Res); return Compatible; } @@ -6244,9 +6717,9 @@ Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) { if ((lhsType->isPointerType() || lhsType->isObjCObjectPointerType() || lhsType->isBlockPointerType()) - && rExpr->isNullPointerConstant(Context, + && rExpr.get()->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { - ImpCastExprToType(rExpr, lhsType, CK_NullToPointer); + rExpr = ImpCastExprToType(rExpr.take(), lhsType, CK_NullToPointer); return Compatible; } @@ -6256,8 +6729,11 @@ Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) { // expressions that suppress this implicit conversion (&, sizeof). // // Suppress this for references: C++ 8.5.3p5. - if (!lhsType->isReferenceType()) - DefaultFunctionArrayLvalueConversion(rExpr); + if (!lhsType->isReferenceType()) { + rExpr = DefaultFunctionArrayLvalueConversion(rExpr.take()); + if (rExpr.isInvalid()) + return Incompatible; + } CastKind Kind = CK_Invalid; Sema::AssignConvertType result = @@ -6269,25 +6745,25 @@ Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) { // 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 && rExpr->getType() != lhsType) - ImpCastExprToType(rExpr, lhsType.getNonLValueExprType(Context), Kind); + if (result != Incompatible && rExpr.get()->getType() != lhsType) + rExpr = ImpCastExprToType(rExpr.take(), lhsType.getNonLValueExprType(Context), Kind); return result; } -QualType Sema::InvalidOperands(SourceLocation Loc, Expr *&lex, Expr *&rex) { +QualType Sema::InvalidOperands(SourceLocation Loc, ExprResult &lex, ExprResult &rex) { Diag(Loc, diag::err_typecheck_invalid_operands) - << lex->getType() << rex->getType() - << lex->getSourceRange() << rex->getSourceRange(); + << lex.get()->getType() << rex.get()->getType() + << lex.get()->getSourceRange() << rex.get()->getSourceRange(); return QualType(); } -QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex, Expr *&rex) { +QualType Sema::CheckVectorOperands(SourceLocation Loc, ExprResult &lex, ExprResult &rex) { // For conversion purposes, we ignore any qualifiers. // For example, "const float" and "float" are equivalent. QualType lhsType = - Context.getCanonicalType(lex->getType()).getUnqualifiedType(); + Context.getCanonicalType(lex.get()->getType()).getUnqualifiedType(); QualType rhsType = - Context.getCanonicalType(rex->getType()).getUnqualifiedType(); + Context.getCanonicalType(rex.get()->getType()).getUnqualifiedType(); // If the vector types are identical, return. if (lhsType == rhsType) @@ -6301,17 +6777,17 @@ QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex, Expr *&rex) { if (LV->getElementType() == RV->getElementType() && LV->getNumElements() == RV->getNumElements()) { if (lhsType->isExtVectorType()) { - ImpCastExprToType(rex, lhsType, CK_BitCast); + rex = ImpCastExprToType(rex.take(), lhsType, CK_BitCast); return lhsType; } - ImpCastExprToType(lex, rhsType, CK_BitCast); + lex = ImpCastExprToType(lex.take(), rhsType, CK_BitCast); return rhsType; } else if (Context.getTypeSize(lhsType) ==Context.getTypeSize(rhsType)){ // If we are allowing lax vector conversions, and LHS and RHS are both // vectors, the total size only needs to be the same. This is a // bitcast; no bits are changed but the result type is different. - ImpCastExprToType(rex, lhsType, CK_BitCast); + rex = ImpCastExprToType(rex.take(), lhsType, CK_BitCast); return lhsType; } } @@ -6321,7 +6797,7 @@ QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex, Expr *&rex) { // Handle the case of equivalent AltiVec and GCC vector types if (lhsType->isVectorType() && rhsType->isVectorType() && Context.areCompatibleVectorTypes(lhsType, rhsType)) { - ImpCastExprToType(lex, rhsType, CK_BitCast); + lex = ImpCastExprToType(lex.take(), rhsType, CK_BitCast); return rhsType; } @@ -6340,9 +6816,9 @@ QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex, Expr *&rex) { if (EltTy->isIntegralType(Context) && rhsType->isIntegralType(Context)) { int order = Context.getIntegerTypeOrder(EltTy, rhsType); if (order > 0) - ImpCastExprToType(rex, EltTy, CK_IntegralCast); + rex = ImpCastExprToType(rex.take(), EltTy, CK_IntegralCast); if (order >= 0) { - ImpCastExprToType(rex, lhsType, CK_VectorSplat); + rex = ImpCastExprToType(rex.take(), lhsType, CK_VectorSplat); if (swapped) std::swap(rex, lex); return lhsType; } @@ -6351,9 +6827,9 @@ QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex, Expr *&rex) { rhsType->isRealFloatingType()) { int order = Context.getFloatingTypeOrder(EltTy, rhsType); if (order > 0) - ImpCastExprToType(rex, EltTy, CK_FloatingCast); + rex = ImpCastExprToType(rex.take(), EltTy, CK_FloatingCast); if (order >= 0) { - ImpCastExprToType(rex, lhsType, CK_VectorSplat); + rex = ImpCastExprToType(rex.take(), lhsType, CK_VectorSplat); if (swapped) std::swap(rex, lex); return lhsType; } @@ -6362,72 +6838,78 @@ QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex, Expr *&rex) { // Vectors of different size or scalar and non-ext-vector are errors. Diag(Loc, diag::err_typecheck_vector_not_convertable) - << lex->getType() << rex->getType() - << lex->getSourceRange() << rex->getSourceRange(); + << lex.get()->getType() << rex.get()->getType() + << lex.get()->getSourceRange() << rex.get()->getSourceRange(); return QualType(); } QualType Sema::CheckMultiplyDivideOperands( - Expr *&lex, Expr *&rex, SourceLocation Loc, bool isCompAssign, bool isDiv) { - if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) + ExprResult &lex, ExprResult &rex, SourceLocation Loc, bool isCompAssign, bool isDiv) { + if (lex.get()->getType()->isVectorType() || rex.get()->getType()->isVectorType()) return CheckVectorOperands(Loc, lex, rex); QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign); + if (lex.isInvalid() || rex.isInvalid()) + return QualType(); - if (!lex->getType()->isArithmeticType() || - !rex->getType()->isArithmeticType()) + if (!lex.get()->getType()->isArithmeticType() || + !rex.get()->getType()->isArithmeticType()) return InvalidOperands(Loc, lex, rex); // Check for division by zero. if (isDiv && - rex->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull)) - DiagRuntimeBehavior(Loc, rex, PDiag(diag::warn_division_by_zero) - << rex->getSourceRange()); + rex.get()->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull)) + DiagRuntimeBehavior(Loc, rex.get(), PDiag(diag::warn_division_by_zero) + << rex.get()->getSourceRange()); return compType; } QualType Sema::CheckRemainderOperands( - Expr *&lex, Expr *&rex, SourceLocation Loc, bool isCompAssign) { - if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) { - if (lex->getType()->hasIntegerRepresentation() && - rex->getType()->hasIntegerRepresentation()) + ExprResult &lex, ExprResult &rex, SourceLocation Loc, bool isCompAssign) { + if (lex.get()->getType()->isVectorType() || rex.get()->getType()->isVectorType()) { + if (lex.get()->getType()->hasIntegerRepresentation() && + rex.get()->getType()->hasIntegerRepresentation()) return CheckVectorOperands(Loc, lex, rex); return InvalidOperands(Loc, lex, rex); } QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign); + if (lex.isInvalid() || rex.isInvalid()) + return QualType(); - if (!lex->getType()->isIntegerType() || !rex->getType()->isIntegerType()) + if (!lex.get()->getType()->isIntegerType() || !rex.get()->getType()->isIntegerType()) return InvalidOperands(Loc, lex, rex); // Check for remainder by zero. - if (rex->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull)) - DiagRuntimeBehavior(Loc, rex, PDiag(diag::warn_remainder_by_zero) - << rex->getSourceRange()); + if (rex.get()->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull)) + DiagRuntimeBehavior(Loc, rex.get(), PDiag(diag::warn_remainder_by_zero) + << rex.get()->getSourceRange()); return compType; } QualType Sema::CheckAdditionOperands( // C99 6.5.6 - Expr *&lex, Expr *&rex, SourceLocation Loc, QualType* CompLHSTy) { - if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) { + ExprResult &lex, ExprResult &rex, SourceLocation Loc, QualType* CompLHSTy) { + if (lex.get()->getType()->isVectorType() || rex.get()->getType()->isVectorType()) { QualType compType = CheckVectorOperands(Loc, lex, rex); if (CompLHSTy) *CompLHSTy = compType; return compType; } QualType compType = UsualArithmeticConversions(lex, rex, CompLHSTy); + if (lex.isInvalid() || rex.isInvalid()) + return QualType(); // handle the common case first (both operands are arithmetic). - if (lex->getType()->isArithmeticType() && - rex->getType()->isArithmeticType()) { + if (lex.get()->getType()->isArithmeticType() && + rex.get()->getType()->isArithmeticType()) { if (CompLHSTy) *CompLHSTy = compType; return compType; } // Put any potential pointer into PExp - Expr* PExp = lex, *IExp = rex; + Expr* PExp = lex.get(), *IExp = rex.get(); if (IExp->getType()->isAnyPointerType()) std::swap(PExp, IExp); @@ -6440,23 +6922,23 @@ QualType Sema::CheckAdditionOperands( // C99 6.5.6 if (PointeeTy->isVoidType()) { if (getLangOptions().CPlusPlus) { Diag(Loc, diag::err_typecheck_pointer_arith_void_type) - << lex->getSourceRange() << rex->getSourceRange(); + << lex.get()->getSourceRange() << rex.get()->getSourceRange(); return QualType(); } // GNU extension: arithmetic on pointer to void Diag(Loc, diag::ext_gnu_void_ptr) - << lex->getSourceRange() << rex->getSourceRange(); + << lex.get()->getSourceRange() << rex.get()->getSourceRange(); } else if (PointeeTy->isFunctionType()) { if (getLangOptions().CPlusPlus) { Diag(Loc, diag::err_typecheck_pointer_arith_function_type) - << lex->getType() << lex->getSourceRange(); + << lex.get()->getType() << lex.get()->getSourceRange(); return QualType(); } // GNU extension: arithmetic on pointer to function Diag(Loc, diag::ext_gnu_ptr_func_arith) - << lex->getType() << lex->getSourceRange(); + << lex.get()->getType() << lex.get()->getSourceRange(); } else { // Check if we require a complete type. if (((PExp->getType()->isPointerType() && @@ -6476,9 +6958,9 @@ QualType Sema::CheckAdditionOperands( // C99 6.5.6 } if (CompLHSTy) { - QualType LHSTy = Context.isPromotableBitField(lex); + QualType LHSTy = Context.isPromotableBitField(lex.get()); if (LHSTy.isNull()) { - LHSTy = lex->getType(); + LHSTy = lex.get()->getType(); if (LHSTy->isPromotableIntegerType()) LHSTy = Context.getPromotedIntegerType(LHSTy); } @@ -6492,28 +6974,30 @@ QualType Sema::CheckAdditionOperands( // C99 6.5.6 } // C99 6.5.6 -QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex, +QualType Sema::CheckSubtractionOperands(ExprResult &lex, ExprResult &rex, SourceLocation Loc, QualType* CompLHSTy) { - if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) { + if (lex.get()->getType()->isVectorType() || rex.get()->getType()->isVectorType()) { QualType compType = CheckVectorOperands(Loc, lex, rex); if (CompLHSTy) *CompLHSTy = compType; return compType; } QualType compType = UsualArithmeticConversions(lex, rex, CompLHSTy); + if (lex.isInvalid() || rex.isInvalid()) + return QualType(); // Enforce type constraints: C99 6.5.6p3. // Handle the common case first (both operands are arithmetic). - if (lex->getType()->isArithmeticType() - && rex->getType()->isArithmeticType()) { + if (lex.get()->getType()->isArithmeticType() && + rex.get()->getType()->isArithmeticType()) { if (CompLHSTy) *CompLHSTy = compType; return compType; } // Either ptr - int or ptr - ptr. - if (lex->getType()->isAnyPointerType()) { - QualType lpointee = lex->getType()->getPointeeType(); + if (lex.get()->getType()->isAnyPointerType()) { + QualType lpointee = lex.get()->getType()->getPointeeType(); // The LHS must be an completely-defined object type. @@ -6522,7 +7006,7 @@ QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex, if (lpointee->isVoidType()) { if (getLangOptions().CPlusPlus) { Diag(Loc, diag::err_typecheck_pointer_arith_void_type) - << lex->getSourceRange() << rex->getSourceRange(); + << lex.get()->getSourceRange() << rex.get()->getSourceRange(); return QualType(); } @@ -6531,42 +7015,42 @@ QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex, } else if (lpointee->isFunctionType()) { if (getLangOptions().CPlusPlus) { Diag(Loc, diag::err_typecheck_pointer_arith_function_type) - << lex->getType() << lex->getSourceRange(); + << lex.get()->getType() << lex.get()->getSourceRange(); return QualType(); } // GNU C extension: arithmetic on pointer to function - ComplainAboutFunc = lex; + ComplainAboutFunc = lex.get(); } else if (!lpointee->isDependentType() && RequireCompleteType(Loc, lpointee, PDiag(diag::err_typecheck_sub_ptr_object) - << lex->getSourceRange() - << lex->getType())) + << lex.get()->getSourceRange() + << lex.get()->getType())) return QualType(); // Diagnose bad cases where we step over interface counts. if (lpointee->isObjCObjectType() && LangOpts.ObjCNonFragileABI) { Diag(Loc, diag::err_arithmetic_nonfragile_interface) - << lpointee << lex->getSourceRange(); + << lpointee << lex.get()->getSourceRange(); return QualType(); } // The result type of a pointer-int computation is the pointer type. - if (rex->getType()->isIntegerType()) { + if (rex.get()->getType()->isIntegerType()) { if (ComplainAboutVoid) Diag(Loc, diag::ext_gnu_void_ptr) - << lex->getSourceRange() << rex->getSourceRange(); + << lex.get()->getSourceRange() << rex.get()->getSourceRange(); if (ComplainAboutFunc) Diag(Loc, diag::ext_gnu_ptr_func_arith) << ComplainAboutFunc->getType() << ComplainAboutFunc->getSourceRange(); - if (CompLHSTy) *CompLHSTy = lex->getType(); - return lex->getType(); + if (CompLHSTy) *CompLHSTy = lex.get()->getType(); + return lex.get()->getType(); } // Handle pointer-pointer subtractions. - if (const PointerType *RHSPTy = rex->getType()->getAs<PointerType>()) { + if (const PointerType *RHSPTy = rex.get()->getType()->getAs<PointerType>()) { QualType rpointee = RHSPTy->getPointeeType(); // RHS must be a completely-type object type. @@ -6574,7 +7058,7 @@ QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex, if (rpointee->isVoidType()) { if (getLangOptions().CPlusPlus) { Diag(Loc, diag::err_typecheck_pointer_arith_void_type) - << lex->getSourceRange() << rex->getSourceRange(); + << lex.get()->getSourceRange() << rex.get()->getSourceRange(); return QualType(); } @@ -6582,26 +7066,26 @@ QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex, } else if (rpointee->isFunctionType()) { if (getLangOptions().CPlusPlus) { Diag(Loc, diag::err_typecheck_pointer_arith_function_type) - << rex->getType() << rex->getSourceRange(); + << rex.get()->getType() << rex.get()->getSourceRange(); return QualType(); } // GNU extension: arithmetic on pointer to function if (!ComplainAboutFunc) - ComplainAboutFunc = rex; + ComplainAboutFunc = rex.get(); } else if (!rpointee->isDependentType() && RequireCompleteType(Loc, rpointee, PDiag(diag::err_typecheck_sub_ptr_object) - << rex->getSourceRange() - << rex->getType())) + << rex.get()->getSourceRange() + << rex.get()->getType())) return QualType(); if (getLangOptions().CPlusPlus) { // Pointee types must be the same: C++ [expr.add] if (!Context.hasSameUnqualifiedType(lpointee, rpointee)) { Diag(Loc, diag::err_typecheck_sub_ptr_compatible) - << lex->getType() << rex->getType() - << lex->getSourceRange() << rex->getSourceRange(); + << lex.get()->getType() << rex.get()->getType() + << lex.get()->getSourceRange() << rex.get()->getSourceRange(); return QualType(); } } else { @@ -6610,21 +7094,21 @@ QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex, Context.getCanonicalType(lpointee).getUnqualifiedType(), Context.getCanonicalType(rpointee).getUnqualifiedType())) { Diag(Loc, diag::err_typecheck_sub_ptr_compatible) - << lex->getType() << rex->getType() - << lex->getSourceRange() << rex->getSourceRange(); + << lex.get()->getType() << rex.get()->getType() + << lex.get()->getSourceRange() << rex.get()->getSourceRange(); return QualType(); } } if (ComplainAboutVoid) Diag(Loc, diag::ext_gnu_void_ptr) - << lex->getSourceRange() << rex->getSourceRange(); + << lex.get()->getSourceRange() << rex.get()->getSourceRange(); if (ComplainAboutFunc) Diag(Loc, diag::ext_gnu_ptr_func_arith) << ComplainAboutFunc->getType() << ComplainAboutFunc->getSourceRange(); - if (CompLHSTy) *CompLHSTy = lex->getType(); + if (CompLHSTy) *CompLHSTy = lex.get()->getType(); return Context.getPointerDiffType(); } } @@ -6638,22 +7122,26 @@ static bool isScopedEnumerationType(QualType T) { return false; } -static void DiagnoseBadShiftValues(Sema& S, Expr *&lex, Expr *&rex, +static void DiagnoseBadShiftValues(Sema& S, ExprResult &lex, ExprResult &rex, SourceLocation Loc, unsigned Opc, QualType LHSTy) { llvm::APSInt Right; // Check right/shifter operand - if (rex->isValueDependent() || !rex->isIntegerConstantExpr(Right, S.Context)) + if (rex.get()->isValueDependent() || !rex.get()->isIntegerConstantExpr(Right, S.Context)) return; if (Right.isNegative()) { - S.Diag(Loc, diag::warn_shift_negative) << rex->getSourceRange(); + S.DiagRuntimeBehavior(Loc, rex.get(), + S.PDiag(diag::warn_shift_negative) + << rex.get()->getSourceRange()); return; } llvm::APInt LeftBits(Right.getBitWidth(), - S.Context.getTypeSize(lex->getType())); + S.Context.getTypeSize(lex.get()->getType())); if (Right.uge(LeftBits)) { - S.Diag(Loc, diag::warn_shift_gt_typewidth) << rex->getSourceRange(); + S.DiagRuntimeBehavior(Loc, rex.get(), + S.PDiag(diag::warn_shift_gt_typewidth) + << rex.get()->getSourceRange()); return; } if (Opc != BO_Shl) @@ -6664,7 +7152,7 @@ static void DiagnoseBadShiftValues(Sema& S, Expr *&lex, Expr *&rex, // 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 (lex->isValueDependent() || !lex->isIntegerConstantExpr(Left, S.Context) || + if (lex.get()->isValueDependent() || !lex.get()->isIntegerConstantExpr(Left, S.Context) || LHSTy->hasUnsignedIntegerRepresentation()) return; llvm::APInt ResultBits = @@ -6681,32 +7169,32 @@ static void DiagnoseBadShiftValues(Sema& S, Expr *&lex, Expr *&rex, if (LeftBits == ResultBits - 1) { S.Diag(Loc, diag::warn_shift_result_overrides_sign_bit) << Result.toString(10) << LHSTy - << lex->getSourceRange() << rex->getSourceRange(); + << lex.get()->getSourceRange() << rex.get()->getSourceRange(); return; } S.Diag(Loc, diag::warn_shift_result_gt_typewidth) << Result.toString(10) << Result.getMinSignedBits() << LHSTy - << Left.getBitWidth() << lex->getSourceRange() << rex->getSourceRange(); + << Left.getBitWidth() << lex.get()->getSourceRange() << rex.get()->getSourceRange(); } // C99 6.5.7 -QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, +QualType Sema::CheckShiftOperands(ExprResult &lex, ExprResult &rex, SourceLocation Loc, unsigned Opc, bool isCompAssign) { // C99 6.5.7p2: Each of the operands shall have integer type. - if (!lex->getType()->hasIntegerRepresentation() || - !rex->getType()->hasIntegerRepresentation()) + if (!lex.get()->getType()->hasIntegerRepresentation() || + !rex.get()->getType()->hasIntegerRepresentation()) return InvalidOperands(Loc, lex, rex); // C++0x: Don't allow scoped enums. FIXME: Use something better than // hasIntegerRepresentation() above instead of this. - if (isScopedEnumerationType(lex->getType()) || - isScopedEnumerationType(rex->getType())) { + if (isScopedEnumerationType(lex.get()->getType()) || + isScopedEnumerationType(rex.get()->getType())) { return InvalidOperands(Loc, lex, rex); } // Vector shifts promote their scalar inputs to vector type. - if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) + if (lex.get()->getType()->isVectorType() || rex.get()->getType()->isVectorType()) return CheckVectorOperands(Loc, lex, rex); // Shifts don't perform usual arithmetic conversions, they just do integer @@ -6714,13 +7202,17 @@ QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, // For the LHS, do usual unary conversions, but then reset them away // if this is a compound assignment. - Expr *old_lex = lex; - UsualUnaryConversions(lex); - QualType LHSTy = lex->getType(); + ExprResult old_lex = lex; + lex = UsualUnaryConversions(lex.take()); + if (lex.isInvalid()) + return QualType(); + QualType LHSTy = lex.get()->getType(); if (isCompAssign) lex = old_lex; // The RHS is simpler. - UsualUnaryConversions(rex); + rex = UsualUnaryConversions(rex.take()); + if (rex.isInvalid()) + return QualType(); // Sanity-check shift operands DiagnoseBadShiftValues(*this, lex, rex, Loc, Opc, LHSTy); @@ -6740,22 +7232,24 @@ static bool IsWithinTemplateSpecialization(Decl *D) { } // C99 6.5.8, C++ [expr.rel] -QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, +QualType Sema::CheckCompareOperands(ExprResult &lex, ExprResult &rex, SourceLocation Loc, unsigned OpaqueOpc, bool isRelational) { BinaryOperatorKind Opc = (BinaryOperatorKind) OpaqueOpc; // Handle vector comparisons separately. - if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) + if (lex.get()->getType()->isVectorType() || rex.get()->getType()->isVectorType()) return CheckVectorCompareOperands(lex, rex, Loc, isRelational); - QualType lType = lex->getType(); - QualType rType = rex->getType(); - - Expr *LHSStripped = lex->IgnoreParenImpCasts(); - Expr *RHSStripped = rex->IgnoreParenImpCasts(); + QualType lType = lex.get()->getType(); + QualType rType = rex.get()->getType(); + + Expr *LHSStripped = lex.get()->IgnoreParenImpCasts(); + Expr *RHSStripped = rex.get()->IgnoreParenImpCasts(); QualType LHSStrippedType = LHSStripped->getType(); QualType RHSStrippedType = RHSStripped->getType(); + + // Two different enums will raise a warning when compared. if (const EnumType *LHSEnumType = LHSStrippedType->getAs<EnumType>()) { if (const EnumType *RHSEnumType = RHSStrippedType->getAs<EnumType>()) { @@ -6764,15 +7258,15 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, !Context.hasSameUnqualifiedType(LHSStrippedType, RHSStrippedType)) { Diag(Loc, diag::warn_comparison_of_mixed_enum_types) << LHSStrippedType << RHSStrippedType - << lex->getSourceRange() << rex->getSourceRange(); + << lex.get()->getSourceRange() << rex.get()->getSourceRange(); } } } if (!lType->hasFloatingRepresentation() && !(lType->isBlockPointerType() && isRelational) && - !lex->getLocStart().isMacroID() && - !rex->getLocStart().isMacroID()) { + !lex.get()->getLocStart().isMacroID() && + !rex.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. @@ -6828,13 +7322,13 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, if ((isa<StringLiteral>(LHSStripped) || isa<ObjCEncodeExpr>(LHSStripped)) && !RHSStripped->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { - literalString = lex; + literalString = lex.get(); literalStringStripped = LHSStripped; } else if ((isa<StringLiteral>(RHSStripped) || isa<ObjCEncodeExpr>(RHSStripped)) && !LHSStripped->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { - literalString = rex; + literalString = rex.get(); literalStringStripped = RHSStripped; } @@ -6858,15 +7352,23 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, } // C99 6.5.8p3 / C99 6.5.9p4 - if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType()) + if (lex.get()->getType()->isArithmeticType() && rex.get()->getType()->isArithmeticType()) { UsualArithmeticConversions(lex, rex); + if (lex.isInvalid() || rex.isInvalid()) + return QualType(); + } else { - UsualUnaryConversions(lex); - UsualUnaryConversions(rex); + lex = UsualUnaryConversions(lex.take()); + if (lex.isInvalid()) + return QualType(); + + rex = UsualUnaryConversions(rex.take()); + if (rex.isInvalid()) + return QualType(); } - lType = lex->getType(); - rType = rex->getType(); + lType = lex.get()->getType(); + rType = rex.get()->getType(); // The result of comparisons is 'bool' in C++, 'int' in C. QualType ResultTy = Context.getLogicalOperationType(); @@ -6877,15 +7379,15 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, } else { // Check for comparisons of floating point operands using != and ==. if (lType->hasFloatingRepresentation()) - CheckFloatComparison(Loc,lex,rex); + CheckFloatComparison(Loc, lex.get(), rex.get()); if (lType->isArithmeticType() && rType->isArithmeticType()) return ResultTy; } - bool LHSIsNull = lex->isNullPointerConstant(Context, + bool LHSIsNull = lex.get()->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull); - bool RHSIsNull = rex->isNullPointerConstant(Context, + bool RHSIsNull = rex.get()->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull); // All of the following pointer-related warnings are GCC extensions, except @@ -6911,12 +7413,12 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, isSFINAEContext()? diag::err_typecheck_comparison_of_fptr_to_void : diag::ext_typecheck_comparison_of_fptr_to_void) - << lType << rType << lex->getSourceRange() << rex->getSourceRange(); + << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange(); if (isSFINAEContext()) return QualType(); - ImpCastExprToType(rex, lType, CK_BitCast); + rex = ImpCastExprToType(rex.take(), lType, CK_BitCast); return ResultTy; } } @@ -6934,17 +7436,17 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, isSFINAEContext()? 0 : &NonStandardCompositeType); if (T.isNull()) { Diag(Loc, diag::err_typecheck_comparison_of_distinct_pointers) - << lType << rType << lex->getSourceRange() << rex->getSourceRange(); + << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange(); return QualType(); } else if (NonStandardCompositeType) { Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers_nonstandard) << lType << rType << T - << lex->getSourceRange() << rex->getSourceRange(); + << lex.get()->getSourceRange() << rex.get()->getSourceRange(); } - ImpCastExprToType(lex, T, CK_BitCast); - ImpCastExprToType(rex, T, CK_BitCast); + lex = ImpCastExprToType(lex.take(), T, CK_BitCast); + rex = ImpCastExprToType(rex.take(), T, CK_BitCast); return ResultTy; } // C99 6.5.9p2 and C99 6.5.8p2 @@ -6953,7 +7455,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, // Valid unless a relational comparison of function pointers if (isRelational && LCanPointeeTy->isFunctionType()) { Diag(Loc, diag::ext_typecheck_ordered_comparison_of_function_pointers) - << lType << rType << lex->getSourceRange() << rex->getSourceRange(); + << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange(); } } else if (!isRelational && (LCanPointeeTy->isVoidType() || RCanPointeeTy->isVoidType())) { @@ -6961,15 +7463,19 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, if ((LCanPointeeTy->isFunctionType() || RCanPointeeTy->isFunctionType()) && !LHSIsNull && !RHSIsNull) { Diag(Loc, diag::ext_typecheck_comparison_of_fptr_to_void) - << lType << rType << lex->getSourceRange() << rex->getSourceRange(); + << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange(); } } else { // Invalid Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers) - << lType << rType << lex->getSourceRange() << rex->getSourceRange(); + << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange(); + } + if (LCanPointeeTy != RCanPointeeTy) { + if (LHSIsNull && !RHSIsNull) + lex = ImpCastExprToType(lex.take(), rType, CK_BitCast); + else + rex = ImpCastExprToType(rex.take(), lType, CK_BitCast); } - if (LCanPointeeTy != RCanPointeeTy) - ImpCastExprToType(rex, lType, CK_BitCast); return ResultTy; } @@ -6983,7 +7489,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, if (RHSIsNull && ((lType->isPointerType() || lType->isNullPtrType()) || (!isRelational && lType->isMemberPointerType()))) { - ImpCastExprToType(rex, lType, + rex = ImpCastExprToType(rex.take(), lType, lType->isMemberPointerType() ? CK_NullToMemberPointer : CK_NullToPointer); @@ -6992,7 +7498,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, if (LHSIsNull && ((rType->isPointerType() || rType->isNullPtrType()) || (!isRelational && rType->isMemberPointerType()))) { - ImpCastExprToType(lex, rType, + lex = ImpCastExprToType(lex.take(), rType, rType->isMemberPointerType() ? CK_NullToMemberPointer : CK_NullToPointer); @@ -7017,19 +7523,25 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, isSFINAEContext()? 0 : &NonStandardCompositeType); if (T.isNull()) { Diag(Loc, diag::err_typecheck_comparison_of_distinct_pointers) - << lType << rType << lex->getSourceRange() << rex->getSourceRange(); + << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange(); return QualType(); } else if (NonStandardCompositeType) { Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers_nonstandard) << lType << rType << T - << lex->getSourceRange() << rex->getSourceRange(); + << lex.get()->getSourceRange() << rex.get()->getSourceRange(); } - ImpCastExprToType(lex, T, CK_BitCast); - ImpCastExprToType(rex, T, CK_BitCast); + lex = ImpCastExprToType(lex.take(), T, CK_BitCast); + rex = ImpCastExprToType(rex.take(), T, CK_BitCast); return ResultTy; } + + // Handle scoped enumeration types specifically, since they don't promote + // to integers. + if (lex.get()->getType()->isEnumeralType() && + Context.hasSameUnqualifiedType(lex.get()->getType(), rex.get()->getType())) + return ResultTy; } // Handle block pointer types. @@ -7040,49 +7552,57 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, if (!LHSIsNull && !RHSIsNull && !Context.typesAreCompatible(lpointee, rpointee)) { Diag(Loc, diag::err_typecheck_comparison_of_distinct_blocks) - << lType << rType << lex->getSourceRange() << rex->getSourceRange(); + << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange(); } - ImpCastExprToType(rex, lType, CK_BitCast); + rex = ImpCastExprToType(rex.take(), lType, CK_BitCast); return ResultTy; } + // Allow block pointers to be compared with null pointer constants. if (!isRelational && ((lType->isBlockPointerType() && rType->isPointerType()) || (lType->isPointerType() && rType->isBlockPointerType()))) { if (!LHSIsNull && !RHSIsNull) { - if (!((rType->isPointerType() && rType->getAs<PointerType>() + if (!((rType->isPointerType() && rType->castAs<PointerType>() ->getPointeeType()->isVoidType()) - || (lType->isPointerType() && lType->getAs<PointerType>() + || (lType->isPointerType() && lType->castAs<PointerType>() ->getPointeeType()->isVoidType()))) Diag(Loc, diag::err_typecheck_comparison_of_distinct_blocks) - << lType << rType << lex->getSourceRange() << rex->getSourceRange(); + << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange(); } - ImpCastExprToType(rex, lType, CK_BitCast); + if (LHSIsNull && !RHSIsNull) + lex = ImpCastExprToType(lex.take(), rType, CK_BitCast); + else + rex = ImpCastExprToType(rex.take(), lType, CK_BitCast); return ResultTy; } - if ((lType->isObjCObjectPointerType() || rType->isObjCObjectPointerType())) { - if (lType->isPointerType() || rType->isPointerType()) { - const PointerType *LPT = lType->getAs<PointerType>(); - const PointerType *RPT = rType->getAs<PointerType>(); - bool LPtrToVoid = LPT ? - Context.getCanonicalType(LPT->getPointeeType())->isVoidType() : false; - bool RPtrToVoid = RPT ? - Context.getCanonicalType(RPT->getPointeeType())->isVoidType() : false; + if (lType->isObjCObjectPointerType() || rType->isObjCObjectPointerType()) { + const PointerType *LPT = lType->getAs<PointerType>(); + const PointerType *RPT = rType->getAs<PointerType>(); + if (LPT || RPT) { + bool LPtrToVoid = LPT ? LPT->getPointeeType()->isVoidType() : false; + bool RPtrToVoid = RPT ? RPT->getPointeeType()->isVoidType() : false; if (!LPtrToVoid && !RPtrToVoid && !Context.typesAreCompatible(lType, rType)) { Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers) - << lType << rType << lex->getSourceRange() << rex->getSourceRange(); + << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange(); } - ImpCastExprToType(rex, lType, CK_BitCast); + if (LHSIsNull && !RHSIsNull) + lex = ImpCastExprToType(lex.take(), rType, CK_BitCast); + else + rex = ImpCastExprToType(rex.take(), lType, CK_BitCast); return ResultTy; } if (lType->isObjCObjectPointerType() && rType->isObjCObjectPointerType()) { if (!Context.areComparableObjCPointerTypes(lType, rType)) Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers) - << lType << rType << lex->getSourceRange() << rex->getSourceRange(); - ImpCastExprToType(rex, lType, CK_BitCast); + << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange(); + if (LHSIsNull && !RHSIsNull) + lex = ImpCastExprToType(lex.take(), rType, CK_BitCast); + else + rex = ImpCastExprToType(rex.take(), lType, CK_BitCast); return ResultTy; } } @@ -7104,16 +7624,16 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, if (DiagID) { Diag(Loc, DiagID) - << lType << rType << lex->getSourceRange() << rex->getSourceRange(); + << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange(); if (isError) return QualType(); } if (lType->isIntegerType()) - ImpCastExprToType(lex, rType, + lex = ImpCastExprToType(lex.take(), rType, LHSIsNull ? CK_NullToPointer : CK_IntegralToPointer); else - ImpCastExprToType(rex, lType, + rex = ImpCastExprToType(rex.take(), lType, RHSIsNull ? CK_NullToPointer : CK_IntegralToPointer); return ResultTy; } @@ -7121,14 +7641,15 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, // Handle block pointers. if (!isRelational && RHSIsNull && lType->isBlockPointerType() && rType->isIntegerType()) { - ImpCastExprToType(rex, lType, CK_NullToPointer); + rex = ImpCastExprToType(rex.take(), lType, CK_NullToPointer); return ResultTy; } if (!isRelational && LHSIsNull && lType->isIntegerType() && rType->isBlockPointerType()) { - ImpCastExprToType(lex, rType, CK_NullToPointer); + lex = ImpCastExprToType(lex.take(), rType, CK_NullToPointer); return ResultTy; } + return InvalidOperands(Loc, lex, rex); } @@ -7136,7 +7657,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, /// 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(Expr *&lex, Expr *&rex, +QualType Sema::CheckVectorCompareOperands(ExprResult &lex, ExprResult &rex, SourceLocation Loc, bool isRelational) { // Check to make sure we're operating on vectors of the same type and width, @@ -7145,20 +7666,20 @@ QualType Sema::CheckVectorCompareOperands(Expr *&lex, Expr *&rex, if (vType.isNull()) return vType; + QualType lType = lex.get()->getType(); + QualType rType = rex.get()->getType(); + // If AltiVec, the comparison results in a numeric type, i.e. // bool for C++, int for C - if (getLangOptions().AltiVec) + if (vType->getAs<VectorType>()->getVectorKind() == VectorType::AltiVecVector) return Context.getLogicalOperationType(); - QualType lType = lex->getType(); - QualType rType = rex->getType(); - // 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 (!lType->hasFloatingRepresentation()) { - if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(lex->IgnoreParens())) - if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(rex->IgnoreParens())) + if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(lex.get()->IgnoreParens())) + if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(rex.get()->IgnoreParens())) if (DRL->getDecl() == DRR->getDecl()) DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always) @@ -7170,7 +7691,7 @@ QualType Sema::CheckVectorCompareOperands(Expr *&lex, Expr *&rex, // Check for comparisons of floating point operands using != and ==. if (!isRelational && lType->hasFloatingRepresentation()) { assert (rType->hasFloatingRepresentation()); - CheckFloatComparison(Loc,lex,rex); + CheckFloatComparison(Loc, lex.get(), rex.get()); } // Return the type for the comparison, which is the same as vector type for @@ -7192,51 +7713,61 @@ QualType Sema::CheckVectorCompareOperands(Expr *&lex, Expr *&rex, } inline QualType Sema::CheckBitwiseOperands( - Expr *&lex, Expr *&rex, SourceLocation Loc, bool isCompAssign) { - if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) { - if (lex->getType()->hasIntegerRepresentation() && - rex->getType()->hasIntegerRepresentation()) + ExprResult &lex, ExprResult &rex, SourceLocation Loc, bool isCompAssign) { + if (lex.get()->getType()->isVectorType() || rex.get()->getType()->isVectorType()) { + if (lex.get()->getType()->hasIntegerRepresentation() && + rex.get()->getType()->hasIntegerRepresentation()) return CheckVectorOperands(Loc, lex, rex); return InvalidOperands(Loc, lex, rex); } - QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign); + ExprResult lexResult = Owned(lex), rexResult = Owned(rex); + QualType compType = UsualArithmeticConversions(lexResult, rexResult, isCompAssign); + if (lexResult.isInvalid() || rexResult.isInvalid()) + return QualType(); + lex = lexResult.take(); + rex = rexResult.take(); - if (lex->getType()->isIntegralOrUnscopedEnumerationType() && - rex->getType()->isIntegralOrUnscopedEnumerationType()) + if (lex.get()->getType()->isIntegralOrUnscopedEnumerationType() && + rex.get()->getType()->isIntegralOrUnscopedEnumerationType()) return compType; return InvalidOperands(Loc, lex, rex); } inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14] - Expr *&lex, Expr *&rex, SourceLocation Loc, unsigned Opc) { + ExprResult &lex, ExprResult &rex, SourceLocation Loc, unsigned Opc) { // 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 (lex->getType()->isIntegerType() && !lex->getType()->isBooleanType() && - rex->getType()->isIntegerType() && !rex->isValueDependent() && + if (lex.get()->getType()->isIntegerType() && !lex.get()->getType()->isBooleanType() && + rex.get()->getType()->isIntegerType() && !rex.get()->isValueDependent() && // Don't warn in macros. !Loc.isMacroID()) { // If the RHS can be constant folded, and if it constant folds to something // that isn't 0 or 1 (which indicate a potential logical operation that // happened to fold to true/false) then warn. Expr::EvalResult Result; - if (rex->Evaluate(Result, Context) && !Result.HasSideEffects && + if (rex.get()->Evaluate(Result, Context) && !Result.HasSideEffects && Result.Val.getInt() != 0 && Result.Val.getInt() != 1) { Diag(Loc, diag::warn_logical_instead_of_bitwise) - << rex->getSourceRange() + << rex.get()->getSourceRange() << (Opc == BO_LAnd ? "&&" : "||") << (Opc == BO_LAnd ? "&" : "|"); } } if (!Context.getLangOptions().CPlusPlus) { - UsualUnaryConversions(lex); - UsualUnaryConversions(rex); + lex = UsualUnaryConversions(lex.take()); + if (lex.isInvalid()) + return QualType(); + + rex = UsualUnaryConversions(rex.take()); + if (rex.isInvalid()) + return QualType(); - if (!lex->getType()->isScalarType() || !rex->getType()->isScalarType()) + if (!lex.get()->getType()->isScalarType() || !rex.get()->getType()->isScalarType()) return InvalidOperands(Loc, lex, rex); return Context.IntTy; @@ -7248,9 +7779,15 @@ inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14] // C++ [expr.log.and]p1 // C++ [expr.log.or]p1 // The operands are both contextually converted to type bool. - if (PerformContextuallyConvertToBool(lex) || - PerformContextuallyConvertToBool(rex)) + ExprResult lexRes = PerformContextuallyConvertToBool(lex.get()); + if (lexRes.isInvalid()) + return InvalidOperands(Loc, lex, rex); + lex = move(lexRes); + + ExprResult rexRes = PerformContextuallyConvertToBool(rex.get()); + if (rexRes.isInvalid()) return InvalidOperands(Loc, lex, rex); + rex = move(rexRes); // C++ [expr.log.and]p2 // C++ [expr.log.or]p2 @@ -7281,6 +7818,35 @@ static bool IsReadonlyProperty(Expr *E, Sema &S) { return false; } +static bool IsConstProperty(Expr *E, Sema &S) { + if (E->getStmtClass() == Expr::ObjCPropertyRefExprClass) { + const ObjCPropertyRefExpr* PropExpr = cast<ObjCPropertyRefExpr>(E); + if (PropExpr->isImplicitProperty()) return false; + + ObjCPropertyDecl *PDecl = PropExpr->getExplicitProperty(); + QualType T = PDecl->getType(); + if (T->isReferenceType()) + T = T->getAs<ReferenceType>()->getPointeeType(); + CanQualType CT = S.Context.getCanonicalType(T); + return CT.isConstQualified(); + } + return false; +} + +static bool IsReadonlyMessage(Expr *E, Sema &S) { + if (E->getStmtClass() != Expr::MemberExprClass) + return false; + const MemberExpr *ME = cast<MemberExpr>(E); + NamedDecl *Member = ME->getMemberDecl(); + if (isa<FieldDecl>(Member)) { + Expr *Base = ME->getBase()->IgnoreParenImpCasts(); + if (Base->getStmtClass() != Expr::ObjCMessageExprClass) + return false; + return cast<ObjCMessageExpr>(Base)->getMethodDecl() != 0; + } + return false; +} + /// 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) { @@ -7289,6 +7855,10 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) { &Loc); if (IsLV == Expr::MLV_Valid && IsReadonlyProperty(E, S)) IsLV = Expr::MLV_ReadonlyProperty; + else if (Expr::MLV_ConstQualified && IsConstProperty(E, S)) + IsLV = Expr::MLV_Valid; + else if (IsLV == Expr::MLV_ClassTemporary && IsReadonlyMessage(E, S)) + IsLV = Expr::MLV_InvalidMessageExpression; if (IsLV == Expr::MLV_Valid) return false; @@ -7331,6 +7901,9 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) { case Expr::MLV_NoSetterProperty: Diag = diag::error_nosetter_property_assignment; break; + case Expr::MLV_InvalidMessageExpression: + Diag = diag::error_readonly_message_assignment; + break; case Expr::MLV_SubObjCPropertySetting: Diag = diag::error_no_subobject_property_setting; break; @@ -7349,7 +7922,7 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) { // C99 6.5.16.1 -QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS, +QualType Sema::CheckAssignmentOperands(Expr *LHS, ExprResult &RHS, SourceLocation Loc, QualType CompoundType) { // Verify that LHS is a modifiable lvalue, and emit error if not. @@ -7357,14 +7930,21 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS, return QualType(); QualType LHSType = LHS->getType(); - QualType RHSType = CompoundType.isNull() ? RHS->getType() : CompoundType; + QualType RHSType = CompoundType.isNull() ? RHS.get()->getType() : CompoundType; AssignConvertType ConvTy; if (CompoundType.isNull()) { QualType LHSTy(LHSType); // Simple assignment "x = y". - if (LHS->getObjectKind() == OK_ObjCProperty) - ConvertPropertyForLValue(LHS, RHS, LHSTy); + if (LHS->getObjectKind() == OK_ObjCProperty) { + ExprResult LHSResult = Owned(LHS); + ConvertPropertyForLValue(LHSResult, RHS, LHSTy); + if (LHSResult.isInvalid()) + return QualType(); + LHS = LHSResult.take(); + } 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) && @@ -7382,7 +7962,7 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS, // 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; + Expr *RHSCheck = RHS.get(); if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(RHSCheck)) RHSCheck = ICE->getSubExpr(); if (UnaryOperator *UO = dyn_cast<UnaryOperator>(RHSCheck)) { @@ -7406,32 +7986,12 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS, } if (DiagnoseAssignmentResult(ConvTy, Loc, LHSType, RHSType, - RHS, AA_Assigning)) + RHS.get(), AA_Assigning)) return QualType(); - - // Check to see if the destination operand is a dereferenced 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 = whatever", which is a very syntactic - // check. - if (UnaryOperator *UO = dyn_cast<UnaryOperator>(LHS->IgnoreParenCasts())) - if (UO->getOpcode() == UO_Deref && - UO->getSubExpr()->IgnoreParenCasts()-> - isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull) && - !UO->getType().isVolatileQualified()) { - DiagRuntimeBehavior(UO->getOperatorLoc(), UO, - PDiag(diag::warn_indirection_through_null) - << UO->getSubExpr()->getSourceRange()); - DiagRuntimeBehavior(UO->getOperatorLoc(), UO, - PDiag(diag::note_indirection_through_null)); - } - + CheckForNullPointerDereference(*this, LHS); // Check for trivial buffer overflows. - if (const ArraySubscriptExpr *ae - = dyn_cast<ArraySubscriptExpr>(LHS->IgnoreParenCasts())) - CheckArrayAccess(ae); + CheckArrayAccess(LHS->IgnoreParenCasts()); // 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 @@ -7445,34 +8005,34 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS, } // C99 6.5.17 -static QualType CheckCommaOperands(Sema &S, Expr *&LHS, Expr *&RHS, +static QualType CheckCommaOperands(Sema &S, ExprResult &LHS, ExprResult &RHS, SourceLocation Loc) { - S.DiagnoseUnusedExprResult(LHS); + S.DiagnoseUnusedExprResult(LHS.get()); - ExprResult LHSResult = S.CheckPlaceholderExpr(LHS, Loc); - if (LHSResult.isInvalid()) + LHS = S.CheckPlaceholderExpr(LHS.take()); + RHS = S.CheckPlaceholderExpr(RHS.take()); + if (LHS.isInvalid() || RHS.isInvalid()) return QualType(); - ExprResult RHSResult = S.CheckPlaceholderExpr(RHS, Loc); - if (RHSResult.isInvalid()) - return QualType(); - RHS = RHSResult.take(); - // 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. - S.IgnoredValueConversions(LHS); + LHS = S.IgnoredValueConversions(LHS.take()); + if (LHS.isInvalid()) + return QualType(); if (!S.getLangOptions().CPlusPlus) { - S.DefaultFunctionArrayLvalueConversion(RHS); - if (!RHS->getType()->isVoidType()) - S.RequireCompleteType(Loc, RHS->getType(), diag::err_incomplete_type); + 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->getType(); + return RHS.get()->getType(); } /// CheckIncrementDecrementOperand - unlike most "Check" methods, this routine @@ -7535,7 +8095,7 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op, S.Diag(OpLoc, diag::ext_integer_increment_complex) << ResType << Op->getSourceRange(); } else if (ResType->isPlaceholderType()) { - ExprResult PR = S.CheckPlaceholderExpr(Op, OpLoc); + ExprResult PR = S.CheckPlaceholderExpr(Op); if (PR.isInvalid()) return QualType(); return CheckIncrementDecrementOperand(S, PR.take(), VK, OpLoc, isInc, isPrefix); @@ -7562,7 +8122,7 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op, } } -void Sema::ConvertPropertyForRValue(Expr *&E) { +ExprResult Sema::ConvertPropertyForRValue(Expr *E) { assert(E->getValueKind() == VK_LValue && E->getObjectKind() == OK_ObjCProperty); const ObjCPropertyRefExpr *PRE = E->getObjCProperty(); @@ -7586,28 +8146,30 @@ void Sema::ConvertPropertyForRValue(Expr *&E) { ExprResult Result = MaybeBindToTemporary(E); if (!Result.isInvalid()) E = Result.take(); + + return Owned(E); } -void Sema::ConvertPropertyForLValue(Expr *&LHS, Expr *&RHS, QualType &LHSTy) { - assert(LHS->getValueKind() == VK_LValue && - LHS->getObjectKind() == OK_ObjCProperty); - const ObjCPropertyRefExpr *PRE = LHS->getObjCProperty(); +void Sema::ConvertPropertyForLValue(ExprResult &LHS, ExprResult &RHS, QualType &LHSTy) { + assert(LHS.get()->getValueKind() == VK_LValue && + LHS.get()->getObjectKind() == OK_ObjCProperty); + const ObjCPropertyRefExpr *PropRef = LHS.get()->getObjCProperty(); - if (PRE->isImplicitProperty()) { + if (PropRef->isImplicitProperty()) { // If using property-dot syntax notation for assignment, and there is a // setter, RHS expression is being passed to the setter argument. So, // type conversion (and comparison) is RHS to setter's argument type. - if (const ObjCMethodDecl *SetterMD = PRE->getImplicitPropertySetter()) { + if (const ObjCMethodDecl *SetterMD = PropRef->getImplicitPropertySetter()) { ObjCMethodDecl::param_iterator P = SetterMD->param_begin(); LHSTy = (*P)->getType(); // Otherwise, if the getter returns an l-value, just call that. } else { - QualType Result = PRE->getImplicitPropertyGetter()->getResultType(); + QualType Result = PropRef->getImplicitPropertyGetter()->getResultType(); ExprValueKind VK = Expr::getValueKindForType(Result); if (VK == VK_LValue) { - LHS = ImplicitCastExpr::Create(Context, LHS->getType(), - CK_GetObjCProperty, LHS, 0, VK); + LHS = ImplicitCastExpr::Create(Context, LHS.get()->getType(), + CK_GetObjCProperty, LHS.take(), 0, VK); return; } } @@ -7616,11 +8178,9 @@ void Sema::ConvertPropertyForLValue(Expr *&LHS, Expr *&RHS, QualType &LHSTy) { if (getLangOptions().CPlusPlus && LHSTy->isRecordType()) { InitializedEntity Entity = InitializedEntity::InitializeParameter(Context, LHSTy); - Expr *Arg = RHS; - ExprResult ArgE = PerformCopyInitialization(Entity, SourceLocation(), - Owned(Arg)); + ExprResult ArgE = PerformCopyInitialization(Entity, SourceLocation(), RHS); if (!ArgE.isInvalid()) - RHS = ArgE.takeAs<Expr>(); + RHS = ArgE; } } @@ -7695,10 +8255,15 @@ static QualType CheckAddressOfOperand(Sema &S, Expr *OrigOp, return S.Context.DependentTy; if (OrigOp->getType() == S.Context.OverloadTy) return S.Context.OverloadTy; + if (OrigOp->getType() == S.Context.UnknownAnyTy) + return S.Context.UnknownAnyTy; + if (OrigOp->getType() == S.Context.BoundMemberTy) { + S.Diag(OpLoc, diag::err_invalid_form_pointer_member_function) + << OrigOp->getSourceRange(); + return QualType(); + } - ExprResult PR = S.CheckPlaceholderExpr(OrigOp, OpLoc); - if (PR.isInvalid()) return QualType(); - OrigOp = PR.take(); + assert(!OrigOp->getType()->isPlaceholderType()); // Make sure to ignore parentheses in subsequent checks Expr *op = OrigOp->IgnoreParens(); @@ -7717,7 +8282,7 @@ static QualType CheckAddressOfOperand(Sema &S, Expr *OrigOp, ValueDecl *dcl = getPrimaryDecl(op); Expr::LValueClassification lval = op->ClassifyLValue(S.Context); - if (lval == Expr::LV_ClassTemporary) { + 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) @@ -7833,7 +8398,10 @@ static QualType CheckIndirectionOperand(Sema &S, Expr *Op, ExprValueKind &VK, if (Op->isTypeDependent()) return S.Context.DependentTy; - S.UsualUnaryConversions(Op); + ExprResult ConvResult = S.UsualUnaryConversions(Op); + if (ConvResult.isInvalid()) + return QualType(); + Op = ConvResult.take(); QualType OpTy = Op->getType(); QualType Result; @@ -7847,7 +8415,7 @@ static QualType CheckIndirectionOperand(Sema &S, Expr *Op, ExprValueKind &VK, OpTy->getAs<ObjCObjectPointerType>()) Result = OPT->getPointeeType(); else { - ExprResult PR = S.CheckPlaceholderExpr(Op, OpLoc); + ExprResult PR = S.CheckPlaceholderExpr(Op); if (PR.isInvalid()) return QualType(); if (PR.take() != Op) return CheckIndirectionOperand(S, PR.take(), VK, OpLoc); @@ -7970,7 +8538,8 @@ static void DiagnoseSelfAssignment(Sema &S, Expr *lhs, Expr *rhs, /// built-in operations; ActOnBinOp handles overloaded operators. ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, BinaryOperatorKind Opc, - Expr *lhs, Expr *rhs) { + Expr *lhsExpr, Expr *rhsExpr) { + 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 @@ -7978,16 +8547,33 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, ExprValueKind VK = VK_RValue; ExprObjectKind OK = OK_Ordinary; + // Check if a 'foo<int>' involved in a binary op, identifies a single + // function unambiguously (i.e. an lvalue ala 13.4) + // But since an assignment can trigger target based overload, exclude it in + // our blind search. i.e: + // template<class T> void f(); template<class T, class U> void f(U); + // f<int> == 0; // resolve f<int> blindly + // void (*p)(int); p = f<int>; // resolve f<int> using target + if (Opc != BO_Assign) { + ExprResult resolvedLHS = CheckPlaceholderExpr(lhs.get()); + if (!resolvedLHS.isUsable()) return ExprError(); + lhs = move(resolvedLHS); + + ExprResult resolvedRHS = CheckPlaceholderExpr(rhs.get()); + if (!resolvedRHS.isUsable()) return ExprError(); + rhs = move(resolvedRHS); + } + switch (Opc) { case BO_Assign: - ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, QualType()); + ResultTy = CheckAssignmentOperands(lhs.get(), rhs, OpLoc, QualType()); if (getLangOptions().CPlusPlus && - lhs->getObjectKind() != OK_ObjCProperty) { - VK = lhs->getValueKind(); - OK = lhs->getObjectKind(); + lhs.get()->getObjectKind() != OK_ObjCProperty) { + VK = lhs.get()->getValueKind(); + OK = lhs.get()->getObjectKind(); } if (!ResultTy.isNull()) - DiagnoseSelfAssignment(*this, lhs, rhs, OpLoc); + DiagnoseSelfAssignment(*this, lhs.get(), rhs.get(), OpLoc); break; case BO_PtrMemD: case BO_PtrMemI: @@ -8036,60 +8622,59 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, CompResultTy = CheckMultiplyDivideOperands(lhs, rhs, OpLoc, true, Opc == BO_DivAssign); CompLHSTy = CompResultTy; - if (!CompResultTy.isNull()) - ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, 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()) - ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy); + if (!CompResultTy.isNull() && !lhs.isInvalid() && !rhs.isInvalid()) + ResultTy = CheckAssignmentOperands(lhs.get(), rhs, OpLoc, CompResultTy); break; case BO_AddAssign: CompResultTy = CheckAdditionOperands(lhs, rhs, OpLoc, &CompLHSTy); - if (!CompResultTy.isNull()) - ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy); + 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()) - ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy); + 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()) - ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, 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()) - ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, 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 (getLangOptions().CPlusPlus) { - VK = rhs->getValueKind(); - OK = rhs->getObjectKind(); + if (getLangOptions().CPlusPlus && !rhs.isInvalid()) { + VK = rhs.get()->getValueKind(); + OK = rhs.get()->getObjectKind(); } break; } - if (ResultTy.isNull()) + if (ResultTy.isNull() || lhs.isInvalid() || rhs.isInvalid()) return ExprError(); if (CompResultTy.isNull()) - return Owned(new (Context) BinaryOperator(lhs, rhs, Opc, ResultTy, - VK, OK, OpLoc)); - - if (getLangOptions().CPlusPlus && lhs->getObjectKind() != OK_ObjCProperty) { + return Owned(new (Context) BinaryOperator(lhs.take(), rhs.take(), Opc, + ResultTy, VK, OK, OpLoc)); + if (getLangOptions().CPlusPlus && lhs.get()->getObjectKind() != OK_ObjCProperty) { VK = VK_LValue; - OK = lhs->getObjectKind(); + OK = lhs.get()->getObjectKind(); } - return Owned(new (Context) CompoundAssignOperator(lhs, rhs, Opc, ResultTy, - VK, OK, CompLHSTy, + return Owned(new (Context) CompoundAssignOperator(lhs.take(), rhs.take(), Opc, + ResultTy, VK, OK, CompLHSTy, CompResultTy, OpLoc)); } @@ -8161,23 +8746,23 @@ static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperatorKind Opc, Self.PDiag(diag::warn_precedence_bitwise_rel) << SourceRange(lhs->getLocStart(), OpLoc) << BinOp::getOpcodeStr(Opc) << BinOp::getOpcodeStr(lhsopc), - Self.PDiag(diag::note_precedence_bitwise_first) - << BinOp::getOpcodeStr(Opc), - SourceRange(cast<BinOp>(lhs)->getRHS()->getLocStart(), rhs->getLocEnd()), Self.PDiag(diag::note_precedence_bitwise_silence) << BinOp::getOpcodeStr(lhsopc), - lhs->getSourceRange()); + lhs->getSourceRange(), + Self.PDiag(diag::note_precedence_bitwise_first) + << BinOp::getOpcodeStr(Opc), + SourceRange(cast<BinOp>(lhs)->getRHS()->getLocStart(), rhs->getLocEnd())); else if (BinOp::isComparisonOp(rhsopc)) SuggestParentheses(Self, OpLoc, Self.PDiag(diag::warn_precedence_bitwise_rel) << SourceRange(OpLoc, rhs->getLocEnd()) << BinOp::getOpcodeStr(Opc) << BinOp::getOpcodeStr(rhsopc), + Self.PDiag(diag::note_precedence_bitwise_silence) + << BinOp::getOpcodeStr(rhsopc), + rhs->getSourceRange(), Self.PDiag(diag::note_precedence_bitwise_first) << BinOp::getOpcodeStr(Opc), - SourceRange(lhs->getLocEnd(), cast<BinOp>(rhs)->getLHS()->getLocStart()), - Self.PDiag(diag::note_precedence_bitwise_silence) - << BinOp::getOpcodeStr(rhsopc), - rhs->getSourceRange()); + SourceRange(lhs->getLocEnd(), cast<BinOp>(rhs)->getLHS()->getLocStart())); } /// \brief It accepts a '&&' expr that is inside a '||' one. @@ -8185,14 +8770,13 @@ static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperatorKind Opc, /// in parentheses. static void EmitDiagnosticForLogicalAndInLogicalOr(Sema &Self, SourceLocation OpLoc, - Expr *E) { - assert(isa<BinaryOperator>(E) && - cast<BinaryOperator>(E)->getOpcode() == BO_LAnd); - SuggestParentheses(Self, OpLoc, + BinaryOperator *Bop) { + assert(Bop->getOpcode() == BO_LAnd); + SuggestParentheses(Self, Bop->getOperatorLoc(), Self.PDiag(diag::warn_logical_and_in_logical_or) - << E->getSourceRange(), + << Bop->getSourceRange() << OpLoc, Self.PDiag(diag::note_logical_and_in_logical_or_silence), - E->getSourceRange(), + Bop->getSourceRange(), Self.PDiag(0), SourceRange()); } @@ -8316,7 +8900,8 @@ ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc, ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, - Expr *Input) { + Expr *InputExpr) { + ExprResult Input = Owned(InputExpr); ExprValueKind VK = VK_RValue; ExprObjectKind OK = OK_Ordinary; QualType resultType; @@ -8325,23 +8910,28 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, case UO_PreDec: case UO_PostInc: case UO_PostDec: - resultType = CheckIncrementDecrementOperand(*this, Input, VK, OpLoc, + 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); + resultType = CheckAddressOfOperand(*this, Input.get(), OpLoc); break; - case UO_Deref: - DefaultFunctionArrayLvalueConversion(Input); - resultType = CheckIndirectionOperand(*this, Input, VK, OpLoc); + case UO_Deref: { + ExprResult resolved = CheckPlaceholderExpr(Input.get()); + if (!resolved.isUsable()) return ExprError(); + Input = move(resolved); + Input = DefaultFunctionArrayLvalueConversion(Input.take()); + resultType = CheckIndirectionOperand(*this, Input.get(), VK, OpLoc); break; + } case UO_Plus: case UO_Minus: - UsualUnaryConversions(Input); - resultType = Input->getType(); + 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 @@ -8355,49 +8945,59 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, resultType->isPointerType()) break; else if (resultType->isPlaceholderType()) { - ExprResult PR = CheckPlaceholderExpr(Input, OpLoc); - if (PR.isInvalid()) return ExprError(); - return CreateBuiltinUnaryOp(OpLoc, Opc, PR.take()); + Input = CheckPlaceholderExpr(Input.take()); + if (Input.isInvalid()) return ExprError(); + return CreateBuiltinUnaryOp(OpLoc, Opc, Input.take()); } return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) - << resultType << Input->getSourceRange()); + << resultType << Input.get()->getSourceRange()); + case UO_Not: // bitwise complement - UsualUnaryConversions(Input); - resultType = Input->getType(); + 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->getSourceRange(); + << resultType << Input.get()->getSourceRange(); else if (resultType->hasIntegerRepresentation()) break; else if (resultType->isPlaceholderType()) { - ExprResult PR = CheckPlaceholderExpr(Input, OpLoc); - if (PR.isInvalid()) return ExprError(); - return CreateBuiltinUnaryOp(OpLoc, Opc, PR.take()); + Input = CheckPlaceholderExpr(Input.take()); + if (Input.isInvalid()) return ExprError(); + return CreateBuiltinUnaryOp(OpLoc, Opc, Input.take()); } else { return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) - << resultType << Input->getSourceRange()); + << resultType << Input.get()->getSourceRange()); } break; + case UO_LNot: // logical negation // Unlike +/-/~, integer promotions aren't done here (C99 6.5.3.3p5). - DefaultFunctionArrayLvalueConversion(Input); - resultType = Input->getType(); + Input = DefaultFunctionArrayLvalueConversion(Input.take()); + if (Input.isInvalid()) return ExprError(); + resultType = Input.get()->getType(); if (resultType->isDependentType()) break; - if (resultType->isScalarType()) { // C99 6.5.3.3p1 - // ok, fallthrough + if (resultType->isScalarType()) { + // C99 6.5.3.3p1: ok, fallthrough; + if (Context.getLangOptions().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->isPlaceholderType()) { - ExprResult PR = CheckPlaceholderExpr(Input, OpLoc); - if (PR.isInvalid()) return ExprError(); - return CreateBuiltinUnaryOp(OpLoc, Opc, PR.take()); + Input = CheckPlaceholderExpr(Input.take()); + if (Input.isInvalid()) return ExprError(); + return CreateBuiltinUnaryOp(OpLoc, Opc, Input.take()); } else { return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) - << resultType << Input->getSourceRange()); + << resultType << Input.get()->getSourceRange()); } // LNot always has type int. C99 6.5.3.3p5. @@ -8408,20 +9008,21 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, case UO_Imag: resultType = CheckRealImagOperand(*this, Input, OpLoc, Opc == UO_Real); // _Real and _Imag map ordinary l-values into ordinary l-values. - if (Input->getValueKind() != VK_RValue && - Input->getObjectKind() == OK_Ordinary) - VK = Input->getValueKind(); + if (Input.isInvalid()) return ExprError(); + if (Input.get()->getValueKind() != VK_RValue && + Input.get()->getObjectKind() == OK_Ordinary) + VK = Input.get()->getValueKind(); break; case UO_Extension: - resultType = Input->getType(); - VK = Input->getValueKind(); - OK = Input->getObjectKind(); + resultType = Input.get()->getType(); + VK = Input.get()->getValueKind(); + OK = Input.get()->getObjectKind(); break; } - if (resultType.isNull()) + if (resultType.isNull() || Input.isInvalid()) return ExprError(); - return Owned(new (Context) UnaryOperator(Input, Opc, resultType, + return Owned(new (Context) UnaryOperator(Input.take(), Opc, resultType, VK, OK, OpLoc)); } @@ -8488,26 +9089,28 @@ Sema::ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt, LastLabelStmt = Label; LastStmt = Label->getSubStmt(); } - if (Expr *LastExpr = dyn_cast<Expr>(LastStmt)) { + if (Expr *LastE = dyn_cast<Expr>(LastStmt)) { // Do function/array conversion on the last expression, but not // lvalue-to-rvalue. However, initialize an unqualified type. - DefaultFunctionArrayConversion(LastExpr); - Ty = LastExpr->getType().getUnqualifiedType(); + ExprResult LastExpr = DefaultFunctionArrayConversion(LastE); + if (LastExpr.isInvalid()) + return ExprError(); + Ty = LastExpr.get()->getType().getUnqualifiedType(); - if (!Ty->isDependentType() && !LastExpr->isTypeDependent()) { - ExprResult Res = PerformCopyInitialization( + if (!Ty->isDependentType() && !LastExpr.get()->isTypeDependent()) { + LastExpr = PerformCopyInitialization( InitializedEntity::InitializeResult(LPLoc, Ty, false), SourceLocation(), - Owned(LastExpr)); - if (Res.isInvalid()) + LastExpr); + if (LastExpr.isInvalid()) return ExprError(); - if ((LastExpr = Res.takeAs<Expr>())) { + if (LastExpr.get() != 0) { if (!LastLabelStmt) - Compound->setLastStmt(LastExpr); + Compound->setLastStmt(LastExpr.take()); else - LastLabelStmt->setSubStmt(LastExpr); + LastLabelStmt->setSubStmt(LastExpr.take()); StmtExprMayBindToTemp = true; } } @@ -8779,8 +9382,8 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) { // Check whether that explicit signature was synthesized by // GetTypeForDeclarator. If so, don't save that as part of the // written signature. - if (ExplicitSignature.getLParenLoc() == - ExplicitSignature.getRParenLoc()) { + if (ExplicitSignature.getLocalRangeBegin() == + ExplicitSignature.getLocalRangeEnd()) { // This would be much cheaper if we stored TypeLocs instead of // TypeSourceInfos. TypeLoc Result = ExplicitSignature.getResultLoc(); @@ -8942,7 +9545,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, // If we don't have a function type, just build one from nothing. } else { FunctionProtoType::ExtProtoInfo EPI; - EPI.ExtInfo = FunctionType::ExtInfo(NoReturn, 0, CC_Default); + EPI.ExtInfo = FunctionType::ExtInfo(NoReturn, false, 0, CC_Default); BlockTy = Context.getFunctionType(RetTy, 0, 0, EPI); } @@ -8984,7 +9587,10 @@ ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc, // a pointer for va_arg. VaListType = Context.getArrayDecayedType(VaListType); // Make sure the input expression also decays appropriately. - UsualUnaryConversions(E); + 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. @@ -9260,6 +9866,8 @@ Sema::PopExpressionEvaluationContext() { void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) { assert(D && "No declaration?"); + D->setReferenced(); + if (D->isUsed(false)) return; @@ -9393,6 +10001,9 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) { if (MSInfo->getPointOfInstantiation().isInvalid() && MSInfo->getTemplateSpecializationKind()== TSK_ImplicitInstantiation) { MSInfo->setPointOfInstantiation(Loc); + // This is a modification of an existing AST node. Notify listeners. + if (ASTMutationListener *L = getASTMutationListener()) + L->StaticDataMemberInstantiated(Var); PendingInstantiations.push_back(std::make_pair(Var, Loc)); } } @@ -9624,10 +10235,13 @@ void Sema::DiagnoseAssignmentAsCondition(Expr *E) { return; } + Diag(Loc, diagnostic) << E->getSourceRange(); + SourceLocation Open = E->getSourceRange().getBegin(); SourceLocation Close = PP.getLocForEndOfToken(E->getSourceRange().getEnd()); - - Diag(Loc, diagnostic) << E->getSourceRange(); + Diag(Loc, diag::note_condition_assign_silence) + << FixItHint::CreateInsertion(Open, "(") + << FixItHint::CreateInsertion(Close, ")"); if (IsOrAssign) Diag(Loc, diag::note_condition_or_assign_to_comparison) @@ -9635,10 +10249,6 @@ void Sema::DiagnoseAssignmentAsCondition(Expr *E) { else Diag(Loc, diag::note_condition_assign_to_comparison) << FixItHint::CreateReplacement(Loc, "=="); - - Diag(Loc, diag::note_condition_assign_silence) - << FixItHint::CreateInsertion(Open, "(") - << FixItHint::CreateInsertion(Close, ")"); } /// \brief Redundant parentheses over an equality comparison can indicate @@ -9648,6 +10258,9 @@ void Sema::DiagnoseEqualityWithExtraParens(ParenExpr *parenE) { SourceLocation parenLoc = parenE->getLocStart(); if (parenLoc.isInvalid() || parenLoc.isMacroID()) return; + // Don't warn for dependent expressions. + if (parenE->isTypeDependent()) + return; Expr *E = parenE->IgnoreParens(); @@ -9658,68 +10271,467 @@ void Sema::DiagnoseEqualityWithExtraParens(ParenExpr *parenE) { SourceLocation Loc = opE->getOperatorLoc(); Diag(Loc, diag::warn_equality_with_extra_parens) << E->getSourceRange(); - Diag(Loc, diag::note_equality_comparison_to_assign) - << FixItHint::CreateReplacement(Loc, "="); Diag(Loc, diag::note_equality_comparison_silence) << FixItHint::CreateRemoval(parenE->getSourceRange().getBegin()) << FixItHint::CreateRemoval(parenE->getSourceRange().getEnd()); + Diag(Loc, diag::note_equality_comparison_to_assign) + << FixItHint::CreateReplacement(Loc, "="); } } -bool Sema::CheckBooleanCondition(Expr *&E, SourceLocation Loc) { +ExprResult Sema::CheckBooleanCondition(Expr *E, SourceLocation Loc) { DiagnoseAssignmentAsCondition(E); if (ParenExpr *parenE = dyn_cast<ParenExpr>(E)) DiagnoseEqualityWithExtraParens(parenE); - if (!E->isTypeDependent()) { - if (E->isBoundMemberFunction(Context)) - return Diag(E->getLocStart(), diag::err_invalid_use_of_bound_member_func) - << E->getSourceRange(); + ExprResult result = CheckPlaceholderExpr(E); + if (result.isInvalid()) return ExprError(); + E = result.take(); + if (!E->isTypeDependent()) { if (getLangOptions().CPlusPlus) return CheckCXXBooleanCondition(E); // C++ 6.4p4 - DefaultFunctionArrayLvalueConversion(E); + ExprResult ERes = DefaultFunctionArrayLvalueConversion(E); + if (ERes.isInvalid()) + return ExprError(); + E = ERes.take(); QualType T = E->getType(); - if (!T->isScalarType()) // C99 6.8.4.1p1 - return Diag(Loc, diag::err_typecheck_statement_requires_scalar) - << T << E->getSourceRange(); + if (!T->isScalarType()) { // C99 6.8.4.1p1 + Diag(Loc, diag::err_typecheck_statement_requires_scalar) + << T << E->getSourceRange(); + return ExprError(); + } } - return false; + return Owned(E); } ExprResult Sema::ActOnBooleanCondition(Scope *S, SourceLocation Loc, Expr *Sub) { if (!Sub) return ExprError(); - - if (CheckBooleanCondition(Sub, Loc)) + + return CheckBooleanCondition(Sub, Loc); +} + +namespace { + /// A visitor for rebuilding a call to an __unknown_any expression + /// to have an appropriate type. + struct RebuildUnknownAnyFunction + : StmtVisitor<RebuildUnknownAnyFunction, ExprResult> { + + Sema &S; + + RebuildUnknownAnyFunction(Sema &S) : S(S) {} + + ExprResult VisitStmt(Stmt *S) { + llvm_unreachable("unexpected statement!"); + return ExprError(); + } + + ExprResult VisitExpr(Expr *expr) { + S.Diag(expr->getExprLoc(), diag::err_unsupported_unknown_any_call) + << expr->getSourceRange(); + return ExprError(); + } + + /// Rebuild an expression which simply semantically wraps another + /// expression which it shares the type and value kind of. + template <class T> ExprResult rebuildSugarExpr(T *expr) { + ExprResult subResult = Visit(expr->getSubExpr()); + if (subResult.isInvalid()) return ExprError(); + + Expr *subExpr = subResult.take(); + expr->setSubExpr(subExpr); + expr->setType(subExpr->getType()); + expr->setValueKind(subExpr->getValueKind()); + assert(expr->getObjectKind() == OK_Ordinary); + return expr; + } + + ExprResult VisitParenExpr(ParenExpr *paren) { + return rebuildSugarExpr(paren); + } + + ExprResult VisitUnaryExtension(UnaryOperator *op) { + return rebuildSugarExpr(op); + } + + ExprResult VisitUnaryAddrOf(UnaryOperator *op) { + ExprResult subResult = Visit(op->getSubExpr()); + if (subResult.isInvalid()) return ExprError(); + + Expr *subExpr = subResult.take(); + op->setSubExpr(subExpr); + op->setType(S.Context.getPointerType(subExpr->getType())); + assert(op->getValueKind() == VK_RValue); + assert(op->getObjectKind() == OK_Ordinary); + return op; + } + + ExprResult resolveDecl(Expr *expr, ValueDecl *decl) { + if (!isa<FunctionDecl>(decl)) return VisitExpr(expr); + + expr->setType(decl->getType()); + + assert(expr->getValueKind() == VK_RValue); + if (S.getLangOptions().CPlusPlus && + !(isa<CXXMethodDecl>(decl) && + cast<CXXMethodDecl>(decl)->isInstance())) + expr->setValueKind(VK_LValue); + + return expr; + } + + ExprResult VisitMemberExpr(MemberExpr *mem) { + return resolveDecl(mem, mem->getMemberDecl()); + } + + ExprResult VisitDeclRefExpr(DeclRefExpr *ref) { + return resolveDecl(ref, ref->getDecl()); + } + }; +} + +/// Given a function expression of unknown-any type, try to rebuild it +/// to have a function type. +static ExprResult rebuildUnknownAnyFunction(Sema &S, Expr *fn) { + ExprResult result = RebuildUnknownAnyFunction(S).Visit(fn); + 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<RebuildUnknownAnyExpr, ExprResult> { + + 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!"); + return ExprError(); + } + + ExprResult VisitExpr(Expr *expr) { + S.Diag(expr->getExprLoc(), diag::err_unsupported_unknown_any_expr) + << expr->getSourceRange(); + return ExprError(); + } + + ExprResult VisitCallExpr(CallExpr *call); + ExprResult VisitObjCMessageExpr(ObjCMessageExpr *message); + + /// Rebuild an expression which simply semantically wraps another + /// expression which it shares the type and value kind of. + template <class T> ExprResult rebuildSugarExpr(T *expr) { + ExprResult subResult = Visit(expr->getSubExpr()); + if (subResult.isInvalid()) return ExprError(); + Expr *subExpr = subResult.take(); + expr->setSubExpr(subExpr); + expr->setType(subExpr->getType()); + expr->setValueKind(subExpr->getValueKind()); + assert(expr->getObjectKind() == OK_Ordinary); + return expr; + } + + ExprResult VisitParenExpr(ParenExpr *paren) { + return rebuildSugarExpr(paren); + } + + ExprResult VisitUnaryExtension(UnaryOperator *op) { + return rebuildSugarExpr(op); + } + + ExprResult VisitUnaryAddrOf(UnaryOperator *op) { + const PointerType *ptr = DestType->getAs<PointerType>(); + if (!ptr) { + S.Diag(op->getOperatorLoc(), diag::err_unknown_any_addrof) + << op->getSourceRange(); + return ExprError(); + } + assert(op->getValueKind() == VK_RValue); + assert(op->getObjectKind() == OK_Ordinary); + op->setType(DestType); + + // Build the sub-expression as if it were an object of the pointee type. + DestType = ptr->getPointeeType(); + ExprResult subResult = Visit(op->getSubExpr()); + if (subResult.isInvalid()) return ExprError(); + op->setSubExpr(subResult.take()); + return op; + } + + ExprResult VisitImplicitCastExpr(ImplicitCastExpr *ice); + + ExprResult resolveDecl(Expr *expr, ValueDecl *decl); + + ExprResult VisitMemberExpr(MemberExpr *mem) { + return resolveDecl(mem, mem->getMemberDecl()); + } + + ExprResult VisitDeclRefExpr(DeclRefExpr *ref) { + return resolveDecl(ref, ref->getDecl()); + } + }; +} + +/// Rebuilds a call expression which yielded __unknown_anytype. +ExprResult RebuildUnknownAnyExpr::VisitCallExpr(CallExpr *call) { + Expr *callee = call->getCallee(); + + enum FnKind { + FK_MemberFunction, + FK_FunctionPointer, + FK_BlockPointer + }; + + FnKind kind; + QualType type = callee->getType(); + if (type == S.Context.BoundMemberTy) { + assert(isa<CXXMemberCallExpr>(call) || isa<CXXOperatorCallExpr>(call)); + kind = FK_MemberFunction; + type = Expr::findBoundMemberType(callee); + } else if (const PointerType *ptr = type->getAs<PointerType>()) { + type = ptr->getPointeeType(); + kind = FK_FunctionPointer; + } else { + type = type->castAs<BlockPointerType>()->getPointeeType(); + kind = FK_BlockPointer; + } + const FunctionType *fnType = type->castAs<FunctionType>(); + + // 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(call->getExprLoc(), diagID) + << DestType->isFunctionType() << DestType; return ExprError(); - - return Owned(Sub); + } + + // Otherwise, go ahead and set DestType as the call's result. + call->setType(DestType.getNonLValueExprType(S.Context)); + call->setValueKind(Expr::getValueKindForType(DestType)); + assert(call->getObjectKind() == OK_Ordinary); + + // Rebuild the function type, replacing the result type with DestType. + if (const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(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(callee); + if (!calleeResult.isUsable()) return ExprError(); + call->setCallee(calleeResult.take()); + + // Bind a temporary if necessary. + return S.MaybeBindToTemporary(call); } -/// 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, SourceLocation Loc) { - const BuiltinType *BT = E->getType()->getAs<BuiltinType>(); - if (!BT || !BT->isPlaceholderType()) return Owned(E); - - // If this is overload, check for a single overload. - assert(BT->getKind() == BuiltinType::Overload); - - if (FunctionDecl *Specialization - = ResolveSingleFunctionTemplateSpecialization(E)) { - // The access doesn't really matter in this case. - DeclAccessPair Found = DeclAccessPair::make(Specialization, - Specialization->getAccess()); - E = FixOverloadedFunctionReference(E, Found, Specialization); - if (!E) return ExprError(); - return Owned(E); +ExprResult RebuildUnknownAnyExpr::VisitObjCMessageExpr(ObjCMessageExpr *msg) { + ObjCMethodDecl *method = msg->getMethodDecl(); + assert(method && "__unknown_anytype message without result type?"); + + // Verify that this is a legal result type of a call. + if (DestType->isArrayType() || DestType->isFunctionType()) { + S.Diag(msg->getExprLoc(), diag::err_func_returning_array_function) + << DestType->isFunctionType() << DestType; + return ExprError(); } - Diag(Loc, diag::err_ovl_unresolvable) << E->getSourceRange(); + assert(method->getResultType() == S.Context.UnknownAnyTy); + method->setResultType(DestType); + + // Change the type of the message. + msg->setType(DestType.getNonReferenceType()); + msg->setValueKind(Expr::getValueKindForType(DestType)); + + return S.MaybeBindToTemporary(msg); +} + +ExprResult RebuildUnknownAnyExpr::VisitImplicitCastExpr(ImplicitCastExpr *ice) { + // The only case we should ever see here is a function-to-pointer decay. + assert(ice->getCastKind() == CK_FunctionToPointerDecay); + assert(ice->getValueKind() == VK_RValue); + assert(ice->getObjectKind() == OK_Ordinary); + + ice->setType(DestType); + + // Rebuild the sub-expression as the pointee (function) type. + DestType = DestType->castAs<PointerType>()->getPointeeType(); + + ExprResult result = Visit(ice->getSubExpr()); + if (!result.isUsable()) return ExprError(); + + ice->setSubExpr(result.take()); + return S.Owned(ice); +} + +ExprResult RebuildUnknownAnyExpr::resolveDecl(Expr *expr, ValueDecl *decl) { + ExprValueKind valueKind = VK_LValue; + QualType type = DestType; + + // We know how to make this work for certain kinds of decls: + + // - functions + if (FunctionDecl *fn = dyn_cast<FunctionDecl>(decl)) { + // This is true because FunctionDecls must always have function + // type, so we can't be resolving the entire thing at once. + assert(type->isFunctionType()); + + if (CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(fn)) + if (method->isInstance()) { + valueKind = VK_RValue; + type = S.Context.BoundMemberTy; + } + + // Function references aren't l-values in C. + if (!S.getLangOptions().CPlusPlus) + valueKind = VK_RValue; + + // - variables + } else if (isa<VarDecl>(decl)) { + if (const ReferenceType *refTy = type->getAs<ReferenceType>()) { + type = refTy->getPointeeType(); + } else if (type->isFunctionType()) { + S.Diag(expr->getExprLoc(), diag::err_unknown_any_var_function_type) + << decl << expr->getSourceRange(); + return ExprError(); + } + + // - nothing else + } else { + S.Diag(expr->getExprLoc(), diag::err_unsupported_unknown_any_decl) + << decl << expr->getSourceRange(); + return ExprError(); + } + + decl->setType(DestType); + expr->setType(type); + expr->setValueKind(valueKind); + return S.Owned(expr); +} + +/// 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; +} + +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<CallExpr>(e)) { + e = call->getCallee(); + diagID = diag::err_uncasted_call_of_unknown_any; + } else { + break; + } + } + + SourceLocation loc; + NamedDecl *d; + if (DeclRefExpr *ref = dyn_cast<DeclRefExpr>(e)) { + loc = ref->getLocation(); + d = ref->getDecl(); + } else if (MemberExpr *mem = dyn_cast<MemberExpr>(e)) { + loc = mem->getMemberLoc(); + d = mem->getMemberDecl(); + } else if (ObjCMessageExpr *msg = dyn_cast<ObjCMessageExpr>(e)) { + diagID = diag::err_uncasted_call_of_unknown_any; + loc = msg->getSelectorLoc(); + d = msg->getMethodDecl(); + assert(d && "unknown method returning __unknown_any?"); + } 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) { + // Placeholder types are always *exactly* the appropriate builtin type. + QualType type = E->getType(); + + // Overloaded expressions. + if (type == Context.OverloadTy) + return ResolveAndFixSingleFunctionTemplateSpecialization(E, false, true, + E->getSourceRange(), + QualType(), + diag::err_ovl_unresolvable); + + // Bound member functions. + if (type == Context.BoundMemberTy) { + Diag(E->getLocStart(), diag::err_invalid_use_of_bound_member_func) + << E->getSourceRange(); + return ExprError(); + } + + // Expressions of unknown type. + if (type == Context.UnknownAnyTy) + return diagnoseUnknownAnyExpr(*this, E); + + assert(!type->isPlaceholderType()); + return Owned(E); +} + +bool Sema::CheckCaseExpression(Expr *expr) { + if (expr->isTypeDependent()) + return true; + if (expr->isValueDependent() || expr->isIntegerConstantExpr(Context)) + return expr->getType()->isIntegralOrEnumerationType(); + return false; +} diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp index 6dd7aab..7f1bf59 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp @@ -28,6 +28,7 @@ #include "clang/Basic/TargetInfo.h" #include "clang/Lex/Preprocessor.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/Support/ErrorHandling.h" using namespace clang; using namespace sema; @@ -138,10 +139,11 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc, 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 sope (if + // 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) @@ -164,6 +166,9 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc, return ParsedType::make(T); } + + if (!SearchType.isNull()) + NonMatchingTypeDecl = Type; } // If the name that we found is a class template name, and it is @@ -236,24 +241,22 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc, if (isDependent) { // We didn't find our type, but that's okay: it's dependent // anyway. - NestedNameSpecifier *NNS = 0; - SourceRange Range; - if (SS.isSet()) { - NNS = (NestedNameSpecifier *)SS.getScopeRep(); - Range = SourceRange(SS.getRange().getBegin(), NameLoc); - } else { - NNS = NestedNameSpecifier::Create(Context, &II); - Range = SourceRange(NameLoc); - } - - QualType T = CheckTypenameType(ETK_None, NNS, II, - SourceLocation(), - Range, NameLoc); + + // 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 (ObjectTypePtr) - Diag(NameLoc, diag::err_ident_in_pseudo_dtor_not_a_type) + 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); @@ -321,7 +324,7 @@ ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType, QualType UnqualT = Context.getUnqualifiedArrayType(T, Quals); if (!Context.hasSameType(T, UnqualT)) { T = UnqualT; - ImpCastExprToType(E, UnqualT, CK_NoOp, CastCategory(E)); + E = ImpCastExprToType(E, UnqualT, CK_NoOp, CastCategory(E)).take(); } } @@ -341,7 +344,7 @@ ExprResult Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc, bool isType, void *TyOrExpr, SourceLocation RParenLoc) { // Find the std::type_info type. - if (!StdNamespace) + if (!getStdNamespace()) return ExprError(Diag(OpLoc, diag::err_need_header_before_typeid)); if (!CXXTypeInfoDecl) { @@ -477,17 +480,21 @@ Sema::ActOnCXXNullPtrLiteral(SourceLocation Loc) { ExprResult Sema::ActOnCXXThrow(SourceLocation OpLoc, Expr *Ex) { // Don't report an error if 'throw' is used in system headers. - if (!getLangOptions().Exceptions && + if (!getLangOptions().CXXExceptions && !getSourceManager().isInSystemHeader(OpLoc)) Diag(OpLoc, diag::err_exceptions_disabled) << "throw"; - if (Ex && !Ex->isTypeDependent() && CheckCXXThrowOperand(OpLoc, Ex)) - return ExprError(); + if (Ex && !Ex->isTypeDependent()) { + ExprResult ExRes = CheckCXXThrowOperand(OpLoc, Ex); + if (ExRes.isInvalid()) + return ExprError(); + Ex = ExRes.take(); + } return Owned(new (Context) CXXThrowExpr(Ex, Context.VoidTy, OpLoc)); } /// CheckCXXThrowOperand - Validate the operand of a throw. -bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *&E) { +ExprResult Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *E) { // 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 @@ -495,10 +502,13 @@ bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *&E) { // the type from "array of T" or "function returning T" to "pointer to T" // or "pointer to function returning T", [...] if (E->getType().hasQualifiers()) - ImpCastExprToType(E, E->getType().getUnqualifiedType(), CK_NoOp, - CastCategory(E)); + E = ImpCastExprToType(E, E->getType().getUnqualifiedType(), CK_NoOp, + CastCategory(E)).take(); - DefaultFunctionArrayConversion(E); + 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. @@ -513,12 +523,12 @@ bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *&E) { PDiag(isPointer ? diag::err_throw_incomplete_ptr : diag::err_throw_incomplete) << E->getSourceRange())) - return true; + return ExprError(); if (RequireNonAbstractType(ThrowLoc, E->getType(), PDiag(diag::err_throw_abstract_type) << E->getSourceRange())) - return true; + return ExprError(); } // Initialize the exception result. This implicitly weeds out @@ -529,16 +539,16 @@ bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *&E) { InitializedEntity Entity = InitializedEntity::InitializeException(ThrowLoc, E->getType(), /*NRVO=*/false); - ExprResult Res = PerformMoveOrCopyInitialization(Entity, NRVOVariable, - QualType(), E); + Res = PerformMoveOrCopyInitialization(Entity, NRVOVariable, + QualType(), E); if (Res.isInvalid()) - return true; - E = Res.takeAs<Expr>(); + return ExprError(); + E = Res.take(); // If the exception has class type, we need additional handling. const RecordType *RecordTy = Ty->getAs<RecordType>(); if (!RecordTy) - return false; + return Owned(E); CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl()); // If we are throwing a polymorphic class type or pointer thereof, @@ -547,21 +557,21 @@ bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *&E) { // If a pointer is thrown, the referenced object will not be destroyed. if (isPointer) - return false; + return Owned(E); // If the class has a non-trivial destructor, we must be able to call it. if (RD->hasTrivialDestructor()) - return false; + return Owned(E); CXXDestructorDecl *Destructor = const_cast<CXXDestructorDecl*>(LookupDestructor(RD)); if (!Destructor) - return false; + return Owned(E); MarkDeclarationReferenced(E->getExprLoc(), Destructor); CheckDestructorAccess(E->getExprLoc(), Destructor, PDiag(diag::err_access_dtor_exception) << Ty); - return false; + return Owned(E); } CXXMethodDecl *Sema::tryCaptureCXXThis() { @@ -666,10 +676,13 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, CastKind Kind = CK_Invalid; ExprValueKind VK = VK_RValue; CXXCastPath BasePath; - if (CheckCastTypes(TInfo->getTypeLoc().getSourceRange(), Ty, Exprs[0], - Kind, VK, BasePath, - /*FunctionalStyle=*/true)) + ExprResult CastExpr = + CheckCastTypes(TInfo->getTypeLoc().getSourceRange(), Ty, Exprs[0], + Kind, VK, BasePath, + /*FunctionalStyle=*/true); + if (CastExpr.isInvalid()) return ExprError(); + Exprs[0] = CastExpr.take(); exprs.release(); @@ -846,16 +859,18 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, diag::err_auto_new_ctor_multiple_expressions) << AllocType << TypeRange); } - QualType DeducedType; - if (!DeduceAutoType(AllocType, ConstructorArgs.get()[0], DeducedType)) + TypeSourceInfo *DeducedType = 0; + if (!DeduceAutoType(AllocTypeInfo, ConstructorArgs.get()[0], DeducedType)) return ExprError(Diag(StartLoc, diag::err_auto_new_deduction_failure) << AllocType << ConstructorArgs.get()[0]->getType() << TypeRange << ConstructorArgs.get()[0]->getSourceRange()); + if (!DeducedType) + return ExprError(); - AllocType = DeducedType; - AllocTypeInfo = Context.getTrivialTypeSourceInfo(AllocType, StartLoc); + AllocTypeInfo = DeducedType; + AllocType = AllocTypeInfo->getType(); } // Per C++0x [expr.new]p5, the type being constructed may be a @@ -935,8 +950,8 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, } } - ImpCastExprToType(ArraySize, Context.getSizeType(), - CK_IntegralCast); + ArraySize = ImpCastExprToType(ArraySize, Context.getSizeType(), + CK_IntegralCast).take(); } FunctionDecl *OperatorNew = 0; @@ -1090,7 +1105,10 @@ bool Sema::CheckAllocatedType(QualType AllocType, SourceLocation Loc, 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; + return false; } @@ -1384,16 +1402,16 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range, Candidates.NoteCandidates(*this, OCD_ViableCandidates, Args, NumArgs); return true; - case OR_Deleted: + case OR_Deleted: { Diag(StartLoc, diag::err_ovl_deleted_call) << Best->Function->isDeleted() << Name - << Best->Function->getMessageUnavailableAttr( - !Best->Function->isDeleted()) + << getDeletedOrUnavailableSuffix(Best->Function) << Range; Candidates.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); return true; } + } assert(false && "Unreachable, bad result from BestViableFunction"); return true; } @@ -1402,11 +1420,18 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range, /// 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 \<new\>. void Sema::DeclareGlobalNewDelete() { @@ -1418,10 +1443,16 @@ void Sema::DeclareGlobalNewDelete() { // 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[]. @@ -1430,14 +1461,16 @@ void Sema::DeclareGlobalNewDelete() { // "std" or "bad_alloc" as necessary to form the exception specification. // However, we do not make these implicit declarations visible to name // lookup. - if (!StdBadAlloc) { + // Note that the C++0x versions of operator delete are deallocation functions, + // and thus are implicitly noexcept. + if (!StdBadAlloc && !getLangOptions().CPlusPlus0x) { // The "std::bad_alloc" class has not yet been declared, so build it // implicitly. StdBadAlloc = CXXRecordDecl::Create(Context, TTK_Class, getOrCreateStdNamespace(), - SourceLocation(), + SourceLocation(), SourceLocation(), &PP.getIdentifierTable().get("bad_alloc"), - SourceLocation(), 0); + 0); getStdBadAlloc()->setImplicit(true); } @@ -1493,21 +1526,27 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, bool HasBadAllocExceptionSpec = (Name.getCXXOverloadedOperator() == OO_New || Name.getCXXOverloadedOperator() == OO_Array_New); - if (HasBadAllocExceptionSpec) { + if (HasBadAllocExceptionSpec && !getLangOptions().CPlusPlus0x) { assert(StdBadAlloc && "Must have std::bad_alloc declared"); BadAllocType = Context.getTypeDeclType(getStdBadAlloc()); } FunctionProtoType::ExtProtoInfo EPI; - EPI.HasExceptionSpec = true; if (HasBadAllocExceptionSpec) { - EPI.NumExceptions = 1; - EPI.Exceptions = &BadAllocType; + if (!getLangOptions().CPlusPlus0x) { + EPI.ExceptionSpecType = EST_Dynamic; + EPI.NumExceptions = 1; + EPI.Exceptions = &BadAllocType; + } + } else { + EPI.ExceptionSpecType = getLangOptions().CPlusPlus0x ? + EST_BasicNoexcept : EST_DynamicNone; } QualType FnType = Context.getFunctionType(Return, &Argument, 1, EPI); FunctionDecl *Alloc = - FunctionDecl::Create(Context, GlobalCtx, SourceLocation(), Name, + FunctionDecl::Create(Context, GlobalCtx, SourceLocation(), + SourceLocation(), Name, FnType, /*TInfo=*/0, SC_None, SC_None, false, true); Alloc->setImplicit(); @@ -1516,9 +1555,9 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, Alloc->addAttr(::new (Context) MallocAttr(SourceLocation(), Context)); ParmVarDecl *Param = ParmVarDecl::Create(Context, Alloc, SourceLocation(), - 0, Argument, /*TInfo=*/0, - SC_None, - SC_None, 0); + SourceLocation(), 0, + Argument, /*TInfo=*/0, + SC_None, SC_None, 0); Alloc->setParams(&Param, 1); // FIXME: Also add this declaration to the IdentifierResolver, but @@ -1608,19 +1647,20 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, /// @code delete [] ptr; @endcode ExprResult Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, - bool ArrayForm, Expr *Ex) { + 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->isTypeDependent()) { - QualType Type = Ex->getType(); + if (!Ex.get()->isTypeDependent()) { + QualType Type = Ex.get()->getType(); if (const RecordType *Record = Type->getAs<RecordType>()) { if (RequireCompleteType(StartLoc, Type, @@ -1652,15 +1692,18 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, // We have a single conversion to a pointer-to-object type. Perform // that conversion. // TODO: don't redo the conversion calculation. - if (!PerformImplicitConversion(Ex, + ExprResult Res = + PerformImplicitConversion(Ex.get(), ObjectPtrConversions.front()->getConversionType(), - AA_Converting)) { - Type = Ex->getType(); + 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->getSourceRange(); + << Type << Ex.get()->getSourceRange(); for (unsigned i= 0; i < ObjectPtrConversions.size(); i++) NoteOverloadCandidate(ObjectPtrConversions[i]); return ExprError(); @@ -1669,7 +1712,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, if (!Type->isPointerType()) return ExprError(Diag(StartLoc, diag::err_delete_operand) - << Type << Ex->getSourceRange()); + << Type << Ex.get()->getSourceRange()); QualType Pointee = Type->getAs<PointerType>()->getPointeeType(); if (Pointee->isVoidType() && !isSFINAEContext()) { @@ -1677,27 +1720,30 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, // 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->getSourceRange(); + << Type << Ex.get()->getSourceRange(); } else if (Pointee->isFunctionType() || Pointee->isVoidType()) return ExprError(Diag(StartLoc, diag::err_delete_operand) - << Type << Ex->getSourceRange()); + << Type << Ex.get()->getSourceRange()); else if (!Pointee->isDependentType() && RequireCompleteType(StartLoc, Pointee, PDiag(diag::warn_delete_incomplete) - << Ex->getSourceRange())) + << Ex.get()->getSourceRange())) return ExprError(); - + else if (unsigned AddressSpace = Pointee.getAddressSpace()) + return Diag(Ex.get()->getLocStart(), + diag::err_address_space_qualified_delete) + << Pointee.getUnqualifiedType() << AddressSpace; // 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. ] - ImpCastExprToType(Ex, Context.getPointerType(Context.VoidTy), + Ex = ImpCastExprToType(Ex.take(), Context.getPointerType(Context.VoidTy), CK_NoOp); if (Pointee->isArrayType() && !ArrayForm) { Diag(StartLoc, diag::warn_delete_array_type) - << Type << Ex->getSourceRange() + << Type << Ex.get()->getSourceRange() << FixItHint::CreateInsertion(PP.getLocForEndOfToken(StartLoc), "[]"); ArrayForm = true; } @@ -1740,8 +1786,9 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, // Look for a global declaration. DeclareGlobalNewDelete(); DeclContext *TUDecl = Context.getTranslationUnitDecl(); + Expr *Arg = Ex.get(); if (FindAllocationOverload(StartLoc, SourceRange(), DeleteName, - &Ex, 1, TUDecl, /*AllowMissing=*/false, + &Arg, 1, TUDecl, /*AllowMissing=*/false, OperatorDelete)) return ExprError(); } @@ -1752,7 +1799,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, if (const RecordType *RT = PointeeElem->getAs<RecordType>()) { CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); if (CXXDestructorDecl *Dtor = LookupDestructor(RD)) { - CheckDestructorAccess(Ex->getExprLoc(), Dtor, + CheckDestructorAccess(Ex.get()->getExprLoc(), Dtor, PDiag(diag::err_access_dtor) << PointeeElem); } } @@ -1762,7 +1809,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, return Owned(new (Context) CXXDeleteExpr(Context.VoidTy, UseGlobal, ArrayForm, ArrayFormAsWritten, UsualArrayDeleteWantsSize, - OperatorDelete, Ex, StartLoc)); + OperatorDelete, Ex.take(), StartLoc)); } /// \brief Check the use of the given variable as a C++ condition in an if, @@ -1783,18 +1830,23 @@ ExprResult Sema::CheckConditionVariable(VarDecl *ConditionVar, diag::err_invalid_use_of_array_type) << ConditionVar->getSourceRange()); - Expr *Condition = DeclRefExpr::Create(Context, 0, SourceRange(), ConditionVar, + ExprResult Condition = + Owned(DeclRefExpr::Create(Context, NestedNameSpecifierLoc(), + ConditionVar, ConditionVar->getLocation(), ConditionVar->getType().getNonReferenceType(), - VK_LValue); - if (ConvertToBoolean && CheckBooleanCondition(Condition, StmtLoc)) - return ExprError(); + VK_LValue)); + if (ConvertToBoolean) { + Condition = CheckBooleanCondition(Condition.take(), StmtLoc); + if (Condition.isInvalid()) + return ExprError(); + } - return Owned(Condition); + return move(Condition); } /// CheckCXXBooleanCondition - Returns true if a conversion to bool is invalid. -bool Sema::CheckCXXBooleanCondition(Expr *&CondExpr) { +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 @@ -1880,20 +1932,22 @@ static ExprResult BuildCXXCastArgument(Sema &S, /// PerformImplicitConversion - Perform an implicit conversion of the /// expression From to the type ToType using the pre-computed implicit -/// conversion sequence ICS. Returns true if there was an error, false -/// otherwise. The expression From is replaced with the converted +/// conversion sequence ICS. Returns the converted /// expression. Action is the kind of conversion we're performing, /// used in the error message. -bool -Sema::PerformImplicitConversion(Expr *&From, QualType ToType, +ExprResult +Sema::PerformImplicitConversion(Expr *From, QualType ToType, const ImplicitConversionSequence &ICS, AssignmentAction Action, bool CStyle) { switch (ICS.getKind()) { - case ImplicitConversionSequence::StandardConversion: - if (PerformImplicitConversion(From, ToType, ICS.Standard, Action, - CStyle)) - return true; + case ImplicitConversionSequence::StandardConversion: { + ExprResult Res = PerformImplicitConversion(From, ToType, ICS.Standard, + Action, CStyle); + if (Res.isInvalid()) + return ExprError(); + From = Res.take(); break; + } case ImplicitConversionSequence::UserDefinedConversion: { @@ -1920,10 +1974,13 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, } // Watch out for elipsis conversion. if (!ICS.UserDefined.EllipsisConversion) { - if (PerformImplicitConversion(From, BeforeToType, - ICS.UserDefined.Before, AA_Converting, - CStyle)) - return true; + ExprResult Res = + PerformImplicitConversion(From, BeforeToType, + ICS.UserDefined.Before, AA_Converting, + CStyle); + if (Res.isInvalid()) + return ExprError(); + From = Res.take(); } ExprResult CastArg @@ -1935,9 +1992,9 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, From); if (CastArg.isInvalid()) - return true; + return ExprError(); - From = CastArg.takeAs<Expr>(); + From = CastArg.take(); return PerformImplicitConversion(From, ToType, ICS.UserDefined.After, AA_Converting, CStyle); @@ -1947,28 +2004,27 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, ICS.DiagnoseAmbiguousConversion(*this, From->getExprLoc(), PDiag(diag::err_typecheck_ambiguous_condition) << From->getSourceRange()); - return true; + return ExprError(); case ImplicitConversionSequence::EllipsisConversion: assert(false && "Cannot perform an ellipsis conversion"); - return false; + return Owned(From); case ImplicitConversionSequence::BadConversion: - return true; + return ExprError(); } // Everything went well. - return false; + return Owned(From); } /// PerformImplicitConversion - Perform an implicit conversion of the /// expression From to the type ToType by following the standard -/// conversion sequence SCS. Returns true if there was an error, false -/// otherwise. The expression From is replaced with the converted +/// conversion sequence SCS. Returns the converted /// expression. Flavor is the context in which we're performing this /// conversion, for use in error messages. -bool -Sema::PerformImplicitConversion(Expr *&From, QualType ToType, +ExprResult +Sema::PerformImplicitConversion(Expr *From, QualType ToType, const StandardConversionSequence& SCS, AssignmentAction Action, bool CStyle) { // Overall FIXME: we are recomputing too many types here and doing far too @@ -1986,32 +2042,20 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, MultiExprArg(*this, &From, 1), /*FIXME:ConstructLoc*/SourceLocation(), ConstructorArgs)) - return true; - ExprResult FromResult = - BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(), - ToType, SCS.CopyConstructor, - move_arg(ConstructorArgs), - /*ZeroInit*/ false, - CXXConstructExpr::CK_Complete, - SourceRange()); - if (FromResult.isInvalid()) - return true; - From = FromResult.takeAs<Expr>(); - return false; + return ExprError(); + return BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(), + ToType, SCS.CopyConstructor, + move_arg(ConstructorArgs), + /*ZeroInit*/ false, + CXXConstructExpr::CK_Complete, + SourceRange()); } - ExprResult FromResult = - BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(), - ToType, SCS.CopyConstructor, - MultiExprArg(*this, &From, 1), - /*ZeroInit*/ false, - CXXConstructExpr::CK_Complete, - SourceRange()); - - if (FromResult.isInvalid()) - return true; - - From = FromResult.takeAs<Expr>(); - return false; + return BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(), + ToType, SCS.CopyConstructor, + MultiExprArg(*this, &From, 1), + /*ZeroInit*/ false, + CXXConstructExpr::CK_Complete, + SourceRange()); } // Resolve overloaded function references. @@ -2020,10 +2064,10 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(From, ToType, true, Found); if (!Fn) - return true; + return ExprError(); if (DiagnoseUseOfDecl(Fn, From->getSourceRange().getBegin())) - return true; + return ExprError(); From = FixOverloadedFunctionReference(From, Found, Fn); FromType = From->getType(); @@ -2038,13 +2082,15 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, case ICK_Lvalue_To_Rvalue: // Should this get its own ICK? if (From->getObjectKind() == OK_ObjCProperty) { - ConvertPropertyForRValue(From); + ExprResult FromRes = ConvertPropertyForRValue(From); + if (FromRes.isInvalid()) + return ExprError(); + From = FromRes.take(); if (!From->isGLValue()) break; } // Check for trivial buffer overflows. - if (const ArraySubscriptExpr *AE = dyn_cast<ArraySubscriptExpr>(From)) - CheckArrayAccess(AE); + CheckArrayAccess(From); FromType = FromType.getUnqualifiedType(); From = ImplicitCastExpr::Create(Context, FromType, CK_LValueToRValue, @@ -2053,12 +2099,12 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, case ICK_Array_To_Pointer: FromType = Context.getArrayDecayedType(FromType); - ImpCastExprToType(From, FromType, CK_ArrayToPointerDecay); + From = ImpCastExprToType(From, FromType, CK_ArrayToPointerDecay).take(); break; case ICK_Function_To_Pointer: FromType = Context.getPointerType(FromType); - ImpCastExprToType(From, FromType, CK_FunctionToPointerDecay); + From = ImpCastExprToType(From, FromType, CK_FunctionToPointerDecay).take(); break; default: @@ -2072,7 +2118,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, // If both sides are functions (or pointers/references to them), there could // be incompatible exception declarations. if (CheckExceptionSpecCompatibility(From, ToType)) - return true; + return ExprError(); // Nothing else to do. break; @@ -2080,19 +2126,19 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, // If both sides are functions (or pointers/references to them), there could // be incompatible exception declarations. if (CheckExceptionSpecCompatibility(From, ToType)) - return true; + return ExprError(); - ImpCastExprToType(From, ToType, CK_NoOp); + From = ImpCastExprToType(From, ToType, CK_NoOp).take(); break; case ICK_Integral_Promotion: case ICK_Integral_Conversion: - ImpCastExprToType(From, ToType, CK_IntegralCast); + From = ImpCastExprToType(From, ToType, CK_IntegralCast).take(); break; case ICK_Floating_Promotion: case ICK_Floating_Conversion: - ImpCastExprToType(From, ToType, CK_FloatingCast); + From = ImpCastExprToType(From, ToType, CK_FloatingCast).take(); break; case ICK_Complex_Promotion: @@ -2110,35 +2156,41 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, } else { CK = CK_IntegralComplexCast; } - ImpCastExprToType(From, ToType, CK); + From = ImpCastExprToType(From, ToType, CK).take(); break; } case ICK_Floating_Integral: if (ToType->isRealFloatingType()) - ImpCastExprToType(From, ToType, CK_IntegralToFloating); + From = ImpCastExprToType(From, ToType, CK_IntegralToFloating).take(); else - ImpCastExprToType(From, ToType, CK_FloatingToIntegral); + From = ImpCastExprToType(From, ToType, CK_FloatingToIntegral).take(); break; case ICK_Compatible_Conversion: - ImpCastExprToType(From, ToType, CK_NoOp); + From = ImpCastExprToType(From, ToType, CK_NoOp).take(); break; case ICK_Pointer_Conversion: { if (SCS.IncompatibleObjC && Action != AA_Casting) { // Diagnose incompatible Objective-C conversions - Diag(From->getSourceRange().getBegin(), - diag::ext_typecheck_convert_incompatible_pointer) - << From->getType() << ToType << Action - << From->getSourceRange(); + if (Action == AA_Initializing) + Diag(From->getSourceRange().getBegin(), + diag::ext_typecheck_convert_incompatible_pointer) + << ToType << From->getType() << Action + << From->getSourceRange(); + else + Diag(From->getSourceRange().getBegin(), + diag::ext_typecheck_convert_incompatible_pointer) + << From->getType() << ToType << Action + << From->getSourceRange(); } CastKind Kind = CK_Invalid; CXXCastPath BasePath; if (CheckPointerConversion(From, ToType, Kind, BasePath, CStyle)) - return true; - ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath); + return ExprError(); + From = ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath).take(); break; } @@ -2146,27 +2198,17 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, CastKind Kind = CK_Invalid; CXXCastPath BasePath; if (CheckMemberPointerConversion(From, ToType, Kind, BasePath, CStyle)) - return true; + return ExprError(); if (CheckExceptionSpecCompatibility(From, ToType)) - return true; - ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath); + return ExprError(); + From = ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath).take(); break; } - case ICK_Boolean_Conversion: { - CastKind Kind = CK_Invalid; - switch (FromType->getScalarTypeKind()) { - case Type::STK_Pointer: Kind = CK_PointerToBoolean; break; - case Type::STK_MemberPointer: Kind = CK_MemberPointerToBoolean; break; - case Type::STK_Bool: llvm_unreachable("bool -> bool conversion?"); - case Type::STK_Integral: Kind = CK_IntegralToBoolean; break; - case Type::STK_Floating: Kind = CK_FloatingToBoolean; break; - case Type::STK_IntegralComplex: Kind = CK_IntegralComplexToBoolean; break; - case Type::STK_FloatingComplex: Kind = CK_FloatingComplexToBoolean; break; - } - ImpCastExprToType(From, Context.BoolTy, Kind); + case ICK_Boolean_Conversion: + From = ImpCastExprToType(From, Context.BoolTy, + ScalarTypeToBooleanCastKind(FromType)).take(); break; - } case ICK_Derived_To_Base: { CXXCastPath BasePath; @@ -2176,20 +2218,20 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, From->getSourceRange(), &BasePath, CStyle)) - return true; + return ExprError(); - ImpCastExprToType(From, ToType.getNonReferenceType(), + From = ImpCastExprToType(From, ToType.getNonReferenceType(), CK_DerivedToBase, CastCategory(From), - &BasePath); + &BasePath).take(); break; } case ICK_Vector_Conversion: - ImpCastExprToType(From, ToType, CK_BitCast); + From = ImpCastExprToType(From, ToType, CK_BitCast).take(); break; case ICK_Vector_Splat: - ImpCastExprToType(From, ToType, CK_VectorSplat); + From = ImpCastExprToType(From, ToType, CK_VectorSplat).take(); break; case ICK_Complex_Real: @@ -2202,17 +2244,17 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, if (Context.hasSameUnqualifiedType(ElType, From->getType())) { // do nothing } else if (From->getType()->isRealFloatingType()) { - ImpCastExprToType(From, ElType, - isFloatingComplex ? CK_FloatingCast : CK_FloatingToIntegral); + From = ImpCastExprToType(From, ElType, + isFloatingComplex ? CK_FloatingCast : CK_FloatingToIntegral).take(); } else { assert(From->getType()->isIntegerType()); - ImpCastExprToType(From, ElType, - isFloatingComplex ? CK_IntegralToFloating : CK_IntegralCast); + From = ImpCastExprToType(From, ElType, + isFloatingComplex ? CK_IntegralToFloating : CK_IntegralCast).take(); } // y -> _Complex y - ImpCastExprToType(From, ToType, + From = ImpCastExprToType(From, ToType, isFloatingComplex ? CK_FloatingRealToComplex - : CK_IntegralRealToComplex); + : CK_IntegralRealToComplex).take(); // Case 2. _Complex x -> y } else { @@ -2223,29 +2265,43 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, bool isFloatingComplex = ElType->isRealFloatingType(); // _Complex x -> x - ImpCastExprToType(From, ElType, + From = ImpCastExprToType(From, ElType, isFloatingComplex ? CK_FloatingComplexToReal - : CK_IntegralComplexToReal); + : CK_IntegralComplexToReal).take(); // x -> y if (Context.hasSameUnqualifiedType(ElType, ToType)) { // do nothing } else if (ToType->isRealFloatingType()) { - ImpCastExprToType(From, ToType, - isFloatingComplex ? CK_FloatingCast : CK_IntegralToFloating); + From = ImpCastExprToType(From, ToType, + isFloatingComplex ? CK_FloatingCast : CK_IntegralToFloating).take(); } else { assert(ToType->isIntegerType()); - ImpCastExprToType(From, ToType, - isFloatingComplex ? CK_FloatingToIntegral : CK_IntegralCast); + From = ImpCastExprToType(From, ToType, + isFloatingComplex ? CK_FloatingToIntegral : CK_IntegralCast).take(); } } break; case ICK_Block_Pointer_Conversion: { - ImpCastExprToType(From, ToType.getUnqualifiedType(), CK_BitCast, VK_RValue); + From = ImpCastExprToType(From, ToType.getUnqualifiedType(), CK_BitCast, + VK_RValue).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: @@ -2265,10 +2321,11 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, // target type isn't a reference. ExprValueKind VK = ToType->isReferenceType() ? CastCategory(From) : VK_RValue; - ImpCastExprToType(From, ToType.getNonLValueExprType(Context), - CK_NoOp, VK); + From = ImpCastExprToType(From, ToType.getNonLValueExprType(Context), + CK_NoOp, VK).take(); - if (SCS.DeprecatedStringLiteralToCharPtr) + if (SCS.DeprecatedStringLiteralToCharPtr && + !getLangOptions().WritableStrings) Diag(From->getLocStart(), diag::warn_deprecated_string_literal_conversion) << ToType.getNonReferenceType(); @@ -2280,7 +2337,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, break; } - return false; + return Owned(From); } ExprResult Sema::ActOnUnaryTypeTrait(UnaryTypeTrait UTT, @@ -2295,41 +2352,197 @@ ExprResult Sema::ActOnUnaryTypeTrait(UnaryTypeTrait UTT, return BuildUnaryTypeTrait(UTT, KWLoc, TSInfo, RParen); } -static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, QualType T, - SourceLocation KeyLoc) { - // FIXME: For many of these traits, we need a complete type before we can - // check these properties. - assert(!T->isDependentType() && - "Cannot evaluate traits for dependent types."); +/// \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_IsStandardLayout: + case UTT_IsPOD: + case UTT_IsLiteral: + case UTT_IsEmpty: + case UTT_IsPolymorphic: + case UTT_IsAbstract: + // Fall-through + + // 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_HasTrivialConstructor: + 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) { - default: assert(false && "Unknown type trait or not implemented"); - case UTT_IsPOD: return T->isPODType(); - case UTT_IsLiteral: return T->isLiteralType(); - case UTT_IsClass: // Fallthrough + // 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: - if (const RecordType *Record = T->getAs<RecordType>()) { - bool Union = Record->getDecl()->isUnion(); - return UTT == UTT_IsUnion ? Union : !Union; - } + 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: + 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(); + case UTT_IsStandardLayout: + return T->isStandardLayoutType(); + case UTT_IsPOD: + return T->isPODType(); + case UTT_IsLiteral: + return T->isLiteralType(); + case UTT_IsEmpty: + if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) + return !RD->isUnion() && RD->isEmpty(); return false; - case UTT_IsEnum: return T->isEnumeralType(); case UTT_IsPolymorphic: - if (const RecordType *Record = T->getAs<RecordType>()) { - // Type traits are only parsed in C++, so we've got CXXRecords. - return cast<CXXRecordDecl>(Record->getDecl())->isPolymorphic(); - } + if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) + return RD->isPolymorphic(); return false; case UTT_IsAbstract: - if (const RecordType *RT = T->getAs<RecordType>()) - return cast<CXXRecordDecl>(RT->getDecl())->isAbstract(); - return false; - case UTT_IsEmpty: - if (const RecordType *Record = T->getAs<RecordType>()) { - return !Record->getDecl()->isUnion() - && cast<CXXRecordDecl>(Record->getDecl())->isEmpty(); - } + if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) + return RD->isAbstract(); 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_HasTrivialConstructor: // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: // If __is_pod (type) is true then the trait is true, else if type is @@ -2418,7 +2631,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, QualType T, FoundAssign = true; const FunctionProtoType *CPT = Operator->getType()->getAs<FunctionProtoType>(); - if (!CPT->hasEmptyExceptionSpec()) { + if (!CPT->isNothrow(Self.Context)) { AllNoThrow = false; break; } @@ -2458,9 +2671,9 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, QualType T, FoundConstructor = true; const FunctionProtoType *CPT = Constructor->getType()->getAs<FunctionProtoType>(); - // TODO: check whether evaluating default arguments can throw. + // FIXME: check whether evaluating default arguments can throw. // For now, we'll be conservative and assume that they can throw. - if (!CPT->hasEmptyExceptionSpec() || CPT->getNumArgs() > 1) { + if (!CPT->isNothrow(Self.Context) || CPT->getNumArgs() > 1) { AllNoThrow = false; break; } @@ -2495,7 +2708,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, QualType T, = Constructor->getType()->getAs<FunctionProtoType>(); // TODO: check whether evaluating default arguments can throw. // For now, we'll be conservative and assume that they can throw. - return CPT->hasEmptyExceptionSpec() && CPT->getNumArgs() == 0; + return CPT->isNothrow(Self.Context) && CPT->getNumArgs() == 0; } } } @@ -2510,7 +2723,17 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, QualType T, 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, @@ -2518,23 +2741,12 @@ ExprResult Sema::BuildUnaryTypeTrait(UnaryTypeTrait UTT, TypeSourceInfo *TSInfo, SourceLocation RParen) { QualType T = TSInfo->getType(); - - // According to http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html - // all traits except __is_class, __is_enum and __is_union require a the type - // to be complete, an array of unknown bound, or void. - if (UTT != UTT_IsClass && UTT != UTT_IsEnum && UTT != UTT_IsUnion) { - QualType E = T; - if (T->isIncompleteArrayType()) - E = Context.getAsArrayType(T)->getElementType(); - if (!T->isVoidType() && - RequireCompleteType(KWLoc, E, - diag::err_incomplete_type_used_in_type_trait_expr)) - return ExprError(); - } + if (!CheckUnaryTypeTraitTypeCompleteness(*this, UTT, KWLoc, T)) + return ExprError(); bool Value = false; if (!T->isDependentType()) - Value = EvaluateUnaryTypeTrait(*this, UTT, T, KWLoc); + Value = EvaluateUnaryTypeTrait(*this, UTT, KWLoc, T); return Owned(new (Context) UnaryTypeTraitExpr(KWLoc, UTT, TSInfo, Value, RParen, Context.BoolTy)); @@ -2561,8 +2773,8 @@ ExprResult Sema::ActOnBinaryTypeTrait(BinaryTypeTrait BTT, static bool EvaluateBinaryTypeTrait(Sema &Self, BinaryTypeTrait BTT, QualType LhsT, QualType RhsT, SourceLocation KeyLoc) { - assert((!LhsT->isDependentType() || RhsT->isDependentType()) && - "Cannot evaluate traits for dependent types."); + assert(!LhsT->isDependentType() && !RhsT->isDependentType() && + "Cannot evaluate traits of dependent types"); switch(BTT) { case BTT_IsBaseOf: { @@ -2594,11 +2806,12 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, BinaryTypeTrait BTT, return cast<CXXRecordDecl>(rhsRecord->getDecl()) ->isDerivedFrom(cast<CXXRecordDecl>(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: @@ -2673,6 +2886,8 @@ ExprResult Sema::BuildBinaryTypeTrait(BinaryTypeTrait BTT, 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; } @@ -2682,7 +2897,138 @@ ExprResult Sema::BuildBinaryTypeTrait(BinaryTypeTrait BTT, ResultType)); } -QualType Sema::CheckPointerToMemberOperands(Expr *&lex, Expr *&rex, +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 (DimExpr->isIntegerConstantExpr(Value, Self.Context, 0, false)) { + if (Value < llvm::APSInt(Value.getBitWidth(), Value.isUnsigned())) { + Self.Diag(KeyLoc, diag::err_dimension_expr_not_constant_integer) << + DimExpr->getSourceRange(); + return false; + } + Dim = Value.getLimitedValue(); + } else { + Self.Diag(KeyLoc, diag::err_dimension_expr_not_constant_integer) << + DimExpr->getSourceRange(); + return false; + } + + 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 &lex, ExprResult &rex, ExprValueKind &VK, SourceLocation Loc, bool isIndirect) { @@ -2691,11 +3037,11 @@ QualType Sema::CheckPointerToMemberOperands(Expr *&lex, Expr *&rex, // 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 RType = rex->getType(); + QualType RType = rex.get()->getType(); const MemberPointerType *MemPtr = RType->getAs<MemberPointerType>(); if (!MemPtr) { Diag(Loc, diag::err_bad_memptr_rhs) - << OpSpelling << RType << rex->getSourceRange(); + << OpSpelling << RType << rex.get()->getSourceRange(); return QualType(); } @@ -2711,7 +3057,7 @@ QualType Sema::CheckPointerToMemberOperands(Expr *&lex, Expr *&rex, // [...] 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 LType = lex->getType(); + QualType LType = lex.get()->getType(); if (isIndirect) { if (const PointerType *Ptr = LType->getAs<PointerType>()) LType = Ptr->getPointeeType(); @@ -2736,20 +3082,20 @@ QualType Sema::CheckPointerToMemberOperands(Expr *&lex, Expr *&rex, if (!IsDerivedFrom(LType, Class, Paths) || Paths.isAmbiguous(Context.getCanonicalType(Class))) { Diag(Loc, diag::err_bad_memptr_lhs) << OpSpelling - << (int)isIndirect << lex->getType(); + << (int)isIndirect << lex.get()->getType(); return QualType(); } // Cast LHS to type of use. QualType UseType = isIndirect ? Context.getPointerType(Class) : Class; ExprValueKind VK = - isIndirect ? VK_RValue : CastCategory(lex); + isIndirect ? VK_RValue : CastCategory(lex.get()); CXXCastPath BasePath; BuildBasePathArray(Paths, BasePath); - ImpCastExprToType(lex, UseType, CK_DerivedToBase, VK, &BasePath); + lex = ImpCastExprToType(lex.take(), UseType, CK_DerivedToBase, VK, &BasePath); } - if (isa<CXXScalarValueInitExpr>(rex->IgnoreParens())) { + if (isa<CXXScalarValueInitExpr>(rex.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; @@ -2761,13 +3107,6 @@ QualType Sema::CheckPointerToMemberOperands(Expr *&lex, Expr *&rex, // 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. - // FIXME: This returns a dereferenced member function pointer as a normal - // function type. However, the only operation valid on such functions is - // calling them. There's also a GCC extension to get a function pointer to the - // thing, which is another complication, because this type - unlike the type - // that is the result of this expression - takes the class as the first - // argument. - // We probably need a "MemberFunctionClosureType" or something like that. QualType Result = MemPtr->getPointeeType(); Result = Context.getCVRQualifiedType(Result, LType.getCVRQualifiers()); @@ -2784,15 +3123,15 @@ QualType Sema::CheckPointerToMemberOperands(Expr *&lex, Expr *&rex, break; case RQ_LValue: - if (!isIndirect && !lex->Classify(Context).isLValue()) + if (!isIndirect && !lex.get()->Classify(Context).isLValue()) Diag(Loc, diag::err_pointer_to_member_oper_value_classify) - << RType << 1 << lex->getSourceRange(); + << RType << 1 << lex.get()->getSourceRange(); break; case RQ_RValue: - if (isIndirect || !lex->Classify(Context).isRValue()) + if (isIndirect || !lex.get()->Classify(Context).isRValue()) Diag(Loc, diag::err_pointer_to_member_oper_value_classify) - << RType << 0 << lex->getSourceRange(); + << RType << 0 << lex.get()->getSourceRange(); break; } } @@ -2804,12 +3143,14 @@ QualType Sema::CheckPointerToMemberOperands(Expr *&lex, Expr *&rex, // 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()) + if (Result->isFunctionType()) { VK = VK_RValue; - else if (isIndirect) + return Context.BoundMemberTy; + } else if (isIndirect) { VK = VK_LValue; - else - VK = lex->getValueKind(); + } else { + VK = lex.get()->getValueKind(); + } return Result; } @@ -2910,43 +3251,52 @@ static bool TryClassUnification(Sema &Self, Expr *From, Expr *To, /// 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, Expr *&LHS, Expr *&RHS, +static bool FindConditionalOverload(Sema &Self, ExprResult &LHS, ExprResult &RHS, SourceLocation QuestionLoc) { - Expr *Args[2] = { LHS, RHS }; + 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: + case OR_Success: { // We found a match. Perform the conversions on the arguments and move on. - if (Self.PerformImplicitConversion(LHS, Best->BuiltinTypes.ParamTypes[0], - Best->Conversions[0], Sema::AA_Converting) || - Self.PerformImplicitConversion(RHS, Best->BuiltinTypes.ParamTypes[1], - Best->Conversions[1], Sema::AA_Converting)) + 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.MarkDeclarationReferenced(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, RHS, QuestionLoc)) + if (Self.DiagnoseConditionalForNull(LHS.get(), RHS.get(), QuestionLoc)) return true; Self.Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands) - << LHS->getType() << RHS->getType() - << LHS->getSourceRange() << RHS->getSourceRange(); + << 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->getType() << RHS->getType() - << LHS->getSourceRange() << RHS->getSourceRange(); + << 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; @@ -2960,16 +3310,17 @@ static bool FindConditionalOverload(Sema &Self, Expr *&LHS, Expr *&RHS, /// \brief Perform an "extended" implicit conversion as returned by /// TryClassUnification. -static bool ConvertForConditional(Sema &Self, Expr *&E, QualType T) { +static bool ConvertForConditional(Sema &Self, ExprResult &E, QualType T) { InitializedEntity Entity = InitializedEntity::InitializeTemporary(T); - InitializationKind Kind = InitializationKind::CreateCopy(E->getLocStart(), + InitializationKind Kind = InitializationKind::CreateCopy(E.get()->getLocStart(), SourceLocation()); - InitializationSequence InitSeq(Self, Entity, Kind, &E, 1); - ExprResult Result = InitSeq.Perform(Self, Entity, Kind, MultiExprArg(&E, 1)); + 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.takeAs<Expr>(); + E = Result; return false; } @@ -2977,7 +3328,7 @@ static bool ConvertForConditional(Sema &Self, Expr *&E, QualType T) { /// /// 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(Expr *&Cond, Expr *&LHS, Expr *&RHS, +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++ @@ -2985,9 +3336,11 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, // C++0x 5.16p1 // The first expression is contextually converted to bool. - if (!Cond->isTypeDependent()) { - if (CheckCXXBooleanCondition(Cond)) + if (!Cond.get()->isTypeDependent()) { + ExprResult CondRes = CheckCXXBooleanCondition(Cond.take()); + if (CondRes.isInvalid()) return QualType(); + Cond = move(CondRes); } // Assume r-value. @@ -2995,28 +3348,30 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, OK = OK_Ordinary; // Either of the arguments dependent? - if (LHS->isTypeDependent() || RHS->isTypeDependent()) + 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->getType(); - QualType RTy = RHS->getType(); + 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 ... - DefaultFunctionArrayLvalueConversion(LHS); - DefaultFunctionArrayLvalueConversion(RHS); - LTy = LHS->getType(); - RTy = RHS->getType(); + 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<CXXThrowExpr>(LHS); - bool RThrow = isa<CXXThrowExpr>(RHS); + bool LThrow = isa<CXXThrowExpr>(LHS.get()); + bool RThrow = isa<CXXThrowExpr>(RHS.get()); if (LThrow && !RThrow) return RTy; if (RThrow && !LThrow) @@ -3030,7 +3385,7 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, // Neither holds, error. Diag(QuestionLoc, diag::err_conditional_void_nonvoid) << (LVoid ? RTy : LTy) << (LVoid ? 0 : 1) - << LHS->getSourceRange() << RHS->getSourceRange(); + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); return QualType(); } @@ -3046,15 +3401,15 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, // These return true if a single direction is already ambiguous. QualType L2RType, R2LType; bool HaveL2R, HaveR2L; - if (TryClassUnification(*this, LHS, RHS, QuestionLoc, HaveL2R, L2RType)) + if (TryClassUnification(*this, LHS.get(), RHS.get(), QuestionLoc, HaveL2R, L2RType)) return QualType(); - if (TryClassUnification(*this, RHS, LHS, QuestionLoc, HaveR2L, R2LType)) + 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->getSourceRange() << RHS->getSourceRange(); + << LTy << RTy << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); return QualType(); } @@ -3062,13 +3417,13 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, // 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)) + if (ConvertForConditional(*this, LHS, L2RType) || LHS.isInvalid()) return QualType(); - LTy = LHS->getType(); + LTy = LHS.get()->getType(); } else if (HaveR2L) { - if (ConvertForConditional(*this, RHS, R2LType)) + if (ConvertForConditional(*this, RHS, R2LType) || RHS.isInvalid()) return QualType(); - RTy = RHS->getType(); + RTy = RHS.get()->getType(); } } @@ -3081,13 +3436,13 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, // l-values. bool Same = Context.hasSameType(LTy, RTy); if (Same && - LHS->isGLValue() && - LHS->getValueKind() == RHS->getValueKind() && - LHS->isOrdinaryOrBitFieldObject() && - RHS->isOrdinaryOrBitFieldObject()) { - VK = LHS->getValueKind(); - if (LHS->getObjectKind() == OK_BitField || - RHS->getObjectKind() == OK_BitField) + 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; } @@ -3106,10 +3461,12 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, // C++0x 5.16p6 // LValue-to-rvalue, array-to-pointer, and function-to-pointer standard // conversions are performed on the second and third operands. - DefaultFunctionArrayLvalueConversion(LHS); - DefaultFunctionArrayLvalueConversion(RHS); - LTy = LHS->getType(); - RTy = RHS->getType(); + 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 @@ -3123,18 +3480,18 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, InitializedEntity Entity = InitializedEntity::InitializeTemporary(LTy); ExprResult LHSCopy = PerformCopyInitialization(Entity, SourceLocation(), - Owned(LHS)); + LHS); if (LHSCopy.isInvalid()) return QualType(); ExprResult RHSCopy = PerformCopyInitialization(Entity, SourceLocation(), - Owned(RHS)); + RHS); if (RHSCopy.isInvalid()) return QualType(); - LHS = LHSCopy.takeAs<Expr>(); - RHS = RHSCopy.takeAs<Expr>(); + LHS = LHSCopy; + RHS = RHSCopy; } return LTy; @@ -3149,7 +3506,9 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, // common type, and the result is of that type. if (LTy->isArithmeticType() && RTy->isArithmeticType()) { UsualArithmeticConversions(LHS, RHS); - return LHS->getType(); + if (LHS.isInvalid() || RHS.isInvalid()) + return QualType(); + return LHS.get()->getType(); } // -- The second and third operands have pointer type, or one has pointer @@ -3170,7 +3529,7 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, Diag(QuestionLoc, diag::ext_typecheck_cond_incompatible_operands_nonstandard) << LTy << RTy << Composite - << LHS->getSourceRange() << RHS->getSourceRange(); + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); return Composite; } @@ -3181,12 +3540,12 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, return Composite; // Check if we are using a null with a non-pointer type. - if (DiagnoseConditionalForNull(LHS, RHS, QuestionLoc)) + if (DiagnoseConditionalForNull(LHS.get(), RHS.get(), QuestionLoc)) return QualType(); Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands) - << LHS->getType() << RHS->getType() - << LHS->getSourceRange() << RHS->getSourceRange(); + << LHS.get()->getType() << RHS.get()->getType() + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); return QualType(); } @@ -3224,16 +3583,16 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc, // the type of the other operand. if (E1->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { if (T2->isMemberPointerType()) - ImpCastExprToType(E1, T2, CK_NullToMemberPointer); + E1 = ImpCastExprToType(E1, T2, CK_NullToMemberPointer).take(); else - ImpCastExprToType(E1, T2, CK_NullToPointer); + E1 = ImpCastExprToType(E1, T2, CK_NullToPointer).take(); return T2; } if (E2->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { if (T1->isMemberPointerType()) - ImpCastExprToType(E2, T1, CK_NullToMemberPointer); + E2 = ImpCastExprToType(E2, T1, CK_NullToMemberPointer).take(); else - ImpCastExprToType(E2, T1, CK_NullToPointer); + E2 = ImpCastExprToType(E2, T1, CK_NullToPointer).take(); return T1; } @@ -3763,7 +4122,8 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, ASTTemplateArgsPtr TemplateArgsPtr(*this, TemplateId->getTemplateArgs(), TemplateId->NumArgs); - TypeResult T = ActOnTemplateIdType(TemplateId->Template, + TypeResult T = ActOnTemplateIdType(TemplateId->SS, + TemplateId->Template, TemplateId->TemplateNameLoc, TemplateId->LAngleLoc, TemplateArgsPtr, @@ -3811,7 +4171,8 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, ASTTemplateArgsPtr TemplateArgsPtr(*this, TemplateId->getTemplateArgs(), TemplateId->NumArgs); - TypeResult T = ActOnTemplateIdType(TemplateId->Template, + TypeResult T = ActOnTemplateIdType(TemplateId->SS, + TemplateId->Template, TemplateId->TemplateNameLoc, TemplateId->LAngleLoc, TemplateArgsPtr, @@ -3834,24 +4195,25 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, Destructed, HasTrailingLParen); } -ExprResult Sema::BuildCXXMemberCallExpr(Expr *Exp, NamedDecl *FoundDecl, +ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl, CXXMethodDecl *Method) { - if (PerformObjectArgumentInitialization(Exp, /*Qualifier=*/0, - FoundDecl, Method)) + ExprResult Exp = PerformObjectArgumentInitialization(E, /*Qualifier=*/0, + FoundDecl, Method); + if (Exp.isInvalid()) return true; MemberExpr *ME = - new (Context) MemberExpr(Exp, /*IsArrow=*/false, Method, + new (Context) MemberExpr(Exp.take(), /*IsArrow=*/false, Method, SourceLocation(), Method->getType(), VK_RValue, OK_Ordinary); QualType ResultType = Method->getResultType(); ExprValueKind VK = Expr::getValueKindForType(ResultType); ResultType = ResultType.getNonLValueExprType(Context); - MarkDeclarationReferenced(Exp->getLocStart(), Method); + MarkDeclarationReferenced(Exp.get()->getLocStart(), Method); CXXMemberCallExpr *CE = new (Context) CXXMemberCallExpr(Context, ME, 0, 0, ResultType, VK, - Exp->getLocEnd()); + Exp.get()->getLocEnd()); return CE; } @@ -3869,46 +4231,62 @@ ExprResult Sema::ActOnNoexceptExpr(SourceLocation KeyLoc, SourceLocation, /// Perform the conversions required for an expression used in a /// context that ignores the result. -void Sema::IgnoredValueConversions(Expr *&E) { +ExprResult Sema::IgnoredValueConversions(Expr *E) { // 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()) return; + if (E->isRValue()) return Owned(E); // We always want to do this on ObjC property references. if (E->getObjectKind() == OK_ObjCProperty) { - ConvertPropertyForRValue(E); - if (E->isRValue()) return; + ExprResult Res = ConvertPropertyForRValue(E); + if (Res.isInvalid()) return Owned(E); + E = Res.take(); + if (E->isRValue()) return Owned(E); } // Otherwise, this rule does not apply in C++, at least not for the moment. - if (getLangOptions().CPlusPlus) return; + if (getLangOptions().CPlusPlus) return Owned(E); // GCC seems to also exclude expressions of incomplete enum type. if (const EnumType *T = E->getType()->getAs<EnumType>()) { if (!T->getDecl()->isComplete()) { // FIXME: stupid workaround for a codegen bug! - ImpCastExprToType(E, Context.VoidTy, CK_ToVoid); - return; + E = ImpCastExprToType(E, Context.VoidTy, CK_ToVoid).take(); + return Owned(E); } } - DefaultFunctionArrayLvalueConversion(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 *FullExpr) { - if (!FullExpr) +ExprResult Sema::ActOnFinishFullExpr(Expr *FE) { + ExprResult FullExpr = Owned(FE); + + if (!FullExpr.get()) + return ExprError(); + + if (DiagnoseUnexpandedParameterPack(FullExpr.get())) + return ExprError(); + + FullExpr = CheckPlaceholderExpr(FullExpr.take()); + if (FullExpr.isInvalid()) return ExprError(); - if (DiagnoseUnexpandedParameterPack(FullExpr)) + FullExpr = IgnoredValueConversions(FullExpr.take()); + if (FullExpr.isInvalid()) return ExprError(); - IgnoredValueConversions(FullExpr); - CheckImplicitConversions(FullExpr); + CheckImplicitConversions(FullExpr.get()); return MaybeCreateExprWithCleanups(FullExpr); } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp index 4d03b06..2a262f0 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp @@ -62,7 +62,8 @@ ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs, // Create the aggregate string with the appropriate content and location // information. - S = StringLiteral::Create(Context, &StrBuf[0], StrBuf.size(), false, + S = StringLiteral::Create(Context, &StrBuf[0], StrBuf.size(), + /*Wide=*/false, /*Pascal=*/false, Context.getPointerType(Context.CharTy), &StrLocs[0], StrLocs.size()); } @@ -246,7 +247,10 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, if (Args[i]->isTypeDependent()) continue; - DefaultArgumentPromotion(Args[i]); + ExprResult Result = DefaultArgumentPromotion(Args[i]); + if (Result.isInvalid()) + return true; + Args[i] = Result.take(); } unsigned DiagID = isClassMessage ? diag::warn_class_method_not_found : @@ -305,7 +309,9 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, if (Args[i]->isTypeDependent()) continue; - IsError |= DefaultVariadicArgumentPromotion(Args[i], VariadicMethod, 0); + ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], VariadicMethod, 0); + IsError |= Arg.isInvalid(); + Args[i] = Arg.take(); } } else { // Check for extra arguments to non-variadic methods. @@ -318,12 +324,24 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, Args[NumArgs-1]->getLocEnd()); } } + // diagnose nonnull arguments. + for (specific_attr_iterator<NonNullAttr> + i = Method->specific_attr_begin<NonNullAttr>(), + e = Method->specific_attr_end<NonNullAttr>(); i != e; ++i) { + CheckNonNullArguments(*i, Args, lbrac); + } DiagnoseSentinelCalls(Method, lbrac, Args, NumArgs); return IsError; } bool Sema::isSelfExpr(Expr *RExpr) { + // 'self' is objc 'self' in an objc method only. + DeclContext *DC = CurContext; + while (isa<BlockDecl>(DC)) + DC = DC->getParent(); + if (DC && !isa<ObjCMethodDecl>(DC)) + return false; if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(RExpr)) if (ICE->getCastKind() == CK_LValueToRValue) RExpr = ICE->getSubExpr(); @@ -381,6 +399,23 @@ ObjCMethodDecl *Sema::LookupPrivateInstanceMethod(Selector Sel, return Method; } +/// 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:: @@ -391,6 +426,13 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, 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(); if (IFace->isForwardDecl()) { @@ -405,6 +447,7 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, if (DiagnoseUseOfDecl(PD, MemberLoc)) return ExprError(); QualType ResTy = PD->getType(); + ResTy = ResTy.getNonLValueExprType(Context); Selector Sel = PP.getSelectorTable().getNullarySelector(Member); ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel); if (DiagnosePropertyAccessorMismatch(PD, Getter, MemberLoc)) @@ -448,6 +491,10 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, 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) @@ -467,6 +514,11 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, 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. @@ -475,7 +527,7 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, // Look through local category implementations associated with the class. if (!Setter) Setter = IFace->getCategoryInstanceMethod(SetterSel); - + if (Setter && DiagnoseUseOfDecl(Setter, MemberLoc)) return ExprError(); @@ -868,7 +920,7 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, return ExprError(); } assert(Class && "We don't know which class we're messaging?"); - + (void)DiagnoseUseOfDecl(Class, Loc); // Find the method we are messaging. if (!Method) { if (Class->isForwardDecl()) { @@ -1007,7 +1059,10 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, // If necessary, apply function/array conversion to the receiver. // C99 6.7.5.3p[7,8]. - DefaultFunctionArrayLvalueConversion(Receiver); + ExprResult Result = DefaultFunctionArrayLvalueConversion(Receiver); + if (Result.isInvalid()) + return ExprError(); + Receiver = Result.take(); ReceiverType = Receiver->getType(); } @@ -1026,39 +1081,53 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, } else if (ReceiverType->isObjCClassType() || ReceiverType->isObjCQualifiedClassType()) { // Handle messages to Class. - 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); + // We allow sending a message to a qualified Class ("Class<foo>"), 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); + } + } + } else { + if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) { + if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) { + // First check the public methods in the class interface. + Method = ClassDecl->lookupClassMethod(Sel); - // FIXME: if we still haven't found a method, we need to look in - // protocols (if we have qualifiers). + if (!Method) + Method = LookupPrivateClassMethod(Sel, ClassDecl); + } + if (Method && DiagnoseUseOfDecl(Method, Loc)) + return ExprError(); } - 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, + 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<ObjCInterfaceDecl>(Method->getDeclContext())) { - if (ID->getSuperClass()) - Diag(Loc, diag::warn_root_inst_method_not_found) - << Sel << SourceRange(LBracLoc, RBracLoc); - } + true); + if (Method) + if (const ObjCInterfaceDecl *ID = + dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext())) { + if (ID->getSuperClass()) + Diag(Loc, diag::warn_root_inst_method_not_found) + << Sel << SourceRange(LBracLoc, RBracLoc); + } + } } } } @@ -1070,15 +1139,9 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, if (const ObjCObjectPointerType *QIdTy = ReceiverType->getAsObjCQualifiedIdType()) { // Search protocols for instance methods. - for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(), - E = QIdTy->qual_end(); I != E; ++I) { - ObjCProtocolDecl *PDecl = *I; - if (PDecl && (Method = PDecl->lookupInstanceMethod(Sel))) - break; - // Since we aren't supporting "Class<foo>", look for a class method. - if (PDecl && (Method = PDecl->lookupClassMethod(Sel))) - break; - } + 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). @@ -1088,15 +1151,11 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, // The idea is to add class info to MethodPool. Method = ClassDecl->lookupInstanceMethod(Sel); - if (!Method) { + if (!Method) // Search protocol qualifiers. - for (ObjCObjectPointerType::qual_iterator QI = OCIType->qual_begin(), - E = OCIType->qual_end(); QI != E; ++QI) { - if ((Method = (*QI)->lookupInstanceMethod(Sel))) - break; - } - } - bool forwardClass = false; + Method = LookupMethodInQualifiedType(Sel, OCIType, true); + + const ObjCInterfaceDecl *forwardClass = 0; if (!Method) { // If we have implementations in scope, check "private" methods. Method = LookupPrivateInstanceMethod(Sel, ClassDecl); @@ -1108,7 +1167,8 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, if (OCIType->qual_empty()) { Method = LookupInstanceMethodInGlobalPool(Sel, SourceRange(LBracLoc, RBracLoc)); - forwardClass = OCIType->getInterfaceDecl()->isForwardDecl(); + if (OCIType->getInterfaceDecl()->isForwardDecl()) + forwardClass = OCIType->getInterfaceDecl(); if (Method && !forwardClass) Diag(Loc, diag::warn_maynot_respond) << OCIType->getInterfaceDecl()->getIdentifier() << Sel; @@ -1125,37 +1185,42 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, << ReceiverType << Receiver->getSourceRange(); if (ReceiverType->isPointerType()) - ImpCastExprToType(Receiver, Context.getObjCIdType(), - CK_BitCast); + Receiver = ImpCastExprToType(Receiver, Context.getObjCIdType(), + CK_BitCast).take(); else { // TODO: specialized warning on null receivers? bool IsNull = Receiver->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull); - ImpCastExprToType(Receiver, Context.getObjCIdType(), - IsNull ? CK_NullToPointer : CK_IntegralToPointer); + Receiver = ImpCastExprToType(Receiver, Context.getObjCIdType(), + IsNull ? CK_NullToPointer : CK_IntegralToPointer).take(); } ReceiverType = Receiver->getType(); } - else if (getLangOptions().CPlusPlus && - !PerformContextuallyConvertToObjCId(Receiver)) { - if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Receiver)) { - Receiver = ICE->getSubExpr(); - ReceiverType = Receiver->getType(); + else { + ExprResult ReceiverRes; + if (getLangOptions().CPlusPlus) + ReceiverRes = PerformContextuallyConvertToObjCId(Receiver); + if (ReceiverRes.isUsable()) { + Receiver = ReceiverRes.take(); + if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Receiver)) { + Receiver = ICE->getSubExpr(); + ReceiverType = Receiver->getType(); + } + return BuildInstanceMessage(Receiver, + ReceiverType, + SuperLoc, + Sel, + Method, + LBracLoc, + SelectorLoc, + RBracLoc, + move(ArgsIn)); + } else { + // Reject other random receiver types (e.g. structs). + Diag(Loc, diag::err_bad_receiver_type) + << ReceiverType << Receiver->getSourceRange(); + return ExprError(); } - return BuildInstanceMessage(Receiver, - ReceiverType, - SuperLoc, - Sel, - Method, - LBracLoc, - SelectorLoc, - RBracLoc, - move(ArgsIn)); - } else { - // Reject other random receiver types (e.g. structs). - Diag(Loc, diag::err_bad_receiver_type) - << ReceiverType << Receiver->getSourceRange(); - return ExprError(); } } } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp index 5882da0..ca3fd6d 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp @@ -92,13 +92,31 @@ static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT, const ConstantArrayType *CAT = cast<ConstantArrayType>(AT); - // C99 6.7.8p14. We have an array of character type with known size. However, + // 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 (StrLength-1 > CAT->getSize().getZExtValue()) - S.Diag(Str->getSourceRange().getBegin(), - diag::warn_initializer_string_for_char_array_too_long) - << Str->getSourceRange(); + if (S.getLangOptions().CPlusPlus) { + if (StringLiteral *SL = dyn_cast<StringLiteral>(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->getSourceRange().getBegin(), + 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->getSourceRange().getBegin(), + 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: @@ -386,15 +404,29 @@ InitListChecker::FillInValueInitializations(const InitializedEntity &Entity, if (hadError) { // Do nothing } else if (Init < NumInits) { - ILE->setInit(Init, ElementInit.takeAs<Expr>()); - } else if (InitSeq.getKind() + // 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<Expr>()); + else + ILE->setInit(Init, ElementInit.takeAs<Expr>()); + } 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<Expr>()); + return; + } + + if (InitSeq.getKind() == InitializationSequence::ConstructorInitialization) { - // 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<Expr>()); - RequiresSecondPass = true; + // 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<Expr>()); + RequiresSecondPass = true; + } } } else if (InitListExpr *InnerILE = dyn_cast<InitListExpr>(ILE->getInit(Init))) @@ -713,15 +745,23 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity, // 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, expr) + SemaRef.CheckSingleAssignmentConstraints(ElemType, ExprRes) == Sema::Compatible) { - SemaRef.DefaultFunctionArrayLvalueConversion(expr); - UpdateStructuredListElement(StructuredList, StructuredIndex, expr); + if (ExprRes.isInvalid()) + hadError = true; + else { + ExprRes = SemaRef.DefaultFunctionArrayLvalueConversion(ExprRes.take()); + if (ExprRes.isInvalid()) + hadError = true; + } + UpdateStructuredListElement(StructuredList, StructuredIndex, + ExprRes.takeAs<Expr>()); ++Index; return; } - + ExprRes.release(); // Fall through for subaggregate initialization } @@ -1755,11 +1795,15 @@ InitListChecker::getStructuredSubobjectInit(InitListExpr *IList, unsigned Index, // Pre-allocate storage for the structured initializer list. unsigned NumElements = 0; unsigned NumInits = 0; - if (!StructuredList) + bool GotNumInits = false; + if (!StructuredList) { NumInits = IList->getNumInits(); - else if (Index < IList->getNumInits()) { - if (InitListExpr *SubList = dyn_cast<InitListExpr>(IList->getInit(Index))) + GotNumInits = true; + } else if (Index < IList->getNumInits()) { + if (InitListExpr *SubList = dyn_cast<InitListExpr>(IList->getInit(Index))) { NumInits = SubList->getNumInits(); + GotNumInits = true; + } } if (const ArrayType *AType @@ -1768,7 +1812,7 @@ InitListChecker::getStructuredSubobjectInit(InitListExpr *IList, unsigned Index, NumElements = CAType->getSize().getZExtValue(); // Simple heuristic so that we don't allocate a very large // initializer with many empty entries at the end. - if (NumInits && NumElements > NumInits) + if (GotNumInits && NumElements > NumInits) NumElements = 0; } } else if (const VectorType *VType = CurrentObjectType->getAs<VectorType>()) @@ -1936,6 +1980,9 @@ ExprResult Sema::ActOnDesignatedInitializer(Designation &Desig, Loc, GNUSyntax, Init.takeAs<Expr>()); if (getLangOptions().CPlusPlus) + Diag(DIE->getLocStart(), diag::ext_designated_init_cxx) + << DIE->getSourceRange(); + else if (!getLangOptions().C99) Diag(DIE->getLocStart(), diag::ext_designated_init) << DIE->getSourceRange(); @@ -1998,6 +2045,7 @@ DeclarationName InitializedEntity::getName() const { case EK_New: case EK_Temporary: case EK_Base: + case EK_Delegating: case EK_ArrayElement: case EK_VectorElement: case EK_BlockElement: @@ -2020,6 +2068,7 @@ DeclaratorDecl *InitializedEntity::getDecl() const { case EK_New: case EK_Temporary: case EK_Base: + case EK_Delegating: case EK_ArrayElement: case EK_VectorElement: case EK_BlockElement: @@ -2042,6 +2091,7 @@ bool InitializedEntity::allowsNRVO() const { case EK_New: case EK_Temporary: case EK_Base: + case EK_Delegating: case EK_ArrayElement: case EK_VectorElement: case EK_BlockElement: @@ -2101,6 +2151,7 @@ bool InitializationSequence::isAmbiguous() const { case FK_ReferenceInitDropsQualifiers: case FK_ReferenceInitFailed: case FK_ConversionFailed: + case FK_ConversionFromPropertyFailed: case FK_TooManyInitsForScalar: case FK_ReferenceBindingToInitList: case FK_InitListBadDestinationType: @@ -3126,8 +3177,14 @@ InitializationSequence::InitializationSequence(Sema &S, } for (unsigned I = 0; I != NumArgs; ++I) - if (Args[I]->getObjectKind() == OK_ObjCProperty) - S.ConvertPropertyForRValue(Args[I]); + if (Args[I]->getObjectKind() == OK_ObjCProperty) { + ExprResult Result = S.ConvertPropertyForRValue(Args[I]); + if (Result.isInvalid()) { + SetFailed(FK_ConversionFromPropertyFailed); + return; + } + Args[I] = Result.take(); + } QualType SourceType; Expr *Initializer = 0; @@ -3289,6 +3346,7 @@ getAssignmentAction(const InitializedEntity &Entity) { case InitializedEntity::EK_New: case InitializedEntity::EK_Exception: case InitializedEntity::EK_Base: + case InitializedEntity::EK_Delegating: return Sema::AA_Initializing; case InitializedEntity::EK_Parameter: @@ -3325,6 +3383,7 @@ static bool shouldBindAsTemporary(const InitializedEntity &Entity) { case InitializedEntity::EK_New: case InitializedEntity::EK_Variable: case InitializedEntity::EK_Base: + case InitializedEntity::EK_Delegating: case InitializedEntity::EK_VectorElement: case InitializedEntity::EK_Exception: case InitializedEntity::EK_BlockElement: @@ -3346,6 +3405,7 @@ static bool shouldDestroyTemporary(const InitializedEntity &Entity) { case InitializedEntity::EK_Result: case InitializedEntity::EK_New: case InitializedEntity::EK_Base: + case InitializedEntity::EK_Delegating: case InitializedEntity::EK_VectorElement: case InitializedEntity::EK_BlockElement: return false; @@ -3430,6 +3490,7 @@ static ExprResult CopyObject(Sema &S, case InitializedEntity::EK_Temporary: case InitializedEntity::EK_New: case InitializedEntity::EK_Base: + case InitializedEntity::EK_Delegating: case InitializedEntity::EK_VectorElement: case InitializedEntity::EK_BlockElement: Loc = CurInitExpr->getLocStart(); @@ -3686,14 +3747,15 @@ InitializationSequence::Perform(Sema &S, case SK_ObjCObjectConversion: case SK_ArrayInit: { assert(Args.size() == 1); - Expr *CurInitExpr = Args.get()[0]; - if (!CurInitExpr) return ExprError(); + CurInit = Args.get()[0]; + if (!CurInit.get()) return ExprError(); // Read from a property when initializing something with it. - if (CurInitExpr->getObjectKind() == OK_ObjCProperty) - S.ConvertPropertyForRValue(CurInitExpr); - - CurInit = ExprResult(CurInitExpr); + if (CurInit.get()->getObjectKind() == OK_ObjCProperty) { + CurInit = S.ConvertPropertyForRValue(CurInit.take()); + if (CurInit.isInvalid()) + return ExprError(); + } break; } @@ -3710,14 +3772,13 @@ InitializationSequence::Perform(Sema &S, if (CurInit.isInvalid()) return ExprError(); - Expr *CurInitExpr = CurInit.get(); - QualType SourceType = CurInitExpr? CurInitExpr->getType() : QualType(); + 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(CurInitExpr, Step->Function.FoundDecl); + S.CheckAddressOfMemberAccess(CurInit.get(), Step->Function.FoundDecl); S.DiagnoseUseOfDecl(Step->Function.FoundDecl, Kind.getLocation()); CurInit = S.FixOverloadedFunctionReference(move(CurInit), Step->Function.FoundDecl, @@ -3735,8 +3796,8 @@ InitializationSequence::Perform(Sema &S, // Casts to inaccessible base classes are allowed with C-style casts. bool IgnoreBaseAccess = Kind.isCStyleOrFunctionalCast(); if (S.CheckDerivedToBaseConversion(SourceType, Step->Type, - CurInitExpr->getLocStart(), - CurInitExpr->getSourceRange(), + CurInit.get()->getLocStart(), + CurInit.get()->getSourceRange(), &BasePath, IgnoreBaseAccess)) return ExprError(); @@ -3745,7 +3806,7 @@ InitializationSequence::Perform(Sema &S, if (const PointerType *Pointer = T->getAs<PointerType>()) T = Pointer->getPointeeType(); if (const RecordType *RecordTy = T->getAs<RecordType>()) - S.MarkVTableUsed(CurInitExpr->getLocStart(), + S.MarkVTableUsed(CurInit.get()->getLocStart(), cast<CXXRecordDecl>(RecordTy->getDecl())); } @@ -3764,21 +3825,21 @@ InitializationSequence::Perform(Sema &S, } case SK_BindReference: - if (FieldDecl *BitField = CurInitExpr->getBitField()) { + 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() - << CurInitExpr->getSourceRange(); + << CurInit.get()->getSourceRange(); S.Diag(BitField->getLocation(), diag::note_bitfield_decl); return ExprError(); } - if (CurInitExpr->refersToVectorElement()) { + if (CurInit.get()->refersToVectorElement()) { // References cannot bind to vector elements. S.Diag(Kind.getLocation(), diag::err_reference_bind_to_vector_element) << Entity.getType().isVolatileQualified() - << CurInitExpr->getSourceRange(); + << CurInit.get()->getSourceRange(); PrintInitLocationNote(S, Entity); return ExprError(); } @@ -3786,7 +3847,7 @@ InitializationSequence::Perform(Sema &S, // Reference binding does not have any corresponding ASTs. // Check exception specifications - if (S.CheckExceptionSpecCompatibility(CurInitExpr, DestType)) + if (S.CheckExceptionSpecCompatibility(CurInit.get(), DestType)) return ExprError(); break; @@ -3795,7 +3856,7 @@ InitializationSequence::Perform(Sema &S, // Reference binding does not have any corresponding ASTs. // Check exception specifications - if (S.CheckExceptionSpecCompatibility(CurInitExpr, DestType)) + if (S.CheckExceptionSpecCompatibility(CurInit.get(), DestType)) return ExprError(); break; @@ -3817,13 +3878,14 @@ InitializationSequence::Perform(Sema &S, if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Fn)) { // Build a call to the selected constructor. ASTOwningVector<Expr*> ConstructorArgs(S); - SourceLocation Loc = CurInitExpr->getLocStart(); + 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(&CurInitExpr, 1), + MultiExprArg(&Arg, 1), Loc, ConstructorArgs)) return ExprError(); @@ -3851,23 +3913,22 @@ InitializationSequence::Perform(Sema &S, // Build a call to the conversion function. CXXConversionDecl *Conversion = cast<CXXConversionDecl>(Fn); IsLvalue = Conversion->getResultType()->isLValueReferenceType(); - S.CheckMemberOperatorAccess(Kind.getLocation(), CurInitExpr, 0, + 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. - if (S.PerformObjectArgumentInitialization(CurInitExpr, /*Qualifier=*/0, - FoundFn, Conversion)) + ExprResult CurInitExprRes = + S.PerformObjectArgumentInitialization(CurInit.take(), /*Qualifier=*/0, + FoundFn, Conversion); + if(CurInitExprRes.isInvalid()) return ExprError(); - - // Do a little dance to make sure that CurInit has the proper - // pointer. - CurInit.release(); + CurInit = move(CurInitExprRes); // Build the actual call to the conversion function. - CurInit = S.BuildCXXMemberCallExpr(CurInitExpr, FoundFn, Conversion); + CurInit = S.BuildCXXMemberCallExpr(CurInit.get(), FoundFn, Conversion); if (CurInit.isInvalid() || !CurInit.get()) return ExprError(); @@ -3881,23 +3942,21 @@ InitializationSequence::Perform(Sema &S, if (RequiresCopy || shouldBindAsTemporary(Entity)) CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>()); else if (CreatedObject && shouldDestroyTemporary(Entity)) { - CurInitExpr = static_cast<Expr *>(CurInit.get()); - QualType T = CurInitExpr->getType(); + QualType T = CurInit.get()->getType(); if (const RecordType *Record = T->getAs<RecordType>()) { CXXDestructorDecl *Destructor = S.LookupDestructor(cast<CXXRecordDecl>(Record->getDecl())); - S.CheckDestructorAccess(CurInitExpr->getLocStart(), Destructor, + S.CheckDestructorAccess(CurInit.get()->getLocStart(), Destructor, S.PDiag(diag::err_access_dtor_temp) << T); - S.MarkDeclarationReferenced(CurInitExpr->getLocStart(), Destructor); - S.DiagnoseUseOfDecl(Destructor, CurInitExpr->getLocStart()); + S.MarkDeclarationReferenced(CurInit.get()->getLocStart(), Destructor); + S.DiagnoseUseOfDecl(Destructor, CurInit.get()->getLocStart()); } } - CurInitExpr = CurInit.takeAs<Expr>(); // FIXME: xvalues CurInit = S.Owned(ImplicitCastExpr::Create(S.Context, - CurInitExpr->getType(), - CastKind, CurInitExpr, 0, + CurInit.get()->getType(), + CastKind, CurInit.get(), 0, IsLvalue ? VK_LValue : VK_RValue)); if (RequiresCopy) @@ -3917,25 +3976,23 @@ InitializationSequence::Perform(Sema &S, (Step->Kind == SK_QualificationConversionXValue ? VK_XValue : VK_RValue); - S.ImpCastExprToType(CurInitExpr, Step->Type, CK_NoOp, VK); - CurInit.release(); - CurInit = S.Owned(CurInitExpr); + CurInit = S.ImpCastExprToType(CurInit.take(), Step->Type, CK_NoOp, VK); break; } case SK_ConversionSequence: { - if (S.PerformImplicitConversion(CurInitExpr, Step->Type, *Step->ICS, - getAssignmentAction(Entity), - Kind.isCStyleOrFunctionalCast())) + ExprResult CurInitExprRes = + S.PerformImplicitConversion(CurInit.get(), Step->Type, *Step->ICS, + getAssignmentAction(Entity), + Kind.isCStyleOrFunctionalCast()); + if (CurInitExprRes.isInvalid()) return ExprError(); - - CurInit.release(); - CurInit = S.Owned(CurInitExpr); + CurInit = move(CurInitExprRes); break; } case SK_ListInitialization: { - InitListExpr *InitList = cast<InitListExpr>(CurInitExpr); + InitListExpr *InitList = cast<InitListExpr>(CurInit.get()); QualType Ty = Step->Type; if (S.CheckInitList(Entity, InitList, ResultType? *ResultType : Ty)) return ExprError(); @@ -4004,6 +4061,9 @@ InitializationSequence::Perform(Sema &S, CXXConstructExpr::CK_VirtualBase : CXXConstructExpr::CK_NonVirtualBase; } + if (Entity.getKind() == InitializedEntity::EK_Delegating) { + ConstructKind = CXXConstructExpr::CK_Delegating; + } // Only get the parenthesis range if it is a direct construction. SourceRange parenRange = @@ -4068,54 +4128,57 @@ InitializationSequence::Perform(Sema &S, } case SK_CAssignment: { - QualType SourceType = CurInitExpr->getType(); + QualType SourceType = CurInit.get()->getType(); + ExprResult Result = move(CurInit); Sema::AssignConvertType ConvTy = - S.CheckSingleAssignmentConstraints(Step->Type, CurInitExpr); + 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, CurInitExpr) + 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, - CurInitExpr, + CurInit.get(), getAssignmentAction(Entity), &Complained)) { PrintInitLocationNote(S, Entity); return ExprError(); } else if (Complained) PrintInitLocationNote(S, Entity); - - CurInit.release(); - CurInit = S.Owned(CurInitExpr); break; } case SK_StringInit: { QualType Ty = Step->Type; - CheckStringInit(CurInitExpr, ResultType ? *ResultType : Ty, + CheckStringInit(CurInit.get(), ResultType ? *ResultType : Ty, S.Context.getAsArrayType(Ty), S); break; } case SK_ObjCObjectConversion: - S.ImpCastExprToType(CurInitExpr, Step->Type, + CurInit = S.ImpCastExprToType(CurInit.take(), Step->Type, CK_ObjCObjectLValueCast, - S.CastCategory(CurInitExpr)); - CurInit.release(); - CurInit = S.Owned(CurInitExpr); + S.CastCategory(CurInit.get())); 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 << CurInitExpr->getType() - << CurInitExpr->getSourceRange(); + << Step->Type << CurInit.get()->getType() + << CurInit.get()->getSourceRange(); // If the destination type is an incomplete array type, update the // type accordingly. @@ -4123,7 +4186,7 @@ InitializationSequence::Perform(Sema &S, if (const IncompleteArrayType *IncompleteDest = S.Context.getAsIncompleteArrayType(Step->Type)) { if (const ConstantArrayType *ConstantSource - = S.Context.getAsConstantArrayType(CurInitExpr->getType())) { + = S.Context.getAsConstantArrayType(CurInit.get()->getType())) { *ResultType = S.Context.getConstantArrayType( IncompleteDest->getElementType(), ConstantSource->getSize(), @@ -4283,6 +4346,11 @@ bool InitializationSequence::Diagnose(Sema &S, << Args[0]->getSourceRange(); break; } + + case FK_ConversionFromPropertyFailed: + // No-op. This error has already been reported. + break; + case FK_TooManyInitsForScalar: { SourceRange R; @@ -4482,6 +4550,10 @@ void InitializationSequence::dump(llvm::raw_ostream &OS) const { OS << "conversion failed"; break; + case FK_ConversionFromPropertyFailed: + OS << "conversion from property failed"; + break; + case FK_TooManyInitsForScalar: OS << "too many initializers for scalar"; break; diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp index 3deb403..309c771 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp @@ -686,8 +686,7 @@ static bool LookupDirect(Sema &S, LookupResult &R, const DeclContext *DC) { // FIXME: Calling convention! FunctionProtoType::ExtProtoInfo EPI = ConvProto->getExtProtoInfo(); EPI.ExtInfo = EPI.ExtInfo.withCallingConv(CC_Default); - EPI.HasExceptionSpec = false; - EPI.HasAnyExceptionSpec = false; + EPI.ExceptionSpecType = EST_None; EPI.NumExceptions = 0; QualType ExpectedType = R.getSema().Context.getFunctionType(R.getLookupName().getCXXNameType(), @@ -1130,8 +1129,8 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) { // 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) - return LookupBuiltin(*this, R); + 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. @@ -1964,10 +1963,13 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) { case Type::Complex: break; - // These are ignored by ADL. + // 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; } @@ -2203,7 +2205,8 @@ void ADLResult::insert(NamedDecl *New) { void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator, Expr **Args, unsigned NumArgs, - ADLResult &Result) { + ADLResult &Result, + bool StdNamespaceIsAssociated) { // Find all of the associated namespaces and classes based on the // arguments we have. AssociatedNamespaceSet AssociatedNamespaces; @@ -2211,6 +2214,8 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator, FindAssociatedClassesAndNamespaces(Args, NumArgs, AssociatedNamespaces, AssociatedClasses); + if (StdNamespaceIsAssociated && StdNamespace) + AssociatedNamespaces.insert(getStdNamespace()); QualType T1, T2; if (Operator) { @@ -2766,30 +2771,35 @@ void Sema::LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind, } /// LookupOrCreateLabel - Do a name lookup of a label with the specified name. -/// If isLocalLabel is true, then this is a definition of an __label__ label -/// name, otherwise it is a normal label definition or use. +/// 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, - bool isLocalLabel) { + SourceLocation GnuLabelLoc) { // Do a lookup to see if we have a label with this name already. NamedDecl *Res = 0; - - // Local label definitions always shadow existing labels. - if (!isLocalLabel) - 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 (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<LabelDecl>(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 = isLocalLabel ? CurScope : CurScope->getFnParent(); + Scope *S = CurScope->getFnParent(); assert(S && "Not in a function?"); PushOnScopeChains(Res, S, true); } - return cast<LabelDecl>(Res); } @@ -2853,8 +2863,6 @@ void TypoCorrectionConsumer::FoundDecl(NamedDecl *ND, NamedDecl *Hiding, } void TypoCorrectionConsumer::FoundName(llvm::StringRef Name) { - using namespace std; - // 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()); @@ -2863,7 +2871,8 @@ void TypoCorrectionConsumer::FoundName(llvm::StringRef Name) { // Compute an upper bound on the allowable edit distance, so that the // edit-distance algorithm can short-circuit. - unsigned UpperBound = min(unsigned((Typo.size() + 2) / 3), BestEditDistance); + unsigned UpperBound = + std::min(unsigned((Typo.size() + 2) / 3), BestEditDistance); // Compute the edit distance between the typo and the name of this // entity. If this edit distance is not worse than the best edit diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp index b086ca7..6c4469c 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp @@ -45,11 +45,7 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, !(Attributes & ObjCDeclSpec::DQ_PR_copy))); TypeSourceInfo *TSI = GetTypeForDeclarator(FD.D, S); - QualType T = TSI->getType(); - if (T->isReferenceType()) { - Diag(AtLoc, diag::error_reference_property); - return 0; - } + // Proceed with constructing the ObjCPropertDecls. ObjCContainerDecl *ClassDecl = cast<ObjCContainerDecl>(ClassCategory); @@ -404,12 +400,16 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, if (!PropertyIvar) PropertyIvar = PropertyId; QualType PropType = Context.getCanonicalType(property->getType()); + QualType PropertyIvarType = PropType; + if (PropType->isReferenceType()) + PropertyIvarType = cast<ReferenceType>(PropType)->getPointeeType(); // Check that this is a previously declared 'ivar' in 'IDecl' interface ObjCInterfaceDecl *ClassDeclared; Ivar = IDecl->lookupInstanceVariable(PropertyIvar, ClassDeclared); if (!Ivar) { - Ivar = ObjCIvarDecl::Create(Context, ClassImpDecl, PropertyLoc, - PropertyIvar, PropType, /*Dinfo=*/0, + Ivar = ObjCIvarDecl::Create(Context, ClassImpDecl, + PropertyLoc, PropertyLoc, PropertyIvar, + PropertyIvarType, /*Dinfo=*/0, ObjCIvarDecl::Private, (Expr *)0, true); ClassImpDecl->addDecl(Ivar); @@ -432,19 +432,19 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, QualType IvarType = Context.getCanonicalType(Ivar->getType()); // Check that type of property and its ivar are type compatible. - if (PropType != IvarType) { + if (PropertyIvarType != IvarType) { bool compat = false; - if (isa<ObjCObjectPointerType>(PropType) + if (isa<ObjCObjectPointerType>(PropertyIvarType) && isa<ObjCObjectPointerType>(IvarType)) compat = Context.canAssignObjCInterfaces( - PropType->getAs<ObjCObjectPointerType>(), + PropertyIvarType->getAs<ObjCObjectPointerType>(), IvarType->getAs<ObjCObjectPointerType>()); else { SourceLocation Loc = PropertyIvarLoc; if (Loc.isInvalid()) Loc = PropertyLoc; - compat = (CheckAssignmentConstraints(Loc, PropType, IvarType) + compat = (CheckAssignmentConstraints(Loc, PropertyIvarType, IvarType) == Compatible); } if (!compat) { @@ -459,7 +459,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, // 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(PropType).getUnqualifiedType(); + QualType lhsType =Context.getCanonicalType(PropertyIvarType).getUnqualifiedType(); QualType rhsType =Context.getCanonicalType(IvarType).getUnqualifiedType(); if (lhsType != rhsType && lhsType->isArithmeticType()) { @@ -538,7 +538,10 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, SelfExpr, true, true); ObjCMethodDecl::param_iterator P = setterMethod->param_begin(); ParmVarDecl *Param = (*P); - Expr *rhs = new (Context) DeclRefExpr(Param, Param->getType(), + QualType T = Param->getType(); + if (T->isReferenceType()) + T = T->getAs<ReferenceType>()->getPointeeType(); + Expr *rhs = new (Context) DeclRefExpr(Param, T, VK_LValue, SourceLocation()); ExprResult Res = BuildBinOp(S, lhs->getLocEnd(), BO_Assign, lhs, rhs); @@ -682,7 +685,7 @@ bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property, /// ComparePropertiesInBaseAndSuper - This routine compares property /// declarations in base and its super class, if any, and issues -/// diagnostics in a variety of inconsistant situations. +/// diagnostics in a variety of inconsistent situations. /// void Sema::ComparePropertiesInBaseAndSuper(ObjCInterfaceDecl *IDecl) { ObjCInterfaceDecl *SDecl = IDecl->getSuperClass(); @@ -1137,10 +1140,14 @@ Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl, static void AddPropertyAttrs(Sema &S, ObjCMethodDecl *PropertyMethod, ObjCPropertyDecl *Property) { // Should we just clone all attributes over? - if (DeprecatedAttr *A = Property->getAttr<DeprecatedAttr>()) - PropertyMethod->addAttr(A->clone(S.Context)); - if (UnavailableAttr *A = Property->getAttr<UnavailableAttr>()) - PropertyMethod->addAttr(A->clone(S.Context)); + for (Decl::attr_iterator A = Property->attr_begin(), + AEnd = Property->attr_end(); + A != AEnd; ++A) { + if (isa<DeprecatedAttr>(*A) || + isa<UnavailableAttr>(*A) || + isa<AvailabilityAttr>(*A)) + PropertyMethod->addAttr((*A)->clone(S.Context)); + } } /// ProcessPropertyDecl - Make sure that any user-defined setter/getter methods @@ -1235,7 +1242,8 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property, // Invent the arguments for the setter. We don't bother making a // nice name for the argument. - ParmVarDecl *Argument = ParmVarDecl::Create(Context, SetterMethod, Loc, + ParmVarDecl *Argument = ParmVarDecl::Create(Context, SetterMethod, + Loc, Loc, property->getIdentifier(), property->getType(), /*TInfo=*/0, diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp index 8d03285..3f3ed0e 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp @@ -36,18 +36,26 @@ using namespace sema; /// A convenience routine for creating a decayed reference to a /// function. -static Expr * +static ExprResult CreateFunctionRefExpr(Sema &S, FunctionDecl *Fn, SourceLocation Loc = SourceLocation()) { - Expr *E = new (S.Context) DeclRefExpr(Fn, Fn->getType(), VK_LValue, Loc); - S.DefaultFunctionArrayConversion(E); - return E; + ExprResult E = S.Owned(new (S.Context) DeclRefExpr(Fn, Fn->getType(), VK_LValue, Loc)); + 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); + +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, @@ -128,7 +136,9 @@ ImplicitConversionRank GetConversionRank(ImplicitConversionKind Kind) { ICR_Conversion, ICR_Conversion, ICR_Conversion, - ICR_Complex_Real_Conversion + ICR_Complex_Real_Conversion, + ICR_Conversion, + ICR_Conversion }; return Rank[(int)Kind]; } @@ -157,7 +167,9 @@ const char* GetImplicitConversionName(ImplicitConversionKind Kind) { "Derived-to-base conversion", "Vector conversion", "Vector splat", - "Complex-real conversion" + "Complex-real conversion", + "Block Pointer conversion", + "Transparent Union Conversion" }; return Name[Kind]; } @@ -228,7 +240,7 @@ isPointerConversionToVoidPointer(ASTContext& Context) const { if (First == ICK_Array_To_Pointer) FromType = Context.getArrayDecayedType(FromType); - if (Second == ICK_Pointer_Conversion && FromType->isPointerType()) + if (Second == ICK_Pointer_Conversion && FromType->isAnyPointerType()) if (const PointerType* ToPtrType = ToType->getAs<PointerType>()) return ToPtrType->getPointeeType()->isVoidType(); @@ -876,20 +888,19 @@ bool Sema::TryImplicitConversion(InitializationSequence &Sequence, } /// PerformImplicitConversion - Perform an implicit conversion of the -/// expression From to the type ToType. Returns true if there was an -/// error, false otherwise. The expression From is replaced with the +/// 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. -bool -Sema::PerformImplicitConversion(Expr *&From, QualType ToType, +ExprResult +Sema::PerformImplicitConversion(Expr *From, QualType ToType, AssignmentAction Action, bool AllowExplicit) { ImplicitConversionSequence ICS; return PerformImplicitConversion(From, ToType, Action, AllowExplicit, ICS); } -bool -Sema::PerformImplicitConversion(Expr *&From, QualType ToType, +ExprResult +Sema::PerformImplicitConversion(Expr *From, QualType ToType, AssignmentAction Action, bool AllowExplicit, ImplicitConversionSequence& ICS) { ICS = clang::TryImplicitConversion(*this, From, ToType, @@ -1048,27 +1059,33 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, // otherwise, only a boolean conversion is standard if (!ToType->isBooleanType()) return false; - - } - - if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn)) { - if (!Method->isStatic()) { - const Type *ClassType - = S.Context.getTypeDeclType(Method->getParent()).getTypePtr(); - FromType = S.Context.getMemberPointerType(FromType, ClassType); - } } - // If the "from" expression takes the address of the overloaded - // function, update the type of the resulting expression accordingly. - if (FromType->getAs<FunctionType>()) - if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(From->IgnoreParens())) - if (UnOp->getOpcode() == UO_AddrOf) - FromType = S.Context.getPointerType(FromType); + // 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<CXXMethodDecl>(Fn); + if (Method && !Method->isStatic()) { + assert(isa<UnaryOperator>(From->IgnoreParens()) && + "Non-unary operator on non-static member address"); + assert(cast<UnaryOperator>(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<UnaryOperator>(From->IgnoreParens())) { + assert(cast<UnaryOperator>(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())); + assert(S.Context.hasSameType( + FromType, + S.FixOverloadedFunctionReference(From, AccessPair, Fn)->getType())); } else { return false; } @@ -1188,6 +1205,7 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, // 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). @@ -1203,6 +1221,11 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, } else if (IsNoReturnConversion(S.Context, 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 { // No second conversion required. SCS.Second = ICK_Identity; @@ -1244,6 +1267,30 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, 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<TransparentUnionAttr>()) + 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)) { + ToType = it->getType(); + return true; + } + } + return false; +} /// IsIntegralPromotion - Determines whether the conversion from the /// expression From (whose potentially-adjusted type is FromType) to @@ -1615,8 +1662,30 @@ bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType, 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, @@ -1627,6 +1696,9 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, if (!getLangOptions().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<ObjCObjectPointerType>(); @@ -1640,10 +1712,11 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, 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 = ToType; + ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers); return true; } // Conversions with Objective-C's id<...>. @@ -1651,7 +1724,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, ToObjCPtr->isObjCQualifiedIdType()) && Context.ObjCQualifiedIdTypesAreCompatible(ToType, FromType, /*compare=*/false)) { - ConvertedType = ToType; + ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers); return true; } // Objective C++: We're able to convert from a pointer to an @@ -1666,6 +1739,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, ConvertedType = BuildSimilarlyQualifiedPointerType(FromObjCPtr, ToObjCPtr->getPointeeType(), ToType, Context); + ConvertedType = AdoptQualifiers(Context, ConvertedType, FromQualifiers); return true; } @@ -1677,6 +1751,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, ConvertedType = BuildSimilarlyQualifiedPointerType(FromObjCPtr, ToObjCPtr->getPointeeType(), ToType, Context); + ConvertedType = AdoptQualifiers(Context, ConvertedType, FromQualifiers); return true; } } @@ -1689,7 +1764,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, // Objective C++: We're able to convert from a pointer to any object // to a block pointer type. if (FromObjCPtr && FromObjCPtr->isObjCBuiltinType()) { - ConvertedType = ToType; + ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers); return true; } ToPointeeType = ToBlockPtr->getPointeeType(); @@ -1698,7 +1773,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, ToObjCPtr && ToObjCPtr->isObjCBuiltinType()) { // Objective C++: We're able to convert from a block pointer type to a // pointer to any object. - ConvertedType = ToType; + ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers); return true; } else @@ -1721,6 +1796,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, // 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; @@ -1730,6 +1806,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, isObjCPointerConversion(FromPointeeType, ToPointeeType, ConvertedType, IncompatibleObjC)) { ConvertedType = Context.getPointerType(ConvertedType); + ConvertedType = AdoptQualifiers(Context, ConvertedType, FromQualifiers); return true; } @@ -1790,7 +1867,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, if (HasObjCConversion) { // We had an Objective-C conversion. Allow this pointer // conversion, but complain about it. - ConvertedType = ToType; + ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers); IncompatibleObjC = true; return true; } @@ -1936,11 +2013,12 @@ bool Sema::CheckPointerConversion(Expr *From, QualType ToType, Kind = CK_BitCast; - if (CXXBoolLiteralExpr* LitBool - = dyn_cast<CXXBoolLiteralExpr>(From->IgnoreParens())) - if (!IsCStyleOrFunctionalCast && LitBool->getValue() == false) - Diag(LitBool->getExprLoc(), diag::warn_init_pointer_from_false) - << ToType; + 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 *FromPtrType = FromType->getAs<PointerType>()) if (const PointerType *ToPtrType = ToType->getAs<PointerType>()) { @@ -2116,21 +2194,24 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType, // unwrap. UnwrappedAnyPointer = true; + Qualifiers FromQuals = FromType.getQualifiers(); + Qualifiers ToQuals = ToType.getQualifiers(); + // -- for every j > 0, if const is in cv 1,j then const is in cv // 2,j, and similarly for volatile. - if (!CStyle && !ToType.isAtLeastAsQualifiedAs(FromType)) + 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 && FromType.getCVRQualifiers() != ToType.getCVRQualifiers() + 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 && ToType.isConstQualified(); + = PreviousToQualsIncludeConst && ToQuals.hasConst(); } // We are left with FromType and ToType being the pointee types @@ -2175,7 +2256,11 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, S.IsDerivedFrom(From->getType(), ToType))) ConstructorsOnly = true; - if (S.RequireCompleteType(From->getLocStart(), ToType, S.PDiag())) { + 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<CXXRecordDecl>(ToRecordType->getDecl())) { @@ -2546,7 +2631,8 @@ CompareStandardConversionSequences(Sema &S, if (ImplicitConversionSequence::CompareKind DerivedCK = CompareDerivedToBaseConversions(S, SCS1, SCS2)) return DerivedCK; - } else if (SCS1ConvertsToVoid && SCS2ConvertsToVoid) { + } 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. @@ -2560,10 +2646,8 @@ CompareStandardConversionSequences(Sema &S, if (SCS2.First == ICK_Array_To_Pointer) FromType2 = S.Context.getArrayDecayedType(FromType2); - QualType FromPointee1 - = FromType1->getAs<PointerType>()->getPointeeType().getUnqualifiedType(); - QualType FromPointee2 - = FromType2->getAs<PointerType>()->getPointeeType().getUnqualifiedType(); + QualType FromPointee1 = FromType1->getPointeeType().getUnqualifiedType(); + QualType FromPointee2 = FromType2->getPointeeType().getUnqualifiedType(); if (S.IsDerivedFrom(FromPointee2, FromPointee1)) return ImplicitConversionSequence::Better; @@ -2572,13 +2656,19 @@ CompareStandardConversionSequences(Sema &S, // Objective-C++: If one interface is more specific than the // other, it is the better one. - const ObjCObjectType* FromIface1 = FromPointee1->getAs<ObjCObjectType>(); - const ObjCObjectType* FromIface2 = FromPointee2->getAs<ObjCObjectType>(); - if (FromIface1 && FromIface1) { - if (S.Context.canAssignObjCInterfaces(FromIface2, FromIface1)) - return ImplicitConversionSequence::Better; - else if (S.Context.canAssignObjCInterfaces(FromIface1, FromIface2)) - return ImplicitConversionSequence::Worse; + const ObjCObjectPointerType* FromObjCPtr1 + = FromType1->getAs<ObjCObjectPointerType>(); + const ObjCObjectPointerType* FromObjCPtr2 + = FromType2->getAs<ObjCObjectPointerType>(); + 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; + } } } @@ -2981,7 +3071,12 @@ Sema::CompareReferenceRelationship(SourceLocation Loc, // 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). - if (T1Quals.getCVRQualifiers() == T2Quals.getCVRQualifiers()) + // + // 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 == T2Quals) return Ref_Compatible; else if (T1.isMoreQualifiedThan(T2)) return Ref_Compatible_With_Added_Qualification; @@ -3480,8 +3575,8 @@ TryObjectArgumentInitialization(Sema &S, QualType OrigFromType, /// PerformObjectArgumentInitialization - Perform initialization of /// the implicit object parameter for the given Method with the given /// expression. -bool -Sema::PerformObjectArgumentInitialization(Expr *&From, +ExprResult +Sema::PerformObjectArgumentInitialization(Expr *From, NestedNameSpecifier *Qualifier, NamedDecl *FoundDecl, CXXMethodDecl *Method) { @@ -3517,7 +3612,7 @@ Sema::PerformObjectArgumentInitialization(Expr *&From, << From->getSourceRange(); Diag(Method->getLocation(), diag::note_previous_decl) << Method->getDeclName(); - return true; + return ExprError(); } } @@ -3526,13 +3621,18 @@ Sema::PerformObjectArgumentInitialization(Expr *&From, << ImplicitParamRecordType << FromRecordType << From->getSourceRange(); } - if (ICS.Standard.Second == ICK_Derived_To_Base) - return PerformObjectMemberConversion(From, Qualifier, FoundDecl, Method); + 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)) - ImpCastExprToType(From, DestType, CK_NoOp, - From->getType()->isPointerType() ? VK_RValue : VK_LValue); - return false; + From = ImpCastExprToType(From, DestType, CK_NoOp, + From->getType()->isPointerType() ? VK_RValue : VK_LValue).take(); + return Owned(From); } /// TryContextuallyConvertToBool - Attempt to contextually convert the @@ -3550,16 +3650,16 @@ TryContextuallyConvertToBool(Sema &S, Expr *From) { /// PerformContextuallyConvertToBool - Perform a contextual conversion /// of the expression From to bool (C++0x [conv]p3). -bool Sema::PerformContextuallyConvertToBool(Expr *&From) { +ExprResult Sema::PerformContextuallyConvertToBool(Expr *From) { ImplicitConversionSequence ICS = TryContextuallyConvertToBool(*this, From); if (!ICS.isBad()) return PerformImplicitConversion(From, Context.BoolTy, ICS, AA_Converting); if (!DiagnoseMultipleUserDefinedConversion(From, Context.BoolTy)) - return Diag(From->getSourceRange().getBegin(), - diag::err_typecheck_bool_condition) + return Diag(From->getSourceRange().getBegin(), + diag::err_typecheck_bool_condition) << From->getType() << From->getSourceRange(); - return true; + return ExprError(); } /// TryContextuallyConvertToObjCId - Attempt to contextually convert the @@ -3577,12 +3677,12 @@ TryContextuallyConvertToObjCId(Sema &S, Expr *From) { /// PerformContextuallyConvertToObjCId - Perform a contextual conversion /// of the expression From to 'id'. -bool Sema::PerformContextuallyConvertToObjCId(Expr *&From) { +ExprResult Sema::PerformContextuallyConvertToObjCId(Expr *From) { QualType Ty = Context.getObjCIdType(); ImplicitConversionSequence ICS = TryContextuallyConvertToObjCId(*this, From); if (!ICS.isBad()) return PerformImplicitConversion(From, Ty, ICS, AA_Converting); - return true; + return ExprError(); } /// \brief Attempt to convert the given expression to an integral or @@ -4061,7 +4161,7 @@ void Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, - const TemplateArgumentListInfo *ExplicitTemplateArgs, + TemplateArgumentListInfo *ExplicitTemplateArgs, QualType ObjectType, Expr::Classification ObjectClassification, Expr **Args, unsigned NumArgs, @@ -4114,7 +4214,7 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, void Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl, - const TemplateArgumentListInfo *ExplicitTemplateArgs, + TemplateArgumentListInfo *ExplicitTemplateArgs, Expr **Args, unsigned NumArgs, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions) { @@ -6090,9 +6190,10 @@ void Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, bool Operator, Expr **Args, unsigned NumArgs, - const TemplateArgumentListInfo *ExplicitTemplateArgs, + TemplateArgumentListInfo *ExplicitTemplateArgs, OverloadCandidateSet& CandidateSet, - bool PartialOverloading) { + bool PartialOverloading, + bool StdNamespaceIsAssociated) { ADLResult Fns; // FIXME: This approach for uniquing ADL results (and removing @@ -6103,7 +6204,8 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, // we supposed to consider on ADL candidates, anyway? // FIXME: Pass in the explicit template arguments? - ArgumentDependentLookup(Name, Operator, Args, NumArgs, Fns); + ArgumentDependentLookup(Name, Operator, Args, NumArgs, Fns, + StdNamespaceIsAssociated); // Erase all of the candidates we already knew about. for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(), @@ -6282,8 +6384,7 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc, // Best is the best viable function. if (Best->Function && - (Best->Function->isDeleted() || - Best->Function->getAttr<UnavailableAttr>())) + (Best->Function->isDeleted() || Best->Function->isUnavailable())) return OR_Deleted; return OR_Success; @@ -6473,6 +6574,17 @@ void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) { 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"); @@ -6735,7 +6847,7 @@ void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand, FunctionDecl *Fn = Cand->Function; // Note deleted candidates, but only if they're viable. - if (Cand->Viable && (Fn->isDeleted() || Fn->hasAttr<UnavailableAttr>())) { + if (Cand->Viable && (Fn->isDeleted() || Fn->isUnavailable())) { std::string FnDesc; OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Fn, FnDesc); @@ -7134,8 +7246,23 @@ public: if (!TargetFunctionType->isFunctionType()) { if (OvlExpr->hasExplicitTemplateArgs()) { DeclAccessPair dap; - if( FunctionDecl* Fn = S.ResolveSingleFunctionTemplateSpecialization( + if (FunctionDecl* Fn = S.ResolveSingleFunctionTemplateSpecialization( OvlExpr, false, &dap) ) { + + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(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)); } } @@ -7419,32 +7546,29 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr, QualType TargetTyp /// 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(Expr *From, - bool Complain, - DeclAccessPair* FoundResult) { +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 (From->getType() != Context.OverloadTy) - return 0; - - OverloadExpr *OvlExpr = OverloadExpr::find(From).Expression; // If we didn't actually find any template-ids, we're done. - if (!OvlExpr->hasExplicitTemplateArgs()) + if (!ovl->hasExplicitTemplateArgs()) return 0; TemplateArgumentListInfo ExplicitTemplateArgs; - OvlExpr->getExplicitTemplateArgs().copyInto(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 = OvlExpr->decls_begin(), - E = OvlExpr->decls_end(); I != E; ++I) { + 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 @@ -7461,7 +7585,7 @@ FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From, // function template specialization, which is added to the set of // overloaded functions considered. FunctionDecl *Specialization = 0; - TemplateDeductionInfo Info(Context, OvlExpr->getNameLoc()); + TemplateDeductionInfo Info(Context, ovl->getNameLoc()); if (TemplateDeductionResult Result = DeduceTemplateArguments(FunctionTemplate, &ExplicitTemplateArgs, Specialization, Info)) { @@ -7470,30 +7594,98 @@ FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From, continue; } + assert(Specialization && "no specialization and no error?"); + // Multiple matches; we can't resolve to a single declaration. if (Matched) { - if (FoundResult) - *FoundResult = DeclAccessPair(); - if (Complain) { - Diag(From->getLocStart(), diag::err_addr_ovl_ambiguous) - << OvlExpr->getName(); - NoteAllOverloadCandidates(OvlExpr); + Diag(ovl->getExprLoc(), diag::err_addr_ovl_ambiguous) + << ovl->getName(); + NoteAllOverloadCandidates(ovl); } return 0; - } + } - if ((Matched = Specialization) && FoundResult) - *FoundResult = I.getPair(); + 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 +ExprResult Sema::ResolveAndFixSingleFunctionTemplateSpecialization( + Expr *SrcExpr, bool doFunctionPointerConverion, bool complain, + const SourceRange& OpRangeForComplaining, + QualType DestTypeForComplaining, + unsigned DiagIDForComplaining) { + assert(SrcExpr->getType() == Context.OverloadTy); + + OverloadExpr::FindResult ovl = OverloadExpr::find(SrcExpr); + + DeclAccessPair found; + ExprResult SingleFunctionExpression; + if (FunctionDecl *fn = ResolveSingleFunctionTemplateSpecialization( + ovl.Expression, /*complain*/ false, &found)) { + if (DiagnoseUseOfDecl(fn, SrcExpr->getSourceRange().getBegin())) + return ExprError(); + + // 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<CXXMethodDecl>(fn) && + cast<CXXMethodDecl>(fn)->isInstance()) { + if (complain) { + Diag(ovl.Expression->getExprLoc(), + diag::err_invalid_use_of_bound_member_func) + << 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. + } + + return ExprError(); + } + + // Fix the expresion to refer to 'fn'. + SingleFunctionExpression = + Owned(FixOverloadedFunctionReference(SrcExpr, found, fn)); + + // If desired, do function-to-pointer decay. + if (doFunctionPointerConverion) + SingleFunctionExpression = + DefaultFunctionArrayLvalueConversion(SingleFunctionExpression.take()); + } + + if (!SingleFunctionExpression.isUsable()) { + if (complain) { + Diag(OpRangeForComplaining.getBegin(), DiagIDForComplaining) + << ovl.Expression->getName() + << DestTypeForComplaining + << OpRangeForComplaining + << ovl.Expression->getQualifierLoc().getSourceRange(); + NoteAllOverloadCandidates(SrcExpr); + } + return ExprError(); + } + + return SingleFunctionExpression; +} + /// \brief Add a single candidate to the overload set. static void AddOverloadedCallCandidate(Sema &S, DeclAccessPair FoundDecl, - const TemplateArgumentListInfo *ExplicitTemplateArgs, + TemplateArgumentListInfo *ExplicitTemplateArgs, Expr **Args, unsigned NumArgs, OverloadCandidateSet &CandidateSet, bool PartialOverloading) { @@ -7559,7 +7751,7 @@ void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE, // It would be nice to avoid this copy. TemplateArgumentListInfo TABuffer; - const TemplateArgumentListInfo *ExplicitTemplateArgs = 0; + TemplateArgumentListInfo *ExplicitTemplateArgs = 0; if (ULE->hasExplicitTemplateArgs()) { ULE->copyTemplateArgumentsInto(TABuffer); ExplicitTemplateArgs = &TABuffer; @@ -7576,7 +7768,8 @@ void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE, Args, NumArgs, ExplicitTemplateArgs, CandidateSet, - PartialOverloading); + PartialOverloading, + ULE->isStdAssociatedNamespace()); } /// Attempts to recover from a call where no functions were found. @@ -7590,9 +7783,7 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, SourceLocation RParenLoc) { CXXScopeSpec SS; - if (ULE->getQualifier()) - SS.MakeTrivial(SemaRef.Context, - ULE->getQualifier(), ULE->getQualifierRange()); + SS.Adopt(ULE->getQualifierLoc()); TemplateArgumentListInfo TABuffer; const TemplateArgumentListInfo *ExplicitTemplateArgs = 0; @@ -7657,7 +7848,9 @@ Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, // We don't perform ADL in C. assert(getLangOptions().CPlusPlus && "ADL enabled in C"); - } + } else + assert(!ULE->isStdAssociatedNamespace() && + "std is associated namespace but not doing ADL"); #endif OverloadCandidateSet CandidateSet(Fn->getExprLoc()); @@ -7704,8 +7897,7 @@ Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, Diag(Fn->getSourceRange().getBegin(), diag::err_ovl_deleted_call) << Best->Function->isDeleted() << ULE->getName() - << Best->Function->getMessageUnavailableAttr( - !Best->Function->isDeleted()) + << getDeletedOrUnavailableSuffix(Best->Function) << Fn->getSourceRange(); CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); } @@ -7749,8 +7941,12 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, // TODO: provide better source location info. DeclarationNameInfo OpNameInfo(OpName, OpLoc); - if (Input->getObjectKind() == OK_ObjCProperty) - ConvertPropertyForRValue(Input); + if (Input->getObjectKind() == OK_ObjCProperty) { + ExprResult Result = ConvertPropertyForRValue(Input); + if (Result.isInvalid()) + return ExprError(); + Input = Result.take(); + } Expr *Args[2] = { Input, 0 }; unsigned NumArgs = 1; @@ -7776,11 +7972,11 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators UnresolvedLookupExpr *Fn = UnresolvedLookupExpr::Create(Context, NamingClass, - 0, SourceRange(), OpNameInfo, + NestedNameSpecifierLoc(), OpNameInfo, /*ADL*/ true, IsOverloaded(Fns), Fns.begin(), Fns.end()); return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn, - &Args[0], NumArgs, + &Args[0], NumArgs, Context.DependentTy, VK_RValue, OpLoc)); @@ -7821,9 +8017,12 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) { CheckMemberOperatorAccess(OpLoc, Args[0], 0, Best->FoundDecl); - if (PerformObjectArgumentInitialization(Input, /*Qualifier=*/0, - Best->FoundDecl, Method)) + ExprResult InputRes = + PerformObjectArgumentInitialization(Input, /*Qualifier=*/0, + Best->FoundDecl, Method); + if (InputRes.isInvalid()) return ExprError(); + Input = InputRes.take(); } else { // Convert the arguments. ExprResult InputInit @@ -7845,11 +8044,13 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, ResultTy = ResultTy.getNonLValueExprType(Context); // Build the actual expression node. - Expr *FnExpr = CreateFunctionRefExpr(*this, FnDecl); + ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl); + if (FnExpr.isInvalid()) + return ExprError(); Args[0] = Input; CallExpr *TheCall = - new (Context) CXXOperatorCallExpr(Context, Op, FnExpr, + new (Context) CXXOperatorCallExpr(Context, Op, FnExpr.take(), Args, NumArgs, ResultTy, VK, OpLoc); if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall, @@ -7861,39 +8062,40 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, // We matched a built-in operator. Convert the arguments, then // break out so that we will build the appropriate built-in // operator node. - if (PerformImplicitConversion(Input, Best->BuiltinTypes.ParamTypes[0], - Best->Conversions[0], AA_Passing)) - return ExprError(); - - break; - } - } - - case OR_No_Viable_Function: - // No viable function; fall through to handling this as a - // built-in operator, which will produce an error message for us. + ExprResult InputRes = + PerformImplicitConversion(Input, Best->BuiltinTypes.ParamTypes[0], + Best->Conversions[0], AA_Passing); + if (InputRes.isInvalid()) + return ExprError(); + Input = InputRes.take(); break; + } + } - case OR_Ambiguous: - Diag(OpLoc, diag::err_ovl_ambiguous_oper_unary) - << UnaryOperator::getOpcodeStr(Opc) - << Input->getType() - << Input->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, - Args, NumArgs, - UnaryOperator::getOpcodeStr(Opc), OpLoc); - return ExprError(); + case OR_No_Viable_Function: + // No viable function; fall through to handling this as a + // built-in operator, which will produce an error message for us. + break; - case OR_Deleted: - Diag(OpLoc, diag::err_ovl_deleted_oper) - << Best->Function->isDeleted() + case OR_Ambiguous: + Diag(OpLoc, diag::err_ovl_ambiguous_oper_unary) << UnaryOperator::getOpcodeStr(Opc) - << Best->Function->getMessageUnavailableAttr( - !Best->Function->isDeleted()) + << Input->getType() << Input->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); - return ExprError(); - } + CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, + 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, Args, NumArgs); + return ExprError(); + } // Either we found no viable overloaded operator or we matched a // built-in operator. In either case, fall through to trying to @@ -7956,8 +8158,9 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // TODO: provide better source location info in DNLoc component. DeclarationNameInfo OpNameInfo(OpName, OpLoc); UnresolvedLookupExpr *Fn - = UnresolvedLookupExpr::Create(Context, NamingClass, 0, SourceRange(), - OpNameInfo, /*ADL*/ true, IsOverloaded(Fns), + = UnresolvedLookupExpr::Create(Context, NamingClass, + NestedNameSpecifierLoc(), OpNameInfo, + /*ADL*/ true, IsOverloaded(Fns), Fns.begin(), Fns.end()); return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn, Args, 2, @@ -7967,8 +8170,12 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, } // Always do property rvalue conversions on the RHS. - if (Args[1]->getObjectKind() == OK_ObjCProperty) - ConvertPropertyForRValue(Args[1]); + if (Args[1]->getObjectKind() == OK_ObjCProperty) { + ExprResult Result = ConvertPropertyForRValue(Args[1]); + if (Result.isInvalid()) + return ExprError(); + Args[1] = Result.take(); + } // The LHS is more complicated. if (Args[0]->getObjectKind() == OK_ObjCProperty) { @@ -7996,7 +8203,10 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]); } - ConvertPropertyForRValue(Args[0]); + ExprResult Result = ConvertPropertyForRValue(Args[0]); + if (Result.isInvalid()) + return ExprError(); + Args[0] = Result.take(); } // If this is the assignment operator, we only perform overload resolution @@ -8057,10 +8267,12 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, if (Arg1.isInvalid()) return ExprError(); - if (PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0, - Best->FoundDecl, Method)) + ExprResult Arg0 = + PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0, + Best->FoundDecl, Method); + if (Arg0.isInvalid()) return ExprError(); - + Args[0] = Arg0.takeAs<Expr>(); Args[1] = RHS = Arg1.takeAs<Expr>(); } else { // Convert the arguments. @@ -8090,10 +8302,12 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, ResultTy = ResultTy.getNonLValueExprType(Context); // Build the actual expression node. - Expr *FnExpr = CreateFunctionRefExpr(*this, FnDecl, OpLoc); + ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl, OpLoc); + if (FnExpr.isInvalid()) + return ExprError(); CXXOperatorCallExpr *TheCall = - new (Context) CXXOperatorCallExpr(Context, Op, FnExpr, + new (Context) CXXOperatorCallExpr(Context, Op, FnExpr.take(), Args, 2, ResultTy, VK, OpLoc); if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall, @@ -8105,12 +8319,19 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // We matched a built-in operator. Convert the arguments, then // break out so that we will build the appropriate built-in // operator node. - if (PerformImplicitConversion(Args[0], Best->BuiltinTypes.ParamTypes[0], - Best->Conversions[0], AA_Passing) || - PerformImplicitConversion(Args[1], Best->BuiltinTypes.ParamTypes[1], - Best->Conversions[1], AA_Passing)) + 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; } } @@ -8158,8 +8379,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, Diag(OpLoc, diag::err_ovl_deleted_oper) << Best->Function->isDeleted() << BinaryOperator::getOpcodeStr(Opc) - << Best->Function->getMessageUnavailableAttr( - !Best->Function->isDeleted()) + << getDeletedOrUnavailableSuffix(Best->Function) << Args[0]->getSourceRange() << Args[1]->getSourceRange(); CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, 2); return ExprError(); @@ -8187,7 +8407,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, OpNameInfo.setCXXOperatorNameRange(SourceRange(LLoc, RLoc)); UnresolvedLookupExpr *Fn = UnresolvedLookupExpr::Create(Context, NamingClass, - 0, SourceRange(), OpNameInfo, + NestedNameSpecifierLoc(), OpNameInfo, /*ADL*/ true, /*Overloaded*/ false, UnresolvedSetIterator(), UnresolvedSetIterator()); @@ -8200,10 +8420,18 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, RLoc)); } - if (Args[0]->getObjectKind() == OK_ObjCProperty) - ConvertPropertyForRValue(Args[0]); - if (Args[1]->getObjectKind() == OK_ObjCProperty) - ConvertPropertyForRValue(Args[1]); + if (Args[0]->getObjectKind() == OK_ObjCProperty) { + ExprResult Result = ConvertPropertyForRValue(Args[0]); + if (Result.isInvalid()) + return ExprError(); + Args[0] = Result.take(); + } + if (Args[1]->getObjectKind() == OK_ObjCProperty) { + ExprResult Result = ConvertPropertyForRValue(Args[1]); + if (Result.isInvalid()) + return ExprError(); + Args[1] = Result.take(); + } // Build an empty overload set. OverloadCandidateSet CandidateSet(LLoc); @@ -8234,9 +8462,12 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, // Convert the arguments. CXXMethodDecl *Method = cast<CXXMethodDecl>(FnDecl); - if (PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0, - Best->FoundDecl, Method)) + ExprResult Arg0 = + PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0, + Best->FoundDecl, Method); + if (Arg0.isInvalid()) return ExprError(); + Args[0] = Arg0.take(); // Convert the arguments. ExprResult InputInit @@ -8256,11 +8487,13 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, ResultTy = ResultTy.getNonLValueExprType(Context); // Build the actual expression node. - Expr *FnExpr = CreateFunctionRefExpr(*this, FnDecl, LLoc); + ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl, LLoc); + if (FnExpr.isInvalid()) + return ExprError(); CXXOperatorCallExpr *TheCall = new (Context) CXXOperatorCallExpr(Context, OO_Subscript, - FnExpr, Args, 2, + FnExpr.take(), Args, 2, ResultTy, VK, RLoc); if (CheckCallReturnType(FnDecl->getResultType(), LLoc, TheCall, @@ -8272,11 +8505,19 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, // We matched a built-in operator. Convert the arguments, then // break out so that we will build the appropriate built-in // operator node. - if (PerformImplicitConversion(Args[0], Best->BuiltinTypes.ParamTypes[0], - Best->Conversions[0], AA_Passing) || - PerformImplicitConversion(Args[1], Best->BuiltinTypes.ParamTypes[1], - Best->Conversions[1], AA_Passing)) + 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; } @@ -8308,8 +8549,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, case OR_Deleted: Diag(LLoc, diag::err_ovl_deleted_oper) << Best->Function->isDeleted() << "[]" - << Best->Function->getMessageUnavailableAttr( - !Best->Function->isDeleted()) + << getDeletedOrUnavailableSuffix(Best->Function) << Args[0]->getSourceRange() << Args[1]->getSourceRange(); CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, 2, "[]", LLoc); @@ -8325,16 +8565,66 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, /// 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 member function or an overloaded member -/// function. +/// 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<BinaryOperator>(NakedMemExpr)) { + assert(op->getType() == Context.BoundMemberTy); + assert(op->getOpcode() == BO_PtrMemD || op->getOpcode() == BO_PtrMemI); + + QualType fnType = + op->getRHS()->getType()->castAs<MemberPointerType>()->getPointeeType(); + + const FunctionProtoType *proto = fnType->castAs<FunctionProtoType>(); + 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<PointerType>()->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()->getSourceRange().getBegin(), + call, 0)) + return ExprError(); + + if (ConvertArgumentsForCall(call, op, 0, proto, Args, NumArgs, RParenLoc)) + return ExprError(); + + return MaybeBindToTemporary(call); + } + MemberExpr *MemExpr; CXXMethodDecl *Method = 0; DeclAccessPair FoundDecl = DeclAccessPair::make(0, AS_public); @@ -8427,8 +8717,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, Diag(UnresExpr->getMemberLoc(), diag::err_ovl_deleted_member_call) << Best->Function->isDeleted() << DeclName - << Best->Function->getMessageUnavailableAttr( - !Best->Function->isDeleted()) + << getDeletedOrUnavailableSuffix(Best->Function) << MemExprE->getSourceRange(); CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); // FIXME: Leaking incoming expressions! @@ -8464,12 +8753,14 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, // 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. - Expr *ObjectArg = MemExpr->getBase(); - if (!Method->isStatic() && - PerformObjectArgumentInitialization(ObjectArg, Qualifier, - FoundDecl, Method)) - return ExprError(); - MemExpr->setBase(ObjectArg); + 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 = @@ -8489,15 +8780,19 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, /// overloaded function call operator (@c operator()) or performing a /// user-defined conversion on the object argument. ExprResult -Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, +Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, SourceLocation LParenLoc, Expr **Args, unsigned NumArgs, SourceLocation RParenLoc) { - if (Object->getObjectKind() == OK_ObjCProperty) - ConvertPropertyForRValue(Object); + ExprResult Object = Owned(Obj); + if (Object.get()->getObjectKind() == OK_ObjCProperty) { + Object = ConvertPropertyForRValue(Object.take()); + if (Object.isInvalid()) + return ExprError(); + } - assert(Object->getType()->isRecordType() && "Requires object type argument"); - const RecordType *Record = Object->getType()->getAs<RecordType>(); + assert(Object.get()->getType()->isRecordType() && "Requires object type argument"); + const RecordType *Record = Object.get()->getType()->getAs<RecordType>(); // C++ [over.call.object]p1: // If the primary-expression E in the function call syntax @@ -8509,9 +8804,9 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, OverloadCandidateSet CandidateSet(LParenLoc); DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Call); - if (RequireCompleteType(LParenLoc, Object->getType(), + if (RequireCompleteType(LParenLoc, Object.get()->getType(), PDiag(diag::err_incomplete_object_call) - << Object->getSourceRange())) + << Object.get()->getSourceRange())) return true; LookupResult R(*this, OpName, LParenLoc, LookupOrdinaryName); @@ -8520,8 +8815,8 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end(); Oper != OperEnd; ++Oper) { - AddMethodCandidate(Oper.getPair(), Object->getType(), - Object->Classify(Context), Args, NumArgs, CandidateSet, + AddMethodCandidate(Oper.getPair(), Object.get()->getType(), + Object.get()->Classify(Context), Args, NumArgs, CandidateSet, /*SuppressUserConversions=*/ false); } @@ -8566,12 +8861,12 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, if (const FunctionProtoType *Proto = ConvType->getAs<FunctionProtoType>()) AddSurrogateCandidate(Conv, I.getPair(), ActingContext, Proto, - Object, Args, NumArgs, CandidateSet); + Object.get(), Args, NumArgs, CandidateSet); } // Perform overload resolution. OverloadCandidateSet::iterator Best; - switch (CandidateSet.BestViableFunction(*this, Object->getLocStart(), + switch (CandidateSet.BestViableFunction(*this, Object.get()->getLocStart(), Best)) { case OR_Success: // Overload resolution succeeded; we'll build the appropriate call @@ -8580,31 +8875,30 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, case OR_No_Viable_Function: if (CandidateSet.empty()) - Diag(Object->getSourceRange().getBegin(), diag::err_ovl_no_oper) - << Object->getType() << /*call*/ 1 - << Object->getSourceRange(); + Diag(Object.get()->getSourceRange().getBegin(), diag::err_ovl_no_oper) + << Object.get()->getType() << /*call*/ 1 + << Object.get()->getSourceRange(); else - Diag(Object->getSourceRange().getBegin(), + Diag(Object.get()->getSourceRange().getBegin(), diag::err_ovl_no_viable_object_call) - << Object->getType() << Object->getSourceRange(); + << Object.get()->getType() << Object.get()->getSourceRange(); CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); break; case OR_Ambiguous: - Diag(Object->getSourceRange().getBegin(), + Diag(Object.get()->getSourceRange().getBegin(), diag::err_ovl_ambiguous_object_call) - << Object->getType() << Object->getSourceRange(); + << Object.get()->getType() << Object.get()->getSourceRange(); CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args, NumArgs); break; case OR_Deleted: - Diag(Object->getSourceRange().getBegin(), + Diag(Object.get()->getSourceRange().getBegin(), diag::err_ovl_deleted_object_call) << Best->Function->isDeleted() - << Object->getType() - << Best->Function->getMessageUnavailableAttr( - !Best->Function->isDeleted()) - << Object->getSourceRange(); + << Object.get()->getType() + << getDeletedOrUnavailableSuffix(Best->Function) + << Object.get()->getSourceRange(); CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); break; } @@ -8619,7 +8913,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, = cast<CXXConversionDecl>( Best->Conversions[0].UserDefined.ConversionFunction); - CheckMemberOperatorAccess(LParenLoc, Object, 0, Best->FoundDecl); + CheckMemberOperatorAccess(LParenLoc, Object.get(), 0, Best->FoundDecl); DiagnoseUseOfDecl(Best->FoundDecl, LParenLoc); // We selected one of the surrogate functions that converts the @@ -8628,7 +8922,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, // Create an implicit member expr to refer to the conversion operator. // and then call it. - ExprResult Call = BuildCXXMemberCallExpr(Object, Best->FoundDecl, Conv); + ExprResult Call = BuildCXXMemberCallExpr(Object.get(), Best->FoundDecl, Conv); if (Call.isInvalid()) return ExprError(); @@ -8637,7 +8931,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, } MarkDeclarationReferenced(LParenLoc, Best->Function); - CheckMemberOperatorAccess(LParenLoc, Object, 0, Best->FoundDecl); + CheckMemberOperatorAccess(LParenLoc, Object.get(), 0, Best->FoundDecl); DiagnoseUseOfDecl(Best->FoundDecl, LParenLoc); // We found an overloaded operator(). Build a CXXOperatorCallExpr @@ -8660,11 +8954,13 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, } else { MethodArgs = new Expr*[NumArgs + 1]; } - MethodArgs[0] = Object; + MethodArgs[0] = Object.get(); for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) MethodArgs[ArgIdx + 1] = Args[ArgIdx]; - Expr *NewFn = CreateFunctionRefExpr(*this, Method); + ExprResult NewFn = CreateFunctionRefExpr(*this, Method); + if (NewFn.isInvalid()) + return true; // Once we've built TheCall, all of the expressions are properly // owned. @@ -8673,7 +8969,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, ResultTy = ResultTy.getNonLValueExprType(Context); CXXOperatorCallExpr *TheCall = - new (Context) CXXOperatorCallExpr(Context, OO_Call, NewFn, + new (Context) CXXOperatorCallExpr(Context, OO_Call, NewFn.take(), MethodArgs, NumArgs + 1, ResultTy, VK, RParenLoc); delete [] MethodArgs; @@ -8692,10 +8988,14 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, bool IsError = false; // Initialize the implicit object parameter. - IsError |= PerformObjectArgumentInitialization(Object, /*Qualifier=*/0, - Best->FoundDecl, Method); - TheCall->setArg(0, Object); - + 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++) { @@ -8731,9 +9031,9 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, if (Proto->isVariadic()) { // Promote the arguments (C99 6.5.2.2p7). for (unsigned i = NumArgsInProto; i != NumArgs; i++) { - Expr *Arg = Args[i]; - IsError |= DefaultVariadicArgumentPromotion(Arg, VariadicMethod, 0); - TheCall->setArg(i + 1, Arg); + ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], VariadicMethod, 0); + IsError |= Arg.isInvalid(); + TheCall->setArg(i + 1, Arg.take()); } } @@ -8753,8 +9053,12 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) { assert(Base->getType()->isRecordType() && "left-hand side must have class type"); - if (Base->getObjectKind() == OK_ObjCProperty) - ConvertPropertyForRValue(Base); + if (Base->getObjectKind() == OK_ObjCProperty) { + ExprResult Result = ConvertPropertyForRValue(Base); + if (Result.isInvalid()) + return ExprError(); + Base = Result.take(); + } SourceLocation Loc = Base->getExprLoc(); @@ -8811,8 +9115,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) { Diag(OpLoc, diag::err_ovl_deleted_oper) << Best->Function->isDeleted() << "->" - << Best->Function->getMessageUnavailableAttr( - !Best->Function->isDeleted()) + << getDeletedOrUnavailableSuffix(Best->Function) << Base->getSourceRange(); CandidateSet.NoteCandidates(*this, OCD_AllCandidates, &Base, 1); return ExprError(); @@ -8824,24 +9127,30 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) { // Convert the object parameter. CXXMethodDecl *Method = cast<CXXMethodDecl>(Best->Function); - if (PerformObjectArgumentInitialization(Base, /*Qualifier=*/0, - Best->FoundDecl, Method)) + ExprResult BaseResult = + PerformObjectArgumentInitialization(Base, /*Qualifier=*/0, + Best->FoundDecl, Method); + if (BaseResult.isInvalid()) return ExprError(); + Base = BaseResult.take(); // Build the operator call. - Expr *FnExpr = CreateFunctionRefExpr(*this, Method); + ExprResult FnExpr = CreateFunctionRefExpr(*this, Method); + 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, + new (Context) CXXOperatorCallExpr(Context, OO_Arrow, FnExpr.take(), &Base, 1, ResultTy, VK, OpLoc); if (CheckCallReturnType(Method->getResultType(), OpLoc, TheCall, Method)) return ExprError(); - return Owned(TheCall); + + return MaybeBindToTemporary(TheCall); } /// FixOverloadedFunctionReference - E is an expression that refers to @@ -8930,12 +9239,12 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, } return DeclRefExpr::Create(Context, - ULE->getQualifier(), - ULE->getQualifierRange(), + ULE->getQualifierLoc(), Fn, ULE->getNameLoc(), Fn->getType(), VK_LValue, + Found.getDecl(), TemplateArgs); } @@ -8954,17 +9263,17 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, if (MemExpr->isImplicitAccess()) { if (cast<CXXMethodDecl>(Fn)->isStatic()) { return DeclRefExpr::Create(Context, - MemExpr->getQualifier(), - MemExpr->getQualifierRange(), + MemExpr->getQualifierLoc(), Fn, MemExpr->getMemberLoc(), Fn->getType(), VK_LValue, + Found.getDecl(), TemplateArgs); } else { SourceLocation Loc = MemExpr->getMemberLoc(); if (MemExpr->getQualifier()) - Loc = MemExpr->getQualifierRange().getBegin(); + Loc = MemExpr->getQualifierLoc().getBeginLoc(); Base = new (Context) CXXThisExpr(Loc, MemExpr->getBaseType(), /*isImplicit=*/true); @@ -8972,18 +9281,24 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, } else Base = MemExpr->getBase(); + ExprValueKind valueKind; + QualType type; + if (cast<CXXMethodDecl>(Fn)->isStatic()) { + valueKind = VK_LValue; + type = Fn->getType(); + } else { + valueKind = VK_RValue; + type = Context.BoundMemberTy; + } + return MemberExpr::Create(Context, Base, MemExpr->isArrow(), - MemExpr->getQualifier(), - MemExpr->getQualifierRange(), + MemExpr->getQualifierLoc(), Fn, Found, MemExpr->getMemberNameInfo(), TemplateArgs, - Fn->getType(), - cast<CXXMethodDecl>(Fn)->isStatic() - ? VK_LValue : VK_RValue, - OK_Ordinary); + type, valueKind, OK_Ordinary); } llvm_unreachable("Invalid reference to overloaded function"); diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp index 89957e6..65cea7a 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp @@ -15,6 +15,7 @@ #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/Initialization.h" +#include "clang/Sema/Lookup.h" #include "clang/AST/APValue.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" @@ -45,8 +46,9 @@ StmtResult Sema::ActOnExprStmt(FullExprArg expr) { } -StmtResult Sema::ActOnNullStmt(SourceLocation SemiLoc, bool LeadingEmptyMacro) { - return Owned(new (Context) NullStmt(SemiLoc, LeadingEmptyMacro)); +StmtResult Sema::ActOnNullStmt(SourceLocation SemiLoc, + SourceLocation LeadingEmptyMacroLoc) { + return Owned(new (Context) NullStmt(SemiLoc, LeadingEmptyMacroLoc)); } StmtResult Sema::ActOnDeclStmt(DeclGroupPtrTy dg, SourceLocation StartLoc, @@ -76,12 +78,6 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) { if (!E) return; - if (E->isBoundMemberFunction(Context)) { - Diag(E->getLocStart(), diag::err_invalid_use_of_bound_member_func) - << E->getSourceRange(); - return; - } - SourceLocation Loc; SourceRange R1, R2; if (!E->isUnusedResultAWarning(Loc, R1, R2, Context)) @@ -245,11 +241,10 @@ Sema::ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl, } // Otherwise, things are good. Fill in the declaration and return it. - TheDecl->setLocation(IdentLoc); - LabelStmt *LS = new (Context) LabelStmt(IdentLoc, TheDecl, SubStmt); TheDecl->setStmt(LS); - TheDecl->setLocation(IdentLoc); + if (!TheDecl->isGnuLocal()) + TheDecl->setLocation(IdentLoc); return Owned(LS); } @@ -470,7 +465,10 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, GetTypeBeforeIntegralPromotion(CondExpr); // C99 6.8.4.2p5 - Integer promotions are performed on the controlling expr. - UsualUnaryConversions(CondExpr); + ExprResult CondResult = UsualUnaryConversions(CondExpr); + if (CondResult.isInvalid()) + return StmtError(); + CondExpr = CondResult.take(); QualType CondType = CondExpr->getType(); SS->setCond(CondExpr); @@ -556,7 +554,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, // If the LHS is not the same type as the condition, insert an implicit // cast. - ImpCastExprToType(Lo, CondType, CK_IntegralCast); + Lo = ImpCastExprToType(Lo, CondType, CK_IntegralCast).take(); CS->setLHS(Lo); // If this is a case range, remember it in CaseRanges, otherwise CaseVals. @@ -635,7 +633,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, // If the LHS is not the same type as the condition, insert an implicit // cast. - ImpCastExprToType(Hi, CondType, CK_IntegralCast); + Hi = ImpCastExprToType(Hi, CondType, CK_IntegralCast).take(); CR->setRHS(Hi); // If the low value is bigger than the high value, the case is empty. @@ -869,11 +867,13 @@ Sema::ActOnDoStmt(SourceLocation DoLoc, Stmt *Body, Expr *Cond, SourceLocation CondRParen) { assert(Cond && "ActOnDoStmt(): missing expression"); - if (CheckBooleanCondition(Cond, DoLoc)) + ExprResult CondResult = CheckBooleanCondition(Cond, DoLoc); + if (CondResult.isInvalid() || CondResult.isInvalid()) return StmtError(); + Cond = CondResult.take(); CheckImplicitConversions(Cond, DoLoc); - ExprResult CondResult = MaybeCreateExprWithCleanups(Cond); + CondResult = MaybeCreateExprWithCleanups(Cond); if (CondResult.isInvalid()) return StmtError(); Cond = CondResult.take(); @@ -974,7 +974,10 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc, << FirstType << First->getSourceRange(); } if (Second && !Second->isTypeDependent()) { - DefaultFunctionArrayLvalueConversion(Second); + ExprResult Result = DefaultFunctionArrayLvalueConversion(Second); + if (Result.isInvalid()) + return StmtError(); + Second = Result.take(); QualType SecondType = Second->getType(); if (!SecondType->isObjCObjectPointerType()) Diag(ForLoc, diag::err_collection_expr_type) @@ -992,7 +995,8 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc, Selector CSelector = Context.Selectors.getSelector(3, &KeyIdents[0]); if (ObjCInterfaceDecl *IDecl = OPT->getInterfaceDecl()) { if (!IDecl->isForwardDecl() && - !IDecl->lookupInstanceMethod(CSelector)) { + !IDecl->lookupInstanceMethod(CSelector) && + !LookupMethodInQualifiedType(CSelector, OPT, true)) { // Must further look into private implementation methods. if (!LookupPrivateInstanceMethod(CSelector, IDecl)) Diag(ForLoc, diag::warn_collection_expr_type) @@ -1005,6 +1009,389 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc, 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 (Init->getType()->isVoidType() || + !SemaRef.DeduceAutoType(Decl->getTypeSourceInfo(), Init, InitTSI)) + SemaRef.Diag(Loc, diag) << Init->getType(); + if (!InitTSI) { + Decl->setInvalidDecl(); + return true; + } + Decl->setTypeSourceInfo(InitTSI); + Decl->setType(InitTSI->getType()); + + 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<CallExpr>(E); + if (!CE) + return; + FunctionDecl *D = dyn_cast<FunctionDecl>(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(), + /*Qualifier=*/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); + 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<DeclStmt>(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<DeclStmt>(RangeDecl); + VarDecl *RangeVar = cast<VarDecl>(RangeDS->getSingleDecl()); + QualType RangeVarType = RangeVar->getType(); + + DeclStmt *LoopVarDS = cast<DeclStmt>(LoopVarDecl); + VarDecl *LoopVar = cast<VarDecl>(LoopVarDS->getSingleDecl()); + + StmtResult BeginEndDecl = BeginEnd; + ExprResult NotEqExpr = Cond, IncrExpr = Inc; + + if (!BeginEndDecl.get() && !RangeVarType->isDependentType()) { + SourceLocation RangeLoc = RangeVar->getLocation(); + + ExprResult RangeRef = BuildDeclRefExpr(RangeVar, + RangeVarType.getNonReferenceType(), + VK_LValue, ColonLoc); + if (RangeRef.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 = RangeRef; + if (FinishForRangeVarDecl(*this, BeginVar, RangeRef.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<ConstantArrayType>(UnqAT)) + BoundExpr = Owned(IntegerLiteral::Create(Context, CAT->getSize(), + Context.IntTy, RangeLoc)); + else if (const VariableArrayType *VAT = + dyn_cast<VariableArrayType>(UnqAT)) + BoundExpr = VAT->getSizeExpr(); + else { + // Can't be a DependentSizedArrayType or an IncompleteArrayType since + // UnqAT is not incomplete and Range is not type-dependent. + assert(0 && "Unexpected array type in for-range"); + return StmtError(); + } + + // end-expr is __range + __bound. + EndExpr = ActOnBinOp(S, ColonLoc, tok::plus, RangeRef.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, RangeRef.get()); + if (BeginExpr.isInvalid()) + return StmtError(); + + EndExpr = BuildForRangeBeginEndCall(*this, S, ColonLoc, EndVar, + BEF_end, EndNameInfo, + EndMemberLookup, RangeRef.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); + + ExprResult BeginRef = BuildDeclRefExpr(BeginVar, + BeginType.getNonReferenceType(), + VK_LValue, ColonLoc); + ExprResult EndRef = BuildDeclRefExpr(EndVar, EndType.getNonReferenceType(), + VK_LValue, ColonLoc); + + // 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. + 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. + 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); + } + } + + return Owned(new (Context) CXXForRangeStmt(RangeDS, + cast_or_null<DeclStmt>(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(); + + cast<CXXForRangeStmt>(S)->setBody(B); + return S; +} + StmtResult Sema::ActOnGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc, LabelDecl *TheDecl) { @@ -1020,8 +1407,12 @@ Sema::ActOnIndirectGotoStmt(SourceLocation GotoLoc, SourceLocation StarLoc, if (!E->isTypeDependent()) { QualType ETy = E->getType(); QualType DestTy = Context.getPointerType(Context.VoidTy.withConst()); + ExprResult ExprRes = Owned(E); AssignConvertType ConvTy = - CheckSingleAssignmentConstraints(DestTy, E); + CheckSingleAssignmentConstraints(DestTy, ExprRes); + if (ExprRes.isInvalid()) + return StmtError(); + E = ExprRes.take(); if (DiagnoseAssignmentResult(ConvTy, StarLoc, DestTy, ETy, E, AA_Passing)) return StmtError(); } @@ -1188,7 +1579,10 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { if (RetValExp) { // Don't call UsualUnaryConversions(), since we don't want to do // integer promotions here. - DefaultFunctionArrayLvalueConversion(RetValExp); + ExprResult Result = DefaultFunctionArrayLvalueConversion(RetValExp); + if (Result.isInvalid()) + return StmtError(); + RetValExp = Result.take(); CurBlock->ReturnType = RetValExp->getType(); if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(RetValExp)) { // We have to remove a 'const' added to copied-in variable which was @@ -1290,8 +1684,12 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { if (RetValExp->getType()->isVoidType()) D = diag::ext_return_has_void_expr; else { - IgnoredValueConversions(RetValExp); - ImpCastExprToType(RetValExp, Context.VoidTy, CK_ToVoid); + 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++. @@ -1498,8 +1896,11 @@ StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple, } } - DefaultFunctionArrayLvalueConversion(Exprs[i]); + ExprResult Result = DefaultFunctionArrayLvalueConversion(Exprs[i]); + if (Result.isInvalid()) + return StmtError(); + Exprs[i] = Result.take(); InputConstraintInfos.push_back(Info); } @@ -1614,7 +2015,7 @@ StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple, if (InputDomain == AD_Int && OutputDomain == AD_Int && !isOperandMentioned(InputOpNo, Pieces) && InputExpr->isEvaluatable(Context)) { - ImpCastExprToType(InputExpr, OutTy, CK_IntegralCast); + InputExpr = ImpCastExprToType(InputExpr, OutTy, CK_IntegralCast).take(); Exprs[InputOpNo] = InputExpr; NS->setInputExpr(i, InputExpr); continue; @@ -1663,8 +2064,11 @@ Sema::ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try, StmtResult Sema::BuildObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw) { if (Throw) { - DefaultLvalueConversion(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() && @@ -1703,8 +2107,11 @@ Sema::ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, Expr *SyncExpr, Stmt *SyncBody) { getCurFunction()->setHasBranchProtectedScope(); - DefaultLvalueConversion(SyncExpr); + ExprResult Result = DefaultLvalueConversion(SyncExpr); + if (Result.isInvalid()) + return StmtError(); + SyncExpr = Result.take(); // Make sure the expression type is an ObjC pointer or "void *". if (!SyncExpr->getType()->isDependentType() && !SyncExpr->getType()->isObjCObjectPointerType()) { @@ -1766,7 +2173,7 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, MultiStmtArg RawHandlers) { // Don't report an error if 'try' is used in system headers. - if (!getLangOptions().Exceptions && + if (!getLangOptions().CXXExceptions && !getSourceManager().isInSystemHeader(TryLoc)) Diag(TryLoc, diag::err_exceptions_disabled) << "try"; @@ -1824,3 +2231,36 @@ Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, 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)); +} + diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp index f02dd25..ef09124 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp @@ -76,13 +76,13 @@ static NamedDecl *isAcceptableTemplateName(ASTContext &Context, return 0; } -static void FilterAcceptableTemplateNames(ASTContext &C, LookupResult &R) { +void Sema::FilterAcceptableTemplateNames(LookupResult &R) { // The set of class templates we've already seen. llvm::SmallPtrSet<ClassTemplateDecl *, 8> ClassTemplates; LookupResult::Filter filter = R.makeFilter(); while (filter.hasNext()) { NamedDecl *Orig = filter.next(); - NamedDecl *Repl = isAcceptableTemplateName(C, Orig); + NamedDecl *Repl = isAcceptableTemplateName(Context, Orig); if (!Repl) filter.erase(); else if (Repl != Orig) { @@ -114,6 +114,14 @@ static void FilterAcceptableTemplateNames(ASTContext &C, LookupResult &R) { filter.done(); } +bool Sema::hasAnyAcceptableTemplateNames(LookupResult &R) { + for (LookupResult::iterator I = R.begin(), IEnd = R.end(); I != IEnd; ++I) + if (isAcceptableTemplateName(Context, *I)) + return true; + + return false; +} + TemplateNameKind Sema::isTemplateName(Scope *S, CXXScopeSpec &SS, bool hasTemplateKeyword, @@ -289,7 +297,7 @@ void Sema::LookupTemplateName(LookupResult &Found, DeclarationName Name = Found.getLookupName(); if (DeclarationName Corrected = CorrectTypo(Found, S, &SS, LookupCtx, false, CTC_CXXCasts)) { - FilterAcceptableTemplateNames(Context, Found); + FilterAcceptableTemplateNames(Found); if (!Found.empty()) { if (LookupCtx) Diag(Found.getNameLoc(), diag::err_no_member_template_suggest) @@ -311,7 +319,7 @@ void Sema::LookupTemplateName(LookupResult &Found, } } - FilterAcceptableTemplateNames(Context, Found); + FilterAcceptableTemplateNames(Found); if (Found.empty()) { if (isDependent) MemberOfUnknownSpecialization = true; @@ -327,7 +335,7 @@ void Sema::LookupTemplateName(LookupResult &Found, LookupResult FoundOuter(*this, Found.getLookupName(), Found.getNameLoc(), LookupOrdinaryName); LookupName(FoundOuter, S); - FilterAcceptableTemplateNames(Context, FoundOuter); + FilterAcceptableTemplateNames(FoundOuter); if (FoundOuter.empty()) { // - if the name is not found, the name found in the class of the @@ -368,9 +376,6 @@ Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, bool isAddressOfOperand, const TemplateArgumentListInfo *TemplateArgs) { - NestedNameSpecifier *Qualifier - = static_cast<NestedNameSpecifier*>(SS.getScopeRep()); - DeclContext *DC = getFunctionLevelDeclContext(); if (!isAddressOfOperand && @@ -386,7 +391,7 @@ Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS, /*This*/ 0, ThisType, /*IsArrow*/ true, /*Op*/ SourceLocation(), - Qualifier, SS.getRange(), + SS.getWithLocInContext(Context), FirstQualifierInScope, NameInfo, TemplateArgs)); @@ -472,7 +477,8 @@ static TemplateArgumentLoc translateTemplateArgument(Sema &SemaRef, else TArg = Template; return TemplateArgumentLoc(TArg, - Arg.getScopeSpec().getRange(), + Arg.getScopeSpec().getWithLocInContext( + SemaRef.Context), Arg.getLocation(), Arg.getEllipsisLoc()); } @@ -497,7 +503,7 @@ void Sema::translateTemplateArguments(const ASTTemplateArgsPtr &TemplateArgsIn, /// (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 -/// ParamName is the location of the parameter name (if any). +/// 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, @@ -527,8 +533,9 @@ Decl *Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis, TemplateTypeParmDecl *Param = TemplateTypeParmDecl::Create(Context, Context.getTranslationUnitDecl(), - Loc, Depth, Position, ParamName, Typename, - Ellipsis); + KeyLoc, Loc, Depth, Position, ParamName, + Typename, Ellipsis); + Param->setAccess(AS_public); if (Invalid) Param->setInvalidDecl(); @@ -651,9 +658,12 @@ Decl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, bool IsParameterPack = D.hasEllipsis(); NonTypeTemplateParmDecl *Param = NonTypeTemplateParmDecl::Create(Context, Context.getTranslationUnitDecl(), + D.getSourceRange().getBegin(), D.getIdentifierLoc(), Depth, Position, ParamName, T, IsParameterPack, TInfo); + Param->setAccess(AS_public); + if (Invalid) Param->setInvalidDecl(); @@ -678,10 +688,12 @@ Decl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, return Param; TemplateArgument Converted; - if (CheckTemplateArgument(Param, Param->getType(), Default, Converted)) { + ExprResult DefaultRes = CheckTemplateArgument(Param, Param->getType(), Default, Converted); + if (DefaultRes.isInvalid()) { Param->setInvalidDecl(); return Param; } + Default = DefaultRes.take(); Param->setDefaultArgument(Default, false); } @@ -707,13 +719,13 @@ Decl *Sema::ActOnTemplateTemplateParameter(Scope* S, // Construct the parameter object. bool IsParameterPack = EllipsisLoc.isValid(); - // FIXME: Pack-ness is dropped TemplateTemplateParmDecl *Param = TemplateTemplateParmDecl::Create(Context, Context.getTranslationUnitDecl(), NameLoc.isInvalid()? TmpLoc : NameLoc, Depth, Position, IsParameterPack, Name, Params); - + Param->setAccess(AS_public); + // If the template template parameter has a name, then link the identifier // into the scope and lookup mechanisms. if (Name) { @@ -791,7 +803,9 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, IdentifierInfo *Name, SourceLocation NameLoc, AttributeList *Attr, TemplateParameterList *TemplateParams, - AccessSpecifier AS) { + AccessSpecifier AS, + unsigned NumOuterTemplateParamLists, + TemplateParameterList** OuterTemplateParamLists) { assert(TemplateParams && TemplateParams->size() > 0 && "No template parameters"); assert(TUK != TUK_Reference && "Can only declare or define class templates"); @@ -961,11 +975,15 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, } CXXRecordDecl *NewClass = - CXXRecordDecl::Create(Context, Kind, SemanticContext, NameLoc, Name, KWLoc, + CXXRecordDecl::Create(Context, Kind, SemanticContext, KWLoc, NameLoc, Name, PrevClassTemplate? PrevClassTemplate->getTemplatedDecl() : 0, /*DelayTypeCreation=*/true); SetNestedNameSpecifier(NewClass, SS); + if (NumOuterTemplateParamLists > 0) + NewClass->setTemplateParameterListsInfo(Context, + NumOuterTemplateParamLists, + OuterTemplateParamLists); ClassTemplateDecl *NewTemplate = ClassTemplateDecl::Create(Context, SemanticContext, NameLoc, @@ -1089,7 +1107,8 @@ static bool DiagnoseDefaultTemplateArgument(Sema &S, /// \brief Check for unexpanded parameter packs within the template parameters /// of a template template parameter, recursively. -bool DiagnoseUnexpandedParameterPacks(Sema &S, TemplateTemplateParmDecl *TTP){ +static bool DiagnoseUnexpandedParameterPacks(Sema &S, + TemplateTemplateParmDecl *TTP) { TemplateParameterList *Params = TTP->getTemplateParameters(); for (unsigned I = 0, N = Params->size(); I != N; ++I) { NamedDecl *P = Params->getParam(I); @@ -1448,9 +1467,9 @@ DependsOnTemplateParameters(const TemplateSpecializationType *TemplateId, /// /// \returns the template parameter list, if any, that corresponds to the /// name that is preceded by the scope specifier @p SS. This template -/// parameter list may be have template parameters (if we're declaring a +/// parameter list may have template parameters (if we're declaring a /// template) or may have no template parameters (if we're declaring a -/// template specialization), or may be NULL (if we were's declaring isn't +/// template specialization), or may be NULL (if what we're declaring isn't /// itself a template). TemplateParameterList * Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, @@ -1631,14 +1650,42 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, return ParamLists[NumParamLists - 1]; } +void Sema::NoteAllFoundTemplates(TemplateName Name) { + if (TemplateDecl *Template = Name.getAsTemplateDecl()) { + Diag(Template->getLocation(), diag::note_template_declared_here) + << (isa<FunctionTemplateDecl>(Template)? 0 + : isa<ClassTemplateDecl>(Template)? 1 + : 2) + << Template->getDeclName(); + return; + } + + if (OverloadedTemplateStorage *OST = Name.getAsOverloadedTemplate()) { + for (OverloadedTemplateStorage::iterator I = OST->begin(), + IEnd = OST->end(); + I != IEnd; ++I) + Diag((*I)->getLocation(), diag::note_template_declared_here) + << 0 << (*I)->getDeclName(); + + return; + } +} + + QualType Sema::CheckTemplateIdType(TemplateName Name, SourceLocation TemplateLoc, - const TemplateArgumentListInfo &TemplateArgs) { + TemplateArgumentListInfo &TemplateArgs) { TemplateDecl *Template = Name.getAsTemplateDecl(); - if (!Template) { - // The template name does not resolve to a template, so we just - // build a dependent template-id type. - return Context.getTemplateSpecializationType(Name, TemplateArgs); + if (!Template || isa<FunctionTemplateDecl>(Template)) { + // We might have a substituted template template parameter pack. If so, + // build a template specialization type for it. + if (Name.getAsSubstTemplateTemplateParmPack()) + return Context.getTemplateSpecializationType(Name, TemplateArgs); + + Diag(TemplateLoc, diag::err_template_id_not_a_type) + << Name; + NoteAllFoundTemplates(Name); + return QualType(); } // Check that the template argument list is well-formed for this @@ -1727,6 +1774,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, ClassTemplate->getTemplatedDecl()->getTagKind(), ClassTemplate->getDeclContext(), ClassTemplate->getLocation(), + ClassTemplate->getLocation(), ClassTemplate, Converted.data(), Converted.size(), 0); @@ -1746,77 +1794,148 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, } TypeResult -Sema::ActOnTemplateIdType(TemplateTy TemplateD, SourceLocation TemplateLoc, +Sema::ActOnTemplateIdType(CXXScopeSpec &SS, + TemplateTy TemplateD, SourceLocation TemplateLoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgsIn, SourceLocation RAngleLoc) { + if (SS.isInvalid()) + return true; + TemplateName Template = TemplateD.getAsVal<TemplateName>(); // Translate the parser's template argument list in our AST format. TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc); translateTemplateArguments(TemplateArgsIn, TemplateArgs); + if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) { + QualType T = Context.getDependentTemplateSpecializationType(ETK_None, + DTN->getQualifier(), + DTN->getIdentifier(), + TemplateArgs); + + // Build type-source information. + TypeLocBuilder TLB; + DependentTemplateSpecializationTypeLoc SpecTL + = TLB.push<DependentTemplateSpecializationTypeLoc>(T); + SpecTL.setKeywordLoc(SourceLocation()); + SpecTL.setNameLoc(TemplateLoc); + SpecTL.setLAngleLoc(LAngleLoc); + SpecTL.setRAngleLoc(RAngleLoc); + SpecTL.setQualifierLoc(SS.getWithLocInContext(Context)); + for (unsigned I = 0, N = SpecTL.getNumArgs(); I != N; ++I) + SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo()); + return CreateParsedType(T, TLB.getTypeSourceInfo(Context, T)); + } + QualType Result = CheckTemplateIdType(Template, TemplateLoc, TemplateArgs); TemplateArgsIn.release(); if (Result.isNull()) return true; - TypeSourceInfo *DI = Context.CreateTypeSourceInfo(Result); - TemplateSpecializationTypeLoc TL - = cast<TemplateSpecializationTypeLoc>(DI->getTypeLoc()); - TL.setTemplateNameLoc(TemplateLoc); - TL.setLAngleLoc(LAngleLoc); - TL.setRAngleLoc(RAngleLoc); - for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) - TL.setArgLocInfo(i, TemplateArgs[i].getLocInfo()); - - return CreateParsedType(Result, DI); + // Build type-source information. + TypeLocBuilder TLB; + TemplateSpecializationTypeLoc SpecTL + = TLB.push<TemplateSpecializationTypeLoc>(Result); + SpecTL.setTemplateNameLoc(TemplateLoc); + SpecTL.setLAngleLoc(LAngleLoc); + SpecTL.setRAngleLoc(RAngleLoc); + for (unsigned i = 0, e = SpecTL.getNumArgs(); i != e; ++i) + SpecTL.setArgLocInfo(i, TemplateArgs[i].getLocInfo()); + + if (SS.isNotEmpty()) { + // Create an elaborated-type-specifier containing the nested-name-specifier. + Result = Context.getElaboratedType(ETK_None, SS.getScopeRep(), Result); + ElaboratedTypeLoc ElabTL = TLB.push<ElaboratedTypeLoc>(Result); + ElabTL.setKeywordLoc(SourceLocation()); + ElabTL.setQualifierLoc(SS.getWithLocInContext(Context)); + } + + return CreateParsedType(Result, TLB.getTypeSourceInfo(Context, Result)); } -TypeResult Sema::ActOnTagTemplateIdType(CXXScopeSpec &SS, - TypeResult TypeResult, - TagUseKind TUK, +TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK, TypeSpecifierType TagSpec, - SourceLocation TagLoc) { - if (TypeResult.isInvalid()) - return ::TypeResult(); - - TypeSourceInfo *DI; - QualType Type = GetTypeFromParser(TypeResult.get(), &DI); - - // Verify the tag specifier. + SourceLocation TagLoc, + CXXScopeSpec &SS, + TemplateTy TemplateD, + SourceLocation TemplateLoc, + SourceLocation LAngleLoc, + ASTTemplateArgsPtr TemplateArgsIn, + SourceLocation RAngleLoc) { + TemplateName Template = TemplateD.getAsVal<TemplateName>(); + + // Translate the parser's template argument list in our AST format. + TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc); + translateTemplateArguments(TemplateArgsIn, TemplateArgs); + + // Determine the tag kind TagTypeKind TagKind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec); + ElaboratedTypeKeyword Keyword + = TypeWithKeyword::getKeywordForTagTypeKind(TagKind); - if (const RecordType *RT = Type->getAs<RecordType>()) { + if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) { + QualType T = Context.getDependentTemplateSpecializationType(Keyword, + DTN->getQualifier(), + DTN->getIdentifier(), + TemplateArgs); + + // Build type-source information. + TypeLocBuilder TLB; + DependentTemplateSpecializationTypeLoc SpecTL + = TLB.push<DependentTemplateSpecializationTypeLoc>(T); + SpecTL.setKeywordLoc(TagLoc); + SpecTL.setNameLoc(TemplateLoc); + SpecTL.setLAngleLoc(LAngleLoc); + SpecTL.setRAngleLoc(RAngleLoc); + SpecTL.setQualifierLoc(SS.getWithLocInContext(Context)); + for (unsigned I = 0, N = SpecTL.getNumArgs(); I != N; ++I) + SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo()); + return CreateParsedType(T, TLB.getTypeSourceInfo(Context, T)); + } + + QualType Result = CheckTemplateIdType(Template, TemplateLoc, TemplateArgs); + if (Result.isNull()) + return TypeResult(); + + // Check the tag kind + if (const RecordType *RT = Result->getAs<RecordType>()) { RecordDecl *D = RT->getDecl(); - + IdentifierInfo *Id = D->getIdentifier(); assert(Id && "templated class must have an identifier"); - + if (!isAcceptableTagRedeclaration(D, TagKind, TagLoc, *Id)) { Diag(TagLoc, diag::err_use_with_wrong_tag) - << Type + << Result << FixItHint::CreateReplacement(SourceRange(TagLoc), D->getKindName()); Diag(D->getLocation(), diag::note_previous_use); } } - - ElaboratedTypeKeyword Keyword - = TypeWithKeyword::getKeywordForTagTypeKind(TagKind); - QualType ElabType = Context.getElaboratedType(Keyword, /*NNS=*/0, Type); - - TypeSourceInfo *ElabDI = Context.CreateTypeSourceInfo(ElabType); - ElaboratedTypeLoc TL = cast<ElaboratedTypeLoc>(ElabDI->getTypeLoc()); - TL.setKeywordLoc(TagLoc); - TL.setQualifierRange(SS.getRange()); - TL.getNamedTypeLoc().initializeFullCopy(DI->getTypeLoc()); - return CreateParsedType(ElabType, ElabDI); + + // Provide source-location information for the template specialization. + TypeLocBuilder TLB; + TemplateSpecializationTypeLoc SpecTL + = TLB.push<TemplateSpecializationTypeLoc>(Result); + SpecTL.setTemplateNameLoc(TemplateLoc); + SpecTL.setLAngleLoc(LAngleLoc); + SpecTL.setRAngleLoc(RAngleLoc); + for (unsigned i = 0, e = SpecTL.getNumArgs(); i != e; ++i) + SpecTL.setArgLocInfo(i, TemplateArgs[i].getLocInfo()); + + // Construct an elaborated type containing the nested-name-specifier (if any) + // and keyword. + Result = Context.getElaboratedType(Keyword, SS.getScopeRep(), Result); + ElaboratedTypeLoc ElabTL = TLB.push<ElaboratedTypeLoc>(Result); + ElabTL.setKeywordLoc(TagLoc); + ElabTL.setQualifierLoc(SS.getWithLocInContext(Context)); + return CreateParsedType(Result, TLB.getTypeSourceInfo(Context, Result)); } ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS, - LookupResult &R, - bool RequiresADL, + LookupResult &R, + bool RequiresADL, const TemplateArgumentListInfo &TemplateArgs) { // FIXME: Can we do any checking at this point? I guess we could check the // template arguments that we have against the template name, if the template @@ -1832,19 +1951,12 @@ ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS, assert(!R.empty() && "empty lookup results when building templateid"); assert(!R.isAmbiguous() && "ambiguous lookup when building templateid"); - NestedNameSpecifier *Qualifier = 0; - SourceRange QualifierRange; - if (SS.isSet()) { - Qualifier = static_cast<NestedNameSpecifier*>(SS.getScopeRep()); - QualifierRange = SS.getRange(); - } - // We don't want lookup warnings at this point. R.suppressDiagnostics(); UnresolvedLookupExpr *ULE = UnresolvedLookupExpr::Create(Context, R.getNamingClass(), - Qualifier, QualifierRange, + SS.getWithLocInContext(Context), R.getLookupNameInfo(), RequiresADL, TemplateArgs, R.begin(), R.end()); @@ -1935,7 +2047,8 @@ TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S, MemberOfUnknownSpecialization); if (TNK == TNK_Non_template && LookupCtx->isDependentContext() && isa<CXXRecordDecl>(LookupCtx) && - cast<CXXRecordDecl>(LookupCtx)->hasAnyDependentBases()) { + (!cast<CXXRecordDecl>(LookupCtx)->hasDefinition() || + cast<CXXRecordDecl>(LookupCtx)->hasAnyDependentBases())) { // This is a dependent template. Handle it below. } else if (TNK == TNK_Non_template) { Diag(Name.getSourceRange().getBegin(), @@ -2043,7 +2156,6 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, /// /// \param Converted the list of template arguments provided for template /// parameters that precede \p Param in the template parameter list. -/// /// \returns the substituted template argument, or NULL if an error occurred. static TypeSourceInfo * SubstDefaultTemplateArgument(Sema &SemaRef, @@ -2140,6 +2252,9 @@ SubstDefaultTemplateArgument(Sema &SemaRef, /// \param Converted the list of template arguments provided for template /// parameters that precede \p Param in the template parameter list. /// +/// \param QualifierLoc Will be set to the nested-name-specifier (with +/// source-location information) that precedes the template name. +/// /// \returns the substituted template argument, or NULL if an error occurred. static TemplateName SubstDefaultTemplateArgument(Sema &SemaRef, @@ -2147,7 +2262,8 @@ SubstDefaultTemplateArgument(Sema &SemaRef, SourceLocation TemplateLoc, SourceLocation RAngleLoc, TemplateTemplateParmDecl *Param, - llvm::SmallVectorImpl<TemplateArgument> &Converted) { + llvm::SmallVectorImpl<TemplateArgument> &Converted, + NestedNameSpecifierLoc &QualifierLoc) { TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Converted.data(), Converted.size()); @@ -2159,7 +2275,16 @@ SubstDefaultTemplateArgument(Sema &SemaRef, Converted.size(), SourceRange(TemplateLoc, RAngleLoc)); - return SemaRef.SubstTemplateName( + // Substitute into the nested-name-specifier first, + QualifierLoc = Param->getDefaultArgument().getTemplateQualifierLoc(); + if (QualifierLoc) { + QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, + AllTemplateArgs); + if (!QualifierLoc) + return TemplateName(); + } + + return SemaRef.SubstTemplateName(QualifierLoc, Param->getDefaultArgument().getArgument().getAsTemplate(), Param->getDefaultArgument().getTemplateNameLoc(), AllTemplateArgs); @@ -2195,10 +2320,10 @@ Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template, return TemplateArgumentLoc(); ExprResult Arg = SubstDefaultTemplateArgument(*this, Template, - TemplateLoc, - RAngleLoc, - NonTypeParm, - Converted); + TemplateLoc, + RAngleLoc, + NonTypeParm, + Converted); if (Arg.isInvalid()) return TemplateArgumentLoc(); @@ -2211,16 +2336,19 @@ Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template, if (!TempTempParm->hasDefaultArgument()) return TemplateArgumentLoc(); + + NestedNameSpecifierLoc QualifierLoc; TemplateName TName = SubstDefaultTemplateArgument(*this, Template, TemplateLoc, RAngleLoc, TempTempParm, - Converted); + Converted, + QualifierLoc); if (TName.isNull()) return TemplateArgumentLoc(); return TemplateArgumentLoc(TemplateArgument(TName), - TempTempParm->getDefaultArgument().getTemplateQualifierRange(), + TempTempParm->getDefaultArgument().getTemplateQualifierLoc(), TempTempParm->getDefaultArgument().getTemplateNameLoc()); } @@ -2300,9 +2428,11 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, return true; case TemplateArgument::Expression: { - Expr *E = Arg.getArgument().getAsExpr(); TemplateArgument Result; - if (CheckTemplateArgument(NTTP, NTTPType, E, Result, CTAK)) + ExprResult Res = + CheckTemplateArgument(NTTP, NTTPType, Arg.getArgument().getAsExpr(), + Result, CTAK); + if (Res.isInvalid()) return true; Converted.push_back(Result); @@ -2331,28 +2461,23 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, DeclarationNameInfo NameInfo(DTN->getIdentifier(), Arg.getTemplateNameLoc()); - // FIXME: TemplateArgumentLoc should store a NestedNameSpecifierLoc - // for the template name. CXXScopeSpec SS; - SS.MakeTrivial(Context, DTN->getQualifier(), - Arg.getTemplateQualifierRange()); - Expr *E = DependentScopeDeclRefExpr::Create(Context, + SS.Adopt(Arg.getTemplateQualifierLoc()); + ExprResult E = Owned(DependentScopeDeclRefExpr::Create(Context, SS.getWithLocInContext(Context), - NameInfo); + NameInfo)); // If we parsed the template argument as a pack expansion, create a // pack expansion expression. if (Arg.getArgument().getKind() == TemplateArgument::TemplateExpansion){ - ExprResult Expansion = ActOnPackExpansion(E, - Arg.getTemplateEllipsisLoc()); - if (Expansion.isInvalid()) + E = ActOnPackExpansion(E.take(), Arg.getTemplateEllipsisLoc()); + if (E.isInvalid()) return true; - - E = Expansion.get(); } TemplateArgument Result; - if (CheckTemplateArgument(NTTP, NTTPType, E, Result)) + E = CheckTemplateArgument(NTTP, NTTPType, E.take(), Result); + if (E.isInvalid()) return true; Converted.push_back(Result); @@ -2461,7 +2586,7 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, /// for specializing the given template. bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, SourceLocation TemplateLoc, - const TemplateArgumentListInfo &TemplateArgs, + TemplateArgumentListInfo &TemplateArgs, bool PartialTemplateArgs, llvm::SmallVectorImpl<TemplateArgument> &Converted) { TemplateParameterList *Params = Template->getTemplateParameters(); @@ -2499,6 +2624,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, // a template-id shall match the type and form specified for the // corresponding parameter declared by the template in its // template-parameter-list. + bool isTemplateTemplateParameter = isa<TemplateTemplateParmDecl>(Template); llvm::SmallVector<TemplateArgument, 2> ArgumentPack; TemplateParameterList::iterator Param = Params->begin(), ParamEnd = Params->end(); @@ -2604,17 +2730,18 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, break; } + NestedNameSpecifierLoc QualifierLoc; TemplateName Name = SubstDefaultTemplateArgument(*this, Template, TemplateLoc, RAngleLoc, TempParm, - Converted); + Converted, + QualifierLoc); if (Name.isNull()) return true; - Arg = TemplateArgumentLoc(TemplateArgument(Name), - TempParm->getDefaultArgument().getTemplateQualifierRange(), - TempParm->getDefaultArgument().getTemplateNameLoc()); + Arg = TemplateArgumentLoc(TemplateArgument(Name), QualifierLoc, + TempParm->getDefaultArgument().getTemplateNameLoc()); } // Introduce an instantiation record that describes where we are using @@ -2628,6 +2755,12 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, RAngleLoc, 0, Converted)) return true; + // Core issue 150 (assumed resolution): if this is a template template + // parameter, keep track of the default template arguments from the + // template definition. + if (isTemplateTemplateParameter) + TemplateArgs.addArgument(Arg); + // Move to the next template parameter and argument. ++Param; ++ArgIdx; @@ -2853,7 +2986,7 @@ bool UnnamedLocalNoLinkageFinder::VisitTagDecl(const TagDecl *Tag) { return true; } - if (!Tag->getDeclName() && !Tag->getTypedefForAnonDecl()) { + if (!Tag->getDeclName() && !Tag->getTypedefNameForAnonDecl()) { S.Diag(SR.getBegin(), diag::ext_template_arg_unnamed_type) << SR; S.Diag(Tag->getLocation(), diag::note_template_unnamed_type_here); return true; @@ -2961,13 +3094,25 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, SourceLocation AddrOpLoc; if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(Arg)) { if (UnOp->getOpcode() == UO_AddrOf) { + // Support &__uuidof(class_with_uuid) as a non-type template argument. + // Very common in Microsoft COM headers. + if (S.getLangOptions().Microsoft && + isa<CXXUuidofExpr>(UnOp->getSubExpr())) { + Converted = TemplateArgument(ArgIn); + return false; + } + DRE = dyn_cast<DeclRefExpr>(UnOp->getSubExpr()); AddressTaken = true; AddrOpLoc = UnOp->getOperatorLoc(); } - } else + } else { + if (S.getLangOptions().Microsoft && isa<CXXUuidofExpr>(Arg)) { + Converted = TemplateArgument(ArgIn); + return false; + } DRE = dyn_cast<DeclRefExpr>(Arg); - + } if (!DRE) { S.Diag(Arg->getLocStart(), diag::err_template_arg_not_decl_ref) << Arg->getSourceRange(); @@ -3266,15 +3411,14 @@ bool Sema::CheckTemplateArgumentPointerToMember(Expr *Arg, /// non-type template parameter. /// /// This routine implements the semantics of C++ [temp.arg.nontype]. -/// It returns true if an error occurred, and false otherwise. \p +/// If an error occurred, it returns ExprError(); otherwise, it +/// returns the converted template argument. \p /// InstantiatedParamType is the type of the non-type template /// parameter after it has been instantiated. -/// -/// If no error was detected, Converted receives the converted template argument. -bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, - QualType InstantiatedParamType, Expr *&Arg, - TemplateArgument &Converted, - CheckTemplateArgumentKind CTAK) { +ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, + QualType InstantiatedParamType, Expr *Arg, + TemplateArgument &Converted, + CheckTemplateArgumentKind CTAK) { SourceLocation StartLoc = Arg->getSourceRange().getBegin(); // If either the parameter has a dependent type or the argument is @@ -3282,7 +3426,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, if (InstantiatedParamType->isDependentType() || Arg->isTypeDependent()) { // FIXME: Produce a cloned, canonical expression? Converted = TemplateArgument(Arg); - return false; + return Owned(Arg); } // C++ [temp.arg.nontype]p5: @@ -3312,12 +3456,12 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, diag::err_template_arg_not_integral_or_enumeral) << ArgType << Arg->getSourceRange(); Diag(Param->getLocation(), diag::note_template_param_here); - return true; + return ExprError(); } else if (!Arg->isValueDependent() && !Arg->isIntegerConstantExpr(Value, Context, &NonConstantLoc)) { Diag(NonConstantLoc, diag::err_template_arg_not_ice) << ArgType << Arg->getSourceRange(); - return true; + return ExprError(); } // From here on out, all we care about are the unqualified forms @@ -3340,21 +3484,21 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, Diag(StartLoc, diag::err_deduced_non_type_template_arg_type_mismatch) << ArgType << ParamType; Diag(Param->getLocation(), diag::note_template_param_here); - return true; + return ExprError(); } else if (ParamType->isBooleanType()) { // This is an integral-to-boolean conversion. - ImpCastExprToType(Arg, ParamType, CK_IntegralToBoolean); + Arg = ImpCastExprToType(Arg, ParamType, CK_IntegralToBoolean).take(); } else if (IsIntegralPromotion(Arg, ArgType, ParamType) || !ParamType->isEnumeralType()) { // This is an integral promotion or conversion. - ImpCastExprToType(Arg, ParamType, CK_IntegralCast); + Arg = ImpCastExprToType(Arg, ParamType, CK_IntegralCast).take(); } else { // We can't perform this conversion. Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_not_convertible) << Arg->getType() << InstantiatedParamType << Arg->getSourceRange(); Diag(Param->getLocation(), diag::note_template_param_here); - return true; + return ExprError(); } QualType IntegerType = Context.getCanonicalType(ParamType); @@ -3404,13 +3548,13 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, // The argument is value-dependent. Create a new // TemplateArgument with the converted expression. Converted = TemplateArgument(Arg); - return false; + return Owned(Arg); } Converted = TemplateArgument(Value, ParamType->isEnumeralType() ? ParamType : IntegerType); - return false; + return Owned(Arg); } DeclAccessPair FoundResult; // temporary for ResolveOverloadedFunction @@ -3422,7 +3566,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, if (ArgType->isNullPtrType() && (ParamType->isPointerType() || ParamType->isMemberPointerType())) { Converted = TemplateArgument((NamedDecl *)0); - return false; + return Owned(Arg); } // Handle pointer-to-function, reference-to-function, and @@ -3454,22 +3598,25 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, true, FoundResult)) { if (DiagnoseUseOfDecl(Fn, Arg->getSourceRange().getBegin())) - return true; + return ExprError(); Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn); ArgType = Arg->getType(); } else - return true; + return ExprError(); } - if (!ParamType->isMemberPointerType()) - return CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param, - ParamType, - Arg, Converted); + if (!ParamType->isMemberPointerType()) { + if (CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param, + ParamType, + Arg, Converted)) + return ExprError(); + return Owned(Arg); + } if (IsQualificationConversion(ArgType, ParamType.getNonReferenceType(), false)) { - ImpCastExprToType(Arg, ParamType, CK_NoOp, CastCategory(Arg)); + Arg = ImpCastExprToType(Arg, ParamType, CK_NoOp, CastCategory(Arg)).take(); } else if (!Context.hasSameUnqualifiedType(ArgType, ParamType.getNonReferenceType())) { // We can't perform this conversion. @@ -3477,10 +3624,12 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, diag::err_template_arg_not_convertible) << Arg->getType() << InstantiatedParamType << Arg->getSourceRange(); Diag(Param->getLocation(), diag::note_template_param_here); - return true; + return ExprError(); } - return CheckTemplateArgumentPointerToMember(Arg, Converted); + if (CheckTemplateArgumentPointerToMember(Arg, Converted)) + return ExprError(); + return Owned(Arg); } if (ParamType->isPointerType()) { @@ -3491,9 +3640,11 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, assert(ParamType->getPointeeType()->isIncompleteOrObjectType() && "Only object pointers allowed here"); - return CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param, - ParamType, - Arg, Converted); + if (CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param, + ParamType, + Arg, Converted)) + return ExprError(); + return Owned(Arg); } if (const ReferenceType *ParamRefType = ParamType->getAs<ReferenceType>()) { @@ -3512,17 +3663,19 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, true, FoundResult)) { if (DiagnoseUseOfDecl(Fn, Arg->getSourceRange().getBegin())) - return true; + return ExprError(); Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn); ArgType = Arg->getType(); } else - return true; + return ExprError(); } - return CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param, - ParamType, - Arg, Converted); + if (CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param, + ParamType, + Arg, Converted)) + return ExprError(); + return Owned(Arg); } // -- For a non-type template-parameter of type pointer to data @@ -3532,17 +3685,19 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, if (Context.hasSameUnqualifiedType(ParamType, ArgType)) { // Types match exactly: nothing more to do here. } else if (IsQualificationConversion(ArgType, ParamType, false)) { - ImpCastExprToType(Arg, ParamType, CK_NoOp, CastCategory(Arg)); + Arg = ImpCastExprToType(Arg, ParamType, CK_NoOp, CastCategory(Arg)).take(); } else { // We can't perform this conversion. Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_not_convertible) << Arg->getType() << InstantiatedParamType << Arg->getSourceRange(); Diag(Param->getLocation(), diag::note_template_param_here); - return true; + return ExprError(); } - return CheckTemplateArgumentPointerToMember(Arg, Converted); + if (CheckTemplateArgumentPointerToMember(Arg, Converted)) + return ExprError(); + return Owned(Arg); } /// \brief Check a template argument against its corresponding @@ -3636,11 +3791,8 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg, // the element type on the parameter could be more qualified than the // element type in the expression we constructed. if (IsQualificationConversion(((Expr*) RefExpr.get())->getType(), - ParamType.getUnqualifiedType(), false)) { - Expr *RefE = RefExpr.takeAs<Expr>(); - ImpCastExprToType(RefE, ParamType.getUnqualifiedType(), CK_NoOp); - RefExpr = Owned(RefE); - } + ParamType.getUnqualifiedType(), false)) + RefExpr = ImpCastExprToType(RefExpr.take(), ParamType.getUnqualifiedType(), CK_NoOp); assert(!RefExpr.isInvalid() && Context.hasSameType(((Expr*) RefExpr.get())->getType(), @@ -3659,12 +3811,9 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg, if (T->isFunctionType() || T->isArrayType()) { // Decay functions and arrays. - Expr *RefE = (Expr *)RefExpr.get(); - DefaultFunctionArrayConversion(RefE); - if (RefE != RefExpr.get()) { - RefExpr.release(); - RefExpr = Owned(RefE); - } + RefExpr = DefaultFunctionArrayConversion(RefExpr.take()); + if (RefExpr.isInvalid()) + return ExprError(); return move(RefExpr); } @@ -3703,18 +3852,18 @@ Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg, if (T->isCharType() || T->isWideCharType()) return Owned(new (Context) CharacterLiteral( Arg.getAsIntegral()->getZExtValue(), - T->isWideCharType(), - T, - Loc)); + T->isWideCharType(), T, Loc)); if (T->isBooleanType()) return Owned(new (Context) CXXBoolLiteralExpr( Arg.getAsIntegral()->getBoolValue(), - T, - Loc)); + T, Loc)); + // If this is an enum type that we're instantiating, we need to use an integer + // type the same size as the enumerator. We don't want to build an + // IntegerLiteral with enum type. QualType BT; if (const EnumType *ET = T->getAs<EnumType>()) - BT = ET->getDecl()->getPromotionType(); + BT = ET->getDecl()->getIntegerType(); else BT = T; @@ -3722,10 +3871,9 @@ Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg, if (T->isEnumeralType()) { // FIXME: This is a hack. We need a better way to handle substituted // non-type template parameters. - E = CStyleCastExpr::Create(Context, T, VK_RValue, CK_IntegralCast, - E, 0, - Context.getTrivialTypeSourceInfo(T, Loc), - Loc, Loc); + E = CStyleCastExpr::Create(Context, T, VK_RValue, CK_IntegralCast, E, 0, + Context.getTrivialTypeSourceInfo(T, Loc), + Loc, Loc); } return Owned(E); @@ -4245,7 +4393,7 @@ static NamedDecl *getPreviousDecl(NamedDecl *ND) { return FD->getPreviousDeclaration(); if (TagDecl *TD = dyn_cast<TagDecl>(ND)) return TD->getPreviousDeclaration(); - if (TypedefDecl *TD = dyn_cast<TypedefDecl>(ND)) + if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(ND)) return TD->getPreviousDeclaration(); if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(ND)) return FTD->getPreviousDeclaration(); @@ -4268,6 +4416,11 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, MultiTemplateParamsArg TemplateParameterLists) { assert(TUK != TUK_Reference && "References are not specializations"); + // NOTE: KWLoc is the location of the tag keyword. This will instead + // store the location of the outermost template keyword in the declaration. + SourceLocation TemplateKWLoc = TemplateParameterLists.size() > 0 + ? TemplateParameterLists.get()[0]->getTemplateLoc() : SourceLocation(); + // Find the class template we're specializing TemplateName Name = TemplateD.getAsVal<TemplateName>(); ClassTemplateDecl *ClassTemplate @@ -4298,10 +4451,6 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, if (Invalid) return true; - unsigned NumMatchedTemplateParamLists = TemplateParameterLists.size(); - if (TemplateParams) - --NumMatchedTemplateParamLists; - if (TemplateParams && TemplateParams->size() > 0) { isPartialSpecialization = true; @@ -4443,10 +4592,15 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, // Since the only prior class template specialization with these // arguments was referenced but not declared, or we're only // referencing this specialization as a friend, reuse that - // declaration node as our own, updating its source location to - // reflect our new declaration. + // declaration node as our own, updating its source location and + // the list of outer template parameters to reflect our new declaration. Specialization = PrevDecl; Specialization->setLocation(TemplateNameLoc); + if (TemplateParameterLists.size() > 0) { + Specialization->setTemplateParameterListsInfo(Context, + TemplateParameterLists.size(), + (TemplateParameterList**) TemplateParameterLists.release()); + } PrevDecl = 0; CanonType = Context.getTypeDeclType(Specialization); } else if (isPartialSpecialization) { @@ -4471,7 +4625,9 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TemplateNameLoc, Attr, TemplateParams, - AS_none); + AS_none, + TemplateParameterLists.size() - 1, + (TemplateParameterList**) TemplateParameterLists.release()); } // Create a new class template partial specialization declaration node. @@ -4482,7 +4638,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, ClassTemplatePartialSpecializationDecl *Partial = ClassTemplatePartialSpecializationDecl::Create(Context, Kind, ClassTemplate->getDeclContext(), - TemplateNameLoc, + KWLoc, TemplateNameLoc, TemplateParams, ClassTemplate, Converted.data(), @@ -4492,9 +4648,9 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, PrevPartial, SequenceNumber); SetNestedNameSpecifier(Partial, SS); - if (NumMatchedTemplateParamLists > 0 && SS.isSet()) { + if (TemplateParameterLists.size() > 1 && SS.isSet()) { Partial->setTemplateParameterListsInfo(Context, - NumMatchedTemplateParamLists, + TemplateParameterLists.size() - 1, (TemplateParameterList**) TemplateParameterLists.release()); } @@ -4545,15 +4701,15 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, Specialization = ClassTemplateSpecializationDecl::Create(Context, Kind, ClassTemplate->getDeclContext(), - TemplateNameLoc, + KWLoc, TemplateNameLoc, ClassTemplate, Converted.data(), Converted.size(), PrevDecl); SetNestedNameSpecifier(Specialization, SS); - if (NumMatchedTemplateParamLists > 0 && SS.isSet()) { + if (TemplateParameterLists.size() > 0) { Specialization->setTemplateParameterListsInfo(Context, - NumMatchedTemplateParamLists, + TemplateParameterLists.size(), (TemplateParameterList**) TemplateParameterLists.release()); } @@ -4623,8 +4779,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TemplateArgs, CanonType); if (TUK != TUK_Friend) { Specialization->setTypeAsWritten(WrittenTy); - if (TemplateParams) - Specialization->setTemplateKeywordLoc(TemplateParams->getTemplateLoc()); + Specialization->setTemplateKeywordLoc(TemplateKWLoc); } TemplateArgsIn.release(); @@ -4927,7 +5082,7 @@ Sema::CheckDependentFunctionTemplateSpecialization(FunctionDecl *FD, /// this function specialization. bool Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, - const TemplateArgumentListInfo *ExplicitTemplateArgs, + TemplateArgumentListInfo *ExplicitTemplateArgs, LookupResult &Previous) { // The set of function template specializations that could match this // explicit function template specialization. @@ -4983,7 +5138,17 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, // Ignore access information; it doesn't figure into redeclaration checking. FunctionDecl *Specialization = cast<FunctionDecl>(*Result); - Specialization->setLocation(FD->getLocation()); + + FunctionTemplateSpecializationInfo *SpecInfo + = Specialization->getTemplateSpecializationInfo(); + assert(SpecInfo && "Function template specialization info missing?"); + { + // Note: do not overwrite location info if previous template + // specialization kind was explicit. + TemplateSpecializationKind TSK = SpecInfo->getTemplateSpecializationKind(); + if (TSK == TSK_Undeclared || TSK == TSK_ImplicitInstantiation) + Specialization->setLocation(FD->getLocation()); + } // FIXME: Check if the prior specialization has a point of instantiation. // If so, we have run afoul of . @@ -5006,10 +5171,6 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, // before the first use of that specialization that would cause an implicit // instantiation to take place, in every translation unit in which such a // use occurs; no diagnostic is required. - FunctionTemplateSpecializationInfo *SpecInfo - = Specialization->getTemplateSpecializationInfo(); - assert(SpecInfo && "Function template specialization info missing?"); - bool HasNoEffect = false; if (!isFriend && CheckSpecializationInstantiationRedecl(FD->getLocation(), @@ -5402,7 +5563,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, Specialization = ClassTemplateSpecializationDecl::Create(Context, Kind, ClassTemplate->getDeclContext(), - TemplateNameLoc, + KWLoc, TemplateNameLoc, ClassTemplate, Converted.data(), Converted.size(), @@ -5883,26 +6044,34 @@ Sema::ActOnDependentTag(Scope *S, unsigned TagSpec, TagUseKind TUK, return true; } + // Create the resulting type. ElaboratedTypeKeyword Kwd = TypeWithKeyword::getKeywordForTagTypeKind(Kind); - return ParsedType::make(Context.getDependentNameType(Kwd, NNS, Name)); + QualType Result = Context.getDependentNameType(Kwd, NNS, Name); + + // Create type-source location information for this type. + TypeLocBuilder TLB; + DependentNameTypeLoc TL = TLB.push<DependentNameTypeLoc>(Result); + TL.setKeywordLoc(TagLoc); + TL.setQualifierLoc(SS.getWithLocInContext(Context)); + TL.setNameLoc(NameLoc); + return CreateParsedType(Result, TLB.getTypeSourceInfo(Context, Result)); } TypeResult Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, const CXXScopeSpec &SS, const IdentifierInfo &II, SourceLocation IdLoc) { - NestedNameSpecifier *NNS - = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); - if (!NNS) + if (SS.isInvalid()) return true; - + if (TypenameLoc.isValid() && S && !S->getTemplateParamParent() && !getLangOptions().CPlusPlus0x) Diag(TypenameLoc, diag::ext_typename_outside_of_template) << FixItHint::CreateRemoval(TypenameLoc); - QualType T = CheckTypenameType(ETK_Typename, NNS, II, - TypenameLoc, SS.getRange(), IdLoc); + NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context); + QualType T = CheckTypenameType(TypenameLoc.isValid()? ETK_Typename : ETK_None, + TypenameLoc, QualifierLoc, II, IdLoc); if (T.isNull()) return true; @@ -5910,12 +6079,12 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, if (isa<DependentNameType>(T)) { DependentNameTypeLoc TL = cast<DependentNameTypeLoc>(TSI->getTypeLoc()); TL.setKeywordLoc(TypenameLoc); - TL.setQualifierRange(SS.getRange()); + TL.setQualifierLoc(QualifierLoc); TL.setNameLoc(IdLoc); } else { ElaboratedTypeLoc TL = cast<ElaboratedTypeLoc>(TSI->getTypeLoc()); TL.setKeywordLoc(TypenameLoc); - TL.setQualifierRange(SS.getRange()); + TL.setQualifierLoc(QualifierLoc); cast<TypeSpecTypeLoc>(TL.getNamedTypeLoc()).setNameLoc(IdLoc); } @@ -5923,91 +6092,94 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, } TypeResult -Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, - const CXXScopeSpec &SS, SourceLocation TemplateLoc, - ParsedType Ty) { +Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, + const CXXScopeSpec &SS, + SourceLocation TemplateLoc, + TemplateTy TemplateIn, + SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, + ASTTemplateArgsPtr TemplateArgsIn, + SourceLocation RAngleLoc) { if (TypenameLoc.isValid() && S && !S->getTemplateParamParent() && !getLangOptions().CPlusPlus0x) Diag(TypenameLoc, diag::ext_typename_outside_of_template) - << FixItHint::CreateRemoval(TypenameLoc); - - TypeSourceInfo *InnerTSI = 0; - QualType T = GetTypeFromParser(Ty, &InnerTSI); - - assert(isa<TemplateSpecializationType>(T) && - "Expected a template specialization type"); - - if (computeDeclContext(SS, false)) { - // If we can compute a declaration context, then the "typename" - // keyword was superfluous. Just build an ElaboratedType to keep - // track of the nested-name-specifier. - - // Push the inner type, preserving its source locations if possible. + << FixItHint::CreateRemoval(TypenameLoc); + + // Translate the parser's template argument list in our AST format. + TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc); + translateTemplateArguments(TemplateArgsIn, TemplateArgs); + + TemplateName Template = TemplateIn.get(); + if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) { + // Construct a dependent template specialization type. + assert(DTN && "dependent template has non-dependent name?"); + assert(DTN->getQualifier() + == static_cast<NestedNameSpecifier*>(SS.getScopeRep())); + QualType T = Context.getDependentTemplateSpecializationType(ETK_Typename, + DTN->getQualifier(), + DTN->getIdentifier(), + TemplateArgs); + + // Create source-location information for this type. TypeLocBuilder Builder; - if (InnerTSI) - Builder.pushFullCopy(InnerTSI->getTypeLoc()); - else - Builder.push<TemplateSpecializationTypeLoc>(T).initialize(Context, - TemplateLoc); - - /* Note: NNS already embedded in template specialization type T. */ - T = Context.getElaboratedType(ETK_Typename, /*NNS=*/0, T); - ElaboratedTypeLoc TL = Builder.push<ElaboratedTypeLoc>(T); - TL.setKeywordLoc(TypenameLoc); - TL.setQualifierRange(SS.getRange()); - - TypeSourceInfo *TSI = Builder.getTypeSourceInfo(Context, T); - return CreateParsedType(T, TSI); - } - - // TODO: it's really silly that we make a template specialization - // type earlier only to drop it again here. - const TemplateSpecializationType *TST = cast<TemplateSpecializationType>(T); - DependentTemplateName *DTN = - TST->getTemplateName().getAsDependentTemplateName(); - assert(DTN && "dependent template has non-dependent name?"); - assert(DTN->getQualifier() - == static_cast<NestedNameSpecifier*>(SS.getScopeRep())); - T = Context.getDependentTemplateSpecializationType(ETK_Typename, - DTN->getQualifier(), - DTN->getIdentifier(), - TST->getNumArgs(), - TST->getArgs()); - TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T); - DependentTemplateSpecializationTypeLoc TL = - cast<DependentTemplateSpecializationTypeLoc>(TSI->getTypeLoc()); - if (InnerTSI) { - TemplateSpecializationTypeLoc TSTL = - cast<TemplateSpecializationTypeLoc>(InnerTSI->getTypeLoc()); - TL.setLAngleLoc(TSTL.getLAngleLoc()); - TL.setRAngleLoc(TSTL.getRAngleLoc()); - for (unsigned I = 0, E = TST->getNumArgs(); I != E; ++I) - TL.setArgLocInfo(I, TSTL.getArgLocInfo(I)); - } else { - // FIXME: Poor source-location information here. - TL.initializeLocal(Context, TemplateLoc); + DependentTemplateSpecializationTypeLoc SpecTL + = Builder.push<DependentTemplateSpecializationTypeLoc>(T); + SpecTL.setLAngleLoc(LAngleLoc); + SpecTL.setRAngleLoc(RAngleLoc); + SpecTL.setKeywordLoc(TypenameLoc); + SpecTL.setQualifierLoc(SS.getWithLocInContext(Context)); + SpecTL.setNameLoc(TemplateNameLoc); + for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) + SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo()); + return CreateParsedType(T, Builder.getTypeSourceInfo(Context, T)); } + + QualType T = CheckTemplateIdType(Template, TemplateNameLoc, TemplateArgs); + if (T.isNull()) + return true; + + // Provide source-location information for the template specialization + // type. + TypeLocBuilder Builder; + TemplateSpecializationTypeLoc SpecTL + = Builder.push<TemplateSpecializationTypeLoc>(T); + + // FIXME: No place to set the location of the 'template' keyword! + SpecTL.setLAngleLoc(LAngleLoc); + SpecTL.setRAngleLoc(RAngleLoc); + SpecTL.setTemplateNameLoc(TemplateNameLoc); + for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) + SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo()); + + T = Context.getElaboratedType(ETK_Typename, SS.getScopeRep(), T); + ElaboratedTypeLoc TL = Builder.push<ElaboratedTypeLoc>(T); TL.setKeywordLoc(TypenameLoc); - TL.setQualifierRange(SS.getRange()); + TL.setQualifierLoc(SS.getWithLocInContext(Context)); + + TypeSourceInfo *TSI = Builder.getTypeSourceInfo(Context, T); return CreateParsedType(T, TSI); } + /// \brief Build the type that describes a C++ typename specifier, /// e.g., "typename T::type". QualType -Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, - NestedNameSpecifier *NNS, const IdentifierInfo &II, - SourceLocation KeywordLoc, SourceRange NNSRange, +Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, + SourceLocation KeywordLoc, + NestedNameSpecifierLoc QualifierLoc, + const IdentifierInfo &II, SourceLocation IILoc) { CXXScopeSpec SS; - SS.MakeTrivial(Context, NNS, NNSRange); + SS.Adopt(QualifierLoc); DeclContext *Ctx = computeDeclContext(SS); if (!Ctx) { // If the nested-name-specifier is dependent and couldn't be // resolved to a type, build a typename type. - assert(NNS->isDependent()); - return Context.getDependentNameType(Keyword, NNS, &II); + assert(QualifierLoc.getNestedNameSpecifier()->isDependent()); + return Context.getDependentNameType(Keyword, + QualifierLoc.getNestedNameSpecifier(), + &II); } // If the nested-name-specifier refers to the current instantiation, @@ -6032,7 +6204,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, case LookupResult::FoundUnresolvedValue: { // We found a using declaration that is a value. Most likely, the using // declaration itself is meant to have the 'typename' keyword. - SourceRange FullRange(KeywordLoc.isValid() ? KeywordLoc : NNSRange.getBegin(), + SourceRange FullRange(KeywordLoc.isValid() ? KeywordLoc : SS.getBeginLoc(), IILoc); Diag(IILoc, diag::err_typename_refers_to_using_value_decl) << Name << Ctx << FullRange; @@ -6048,13 +6220,16 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, case LookupResult::NotFoundInCurrentInstantiation: // Okay, it's a member of an unknown instantiation. - return Context.getDependentNameType(Keyword, NNS, &II); + return Context.getDependentNameType(Keyword, + QualifierLoc.getNestedNameSpecifier(), + &II); case LookupResult::Found: if (TypeDecl *Type = dyn_cast<TypeDecl>(Result.getFoundDecl())) { // We found a type. Build an ElaboratedType, since the // typename-specifier was just sugar. - return Context.getElaboratedType(ETK_Typename, NNS, + return Context.getElaboratedType(ETK_Typename, + QualifierLoc.getNestedNameSpecifier(), Context.getTypeDeclType(Type)); } @@ -6077,7 +6252,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, // If we get here, it's because name lookup did not find a // type. Emit an appropriate diagnostic and return an error. - SourceRange FullRange(KeywordLoc.isValid() ? KeywordLoc : NNSRange.getBegin(), + SourceRange FullRange(KeywordLoc.isValid() ? KeywordLoc : SS.getBeginLoc(), IILoc); Diag(IILoc, DiagID) << FullRange << Name << Ctx; if (Referenced) @@ -6225,3 +6400,24 @@ Sema::getTemplateArgumentBindingsText(const TemplateParameterList *Params, Out << ']'; return Out.str(); } + +void Sema::MarkAsLateParsedTemplate(FunctionDecl *FD, bool Flag) { + if (!FD) + return; + FD->setLateTemplateParsed(Flag); +} + +bool Sema::IsInsideALocalClassWithinATemplateFunction() { + DeclContext *DC = CurContext; + + while (DC) { + if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(CurContext)) { + const FunctionDecl *FD = RD->isLocalClass(); + return (FD && FD->getTemplatedKind() != FunctionDecl::TK_NonTemplate); + } else if (DC->isTranslationUnit() || DC->isNamespace()) + return false; + + DC = DC->getParent(); + } + return false; +} diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp index 139fafb..235af04 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -800,6 +800,32 @@ DeduceTemplateArguments(Sema &S, return Sema::TDK_Success; } +/// \brief Determine whether the parameter has qualifiers that are either +/// inconsistent with or a superset of the argument's qualifiers. +static bool hasInconsistentOrSupersetQualifiersOf(QualType ParamType, + QualType ArgType) { + Qualifiers ParamQs = ParamType.getQualifiers(); + Qualifiers ArgQs = ArgType.getQualifiers(); + + if (ParamQs == ArgQs) + return false; + + // Mismatched (but not missing) Objective-C GC attributes. + if (ParamQs.getObjCGCAttr() != ArgQs.getObjCGCAttr() && + ParamQs.hasObjCGCAttr()) + return true; + + // Mismatched (but not missing) address spaces. + if (ParamQs.getAddressSpace() != ArgQs.getAddressSpace() && + ParamQs.hasAddressSpace()) + return true; + + // CVR qualifier superset. + return (ParamQs.getCVRQualifiers() != ArgQs.getCVRQualifiers()) && + ((ParamQs.getCVRQualifiers() | ArgQs.getCVRQualifiers()) + == ParamQs.getCVRQualifiers()); +} + /// \brief Deduce the template arguments by comparing the parameter type and /// the argument type (C++ [temp.deduct.type]). /// @@ -875,9 +901,12 @@ DeduceTemplateArguments(Sema &S, Comparison.ParamIsRvalueRef = ParamRef->getAs<RValueReferenceType>(); Comparison.ArgIsRvalueRef = ArgRef->getAs<RValueReferenceType>(); Comparison.Qualifiers = NeitherMoreQualified; - if (Param.isMoreQualifiedThan(Arg)) + + Qualifiers ParamQuals = Param.getQualifiers(); + Qualifiers ArgQuals = Arg.getQualifiers(); + if (ParamQuals.isStrictSupersetOf(ArgQuals)) Comparison.Qualifiers = ParamMoreQualified; - else if (Arg.isMoreQualifiedThan(Param)) + else if (ArgQuals.isStrictSupersetOf(ParamQuals)) Comparison.Qualifiers = ArgMoreQualified; RefParamComparisons->push_back(Comparison); } @@ -949,7 +978,6 @@ DeduceTemplateArguments(Sema &S, // If the argument type is an array type, move the qualifiers up to the // top level, so they can be matched with the qualifiers on the parameter. - // FIXME: address spaces, ObjC GC qualifiers if (isa<ArrayType>(Arg)) { Qualifiers Quals; Arg = S.Context.getUnqualifiedArrayType(Arg, Quals); @@ -961,7 +989,8 @@ DeduceTemplateArguments(Sema &S, // The argument type can not be less qualified than the parameter // type. - if (Param.isMoreQualifiedThan(Arg) && !(TDF & TDF_IgnoreQualifiers)) { + if (!(TDF & TDF_IgnoreQualifiers) && + hasInconsistentOrSupersetQualifiersOf(Param, Arg)) { Info.Param = cast<TemplateTypeParmDecl>(TemplateParams->getParam(Index)); Info.FirstArg = TemplateArgument(Param); Info.SecondArg = TemplateArgument(Arg); @@ -972,8 +1001,18 @@ DeduceTemplateArguments(Sema &S, assert(Arg != S.Context.OverloadTy && "Unresolved overloaded function"); QualType DeducedType = Arg; - // local manipulation is okay because it's canonical - DeducedType.removeLocalCVRQualifiers(Param.getCVRQualifiers()); + // Remove any qualifiers on the parameter from the deduced type. + // We checked the qualifiers for consistency above. + Qualifiers DeducedQs = DeducedType.getQualifiers(); + Qualifiers ParamQs = Param.getQualifiers(); + DeducedQs.removeCVRQualifiers(ParamQs.getCVRQualifiers()); + if (ParamQs.hasObjCGCAttr()) + DeducedQs.removeObjCGCAttr(); + if (ParamQs.hasAddressSpace()) + DeducedQs.removeAddressSpace(); + DeducedType = S.Context.getQualifiedType(DeducedType.getUnqualifiedType(), + DeducedQs); + if (RecanonicalizeArg) DeducedType = S.Context.getCanonicalType(DeducedType); @@ -1006,7 +1045,7 @@ DeduceTemplateArguments(Sema &S, // Check the cv-qualifiers on the parameter and argument types. if (!(TDF & TDF_IgnoreQualifiers)) { if (TDF & TDF_ParamWithReferenceType) { - if (Param.isMoreQualifiedThan(Arg)) + if (hasInconsistentOrSupersetQualifiersOf(Param, Arg)) return Sema::TDK_NonDeducedMismatch; } else if (!IsPossiblyOpaquelyQualifiedType(Param)) { if (Param.getCVRQualifiers() != Arg.getCVRQualifiers()) @@ -1728,11 +1767,24 @@ getTrivialTemplateArgumentLoc(Sema &S, return TemplateArgumentLoc(TemplateArgument(E), E); } - case TemplateArgument::Template: - return TemplateArgumentLoc(Arg, SourceRange(), Loc); - - case TemplateArgument::TemplateExpansion: - return TemplateArgumentLoc(Arg, SourceRange(), Loc, Loc); + case TemplateArgument::Template: + case TemplateArgument::TemplateExpansion: { + NestedNameSpecifierLocBuilder Builder; + TemplateName Template = Arg.getAsTemplate(); + if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) + Builder.MakeTrivial(S.Context, DTN->getQualifier(), Loc); + else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) + Builder.MakeTrivial(S.Context, QTN->getQualifier(), Loc); + + if (Arg.getKind() == TemplateArgument::Template) + return TemplateArgumentLoc(Arg, + Builder.getWithLocInContext(S.Context), + Loc); + + + return TemplateArgumentLoc(Arg, Builder.getWithLocInContext(S.Context), + Loc, Loc); + } case TemplateArgument::Expression: return TemplateArgumentLoc(Arg, Arg.getAsExpr()); @@ -1996,7 +2048,7 @@ static bool isSimpleTemplateIdType(QualType T) { Sema::TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments( FunctionTemplateDecl *FunctionTemplate, - const TemplateArgumentListInfo &ExplicitTemplateArgs, + TemplateArgumentListInfo &ExplicitTemplateArgs, llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced, llvm::SmallVectorImpl<QualType> &ParamTypes, QualType *FunctionType, @@ -2442,8 +2494,8 @@ static bool AdjustFunctionParmAndArgTypesForDeduction(Sema &S, // C++0x [temp.deduct.call]p3: // If P is a cv-qualified type, the top level cv-qualifiers of P's type // are ignored for type deduction. - if (ParamType.getCVRQualifiers()) - ParamType = ParamType.getLocalUnqualifiedType(); + if (ParamType.hasQualifiers()) + ParamType = ParamType.getUnqualifiedType(); const ReferenceType *ParamRefType = ParamType->getAs<ReferenceType>(); if (ParamRefType) { QualType PointeeType = ParamRefType->getPointeeType(); @@ -2499,8 +2551,7 @@ static bool AdjustFunctionParmAndArgTypesForDeduction(Sema &S, else { // - If A is a cv-qualified type, the top level cv-qualifiers of A's // type are ignored for type deduction. - if (ArgType.getCVRQualifiers()) - ArgType = ArgType.getUnqualifiedType(); + ArgType = ArgType.getUnqualifiedType(); } } @@ -2563,7 +2614,7 @@ static bool AdjustFunctionParmAndArgTypesForDeduction(Sema &S, /// \returns the result of template argument deduction. Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, - const TemplateArgumentListInfo *ExplicitTemplateArgs, + TemplateArgumentListInfo *ExplicitTemplateArgs, Expr **Args, unsigned NumArgs, FunctionDecl *&Specialization, TemplateDeductionInfo &Info) { @@ -2761,7 +2812,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, /// \returns the result of template argument deduction. Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, - const TemplateArgumentListInfo *ExplicitTemplateArgs, + TemplateArgumentListInfo *ExplicitTemplateArgs, QualType ArgFunctionType, FunctionDecl *&Specialization, TemplateDeductionInfo &Info) { @@ -2832,18 +2883,18 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, QualType P = Context.getCanonicalType(FromType); QualType A = Context.getCanonicalType(ToType); - // C++0x [temp.deduct.conv]p3: + // C++0x [temp.deduct.conv]p2: // If P is a reference type, the type referred to by P is used for // type deduction. if (const ReferenceType *PRef = P->getAs<ReferenceType>()) P = PRef->getPointeeType(); - // C++0x [temp.deduct.conv]p3: - // If A is a reference type, the type referred to by A is used + // C++0x [temp.deduct.conv]p4: + // [...] If A is a reference type, the type referred to by A is used // for type deduction. if (const ReferenceType *ARef = A->getAs<ReferenceType>()) - A = ARef->getPointeeType(); - // C++ [temp.deduct.conv]p2: + A = ARef->getPointeeType().getUnqualifiedType(); + // C++ [temp.deduct.conv]p3: // // If A is not a reference type: else { @@ -2864,9 +2915,10 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, else P = P.getUnqualifiedType(); - // C++0x [temp.deduct.conv]p3: + // C++0x [temp.deduct.conv]p4: // If A is a cv-qualified type, the top level cv-qualifiers of A's - // type are ignored for type deduction. + // type are ignored for type deduction. If A is a reference type, the type + // referred to by A is used for type deduction. A = A.getUnqualifiedType(); } @@ -2941,7 +2993,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, /// \returns the result of template argument deduction. Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, - const TemplateArgumentListInfo *ExplicitTemplateArgs, + TemplateArgumentListInfo *ExplicitTemplateArgs, FunctionDecl *&Specialization, TemplateDeductionInfo &Info) { return DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs, @@ -2989,11 +3041,14 @@ namespace { /// /// \param Result if type deduction was successful, this will be set to the /// deduced type. This may still contain undeduced autos if the type is -/// dependent. +/// dependent. This will be set to null if deduction succeeded, but auto +/// substitution failed; the appropriate diagnostic will already have been +/// produced in that case. /// /// \returns true if deduction succeeded, false if it failed. bool -Sema::DeduceAutoType(QualType Type, Expr *Init, QualType &Result) { +Sema::DeduceAutoType(TypeSourceInfo *Type, Expr *Init, + TypeSourceInfo *&Result) { if (Init->isTypeDependent()) { Result = Type; return true; @@ -3004,14 +3059,18 @@ Sema::DeduceAutoType(QualType Type, Expr *Init, QualType &Result) { LocalInstantiationScope InstScope(*this); // Build template<class TemplParam> void Func(FuncParam); - QualType TemplArg = Context.getTemplateTypeParmType(0, 0, false); - TemplateTypeParmDecl TemplParam(0, Loc, 0, false, TemplArg, false); - NamedDecl *TemplParamPtr = &TemplParam; + TemplateTypeParmDecl *TemplParam = + TemplateTypeParmDecl::Create(Context, 0, SourceLocation(), Loc, 0, 0, 0, + false, false); + QualType TemplArg = QualType(TemplParam->getTypeForDecl(), 0); + NamedDecl *TemplParamPtr = TemplParam; FixedSizeTemplateParameterList<1> TemplateParams(Loc, Loc, &TemplParamPtr, Loc); - QualType FuncParam = + TypeSourceInfo *FuncParamInfo = SubstituteAutoTransform(*this, TemplArg).TransformType(Type); + assert(FuncParamInfo && "substituting template parameter for 'auto' failed"); + QualType FuncParam = FuncParamInfo->getType(); // Deduce type of TemplParam in Func(Init) llvm::SmallVector<DeducedTemplateArgument, 1> Deduced; diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp index ae0ac9c..92ba095 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -95,6 +95,12 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D, assert(Function->getPrimaryTemplate() && "No function template?"); if (Function->getPrimaryTemplate()->isMemberSpecialization()) break; + } else if (FunctionTemplateDecl *FunTmpl + = Function->getDescribedFunctionTemplate()) { + // Add the "injected" template arguments. + std::pair<const TemplateArgument *, unsigned> + Injected = FunTmpl->getInjectedTemplateArgs(); + Result.addOuterTemplateArguments(Injected.first, Injected.second); } // If this is a friend declaration and it declares an entity at @@ -718,8 +724,9 @@ namespace { /// as an instantiated local. VarDecl *RebuildExceptionDecl(VarDecl *ExceptionDecl, TypeSourceInfo *Declarator, - IdentifierInfo *Name, - SourceLocation Loc); + SourceLocation StartLoc, + SourceLocation NameLoc, + IdentifierInfo *Name); /// \brief Rebuild the Objective-C exception declaration and register the /// declaration as an instantiated local. @@ -730,9 +737,12 @@ namespace { /// elaborated type. QualType RebuildElaboratedType(SourceLocation KeywordLoc, ElaboratedTypeKeyword Keyword, - NestedNameSpecifier *NNS, QualType T); + NestedNameSpecifierLoc QualifierLoc, + QualType T); - TemplateName TransformTemplateName(TemplateName Name, + TemplateName TransformTemplateName(CXXScopeSpec &SS, + TemplateName Name, + SourceLocation NameLoc, QualType ObjectType = QualType(), NamedDecl *FirstQualifierInScope = 0); @@ -747,6 +757,7 @@ namespace { QualType TransformFunctionProtoType(TypeLocBuilder &TLB, FunctionProtoTypeLoc TL); ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm, + int indexAdjustment, llvm::Optional<unsigned> NumExpansions); /// \brief Transforms a template type parameter type by performing @@ -871,10 +882,11 @@ TemplateInstantiator::TransformFirstQualifierInScope(NamedDecl *D, VarDecl * TemplateInstantiator::RebuildExceptionDecl(VarDecl *ExceptionDecl, TypeSourceInfo *Declarator, - IdentifierInfo *Name, - SourceLocation Loc) { + SourceLocation StartLoc, + SourceLocation NameLoc, + IdentifierInfo *Name) { VarDecl *Var = inherited::RebuildExceptionDecl(ExceptionDecl, Declarator, - Name, Loc); + StartLoc, NameLoc, Name); if (Var) getSema().CurrentInstantiationScope->InstantiatedLocal(ExceptionDecl, Var); return Var; @@ -892,7 +904,7 @@ VarDecl *TemplateInstantiator::RebuildObjCExceptionDecl(VarDecl *ExceptionDecl, QualType TemplateInstantiator::RebuildElaboratedType(SourceLocation KeywordLoc, ElaboratedTypeKeyword Keyword, - NestedNameSpecifier *NNS, + NestedNameSpecifierLoc QualifierLoc, QualType T) { if (const TagType *TT = T->getAs<TagType>()) { TagDecl* TD = TT->getDecl(); @@ -918,10 +930,13 @@ TemplateInstantiator::RebuildElaboratedType(SourceLocation KeywordLoc, return TreeTransform<TemplateInstantiator>::RebuildElaboratedType(KeywordLoc, Keyword, - NNS, T); + QualifierLoc, + T); } -TemplateName TemplateInstantiator::TransformTemplateName(TemplateName Name, +TemplateName TemplateInstantiator::TransformTemplateName(CXXScopeSpec &SS, + TemplateName Name, + SourceLocation NameLoc, QualType ObjectType, NamedDecl *FirstQualifierInScope) { if (TemplateTemplateParmDecl *TTP @@ -955,24 +970,31 @@ TemplateName TemplateInstantiator::TransformTemplateName(TemplateName Name, TemplateName Template = Arg.getAsTemplate(); assert(!Template.isNull() && Template.getAsTemplateDecl() && "Wrong kind of template template argument"); + + // We don't ever want to substitute for a qualified template name, since + // the qualifier is handled separately. So, look through the qualified + // template name to its underlying declaration. + if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) + Template = TemplateName(QTN->getTemplateDecl()); + return Template; } } if (SubstTemplateTemplateParmPackStorage *SubstPack - = Name.getAsSubstTemplateTemplateParmPack()) { + = Name.getAsSubstTemplateTemplateParmPack()) { if (getSema().ArgumentPackSubstitutionIndex == -1) return Name; - + const TemplateArgument &ArgPack = SubstPack->getArgumentPack(); assert(getSema().ArgumentPackSubstitutionIndex < (int)ArgPack.pack_size() && "Pack substitution index out-of-range"); return ArgPack.pack_begin()[getSema().ArgumentPackSubstitutionIndex] - .getAsTemplate(); + .getAsTemplate(); } - return inherited::TransformTemplateName(Name, ObjectType, - FirstQualifierInScope); + return inherited::TransformTemplateName(SS, Name, NameLoc, ObjectType, + FirstQualifierInScope); } ExprResult @@ -1153,8 +1175,9 @@ QualType TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder &TLB, ParmVarDecl * TemplateInstantiator::TransformFunctionTypeParam(ParmVarDecl *OldParm, + int indexAdjustment, llvm::Optional<unsigned> NumExpansions) { - return SemaRef.SubstParmVarDecl(OldParm, TemplateArgs, + return SemaRef.SubstParmVarDecl(OldParm, TemplateArgs, indexAdjustment, NumExpansions); } @@ -1217,12 +1240,17 @@ TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB, // the template parameter list of a member template inside the // template we are instantiating). Create a new template type // parameter with the template "level" reduced by one. + TemplateTypeParmDecl *NewTTPDecl = 0; + if (TemplateTypeParmDecl *OldTTPDecl = T->getDecl()) + NewTTPDecl = cast_or_null<TemplateTypeParmDecl>( + TransformDecl(TL.getNameLoc(), OldTTPDecl)); + QualType Result = getSema().Context.getTemplateTypeParmType(T->getDepth() - TemplateArgs.getNumLevels(), T->getIndex(), T->isParameterPack(), - T->getName()); + NewTTPDecl); TemplateTypeParmTypeLoc NewTL = TLB.push<TemplateTypeParmTypeLoc>(Result); NewTL.setNameLoc(TL.getNameLoc()); return Result; @@ -1396,6 +1424,7 @@ TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T, ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm, const MultiLevelTemplateArgumentList &TemplateArgs, + int indexAdjustment, llvm::Optional<unsigned> NumExpansions) { TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo(); TypeSourceInfo *NewDI = 0; @@ -1432,9 +1461,10 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm, } ParmVarDecl *NewParm = CheckParameter(Context.getTranslationUnitDecl(), - NewDI, NewDI->getType(), - OldParm->getIdentifier(), + OldParm->getInnerLocStart(), OldParm->getLocation(), + OldParm->getIdentifier(), + NewDI->getType(), NewDI, OldParm->getStorageClass(), OldParm->getStorageClassAsWritten()); if (!NewParm) @@ -1465,6 +1495,9 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm, // FIXME: OldParm may come from a FunctionProtoType, in which case CurContext // can be anything, is this right ? NewParm->setDeclContext(CurContext); + + NewParm->setScopeInfo(OldParm->getFunctionScopeDepth(), + OldParm->getFunctionScopeIndex() + indexAdjustment); return NewParm; } @@ -1508,6 +1541,7 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation, } SourceLocation EllipsisLoc; + TypeSourceInfo *BaseTypeLoc; if (Base->isPackExpansion()) { // This is a pack expansion. See whether we should expand it now, or // wait until later. @@ -1558,13 +1592,18 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation, // The resulting base specifier will (still) be a pack expansion. EllipsisLoc = Base->getEllipsisLoc(); + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, -1); + BaseTypeLoc = SubstType(Base->getTypeSourceInfo(), + TemplateArgs, + Base->getSourceRange().getBegin(), + DeclarationName()); + } else { + BaseTypeLoc = SubstType(Base->getTypeSourceInfo(), + TemplateArgs, + Base->getSourceRange().getBegin(), + DeclarationName()); } - Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, -1); - TypeSourceInfo *BaseTypeLoc = SubstType(Base->getTypeSourceInfo(), - TemplateArgs, - Base->getSourceRange().getBegin(), - DeclarationName()); if (!BaseTypeLoc) { Invalid = true; continue; @@ -1622,9 +1661,18 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, CXXRecordDecl *PatternDef = cast_or_null<CXXRecordDecl>(Pattern->getDefinition()); - if (!PatternDef) { - if (!Complain) { + if (!PatternDef || PatternDef->isBeingDefined()) { + if (!Complain || (PatternDef && PatternDef->isInvalidDecl())) { // Say nothing + } else if (PatternDef) { + assert(PatternDef->isBeingDefined()); + Diag(PointOfInstantiation, + diag::err_template_instantiate_within_definition) + << (TSK != TSK_ImplicitInstantiation) + << Context.getTypeDeclType(Instantiation); + // Not much point in noting the template declaration here, since + // we're lexically inside it. + Instantiation->setInvalidDecl(); } else if (Pattern == Instantiation->getInstantiatedFromMemberClass()) { Diag(PointOfInstantiation, diag::err_implicit_instantiate_member_undefined) @@ -2130,16 +2178,6 @@ bool Sema::SubstExprs(Expr **Exprs, unsigned NumExprs, bool IsCall, return Instantiator.TransformExprs(Exprs, NumExprs, IsCall, Outputs); } -/// \brief Do template substitution on a nested-name-specifier. -NestedNameSpecifier * -Sema::SubstNestedNameSpecifier(NestedNameSpecifier *NNS, - SourceRange Range, - const MultiLevelTemplateArgumentList &TemplateArgs) { - TemplateInstantiator Instantiator(*this, TemplateArgs, Range.getBegin(), - DeclarationName()); - return Instantiator.TransformNestedNameSpecifier(NNS, Range); -} - NestedNameSpecifierLoc Sema::SubstNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, const MultiLevelTemplateArgumentList &TemplateArgs) { @@ -2161,11 +2199,14 @@ Sema::SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo, } TemplateName -Sema::SubstTemplateName(TemplateName Name, SourceLocation Loc, +Sema::SubstTemplateName(NestedNameSpecifierLoc QualifierLoc, + TemplateName Name, SourceLocation Loc, const MultiLevelTemplateArgumentList &TemplateArgs) { TemplateInstantiator Instantiator(*this, TemplateArgs, Loc, DeclarationName()); - return Instantiator.TransformTemplateName(Name); + CXXScopeSpec SS; + SS.Adopt(QualifierLoc); + return Instantiator.TransformTemplateName(SS, Name, Loc); } bool Sema::Subst(const TemplateArgumentLoc *Args, unsigned NumArgs, diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 3a40b6f..6e11ef5 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -128,7 +128,8 @@ TemplateDeclInstantiator::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { return Inst; } -Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) { +Decl *TemplateDeclInstantiator::VisitTypedefNameDecl(TypedefNameDecl *D, + bool IsTypeAlias) { bool Invalid = false; TypeSourceInfo *DI = D->getTypeSourceInfo(); if (DI->getType()->isDependentType() || @@ -144,9 +145,13 @@ Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) { } // Create the new typedef - TypedefDecl *Typedef - = TypedefDecl::Create(SemaRef.Context, Owner, D->getLocation(), - D->getIdentifier(), DI); + TypedefNameDecl *Typedef; + if (IsTypeAlias) + Typedef = TypeAliasDecl::Create(SemaRef.Context, Owner, D->getLocStart(), + D->getLocation(), D->getIdentifier(), DI); + else + Typedef = TypedefDecl::Create(SemaRef.Context, Owner, D->getLocStart(), + D->getLocation(), D->getIdentifier(), DI); if (Invalid) Typedef->setInvalidDecl(); @@ -154,17 +159,20 @@ Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) { // tag decl, re-establish that relationship for the new typedef. if (const TagType *oldTagType = D->getUnderlyingType()->getAs<TagType>()) { TagDecl *oldTag = oldTagType->getDecl(); - if (oldTag->getTypedefForAnonDecl() == D) { + if (oldTag->getTypedefNameForAnonDecl() == D) { TagDecl *newTag = DI->getType()->castAs<TagType>()->getDecl(); - assert(!newTag->getIdentifier() && !newTag->getTypedefForAnonDecl()); - newTag->setTypedefForAnonDecl(Typedef); + assert(!newTag->getIdentifier() && !newTag->getTypedefNameForAnonDecl()); + newTag->setTypedefNameForAnonDecl(Typedef); } } - if (TypedefDecl *Prev = D->getPreviousDeclaration()) { + if (TypedefNameDecl *Prev = D->getPreviousDeclaration()) { NamedDecl *InstPrev = SemaRef.FindInstantiatedDecl(D->getLocation(), Prev, TemplateArgs); - Typedef->setPreviousDeclaration(cast<TypedefDecl>(InstPrev)); + if (!InstPrev) + return 0; + + Typedef->setPreviousDeclaration(cast<TypedefNameDecl>(InstPrev)); } SemaRef.InstantiateAttrs(TemplateArgs, D, Typedef); @@ -175,6 +183,14 @@ Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) { return Typedef; } +Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) { + return VisitTypedefNameDecl(D, /*IsTypeAlias=*/false); +} + +Decl *TemplateDeclInstantiator::VisitTypeAliasDecl(TypeAliasDecl *D) { + return VisitTypedefNameDecl(D, /*IsTypeAlias=*/true); +} + /// \brief Instantiate an initializer, breaking it into separate /// initialization arguments. /// @@ -261,12 +277,14 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { // Build the instantiated declaration VarDecl *Var = VarDecl::Create(SemaRef.Context, Owner, + D->getInnerLocStart(), D->getLocation(), D->getIdentifier(), DI->getType(), DI, D->getStorageClass(), D->getStorageClassAsWritten()); Var->setThreadSpecified(D->isThreadSpecified()); Var->setCXXDirectInitializer(D->hasCXXDirectInitializer()); + Var->setCXXForRangeDecl(D->isCXXForRangeDecl()); // Substitute the nested name specifier, if any. if (SubstQualifier(D, Var)) @@ -280,8 +298,10 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { Var->setAccess(D->getAccess()); - if (!D->isStaticDataMember()) + if (!D->isStaticDataMember()) { Var->setUsed(D->isUsed(false)); + Var->setReferenced(D->isReferenced()); + } // FIXME: In theory, we could have a previous declaration for variables that // are not static data members. @@ -346,7 +366,8 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { } SemaRef.PopExpressionEvaluationContext(); - } else if (!Var->isStaticDataMember() || Var->isOutOfLine()) + } else if ((!Var->isStaticDataMember() || Var->isOutOfLine()) && + !Var->isCXXForRangeDecl()) SemaRef.ActOnUninitializedDecl(Var, false); // Diagnose unused local variables. @@ -448,9 +469,14 @@ Decl *TemplateDeclInstantiator::VisitIndirectFieldDecl(IndirectFieldDecl *D) { int i = 0; for (IndirectFieldDecl::chain_iterator PI = D->chain_begin(), PE = D->chain_end(); - PI != PE; ++PI) - NamedChain[i++] = (SemaRef.FindInstantiatedDecl(D->getLocation(), - *PI, TemplateArgs)); + PI != PE; ++PI) { + NamedDecl *Next = SemaRef.FindInstantiatedDecl(D->getLocation(), *PI, + TemplateArgs); + if (!Next) + return 0; + + NamedChain[i++] = Next; + } QualType T = cast<FieldDecl>(NamedChain[i-1])->getType(); IndirectFieldDecl* IndirectField @@ -469,10 +495,18 @@ Decl *TemplateDeclInstantiator::VisitFriendDecl(FriendDecl *D) { // Handle friend type expressions by simply substituting template // parameters into the pattern type and checking the result. if (TypeSourceInfo *Ty = D->getFriendType()) { - TypeSourceInfo *InstTy = - SemaRef.SubstType(Ty, TemplateArgs, - D->getLocation(), DeclarationName()); - if (!InstTy) + TypeSourceInfo *InstTy; + // If this is an unsupported friend, don't bother substituting template + // arguments into it. The actual type referred to won't be used by any + // parts of Clang, and may not be valid for instantiating. Just use the + // same info for the instantiated friend. + if (D->isUnsupportedFriend()) { + InstTy = Ty; + } else { + InstTy = SemaRef.SubstType(Ty, TemplateArgs, + D->getLocation(), DeclarationName()); + } + if (!InstTy) return 0; FriendDecl *FD = SemaRef.CheckFriendTypeDecl(D->getFriendLoc(), InstTy); @@ -519,13 +553,13 @@ Decl *TemplateDeclInstantiator::VisitStaticAssertDecl(StaticAssertDecl *D) { D->getMessage(); return SemaRef.ActOnStaticAssertDeclaration(D->getLocation(), InstantiatedAssertExpr.get(), - Message.get()); + Message.get(), + D->getRParenLoc()); } Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) { - EnumDecl *Enum = EnumDecl::Create(SemaRef.Context, Owner, + EnumDecl *Enum = EnumDecl::Create(SemaRef.Context, Owner, D->getLocStart(), D->getLocation(), D->getIdentifier(), - D->getTagKeywordLoc(), /*PrevDecl=*/0, D->isScoped(), D->isScopedUsingClassTag(), D->isFixed()); if (D->isFixed()) { @@ -750,8 +784,8 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { CXXRecordDecl *RecordInst = CXXRecordDecl::Create(SemaRef.Context, Pattern->getTagKind(), DC, - Pattern->getLocation(), Pattern->getIdentifier(), - Pattern->getTagKeywordLoc(), PrevDecl, + Pattern->getLocStart(), Pattern->getLocation(), + Pattern->getIdentifier(), PrevDecl, /*DelayTypeCreation=*/true); if (QualifierLoc) @@ -892,8 +926,8 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { CXXRecordDecl *Record = CXXRecordDecl::Create(SemaRef.Context, D->getTagKind(), Owner, - D->getLocation(), D->getIdentifier(), - D->getTagKeywordLoc(), PrevDecl); + D->getLocStart(), D->getLocation(), + D->getIdentifier(), PrevDecl); // Substitute the nested name specifier, if any. if (SubstQualifier(D, Record)) @@ -991,8 +1025,8 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, } FunctionDecl *Function = - FunctionDecl::Create(SemaRef.Context, DC, D->getLocation(), - D->getDeclName(), T, TInfo, + FunctionDecl::Create(SemaRef.Context, DC, D->getInnerLocStart(), + D->getLocation(), D->getDeclName(), T, TInfo, D->getStorageClass(), D->getStorageClassAsWritten(), D->isInlineSpecified(), D->hasWrittenPrototype()); @@ -1288,30 +1322,33 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, CXXRecordDecl *Record = cast<CXXRecordDecl>(DC); CXXMethodDecl *Method = 0; + SourceLocation StartLoc = D->getInnerLocStart(); DeclarationNameInfo NameInfo = SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs); if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) { Method = CXXConstructorDecl::Create(SemaRef.Context, Record, - NameInfo, T, TInfo, + StartLoc, NameInfo, T, TInfo, Constructor->isExplicit(), Constructor->isInlineSpecified(), false); } else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) { Method = CXXDestructorDecl::Create(SemaRef.Context, Record, - NameInfo, T, TInfo, + StartLoc, NameInfo, T, TInfo, Destructor->isInlineSpecified(), false); } else if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(D)) { Method = CXXConversionDecl::Create(SemaRef.Context, Record, - NameInfo, T, TInfo, + StartLoc, NameInfo, T, TInfo, Conversion->isInlineSpecified(), - Conversion->isExplicit()); + Conversion->isExplicit(), + Conversion->getLocEnd()); } else { Method = CXXMethodDecl::Create(SemaRef.Context, Record, - NameInfo, T, TInfo, + StartLoc, NameInfo, T, TInfo, D->isStatic(), D->getStorageClassAsWritten(), - D->isInlineSpecified()); + D->isInlineSpecified(), + D->getLocEnd()); } if (QualifierLoc) @@ -1431,23 +1468,24 @@ Decl *TemplateDeclInstantiator::VisitCXXConversionDecl(CXXConversionDecl *D) { } ParmVarDecl *TemplateDeclInstantiator::VisitParmVarDecl(ParmVarDecl *D) { - return SemaRef.SubstParmVarDecl(D, TemplateArgs, llvm::Optional<unsigned>()); + return SemaRef.SubstParmVarDecl(D, TemplateArgs, /*indexAdjustment*/ 0, + llvm::Optional<unsigned>()); } Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl( TemplateTypeParmDecl *D) { // TODO: don't always clone when decls are refcounted. - const Type* T = D->getTypeForDecl(); - assert(T->isTemplateTypeParmType()); - const TemplateTypeParmType *TTPT = T->getAs<TemplateTypeParmType>(); + assert(D->getTypeForDecl()->isTemplateTypeParmType()); TemplateTypeParmDecl *Inst = - TemplateTypeParmDecl::Create(SemaRef.Context, Owner, D->getLocation(), - TTPT->getDepth() - TemplateArgs.getNumLevels(), - TTPT->getIndex(), D->getIdentifier(), + TemplateTypeParmDecl::Create(SemaRef.Context, Owner, + D->getLocStart(), D->getLocation(), + D->getDepth() - TemplateArgs.getNumLevels(), + D->getIndex(), D->getIdentifier(), D->wasDeclaredWithTypename(), D->isParameterPack()); - + Inst->setAccess(AS_public); + if (D->hasDefaultArgument()) Inst->setDefaultArgument(D->getDefaultArgumentInfo(), false); @@ -1567,7 +1605,6 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl( return 0; // Check that this type is acceptable for a non-type template parameter. - bool Invalid = false; T = SemaRef.CheckNonTypeTemplateParameterType(DI->getType(), D->getLocation()); if (T.isNull()) { @@ -1579,7 +1616,8 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl( NonTypeTemplateParmDecl *Param; if (IsExpandedParameterPack) Param = NonTypeTemplateParmDecl::Create(SemaRef.Context, Owner, - D->getLocation(), + D->getInnerLocStart(), + D->getLocation(), D->getDepth() - TemplateArgs.getNumLevels(), D->getPosition(), D->getIdentifier(), T, @@ -1589,12 +1627,14 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl( ExpandedParameterPackTypesAsWritten.data()); else Param = NonTypeTemplateParmDecl::Create(SemaRef.Context, Owner, + D->getInnerLocStart(), D->getLocation(), D->getDepth() - TemplateArgs.getNumLevels(), D->getPosition(), D->getIdentifier(), T, D->isParameterPack(), DI); + Param->setAccess(AS_public); if (Invalid) Param->setInvalidDecl(); @@ -1628,6 +1668,7 @@ TemplateDeclInstantiator::VisitTemplateTemplateParmDecl( D->getPosition(), D->isParameterPack(), D->getIdentifier(), InstParams); Param->setDefaultArgument(D->getDefaultArgument(), false); + Param->setAccess(AS_public); // Introduce this template parameter's instantiation into the instantiation // scope. @@ -1719,9 +1760,12 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) { I != E; ++I) { UsingShadowDecl *Shadow = *I; NamedDecl *InstTarget = - cast<NamedDecl>(SemaRef.FindInstantiatedDecl(Shadow->getLocation(), - Shadow->getTargetDecl(), - TemplateArgs)); + cast_or_null<NamedDecl>(SemaRef.FindInstantiatedDecl( + Shadow->getLocation(), + Shadow->getTargetDecl(), + TemplateArgs)); + if (!InstTarget) + return 0; if (CheckRedeclaration && SemaRef.CheckUsingShadowDecl(NewUD, InstTarget, Prev)) @@ -1936,7 +1980,8 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization( = ClassTemplatePartialSpecializationDecl::Create(SemaRef.Context, PartialSpec->getTagKind(), Owner, - PartialSpec->getLocation(), + PartialSpec->getLocStart(), + PartialSpec->getLocation(), InstParams, ClassTemplate, Converted.data(), @@ -2063,8 +2108,7 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, const FunctionProtoType *Proto = Tmpl->getType()->getAs<FunctionProtoType>(); assert(Proto && "Function template without prototype?"); - if (Proto->hasExceptionSpec() || Proto->hasAnyExceptionSpec() || - Proto->getNoReturnAttr()) { + if (Proto->hasExceptionSpec() || Proto->getNoReturnAttr()) { // The function has an exception specification or a "noreturn" // attribute. Substitute into each of the exception types. llvm::SmallVector<QualType, 4> Exceptions; @@ -2078,7 +2122,7 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, Unexpanded); assert(!Unexpanded.empty() && "Pack expansion without parameter packs?"); - + bool Expand = false; bool RetainExpansion = false; llvm::Optional<unsigned> NumExpansions @@ -2092,7 +2136,7 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, RetainExpansion, NumExpansions)) break; - + if (!Expand) { // We can't expand this pack expansion into separate arguments yet; // just substitute into the pattern and create a new pack expansion @@ -2108,7 +2152,7 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, Exceptions.push_back(T); continue; } - + // Substitute into the pack expansion pattern for each template bool Invalid = false; for (unsigned ArgIdx = 0; ArgIdx != *NumExpansions; ++ArgIdx) { @@ -2121,13 +2165,13 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, Invalid = true; break; } - + Exceptions.push_back(T); } - + if (Invalid) break; - + continue; } @@ -2140,14 +2184,20 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, Exceptions.push_back(T); } + Expr *NoexceptExpr = 0; + if (Expr *OldNoexceptExpr = Proto->getNoexceptExpr()) { + ExprResult E = SemaRef.SubstExpr(OldNoexceptExpr, TemplateArgs); + if (E.isUsable()) + NoexceptExpr = E.take(); + } // Rebuild the function type FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo(); - EPI.HasExceptionSpec = Proto->hasExceptionSpec(); - EPI.HasAnyExceptionSpec = Proto->hasAnyExceptionSpec(); + EPI.ExceptionSpecType = Proto->getExceptionSpecType(); EPI.NumExceptions = Exceptions.size(); EPI.Exceptions = Exceptions.data(); + EPI.NoexceptExpr = NoexceptExpr; EPI.ExtInfo = Proto->getExtInfo(); const FunctionProtoType *NewProto @@ -2218,6 +2268,21 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, if (PatternDecl) Pattern = PatternDecl->getBody(PatternDecl); + // Postpone late parsed template instantiations. + if (PatternDecl->isLateTemplateParsed() && !LateTemplateParser) { + PendingInstantiations.push_back( + std::make_pair(Function, PointOfInstantiation)); + return; + } + + // Call the LateTemplateParser callback if there a need to late parse + // a templated function definition. + if (!Pattern && PatternDecl && PatternDecl->isLateTemplateParsed() && + LateTemplateParser) { + LateTemplateParser(OpaqueParser, PatternDecl); + Pattern = PatternDecl->getBody(PatternDecl); + } + if (!Pattern) { if (DefinitionRequired) { if (Function->getPrimaryTemplate()) @@ -2573,10 +2638,15 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, New->getParent(), EllipsisLoc); } else if (Init->isMemberInitializer()) { - FieldDecl *Member = cast<FieldDecl>(FindInstantiatedDecl( + FieldDecl *Member = cast_or_null<FieldDecl>(FindInstantiatedDecl( Init->getMemberLocation(), Init->getMember(), TemplateArgs)); + if (!Member) { + AnyErrors = true; + New->setInvalidDecl(); + continue; + } NewInit = BuildMemberInitializer(Member, (Expr **)NewArgs.data(), NewArgs.size(), @@ -2585,10 +2655,16 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, Init->getRParenLoc()); } else if (Init->isIndirectMemberInitializer()) { IndirectFieldDecl *IndirectMember = - cast<IndirectFieldDecl>(FindInstantiatedDecl( + cast_or_null<IndirectFieldDecl>(FindInstantiatedDecl( Init->getMemberLocation(), Init->getIndirectMember(), TemplateArgs)); + if (!IndirectMember) { + AnyErrors = true; + New->setInvalidDecl(); + continue; + } + NewInit = BuildMemberInitializer(IndirectMember, (Expr **)NewArgs.data(), NewArgs.size(), Init->getSourceLocation(), @@ -2917,7 +2993,7 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, // FIXME: Can we use the CurrentInstantiationScope to avoid this // extra instantiation in the common case? - T = SubstType(T, TemplateArgs, SourceLocation(), DeclarationName()); + T = SubstType(T, TemplateArgs, Loc, DeclarationName()); assert(!T.isNull() && "Instantiation of injected-class-name cannot fail."); if (!T->isDependentType()) { @@ -2974,11 +3050,14 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, // If our context used to be dependent, we may need to instantiate // it before performing lookup into that context. + bool IsBeingInstantiated = false; if (CXXRecordDecl *Spec = dyn_cast<CXXRecordDecl>(ParentDC)) { if (!Spec->isDependentContext()) { QualType T = Context.getTypeDeclType(Spec); const RecordType *Tag = T->getAs<RecordType>(); assert(Tag && "type of non-dependent record is not a RecordType"); + if (Tag->isBeingDefined()) + IsBeingInstantiated = true; if (!Tag->isBeingDefined() && RequireCompleteType(Loc, T, diag::err_incomplete_type)) return 0; @@ -3005,11 +3084,29 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, ParentDC->decls_end()); } - // UsingShadowDecls can instantiate to nothing because of using hiding. - assert((Result || isa<UsingShadowDecl>(D) || D->isInvalidDecl() || - cast<Decl>(ParentDC)->isInvalidDecl()) - && "Unable to find instantiation of declaration!"); - + if (!Result) { + if (isa<UsingShadowDecl>(D)) { + // UsingShadowDecls can instantiate to nothing because of using hiding. + } else if (Diags.hasErrorOccurred()) { + // We've already complained about something, so most likely this + // declaration failed to instantiate. There's no point in complaining + // further, since this is normal in invalid code. + } else if (IsBeingInstantiated) { + // The class in which this member exists is currently being + // instantiated, and we haven't gotten around to instantiating this + // member yet. This can happen when the code uses forward declarations + // of member classes, and introduces ordering dependencies via + // template instantiation. + Diag(Loc, diag::err_member_not_yet_instantiated) + << D->getDeclName() + << Context.getTypeDeclType(cast<CXXRecordDecl>(ParentDC)); + Diag(D->getLocation(), diag::note_non_instantiated_member_here); + } else { + // We should have found something, but didn't. + llvm_unreachable("Unable to find instantiation of declaration!"); + } + } + D = Result; } @@ -3018,7 +3115,10 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, /// \brief Performs template instantiation for all implicit template /// instantiations we have seen until this point. -void Sema::PerformPendingInstantiations(bool LocalOnly) { +/// +/// \returns true if anything was instantiated. +bool Sema::PerformPendingInstantiations(bool LocalOnly) { + bool InstantiatedAnything = false; while (!PendingLocalImplicitInstantiations.empty() || (!LocalOnly && !PendingInstantiations.empty())) { PendingImplicitInstantiation Inst; @@ -3039,6 +3139,7 @@ void Sema::PerformPendingInstantiations(bool LocalOnly) { TSK_ExplicitInstantiationDefinition; InstantiateFunctionDefinition(/*FIXME:*/Inst.second, Function, true, DefinitionRequired); + InstantiatedAnything = true; continue; } @@ -3075,7 +3176,10 @@ void Sema::PerformPendingInstantiations(bool LocalOnly) { TSK_ExplicitInstantiationDefinition; InstantiateStaticDataMemberDefinition(/*FIXME:*/Inst.second, Var, true, DefinitionRequired); + InstantiatedAnything = true; } + + return InstantiatedAnything; } void Sema::PerformDependentDiagnostics(const DeclContext *Pattern, diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp index 0da801c..096d353 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -167,7 +167,7 @@ DiagnoseUnexpandedParameterPacks(Sema &S, SourceLocation Loc, IdentifierInfo *Name = 0; if (const TemplateTypeParmType *TTP = Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>()) - Name = TTP->getName(); + Name = TTP->getIdentifier(); else Name = Unexpanded[I].first.get<NamedDecl *>()->getIdentifier(); @@ -483,7 +483,7 @@ bool Sema::CheckParameterPacksForExpansion(SourceLocation EllipsisLoc, = Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>()) { Depth = TTP->getDepth(); Index = TTP->getIndex(); - Name = TTP->getName(); + Name = TTP->getIdentifier(); } else { NamedDecl *ND = Unexpanded[I].first.get<NamedDecl *>(); if (isa<ParmVarDecl>(ND)) @@ -649,6 +649,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) { case TST_struct: case TST_class: case TST_auto: + case TST_unknown_anytype: case TST_error: break; } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp index ba80076..00ac1d6 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp @@ -13,6 +13,7 @@ #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" +#include "clang/Basic/OpenCL.h" #include "clang/AST/ASTContext.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclObjC.h" @@ -22,6 +23,7 @@ #include "clang/AST/Expr.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/TargetInfo.h" +#include "clang/Lex/Preprocessor.h" #include "clang/Sema/DeclSpec.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/ErrorHandling.h" @@ -70,6 +72,40 @@ static bool isOmittedBlockReturnType(const Declarator &D) { return false; } +/// diagnoseBadTypeAttribute - Diagnoses a type attribute which +/// doesn't apply to the given type. +static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr, + QualType type) { + bool useInstantiationLoc = false; + + unsigned diagID = 0; + switch (attr.getKind()) { + case AttributeList::AT_objc_gc: + diagID = diag::warn_pointer_attribute_wrong_type; + useInstantiationLoc = true; + break; + + default: + // Assume everything else was a function attribute. + diagID = diag::warn_function_attribute_wrong_type; + break; + } + + SourceLocation loc = attr.getLoc(); + llvm::StringRef name = attr.getName()->getName(); + + // The GC attributes are usually written with macros; special-case them. + if (useInstantiationLoc && loc.isMacroID() && attr.getParameterName()) { + if (attr.getParameterName()->isStr("strong")) { + if (S.findMacroSpelling(loc, "__strong")) name = "__strong"; + } else if (attr.getParameterName()->isStr("weak")) { + if (S.findMacroSpelling(loc, "__weak")) name = "__weak"; + } + } + + S.Diag(loc, diagID) << name << type; +} + // objc_gc applies to Objective-C pointers or, otherwise, to the // smallest available pointer type (i.e. 'void*' in 'void**'). #define OBJC_POINTER_TYPE_ATTRS_CASELIST \ @@ -83,7 +119,8 @@ static bool isOmittedBlockReturnType(const Declarator &D) { case AttributeList::AT_stdcall: \ case AttributeList::AT_thiscall: \ case AttributeList::AT_pascal: \ - case AttributeList::AT_regparm + case AttributeList::AT_regparm: \ + case AttributeList::AT_pcs \ namespace { /// An object which stores processing state for the entire @@ -102,6 +139,9 @@ namespace { /// Whether there are non-trivial modifications to the decl spec. bool trivial; + /// Whether we saved the attributes in the decl spec. + bool hasSavedAttrs; + /// The original set of attributes on the DeclSpec. llvm::SmallVector<AttributeList*, 2> savedAttrs; @@ -113,7 +153,7 @@ namespace { TypeProcessingState(Sema &sema, Declarator &declarator) : sema(sema), declarator(declarator), chunkIndex(declarator.getNumTypeObjects()), - trivial(true) {} + trivial(true), hasSavedAttrs(false) {} Sema &getSema() const { return sema; @@ -142,13 +182,14 @@ namespace { /// Save the current set of attributes on the DeclSpec. void saveDeclSpecAttrs() { // Don't try to save them multiple times. - if (!savedAttrs.empty()) return; + if (hasSavedAttrs) return; DeclSpec &spec = getMutableDeclSpec(); for (AttributeList *attr = spec.getAttributes().getList(); attr; attr = attr->getNext()) savedAttrs.push_back(attr); trivial &= savedAttrs.empty(); + hasSavedAttrs = true; } /// Record that we had nowhere to put the given type attribute. @@ -162,11 +203,8 @@ namespace { void diagnoseIgnoredTypeAttrs(QualType type) const { for (llvm::SmallVectorImpl<AttributeList*>::const_iterator i = ignoredTypeAttrs.begin(), e = ignoredTypeAttrs.end(); - i != e; ++i) { - AttributeList &attr = **i; - getSema().Diag(attr.getLoc(), diag::warn_function_attribute_wrong_type) - << attr.getName() << type; - } + i != e; ++i) + diagnoseBadTypeAttribute(getSema(), **i, type); } ~TypeProcessingState() { @@ -181,7 +219,13 @@ namespace { } void restoreDeclSpecAttrs() { - assert(!savedAttrs.empty()); + assert(hasSavedAttrs); + + if (savedAttrs.empty()) { + getMutableDeclSpec().getAttributes().set(0); + return; + } + getMutableDeclSpec().getAttributes().set(savedAttrs[0]); for (unsigned i = 0, e = savedAttrs.size() - 1; i != e; ++i) savedAttrs[i]->setNext(savedAttrs[i+1]); @@ -287,9 +331,8 @@ static void distributeObjCPointerTypeAttr(TypeProcessingState &state, } } error: - - state.getSema().Diag(attr.getLoc(), diag::warn_function_attribute_wrong_type) - << attr.getName() << type; + + diagnoseBadTypeAttribute(state.getSema(), attr, type); } /// Distribute an objc_gc type attribute that was written on the @@ -328,8 +371,15 @@ distributeObjCPointerTypeAttrFromDeclarator(TypeProcessingState &state, // That might actually be the decl spec if we weren't blocked by // anything in the declarator. if (considerDeclSpec) { - if (handleObjCPointerTypeAttr(state, attr, declSpecType)) + if (handleObjCPointerTypeAttr(state, attr, declSpecType)) { + // Splice the attribute into the decl spec. Prevents the + // attribute from being applied multiple times and gives + // the source-location-filler something to work with. + state.saveDeclSpecAttrs(); + moveAttrFromListToList(attr, declarator.getAttrListRef(), + declarator.getMutableDeclSpec().getAttributes().getListRef()); return; + } } // Otherwise, if we found an appropriate chunk, splice the attribute @@ -374,8 +424,7 @@ static void distributeFunctionTypeAttr(TypeProcessingState &state, } } - state.getSema().Diag(attr.getLoc(), diag::warn_function_attribute_wrong_type) - << attr.getName() << type; + diagnoseBadTypeAttribute(state.getSema(), attr, type); } /// Try to distribute a function type attribute to the innermost @@ -505,13 +554,12 @@ static void maybeSynthesizeBlockSignature(TypeProcessingState &state, // ...and *prepend* it to the declarator. declarator.AddInnermostTypeInfo(DeclaratorChunk::getFunction( - ParsedAttributes(), /*proto*/ true, /*variadic*/ false, SourceLocation(), /*args*/ 0, 0, /*type quals*/ 0, /*ref-qualifier*/true, SourceLocation(), - /*EH*/ false, SourceLocation(), false, 0, 0, 0, + /*EH*/ EST_None, SourceLocation(), 0, 0, 0, 0, /*parens*/ loc, loc, declarator)); @@ -698,7 +746,7 @@ static QualType ConvertDeclSpecToType(Sema &S, TypeProcessingState &state) { } // If the type is deprecated or unavailable, diagnose it. - S.DiagnoseUseOfDecl(D, DS.getTypeSpecTypeLoc()); + S.DiagnoseUseOfDecl(D, DS.getTypeSpecTypeNameLoc()); assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 && DS.getTypeSpecSign() == 0 && "No qualifiers on tag names!"); @@ -706,12 +754,11 @@ static QualType ConvertDeclSpecToType(Sema &S, TypeProcessingState &state) { // TypeQuals handled by caller. Result = Context.getTypeDeclType(D); - // In C++, make an ElaboratedType. - if (S.getLangOptions().CPlusPlus) { - ElaboratedTypeKeyword Keyword - = ElaboratedType::getKeywordForTypeSpec(DS.getTypeSpecType()); - Result = S.getElaboratedType(Keyword, DS.getTypeSpecScope(), Result); - } + // In both C and C++, make an ElaboratedType. + ElaboratedTypeKeyword Keyword + = ElaboratedType::getKeywordForTypeSpec(DS.getTypeSpecType()); + Result = S.getElaboratedType(Keyword, DS.getTypeSpecScope(), Result); + if (D->isInvalidDecl()) declarator.setInvalidType(true); break; @@ -795,6 +842,10 @@ static QualType ConvertDeclSpecToType(Sema &S, TypeProcessingState &state) { break; } + case DeclSpec::TST_unknown_anytype: + Result = Context.UnknownAnyTy; + break; + case DeclSpec::TST_error: Result = Context.IntTy; declarator.setInvalidType(true); @@ -1108,8 +1159,13 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, } // Do lvalue-to-rvalue conversions on the array size expression. - if (ArraySize && !ArraySize->isRValue()) - DefaultLvalueConversion(ArraySize); + if (ArraySize && !ArraySize->isRValue()) { + ExprResult Result = DefaultLvalueConversion(ArraySize); + if (Result.isInvalid()) + return QualType(); + + ArraySize = Result.take(); + } // C99 6.7.5.2p1: The size expression shall have integer type. // TODO: in theory, if we were insane, we could allow contextual @@ -1464,19 +1520,27 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, TypeProcessingState state(*this, D); + // In C++0x, deallocation functions (normal and array operator delete) + // are implicitly noexcept. + bool ImplicitlyNoexcept = false; + switch (D.getName().getKind()) { - case UnqualifiedId::IK_Identifier: case UnqualifiedId::IK_OperatorFunctionId: + if (getLangOptions().CPlusPlus0x) { + OverloadedOperatorKind OO = D.getName().OperatorFunctionId.Operator; + if (OO == OO_Delete || OO == OO_Array_Delete) + ImplicitlyNoexcept = true; + } + // Intentional fall-through. + case UnqualifiedId::IK_Identifier: case UnqualifiedId::IK_LiteralOperatorId: case UnqualifiedId::IK_TemplateId: T = ConvertDeclSpecToType(*this, state); if (!D.isInvalidType() && D.getDeclSpec().isTypeSpecOwned()) { TagDecl* Owned = cast<TagDecl>(D.getDeclSpec().getRepAsDecl()); - // Owned is embedded if it was defined here, or if it is the - // very first (i.e., canonical) declaration of this tag type. - Owned->setEmbeddedInDeclarator(Owned->isDefinition() || - Owned->isCanonicalDecl()); + // Owned declaration is embedded in declarator. + Owned->setEmbeddedInDeclarator(true); if (OwnedDecl) *OwnedDecl = Owned; } break; @@ -1512,6 +1576,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, case Declarator::KNRTypeListContext: assert(0 && "K&R type lists aren't allowed in C++"); break; + case Declarator::ObjCPrototypeContext: case Declarator::PrototypeContext: Error = 0; // Function prototype break; @@ -1535,9 +1600,12 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, case Declarator::TemplateTypeArgContext: Error = 7; // Template type argument break; + case Declarator::AliasDeclContext: + Error = 9; // Type alias + break; case Declarator::TypeNameContext: if (!AutoAllowedInTypeName) - Error = 10; // Generic + Error = 11; // Generic break; case Declarator::FileContext: case Declarator::BlockContext: @@ -1551,7 +1619,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, // In Objective-C it is an error to use 'auto' on a function declarator. if (D.isFunctionDeclarator()) - Error = 9; + Error = 10; // C++0x [dcl.spec.auto]p2: 'auto' is always fine if the declarator // contains a trailing return type. That is only legal at the outermost @@ -1588,6 +1656,11 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, if (D.getIdentifier()) Name = D.getIdentifier(); + // Does this declaration declare a typedef-name? + bool IsTypedefName = + D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef || + D.getContext() == Declarator::AliasDeclContext; + // Walk the DeclTypeInfo, building the recursive type as we go. // DeclTypeInfos are ordered from the identifier out, which is // opposite of what we want :). @@ -1660,8 +1733,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, ASM = ArrayType::Static; else ASM = ArrayType::Normal; - if (ASM == ArrayType::Star && - D.getContext() != Declarator::PrototypeContext) { + if (ASM == ArrayType::Star && !D.isPrototypeContext()) { // FIXME: This check isn't quite right: it allows star in prototypes // for function definitions, and disallows some edge cases detailed // in http://gcc.gnu.org/ml/gcc-patches/2009-02/msg00133.html @@ -1728,7 +1800,8 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, // cv-qualifiers on return types are pointless except when the type is a // class type in C++. - if (T->isPointerType() && T.getCVRQualifiers() && + if (isa<PointerType>(T) && T.getLocalCVRQualifiers() && + (D.getName().getKind() != UnqualifiedId::IK_ConversionFunctionId) && (!getLangOptions().CPlusPlus || !T->isDependentType())) { assert(chunkIndex + 1 < e && "No DeclaratorChunk for the return type?"); DeclaratorChunk ReturnTypeChunk = D.getTypeObject(chunkIndex + 1); @@ -1764,9 +1837,9 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, // Exception specs are not allowed in typedefs. Complain, but add it // anyway. - if (FTI.hasExceptionSpec && - D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) - Diag(FTI.getThrowLoc(), diag::err_exception_spec_in_typedef); + if (IsTypedefName && FTI.getExceptionSpecType()) + Diag(FTI.getExceptionSpecLoc(), diag::err_exception_spec_in_typedef) + << (D.getContext() == Declarator::AliasDeclContext); if (!FTI.NumArgs && !FTI.isVariadic && !getLangOptions().CPlusPlus) { // Simple void foo(), where the incoming T is the result type. @@ -1845,9 +1918,12 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, } else if (!FTI.hasPrototype) { if (ArgTy->isPromotableIntegerType()) { ArgTy = Context.getPromotedIntegerType(ArgTy); + Param->setKNRPromoted(true); } else if (const BuiltinType* BTy = ArgTy->getAs<BuiltinType>()) { - if (BTy->getKind() == BuiltinType::Float) + if (BTy->getKind() == BuiltinType::Float) { ArgTy = Context.DoubleTy; + Param->setKNRPromoted(true); + } } } @@ -1855,9 +1931,8 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, } llvm::SmallVector<QualType, 4> Exceptions; - if (FTI.hasExceptionSpec) { - EPI.HasExceptionSpec = FTI.hasExceptionSpec; - EPI.HasAnyExceptionSpec = FTI.hasAnyExceptionSpec; + EPI.ExceptionSpecType = FTI.getExceptionSpecType(); + if (FTI.getExceptionSpecType() == EST_Dynamic) { Exceptions.reserve(FTI.NumExceptions); for (unsigned ei = 0, ee = FTI.NumExceptions; ei != ee; ++ei) { // FIXME: Preserve type source info. @@ -1869,6 +1944,27 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, } EPI.NumExceptions = Exceptions.size(); EPI.Exceptions = Exceptions.data(); + } else if (FTI.getExceptionSpecType() == EST_ComputedNoexcept) { + // If an error occurred, there's no expression here. + if (Expr *NoexceptExpr = FTI.NoexceptExpr) { + assert((NoexceptExpr->isTypeDependent() || + NoexceptExpr->getType()->getCanonicalTypeUnqualified() == + Context.BoolTy) && + "Parser should have made sure that the expression is boolean"); + SourceLocation ErrLoc; + llvm::APSInt Dummy; + if (!NoexceptExpr->isValueDependent() && + !NoexceptExpr->isIntegerConstantExpr(Dummy, Context, &ErrLoc, + /*evaluated*/false)) + Diag(ErrLoc, diag::err_noexcept_needs_constant_expression) + << NoexceptExpr->getSourceRange(); + else + EPI.NoexceptExpr = NoexceptExpr; + } + } else if (FTI.getExceptionSpecType() == EST_None && + ImplicitlyNoexcept && chunkIndex == 0) { + // Only the outermost chunk is marked noexcept, of course. + EPI.ExceptionSpecType = EST_BasicNoexcept; } T = Context.getFunctionType(T, ArgTys.data(), ArgTys.size(), EPI); @@ -1903,11 +1999,12 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, case NestedNameSpecifier::TypeSpec: case NestedNameSpecifier::TypeSpecWithTemplate: ClsType = QualType(NNS->getAsType(), 0); - // Note: if NNS is dependent, then its prefix (if any) is already - // included in ClsType; this does not hold if the NNS is - // nondependent: in this case (if there is indeed a prefix) - // ClsType needs to be wrapped into an elaborated type. - if (NNSPrefix && !NNS->isDependent()) + // Note: if the NNS has a prefix and ClsType is a nondependent + // TemplateSpecializationType, then the NNS prefix is NOT included + // in ClsType; hence we wrap ClsType into an ElaboratedType. + // NOTE: in particular, no wrap occurs if ClsType already is an + // Elaborated, DependentName, or DependentTemplateSpecialization. + if (NNSPrefix && isa<TemplateSpecializationType>(NNS->getAsType())) ClsType = Context.getElaboratedType(ETK_None, NNSPrefix, ClsType); break; } @@ -1968,8 +2065,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, // declaration. if ((FnTy->getTypeQuals() != 0 || FnTy->getRefQualifier()) && !(D.getContext() == Declarator::TemplateTypeArgContext && - !D.isFunctionDeclarator()) && - D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef && + !D.isFunctionDeclarator()) && !IsTypedefName && (FreeFunction || D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static)) { if (D.getContext() == Declarator::TemplateTypeArgContext) { @@ -2053,8 +2149,10 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, // Diagnose any ignored type attributes. if (!T.isNull()) state.diagnoseIgnoredTypeAttrs(T); - // If there's a constexpr specifier, treat it as a top-level const. - if (D.getDeclSpec().isConstexprSpecified()) { + // C++0x [dcl.constexpr]p9: + // A constexpr specifier used in an object declaration declares the object + // as const. + if (D.getDeclSpec().isConstexprSpecified() && T->isObjectType()) { T.addConst(); } @@ -2103,7 +2201,9 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, case Declarator::FileContext: case Declarator::KNRTypeListContext: + case Declarator::ObjCPrototypeContext: // FIXME: special diagnostic here? case Declarator::TypeNameContext: + case Declarator::AliasDeclContext: case Declarator::MemberContext: case Declarator::BlockContext: case Declarator::ForContext: @@ -2126,6 +2226,62 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, return GetTypeSourceInfoForDeclarator(D, T, ReturnTypeInfo); } +/// Map an AttributedType::Kind to an AttributeList::Kind. +static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) { + switch (kind) { + case AttributedType::attr_address_space: + return AttributeList::AT_address_space; + case AttributedType::attr_regparm: + return AttributeList::AT_regparm; + case AttributedType::attr_vector_size: + return AttributeList::AT_vector_size; + case AttributedType::attr_neon_vector_type: + return AttributeList::AT_neon_vector_type; + case AttributedType::attr_neon_polyvector_type: + return AttributeList::AT_neon_polyvector_type; + case AttributedType::attr_objc_gc: + return AttributeList::AT_objc_gc; + case AttributedType::attr_noreturn: + return AttributeList::AT_noreturn; + case AttributedType::attr_cdecl: + return AttributeList::AT_cdecl; + case AttributedType::attr_fastcall: + return AttributeList::AT_fastcall; + case AttributedType::attr_stdcall: + return AttributeList::AT_stdcall; + case AttributedType::attr_thiscall: + return AttributeList::AT_thiscall; + case AttributedType::attr_pascal: + return AttributeList::AT_pascal; + case AttributedType::attr_pcs: + return AttributeList::AT_pcs; + } + llvm_unreachable("unexpected attribute kind!"); + return AttributeList::Kind(); +} + +static void fillAttributedTypeLoc(AttributedTypeLoc TL, + const AttributeList *attrs) { + AttributedType::Kind kind = TL.getAttrKind(); + + assert(attrs && "no type attributes in the expected location!"); + AttributeList::Kind parsedKind = getAttrListKind(kind); + while (attrs->getKind() != parsedKind) { + attrs = attrs->getNext(); + assert(attrs && "no matching attribute in expected location!"); + } + + TL.setAttrNameLoc(attrs->getLoc()); + if (TL.hasAttrExprOperand()) + TL.setAttrExprOperand(attrs->getArg(0)); + else if (TL.hasAttrEnumOperand()) + TL.setAttrEnumOperandLoc(attrs->getParameterLoc()); + + // FIXME: preserve this information to here. + if (TL.hasAttrOperand()) + TL.setAttrOperandParensRange(SourceRange()); +} + namespace { class TypeSpecLocFiller : public TypeLocVisitor<TypeSpecLocFiller> { ASTContext &Context; @@ -2135,6 +2291,10 @@ namespace { TypeSpecLocFiller(ASTContext &Context, const DeclSpec &DS) : Context(Context), DS(DS) {} + void VisitAttributedTypeLoc(AttributedTypeLoc TL) { + fillAttributedTypeLoc(TL, DS.getAttributes().getList()); + Visit(TL.getModifiedLoc()); + } void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) { Visit(TL.getUnqualifiedLoc()); } @@ -2179,7 +2339,7 @@ namespace { // If we got no declarator info from previous Sema routines, // just fill with the typespec loc. if (!TInfo) { - TL.initialize(Context, DS.getTypeSpecTypeLoc()); + TL.initialize(Context, DS.getTypeSpecTypeNameLoc()); return; } @@ -2237,7 +2397,7 @@ namespace { ? DS.getTypeSpecTypeLoc() : SourceLocation()); const CXXScopeSpec& SS = DS.getTypeSpecScope(); - TL.setQualifierRange(SS.isEmpty() ? SourceRange(): SS.getRange()); + TL.setQualifierLoc(SS.getWithLocInContext(Context)); Visit(TL.getNextTypeLoc().getUnqualifiedLoc()); } void VisitDependentNameTypeLoc(DependentNameTypeLoc TL) { @@ -2255,9 +2415,8 @@ namespace { ? DS.getTypeSpecTypeLoc() : SourceLocation()); const CXXScopeSpec& SS = DS.getTypeSpecScope(); - TL.setQualifierRange(SS.isEmpty() ? SourceRange() : SS.getRange()); - // FIXME: load appropriate source location. - TL.setNameLoc(DS.getTypeSpecTypeLoc()); + TL.setQualifierLoc(SS.getWithLocInContext(Context)); + TL.setNameLoc(DS.getTypeSpecTypeNameLoc()); } void VisitDependentTemplateSpecializationTypeLoc( DependentTemplateSpecializationTypeLoc TL) { @@ -2277,9 +2436,11 @@ namespace { ? DS.getTypeSpecTypeLoc() : SourceLocation()); const CXXScopeSpec& SS = DS.getTypeSpecScope(); - TL.setQualifierRange(SS.isEmpty() ? SourceRange() : SS.getRange()); - // FIXME: load appropriate source location. - TL.setNameLoc(DS.getTypeSpecTypeLoc()); + TL.setQualifierLoc(SS.getWithLocInContext(Context)); + TL.setNameLoc(DS.getTypeSpecTypeNameLoc()); + } + void VisitTagTypeLoc(TagTypeLoc TL) { + TL.setNameLoc(DS.getTypeSpecTypeNameLoc()); } void VisitTypeLoc(TypeLoc TL) { @@ -2289,10 +2450,12 @@ namespace { }; class DeclaratorLocFiller : public TypeLocVisitor<DeclaratorLocFiller> { + ASTContext &Context; const DeclaratorChunk &Chunk; public: - DeclaratorLocFiller(const DeclaratorChunk &Chunk) : Chunk(Chunk) {} + DeclaratorLocFiller(ASTContext &Context, const DeclaratorChunk &Chunk) + : Context(Context), Chunk(Chunk) {} void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) { llvm_unreachable("qualified type locs not expected here!"); @@ -2312,8 +2475,48 @@ namespace { } void VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) { assert(Chunk.Kind == DeclaratorChunk::MemberPointer); + const CXXScopeSpec& SS = Chunk.Mem.Scope(); + NestedNameSpecifierLoc NNSLoc = SS.getWithLocInContext(Context); + + const Type* ClsTy = TL.getClass(); + QualType ClsQT = QualType(ClsTy, 0); + TypeSourceInfo *ClsTInfo = Context.CreateTypeSourceInfo(ClsQT, 0); + // Now copy source location info into the type loc component. + TypeLoc ClsTL = ClsTInfo->getTypeLoc(); + switch (NNSLoc.getNestedNameSpecifier()->getKind()) { + case NestedNameSpecifier::Identifier: + assert(isa<DependentNameType>(ClsTy) && "Unexpected TypeLoc"); + { + DependentNameTypeLoc DNTLoc = cast<DependentNameTypeLoc>(ClsTL); + DNTLoc.setKeywordLoc(SourceLocation()); + DNTLoc.setQualifierLoc(NNSLoc.getPrefix()); + DNTLoc.setNameLoc(NNSLoc.getLocalBeginLoc()); + } + break; + + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: + if (isa<ElaboratedType>(ClsTy)) { + ElaboratedTypeLoc ETLoc = *cast<ElaboratedTypeLoc>(&ClsTL); + ETLoc.setKeywordLoc(SourceLocation()); + ETLoc.setQualifierLoc(NNSLoc.getPrefix()); + TypeLoc NamedTL = ETLoc.getNamedTypeLoc(); + NamedTL.initializeFullCopy(NNSLoc.getTypeLoc()); + } else { + ClsTL.initializeFullCopy(NNSLoc.getTypeLoc()); + } + break; + + case NestedNameSpecifier::Namespace: + case NestedNameSpecifier::NamespaceAlias: + case NestedNameSpecifier::Global: + llvm_unreachable("Nested-name-specifier must name a type"); + break; + } + + // Finally fill in MemberPointerLocInfo fields. TL.setStarLoc(Chunk.Loc); - // FIXME: nested name specifier + TL.setClassTInfo(ClsTInfo); } void VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) { assert(Chunk.Kind == DeclaratorChunk::Reference); @@ -2334,8 +2537,8 @@ namespace { } void VisitFunctionTypeLoc(FunctionTypeLoc TL) { assert(Chunk.Kind == DeclaratorChunk::Function); - TL.setLParenLoc(Chunk.Loc); - TL.setRParenLoc(Chunk.EndLoc); + TL.setLocalRangeBegin(Chunk.Loc); + TL.setLocalRangeEnd(Chunk.EndLoc); TL.setTrailingReturn(!!Chunk.Fun.TrailingReturnType); const DeclaratorChunk::FunctionTypeInfo &FTI = Chunk.Fun; @@ -2378,7 +2581,13 @@ Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T, } for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) { - DeclaratorLocFiller(D.getTypeObject(i)).Visit(CurrTL); + while (isa<AttributedTypeLoc>(CurrTL)) { + AttributedTypeLoc TL = cast<AttributedTypeLoc>(CurrTL); + fillAttributedTypeLoc(TL, D.getTypeObject(i).getAttrs()); + CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc(); + } + + DeclaratorLocFiller(Context, D.getTypeObject(i)).Visit(CurrTL); CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc(); } @@ -2434,7 +2643,8 @@ TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) { // A type-specifier-seq shall not define a class or enumeration // unless it appears in the type-id of an alias-declaration // (7.1.3). - if (OwnedTag && OwnedTag->isDefinition()) + if (OwnedTag && OwnedTag->isDefinition() && + D.getContext() != Declarator::AliasDeclContext) Diag(OwnedTag->getLocation(), diag::err_type_defined_in_type_specifier) << Context.getTypeDeclType(OwnedTag); } @@ -2547,7 +2757,14 @@ static bool handleObjCGCTypeAttr(TypeProcessingState &state, return true; } - type = S.Context.getObjCGCQualType(type, GCAttr); + QualType origType = type; + type = S.Context.getObjCGCQualType(origType, GCAttr); + + // Make an attributed type to preserve the source information. + if (attr.getLoc().isValid()) + type = S.Context.getAttributedType(AttributedType::attr_objc_gc, + origType, type); + return true; } @@ -2775,7 +2992,7 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, } // Also diagnose fastcall with regparm. - if (fn->getRegParmType()) { + if (fn->getHasRegParm()) { S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible) << "regparm" << FunctionType::getNameForCallConv(CC); @@ -2789,6 +3006,41 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, return true; } +/// Handle OpenCL image access qualifiers: read_only, write_only, read_write +static void HandleOpenCLImageAccessAttribute(QualType& CurType, + const AttributeList &Attr, + Sema &S) { + // Check the attribute arguments. + if (Attr.getNumArgs() != 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + Attr.setInvalid(); + return; + } + Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0)); + llvm::APSInt arg(32); + if (sizeExpr->isTypeDependent() || sizeExpr->isValueDependent() || + !sizeExpr->isIntegerConstantExpr(arg, S.Context)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) + << "opencl_image_access" << sizeExpr->getSourceRange(); + Attr.setInvalid(); + return; + } + unsigned iarg = static_cast<unsigned>(arg.getZExtValue()); + switch (iarg) { + case CLIA_read_only: + case CLIA_write_only: + case CLIA_read_write: + // Implemented in a separate patch + break; + default: + // Implemented in a separate patch + S.Diag(Attr.getLoc(), diag::err_attribute_invalid_size) + << sizeExpr->getSourceRange(); + Attr.setInvalid(); + break; + } +} + /// HandleVectorSizeAttribute - this attribute is only applicable to integral /// and float scalars, although arrays, pointers, and function return values are /// allowed in conjunction with this construct. Aggregates with this attribute @@ -2943,6 +3195,10 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, "neon_polyvector_type"); break; + case AttributeList::AT_opencl_image_access: + HandleOpenCLImageAccessAttribute(type, attr, state.getSema()); + break; + FUNCTION_TYPE_ATTRS_CASELIST: // Never process function type attributes as part of the // declaration-specifiers. @@ -3088,7 +3344,7 @@ QualType Sema::getElaboratedType(ElaboratedTypeKeyword Keyword, } QualType Sema::BuildTypeofExprType(Expr *E, SourceLocation Loc) { - ExprResult ER = CheckPlaceholderExpr(E, Loc); + ExprResult ER = CheckPlaceholderExpr(E); if (ER.isInvalid()) return QualType(); E = ER.take(); @@ -3101,7 +3357,7 @@ QualType Sema::BuildTypeofExprType(Expr *E, SourceLocation Loc) { } QualType Sema::BuildDecltypeType(Expr *E, SourceLocation Loc) { - ExprResult ER = CheckPlaceholderExpr(E, Loc); + ExprResult ER = CheckPlaceholderExpr(E); if (ER.isInvalid()) return QualType(); E = ER.take(); diff --git a/contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.cpp b/contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.cpp index c3415cb..ab697ee 100644 --- a/contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.cpp @@ -136,7 +136,7 @@ static void HandleX86ForceAlignArgPointerAttr(Decl *D, if (VD && VD->getType()->isFunctionPointerType()) return; // Also don't warn on function pointer typedefs. - TypedefDecl *TD = dyn_cast<TypedefDecl>(D); + TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D); if (TD && (TD->getUnderlyingType()->isFunctionPointerType() || TD->getUnderlyingType()->isFunctionType())) return; diff --git a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h index 57a44ad..2a71e14 100644 --- a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h +++ b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h @@ -67,7 +67,7 @@ using namespace sema; /// /// Subclasses can customize the transformation at various levels. The /// most coarse-grained transformations involve replacing TransformType(), -/// TransformExpr(), TransformDecl(), TransformNestedNameSpecifier(), +/// TransformExpr(), TransformDecl(), TransformNestedNameSpecifierLoc(), /// TransformTemplateName(), or TransformTemplateArgument() with entirely /// new implementations. /// @@ -375,16 +375,6 @@ public: return cast_or_null<NamedDecl>(getDerived().TransformDecl(Loc, D)); } - /// \brief Transform the given nested-name-specifier. - /// - /// By default, transforms all of the types and declarations within the - /// nested-name-specifier. Subclasses may override this function to provide - /// alternate behavior. - NestedNameSpecifier *TransformNestedNameSpecifier(NestedNameSpecifier *NNS, - SourceRange Range, - QualType ObjectType = QualType(), - NamedDecl *FirstQualifierInScope = 0); - /// \brief Transform the given nested-name-specifier with source-location /// information. /// @@ -407,10 +397,27 @@ public: /// \brief Transform the given template name. /// + /// \param SS The nested-name-specifier that qualifies the template + /// name. This nested-name-specifier must already have been transformed. + /// + /// \param Name The template name to transform. + /// + /// \param NameLoc The source location of the template name. + /// + /// \param ObjectType If we're translating a template name within a member + /// access expression, this is the type of the object whose member template + /// is being referenced. + /// + /// \param FirstQualifierInScope If the first part of a nested-name-specifier + /// also refers to a name within the current (lexical) scope, this is the + /// declaration it refers to. + /// /// By default, transforms the template name by transforming the declarations /// and nested-name-specifiers that occur within the template name. /// Subclasses may override this function to provide alternate behavior. - TemplateName TransformTemplateName(TemplateName Name, + TemplateName TransformTemplateName(CXXScopeSpec &SS, + TemplateName Name, + SourceLocation NameLoc, QualType ObjectType = QualType(), NamedDecl *FirstQualifierInScope = 0); @@ -483,6 +490,9 @@ public: QualType Transform##CLASS##Type(TypeLocBuilder &TLB, CLASS##TypeLoc T); #include "clang/AST/TypeLocNodes.def" + StmtResult + TransformSEHHandler(Stmt *Handler); + QualType TransformTemplateSpecializationType(TypeLocBuilder &TLB, TemplateSpecializationTypeLoc TL, @@ -491,7 +501,13 @@ public: QualType TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB, DependentTemplateSpecializationTypeLoc TL, - NestedNameSpecifier *Prefix); + TemplateName Template, + CXXScopeSpec &SS); + + QualType + TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB, + DependentTemplateSpecializationTypeLoc TL, + NestedNameSpecifierLoc QualifierLoc); /// \brief Transforms the parameters of a function type into the /// given vectors. @@ -508,7 +524,11 @@ public: /// \brief Transforms a single function-type parameter. Return null /// on error. + /// + /// \param indexAdjustment - A number to add to the parameter's + /// scope index; can be negative ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm, + int indexAdjustment, llvm::Optional<unsigned> NumExpansions); QualType TransformReferenceType(TypeLocBuilder &TLB, ReferenceTypeLoc TL); @@ -656,7 +676,7 @@ public: QualType RebuildUnresolvedUsingType(Decl *D); /// \brief Build a new typedef type. - QualType RebuildTypedefType(TypedefDecl *Typedef) { + QualType RebuildTypedefType(TypedefNameDecl *Typedef) { return SemaRef.Context.getTypeDeclType(Typedef); } @@ -701,7 +721,7 @@ public: /// different behavior. QualType RebuildTemplateSpecializationType(TemplateName Template, SourceLocation TemplateLoc, - const TemplateArgumentListInfo &Args); + TemplateArgumentListInfo &Args); /// \brief Build a new parenthesized type. /// @@ -718,8 +738,11 @@ public: /// Subclasses may override this routine to provide different behavior. QualType RebuildElaboratedType(SourceLocation KeywordLoc, ElaboratedTypeKeyword Keyword, - NestedNameSpecifier *NNS, QualType Named) { - return SemaRef.Context.getElaboratedType(Keyword, NNS, Named); + NestedNameSpecifierLoc QualifierLoc, + QualType Named) { + return SemaRef.Context.getElaboratedType(Keyword, + QualifierLoc.getNestedNameSpecifier(), + Named); } /// \brief Build a new typename type that refers to a template-id. @@ -728,34 +751,40 @@ public: /// nested-name-specifier and the given type. Subclasses may override /// this routine to provide different behavior. QualType RebuildDependentTemplateSpecializationType( - ElaboratedTypeKeyword Keyword, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, - const IdentifierInfo *Name, - SourceLocation NameLoc, - const TemplateArgumentListInfo &Args) { + ElaboratedTypeKeyword Keyword, + NestedNameSpecifierLoc QualifierLoc, + const IdentifierInfo *Name, + SourceLocation NameLoc, + TemplateArgumentListInfo &Args) { // Rebuild the template name. // TODO: avoid TemplateName abstraction - TemplateName InstName = - getDerived().RebuildTemplateName(Qualifier, QualifierRange, *Name, - QualType(), 0); + CXXScopeSpec SS; + SS.Adopt(QualifierLoc); + TemplateName InstName + = getDerived().RebuildTemplateName(SS, *Name, NameLoc, QualType(), 0); if (InstName.isNull()) return QualType(); - + // If it's still dependent, make a dependent specialization. if (InstName.getAsDependentTemplateName()) - return SemaRef.Context.getDependentTemplateSpecializationType( - Keyword, Qualifier, Name, Args); - + return SemaRef.Context.getDependentTemplateSpecializationType(Keyword, + QualifierLoc.getNestedNameSpecifier(), + Name, + Args); + // Otherwise, make an elaborated type wrapping a non-dependent // specialization. QualType T = - getDerived().RebuildTemplateSpecializationType(InstName, NameLoc, Args); + getDerived().RebuildTemplateSpecializationType(InstName, NameLoc, Args); if (T.isNull()) return QualType(); - - // NOTE: NNS is already recorded in template specialization type T. - return SemaRef.Context.getElaboratedType(Keyword, /*NNS=*/0, T); + + if (Keyword == ETK_None && QualifierLoc.getNestedNameSpecifier() == 0) + return T; + + return SemaRef.Context.getElaboratedType(Keyword, + QualifierLoc.getNestedNameSpecifier(), + T); } /// \brief Build a new typename type that refers to an identifier. @@ -764,23 +793,24 @@ public: /// (or elaborated type). Subclasses may override this routine to provide /// different behavior. QualType RebuildDependentNameType(ElaboratedTypeKeyword Keyword, - NestedNameSpecifier *NNS, - const IdentifierInfo *Id, SourceLocation KeywordLoc, - SourceRange NNSRange, + NestedNameSpecifierLoc QualifierLoc, + const IdentifierInfo *Id, SourceLocation IdLoc) { CXXScopeSpec SS; - SS.MakeTrivial(SemaRef.Context, NNS, NNSRange); + SS.Adopt(QualifierLoc); - if (NNS->isDependent()) { + if (QualifierLoc.getNestedNameSpecifier()->isDependent()) { // If the name is still dependent, just build a new dependent name type. if (!SemaRef.computeDeclContext(SS)) - return SemaRef.Context.getDependentNameType(Keyword, NNS, Id); + return SemaRef.Context.getDependentNameType(Keyword, + QualifierLoc.getNestedNameSpecifier(), + Id); } if (Keyword == ETK_None || Keyword == ETK_Typename) - return SemaRef.CheckTypenameType(Keyword, NNS, *Id, - KeywordLoc, NNSRange, IdLoc); + return SemaRef.CheckTypenameType(Keyword, KeywordLoc, QualifierLoc, + *Id, IdLoc); TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForKeyword(Keyword); @@ -828,7 +858,8 @@ public: NamedDecl *SomeDecl = Result.getRepresentativeDecl(); unsigned Kind = 0; if (isa<TypedefDecl>(SomeDecl)) Kind = 1; - else if (isa<ClassTemplateDecl>(SomeDecl)) Kind = 2; + else if (isa<TypeAliasDecl>(SomeDecl)) Kind = 2; + else if (isa<ClassTemplateDecl>(SomeDecl)) Kind = 3; SemaRef.Diag(IdLoc, diag::err_tag_reference_non_tag) << Kind; SemaRef.Diag(SomeDecl->getLocation(), diag::note_declared_at); break; @@ -850,7 +881,9 @@ public: // Build the elaborated-type-specifier type. QualType T = SemaRef.Context.getTypeDeclType(Tag); - return SemaRef.Context.getElaboratedType(Keyword, NNS, T); + return SemaRef.Context.getElaboratedType(Keyword, + QualifierLoc.getNestedNameSpecifier(), + T); } /// \brief Build a new pack expansion type. @@ -865,56 +898,13 @@ public: NumExpansions); } - /// \brief Build a new nested-name-specifier given the prefix and an - /// identifier that names the next step in the nested-name-specifier. - /// - /// By default, performs semantic analysis when building the new - /// nested-name-specifier. Subclasses may override this routine to provide - /// different behavior. - NestedNameSpecifier *RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix, - SourceRange Range, - IdentifierInfo &II, - QualType ObjectType, - NamedDecl *FirstQualifierInScope); - - /// \brief Build a new nested-name-specifier given the prefix and the - /// namespace named in the next step in the nested-name-specifier. - /// - /// By default, performs semantic analysis when building the new - /// nested-name-specifier. Subclasses may override this routine to provide - /// different behavior. - NestedNameSpecifier *RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix, - SourceRange Range, - NamespaceDecl *NS); - - /// \brief Build a new nested-name-specifier given the prefix and the - /// namespace alias named in the next step in the nested-name-specifier. - /// - /// By default, performs semantic analysis when building the new - /// nested-name-specifier. Subclasses may override this routine to provide - /// different behavior. - NestedNameSpecifier *RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix, - SourceRange Range, - NamespaceAliasDecl *Alias); - - /// \brief Build a new nested-name-specifier given the prefix and the - /// type named in the next step in the nested-name-specifier. - /// - /// By default, performs semantic analysis when building the new - /// nested-name-specifier. Subclasses may override this routine to provide - /// different behavior. - NestedNameSpecifier *RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix, - SourceRange Range, - bool TemplateKW, - QualType T); - /// \brief Build a new template name given a nested name specifier, a flag /// indicating whether the "template" keyword was provided, and the template /// that the template name refers to. /// /// By default, builds the new template name directly. Subclasses may override /// this routine to provide different behavior. - TemplateName RebuildTemplateName(NestedNameSpecifier *Qualifier, + TemplateName RebuildTemplateName(CXXScopeSpec &SS, bool TemplateKW, TemplateDecl *Template); @@ -925,9 +915,9 @@ public: /// be resolved to a specific template, then builds the appropriate kind of /// template name. Subclasses may override this routine to provide different /// behavior. - TemplateName RebuildTemplateName(NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, - const IdentifierInfo &II, + TemplateName RebuildTemplateName(CXXScopeSpec &SS, + const IdentifierInfo &Name, + SourceLocation NameLoc, QualType ObjectType, NamedDecl *FirstQualifierInScope); @@ -938,8 +928,9 @@ public: /// be resolved to a specific template, then builds the appropriate kind of /// template name. Subclasses may override this routine to provide different /// behavior. - TemplateName RebuildTemplateName(NestedNameSpecifier *Qualifier, + TemplateName RebuildTemplateName(CXXScopeSpec &SS, OverloadedOperatorKind Operator, + SourceLocation NameLoc, QualType ObjectType); /// \brief Build a new template name given a template template parameter pack @@ -1147,9 +1138,10 @@ public: /// Subclasses may override this routine to provide different behavior. VarDecl *RebuildObjCExceptionDecl(VarDecl *ExceptionDecl, TypeSourceInfo *TInfo, QualType T) { - return getSema().BuildObjCExceptionDecl(TInfo, T, - ExceptionDecl->getIdentifier(), - ExceptionDecl->getLocation()); + return getSema().BuildObjCExceptionDecl(TInfo, T, + ExceptionDecl->getInnerLocStart(), + ExceptionDecl->getLocation(), + ExceptionDecl->getIdentifier()); } /// \brief Build a new Objective-C @catch statement. @@ -1214,11 +1206,16 @@ public: /// /// By default, performs semantic analysis to build the new decaration. /// Subclasses may override this routine to provide different behavior. - VarDecl *RebuildExceptionDecl(VarDecl *ExceptionDecl, + VarDecl *RebuildExceptionDecl(VarDecl *ExceptionDecl, TypeSourceInfo *Declarator, - IdentifierInfo *Name, - SourceLocation Loc) { - return getSema().BuildExceptionDeclaration(0, Declarator, Name, Loc); + SourceLocation StartLoc, + SourceLocation IdLoc, + IdentifierInfo *Id) { + VarDecl *Var = getSema().BuildExceptionDeclaration(0, Declarator, + StartLoc, IdLoc, Id); + if (Var) + getSema().CurContext->addDecl(Var); + return Var; } /// \brief Build a new C++ catch statement. @@ -1242,6 +1239,46 @@ public: return getSema().ActOnCXXTryBlock(TryLoc, TryBlock, move(Handlers)); } + /// \brief Build a new C++0x range-based for statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + StmtResult RebuildCXXForRangeStmt(SourceLocation ForLoc, + SourceLocation ColonLoc, + Stmt *Range, Stmt *BeginEnd, + Expr *Cond, Expr *Inc, + Stmt *LoopVar, + SourceLocation RParenLoc) { + return getSema().BuildCXXForRangeStmt(ForLoc, ColonLoc, Range, BeginEnd, + Cond, Inc, LoopVar, RParenLoc); + } + + /// \brief Attach body to a C++0x range-based for statement. + /// + /// By default, performs semantic analysis to finish the new statement. + /// Subclasses may override this routine to provide different behavior. + StmtResult FinishCXXForRangeStmt(Stmt *ForRange, Stmt *Body) { + return getSema().FinishCXXForRangeStmt(ForRange, Body); + } + + StmtResult RebuildSEHTryStmt(bool IsCXXTry, + SourceLocation TryLoc, + Stmt *TryBlock, + Stmt *Handler) { + return getSema().ActOnSEHTryBlock(IsCXXTry,TryLoc,TryBlock,Handler); + } + + StmtResult RebuildSEHExceptStmt(SourceLocation Loc, + Expr *FilterExpr, + Stmt *Block) { + return getSema().ActOnSEHExceptBlock(Loc,FilterExpr,Block); + } + + StmtResult RebuildSEHFinallyStmt(SourceLocation Loc, + Stmt *Block) { + return getSema().ActOnSEHFinallyBlock(Loc,Block); + } + /// \brief Build a new expression that references a declaration. /// /// By default, performs semantic analysis to build the new expression. @@ -1257,13 +1294,12 @@ public: /// /// By default, performs semantic analysis to build the new expression. /// Subclasses may override this routine to provide different behavior. - ExprResult RebuildDeclRefExpr(NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + ExprResult RebuildDeclRefExpr(NestedNameSpecifierLoc QualifierLoc, ValueDecl *VD, const DeclarationNameInfo &NameInfo, TemplateArgumentListInfo *TemplateArgs) { CXXScopeSpec SS; - SS.MakeTrivial(SemaRef.Context, Qualifier, QualifierRange); + SS.Adopt(QualifierLoc); // FIXME: loses template args. @@ -1315,25 +1351,28 @@ public: NumComponents, RParenLoc); } - /// \brief Build a new sizeof or alignof expression with a type argument. + /// \brief Build a new sizeof, alignof or vec_step expression with a + /// type argument. /// /// By default, performs semantic analysis to build the new expression. /// Subclasses may override this routine to provide different behavior. - ExprResult RebuildSizeOfAlignOf(TypeSourceInfo *TInfo, - SourceLocation OpLoc, - bool isSizeOf, SourceRange R) { - return getSema().CreateSizeOfAlignOfExpr(TInfo, OpLoc, isSizeOf, R); + ExprResult RebuildUnaryExprOrTypeTrait(TypeSourceInfo *TInfo, + SourceLocation OpLoc, + UnaryExprOrTypeTrait ExprKind, + SourceRange R) { + return getSema().CreateUnaryExprOrTypeTraitExpr(TInfo, OpLoc, ExprKind, R); } - /// \brief Build a new sizeof or alignof expression with an expression - /// argument. + /// \brief Build a new sizeof, alignof or vec step expression with an + /// expression argument. /// /// By default, performs semantic analysis to build the new expression. /// Subclasses may override this routine to provide different behavior. - ExprResult RebuildSizeOfAlignOf(Expr *SubExpr, SourceLocation OpLoc, - bool isSizeOf, SourceRange R) { + ExprResult RebuildUnaryExprOrTypeTrait(Expr *SubExpr, SourceLocation OpLoc, + UnaryExprOrTypeTrait ExprKind, + SourceRange R) { ExprResult Result - = getSema().CreateSizeOfAlignOfExpr(SubExpr, OpLoc, isSizeOf, R); + = getSema().CreateUnaryExprOrTypeTraitExpr(SubExpr, OpLoc, ExprKind, R); if (Result.isInvalid()) return ExprError(); @@ -1371,8 +1410,7 @@ public: /// Subclasses may override this routine to provide different behavior. ExprResult RebuildMemberExpr(Expr *Base, SourceLocation OpLoc, bool isArrow, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &MemberNameInfo, ValueDecl *Member, NamedDecl *FoundDecl, @@ -1382,14 +1420,17 @@ public: // We have a reference to an unnamed field. This is always the // base of an anonymous struct/union member access, i.e. the // field is always of record type. - assert(!Qualifier && "Can't have an unnamed field with a qualifier!"); + assert(!QualifierLoc && "Can't have an unnamed field with a qualifier!"); assert(Member->getType()->isRecordType() && "unnamed member not of record type?"); - if (getSema().PerformObjectMemberConversion(Base, Qualifier, - FoundDecl, Member)) + ExprResult BaseResult = + getSema().PerformObjectMemberConversion(Base, + QualifierLoc.getNestedNameSpecifier(), + FoundDecl, Member); + if (BaseResult.isInvalid()) return ExprError(); - + Base = BaseResult.take(); ExprValueKind VK = isArrow ? VK_LValue : Base->getValueKind(); MemberExpr *ME = new (getSema().Context) MemberExpr(Base, isArrow, @@ -1400,11 +1441,12 @@ public: } CXXScopeSpec SS; - if (Qualifier) { - SS.MakeTrivial(SemaRef.Context, Qualifier, QualifierRange); - } + SS.Adopt(QualifierLoc); - getSema().DefaultFunctionArrayConversion(Base); + ExprResult BaseResult = getSema().DefaultFunctionArrayConversion(Base); + if (BaseResult.isInvalid()) + return ExprError(); + Base = BaseResult.take(); QualType BaseType = Base->getType(); // FIXME: this involves duplicating earlier analysis in a lot of @@ -1586,6 +1628,22 @@ public: RParenLoc); } + /// \brief Build a new generic selection expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildGenericSelectionExpr(SourceLocation KeyLoc, + SourceLocation DefaultLoc, + SourceLocation RParenLoc, + Expr *ControllingExpr, + TypeSourceInfo **Types, + Expr **Exprs, + unsigned NumAssocs) { + return getSema().CreateGenericSelectionExpr(KeyLoc, DefaultLoc, RParenLoc, + ControllingExpr, Types, Exprs, + NumAssocs); + } + /// \brief Build a new overloaded operator call expression. /// /// By default, performs semantic analysis to build the new expression. @@ -1882,6 +1940,29 @@ public: return getSema().BuildBinaryTypeTrait(Trait, StartLoc, LhsT, RhsT, RParenLoc); } + /// \brief Build a new array type trait expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildArrayTypeTrait(ArrayTypeTrait Trait, + SourceLocation StartLoc, + TypeSourceInfo *TSInfo, + Expr *DimExpr, + SourceLocation RParenLoc) { + return getSema().BuildArrayTypeTrait(Trait, StartLoc, TSInfo, DimExpr, RParenLoc); + } + + /// \brief Build a new expression trait expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildExpressionTrait(ExpressionTrait Trait, + SourceLocation StartLoc, + Expr *Queried, + SourceLocation RParenLoc) { + return getSema().BuildExpressionTrait(Trait, StartLoc, Queried, RParenLoc); + } + /// \brief Build a new (previously unresolved) declaration reference /// expression. /// @@ -1968,16 +2049,15 @@ public: /// By default, performs semantic analysis to build the new expression. /// Subclasses may override this routine to provide different behavior. ExprResult RebuildCXXDependentScopeMemberExpr(Expr *BaseE, - QualType BaseType, - bool IsArrow, - SourceLocation OperatorLoc, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + QualType BaseType, + bool IsArrow, + SourceLocation OperatorLoc, + NestedNameSpecifierLoc QualifierLoc, NamedDecl *FirstQualifierInScope, const DeclarationNameInfo &MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs) { CXXScopeSpec SS; - SS.MakeTrivial(SemaRef.Context, Qualifier, QualifierRange); + SS.Adopt(QualifierLoc); return SemaRef.BuildMemberReferenceExpr(BaseE, BaseType, OperatorLoc, IsArrow, @@ -1994,13 +2074,12 @@ public: QualType BaseType, SourceLocation OperatorLoc, bool IsArrow, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, NamedDecl *FirstQualifierInScope, LookupResult &R, const TemplateArgumentListInfo *TemplateArgs) { CXXScopeSpec SS; - SS.MakeTrivial(SemaRef.Context, Qualifier, QualifierRange); + SS.Adopt(QualifierLoc); return SemaRef.BuildMemberReferenceExpr(BaseE, BaseType, OperatorLoc, IsArrow, @@ -2076,20 +2155,20 @@ public: bool IsArrow, bool IsFreeIvar) { // FIXME: We lose track of the IsFreeIvar bit. CXXScopeSpec SS; - Expr *Base = BaseArg; + ExprResult Base = getSema().Owned(BaseArg); LookupResult R(getSema(), Ivar->getDeclName(), IvarLoc, Sema::LookupMemberName); ExprResult Result = getSema().LookupMemberExpr(R, Base, IsArrow, /*FIME:*/IvarLoc, SS, 0, false); - if (Result.isInvalid()) + if (Result.isInvalid() || Base.isInvalid()) return ExprError(); if (Result.get()) return move(Result); - return getSema().BuildMemberReferenceExpr(Base, Base->getType(), + return getSema().BuildMemberReferenceExpr(Base.get(), Base.get()->getType(), /*FIXME:*/IvarLoc, IsArrow, SS, /*FirstQualifierInScope=*/0, R, @@ -2104,20 +2183,20 @@ public: ObjCPropertyDecl *Property, SourceLocation PropertyLoc) { CXXScopeSpec SS; - Expr *Base = BaseArg; + ExprResult Base = getSema().Owned(BaseArg); LookupResult R(getSema(), Property->getDeclName(), PropertyLoc, Sema::LookupMemberName); bool IsArrow = false; ExprResult Result = getSema().LookupMemberExpr(R, Base, IsArrow, /*FIME:*/PropertyLoc, SS, 0, false); - if (Result.isInvalid()) + if (Result.isInvalid() || Base.isInvalid()) return ExprError(); if (Result.get()) return move(Result); - return getSema().BuildMemberReferenceExpr(Base, Base->getType(), + return getSema().BuildMemberReferenceExpr(Base.get(), Base.get()->getType(), /*FIXME:*/PropertyLoc, IsArrow, SS, /*FirstQualifierInScope=*/0, @@ -2148,19 +2227,19 @@ public: ExprResult RebuildObjCIsaExpr(Expr *BaseArg, SourceLocation IsaLoc, bool IsArrow) { CXXScopeSpec SS; - Expr *Base = BaseArg; + ExprResult Base = getSema().Owned(BaseArg); LookupResult R(getSema(), &getSema().Context.Idents.get("isa"), IsaLoc, Sema::LookupMemberName); ExprResult Result = getSema().LookupMemberExpr(R, Base, IsArrow, /*FIME:*/IsaLoc, SS, 0, false); - if (Result.isInvalid()) + if (Result.isInvalid() || Base.isInvalid()) return ExprError(); if (Result.get()) return move(Result); - return getSema().BuildMemberReferenceExpr(Base, Base->getType(), + return getSema().BuildMemberReferenceExpr(Base.get(), Base.get()->getType(), /*FIXME:*/IsaLoc, IsArrow, SS, /*FirstQualifierInScope=*/0, R, @@ -2183,28 +2262,25 @@ public: // Build a reference to the __builtin_shufflevector builtin FunctionDecl *Builtin = cast<FunctionDecl>(*Lookup.first); - Expr *Callee - = new (SemaRef.Context) DeclRefExpr(Builtin, Builtin->getType(), - VK_LValue, BuiltinLoc); - SemaRef.UsualUnaryConversions(Callee); + ExprResult Callee + = SemaRef.Owned(new (SemaRef.Context) DeclRefExpr(Builtin, Builtin->getType(), + VK_LValue, BuiltinLoc)); + Callee = SemaRef.UsualUnaryConversions(Callee.take()); + if (Callee.isInvalid()) + return ExprError(); // Build the CallExpr unsigned NumSubExprs = SubExprs.size(); Expr **Subs = (Expr **)SubExprs.release(); - CallExpr *TheCall = new (SemaRef.Context) CallExpr(SemaRef.Context, Callee, + ExprResult TheCall = SemaRef.Owned( + new (SemaRef.Context) CallExpr(SemaRef.Context, Callee.take(), Subs, NumSubExprs, Builtin->getCallResultType(), Expr::getValueKindForType(Builtin->getResultType()), - RParenLoc); - ExprResult OwnedCall(SemaRef.Owned(TheCall)); + RParenLoc)); // Type-check the __builtin_shufflevector expression. - ExprResult Result = SemaRef.SemaBuiltinShuffleVector(TheCall); - if (Result.isInvalid()) - return ExprError(); - - OwnedCall.release(); - return move(Result); + return SemaRef.SemaBuiltinShuffleVector(cast<CallExpr>(TheCall.take())); } /// \brief Build a new template argument pack expansion. @@ -2230,7 +2306,7 @@ public: return TemplateArgumentLoc(TemplateArgument( Pattern.getArgument().getAsTemplate(), NumExpansions), - Pattern.getTemplateQualifierRange(), + Pattern.getTemplateQualifierLoc(), Pattern.getTemplateNameLoc(), EllipsisLoc); @@ -2265,20 +2341,15 @@ public: } private: - QualType TransformTypeInObjectScope(QualType T, - QualType ObjectType, - NamedDecl *FirstQualifierInScope, - NestedNameSpecifier *Prefix); - - TypeSourceInfo *TransformTypeInObjectScope(TypeSourceInfo *T, - QualType ObjectType, - NamedDecl *FirstQualifierInScope, - NestedNameSpecifier *Prefix); - TypeLoc TransformTypeInObjectScope(TypeLoc TL, QualType ObjectType, NamedDecl *FirstQualifierInScope, CXXScopeSpec &SS); + + TypeSourceInfo *TransformTypeInObjectScope(TypeSourceInfo *TSInfo, + QualType ObjectType, + NamedDecl *FirstQualifierInScope, + CXXScopeSpec &SS); }; template<typename Derived> @@ -2426,99 +2497,6 @@ bool TreeTransform<Derived>::TransformExprs(Expr **Inputs, } template<typename Derived> -NestedNameSpecifier * -TreeTransform<Derived>::TransformNestedNameSpecifier(NestedNameSpecifier *NNS, - SourceRange Range, - QualType ObjectType, - NamedDecl *FirstQualifierInScope) { - NestedNameSpecifier *Prefix = NNS->getPrefix(); - - // Transform the prefix of this nested name specifier. - if (Prefix) { - Prefix = getDerived().TransformNestedNameSpecifier(Prefix, Range, - ObjectType, - FirstQualifierInScope); - if (!Prefix) - return 0; - } - - switch (NNS->getKind()) { - case NestedNameSpecifier::Identifier: - if (Prefix) { - // The object type and qualifier-in-scope really apply to the - // leftmost entity. - ObjectType = QualType(); - FirstQualifierInScope = 0; - } - - assert((Prefix || !ObjectType.isNull()) && - "Identifier nested-name-specifier with no prefix or object type"); - if (!getDerived().AlwaysRebuild() && Prefix == NNS->getPrefix() && - ObjectType.isNull()) - return NNS; - - return getDerived().RebuildNestedNameSpecifier(Prefix, Range, - *NNS->getAsIdentifier(), - ObjectType, - FirstQualifierInScope); - - case NestedNameSpecifier::Namespace: { - NamespaceDecl *NS - = cast_or_null<NamespaceDecl>( - getDerived().TransformDecl(Range.getBegin(), - NNS->getAsNamespace())); - if (!getDerived().AlwaysRebuild() && - Prefix == NNS->getPrefix() && - NS == NNS->getAsNamespace()) - return NNS; - - return getDerived().RebuildNestedNameSpecifier(Prefix, Range, NS); - } - - case NestedNameSpecifier::NamespaceAlias: { - NamespaceAliasDecl *Alias - = cast_or_null<NamespaceAliasDecl>( - getDerived().TransformDecl(Range.getBegin(), - NNS->getAsNamespaceAlias())); - if (!getDerived().AlwaysRebuild() && - Prefix == NNS->getPrefix() && - Alias == NNS->getAsNamespaceAlias()) - return NNS; - - return getDerived().RebuildNestedNameSpecifier(Prefix, Range, Alias); - } - - case NestedNameSpecifier::Global: - // There is no meaningful transformation that one could perform on the - // global scope. - return NNS; - - case NestedNameSpecifier::TypeSpecWithTemplate: - case NestedNameSpecifier::TypeSpec: { - TemporaryBase Rebase(*this, Range.getBegin(), DeclarationName()); - QualType T = TransformTypeInObjectScope(QualType(NNS->getAsType(), 0), - ObjectType, - FirstQualifierInScope, - Prefix); - if (T.isNull()) - return 0; - - if (!getDerived().AlwaysRebuild() && - Prefix == NNS->getPrefix() && - T == QualType(NNS->getAsType(), 0)) - return NNS; - - return getDerived().RebuildNestedNameSpecifier(Prefix, Range, - NNS->getKind() == NestedNameSpecifier::TypeSpecWithTemplate, - T); - } - } - - // Required to silence a GCC warning - return 0; -} - -template<typename Derived> NestedNameSpecifierLoc TreeTransform<Derived>::TransformNestedNameSpecifierLoc( NestedNameSpecifierLoc NNS, @@ -2594,10 +2572,11 @@ TreeTransform<Derived>::TransformNestedNameSpecifierLoc( << TL.getType() << SS.getRange(); return NestedNameSpecifierLoc(); } - } + } - // The qualifier-in-scope only applies to the leftmost entity. + // The qualifier-in-scope and object type only apply to the leftmost entity. FirstQualifierInScope = 0; + ObjectType = QualType(); } // Don't rebuild the nested-name-specifier if we don't have to. @@ -2669,89 +2648,73 @@ TreeTransform<Derived> template<typename Derived> TemplateName -TreeTransform<Derived>::TransformTemplateName(TemplateName Name, +TreeTransform<Derived>::TransformTemplateName(CXXScopeSpec &SS, + TemplateName Name, + SourceLocation NameLoc, QualType ObjectType, NamedDecl *FirstQualifierInScope) { - SourceLocation Loc = getDerived().getBaseLocation(); - if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) { - NestedNameSpecifier *NNS - = getDerived().TransformNestedNameSpecifier(QTN->getQualifier(), - /*FIXME*/ SourceRange(Loc), - ObjectType, - FirstQualifierInScope); - if (!NNS) + TemplateDecl *Template = QTN->getTemplateDecl(); + assert(Template && "qualified template name must refer to a template"); + + TemplateDecl *TransTemplate + = cast_or_null<TemplateDecl>(getDerived().TransformDecl(NameLoc, + Template)); + if (!TransTemplate) return TemplateName(); - - if (TemplateDecl *Template = QTN->getTemplateDecl()) { - TemplateDecl *TransTemplate - = cast_or_null<TemplateDecl>(getDerived().TransformDecl(Loc, Template)); - if (!TransTemplate) - return TemplateName(); - - if (!getDerived().AlwaysRebuild() && - NNS == QTN->getQualifier() && - TransTemplate == Template) - return Name; - - return getDerived().RebuildTemplateName(NNS, QTN->hasTemplateKeyword(), - TransTemplate); - } - - // These should be getting filtered out before they make it into the AST. - llvm_unreachable("overloaded template name survived to here"); + + if (!getDerived().AlwaysRebuild() && + SS.getScopeRep() == QTN->getQualifier() && + TransTemplate == Template) + return Name; + + return getDerived().RebuildTemplateName(SS, QTN->hasTemplateKeyword(), + TransTemplate); } - + if (DependentTemplateName *DTN = Name.getAsDependentTemplateName()) { - NestedNameSpecifier *NNS = DTN->getQualifier(); - if (NNS) { - NNS = getDerived().TransformNestedNameSpecifier(NNS, - /*FIXME:*/SourceRange(Loc), - ObjectType, - FirstQualifierInScope); - if (!NNS) return TemplateName(); - + if (SS.getScopeRep()) { // These apply to the scope specifier, not the template. ObjectType = QualType(); FirstQualifierInScope = 0; - } - + } + if (!getDerived().AlwaysRebuild() && - NNS == DTN->getQualifier() && + SS.getScopeRep() == DTN->getQualifier() && ObjectType.isNull()) return Name; - + if (DTN->isIdentifier()) { - // FIXME: Bad range - SourceRange QualifierRange(getDerived().getBaseLocation()); - return getDerived().RebuildTemplateName(NNS, QualifierRange, + return getDerived().RebuildTemplateName(SS, *DTN->getIdentifier(), + NameLoc, ObjectType, FirstQualifierInScope); } - return getDerived().RebuildTemplateName(NNS, DTN->getOperator(), + return getDerived().RebuildTemplateName(SS, DTN->getOperator(), NameLoc, ObjectType); } - + if (TemplateDecl *Template = Name.getAsTemplateDecl()) { TemplateDecl *TransTemplate - = cast_or_null<TemplateDecl>(getDerived().TransformDecl(Loc, Template)); + = cast_or_null<TemplateDecl>(getDerived().TransformDecl(NameLoc, + Template)); if (!TransTemplate) return TemplateName(); - + if (!getDerived().AlwaysRebuild() && TransTemplate == Template) return Name; - + return TemplateName(TransTemplate); } - + if (SubstTemplateTemplateParmPackStorage *SubstPack - = Name.getAsSubstTemplateTemplateParmPack()) { + = Name.getAsSubstTemplateTemplateParmPack()) { TemplateTemplateParmDecl *TransParam - = cast_or_null<TemplateTemplateParmDecl>( - getDerived().TransformDecl(Loc, SubstPack->getParameterPack())); + = cast_or_null<TemplateTemplateParmDecl>( + getDerived().TransformDecl(NameLoc, SubstPack->getParameterPack())); if (!TransParam) return TemplateName(); @@ -2785,12 +2748,25 @@ void TreeTransform<Derived>::InventTemplateArgumentLoc( break; case TemplateArgument::Template: - Output = TemplateArgumentLoc(Arg, SourceRange(), Loc); - break; - - case TemplateArgument::TemplateExpansion: - Output = TemplateArgumentLoc(Arg, SourceRange(), Loc, Loc); + case TemplateArgument::TemplateExpansion: { + NestedNameSpecifierLocBuilder Builder; + TemplateName Template = Arg.getAsTemplate(); + if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) + Builder.MakeTrivial(SemaRef.Context, DTN->getQualifier(), Loc); + else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) + Builder.MakeTrivial(SemaRef.Context, QTN->getQualifier(), Loc); + + if (Arg.getKind() == TemplateArgument::Template) + Output = TemplateArgumentLoc(Arg, + Builder.getWithLocInContext(SemaRef.Context), + Loc); + else + Output = TemplateArgumentLoc(Arg, + Builder.getWithLocInContext(SemaRef.Context), + Loc, Loc); + break; + } case TemplateArgument::Expression: Output = TemplateArgumentLoc(Arg, Arg.getAsExpr()); @@ -2849,14 +2825,22 @@ bool TreeTransform<Derived>::TransformTemplateArgument( } case TemplateArgument::Template: { - TemporaryBase Rebase(*this, Input.getLocation(), DeclarationName()); + NestedNameSpecifierLoc QualifierLoc = Input.getTemplateQualifierLoc(); + if (QualifierLoc) { + QualifierLoc = getDerived().TransformNestedNameSpecifierLoc(QualifierLoc); + if (!QualifierLoc) + return true; + } + + CXXScopeSpec SS; + SS.Adopt(QualifierLoc); TemplateName Template - = getDerived().TransformTemplateName(Arg.getAsTemplate()); + = getDerived().TransformTemplateName(SS, Arg.getAsTemplate(), + Input.getTemplateNameLoc()); if (Template.isNull()) return true; - Output = TemplateArgumentLoc(TemplateArgument(Template), - Input.getTemplateQualifierRange(), + Output = TemplateArgumentLoc(TemplateArgument(Template), QualifierLoc, Input.getTemplateNameLoc()); return false; } @@ -2872,8 +2856,7 @@ bool TreeTransform<Derived>::TransformTemplateArgument( Expr *InputExpr = Input.getSourceExpression(); if (!InputExpr) InputExpr = Input.getArgument().getAsExpr(); - ExprResult E - = getDerived().TransformExpr(InputExpr); + ExprResult E = getDerived().TransformExpr(InputExpr); if (E.isInvalid()) return true; Output = TemplateArgumentLoc(TemplateArgument(E.take()), E.take()); return false; @@ -3177,112 +3160,87 @@ TreeTransform<Derived>::TransformQualifiedType(TypeLocBuilder &TLB, return Result; } -/// \brief Transforms a type that was written in a scope specifier, -/// given an object type, the results of unqualified lookup, and -/// an already-instantiated prefix. -/// -/// The object type is provided iff the scope specifier qualifies the -/// member of a dependent member-access expression. The prefix is -/// provided iff the the scope specifier in which this appears has a -/// prefix. -/// -/// This is private to TreeTransform. template<typename Derived> -QualType -TreeTransform<Derived>::TransformTypeInObjectScope(QualType T, - QualType ObjectType, - NamedDecl *UnqualLookup, - NestedNameSpecifier *Prefix) { - if (getDerived().AlreadyTransformed(T)) - return T; - - TypeSourceInfo *TSI = - SemaRef.Context.getTrivialTypeSourceInfo(T, getDerived().getBaseLocation()); - - TSI = getDerived().TransformTypeInObjectScope(TSI, ObjectType, - UnqualLookup, Prefix); - if (!TSI) return QualType(); - return TSI->getType(); -} - -template<typename Derived> -TypeSourceInfo * -TreeTransform<Derived>::TransformTypeInObjectScope(TypeSourceInfo *TSI, +TypeLoc +TreeTransform<Derived>::TransformTypeInObjectScope(TypeLoc TL, QualType ObjectType, NamedDecl *UnqualLookup, - NestedNameSpecifier *Prefix) { - // TODO: in some cases, we might have some verification to do here. - if (ObjectType.isNull()) - return getDerived().TransformType(TSI); - - QualType T = TSI->getType(); + CXXScopeSpec &SS) { + QualType T = TL.getType(); if (getDerived().AlreadyTransformed(T)) - return TSI; - + return TL; + TypeLocBuilder TLB; QualType Result; - + if (isa<TemplateSpecializationType>(T)) { - TemplateSpecializationTypeLoc TL - = cast<TemplateSpecializationTypeLoc>(TSI->getTypeLoc()); - + TemplateSpecializationTypeLoc SpecTL + = cast<TemplateSpecializationTypeLoc>(TL); + TemplateName Template = - getDerived().TransformTemplateName(TL.getTypePtr()->getTemplateName(), + getDerived().TransformTemplateName(SS, + SpecTL.getTypePtr()->getTemplateName(), + SpecTL.getTemplateNameLoc(), ObjectType, UnqualLookup); - if (Template.isNull()) return 0; - - Result = getDerived() - .TransformTemplateSpecializationType(TLB, TL, Template); + if (Template.isNull()) + return TypeLoc(); + + Result = getDerived().TransformTemplateSpecializationType(TLB, SpecTL, + Template); } else if (isa<DependentTemplateSpecializationType>(T)) { - DependentTemplateSpecializationTypeLoc TL - = cast<DependentTemplateSpecializationTypeLoc>(TSI->getTypeLoc()); - - Result = getDerived() - .TransformDependentTemplateSpecializationType(TLB, TL, Prefix); + DependentTemplateSpecializationTypeLoc SpecTL + = cast<DependentTemplateSpecializationTypeLoc>(TL); + + TemplateName Template + = getDerived().RebuildTemplateName(SS, + *SpecTL.getTypePtr()->getIdentifier(), + SpecTL.getNameLoc(), + ObjectType, UnqualLookup); + if (Template.isNull()) + return TypeLoc(); + + Result = getDerived().TransformDependentTemplateSpecializationType(TLB, + SpecTL, + Template, + SS); } else { // Nothing special needs to be done for these. - Result = getDerived().TransformType(TLB, TSI->getTypeLoc()); + Result = getDerived().TransformType(TLB, TL); } - - if (Result.isNull()) return 0; - return TLB.getTypeSourceInfo(SemaRef.Context, Result); + + if (Result.isNull()) + return TypeLoc(); + + return TLB.getTypeSourceInfo(SemaRef.Context, Result)->getTypeLoc(); } template<typename Derived> -TypeLoc -TreeTransform<Derived>::TransformTypeInObjectScope(TypeLoc TL, +TypeSourceInfo * +TreeTransform<Derived>::TransformTypeInObjectScope(TypeSourceInfo *TSInfo, QualType ObjectType, NamedDecl *UnqualLookup, CXXScopeSpec &SS) { // FIXME: Painfully copy-paste from the above! - // TODO: in some cases, we might have some verification to do here. - if (ObjectType.isNull()) { - TypeLocBuilder TLB; - TLB.reserve(TL.getFullDataSize()); - QualType Result = getDerived().TransformType(TLB, TL); - if (Result.isNull()) - return TypeLoc(); - - return TLB.getTypeSourceInfo(SemaRef.Context, Result)->getTypeLoc(); - } - - QualType T = TL.getType(); + QualType T = TSInfo->getType(); if (getDerived().AlreadyTransformed(T)) - return TL; + return TSInfo; TypeLocBuilder TLB; QualType Result; + TypeLoc TL = TSInfo->getTypeLoc(); if (isa<TemplateSpecializationType>(T)) { TemplateSpecializationTypeLoc SpecTL = cast<TemplateSpecializationTypeLoc>(TL); - TemplateName Template = - getDerived().TransformTemplateName(SpecTL.getTypePtr()->getTemplateName(), + TemplateName Template + = getDerived().TransformTemplateName(SS, + SpecTL.getTypePtr()->getTemplateName(), + SpecTL.getTemplateNameLoc(), ObjectType, UnqualLookup); if (Template.isNull()) - return TypeLoc(); + return 0; Result = getDerived().TransformTemplateSpecializationType(TLB, SpecTL, Template); @@ -3290,18 +3248,27 @@ TreeTransform<Derived>::TransformTypeInObjectScope(TypeLoc TL, DependentTemplateSpecializationTypeLoc SpecTL = cast<DependentTemplateSpecializationTypeLoc>(TL); + TemplateName Template + = getDerived().RebuildTemplateName(SS, + *SpecTL.getTypePtr()->getIdentifier(), + SpecTL.getNameLoc(), + ObjectType, UnqualLookup); + if (Template.isNull()) + return 0; + Result = getDerived().TransformDependentTemplateSpecializationType(TLB, - SpecTL, - SS.getScopeRep()); + SpecTL, + Template, + SS); } else { // Nothing special needs to be done for these. Result = getDerived().TransformType(TLB, TL); } if (Result.isNull()) - return TypeLoc(); + return 0; - return TLB.getTypeSourceInfo(SemaRef.Context, Result)->getTypeLoc(); + return TLB.getTypeSourceInfo(SemaRef.Context, Result); } template <class TyLoc> static inline @@ -3438,23 +3405,34 @@ template<typename Derived> QualType TreeTransform<Derived>::TransformMemberPointerType(TypeLocBuilder &TLB, MemberPointerTypeLoc TL) { - const MemberPointerType *T = TL.getTypePtr(); - QualType PointeeType = getDerived().TransformType(TLB, TL.getPointeeLoc()); if (PointeeType.isNull()) return QualType(); - // TODO: preserve source information for this. - QualType ClassType - = getDerived().TransformType(QualType(T->getClass(), 0)); - if (ClassType.isNull()) - return QualType(); + TypeSourceInfo* OldClsTInfo = TL.getClassTInfo(); + TypeSourceInfo* NewClsTInfo = 0; + if (OldClsTInfo) { + NewClsTInfo = getDerived().TransformType(OldClsTInfo); + if (!NewClsTInfo) + return QualType(); + } + + const MemberPointerType *T = TL.getTypePtr(); + QualType OldClsType = QualType(T->getClass(), 0); + QualType NewClsType; + if (NewClsTInfo) + NewClsType = NewClsTInfo->getType(); + else { + NewClsType = getDerived().TransformType(OldClsType); + if (NewClsType.isNull()) + return QualType(); + } QualType Result = TL.getType(); if (getDerived().AlwaysRebuild() || PointeeType != T->getPointeeType() || - ClassType != QualType(T->getClass(), 0)) { - Result = getDerived().RebuildMemberPointerType(PointeeType, ClassType, + NewClsType != OldClsType) { + Result = getDerived().RebuildMemberPointerType(PointeeType, NewClsType, TL.getStarLoc()); if (Result.isNull()) return QualType(); @@ -3462,6 +3440,7 @@ TreeTransform<Derived>::TransformMemberPointerType(TypeLocBuilder &TLB, MemberPointerTypeLoc NewTL = TLB.push<MemberPointerTypeLoc>(Result); NewTL.setSigilLoc(TL.getSigilLoc()); + NewTL.setClassTInfo(NewClsTInfo); return Result; } @@ -3707,6 +3686,7 @@ QualType TreeTransform<Derived>::TransformExtVectorType(TypeLocBuilder &TLB, template<typename Derived> ParmVarDecl * TreeTransform<Derived>::TransformFunctionTypeParam(ParmVarDecl *OldParm, + int indexAdjustment, llvm::Optional<unsigned> NumExpansions) { TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo(); TypeSourceInfo *NewDI = 0; @@ -3741,18 +3721,22 @@ TreeTransform<Derived>::TransformFunctionTypeParam(ParmVarDecl *OldParm, if (!NewDI) return 0; - if (NewDI == OldDI) + if (NewDI == OldDI && indexAdjustment == 0) return OldParm; - else - return ParmVarDecl::Create(SemaRef.Context, - OldParm->getDeclContext(), - OldParm->getLocation(), - OldParm->getIdentifier(), - NewDI->getType(), - NewDI, - OldParm->getStorageClass(), - OldParm->getStorageClassAsWritten(), - /* DefArg */ NULL); + + ParmVarDecl *newParm = ParmVarDecl::Create(SemaRef.Context, + OldParm->getDeclContext(), + OldParm->getInnerLocStart(), + OldParm->getLocation(), + OldParm->getIdentifier(), + NewDI->getType(), + NewDI, + OldParm->getStorageClass(), + OldParm->getStorageClassAsWritten(), + /* DefArg */ NULL); + newParm->setScopeInfo(OldParm->getFunctionScopeDepth(), + OldParm->getFunctionScopeIndex() + indexAdjustment); + return newParm; } template<typename Derived> @@ -3762,9 +3746,14 @@ bool TreeTransform<Derived>:: const QualType *ParamTypes, llvm::SmallVectorImpl<QualType> &OutParamTypes, llvm::SmallVectorImpl<ParmVarDecl*> *PVars) { + int indexAdjustment = 0; + for (unsigned i = 0; i != NumParams; ++i) { if (ParmVarDecl *OldParm = Params[i]) { + assert(OldParm->getFunctionScopeIndex() == i); + llvm::Optional<unsigned> NumExpansions; + ParmVarDecl *NewParm = 0; if (OldParm->isParameterPack()) { // We have a function parameter pack that may need to be expanded. llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded; @@ -3774,7 +3763,8 @@ bool TreeTransform<Derived>:: PackExpansionTypeLoc ExpansionTL = cast<PackExpansionTypeLoc>(TL); TypeLoc Pattern = ExpansionTL.getPatternLoc(); SemaRef.collectUnexpandedParameterPacks(Pattern, Unexpanded); - + assert(Unexpanded.size() > 0 && "Could not find parameter packs!"); + // Determine whether we should expand the parameter packs. bool ShouldExpand = false; bool RetainExpansion = false; @@ -3799,6 +3789,7 @@ bool TreeTransform<Derived>:: Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I); ParmVarDecl *NewParm = getDerived().TransformFunctionTypeParam(OldParm, + indexAdjustment++, OrigNumExpansions); if (!NewParm) return true; @@ -3814,6 +3805,7 @@ bool TreeTransform<Derived>:: ForgetPartiallySubstitutedPackRAII Forget(getDerived()); ParmVarDecl *NewParm = getDerived().TransformFunctionTypeParam(OldParm, + indexAdjustment++, OrigNumExpansions); if (!NewParm) return true; @@ -3823,17 +3815,28 @@ bool TreeTransform<Derived>:: PVars->push_back(NewParm); } + // The next parameter should have the same adjustment as the + // last thing we pushed, but we post-incremented indexAdjustment + // on every push. Also, if we push nothing, the adjustment should + // go down by one. + indexAdjustment--; + // We're done with the pack expansion. continue; } // We'll substitute the parameter now without expanding the pack // expansion. + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1); + NewParm = getDerived().TransformFunctionTypeParam(OldParm, + indexAdjustment, + NumExpansions); + } else { + NewParm = getDerived().TransformFunctionTypeParam(OldParm, + indexAdjustment, + llvm::Optional<unsigned>()); } - - Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1); - ParmVarDecl *NewParm = getDerived().TransformFunctionTypeParam(OldParm, - NumExpansions); + if (!NewParm) return true; @@ -3848,6 +3851,7 @@ bool TreeTransform<Derived>:: QualType OldType = ParamTypes[i]; bool IsPackExpansion = false; llvm::Optional<unsigned> NumExpansions; + QualType NewType; if (const PackExpansionType *Expansion = dyn_cast<PackExpansionType>(OldType)) { // We have a function parameter pack that may need to be expanded. @@ -3902,10 +3906,12 @@ bool TreeTransform<Derived>:: // expansion. OldType = Expansion->getPattern(); IsPackExpansion = true; + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1); + NewType = getDerived().TransformType(OldType); + } else { + NewType = getDerived().TransformType(OldType); } - Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1); - QualType NewType = getDerived().TransformType(OldType); if (NewType.isNull()) return true; @@ -3918,8 +3924,16 @@ bool TreeTransform<Derived>:: PVars->push_back(0); } - return false; +#ifndef NDEBUG + if (PVars) { + for (unsigned i = 0, e = PVars->size(); i != e; ++i) + if (ParmVarDecl *parm = (*PVars)[i]) + assert(parm->getFunctionScopeIndex() == i); } +#endif + + return false; +} template<typename Derived> QualType @@ -3983,8 +3997,8 @@ TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB, } FunctionProtoTypeLoc NewTL = TLB.push<FunctionProtoTypeLoc>(Result); - NewTL.setLParenLoc(TL.getLParenLoc()); - NewTL.setRParenLoc(TL.getRParenLoc()); + NewTL.setLocalRangeBegin(TL.getLocalRangeBegin()); + NewTL.setLocalRangeEnd(TL.getLocalRangeEnd()); NewTL.setTrailingReturn(TL.getTrailingReturn()); for (unsigned i = 0, e = NewTL.getNumArgs(); i != e; ++i) NewTL.setArg(i, ParamDecls[i]); @@ -4007,8 +4021,8 @@ QualType TreeTransform<Derived>::TransformFunctionNoProtoType( Result = getDerived().RebuildFunctionNoProtoType(ResultType); FunctionNoProtoTypeLoc NewTL = TLB.push<FunctionNoProtoTypeLoc>(Result); - NewTL.setLParenLoc(TL.getLParenLoc()); - NewTL.setRParenLoc(TL.getRParenLoc()); + NewTL.setLocalRangeBegin(TL.getLocalRangeBegin()); + NewTL.setLocalRangeEnd(TL.getLocalRangeEnd()); NewTL.setTrailingReturn(false); return Result; @@ -4041,9 +4055,9 @@ template<typename Derived> QualType TreeTransform<Derived>::TransformTypedefType(TypeLocBuilder &TLB, TypedefTypeLoc TL) { const TypedefType *T = TL.getTypePtr(); - TypedefDecl *Typedef - = cast_or_null<TypedefDecl>(getDerived().TransformDecl(TL.getNameLoc(), - T->getDecl())); + TypedefNameDecl *Typedef + = cast_or_null<TypedefNameDecl>(getDerived().TransformDecl(TL.getNameLoc(), + T->getDecl())); if (!Typedef) return QualType(); @@ -4236,7 +4250,28 @@ template<typename Derived> QualType TreeTransform<Derived>::TransformSubstTemplateTypeParmType( TypeLocBuilder &TLB, SubstTemplateTypeParmTypeLoc TL) { - return TransformTypeSpecType(TLB, TL); + const SubstTemplateTypeParmType *T = TL.getTypePtr(); + + // Substitute into the replacement type, which itself might involve something + // that needs to be transformed. This only tends to occur with default + // template arguments of template template parameters. + TemporaryBase Rebase(*this, TL.getNameLoc(), DeclarationName()); + QualType Replacement = getDerived().TransformType(T->getReplacementType()); + if (Replacement.isNull()) + return QualType(); + + // Always canonicalize the replacement type. + Replacement = SemaRef.Context.getCanonicalType(Replacement); + QualType Result + = SemaRef.Context.getSubstTemplateTypeParmType(T->getReplacedParameter(), + Replacement); + + // Propagate type-source information. + SubstTemplateTypeParmTypeLoc NewTL + = TLB.push<SubstTemplateTypeParmTypeLoc>(Result); + NewTL.setNameLoc(TL.getNameLoc()); + return Result; + } template<typename Derived> @@ -4252,8 +4287,12 @@ QualType TreeTransform<Derived>::TransformTemplateSpecializationType( TemplateSpecializationTypeLoc TL) { const TemplateSpecializationType *T = TL.getTypePtr(); + // The nested-name-specifier never matters in a TemplateSpecializationType, + // because we can't have a dependent nested-name-specifier anyway. + CXXScopeSpec SS; TemplateName Template - = getDerived().TransformTemplateName(T->getTemplateName()); + = getDerived().TransformTemplateName(SS, T->getTemplateName(), + TL.getTemplateNameLoc()); if (Template.isNull()) return QualType(); @@ -4362,18 +4401,76 @@ QualType TreeTransform<Derived>::TransformTemplateSpecializationType( return Result; } +template <typename Derived> +QualType TreeTransform<Derived>::TransformDependentTemplateSpecializationType( + TypeLocBuilder &TLB, + DependentTemplateSpecializationTypeLoc TL, + TemplateName Template, + CXXScopeSpec &SS) { + TemplateArgumentListInfo NewTemplateArgs; + NewTemplateArgs.setLAngleLoc(TL.getLAngleLoc()); + NewTemplateArgs.setRAngleLoc(TL.getRAngleLoc()); + typedef TemplateArgumentLocContainerIterator< + DependentTemplateSpecializationTypeLoc> ArgIterator; + if (getDerived().TransformTemplateArguments(ArgIterator(TL, 0), + ArgIterator(TL, TL.getNumArgs()), + NewTemplateArgs)) + return QualType(); + + // FIXME: maybe don't rebuild if all the template arguments are the same. + + if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) { + QualType Result + = getSema().Context.getDependentTemplateSpecializationType( + TL.getTypePtr()->getKeyword(), + DTN->getQualifier(), + DTN->getIdentifier(), + NewTemplateArgs); + + DependentTemplateSpecializationTypeLoc NewTL + = TLB.push<DependentTemplateSpecializationTypeLoc>(Result); + NewTL.setKeywordLoc(TL.getKeywordLoc()); + + NewTL.setQualifierLoc(SS.getWithLocInContext(SemaRef.Context)); + NewTL.setNameLoc(TL.getNameLoc()); + NewTL.setLAngleLoc(TL.getLAngleLoc()); + NewTL.setRAngleLoc(TL.getRAngleLoc()); + for (unsigned i = 0, e = NewTemplateArgs.size(); i != e; ++i) + NewTL.setArgLocInfo(i, NewTemplateArgs[i].getLocInfo()); + return Result; + } + + QualType Result + = getDerived().RebuildTemplateSpecializationType(Template, + TL.getNameLoc(), + NewTemplateArgs); + + if (!Result.isNull()) { + /// FIXME: Wrap this in an elaborated-type-specifier? + TemplateSpecializationTypeLoc NewTL + = TLB.push<TemplateSpecializationTypeLoc>(Result); + NewTL.setTemplateNameLoc(TL.getNameLoc()); + NewTL.setLAngleLoc(TL.getLAngleLoc()); + NewTL.setRAngleLoc(TL.getRAngleLoc()); + for (unsigned i = 0, e = NewTemplateArgs.size(); i != e; ++i) + NewTL.setArgLocInfo(i, NewTemplateArgs[i].getLocInfo()); + } + + return Result; +} + template<typename Derived> QualType TreeTransform<Derived>::TransformElaboratedType(TypeLocBuilder &TLB, ElaboratedTypeLoc TL) { const ElaboratedType *T = TL.getTypePtr(); - NestedNameSpecifier *NNS = 0; + NestedNameSpecifierLoc QualifierLoc; // NOTE: the qualifier in an ElaboratedType is optional. - if (T->getQualifier() != 0) { - NNS = getDerived().TransformNestedNameSpecifier(T->getQualifier(), - TL.getQualifierRange()); - if (!NNS) + if (TL.getQualifierLoc()) { + QualifierLoc + = getDerived().TransformNestedNameSpecifierLoc(TL.getQualifierLoc()); + if (!QualifierLoc) return QualType(); } @@ -4383,18 +4480,18 @@ TreeTransform<Derived>::TransformElaboratedType(TypeLocBuilder &TLB, QualType Result = TL.getType(); if (getDerived().AlwaysRebuild() || - NNS != T->getQualifier() || + QualifierLoc != TL.getQualifierLoc() || NamedT != T->getNamedType()) { Result = getDerived().RebuildElaboratedType(TL.getKeywordLoc(), - T->getKeyword(), NNS, NamedT); + T->getKeyword(), + QualifierLoc, NamedT); if (Result.isNull()) return QualType(); } ElaboratedTypeLoc NewTL = TLB.push<ElaboratedTypeLoc>(Result); NewTL.setKeywordLoc(TL.getKeywordLoc()); - NewTL.setQualifierRange(TL.getQualifierRange()); - + NewTL.setQualifierLoc(QualifierLoc); return Result; } @@ -4462,17 +4559,16 @@ QualType TreeTransform<Derived>::TransformDependentNameType(TypeLocBuilder &TLB, DependentNameTypeLoc TL) { const DependentNameType *T = TL.getTypePtr(); - NestedNameSpecifier *NNS - = getDerived().TransformNestedNameSpecifier(T->getQualifier(), - TL.getQualifierRange()); - if (!NNS) + NestedNameSpecifierLoc QualifierLoc + = getDerived().TransformNestedNameSpecifierLoc(TL.getQualifierLoc()); + if (!QualifierLoc) return QualType(); QualType Result - = getDerived().RebuildDependentNameType(T->getKeyword(), NNS, - T->getIdentifier(), + = getDerived().RebuildDependentNameType(T->getKeyword(), TL.getKeywordLoc(), - TL.getQualifierRange(), + QualifierLoc, + T->getIdentifier(), TL.getNameLoc()); if (Result.isNull()) return QualType(); @@ -4483,11 +4579,11 @@ QualType TreeTransform<Derived>::TransformDependentNameType(TypeLocBuilder &TLB, ElaboratedTypeLoc NewTL = TLB.push<ElaboratedTypeLoc>(Result); NewTL.setKeywordLoc(TL.getKeywordLoc()); - NewTL.setQualifierRange(TL.getQualifierRange()); + NewTL.setQualifierLoc(QualifierLoc); } else { DependentNameTypeLoc NewTL = TLB.push<DependentNameTypeLoc>(Result); NewTL.setKeywordLoc(TL.getKeywordLoc()); - NewTL.setQualifierRange(TL.getQualifierRange()); + NewTL.setQualifierLoc(QualifierLoc); NewTL.setNameLoc(TL.getNameLoc()); } return Result; @@ -4497,65 +4593,79 @@ template<typename Derived> QualType TreeTransform<Derived>:: TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB, DependentTemplateSpecializationTypeLoc TL) { - const DependentTemplateSpecializationType *T = TL.getTypePtr(); - - NestedNameSpecifier *NNS - = getDerived().TransformNestedNameSpecifier(T->getQualifier(), - TL.getQualifierRange()); - if (!NNS) - return QualType(); - + NestedNameSpecifierLoc QualifierLoc; + if (TL.getQualifierLoc()) { + QualifierLoc + = getDerived().TransformNestedNameSpecifierLoc(TL.getQualifierLoc()); + if (!QualifierLoc) + return QualType(); + } + return getDerived() - .TransformDependentTemplateSpecializationType(TLB, TL, NNS); + .TransformDependentTemplateSpecializationType(TLB, TL, QualifierLoc); } template<typename Derived> QualType TreeTransform<Derived>:: - TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB, - DependentTemplateSpecializationTypeLoc TL, - NestedNameSpecifier *NNS) { +TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB, + DependentTemplateSpecializationTypeLoc TL, + NestedNameSpecifierLoc QualifierLoc) { const DependentTemplateSpecializationType *T = TL.getTypePtr(); - + TemplateArgumentListInfo NewTemplateArgs; NewTemplateArgs.setLAngleLoc(TL.getLAngleLoc()); NewTemplateArgs.setRAngleLoc(TL.getRAngleLoc()); - - // FIXME: Nested-name-specifier source location info! + typedef TemplateArgumentLocContainerIterator< - DependentTemplateSpecializationTypeLoc> ArgIterator; + DependentTemplateSpecializationTypeLoc> ArgIterator; if (getDerived().TransformTemplateArguments(ArgIterator(TL, 0), ArgIterator(TL, TL.getNumArgs()), NewTemplateArgs)) return QualType(); - + QualType Result = getDerived().RebuildDependentTemplateSpecializationType(T->getKeyword(), - NNS, - TL.getQualifierRange(), + QualifierLoc, T->getIdentifier(), - TL.getNameLoc(), - NewTemplateArgs); + TL.getNameLoc(), + NewTemplateArgs); if (Result.isNull()) return QualType(); - + if (const ElaboratedType *ElabT = dyn_cast<ElaboratedType>(Result)) { QualType NamedT = ElabT->getNamedType(); - + // Copy information relevant to the template specialization. TemplateSpecializationTypeLoc NamedTL = TLB.push<TemplateSpecializationTypeLoc>(NamedT); + NamedTL.setTemplateNameLoc(TL.getNameLoc()); NamedTL.setLAngleLoc(TL.getLAngleLoc()); NamedTL.setRAngleLoc(TL.getRAngleLoc()); - for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) - NamedTL.setArgLocInfo(I, TL.getArgLocInfo(I)); - + for (unsigned I = 0, E = NewTemplateArgs.size(); I != E; ++I) + NamedTL.setArgLocInfo(I, NewTemplateArgs[I].getLocInfo()); + // Copy information relevant to the elaborated type. ElaboratedTypeLoc NewTL = TLB.push<ElaboratedTypeLoc>(Result); NewTL.setKeywordLoc(TL.getKeywordLoc()); - NewTL.setQualifierRange(TL.getQualifierRange()); + NewTL.setQualifierLoc(QualifierLoc); + } else if (isa<DependentTemplateSpecializationType>(Result)) { + DependentTemplateSpecializationTypeLoc SpecTL + = TLB.push<DependentTemplateSpecializationTypeLoc>(Result); + SpecTL.setKeywordLoc(TL.getKeywordLoc()); + SpecTL.setQualifierLoc(QualifierLoc); + SpecTL.setNameLoc(TL.getNameLoc()); + SpecTL.setLAngleLoc(TL.getLAngleLoc()); + SpecTL.setRAngleLoc(TL.getRAngleLoc()); + for (unsigned I = 0, E = NewTemplateArgs.size(); I != E; ++I) + SpecTL.setArgLocInfo(I, NewTemplateArgs[I].getLocInfo()); } else { - TypeLoc NewTL(Result, TL.getOpaqueData()); - TLB.pushFullCopy(NewTL); + TemplateSpecializationTypeLoc SpecTL + = TLB.push<TemplateSpecializationTypeLoc>(Result); + SpecTL.setTemplateNameLoc(TL.getNameLoc()); + SpecTL.setLAngleLoc(TL.getLAngleLoc()); + SpecTL.setRAngleLoc(TL.getRAngleLoc()); + for (unsigned I = 0, E = NewTemplateArgs.size(); I != E; ++I) + SpecTL.setArgLocInfo(I, NewTemplateArgs[I].getLocInfo()); } return Result; } @@ -5304,8 +5414,9 @@ TreeTransform<Derived>::TransformCXXCatchStmt(CXXCatchStmt *S) { return StmtError(); Var = getDerived().RebuildExceptionDecl(ExceptionDecl, T, - ExceptionDecl->getIdentifier(), - ExceptionDecl->getLocation()); + ExceptionDecl->getInnerLocStart(), + ExceptionDecl->getLocation(), + ExceptionDecl->getIdentifier()); if (!Var || Var->isInvalidDecl()) return StmtError(); } @@ -5356,6 +5467,112 @@ TreeTransform<Derived>::TransformCXXTryStmt(CXXTryStmt *S) { move_arg(Handlers)); } +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformCXXForRangeStmt(CXXForRangeStmt *S) { + StmtResult Range = getDerived().TransformStmt(S->getRangeStmt()); + if (Range.isInvalid()) + return StmtError(); + + StmtResult BeginEnd = getDerived().TransformStmt(S->getBeginEndStmt()); + if (BeginEnd.isInvalid()) + return StmtError(); + + ExprResult Cond = getDerived().TransformExpr(S->getCond()); + if (Cond.isInvalid()) + return StmtError(); + + ExprResult Inc = getDerived().TransformExpr(S->getInc()); + if (Inc.isInvalid()) + return StmtError(); + + StmtResult LoopVar = getDerived().TransformStmt(S->getLoopVarStmt()); + if (LoopVar.isInvalid()) + return StmtError(); + + StmtResult NewStmt = S; + if (getDerived().AlwaysRebuild() || + Range.get() != S->getRangeStmt() || + BeginEnd.get() != S->getBeginEndStmt() || + Cond.get() != S->getCond() || + Inc.get() != S->getInc() || + LoopVar.get() != S->getLoopVarStmt()) + NewStmt = getDerived().RebuildCXXForRangeStmt(S->getForLoc(), + S->getColonLoc(), Range.get(), + BeginEnd.get(), Cond.get(), + Inc.get(), LoopVar.get(), + S->getRParenLoc()); + + StmtResult Body = getDerived().TransformStmt(S->getBody()); + if (Body.isInvalid()) + return StmtError(); + + // Body has changed but we didn't rebuild the for-range statement. Rebuild + // it now so we have a new statement to attach the body to. + if (Body.get() != S->getBody() && NewStmt.get() == S) + NewStmt = getDerived().RebuildCXXForRangeStmt(S->getForLoc(), + S->getColonLoc(), Range.get(), + BeginEnd.get(), Cond.get(), + Inc.get(), LoopVar.get(), + S->getRParenLoc()); + + if (NewStmt.get() == S) + return SemaRef.Owned(S); + + return FinishCXXForRangeStmt(NewStmt.get(), Body.get()); +} + +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformSEHTryStmt(SEHTryStmt *S) { + StmtResult TryBlock; // = getDerived().TransformCompoundStmt(S->getTryBlock()); + if(TryBlock.isInvalid()) return StmtError(); + + StmtResult Handler = getDerived().TransformSEHHandler(S->getHandler()); + if(!getDerived().AlwaysRebuild() && + TryBlock.get() == S->getTryBlock() && + Handler.get() == S->getHandler()) + return SemaRef.Owned(S); + + return getDerived().RebuildSEHTryStmt(S->getIsCXXTry(), + S->getTryLoc(), + TryBlock.take(), + Handler.take()); +} + +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformSEHFinallyStmt(SEHFinallyStmt *S) { + StmtResult Block; // = getDerived().TransformCompoundStatement(S->getBlock()); + if(Block.isInvalid()) return StmtError(); + + return getDerived().RebuildSEHFinallyStmt(S->getFinallyLoc(), + Block.take()); +} + +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformSEHExceptStmt(SEHExceptStmt *S) { + ExprResult FilterExpr = getDerived().TransformExpr(S->getFilterExpr()); + if(FilterExpr.isInvalid()) return StmtError(); + + StmtResult Block; // = getDerived().TransformCompoundStatement(S->getBlock()); + if(Block.isInvalid()) return StmtError(); + + return getDerived().RebuildSEHExceptStmt(S->getExceptLoc(), + FilterExpr.take(), + Block.take()); +} + +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformSEHHandler(Stmt *Handler) { + if(isa<SEHFinallyStmt>(Handler)) + return getDerived().TransformSEHFinallyStmt(cast<SEHFinallyStmt>(Handler)); + else + return getDerived().TransformSEHExceptStmt(cast<SEHExceptStmt>(Handler)); +} + //===----------------------------------------------------------------------===// // Expression transformation //===----------------------------------------------------------------------===// @@ -5368,11 +5585,11 @@ TreeTransform<Derived>::TransformPredefinedExpr(PredefinedExpr *E) { template<typename Derived> ExprResult TreeTransform<Derived>::TransformDeclRefExpr(DeclRefExpr *E) { - NestedNameSpecifier *Qualifier = 0; - if (E->getQualifier()) { - Qualifier = getDerived().TransformNestedNameSpecifier(E->getQualifier(), - E->getQualifierRange()); - if (!Qualifier) + NestedNameSpecifierLoc QualifierLoc; + if (E->getQualifierLoc()) { + QualifierLoc + = getDerived().TransformNestedNameSpecifierLoc(E->getQualifierLoc()); + if (!QualifierLoc) return ExprError(); } @@ -5390,7 +5607,7 @@ TreeTransform<Derived>::TransformDeclRefExpr(DeclRefExpr *E) { } if (!getDerived().AlwaysRebuild() && - Qualifier == E->getQualifier() && + QualifierLoc == E->getQualifierLoc() && ND == E->getDecl() && NameInfo.getName() == E->getDecl()->getDeclName() && !E->hasExplicitTemplateArgs()) { @@ -5413,8 +5630,8 @@ TreeTransform<Derived>::TransformDeclRefExpr(DeclRefExpr *E) { return ExprError(); } - return getDerived().RebuildDeclRefExpr(Qualifier, E->getQualifierRange(), - ND, NameInfo, TemplateArgs); + return getDerived().RebuildDeclRefExpr(QualifierLoc, ND, NameInfo, + TemplateArgs); } template<typename Derived> @@ -5449,6 +5666,42 @@ TreeTransform<Derived>::TransformCharacterLiteral(CharacterLiteral *E) { template<typename Derived> ExprResult +TreeTransform<Derived>::TransformGenericSelectionExpr(GenericSelectionExpr *E) { + ExprResult ControllingExpr = + getDerived().TransformExpr(E->getControllingExpr()); + if (ControllingExpr.isInvalid()) + return ExprError(); + + llvm::SmallVector<Expr *, 4> AssocExprs; + llvm::SmallVector<TypeSourceInfo *, 4> AssocTypes; + for (unsigned i = 0; i != E->getNumAssocs(); ++i) { + TypeSourceInfo *TS = E->getAssocTypeSourceInfo(i); + if (TS) { + TypeSourceInfo *AssocType = getDerived().TransformType(TS); + if (!AssocType) + return ExprError(); + AssocTypes.push_back(AssocType); + } else { + AssocTypes.push_back(0); + } + + ExprResult AssocExpr = getDerived().TransformExpr(E->getAssocExpr(i)); + if (AssocExpr.isInvalid()) + return ExprError(); + AssocExprs.push_back(AssocExpr.release()); + } + + return getDerived().RebuildGenericSelectionExpr(E->getGenericLoc(), + E->getDefaultLoc(), + E->getRParenLoc(), + ControllingExpr.release(), + AssocTypes.data(), + AssocExprs.data(), + E->getNumAssocs()); +} + +template<typename Derived> +ExprResult TreeTransform<Derived>::TransformParenExpr(ParenExpr *E) { ExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr()); if (SubExpr.isInvalid()) @@ -5498,8 +5751,8 @@ TreeTransform<Derived>::TransformOffsetOfExpr(OffsetOfExpr *E) { const Node &ON = E->getComponent(I); Component Comp; Comp.isBrackets = true; - Comp.LocStart = ON.getRange().getBegin(); - Comp.LocEnd = ON.getRange().getEnd(); + Comp.LocStart = ON.getSourceRange().getBegin(); + Comp.LocEnd = ON.getSourceRange().getEnd(); switch (ON.getKind()) { case Node::Array: { Expr *FromIndex = E->getIndexExpr(ON.getArrayExprIndex()); @@ -5552,7 +5805,8 @@ TreeTransform<Derived>::TransformOpaqueValueExpr(OpaqueValueExpr *E) { template<typename Derived> ExprResult -TreeTransform<Derived>::TransformSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { +TreeTransform<Derived>::TransformUnaryExprOrTypeTraitExpr( + UnaryExprOrTypeTraitExpr *E) { if (E->isArgumentType()) { TypeSourceInfo *OldT = E->getArgumentTypeInfo(); @@ -5563,9 +5817,9 @@ TreeTransform<Derived>::TransformSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { if (!getDerived().AlwaysRebuild() && OldT == NewT) return SemaRef.Owned(E); - return getDerived().RebuildSizeOfAlignOf(NewT, E->getOperatorLoc(), - E->isSizeOf(), - E->getSourceRange()); + return getDerived().RebuildUnaryExprOrTypeTrait(NewT, E->getOperatorLoc(), + E->getKind(), + E->getSourceRange()); } ExprResult SubExpr; @@ -5583,9 +5837,10 @@ TreeTransform<Derived>::TransformSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { return SemaRef.Owned(E); } - return getDerived().RebuildSizeOfAlignOf(SubExpr.get(), E->getOperatorLoc(), - E->isSizeOf(), - E->getSourceRange()); + return getDerived().RebuildUnaryExprOrTypeTrait(SubExpr.get(), + E->getOperatorLoc(), + E->getKind(), + E->getSourceRange()); } template<typename Derived> @@ -5646,12 +5901,12 @@ TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E) { if (Base.isInvalid()) return ExprError(); - NestedNameSpecifier *Qualifier = 0; + NestedNameSpecifierLoc QualifierLoc; if (E->hasQualifier()) { - Qualifier - = getDerived().TransformNestedNameSpecifier(E->getQualifier(), - E->getQualifierRange()); - if (Qualifier == 0) + QualifierLoc + = getDerived().TransformNestedNameSpecifierLoc(E->getQualifierLoc()); + + if (!QualifierLoc) return ExprError(); } @@ -5673,7 +5928,7 @@ TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E) { if (!getDerived().AlwaysRebuild() && Base.get() == E->getBase() && - Qualifier == E->getQualifier() && + QualifierLoc == E->getQualifierLoc() && Member == E->getMemberDecl() && FoundDecl == E->getFoundDecl() && !E->hasExplicitTemplateArgs()) { @@ -5706,8 +5961,7 @@ TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E) { return getDerived().RebuildMemberExpr(Base.get(), FakeOperatorLoc, E->isArrow(), - Qualifier, - E->getQualifierRange(), + QualifierLoc, E->getMemberNameInfo(), Member, FoundDecl, @@ -6333,7 +6587,7 @@ TreeTransform<Derived>::TransformCXXUuidofExpr(CXXUuidofExpr *E) { TInfo == E->getTypeOperandSourceInfo()) return SemaRef.Owned(E); - return getDerived().RebuildCXXTypeidExpr(E->getType(), + return getDerived().RebuildCXXUuidofExpr(E->getType(), E->getLocStart(), TInfo, E->getLocEnd()); @@ -6623,8 +6877,7 @@ TreeTransform<Derived>::TransformCXXPseudoDestructorExpr( if (E->getDestroyedTypeInfo()) { TypeSourceInfo *DestroyedTypeInfo = getDerived().TransformTypeInObjectScope(E->getDestroyedTypeInfo(), - ObjectType, 0, - QualifierLoc.getNestedNameSpecifier()); + ObjectType, 0, SS); if (!DestroyedTypeInfo) return ExprError(); Destroyed = DestroyedTypeInfo; @@ -6670,8 +6923,6 @@ template<typename Derived> ExprResult TreeTransform<Derived>::TransformUnresolvedLookupExpr( UnresolvedLookupExpr *Old) { - TemporaryBase Rebase(*this, Old->getNameLoc(), DeclarationName()); - LookupResult R(SemaRef, Old->getName(), Old->getNameLoc(), Sema::LookupOrdinaryName); @@ -6708,14 +6959,13 @@ TreeTransform<Derived>::TransformUnresolvedLookupExpr( // Rebuild the nested-name qualifier, if present. CXXScopeSpec SS; - NestedNameSpecifier *Qualifier = 0; - if (Old->getQualifier()) { - Qualifier = getDerived().TransformNestedNameSpecifier(Old->getQualifier(), - Old->getQualifierRange()); - if (!Qualifier) + if (Old->getQualifierLoc()) { + NestedNameSpecifierLoc QualifierLoc + = getDerived().TransformNestedNameSpecifierLoc(Old->getQualifierLoc()); + if (!QualifierLoc) return ExprError(); - SS.MakeTrivial(SemaRef.Context, Qualifier, Old->getQualifierRange()); + SS.Adopt(QualifierLoc); } if (Old->getNamingClass()) { @@ -6785,6 +7035,53 @@ TreeTransform<Derived>::TransformBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) { template<typename Derived> ExprResult +TreeTransform<Derived>::TransformArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { + TypeSourceInfo *T = getDerived().TransformType(E->getQueriedTypeSourceInfo()); + if (!T) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && + T == E->getQueriedTypeSourceInfo()) + return SemaRef.Owned(E); + + ExprResult SubExpr; + { + EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); + SubExpr = getDerived().TransformExpr(E->getDimensionExpression()); + if (SubExpr.isInvalid()) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && SubExpr.get() == E->getDimensionExpression()) + return SemaRef.Owned(E); + } + + return getDerived().RebuildArrayTypeTrait(E->getTrait(), + E->getLocStart(), + T, + SubExpr.get(), + E->getLocEnd()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformExpressionTraitExpr(ExpressionTraitExpr *E) { + ExprResult SubExpr; + { + EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); + SubExpr = getDerived().TransformExpr(E->getQueriedExpression()); + if (SubExpr.isInvalid()) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && SubExpr.get() == E->getQueriedExpression()) + return SemaRef.Owned(E); + } + + return getDerived().RebuildExpressionTrait( + E->getTrait(), E->getLocStart(), SubExpr.get(), E->getLocEnd()); +} + +template<typename Derived> +ExprResult TreeTransform<Derived>::TransformDependentScopeDeclRefExpr( DependentScopeDeclRefExpr *E) { NestedNameSpecifierLoc QualifierLoc @@ -6994,16 +7291,16 @@ TreeTransform<Derived>::TransformCXXDependentScopeMemberExpr( // the member name. NamedDecl *FirstQualifierInScope = getDerived().TransformFirstQualifierInScope( - E->getFirstQualifierFoundInScope(), - E->getQualifierRange().getBegin()); + E->getFirstQualifierFoundInScope(), + E->getQualifierLoc().getBeginLoc()); - NestedNameSpecifier *Qualifier = 0; + NestedNameSpecifierLoc QualifierLoc; if (E->getQualifier()) { - Qualifier = getDerived().TransformNestedNameSpecifier(E->getQualifier(), - E->getQualifierRange(), - ObjectType, - FirstQualifierInScope); - if (!Qualifier) + QualifierLoc + = getDerived().TransformNestedNameSpecifierLoc(E->getQualifierLoc(), + ObjectType, + FirstQualifierInScope); + if (!QualifierLoc) return ExprError(); } @@ -7022,7 +7319,7 @@ TreeTransform<Derived>::TransformCXXDependentScopeMemberExpr( if (!getDerived().AlwaysRebuild() && Base.get() == OldBase && BaseType == E->getBaseType() && - Qualifier == E->getQualifier() && + QualifierLoc == E->getQualifierLoc() && NameInfo.getName() == E->getMember() && FirstQualifierInScope == E->getFirstQualifierFoundInScope()) return SemaRef.Owned(E); @@ -7031,8 +7328,7 @@ TreeTransform<Derived>::TransformCXXDependentScopeMemberExpr( BaseType, E->isArrow(), E->getOperatorLoc(), - Qualifier, - E->getQualifierRange(), + QualifierLoc, FirstQualifierInScope, NameInfo, /*TemplateArgs*/ 0); @@ -7048,8 +7344,7 @@ TreeTransform<Derived>::TransformCXXDependentScopeMemberExpr( BaseType, E->isArrow(), E->getOperatorLoc(), - Qualifier, - E->getQualifierRange(), + QualifierLoc, FirstQualifierInScope, NameInfo, &TransArgs); @@ -7070,12 +7365,11 @@ TreeTransform<Derived>::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old) BaseType = getDerived().TransformType(Old->getBaseType()); } - NestedNameSpecifier *Qualifier = 0; - if (Old->getQualifier()) { - Qualifier - = getDerived().TransformNestedNameSpecifier(Old->getQualifier(), - Old->getQualifierRange()); - if (Qualifier == 0) + NestedNameSpecifierLoc QualifierLoc; + if (Old->getQualifierLoc()) { + QualifierLoc + = getDerived().TransformNestedNameSpecifierLoc(Old->getQualifierLoc()); + if (!QualifierLoc) return ExprError(); } @@ -7093,8 +7387,10 @@ TreeTransform<Derived>::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old) // This can happen because of dependent hiding. if (isa<UsingShadowDecl>(*I)) continue; - else + else { + R.clear(); return ExprError(); + } } // Expand using declarations. @@ -7143,8 +7439,7 @@ TreeTransform<Derived>::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old) BaseType, Old->getOperatorLoc(), Old->isArrow(), - Qualifier, - Old->getQualifierRange(), + QualifierLoc, FirstQualifierInScope, R, (Old->hasExplicitTemplateArgs() @@ -7490,8 +7785,6 @@ TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) { template<typename Derived> ExprResult TreeTransform<Derived>::TransformBlockDeclRefExpr(BlockDeclRefExpr *E) { - NestedNameSpecifier *Qualifier = 0; - ValueDecl *ND = cast_or_null<ValueDecl>(getDerived().TransformDecl(E->getLocation(), E->getDecl())); @@ -7508,7 +7801,7 @@ TreeTransform<Derived>::TransformBlockDeclRefExpr(BlockDeclRefExpr *E) { } DeclarationNameInfo NameInfo(E->getDecl()->getDeclName(), E->getLocation()); - return getDerived().RebuildDeclRefExpr(Qualifier, SourceLocation(), + return getDerived().RebuildDeclRefExpr(NestedNameSpecifierLoc(), ND, NameInfo, 0); } @@ -7720,88 +8013,33 @@ template<typename Derived> QualType TreeTransform<Derived>::RebuildTemplateSpecializationType( TemplateName Template, SourceLocation TemplateNameLoc, - const TemplateArgumentListInfo &TemplateArgs) { + TemplateArgumentListInfo &TemplateArgs) { return SemaRef.CheckTemplateIdType(Template, TemplateNameLoc, TemplateArgs); } template<typename Derived> -NestedNameSpecifier * -TreeTransform<Derived>::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix, - SourceRange Range, - IdentifierInfo &II, - QualType ObjectType, - NamedDecl *FirstQualifierInScope) { - CXXScopeSpec SS; - // FIXME: The source location information is all wrong. - SS.MakeTrivial(SemaRef.Context, Prefix, Range); - if (SemaRef.BuildCXXNestedNameSpecifier(0, II, /*FIXME:*/Range.getBegin(), - /*FIXME:*/Range.getEnd(), - ObjectType, false, - SS, FirstQualifierInScope, - false)) - return 0; - - return SS.getScopeRep(); -} - -template<typename Derived> -NestedNameSpecifier * -TreeTransform<Derived>::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix, - SourceRange Range, - NamespaceDecl *NS) { - return NestedNameSpecifier::Create(SemaRef.Context, Prefix, NS); -} - -template<typename Derived> -NestedNameSpecifier * -TreeTransform<Derived>::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix, - SourceRange Range, - NamespaceAliasDecl *Alias) { - return NestedNameSpecifier::Create(SemaRef.Context, Prefix, Alias); -} - -template<typename Derived> -NestedNameSpecifier * -TreeTransform<Derived>::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix, - SourceRange Range, - bool TemplateKW, - QualType T) { - if (T->isDependentType() || T->isRecordType() || - (SemaRef.getLangOptions().CPlusPlus0x && T->isEnumeralType())) { - assert(!T.hasLocalQualifiers() && "Can't get cv-qualifiers here"); - return NestedNameSpecifier::Create(SemaRef.Context, Prefix, TemplateKW, - T.getTypePtr()); - } - - SemaRef.Diag(Range.getBegin(), diag::err_nested_name_spec_non_tag) << T; - return 0; -} - -template<typename Derived> TemplateName -TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier, +TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS, bool TemplateKW, TemplateDecl *Template) { - return SemaRef.Context.getQualifiedTemplateName(Qualifier, TemplateKW, + return SemaRef.Context.getQualifiedTemplateName(SS.getScopeRep(), TemplateKW, Template); } template<typename Derived> TemplateName -TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, - const IdentifierInfo &II, +TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS, + const IdentifierInfo &Name, + SourceLocation NameLoc, QualType ObjectType, NamedDecl *FirstQualifierInScope) { - CXXScopeSpec SS; - SS.MakeTrivial(SemaRef.Context, Qualifier, QualifierRange); - UnqualifiedId Name; - Name.setIdentifier(&II, /*FIXME:*/getDerived().getBaseLocation()); + UnqualifiedId TemplateName; + TemplateName.setIdentifier(&Name, NameLoc); Sema::TemplateTy Template; getSema().ActOnDependentTemplateName(/*Scope=*/0, - /*FIXME:*/getDerived().getBaseLocation(), + /*FIXME:*/SourceLocation(), SS, - Name, + TemplateName, ParsedType::make(ObjectType), /*EnteringContext=*/false, Template); @@ -7810,18 +8048,17 @@ TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier, template<typename Derived> TemplateName -TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier, +TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS, OverloadedOperatorKind Operator, + SourceLocation NameLoc, QualType ObjectType) { - CXXScopeSpec SS; - SS.MakeTrivial(SemaRef.Context, Qualifier, SourceRange(getDerived().getBaseLocation())); UnqualifiedId Name; - SourceLocation SymbolLocations[3]; // FIXME: Bogus location information. - Name.setOperatorFunctionId(/*FIXME:*/getDerived().getBaseLocation(), - Operator, SymbolLocations); + // FIXME: Bogus location information. + SourceLocation SymbolLocations[3] = { NameLoc, NameLoc, NameLoc }; + Name.setOperatorFunctionId(NameLoc, Operator, SymbolLocations); Sema::TemplateTy Template; getSema().ActOnDependentTemplateName(/*Scope=*/0, - /*FIXME:*/getDerived().getBaseLocation(), + /*FIXME:*/SourceLocation(), SS, Name, ParsedType::make(ObjectType), diff --git a/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h b/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h index 1e0a7c4..3570737 100644 --- a/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h +++ b/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h @@ -44,8 +44,7 @@ class TypeLocBuilder { public: TypeLocBuilder() - : Buffer(InlineBuffer), Capacity(InlineCapacity), Index(InlineCapacity) - {} + : Buffer(InlineBuffer), Capacity(InlineCapacity), Index(InlineCapacity) {} ~TypeLocBuilder() { if (Buffer != InlineBuffer) |